[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20190510104639.15170-2-qiangqing.zhang@nxp.com>
Date: Fri, 10 May 2019 10:49:55 +0000
From: Joakim Zhang <qiangqing.zhang@....com>
To: "mkl@...gutronix.de" <mkl@...gutronix.de>,
"linux-can@...r.kernel.org" <linux-can@...r.kernel.org>
CC: dl-linux-imx <linux-imx@....com>,
"wg@...ndegger.com" <wg@...ndegger.com>,
"netdev@...r.kernel.org" <netdev@...r.kernel.org>,
Stefan-gabriel Mirea <stefan-gabriel.mirea@....com>,
Joakim Zhang <qiangqing.zhang@....com>
Subject: [PATCH V3 1/7] can: flexcan: allocate skb in mailbox_read
We need to use alloc_canfd_skb() for CAN FD frames and alloc_can_skb()
for CAN classic frames. So we have to alloc skb in flexcan_mailbox_read().
Signed-off-by: Joakim Zhang <qiangqing.zhang@....com>
ChangeLog:
----------
V1->V2:
*None
V2->V3:
*Change the way to allocate skb
---
drivers/net/can/flexcan.c | 38 ++++++++++++++++++++--------------
drivers/net/can/rx-offload.c | 29 +++++++-------------------
include/linux/can/rx-offload.h | 5 +++--
3 files changed, 33 insertions(+), 39 deletions(-)
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index e35083ff31ee..f742077e8f93 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -789,14 +789,15 @@ static inline struct flexcan_priv *rx_offload_to_priv(struct can_rx_offload *off
return container_of(offload, struct flexcan_priv, offload);
}
-static unsigned int flexcan_mailbox_read(struct can_rx_offload *offload,
- struct can_frame *cf,
- u32 *timestamp, unsigned int n)
+static unsigned int flexcan_mailbox_read(struct can_rx_offload *offload, bool drop,
+ struct sk_buff **skb, u32 *timestamp,
+ unsigned int n)
{
struct flexcan_priv *priv = rx_offload_to_priv(offload);
struct flexcan_regs __iomem *regs = priv->regs;
struct flexcan_mb __iomem *mb;
u32 reg_ctrl, reg_id, reg_iflag1;
+ struct can_frame *cf;
int i;
mb = flexcan_get_mb(priv, n);
@@ -827,22 +828,27 @@ static unsigned int flexcan_mailbox_read(struct can_rx_offload *offload,
reg_ctrl = priv->read(&mb->can_ctrl);
}
- /* increase timstamp to full 32 bit */
- *timestamp = reg_ctrl << 16;
+ if (!drop)
+ *skb = alloc_can_skb(offload->dev, &cf);
- reg_id = priv->read(&mb->can_id);
- if (reg_ctrl & FLEXCAN_MB_CNT_IDE)
- cf->can_id = ((reg_id >> 0) & CAN_EFF_MASK) | CAN_EFF_FLAG;
- else
- cf->can_id = (reg_id >> 18) & CAN_SFF_MASK;
+ if (*skb) {
+ /* increase timstamp to full 32 bit */
+ *timestamp = reg_ctrl << 16;
- if (reg_ctrl & FLEXCAN_MB_CNT_RTR)
- cf->can_id |= CAN_RTR_FLAG;
- cf->can_dlc = get_can_dlc((reg_ctrl >> 16) & 0xf);
+ reg_id = priv->read(&mb->can_id);
+ if (reg_ctrl & FLEXCAN_MB_CNT_IDE)
+ cf->can_id = ((reg_id >> 0) & CAN_EFF_MASK) | CAN_EFF_FLAG;
+ else
+ cf->can_id = (reg_id >> 18) & CAN_SFF_MASK;
- for (i = 0; i < cf->can_dlc; i += sizeof(u32)) {
- __be32 data = cpu_to_be32(priv->read(&mb->data[i / sizeof(u32)]));
- *(__be32 *)(cf->data + i) = data;
+ if (reg_ctrl & FLEXCAN_MB_CNT_RTR)
+ cf->can_id |= CAN_RTR_FLAG;
+ cf->can_dlc = get_can_dlc((reg_ctrl >> 16) & 0xf);
+
+ for (i = 0; i < cf->can_dlc; i += sizeof(u32)) {
+ __be32 data = cpu_to_be32(priv->read(&mb->data[i / sizeof(u32)]));
+ *(__be32 *)(cf->data + i) = data;
+ }
}
/* mark as read */
diff --git a/drivers/net/can/rx-offload.c b/drivers/net/can/rx-offload.c
index 2ce4fa8698c7..632919484ff7 100644
--- a/drivers/net/can/rx-offload.c
+++ b/drivers/net/can/rx-offload.c
@@ -121,32 +121,19 @@ static int can_rx_offload_compare(struct sk_buff *a, struct sk_buff *b)
static struct sk_buff *can_rx_offload_offload_one(struct can_rx_offload *offload, unsigned int n)
{
struct sk_buff *skb = NULL;
- struct can_rx_offload_cb *cb;
- struct can_frame *cf;
- int ret;
+ u32 timestamp;
/* If queue is full or skb not available, read to discard mailbox */
- if (likely(skb_queue_len(&offload->skb_queue) <=
- offload->skb_queue_len_max))
- skb = alloc_can_skb(offload->dev, &cf);
+ bool drop = unlikely(skb_queue_len(&offload->skb_queue) >
+ offload->skb_queue_len_max);
- if (!skb) {
- struct can_frame cf_overflow;
- u32 timestamp;
+ if (offload->mailbox_read(offload, drop, &skb, ×tamp, n) && !skb)
+ offload->dev->stats.rx_dropped++;
- ret = offload->mailbox_read(offload, &cf_overflow,
- ×tamp, n);
- if (ret)
- offload->dev->stats.rx_dropped++;
+ if (skb) {
+ struct can_rx_offload_cb *cb = can_rx_offload_get_cb(skb);
- return NULL;
- }
-
- cb = can_rx_offload_get_cb(skb);
- ret = offload->mailbox_read(offload, cf, &cb->timestamp, n);
- if (!ret) {
- kfree_skb(skb);
- return NULL;
+ cb->timestamp = timestamp;
}
return skb;
diff --git a/include/linux/can/rx-offload.h b/include/linux/can/rx-offload.h
index 8268811a697e..c54d80ef4314 100644
--- a/include/linux/can/rx-offload.h
+++ b/include/linux/can/rx-offload.h
@@ -23,8 +23,9 @@
struct can_rx_offload {
struct net_device *dev;
- unsigned int (*mailbox_read)(struct can_rx_offload *offload, struct can_frame *cf,
- u32 *timestamp, unsigned int mb);
+ unsigned int (*mailbox_read)(struct can_rx_offload *offload, bool drop,
+ struct sk_buff **skb, u32 *timestamp,
+ unsigned int mb);
struct sk_buff_head skb_queue;
u32 skb_queue_len_max;
--
2.17.1
Powered by blists - more mailing lists