xref: /kernel/linux/linux-5.10/drivers/net/can/dev/dev.c (revision 8c2ecf20)
18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/* Copyright (C) 2005 Marc Kleine-Budde, Pengutronix
38c2ecf20Sopenharmony_ci * Copyright (C) 2006 Andrey Volkov, Varma Electronics
48c2ecf20Sopenharmony_ci * Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com>
58c2ecf20Sopenharmony_ci */
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include <linux/module.h>
88c2ecf20Sopenharmony_ci#include <linux/kernel.h>
98c2ecf20Sopenharmony_ci#include <linux/slab.h>
108c2ecf20Sopenharmony_ci#include <linux/netdevice.h>
118c2ecf20Sopenharmony_ci#include <linux/if_arp.h>
128c2ecf20Sopenharmony_ci#include <linux/workqueue.h>
138c2ecf20Sopenharmony_ci#include <linux/can.h>
148c2ecf20Sopenharmony_ci#include <linux/can/can-ml.h>
158c2ecf20Sopenharmony_ci#include <linux/can/dev.h>
168c2ecf20Sopenharmony_ci#include <linux/can/skb.h>
178c2ecf20Sopenharmony_ci#include <linux/can/netlink.h>
188c2ecf20Sopenharmony_ci#include <linux/can/led.h>
198c2ecf20Sopenharmony_ci#include <linux/of.h>
208c2ecf20Sopenharmony_ci#include <net/rtnetlink.h>
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci#define MOD_DESC "CAN device driver interface"
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ciMODULE_DESCRIPTION(MOD_DESC);
258c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
268c2ecf20Sopenharmony_ciMODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci/* CAN DLC to real data length conversion helpers */
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_cistatic const u8 dlc2len[] = {0, 1, 2, 3, 4, 5, 6, 7,
318c2ecf20Sopenharmony_ci			     8, 12, 16, 20, 24, 32, 48, 64};
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci/* get data length from can_dlc with sanitized can_dlc */
348c2ecf20Sopenharmony_ciu8 can_dlc2len(u8 can_dlc)
358c2ecf20Sopenharmony_ci{
368c2ecf20Sopenharmony_ci	return dlc2len[can_dlc & 0x0F];
378c2ecf20Sopenharmony_ci}
388c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(can_dlc2len);
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_cistatic const u8 len2dlc[] = {0, 1, 2, 3, 4, 5, 6, 7, 8,		/* 0 - 8 */
418c2ecf20Sopenharmony_ci			     9, 9, 9, 9,			/* 9 - 12 */
428c2ecf20Sopenharmony_ci			     10, 10, 10, 10,			/* 13 - 16 */
438c2ecf20Sopenharmony_ci			     11, 11, 11, 11,			/* 17 - 20 */
448c2ecf20Sopenharmony_ci			     12, 12, 12, 12,			/* 21 - 24 */
458c2ecf20Sopenharmony_ci			     13, 13, 13, 13, 13, 13, 13, 13,	/* 25 - 32 */
468c2ecf20Sopenharmony_ci			     14, 14, 14, 14, 14, 14, 14, 14,	/* 33 - 40 */
478c2ecf20Sopenharmony_ci			     14, 14, 14, 14, 14, 14, 14, 14,	/* 41 - 48 */
488c2ecf20Sopenharmony_ci			     15, 15, 15, 15, 15, 15, 15, 15,	/* 49 - 56 */
498c2ecf20Sopenharmony_ci			     15, 15, 15, 15, 15, 15, 15, 15};	/* 57 - 64 */
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci/* map the sanitized data length to an appropriate data length code */
528c2ecf20Sopenharmony_ciu8 can_len2dlc(u8 len)
538c2ecf20Sopenharmony_ci{
548c2ecf20Sopenharmony_ci	if (unlikely(len > 64))
558c2ecf20Sopenharmony_ci		return 0xF;
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci	return len2dlc[len];
588c2ecf20Sopenharmony_ci}
598c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(can_len2dlc);
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci#ifdef CONFIG_CAN_CALC_BITTIMING
628c2ecf20Sopenharmony_ci#define CAN_CALC_MAX_ERROR 50 /* in one-tenth of a percent */
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci/* Bit-timing calculation derived from:
658c2ecf20Sopenharmony_ci *
668c2ecf20Sopenharmony_ci * Code based on LinCAN sources and H8S2638 project
678c2ecf20Sopenharmony_ci * Copyright 2004-2006 Pavel Pisa - DCE FELK CVUT cz
688c2ecf20Sopenharmony_ci * Copyright 2005      Stanislav Marek
698c2ecf20Sopenharmony_ci * email: pisa@cmp.felk.cvut.cz
708c2ecf20Sopenharmony_ci *
718c2ecf20Sopenharmony_ci * Calculates proper bit-timing parameters for a specified bit-rate
728c2ecf20Sopenharmony_ci * and sample-point, which can then be used to set the bit-timing
738c2ecf20Sopenharmony_ci * registers of the CAN controller. You can find more information
748c2ecf20Sopenharmony_ci * in the header file linux/can/netlink.h.
758c2ecf20Sopenharmony_ci */
768c2ecf20Sopenharmony_cistatic int
778c2ecf20Sopenharmony_cican_update_sample_point(const struct can_bittiming_const *btc,
788c2ecf20Sopenharmony_ci			unsigned int sample_point_nominal, unsigned int tseg,
798c2ecf20Sopenharmony_ci			unsigned int *tseg1_ptr, unsigned int *tseg2_ptr,
808c2ecf20Sopenharmony_ci			unsigned int *sample_point_error_ptr)
818c2ecf20Sopenharmony_ci{
828c2ecf20Sopenharmony_ci	unsigned int sample_point_error, best_sample_point_error = UINT_MAX;
838c2ecf20Sopenharmony_ci	unsigned int sample_point, best_sample_point = 0;
848c2ecf20Sopenharmony_ci	unsigned int tseg1, tseg2;
858c2ecf20Sopenharmony_ci	int i;
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	for (i = 0; i <= 1; i++) {
888c2ecf20Sopenharmony_ci		tseg2 = tseg + CAN_SYNC_SEG -
898c2ecf20Sopenharmony_ci			(sample_point_nominal * (tseg + CAN_SYNC_SEG)) /
908c2ecf20Sopenharmony_ci			1000 - i;
918c2ecf20Sopenharmony_ci		tseg2 = clamp(tseg2, btc->tseg2_min, btc->tseg2_max);
928c2ecf20Sopenharmony_ci		tseg1 = tseg - tseg2;
938c2ecf20Sopenharmony_ci		if (tseg1 > btc->tseg1_max) {
948c2ecf20Sopenharmony_ci			tseg1 = btc->tseg1_max;
958c2ecf20Sopenharmony_ci			tseg2 = tseg - tseg1;
968c2ecf20Sopenharmony_ci		}
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci		sample_point = 1000 * (tseg + CAN_SYNC_SEG - tseg2) /
998c2ecf20Sopenharmony_ci			(tseg + CAN_SYNC_SEG);
1008c2ecf20Sopenharmony_ci		sample_point_error = abs(sample_point_nominal - sample_point);
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci		if (sample_point <= sample_point_nominal &&
1038c2ecf20Sopenharmony_ci		    sample_point_error < best_sample_point_error) {
1048c2ecf20Sopenharmony_ci			best_sample_point = sample_point;
1058c2ecf20Sopenharmony_ci			best_sample_point_error = sample_point_error;
1068c2ecf20Sopenharmony_ci			*tseg1_ptr = tseg1;
1078c2ecf20Sopenharmony_ci			*tseg2_ptr = tseg2;
1088c2ecf20Sopenharmony_ci		}
1098c2ecf20Sopenharmony_ci	}
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	if (sample_point_error_ptr)
1128c2ecf20Sopenharmony_ci		*sample_point_error_ptr = best_sample_point_error;
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci	return best_sample_point;
1158c2ecf20Sopenharmony_ci}
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_cistatic int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt,
1188c2ecf20Sopenharmony_ci			      const struct can_bittiming_const *btc)
1198c2ecf20Sopenharmony_ci{
1208c2ecf20Sopenharmony_ci	struct can_priv *priv = netdev_priv(dev);
1218c2ecf20Sopenharmony_ci	unsigned int bitrate;			/* current bitrate */
1228c2ecf20Sopenharmony_ci	unsigned int bitrate_error;		/* difference between current and nominal value */
1238c2ecf20Sopenharmony_ci	unsigned int best_bitrate_error = UINT_MAX;
1248c2ecf20Sopenharmony_ci	unsigned int sample_point_error;	/* difference between current and nominal value */
1258c2ecf20Sopenharmony_ci	unsigned int best_sample_point_error = UINT_MAX;
1268c2ecf20Sopenharmony_ci	unsigned int sample_point_nominal;	/* nominal sample point */
1278c2ecf20Sopenharmony_ci	unsigned int best_tseg = 0;		/* current best value for tseg */
1288c2ecf20Sopenharmony_ci	unsigned int best_brp = 0;		/* current best value for brp */
1298c2ecf20Sopenharmony_ci	unsigned int brp, tsegall, tseg, tseg1 = 0, tseg2 = 0;
1308c2ecf20Sopenharmony_ci	u64 v64;
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci	/* Use CiA recommended sample points */
1338c2ecf20Sopenharmony_ci	if (bt->sample_point) {
1348c2ecf20Sopenharmony_ci		sample_point_nominal = bt->sample_point;
1358c2ecf20Sopenharmony_ci	} else {
1368c2ecf20Sopenharmony_ci		if (bt->bitrate > 800000)
1378c2ecf20Sopenharmony_ci			sample_point_nominal = 750;
1388c2ecf20Sopenharmony_ci		else if (bt->bitrate > 500000)
1398c2ecf20Sopenharmony_ci			sample_point_nominal = 800;
1408c2ecf20Sopenharmony_ci		else
1418c2ecf20Sopenharmony_ci			sample_point_nominal = 875;
1428c2ecf20Sopenharmony_ci	}
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci	/* tseg even = round down, odd = round up */
1458c2ecf20Sopenharmony_ci	for (tseg = (btc->tseg1_max + btc->tseg2_max) * 2 + 1;
1468c2ecf20Sopenharmony_ci	     tseg >= (btc->tseg1_min + btc->tseg2_min) * 2; tseg--) {
1478c2ecf20Sopenharmony_ci		tsegall = CAN_SYNC_SEG + tseg / 2;
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci		/* Compute all possible tseg choices (tseg=tseg1+tseg2) */
1508c2ecf20Sopenharmony_ci		brp = priv->clock.freq / (tsegall * bt->bitrate) + tseg % 2;
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci		/* choose brp step which is possible in system */
1538c2ecf20Sopenharmony_ci		brp = (brp / btc->brp_inc) * btc->brp_inc;
1548c2ecf20Sopenharmony_ci		if (brp < btc->brp_min || brp > btc->brp_max)
1558c2ecf20Sopenharmony_ci			continue;
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci		bitrate = priv->clock.freq / (brp * tsegall);
1588c2ecf20Sopenharmony_ci		bitrate_error = abs(bt->bitrate - bitrate);
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci		/* tseg brp biterror */
1618c2ecf20Sopenharmony_ci		if (bitrate_error > best_bitrate_error)
1628c2ecf20Sopenharmony_ci			continue;
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_ci		/* reset sample point error if we have a better bitrate */
1658c2ecf20Sopenharmony_ci		if (bitrate_error < best_bitrate_error)
1668c2ecf20Sopenharmony_ci			best_sample_point_error = UINT_MAX;
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci		can_update_sample_point(btc, sample_point_nominal, tseg / 2,
1698c2ecf20Sopenharmony_ci					&tseg1, &tseg2, &sample_point_error);
1708c2ecf20Sopenharmony_ci		if (sample_point_error > best_sample_point_error)
1718c2ecf20Sopenharmony_ci			continue;
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci		best_sample_point_error = sample_point_error;
1748c2ecf20Sopenharmony_ci		best_bitrate_error = bitrate_error;
1758c2ecf20Sopenharmony_ci		best_tseg = tseg / 2;
1768c2ecf20Sopenharmony_ci		best_brp = brp;
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci		if (bitrate_error == 0 && sample_point_error == 0)
1798c2ecf20Sopenharmony_ci			break;
1808c2ecf20Sopenharmony_ci	}
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci	if (best_bitrate_error) {
1838c2ecf20Sopenharmony_ci		/* Error in one-tenth of a percent */
1848c2ecf20Sopenharmony_ci		v64 = (u64)best_bitrate_error * 1000;
1858c2ecf20Sopenharmony_ci		do_div(v64, bt->bitrate);
1868c2ecf20Sopenharmony_ci		bitrate_error = (u32)v64;
1878c2ecf20Sopenharmony_ci		if (bitrate_error > CAN_CALC_MAX_ERROR) {
1888c2ecf20Sopenharmony_ci			netdev_err(dev,
1898c2ecf20Sopenharmony_ci				   "bitrate error %d.%d%% too high\n",
1908c2ecf20Sopenharmony_ci				   bitrate_error / 10, bitrate_error % 10);
1918c2ecf20Sopenharmony_ci			return -EDOM;
1928c2ecf20Sopenharmony_ci		}
1938c2ecf20Sopenharmony_ci		netdev_warn(dev, "bitrate error %d.%d%%\n",
1948c2ecf20Sopenharmony_ci			    bitrate_error / 10, bitrate_error % 10);
1958c2ecf20Sopenharmony_ci	}
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci	/* real sample point */
1988c2ecf20Sopenharmony_ci	bt->sample_point = can_update_sample_point(btc, sample_point_nominal,
1998c2ecf20Sopenharmony_ci						   best_tseg, &tseg1, &tseg2,
2008c2ecf20Sopenharmony_ci						   NULL);
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci	v64 = (u64)best_brp * 1000 * 1000 * 1000;
2038c2ecf20Sopenharmony_ci	do_div(v64, priv->clock.freq);
2048c2ecf20Sopenharmony_ci	bt->tq = (u32)v64;
2058c2ecf20Sopenharmony_ci	bt->prop_seg = tseg1 / 2;
2068c2ecf20Sopenharmony_ci	bt->phase_seg1 = tseg1 - bt->prop_seg;
2078c2ecf20Sopenharmony_ci	bt->phase_seg2 = tseg2;
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci	/* check for sjw user settings */
2108c2ecf20Sopenharmony_ci	if (!bt->sjw || !btc->sjw_max) {
2118c2ecf20Sopenharmony_ci		bt->sjw = 1;
2128c2ecf20Sopenharmony_ci	} else {
2138c2ecf20Sopenharmony_ci		/* bt->sjw is at least 1 -> sanitize upper bound to sjw_max */
2148c2ecf20Sopenharmony_ci		if (bt->sjw > btc->sjw_max)
2158c2ecf20Sopenharmony_ci			bt->sjw = btc->sjw_max;
2168c2ecf20Sopenharmony_ci		/* bt->sjw must not be higher than tseg2 */
2178c2ecf20Sopenharmony_ci		if (tseg2 < bt->sjw)
2188c2ecf20Sopenharmony_ci			bt->sjw = tseg2;
2198c2ecf20Sopenharmony_ci	}
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci	bt->brp = best_brp;
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci	/* real bitrate */
2248c2ecf20Sopenharmony_ci	bt->bitrate = priv->clock.freq /
2258c2ecf20Sopenharmony_ci		(bt->brp * (CAN_SYNC_SEG + tseg1 + tseg2));
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ci	return 0;
2288c2ecf20Sopenharmony_ci}
2298c2ecf20Sopenharmony_ci#else /* !CONFIG_CAN_CALC_BITTIMING */
2308c2ecf20Sopenharmony_cistatic int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt,
2318c2ecf20Sopenharmony_ci			      const struct can_bittiming_const *btc)
2328c2ecf20Sopenharmony_ci{
2338c2ecf20Sopenharmony_ci	netdev_err(dev, "bit-timing calculation not available\n");
2348c2ecf20Sopenharmony_ci	return -EINVAL;
2358c2ecf20Sopenharmony_ci}
2368c2ecf20Sopenharmony_ci#endif /* CONFIG_CAN_CALC_BITTIMING */
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ci/* Checks the validity of the specified bit-timing parameters prop_seg,
2398c2ecf20Sopenharmony_ci * phase_seg1, phase_seg2 and sjw and tries to determine the bitrate
2408c2ecf20Sopenharmony_ci * prescaler value brp. You can find more information in the header
2418c2ecf20Sopenharmony_ci * file linux/can/netlink.h.
2428c2ecf20Sopenharmony_ci */
2438c2ecf20Sopenharmony_cistatic int can_fixup_bittiming(struct net_device *dev, struct can_bittiming *bt,
2448c2ecf20Sopenharmony_ci			       const struct can_bittiming_const *btc)
2458c2ecf20Sopenharmony_ci{
2468c2ecf20Sopenharmony_ci	struct can_priv *priv = netdev_priv(dev);
2478c2ecf20Sopenharmony_ci	int tseg1, alltseg;
2488c2ecf20Sopenharmony_ci	u64 brp64;
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	tseg1 = bt->prop_seg + bt->phase_seg1;
2518c2ecf20Sopenharmony_ci	if (!bt->sjw)
2528c2ecf20Sopenharmony_ci		bt->sjw = 1;
2538c2ecf20Sopenharmony_ci	if (bt->sjw > btc->sjw_max ||
2548c2ecf20Sopenharmony_ci	    tseg1 < btc->tseg1_min || tseg1 > btc->tseg1_max ||
2558c2ecf20Sopenharmony_ci	    bt->phase_seg2 < btc->tseg2_min || bt->phase_seg2 > btc->tseg2_max)
2568c2ecf20Sopenharmony_ci		return -ERANGE;
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci	brp64 = (u64)priv->clock.freq * (u64)bt->tq;
2598c2ecf20Sopenharmony_ci	if (btc->brp_inc > 1)
2608c2ecf20Sopenharmony_ci		do_div(brp64, btc->brp_inc);
2618c2ecf20Sopenharmony_ci	brp64 += 500000000UL - 1;
2628c2ecf20Sopenharmony_ci	do_div(brp64, 1000000000UL); /* the practicable BRP */
2638c2ecf20Sopenharmony_ci	if (btc->brp_inc > 1)
2648c2ecf20Sopenharmony_ci		brp64 *= btc->brp_inc;
2658c2ecf20Sopenharmony_ci	bt->brp = (u32)brp64;
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci	if (bt->brp < btc->brp_min || bt->brp > btc->brp_max)
2688c2ecf20Sopenharmony_ci		return -EINVAL;
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci	alltseg = bt->prop_seg + bt->phase_seg1 + bt->phase_seg2 + 1;
2718c2ecf20Sopenharmony_ci	bt->bitrate = priv->clock.freq / (bt->brp * alltseg);
2728c2ecf20Sopenharmony_ci	bt->sample_point = ((tseg1 + 1) * 1000) / alltseg;
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_ci	return 0;
2758c2ecf20Sopenharmony_ci}
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci/* Checks the validity of predefined bitrate settings */
2788c2ecf20Sopenharmony_cistatic int
2798c2ecf20Sopenharmony_cican_validate_bitrate(struct net_device *dev, struct can_bittiming *bt,
2808c2ecf20Sopenharmony_ci		     const u32 *bitrate_const,
2818c2ecf20Sopenharmony_ci		     const unsigned int bitrate_const_cnt)
2828c2ecf20Sopenharmony_ci{
2838c2ecf20Sopenharmony_ci	struct can_priv *priv = netdev_priv(dev);
2848c2ecf20Sopenharmony_ci	unsigned int i;
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ci	for (i = 0; i < bitrate_const_cnt; i++) {
2878c2ecf20Sopenharmony_ci		if (bt->bitrate == bitrate_const[i])
2888c2ecf20Sopenharmony_ci			break;
2898c2ecf20Sopenharmony_ci	}
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci	if (i >= priv->bitrate_const_cnt)
2928c2ecf20Sopenharmony_ci		return -EINVAL;
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	return 0;
2958c2ecf20Sopenharmony_ci}
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_cistatic int can_get_bittiming(struct net_device *dev, struct can_bittiming *bt,
2988c2ecf20Sopenharmony_ci			     const struct can_bittiming_const *btc,
2998c2ecf20Sopenharmony_ci			     const u32 *bitrate_const,
3008c2ecf20Sopenharmony_ci			     const unsigned int bitrate_const_cnt)
3018c2ecf20Sopenharmony_ci{
3028c2ecf20Sopenharmony_ci	int err;
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_ci	/* Depending on the given can_bittiming parameter structure the CAN
3058c2ecf20Sopenharmony_ci	 * timing parameters are calculated based on the provided bitrate OR
3068c2ecf20Sopenharmony_ci	 * alternatively the CAN timing parameters (tq, prop_seg, etc.) are
3078c2ecf20Sopenharmony_ci	 * provided directly which are then checked and fixed up.
3088c2ecf20Sopenharmony_ci	 */
3098c2ecf20Sopenharmony_ci	if (!bt->tq && bt->bitrate && btc)
3108c2ecf20Sopenharmony_ci		err = can_calc_bittiming(dev, bt, btc);
3118c2ecf20Sopenharmony_ci	else if (bt->tq && !bt->bitrate && btc)
3128c2ecf20Sopenharmony_ci		err = can_fixup_bittiming(dev, bt, btc);
3138c2ecf20Sopenharmony_ci	else if (!bt->tq && bt->bitrate && bitrate_const)
3148c2ecf20Sopenharmony_ci		err = can_validate_bitrate(dev, bt, bitrate_const,
3158c2ecf20Sopenharmony_ci					   bitrate_const_cnt);
3168c2ecf20Sopenharmony_ci	else
3178c2ecf20Sopenharmony_ci		err = -EINVAL;
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ci	return err;
3208c2ecf20Sopenharmony_ci}
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_cistatic void can_update_state_error_stats(struct net_device *dev,
3238c2ecf20Sopenharmony_ci					 enum can_state new_state)
3248c2ecf20Sopenharmony_ci{
3258c2ecf20Sopenharmony_ci	struct can_priv *priv = netdev_priv(dev);
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_ci	if (new_state <= priv->state)
3288c2ecf20Sopenharmony_ci		return;
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci	switch (new_state) {
3318c2ecf20Sopenharmony_ci	case CAN_STATE_ERROR_WARNING:
3328c2ecf20Sopenharmony_ci		priv->can_stats.error_warning++;
3338c2ecf20Sopenharmony_ci		break;
3348c2ecf20Sopenharmony_ci	case CAN_STATE_ERROR_PASSIVE:
3358c2ecf20Sopenharmony_ci		priv->can_stats.error_passive++;
3368c2ecf20Sopenharmony_ci		break;
3378c2ecf20Sopenharmony_ci	case CAN_STATE_BUS_OFF:
3388c2ecf20Sopenharmony_ci		priv->can_stats.bus_off++;
3398c2ecf20Sopenharmony_ci		break;
3408c2ecf20Sopenharmony_ci	default:
3418c2ecf20Sopenharmony_ci		break;
3428c2ecf20Sopenharmony_ci	}
3438c2ecf20Sopenharmony_ci}
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_cistatic int can_tx_state_to_frame(struct net_device *dev, enum can_state state)
3468c2ecf20Sopenharmony_ci{
3478c2ecf20Sopenharmony_ci	switch (state) {
3488c2ecf20Sopenharmony_ci	case CAN_STATE_ERROR_ACTIVE:
3498c2ecf20Sopenharmony_ci		return CAN_ERR_CRTL_ACTIVE;
3508c2ecf20Sopenharmony_ci	case CAN_STATE_ERROR_WARNING:
3518c2ecf20Sopenharmony_ci		return CAN_ERR_CRTL_TX_WARNING;
3528c2ecf20Sopenharmony_ci	case CAN_STATE_ERROR_PASSIVE:
3538c2ecf20Sopenharmony_ci		return CAN_ERR_CRTL_TX_PASSIVE;
3548c2ecf20Sopenharmony_ci	default:
3558c2ecf20Sopenharmony_ci		return 0;
3568c2ecf20Sopenharmony_ci	}
3578c2ecf20Sopenharmony_ci}
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_cistatic int can_rx_state_to_frame(struct net_device *dev, enum can_state state)
3608c2ecf20Sopenharmony_ci{
3618c2ecf20Sopenharmony_ci	switch (state) {
3628c2ecf20Sopenharmony_ci	case CAN_STATE_ERROR_ACTIVE:
3638c2ecf20Sopenharmony_ci		return CAN_ERR_CRTL_ACTIVE;
3648c2ecf20Sopenharmony_ci	case CAN_STATE_ERROR_WARNING:
3658c2ecf20Sopenharmony_ci		return CAN_ERR_CRTL_RX_WARNING;
3668c2ecf20Sopenharmony_ci	case CAN_STATE_ERROR_PASSIVE:
3678c2ecf20Sopenharmony_ci		return CAN_ERR_CRTL_RX_PASSIVE;
3688c2ecf20Sopenharmony_ci	default:
3698c2ecf20Sopenharmony_ci		return 0;
3708c2ecf20Sopenharmony_ci	}
3718c2ecf20Sopenharmony_ci}
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_cistatic const char *can_get_state_str(const enum can_state state)
3748c2ecf20Sopenharmony_ci{
3758c2ecf20Sopenharmony_ci	switch (state) {
3768c2ecf20Sopenharmony_ci	case CAN_STATE_ERROR_ACTIVE:
3778c2ecf20Sopenharmony_ci		return "Error Active";
3788c2ecf20Sopenharmony_ci	case CAN_STATE_ERROR_WARNING:
3798c2ecf20Sopenharmony_ci		return "Error Warning";
3808c2ecf20Sopenharmony_ci	case CAN_STATE_ERROR_PASSIVE:
3818c2ecf20Sopenharmony_ci		return "Error Passive";
3828c2ecf20Sopenharmony_ci	case CAN_STATE_BUS_OFF:
3838c2ecf20Sopenharmony_ci		return "Bus Off";
3848c2ecf20Sopenharmony_ci	case CAN_STATE_STOPPED:
3858c2ecf20Sopenharmony_ci		return "Stopped";
3868c2ecf20Sopenharmony_ci	case CAN_STATE_SLEEPING:
3878c2ecf20Sopenharmony_ci		return "Sleeping";
3888c2ecf20Sopenharmony_ci	default:
3898c2ecf20Sopenharmony_ci		return "<unknown>";
3908c2ecf20Sopenharmony_ci	}
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci	return "<unknown>";
3938c2ecf20Sopenharmony_ci}
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_civoid can_change_state(struct net_device *dev, struct can_frame *cf,
3968c2ecf20Sopenharmony_ci		      enum can_state tx_state, enum can_state rx_state)
3978c2ecf20Sopenharmony_ci{
3988c2ecf20Sopenharmony_ci	struct can_priv *priv = netdev_priv(dev);
3998c2ecf20Sopenharmony_ci	enum can_state new_state = max(tx_state, rx_state);
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ci	if (unlikely(new_state == priv->state)) {
4028c2ecf20Sopenharmony_ci		netdev_warn(dev, "%s: oops, state did not change", __func__);
4038c2ecf20Sopenharmony_ci		return;
4048c2ecf20Sopenharmony_ci	}
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_ci	netdev_dbg(dev, "Controller changed from %s State (%d) into %s State (%d).\n",
4078c2ecf20Sopenharmony_ci		   can_get_state_str(priv->state), priv->state,
4088c2ecf20Sopenharmony_ci		   can_get_state_str(new_state), new_state);
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_ci	can_update_state_error_stats(dev, new_state);
4118c2ecf20Sopenharmony_ci	priv->state = new_state;
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ci	if (!cf)
4148c2ecf20Sopenharmony_ci		return;
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci	if (unlikely(new_state == CAN_STATE_BUS_OFF)) {
4178c2ecf20Sopenharmony_ci		cf->can_id |= CAN_ERR_BUSOFF;
4188c2ecf20Sopenharmony_ci		return;
4198c2ecf20Sopenharmony_ci	}
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ci	cf->can_id |= CAN_ERR_CRTL;
4228c2ecf20Sopenharmony_ci	cf->data[1] |= tx_state >= rx_state ?
4238c2ecf20Sopenharmony_ci		       can_tx_state_to_frame(dev, tx_state) : 0;
4248c2ecf20Sopenharmony_ci	cf->data[1] |= tx_state <= rx_state ?
4258c2ecf20Sopenharmony_ci		       can_rx_state_to_frame(dev, rx_state) : 0;
4268c2ecf20Sopenharmony_ci}
4278c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(can_change_state);
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_ci/* Local echo of CAN messages
4308c2ecf20Sopenharmony_ci *
4318c2ecf20Sopenharmony_ci * CAN network devices *should* support a local echo functionality
4328c2ecf20Sopenharmony_ci * (see Documentation/networking/can.rst). To test the handling of CAN
4338c2ecf20Sopenharmony_ci * interfaces that do not support the local echo both driver types are
4348c2ecf20Sopenharmony_ci * implemented. In the case that the driver does not support the echo
4358c2ecf20Sopenharmony_ci * the IFF_ECHO remains clear in dev->flags. This causes the PF_CAN core
4368c2ecf20Sopenharmony_ci * to perform the echo as a fallback solution.
4378c2ecf20Sopenharmony_ci */
4388c2ecf20Sopenharmony_cistatic void can_flush_echo_skb(struct net_device *dev)
4398c2ecf20Sopenharmony_ci{
4408c2ecf20Sopenharmony_ci	struct can_priv *priv = netdev_priv(dev);
4418c2ecf20Sopenharmony_ci	struct net_device_stats *stats = &dev->stats;
4428c2ecf20Sopenharmony_ci	int i;
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci	for (i = 0; i < priv->echo_skb_max; i++) {
4458c2ecf20Sopenharmony_ci		if (priv->echo_skb[i]) {
4468c2ecf20Sopenharmony_ci			kfree_skb(priv->echo_skb[i]);
4478c2ecf20Sopenharmony_ci			priv->echo_skb[i] = NULL;
4488c2ecf20Sopenharmony_ci			stats->tx_dropped++;
4498c2ecf20Sopenharmony_ci			stats->tx_aborted_errors++;
4508c2ecf20Sopenharmony_ci		}
4518c2ecf20Sopenharmony_ci	}
4528c2ecf20Sopenharmony_ci}
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci/* Put the skb on the stack to be looped backed locally lateron
4558c2ecf20Sopenharmony_ci *
4568c2ecf20Sopenharmony_ci * The function is typically called in the start_xmit function
4578c2ecf20Sopenharmony_ci * of the device driver. The driver must protect access to
4588c2ecf20Sopenharmony_ci * priv->echo_skb, if necessary.
4598c2ecf20Sopenharmony_ci */
4608c2ecf20Sopenharmony_ciint can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
4618c2ecf20Sopenharmony_ci		     unsigned int idx)
4628c2ecf20Sopenharmony_ci{
4638c2ecf20Sopenharmony_ci	struct can_priv *priv = netdev_priv(dev);
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ci	BUG_ON(idx >= priv->echo_skb_max);
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_ci	/* check flag whether this packet has to be looped back */
4688c2ecf20Sopenharmony_ci	if (!(dev->flags & IFF_ECHO) || skb->pkt_type != PACKET_LOOPBACK ||
4698c2ecf20Sopenharmony_ci	    (skb->protocol != htons(ETH_P_CAN) &&
4708c2ecf20Sopenharmony_ci	     skb->protocol != htons(ETH_P_CANFD))) {
4718c2ecf20Sopenharmony_ci		kfree_skb(skb);
4728c2ecf20Sopenharmony_ci		return 0;
4738c2ecf20Sopenharmony_ci	}
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci	if (!priv->echo_skb[idx]) {
4768c2ecf20Sopenharmony_ci		skb = can_create_echo_skb(skb);
4778c2ecf20Sopenharmony_ci		if (!skb)
4788c2ecf20Sopenharmony_ci			return -ENOMEM;
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_ci		/* make settings for echo to reduce code in irq context */
4818c2ecf20Sopenharmony_ci		skb->pkt_type = PACKET_BROADCAST;
4828c2ecf20Sopenharmony_ci		skb->ip_summed = CHECKSUM_UNNECESSARY;
4838c2ecf20Sopenharmony_ci		skb->dev = dev;
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_ci		/* save this skb for tx interrupt echo handling */
4868c2ecf20Sopenharmony_ci		priv->echo_skb[idx] = skb;
4878c2ecf20Sopenharmony_ci	} else {
4888c2ecf20Sopenharmony_ci		/* locking problem with netif_stop_queue() ?? */
4898c2ecf20Sopenharmony_ci		netdev_err(dev, "%s: BUG! echo_skb %d is occupied!\n", __func__, idx);
4908c2ecf20Sopenharmony_ci		kfree_skb(skb);
4918c2ecf20Sopenharmony_ci		return -EBUSY;
4928c2ecf20Sopenharmony_ci	}
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_ci	return 0;
4958c2ecf20Sopenharmony_ci}
4968c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(can_put_echo_skb);
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_cistruct sk_buff *
4998c2ecf20Sopenharmony_ci__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr)
5008c2ecf20Sopenharmony_ci{
5018c2ecf20Sopenharmony_ci	struct can_priv *priv = netdev_priv(dev);
5028c2ecf20Sopenharmony_ci
5038c2ecf20Sopenharmony_ci	if (idx >= priv->echo_skb_max) {
5048c2ecf20Sopenharmony_ci		netdev_err(dev, "%s: BUG! Trying to access can_priv::echo_skb out of bounds (%u/max %u)\n",
5058c2ecf20Sopenharmony_ci			   __func__, idx, priv->echo_skb_max);
5068c2ecf20Sopenharmony_ci		return NULL;
5078c2ecf20Sopenharmony_ci	}
5088c2ecf20Sopenharmony_ci
5098c2ecf20Sopenharmony_ci	if (priv->echo_skb[idx]) {
5108c2ecf20Sopenharmony_ci		/* Using "struct canfd_frame::len" for the frame
5118c2ecf20Sopenharmony_ci		 * length is supported on both CAN and CANFD frames.
5128c2ecf20Sopenharmony_ci		 */
5138c2ecf20Sopenharmony_ci		struct sk_buff *skb = priv->echo_skb[idx];
5148c2ecf20Sopenharmony_ci		struct canfd_frame *cf = (struct canfd_frame *)skb->data;
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_ci		/* get the real payload length for netdev statistics */
5178c2ecf20Sopenharmony_ci		if (cf->can_id & CAN_RTR_FLAG)
5188c2ecf20Sopenharmony_ci			*len_ptr = 0;
5198c2ecf20Sopenharmony_ci		else
5208c2ecf20Sopenharmony_ci			*len_ptr = cf->len;
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_ci		priv->echo_skb[idx] = NULL;
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci		return skb;
5258c2ecf20Sopenharmony_ci	}
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_ci	return NULL;
5288c2ecf20Sopenharmony_ci}
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_ci/* Get the skb from the stack and loop it back locally
5318c2ecf20Sopenharmony_ci *
5328c2ecf20Sopenharmony_ci * The function is typically called when the TX done interrupt
5338c2ecf20Sopenharmony_ci * is handled in the device driver. The driver must protect
5348c2ecf20Sopenharmony_ci * access to priv->echo_skb, if necessary.
5358c2ecf20Sopenharmony_ci */
5368c2ecf20Sopenharmony_ciunsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx)
5378c2ecf20Sopenharmony_ci{
5388c2ecf20Sopenharmony_ci	struct sk_buff *skb;
5398c2ecf20Sopenharmony_ci	u8 len;
5408c2ecf20Sopenharmony_ci
5418c2ecf20Sopenharmony_ci	skb = __can_get_echo_skb(dev, idx, &len);
5428c2ecf20Sopenharmony_ci	if (!skb)
5438c2ecf20Sopenharmony_ci		return 0;
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_ci	skb_get(skb);
5468c2ecf20Sopenharmony_ci	if (netif_rx(skb) == NET_RX_SUCCESS)
5478c2ecf20Sopenharmony_ci		dev_consume_skb_any(skb);
5488c2ecf20Sopenharmony_ci	else
5498c2ecf20Sopenharmony_ci		dev_kfree_skb_any(skb);
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_ci	return len;
5528c2ecf20Sopenharmony_ci}
5538c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(can_get_echo_skb);
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_ci/* Remove the skb from the stack and free it.
5568c2ecf20Sopenharmony_ci *
5578c2ecf20Sopenharmony_ci * The function is typically called when TX failed.
5588c2ecf20Sopenharmony_ci */
5598c2ecf20Sopenharmony_civoid can_free_echo_skb(struct net_device *dev, unsigned int idx)
5608c2ecf20Sopenharmony_ci{
5618c2ecf20Sopenharmony_ci	struct can_priv *priv = netdev_priv(dev);
5628c2ecf20Sopenharmony_ci
5638c2ecf20Sopenharmony_ci	BUG_ON(idx >= priv->echo_skb_max);
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_ci	if (priv->echo_skb[idx]) {
5668c2ecf20Sopenharmony_ci		dev_kfree_skb_any(priv->echo_skb[idx]);
5678c2ecf20Sopenharmony_ci		priv->echo_skb[idx] = NULL;
5688c2ecf20Sopenharmony_ci	}
5698c2ecf20Sopenharmony_ci}
5708c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(can_free_echo_skb);
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_ci/* CAN device restart for bus-off recovery */
5738c2ecf20Sopenharmony_cistatic void can_restart(struct net_device *dev)
5748c2ecf20Sopenharmony_ci{
5758c2ecf20Sopenharmony_ci	struct can_priv *priv = netdev_priv(dev);
5768c2ecf20Sopenharmony_ci	struct net_device_stats *stats = &dev->stats;
5778c2ecf20Sopenharmony_ci	struct sk_buff *skb;
5788c2ecf20Sopenharmony_ci	struct can_frame *cf;
5798c2ecf20Sopenharmony_ci	int err;
5808c2ecf20Sopenharmony_ci
5818c2ecf20Sopenharmony_ci	if (netif_carrier_ok(dev))
5828c2ecf20Sopenharmony_ci		netdev_err(dev, "Attempt to restart for bus-off recovery, but carrier is OK?\n");
5838c2ecf20Sopenharmony_ci
5848c2ecf20Sopenharmony_ci	/* No synchronization needed because the device is bus-off and
5858c2ecf20Sopenharmony_ci	 * no messages can come in or go out.
5868c2ecf20Sopenharmony_ci	 */
5878c2ecf20Sopenharmony_ci	can_flush_echo_skb(dev);
5888c2ecf20Sopenharmony_ci
5898c2ecf20Sopenharmony_ci	/* send restart message upstream */
5908c2ecf20Sopenharmony_ci	skb = alloc_can_err_skb(dev, &cf);
5918c2ecf20Sopenharmony_ci	if (!skb)
5928c2ecf20Sopenharmony_ci		goto restart;
5938c2ecf20Sopenharmony_ci
5948c2ecf20Sopenharmony_ci	cf->can_id |= CAN_ERR_RESTARTED;
5958c2ecf20Sopenharmony_ci
5968c2ecf20Sopenharmony_ci	stats->rx_packets++;
5978c2ecf20Sopenharmony_ci	stats->rx_bytes += cf->can_dlc;
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_ci	netif_rx_ni(skb);
6008c2ecf20Sopenharmony_ci
6018c2ecf20Sopenharmony_cirestart:
6028c2ecf20Sopenharmony_ci	netdev_dbg(dev, "restarted\n");
6038c2ecf20Sopenharmony_ci	priv->can_stats.restarts++;
6048c2ecf20Sopenharmony_ci
6058c2ecf20Sopenharmony_ci	/* Now restart the device */
6068c2ecf20Sopenharmony_ci	netif_carrier_on(dev);
6078c2ecf20Sopenharmony_ci	err = priv->do_set_mode(dev, CAN_MODE_START);
6088c2ecf20Sopenharmony_ci	if (err) {
6098c2ecf20Sopenharmony_ci		netdev_err(dev, "Error %d during restart", err);
6108c2ecf20Sopenharmony_ci		netif_carrier_off(dev);
6118c2ecf20Sopenharmony_ci	}
6128c2ecf20Sopenharmony_ci}
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_cistatic void can_restart_work(struct work_struct *work)
6158c2ecf20Sopenharmony_ci{
6168c2ecf20Sopenharmony_ci	struct delayed_work *dwork = to_delayed_work(work);
6178c2ecf20Sopenharmony_ci	struct can_priv *priv = container_of(dwork, struct can_priv,
6188c2ecf20Sopenharmony_ci					     restart_work);
6198c2ecf20Sopenharmony_ci
6208c2ecf20Sopenharmony_ci	can_restart(priv->dev);
6218c2ecf20Sopenharmony_ci}
6228c2ecf20Sopenharmony_ci
6238c2ecf20Sopenharmony_ciint can_restart_now(struct net_device *dev)
6248c2ecf20Sopenharmony_ci{
6258c2ecf20Sopenharmony_ci	struct can_priv *priv = netdev_priv(dev);
6268c2ecf20Sopenharmony_ci
6278c2ecf20Sopenharmony_ci	/* A manual restart is only permitted if automatic restart is
6288c2ecf20Sopenharmony_ci	 * disabled and the device is in the bus-off state
6298c2ecf20Sopenharmony_ci	 */
6308c2ecf20Sopenharmony_ci	if (priv->restart_ms)
6318c2ecf20Sopenharmony_ci		return -EINVAL;
6328c2ecf20Sopenharmony_ci	if (priv->state != CAN_STATE_BUS_OFF)
6338c2ecf20Sopenharmony_ci		return -EBUSY;
6348c2ecf20Sopenharmony_ci
6358c2ecf20Sopenharmony_ci	cancel_delayed_work_sync(&priv->restart_work);
6368c2ecf20Sopenharmony_ci	can_restart(dev);
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_ci	return 0;
6398c2ecf20Sopenharmony_ci}
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_ci/* CAN bus-off
6428c2ecf20Sopenharmony_ci *
6438c2ecf20Sopenharmony_ci * This functions should be called when the device goes bus-off to
6448c2ecf20Sopenharmony_ci * tell the netif layer that no more packets can be sent or received.
6458c2ecf20Sopenharmony_ci * If enabled, a timer is started to trigger bus-off recovery.
6468c2ecf20Sopenharmony_ci */
6478c2ecf20Sopenharmony_civoid can_bus_off(struct net_device *dev)
6488c2ecf20Sopenharmony_ci{
6498c2ecf20Sopenharmony_ci	struct can_priv *priv = netdev_priv(dev);
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_ci	if (priv->restart_ms)
6528c2ecf20Sopenharmony_ci		netdev_info(dev, "bus-off, scheduling restart in %d ms\n",
6538c2ecf20Sopenharmony_ci			    priv->restart_ms);
6548c2ecf20Sopenharmony_ci	else
6558c2ecf20Sopenharmony_ci		netdev_info(dev, "bus-off\n");
6568c2ecf20Sopenharmony_ci
6578c2ecf20Sopenharmony_ci	netif_carrier_off(dev);
6588c2ecf20Sopenharmony_ci
6598c2ecf20Sopenharmony_ci	if (priv->restart_ms)
6608c2ecf20Sopenharmony_ci		schedule_delayed_work(&priv->restart_work,
6618c2ecf20Sopenharmony_ci				      msecs_to_jiffies(priv->restart_ms));
6628c2ecf20Sopenharmony_ci}
6638c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(can_bus_off);
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_cistatic void can_setup(struct net_device *dev)
6668c2ecf20Sopenharmony_ci{
6678c2ecf20Sopenharmony_ci	dev->type = ARPHRD_CAN;
6688c2ecf20Sopenharmony_ci	dev->mtu = CAN_MTU;
6698c2ecf20Sopenharmony_ci	dev->hard_header_len = 0;
6708c2ecf20Sopenharmony_ci	dev->addr_len = 0;
6718c2ecf20Sopenharmony_ci	dev->tx_queue_len = 10;
6728c2ecf20Sopenharmony_ci
6738c2ecf20Sopenharmony_ci	/* New-style flags. */
6748c2ecf20Sopenharmony_ci	dev->flags = IFF_NOARP;
6758c2ecf20Sopenharmony_ci	dev->features = NETIF_F_HW_CSUM;
6768c2ecf20Sopenharmony_ci}
6778c2ecf20Sopenharmony_ci
6788c2ecf20Sopenharmony_cistruct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf)
6798c2ecf20Sopenharmony_ci{
6808c2ecf20Sopenharmony_ci	struct sk_buff *skb;
6818c2ecf20Sopenharmony_ci
6828c2ecf20Sopenharmony_ci	skb = netdev_alloc_skb(dev, sizeof(struct can_skb_priv) +
6838c2ecf20Sopenharmony_ci			       sizeof(struct can_frame));
6848c2ecf20Sopenharmony_ci	if (unlikely(!skb))
6858c2ecf20Sopenharmony_ci		return NULL;
6868c2ecf20Sopenharmony_ci
6878c2ecf20Sopenharmony_ci	skb->protocol = htons(ETH_P_CAN);
6888c2ecf20Sopenharmony_ci	skb->pkt_type = PACKET_BROADCAST;
6898c2ecf20Sopenharmony_ci	skb->ip_summed = CHECKSUM_UNNECESSARY;
6908c2ecf20Sopenharmony_ci
6918c2ecf20Sopenharmony_ci	skb_reset_mac_header(skb);
6928c2ecf20Sopenharmony_ci	skb_reset_network_header(skb);
6938c2ecf20Sopenharmony_ci	skb_reset_transport_header(skb);
6948c2ecf20Sopenharmony_ci
6958c2ecf20Sopenharmony_ci	can_skb_reserve(skb);
6968c2ecf20Sopenharmony_ci	can_skb_prv(skb)->ifindex = dev->ifindex;
6978c2ecf20Sopenharmony_ci	can_skb_prv(skb)->skbcnt = 0;
6988c2ecf20Sopenharmony_ci
6998c2ecf20Sopenharmony_ci	*cf = skb_put_zero(skb, sizeof(struct can_frame));
7008c2ecf20Sopenharmony_ci
7018c2ecf20Sopenharmony_ci	return skb;
7028c2ecf20Sopenharmony_ci}
7038c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(alloc_can_skb);
7048c2ecf20Sopenharmony_ci
7058c2ecf20Sopenharmony_cistruct sk_buff *alloc_canfd_skb(struct net_device *dev,
7068c2ecf20Sopenharmony_ci				struct canfd_frame **cfd)
7078c2ecf20Sopenharmony_ci{
7088c2ecf20Sopenharmony_ci	struct sk_buff *skb;
7098c2ecf20Sopenharmony_ci
7108c2ecf20Sopenharmony_ci	skb = netdev_alloc_skb(dev, sizeof(struct can_skb_priv) +
7118c2ecf20Sopenharmony_ci			       sizeof(struct canfd_frame));
7128c2ecf20Sopenharmony_ci	if (unlikely(!skb))
7138c2ecf20Sopenharmony_ci		return NULL;
7148c2ecf20Sopenharmony_ci
7158c2ecf20Sopenharmony_ci	skb->protocol = htons(ETH_P_CANFD);
7168c2ecf20Sopenharmony_ci	skb->pkt_type = PACKET_BROADCAST;
7178c2ecf20Sopenharmony_ci	skb->ip_summed = CHECKSUM_UNNECESSARY;
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_ci	skb_reset_mac_header(skb);
7208c2ecf20Sopenharmony_ci	skb_reset_network_header(skb);
7218c2ecf20Sopenharmony_ci	skb_reset_transport_header(skb);
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci	can_skb_reserve(skb);
7248c2ecf20Sopenharmony_ci	can_skb_prv(skb)->ifindex = dev->ifindex;
7258c2ecf20Sopenharmony_ci	can_skb_prv(skb)->skbcnt = 0;
7268c2ecf20Sopenharmony_ci
7278c2ecf20Sopenharmony_ci	*cfd = skb_put_zero(skb, sizeof(struct canfd_frame));
7288c2ecf20Sopenharmony_ci
7298c2ecf20Sopenharmony_ci	return skb;
7308c2ecf20Sopenharmony_ci}
7318c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(alloc_canfd_skb);
7328c2ecf20Sopenharmony_ci
7338c2ecf20Sopenharmony_cistruct sk_buff *alloc_can_err_skb(struct net_device *dev, struct can_frame **cf)
7348c2ecf20Sopenharmony_ci{
7358c2ecf20Sopenharmony_ci	struct sk_buff *skb;
7368c2ecf20Sopenharmony_ci
7378c2ecf20Sopenharmony_ci	skb = alloc_can_skb(dev, cf);
7388c2ecf20Sopenharmony_ci	if (unlikely(!skb))
7398c2ecf20Sopenharmony_ci		return NULL;
7408c2ecf20Sopenharmony_ci
7418c2ecf20Sopenharmony_ci	(*cf)->can_id = CAN_ERR_FLAG;
7428c2ecf20Sopenharmony_ci	(*cf)->can_dlc = CAN_ERR_DLC;
7438c2ecf20Sopenharmony_ci
7448c2ecf20Sopenharmony_ci	return skb;
7458c2ecf20Sopenharmony_ci}
7468c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(alloc_can_err_skb);
7478c2ecf20Sopenharmony_ci
7488c2ecf20Sopenharmony_ci/* Allocate and setup space for the CAN network device */
7498c2ecf20Sopenharmony_cistruct net_device *alloc_candev_mqs(int sizeof_priv, unsigned int echo_skb_max,
7508c2ecf20Sopenharmony_ci				    unsigned int txqs, unsigned int rxqs)
7518c2ecf20Sopenharmony_ci{
7528c2ecf20Sopenharmony_ci	struct can_ml_priv *can_ml;
7538c2ecf20Sopenharmony_ci	struct net_device *dev;
7548c2ecf20Sopenharmony_ci	struct can_priv *priv;
7558c2ecf20Sopenharmony_ci	int size;
7568c2ecf20Sopenharmony_ci
7578c2ecf20Sopenharmony_ci	/* We put the driver's priv, the CAN mid layer priv and the
7588c2ecf20Sopenharmony_ci	 * echo skb into the netdevice's priv. The memory layout for
7598c2ecf20Sopenharmony_ci	 * the netdev_priv is like this:
7608c2ecf20Sopenharmony_ci	 *
7618c2ecf20Sopenharmony_ci	 * +-------------------------+
7628c2ecf20Sopenharmony_ci	 * | driver's priv           |
7638c2ecf20Sopenharmony_ci	 * +-------------------------+
7648c2ecf20Sopenharmony_ci	 * | struct can_ml_priv      |
7658c2ecf20Sopenharmony_ci	 * +-------------------------+
7668c2ecf20Sopenharmony_ci	 * | array of struct sk_buff |
7678c2ecf20Sopenharmony_ci	 * +-------------------------+
7688c2ecf20Sopenharmony_ci	 */
7698c2ecf20Sopenharmony_ci
7708c2ecf20Sopenharmony_ci	size = ALIGN(sizeof_priv, NETDEV_ALIGN) + sizeof(struct can_ml_priv);
7718c2ecf20Sopenharmony_ci
7728c2ecf20Sopenharmony_ci	if (echo_skb_max)
7738c2ecf20Sopenharmony_ci		size = ALIGN(size, sizeof(struct sk_buff *)) +
7748c2ecf20Sopenharmony_ci			echo_skb_max * sizeof(struct sk_buff *);
7758c2ecf20Sopenharmony_ci
7768c2ecf20Sopenharmony_ci	dev = alloc_netdev_mqs(size, "can%d", NET_NAME_UNKNOWN, can_setup,
7778c2ecf20Sopenharmony_ci			       txqs, rxqs);
7788c2ecf20Sopenharmony_ci	if (!dev)
7798c2ecf20Sopenharmony_ci		return NULL;
7808c2ecf20Sopenharmony_ci
7818c2ecf20Sopenharmony_ci	priv = netdev_priv(dev);
7828c2ecf20Sopenharmony_ci	priv->dev = dev;
7838c2ecf20Sopenharmony_ci
7848c2ecf20Sopenharmony_ci	can_ml = (void *)priv + ALIGN(sizeof_priv, NETDEV_ALIGN);
7858c2ecf20Sopenharmony_ci	can_set_ml_priv(dev, can_ml);
7868c2ecf20Sopenharmony_ci
7878c2ecf20Sopenharmony_ci	if (echo_skb_max) {
7888c2ecf20Sopenharmony_ci		priv->echo_skb_max = echo_skb_max;
7898c2ecf20Sopenharmony_ci		priv->echo_skb = (void *)priv +
7908c2ecf20Sopenharmony_ci			(size - echo_skb_max * sizeof(struct sk_buff *));
7918c2ecf20Sopenharmony_ci	}
7928c2ecf20Sopenharmony_ci
7938c2ecf20Sopenharmony_ci	priv->state = CAN_STATE_STOPPED;
7948c2ecf20Sopenharmony_ci
7958c2ecf20Sopenharmony_ci	INIT_DELAYED_WORK(&priv->restart_work, can_restart_work);
7968c2ecf20Sopenharmony_ci
7978c2ecf20Sopenharmony_ci	return dev;
7988c2ecf20Sopenharmony_ci}
7998c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(alloc_candev_mqs);
8008c2ecf20Sopenharmony_ci
8018c2ecf20Sopenharmony_ci/* Free space of the CAN network device */
8028c2ecf20Sopenharmony_civoid free_candev(struct net_device *dev)
8038c2ecf20Sopenharmony_ci{
8048c2ecf20Sopenharmony_ci	free_netdev(dev);
8058c2ecf20Sopenharmony_ci}
8068c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(free_candev);
8078c2ecf20Sopenharmony_ci
8088c2ecf20Sopenharmony_ci/* changing MTU and control mode for CAN/CANFD devices */
8098c2ecf20Sopenharmony_ciint can_change_mtu(struct net_device *dev, int new_mtu)
8108c2ecf20Sopenharmony_ci{
8118c2ecf20Sopenharmony_ci	struct can_priv *priv = netdev_priv(dev);
8128c2ecf20Sopenharmony_ci
8138c2ecf20Sopenharmony_ci	/* Do not allow changing the MTU while running */
8148c2ecf20Sopenharmony_ci	if (dev->flags & IFF_UP)
8158c2ecf20Sopenharmony_ci		return -EBUSY;
8168c2ecf20Sopenharmony_ci
8178c2ecf20Sopenharmony_ci	/* allow change of MTU according to the CANFD ability of the device */
8188c2ecf20Sopenharmony_ci	switch (new_mtu) {
8198c2ecf20Sopenharmony_ci	case CAN_MTU:
8208c2ecf20Sopenharmony_ci		/* 'CANFD-only' controllers can not switch to CAN_MTU */
8218c2ecf20Sopenharmony_ci		if (priv->ctrlmode_static & CAN_CTRLMODE_FD)
8228c2ecf20Sopenharmony_ci			return -EINVAL;
8238c2ecf20Sopenharmony_ci
8248c2ecf20Sopenharmony_ci		priv->ctrlmode &= ~CAN_CTRLMODE_FD;
8258c2ecf20Sopenharmony_ci		break;
8268c2ecf20Sopenharmony_ci
8278c2ecf20Sopenharmony_ci	case CANFD_MTU:
8288c2ecf20Sopenharmony_ci		/* check for potential CANFD ability */
8298c2ecf20Sopenharmony_ci		if (!(priv->ctrlmode_supported & CAN_CTRLMODE_FD) &&
8308c2ecf20Sopenharmony_ci		    !(priv->ctrlmode_static & CAN_CTRLMODE_FD))
8318c2ecf20Sopenharmony_ci			return -EINVAL;
8328c2ecf20Sopenharmony_ci
8338c2ecf20Sopenharmony_ci		priv->ctrlmode |= CAN_CTRLMODE_FD;
8348c2ecf20Sopenharmony_ci		break;
8358c2ecf20Sopenharmony_ci
8368c2ecf20Sopenharmony_ci	default:
8378c2ecf20Sopenharmony_ci		return -EINVAL;
8388c2ecf20Sopenharmony_ci	}
8398c2ecf20Sopenharmony_ci
8408c2ecf20Sopenharmony_ci	dev->mtu = new_mtu;
8418c2ecf20Sopenharmony_ci	return 0;
8428c2ecf20Sopenharmony_ci}
8438c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(can_change_mtu);
8448c2ecf20Sopenharmony_ci
8458c2ecf20Sopenharmony_ci/* Common open function when the device gets opened.
8468c2ecf20Sopenharmony_ci *
8478c2ecf20Sopenharmony_ci * This function should be called in the open function of the device
8488c2ecf20Sopenharmony_ci * driver.
8498c2ecf20Sopenharmony_ci */
8508c2ecf20Sopenharmony_ciint open_candev(struct net_device *dev)
8518c2ecf20Sopenharmony_ci{
8528c2ecf20Sopenharmony_ci	struct can_priv *priv = netdev_priv(dev);
8538c2ecf20Sopenharmony_ci
8548c2ecf20Sopenharmony_ci	if (!priv->bittiming.bitrate) {
8558c2ecf20Sopenharmony_ci		netdev_err(dev, "bit-timing not yet defined\n");
8568c2ecf20Sopenharmony_ci		return -EINVAL;
8578c2ecf20Sopenharmony_ci	}
8588c2ecf20Sopenharmony_ci
8598c2ecf20Sopenharmony_ci	/* For CAN FD the data bitrate has to be >= the arbitration bitrate */
8608c2ecf20Sopenharmony_ci	if ((priv->ctrlmode & CAN_CTRLMODE_FD) &&
8618c2ecf20Sopenharmony_ci	    (!priv->data_bittiming.bitrate ||
8628c2ecf20Sopenharmony_ci	     priv->data_bittiming.bitrate < priv->bittiming.bitrate)) {
8638c2ecf20Sopenharmony_ci		netdev_err(dev, "incorrect/missing data bit-timing\n");
8648c2ecf20Sopenharmony_ci		return -EINVAL;
8658c2ecf20Sopenharmony_ci	}
8668c2ecf20Sopenharmony_ci
8678c2ecf20Sopenharmony_ci	/* Switch carrier on if device was stopped while in bus-off state */
8688c2ecf20Sopenharmony_ci	if (!netif_carrier_ok(dev))
8698c2ecf20Sopenharmony_ci		netif_carrier_on(dev);
8708c2ecf20Sopenharmony_ci
8718c2ecf20Sopenharmony_ci	return 0;
8728c2ecf20Sopenharmony_ci}
8738c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(open_candev);
8748c2ecf20Sopenharmony_ci
8758c2ecf20Sopenharmony_ci#ifdef CONFIG_OF
8768c2ecf20Sopenharmony_ci/* Common function that can be used to understand the limitation of
8778c2ecf20Sopenharmony_ci * a transceiver when it provides no means to determine these limitations
8788c2ecf20Sopenharmony_ci * at runtime.
8798c2ecf20Sopenharmony_ci */
8808c2ecf20Sopenharmony_civoid of_can_transceiver(struct net_device *dev)
8818c2ecf20Sopenharmony_ci{
8828c2ecf20Sopenharmony_ci	struct device_node *dn;
8838c2ecf20Sopenharmony_ci	struct can_priv *priv = netdev_priv(dev);
8848c2ecf20Sopenharmony_ci	struct device_node *np = dev->dev.parent->of_node;
8858c2ecf20Sopenharmony_ci	int ret;
8868c2ecf20Sopenharmony_ci
8878c2ecf20Sopenharmony_ci	dn = of_get_child_by_name(np, "can-transceiver");
8888c2ecf20Sopenharmony_ci	if (!dn)
8898c2ecf20Sopenharmony_ci		return;
8908c2ecf20Sopenharmony_ci
8918c2ecf20Sopenharmony_ci	ret = of_property_read_u32(dn, "max-bitrate", &priv->bitrate_max);
8928c2ecf20Sopenharmony_ci	of_node_put(dn);
8938c2ecf20Sopenharmony_ci	if ((ret && ret != -EINVAL) || (!ret && !priv->bitrate_max))
8948c2ecf20Sopenharmony_ci		netdev_warn(dev, "Invalid value for transceiver max bitrate. Ignoring bitrate limit.\n");
8958c2ecf20Sopenharmony_ci}
8968c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(of_can_transceiver);
8978c2ecf20Sopenharmony_ci#endif
8988c2ecf20Sopenharmony_ci
8998c2ecf20Sopenharmony_ci/* Common close function for cleanup before the device gets closed.
9008c2ecf20Sopenharmony_ci *
9018c2ecf20Sopenharmony_ci * This function should be called in the close function of the device
9028c2ecf20Sopenharmony_ci * driver.
9038c2ecf20Sopenharmony_ci */
9048c2ecf20Sopenharmony_civoid close_candev(struct net_device *dev)
9058c2ecf20Sopenharmony_ci{
9068c2ecf20Sopenharmony_ci	struct can_priv *priv = netdev_priv(dev);
9078c2ecf20Sopenharmony_ci
9088c2ecf20Sopenharmony_ci	cancel_delayed_work_sync(&priv->restart_work);
9098c2ecf20Sopenharmony_ci	can_flush_echo_skb(dev);
9108c2ecf20Sopenharmony_ci}
9118c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(close_candev);
9128c2ecf20Sopenharmony_ci
9138c2ecf20Sopenharmony_ci/* CAN netlink interface */
9148c2ecf20Sopenharmony_cistatic const struct nla_policy can_policy[IFLA_CAN_MAX + 1] = {
9158c2ecf20Sopenharmony_ci	[IFLA_CAN_STATE]	= { .type = NLA_U32 },
9168c2ecf20Sopenharmony_ci	[IFLA_CAN_CTRLMODE]	= { .len = sizeof(struct can_ctrlmode) },
9178c2ecf20Sopenharmony_ci	[IFLA_CAN_RESTART_MS]	= { .type = NLA_U32 },
9188c2ecf20Sopenharmony_ci	[IFLA_CAN_RESTART]	= { .type = NLA_U32 },
9198c2ecf20Sopenharmony_ci	[IFLA_CAN_BITTIMING]	= { .len = sizeof(struct can_bittiming) },
9208c2ecf20Sopenharmony_ci	[IFLA_CAN_BITTIMING_CONST]
9218c2ecf20Sopenharmony_ci				= { .len = sizeof(struct can_bittiming_const) },
9228c2ecf20Sopenharmony_ci	[IFLA_CAN_CLOCK]	= { .len = sizeof(struct can_clock) },
9238c2ecf20Sopenharmony_ci	[IFLA_CAN_BERR_COUNTER]	= { .len = sizeof(struct can_berr_counter) },
9248c2ecf20Sopenharmony_ci	[IFLA_CAN_DATA_BITTIMING]
9258c2ecf20Sopenharmony_ci				= { .len = sizeof(struct can_bittiming) },
9268c2ecf20Sopenharmony_ci	[IFLA_CAN_DATA_BITTIMING_CONST]
9278c2ecf20Sopenharmony_ci				= { .len = sizeof(struct can_bittiming_const) },
9288c2ecf20Sopenharmony_ci	[IFLA_CAN_TERMINATION]	= { .type = NLA_U16 },
9298c2ecf20Sopenharmony_ci};
9308c2ecf20Sopenharmony_ci
9318c2ecf20Sopenharmony_cistatic int can_validate(struct nlattr *tb[], struct nlattr *data[],
9328c2ecf20Sopenharmony_ci			struct netlink_ext_ack *extack)
9338c2ecf20Sopenharmony_ci{
9348c2ecf20Sopenharmony_ci	bool is_can_fd = false;
9358c2ecf20Sopenharmony_ci
9368c2ecf20Sopenharmony_ci	/* Make sure that valid CAN FD configurations always consist of
9378c2ecf20Sopenharmony_ci	 * - nominal/arbitration bittiming
9388c2ecf20Sopenharmony_ci	 * - data bittiming
9398c2ecf20Sopenharmony_ci	 * - control mode with CAN_CTRLMODE_FD set
9408c2ecf20Sopenharmony_ci	 */
9418c2ecf20Sopenharmony_ci
9428c2ecf20Sopenharmony_ci	if (!data)
9438c2ecf20Sopenharmony_ci		return 0;
9448c2ecf20Sopenharmony_ci
9458c2ecf20Sopenharmony_ci	if (data[IFLA_CAN_CTRLMODE]) {
9468c2ecf20Sopenharmony_ci		struct can_ctrlmode *cm = nla_data(data[IFLA_CAN_CTRLMODE]);
9478c2ecf20Sopenharmony_ci
9488c2ecf20Sopenharmony_ci		is_can_fd = cm->flags & cm->mask & CAN_CTRLMODE_FD;
9498c2ecf20Sopenharmony_ci	}
9508c2ecf20Sopenharmony_ci
9518c2ecf20Sopenharmony_ci	if (is_can_fd) {
9528c2ecf20Sopenharmony_ci		if (!data[IFLA_CAN_BITTIMING] || !data[IFLA_CAN_DATA_BITTIMING])
9538c2ecf20Sopenharmony_ci			return -EOPNOTSUPP;
9548c2ecf20Sopenharmony_ci	}
9558c2ecf20Sopenharmony_ci
9568c2ecf20Sopenharmony_ci	if (data[IFLA_CAN_DATA_BITTIMING]) {
9578c2ecf20Sopenharmony_ci		if (!is_can_fd || !data[IFLA_CAN_BITTIMING])
9588c2ecf20Sopenharmony_ci			return -EOPNOTSUPP;
9598c2ecf20Sopenharmony_ci	}
9608c2ecf20Sopenharmony_ci
9618c2ecf20Sopenharmony_ci	return 0;
9628c2ecf20Sopenharmony_ci}
9638c2ecf20Sopenharmony_ci
9648c2ecf20Sopenharmony_cistatic int can_changelink(struct net_device *dev, struct nlattr *tb[],
9658c2ecf20Sopenharmony_ci			  struct nlattr *data[],
9668c2ecf20Sopenharmony_ci			  struct netlink_ext_ack *extack)
9678c2ecf20Sopenharmony_ci{
9688c2ecf20Sopenharmony_ci	struct can_priv *priv = netdev_priv(dev);
9698c2ecf20Sopenharmony_ci	int err;
9708c2ecf20Sopenharmony_ci
9718c2ecf20Sopenharmony_ci	/* We need synchronization with dev->stop() */
9728c2ecf20Sopenharmony_ci	ASSERT_RTNL();
9738c2ecf20Sopenharmony_ci
9748c2ecf20Sopenharmony_ci	if (data[IFLA_CAN_BITTIMING]) {
9758c2ecf20Sopenharmony_ci		struct can_bittiming bt;
9768c2ecf20Sopenharmony_ci
9778c2ecf20Sopenharmony_ci		/* Do not allow changing bittiming while running */
9788c2ecf20Sopenharmony_ci		if (dev->flags & IFF_UP)
9798c2ecf20Sopenharmony_ci			return -EBUSY;
9808c2ecf20Sopenharmony_ci
9818c2ecf20Sopenharmony_ci		/* Calculate bittiming parameters based on
9828c2ecf20Sopenharmony_ci		 * bittiming_const if set, otherwise pass bitrate
9838c2ecf20Sopenharmony_ci		 * directly via do_set_bitrate(). Bail out if neither
9848c2ecf20Sopenharmony_ci		 * is given.
9858c2ecf20Sopenharmony_ci		 */
9868c2ecf20Sopenharmony_ci		if (!priv->bittiming_const && !priv->do_set_bittiming)
9878c2ecf20Sopenharmony_ci			return -EOPNOTSUPP;
9888c2ecf20Sopenharmony_ci
9898c2ecf20Sopenharmony_ci		memcpy(&bt, nla_data(data[IFLA_CAN_BITTIMING]), sizeof(bt));
9908c2ecf20Sopenharmony_ci		err = can_get_bittiming(dev, &bt,
9918c2ecf20Sopenharmony_ci					priv->bittiming_const,
9928c2ecf20Sopenharmony_ci					priv->bitrate_const,
9938c2ecf20Sopenharmony_ci					priv->bitrate_const_cnt);
9948c2ecf20Sopenharmony_ci		if (err)
9958c2ecf20Sopenharmony_ci			return err;
9968c2ecf20Sopenharmony_ci
9978c2ecf20Sopenharmony_ci		if (priv->bitrate_max && bt.bitrate > priv->bitrate_max) {
9988c2ecf20Sopenharmony_ci			netdev_err(dev, "arbitration bitrate surpasses transceiver capabilities of %d bps\n",
9998c2ecf20Sopenharmony_ci				   priv->bitrate_max);
10008c2ecf20Sopenharmony_ci			return -EINVAL;
10018c2ecf20Sopenharmony_ci		}
10028c2ecf20Sopenharmony_ci
10038c2ecf20Sopenharmony_ci		memcpy(&priv->bittiming, &bt, sizeof(bt));
10048c2ecf20Sopenharmony_ci
10058c2ecf20Sopenharmony_ci		if (priv->do_set_bittiming) {
10068c2ecf20Sopenharmony_ci			/* Finally, set the bit-timing registers */
10078c2ecf20Sopenharmony_ci			err = priv->do_set_bittiming(dev);
10088c2ecf20Sopenharmony_ci			if (err)
10098c2ecf20Sopenharmony_ci				return err;
10108c2ecf20Sopenharmony_ci		}
10118c2ecf20Sopenharmony_ci	}
10128c2ecf20Sopenharmony_ci
10138c2ecf20Sopenharmony_ci	if (data[IFLA_CAN_CTRLMODE]) {
10148c2ecf20Sopenharmony_ci		struct can_ctrlmode *cm;
10158c2ecf20Sopenharmony_ci		u32 ctrlstatic;
10168c2ecf20Sopenharmony_ci		u32 maskedflags;
10178c2ecf20Sopenharmony_ci
10188c2ecf20Sopenharmony_ci		/* Do not allow changing controller mode while running */
10198c2ecf20Sopenharmony_ci		if (dev->flags & IFF_UP)
10208c2ecf20Sopenharmony_ci			return -EBUSY;
10218c2ecf20Sopenharmony_ci		cm = nla_data(data[IFLA_CAN_CTRLMODE]);
10228c2ecf20Sopenharmony_ci		ctrlstatic = priv->ctrlmode_static;
10238c2ecf20Sopenharmony_ci		maskedflags = cm->flags & cm->mask;
10248c2ecf20Sopenharmony_ci
10258c2ecf20Sopenharmony_ci		/* check whether provided bits are allowed to be passed */
10268c2ecf20Sopenharmony_ci		if (cm->mask & ~(priv->ctrlmode_supported | ctrlstatic))
10278c2ecf20Sopenharmony_ci			return -EOPNOTSUPP;
10288c2ecf20Sopenharmony_ci
10298c2ecf20Sopenharmony_ci		/* do not check for static fd-non-iso if 'fd' is disabled */
10308c2ecf20Sopenharmony_ci		if (!(maskedflags & CAN_CTRLMODE_FD))
10318c2ecf20Sopenharmony_ci			ctrlstatic &= ~CAN_CTRLMODE_FD_NON_ISO;
10328c2ecf20Sopenharmony_ci
10338c2ecf20Sopenharmony_ci		/* make sure static options are provided by configuration */
10348c2ecf20Sopenharmony_ci		if ((maskedflags & ctrlstatic) != ctrlstatic)
10358c2ecf20Sopenharmony_ci			return -EOPNOTSUPP;
10368c2ecf20Sopenharmony_ci
10378c2ecf20Sopenharmony_ci		/* clear bits to be modified and copy the flag values */
10388c2ecf20Sopenharmony_ci		priv->ctrlmode &= ~cm->mask;
10398c2ecf20Sopenharmony_ci		priv->ctrlmode |= maskedflags;
10408c2ecf20Sopenharmony_ci
10418c2ecf20Sopenharmony_ci		/* CAN_CTRLMODE_FD can only be set when driver supports FD */
10428c2ecf20Sopenharmony_ci		if (priv->ctrlmode & CAN_CTRLMODE_FD)
10438c2ecf20Sopenharmony_ci			dev->mtu = CANFD_MTU;
10448c2ecf20Sopenharmony_ci		else
10458c2ecf20Sopenharmony_ci			dev->mtu = CAN_MTU;
10468c2ecf20Sopenharmony_ci	}
10478c2ecf20Sopenharmony_ci
10488c2ecf20Sopenharmony_ci	if (data[IFLA_CAN_RESTART_MS]) {
10498c2ecf20Sopenharmony_ci		/* Do not allow changing restart delay while running */
10508c2ecf20Sopenharmony_ci		if (dev->flags & IFF_UP)
10518c2ecf20Sopenharmony_ci			return -EBUSY;
10528c2ecf20Sopenharmony_ci		priv->restart_ms = nla_get_u32(data[IFLA_CAN_RESTART_MS]);
10538c2ecf20Sopenharmony_ci	}
10548c2ecf20Sopenharmony_ci
10558c2ecf20Sopenharmony_ci	if (data[IFLA_CAN_RESTART]) {
10568c2ecf20Sopenharmony_ci		/* Do not allow a restart while not running */
10578c2ecf20Sopenharmony_ci		if (!(dev->flags & IFF_UP))
10588c2ecf20Sopenharmony_ci			return -EINVAL;
10598c2ecf20Sopenharmony_ci		err = can_restart_now(dev);
10608c2ecf20Sopenharmony_ci		if (err)
10618c2ecf20Sopenharmony_ci			return err;
10628c2ecf20Sopenharmony_ci	}
10638c2ecf20Sopenharmony_ci
10648c2ecf20Sopenharmony_ci	if (data[IFLA_CAN_DATA_BITTIMING]) {
10658c2ecf20Sopenharmony_ci		struct can_bittiming dbt;
10668c2ecf20Sopenharmony_ci
10678c2ecf20Sopenharmony_ci		/* Do not allow changing bittiming while running */
10688c2ecf20Sopenharmony_ci		if (dev->flags & IFF_UP)
10698c2ecf20Sopenharmony_ci			return -EBUSY;
10708c2ecf20Sopenharmony_ci
10718c2ecf20Sopenharmony_ci		/* Calculate bittiming parameters based on
10728c2ecf20Sopenharmony_ci		 * data_bittiming_const if set, otherwise pass bitrate
10738c2ecf20Sopenharmony_ci		 * directly via do_set_bitrate(). Bail out if neither
10748c2ecf20Sopenharmony_ci		 * is given.
10758c2ecf20Sopenharmony_ci		 */
10768c2ecf20Sopenharmony_ci		if (!priv->data_bittiming_const && !priv->do_set_data_bittiming)
10778c2ecf20Sopenharmony_ci			return -EOPNOTSUPP;
10788c2ecf20Sopenharmony_ci
10798c2ecf20Sopenharmony_ci		memcpy(&dbt, nla_data(data[IFLA_CAN_DATA_BITTIMING]),
10808c2ecf20Sopenharmony_ci		       sizeof(dbt));
10818c2ecf20Sopenharmony_ci		err = can_get_bittiming(dev, &dbt,
10828c2ecf20Sopenharmony_ci					priv->data_bittiming_const,
10838c2ecf20Sopenharmony_ci					priv->data_bitrate_const,
10848c2ecf20Sopenharmony_ci					priv->data_bitrate_const_cnt);
10858c2ecf20Sopenharmony_ci		if (err)
10868c2ecf20Sopenharmony_ci			return err;
10878c2ecf20Sopenharmony_ci
10888c2ecf20Sopenharmony_ci		if (priv->bitrate_max && dbt.bitrate > priv->bitrate_max) {
10898c2ecf20Sopenharmony_ci			netdev_err(dev, "canfd data bitrate surpasses transceiver capabilities of %d bps\n",
10908c2ecf20Sopenharmony_ci				   priv->bitrate_max);
10918c2ecf20Sopenharmony_ci			return -EINVAL;
10928c2ecf20Sopenharmony_ci		}
10938c2ecf20Sopenharmony_ci
10948c2ecf20Sopenharmony_ci		memcpy(&priv->data_bittiming, &dbt, sizeof(dbt));
10958c2ecf20Sopenharmony_ci
10968c2ecf20Sopenharmony_ci		if (priv->do_set_data_bittiming) {
10978c2ecf20Sopenharmony_ci			/* Finally, set the bit-timing registers */
10988c2ecf20Sopenharmony_ci			err = priv->do_set_data_bittiming(dev);
10998c2ecf20Sopenharmony_ci			if (err)
11008c2ecf20Sopenharmony_ci				return err;
11018c2ecf20Sopenharmony_ci		}
11028c2ecf20Sopenharmony_ci	}
11038c2ecf20Sopenharmony_ci
11048c2ecf20Sopenharmony_ci	if (data[IFLA_CAN_TERMINATION]) {
11058c2ecf20Sopenharmony_ci		const u16 termval = nla_get_u16(data[IFLA_CAN_TERMINATION]);
11068c2ecf20Sopenharmony_ci		const unsigned int num_term = priv->termination_const_cnt;
11078c2ecf20Sopenharmony_ci		unsigned int i;
11088c2ecf20Sopenharmony_ci
11098c2ecf20Sopenharmony_ci		if (!priv->do_set_termination)
11108c2ecf20Sopenharmony_ci			return -EOPNOTSUPP;
11118c2ecf20Sopenharmony_ci
11128c2ecf20Sopenharmony_ci		/* check whether given value is supported by the interface */
11138c2ecf20Sopenharmony_ci		for (i = 0; i < num_term; i++) {
11148c2ecf20Sopenharmony_ci			if (termval == priv->termination_const[i])
11158c2ecf20Sopenharmony_ci				break;
11168c2ecf20Sopenharmony_ci		}
11178c2ecf20Sopenharmony_ci		if (i >= num_term)
11188c2ecf20Sopenharmony_ci			return -EINVAL;
11198c2ecf20Sopenharmony_ci
11208c2ecf20Sopenharmony_ci		/* Finally, set the termination value */
11218c2ecf20Sopenharmony_ci		err = priv->do_set_termination(dev, termval);
11228c2ecf20Sopenharmony_ci		if (err)
11238c2ecf20Sopenharmony_ci			return err;
11248c2ecf20Sopenharmony_ci
11258c2ecf20Sopenharmony_ci		priv->termination = termval;
11268c2ecf20Sopenharmony_ci	}
11278c2ecf20Sopenharmony_ci
11288c2ecf20Sopenharmony_ci	return 0;
11298c2ecf20Sopenharmony_ci}
11308c2ecf20Sopenharmony_ci
11318c2ecf20Sopenharmony_cistatic size_t can_get_size(const struct net_device *dev)
11328c2ecf20Sopenharmony_ci{
11338c2ecf20Sopenharmony_ci	struct can_priv *priv = netdev_priv(dev);
11348c2ecf20Sopenharmony_ci	size_t size = 0;
11358c2ecf20Sopenharmony_ci
11368c2ecf20Sopenharmony_ci	if (priv->bittiming.bitrate)				/* IFLA_CAN_BITTIMING */
11378c2ecf20Sopenharmony_ci		size += nla_total_size(sizeof(struct can_bittiming));
11388c2ecf20Sopenharmony_ci	if (priv->bittiming_const)				/* IFLA_CAN_BITTIMING_CONST */
11398c2ecf20Sopenharmony_ci		size += nla_total_size(sizeof(struct can_bittiming_const));
11408c2ecf20Sopenharmony_ci	size += nla_total_size(sizeof(struct can_clock));	/* IFLA_CAN_CLOCK */
11418c2ecf20Sopenharmony_ci	size += nla_total_size(sizeof(u32));			/* IFLA_CAN_STATE */
11428c2ecf20Sopenharmony_ci	size += nla_total_size(sizeof(struct can_ctrlmode));	/* IFLA_CAN_CTRLMODE */
11438c2ecf20Sopenharmony_ci	size += nla_total_size(sizeof(u32));			/* IFLA_CAN_RESTART_MS */
11448c2ecf20Sopenharmony_ci	if (priv->do_get_berr_counter)				/* IFLA_CAN_BERR_COUNTER */
11458c2ecf20Sopenharmony_ci		size += nla_total_size(sizeof(struct can_berr_counter));
11468c2ecf20Sopenharmony_ci	if (priv->data_bittiming.bitrate)			/* IFLA_CAN_DATA_BITTIMING */
11478c2ecf20Sopenharmony_ci		size += nla_total_size(sizeof(struct can_bittiming));
11488c2ecf20Sopenharmony_ci	if (priv->data_bittiming_const)				/* IFLA_CAN_DATA_BITTIMING_CONST */
11498c2ecf20Sopenharmony_ci		size += nla_total_size(sizeof(struct can_bittiming_const));
11508c2ecf20Sopenharmony_ci	if (priv->termination_const) {
11518c2ecf20Sopenharmony_ci		size += nla_total_size(sizeof(priv->termination));		/* IFLA_CAN_TERMINATION */
11528c2ecf20Sopenharmony_ci		size += nla_total_size(sizeof(*priv->termination_const) *	/* IFLA_CAN_TERMINATION_CONST */
11538c2ecf20Sopenharmony_ci				       priv->termination_const_cnt);
11548c2ecf20Sopenharmony_ci	}
11558c2ecf20Sopenharmony_ci	if (priv->bitrate_const)				/* IFLA_CAN_BITRATE_CONST */
11568c2ecf20Sopenharmony_ci		size += nla_total_size(sizeof(*priv->bitrate_const) *
11578c2ecf20Sopenharmony_ci				       priv->bitrate_const_cnt);
11588c2ecf20Sopenharmony_ci	if (priv->data_bitrate_const)				/* IFLA_CAN_DATA_BITRATE_CONST */
11598c2ecf20Sopenharmony_ci		size += nla_total_size(sizeof(*priv->data_bitrate_const) *
11608c2ecf20Sopenharmony_ci				       priv->data_bitrate_const_cnt);
11618c2ecf20Sopenharmony_ci	size += sizeof(priv->bitrate_max);			/* IFLA_CAN_BITRATE_MAX */
11628c2ecf20Sopenharmony_ci
11638c2ecf20Sopenharmony_ci	return size;
11648c2ecf20Sopenharmony_ci}
11658c2ecf20Sopenharmony_ci
11668c2ecf20Sopenharmony_cistatic int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
11678c2ecf20Sopenharmony_ci{
11688c2ecf20Sopenharmony_ci	struct can_priv *priv = netdev_priv(dev);
11698c2ecf20Sopenharmony_ci	struct can_ctrlmode cm = {.flags = priv->ctrlmode};
11708c2ecf20Sopenharmony_ci	struct can_berr_counter bec = { };
11718c2ecf20Sopenharmony_ci	enum can_state state = priv->state;
11728c2ecf20Sopenharmony_ci
11738c2ecf20Sopenharmony_ci	if (priv->do_get_state)
11748c2ecf20Sopenharmony_ci		priv->do_get_state(dev, &state);
11758c2ecf20Sopenharmony_ci
11768c2ecf20Sopenharmony_ci	if ((priv->bittiming.bitrate &&
11778c2ecf20Sopenharmony_ci	     nla_put(skb, IFLA_CAN_BITTIMING,
11788c2ecf20Sopenharmony_ci		     sizeof(priv->bittiming), &priv->bittiming)) ||
11798c2ecf20Sopenharmony_ci
11808c2ecf20Sopenharmony_ci	    (priv->bittiming_const &&
11818c2ecf20Sopenharmony_ci	     nla_put(skb, IFLA_CAN_BITTIMING_CONST,
11828c2ecf20Sopenharmony_ci		     sizeof(*priv->bittiming_const), priv->bittiming_const)) ||
11838c2ecf20Sopenharmony_ci
11848c2ecf20Sopenharmony_ci	    nla_put(skb, IFLA_CAN_CLOCK, sizeof(priv->clock), &priv->clock) ||
11858c2ecf20Sopenharmony_ci	    nla_put_u32(skb, IFLA_CAN_STATE, state) ||
11868c2ecf20Sopenharmony_ci	    nla_put(skb, IFLA_CAN_CTRLMODE, sizeof(cm), &cm) ||
11878c2ecf20Sopenharmony_ci	    nla_put_u32(skb, IFLA_CAN_RESTART_MS, priv->restart_ms) ||
11888c2ecf20Sopenharmony_ci
11898c2ecf20Sopenharmony_ci	    (priv->do_get_berr_counter &&
11908c2ecf20Sopenharmony_ci	     !priv->do_get_berr_counter(dev, &bec) &&
11918c2ecf20Sopenharmony_ci	     nla_put(skb, IFLA_CAN_BERR_COUNTER, sizeof(bec), &bec)) ||
11928c2ecf20Sopenharmony_ci
11938c2ecf20Sopenharmony_ci	    (priv->data_bittiming.bitrate &&
11948c2ecf20Sopenharmony_ci	     nla_put(skb, IFLA_CAN_DATA_BITTIMING,
11958c2ecf20Sopenharmony_ci		     sizeof(priv->data_bittiming), &priv->data_bittiming)) ||
11968c2ecf20Sopenharmony_ci
11978c2ecf20Sopenharmony_ci	    (priv->data_bittiming_const &&
11988c2ecf20Sopenharmony_ci	     nla_put(skb, IFLA_CAN_DATA_BITTIMING_CONST,
11998c2ecf20Sopenharmony_ci		     sizeof(*priv->data_bittiming_const),
12008c2ecf20Sopenharmony_ci		     priv->data_bittiming_const)) ||
12018c2ecf20Sopenharmony_ci
12028c2ecf20Sopenharmony_ci	    (priv->termination_const &&
12038c2ecf20Sopenharmony_ci	     (nla_put_u16(skb, IFLA_CAN_TERMINATION, priv->termination) ||
12048c2ecf20Sopenharmony_ci	      nla_put(skb, IFLA_CAN_TERMINATION_CONST,
12058c2ecf20Sopenharmony_ci		      sizeof(*priv->termination_const) *
12068c2ecf20Sopenharmony_ci		      priv->termination_const_cnt,
12078c2ecf20Sopenharmony_ci		      priv->termination_const))) ||
12088c2ecf20Sopenharmony_ci
12098c2ecf20Sopenharmony_ci	    (priv->bitrate_const &&
12108c2ecf20Sopenharmony_ci	     nla_put(skb, IFLA_CAN_BITRATE_CONST,
12118c2ecf20Sopenharmony_ci		     sizeof(*priv->bitrate_const) *
12128c2ecf20Sopenharmony_ci		     priv->bitrate_const_cnt,
12138c2ecf20Sopenharmony_ci		     priv->bitrate_const)) ||
12148c2ecf20Sopenharmony_ci
12158c2ecf20Sopenharmony_ci	    (priv->data_bitrate_const &&
12168c2ecf20Sopenharmony_ci	     nla_put(skb, IFLA_CAN_DATA_BITRATE_CONST,
12178c2ecf20Sopenharmony_ci		     sizeof(*priv->data_bitrate_const) *
12188c2ecf20Sopenharmony_ci		     priv->data_bitrate_const_cnt,
12198c2ecf20Sopenharmony_ci		     priv->data_bitrate_const)) ||
12208c2ecf20Sopenharmony_ci
12218c2ecf20Sopenharmony_ci	    (nla_put(skb, IFLA_CAN_BITRATE_MAX,
12228c2ecf20Sopenharmony_ci		     sizeof(priv->bitrate_max),
12238c2ecf20Sopenharmony_ci		     &priv->bitrate_max))
12248c2ecf20Sopenharmony_ci	    )
12258c2ecf20Sopenharmony_ci
12268c2ecf20Sopenharmony_ci		return -EMSGSIZE;
12278c2ecf20Sopenharmony_ci
12288c2ecf20Sopenharmony_ci	return 0;
12298c2ecf20Sopenharmony_ci}
12308c2ecf20Sopenharmony_ci
12318c2ecf20Sopenharmony_cistatic size_t can_get_xstats_size(const struct net_device *dev)
12328c2ecf20Sopenharmony_ci{
12338c2ecf20Sopenharmony_ci	return sizeof(struct can_device_stats);
12348c2ecf20Sopenharmony_ci}
12358c2ecf20Sopenharmony_ci
12368c2ecf20Sopenharmony_cistatic int can_fill_xstats(struct sk_buff *skb, const struct net_device *dev)
12378c2ecf20Sopenharmony_ci{
12388c2ecf20Sopenharmony_ci	struct can_priv *priv = netdev_priv(dev);
12398c2ecf20Sopenharmony_ci
12408c2ecf20Sopenharmony_ci	if (nla_put(skb, IFLA_INFO_XSTATS,
12418c2ecf20Sopenharmony_ci		    sizeof(priv->can_stats), &priv->can_stats))
12428c2ecf20Sopenharmony_ci		goto nla_put_failure;
12438c2ecf20Sopenharmony_ci	return 0;
12448c2ecf20Sopenharmony_ci
12458c2ecf20Sopenharmony_cinla_put_failure:
12468c2ecf20Sopenharmony_ci	return -EMSGSIZE;
12478c2ecf20Sopenharmony_ci}
12488c2ecf20Sopenharmony_ci
12498c2ecf20Sopenharmony_cistatic int can_newlink(struct net *src_net, struct net_device *dev,
12508c2ecf20Sopenharmony_ci		       struct nlattr *tb[], struct nlattr *data[],
12518c2ecf20Sopenharmony_ci		       struct netlink_ext_ack *extack)
12528c2ecf20Sopenharmony_ci{
12538c2ecf20Sopenharmony_ci	return -EOPNOTSUPP;
12548c2ecf20Sopenharmony_ci}
12558c2ecf20Sopenharmony_ci
12568c2ecf20Sopenharmony_cistatic void can_dellink(struct net_device *dev, struct list_head *head)
12578c2ecf20Sopenharmony_ci{
12588c2ecf20Sopenharmony_ci}
12598c2ecf20Sopenharmony_ci
12608c2ecf20Sopenharmony_cistatic struct rtnl_link_ops can_link_ops __read_mostly = {
12618c2ecf20Sopenharmony_ci	.kind		= "can",
12628c2ecf20Sopenharmony_ci	.netns_refund	= true,
12638c2ecf20Sopenharmony_ci	.maxtype	= IFLA_CAN_MAX,
12648c2ecf20Sopenharmony_ci	.policy		= can_policy,
12658c2ecf20Sopenharmony_ci	.setup		= can_setup,
12668c2ecf20Sopenharmony_ci	.validate	= can_validate,
12678c2ecf20Sopenharmony_ci	.newlink	= can_newlink,
12688c2ecf20Sopenharmony_ci	.changelink	= can_changelink,
12698c2ecf20Sopenharmony_ci	.dellink	= can_dellink,
12708c2ecf20Sopenharmony_ci	.get_size	= can_get_size,
12718c2ecf20Sopenharmony_ci	.fill_info	= can_fill_info,
12728c2ecf20Sopenharmony_ci	.get_xstats_size = can_get_xstats_size,
12738c2ecf20Sopenharmony_ci	.fill_xstats	= can_fill_xstats,
12748c2ecf20Sopenharmony_ci};
12758c2ecf20Sopenharmony_ci
12768c2ecf20Sopenharmony_ci/* Register the CAN network device */
12778c2ecf20Sopenharmony_ciint register_candev(struct net_device *dev)
12788c2ecf20Sopenharmony_ci{
12798c2ecf20Sopenharmony_ci	struct can_priv *priv = netdev_priv(dev);
12808c2ecf20Sopenharmony_ci
12818c2ecf20Sopenharmony_ci	/* Ensure termination_const, termination_const_cnt and
12828c2ecf20Sopenharmony_ci	 * do_set_termination consistency. All must be either set or
12838c2ecf20Sopenharmony_ci	 * unset.
12848c2ecf20Sopenharmony_ci	 */
12858c2ecf20Sopenharmony_ci	if ((!priv->termination_const != !priv->termination_const_cnt) ||
12868c2ecf20Sopenharmony_ci	    (!priv->termination_const != !priv->do_set_termination))
12878c2ecf20Sopenharmony_ci		return -EINVAL;
12888c2ecf20Sopenharmony_ci
12898c2ecf20Sopenharmony_ci	if (!priv->bitrate_const != !priv->bitrate_const_cnt)
12908c2ecf20Sopenharmony_ci		return -EINVAL;
12918c2ecf20Sopenharmony_ci
12928c2ecf20Sopenharmony_ci	if (!priv->data_bitrate_const != !priv->data_bitrate_const_cnt)
12938c2ecf20Sopenharmony_ci		return -EINVAL;
12948c2ecf20Sopenharmony_ci
12958c2ecf20Sopenharmony_ci	dev->rtnl_link_ops = &can_link_ops;
12968c2ecf20Sopenharmony_ci	netif_carrier_off(dev);
12978c2ecf20Sopenharmony_ci
12988c2ecf20Sopenharmony_ci	return register_netdev(dev);
12998c2ecf20Sopenharmony_ci}
13008c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(register_candev);
13018c2ecf20Sopenharmony_ci
13028c2ecf20Sopenharmony_ci/* Unregister the CAN network device */
13038c2ecf20Sopenharmony_civoid unregister_candev(struct net_device *dev)
13048c2ecf20Sopenharmony_ci{
13058c2ecf20Sopenharmony_ci	unregister_netdev(dev);
13068c2ecf20Sopenharmony_ci}
13078c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(unregister_candev);
13088c2ecf20Sopenharmony_ci
13098c2ecf20Sopenharmony_ci/* Test if a network device is a candev based device
13108c2ecf20Sopenharmony_ci * and return the can_priv* if so.
13118c2ecf20Sopenharmony_ci */
13128c2ecf20Sopenharmony_cistruct can_priv *safe_candev_priv(struct net_device *dev)
13138c2ecf20Sopenharmony_ci{
13148c2ecf20Sopenharmony_ci	if (dev->type != ARPHRD_CAN || dev->rtnl_link_ops != &can_link_ops)
13158c2ecf20Sopenharmony_ci		return NULL;
13168c2ecf20Sopenharmony_ci
13178c2ecf20Sopenharmony_ci	return netdev_priv(dev);
13188c2ecf20Sopenharmony_ci}
13198c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(safe_candev_priv);
13208c2ecf20Sopenharmony_ci
13218c2ecf20Sopenharmony_cistatic __init int can_dev_init(void)
13228c2ecf20Sopenharmony_ci{
13238c2ecf20Sopenharmony_ci	int err;
13248c2ecf20Sopenharmony_ci
13258c2ecf20Sopenharmony_ci	can_led_notifier_init();
13268c2ecf20Sopenharmony_ci
13278c2ecf20Sopenharmony_ci	err = rtnl_link_register(&can_link_ops);
13288c2ecf20Sopenharmony_ci	if (!err)
13298c2ecf20Sopenharmony_ci		pr_info(MOD_DESC "\n");
13308c2ecf20Sopenharmony_ci
13318c2ecf20Sopenharmony_ci	return err;
13328c2ecf20Sopenharmony_ci}
13338c2ecf20Sopenharmony_cimodule_init(can_dev_init);
13348c2ecf20Sopenharmony_ci
13358c2ecf20Sopenharmony_cistatic __exit void can_dev_exit(void)
13368c2ecf20Sopenharmony_ci{
13378c2ecf20Sopenharmony_ci	rtnl_link_unregister(&can_link_ops);
13388c2ecf20Sopenharmony_ci
13398c2ecf20Sopenharmony_ci	can_led_notifier_exit();
13408c2ecf20Sopenharmony_ci}
13418c2ecf20Sopenharmony_cimodule_exit(can_dev_exit);
13428c2ecf20Sopenharmony_ci
13438c2ecf20Sopenharmony_ciMODULE_ALIAS_RTNL_LINK("can");
1344