diff options
author | Joakim Zhang <qiangqing.zhang@nxp.com> | 2019-07-12 08:02:38 +0000 |
---|---|---|
committer | Marc Kleine-Budde <mkl@pengutronix.de> | 2019-11-11 21:58:10 +0100 |
commit | 4e9c9484b085dbba60b299182dd490eaeb84d18a (patch) | |
tree | 2132ffbed1a86dc3085c9a2c0cad7fd2d1f9c2f8 /drivers/net/can/flexcan.c | |
parent | 61d2350615c2c42f7af65d9a575f5dbf9738a10e (diff) | |
download | lwn-4e9c9484b085dbba60b299182dd490eaeb84d18a.tar.gz lwn-4e9c9484b085dbba60b299182dd490eaeb84d18a.zip |
can: rx-offload: Prepare for CAN FD support
The skbs for classic CAN and CAN FD frames are allocated with seperate
functions: alloc_can_skb() and alloc_canfd_skb().
In order to support CAN FD frames via the rx-offload helper, the driver
itself has to allocate the skb (depending whether it received a classic
CAN or CAN FD frame), as the rx-offload helper cannot know which kind of
CAN frame the driver has received.
This patch moves the allocation of the skb into the struct
can_rx_offload::mailbox_read callbacks of the the flexcan and ti_hecc
driver and adjusts the rx-offload helper accordingly.
Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Diffstat (limited to 'drivers/net/can/flexcan.c')
-rw-r--r-- | drivers/net/can/flexcan.c | 27 |
1 files changed, 20 insertions, 7 deletions
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 57f9a2f51085..1a8198163b80 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -783,16 +783,23 @@ 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 struct sk_buff *flexcan_mailbox_read(struct can_rx_offload *offload, + unsigned int n, u32 *timestamp, + bool drop) { struct flexcan_priv *priv = rx_offload_to_priv(offload); struct flexcan_regs __iomem *regs = priv->regs; struct flexcan_mb __iomem *mb; + struct sk_buff *skb; + struct can_frame *cf; u32 reg_ctrl, reg_id, reg_iflag1; int i; + if (unlikely(drop)) { + skb = ERR_PTR(-ENOBUFS); + goto mark_as_read; + } + mb = flexcan_get_mb(priv, n); if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) { @@ -806,7 +813,7 @@ static unsigned int flexcan_mailbox_read(struct can_rx_offload *offload, code = reg_ctrl & FLEXCAN_MB_CODE_MASK; if ((code != FLEXCAN_MB_CODE_RX_FULL) && (code != FLEXCAN_MB_CODE_RX_OVERRUN)) - return 0; + return NULL; if (code == FLEXCAN_MB_CODE_RX_OVERRUN) { /* This MB was overrun, we lost data */ @@ -816,11 +823,17 @@ static unsigned int flexcan_mailbox_read(struct can_rx_offload *offload, } else { reg_iflag1 = priv->read(®s->iflag1); if (!(reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE)) - return 0; + return NULL; reg_ctrl = priv->read(&mb->can_ctrl); } + skb = alloc_can_skb(offload->dev, &cf); + if (!skb) { + skb = ERR_PTR(-ENOMEM); + goto mark_as_read; + } + /* increase timstamp to full 32 bit */ *timestamp = reg_ctrl << 16; @@ -839,7 +852,7 @@ static unsigned int flexcan_mailbox_read(struct can_rx_offload *offload, *(__be32 *)(cf->data + i) = data; } - /* mark as read */ + mark_as_read: if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) { /* Clear IRQ */ if (n < 32) @@ -856,7 +869,7 @@ static unsigned int flexcan_mailbox_read(struct can_rx_offload *offload, */ priv->read(®s->timer); - return 1; + return skb; } |