0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <asm/unaligned.h>
0016 #include <linux/bitfield.h>
0017
0018 #include "mcp251xfd.h"
0019
0020 static inline struct
0021 mcp251xfd_tx_obj *mcp251xfd_get_tx_obj_next(struct mcp251xfd_tx_ring *tx_ring)
0022 {
0023 u8 tx_head;
0024
0025 tx_head = mcp251xfd_get_tx_head(tx_ring);
0026
0027 return &tx_ring->obj[tx_head];
0028 }
0029
0030 static void
0031 mcp251xfd_tx_obj_from_skb(const struct mcp251xfd_priv *priv,
0032 struct mcp251xfd_tx_obj *tx_obj,
0033 const struct sk_buff *skb,
0034 unsigned int seq)
0035 {
0036 const struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
0037 struct mcp251xfd_hw_tx_obj_raw *hw_tx_obj;
0038 union mcp251xfd_tx_obj_load_buf *load_buf;
0039 u8 dlc;
0040 u32 id, flags;
0041 int len_sanitized = 0, len;
0042
0043 if (cfd->can_id & CAN_EFF_FLAG) {
0044 u32 sid, eid;
0045
0046 sid = FIELD_GET(MCP251XFD_REG_FRAME_EFF_SID_MASK, cfd->can_id);
0047 eid = FIELD_GET(MCP251XFD_REG_FRAME_EFF_EID_MASK, cfd->can_id);
0048
0049 id = FIELD_PREP(MCP251XFD_OBJ_ID_EID_MASK, eid) |
0050 FIELD_PREP(MCP251XFD_OBJ_ID_SID_MASK, sid);
0051
0052 flags = MCP251XFD_OBJ_FLAGS_IDE;
0053 } else {
0054 id = FIELD_PREP(MCP251XFD_OBJ_ID_SID_MASK, cfd->can_id);
0055 flags = 0;
0056 }
0057
0058
0059
0060
0061
0062 flags |= FIELD_PREP(MCP251XFD_OBJ_FLAGS_SEQ_MCP2518FD_MASK, seq);
0063
0064 if (cfd->can_id & CAN_RTR_FLAG)
0065 flags |= MCP251XFD_OBJ_FLAGS_RTR;
0066 else
0067 len_sanitized = canfd_sanitize_len(cfd->len);
0068
0069
0070 if (can_is_canfd_skb(skb)) {
0071 if (cfd->flags & CANFD_ESI)
0072 flags |= MCP251XFD_OBJ_FLAGS_ESI;
0073
0074 flags |= MCP251XFD_OBJ_FLAGS_FDF;
0075
0076 if (cfd->flags & CANFD_BRS)
0077 flags |= MCP251XFD_OBJ_FLAGS_BRS;
0078
0079 dlc = can_fd_len2dlc(cfd->len);
0080 } else {
0081 dlc = can_get_cc_dlc((struct can_frame *)cfd,
0082 priv->can.ctrlmode);
0083 }
0084
0085 flags |= FIELD_PREP(MCP251XFD_OBJ_FLAGS_DLC_MASK, dlc);
0086
0087 load_buf = &tx_obj->buf;
0088 if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_TX)
0089 hw_tx_obj = &load_buf->crc.hw_tx_obj;
0090 else
0091 hw_tx_obj = &load_buf->nocrc.hw_tx_obj;
0092
0093 put_unaligned_le32(id, &hw_tx_obj->id);
0094 put_unaligned_le32(flags, &hw_tx_obj->flags);
0095
0096
0097 memcpy(hw_tx_obj->data, cfd->data, cfd->len);
0098
0099
0100 if (MCP251XFD_SANITIZE_CAN && len_sanitized) {
0101 int pad_len;
0102
0103 pad_len = len_sanitized - cfd->len;
0104 if (pad_len)
0105 memset(hw_tx_obj->data + cfd->len, 0x0, pad_len);
0106 }
0107
0108
0109 len = sizeof(hw_tx_obj->id) + sizeof(hw_tx_obj->flags);
0110 if (MCP251XFD_SANITIZE_CAN)
0111 len += round_up(len_sanitized, sizeof(u32));
0112 else
0113 len += round_up(cfd->len, sizeof(u32));
0114
0115 if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_TX) {
0116 u16 crc;
0117
0118 mcp251xfd_spi_cmd_crc_set_len_in_ram(&load_buf->crc.cmd,
0119 len);
0120
0121 len += sizeof(load_buf->crc.cmd);
0122 crc = mcp251xfd_crc16_compute(&load_buf->crc, len);
0123 put_unaligned_be16(crc, (void *)load_buf + len);
0124
0125
0126 len += sizeof(load_buf->crc.crc);
0127 } else {
0128 len += sizeof(load_buf->nocrc.cmd);
0129 }
0130
0131 tx_obj->xfer[0].len = len;
0132 }
0133
0134 static int mcp251xfd_tx_obj_write(const struct mcp251xfd_priv *priv,
0135 struct mcp251xfd_tx_obj *tx_obj)
0136 {
0137 return spi_async(priv->spi, &tx_obj->msg);
0138 }
0139
0140 static bool mcp251xfd_tx_busy(const struct mcp251xfd_priv *priv,
0141 struct mcp251xfd_tx_ring *tx_ring)
0142 {
0143 if (mcp251xfd_get_tx_free(tx_ring) > 0)
0144 return false;
0145
0146 netif_stop_queue(priv->ndev);
0147
0148
0149 smp_mb();
0150
0151 if (mcp251xfd_get_tx_free(tx_ring) == 0) {
0152 netdev_dbg(priv->ndev,
0153 "Stopping tx-queue (tx_head=0x%08x, tx_tail=0x%08x, len=%d).\n",
0154 tx_ring->head, tx_ring->tail,
0155 tx_ring->head - tx_ring->tail);
0156
0157 return true;
0158 }
0159
0160 netif_start_queue(priv->ndev);
0161
0162 return false;
0163 }
0164
0165 netdev_tx_t mcp251xfd_start_xmit(struct sk_buff *skb,
0166 struct net_device *ndev)
0167 {
0168 struct mcp251xfd_priv *priv = netdev_priv(ndev);
0169 struct mcp251xfd_tx_ring *tx_ring = priv->tx;
0170 struct mcp251xfd_tx_obj *tx_obj;
0171 unsigned int frame_len;
0172 u8 tx_head;
0173 int err;
0174
0175 if (can_dropped_invalid_skb(ndev, skb))
0176 return NETDEV_TX_OK;
0177
0178 if (mcp251xfd_tx_busy(priv, tx_ring))
0179 return NETDEV_TX_BUSY;
0180
0181 tx_obj = mcp251xfd_get_tx_obj_next(tx_ring);
0182 mcp251xfd_tx_obj_from_skb(priv, tx_obj, skb, tx_ring->head);
0183
0184
0185 tx_head = mcp251xfd_get_tx_head(tx_ring);
0186 tx_ring->head++;
0187 if (mcp251xfd_get_tx_free(tx_ring) == 0)
0188 netif_stop_queue(ndev);
0189
0190 frame_len = can_skb_get_frame_len(skb);
0191 err = can_put_echo_skb(skb, ndev, tx_head, frame_len);
0192 if (!err)
0193 netdev_sent_queue(priv->ndev, frame_len);
0194
0195 err = mcp251xfd_tx_obj_write(priv, tx_obj);
0196 if (err)
0197 goto out_err;
0198
0199 return NETDEV_TX_OK;
0200
0201 out_err:
0202 netdev_err(priv->ndev, "ERROR in %s: %d\n", __func__, err);
0203
0204 return NETDEV_TX_OK;
0205 }