xref: /linux/drivers/net/can/rockchip/rockchip_canfd-tx.c (revision c7546e2c3cb739a3c1a2f5acaf9bb629d401afe5)
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 bool rkcanfd_tx_tail_is_eff(const struct rkcanfd_priv *priv)
12 {
13 	const struct canfd_frame *cfd;
14 	const struct sk_buff *skb;
15 	unsigned int tx_tail;
16 
17 	if (!rkcanfd_get_tx_pending(priv))
18 		return false;
19 
20 	tx_tail = rkcanfd_get_tx_tail(priv);
21 	skb = priv->can.echo_skb[tx_tail];
22 	if (!skb) {
23 		netdev_err(priv->ndev,
24 			   "%s: echo_skb[%u]=NULL tx_head=0x%08x tx_tail=0x%08x\n",
25 			   __func__, tx_tail,
26 			   priv->tx_head, priv->tx_tail);
27 
28 		return false;
29 	}
30 
31 	cfd = (struct canfd_frame *)skb->data;
32 
33 	return cfd->can_id & CAN_EFF_FLAG;
34 }
35 
36 unsigned int rkcanfd_get_effective_tx_free(const struct rkcanfd_priv *priv)
37 {
38 	if (priv->devtype_data.quirks & RKCANFD_QUIRK_RK3568_ERRATUM_6 &&
39 	    rkcanfd_tx_tail_is_eff(priv))
40 		return 0;
41 
42 	return rkcanfd_get_tx_free(priv);
43 }
44 
45 static void rkcanfd_start_xmit_write_cmd(const struct rkcanfd_priv *priv,
46 					 const u32 reg_cmd)
47 {
48 	if (priv->devtype_data.quirks & RKCANFD_QUIRK_RK3568_ERRATUM_12)
49 		rkcanfd_write(priv, RKCANFD_REG_MODE, priv->reg_mode_default |
50 			      RKCANFD_REG_MODE_SPACE_RX_MODE);
51 
52 	rkcanfd_write(priv, RKCANFD_REG_CMD, reg_cmd);
53 
54 	if (priv->devtype_data.quirks & RKCANFD_QUIRK_RK3568_ERRATUM_12)
55 		rkcanfd_write(priv, RKCANFD_REG_MODE, priv->reg_mode_default);
56 }
57 
58 void rkcanfd_xmit_retry(struct rkcanfd_priv *priv)
59 {
60 	const unsigned int tx_head = rkcanfd_get_tx_head(priv);
61 	const u32 reg_cmd = RKCANFD_REG_CMD_TX_REQ(tx_head);
62 
63 	rkcanfd_start_xmit_write_cmd(priv, reg_cmd);
64 }
65 
66 netdev_tx_t rkcanfd_start_xmit(struct sk_buff *skb, struct net_device *ndev)
67 {
68 	struct rkcanfd_priv *priv = netdev_priv(ndev);
69 	u32 reg_frameinfo, reg_id, reg_cmd;
70 	unsigned int tx_head, frame_len;
71 	const struct canfd_frame *cfd;
72 	int err;
73 	u8 i;
74 
75 	if (can_dropped_invalid_skb(ndev, skb))
76 		return NETDEV_TX_OK;
77 
78 	if (!netif_subqueue_maybe_stop(priv->ndev, 0,
79 				       rkcanfd_get_effective_tx_free(priv),
80 				       RKCANFD_TX_STOP_THRESHOLD,
81 				       RKCANFD_TX_START_THRESHOLD)) {
82 		if (net_ratelimit())
83 			netdev_info(priv->ndev,
84 				    "Stopping tx-queue (tx_head=0x%08x, tx_tail=0x%08x, tx_pending=%d)\n",
85 				    priv->tx_head, priv->tx_tail,
86 				    rkcanfd_get_tx_pending(priv));
87 
88 		return NETDEV_TX_BUSY;
89 	}
90 
91 	cfd = (struct canfd_frame *)skb->data;
92 
93 	if (cfd->can_id & CAN_EFF_FLAG) {
94 		reg_frameinfo = RKCANFD_REG_FD_FRAMEINFO_FRAME_FORMAT;
95 		reg_id = FIELD_PREP(RKCANFD_REG_FD_ID_EFF, cfd->can_id);
96 	} else {
97 		reg_frameinfo = 0;
98 		reg_id = FIELD_PREP(RKCANFD_REG_FD_ID_SFF, cfd->can_id);
99 	}
100 
101 	if (cfd->can_id & CAN_RTR_FLAG)
102 		reg_frameinfo |= RKCANFD_REG_FD_FRAMEINFO_RTR;
103 
104 	if (can_is_canfd_skb(skb)) {
105 		reg_frameinfo |= RKCANFD_REG_FD_FRAMEINFO_FDF;
106 
107 		if (cfd->flags & CANFD_BRS)
108 			reg_frameinfo |= RKCANFD_REG_FD_FRAMEINFO_BRS;
109 
110 		reg_frameinfo |= FIELD_PREP(RKCANFD_REG_FD_FRAMEINFO_DATA_LENGTH,
111 					    can_fd_len2dlc(cfd->len));
112 	} else {
113 		reg_frameinfo |= FIELD_PREP(RKCANFD_REG_FD_FRAMEINFO_DATA_LENGTH,
114 					    cfd->len);
115 	}
116 
117 	tx_head = rkcanfd_get_tx_head(priv);
118 	reg_cmd = RKCANFD_REG_CMD_TX_REQ(tx_head);
119 
120 	rkcanfd_write(priv, RKCANFD_REG_FD_TXFRAMEINFO, reg_frameinfo);
121 	rkcanfd_write(priv, RKCANFD_REG_FD_TXID, reg_id);
122 	for (i = 0; i < cfd->len; i += 4)
123 		rkcanfd_write(priv, RKCANFD_REG_FD_TXDATA0 + i,
124 			      *(u32 *)(cfd->data + i));
125 
126 	frame_len = can_skb_get_frame_len(skb);
127 	err = can_put_echo_skb(skb, ndev, tx_head, frame_len);
128 	if (!err)
129 		netdev_sent_queue(priv->ndev, frame_len);
130 
131 	WRITE_ONCE(priv->tx_head, priv->tx_head + 1);
132 
133 	rkcanfd_start_xmit_write_cmd(priv, reg_cmd);
134 
135 	netif_subqueue_maybe_stop(priv->ndev, 0,
136 				  rkcanfd_get_effective_tx_free(priv),
137 				  RKCANFD_TX_STOP_THRESHOLD,
138 				  RKCANFD_TX_START_THRESHOLD);
139 
140 	return NETDEV_TX_OK;
141 }
142 
143 void rkcanfd_handle_tx_done_one(struct rkcanfd_priv *priv, const u32 ts,
144 				unsigned int *frame_len_p)
145 {
146 	struct net_device_stats *stats = &priv->ndev->stats;
147 	unsigned int tx_tail;
148 	struct sk_buff *skb;
149 
150 	tx_tail = rkcanfd_get_tx_tail(priv);
151 	skb = priv->can.echo_skb[tx_tail];
152 
153 	/* Manual handling of CAN Bus Error counters. See
154 	 * rkcanfd_get_corrected_berr_counter() for detailed
155 	 * explanation.
156 	 */
157 	if (priv->bec.txerr)
158 		priv->bec.txerr--;
159 
160 	if (skb)
161 		rkcanfd_skb_set_timestamp(priv, skb, ts);
162 	stats->tx_bytes +=
163 		can_rx_offload_get_echo_skb_queue_timestamp(&priv->offload,
164 							    tx_tail, ts,
165 							    frame_len_p);
166 	stats->tx_packets++;
167 }
168