0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <linux/bitfield.h>
0016
0017 #include "mcp251xfd.h"
0018
0019 static inline int
0020 mcp251xfd_rx_head_get_from_chip(const struct mcp251xfd_priv *priv,
0021 const struct mcp251xfd_rx_ring *ring,
0022 u8 *rx_head, bool *fifo_empty)
0023 {
0024 u32 fifo_sta;
0025 int err;
0026
0027 err = regmap_read(priv->map_reg, MCP251XFD_REG_FIFOSTA(ring->fifo_nr),
0028 &fifo_sta);
0029 if (err)
0030 return err;
0031
0032 *rx_head = FIELD_GET(MCP251XFD_REG_FIFOSTA_FIFOCI_MASK, fifo_sta);
0033 *fifo_empty = !(fifo_sta & MCP251XFD_REG_FIFOSTA_TFNRFNIF);
0034
0035 return 0;
0036 }
0037
0038 static inline int
0039 mcp251xfd_rx_tail_get_from_chip(const struct mcp251xfd_priv *priv,
0040 const struct mcp251xfd_rx_ring *ring,
0041 u8 *rx_tail)
0042 {
0043 u32 fifo_ua;
0044 int err;
0045
0046 err = regmap_read(priv->map_reg, MCP251XFD_REG_FIFOUA(ring->fifo_nr),
0047 &fifo_ua);
0048 if (err)
0049 return err;
0050
0051 fifo_ua -= ring->base - MCP251XFD_RAM_START;
0052 *rx_tail = fifo_ua / ring->obj_size;
0053
0054 return 0;
0055 }
0056
0057 static int
0058 mcp251xfd_check_rx_tail(const struct mcp251xfd_priv *priv,
0059 const struct mcp251xfd_rx_ring *ring)
0060 {
0061 u8 rx_tail_chip, rx_tail;
0062 int err;
0063
0064 if (!IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY))
0065 return 0;
0066
0067 err = mcp251xfd_rx_tail_get_from_chip(priv, ring, &rx_tail_chip);
0068 if (err)
0069 return err;
0070
0071 rx_tail = mcp251xfd_get_rx_tail(ring);
0072 if (rx_tail_chip != rx_tail) {
0073 netdev_err(priv->ndev,
0074 "RX tail of chip (%d) and ours (%d) inconsistent.\n",
0075 rx_tail_chip, rx_tail);
0076 return -EILSEQ;
0077 }
0078
0079 return 0;
0080 }
0081
0082 static int
0083 mcp251xfd_rx_ring_update(const struct mcp251xfd_priv *priv,
0084 struct mcp251xfd_rx_ring *ring)
0085 {
0086 u32 new_head;
0087 u8 chip_rx_head;
0088 bool fifo_empty;
0089 int err;
0090
0091 err = mcp251xfd_rx_head_get_from_chip(priv, ring, &chip_rx_head,
0092 &fifo_empty);
0093 if (err || fifo_empty)
0094 return err;
0095
0096
0097
0098
0099 new_head = round_down(ring->head, ring->obj_num) + chip_rx_head;
0100 if (new_head <= ring->head)
0101 new_head += ring->obj_num;
0102
0103 ring->head = new_head;
0104
0105 return mcp251xfd_check_rx_tail(priv, ring);
0106 }
0107
0108 static void
0109 mcp251xfd_hw_rx_obj_to_skb(const struct mcp251xfd_priv *priv,
0110 const struct mcp251xfd_hw_rx_obj_canfd *hw_rx_obj,
0111 struct sk_buff *skb)
0112 {
0113 struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
0114 u8 dlc;
0115
0116 if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_IDE) {
0117 u32 sid, eid;
0118
0119 eid = FIELD_GET(MCP251XFD_OBJ_ID_EID_MASK, hw_rx_obj->id);
0120 sid = FIELD_GET(MCP251XFD_OBJ_ID_SID_MASK, hw_rx_obj->id);
0121
0122 cfd->can_id = CAN_EFF_FLAG |
0123 FIELD_PREP(MCP251XFD_REG_FRAME_EFF_EID_MASK, eid) |
0124 FIELD_PREP(MCP251XFD_REG_FRAME_EFF_SID_MASK, sid);
0125 } else {
0126 cfd->can_id = FIELD_GET(MCP251XFD_OBJ_ID_SID_MASK,
0127 hw_rx_obj->id);
0128 }
0129
0130 dlc = FIELD_GET(MCP251XFD_OBJ_FLAGS_DLC_MASK, hw_rx_obj->flags);
0131
0132
0133 if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_FDF) {
0134 if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_ESI)
0135 cfd->flags |= CANFD_ESI;
0136
0137 if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_BRS)
0138 cfd->flags |= CANFD_BRS;
0139
0140 cfd->len = can_fd_dlc2len(dlc);
0141 } else {
0142 if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_RTR)
0143 cfd->can_id |= CAN_RTR_FLAG;
0144
0145 can_frame_set_cc_len((struct can_frame *)cfd, dlc,
0146 priv->can.ctrlmode);
0147 }
0148
0149 if (!(hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_RTR))
0150 memcpy(cfd->data, hw_rx_obj->data, cfd->len);
0151
0152 mcp251xfd_skb_set_timestamp(priv, skb, hw_rx_obj->ts);
0153 }
0154
0155 static int
0156 mcp251xfd_handle_rxif_one(struct mcp251xfd_priv *priv,
0157 struct mcp251xfd_rx_ring *ring,
0158 const struct mcp251xfd_hw_rx_obj_canfd *hw_rx_obj)
0159 {
0160 struct net_device_stats *stats = &priv->ndev->stats;
0161 struct sk_buff *skb;
0162 struct canfd_frame *cfd;
0163 int err;
0164
0165 if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_FDF)
0166 skb = alloc_canfd_skb(priv->ndev, &cfd);
0167 else
0168 skb = alloc_can_skb(priv->ndev, (struct can_frame **)&cfd);
0169
0170 if (!skb) {
0171 stats->rx_dropped++;
0172 return 0;
0173 }
0174
0175 mcp251xfd_hw_rx_obj_to_skb(priv, hw_rx_obj, skb);
0176 err = can_rx_offload_queue_timestamp(&priv->offload, skb, hw_rx_obj->ts);
0177 if (err)
0178 stats->rx_fifo_errors++;
0179
0180 return 0;
0181 }
0182
0183 static inline int
0184 mcp251xfd_rx_obj_read(const struct mcp251xfd_priv *priv,
0185 const struct mcp251xfd_rx_ring *ring,
0186 struct mcp251xfd_hw_rx_obj_canfd *hw_rx_obj,
0187 const u8 offset, const u8 len)
0188 {
0189 const int val_bytes = regmap_get_val_bytes(priv->map_rx);
0190 int err;
0191
0192 err = regmap_bulk_read(priv->map_rx,
0193 mcp251xfd_get_rx_obj_addr(ring, offset),
0194 hw_rx_obj,
0195 len * ring->obj_size / val_bytes);
0196
0197 return err;
0198 }
0199
0200 static int
0201 mcp251xfd_handle_rxif_ring(struct mcp251xfd_priv *priv,
0202 struct mcp251xfd_rx_ring *ring)
0203 {
0204 struct mcp251xfd_hw_rx_obj_canfd *hw_rx_obj = ring->obj;
0205 u8 rx_tail, len;
0206 int err, i;
0207
0208 err = mcp251xfd_rx_ring_update(priv, ring);
0209 if (err)
0210 return err;
0211
0212 while ((len = mcp251xfd_get_rx_linear_len(ring))) {
0213 int offset;
0214
0215 rx_tail = mcp251xfd_get_rx_tail(ring);
0216
0217 err = mcp251xfd_rx_obj_read(priv, ring, hw_rx_obj,
0218 rx_tail, len);
0219 if (err)
0220 return err;
0221
0222 for (i = 0; i < len; i++) {
0223 err = mcp251xfd_handle_rxif_one(priv, ring,
0224 (void *)hw_rx_obj +
0225 i * ring->obj_size);
0226 if (err)
0227 return err;
0228 }
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239 offset = ARRAY_SIZE(ring->uinc_xfer) - len;
0240 err = spi_sync_transfer(priv->spi,
0241 ring->uinc_xfer + offset, len);
0242 if (err)
0243 return err;
0244
0245 ring->tail += len;
0246 }
0247
0248 return 0;
0249 }
0250
0251 int mcp251xfd_handle_rxif(struct mcp251xfd_priv *priv)
0252 {
0253 struct mcp251xfd_rx_ring *ring;
0254 int err, n;
0255
0256 mcp251xfd_for_each_rx_ring(priv, ring, n) {
0257
0258
0259
0260 if ((ring->nr > 0 || !priv->rx_obj_num_coalesce_irq) &&
0261 !(priv->regs_status.rxif & BIT(ring->fifo_nr)))
0262 continue;
0263
0264 err = mcp251xfd_handle_rxif_ring(priv, ring);
0265 if (err)
0266 return err;
0267 }
0268
0269 if (priv->rx_coalesce_usecs_irq)
0270 hrtimer_start(&priv->rx_irq_timer,
0271 ns_to_ktime(priv->rx_coalesce_usecs_irq *
0272 NSEC_PER_USEC),
0273 HRTIMER_MODE_REL);
0274
0275 return 0;
0276 }