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.
Unified · Split
| @@ -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 | ||
| 786 | static unsigned int flexcan_mailbox_read(struct can_rx_offload *offload, | 786 | static 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(®s->iflag1); | 824 | reg_iflag1 = priv->read(®s->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(®s->timer); | 870 | priv->read(®s->timer); |
| 858 | 871 | ||
| 859 | return 1; | 872 | return skb; |
| 860 | } | 873 | } |
| 861 | 874 | ||
| 862 | 875 | ||
| @@ -139,71 +139,35 @@ static int can_rx_offload_compare(struct sk_buff *a, struct sk_buff *b) · 138 unmodified lines | |||
| 139 | static struct sk_buff * | 139 | static struct sk_buff * |
| 140 | can_rx_offload_offload_one(struct can_rx_offload *offload, unsigned int n) | 140 | can_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 | ×tamp, 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, ×tamp, 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 | ||
| @@ -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 | ||
| 538 | static unsigned int ti_hecc_mailbox_read(struct can_rx_offload *offload, | 538 | static 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 | ||
| 588 | static int ti_hecc_error(struct net_device *ndev, int int_status, | 602 | static int ti_hecc_error(struct net_device *ndev, int int_status, |
| @@ -15,9 +15,9 @@ · 14 unmodified lines | |||
| 15 | struct can_rx_offload { | 15 | struct 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; |