Skip to content

Commit 4e9c948

Browse files
Joakim Zhangmarckleinebudde
authored andcommitted
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 <[email protected]> Signed-off-by: Marc Kleine-Budde <[email protected]>
1 parent 61d2350 commit 4e9c948

File tree

4 files changed

+60
-69
lines changed

4 files changed

+60
-69
lines changed

drivers/net/can/flexcan.c

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -783,16 +783,23 @@ static inline struct flexcan_priv *rx_offload_to_priv(struct can_rx_offload *off
783783
return container_of(offload, struct flexcan_priv, offload);
784784
}
785785

786-
static unsigned int flexcan_mailbox_read(struct can_rx_offload *offload,
787-
struct can_frame *cf,
788-
u32 *timestamp, unsigned int n)
786+
static struct sk_buff *flexcan_mailbox_read(struct can_rx_offload *offload,
787+
unsigned int n, u32 *timestamp,
788+
bool drop)
789789
{
790790
struct flexcan_priv *priv = rx_offload_to_priv(offload);
791791
struct flexcan_regs __iomem *regs = priv->regs;
792792
struct flexcan_mb __iomem *mb;
793+
struct sk_buff *skb;
794+
struct can_frame *cf;
793795
u32 reg_ctrl, reg_id, reg_iflag1;
794796
int i;
795797

798+
if (unlikely(drop)) {
799+
skb = ERR_PTR(-ENOBUFS);
800+
goto mark_as_read;
801+
}
802+
796803
mb = flexcan_get_mb(priv, n);
797804

798805
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,
806813
code = reg_ctrl & FLEXCAN_MB_CODE_MASK;
807814
if ((code != FLEXCAN_MB_CODE_RX_FULL) &&
808815
(code != FLEXCAN_MB_CODE_RX_OVERRUN))
809-
return 0;
816+
return NULL;
810817

811818
if (code == FLEXCAN_MB_CODE_RX_OVERRUN) {
812819
/* This MB was overrun, we lost data */
@@ -816,11 +823,17 @@ static unsigned int flexcan_mailbox_read(struct can_rx_offload *offload,
816823
} else {
817824
reg_iflag1 = priv->read(&regs->iflag1);
818825
if (!(reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE))
819-
return 0;
826+
return NULL;
820827

821828
reg_ctrl = priv->read(&mb->can_ctrl);
822829
}
823830

831+
skb = alloc_can_skb(offload->dev, &cf);
832+
if (!skb) {
833+
skb = ERR_PTR(-ENOMEM);
834+
goto mark_as_read;
835+
}
836+
824837
/* increase timstamp to full 32 bit */
825838
*timestamp = reg_ctrl << 16;
826839

@@ -839,7 +852,7 @@ static unsigned int flexcan_mailbox_read(struct can_rx_offload *offload,
839852
*(__be32 *)(cf->data + i) = data;
840853
}
841854

842-
/* mark as read */
855+
mark_as_read:
843856
if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) {
844857
/* Clear IRQ */
845858
if (n < 32)
@@ -856,7 +869,7 @@ static unsigned int flexcan_mailbox_read(struct can_rx_offload *offload,
856869
*/
857870
priv->read(&regs->timer);
858871

859-
return 1;
872+
return skb;
860873
}
861874

862875

drivers/net/can/rx-offload.c

Lines changed: 17 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -139,71 +139,35 @@ static int can_rx_offload_compare(struct sk_buff *a, struct sk_buff *b)
139139
static struct sk_buff *
140140
can_rx_offload_offload_one(struct can_rx_offload *offload, unsigned int n)
141141
{
142-
struct sk_buff *skb = NULL, *skb_error = NULL;
142+
struct sk_buff *skb;
143143
struct can_rx_offload_cb *cb;
144-
struct can_frame *cf;
145-
int ret;
146-
147-
if (likely(skb_queue_len(&offload->skb_queue) <
148-
offload->skb_queue_len_max)) {
149-
skb = alloc_can_skb(offload->dev, &cf);
150-
if (unlikely(!skb))
151-
skb_error = ERR_PTR(-ENOMEM); /* skb alloc failed */
152-
} else {
153-
skb_error = ERR_PTR(-ENOBUFS); /* skb_queue is full */
154-
}
155-
156-
/* If queue is full or skb not available, drop by reading into
157-
* overflow buffer.
158-
*/
159-
if (unlikely(skb_error)) {
160-
struct can_frame cf_overflow;
161-
u32 timestamp;
162-
163-
ret = offload->mailbox_read(offload, &cf_overflow,
164-
&timestamp, n);
165-
166-
/* Mailbox was empty. */
167-
if (unlikely(!ret))
168-
return NULL;
169-
170-
/* Mailbox has been read and we're dropping it or
171-
* there was a problem reading the mailbox.
172-
*
173-
* Increment error counters in any case.
174-
*/
175-
offload->dev->stats.rx_dropped++;
176-
offload->dev->stats.rx_fifo_errors++;
177-
178-
/* There was a problem reading the mailbox, propagate
179-
* error value.
180-
*/
181-
if (unlikely(ret < 0))
182-
return ERR_PTR(ret);
183-
184-
return skb_error;
185-
}
144+
bool drop = false;
145+
u32 timestamp;
186146

187-
cb = can_rx_offload_get_cb(skb);
188-
ret = offload->mailbox_read(offload, cf, &cb->timestamp, n);
147+
/* If queue is full drop frame */
148+
if (unlikely(skb_queue_len(&offload->skb_queue) >
149+
offload->skb_queue_len_max))
150+
drop = true;
189151

152+
skb = offload->mailbox_read(offload, n, &timestamp, drop);
190153
/* Mailbox was empty. */
191-
if (unlikely(!ret)) {
192-
kfree_skb(skb);
154+
if (unlikely(!skb))
193155
return NULL;
194-
}
195-
196-
/* There was a problem reading the mailbox, propagate error value. */
197-
if (unlikely(ret < 0)) {
198-
kfree_skb(skb);
199156

157+
/* There was a problem reading the mailbox, propagate
158+
* error value.
159+
*/
160+
if (unlikely(IS_ERR(skb))) {
200161
offload->dev->stats.rx_dropped++;
201162
offload->dev->stats.rx_fifo_errors++;
202163

203-
return ERR_PTR(ret);
164+
return skb;
204165
}
205166

206167
/* Mailbox was read. */
168+
cb = can_rx_offload_get_cb(skb);
169+
cb->timestamp = timestamp;
170+
207171
return skb;
208172
}
209173

drivers/net/can/ti_hecc.c

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -535,15 +535,28 @@ struct ti_hecc_priv *rx_offload_to_priv(struct can_rx_offload *offload)
535535
return container_of(offload, struct ti_hecc_priv, offload);
536536
}
537537

538-
static unsigned int ti_hecc_mailbox_read(struct can_rx_offload *offload,
539-
struct can_frame *cf,
540-
u32 *timestamp, unsigned int mbxno)
538+
static struct sk_buff *ti_hecc_mailbox_read(struct can_rx_offload *offload,
539+
unsigned int mbxno, u32 *timestamp,
540+
bool drop)
541541
{
542542
struct ti_hecc_priv *priv = rx_offload_to_priv(offload);
543+
struct sk_buff *skb;
544+
struct can_frame *cf;
543545
u32 data, mbx_mask;
544-
int ret = 1;
545546

546547
mbx_mask = BIT(mbxno);
548+
549+
if (unlikely(drop)) {
550+
skb = ERR_PTR(-ENOBUFS);
551+
goto mark_as_read;
552+
}
553+
554+
skb = alloc_can_skb(offload->dev, &cf);
555+
if (unlikely(!skb)) {
556+
skb = ERR_PTR(-ENOMEM);
557+
goto mark_as_read;
558+
}
559+
547560
data = hecc_read_mbx(priv, mbxno, HECC_CANMID);
548561
if (data & HECC_CANMID_IDE)
549562
cf->can_id = (data & CAN_EFF_MASK) | CAN_EFF_FLAG;
@@ -578,11 +591,12 @@ static unsigned int ti_hecc_mailbox_read(struct can_rx_offload *offload,
578591
*/
579592
if (unlikely(mbxno == HECC_RX_LAST_MBOX &&
580593
hecc_read(priv, HECC_CANRML) & mbx_mask))
581-
ret = -ENOBUFS;
594+
skb = ERR_PTR(-ENOBUFS);
582595

596+
mark_as_read:
583597
hecc_write(priv, HECC_CANRMP, mbx_mask);
584598

585-
return ret;
599+
return skb;
586600
}
587601

588602
static int ti_hecc_error(struct net_device *ndev, int int_status,

include/linux/can/rx-offload.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@
1515
struct can_rx_offload {
1616
struct net_device *dev;
1717

18-
unsigned int (*mailbox_read)(struct can_rx_offload *offload,
19-
struct can_frame *cf,
20-
u32 *timestamp, unsigned int mb);
18+
struct sk_buff *(*mailbox_read)(struct can_rx_offload *offload,
19+
unsigned int mb, u32 *timestamp,
20+
bool drop);
2121

2222
struct sk_buff_head skb_queue;
2323
u32 skb_queue_len_max;

0 commit comments

Comments
 (0)