1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /* Copyright (C) 2007, 2011 Wolfgang Grandegger <wg@grandegger.com>
3*4882a593Smuzhiyun * Copyright (C) 2012 Stephane Grosjean <s.grosjean@peak-system.com>
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2016 PEAK System-Technik GmbH
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #include <linux/can.h>
9*4882a593Smuzhiyun #include <linux/can/dev.h>
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun #include "peak_canfd_user.h"
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun /* internal IP core cache size (used as default echo skbs max number) */
14*4882a593Smuzhiyun #define PCANFD_ECHO_SKB_MAX 24
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun /* bittiming ranges of the PEAK-System PC CAN-FD interfaces */
17*4882a593Smuzhiyun static const struct can_bittiming_const peak_canfd_nominal_const = {
18*4882a593Smuzhiyun .name = "peak_canfd",
19*4882a593Smuzhiyun .tseg1_min = 1,
20*4882a593Smuzhiyun .tseg1_max = (1 << PUCAN_TSLOW_TSGEG1_BITS),
21*4882a593Smuzhiyun .tseg2_min = 1,
22*4882a593Smuzhiyun .tseg2_max = (1 << PUCAN_TSLOW_TSGEG2_BITS),
23*4882a593Smuzhiyun .sjw_max = (1 << PUCAN_TSLOW_SJW_BITS),
24*4882a593Smuzhiyun .brp_min = 1,
25*4882a593Smuzhiyun .brp_max = (1 << PUCAN_TSLOW_BRP_BITS),
26*4882a593Smuzhiyun .brp_inc = 1,
27*4882a593Smuzhiyun };
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun static const struct can_bittiming_const peak_canfd_data_const = {
30*4882a593Smuzhiyun .name = "peak_canfd",
31*4882a593Smuzhiyun .tseg1_min = 1,
32*4882a593Smuzhiyun .tseg1_max = (1 << PUCAN_TFAST_TSGEG1_BITS),
33*4882a593Smuzhiyun .tseg2_min = 1,
34*4882a593Smuzhiyun .tseg2_max = (1 << PUCAN_TFAST_TSGEG2_BITS),
35*4882a593Smuzhiyun .sjw_max = (1 << PUCAN_TFAST_SJW_BITS),
36*4882a593Smuzhiyun .brp_min = 1,
37*4882a593Smuzhiyun .brp_max = (1 << PUCAN_TFAST_BRP_BITS),
38*4882a593Smuzhiyun .brp_inc = 1,
39*4882a593Smuzhiyun };
40*4882a593Smuzhiyun
pucan_init_cmd(struct peak_canfd_priv * priv)41*4882a593Smuzhiyun static struct peak_canfd_priv *pucan_init_cmd(struct peak_canfd_priv *priv)
42*4882a593Smuzhiyun {
43*4882a593Smuzhiyun priv->cmd_len = 0;
44*4882a593Smuzhiyun return priv;
45*4882a593Smuzhiyun }
46*4882a593Smuzhiyun
pucan_add_cmd(struct peak_canfd_priv * priv,int cmd_op)47*4882a593Smuzhiyun static void *pucan_add_cmd(struct peak_canfd_priv *priv, int cmd_op)
48*4882a593Smuzhiyun {
49*4882a593Smuzhiyun struct pucan_command *cmd;
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun if (priv->cmd_len + sizeof(*cmd) > priv->cmd_maxlen)
52*4882a593Smuzhiyun return NULL;
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun cmd = priv->cmd_buffer + priv->cmd_len;
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun /* reset all unused bit to default */
57*4882a593Smuzhiyun memset(cmd, 0, sizeof(*cmd));
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun cmd->opcode_channel = pucan_cmd_opcode_channel(priv->index, cmd_op);
60*4882a593Smuzhiyun priv->cmd_len += sizeof(*cmd);
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun return cmd;
63*4882a593Smuzhiyun }
64*4882a593Smuzhiyun
pucan_write_cmd(struct peak_canfd_priv * priv)65*4882a593Smuzhiyun static int pucan_write_cmd(struct peak_canfd_priv *priv)
66*4882a593Smuzhiyun {
67*4882a593Smuzhiyun int err;
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun if (priv->pre_cmd) {
70*4882a593Smuzhiyun err = priv->pre_cmd(priv);
71*4882a593Smuzhiyun if (err)
72*4882a593Smuzhiyun return err;
73*4882a593Smuzhiyun }
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun err = priv->write_cmd(priv);
76*4882a593Smuzhiyun if (err)
77*4882a593Smuzhiyun return err;
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun if (priv->post_cmd)
80*4882a593Smuzhiyun err = priv->post_cmd(priv);
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun return err;
83*4882a593Smuzhiyun }
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun /* uCAN commands interface functions */
pucan_set_reset_mode(struct peak_canfd_priv * priv)86*4882a593Smuzhiyun static int pucan_set_reset_mode(struct peak_canfd_priv *priv)
87*4882a593Smuzhiyun {
88*4882a593Smuzhiyun pucan_add_cmd(pucan_init_cmd(priv), PUCAN_CMD_RESET_MODE);
89*4882a593Smuzhiyun return pucan_write_cmd(priv);
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun
pucan_set_normal_mode(struct peak_canfd_priv * priv)92*4882a593Smuzhiyun static int pucan_set_normal_mode(struct peak_canfd_priv *priv)
93*4882a593Smuzhiyun {
94*4882a593Smuzhiyun int err;
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun pucan_add_cmd(pucan_init_cmd(priv), PUCAN_CMD_NORMAL_MODE);
97*4882a593Smuzhiyun err = pucan_write_cmd(priv);
98*4882a593Smuzhiyun if (!err)
99*4882a593Smuzhiyun priv->can.state = CAN_STATE_ERROR_ACTIVE;
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun return err;
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun
pucan_set_listen_only_mode(struct peak_canfd_priv * priv)104*4882a593Smuzhiyun static int pucan_set_listen_only_mode(struct peak_canfd_priv *priv)
105*4882a593Smuzhiyun {
106*4882a593Smuzhiyun int err;
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun pucan_add_cmd(pucan_init_cmd(priv), PUCAN_CMD_LISTEN_ONLY_MODE);
109*4882a593Smuzhiyun err = pucan_write_cmd(priv);
110*4882a593Smuzhiyun if (!err)
111*4882a593Smuzhiyun priv->can.state = CAN_STATE_ERROR_ACTIVE;
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun return err;
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun
pucan_set_timing_slow(struct peak_canfd_priv * priv,const struct can_bittiming * pbt)116*4882a593Smuzhiyun static int pucan_set_timing_slow(struct peak_canfd_priv *priv,
117*4882a593Smuzhiyun const struct can_bittiming *pbt)
118*4882a593Smuzhiyun {
119*4882a593Smuzhiyun struct pucan_timing_slow *cmd;
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun cmd = pucan_add_cmd(pucan_init_cmd(priv), PUCAN_CMD_TIMING_SLOW);
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun cmd->sjw_t = PUCAN_TSLOW_SJW_T(pbt->sjw - 1,
124*4882a593Smuzhiyun priv->can.ctrlmode &
125*4882a593Smuzhiyun CAN_CTRLMODE_3_SAMPLES);
126*4882a593Smuzhiyun cmd->tseg1 = PUCAN_TSLOW_TSEG1(pbt->prop_seg + pbt->phase_seg1 - 1);
127*4882a593Smuzhiyun cmd->tseg2 = PUCAN_TSLOW_TSEG2(pbt->phase_seg2 - 1);
128*4882a593Smuzhiyun cmd->brp = cpu_to_le16(PUCAN_TSLOW_BRP(pbt->brp - 1));
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun cmd->ewl = 96; /* default */
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun netdev_dbg(priv->ndev,
133*4882a593Smuzhiyun "nominal: brp=%u tseg1=%u tseg2=%u sjw=%u\n",
134*4882a593Smuzhiyun le16_to_cpu(cmd->brp), cmd->tseg1, cmd->tseg2, cmd->sjw_t);
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun return pucan_write_cmd(priv);
137*4882a593Smuzhiyun }
138*4882a593Smuzhiyun
pucan_set_timing_fast(struct peak_canfd_priv * priv,const struct can_bittiming * pbt)139*4882a593Smuzhiyun static int pucan_set_timing_fast(struct peak_canfd_priv *priv,
140*4882a593Smuzhiyun const struct can_bittiming *pbt)
141*4882a593Smuzhiyun {
142*4882a593Smuzhiyun struct pucan_timing_fast *cmd;
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun cmd = pucan_add_cmd(pucan_init_cmd(priv), PUCAN_CMD_TIMING_FAST);
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun cmd->sjw = PUCAN_TFAST_SJW(pbt->sjw - 1);
147*4882a593Smuzhiyun cmd->tseg1 = PUCAN_TFAST_TSEG1(pbt->prop_seg + pbt->phase_seg1 - 1);
148*4882a593Smuzhiyun cmd->tseg2 = PUCAN_TFAST_TSEG2(pbt->phase_seg2 - 1);
149*4882a593Smuzhiyun cmd->brp = cpu_to_le16(PUCAN_TFAST_BRP(pbt->brp - 1));
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun netdev_dbg(priv->ndev,
152*4882a593Smuzhiyun "data: brp=%u tseg1=%u tseg2=%u sjw=%u\n",
153*4882a593Smuzhiyun le16_to_cpu(cmd->brp), cmd->tseg1, cmd->tseg2, cmd->sjw);
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun return pucan_write_cmd(priv);
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun
pucan_set_std_filter(struct peak_canfd_priv * priv,u8 row,u32 mask)158*4882a593Smuzhiyun static int pucan_set_std_filter(struct peak_canfd_priv *priv, u8 row, u32 mask)
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun struct pucan_std_filter *cmd;
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun cmd = pucan_add_cmd(pucan_init_cmd(priv), PUCAN_CMD_SET_STD_FILTER);
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun /* all the 11-bits CAN ID values are represented by one bit in a
165*4882a593Smuzhiyun * 64 rows array of 32 bits: the upper 6 bits of the CAN ID select the
166*4882a593Smuzhiyun * row while the lowest 5 bits select the bit in that row.
167*4882a593Smuzhiyun *
168*4882a593Smuzhiyun * bit filter
169*4882a593Smuzhiyun * 1 passed
170*4882a593Smuzhiyun * 0 discarded
171*4882a593Smuzhiyun */
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun /* select the row */
174*4882a593Smuzhiyun cmd->idx = row;
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun /* set/unset bits in the row */
177*4882a593Smuzhiyun cmd->mask = cpu_to_le32(mask);
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun return pucan_write_cmd(priv);
180*4882a593Smuzhiyun }
181*4882a593Smuzhiyun
pucan_tx_abort(struct peak_canfd_priv * priv,u16 flags)182*4882a593Smuzhiyun static int pucan_tx_abort(struct peak_canfd_priv *priv, u16 flags)
183*4882a593Smuzhiyun {
184*4882a593Smuzhiyun struct pucan_tx_abort *cmd;
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun cmd = pucan_add_cmd(pucan_init_cmd(priv), PUCAN_CMD_TX_ABORT);
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun cmd->flags = cpu_to_le16(flags);
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun return pucan_write_cmd(priv);
191*4882a593Smuzhiyun }
192*4882a593Smuzhiyun
pucan_clr_err_counters(struct peak_canfd_priv * priv)193*4882a593Smuzhiyun static int pucan_clr_err_counters(struct peak_canfd_priv *priv)
194*4882a593Smuzhiyun {
195*4882a593Smuzhiyun struct pucan_wr_err_cnt *cmd;
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun cmd = pucan_add_cmd(pucan_init_cmd(priv), PUCAN_CMD_WR_ERR_CNT);
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun cmd->sel_mask = cpu_to_le16(PUCAN_WRERRCNT_TE | PUCAN_WRERRCNT_RE);
200*4882a593Smuzhiyun cmd->tx_counter = 0;
201*4882a593Smuzhiyun cmd->rx_counter = 0;
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun return pucan_write_cmd(priv);
204*4882a593Smuzhiyun }
205*4882a593Smuzhiyun
pucan_set_options(struct peak_canfd_priv * priv,u16 opt_mask)206*4882a593Smuzhiyun static int pucan_set_options(struct peak_canfd_priv *priv, u16 opt_mask)
207*4882a593Smuzhiyun {
208*4882a593Smuzhiyun struct pucan_options *cmd;
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun cmd = pucan_add_cmd(pucan_init_cmd(priv), PUCAN_CMD_SET_EN_OPTION);
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun cmd->options = cpu_to_le16(opt_mask);
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun return pucan_write_cmd(priv);
215*4882a593Smuzhiyun }
216*4882a593Smuzhiyun
pucan_clr_options(struct peak_canfd_priv * priv,u16 opt_mask)217*4882a593Smuzhiyun static int pucan_clr_options(struct peak_canfd_priv *priv, u16 opt_mask)
218*4882a593Smuzhiyun {
219*4882a593Smuzhiyun struct pucan_options *cmd;
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun cmd = pucan_add_cmd(pucan_init_cmd(priv), PUCAN_CMD_CLR_DIS_OPTION);
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun cmd->options = cpu_to_le16(opt_mask);
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun return pucan_write_cmd(priv);
226*4882a593Smuzhiyun }
227*4882a593Smuzhiyun
pucan_setup_rx_barrier(struct peak_canfd_priv * priv)228*4882a593Smuzhiyun static int pucan_setup_rx_barrier(struct peak_canfd_priv *priv)
229*4882a593Smuzhiyun {
230*4882a593Smuzhiyun pucan_add_cmd(pucan_init_cmd(priv), PUCAN_CMD_RX_BARRIER);
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun return pucan_write_cmd(priv);
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun
pucan_netif_rx(struct sk_buff * skb,__le32 ts_low,__le32 ts_high)235*4882a593Smuzhiyun static int pucan_netif_rx(struct sk_buff *skb, __le32 ts_low, __le32 ts_high)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun struct skb_shared_hwtstamps *hwts = skb_hwtstamps(skb);
238*4882a593Smuzhiyun u64 ts_us;
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun ts_us = (u64)le32_to_cpu(ts_high) << 32;
241*4882a593Smuzhiyun ts_us |= le32_to_cpu(ts_low);
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun /* IP core timestamps are µs. */
244*4882a593Smuzhiyun hwts->hwtstamp = ns_to_ktime(ts_us * NSEC_PER_USEC);
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun return netif_rx(skb);
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun /* handle the reception of one CAN frame */
pucan_handle_can_rx(struct peak_canfd_priv * priv,struct pucan_rx_msg * msg)250*4882a593Smuzhiyun static int pucan_handle_can_rx(struct peak_canfd_priv *priv,
251*4882a593Smuzhiyun struct pucan_rx_msg *msg)
252*4882a593Smuzhiyun {
253*4882a593Smuzhiyun struct net_device_stats *stats = &priv->ndev->stats;
254*4882a593Smuzhiyun struct canfd_frame *cf;
255*4882a593Smuzhiyun struct sk_buff *skb;
256*4882a593Smuzhiyun const u16 rx_msg_flags = le16_to_cpu(msg->flags);
257*4882a593Smuzhiyun u8 cf_len;
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun if (rx_msg_flags & PUCAN_MSG_EXT_DATA_LEN)
260*4882a593Smuzhiyun cf_len = can_dlc2len(get_canfd_dlc(pucan_msg_get_dlc(msg)));
261*4882a593Smuzhiyun else
262*4882a593Smuzhiyun cf_len = get_can_dlc(pucan_msg_get_dlc(msg));
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun /* if this frame is an echo, */
265*4882a593Smuzhiyun if (rx_msg_flags & PUCAN_MSG_LOOPED_BACK) {
266*4882a593Smuzhiyun unsigned long flags;
267*4882a593Smuzhiyun
268*4882a593Smuzhiyun spin_lock_irqsave(&priv->echo_lock, flags);
269*4882a593Smuzhiyun can_get_echo_skb(priv->ndev, msg->client);
270*4882a593Smuzhiyun
271*4882a593Smuzhiyun /* count bytes of the echo instead of skb */
272*4882a593Smuzhiyun stats->tx_bytes += cf_len;
273*4882a593Smuzhiyun stats->tx_packets++;
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun /* restart tx queue (a slot is free) */
276*4882a593Smuzhiyun netif_wake_queue(priv->ndev);
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun spin_unlock_irqrestore(&priv->echo_lock, flags);
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun /* if this frame is only an echo, stop here. Otherwise,
281*4882a593Smuzhiyun * continue to push this application self-received frame into
282*4882a593Smuzhiyun * its own rx queue.
283*4882a593Smuzhiyun */
284*4882a593Smuzhiyun if (!(rx_msg_flags & PUCAN_MSG_SELF_RECEIVE))
285*4882a593Smuzhiyun return 0;
286*4882a593Smuzhiyun }
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun /* otherwise, it should be pushed into rx fifo */
289*4882a593Smuzhiyun if (rx_msg_flags & PUCAN_MSG_EXT_DATA_LEN) {
290*4882a593Smuzhiyun /* CANFD frame case */
291*4882a593Smuzhiyun skb = alloc_canfd_skb(priv->ndev, &cf);
292*4882a593Smuzhiyun if (!skb)
293*4882a593Smuzhiyun return -ENOMEM;
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun if (rx_msg_flags & PUCAN_MSG_BITRATE_SWITCH)
296*4882a593Smuzhiyun cf->flags |= CANFD_BRS;
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun if (rx_msg_flags & PUCAN_MSG_ERROR_STATE_IND)
299*4882a593Smuzhiyun cf->flags |= CANFD_ESI;
300*4882a593Smuzhiyun } else {
301*4882a593Smuzhiyun /* CAN 2.0 frame case */
302*4882a593Smuzhiyun skb = alloc_can_skb(priv->ndev, (struct can_frame **)&cf);
303*4882a593Smuzhiyun if (!skb)
304*4882a593Smuzhiyun return -ENOMEM;
305*4882a593Smuzhiyun }
306*4882a593Smuzhiyun
307*4882a593Smuzhiyun cf->can_id = le32_to_cpu(msg->can_id);
308*4882a593Smuzhiyun cf->len = cf_len;
309*4882a593Smuzhiyun
310*4882a593Smuzhiyun if (rx_msg_flags & PUCAN_MSG_EXT_ID)
311*4882a593Smuzhiyun cf->can_id |= CAN_EFF_FLAG;
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun if (rx_msg_flags & PUCAN_MSG_RTR)
314*4882a593Smuzhiyun cf->can_id |= CAN_RTR_FLAG;
315*4882a593Smuzhiyun else
316*4882a593Smuzhiyun memcpy(cf->data, msg->d, cf->len);
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun stats->rx_bytes += cf->len;
319*4882a593Smuzhiyun stats->rx_packets++;
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun pucan_netif_rx(skb, msg->ts_low, msg->ts_high);
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun return 0;
324*4882a593Smuzhiyun }
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun /* handle rx/tx error counters notification */
pucan_handle_error(struct peak_canfd_priv * priv,struct pucan_error_msg * msg)327*4882a593Smuzhiyun static int pucan_handle_error(struct peak_canfd_priv *priv,
328*4882a593Smuzhiyun struct pucan_error_msg *msg)
329*4882a593Smuzhiyun {
330*4882a593Smuzhiyun priv->bec.txerr = msg->tx_err_cnt;
331*4882a593Smuzhiyun priv->bec.rxerr = msg->rx_err_cnt;
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun return 0;
334*4882a593Smuzhiyun }
335*4882a593Smuzhiyun
336*4882a593Smuzhiyun /* handle status notification */
pucan_handle_status(struct peak_canfd_priv * priv,struct pucan_status_msg * msg)337*4882a593Smuzhiyun static int pucan_handle_status(struct peak_canfd_priv *priv,
338*4882a593Smuzhiyun struct pucan_status_msg *msg)
339*4882a593Smuzhiyun {
340*4882a593Smuzhiyun struct net_device *ndev = priv->ndev;
341*4882a593Smuzhiyun struct net_device_stats *stats = &ndev->stats;
342*4882a593Smuzhiyun struct can_frame *cf;
343*4882a593Smuzhiyun struct sk_buff *skb;
344*4882a593Smuzhiyun
345*4882a593Smuzhiyun /* this STATUS is the CNF of the RX_BARRIER: Tx path can be setup */
346*4882a593Smuzhiyun if (pucan_status_is_rx_barrier(msg)) {
347*4882a593Smuzhiyun if (priv->enable_tx_path) {
348*4882a593Smuzhiyun int err = priv->enable_tx_path(priv);
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun if (err)
351*4882a593Smuzhiyun return err;
352*4882a593Smuzhiyun }
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun /* wake network queue up (echo_skb array is empty) */
355*4882a593Smuzhiyun netif_wake_queue(ndev);
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun return 0;
358*4882a593Smuzhiyun }
359*4882a593Smuzhiyun
360*4882a593Smuzhiyun skb = alloc_can_err_skb(ndev, &cf);
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun /* test state error bits according to their priority */
363*4882a593Smuzhiyun if (pucan_status_is_busoff(msg)) {
364*4882a593Smuzhiyun netdev_dbg(ndev, "Bus-off entry status\n");
365*4882a593Smuzhiyun priv->can.state = CAN_STATE_BUS_OFF;
366*4882a593Smuzhiyun priv->can.can_stats.bus_off++;
367*4882a593Smuzhiyun can_bus_off(ndev);
368*4882a593Smuzhiyun if (skb)
369*4882a593Smuzhiyun cf->can_id |= CAN_ERR_BUSOFF;
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun } else if (pucan_status_is_passive(msg)) {
372*4882a593Smuzhiyun netdev_dbg(ndev, "Error passive status\n");
373*4882a593Smuzhiyun priv->can.state = CAN_STATE_ERROR_PASSIVE;
374*4882a593Smuzhiyun priv->can.can_stats.error_passive++;
375*4882a593Smuzhiyun if (skb) {
376*4882a593Smuzhiyun cf->can_id |= CAN_ERR_CRTL;
377*4882a593Smuzhiyun cf->data[1] = (priv->bec.txerr > priv->bec.rxerr) ?
378*4882a593Smuzhiyun CAN_ERR_CRTL_TX_PASSIVE :
379*4882a593Smuzhiyun CAN_ERR_CRTL_RX_PASSIVE;
380*4882a593Smuzhiyun cf->data[6] = priv->bec.txerr;
381*4882a593Smuzhiyun cf->data[7] = priv->bec.rxerr;
382*4882a593Smuzhiyun }
383*4882a593Smuzhiyun
384*4882a593Smuzhiyun } else if (pucan_status_is_warning(msg)) {
385*4882a593Smuzhiyun netdev_dbg(ndev, "Error warning status\n");
386*4882a593Smuzhiyun priv->can.state = CAN_STATE_ERROR_WARNING;
387*4882a593Smuzhiyun priv->can.can_stats.error_warning++;
388*4882a593Smuzhiyun if (skb) {
389*4882a593Smuzhiyun cf->can_id |= CAN_ERR_CRTL;
390*4882a593Smuzhiyun cf->data[1] = (priv->bec.txerr > priv->bec.rxerr) ?
391*4882a593Smuzhiyun CAN_ERR_CRTL_TX_WARNING :
392*4882a593Smuzhiyun CAN_ERR_CRTL_RX_WARNING;
393*4882a593Smuzhiyun cf->data[6] = priv->bec.txerr;
394*4882a593Smuzhiyun cf->data[7] = priv->bec.rxerr;
395*4882a593Smuzhiyun }
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun } else if (priv->can.state != CAN_STATE_ERROR_ACTIVE) {
398*4882a593Smuzhiyun /* back to ERROR_ACTIVE */
399*4882a593Smuzhiyun netdev_dbg(ndev, "Error active status\n");
400*4882a593Smuzhiyun can_change_state(ndev, cf, CAN_STATE_ERROR_ACTIVE,
401*4882a593Smuzhiyun CAN_STATE_ERROR_ACTIVE);
402*4882a593Smuzhiyun } else {
403*4882a593Smuzhiyun dev_kfree_skb(skb);
404*4882a593Smuzhiyun return 0;
405*4882a593Smuzhiyun }
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun if (!skb) {
408*4882a593Smuzhiyun stats->rx_dropped++;
409*4882a593Smuzhiyun return -ENOMEM;
410*4882a593Smuzhiyun }
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun stats->rx_packets++;
413*4882a593Smuzhiyun stats->rx_bytes += cf->can_dlc;
414*4882a593Smuzhiyun pucan_netif_rx(skb, msg->ts_low, msg->ts_high);
415*4882a593Smuzhiyun
416*4882a593Smuzhiyun return 0;
417*4882a593Smuzhiyun }
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun /* handle uCAN Rx overflow notification */
pucan_handle_cache_critical(struct peak_canfd_priv * priv)420*4882a593Smuzhiyun static int pucan_handle_cache_critical(struct peak_canfd_priv *priv)
421*4882a593Smuzhiyun {
422*4882a593Smuzhiyun struct net_device_stats *stats = &priv->ndev->stats;
423*4882a593Smuzhiyun struct can_frame *cf;
424*4882a593Smuzhiyun struct sk_buff *skb;
425*4882a593Smuzhiyun
426*4882a593Smuzhiyun stats->rx_over_errors++;
427*4882a593Smuzhiyun stats->rx_errors++;
428*4882a593Smuzhiyun
429*4882a593Smuzhiyun skb = alloc_can_err_skb(priv->ndev, &cf);
430*4882a593Smuzhiyun if (!skb) {
431*4882a593Smuzhiyun stats->rx_dropped++;
432*4882a593Smuzhiyun return -ENOMEM;
433*4882a593Smuzhiyun }
434*4882a593Smuzhiyun
435*4882a593Smuzhiyun cf->can_id |= CAN_ERR_CRTL;
436*4882a593Smuzhiyun cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
437*4882a593Smuzhiyun
438*4882a593Smuzhiyun cf->data[6] = priv->bec.txerr;
439*4882a593Smuzhiyun cf->data[7] = priv->bec.rxerr;
440*4882a593Smuzhiyun
441*4882a593Smuzhiyun stats->rx_bytes += cf->can_dlc;
442*4882a593Smuzhiyun stats->rx_packets++;
443*4882a593Smuzhiyun netif_rx(skb);
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun return 0;
446*4882a593Smuzhiyun }
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun /* handle a single uCAN message */
peak_canfd_handle_msg(struct peak_canfd_priv * priv,struct pucan_rx_msg * msg)449*4882a593Smuzhiyun int peak_canfd_handle_msg(struct peak_canfd_priv *priv,
450*4882a593Smuzhiyun struct pucan_rx_msg *msg)
451*4882a593Smuzhiyun {
452*4882a593Smuzhiyun u16 msg_type = le16_to_cpu(msg->type);
453*4882a593Smuzhiyun int msg_size = le16_to_cpu(msg->size);
454*4882a593Smuzhiyun int err;
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun if (!msg_size || !msg_type) {
457*4882a593Smuzhiyun /* null packet found: end of list */
458*4882a593Smuzhiyun goto exit;
459*4882a593Smuzhiyun }
460*4882a593Smuzhiyun
461*4882a593Smuzhiyun switch (msg_type) {
462*4882a593Smuzhiyun case PUCAN_MSG_CAN_RX:
463*4882a593Smuzhiyun err = pucan_handle_can_rx(priv, (struct pucan_rx_msg *)msg);
464*4882a593Smuzhiyun break;
465*4882a593Smuzhiyun case PUCAN_MSG_ERROR:
466*4882a593Smuzhiyun err = pucan_handle_error(priv, (struct pucan_error_msg *)msg);
467*4882a593Smuzhiyun break;
468*4882a593Smuzhiyun case PUCAN_MSG_STATUS:
469*4882a593Smuzhiyun err = pucan_handle_status(priv, (struct pucan_status_msg *)msg);
470*4882a593Smuzhiyun break;
471*4882a593Smuzhiyun case PUCAN_MSG_CACHE_CRITICAL:
472*4882a593Smuzhiyun err = pucan_handle_cache_critical(priv);
473*4882a593Smuzhiyun break;
474*4882a593Smuzhiyun default:
475*4882a593Smuzhiyun err = 0;
476*4882a593Smuzhiyun }
477*4882a593Smuzhiyun
478*4882a593Smuzhiyun if (err < 0)
479*4882a593Smuzhiyun return err;
480*4882a593Smuzhiyun
481*4882a593Smuzhiyun exit:
482*4882a593Smuzhiyun return msg_size;
483*4882a593Smuzhiyun }
484*4882a593Smuzhiyun
485*4882a593Smuzhiyun /* handle a list of rx_count messages from rx_msg memory address */
peak_canfd_handle_msgs_list(struct peak_canfd_priv * priv,struct pucan_rx_msg * msg_list,int msg_count)486*4882a593Smuzhiyun int peak_canfd_handle_msgs_list(struct peak_canfd_priv *priv,
487*4882a593Smuzhiyun struct pucan_rx_msg *msg_list, int msg_count)
488*4882a593Smuzhiyun {
489*4882a593Smuzhiyun void *msg_ptr = msg_list;
490*4882a593Smuzhiyun int i, msg_size = 0;
491*4882a593Smuzhiyun
492*4882a593Smuzhiyun for (i = 0; i < msg_count; i++) {
493*4882a593Smuzhiyun msg_size = peak_canfd_handle_msg(priv, msg_ptr);
494*4882a593Smuzhiyun
495*4882a593Smuzhiyun /* a null packet can be found at the end of a list */
496*4882a593Smuzhiyun if (msg_size <= 0)
497*4882a593Smuzhiyun break;
498*4882a593Smuzhiyun
499*4882a593Smuzhiyun msg_ptr += ALIGN(msg_size, 4);
500*4882a593Smuzhiyun }
501*4882a593Smuzhiyun
502*4882a593Smuzhiyun if (msg_size < 0)
503*4882a593Smuzhiyun return msg_size;
504*4882a593Smuzhiyun
505*4882a593Smuzhiyun return i;
506*4882a593Smuzhiyun }
507*4882a593Smuzhiyun
peak_canfd_start(struct peak_canfd_priv * priv)508*4882a593Smuzhiyun static int peak_canfd_start(struct peak_canfd_priv *priv)
509*4882a593Smuzhiyun {
510*4882a593Smuzhiyun int err;
511*4882a593Smuzhiyun
512*4882a593Smuzhiyun err = pucan_clr_err_counters(priv);
513*4882a593Smuzhiyun if (err)
514*4882a593Smuzhiyun goto err_exit;
515*4882a593Smuzhiyun
516*4882a593Smuzhiyun priv->echo_idx = 0;
517*4882a593Smuzhiyun
518*4882a593Smuzhiyun priv->bec.txerr = 0;
519*4882a593Smuzhiyun priv->bec.rxerr = 0;
520*4882a593Smuzhiyun
521*4882a593Smuzhiyun if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
522*4882a593Smuzhiyun err = pucan_set_listen_only_mode(priv);
523*4882a593Smuzhiyun else
524*4882a593Smuzhiyun err = pucan_set_normal_mode(priv);
525*4882a593Smuzhiyun
526*4882a593Smuzhiyun err_exit:
527*4882a593Smuzhiyun return err;
528*4882a593Smuzhiyun }
529*4882a593Smuzhiyun
peak_canfd_stop(struct peak_canfd_priv * priv)530*4882a593Smuzhiyun static void peak_canfd_stop(struct peak_canfd_priv *priv)
531*4882a593Smuzhiyun {
532*4882a593Smuzhiyun int err;
533*4882a593Smuzhiyun
534*4882a593Smuzhiyun /* go back to RESET mode */
535*4882a593Smuzhiyun err = pucan_set_reset_mode(priv);
536*4882a593Smuzhiyun if (err) {
537*4882a593Smuzhiyun netdev_err(priv->ndev, "channel %u reset failed\n",
538*4882a593Smuzhiyun priv->index);
539*4882a593Smuzhiyun } else {
540*4882a593Smuzhiyun /* abort last Tx (MUST be done in RESET mode only!) */
541*4882a593Smuzhiyun pucan_tx_abort(priv, PUCAN_TX_ABORT_FLUSH);
542*4882a593Smuzhiyun }
543*4882a593Smuzhiyun }
544*4882a593Smuzhiyun
peak_canfd_set_mode(struct net_device * ndev,enum can_mode mode)545*4882a593Smuzhiyun static int peak_canfd_set_mode(struct net_device *ndev, enum can_mode mode)
546*4882a593Smuzhiyun {
547*4882a593Smuzhiyun struct peak_canfd_priv *priv = netdev_priv(ndev);
548*4882a593Smuzhiyun
549*4882a593Smuzhiyun switch (mode) {
550*4882a593Smuzhiyun case CAN_MODE_START:
551*4882a593Smuzhiyun peak_canfd_start(priv);
552*4882a593Smuzhiyun netif_wake_queue(ndev);
553*4882a593Smuzhiyun break;
554*4882a593Smuzhiyun default:
555*4882a593Smuzhiyun return -EOPNOTSUPP;
556*4882a593Smuzhiyun }
557*4882a593Smuzhiyun
558*4882a593Smuzhiyun return 0;
559*4882a593Smuzhiyun }
560*4882a593Smuzhiyun
peak_canfd_get_berr_counter(const struct net_device * ndev,struct can_berr_counter * bec)561*4882a593Smuzhiyun static int peak_canfd_get_berr_counter(const struct net_device *ndev,
562*4882a593Smuzhiyun struct can_berr_counter *bec)
563*4882a593Smuzhiyun {
564*4882a593Smuzhiyun struct peak_canfd_priv *priv = netdev_priv(ndev);
565*4882a593Smuzhiyun
566*4882a593Smuzhiyun *bec = priv->bec;
567*4882a593Smuzhiyun return 0;
568*4882a593Smuzhiyun }
569*4882a593Smuzhiyun
peak_canfd_open(struct net_device * ndev)570*4882a593Smuzhiyun static int peak_canfd_open(struct net_device *ndev)
571*4882a593Smuzhiyun {
572*4882a593Smuzhiyun struct peak_canfd_priv *priv = netdev_priv(ndev);
573*4882a593Smuzhiyun int i, err = 0;
574*4882a593Smuzhiyun
575*4882a593Smuzhiyun err = open_candev(ndev);
576*4882a593Smuzhiyun if (err) {
577*4882a593Smuzhiyun netdev_err(ndev, "open_candev() failed, error %d\n", err);
578*4882a593Smuzhiyun goto err_exit;
579*4882a593Smuzhiyun }
580*4882a593Smuzhiyun
581*4882a593Smuzhiyun err = pucan_set_reset_mode(priv);
582*4882a593Smuzhiyun if (err)
583*4882a593Smuzhiyun goto err_close;
584*4882a593Smuzhiyun
585*4882a593Smuzhiyun if (priv->can.ctrlmode & CAN_CTRLMODE_FD) {
586*4882a593Smuzhiyun if (priv->can.ctrlmode & CAN_CTRLMODE_FD_NON_ISO)
587*4882a593Smuzhiyun err = pucan_clr_options(priv, PUCAN_OPTION_CANDFDISO);
588*4882a593Smuzhiyun else
589*4882a593Smuzhiyun err = pucan_set_options(priv, PUCAN_OPTION_CANDFDISO);
590*4882a593Smuzhiyun
591*4882a593Smuzhiyun if (err)
592*4882a593Smuzhiyun goto err_close;
593*4882a593Smuzhiyun }
594*4882a593Smuzhiyun
595*4882a593Smuzhiyun /* set option: get rx/tx error counters */
596*4882a593Smuzhiyun err = pucan_set_options(priv, PUCAN_OPTION_ERROR);
597*4882a593Smuzhiyun if (err)
598*4882a593Smuzhiyun goto err_close;
599*4882a593Smuzhiyun
600*4882a593Smuzhiyun /* accept all standard CAN ID */
601*4882a593Smuzhiyun for (i = 0; i <= PUCAN_FLTSTD_ROW_IDX_MAX; i++)
602*4882a593Smuzhiyun pucan_set_std_filter(priv, i, 0xffffffff);
603*4882a593Smuzhiyun
604*4882a593Smuzhiyun err = peak_canfd_start(priv);
605*4882a593Smuzhiyun if (err)
606*4882a593Smuzhiyun goto err_close;
607*4882a593Smuzhiyun
608*4882a593Smuzhiyun /* receiving the RB status says when Tx path is ready */
609*4882a593Smuzhiyun err = pucan_setup_rx_barrier(priv);
610*4882a593Smuzhiyun if (!err)
611*4882a593Smuzhiyun goto err_exit;
612*4882a593Smuzhiyun
613*4882a593Smuzhiyun err_close:
614*4882a593Smuzhiyun close_candev(ndev);
615*4882a593Smuzhiyun err_exit:
616*4882a593Smuzhiyun return err;
617*4882a593Smuzhiyun }
618*4882a593Smuzhiyun
peak_canfd_set_bittiming(struct net_device * ndev)619*4882a593Smuzhiyun static int peak_canfd_set_bittiming(struct net_device *ndev)
620*4882a593Smuzhiyun {
621*4882a593Smuzhiyun struct peak_canfd_priv *priv = netdev_priv(ndev);
622*4882a593Smuzhiyun
623*4882a593Smuzhiyun return pucan_set_timing_slow(priv, &priv->can.bittiming);
624*4882a593Smuzhiyun }
625*4882a593Smuzhiyun
peak_canfd_set_data_bittiming(struct net_device * ndev)626*4882a593Smuzhiyun static int peak_canfd_set_data_bittiming(struct net_device *ndev)
627*4882a593Smuzhiyun {
628*4882a593Smuzhiyun struct peak_canfd_priv *priv = netdev_priv(ndev);
629*4882a593Smuzhiyun
630*4882a593Smuzhiyun return pucan_set_timing_fast(priv, &priv->can.data_bittiming);
631*4882a593Smuzhiyun }
632*4882a593Smuzhiyun
peak_canfd_close(struct net_device * ndev)633*4882a593Smuzhiyun static int peak_canfd_close(struct net_device *ndev)
634*4882a593Smuzhiyun {
635*4882a593Smuzhiyun struct peak_canfd_priv *priv = netdev_priv(ndev);
636*4882a593Smuzhiyun
637*4882a593Smuzhiyun netif_stop_queue(ndev);
638*4882a593Smuzhiyun peak_canfd_stop(priv);
639*4882a593Smuzhiyun close_candev(ndev);
640*4882a593Smuzhiyun
641*4882a593Smuzhiyun return 0;
642*4882a593Smuzhiyun }
643*4882a593Smuzhiyun
peak_canfd_start_xmit(struct sk_buff * skb,struct net_device * ndev)644*4882a593Smuzhiyun static netdev_tx_t peak_canfd_start_xmit(struct sk_buff *skb,
645*4882a593Smuzhiyun struct net_device *ndev)
646*4882a593Smuzhiyun {
647*4882a593Smuzhiyun struct peak_canfd_priv *priv = netdev_priv(ndev);
648*4882a593Smuzhiyun struct net_device_stats *stats = &ndev->stats;
649*4882a593Smuzhiyun struct canfd_frame *cf = (struct canfd_frame *)skb->data;
650*4882a593Smuzhiyun struct pucan_tx_msg *msg;
651*4882a593Smuzhiyun u16 msg_size, msg_flags;
652*4882a593Smuzhiyun unsigned long flags;
653*4882a593Smuzhiyun bool should_stop_tx_queue;
654*4882a593Smuzhiyun int room_left;
655*4882a593Smuzhiyun u8 can_dlc;
656*4882a593Smuzhiyun
657*4882a593Smuzhiyun if (can_dropped_invalid_skb(ndev, skb))
658*4882a593Smuzhiyun return NETDEV_TX_OK;
659*4882a593Smuzhiyun
660*4882a593Smuzhiyun msg_size = ALIGN(sizeof(*msg) + cf->len, 4);
661*4882a593Smuzhiyun msg = priv->alloc_tx_msg(priv, msg_size, &room_left);
662*4882a593Smuzhiyun
663*4882a593Smuzhiyun /* should never happen except under bus-off condition and (auto-)restart
664*4882a593Smuzhiyun * mechanism
665*4882a593Smuzhiyun */
666*4882a593Smuzhiyun if (!msg) {
667*4882a593Smuzhiyun stats->tx_dropped++;
668*4882a593Smuzhiyun netif_stop_queue(ndev);
669*4882a593Smuzhiyun return NETDEV_TX_BUSY;
670*4882a593Smuzhiyun }
671*4882a593Smuzhiyun
672*4882a593Smuzhiyun msg->size = cpu_to_le16(msg_size);
673*4882a593Smuzhiyun msg->type = cpu_to_le16(PUCAN_MSG_CAN_TX);
674*4882a593Smuzhiyun msg_flags = 0;
675*4882a593Smuzhiyun
676*4882a593Smuzhiyun if (cf->can_id & CAN_EFF_FLAG) {
677*4882a593Smuzhiyun msg_flags |= PUCAN_MSG_EXT_ID;
678*4882a593Smuzhiyun msg->can_id = cpu_to_le32(cf->can_id & CAN_EFF_MASK);
679*4882a593Smuzhiyun } else {
680*4882a593Smuzhiyun msg->can_id = cpu_to_le32(cf->can_id & CAN_SFF_MASK);
681*4882a593Smuzhiyun }
682*4882a593Smuzhiyun
683*4882a593Smuzhiyun if (can_is_canfd_skb(skb)) {
684*4882a593Smuzhiyun /* CAN FD frame format */
685*4882a593Smuzhiyun can_dlc = can_len2dlc(cf->len);
686*4882a593Smuzhiyun
687*4882a593Smuzhiyun msg_flags |= PUCAN_MSG_EXT_DATA_LEN;
688*4882a593Smuzhiyun
689*4882a593Smuzhiyun if (cf->flags & CANFD_BRS)
690*4882a593Smuzhiyun msg_flags |= PUCAN_MSG_BITRATE_SWITCH;
691*4882a593Smuzhiyun
692*4882a593Smuzhiyun if (cf->flags & CANFD_ESI)
693*4882a593Smuzhiyun msg_flags |= PUCAN_MSG_ERROR_STATE_IND;
694*4882a593Smuzhiyun } else {
695*4882a593Smuzhiyun /* CAN 2.0 frame format */
696*4882a593Smuzhiyun can_dlc = cf->len;
697*4882a593Smuzhiyun
698*4882a593Smuzhiyun if (cf->can_id & CAN_RTR_FLAG)
699*4882a593Smuzhiyun msg_flags |= PUCAN_MSG_RTR;
700*4882a593Smuzhiyun }
701*4882a593Smuzhiyun
702*4882a593Smuzhiyun /* always ask loopback for echo management */
703*4882a593Smuzhiyun msg_flags |= PUCAN_MSG_LOOPED_BACK;
704*4882a593Smuzhiyun
705*4882a593Smuzhiyun /* set driver specific bit to differentiate with application loopback */
706*4882a593Smuzhiyun if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)
707*4882a593Smuzhiyun msg_flags |= PUCAN_MSG_SELF_RECEIVE;
708*4882a593Smuzhiyun
709*4882a593Smuzhiyun msg->flags = cpu_to_le16(msg_flags);
710*4882a593Smuzhiyun msg->channel_dlc = PUCAN_MSG_CHANNEL_DLC(priv->index, can_dlc);
711*4882a593Smuzhiyun memcpy(msg->d, cf->data, cf->len);
712*4882a593Smuzhiyun
713*4882a593Smuzhiyun /* struct msg client field is used as an index in the echo skbs ring */
714*4882a593Smuzhiyun msg->client = priv->echo_idx;
715*4882a593Smuzhiyun
716*4882a593Smuzhiyun spin_lock_irqsave(&priv->echo_lock, flags);
717*4882a593Smuzhiyun
718*4882a593Smuzhiyun /* prepare and save echo skb in internal slot */
719*4882a593Smuzhiyun can_put_echo_skb(skb, ndev, priv->echo_idx);
720*4882a593Smuzhiyun
721*4882a593Smuzhiyun /* move echo index to the next slot */
722*4882a593Smuzhiyun priv->echo_idx = (priv->echo_idx + 1) % priv->can.echo_skb_max;
723*4882a593Smuzhiyun
724*4882a593Smuzhiyun /* if next slot is not free, stop network queue (no slot free in echo
725*4882a593Smuzhiyun * skb ring means that the controller did not write these frames on
726*4882a593Smuzhiyun * the bus: no need to continue).
727*4882a593Smuzhiyun */
728*4882a593Smuzhiyun should_stop_tx_queue = !!(priv->can.echo_skb[priv->echo_idx]);
729*4882a593Smuzhiyun
730*4882a593Smuzhiyun /* stop network tx queue if not enough room to save one more msg too */
731*4882a593Smuzhiyun if (priv->can.ctrlmode & CAN_CTRLMODE_FD)
732*4882a593Smuzhiyun should_stop_tx_queue |= (room_left <
733*4882a593Smuzhiyun (sizeof(*msg) + CANFD_MAX_DLEN));
734*4882a593Smuzhiyun else
735*4882a593Smuzhiyun should_stop_tx_queue |= (room_left <
736*4882a593Smuzhiyun (sizeof(*msg) + CAN_MAX_DLEN));
737*4882a593Smuzhiyun
738*4882a593Smuzhiyun if (should_stop_tx_queue)
739*4882a593Smuzhiyun netif_stop_queue(ndev);
740*4882a593Smuzhiyun
741*4882a593Smuzhiyun spin_unlock_irqrestore(&priv->echo_lock, flags);
742*4882a593Smuzhiyun
743*4882a593Smuzhiyun /* write the skb on the interface */
744*4882a593Smuzhiyun priv->write_tx_msg(priv, msg);
745*4882a593Smuzhiyun
746*4882a593Smuzhiyun return NETDEV_TX_OK;
747*4882a593Smuzhiyun }
748*4882a593Smuzhiyun
749*4882a593Smuzhiyun static const struct net_device_ops peak_canfd_netdev_ops = {
750*4882a593Smuzhiyun .ndo_open = peak_canfd_open,
751*4882a593Smuzhiyun .ndo_stop = peak_canfd_close,
752*4882a593Smuzhiyun .ndo_start_xmit = peak_canfd_start_xmit,
753*4882a593Smuzhiyun .ndo_change_mtu = can_change_mtu,
754*4882a593Smuzhiyun };
755*4882a593Smuzhiyun
alloc_peak_canfd_dev(int sizeof_priv,int index,int echo_skb_max)756*4882a593Smuzhiyun struct net_device *alloc_peak_canfd_dev(int sizeof_priv, int index,
757*4882a593Smuzhiyun int echo_skb_max)
758*4882a593Smuzhiyun {
759*4882a593Smuzhiyun struct net_device *ndev;
760*4882a593Smuzhiyun struct peak_canfd_priv *priv;
761*4882a593Smuzhiyun
762*4882a593Smuzhiyun /* we DO support local echo */
763*4882a593Smuzhiyun if (echo_skb_max < 0)
764*4882a593Smuzhiyun echo_skb_max = PCANFD_ECHO_SKB_MAX;
765*4882a593Smuzhiyun
766*4882a593Smuzhiyun /* allocate the candev object */
767*4882a593Smuzhiyun ndev = alloc_candev(sizeof_priv, echo_skb_max);
768*4882a593Smuzhiyun if (!ndev)
769*4882a593Smuzhiyun return NULL;
770*4882a593Smuzhiyun
771*4882a593Smuzhiyun priv = netdev_priv(ndev);
772*4882a593Smuzhiyun
773*4882a593Smuzhiyun /* complete now socket-can initialization side */
774*4882a593Smuzhiyun priv->can.state = CAN_STATE_STOPPED;
775*4882a593Smuzhiyun priv->can.bittiming_const = &peak_canfd_nominal_const;
776*4882a593Smuzhiyun priv->can.data_bittiming_const = &peak_canfd_data_const;
777*4882a593Smuzhiyun
778*4882a593Smuzhiyun priv->can.do_set_mode = peak_canfd_set_mode;
779*4882a593Smuzhiyun priv->can.do_get_berr_counter = peak_canfd_get_berr_counter;
780*4882a593Smuzhiyun priv->can.do_set_bittiming = peak_canfd_set_bittiming;
781*4882a593Smuzhiyun priv->can.do_set_data_bittiming = peak_canfd_set_data_bittiming;
782*4882a593Smuzhiyun priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
783*4882a593Smuzhiyun CAN_CTRLMODE_LISTENONLY |
784*4882a593Smuzhiyun CAN_CTRLMODE_3_SAMPLES |
785*4882a593Smuzhiyun CAN_CTRLMODE_FD |
786*4882a593Smuzhiyun CAN_CTRLMODE_FD_NON_ISO |
787*4882a593Smuzhiyun CAN_CTRLMODE_BERR_REPORTING;
788*4882a593Smuzhiyun
789*4882a593Smuzhiyun priv->ndev = ndev;
790*4882a593Smuzhiyun priv->index = index;
791*4882a593Smuzhiyun priv->cmd_len = 0;
792*4882a593Smuzhiyun spin_lock_init(&priv->echo_lock);
793*4882a593Smuzhiyun
794*4882a593Smuzhiyun ndev->flags |= IFF_ECHO;
795*4882a593Smuzhiyun ndev->netdev_ops = &peak_canfd_netdev_ops;
796*4882a593Smuzhiyun ndev->dev_id = index;
797*4882a593Smuzhiyun
798*4882a593Smuzhiyun return ndev;
799*4882a593Smuzhiyun }
800