History

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.

Joakim Zhang committed 7 years ago

Commit 4e9c9481 parent 61d23504 files · +60 −69Browse files

Unified · Split

4 files
  1. drivers/net/can/flexcan.c +20 −7
  2. drivers/net/can/rx-offload.c +17 −53
  3. drivers/net/can/ti_hecc.c +20 −6
  4. include/linux/can/rx-offload.h +3 −3
drivers/net/can/flexcan.c+20−7
@@ -783,16 +783,23 @@ static inline struct flexcan_priv *rx_offload_to_priv(struct can_rx_offload *off · 782 unmodified lines
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, · 7 unmodified lines
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, · 3 unmodified lines
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, · 12 unmodified lines
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, · 10 unmodified lines
856869 */
857870 priv->read(&regs->timer);
858871
859− return 1;
872+ return skb;
860873 }
861874
862875
drivers/net/can/rx-offload.c+17−53
@@ -139,71 +139,35 @@ static int can_rx_offload_compare(struct sk_buff *a, struct sk_buff *b) · 138 unmodified lines
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+20−6
@@ -535,15 +535,28 @@ struct ti_hecc_priv *rx_offload_to_priv(struct can_rx_offload *offload) · 534 unmodified lines
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, · 28 unmodified lines
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+3−3
@@ -15,9 +15,9 @@ · 14 unmodified lines
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;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t