162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/* CAN driver for Geschwister Schneider USB/CAN devices
362306a36Sopenharmony_ci * and bytewerk.org candleLight USB CAN interfaces.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2013-2016 Geschwister Schneider Technologie-,
662306a36Sopenharmony_ci * Entwicklungs- und Vertriebs UG (Haftungsbeschränkt).
762306a36Sopenharmony_ci * Copyright (C) 2016 Hubert Denkmair
862306a36Sopenharmony_ci * Copyright (c) 2023 Pengutronix, Marc Kleine-Budde <kernel@pengutronix.de>
962306a36Sopenharmony_ci *
1062306a36Sopenharmony_ci * Many thanks to all socketcan devs!
1162306a36Sopenharmony_ci */
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <linux/bitfield.h>
1462306a36Sopenharmony_ci#include <linux/clocksource.h>
1562306a36Sopenharmony_ci#include <linux/ethtool.h>
1662306a36Sopenharmony_ci#include <linux/init.h>
1762306a36Sopenharmony_ci#include <linux/module.h>
1862306a36Sopenharmony_ci#include <linux/netdevice.h>
1962306a36Sopenharmony_ci#include <linux/signal.h>
2062306a36Sopenharmony_ci#include <linux/timecounter.h>
2162306a36Sopenharmony_ci#include <linux/units.h>
2262306a36Sopenharmony_ci#include <linux/usb.h>
2362306a36Sopenharmony_ci#include <linux/workqueue.h>
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#include <linux/can.h>
2662306a36Sopenharmony_ci#include <linux/can/dev.h>
2762306a36Sopenharmony_ci#include <linux/can/error.h>
2862306a36Sopenharmony_ci#include <linux/can/rx-offload.h>
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci/* Device specific constants */
3162306a36Sopenharmony_ci#define USB_GS_USB_1_VENDOR_ID 0x1d50
3262306a36Sopenharmony_ci#define USB_GS_USB_1_PRODUCT_ID 0x606f
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci#define USB_CANDLELIGHT_VENDOR_ID 0x1209
3562306a36Sopenharmony_ci#define USB_CANDLELIGHT_PRODUCT_ID 0x2323
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci#define USB_CES_CANEXT_FD_VENDOR_ID 0x1cd2
3862306a36Sopenharmony_ci#define USB_CES_CANEXT_FD_PRODUCT_ID 0x606f
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci#define USB_ABE_CANDEBUGGER_FD_VENDOR_ID 0x16d0
4162306a36Sopenharmony_ci#define USB_ABE_CANDEBUGGER_FD_PRODUCT_ID 0x10b8
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci#define GS_USB_ENDPOINT_IN 1
4462306a36Sopenharmony_ci#define GS_USB_ENDPOINT_OUT 2
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci/* Timestamp 32 bit timer runs at 1 MHz (1 µs tick). Worker accounts
4762306a36Sopenharmony_ci * for timer overflow (will be after ~71 minutes)
4862306a36Sopenharmony_ci */
4962306a36Sopenharmony_ci#define GS_USB_TIMESTAMP_TIMER_HZ (1 * HZ_PER_MHZ)
5062306a36Sopenharmony_ci#define GS_USB_TIMESTAMP_WORK_DELAY_SEC 1800
5162306a36Sopenharmony_cistatic_assert(GS_USB_TIMESTAMP_WORK_DELAY_SEC <
5262306a36Sopenharmony_ci	      CYCLECOUNTER_MASK(32) / GS_USB_TIMESTAMP_TIMER_HZ / 2);
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci/* Device specific constants */
5562306a36Sopenharmony_cienum gs_usb_breq {
5662306a36Sopenharmony_ci	GS_USB_BREQ_HOST_FORMAT = 0,
5762306a36Sopenharmony_ci	GS_USB_BREQ_BITTIMING,
5862306a36Sopenharmony_ci	GS_USB_BREQ_MODE,
5962306a36Sopenharmony_ci	GS_USB_BREQ_BERR,
6062306a36Sopenharmony_ci	GS_USB_BREQ_BT_CONST,
6162306a36Sopenharmony_ci	GS_USB_BREQ_DEVICE_CONFIG,
6262306a36Sopenharmony_ci	GS_USB_BREQ_TIMESTAMP,
6362306a36Sopenharmony_ci	GS_USB_BREQ_IDENTIFY,
6462306a36Sopenharmony_ci	GS_USB_BREQ_GET_USER_ID,
6562306a36Sopenharmony_ci	GS_USB_BREQ_QUIRK_CANTACT_PRO_DATA_BITTIMING = GS_USB_BREQ_GET_USER_ID,
6662306a36Sopenharmony_ci	GS_USB_BREQ_SET_USER_ID,
6762306a36Sopenharmony_ci	GS_USB_BREQ_DATA_BITTIMING,
6862306a36Sopenharmony_ci	GS_USB_BREQ_BT_CONST_EXT,
6962306a36Sopenharmony_ci	GS_USB_BREQ_SET_TERMINATION,
7062306a36Sopenharmony_ci	GS_USB_BREQ_GET_TERMINATION,
7162306a36Sopenharmony_ci	GS_USB_BREQ_GET_STATE,
7262306a36Sopenharmony_ci};
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_cienum gs_can_mode {
7562306a36Sopenharmony_ci	/* reset a channel. turns it off */
7662306a36Sopenharmony_ci	GS_CAN_MODE_RESET = 0,
7762306a36Sopenharmony_ci	/* starts a channel */
7862306a36Sopenharmony_ci	GS_CAN_MODE_START
7962306a36Sopenharmony_ci};
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_cienum gs_can_state {
8262306a36Sopenharmony_ci	GS_CAN_STATE_ERROR_ACTIVE = 0,
8362306a36Sopenharmony_ci	GS_CAN_STATE_ERROR_WARNING,
8462306a36Sopenharmony_ci	GS_CAN_STATE_ERROR_PASSIVE,
8562306a36Sopenharmony_ci	GS_CAN_STATE_BUS_OFF,
8662306a36Sopenharmony_ci	GS_CAN_STATE_STOPPED,
8762306a36Sopenharmony_ci	GS_CAN_STATE_SLEEPING
8862306a36Sopenharmony_ci};
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_cienum gs_can_identify_mode {
9162306a36Sopenharmony_ci	GS_CAN_IDENTIFY_OFF = 0,
9262306a36Sopenharmony_ci	GS_CAN_IDENTIFY_ON
9362306a36Sopenharmony_ci};
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_cienum gs_can_termination_state {
9662306a36Sopenharmony_ci	GS_CAN_TERMINATION_STATE_OFF = 0,
9762306a36Sopenharmony_ci	GS_CAN_TERMINATION_STATE_ON
9862306a36Sopenharmony_ci};
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci#define GS_USB_TERMINATION_DISABLED CAN_TERMINATION_DISABLED
10162306a36Sopenharmony_ci#define GS_USB_TERMINATION_ENABLED 120
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci/* data types passed between host and device */
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci/* The firmware on the original USB2CAN by Geschwister Schneider
10662306a36Sopenharmony_ci * Technologie Entwicklungs- und Vertriebs UG exchanges all data
10762306a36Sopenharmony_ci * between the host and the device in host byte order. This is done
10862306a36Sopenharmony_ci * with the struct gs_host_config::byte_order member, which is sent
10962306a36Sopenharmony_ci * first to indicate the desired byte order.
11062306a36Sopenharmony_ci *
11162306a36Sopenharmony_ci * The widely used open source firmware candleLight doesn't support
11262306a36Sopenharmony_ci * this feature and exchanges the data in little endian byte order.
11362306a36Sopenharmony_ci */
11462306a36Sopenharmony_cistruct gs_host_config {
11562306a36Sopenharmony_ci	__le32 byte_order;
11662306a36Sopenharmony_ci} __packed;
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_cistruct gs_device_config {
11962306a36Sopenharmony_ci	u8 reserved1;
12062306a36Sopenharmony_ci	u8 reserved2;
12162306a36Sopenharmony_ci	u8 reserved3;
12262306a36Sopenharmony_ci	u8 icount;
12362306a36Sopenharmony_ci	__le32 sw_version;
12462306a36Sopenharmony_ci	__le32 hw_version;
12562306a36Sopenharmony_ci} __packed;
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci#define GS_CAN_MODE_NORMAL 0
12862306a36Sopenharmony_ci#define GS_CAN_MODE_LISTEN_ONLY BIT(0)
12962306a36Sopenharmony_ci#define GS_CAN_MODE_LOOP_BACK BIT(1)
13062306a36Sopenharmony_ci#define GS_CAN_MODE_TRIPLE_SAMPLE BIT(2)
13162306a36Sopenharmony_ci#define GS_CAN_MODE_ONE_SHOT BIT(3)
13262306a36Sopenharmony_ci#define GS_CAN_MODE_HW_TIMESTAMP BIT(4)
13362306a36Sopenharmony_ci/* GS_CAN_FEATURE_IDENTIFY BIT(5) */
13462306a36Sopenharmony_ci/* GS_CAN_FEATURE_USER_ID BIT(6) */
13562306a36Sopenharmony_ci#define GS_CAN_MODE_PAD_PKTS_TO_MAX_PKT_SIZE BIT(7)
13662306a36Sopenharmony_ci#define GS_CAN_MODE_FD BIT(8)
13762306a36Sopenharmony_ci/* GS_CAN_FEATURE_REQ_USB_QUIRK_LPC546XX BIT(9) */
13862306a36Sopenharmony_ci/* GS_CAN_FEATURE_BT_CONST_EXT BIT(10) */
13962306a36Sopenharmony_ci/* GS_CAN_FEATURE_TERMINATION BIT(11) */
14062306a36Sopenharmony_ci#define GS_CAN_MODE_BERR_REPORTING BIT(12)
14162306a36Sopenharmony_ci/* GS_CAN_FEATURE_GET_STATE BIT(13) */
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_cistruct gs_device_mode {
14462306a36Sopenharmony_ci	__le32 mode;
14562306a36Sopenharmony_ci	__le32 flags;
14662306a36Sopenharmony_ci} __packed;
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_cistruct gs_device_state {
14962306a36Sopenharmony_ci	__le32 state;
15062306a36Sopenharmony_ci	__le32 rxerr;
15162306a36Sopenharmony_ci	__le32 txerr;
15262306a36Sopenharmony_ci} __packed;
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_cistruct gs_device_bittiming {
15562306a36Sopenharmony_ci	__le32 prop_seg;
15662306a36Sopenharmony_ci	__le32 phase_seg1;
15762306a36Sopenharmony_ci	__le32 phase_seg2;
15862306a36Sopenharmony_ci	__le32 sjw;
15962306a36Sopenharmony_ci	__le32 brp;
16062306a36Sopenharmony_ci} __packed;
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_cistruct gs_identify_mode {
16362306a36Sopenharmony_ci	__le32 mode;
16462306a36Sopenharmony_ci} __packed;
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_cistruct gs_device_termination_state {
16762306a36Sopenharmony_ci	__le32 state;
16862306a36Sopenharmony_ci} __packed;
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci#define GS_CAN_FEATURE_LISTEN_ONLY BIT(0)
17162306a36Sopenharmony_ci#define GS_CAN_FEATURE_LOOP_BACK BIT(1)
17262306a36Sopenharmony_ci#define GS_CAN_FEATURE_TRIPLE_SAMPLE BIT(2)
17362306a36Sopenharmony_ci#define GS_CAN_FEATURE_ONE_SHOT BIT(3)
17462306a36Sopenharmony_ci#define GS_CAN_FEATURE_HW_TIMESTAMP BIT(4)
17562306a36Sopenharmony_ci#define GS_CAN_FEATURE_IDENTIFY BIT(5)
17662306a36Sopenharmony_ci#define GS_CAN_FEATURE_USER_ID BIT(6)
17762306a36Sopenharmony_ci#define GS_CAN_FEATURE_PAD_PKTS_TO_MAX_PKT_SIZE BIT(7)
17862306a36Sopenharmony_ci#define GS_CAN_FEATURE_FD BIT(8)
17962306a36Sopenharmony_ci#define GS_CAN_FEATURE_REQ_USB_QUIRK_LPC546XX BIT(9)
18062306a36Sopenharmony_ci#define GS_CAN_FEATURE_BT_CONST_EXT BIT(10)
18162306a36Sopenharmony_ci#define GS_CAN_FEATURE_TERMINATION BIT(11)
18262306a36Sopenharmony_ci#define GS_CAN_FEATURE_BERR_REPORTING BIT(12)
18362306a36Sopenharmony_ci#define GS_CAN_FEATURE_GET_STATE BIT(13)
18462306a36Sopenharmony_ci#define GS_CAN_FEATURE_MASK GENMASK(13, 0)
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci/* internal quirks - keep in GS_CAN_FEATURE space for now */
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci/* CANtact Pro original firmware:
18962306a36Sopenharmony_ci * BREQ DATA_BITTIMING overlaps with GET_USER_ID
19062306a36Sopenharmony_ci */
19162306a36Sopenharmony_ci#define GS_CAN_FEATURE_QUIRK_BREQ_CANTACT_PRO BIT(31)
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_cistruct gs_device_bt_const {
19462306a36Sopenharmony_ci	__le32 feature;
19562306a36Sopenharmony_ci	__le32 fclk_can;
19662306a36Sopenharmony_ci	__le32 tseg1_min;
19762306a36Sopenharmony_ci	__le32 tseg1_max;
19862306a36Sopenharmony_ci	__le32 tseg2_min;
19962306a36Sopenharmony_ci	__le32 tseg2_max;
20062306a36Sopenharmony_ci	__le32 sjw_max;
20162306a36Sopenharmony_ci	__le32 brp_min;
20262306a36Sopenharmony_ci	__le32 brp_max;
20362306a36Sopenharmony_ci	__le32 brp_inc;
20462306a36Sopenharmony_ci} __packed;
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_cistruct gs_device_bt_const_extended {
20762306a36Sopenharmony_ci	__le32 feature;
20862306a36Sopenharmony_ci	__le32 fclk_can;
20962306a36Sopenharmony_ci	__le32 tseg1_min;
21062306a36Sopenharmony_ci	__le32 tseg1_max;
21162306a36Sopenharmony_ci	__le32 tseg2_min;
21262306a36Sopenharmony_ci	__le32 tseg2_max;
21362306a36Sopenharmony_ci	__le32 sjw_max;
21462306a36Sopenharmony_ci	__le32 brp_min;
21562306a36Sopenharmony_ci	__le32 brp_max;
21662306a36Sopenharmony_ci	__le32 brp_inc;
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	__le32 dtseg1_min;
21962306a36Sopenharmony_ci	__le32 dtseg1_max;
22062306a36Sopenharmony_ci	__le32 dtseg2_min;
22162306a36Sopenharmony_ci	__le32 dtseg2_max;
22262306a36Sopenharmony_ci	__le32 dsjw_max;
22362306a36Sopenharmony_ci	__le32 dbrp_min;
22462306a36Sopenharmony_ci	__le32 dbrp_max;
22562306a36Sopenharmony_ci	__le32 dbrp_inc;
22662306a36Sopenharmony_ci} __packed;
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci#define GS_CAN_FLAG_OVERFLOW BIT(0)
22962306a36Sopenharmony_ci#define GS_CAN_FLAG_FD BIT(1)
23062306a36Sopenharmony_ci#define GS_CAN_FLAG_BRS BIT(2)
23162306a36Sopenharmony_ci#define GS_CAN_FLAG_ESI BIT(3)
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_cistruct classic_can {
23462306a36Sopenharmony_ci	u8 data[8];
23562306a36Sopenharmony_ci} __packed;
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_cistruct classic_can_ts {
23862306a36Sopenharmony_ci	u8 data[8];
23962306a36Sopenharmony_ci	__le32 timestamp_us;
24062306a36Sopenharmony_ci} __packed;
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_cistruct classic_can_quirk {
24362306a36Sopenharmony_ci	u8 data[8];
24462306a36Sopenharmony_ci	u8 quirk;
24562306a36Sopenharmony_ci} __packed;
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_cistruct canfd {
24862306a36Sopenharmony_ci	u8 data[64];
24962306a36Sopenharmony_ci} __packed;
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_cistruct canfd_ts {
25262306a36Sopenharmony_ci	u8 data[64];
25362306a36Sopenharmony_ci	__le32 timestamp_us;
25462306a36Sopenharmony_ci} __packed;
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_cistruct canfd_quirk {
25762306a36Sopenharmony_ci	u8 data[64];
25862306a36Sopenharmony_ci	u8 quirk;
25962306a36Sopenharmony_ci} __packed;
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_cistruct gs_host_frame {
26262306a36Sopenharmony_ci	u32 echo_id;
26362306a36Sopenharmony_ci	__le32 can_id;
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci	u8 can_dlc;
26662306a36Sopenharmony_ci	u8 channel;
26762306a36Sopenharmony_ci	u8 flags;
26862306a36Sopenharmony_ci	u8 reserved;
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci	union {
27162306a36Sopenharmony_ci		DECLARE_FLEX_ARRAY(struct classic_can, classic_can);
27262306a36Sopenharmony_ci		DECLARE_FLEX_ARRAY(struct classic_can_ts, classic_can_ts);
27362306a36Sopenharmony_ci		DECLARE_FLEX_ARRAY(struct classic_can_quirk, classic_can_quirk);
27462306a36Sopenharmony_ci		DECLARE_FLEX_ARRAY(struct canfd, canfd);
27562306a36Sopenharmony_ci		DECLARE_FLEX_ARRAY(struct canfd_ts, canfd_ts);
27662306a36Sopenharmony_ci		DECLARE_FLEX_ARRAY(struct canfd_quirk, canfd_quirk);
27762306a36Sopenharmony_ci	};
27862306a36Sopenharmony_ci} __packed;
27962306a36Sopenharmony_ci/* The GS USB devices make use of the same flags and masks as in
28062306a36Sopenharmony_ci * linux/can.h and linux/can/error.h, and no additional mapping is necessary.
28162306a36Sopenharmony_ci */
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci/* Only send a max of GS_MAX_TX_URBS frames per channel at a time. */
28462306a36Sopenharmony_ci#define GS_MAX_TX_URBS 10
28562306a36Sopenharmony_ci/* Only launch a max of GS_MAX_RX_URBS usb requests at a time. */
28662306a36Sopenharmony_ci#define GS_MAX_RX_URBS 30
28762306a36Sopenharmony_ci#define GS_NAPI_WEIGHT 32
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_ci/* Maximum number of interfaces the driver supports per device.
29062306a36Sopenharmony_ci * Current hardware only supports 3 interfaces. The future may vary.
29162306a36Sopenharmony_ci */
29262306a36Sopenharmony_ci#define GS_MAX_INTF 3
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_cistruct gs_tx_context {
29562306a36Sopenharmony_ci	struct gs_can *dev;
29662306a36Sopenharmony_ci	unsigned int echo_id;
29762306a36Sopenharmony_ci};
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_cistruct gs_can {
30062306a36Sopenharmony_ci	struct can_priv can; /* must be the first member */
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci	struct can_rx_offload offload;
30362306a36Sopenharmony_ci	struct gs_usb *parent;
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci	struct net_device *netdev;
30662306a36Sopenharmony_ci	struct usb_device *udev;
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci	struct can_bittiming_const bt_const, data_bt_const;
30962306a36Sopenharmony_ci	unsigned int channel;	/* channel number */
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci	u32 feature;
31262306a36Sopenharmony_ci	unsigned int hf_size_tx;
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci	/* This lock prevents a race condition between xmit and receive. */
31562306a36Sopenharmony_ci	spinlock_t tx_ctx_lock;
31662306a36Sopenharmony_ci	struct gs_tx_context tx_context[GS_MAX_TX_URBS];
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	struct usb_anchor tx_submitted;
31962306a36Sopenharmony_ci	atomic_t active_tx_urbs;
32062306a36Sopenharmony_ci};
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci/* usb interface struct */
32362306a36Sopenharmony_cistruct gs_usb {
32462306a36Sopenharmony_ci	struct gs_can *canch[GS_MAX_INTF];
32562306a36Sopenharmony_ci	struct usb_anchor rx_submitted;
32662306a36Sopenharmony_ci	struct usb_device *udev;
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ci	/* time counter for hardware timestamps */
32962306a36Sopenharmony_ci	struct cyclecounter cc;
33062306a36Sopenharmony_ci	struct timecounter tc;
33162306a36Sopenharmony_ci	spinlock_t tc_lock; /* spinlock to guard access tc->cycle_last */
33262306a36Sopenharmony_ci	struct delayed_work timestamp;
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci	unsigned int hf_size_rx;
33562306a36Sopenharmony_ci	u8 active_channels;
33662306a36Sopenharmony_ci};
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ci/* 'allocate' a tx context.
33962306a36Sopenharmony_ci * returns a valid tx context or NULL if there is no space.
34062306a36Sopenharmony_ci */
34162306a36Sopenharmony_cistatic struct gs_tx_context *gs_alloc_tx_context(struct gs_can *dev)
34262306a36Sopenharmony_ci{
34362306a36Sopenharmony_ci	int i = 0;
34462306a36Sopenharmony_ci	unsigned long flags;
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_ci	spin_lock_irqsave(&dev->tx_ctx_lock, flags);
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci	for (; i < GS_MAX_TX_URBS; i++) {
34962306a36Sopenharmony_ci		if (dev->tx_context[i].echo_id == GS_MAX_TX_URBS) {
35062306a36Sopenharmony_ci			dev->tx_context[i].echo_id = i;
35162306a36Sopenharmony_ci			spin_unlock_irqrestore(&dev->tx_ctx_lock, flags);
35262306a36Sopenharmony_ci			return &dev->tx_context[i];
35362306a36Sopenharmony_ci		}
35462306a36Sopenharmony_ci	}
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_ci	spin_unlock_irqrestore(&dev->tx_ctx_lock, flags);
35762306a36Sopenharmony_ci	return NULL;
35862306a36Sopenharmony_ci}
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci/* releases a tx context
36162306a36Sopenharmony_ci */
36262306a36Sopenharmony_cistatic void gs_free_tx_context(struct gs_tx_context *txc)
36362306a36Sopenharmony_ci{
36462306a36Sopenharmony_ci	txc->echo_id = GS_MAX_TX_URBS;
36562306a36Sopenharmony_ci}
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_ci/* Get a tx context by id.
36862306a36Sopenharmony_ci */
36962306a36Sopenharmony_cistatic struct gs_tx_context *gs_get_tx_context(struct gs_can *dev,
37062306a36Sopenharmony_ci					       unsigned int id)
37162306a36Sopenharmony_ci{
37262306a36Sopenharmony_ci	unsigned long flags;
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci	if (id < GS_MAX_TX_URBS) {
37562306a36Sopenharmony_ci		spin_lock_irqsave(&dev->tx_ctx_lock, flags);
37662306a36Sopenharmony_ci		if (dev->tx_context[id].echo_id == id) {
37762306a36Sopenharmony_ci			spin_unlock_irqrestore(&dev->tx_ctx_lock, flags);
37862306a36Sopenharmony_ci			return &dev->tx_context[id];
37962306a36Sopenharmony_ci		}
38062306a36Sopenharmony_ci		spin_unlock_irqrestore(&dev->tx_ctx_lock, flags);
38162306a36Sopenharmony_ci	}
38262306a36Sopenharmony_ci	return NULL;
38362306a36Sopenharmony_ci}
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_cistatic int gs_cmd_reset(struct gs_can *dev)
38662306a36Sopenharmony_ci{
38762306a36Sopenharmony_ci	struct gs_device_mode dm = {
38862306a36Sopenharmony_ci		.mode = GS_CAN_MODE_RESET,
38962306a36Sopenharmony_ci	};
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci	return usb_control_msg_send(dev->udev, 0, GS_USB_BREQ_MODE,
39262306a36Sopenharmony_ci				    USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
39362306a36Sopenharmony_ci				    dev->channel, 0, &dm, sizeof(dm), 1000,
39462306a36Sopenharmony_ci				    GFP_KERNEL);
39562306a36Sopenharmony_ci}
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_cistatic inline int gs_usb_get_timestamp(const struct gs_usb *parent,
39862306a36Sopenharmony_ci				       u32 *timestamp_p)
39962306a36Sopenharmony_ci{
40062306a36Sopenharmony_ci	__le32 timestamp;
40162306a36Sopenharmony_ci	int rc;
40262306a36Sopenharmony_ci
40362306a36Sopenharmony_ci	rc = usb_control_msg_recv(parent->udev, 0, GS_USB_BREQ_TIMESTAMP,
40462306a36Sopenharmony_ci				  USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
40562306a36Sopenharmony_ci				  0, 0,
40662306a36Sopenharmony_ci				  &timestamp, sizeof(timestamp),
40762306a36Sopenharmony_ci				  USB_CTRL_GET_TIMEOUT,
40862306a36Sopenharmony_ci				  GFP_KERNEL);
40962306a36Sopenharmony_ci	if (rc)
41062306a36Sopenharmony_ci		return rc;
41162306a36Sopenharmony_ci
41262306a36Sopenharmony_ci	*timestamp_p = le32_to_cpu(timestamp);
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_ci	return 0;
41562306a36Sopenharmony_ci}
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_cistatic u64 gs_usb_timestamp_read(const struct cyclecounter *cc) __must_hold(&dev->tc_lock)
41862306a36Sopenharmony_ci{
41962306a36Sopenharmony_ci	struct gs_usb *parent = container_of(cc, struct gs_usb, cc);
42062306a36Sopenharmony_ci	u32 timestamp = 0;
42162306a36Sopenharmony_ci	int err;
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci	lockdep_assert_held(&parent->tc_lock);
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci	/* drop lock for synchronous USB transfer */
42662306a36Sopenharmony_ci	spin_unlock_bh(&parent->tc_lock);
42762306a36Sopenharmony_ci	err = gs_usb_get_timestamp(parent, &timestamp);
42862306a36Sopenharmony_ci	spin_lock_bh(&parent->tc_lock);
42962306a36Sopenharmony_ci	if (err)
43062306a36Sopenharmony_ci		dev_err(&parent->udev->dev,
43162306a36Sopenharmony_ci			"Error %d while reading timestamp. HW timestamps may be inaccurate.",
43262306a36Sopenharmony_ci			err);
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_ci	return timestamp;
43562306a36Sopenharmony_ci}
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_cistatic void gs_usb_timestamp_work(struct work_struct *work)
43862306a36Sopenharmony_ci{
43962306a36Sopenharmony_ci	struct delayed_work *delayed_work = to_delayed_work(work);
44062306a36Sopenharmony_ci	struct gs_usb *parent;
44162306a36Sopenharmony_ci
44262306a36Sopenharmony_ci	parent = container_of(delayed_work, struct gs_usb, timestamp);
44362306a36Sopenharmony_ci	spin_lock_bh(&parent->tc_lock);
44462306a36Sopenharmony_ci	timecounter_read(&parent->tc);
44562306a36Sopenharmony_ci	spin_unlock_bh(&parent->tc_lock);
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ci	schedule_delayed_work(&parent->timestamp,
44862306a36Sopenharmony_ci			      GS_USB_TIMESTAMP_WORK_DELAY_SEC * HZ);
44962306a36Sopenharmony_ci}
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_cistatic void gs_usb_skb_set_timestamp(struct gs_can *dev,
45262306a36Sopenharmony_ci				     struct sk_buff *skb, u32 timestamp)
45362306a36Sopenharmony_ci{
45462306a36Sopenharmony_ci	struct skb_shared_hwtstamps *hwtstamps = skb_hwtstamps(skb);
45562306a36Sopenharmony_ci	struct gs_usb *parent = dev->parent;
45662306a36Sopenharmony_ci	u64 ns;
45762306a36Sopenharmony_ci
45862306a36Sopenharmony_ci	spin_lock_bh(&parent->tc_lock);
45962306a36Sopenharmony_ci	ns = timecounter_cyc2time(&parent->tc, timestamp);
46062306a36Sopenharmony_ci	spin_unlock_bh(&parent->tc_lock);
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_ci	hwtstamps->hwtstamp = ns_to_ktime(ns);
46362306a36Sopenharmony_ci}
46462306a36Sopenharmony_ci
46562306a36Sopenharmony_cistatic void gs_usb_timestamp_init(struct gs_usb *parent)
46662306a36Sopenharmony_ci{
46762306a36Sopenharmony_ci	struct cyclecounter *cc = &parent->cc;
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_ci	cc->read = gs_usb_timestamp_read;
47062306a36Sopenharmony_ci	cc->mask = CYCLECOUNTER_MASK(32);
47162306a36Sopenharmony_ci	cc->shift = 32 - bits_per(NSEC_PER_SEC / GS_USB_TIMESTAMP_TIMER_HZ);
47262306a36Sopenharmony_ci	cc->mult = clocksource_hz2mult(GS_USB_TIMESTAMP_TIMER_HZ, cc->shift);
47362306a36Sopenharmony_ci
47462306a36Sopenharmony_ci	spin_lock_init(&parent->tc_lock);
47562306a36Sopenharmony_ci	spin_lock_bh(&parent->tc_lock);
47662306a36Sopenharmony_ci	timecounter_init(&parent->tc, &parent->cc, ktime_get_real_ns());
47762306a36Sopenharmony_ci	spin_unlock_bh(&parent->tc_lock);
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_ci	INIT_DELAYED_WORK(&parent->timestamp, gs_usb_timestamp_work);
48062306a36Sopenharmony_ci	schedule_delayed_work(&parent->timestamp,
48162306a36Sopenharmony_ci			      GS_USB_TIMESTAMP_WORK_DELAY_SEC * HZ);
48262306a36Sopenharmony_ci}
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_cistatic void gs_usb_timestamp_stop(struct gs_usb *parent)
48562306a36Sopenharmony_ci{
48662306a36Sopenharmony_ci	cancel_delayed_work_sync(&parent->timestamp);
48762306a36Sopenharmony_ci}
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_cistatic void gs_update_state(struct gs_can *dev, struct can_frame *cf)
49062306a36Sopenharmony_ci{
49162306a36Sopenharmony_ci	struct can_device_stats *can_stats = &dev->can.can_stats;
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ci	if (cf->can_id & CAN_ERR_RESTARTED) {
49462306a36Sopenharmony_ci		dev->can.state = CAN_STATE_ERROR_ACTIVE;
49562306a36Sopenharmony_ci		can_stats->restarts++;
49662306a36Sopenharmony_ci	} else if (cf->can_id & CAN_ERR_BUSOFF) {
49762306a36Sopenharmony_ci		dev->can.state = CAN_STATE_BUS_OFF;
49862306a36Sopenharmony_ci		can_stats->bus_off++;
49962306a36Sopenharmony_ci	} else if (cf->can_id & CAN_ERR_CRTL) {
50062306a36Sopenharmony_ci		if ((cf->data[1] & CAN_ERR_CRTL_TX_WARNING) ||
50162306a36Sopenharmony_ci		    (cf->data[1] & CAN_ERR_CRTL_RX_WARNING)) {
50262306a36Sopenharmony_ci			dev->can.state = CAN_STATE_ERROR_WARNING;
50362306a36Sopenharmony_ci			can_stats->error_warning++;
50462306a36Sopenharmony_ci		} else if ((cf->data[1] & CAN_ERR_CRTL_TX_PASSIVE) ||
50562306a36Sopenharmony_ci			   (cf->data[1] & CAN_ERR_CRTL_RX_PASSIVE)) {
50662306a36Sopenharmony_ci			dev->can.state = CAN_STATE_ERROR_PASSIVE;
50762306a36Sopenharmony_ci			can_stats->error_passive++;
50862306a36Sopenharmony_ci		} else {
50962306a36Sopenharmony_ci			dev->can.state = CAN_STATE_ERROR_ACTIVE;
51062306a36Sopenharmony_ci		}
51162306a36Sopenharmony_ci	}
51262306a36Sopenharmony_ci}
51362306a36Sopenharmony_ci
51462306a36Sopenharmony_cistatic u32 gs_usb_set_timestamp(struct gs_can *dev, struct sk_buff *skb,
51562306a36Sopenharmony_ci				const struct gs_host_frame *hf)
51662306a36Sopenharmony_ci{
51762306a36Sopenharmony_ci	u32 timestamp;
51862306a36Sopenharmony_ci
51962306a36Sopenharmony_ci	if (hf->flags & GS_CAN_FLAG_FD)
52062306a36Sopenharmony_ci		timestamp = le32_to_cpu(hf->canfd_ts->timestamp_us);
52162306a36Sopenharmony_ci	else
52262306a36Sopenharmony_ci		timestamp = le32_to_cpu(hf->classic_can_ts->timestamp_us);
52362306a36Sopenharmony_ci
52462306a36Sopenharmony_ci	if (skb)
52562306a36Sopenharmony_ci		gs_usb_skb_set_timestamp(dev, skb, timestamp);
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_ci	return timestamp;
52862306a36Sopenharmony_ci}
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_cistatic void gs_usb_rx_offload(struct gs_can *dev, struct sk_buff *skb,
53162306a36Sopenharmony_ci			      const struct gs_host_frame *hf)
53262306a36Sopenharmony_ci{
53362306a36Sopenharmony_ci	struct can_rx_offload *offload = &dev->offload;
53462306a36Sopenharmony_ci	int rc;
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_ci	if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP) {
53762306a36Sopenharmony_ci		const u32 ts = gs_usb_set_timestamp(dev, skb, hf);
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_ci		rc = can_rx_offload_queue_timestamp(offload, skb, ts);
54062306a36Sopenharmony_ci	} else {
54162306a36Sopenharmony_ci		rc = can_rx_offload_queue_tail(offload, skb);
54262306a36Sopenharmony_ci	}
54362306a36Sopenharmony_ci
54462306a36Sopenharmony_ci	if (rc)
54562306a36Sopenharmony_ci		dev->netdev->stats.rx_fifo_errors++;
54662306a36Sopenharmony_ci}
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_cistatic unsigned int
54962306a36Sopenharmony_cigs_usb_get_echo_skb(struct gs_can *dev, struct sk_buff *skb,
55062306a36Sopenharmony_ci		    const struct gs_host_frame *hf)
55162306a36Sopenharmony_ci{
55262306a36Sopenharmony_ci	struct can_rx_offload *offload = &dev->offload;
55362306a36Sopenharmony_ci	const u32 echo_id = hf->echo_id;
55462306a36Sopenharmony_ci	unsigned int len;
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_ci	if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP) {
55762306a36Sopenharmony_ci		const u32 ts = gs_usb_set_timestamp(dev, skb, hf);
55862306a36Sopenharmony_ci
55962306a36Sopenharmony_ci		len = can_rx_offload_get_echo_skb_queue_timestamp(offload, echo_id,
56062306a36Sopenharmony_ci								  ts, NULL);
56162306a36Sopenharmony_ci	} else {
56262306a36Sopenharmony_ci		len = can_rx_offload_get_echo_skb_queue_tail(offload, echo_id,
56362306a36Sopenharmony_ci							     NULL);
56462306a36Sopenharmony_ci	}
56562306a36Sopenharmony_ci
56662306a36Sopenharmony_ci	return len;
56762306a36Sopenharmony_ci}
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_cistatic void gs_usb_receive_bulk_callback(struct urb *urb)
57062306a36Sopenharmony_ci{
57162306a36Sopenharmony_ci	struct gs_usb *parent = urb->context;
57262306a36Sopenharmony_ci	struct gs_can *dev;
57362306a36Sopenharmony_ci	struct net_device *netdev;
57462306a36Sopenharmony_ci	int rc;
57562306a36Sopenharmony_ci	struct net_device_stats *stats;
57662306a36Sopenharmony_ci	struct gs_host_frame *hf = urb->transfer_buffer;
57762306a36Sopenharmony_ci	struct gs_tx_context *txc;
57862306a36Sopenharmony_ci	struct can_frame *cf;
57962306a36Sopenharmony_ci	struct canfd_frame *cfd;
58062306a36Sopenharmony_ci	struct sk_buff *skb;
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_ci	BUG_ON(!parent);
58362306a36Sopenharmony_ci
58462306a36Sopenharmony_ci	switch (urb->status) {
58562306a36Sopenharmony_ci	case 0: /* success */
58662306a36Sopenharmony_ci		break;
58762306a36Sopenharmony_ci	case -ENOENT:
58862306a36Sopenharmony_ci	case -ESHUTDOWN:
58962306a36Sopenharmony_ci		return;
59062306a36Sopenharmony_ci	default:
59162306a36Sopenharmony_ci		/* do not resubmit aborted urbs. eg: when device goes down */
59262306a36Sopenharmony_ci		return;
59362306a36Sopenharmony_ci	}
59462306a36Sopenharmony_ci
59562306a36Sopenharmony_ci	/* device reports out of range channel id */
59662306a36Sopenharmony_ci	if (hf->channel >= GS_MAX_INTF)
59762306a36Sopenharmony_ci		goto device_detach;
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_ci	dev = parent->canch[hf->channel];
60062306a36Sopenharmony_ci
60162306a36Sopenharmony_ci	netdev = dev->netdev;
60262306a36Sopenharmony_ci	stats = &netdev->stats;
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_ci	if (!netif_device_present(netdev))
60562306a36Sopenharmony_ci		return;
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_ci	if (!netif_running(netdev))
60862306a36Sopenharmony_ci		goto resubmit_urb;
60962306a36Sopenharmony_ci
61062306a36Sopenharmony_ci	if (hf->echo_id == -1) { /* normal rx */
61162306a36Sopenharmony_ci		if (hf->flags & GS_CAN_FLAG_FD) {
61262306a36Sopenharmony_ci			skb = alloc_canfd_skb(netdev, &cfd);
61362306a36Sopenharmony_ci			if (!skb)
61462306a36Sopenharmony_ci				return;
61562306a36Sopenharmony_ci
61662306a36Sopenharmony_ci			cfd->can_id = le32_to_cpu(hf->can_id);
61762306a36Sopenharmony_ci			cfd->len = can_fd_dlc2len(hf->can_dlc);
61862306a36Sopenharmony_ci			if (hf->flags & GS_CAN_FLAG_BRS)
61962306a36Sopenharmony_ci				cfd->flags |= CANFD_BRS;
62062306a36Sopenharmony_ci			if (hf->flags & GS_CAN_FLAG_ESI)
62162306a36Sopenharmony_ci				cfd->flags |= CANFD_ESI;
62262306a36Sopenharmony_ci
62362306a36Sopenharmony_ci			memcpy(cfd->data, hf->canfd->data, cfd->len);
62462306a36Sopenharmony_ci		} else {
62562306a36Sopenharmony_ci			skb = alloc_can_skb(netdev, &cf);
62662306a36Sopenharmony_ci			if (!skb)
62762306a36Sopenharmony_ci				return;
62862306a36Sopenharmony_ci
62962306a36Sopenharmony_ci			cf->can_id = le32_to_cpu(hf->can_id);
63062306a36Sopenharmony_ci			can_frame_set_cc_len(cf, hf->can_dlc, dev->can.ctrlmode);
63162306a36Sopenharmony_ci
63262306a36Sopenharmony_ci			memcpy(cf->data, hf->classic_can->data, 8);
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_ci			/* ERROR frames tell us information about the controller */
63562306a36Sopenharmony_ci			if (le32_to_cpu(hf->can_id) & CAN_ERR_FLAG)
63662306a36Sopenharmony_ci				gs_update_state(dev, cf);
63762306a36Sopenharmony_ci		}
63862306a36Sopenharmony_ci
63962306a36Sopenharmony_ci		gs_usb_rx_offload(dev, skb, hf);
64062306a36Sopenharmony_ci	} else { /* echo_id == hf->echo_id */
64162306a36Sopenharmony_ci		if (hf->echo_id >= GS_MAX_TX_URBS) {
64262306a36Sopenharmony_ci			netdev_err(netdev,
64362306a36Sopenharmony_ci				   "Unexpected out of range echo id %u\n",
64462306a36Sopenharmony_ci				   hf->echo_id);
64562306a36Sopenharmony_ci			goto resubmit_urb;
64662306a36Sopenharmony_ci		}
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_ci		txc = gs_get_tx_context(dev, hf->echo_id);
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_ci		/* bad devices send bad echo_ids. */
65162306a36Sopenharmony_ci		if (!txc) {
65262306a36Sopenharmony_ci			netdev_err(netdev,
65362306a36Sopenharmony_ci				   "Unexpected unused echo id %u\n",
65462306a36Sopenharmony_ci				   hf->echo_id);
65562306a36Sopenharmony_ci			goto resubmit_urb;
65662306a36Sopenharmony_ci		}
65762306a36Sopenharmony_ci
65862306a36Sopenharmony_ci		skb = dev->can.echo_skb[hf->echo_id];
65962306a36Sopenharmony_ci		stats->tx_packets++;
66062306a36Sopenharmony_ci		stats->tx_bytes += gs_usb_get_echo_skb(dev, skb, hf);
66162306a36Sopenharmony_ci		gs_free_tx_context(txc);
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_ci		atomic_dec(&dev->active_tx_urbs);
66462306a36Sopenharmony_ci
66562306a36Sopenharmony_ci		netif_wake_queue(netdev);
66662306a36Sopenharmony_ci	}
66762306a36Sopenharmony_ci
66862306a36Sopenharmony_ci	if (hf->flags & GS_CAN_FLAG_OVERFLOW) {
66962306a36Sopenharmony_ci		stats->rx_over_errors++;
67062306a36Sopenharmony_ci		stats->rx_errors++;
67162306a36Sopenharmony_ci
67262306a36Sopenharmony_ci		skb = alloc_can_err_skb(netdev, &cf);
67362306a36Sopenharmony_ci		if (!skb)
67462306a36Sopenharmony_ci			goto resubmit_urb;
67562306a36Sopenharmony_ci
67662306a36Sopenharmony_ci		cf->can_id |= CAN_ERR_CRTL;
67762306a36Sopenharmony_ci		cf->len = CAN_ERR_DLC;
67862306a36Sopenharmony_ci		cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
67962306a36Sopenharmony_ci
68062306a36Sopenharmony_ci		gs_usb_rx_offload(dev, skb, hf);
68162306a36Sopenharmony_ci	}
68262306a36Sopenharmony_ci
68362306a36Sopenharmony_ci	can_rx_offload_irq_finish(&dev->offload);
68462306a36Sopenharmony_ci
68562306a36Sopenharmony_ciresubmit_urb:
68662306a36Sopenharmony_ci	usb_fill_bulk_urb(urb, parent->udev,
68762306a36Sopenharmony_ci			  usb_rcvbulkpipe(parent->udev, GS_USB_ENDPOINT_IN),
68862306a36Sopenharmony_ci			  hf, dev->parent->hf_size_rx,
68962306a36Sopenharmony_ci			  gs_usb_receive_bulk_callback, parent);
69062306a36Sopenharmony_ci
69162306a36Sopenharmony_ci	rc = usb_submit_urb(urb, GFP_ATOMIC);
69262306a36Sopenharmony_ci
69362306a36Sopenharmony_ci	/* USB failure take down all interfaces */
69462306a36Sopenharmony_ci	if (rc == -ENODEV) {
69562306a36Sopenharmony_cidevice_detach:
69662306a36Sopenharmony_ci		for (rc = 0; rc < GS_MAX_INTF; rc++) {
69762306a36Sopenharmony_ci			if (parent->canch[rc])
69862306a36Sopenharmony_ci				netif_device_detach(parent->canch[rc]->netdev);
69962306a36Sopenharmony_ci		}
70062306a36Sopenharmony_ci	}
70162306a36Sopenharmony_ci}
70262306a36Sopenharmony_ci
70362306a36Sopenharmony_cistatic int gs_usb_set_bittiming(struct net_device *netdev)
70462306a36Sopenharmony_ci{
70562306a36Sopenharmony_ci	struct gs_can *dev = netdev_priv(netdev);
70662306a36Sopenharmony_ci	struct can_bittiming *bt = &dev->can.bittiming;
70762306a36Sopenharmony_ci	struct gs_device_bittiming dbt = {
70862306a36Sopenharmony_ci		.prop_seg = cpu_to_le32(bt->prop_seg),
70962306a36Sopenharmony_ci		.phase_seg1 = cpu_to_le32(bt->phase_seg1),
71062306a36Sopenharmony_ci		.phase_seg2 = cpu_to_le32(bt->phase_seg2),
71162306a36Sopenharmony_ci		.sjw = cpu_to_le32(bt->sjw),
71262306a36Sopenharmony_ci		.brp = cpu_to_le32(bt->brp),
71362306a36Sopenharmony_ci	};
71462306a36Sopenharmony_ci
71562306a36Sopenharmony_ci	/* request bit timings */
71662306a36Sopenharmony_ci	return usb_control_msg_send(dev->udev, 0, GS_USB_BREQ_BITTIMING,
71762306a36Sopenharmony_ci				    USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
71862306a36Sopenharmony_ci				    dev->channel, 0, &dbt, sizeof(dbt), 1000,
71962306a36Sopenharmony_ci				    GFP_KERNEL);
72062306a36Sopenharmony_ci}
72162306a36Sopenharmony_ci
72262306a36Sopenharmony_cistatic int gs_usb_set_data_bittiming(struct net_device *netdev)
72362306a36Sopenharmony_ci{
72462306a36Sopenharmony_ci	struct gs_can *dev = netdev_priv(netdev);
72562306a36Sopenharmony_ci	struct can_bittiming *bt = &dev->can.data_bittiming;
72662306a36Sopenharmony_ci	struct gs_device_bittiming dbt = {
72762306a36Sopenharmony_ci		.prop_seg = cpu_to_le32(bt->prop_seg),
72862306a36Sopenharmony_ci		.phase_seg1 = cpu_to_le32(bt->phase_seg1),
72962306a36Sopenharmony_ci		.phase_seg2 = cpu_to_le32(bt->phase_seg2),
73062306a36Sopenharmony_ci		.sjw = cpu_to_le32(bt->sjw),
73162306a36Sopenharmony_ci		.brp = cpu_to_le32(bt->brp),
73262306a36Sopenharmony_ci	};
73362306a36Sopenharmony_ci	u8 request = GS_USB_BREQ_DATA_BITTIMING;
73462306a36Sopenharmony_ci
73562306a36Sopenharmony_ci	if (dev->feature & GS_CAN_FEATURE_QUIRK_BREQ_CANTACT_PRO)
73662306a36Sopenharmony_ci		request = GS_USB_BREQ_QUIRK_CANTACT_PRO_DATA_BITTIMING;
73762306a36Sopenharmony_ci
73862306a36Sopenharmony_ci	/* request data bit timings */
73962306a36Sopenharmony_ci	return usb_control_msg_send(dev->udev, 0, request,
74062306a36Sopenharmony_ci				    USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
74162306a36Sopenharmony_ci				    dev->channel, 0, &dbt, sizeof(dbt), 1000,
74262306a36Sopenharmony_ci				    GFP_KERNEL);
74362306a36Sopenharmony_ci}
74462306a36Sopenharmony_ci
74562306a36Sopenharmony_cistatic void gs_usb_xmit_callback(struct urb *urb)
74662306a36Sopenharmony_ci{
74762306a36Sopenharmony_ci	struct gs_tx_context *txc = urb->context;
74862306a36Sopenharmony_ci	struct gs_can *dev = txc->dev;
74962306a36Sopenharmony_ci	struct net_device *netdev = dev->netdev;
75062306a36Sopenharmony_ci
75162306a36Sopenharmony_ci	if (urb->status)
75262306a36Sopenharmony_ci		netdev_info(netdev, "usb xmit fail %u\n", txc->echo_id);
75362306a36Sopenharmony_ci}
75462306a36Sopenharmony_ci
75562306a36Sopenharmony_cistatic netdev_tx_t gs_can_start_xmit(struct sk_buff *skb,
75662306a36Sopenharmony_ci				     struct net_device *netdev)
75762306a36Sopenharmony_ci{
75862306a36Sopenharmony_ci	struct gs_can *dev = netdev_priv(netdev);
75962306a36Sopenharmony_ci	struct net_device_stats *stats = &dev->netdev->stats;
76062306a36Sopenharmony_ci	struct urb *urb;
76162306a36Sopenharmony_ci	struct gs_host_frame *hf;
76262306a36Sopenharmony_ci	struct can_frame *cf;
76362306a36Sopenharmony_ci	struct canfd_frame *cfd;
76462306a36Sopenharmony_ci	int rc;
76562306a36Sopenharmony_ci	unsigned int idx;
76662306a36Sopenharmony_ci	struct gs_tx_context *txc;
76762306a36Sopenharmony_ci
76862306a36Sopenharmony_ci	if (can_dev_dropped_skb(netdev, skb))
76962306a36Sopenharmony_ci		return NETDEV_TX_OK;
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_ci	/* find an empty context to keep track of transmission */
77262306a36Sopenharmony_ci	txc = gs_alloc_tx_context(dev);
77362306a36Sopenharmony_ci	if (!txc)
77462306a36Sopenharmony_ci		return NETDEV_TX_BUSY;
77562306a36Sopenharmony_ci
77662306a36Sopenharmony_ci	/* create a URB, and a buffer for it */
77762306a36Sopenharmony_ci	urb = usb_alloc_urb(0, GFP_ATOMIC);
77862306a36Sopenharmony_ci	if (!urb)
77962306a36Sopenharmony_ci		goto nomem_urb;
78062306a36Sopenharmony_ci
78162306a36Sopenharmony_ci	hf = kmalloc(dev->hf_size_tx, GFP_ATOMIC);
78262306a36Sopenharmony_ci	if (!hf)
78362306a36Sopenharmony_ci		goto nomem_hf;
78462306a36Sopenharmony_ci
78562306a36Sopenharmony_ci	idx = txc->echo_id;
78662306a36Sopenharmony_ci
78762306a36Sopenharmony_ci	if (idx >= GS_MAX_TX_URBS) {
78862306a36Sopenharmony_ci		netdev_err(netdev, "Invalid tx context %u\n", idx);
78962306a36Sopenharmony_ci		goto badidx;
79062306a36Sopenharmony_ci	}
79162306a36Sopenharmony_ci
79262306a36Sopenharmony_ci	hf->echo_id = idx;
79362306a36Sopenharmony_ci	hf->channel = dev->channel;
79462306a36Sopenharmony_ci	hf->flags = 0;
79562306a36Sopenharmony_ci	hf->reserved = 0;
79662306a36Sopenharmony_ci
79762306a36Sopenharmony_ci	if (can_is_canfd_skb(skb)) {
79862306a36Sopenharmony_ci		cfd = (struct canfd_frame *)skb->data;
79962306a36Sopenharmony_ci
80062306a36Sopenharmony_ci		hf->can_id = cpu_to_le32(cfd->can_id);
80162306a36Sopenharmony_ci		hf->can_dlc = can_fd_len2dlc(cfd->len);
80262306a36Sopenharmony_ci		hf->flags |= GS_CAN_FLAG_FD;
80362306a36Sopenharmony_ci		if (cfd->flags & CANFD_BRS)
80462306a36Sopenharmony_ci			hf->flags |= GS_CAN_FLAG_BRS;
80562306a36Sopenharmony_ci		if (cfd->flags & CANFD_ESI)
80662306a36Sopenharmony_ci			hf->flags |= GS_CAN_FLAG_ESI;
80762306a36Sopenharmony_ci
80862306a36Sopenharmony_ci		memcpy(hf->canfd->data, cfd->data, cfd->len);
80962306a36Sopenharmony_ci	} else {
81062306a36Sopenharmony_ci		cf = (struct can_frame *)skb->data;
81162306a36Sopenharmony_ci
81262306a36Sopenharmony_ci		hf->can_id = cpu_to_le32(cf->can_id);
81362306a36Sopenharmony_ci		hf->can_dlc = can_get_cc_dlc(cf, dev->can.ctrlmode);
81462306a36Sopenharmony_ci
81562306a36Sopenharmony_ci		memcpy(hf->classic_can->data, cf->data, cf->len);
81662306a36Sopenharmony_ci	}
81762306a36Sopenharmony_ci
81862306a36Sopenharmony_ci	usb_fill_bulk_urb(urb, dev->udev,
81962306a36Sopenharmony_ci			  usb_sndbulkpipe(dev->udev, GS_USB_ENDPOINT_OUT),
82062306a36Sopenharmony_ci			  hf, dev->hf_size_tx,
82162306a36Sopenharmony_ci			  gs_usb_xmit_callback, txc);
82262306a36Sopenharmony_ci
82362306a36Sopenharmony_ci	urb->transfer_flags |= URB_FREE_BUFFER;
82462306a36Sopenharmony_ci	usb_anchor_urb(urb, &dev->tx_submitted);
82562306a36Sopenharmony_ci
82662306a36Sopenharmony_ci	can_put_echo_skb(skb, netdev, idx, 0);
82762306a36Sopenharmony_ci
82862306a36Sopenharmony_ci	atomic_inc(&dev->active_tx_urbs);
82962306a36Sopenharmony_ci
83062306a36Sopenharmony_ci	rc = usb_submit_urb(urb, GFP_ATOMIC);
83162306a36Sopenharmony_ci	if (unlikely(rc)) {			/* usb send failed */
83262306a36Sopenharmony_ci		atomic_dec(&dev->active_tx_urbs);
83362306a36Sopenharmony_ci
83462306a36Sopenharmony_ci		can_free_echo_skb(netdev, idx, NULL);
83562306a36Sopenharmony_ci		gs_free_tx_context(txc);
83662306a36Sopenharmony_ci
83762306a36Sopenharmony_ci		usb_unanchor_urb(urb);
83862306a36Sopenharmony_ci
83962306a36Sopenharmony_ci		if (rc == -ENODEV) {
84062306a36Sopenharmony_ci			netif_device_detach(netdev);
84162306a36Sopenharmony_ci		} else {
84262306a36Sopenharmony_ci			netdev_err(netdev, "usb_submit failed (err=%d)\n", rc);
84362306a36Sopenharmony_ci			stats->tx_dropped++;
84462306a36Sopenharmony_ci		}
84562306a36Sopenharmony_ci	} else {
84662306a36Sopenharmony_ci		/* Slow down tx path */
84762306a36Sopenharmony_ci		if (atomic_read(&dev->active_tx_urbs) >= GS_MAX_TX_URBS)
84862306a36Sopenharmony_ci			netif_stop_queue(netdev);
84962306a36Sopenharmony_ci	}
85062306a36Sopenharmony_ci
85162306a36Sopenharmony_ci	/* let usb core take care of this urb */
85262306a36Sopenharmony_ci	usb_free_urb(urb);
85362306a36Sopenharmony_ci
85462306a36Sopenharmony_ci	return NETDEV_TX_OK;
85562306a36Sopenharmony_ci
85662306a36Sopenharmony_cibadidx:
85762306a36Sopenharmony_ci	kfree(hf);
85862306a36Sopenharmony_cinomem_hf:
85962306a36Sopenharmony_ci	usb_free_urb(urb);
86062306a36Sopenharmony_ci
86162306a36Sopenharmony_cinomem_urb:
86262306a36Sopenharmony_ci	gs_free_tx_context(txc);
86362306a36Sopenharmony_ci	dev_kfree_skb(skb);
86462306a36Sopenharmony_ci	stats->tx_dropped++;
86562306a36Sopenharmony_ci	return NETDEV_TX_OK;
86662306a36Sopenharmony_ci}
86762306a36Sopenharmony_ci
86862306a36Sopenharmony_cistatic int gs_can_open(struct net_device *netdev)
86962306a36Sopenharmony_ci{
87062306a36Sopenharmony_ci	struct gs_can *dev = netdev_priv(netdev);
87162306a36Sopenharmony_ci	struct gs_usb *parent = dev->parent;
87262306a36Sopenharmony_ci	struct gs_device_mode dm = {
87362306a36Sopenharmony_ci		.mode = cpu_to_le32(GS_CAN_MODE_START),
87462306a36Sopenharmony_ci	};
87562306a36Sopenharmony_ci	struct gs_host_frame *hf;
87662306a36Sopenharmony_ci	struct urb *urb = NULL;
87762306a36Sopenharmony_ci	u32 ctrlmode;
87862306a36Sopenharmony_ci	u32 flags = 0;
87962306a36Sopenharmony_ci	int rc, i;
88062306a36Sopenharmony_ci
88162306a36Sopenharmony_ci	rc = open_candev(netdev);
88262306a36Sopenharmony_ci	if (rc)
88362306a36Sopenharmony_ci		return rc;
88462306a36Sopenharmony_ci
88562306a36Sopenharmony_ci	ctrlmode = dev->can.ctrlmode;
88662306a36Sopenharmony_ci	if (ctrlmode & CAN_CTRLMODE_FD) {
88762306a36Sopenharmony_ci		if (dev->feature & GS_CAN_FEATURE_REQ_USB_QUIRK_LPC546XX)
88862306a36Sopenharmony_ci			dev->hf_size_tx = struct_size(hf, canfd_quirk, 1);
88962306a36Sopenharmony_ci		else
89062306a36Sopenharmony_ci			dev->hf_size_tx = struct_size(hf, canfd, 1);
89162306a36Sopenharmony_ci	} else {
89262306a36Sopenharmony_ci		if (dev->feature & GS_CAN_FEATURE_REQ_USB_QUIRK_LPC546XX)
89362306a36Sopenharmony_ci			dev->hf_size_tx = struct_size(hf, classic_can_quirk, 1);
89462306a36Sopenharmony_ci		else
89562306a36Sopenharmony_ci			dev->hf_size_tx = struct_size(hf, classic_can, 1);
89662306a36Sopenharmony_ci	}
89762306a36Sopenharmony_ci
89862306a36Sopenharmony_ci	can_rx_offload_enable(&dev->offload);
89962306a36Sopenharmony_ci
90062306a36Sopenharmony_ci	if (!parent->active_channels) {
90162306a36Sopenharmony_ci		if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
90262306a36Sopenharmony_ci			gs_usb_timestamp_init(parent);
90362306a36Sopenharmony_ci
90462306a36Sopenharmony_ci		for (i = 0; i < GS_MAX_RX_URBS; i++) {
90562306a36Sopenharmony_ci			u8 *buf;
90662306a36Sopenharmony_ci
90762306a36Sopenharmony_ci			/* alloc rx urb */
90862306a36Sopenharmony_ci			urb = usb_alloc_urb(0, GFP_KERNEL);
90962306a36Sopenharmony_ci			if (!urb) {
91062306a36Sopenharmony_ci				rc = -ENOMEM;
91162306a36Sopenharmony_ci				goto out_usb_kill_anchored_urbs;
91262306a36Sopenharmony_ci			}
91362306a36Sopenharmony_ci
91462306a36Sopenharmony_ci			/* alloc rx buffer */
91562306a36Sopenharmony_ci			buf = kmalloc(dev->parent->hf_size_rx,
91662306a36Sopenharmony_ci				      GFP_KERNEL);
91762306a36Sopenharmony_ci			if (!buf) {
91862306a36Sopenharmony_ci				rc = -ENOMEM;
91962306a36Sopenharmony_ci				goto out_usb_free_urb;
92062306a36Sopenharmony_ci			}
92162306a36Sopenharmony_ci
92262306a36Sopenharmony_ci			/* fill, anchor, and submit rx urb */
92362306a36Sopenharmony_ci			usb_fill_bulk_urb(urb,
92462306a36Sopenharmony_ci					  dev->udev,
92562306a36Sopenharmony_ci					  usb_rcvbulkpipe(dev->udev,
92662306a36Sopenharmony_ci							  GS_USB_ENDPOINT_IN),
92762306a36Sopenharmony_ci					  buf,
92862306a36Sopenharmony_ci					  dev->parent->hf_size_rx,
92962306a36Sopenharmony_ci					  gs_usb_receive_bulk_callback, parent);
93062306a36Sopenharmony_ci			urb->transfer_flags |= URB_FREE_BUFFER;
93162306a36Sopenharmony_ci
93262306a36Sopenharmony_ci			usb_anchor_urb(urb, &parent->rx_submitted);
93362306a36Sopenharmony_ci
93462306a36Sopenharmony_ci			rc = usb_submit_urb(urb, GFP_KERNEL);
93562306a36Sopenharmony_ci			if (rc) {
93662306a36Sopenharmony_ci				if (rc == -ENODEV)
93762306a36Sopenharmony_ci					netif_device_detach(dev->netdev);
93862306a36Sopenharmony_ci
93962306a36Sopenharmony_ci				netdev_err(netdev,
94062306a36Sopenharmony_ci					   "usb_submit_urb() failed, error %pe\n",
94162306a36Sopenharmony_ci					   ERR_PTR(rc));
94262306a36Sopenharmony_ci
94362306a36Sopenharmony_ci				goto out_usb_unanchor_urb;
94462306a36Sopenharmony_ci			}
94562306a36Sopenharmony_ci
94662306a36Sopenharmony_ci			/* Drop reference,
94762306a36Sopenharmony_ci			 * USB core will take care of freeing it
94862306a36Sopenharmony_ci			 */
94962306a36Sopenharmony_ci			usb_free_urb(urb);
95062306a36Sopenharmony_ci		}
95162306a36Sopenharmony_ci	}
95262306a36Sopenharmony_ci
95362306a36Sopenharmony_ci	/* flags */
95462306a36Sopenharmony_ci	if (ctrlmode & CAN_CTRLMODE_LOOPBACK)
95562306a36Sopenharmony_ci		flags |= GS_CAN_MODE_LOOP_BACK;
95662306a36Sopenharmony_ci
95762306a36Sopenharmony_ci	if (ctrlmode & CAN_CTRLMODE_LISTENONLY)
95862306a36Sopenharmony_ci		flags |= GS_CAN_MODE_LISTEN_ONLY;
95962306a36Sopenharmony_ci
96062306a36Sopenharmony_ci	if (ctrlmode & CAN_CTRLMODE_3_SAMPLES)
96162306a36Sopenharmony_ci		flags |= GS_CAN_MODE_TRIPLE_SAMPLE;
96262306a36Sopenharmony_ci
96362306a36Sopenharmony_ci	if (ctrlmode & CAN_CTRLMODE_ONE_SHOT)
96462306a36Sopenharmony_ci		flags |= GS_CAN_MODE_ONE_SHOT;
96562306a36Sopenharmony_ci
96662306a36Sopenharmony_ci	if (ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
96762306a36Sopenharmony_ci		flags |= GS_CAN_MODE_BERR_REPORTING;
96862306a36Sopenharmony_ci
96962306a36Sopenharmony_ci	if (ctrlmode & CAN_CTRLMODE_FD)
97062306a36Sopenharmony_ci		flags |= GS_CAN_MODE_FD;
97162306a36Sopenharmony_ci
97262306a36Sopenharmony_ci	/* if hardware supports timestamps, enable it */
97362306a36Sopenharmony_ci	if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
97462306a36Sopenharmony_ci		flags |= GS_CAN_MODE_HW_TIMESTAMP;
97562306a36Sopenharmony_ci
97662306a36Sopenharmony_ci	/* finally start device */
97762306a36Sopenharmony_ci	dev->can.state = CAN_STATE_ERROR_ACTIVE;
97862306a36Sopenharmony_ci	dm.flags = cpu_to_le32(flags);
97962306a36Sopenharmony_ci	rc = usb_control_msg_send(dev->udev, 0, GS_USB_BREQ_MODE,
98062306a36Sopenharmony_ci				  USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
98162306a36Sopenharmony_ci				  dev->channel, 0, &dm, sizeof(dm), 1000,
98262306a36Sopenharmony_ci				  GFP_KERNEL);
98362306a36Sopenharmony_ci	if (rc) {
98462306a36Sopenharmony_ci		netdev_err(netdev, "Couldn't start device (err=%d)\n", rc);
98562306a36Sopenharmony_ci		dev->can.state = CAN_STATE_STOPPED;
98662306a36Sopenharmony_ci
98762306a36Sopenharmony_ci		goto out_usb_kill_anchored_urbs;
98862306a36Sopenharmony_ci	}
98962306a36Sopenharmony_ci
99062306a36Sopenharmony_ci	parent->active_channels++;
99162306a36Sopenharmony_ci	if (!(dev->can.ctrlmode & CAN_CTRLMODE_LISTENONLY))
99262306a36Sopenharmony_ci		netif_start_queue(netdev);
99362306a36Sopenharmony_ci
99462306a36Sopenharmony_ci	return 0;
99562306a36Sopenharmony_ci
99662306a36Sopenharmony_ciout_usb_unanchor_urb:
99762306a36Sopenharmony_ci	usb_unanchor_urb(urb);
99862306a36Sopenharmony_ciout_usb_free_urb:
99962306a36Sopenharmony_ci	usb_free_urb(urb);
100062306a36Sopenharmony_ciout_usb_kill_anchored_urbs:
100162306a36Sopenharmony_ci	if (!parent->active_channels) {
100262306a36Sopenharmony_ci		usb_kill_anchored_urbs(&dev->tx_submitted);
100362306a36Sopenharmony_ci
100462306a36Sopenharmony_ci		if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
100562306a36Sopenharmony_ci			gs_usb_timestamp_stop(parent);
100662306a36Sopenharmony_ci	}
100762306a36Sopenharmony_ci
100862306a36Sopenharmony_ci	can_rx_offload_disable(&dev->offload);
100962306a36Sopenharmony_ci	close_candev(netdev);
101062306a36Sopenharmony_ci
101162306a36Sopenharmony_ci	return rc;
101262306a36Sopenharmony_ci}
101362306a36Sopenharmony_ci
101462306a36Sopenharmony_cistatic int gs_usb_get_state(const struct net_device *netdev,
101562306a36Sopenharmony_ci			    struct can_berr_counter *bec,
101662306a36Sopenharmony_ci			    enum can_state *state)
101762306a36Sopenharmony_ci{
101862306a36Sopenharmony_ci	struct gs_can *dev = netdev_priv(netdev);
101962306a36Sopenharmony_ci	struct gs_device_state ds;
102062306a36Sopenharmony_ci	int rc;
102162306a36Sopenharmony_ci
102262306a36Sopenharmony_ci	rc = usb_control_msg_recv(dev->udev, 0, GS_USB_BREQ_GET_STATE,
102362306a36Sopenharmony_ci				  USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
102462306a36Sopenharmony_ci				  dev->channel, 0,
102562306a36Sopenharmony_ci				  &ds, sizeof(ds),
102662306a36Sopenharmony_ci				  USB_CTRL_GET_TIMEOUT,
102762306a36Sopenharmony_ci				  GFP_KERNEL);
102862306a36Sopenharmony_ci	if (rc)
102962306a36Sopenharmony_ci		return rc;
103062306a36Sopenharmony_ci
103162306a36Sopenharmony_ci	if (le32_to_cpu(ds.state) >= CAN_STATE_MAX)
103262306a36Sopenharmony_ci		return -EOPNOTSUPP;
103362306a36Sopenharmony_ci
103462306a36Sopenharmony_ci	*state = le32_to_cpu(ds.state);
103562306a36Sopenharmony_ci	bec->txerr = le32_to_cpu(ds.txerr);
103662306a36Sopenharmony_ci	bec->rxerr = le32_to_cpu(ds.rxerr);
103762306a36Sopenharmony_ci
103862306a36Sopenharmony_ci	return 0;
103962306a36Sopenharmony_ci}
104062306a36Sopenharmony_ci
104162306a36Sopenharmony_cistatic int gs_usb_can_get_berr_counter(const struct net_device *netdev,
104262306a36Sopenharmony_ci				       struct can_berr_counter *bec)
104362306a36Sopenharmony_ci{
104462306a36Sopenharmony_ci	enum can_state state;
104562306a36Sopenharmony_ci
104662306a36Sopenharmony_ci	return gs_usb_get_state(netdev, bec, &state);
104762306a36Sopenharmony_ci}
104862306a36Sopenharmony_ci
104962306a36Sopenharmony_cistatic int gs_can_close(struct net_device *netdev)
105062306a36Sopenharmony_ci{
105162306a36Sopenharmony_ci	int rc;
105262306a36Sopenharmony_ci	struct gs_can *dev = netdev_priv(netdev);
105362306a36Sopenharmony_ci	struct gs_usb *parent = dev->parent;
105462306a36Sopenharmony_ci
105562306a36Sopenharmony_ci	netif_stop_queue(netdev);
105662306a36Sopenharmony_ci
105762306a36Sopenharmony_ci	/* Stop polling */
105862306a36Sopenharmony_ci	parent->active_channels--;
105962306a36Sopenharmony_ci	if (!parent->active_channels) {
106062306a36Sopenharmony_ci		usb_kill_anchored_urbs(&parent->rx_submitted);
106162306a36Sopenharmony_ci
106262306a36Sopenharmony_ci		if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
106362306a36Sopenharmony_ci			gs_usb_timestamp_stop(parent);
106462306a36Sopenharmony_ci	}
106562306a36Sopenharmony_ci
106662306a36Sopenharmony_ci	/* Stop sending URBs */
106762306a36Sopenharmony_ci	usb_kill_anchored_urbs(&dev->tx_submitted);
106862306a36Sopenharmony_ci	atomic_set(&dev->active_tx_urbs, 0);
106962306a36Sopenharmony_ci
107062306a36Sopenharmony_ci	dev->can.state = CAN_STATE_STOPPED;
107162306a36Sopenharmony_ci
107262306a36Sopenharmony_ci	/* reset the device */
107362306a36Sopenharmony_ci	gs_cmd_reset(dev);
107462306a36Sopenharmony_ci
107562306a36Sopenharmony_ci	/* reset tx contexts */
107662306a36Sopenharmony_ci	for (rc = 0; rc < GS_MAX_TX_URBS; rc++) {
107762306a36Sopenharmony_ci		dev->tx_context[rc].dev = dev;
107862306a36Sopenharmony_ci		dev->tx_context[rc].echo_id = GS_MAX_TX_URBS;
107962306a36Sopenharmony_ci	}
108062306a36Sopenharmony_ci
108162306a36Sopenharmony_ci	can_rx_offload_disable(&dev->offload);
108262306a36Sopenharmony_ci
108362306a36Sopenharmony_ci	/* close the netdev */
108462306a36Sopenharmony_ci	close_candev(netdev);
108562306a36Sopenharmony_ci
108662306a36Sopenharmony_ci	return 0;
108762306a36Sopenharmony_ci}
108862306a36Sopenharmony_ci
108962306a36Sopenharmony_cistatic int gs_can_eth_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
109062306a36Sopenharmony_ci{
109162306a36Sopenharmony_ci	const struct gs_can *dev = netdev_priv(netdev);
109262306a36Sopenharmony_ci
109362306a36Sopenharmony_ci	if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
109462306a36Sopenharmony_ci		return can_eth_ioctl_hwts(netdev, ifr, cmd);
109562306a36Sopenharmony_ci
109662306a36Sopenharmony_ci	return -EOPNOTSUPP;
109762306a36Sopenharmony_ci}
109862306a36Sopenharmony_ci
109962306a36Sopenharmony_cistatic const struct net_device_ops gs_usb_netdev_ops = {
110062306a36Sopenharmony_ci	.ndo_open = gs_can_open,
110162306a36Sopenharmony_ci	.ndo_stop = gs_can_close,
110262306a36Sopenharmony_ci	.ndo_start_xmit = gs_can_start_xmit,
110362306a36Sopenharmony_ci	.ndo_change_mtu = can_change_mtu,
110462306a36Sopenharmony_ci	.ndo_eth_ioctl = gs_can_eth_ioctl,
110562306a36Sopenharmony_ci};
110662306a36Sopenharmony_ci
110762306a36Sopenharmony_cistatic int gs_usb_set_identify(struct net_device *netdev, bool do_identify)
110862306a36Sopenharmony_ci{
110962306a36Sopenharmony_ci	struct gs_can *dev = netdev_priv(netdev);
111062306a36Sopenharmony_ci	struct gs_identify_mode imode;
111162306a36Sopenharmony_ci
111262306a36Sopenharmony_ci	if (do_identify)
111362306a36Sopenharmony_ci		imode.mode = cpu_to_le32(GS_CAN_IDENTIFY_ON);
111462306a36Sopenharmony_ci	else
111562306a36Sopenharmony_ci		imode.mode = cpu_to_le32(GS_CAN_IDENTIFY_OFF);
111662306a36Sopenharmony_ci
111762306a36Sopenharmony_ci	return usb_control_msg_send(dev->udev, 0, GS_USB_BREQ_IDENTIFY,
111862306a36Sopenharmony_ci				    USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
111962306a36Sopenharmony_ci				    dev->channel, 0, &imode, sizeof(imode), 100,
112062306a36Sopenharmony_ci				    GFP_KERNEL);
112162306a36Sopenharmony_ci}
112262306a36Sopenharmony_ci
112362306a36Sopenharmony_ci/* blink LED's for finding the this interface */
112462306a36Sopenharmony_cistatic int gs_usb_set_phys_id(struct net_device *netdev,
112562306a36Sopenharmony_ci			      enum ethtool_phys_id_state state)
112662306a36Sopenharmony_ci{
112762306a36Sopenharmony_ci	const struct gs_can *dev = netdev_priv(netdev);
112862306a36Sopenharmony_ci	int rc = 0;
112962306a36Sopenharmony_ci
113062306a36Sopenharmony_ci	if (!(dev->feature & GS_CAN_FEATURE_IDENTIFY))
113162306a36Sopenharmony_ci		return -EOPNOTSUPP;
113262306a36Sopenharmony_ci
113362306a36Sopenharmony_ci	switch (state) {
113462306a36Sopenharmony_ci	case ETHTOOL_ID_ACTIVE:
113562306a36Sopenharmony_ci		rc = gs_usb_set_identify(netdev, GS_CAN_IDENTIFY_ON);
113662306a36Sopenharmony_ci		break;
113762306a36Sopenharmony_ci	case ETHTOOL_ID_INACTIVE:
113862306a36Sopenharmony_ci		rc = gs_usb_set_identify(netdev, GS_CAN_IDENTIFY_OFF);
113962306a36Sopenharmony_ci		break;
114062306a36Sopenharmony_ci	default:
114162306a36Sopenharmony_ci		break;
114262306a36Sopenharmony_ci	}
114362306a36Sopenharmony_ci
114462306a36Sopenharmony_ci	return rc;
114562306a36Sopenharmony_ci}
114662306a36Sopenharmony_ci
114762306a36Sopenharmony_cistatic int gs_usb_get_ts_info(struct net_device *netdev,
114862306a36Sopenharmony_ci			      struct ethtool_ts_info *info)
114962306a36Sopenharmony_ci{
115062306a36Sopenharmony_ci	struct gs_can *dev = netdev_priv(netdev);
115162306a36Sopenharmony_ci
115262306a36Sopenharmony_ci	/* report if device supports HW timestamps */
115362306a36Sopenharmony_ci	if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
115462306a36Sopenharmony_ci		return can_ethtool_op_get_ts_info_hwts(netdev, info);
115562306a36Sopenharmony_ci
115662306a36Sopenharmony_ci	return ethtool_op_get_ts_info(netdev, info);
115762306a36Sopenharmony_ci}
115862306a36Sopenharmony_ci
115962306a36Sopenharmony_cistatic const struct ethtool_ops gs_usb_ethtool_ops = {
116062306a36Sopenharmony_ci	.set_phys_id = gs_usb_set_phys_id,
116162306a36Sopenharmony_ci	.get_ts_info = gs_usb_get_ts_info,
116262306a36Sopenharmony_ci};
116362306a36Sopenharmony_ci
116462306a36Sopenharmony_cistatic int gs_usb_get_termination(struct net_device *netdev, u16 *term)
116562306a36Sopenharmony_ci{
116662306a36Sopenharmony_ci	struct gs_can *dev = netdev_priv(netdev);
116762306a36Sopenharmony_ci	struct gs_device_termination_state term_state;
116862306a36Sopenharmony_ci	int rc;
116962306a36Sopenharmony_ci
117062306a36Sopenharmony_ci	rc = usb_control_msg_recv(dev->udev, 0, GS_USB_BREQ_GET_TERMINATION,
117162306a36Sopenharmony_ci				  USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
117262306a36Sopenharmony_ci				  dev->channel, 0,
117362306a36Sopenharmony_ci				  &term_state, sizeof(term_state), 1000,
117462306a36Sopenharmony_ci				  GFP_KERNEL);
117562306a36Sopenharmony_ci	if (rc)
117662306a36Sopenharmony_ci		return rc;
117762306a36Sopenharmony_ci
117862306a36Sopenharmony_ci	if (term_state.state == cpu_to_le32(GS_CAN_TERMINATION_STATE_ON))
117962306a36Sopenharmony_ci		*term = GS_USB_TERMINATION_ENABLED;
118062306a36Sopenharmony_ci	else
118162306a36Sopenharmony_ci		*term = GS_USB_TERMINATION_DISABLED;
118262306a36Sopenharmony_ci
118362306a36Sopenharmony_ci	return 0;
118462306a36Sopenharmony_ci}
118562306a36Sopenharmony_ci
118662306a36Sopenharmony_cistatic int gs_usb_set_termination(struct net_device *netdev, u16 term)
118762306a36Sopenharmony_ci{
118862306a36Sopenharmony_ci	struct gs_can *dev = netdev_priv(netdev);
118962306a36Sopenharmony_ci	struct gs_device_termination_state term_state;
119062306a36Sopenharmony_ci
119162306a36Sopenharmony_ci	if (term == GS_USB_TERMINATION_ENABLED)
119262306a36Sopenharmony_ci		term_state.state = cpu_to_le32(GS_CAN_TERMINATION_STATE_ON);
119362306a36Sopenharmony_ci	else
119462306a36Sopenharmony_ci		term_state.state = cpu_to_le32(GS_CAN_TERMINATION_STATE_OFF);
119562306a36Sopenharmony_ci
119662306a36Sopenharmony_ci	return usb_control_msg_send(dev->udev, 0, GS_USB_BREQ_SET_TERMINATION,
119762306a36Sopenharmony_ci				    USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
119862306a36Sopenharmony_ci				    dev->channel, 0,
119962306a36Sopenharmony_ci				    &term_state, sizeof(term_state), 1000,
120062306a36Sopenharmony_ci				    GFP_KERNEL);
120162306a36Sopenharmony_ci}
120262306a36Sopenharmony_ci
120362306a36Sopenharmony_cistatic const u16 gs_usb_termination_const[] = {
120462306a36Sopenharmony_ci	GS_USB_TERMINATION_DISABLED,
120562306a36Sopenharmony_ci	GS_USB_TERMINATION_ENABLED
120662306a36Sopenharmony_ci};
120762306a36Sopenharmony_ci
120862306a36Sopenharmony_cistatic struct gs_can *gs_make_candev(unsigned int channel,
120962306a36Sopenharmony_ci				     struct usb_interface *intf,
121062306a36Sopenharmony_ci				     struct gs_device_config *dconf)
121162306a36Sopenharmony_ci{
121262306a36Sopenharmony_ci	struct gs_can *dev;
121362306a36Sopenharmony_ci	struct net_device *netdev;
121462306a36Sopenharmony_ci	int rc;
121562306a36Sopenharmony_ci	struct gs_device_bt_const_extended bt_const_extended;
121662306a36Sopenharmony_ci	struct gs_device_bt_const bt_const;
121762306a36Sopenharmony_ci	u32 feature;
121862306a36Sopenharmony_ci
121962306a36Sopenharmony_ci	/* fetch bit timing constants */
122062306a36Sopenharmony_ci	rc = usb_control_msg_recv(interface_to_usbdev(intf), 0,
122162306a36Sopenharmony_ci				  GS_USB_BREQ_BT_CONST,
122262306a36Sopenharmony_ci				  USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
122362306a36Sopenharmony_ci				  channel, 0, &bt_const, sizeof(bt_const), 1000,
122462306a36Sopenharmony_ci				  GFP_KERNEL);
122562306a36Sopenharmony_ci
122662306a36Sopenharmony_ci	if (rc) {
122762306a36Sopenharmony_ci		dev_err(&intf->dev,
122862306a36Sopenharmony_ci			"Couldn't get bit timing const for channel %d (%pe)\n",
122962306a36Sopenharmony_ci			channel, ERR_PTR(rc));
123062306a36Sopenharmony_ci		return ERR_PTR(rc);
123162306a36Sopenharmony_ci	}
123262306a36Sopenharmony_ci
123362306a36Sopenharmony_ci	/* create netdev */
123462306a36Sopenharmony_ci	netdev = alloc_candev(sizeof(struct gs_can), GS_MAX_TX_URBS);
123562306a36Sopenharmony_ci	if (!netdev) {
123662306a36Sopenharmony_ci		dev_err(&intf->dev, "Couldn't allocate candev\n");
123762306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
123862306a36Sopenharmony_ci	}
123962306a36Sopenharmony_ci
124062306a36Sopenharmony_ci	dev = netdev_priv(netdev);
124162306a36Sopenharmony_ci
124262306a36Sopenharmony_ci	netdev->netdev_ops = &gs_usb_netdev_ops;
124362306a36Sopenharmony_ci	netdev->ethtool_ops = &gs_usb_ethtool_ops;
124462306a36Sopenharmony_ci
124562306a36Sopenharmony_ci	netdev->flags |= IFF_ECHO; /* we support full roundtrip echo */
124662306a36Sopenharmony_ci	netdev->dev_id = channel;
124762306a36Sopenharmony_ci
124862306a36Sopenharmony_ci	/* dev setup */
124962306a36Sopenharmony_ci	strcpy(dev->bt_const.name, KBUILD_MODNAME);
125062306a36Sopenharmony_ci	dev->bt_const.tseg1_min = le32_to_cpu(bt_const.tseg1_min);
125162306a36Sopenharmony_ci	dev->bt_const.tseg1_max = le32_to_cpu(bt_const.tseg1_max);
125262306a36Sopenharmony_ci	dev->bt_const.tseg2_min = le32_to_cpu(bt_const.tseg2_min);
125362306a36Sopenharmony_ci	dev->bt_const.tseg2_max = le32_to_cpu(bt_const.tseg2_max);
125462306a36Sopenharmony_ci	dev->bt_const.sjw_max = le32_to_cpu(bt_const.sjw_max);
125562306a36Sopenharmony_ci	dev->bt_const.brp_min = le32_to_cpu(bt_const.brp_min);
125662306a36Sopenharmony_ci	dev->bt_const.brp_max = le32_to_cpu(bt_const.brp_max);
125762306a36Sopenharmony_ci	dev->bt_const.brp_inc = le32_to_cpu(bt_const.brp_inc);
125862306a36Sopenharmony_ci
125962306a36Sopenharmony_ci	dev->udev = interface_to_usbdev(intf);
126062306a36Sopenharmony_ci	dev->netdev = netdev;
126162306a36Sopenharmony_ci	dev->channel = channel;
126262306a36Sopenharmony_ci
126362306a36Sopenharmony_ci	init_usb_anchor(&dev->tx_submitted);
126462306a36Sopenharmony_ci	atomic_set(&dev->active_tx_urbs, 0);
126562306a36Sopenharmony_ci	spin_lock_init(&dev->tx_ctx_lock);
126662306a36Sopenharmony_ci	for (rc = 0; rc < GS_MAX_TX_URBS; rc++) {
126762306a36Sopenharmony_ci		dev->tx_context[rc].dev = dev;
126862306a36Sopenharmony_ci		dev->tx_context[rc].echo_id = GS_MAX_TX_URBS;
126962306a36Sopenharmony_ci	}
127062306a36Sopenharmony_ci
127162306a36Sopenharmony_ci	/* can setup */
127262306a36Sopenharmony_ci	dev->can.state = CAN_STATE_STOPPED;
127362306a36Sopenharmony_ci	dev->can.clock.freq = le32_to_cpu(bt_const.fclk_can);
127462306a36Sopenharmony_ci	dev->can.bittiming_const = &dev->bt_const;
127562306a36Sopenharmony_ci	dev->can.do_set_bittiming = gs_usb_set_bittiming;
127662306a36Sopenharmony_ci
127762306a36Sopenharmony_ci	dev->can.ctrlmode_supported = CAN_CTRLMODE_CC_LEN8_DLC;
127862306a36Sopenharmony_ci
127962306a36Sopenharmony_ci	feature = le32_to_cpu(bt_const.feature);
128062306a36Sopenharmony_ci	dev->feature = FIELD_GET(GS_CAN_FEATURE_MASK, feature);
128162306a36Sopenharmony_ci	if (feature & GS_CAN_FEATURE_LISTEN_ONLY)
128262306a36Sopenharmony_ci		dev->can.ctrlmode_supported |= CAN_CTRLMODE_LISTENONLY;
128362306a36Sopenharmony_ci
128462306a36Sopenharmony_ci	if (feature & GS_CAN_FEATURE_LOOP_BACK)
128562306a36Sopenharmony_ci		dev->can.ctrlmode_supported |= CAN_CTRLMODE_LOOPBACK;
128662306a36Sopenharmony_ci
128762306a36Sopenharmony_ci	if (feature & GS_CAN_FEATURE_TRIPLE_SAMPLE)
128862306a36Sopenharmony_ci		dev->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES;
128962306a36Sopenharmony_ci
129062306a36Sopenharmony_ci	if (feature & GS_CAN_FEATURE_ONE_SHOT)
129162306a36Sopenharmony_ci		dev->can.ctrlmode_supported |= CAN_CTRLMODE_ONE_SHOT;
129262306a36Sopenharmony_ci
129362306a36Sopenharmony_ci	if (feature & GS_CAN_FEATURE_FD) {
129462306a36Sopenharmony_ci		dev->can.ctrlmode_supported |= CAN_CTRLMODE_FD;
129562306a36Sopenharmony_ci		/* The data bit timing will be overwritten, if
129662306a36Sopenharmony_ci		 * GS_CAN_FEATURE_BT_CONST_EXT is set.
129762306a36Sopenharmony_ci		 */
129862306a36Sopenharmony_ci		dev->can.data_bittiming_const = &dev->bt_const;
129962306a36Sopenharmony_ci		dev->can.do_set_data_bittiming = gs_usb_set_data_bittiming;
130062306a36Sopenharmony_ci	}
130162306a36Sopenharmony_ci
130262306a36Sopenharmony_ci	if (feature & GS_CAN_FEATURE_TERMINATION) {
130362306a36Sopenharmony_ci		rc = gs_usb_get_termination(netdev, &dev->can.termination);
130462306a36Sopenharmony_ci		if (rc) {
130562306a36Sopenharmony_ci			dev->feature &= ~GS_CAN_FEATURE_TERMINATION;
130662306a36Sopenharmony_ci
130762306a36Sopenharmony_ci			dev_info(&intf->dev,
130862306a36Sopenharmony_ci				 "Disabling termination support for channel %d (%pe)\n",
130962306a36Sopenharmony_ci				 channel, ERR_PTR(rc));
131062306a36Sopenharmony_ci		} else {
131162306a36Sopenharmony_ci			dev->can.termination_const = gs_usb_termination_const;
131262306a36Sopenharmony_ci			dev->can.termination_const_cnt = ARRAY_SIZE(gs_usb_termination_const);
131362306a36Sopenharmony_ci			dev->can.do_set_termination = gs_usb_set_termination;
131462306a36Sopenharmony_ci		}
131562306a36Sopenharmony_ci	}
131662306a36Sopenharmony_ci
131762306a36Sopenharmony_ci	if (feature & GS_CAN_FEATURE_BERR_REPORTING)
131862306a36Sopenharmony_ci		dev->can.ctrlmode_supported |= CAN_CTRLMODE_BERR_REPORTING;
131962306a36Sopenharmony_ci
132062306a36Sopenharmony_ci	if (feature & GS_CAN_FEATURE_GET_STATE)
132162306a36Sopenharmony_ci		dev->can.do_get_berr_counter = gs_usb_can_get_berr_counter;
132262306a36Sopenharmony_ci
132362306a36Sopenharmony_ci	/* The CANtact Pro from LinkLayer Labs is based on the
132462306a36Sopenharmony_ci	 * LPC54616 µC, which is affected by the NXP LPC USB transfer
132562306a36Sopenharmony_ci	 * erratum. However, the current firmware (version 2) doesn't
132662306a36Sopenharmony_ci	 * set the GS_CAN_FEATURE_REQ_USB_QUIRK_LPC546XX bit. Set the
132762306a36Sopenharmony_ci	 * feature GS_CAN_FEATURE_REQ_USB_QUIRK_LPC546XX to workaround
132862306a36Sopenharmony_ci	 * this issue.
132962306a36Sopenharmony_ci	 *
133062306a36Sopenharmony_ci	 * For the GS_USB_BREQ_DATA_BITTIMING USB control message the
133162306a36Sopenharmony_ci	 * CANtact Pro firmware uses a request value, which is already
133262306a36Sopenharmony_ci	 * used by the candleLight firmware for a different purpose
133362306a36Sopenharmony_ci	 * (GS_USB_BREQ_GET_USER_ID). Set the feature
133462306a36Sopenharmony_ci	 * GS_CAN_FEATURE_QUIRK_BREQ_CANTACT_PRO to workaround this
133562306a36Sopenharmony_ci	 * issue.
133662306a36Sopenharmony_ci	 */
133762306a36Sopenharmony_ci	if (dev->udev->descriptor.idVendor == cpu_to_le16(USB_GS_USB_1_VENDOR_ID) &&
133862306a36Sopenharmony_ci	    dev->udev->descriptor.idProduct == cpu_to_le16(USB_GS_USB_1_PRODUCT_ID) &&
133962306a36Sopenharmony_ci	    dev->udev->manufacturer && dev->udev->product &&
134062306a36Sopenharmony_ci	    !strcmp(dev->udev->manufacturer, "LinkLayer Labs") &&
134162306a36Sopenharmony_ci	    !strcmp(dev->udev->product, "CANtact Pro") &&
134262306a36Sopenharmony_ci	    (le32_to_cpu(dconf->sw_version) <= 2))
134362306a36Sopenharmony_ci		dev->feature |= GS_CAN_FEATURE_REQ_USB_QUIRK_LPC546XX |
134462306a36Sopenharmony_ci			GS_CAN_FEATURE_QUIRK_BREQ_CANTACT_PRO;
134562306a36Sopenharmony_ci
134662306a36Sopenharmony_ci	/* GS_CAN_FEATURE_IDENTIFY is only supported for sw_version > 1 */
134762306a36Sopenharmony_ci	if (!(le32_to_cpu(dconf->sw_version) > 1 &&
134862306a36Sopenharmony_ci	      feature & GS_CAN_FEATURE_IDENTIFY))
134962306a36Sopenharmony_ci		dev->feature &= ~GS_CAN_FEATURE_IDENTIFY;
135062306a36Sopenharmony_ci
135162306a36Sopenharmony_ci	/* fetch extended bit timing constants if device has feature
135262306a36Sopenharmony_ci	 * GS_CAN_FEATURE_FD and GS_CAN_FEATURE_BT_CONST_EXT
135362306a36Sopenharmony_ci	 */
135462306a36Sopenharmony_ci	if (feature & GS_CAN_FEATURE_FD &&
135562306a36Sopenharmony_ci	    feature & GS_CAN_FEATURE_BT_CONST_EXT) {
135662306a36Sopenharmony_ci		rc = usb_control_msg_recv(interface_to_usbdev(intf), 0,
135762306a36Sopenharmony_ci					  GS_USB_BREQ_BT_CONST_EXT,
135862306a36Sopenharmony_ci					  USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
135962306a36Sopenharmony_ci					  channel, 0, &bt_const_extended,
136062306a36Sopenharmony_ci					  sizeof(bt_const_extended),
136162306a36Sopenharmony_ci					  1000, GFP_KERNEL);
136262306a36Sopenharmony_ci		if (rc) {
136362306a36Sopenharmony_ci			dev_err(&intf->dev,
136462306a36Sopenharmony_ci				"Couldn't get extended bit timing const for channel %d (%pe)\n",
136562306a36Sopenharmony_ci				channel, ERR_PTR(rc));
136662306a36Sopenharmony_ci			goto out_free_candev;
136762306a36Sopenharmony_ci		}
136862306a36Sopenharmony_ci
136962306a36Sopenharmony_ci		strcpy(dev->data_bt_const.name, KBUILD_MODNAME);
137062306a36Sopenharmony_ci		dev->data_bt_const.tseg1_min = le32_to_cpu(bt_const_extended.dtseg1_min);
137162306a36Sopenharmony_ci		dev->data_bt_const.tseg1_max = le32_to_cpu(bt_const_extended.dtseg1_max);
137262306a36Sopenharmony_ci		dev->data_bt_const.tseg2_min = le32_to_cpu(bt_const_extended.dtseg2_min);
137362306a36Sopenharmony_ci		dev->data_bt_const.tseg2_max = le32_to_cpu(bt_const_extended.dtseg2_max);
137462306a36Sopenharmony_ci		dev->data_bt_const.sjw_max = le32_to_cpu(bt_const_extended.dsjw_max);
137562306a36Sopenharmony_ci		dev->data_bt_const.brp_min = le32_to_cpu(bt_const_extended.dbrp_min);
137662306a36Sopenharmony_ci		dev->data_bt_const.brp_max = le32_to_cpu(bt_const_extended.dbrp_max);
137762306a36Sopenharmony_ci		dev->data_bt_const.brp_inc = le32_to_cpu(bt_const_extended.dbrp_inc);
137862306a36Sopenharmony_ci
137962306a36Sopenharmony_ci		dev->can.data_bittiming_const = &dev->data_bt_const;
138062306a36Sopenharmony_ci	}
138162306a36Sopenharmony_ci
138262306a36Sopenharmony_ci	can_rx_offload_add_manual(netdev, &dev->offload, GS_NAPI_WEIGHT);
138362306a36Sopenharmony_ci	SET_NETDEV_DEV(netdev, &intf->dev);
138462306a36Sopenharmony_ci
138562306a36Sopenharmony_ci	rc = register_candev(dev->netdev);
138662306a36Sopenharmony_ci	if (rc) {
138762306a36Sopenharmony_ci		dev_err(&intf->dev,
138862306a36Sopenharmony_ci			"Couldn't register candev for channel %d (%pe)\n",
138962306a36Sopenharmony_ci			channel, ERR_PTR(rc));
139062306a36Sopenharmony_ci		goto out_can_rx_offload_del;
139162306a36Sopenharmony_ci	}
139262306a36Sopenharmony_ci
139362306a36Sopenharmony_ci	return dev;
139462306a36Sopenharmony_ci
139562306a36Sopenharmony_ciout_can_rx_offload_del:
139662306a36Sopenharmony_ci	can_rx_offload_del(&dev->offload);
139762306a36Sopenharmony_ciout_free_candev:
139862306a36Sopenharmony_ci	free_candev(dev->netdev);
139962306a36Sopenharmony_ci	return ERR_PTR(rc);
140062306a36Sopenharmony_ci}
140162306a36Sopenharmony_ci
140262306a36Sopenharmony_cistatic void gs_destroy_candev(struct gs_can *dev)
140362306a36Sopenharmony_ci{
140462306a36Sopenharmony_ci	unregister_candev(dev->netdev);
140562306a36Sopenharmony_ci	can_rx_offload_del(&dev->offload);
140662306a36Sopenharmony_ci	free_candev(dev->netdev);
140762306a36Sopenharmony_ci}
140862306a36Sopenharmony_ci
140962306a36Sopenharmony_cistatic int gs_usb_probe(struct usb_interface *intf,
141062306a36Sopenharmony_ci			const struct usb_device_id *id)
141162306a36Sopenharmony_ci{
141262306a36Sopenharmony_ci	struct usb_device *udev = interface_to_usbdev(intf);
141362306a36Sopenharmony_ci	struct gs_host_frame *hf;
141462306a36Sopenharmony_ci	struct gs_usb *parent;
141562306a36Sopenharmony_ci	struct gs_host_config hconf = {
141662306a36Sopenharmony_ci		.byte_order = cpu_to_le32(0x0000beef),
141762306a36Sopenharmony_ci	};
141862306a36Sopenharmony_ci	struct gs_device_config dconf;
141962306a36Sopenharmony_ci	unsigned int icount, i;
142062306a36Sopenharmony_ci	int rc;
142162306a36Sopenharmony_ci
142262306a36Sopenharmony_ci	/* send host config */
142362306a36Sopenharmony_ci	rc = usb_control_msg_send(udev, 0,
142462306a36Sopenharmony_ci				  GS_USB_BREQ_HOST_FORMAT,
142562306a36Sopenharmony_ci				  USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
142662306a36Sopenharmony_ci				  1, intf->cur_altsetting->desc.bInterfaceNumber,
142762306a36Sopenharmony_ci				  &hconf, sizeof(hconf), 1000,
142862306a36Sopenharmony_ci				  GFP_KERNEL);
142962306a36Sopenharmony_ci	if (rc) {
143062306a36Sopenharmony_ci		dev_err(&intf->dev, "Couldn't send data format (err=%d)\n", rc);
143162306a36Sopenharmony_ci		return rc;
143262306a36Sopenharmony_ci	}
143362306a36Sopenharmony_ci
143462306a36Sopenharmony_ci	/* read device config */
143562306a36Sopenharmony_ci	rc = usb_control_msg_recv(udev, 0,
143662306a36Sopenharmony_ci				  GS_USB_BREQ_DEVICE_CONFIG,
143762306a36Sopenharmony_ci				  USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
143862306a36Sopenharmony_ci				  1, intf->cur_altsetting->desc.bInterfaceNumber,
143962306a36Sopenharmony_ci				  &dconf, sizeof(dconf), 1000,
144062306a36Sopenharmony_ci				  GFP_KERNEL);
144162306a36Sopenharmony_ci	if (rc) {
144262306a36Sopenharmony_ci		dev_err(&intf->dev, "Couldn't get device config: (err=%d)\n",
144362306a36Sopenharmony_ci			rc);
144462306a36Sopenharmony_ci		return rc;
144562306a36Sopenharmony_ci	}
144662306a36Sopenharmony_ci
144762306a36Sopenharmony_ci	icount = dconf.icount + 1;
144862306a36Sopenharmony_ci	dev_info(&intf->dev, "Configuring for %u interfaces\n", icount);
144962306a36Sopenharmony_ci
145062306a36Sopenharmony_ci	if (icount > GS_MAX_INTF) {
145162306a36Sopenharmony_ci		dev_err(&intf->dev,
145262306a36Sopenharmony_ci			"Driver cannot handle more that %u CAN interfaces\n",
145362306a36Sopenharmony_ci			GS_MAX_INTF);
145462306a36Sopenharmony_ci		return -EINVAL;
145562306a36Sopenharmony_ci	}
145662306a36Sopenharmony_ci
145762306a36Sopenharmony_ci	parent = kzalloc(sizeof(*parent), GFP_KERNEL);
145862306a36Sopenharmony_ci	if (!parent)
145962306a36Sopenharmony_ci		return -ENOMEM;
146062306a36Sopenharmony_ci
146162306a36Sopenharmony_ci	init_usb_anchor(&parent->rx_submitted);
146262306a36Sopenharmony_ci
146362306a36Sopenharmony_ci	usb_set_intfdata(intf, parent);
146462306a36Sopenharmony_ci	parent->udev = udev;
146562306a36Sopenharmony_ci
146662306a36Sopenharmony_ci	for (i = 0; i < icount; i++) {
146762306a36Sopenharmony_ci		unsigned int hf_size_rx = 0;
146862306a36Sopenharmony_ci
146962306a36Sopenharmony_ci		parent->canch[i] = gs_make_candev(i, intf, &dconf);
147062306a36Sopenharmony_ci		if (IS_ERR_OR_NULL(parent->canch[i])) {
147162306a36Sopenharmony_ci			/* save error code to return later */
147262306a36Sopenharmony_ci			rc = PTR_ERR(parent->canch[i]);
147362306a36Sopenharmony_ci
147462306a36Sopenharmony_ci			/* on failure destroy previously created candevs */
147562306a36Sopenharmony_ci			icount = i;
147662306a36Sopenharmony_ci			for (i = 0; i < icount; i++)
147762306a36Sopenharmony_ci				gs_destroy_candev(parent->canch[i]);
147862306a36Sopenharmony_ci
147962306a36Sopenharmony_ci			usb_kill_anchored_urbs(&parent->rx_submitted);
148062306a36Sopenharmony_ci			kfree(parent);
148162306a36Sopenharmony_ci			return rc;
148262306a36Sopenharmony_ci		}
148362306a36Sopenharmony_ci		parent->canch[i]->parent = parent;
148462306a36Sopenharmony_ci
148562306a36Sopenharmony_ci		/* set RX packet size based on FD and if hardware
148662306a36Sopenharmony_ci		 * timestamps are supported.
148762306a36Sopenharmony_ci		 */
148862306a36Sopenharmony_ci		if (parent->canch[i]->can.ctrlmode_supported & CAN_CTRLMODE_FD) {
148962306a36Sopenharmony_ci			if (parent->canch[i]->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
149062306a36Sopenharmony_ci				hf_size_rx = struct_size(hf, canfd_ts, 1);
149162306a36Sopenharmony_ci			else
149262306a36Sopenharmony_ci				hf_size_rx = struct_size(hf, canfd, 1);
149362306a36Sopenharmony_ci		} else {
149462306a36Sopenharmony_ci			if (parent->canch[i]->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
149562306a36Sopenharmony_ci				hf_size_rx = struct_size(hf, classic_can_ts, 1);
149662306a36Sopenharmony_ci			else
149762306a36Sopenharmony_ci				hf_size_rx = struct_size(hf, classic_can, 1);
149862306a36Sopenharmony_ci		}
149962306a36Sopenharmony_ci		parent->hf_size_rx = max(parent->hf_size_rx, hf_size_rx);
150062306a36Sopenharmony_ci	}
150162306a36Sopenharmony_ci
150262306a36Sopenharmony_ci	return 0;
150362306a36Sopenharmony_ci}
150462306a36Sopenharmony_ci
150562306a36Sopenharmony_cistatic void gs_usb_disconnect(struct usb_interface *intf)
150662306a36Sopenharmony_ci{
150762306a36Sopenharmony_ci	struct gs_usb *parent = usb_get_intfdata(intf);
150862306a36Sopenharmony_ci	unsigned int i;
150962306a36Sopenharmony_ci
151062306a36Sopenharmony_ci	usb_set_intfdata(intf, NULL);
151162306a36Sopenharmony_ci
151262306a36Sopenharmony_ci	if (!parent) {
151362306a36Sopenharmony_ci		dev_err(&intf->dev, "Disconnect (nodata)\n");
151462306a36Sopenharmony_ci		return;
151562306a36Sopenharmony_ci	}
151662306a36Sopenharmony_ci
151762306a36Sopenharmony_ci	for (i = 0; i < GS_MAX_INTF; i++)
151862306a36Sopenharmony_ci		if (parent->canch[i])
151962306a36Sopenharmony_ci			gs_destroy_candev(parent->canch[i]);
152062306a36Sopenharmony_ci
152162306a36Sopenharmony_ci	kfree(parent);
152262306a36Sopenharmony_ci}
152362306a36Sopenharmony_ci
152462306a36Sopenharmony_cistatic const struct usb_device_id gs_usb_table[] = {
152562306a36Sopenharmony_ci	{ USB_DEVICE_INTERFACE_NUMBER(USB_GS_USB_1_VENDOR_ID,
152662306a36Sopenharmony_ci				      USB_GS_USB_1_PRODUCT_ID, 0) },
152762306a36Sopenharmony_ci	{ USB_DEVICE_INTERFACE_NUMBER(USB_CANDLELIGHT_VENDOR_ID,
152862306a36Sopenharmony_ci				      USB_CANDLELIGHT_PRODUCT_ID, 0) },
152962306a36Sopenharmony_ci	{ USB_DEVICE_INTERFACE_NUMBER(USB_CES_CANEXT_FD_VENDOR_ID,
153062306a36Sopenharmony_ci				      USB_CES_CANEXT_FD_PRODUCT_ID, 0) },
153162306a36Sopenharmony_ci	{ USB_DEVICE_INTERFACE_NUMBER(USB_ABE_CANDEBUGGER_FD_VENDOR_ID,
153262306a36Sopenharmony_ci				      USB_ABE_CANDEBUGGER_FD_PRODUCT_ID, 0) },
153362306a36Sopenharmony_ci	{} /* Terminating entry */
153462306a36Sopenharmony_ci};
153562306a36Sopenharmony_ci
153662306a36Sopenharmony_ciMODULE_DEVICE_TABLE(usb, gs_usb_table);
153762306a36Sopenharmony_ci
153862306a36Sopenharmony_cistatic struct usb_driver gs_usb_driver = {
153962306a36Sopenharmony_ci	.name = KBUILD_MODNAME,
154062306a36Sopenharmony_ci	.probe = gs_usb_probe,
154162306a36Sopenharmony_ci	.disconnect = gs_usb_disconnect,
154262306a36Sopenharmony_ci	.id_table = gs_usb_table,
154362306a36Sopenharmony_ci};
154462306a36Sopenharmony_ci
154562306a36Sopenharmony_cimodule_usb_driver(gs_usb_driver);
154662306a36Sopenharmony_ci
154762306a36Sopenharmony_ciMODULE_AUTHOR("Maximilian Schneider <mws@schneidersoft.net>");
154862306a36Sopenharmony_ciMODULE_DESCRIPTION(
154962306a36Sopenharmony_ci"Socket CAN device driver for Geschwister Schneider Technologie-, "
155062306a36Sopenharmony_ci"Entwicklungs- und Vertriebs UG. USB2.0 to CAN interfaces\n"
155162306a36Sopenharmony_ci"and bytewerk.org candleLight USB CAN interfaces.");
155262306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
1553