18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/* CAN driver for Geschwister Schneider USB/CAN devices
38c2ecf20Sopenharmony_ci * and bytewerk.org candleLight USB CAN interfaces.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2013-2016 Geschwister Schneider Technologie-,
68c2ecf20Sopenharmony_ci * Entwicklungs- und Vertriebs UG (Haftungsbeschränkt).
78c2ecf20Sopenharmony_ci * Copyright (C) 2016 Hubert Denkmair
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * Many thanks to all socketcan devs!
108c2ecf20Sopenharmony_ci */
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include <linux/init.h>
138c2ecf20Sopenharmony_ci#include <linux/signal.h>
148c2ecf20Sopenharmony_ci#include <linux/module.h>
158c2ecf20Sopenharmony_ci#include <linux/netdevice.h>
168c2ecf20Sopenharmony_ci#include <linux/usb.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#include <linux/can.h>
198c2ecf20Sopenharmony_ci#include <linux/can/dev.h>
208c2ecf20Sopenharmony_ci#include <linux/can/error.h>
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci/* Device specific constants */
238c2ecf20Sopenharmony_ci#define USB_GSUSB_1_VENDOR_ID      0x1d50
248c2ecf20Sopenharmony_ci#define USB_GSUSB_1_PRODUCT_ID     0x606f
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci#define USB_CANDLELIGHT_VENDOR_ID  0x1209
278c2ecf20Sopenharmony_ci#define USB_CANDLELIGHT_PRODUCT_ID 0x2323
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci#define GSUSB_ENDPOINT_IN          1
308c2ecf20Sopenharmony_ci#define GSUSB_ENDPOINT_OUT         2
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci/* Device specific constants */
338c2ecf20Sopenharmony_cienum gs_usb_breq {
348c2ecf20Sopenharmony_ci	GS_USB_BREQ_HOST_FORMAT = 0,
358c2ecf20Sopenharmony_ci	GS_USB_BREQ_BITTIMING,
368c2ecf20Sopenharmony_ci	GS_USB_BREQ_MODE,
378c2ecf20Sopenharmony_ci	GS_USB_BREQ_BERR,
388c2ecf20Sopenharmony_ci	GS_USB_BREQ_BT_CONST,
398c2ecf20Sopenharmony_ci	GS_USB_BREQ_DEVICE_CONFIG,
408c2ecf20Sopenharmony_ci	GS_USB_BREQ_TIMESTAMP,
418c2ecf20Sopenharmony_ci	GS_USB_BREQ_IDENTIFY,
428c2ecf20Sopenharmony_ci};
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_cienum gs_can_mode {
458c2ecf20Sopenharmony_ci	/* reset a channel. turns it off */
468c2ecf20Sopenharmony_ci	GS_CAN_MODE_RESET = 0,
478c2ecf20Sopenharmony_ci	/* starts a channel */
488c2ecf20Sopenharmony_ci	GS_CAN_MODE_START
498c2ecf20Sopenharmony_ci};
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_cienum gs_can_state {
528c2ecf20Sopenharmony_ci	GS_CAN_STATE_ERROR_ACTIVE = 0,
538c2ecf20Sopenharmony_ci	GS_CAN_STATE_ERROR_WARNING,
548c2ecf20Sopenharmony_ci	GS_CAN_STATE_ERROR_PASSIVE,
558c2ecf20Sopenharmony_ci	GS_CAN_STATE_BUS_OFF,
568c2ecf20Sopenharmony_ci	GS_CAN_STATE_STOPPED,
578c2ecf20Sopenharmony_ci	GS_CAN_STATE_SLEEPING
588c2ecf20Sopenharmony_ci};
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_cienum gs_can_identify_mode {
618c2ecf20Sopenharmony_ci	GS_CAN_IDENTIFY_OFF = 0,
628c2ecf20Sopenharmony_ci	GS_CAN_IDENTIFY_ON
638c2ecf20Sopenharmony_ci};
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci/* data types passed between host and device */
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci/* The firmware on the original USB2CAN by Geschwister Schneider
688c2ecf20Sopenharmony_ci * Technologie Entwicklungs- und Vertriebs UG exchanges all data
698c2ecf20Sopenharmony_ci * between the host and the device in host byte order. This is done
708c2ecf20Sopenharmony_ci * with the struct gs_host_config::byte_order member, which is sent
718c2ecf20Sopenharmony_ci * first to indicate the desired byte order.
728c2ecf20Sopenharmony_ci *
738c2ecf20Sopenharmony_ci * The widely used open source firmware candleLight doesn't support
748c2ecf20Sopenharmony_ci * this feature and exchanges the data in little endian byte order.
758c2ecf20Sopenharmony_ci */
768c2ecf20Sopenharmony_cistruct gs_host_config {
778c2ecf20Sopenharmony_ci	__le32 byte_order;
788c2ecf20Sopenharmony_ci} __packed;
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_cistruct gs_device_config {
818c2ecf20Sopenharmony_ci	u8 reserved1;
828c2ecf20Sopenharmony_ci	u8 reserved2;
838c2ecf20Sopenharmony_ci	u8 reserved3;
848c2ecf20Sopenharmony_ci	u8 icount;
858c2ecf20Sopenharmony_ci	__le32 sw_version;
868c2ecf20Sopenharmony_ci	__le32 hw_version;
878c2ecf20Sopenharmony_ci} __packed;
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci#define GS_CAN_MODE_NORMAL               0
908c2ecf20Sopenharmony_ci#define GS_CAN_MODE_LISTEN_ONLY          BIT(0)
918c2ecf20Sopenharmony_ci#define GS_CAN_MODE_LOOP_BACK            BIT(1)
928c2ecf20Sopenharmony_ci#define GS_CAN_MODE_TRIPLE_SAMPLE        BIT(2)
938c2ecf20Sopenharmony_ci#define GS_CAN_MODE_ONE_SHOT             BIT(3)
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_cistruct gs_device_mode {
968c2ecf20Sopenharmony_ci	__le32 mode;
978c2ecf20Sopenharmony_ci	__le32 flags;
988c2ecf20Sopenharmony_ci} __packed;
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_cistruct gs_device_state {
1018c2ecf20Sopenharmony_ci	__le32 state;
1028c2ecf20Sopenharmony_ci	__le32 rxerr;
1038c2ecf20Sopenharmony_ci	__le32 txerr;
1048c2ecf20Sopenharmony_ci} __packed;
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_cistruct gs_device_bittiming {
1078c2ecf20Sopenharmony_ci	__le32 prop_seg;
1088c2ecf20Sopenharmony_ci	__le32 phase_seg1;
1098c2ecf20Sopenharmony_ci	__le32 phase_seg2;
1108c2ecf20Sopenharmony_ci	__le32 sjw;
1118c2ecf20Sopenharmony_ci	__le32 brp;
1128c2ecf20Sopenharmony_ci} __packed;
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_cistruct gs_identify_mode {
1158c2ecf20Sopenharmony_ci	__le32 mode;
1168c2ecf20Sopenharmony_ci} __packed;
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci#define GS_CAN_FEATURE_LISTEN_ONLY      BIT(0)
1198c2ecf20Sopenharmony_ci#define GS_CAN_FEATURE_LOOP_BACK        BIT(1)
1208c2ecf20Sopenharmony_ci#define GS_CAN_FEATURE_TRIPLE_SAMPLE    BIT(2)
1218c2ecf20Sopenharmony_ci#define GS_CAN_FEATURE_ONE_SHOT         BIT(3)
1228c2ecf20Sopenharmony_ci#define GS_CAN_FEATURE_HW_TIMESTAMP     BIT(4)
1238c2ecf20Sopenharmony_ci#define GS_CAN_FEATURE_IDENTIFY         BIT(5)
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_cistruct gs_device_bt_const {
1268c2ecf20Sopenharmony_ci	__le32 feature;
1278c2ecf20Sopenharmony_ci	__le32 fclk_can;
1288c2ecf20Sopenharmony_ci	__le32 tseg1_min;
1298c2ecf20Sopenharmony_ci	__le32 tseg1_max;
1308c2ecf20Sopenharmony_ci	__le32 tseg2_min;
1318c2ecf20Sopenharmony_ci	__le32 tseg2_max;
1328c2ecf20Sopenharmony_ci	__le32 sjw_max;
1338c2ecf20Sopenharmony_ci	__le32 brp_min;
1348c2ecf20Sopenharmony_ci	__le32 brp_max;
1358c2ecf20Sopenharmony_ci	__le32 brp_inc;
1368c2ecf20Sopenharmony_ci} __packed;
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci#define GS_CAN_FLAG_OVERFLOW 1
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_cistruct gs_host_frame {
1418c2ecf20Sopenharmony_ci	u32 echo_id;
1428c2ecf20Sopenharmony_ci	__le32 can_id;
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci	u8 can_dlc;
1458c2ecf20Sopenharmony_ci	u8 channel;
1468c2ecf20Sopenharmony_ci	u8 flags;
1478c2ecf20Sopenharmony_ci	u8 reserved;
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci	u8 data[8];
1508c2ecf20Sopenharmony_ci} __packed;
1518c2ecf20Sopenharmony_ci/* The GS USB devices make use of the same flags and masks as in
1528c2ecf20Sopenharmony_ci * linux/can.h and linux/can/error.h, and no additional mapping is necessary.
1538c2ecf20Sopenharmony_ci */
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci/* Only send a max of GS_MAX_TX_URBS frames per channel at a time. */
1568c2ecf20Sopenharmony_ci#define GS_MAX_TX_URBS 10
1578c2ecf20Sopenharmony_ci/* Only launch a max of GS_MAX_RX_URBS usb requests at a time. */
1588c2ecf20Sopenharmony_ci#define GS_MAX_RX_URBS 30
1598c2ecf20Sopenharmony_ci/* Maximum number of interfaces the driver supports per device.
1608c2ecf20Sopenharmony_ci * Current hardware only supports 2 interfaces. The future may vary.
1618c2ecf20Sopenharmony_ci */
1628c2ecf20Sopenharmony_ci#define GS_MAX_INTF 2
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_cistruct gs_tx_context {
1658c2ecf20Sopenharmony_ci	struct gs_can *dev;
1668c2ecf20Sopenharmony_ci	unsigned int echo_id;
1678c2ecf20Sopenharmony_ci};
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_cistruct gs_can {
1708c2ecf20Sopenharmony_ci	struct can_priv can; /* must be the first member */
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci	struct gs_usb *parent;
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	struct net_device *netdev;
1758c2ecf20Sopenharmony_ci	struct usb_device *udev;
1768c2ecf20Sopenharmony_ci	struct usb_interface *iface;
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci	struct can_bittiming_const bt_const;
1798c2ecf20Sopenharmony_ci	unsigned int channel;	/* channel number */
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci	/* This lock prevents a race condition between xmit and receive. */
1828c2ecf20Sopenharmony_ci	spinlock_t tx_ctx_lock;
1838c2ecf20Sopenharmony_ci	struct gs_tx_context tx_context[GS_MAX_TX_URBS];
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci	struct usb_anchor tx_submitted;
1868c2ecf20Sopenharmony_ci	atomic_t active_tx_urbs;
1878c2ecf20Sopenharmony_ci	void *rxbuf[GS_MAX_RX_URBS];
1888c2ecf20Sopenharmony_ci	dma_addr_t rxbuf_dma[GS_MAX_RX_URBS];
1898c2ecf20Sopenharmony_ci};
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci/* usb interface struct */
1928c2ecf20Sopenharmony_cistruct gs_usb {
1938c2ecf20Sopenharmony_ci	struct gs_can *canch[GS_MAX_INTF];
1948c2ecf20Sopenharmony_ci	struct usb_anchor rx_submitted;
1958c2ecf20Sopenharmony_ci	struct usb_device *udev;
1968c2ecf20Sopenharmony_ci	u8 active_channels;
1978c2ecf20Sopenharmony_ci};
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci/* 'allocate' a tx context.
2008c2ecf20Sopenharmony_ci * returns a valid tx context or NULL if there is no space.
2018c2ecf20Sopenharmony_ci */
2028c2ecf20Sopenharmony_cistatic struct gs_tx_context *gs_alloc_tx_context(struct gs_can *dev)
2038c2ecf20Sopenharmony_ci{
2048c2ecf20Sopenharmony_ci	int i = 0;
2058c2ecf20Sopenharmony_ci	unsigned long flags;
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	spin_lock_irqsave(&dev->tx_ctx_lock, flags);
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci	for (; i < GS_MAX_TX_URBS; i++) {
2108c2ecf20Sopenharmony_ci		if (dev->tx_context[i].echo_id == GS_MAX_TX_URBS) {
2118c2ecf20Sopenharmony_ci			dev->tx_context[i].echo_id = i;
2128c2ecf20Sopenharmony_ci			spin_unlock_irqrestore(&dev->tx_ctx_lock, flags);
2138c2ecf20Sopenharmony_ci			return &dev->tx_context[i];
2148c2ecf20Sopenharmony_ci		}
2158c2ecf20Sopenharmony_ci	}
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&dev->tx_ctx_lock, flags);
2188c2ecf20Sopenharmony_ci	return NULL;
2198c2ecf20Sopenharmony_ci}
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci/* releases a tx context
2228c2ecf20Sopenharmony_ci */
2238c2ecf20Sopenharmony_cistatic void gs_free_tx_context(struct gs_tx_context *txc)
2248c2ecf20Sopenharmony_ci{
2258c2ecf20Sopenharmony_ci	txc->echo_id = GS_MAX_TX_URBS;
2268c2ecf20Sopenharmony_ci}
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci/* Get a tx context by id.
2298c2ecf20Sopenharmony_ci */
2308c2ecf20Sopenharmony_cistatic struct gs_tx_context *gs_get_tx_context(struct gs_can *dev,
2318c2ecf20Sopenharmony_ci					       unsigned int id)
2328c2ecf20Sopenharmony_ci{
2338c2ecf20Sopenharmony_ci	unsigned long flags;
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci	if (id < GS_MAX_TX_URBS) {
2368c2ecf20Sopenharmony_ci		spin_lock_irqsave(&dev->tx_ctx_lock, flags);
2378c2ecf20Sopenharmony_ci		if (dev->tx_context[id].echo_id == id) {
2388c2ecf20Sopenharmony_ci			spin_unlock_irqrestore(&dev->tx_ctx_lock, flags);
2398c2ecf20Sopenharmony_ci			return &dev->tx_context[id];
2408c2ecf20Sopenharmony_ci		}
2418c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&dev->tx_ctx_lock, flags);
2428c2ecf20Sopenharmony_ci	}
2438c2ecf20Sopenharmony_ci	return NULL;
2448c2ecf20Sopenharmony_ci}
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_cistatic int gs_cmd_reset(struct gs_can *gsdev)
2478c2ecf20Sopenharmony_ci{
2488c2ecf20Sopenharmony_ci	struct gs_device_mode *dm;
2498c2ecf20Sopenharmony_ci	struct usb_interface *intf = gsdev->iface;
2508c2ecf20Sopenharmony_ci	int rc;
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci	dm = kzalloc(sizeof(*dm), GFP_KERNEL);
2538c2ecf20Sopenharmony_ci	if (!dm)
2548c2ecf20Sopenharmony_ci		return -ENOMEM;
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci	dm->mode = GS_CAN_MODE_RESET;
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci	rc = usb_control_msg(interface_to_usbdev(intf),
2598c2ecf20Sopenharmony_ci			     usb_sndctrlpipe(interface_to_usbdev(intf), 0),
2608c2ecf20Sopenharmony_ci			     GS_USB_BREQ_MODE,
2618c2ecf20Sopenharmony_ci			     USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
2628c2ecf20Sopenharmony_ci			     gsdev->channel,
2638c2ecf20Sopenharmony_ci			     0,
2648c2ecf20Sopenharmony_ci			     dm,
2658c2ecf20Sopenharmony_ci			     sizeof(*dm),
2668c2ecf20Sopenharmony_ci			     1000);
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci	kfree(dm);
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci	return rc;
2718c2ecf20Sopenharmony_ci}
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_cistatic void gs_update_state(struct gs_can *dev, struct can_frame *cf)
2748c2ecf20Sopenharmony_ci{
2758c2ecf20Sopenharmony_ci	struct can_device_stats *can_stats = &dev->can.can_stats;
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci	if (cf->can_id & CAN_ERR_RESTARTED) {
2788c2ecf20Sopenharmony_ci		dev->can.state = CAN_STATE_ERROR_ACTIVE;
2798c2ecf20Sopenharmony_ci		can_stats->restarts++;
2808c2ecf20Sopenharmony_ci	} else if (cf->can_id & CAN_ERR_BUSOFF) {
2818c2ecf20Sopenharmony_ci		dev->can.state = CAN_STATE_BUS_OFF;
2828c2ecf20Sopenharmony_ci		can_stats->bus_off++;
2838c2ecf20Sopenharmony_ci	} else if (cf->can_id & CAN_ERR_CRTL) {
2848c2ecf20Sopenharmony_ci		if ((cf->data[1] & CAN_ERR_CRTL_TX_WARNING) ||
2858c2ecf20Sopenharmony_ci		    (cf->data[1] & CAN_ERR_CRTL_RX_WARNING)) {
2868c2ecf20Sopenharmony_ci			dev->can.state = CAN_STATE_ERROR_WARNING;
2878c2ecf20Sopenharmony_ci			can_stats->error_warning++;
2888c2ecf20Sopenharmony_ci		} else if ((cf->data[1] & CAN_ERR_CRTL_TX_PASSIVE) ||
2898c2ecf20Sopenharmony_ci			   (cf->data[1] & CAN_ERR_CRTL_RX_PASSIVE)) {
2908c2ecf20Sopenharmony_ci			dev->can.state = CAN_STATE_ERROR_PASSIVE;
2918c2ecf20Sopenharmony_ci			can_stats->error_passive++;
2928c2ecf20Sopenharmony_ci		} else {
2938c2ecf20Sopenharmony_ci			dev->can.state = CAN_STATE_ERROR_ACTIVE;
2948c2ecf20Sopenharmony_ci		}
2958c2ecf20Sopenharmony_ci	}
2968c2ecf20Sopenharmony_ci}
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_cistatic void gs_usb_receive_bulk_callback(struct urb *urb)
2998c2ecf20Sopenharmony_ci{
3008c2ecf20Sopenharmony_ci	struct gs_usb *usbcan = urb->context;
3018c2ecf20Sopenharmony_ci	struct gs_can *dev;
3028c2ecf20Sopenharmony_ci	struct net_device *netdev;
3038c2ecf20Sopenharmony_ci	int rc;
3048c2ecf20Sopenharmony_ci	struct net_device_stats *stats;
3058c2ecf20Sopenharmony_ci	struct gs_host_frame *hf = urb->transfer_buffer;
3068c2ecf20Sopenharmony_ci	struct gs_tx_context *txc;
3078c2ecf20Sopenharmony_ci	struct can_frame *cf;
3088c2ecf20Sopenharmony_ci	struct sk_buff *skb;
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ci	BUG_ON(!usbcan);
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci	switch (urb->status) {
3138c2ecf20Sopenharmony_ci	case 0: /* success */
3148c2ecf20Sopenharmony_ci		break;
3158c2ecf20Sopenharmony_ci	case -ENOENT:
3168c2ecf20Sopenharmony_ci	case -ESHUTDOWN:
3178c2ecf20Sopenharmony_ci		return;
3188c2ecf20Sopenharmony_ci	default:
3198c2ecf20Sopenharmony_ci		/* do not resubmit aborted urbs. eg: when device goes down */
3208c2ecf20Sopenharmony_ci		return;
3218c2ecf20Sopenharmony_ci	}
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_ci	/* device reports out of range channel id */
3248c2ecf20Sopenharmony_ci	if (hf->channel >= GS_MAX_INTF)
3258c2ecf20Sopenharmony_ci		goto device_detach;
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_ci	dev = usbcan->canch[hf->channel];
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci	netdev = dev->netdev;
3308c2ecf20Sopenharmony_ci	stats = &netdev->stats;
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci	if (!netif_device_present(netdev))
3338c2ecf20Sopenharmony_ci		return;
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_ci	if (hf->echo_id == -1) { /* normal rx */
3368c2ecf20Sopenharmony_ci		skb = alloc_can_skb(dev->netdev, &cf);
3378c2ecf20Sopenharmony_ci		if (!skb)
3388c2ecf20Sopenharmony_ci			return;
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci		cf->can_id = le32_to_cpu(hf->can_id);
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci		cf->can_dlc = get_can_dlc(hf->can_dlc);
3438c2ecf20Sopenharmony_ci		memcpy(cf->data, hf->data, 8);
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_ci		/* ERROR frames tell us information about the controller */
3468c2ecf20Sopenharmony_ci		if (le32_to_cpu(hf->can_id) & CAN_ERR_FLAG)
3478c2ecf20Sopenharmony_ci			gs_update_state(dev, cf);
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci		netdev->stats.rx_packets++;
3508c2ecf20Sopenharmony_ci		netdev->stats.rx_bytes += hf->can_dlc;
3518c2ecf20Sopenharmony_ci
3528c2ecf20Sopenharmony_ci		netif_rx(skb);
3538c2ecf20Sopenharmony_ci	} else { /* echo_id == hf->echo_id */
3548c2ecf20Sopenharmony_ci		if (hf->echo_id >= GS_MAX_TX_URBS) {
3558c2ecf20Sopenharmony_ci			netdev_err(netdev,
3568c2ecf20Sopenharmony_ci				   "Unexpected out of range echo id %d\n",
3578c2ecf20Sopenharmony_ci				   hf->echo_id);
3588c2ecf20Sopenharmony_ci			goto resubmit_urb;
3598c2ecf20Sopenharmony_ci		}
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ci		netdev->stats.tx_packets++;
3628c2ecf20Sopenharmony_ci		netdev->stats.tx_bytes += hf->can_dlc;
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci		txc = gs_get_tx_context(dev, hf->echo_id);
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci		/* bad devices send bad echo_ids. */
3678c2ecf20Sopenharmony_ci		if (!txc) {
3688c2ecf20Sopenharmony_ci			netdev_err(netdev,
3698c2ecf20Sopenharmony_ci				   "Unexpected unused echo id %d\n",
3708c2ecf20Sopenharmony_ci				   hf->echo_id);
3718c2ecf20Sopenharmony_ci			goto resubmit_urb;
3728c2ecf20Sopenharmony_ci		}
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_ci		can_get_echo_skb(netdev, hf->echo_id);
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_ci		gs_free_tx_context(txc);
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_ci		atomic_dec(&dev->active_tx_urbs);
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci		netif_wake_queue(netdev);
3818c2ecf20Sopenharmony_ci	}
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci	if (hf->flags & GS_CAN_FLAG_OVERFLOW) {
3848c2ecf20Sopenharmony_ci		stats->rx_over_errors++;
3858c2ecf20Sopenharmony_ci		stats->rx_errors++;
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ci		skb = alloc_can_err_skb(netdev, &cf);
3888c2ecf20Sopenharmony_ci		if (!skb)
3898c2ecf20Sopenharmony_ci			goto resubmit_urb;
3908c2ecf20Sopenharmony_ci
3918c2ecf20Sopenharmony_ci		cf->can_id |= CAN_ERR_CRTL;
3928c2ecf20Sopenharmony_ci		cf->can_dlc = CAN_ERR_DLC;
3938c2ecf20Sopenharmony_ci		cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
3948c2ecf20Sopenharmony_ci		netif_rx(skb);
3958c2ecf20Sopenharmony_ci	}
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_ci resubmit_urb:
3988c2ecf20Sopenharmony_ci	usb_fill_bulk_urb(urb,
3998c2ecf20Sopenharmony_ci			  usbcan->udev,
4008c2ecf20Sopenharmony_ci			  usb_rcvbulkpipe(usbcan->udev, GSUSB_ENDPOINT_IN),
4018c2ecf20Sopenharmony_ci			  hf,
4028c2ecf20Sopenharmony_ci			  sizeof(struct gs_host_frame),
4038c2ecf20Sopenharmony_ci			  gs_usb_receive_bulk_callback,
4048c2ecf20Sopenharmony_ci			  usbcan
4058c2ecf20Sopenharmony_ci			  );
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ci	rc = usb_submit_urb(urb, GFP_ATOMIC);
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci	/* USB failure take down all interfaces */
4108c2ecf20Sopenharmony_ci	if (rc == -ENODEV) {
4118c2ecf20Sopenharmony_ci device_detach:
4128c2ecf20Sopenharmony_ci		for (rc = 0; rc < GS_MAX_INTF; rc++) {
4138c2ecf20Sopenharmony_ci			if (usbcan->canch[rc])
4148c2ecf20Sopenharmony_ci				netif_device_detach(usbcan->canch[rc]->netdev);
4158c2ecf20Sopenharmony_ci		}
4168c2ecf20Sopenharmony_ci	}
4178c2ecf20Sopenharmony_ci}
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_cistatic int gs_usb_set_bittiming(struct net_device *netdev)
4208c2ecf20Sopenharmony_ci{
4218c2ecf20Sopenharmony_ci	struct gs_can *dev = netdev_priv(netdev);
4228c2ecf20Sopenharmony_ci	struct can_bittiming *bt = &dev->can.bittiming;
4238c2ecf20Sopenharmony_ci	struct usb_interface *intf = dev->iface;
4248c2ecf20Sopenharmony_ci	int rc;
4258c2ecf20Sopenharmony_ci	struct gs_device_bittiming *dbt;
4268c2ecf20Sopenharmony_ci
4278c2ecf20Sopenharmony_ci	dbt = kmalloc(sizeof(*dbt), GFP_KERNEL);
4288c2ecf20Sopenharmony_ci	if (!dbt)
4298c2ecf20Sopenharmony_ci		return -ENOMEM;
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_ci	dbt->prop_seg = cpu_to_le32(bt->prop_seg);
4328c2ecf20Sopenharmony_ci	dbt->phase_seg1 = cpu_to_le32(bt->phase_seg1);
4338c2ecf20Sopenharmony_ci	dbt->phase_seg2 = cpu_to_le32(bt->phase_seg2);
4348c2ecf20Sopenharmony_ci	dbt->sjw = cpu_to_le32(bt->sjw);
4358c2ecf20Sopenharmony_ci	dbt->brp = cpu_to_le32(bt->brp);
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ci	/* request bit timings */
4388c2ecf20Sopenharmony_ci	rc = usb_control_msg(interface_to_usbdev(intf),
4398c2ecf20Sopenharmony_ci			     usb_sndctrlpipe(interface_to_usbdev(intf), 0),
4408c2ecf20Sopenharmony_ci			     GS_USB_BREQ_BITTIMING,
4418c2ecf20Sopenharmony_ci			     USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
4428c2ecf20Sopenharmony_ci			     dev->channel,
4438c2ecf20Sopenharmony_ci			     0,
4448c2ecf20Sopenharmony_ci			     dbt,
4458c2ecf20Sopenharmony_ci			     sizeof(*dbt),
4468c2ecf20Sopenharmony_ci			     1000);
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_ci	kfree(dbt);
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_ci	if (rc < 0)
4518c2ecf20Sopenharmony_ci		dev_err(netdev->dev.parent, "Couldn't set bittimings (err=%d)",
4528c2ecf20Sopenharmony_ci			rc);
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci	return (rc > 0) ? 0 : rc;
4558c2ecf20Sopenharmony_ci}
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_cistatic void gs_usb_xmit_callback(struct urb *urb)
4588c2ecf20Sopenharmony_ci{
4598c2ecf20Sopenharmony_ci	struct gs_tx_context *txc = urb->context;
4608c2ecf20Sopenharmony_ci	struct gs_can *dev = txc->dev;
4618c2ecf20Sopenharmony_ci	struct net_device *netdev = dev->netdev;
4628c2ecf20Sopenharmony_ci
4638c2ecf20Sopenharmony_ci	if (urb->status)
4648c2ecf20Sopenharmony_ci		netdev_info(netdev, "usb xmit fail %d\n", txc->echo_id);
4658c2ecf20Sopenharmony_ci
4668c2ecf20Sopenharmony_ci	usb_free_coherent(urb->dev,
4678c2ecf20Sopenharmony_ci			  urb->transfer_buffer_length,
4688c2ecf20Sopenharmony_ci			  urb->transfer_buffer,
4698c2ecf20Sopenharmony_ci			  urb->transfer_dma);
4708c2ecf20Sopenharmony_ci}
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_cistatic netdev_tx_t gs_can_start_xmit(struct sk_buff *skb,
4738c2ecf20Sopenharmony_ci				     struct net_device *netdev)
4748c2ecf20Sopenharmony_ci{
4758c2ecf20Sopenharmony_ci	struct gs_can *dev = netdev_priv(netdev);
4768c2ecf20Sopenharmony_ci	struct net_device_stats *stats = &dev->netdev->stats;
4778c2ecf20Sopenharmony_ci	struct urb *urb;
4788c2ecf20Sopenharmony_ci	struct gs_host_frame *hf;
4798c2ecf20Sopenharmony_ci	struct can_frame *cf;
4808c2ecf20Sopenharmony_ci	int rc;
4818c2ecf20Sopenharmony_ci	unsigned int idx;
4828c2ecf20Sopenharmony_ci	struct gs_tx_context *txc;
4838c2ecf20Sopenharmony_ci
4848c2ecf20Sopenharmony_ci	if (can_dropped_invalid_skb(netdev, skb))
4858c2ecf20Sopenharmony_ci		return NETDEV_TX_OK;
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_ci	/* find an empty context to keep track of transmission */
4888c2ecf20Sopenharmony_ci	txc = gs_alloc_tx_context(dev);
4898c2ecf20Sopenharmony_ci	if (!txc)
4908c2ecf20Sopenharmony_ci		return NETDEV_TX_BUSY;
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_ci	/* create a URB, and a buffer for it */
4938c2ecf20Sopenharmony_ci	urb = usb_alloc_urb(0, GFP_ATOMIC);
4948c2ecf20Sopenharmony_ci	if (!urb)
4958c2ecf20Sopenharmony_ci		goto nomem_urb;
4968c2ecf20Sopenharmony_ci
4978c2ecf20Sopenharmony_ci	hf = usb_alloc_coherent(dev->udev, sizeof(*hf), GFP_ATOMIC,
4988c2ecf20Sopenharmony_ci				&urb->transfer_dma);
4998c2ecf20Sopenharmony_ci	if (!hf) {
5008c2ecf20Sopenharmony_ci		netdev_err(netdev, "No memory left for USB buffer\n");
5018c2ecf20Sopenharmony_ci		goto nomem_hf;
5028c2ecf20Sopenharmony_ci	}
5038c2ecf20Sopenharmony_ci
5048c2ecf20Sopenharmony_ci	idx = txc->echo_id;
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ci	if (idx >= GS_MAX_TX_URBS) {
5078c2ecf20Sopenharmony_ci		netdev_err(netdev, "Invalid tx context %d\n", idx);
5088c2ecf20Sopenharmony_ci		goto badidx;
5098c2ecf20Sopenharmony_ci	}
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_ci	hf->echo_id = idx;
5128c2ecf20Sopenharmony_ci	hf->channel = dev->channel;
5138c2ecf20Sopenharmony_ci	hf->flags = 0;
5148c2ecf20Sopenharmony_ci	hf->reserved = 0;
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_ci	cf = (struct can_frame *)skb->data;
5178c2ecf20Sopenharmony_ci
5188c2ecf20Sopenharmony_ci	hf->can_id = cpu_to_le32(cf->can_id);
5198c2ecf20Sopenharmony_ci	hf->can_dlc = cf->can_dlc;
5208c2ecf20Sopenharmony_ci	memcpy(hf->data, cf->data, cf->can_dlc);
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_ci	usb_fill_bulk_urb(urb, dev->udev,
5238c2ecf20Sopenharmony_ci			  usb_sndbulkpipe(dev->udev, GSUSB_ENDPOINT_OUT),
5248c2ecf20Sopenharmony_ci			  hf,
5258c2ecf20Sopenharmony_ci			  sizeof(*hf),
5268c2ecf20Sopenharmony_ci			  gs_usb_xmit_callback,
5278c2ecf20Sopenharmony_ci			  txc);
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_ci	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
5308c2ecf20Sopenharmony_ci	usb_anchor_urb(urb, &dev->tx_submitted);
5318c2ecf20Sopenharmony_ci
5328c2ecf20Sopenharmony_ci	can_put_echo_skb(skb, netdev, idx);
5338c2ecf20Sopenharmony_ci
5348c2ecf20Sopenharmony_ci	atomic_inc(&dev->active_tx_urbs);
5358c2ecf20Sopenharmony_ci
5368c2ecf20Sopenharmony_ci	rc = usb_submit_urb(urb, GFP_ATOMIC);
5378c2ecf20Sopenharmony_ci	if (unlikely(rc)) {			/* usb send failed */
5388c2ecf20Sopenharmony_ci		atomic_dec(&dev->active_tx_urbs);
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci		can_free_echo_skb(netdev, idx);
5418c2ecf20Sopenharmony_ci		gs_free_tx_context(txc);
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_ci		usb_unanchor_urb(urb);
5448c2ecf20Sopenharmony_ci		usb_free_coherent(dev->udev,
5458c2ecf20Sopenharmony_ci				  sizeof(*hf),
5468c2ecf20Sopenharmony_ci				  hf,
5478c2ecf20Sopenharmony_ci				  urb->transfer_dma);
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci		if (rc == -ENODEV) {
5508c2ecf20Sopenharmony_ci			netif_device_detach(netdev);
5518c2ecf20Sopenharmony_ci		} else {
5528c2ecf20Sopenharmony_ci			netdev_err(netdev, "usb_submit failed (err=%d)\n", rc);
5538c2ecf20Sopenharmony_ci			stats->tx_dropped++;
5548c2ecf20Sopenharmony_ci		}
5558c2ecf20Sopenharmony_ci	} else {
5568c2ecf20Sopenharmony_ci		/* Slow down tx path */
5578c2ecf20Sopenharmony_ci		if (atomic_read(&dev->active_tx_urbs) >= GS_MAX_TX_URBS)
5588c2ecf20Sopenharmony_ci			netif_stop_queue(netdev);
5598c2ecf20Sopenharmony_ci	}
5608c2ecf20Sopenharmony_ci
5618c2ecf20Sopenharmony_ci	/* let usb core take care of this urb */
5628c2ecf20Sopenharmony_ci	usb_free_urb(urb);
5638c2ecf20Sopenharmony_ci
5648c2ecf20Sopenharmony_ci	return NETDEV_TX_OK;
5658c2ecf20Sopenharmony_ci
5668c2ecf20Sopenharmony_ci badidx:
5678c2ecf20Sopenharmony_ci	usb_free_coherent(dev->udev,
5688c2ecf20Sopenharmony_ci			  sizeof(*hf),
5698c2ecf20Sopenharmony_ci			  hf,
5708c2ecf20Sopenharmony_ci			  urb->transfer_dma);
5718c2ecf20Sopenharmony_ci nomem_hf:
5728c2ecf20Sopenharmony_ci	usb_free_urb(urb);
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_ci nomem_urb:
5758c2ecf20Sopenharmony_ci	gs_free_tx_context(txc);
5768c2ecf20Sopenharmony_ci	dev_kfree_skb(skb);
5778c2ecf20Sopenharmony_ci	stats->tx_dropped++;
5788c2ecf20Sopenharmony_ci	return NETDEV_TX_OK;
5798c2ecf20Sopenharmony_ci}
5808c2ecf20Sopenharmony_ci
5818c2ecf20Sopenharmony_cistatic int gs_can_open(struct net_device *netdev)
5828c2ecf20Sopenharmony_ci{
5838c2ecf20Sopenharmony_ci	struct gs_can *dev = netdev_priv(netdev);
5848c2ecf20Sopenharmony_ci	struct gs_usb *parent = dev->parent;
5858c2ecf20Sopenharmony_ci	int rc, i;
5868c2ecf20Sopenharmony_ci	struct gs_device_mode *dm;
5878c2ecf20Sopenharmony_ci	u32 ctrlmode;
5888c2ecf20Sopenharmony_ci	u32 flags = 0;
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci	rc = open_candev(netdev);
5918c2ecf20Sopenharmony_ci	if (rc)
5928c2ecf20Sopenharmony_ci		return rc;
5938c2ecf20Sopenharmony_ci
5948c2ecf20Sopenharmony_ci	if (!parent->active_channels) {
5958c2ecf20Sopenharmony_ci		for (i = 0; i < GS_MAX_RX_URBS; i++) {
5968c2ecf20Sopenharmony_ci			struct urb *urb;
5978c2ecf20Sopenharmony_ci			u8 *buf;
5988c2ecf20Sopenharmony_ci			dma_addr_t buf_dma;
5998c2ecf20Sopenharmony_ci
6008c2ecf20Sopenharmony_ci			/* alloc rx urb */
6018c2ecf20Sopenharmony_ci			urb = usb_alloc_urb(0, GFP_KERNEL);
6028c2ecf20Sopenharmony_ci			if (!urb)
6038c2ecf20Sopenharmony_ci				return -ENOMEM;
6048c2ecf20Sopenharmony_ci
6058c2ecf20Sopenharmony_ci			/* alloc rx buffer */
6068c2ecf20Sopenharmony_ci			buf = usb_alloc_coherent(dev->udev,
6078c2ecf20Sopenharmony_ci						 sizeof(struct gs_host_frame),
6088c2ecf20Sopenharmony_ci						 GFP_KERNEL,
6098c2ecf20Sopenharmony_ci						 &buf_dma);
6108c2ecf20Sopenharmony_ci			if (!buf) {
6118c2ecf20Sopenharmony_ci				netdev_err(netdev,
6128c2ecf20Sopenharmony_ci					   "No memory left for USB buffer\n");
6138c2ecf20Sopenharmony_ci				usb_free_urb(urb);
6148c2ecf20Sopenharmony_ci				return -ENOMEM;
6158c2ecf20Sopenharmony_ci			}
6168c2ecf20Sopenharmony_ci
6178c2ecf20Sopenharmony_ci			urb->transfer_dma = buf_dma;
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_ci			/* fill, anchor, and submit rx urb */
6208c2ecf20Sopenharmony_ci			usb_fill_bulk_urb(urb,
6218c2ecf20Sopenharmony_ci					  dev->udev,
6228c2ecf20Sopenharmony_ci					  usb_rcvbulkpipe(dev->udev,
6238c2ecf20Sopenharmony_ci							  GSUSB_ENDPOINT_IN),
6248c2ecf20Sopenharmony_ci					  buf,
6258c2ecf20Sopenharmony_ci					  sizeof(struct gs_host_frame),
6268c2ecf20Sopenharmony_ci					  gs_usb_receive_bulk_callback,
6278c2ecf20Sopenharmony_ci					  parent);
6288c2ecf20Sopenharmony_ci			urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_ci			usb_anchor_urb(urb, &parent->rx_submitted);
6318c2ecf20Sopenharmony_ci
6328c2ecf20Sopenharmony_ci			rc = usb_submit_urb(urb, GFP_KERNEL);
6338c2ecf20Sopenharmony_ci			if (rc) {
6348c2ecf20Sopenharmony_ci				if (rc == -ENODEV)
6358c2ecf20Sopenharmony_ci					netif_device_detach(dev->netdev);
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_ci				netdev_err(netdev,
6388c2ecf20Sopenharmony_ci					   "usb_submit failed (err=%d)\n",
6398c2ecf20Sopenharmony_ci					   rc);
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_ci				usb_unanchor_urb(urb);
6428c2ecf20Sopenharmony_ci				usb_free_coherent(dev->udev,
6438c2ecf20Sopenharmony_ci						  sizeof(struct gs_host_frame),
6448c2ecf20Sopenharmony_ci						  buf,
6458c2ecf20Sopenharmony_ci						  buf_dma);
6468c2ecf20Sopenharmony_ci				usb_free_urb(urb);
6478c2ecf20Sopenharmony_ci				break;
6488c2ecf20Sopenharmony_ci			}
6498c2ecf20Sopenharmony_ci
6508c2ecf20Sopenharmony_ci			dev->rxbuf[i] = buf;
6518c2ecf20Sopenharmony_ci			dev->rxbuf_dma[i] = buf_dma;
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_ci			/* Drop reference,
6548c2ecf20Sopenharmony_ci			 * USB core will take care of freeing it
6558c2ecf20Sopenharmony_ci			 */
6568c2ecf20Sopenharmony_ci			usb_free_urb(urb);
6578c2ecf20Sopenharmony_ci		}
6588c2ecf20Sopenharmony_ci	}
6598c2ecf20Sopenharmony_ci
6608c2ecf20Sopenharmony_ci	dm = kmalloc(sizeof(*dm), GFP_KERNEL);
6618c2ecf20Sopenharmony_ci	if (!dm)
6628c2ecf20Sopenharmony_ci		return -ENOMEM;
6638c2ecf20Sopenharmony_ci
6648c2ecf20Sopenharmony_ci	/* flags */
6658c2ecf20Sopenharmony_ci	ctrlmode = dev->can.ctrlmode;
6668c2ecf20Sopenharmony_ci
6678c2ecf20Sopenharmony_ci	if (ctrlmode & CAN_CTRLMODE_LOOPBACK)
6688c2ecf20Sopenharmony_ci		flags |= GS_CAN_MODE_LOOP_BACK;
6698c2ecf20Sopenharmony_ci	else if (ctrlmode & CAN_CTRLMODE_LISTENONLY)
6708c2ecf20Sopenharmony_ci		flags |= GS_CAN_MODE_LISTEN_ONLY;
6718c2ecf20Sopenharmony_ci
6728c2ecf20Sopenharmony_ci	/* Controller is not allowed to retry TX
6738c2ecf20Sopenharmony_ci	 * this mode is unavailable on atmels uc3c hardware
6748c2ecf20Sopenharmony_ci	 */
6758c2ecf20Sopenharmony_ci	if (ctrlmode & CAN_CTRLMODE_ONE_SHOT)
6768c2ecf20Sopenharmony_ci		flags |= GS_CAN_MODE_ONE_SHOT;
6778c2ecf20Sopenharmony_ci
6788c2ecf20Sopenharmony_ci	if (ctrlmode & CAN_CTRLMODE_3_SAMPLES)
6798c2ecf20Sopenharmony_ci		flags |= GS_CAN_MODE_TRIPLE_SAMPLE;
6808c2ecf20Sopenharmony_ci
6818c2ecf20Sopenharmony_ci	/* finally start device */
6828c2ecf20Sopenharmony_ci	dev->can.state = CAN_STATE_ERROR_ACTIVE;
6838c2ecf20Sopenharmony_ci	dm->mode = cpu_to_le32(GS_CAN_MODE_START);
6848c2ecf20Sopenharmony_ci	dm->flags = cpu_to_le32(flags);
6858c2ecf20Sopenharmony_ci	rc = usb_control_msg(interface_to_usbdev(dev->iface),
6868c2ecf20Sopenharmony_ci			     usb_sndctrlpipe(interface_to_usbdev(dev->iface), 0),
6878c2ecf20Sopenharmony_ci			     GS_USB_BREQ_MODE,
6888c2ecf20Sopenharmony_ci			     USB_DIR_OUT | USB_TYPE_VENDOR |
6898c2ecf20Sopenharmony_ci			     USB_RECIP_INTERFACE,
6908c2ecf20Sopenharmony_ci			     dev->channel,
6918c2ecf20Sopenharmony_ci			     0,
6928c2ecf20Sopenharmony_ci			     dm,
6938c2ecf20Sopenharmony_ci			     sizeof(*dm),
6948c2ecf20Sopenharmony_ci			     1000);
6958c2ecf20Sopenharmony_ci
6968c2ecf20Sopenharmony_ci	if (rc < 0) {
6978c2ecf20Sopenharmony_ci		netdev_err(netdev, "Couldn't start device (err=%d)\n", rc);
6988c2ecf20Sopenharmony_ci		kfree(dm);
6998c2ecf20Sopenharmony_ci		dev->can.state = CAN_STATE_STOPPED;
7008c2ecf20Sopenharmony_ci		return rc;
7018c2ecf20Sopenharmony_ci	}
7028c2ecf20Sopenharmony_ci
7038c2ecf20Sopenharmony_ci	kfree(dm);
7048c2ecf20Sopenharmony_ci
7058c2ecf20Sopenharmony_ci	parent->active_channels++;
7068c2ecf20Sopenharmony_ci	if (!(dev->can.ctrlmode & CAN_CTRLMODE_LISTENONLY))
7078c2ecf20Sopenharmony_ci		netif_start_queue(netdev);
7088c2ecf20Sopenharmony_ci
7098c2ecf20Sopenharmony_ci	return 0;
7108c2ecf20Sopenharmony_ci}
7118c2ecf20Sopenharmony_ci
7128c2ecf20Sopenharmony_cistatic int gs_can_close(struct net_device *netdev)
7138c2ecf20Sopenharmony_ci{
7148c2ecf20Sopenharmony_ci	int rc;
7158c2ecf20Sopenharmony_ci	struct gs_can *dev = netdev_priv(netdev);
7168c2ecf20Sopenharmony_ci	struct gs_usb *parent = dev->parent;
7178c2ecf20Sopenharmony_ci	unsigned int i;
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_ci	netif_stop_queue(netdev);
7208c2ecf20Sopenharmony_ci
7218c2ecf20Sopenharmony_ci	/* Stop polling */
7228c2ecf20Sopenharmony_ci	parent->active_channels--;
7238c2ecf20Sopenharmony_ci	if (!parent->active_channels) {
7248c2ecf20Sopenharmony_ci		usb_kill_anchored_urbs(&parent->rx_submitted);
7258c2ecf20Sopenharmony_ci		for (i = 0; i < GS_MAX_RX_URBS; i++)
7268c2ecf20Sopenharmony_ci			usb_free_coherent(dev->udev,
7278c2ecf20Sopenharmony_ci					  sizeof(struct gs_host_frame),
7288c2ecf20Sopenharmony_ci					  dev->rxbuf[i],
7298c2ecf20Sopenharmony_ci					  dev->rxbuf_dma[i]);
7308c2ecf20Sopenharmony_ci	}
7318c2ecf20Sopenharmony_ci
7328c2ecf20Sopenharmony_ci	/* Stop sending URBs */
7338c2ecf20Sopenharmony_ci	usb_kill_anchored_urbs(&dev->tx_submitted);
7348c2ecf20Sopenharmony_ci	atomic_set(&dev->active_tx_urbs, 0);
7358c2ecf20Sopenharmony_ci
7368c2ecf20Sopenharmony_ci	dev->can.state = CAN_STATE_STOPPED;
7378c2ecf20Sopenharmony_ci
7388c2ecf20Sopenharmony_ci	/* reset the device */
7398c2ecf20Sopenharmony_ci	rc = gs_cmd_reset(dev);
7408c2ecf20Sopenharmony_ci	if (rc < 0)
7418c2ecf20Sopenharmony_ci		netdev_warn(netdev, "Couldn't shutdown device (err=%d)", rc);
7428c2ecf20Sopenharmony_ci
7438c2ecf20Sopenharmony_ci	/* reset tx contexts */
7448c2ecf20Sopenharmony_ci	for (rc = 0; rc < GS_MAX_TX_URBS; rc++) {
7458c2ecf20Sopenharmony_ci		dev->tx_context[rc].dev = dev;
7468c2ecf20Sopenharmony_ci		dev->tx_context[rc].echo_id = GS_MAX_TX_URBS;
7478c2ecf20Sopenharmony_ci	}
7488c2ecf20Sopenharmony_ci
7498c2ecf20Sopenharmony_ci	/* close the netdev */
7508c2ecf20Sopenharmony_ci	close_candev(netdev);
7518c2ecf20Sopenharmony_ci
7528c2ecf20Sopenharmony_ci	return 0;
7538c2ecf20Sopenharmony_ci}
7548c2ecf20Sopenharmony_ci
7558c2ecf20Sopenharmony_cistatic const struct net_device_ops gs_usb_netdev_ops = {
7568c2ecf20Sopenharmony_ci	.ndo_open = gs_can_open,
7578c2ecf20Sopenharmony_ci	.ndo_stop = gs_can_close,
7588c2ecf20Sopenharmony_ci	.ndo_start_xmit = gs_can_start_xmit,
7598c2ecf20Sopenharmony_ci	.ndo_change_mtu = can_change_mtu,
7608c2ecf20Sopenharmony_ci};
7618c2ecf20Sopenharmony_ci
7628c2ecf20Sopenharmony_cistatic int gs_usb_set_identify(struct net_device *netdev, bool do_identify)
7638c2ecf20Sopenharmony_ci{
7648c2ecf20Sopenharmony_ci	struct gs_can *dev = netdev_priv(netdev);
7658c2ecf20Sopenharmony_ci	struct gs_identify_mode *imode;
7668c2ecf20Sopenharmony_ci	int rc;
7678c2ecf20Sopenharmony_ci
7688c2ecf20Sopenharmony_ci	imode = kmalloc(sizeof(*imode), GFP_KERNEL);
7698c2ecf20Sopenharmony_ci
7708c2ecf20Sopenharmony_ci	if (!imode)
7718c2ecf20Sopenharmony_ci		return -ENOMEM;
7728c2ecf20Sopenharmony_ci
7738c2ecf20Sopenharmony_ci	if (do_identify)
7748c2ecf20Sopenharmony_ci		imode->mode = cpu_to_le32(GS_CAN_IDENTIFY_ON);
7758c2ecf20Sopenharmony_ci	else
7768c2ecf20Sopenharmony_ci		imode->mode = cpu_to_le32(GS_CAN_IDENTIFY_OFF);
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_ci	rc = usb_control_msg(interface_to_usbdev(dev->iface),
7798c2ecf20Sopenharmony_ci			     usb_sndctrlpipe(interface_to_usbdev(dev->iface),
7808c2ecf20Sopenharmony_ci					     0),
7818c2ecf20Sopenharmony_ci			     GS_USB_BREQ_IDENTIFY,
7828c2ecf20Sopenharmony_ci			     USB_DIR_OUT | USB_TYPE_VENDOR |
7838c2ecf20Sopenharmony_ci			     USB_RECIP_INTERFACE,
7848c2ecf20Sopenharmony_ci			     dev->channel,
7858c2ecf20Sopenharmony_ci			     0,
7868c2ecf20Sopenharmony_ci			     imode,
7878c2ecf20Sopenharmony_ci			     sizeof(*imode),
7888c2ecf20Sopenharmony_ci			     100);
7898c2ecf20Sopenharmony_ci
7908c2ecf20Sopenharmony_ci	kfree(imode);
7918c2ecf20Sopenharmony_ci
7928c2ecf20Sopenharmony_ci	return (rc > 0) ? 0 : rc;
7938c2ecf20Sopenharmony_ci}
7948c2ecf20Sopenharmony_ci
7958c2ecf20Sopenharmony_ci/* blink LED's for finding the this interface */
7968c2ecf20Sopenharmony_cistatic int gs_usb_set_phys_id(struct net_device *dev,
7978c2ecf20Sopenharmony_ci			      enum ethtool_phys_id_state state)
7988c2ecf20Sopenharmony_ci{
7998c2ecf20Sopenharmony_ci	int rc = 0;
8008c2ecf20Sopenharmony_ci
8018c2ecf20Sopenharmony_ci	switch (state) {
8028c2ecf20Sopenharmony_ci	case ETHTOOL_ID_ACTIVE:
8038c2ecf20Sopenharmony_ci		rc = gs_usb_set_identify(dev, GS_CAN_IDENTIFY_ON);
8048c2ecf20Sopenharmony_ci		break;
8058c2ecf20Sopenharmony_ci	case ETHTOOL_ID_INACTIVE:
8068c2ecf20Sopenharmony_ci		rc = gs_usb_set_identify(dev, GS_CAN_IDENTIFY_OFF);
8078c2ecf20Sopenharmony_ci		break;
8088c2ecf20Sopenharmony_ci	default:
8098c2ecf20Sopenharmony_ci		break;
8108c2ecf20Sopenharmony_ci	}
8118c2ecf20Sopenharmony_ci
8128c2ecf20Sopenharmony_ci	return rc;
8138c2ecf20Sopenharmony_ci}
8148c2ecf20Sopenharmony_ci
8158c2ecf20Sopenharmony_cistatic const struct ethtool_ops gs_usb_ethtool_ops = {
8168c2ecf20Sopenharmony_ci	.set_phys_id = gs_usb_set_phys_id,
8178c2ecf20Sopenharmony_ci};
8188c2ecf20Sopenharmony_ci
8198c2ecf20Sopenharmony_cistatic struct gs_can *gs_make_candev(unsigned int channel,
8208c2ecf20Sopenharmony_ci				     struct usb_interface *intf,
8218c2ecf20Sopenharmony_ci				     struct gs_device_config *dconf)
8228c2ecf20Sopenharmony_ci{
8238c2ecf20Sopenharmony_ci	struct gs_can *dev;
8248c2ecf20Sopenharmony_ci	struct net_device *netdev;
8258c2ecf20Sopenharmony_ci	int rc;
8268c2ecf20Sopenharmony_ci	struct gs_device_bt_const *bt_const;
8278c2ecf20Sopenharmony_ci	u32 feature;
8288c2ecf20Sopenharmony_ci
8298c2ecf20Sopenharmony_ci	bt_const = kmalloc(sizeof(*bt_const), GFP_KERNEL);
8308c2ecf20Sopenharmony_ci	if (!bt_const)
8318c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
8328c2ecf20Sopenharmony_ci
8338c2ecf20Sopenharmony_ci	/* fetch bit timing constants */
8348c2ecf20Sopenharmony_ci	rc = usb_control_msg(interface_to_usbdev(intf),
8358c2ecf20Sopenharmony_ci			     usb_rcvctrlpipe(interface_to_usbdev(intf), 0),
8368c2ecf20Sopenharmony_ci			     GS_USB_BREQ_BT_CONST,
8378c2ecf20Sopenharmony_ci			     USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
8388c2ecf20Sopenharmony_ci			     channel,
8398c2ecf20Sopenharmony_ci			     0,
8408c2ecf20Sopenharmony_ci			     bt_const,
8418c2ecf20Sopenharmony_ci			     sizeof(*bt_const),
8428c2ecf20Sopenharmony_ci			     1000);
8438c2ecf20Sopenharmony_ci
8448c2ecf20Sopenharmony_ci	if (rc < 0) {
8458c2ecf20Sopenharmony_ci		dev_err(&intf->dev,
8468c2ecf20Sopenharmony_ci			"Couldn't get bit timing const for channel (err=%d)\n",
8478c2ecf20Sopenharmony_ci			rc);
8488c2ecf20Sopenharmony_ci		kfree(bt_const);
8498c2ecf20Sopenharmony_ci		return ERR_PTR(rc);
8508c2ecf20Sopenharmony_ci	}
8518c2ecf20Sopenharmony_ci
8528c2ecf20Sopenharmony_ci	/* create netdev */
8538c2ecf20Sopenharmony_ci	netdev = alloc_candev(sizeof(struct gs_can), GS_MAX_TX_URBS);
8548c2ecf20Sopenharmony_ci	if (!netdev) {
8558c2ecf20Sopenharmony_ci		dev_err(&intf->dev, "Couldn't allocate candev\n");
8568c2ecf20Sopenharmony_ci		kfree(bt_const);
8578c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
8588c2ecf20Sopenharmony_ci	}
8598c2ecf20Sopenharmony_ci
8608c2ecf20Sopenharmony_ci	dev = netdev_priv(netdev);
8618c2ecf20Sopenharmony_ci
8628c2ecf20Sopenharmony_ci	netdev->netdev_ops = &gs_usb_netdev_ops;
8638c2ecf20Sopenharmony_ci
8648c2ecf20Sopenharmony_ci	netdev->flags |= IFF_ECHO; /* we support full roundtrip echo */
8658c2ecf20Sopenharmony_ci
8668c2ecf20Sopenharmony_ci	/* dev setup */
8678c2ecf20Sopenharmony_ci	strcpy(dev->bt_const.name, "gs_usb");
8688c2ecf20Sopenharmony_ci	dev->bt_const.tseg1_min = le32_to_cpu(bt_const->tseg1_min);
8698c2ecf20Sopenharmony_ci	dev->bt_const.tseg1_max = le32_to_cpu(bt_const->tseg1_max);
8708c2ecf20Sopenharmony_ci	dev->bt_const.tseg2_min = le32_to_cpu(bt_const->tseg2_min);
8718c2ecf20Sopenharmony_ci	dev->bt_const.tseg2_max = le32_to_cpu(bt_const->tseg2_max);
8728c2ecf20Sopenharmony_ci	dev->bt_const.sjw_max = le32_to_cpu(bt_const->sjw_max);
8738c2ecf20Sopenharmony_ci	dev->bt_const.brp_min = le32_to_cpu(bt_const->brp_min);
8748c2ecf20Sopenharmony_ci	dev->bt_const.brp_max = le32_to_cpu(bt_const->brp_max);
8758c2ecf20Sopenharmony_ci	dev->bt_const.brp_inc = le32_to_cpu(bt_const->brp_inc);
8768c2ecf20Sopenharmony_ci
8778c2ecf20Sopenharmony_ci	dev->udev = interface_to_usbdev(intf);
8788c2ecf20Sopenharmony_ci	dev->iface = intf;
8798c2ecf20Sopenharmony_ci	dev->netdev = netdev;
8808c2ecf20Sopenharmony_ci	dev->channel = channel;
8818c2ecf20Sopenharmony_ci
8828c2ecf20Sopenharmony_ci	init_usb_anchor(&dev->tx_submitted);
8838c2ecf20Sopenharmony_ci	atomic_set(&dev->active_tx_urbs, 0);
8848c2ecf20Sopenharmony_ci	spin_lock_init(&dev->tx_ctx_lock);
8858c2ecf20Sopenharmony_ci	for (rc = 0; rc < GS_MAX_TX_URBS; rc++) {
8868c2ecf20Sopenharmony_ci		dev->tx_context[rc].dev = dev;
8878c2ecf20Sopenharmony_ci		dev->tx_context[rc].echo_id = GS_MAX_TX_URBS;
8888c2ecf20Sopenharmony_ci	}
8898c2ecf20Sopenharmony_ci
8908c2ecf20Sopenharmony_ci	/* can setup */
8918c2ecf20Sopenharmony_ci	dev->can.state = CAN_STATE_STOPPED;
8928c2ecf20Sopenharmony_ci	dev->can.clock.freq = le32_to_cpu(bt_const->fclk_can);
8938c2ecf20Sopenharmony_ci	dev->can.bittiming_const = &dev->bt_const;
8948c2ecf20Sopenharmony_ci	dev->can.do_set_bittiming = gs_usb_set_bittiming;
8958c2ecf20Sopenharmony_ci
8968c2ecf20Sopenharmony_ci	dev->can.ctrlmode_supported = 0;
8978c2ecf20Sopenharmony_ci
8988c2ecf20Sopenharmony_ci	feature = le32_to_cpu(bt_const->feature);
8998c2ecf20Sopenharmony_ci	if (feature & GS_CAN_FEATURE_LISTEN_ONLY)
9008c2ecf20Sopenharmony_ci		dev->can.ctrlmode_supported |= CAN_CTRLMODE_LISTENONLY;
9018c2ecf20Sopenharmony_ci
9028c2ecf20Sopenharmony_ci	if (feature & GS_CAN_FEATURE_LOOP_BACK)
9038c2ecf20Sopenharmony_ci		dev->can.ctrlmode_supported |= CAN_CTRLMODE_LOOPBACK;
9048c2ecf20Sopenharmony_ci
9058c2ecf20Sopenharmony_ci	if (feature & GS_CAN_FEATURE_TRIPLE_SAMPLE)
9068c2ecf20Sopenharmony_ci		dev->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES;
9078c2ecf20Sopenharmony_ci
9088c2ecf20Sopenharmony_ci	if (feature & GS_CAN_FEATURE_ONE_SHOT)
9098c2ecf20Sopenharmony_ci		dev->can.ctrlmode_supported |= CAN_CTRLMODE_ONE_SHOT;
9108c2ecf20Sopenharmony_ci
9118c2ecf20Sopenharmony_ci	SET_NETDEV_DEV(netdev, &intf->dev);
9128c2ecf20Sopenharmony_ci
9138c2ecf20Sopenharmony_ci	if (le32_to_cpu(dconf->sw_version) > 1)
9148c2ecf20Sopenharmony_ci		if (feature & GS_CAN_FEATURE_IDENTIFY)
9158c2ecf20Sopenharmony_ci			netdev->ethtool_ops = &gs_usb_ethtool_ops;
9168c2ecf20Sopenharmony_ci
9178c2ecf20Sopenharmony_ci	kfree(bt_const);
9188c2ecf20Sopenharmony_ci
9198c2ecf20Sopenharmony_ci	rc = register_candev(dev->netdev);
9208c2ecf20Sopenharmony_ci	if (rc) {
9218c2ecf20Sopenharmony_ci		free_candev(dev->netdev);
9228c2ecf20Sopenharmony_ci		dev_err(&intf->dev, "Couldn't register candev (err=%d)\n", rc);
9238c2ecf20Sopenharmony_ci		return ERR_PTR(rc);
9248c2ecf20Sopenharmony_ci	}
9258c2ecf20Sopenharmony_ci
9268c2ecf20Sopenharmony_ci	return dev;
9278c2ecf20Sopenharmony_ci}
9288c2ecf20Sopenharmony_ci
9298c2ecf20Sopenharmony_cistatic void gs_destroy_candev(struct gs_can *dev)
9308c2ecf20Sopenharmony_ci{
9318c2ecf20Sopenharmony_ci	unregister_candev(dev->netdev);
9328c2ecf20Sopenharmony_ci	usb_kill_anchored_urbs(&dev->tx_submitted);
9338c2ecf20Sopenharmony_ci	free_candev(dev->netdev);
9348c2ecf20Sopenharmony_ci}
9358c2ecf20Sopenharmony_ci
9368c2ecf20Sopenharmony_cistatic int gs_usb_probe(struct usb_interface *intf,
9378c2ecf20Sopenharmony_ci			const struct usb_device_id *id)
9388c2ecf20Sopenharmony_ci{
9398c2ecf20Sopenharmony_ci	struct gs_usb *dev;
9408c2ecf20Sopenharmony_ci	int rc = -ENOMEM;
9418c2ecf20Sopenharmony_ci	unsigned int icount, i;
9428c2ecf20Sopenharmony_ci	struct gs_host_config *hconf;
9438c2ecf20Sopenharmony_ci	struct gs_device_config *dconf;
9448c2ecf20Sopenharmony_ci
9458c2ecf20Sopenharmony_ci	hconf = kmalloc(sizeof(*hconf), GFP_KERNEL);
9468c2ecf20Sopenharmony_ci	if (!hconf)
9478c2ecf20Sopenharmony_ci		return -ENOMEM;
9488c2ecf20Sopenharmony_ci
9498c2ecf20Sopenharmony_ci	hconf->byte_order = cpu_to_le32(0x0000beef);
9508c2ecf20Sopenharmony_ci
9518c2ecf20Sopenharmony_ci	/* send host config */
9528c2ecf20Sopenharmony_ci	rc = usb_control_msg(interface_to_usbdev(intf),
9538c2ecf20Sopenharmony_ci			     usb_sndctrlpipe(interface_to_usbdev(intf), 0),
9548c2ecf20Sopenharmony_ci			     GS_USB_BREQ_HOST_FORMAT,
9558c2ecf20Sopenharmony_ci			     USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
9568c2ecf20Sopenharmony_ci			     1,
9578c2ecf20Sopenharmony_ci			     intf->cur_altsetting->desc.bInterfaceNumber,
9588c2ecf20Sopenharmony_ci			     hconf,
9598c2ecf20Sopenharmony_ci			     sizeof(*hconf),
9608c2ecf20Sopenharmony_ci			     1000);
9618c2ecf20Sopenharmony_ci
9628c2ecf20Sopenharmony_ci	kfree(hconf);
9638c2ecf20Sopenharmony_ci
9648c2ecf20Sopenharmony_ci	if (rc < 0) {
9658c2ecf20Sopenharmony_ci		dev_err(&intf->dev, "Couldn't send data format (err=%d)\n",
9668c2ecf20Sopenharmony_ci			rc);
9678c2ecf20Sopenharmony_ci		return rc;
9688c2ecf20Sopenharmony_ci	}
9698c2ecf20Sopenharmony_ci
9708c2ecf20Sopenharmony_ci	dconf = kmalloc(sizeof(*dconf), GFP_KERNEL);
9718c2ecf20Sopenharmony_ci	if (!dconf)
9728c2ecf20Sopenharmony_ci		return -ENOMEM;
9738c2ecf20Sopenharmony_ci
9748c2ecf20Sopenharmony_ci	/* read device config */
9758c2ecf20Sopenharmony_ci	rc = usb_control_msg(interface_to_usbdev(intf),
9768c2ecf20Sopenharmony_ci			     usb_rcvctrlpipe(interface_to_usbdev(intf), 0),
9778c2ecf20Sopenharmony_ci			     GS_USB_BREQ_DEVICE_CONFIG,
9788c2ecf20Sopenharmony_ci			     USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
9798c2ecf20Sopenharmony_ci			     1,
9808c2ecf20Sopenharmony_ci			     intf->cur_altsetting->desc.bInterfaceNumber,
9818c2ecf20Sopenharmony_ci			     dconf,
9828c2ecf20Sopenharmony_ci			     sizeof(*dconf),
9838c2ecf20Sopenharmony_ci			     1000);
9848c2ecf20Sopenharmony_ci	if (rc < 0) {
9858c2ecf20Sopenharmony_ci		dev_err(&intf->dev, "Couldn't get device config: (err=%d)\n",
9868c2ecf20Sopenharmony_ci			rc);
9878c2ecf20Sopenharmony_ci		kfree(dconf);
9888c2ecf20Sopenharmony_ci		return rc;
9898c2ecf20Sopenharmony_ci	}
9908c2ecf20Sopenharmony_ci
9918c2ecf20Sopenharmony_ci	icount = dconf->icount + 1;
9928c2ecf20Sopenharmony_ci	dev_info(&intf->dev, "Configuring for %d interfaces\n", icount);
9938c2ecf20Sopenharmony_ci
9948c2ecf20Sopenharmony_ci	if (icount > GS_MAX_INTF) {
9958c2ecf20Sopenharmony_ci		dev_err(&intf->dev,
9968c2ecf20Sopenharmony_ci			"Driver cannot handle more that %d CAN interfaces\n",
9978c2ecf20Sopenharmony_ci			GS_MAX_INTF);
9988c2ecf20Sopenharmony_ci		kfree(dconf);
9998c2ecf20Sopenharmony_ci		return -EINVAL;
10008c2ecf20Sopenharmony_ci	}
10018c2ecf20Sopenharmony_ci
10028c2ecf20Sopenharmony_ci	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
10038c2ecf20Sopenharmony_ci	if (!dev) {
10048c2ecf20Sopenharmony_ci		kfree(dconf);
10058c2ecf20Sopenharmony_ci		return -ENOMEM;
10068c2ecf20Sopenharmony_ci	}
10078c2ecf20Sopenharmony_ci
10088c2ecf20Sopenharmony_ci	init_usb_anchor(&dev->rx_submitted);
10098c2ecf20Sopenharmony_ci
10108c2ecf20Sopenharmony_ci	usb_set_intfdata(intf, dev);
10118c2ecf20Sopenharmony_ci	dev->udev = interface_to_usbdev(intf);
10128c2ecf20Sopenharmony_ci
10138c2ecf20Sopenharmony_ci	for (i = 0; i < icount; i++) {
10148c2ecf20Sopenharmony_ci		dev->canch[i] = gs_make_candev(i, intf, dconf);
10158c2ecf20Sopenharmony_ci		if (IS_ERR_OR_NULL(dev->canch[i])) {
10168c2ecf20Sopenharmony_ci			/* save error code to return later */
10178c2ecf20Sopenharmony_ci			rc = PTR_ERR(dev->canch[i]);
10188c2ecf20Sopenharmony_ci
10198c2ecf20Sopenharmony_ci			/* on failure destroy previously created candevs */
10208c2ecf20Sopenharmony_ci			icount = i;
10218c2ecf20Sopenharmony_ci			for (i = 0; i < icount; i++)
10228c2ecf20Sopenharmony_ci				gs_destroy_candev(dev->canch[i]);
10238c2ecf20Sopenharmony_ci
10248c2ecf20Sopenharmony_ci			usb_kill_anchored_urbs(&dev->rx_submitted);
10258c2ecf20Sopenharmony_ci			kfree(dconf);
10268c2ecf20Sopenharmony_ci			kfree(dev);
10278c2ecf20Sopenharmony_ci			return rc;
10288c2ecf20Sopenharmony_ci		}
10298c2ecf20Sopenharmony_ci		dev->canch[i]->parent = dev;
10308c2ecf20Sopenharmony_ci	}
10318c2ecf20Sopenharmony_ci
10328c2ecf20Sopenharmony_ci	kfree(dconf);
10338c2ecf20Sopenharmony_ci
10348c2ecf20Sopenharmony_ci	return 0;
10358c2ecf20Sopenharmony_ci}
10368c2ecf20Sopenharmony_ci
10378c2ecf20Sopenharmony_cistatic void gs_usb_disconnect(struct usb_interface *intf)
10388c2ecf20Sopenharmony_ci{
10398c2ecf20Sopenharmony_ci	unsigned i;
10408c2ecf20Sopenharmony_ci	struct gs_usb *dev = usb_get_intfdata(intf);
10418c2ecf20Sopenharmony_ci	usb_set_intfdata(intf, NULL);
10428c2ecf20Sopenharmony_ci
10438c2ecf20Sopenharmony_ci	if (!dev) {
10448c2ecf20Sopenharmony_ci		dev_err(&intf->dev, "Disconnect (nodata)\n");
10458c2ecf20Sopenharmony_ci		return;
10468c2ecf20Sopenharmony_ci	}
10478c2ecf20Sopenharmony_ci
10488c2ecf20Sopenharmony_ci	for (i = 0; i < GS_MAX_INTF; i++)
10498c2ecf20Sopenharmony_ci		if (dev->canch[i])
10508c2ecf20Sopenharmony_ci			gs_destroy_candev(dev->canch[i]);
10518c2ecf20Sopenharmony_ci
10528c2ecf20Sopenharmony_ci	usb_kill_anchored_urbs(&dev->rx_submitted);
10538c2ecf20Sopenharmony_ci	kfree(dev);
10548c2ecf20Sopenharmony_ci}
10558c2ecf20Sopenharmony_ci
10568c2ecf20Sopenharmony_cistatic const struct usb_device_id gs_usb_table[] = {
10578c2ecf20Sopenharmony_ci	{ USB_DEVICE_INTERFACE_NUMBER(USB_GSUSB_1_VENDOR_ID,
10588c2ecf20Sopenharmony_ci				      USB_GSUSB_1_PRODUCT_ID, 0) },
10598c2ecf20Sopenharmony_ci	{ USB_DEVICE_INTERFACE_NUMBER(USB_CANDLELIGHT_VENDOR_ID,
10608c2ecf20Sopenharmony_ci				      USB_CANDLELIGHT_PRODUCT_ID, 0) },
10618c2ecf20Sopenharmony_ci	{} /* Terminating entry */
10628c2ecf20Sopenharmony_ci};
10638c2ecf20Sopenharmony_ci
10648c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(usb, gs_usb_table);
10658c2ecf20Sopenharmony_ci
10668c2ecf20Sopenharmony_cistatic struct usb_driver gs_usb_driver = {
10678c2ecf20Sopenharmony_ci	.name       = "gs_usb",
10688c2ecf20Sopenharmony_ci	.probe      = gs_usb_probe,
10698c2ecf20Sopenharmony_ci	.disconnect = gs_usb_disconnect,
10708c2ecf20Sopenharmony_ci	.id_table   = gs_usb_table,
10718c2ecf20Sopenharmony_ci};
10728c2ecf20Sopenharmony_ci
10738c2ecf20Sopenharmony_cimodule_usb_driver(gs_usb_driver);
10748c2ecf20Sopenharmony_ci
10758c2ecf20Sopenharmony_ciMODULE_AUTHOR("Maximilian Schneider <mws@schneidersoft.net>");
10768c2ecf20Sopenharmony_ciMODULE_DESCRIPTION(
10778c2ecf20Sopenharmony_ci"Socket CAN device driver for Geschwister Schneider Technologie-, "
10788c2ecf20Sopenharmony_ci"Entwicklungs- und Vertriebs UG. USB2.0 to CAN interfaces\n"
10798c2ecf20Sopenharmony_ci"and bytewerk.org candleLight USB CAN interfaces.");
10808c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
1081