1 // SPDX-License-Identifier: GPL-2.0 2 // 3 // Copyright (c) 2023, 2024 Pengutronix, 4 // Marc Kleine-Budde <kernel@pengutronix.de> 5 // 6 7 #include <net/netdev_queues.h> 8 9 #include "rockchip_canfd.h" 10 11 static void rkcanfd_start_xmit_write_cmd(const struct rkcanfd_priv *priv, 12 const u32 reg_cmd) 13 { 14 rkcanfd_write(priv, RKCANFD_REG_CMD, reg_cmd); 15 } 16 17 void rkcanfd_xmit_retry(struct rkcanfd_priv *priv) 18 { 19 const unsigned int tx_head = rkcanfd_get_tx_head(priv); 20 const u32 reg_cmd = RKCANFD_REG_CMD_TX_REQ(tx_head); 21 22 rkcanfd_start_xmit_write_cmd(priv, reg_cmd); 23 } 24 25 int rkcanfd_start_xmit(struct sk_buff *skb, struct net_device *ndev) 26 { 27 struct rkcanfd_priv *priv = netdev_priv(ndev); 28 u32 reg_frameinfo, reg_id, reg_cmd; 29 unsigned int tx_head, frame_len; 30 const struct canfd_frame *cfd; 31 int err; 32 u8 i; 33 34 if (can_dropped_invalid_skb(ndev, skb)) 35 return NETDEV_TX_OK; 36 37 if (!netif_subqueue_maybe_stop(priv->ndev, 0, 38 rkcanfd_get_tx_free(priv), 39 RKCANFD_TX_STOP_THRESHOLD, 40 RKCANFD_TX_START_THRESHOLD)) { 41 if (net_ratelimit()) 42 netdev_info(priv->ndev, 43 "Stopping tx-queue (tx_head=0x%08x, tx_tail=0x%08x, tx_pending=%d)\n", 44 priv->tx_head, priv->tx_tail, 45 rkcanfd_get_tx_pending(priv)); 46 47 return NETDEV_TX_BUSY; 48 } 49 50 cfd = (struct canfd_frame *)skb->data; 51 52 if (cfd->can_id & CAN_EFF_FLAG) { 53 reg_frameinfo = RKCANFD_REG_FD_FRAMEINFO_FRAME_FORMAT; 54 reg_id = FIELD_PREP(RKCANFD_REG_FD_ID_EFF, cfd->can_id); 55 } else { 56 reg_frameinfo = 0; 57 reg_id = FIELD_PREP(RKCANFD_REG_FD_ID_SFF, cfd->can_id); 58 } 59 60 if (cfd->can_id & CAN_RTR_FLAG) 61 reg_frameinfo |= RKCANFD_REG_FD_FRAMEINFO_RTR; 62 63 if (can_is_canfd_skb(skb)) { 64 reg_frameinfo |= RKCANFD_REG_FD_FRAMEINFO_FDF; 65 66 if (cfd->flags & CANFD_BRS) 67 reg_frameinfo |= RKCANFD_REG_FD_FRAMEINFO_BRS; 68 69 reg_frameinfo |= FIELD_PREP(RKCANFD_REG_FD_FRAMEINFO_DATA_LENGTH, 70 can_fd_len2dlc(cfd->len)); 71 } else { 72 reg_frameinfo |= FIELD_PREP(RKCANFD_REG_FD_FRAMEINFO_DATA_LENGTH, 73 cfd->len); 74 } 75 76 tx_head = rkcanfd_get_tx_head(priv); 77 reg_cmd = RKCANFD_REG_CMD_TX_REQ(tx_head); 78 79 rkcanfd_write(priv, RKCANFD_REG_FD_TXFRAMEINFO, reg_frameinfo); 80 rkcanfd_write(priv, RKCANFD_REG_FD_TXID, reg_id); 81 for (i = 0; i < cfd->len; i += 4) 82 rkcanfd_write(priv, RKCANFD_REG_FD_TXDATA0 + i, 83 *(u32 *)(cfd->data + i)); 84 85 frame_len = can_skb_get_frame_len(skb); 86 err = can_put_echo_skb(skb, ndev, tx_head, frame_len); 87 if (!err) 88 netdev_sent_queue(priv->ndev, frame_len); 89 90 WRITE_ONCE(priv->tx_head, priv->tx_head + 1); 91 92 rkcanfd_start_xmit_write_cmd(priv, reg_cmd); 93 94 netif_subqueue_maybe_stop(priv->ndev, 0, 95 rkcanfd_get_tx_free(priv), 96 RKCANFD_TX_STOP_THRESHOLD, 97 RKCANFD_TX_START_THRESHOLD); 98 99 return NETDEV_TX_OK; 100 } 101 102 void rkcanfd_handle_tx_done_one(struct rkcanfd_priv *priv, const u32 ts, 103 unsigned int *frame_len_p) 104 { 105 struct net_device_stats *stats = &priv->ndev->stats; 106 unsigned int tx_tail; 107 108 tx_tail = rkcanfd_get_tx_tail(priv); 109 stats->tx_bytes += 110 can_rx_offload_get_echo_skb_queue_timestamp(&priv->offload, 111 tx_tail, ts, 112 frame_len_p); 113 stats->tx_packets++; 114 } 115