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
783 return container_of(offload, struct flexcan_priv, offload);783 return container_of(offload, struct flexcan_priv, offload);
784}784}
785 785
786static unsigned int flexcan_mailbox_read(struct can_rx_offload *offload,786static struct sk_buff *flexcan_mailbox_read(struct can_rx_offload *offload,
787 struct can_frame *cf,787 unsigned int n, u32 *timestamp,
788 u32 *timestamp, unsigned int n)788 bool drop)
789{789{
790 struct flexcan_priv *priv = rx_offload_to_priv(offload);790 struct flexcan_priv *priv = rx_offload_to_priv(offload);
791 struct flexcan_regs __iomem *regs = priv->regs;791 struct flexcan_regs __iomem *regs = priv->regs;
792 struct flexcan_mb __iomem *mb;792 struct flexcan_mb __iomem *mb;
793 struct sk_buff *skb;
794 struct can_frame *cf;
793 u32 reg_ctrl, reg_id, reg_iflag1;795 u32 reg_ctrl, reg_id, reg_iflag1;
794 int i;796 int i;
795 797
798 if (unlikely(drop)) {
799 skb = ERR_PTR(-ENOBUFS);
800 goto mark_as_read;
801 }
802
796 mb = flexcan_get_mb(priv, n);803 mb = flexcan_get_mb(priv, n);
797 804
798 if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) {805 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
806 code = reg_ctrl & FLEXCAN_MB_CODE_MASK;813 code = reg_ctrl & FLEXCAN_MB_CODE_MASK;
807 if ((code != FLEXCAN_MB_CODE_RX_FULL) &&814 if ((code != FLEXCAN_MB_CODE_RX_FULL) &&
808 (code != FLEXCAN_MB_CODE_RX_OVERRUN))815 (code != FLEXCAN_MB_CODE_RX_OVERRUN))
809 return 0;816 return NULL;
810 817
811 if (code == FLEXCAN_MB_CODE_RX_OVERRUN) {818 if (code == FLEXCAN_MB_CODE_RX_OVERRUN) {
812 /* This MB was overrun, we lost data */819 /* 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
816 } else {823 } else {
817 reg_iflag1 = priv->read(&regs->iflag1);824 reg_iflag1 = priv->read(&regs->iflag1);
818 if (!(reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE))825 if (!(reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE))
819 return 0;826 return NULL;
820 827
821 reg_ctrl = priv->read(&mb->can_ctrl);828 reg_ctrl = priv->read(&mb->can_ctrl);
822 }829 }
823 830
831 skb = alloc_can_skb(offload->dev, &cf);
832 if (!skb) {
833 skb = ERR_PTR(-ENOMEM);
834 goto mark_as_read;
835 }
836
824 /* increase timstamp to full 32 bit */837 /* increase timstamp to full 32 bit */
825 *timestamp = reg_ctrl << 16;838 *timestamp = reg_ctrl << 16;
826 839
@@ -839,7 +852,7 @@ static unsigned int flexcan_mailbox_read(struct can_rx_offload *offload, · 12 unmodified lines
839 *(__be32 *)(cf->data + i) = data;852 *(__be32 *)(cf->data + i) = data;
840 }853 }
841 854
842 /* mark as read */855 mark_as_read:
843 if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) {856 if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) {
844 /* Clear IRQ */857 /* Clear IRQ */
845 if (n < 32)858 if (n < 32)
@@ -856,7 +869,7 @@ static unsigned int flexcan_mailbox_read(struct can_rx_offload *offload, · 10 unmodified lines
856 */869 */
857 priv->read(&regs->timer);870 priv->read(&regs->timer);
858 871
859 return 1;872 return skb;
860}873}
861 874
862 875
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
139static struct sk_buff *139static struct sk_buff *
140can_rx_offload_offload_one(struct can_rx_offload *offload, unsigned int n)140can_rx_offload_offload_one(struct can_rx_offload *offload, unsigned int n)
141{141{
142 struct sk_buff *skb = NULL, *skb_error = NULL;142 struct sk_buff *skb;
143 struct can_rx_offload_cb *cb;143 struct can_rx_offload_cb *cb;
144 struct can_frame *cf;144 bool drop = false;
145 int ret;145 u32 timestamp;
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 }
186 146
187 cb = can_rx_offload_get_cb(skb);147 /* If queue is full drop frame */
188 ret = offload->mailbox_read(offload, cf, &cb->timestamp, n);148 if (unlikely(skb_queue_len(&offload->skb_queue) >
149 offload->skb_queue_len_max))
150 drop = true;
189 151
152 skb = offload->mailbox_read(offload, n, &timestamp, drop);
190 /* Mailbox was empty. */153 /* Mailbox was empty. */
191 if (unlikely(!ret)) {154 if (unlikely(!skb))
192 kfree_skb(skb);
193 return NULL;155 return NULL;
194 }
195
196 /* There was a problem reading the mailbox, propagate error value. */
197 if (unlikely(ret < 0)) {
198 kfree_skb(skb);
199 156
157 /* There was a problem reading the mailbox, propagate
158 * error value.
159 */
160 if (unlikely(IS_ERR(skb))) {
200 offload->dev->stats.rx_dropped++;161 offload->dev->stats.rx_dropped++;
201 offload->dev->stats.rx_fifo_errors++;162 offload->dev->stats.rx_fifo_errors++;
202 163
203 return ERR_PTR(ret);164 return skb;
204 }165 }
205 166
206 /* Mailbox was read. */167 /* Mailbox was read. */
168 cb = can_rx_offload_get_cb(skb);
169 cb->timestamp = timestamp;
170
207 return skb;171 return skb;
208}172}
209 173
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
535 return container_of(offload, struct ti_hecc_priv, offload);535 return container_of(offload, struct ti_hecc_priv, offload);
536}536}
537 537
538static unsigned int ti_hecc_mailbox_read(struct can_rx_offload *offload,538static struct sk_buff *ti_hecc_mailbox_read(struct can_rx_offload *offload,
539 struct can_frame *cf,539 unsigned int mbxno, u32 *timestamp,
540 u32 *timestamp, unsigned int mbxno)540 bool drop)
541{541{
542 struct ti_hecc_priv *priv = rx_offload_to_priv(offload);542 struct ti_hecc_priv *priv = rx_offload_to_priv(offload);
543 struct sk_buff *skb;
544 struct can_frame *cf;
543 u32 data, mbx_mask;545 u32 data, mbx_mask;
544 int ret = 1;
545 546
546 mbx_mask = BIT(mbxno);547 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
547 data = hecc_read_mbx(priv, mbxno, HECC_CANMID);560 data = hecc_read_mbx(priv, mbxno, HECC_CANMID);
548 if (data & HECC_CANMID_IDE)561 if (data & HECC_CANMID_IDE)
549 cf->can_id = (data & CAN_EFF_MASK) | CAN_EFF_FLAG;562 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
578 */591 */
579 if (unlikely(mbxno == HECC_RX_LAST_MBOX &&592 if (unlikely(mbxno == HECC_RX_LAST_MBOX &&
580 hecc_read(priv, HECC_CANRML) & mbx_mask))593 hecc_read(priv, HECC_CANRML) & mbx_mask))
581 ret = -ENOBUFS;594 skb = ERR_PTR(-ENOBUFS);
582 595
596 mark_as_read:
583 hecc_write(priv, HECC_CANRMP, mbx_mask);597 hecc_write(priv, HECC_CANRMP, mbx_mask);
584 598
585 return ret;599 return skb;
586}600}
587 601
588static int ti_hecc_error(struct net_device *ndev, int int_status,602static 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
15struct can_rx_offload {15struct can_rx_offload {
16 struct net_device *dev;16 struct net_device *dev;
17 17
18 unsigned int (*mailbox_read)(struct can_rx_offload *offload,18 struct sk_buff *(*mailbox_read)(struct can_rx_offload *offload,
19 struct can_frame *cf,19 unsigned int mb, u32 *timestamp,
20 u32 *timestamp, unsigned int mb);20 bool drop);
21 21
22 struct sk_buff_head skb_queue;22 struct sk_buff_head skb_queue;
23 u32 skb_queue_len_max;23 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