162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * CAN driver for EMS Dr. Thomas Wuensche CPC-USB/ARM7
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2004-2009 EMS Dr. Thomas Wuensche
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci#include <linux/ethtool.h>
862306a36Sopenharmony_ci#include <linux/signal.h>
962306a36Sopenharmony_ci#include <linux/slab.h>
1062306a36Sopenharmony_ci#include <linux/module.h>
1162306a36Sopenharmony_ci#include <linux/netdevice.h>
1262306a36Sopenharmony_ci#include <linux/usb.h>
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#include <linux/can.h>
1562306a36Sopenharmony_ci#include <linux/can/dev.h>
1662306a36Sopenharmony_ci#include <linux/can/error.h>
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ciMODULE_AUTHOR("Sebastian Haas <haas@ems-wuensche.com>");
1962306a36Sopenharmony_ciMODULE_DESCRIPTION("CAN driver for EMS Dr. Thomas Wuensche CAN/USB interfaces");
2062306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci/* Control-Values for CPC_Control() Command Subject Selection */
2362306a36Sopenharmony_ci#define CONTR_CAN_MESSAGE 0x04
2462306a36Sopenharmony_ci#define CONTR_CAN_STATE   0x0C
2562306a36Sopenharmony_ci#define CONTR_BUS_ERROR   0x1C
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci/* Control Command Actions */
2862306a36Sopenharmony_ci#define CONTR_CONT_OFF 0
2962306a36Sopenharmony_ci#define CONTR_CONT_ON  1
3062306a36Sopenharmony_ci#define CONTR_ONCE     2
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci/* Messages from CPC to PC */
3362306a36Sopenharmony_ci#define CPC_MSG_TYPE_CAN_FRAME       1  /* CAN data frame */
3462306a36Sopenharmony_ci#define CPC_MSG_TYPE_RTR_FRAME       8  /* CAN remote frame */
3562306a36Sopenharmony_ci#define CPC_MSG_TYPE_CAN_PARAMS      12 /* Actual CAN parameters */
3662306a36Sopenharmony_ci#define CPC_MSG_TYPE_CAN_STATE       14 /* CAN state message */
3762306a36Sopenharmony_ci#define CPC_MSG_TYPE_EXT_CAN_FRAME   16 /* Extended CAN data frame */
3862306a36Sopenharmony_ci#define CPC_MSG_TYPE_EXT_RTR_FRAME   17 /* Extended remote frame */
3962306a36Sopenharmony_ci#define CPC_MSG_TYPE_CONTROL         19 /* change interface behavior */
4062306a36Sopenharmony_ci#define CPC_MSG_TYPE_CONFIRM         20 /* command processed confirmation */
4162306a36Sopenharmony_ci#define CPC_MSG_TYPE_OVERRUN         21 /* overrun events */
4262306a36Sopenharmony_ci#define CPC_MSG_TYPE_CAN_FRAME_ERROR 23 /* detected bus errors */
4362306a36Sopenharmony_ci#define CPC_MSG_TYPE_ERR_COUNTER     25 /* RX/TX error counter */
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci/* Messages from the PC to the CPC interface  */
4662306a36Sopenharmony_ci#define CPC_CMD_TYPE_CAN_FRAME     1   /* CAN data frame */
4762306a36Sopenharmony_ci#define CPC_CMD_TYPE_CONTROL       3   /* control of interface behavior */
4862306a36Sopenharmony_ci#define CPC_CMD_TYPE_CAN_PARAMS    6   /* set CAN parameters */
4962306a36Sopenharmony_ci#define CPC_CMD_TYPE_RTR_FRAME     13  /* CAN remote frame */
5062306a36Sopenharmony_ci#define CPC_CMD_TYPE_CAN_STATE     14  /* CAN state message */
5162306a36Sopenharmony_ci#define CPC_CMD_TYPE_EXT_CAN_FRAME 15  /* Extended CAN data frame */
5262306a36Sopenharmony_ci#define CPC_CMD_TYPE_EXT_RTR_FRAME 16  /* Extended CAN remote frame */
5362306a36Sopenharmony_ci#define CPC_CMD_TYPE_CAN_EXIT      200 /* exit the CAN */
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci#define CPC_CMD_TYPE_INQ_ERR_COUNTER 25 /* request the CAN error counters */
5662306a36Sopenharmony_ci#define CPC_CMD_TYPE_CLEAR_MSG_QUEUE 8  /* clear CPC_MSG queue */
5762306a36Sopenharmony_ci#define CPC_CMD_TYPE_CLEAR_CMD_QUEUE 28 /* clear CPC_CMD queue */
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci#define CPC_CC_TYPE_SJA1000 2 /* Philips basic CAN controller */
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci#define CPC_CAN_ECODE_ERRFRAME 0x01 /* Ecode type */
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci/* Overrun types */
6462306a36Sopenharmony_ci#define CPC_OVR_EVENT_CAN       0x01
6562306a36Sopenharmony_ci#define CPC_OVR_EVENT_CANSTATE  0x02
6662306a36Sopenharmony_ci#define CPC_OVR_EVENT_BUSERROR  0x04
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci/*
6962306a36Sopenharmony_ci * If the CAN controller lost a message we indicate it with the highest bit
7062306a36Sopenharmony_ci * set in the count field.
7162306a36Sopenharmony_ci */
7262306a36Sopenharmony_ci#define CPC_OVR_HW 0x80
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci/* Size of the "struct ems_cpc_msg" without the union */
7562306a36Sopenharmony_ci#define CPC_MSG_HEADER_LEN   11
7662306a36Sopenharmony_ci#define CPC_CAN_MSG_MIN_SIZE 5
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci/* Define these values to match your devices */
7962306a36Sopenharmony_ci#define USB_CPCUSB_VENDOR_ID 0x12D6
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci#define USB_CPCUSB_ARM7_PRODUCT_ID 0x0444
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci/* Mode register NXP LPC2119/SJA1000 CAN Controller */
8462306a36Sopenharmony_ci#define SJA1000_MOD_NORMAL 0x00
8562306a36Sopenharmony_ci#define SJA1000_MOD_RM     0x01
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci/* ECC register NXP LPC2119/SJA1000 CAN Controller */
8862306a36Sopenharmony_ci#define SJA1000_ECC_SEG   0x1F
8962306a36Sopenharmony_ci#define SJA1000_ECC_DIR   0x20
9062306a36Sopenharmony_ci#define SJA1000_ECC_ERR   0x06
9162306a36Sopenharmony_ci#define SJA1000_ECC_BIT   0x00
9262306a36Sopenharmony_ci#define SJA1000_ECC_FORM  0x40
9362306a36Sopenharmony_ci#define SJA1000_ECC_STUFF 0x80
9462306a36Sopenharmony_ci#define SJA1000_ECC_MASK  0xc0
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci/* Status register content */
9762306a36Sopenharmony_ci#define SJA1000_SR_BS 0x80
9862306a36Sopenharmony_ci#define SJA1000_SR_ES 0x40
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci#define SJA1000_DEFAULT_OUTPUT_CONTROL 0xDA
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci/*
10362306a36Sopenharmony_ci * The device actually uses a 16MHz clock to generate the CAN clock
10462306a36Sopenharmony_ci * but it expects SJA1000 bit settings based on 8MHz (is internally
10562306a36Sopenharmony_ci * converted).
10662306a36Sopenharmony_ci */
10762306a36Sopenharmony_ci#define EMS_USB_ARM7_CLOCK 8000000
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci#define CPC_TX_QUEUE_TRIGGER_LOW	25
11062306a36Sopenharmony_ci#define CPC_TX_QUEUE_TRIGGER_HIGH	35
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci/*
11362306a36Sopenharmony_ci * CAN-Message representation in a CPC_MSG. Message object type is
11462306a36Sopenharmony_ci * CPC_MSG_TYPE_CAN_FRAME or CPC_MSG_TYPE_RTR_FRAME or
11562306a36Sopenharmony_ci * CPC_MSG_TYPE_EXT_CAN_FRAME or CPC_MSG_TYPE_EXT_RTR_FRAME.
11662306a36Sopenharmony_ci */
11762306a36Sopenharmony_cistruct cpc_can_msg {
11862306a36Sopenharmony_ci	__le32 id;
11962306a36Sopenharmony_ci	u8 length;
12062306a36Sopenharmony_ci	u8 msg[8];
12162306a36Sopenharmony_ci};
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci/* Representation of the CAN parameters for the SJA1000 controller */
12462306a36Sopenharmony_cistruct cpc_sja1000_params {
12562306a36Sopenharmony_ci	u8 mode;
12662306a36Sopenharmony_ci	u8 acc_code0;
12762306a36Sopenharmony_ci	u8 acc_code1;
12862306a36Sopenharmony_ci	u8 acc_code2;
12962306a36Sopenharmony_ci	u8 acc_code3;
13062306a36Sopenharmony_ci	u8 acc_mask0;
13162306a36Sopenharmony_ci	u8 acc_mask1;
13262306a36Sopenharmony_ci	u8 acc_mask2;
13362306a36Sopenharmony_ci	u8 acc_mask3;
13462306a36Sopenharmony_ci	u8 btr0;
13562306a36Sopenharmony_ci	u8 btr1;
13662306a36Sopenharmony_ci	u8 outp_contr;
13762306a36Sopenharmony_ci};
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci/* CAN params message representation */
14062306a36Sopenharmony_cistruct cpc_can_params {
14162306a36Sopenharmony_ci	u8 cc_type;
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	/* Will support M16C CAN controller in the future */
14462306a36Sopenharmony_ci	union {
14562306a36Sopenharmony_ci		struct cpc_sja1000_params sja1000;
14662306a36Sopenharmony_ci	} cc_params;
14762306a36Sopenharmony_ci};
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci/* Structure for confirmed message handling */
15062306a36Sopenharmony_cistruct cpc_confirm {
15162306a36Sopenharmony_ci	u8 error; /* error code */
15262306a36Sopenharmony_ci};
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci/* Structure for overrun conditions */
15562306a36Sopenharmony_cistruct cpc_overrun {
15662306a36Sopenharmony_ci	u8 event;
15762306a36Sopenharmony_ci	u8 count;
15862306a36Sopenharmony_ci};
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci/* SJA1000 CAN errors (compatible to NXP LPC2119) */
16162306a36Sopenharmony_cistruct cpc_sja1000_can_error {
16262306a36Sopenharmony_ci	u8 ecc;
16362306a36Sopenharmony_ci	u8 rxerr;
16462306a36Sopenharmony_ci	u8 txerr;
16562306a36Sopenharmony_ci};
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci/* structure for CAN error conditions */
16862306a36Sopenharmony_cistruct cpc_can_error {
16962306a36Sopenharmony_ci	u8 ecode;
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	struct {
17262306a36Sopenharmony_ci		u8 cc_type;
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci		/* Other controllers may also provide error code capture regs */
17562306a36Sopenharmony_ci		union {
17662306a36Sopenharmony_ci			struct cpc_sja1000_can_error sja1000;
17762306a36Sopenharmony_ci		} regs;
17862306a36Sopenharmony_ci	} cc;
17962306a36Sopenharmony_ci};
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci/*
18262306a36Sopenharmony_ci * Structure containing RX/TX error counter. This structure is used to request
18362306a36Sopenharmony_ci * the values of the CAN controllers TX and RX error counter.
18462306a36Sopenharmony_ci */
18562306a36Sopenharmony_cistruct cpc_can_err_counter {
18662306a36Sopenharmony_ci	u8 rx;
18762306a36Sopenharmony_ci	u8 tx;
18862306a36Sopenharmony_ci};
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci/* Main message type used between library and application */
19162306a36Sopenharmony_cistruct __packed ems_cpc_msg {
19262306a36Sopenharmony_ci	u8 type;	/* type of message */
19362306a36Sopenharmony_ci	u8 length;	/* length of data within union 'msg' */
19462306a36Sopenharmony_ci	u8 msgid;	/* confirmation handle */
19562306a36Sopenharmony_ci	__le32 ts_sec;	/* timestamp in seconds */
19662306a36Sopenharmony_ci	__le32 ts_nsec;	/* timestamp in nano seconds */
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	union __packed {
19962306a36Sopenharmony_ci		u8 generic[64];
20062306a36Sopenharmony_ci		struct cpc_can_msg can_msg;
20162306a36Sopenharmony_ci		struct cpc_can_params can_params;
20262306a36Sopenharmony_ci		struct cpc_confirm confirmation;
20362306a36Sopenharmony_ci		struct cpc_overrun overrun;
20462306a36Sopenharmony_ci		struct cpc_can_error error;
20562306a36Sopenharmony_ci		struct cpc_can_err_counter err_counter;
20662306a36Sopenharmony_ci		u8 can_state;
20762306a36Sopenharmony_ci	} msg;
20862306a36Sopenharmony_ci};
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci/*
21162306a36Sopenharmony_ci * Table of devices that work with this driver
21262306a36Sopenharmony_ci * NOTE: This driver supports only CPC-USB/ARM7 (LPC2119) yet.
21362306a36Sopenharmony_ci */
21462306a36Sopenharmony_cistatic struct usb_device_id ems_usb_table[] = {
21562306a36Sopenharmony_ci	{USB_DEVICE(USB_CPCUSB_VENDOR_ID, USB_CPCUSB_ARM7_PRODUCT_ID)},
21662306a36Sopenharmony_ci	{} /* Terminating entry */
21762306a36Sopenharmony_ci};
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ciMODULE_DEVICE_TABLE(usb, ems_usb_table);
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci#define RX_BUFFER_SIZE      64
22262306a36Sopenharmony_ci#define CPC_HEADER_SIZE     4
22362306a36Sopenharmony_ci#define INTR_IN_BUFFER_SIZE 4
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci#define MAX_RX_URBS 10
22662306a36Sopenharmony_ci#define MAX_TX_URBS 10
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_cistruct ems_usb;
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_cistruct ems_tx_urb_context {
23162306a36Sopenharmony_ci	struct ems_usb *dev;
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci	u32 echo_index;
23462306a36Sopenharmony_ci};
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_cistruct ems_usb {
23762306a36Sopenharmony_ci	struct can_priv can; /* must be the first member */
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci	struct sk_buff *echo_skb[MAX_TX_URBS];
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci	struct usb_device *udev;
24262306a36Sopenharmony_ci	struct net_device *netdev;
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	atomic_t active_tx_urbs;
24562306a36Sopenharmony_ci	struct usb_anchor tx_submitted;
24662306a36Sopenharmony_ci	struct ems_tx_urb_context tx_contexts[MAX_TX_URBS];
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci	struct usb_anchor rx_submitted;
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci	struct urb *intr_urb;
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci	u8 *tx_msg_buffer;
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci	u8 *intr_in_buffer;
25562306a36Sopenharmony_ci	unsigned int free_slots; /* remember number of available slots */
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci	struct ems_cpc_msg active_params; /* active controller parameters */
25862306a36Sopenharmony_ci	void *rxbuf[MAX_RX_URBS];
25962306a36Sopenharmony_ci	dma_addr_t rxbuf_dma[MAX_RX_URBS];
26062306a36Sopenharmony_ci};
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_cistatic void ems_usb_read_interrupt_callback(struct urb *urb)
26362306a36Sopenharmony_ci{
26462306a36Sopenharmony_ci	struct ems_usb *dev = urb->context;
26562306a36Sopenharmony_ci	struct net_device *netdev = dev->netdev;
26662306a36Sopenharmony_ci	int err;
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci	if (!netif_device_present(netdev))
26962306a36Sopenharmony_ci		return;
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci	switch (urb->status) {
27262306a36Sopenharmony_ci	case 0:
27362306a36Sopenharmony_ci		dev->free_slots = dev->intr_in_buffer[1];
27462306a36Sopenharmony_ci		if (dev->free_slots > CPC_TX_QUEUE_TRIGGER_HIGH &&
27562306a36Sopenharmony_ci		    netif_queue_stopped(netdev))
27662306a36Sopenharmony_ci			netif_wake_queue(netdev);
27762306a36Sopenharmony_ci		break;
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_ci	case -ECONNRESET: /* unlink */
28062306a36Sopenharmony_ci	case -ENOENT:
28162306a36Sopenharmony_ci	case -EPIPE:
28262306a36Sopenharmony_ci	case -EPROTO:
28362306a36Sopenharmony_ci	case -ESHUTDOWN:
28462306a36Sopenharmony_ci		return;
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_ci	default:
28762306a36Sopenharmony_ci		netdev_info(netdev, "Rx interrupt aborted %d\n", urb->status);
28862306a36Sopenharmony_ci		break;
28962306a36Sopenharmony_ci	}
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci	err = usb_submit_urb(urb, GFP_ATOMIC);
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci	if (err == -ENODEV)
29462306a36Sopenharmony_ci		netif_device_detach(netdev);
29562306a36Sopenharmony_ci	else if (err)
29662306a36Sopenharmony_ci		netdev_err(netdev, "failed resubmitting intr urb: %d\n", err);
29762306a36Sopenharmony_ci}
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_cistatic void ems_usb_rx_can_msg(struct ems_usb *dev, struct ems_cpc_msg *msg)
30062306a36Sopenharmony_ci{
30162306a36Sopenharmony_ci	struct can_frame *cf;
30262306a36Sopenharmony_ci	struct sk_buff *skb;
30362306a36Sopenharmony_ci	int i;
30462306a36Sopenharmony_ci	struct net_device_stats *stats = &dev->netdev->stats;
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci	skb = alloc_can_skb(dev->netdev, &cf);
30762306a36Sopenharmony_ci	if (skb == NULL)
30862306a36Sopenharmony_ci		return;
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ci	cf->can_id = le32_to_cpu(msg->msg.can_msg.id);
31162306a36Sopenharmony_ci	cf->len = can_cc_dlc2len(msg->msg.can_msg.length & 0xF);
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci	if (msg->type == CPC_MSG_TYPE_EXT_CAN_FRAME ||
31462306a36Sopenharmony_ci	    msg->type == CPC_MSG_TYPE_EXT_RTR_FRAME)
31562306a36Sopenharmony_ci		cf->can_id |= CAN_EFF_FLAG;
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci	if (msg->type == CPC_MSG_TYPE_RTR_FRAME ||
31862306a36Sopenharmony_ci	    msg->type == CPC_MSG_TYPE_EXT_RTR_FRAME) {
31962306a36Sopenharmony_ci		cf->can_id |= CAN_RTR_FLAG;
32062306a36Sopenharmony_ci	} else {
32162306a36Sopenharmony_ci		for (i = 0; i < cf->len; i++)
32262306a36Sopenharmony_ci			cf->data[i] = msg->msg.can_msg.msg[i];
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci		stats->rx_bytes += cf->len;
32562306a36Sopenharmony_ci	}
32662306a36Sopenharmony_ci	stats->rx_packets++;
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ci	netif_rx(skb);
32962306a36Sopenharmony_ci}
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_cistatic void ems_usb_rx_err(struct ems_usb *dev, struct ems_cpc_msg *msg)
33262306a36Sopenharmony_ci{
33362306a36Sopenharmony_ci	struct can_frame *cf;
33462306a36Sopenharmony_ci	struct sk_buff *skb;
33562306a36Sopenharmony_ci	struct net_device_stats *stats = &dev->netdev->stats;
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci	skb = alloc_can_err_skb(dev->netdev, &cf);
33862306a36Sopenharmony_ci	if (skb == NULL)
33962306a36Sopenharmony_ci		return;
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci	if (msg->type == CPC_MSG_TYPE_CAN_STATE) {
34262306a36Sopenharmony_ci		u8 state = msg->msg.can_state;
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci		if (state & SJA1000_SR_BS) {
34562306a36Sopenharmony_ci			dev->can.state = CAN_STATE_BUS_OFF;
34662306a36Sopenharmony_ci			cf->can_id |= CAN_ERR_BUSOFF;
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci			dev->can.can_stats.bus_off++;
34962306a36Sopenharmony_ci			can_bus_off(dev->netdev);
35062306a36Sopenharmony_ci		} else if (state & SJA1000_SR_ES) {
35162306a36Sopenharmony_ci			dev->can.state = CAN_STATE_ERROR_WARNING;
35262306a36Sopenharmony_ci			dev->can.can_stats.error_warning++;
35362306a36Sopenharmony_ci		} else {
35462306a36Sopenharmony_ci			dev->can.state = CAN_STATE_ERROR_ACTIVE;
35562306a36Sopenharmony_ci			dev->can.can_stats.error_passive++;
35662306a36Sopenharmony_ci		}
35762306a36Sopenharmony_ci	} else if (msg->type == CPC_MSG_TYPE_CAN_FRAME_ERROR) {
35862306a36Sopenharmony_ci		u8 ecc = msg->msg.error.cc.regs.sja1000.ecc;
35962306a36Sopenharmony_ci		u8 txerr = msg->msg.error.cc.regs.sja1000.txerr;
36062306a36Sopenharmony_ci		u8 rxerr = msg->msg.error.cc.regs.sja1000.rxerr;
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ci		/* bus error interrupt */
36362306a36Sopenharmony_ci		dev->can.can_stats.bus_error++;
36462306a36Sopenharmony_ci		stats->rx_errors++;
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci		cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_ci		switch (ecc & SJA1000_ECC_MASK) {
36962306a36Sopenharmony_ci		case SJA1000_ECC_BIT:
37062306a36Sopenharmony_ci			cf->data[2] |= CAN_ERR_PROT_BIT;
37162306a36Sopenharmony_ci			break;
37262306a36Sopenharmony_ci		case SJA1000_ECC_FORM:
37362306a36Sopenharmony_ci			cf->data[2] |= CAN_ERR_PROT_FORM;
37462306a36Sopenharmony_ci			break;
37562306a36Sopenharmony_ci		case SJA1000_ECC_STUFF:
37662306a36Sopenharmony_ci			cf->data[2] |= CAN_ERR_PROT_STUFF;
37762306a36Sopenharmony_ci			break;
37862306a36Sopenharmony_ci		default:
37962306a36Sopenharmony_ci			cf->data[3] = ecc & SJA1000_ECC_SEG;
38062306a36Sopenharmony_ci			break;
38162306a36Sopenharmony_ci		}
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci		/* Error occurred during transmission? */
38462306a36Sopenharmony_ci		if ((ecc & SJA1000_ECC_DIR) == 0)
38562306a36Sopenharmony_ci			cf->data[2] |= CAN_ERR_PROT_TX;
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_ci		if (dev->can.state == CAN_STATE_ERROR_WARNING ||
38862306a36Sopenharmony_ci		    dev->can.state == CAN_STATE_ERROR_PASSIVE) {
38962306a36Sopenharmony_ci			cf->can_id |= CAN_ERR_CRTL;
39062306a36Sopenharmony_ci			cf->data[1] = (txerr > rxerr) ?
39162306a36Sopenharmony_ci			    CAN_ERR_CRTL_TX_PASSIVE : CAN_ERR_CRTL_RX_PASSIVE;
39262306a36Sopenharmony_ci		}
39362306a36Sopenharmony_ci	} else if (msg->type == CPC_MSG_TYPE_OVERRUN) {
39462306a36Sopenharmony_ci		cf->can_id |= CAN_ERR_CRTL;
39562306a36Sopenharmony_ci		cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci		stats->rx_over_errors++;
39862306a36Sopenharmony_ci		stats->rx_errors++;
39962306a36Sopenharmony_ci	}
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_ci	netif_rx(skb);
40262306a36Sopenharmony_ci}
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci/*
40562306a36Sopenharmony_ci * callback for bulk IN urb
40662306a36Sopenharmony_ci */
40762306a36Sopenharmony_cistatic void ems_usb_read_bulk_callback(struct urb *urb)
40862306a36Sopenharmony_ci{
40962306a36Sopenharmony_ci	struct ems_usb *dev = urb->context;
41062306a36Sopenharmony_ci	struct net_device *netdev;
41162306a36Sopenharmony_ci	int retval;
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_ci	netdev = dev->netdev;
41462306a36Sopenharmony_ci
41562306a36Sopenharmony_ci	if (!netif_device_present(netdev))
41662306a36Sopenharmony_ci		return;
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ci	switch (urb->status) {
41962306a36Sopenharmony_ci	case 0: /* success */
42062306a36Sopenharmony_ci		break;
42162306a36Sopenharmony_ci
42262306a36Sopenharmony_ci	case -ENOENT:
42362306a36Sopenharmony_ci		return;
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci	default:
42662306a36Sopenharmony_ci		netdev_info(netdev, "Rx URB aborted (%d)\n", urb->status);
42762306a36Sopenharmony_ci		goto resubmit_urb;
42862306a36Sopenharmony_ci	}
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_ci	if (urb->actual_length > CPC_HEADER_SIZE) {
43162306a36Sopenharmony_ci		struct ems_cpc_msg *msg;
43262306a36Sopenharmony_ci		u8 *ibuf = urb->transfer_buffer;
43362306a36Sopenharmony_ci		u8 msg_count, start;
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_ci		msg_count = ibuf[0] & ~0x80;
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_ci		start = CPC_HEADER_SIZE;
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci		while (msg_count) {
44062306a36Sopenharmony_ci			msg = (struct ems_cpc_msg *)&ibuf[start];
44162306a36Sopenharmony_ci
44262306a36Sopenharmony_ci			switch (msg->type) {
44362306a36Sopenharmony_ci			case CPC_MSG_TYPE_CAN_STATE:
44462306a36Sopenharmony_ci				/* Process CAN state changes */
44562306a36Sopenharmony_ci				ems_usb_rx_err(dev, msg);
44662306a36Sopenharmony_ci				break;
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_ci			case CPC_MSG_TYPE_CAN_FRAME:
44962306a36Sopenharmony_ci			case CPC_MSG_TYPE_EXT_CAN_FRAME:
45062306a36Sopenharmony_ci			case CPC_MSG_TYPE_RTR_FRAME:
45162306a36Sopenharmony_ci			case CPC_MSG_TYPE_EXT_RTR_FRAME:
45262306a36Sopenharmony_ci				ems_usb_rx_can_msg(dev, msg);
45362306a36Sopenharmony_ci				break;
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_ci			case CPC_MSG_TYPE_CAN_FRAME_ERROR:
45662306a36Sopenharmony_ci				/* Process errorframe */
45762306a36Sopenharmony_ci				ems_usb_rx_err(dev, msg);
45862306a36Sopenharmony_ci				break;
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci			case CPC_MSG_TYPE_OVERRUN:
46162306a36Sopenharmony_ci				/* Message lost while receiving */
46262306a36Sopenharmony_ci				ems_usb_rx_err(dev, msg);
46362306a36Sopenharmony_ci				break;
46462306a36Sopenharmony_ci			}
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci			start += CPC_MSG_HEADER_LEN + msg->length;
46762306a36Sopenharmony_ci			msg_count--;
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_ci			if (start > urb->transfer_buffer_length) {
47062306a36Sopenharmony_ci				netdev_err(netdev, "format error\n");
47162306a36Sopenharmony_ci				break;
47262306a36Sopenharmony_ci			}
47362306a36Sopenharmony_ci		}
47462306a36Sopenharmony_ci	}
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ciresubmit_urb:
47762306a36Sopenharmony_ci	usb_fill_bulk_urb(urb, dev->udev, usb_rcvbulkpipe(dev->udev, 2),
47862306a36Sopenharmony_ci			  urb->transfer_buffer, RX_BUFFER_SIZE,
47962306a36Sopenharmony_ci			  ems_usb_read_bulk_callback, dev);
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ci	retval = usb_submit_urb(urb, GFP_ATOMIC);
48262306a36Sopenharmony_ci
48362306a36Sopenharmony_ci	if (retval == -ENODEV)
48462306a36Sopenharmony_ci		netif_device_detach(netdev);
48562306a36Sopenharmony_ci	else if (retval)
48662306a36Sopenharmony_ci		netdev_err(netdev,
48762306a36Sopenharmony_ci			   "failed resubmitting read bulk urb: %d\n", retval);
48862306a36Sopenharmony_ci}
48962306a36Sopenharmony_ci
49062306a36Sopenharmony_ci/*
49162306a36Sopenharmony_ci * callback for bulk IN urb
49262306a36Sopenharmony_ci */
49362306a36Sopenharmony_cistatic void ems_usb_write_bulk_callback(struct urb *urb)
49462306a36Sopenharmony_ci{
49562306a36Sopenharmony_ci	struct ems_tx_urb_context *context = urb->context;
49662306a36Sopenharmony_ci	struct ems_usb *dev;
49762306a36Sopenharmony_ci	struct net_device *netdev;
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_ci	BUG_ON(!context);
50062306a36Sopenharmony_ci
50162306a36Sopenharmony_ci	dev = context->dev;
50262306a36Sopenharmony_ci	netdev = dev->netdev;
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ci	/* free up our allocated buffer */
50562306a36Sopenharmony_ci	usb_free_coherent(urb->dev, urb->transfer_buffer_length,
50662306a36Sopenharmony_ci			  urb->transfer_buffer, urb->transfer_dma);
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_ci	atomic_dec(&dev->active_tx_urbs);
50962306a36Sopenharmony_ci
51062306a36Sopenharmony_ci	if (!netif_device_present(netdev))
51162306a36Sopenharmony_ci		return;
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci	if (urb->status)
51462306a36Sopenharmony_ci		netdev_info(netdev, "Tx URB aborted (%d)\n", urb->status);
51562306a36Sopenharmony_ci
51662306a36Sopenharmony_ci	netif_trans_update(netdev);
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_ci	/* transmission complete interrupt */
51962306a36Sopenharmony_ci	netdev->stats.tx_packets++;
52062306a36Sopenharmony_ci	netdev->stats.tx_bytes += can_get_echo_skb(netdev, context->echo_index,
52162306a36Sopenharmony_ci						   NULL);
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ci	/* Release context */
52462306a36Sopenharmony_ci	context->echo_index = MAX_TX_URBS;
52562306a36Sopenharmony_ci
52662306a36Sopenharmony_ci}
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_ci/*
52962306a36Sopenharmony_ci * Send the given CPC command synchronously
53062306a36Sopenharmony_ci */
53162306a36Sopenharmony_cistatic int ems_usb_command_msg(struct ems_usb *dev, struct ems_cpc_msg *msg)
53262306a36Sopenharmony_ci{
53362306a36Sopenharmony_ci	int actual_length;
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ci	/* Copy payload */
53662306a36Sopenharmony_ci	memcpy(&dev->tx_msg_buffer[CPC_HEADER_SIZE], msg,
53762306a36Sopenharmony_ci	       msg->length + CPC_MSG_HEADER_LEN);
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_ci	/* Clear header */
54062306a36Sopenharmony_ci	memset(&dev->tx_msg_buffer[0], 0, CPC_HEADER_SIZE);
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_ci	return usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 2),
54362306a36Sopenharmony_ci			    &dev->tx_msg_buffer[0],
54462306a36Sopenharmony_ci			    msg->length + CPC_MSG_HEADER_LEN + CPC_HEADER_SIZE,
54562306a36Sopenharmony_ci			    &actual_length, 1000);
54662306a36Sopenharmony_ci}
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_ci/*
54962306a36Sopenharmony_ci * Change CAN controllers' mode register
55062306a36Sopenharmony_ci */
55162306a36Sopenharmony_cistatic int ems_usb_write_mode(struct ems_usb *dev, u8 mode)
55262306a36Sopenharmony_ci{
55362306a36Sopenharmony_ci	dev->active_params.msg.can_params.cc_params.sja1000.mode = mode;
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_ci	return ems_usb_command_msg(dev, &dev->active_params);
55662306a36Sopenharmony_ci}
55762306a36Sopenharmony_ci
55862306a36Sopenharmony_ci/*
55962306a36Sopenharmony_ci * Send a CPC_Control command to change behaviour when interface receives a CAN
56062306a36Sopenharmony_ci * message, bus error or CAN state changed notifications.
56162306a36Sopenharmony_ci */
56262306a36Sopenharmony_cistatic int ems_usb_control_cmd(struct ems_usb *dev, u8 val)
56362306a36Sopenharmony_ci{
56462306a36Sopenharmony_ci	struct ems_cpc_msg cmd;
56562306a36Sopenharmony_ci
56662306a36Sopenharmony_ci	cmd.type = CPC_CMD_TYPE_CONTROL;
56762306a36Sopenharmony_ci	cmd.length = CPC_MSG_HEADER_LEN + 1;
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci	cmd.msgid = 0;
57062306a36Sopenharmony_ci
57162306a36Sopenharmony_ci	cmd.msg.generic[0] = val;
57262306a36Sopenharmony_ci
57362306a36Sopenharmony_ci	return ems_usb_command_msg(dev, &cmd);
57462306a36Sopenharmony_ci}
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_ci/*
57762306a36Sopenharmony_ci * Start interface
57862306a36Sopenharmony_ci */
57962306a36Sopenharmony_cistatic int ems_usb_start(struct ems_usb *dev)
58062306a36Sopenharmony_ci{
58162306a36Sopenharmony_ci	struct net_device *netdev = dev->netdev;
58262306a36Sopenharmony_ci	int err, i;
58362306a36Sopenharmony_ci
58462306a36Sopenharmony_ci	dev->intr_in_buffer[0] = 0;
58562306a36Sopenharmony_ci	dev->free_slots = 50; /* initial size */
58662306a36Sopenharmony_ci
58762306a36Sopenharmony_ci	for (i = 0; i < MAX_RX_URBS; i++) {
58862306a36Sopenharmony_ci		struct urb *urb = NULL;
58962306a36Sopenharmony_ci		u8 *buf = NULL;
59062306a36Sopenharmony_ci		dma_addr_t buf_dma;
59162306a36Sopenharmony_ci
59262306a36Sopenharmony_ci		/* create a URB, and a buffer for it */
59362306a36Sopenharmony_ci		urb = usb_alloc_urb(0, GFP_KERNEL);
59462306a36Sopenharmony_ci		if (!urb) {
59562306a36Sopenharmony_ci			err = -ENOMEM;
59662306a36Sopenharmony_ci			break;
59762306a36Sopenharmony_ci		}
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_ci		buf = usb_alloc_coherent(dev->udev, RX_BUFFER_SIZE, GFP_KERNEL,
60062306a36Sopenharmony_ci					 &buf_dma);
60162306a36Sopenharmony_ci		if (!buf) {
60262306a36Sopenharmony_ci			netdev_err(netdev, "No memory left for USB buffer\n");
60362306a36Sopenharmony_ci			usb_free_urb(urb);
60462306a36Sopenharmony_ci			err = -ENOMEM;
60562306a36Sopenharmony_ci			break;
60662306a36Sopenharmony_ci		}
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_ci		urb->transfer_dma = buf_dma;
60962306a36Sopenharmony_ci
61062306a36Sopenharmony_ci		usb_fill_bulk_urb(urb, dev->udev, usb_rcvbulkpipe(dev->udev, 2),
61162306a36Sopenharmony_ci				  buf, RX_BUFFER_SIZE,
61262306a36Sopenharmony_ci				  ems_usb_read_bulk_callback, dev);
61362306a36Sopenharmony_ci		urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
61462306a36Sopenharmony_ci		usb_anchor_urb(urb, &dev->rx_submitted);
61562306a36Sopenharmony_ci
61662306a36Sopenharmony_ci		err = usb_submit_urb(urb, GFP_KERNEL);
61762306a36Sopenharmony_ci		if (err) {
61862306a36Sopenharmony_ci			usb_unanchor_urb(urb);
61962306a36Sopenharmony_ci			usb_free_coherent(dev->udev, RX_BUFFER_SIZE, buf,
62062306a36Sopenharmony_ci					  urb->transfer_dma);
62162306a36Sopenharmony_ci			usb_free_urb(urb);
62262306a36Sopenharmony_ci			break;
62362306a36Sopenharmony_ci		}
62462306a36Sopenharmony_ci
62562306a36Sopenharmony_ci		dev->rxbuf[i] = buf;
62662306a36Sopenharmony_ci		dev->rxbuf_dma[i] = buf_dma;
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_ci		/* Drop reference, USB core will take care of freeing it */
62962306a36Sopenharmony_ci		usb_free_urb(urb);
63062306a36Sopenharmony_ci	}
63162306a36Sopenharmony_ci
63262306a36Sopenharmony_ci	/* Did we submit any URBs */
63362306a36Sopenharmony_ci	if (i == 0) {
63462306a36Sopenharmony_ci		netdev_warn(netdev, "couldn't setup read URBs\n");
63562306a36Sopenharmony_ci		return err;
63662306a36Sopenharmony_ci	}
63762306a36Sopenharmony_ci
63862306a36Sopenharmony_ci	/* Warn if we've couldn't transmit all the URBs */
63962306a36Sopenharmony_ci	if (i < MAX_RX_URBS)
64062306a36Sopenharmony_ci		netdev_warn(netdev, "rx performance may be slow\n");
64162306a36Sopenharmony_ci
64262306a36Sopenharmony_ci	/* Setup and start interrupt URB */
64362306a36Sopenharmony_ci	usb_fill_int_urb(dev->intr_urb, dev->udev,
64462306a36Sopenharmony_ci			 usb_rcvintpipe(dev->udev, 1),
64562306a36Sopenharmony_ci			 dev->intr_in_buffer,
64662306a36Sopenharmony_ci			 INTR_IN_BUFFER_SIZE,
64762306a36Sopenharmony_ci			 ems_usb_read_interrupt_callback, dev, 1);
64862306a36Sopenharmony_ci
64962306a36Sopenharmony_ci	err = usb_submit_urb(dev->intr_urb, GFP_KERNEL);
65062306a36Sopenharmony_ci	if (err) {
65162306a36Sopenharmony_ci		netdev_warn(netdev, "intr URB submit failed: %d\n", err);
65262306a36Sopenharmony_ci
65362306a36Sopenharmony_ci		return err;
65462306a36Sopenharmony_ci	}
65562306a36Sopenharmony_ci
65662306a36Sopenharmony_ci	/* CPC-USB will transfer received message to host */
65762306a36Sopenharmony_ci	err = ems_usb_control_cmd(dev, CONTR_CAN_MESSAGE | CONTR_CONT_ON);
65862306a36Sopenharmony_ci	if (err)
65962306a36Sopenharmony_ci		goto failed;
66062306a36Sopenharmony_ci
66162306a36Sopenharmony_ci	/* CPC-USB will transfer CAN state changes to host */
66262306a36Sopenharmony_ci	err = ems_usb_control_cmd(dev, CONTR_CAN_STATE | CONTR_CONT_ON);
66362306a36Sopenharmony_ci	if (err)
66462306a36Sopenharmony_ci		goto failed;
66562306a36Sopenharmony_ci
66662306a36Sopenharmony_ci	/* CPC-USB will transfer bus errors to host */
66762306a36Sopenharmony_ci	err = ems_usb_control_cmd(dev, CONTR_BUS_ERROR | CONTR_CONT_ON);
66862306a36Sopenharmony_ci	if (err)
66962306a36Sopenharmony_ci		goto failed;
67062306a36Sopenharmony_ci
67162306a36Sopenharmony_ci	err = ems_usb_write_mode(dev, SJA1000_MOD_NORMAL);
67262306a36Sopenharmony_ci	if (err)
67362306a36Sopenharmony_ci		goto failed;
67462306a36Sopenharmony_ci
67562306a36Sopenharmony_ci	dev->can.state = CAN_STATE_ERROR_ACTIVE;
67662306a36Sopenharmony_ci
67762306a36Sopenharmony_ci	return 0;
67862306a36Sopenharmony_ci
67962306a36Sopenharmony_cifailed:
68062306a36Sopenharmony_ci	netdev_warn(netdev, "couldn't submit control: %d\n", err);
68162306a36Sopenharmony_ci
68262306a36Sopenharmony_ci	return err;
68362306a36Sopenharmony_ci}
68462306a36Sopenharmony_ci
68562306a36Sopenharmony_cistatic void unlink_all_urbs(struct ems_usb *dev)
68662306a36Sopenharmony_ci{
68762306a36Sopenharmony_ci	int i;
68862306a36Sopenharmony_ci
68962306a36Sopenharmony_ci	usb_unlink_urb(dev->intr_urb);
69062306a36Sopenharmony_ci
69162306a36Sopenharmony_ci	usb_kill_anchored_urbs(&dev->rx_submitted);
69262306a36Sopenharmony_ci
69362306a36Sopenharmony_ci	for (i = 0; i < MAX_RX_URBS; ++i)
69462306a36Sopenharmony_ci		usb_free_coherent(dev->udev, RX_BUFFER_SIZE,
69562306a36Sopenharmony_ci				  dev->rxbuf[i], dev->rxbuf_dma[i]);
69662306a36Sopenharmony_ci
69762306a36Sopenharmony_ci	usb_kill_anchored_urbs(&dev->tx_submitted);
69862306a36Sopenharmony_ci	atomic_set(&dev->active_tx_urbs, 0);
69962306a36Sopenharmony_ci
70062306a36Sopenharmony_ci	for (i = 0; i < MAX_TX_URBS; i++)
70162306a36Sopenharmony_ci		dev->tx_contexts[i].echo_index = MAX_TX_URBS;
70262306a36Sopenharmony_ci}
70362306a36Sopenharmony_ci
70462306a36Sopenharmony_cistatic int ems_usb_open(struct net_device *netdev)
70562306a36Sopenharmony_ci{
70662306a36Sopenharmony_ci	struct ems_usb *dev = netdev_priv(netdev);
70762306a36Sopenharmony_ci	int err;
70862306a36Sopenharmony_ci
70962306a36Sopenharmony_ci	err = ems_usb_write_mode(dev, SJA1000_MOD_RM);
71062306a36Sopenharmony_ci	if (err)
71162306a36Sopenharmony_ci		return err;
71262306a36Sopenharmony_ci
71362306a36Sopenharmony_ci	/* common open */
71462306a36Sopenharmony_ci	err = open_candev(netdev);
71562306a36Sopenharmony_ci	if (err)
71662306a36Sopenharmony_ci		return err;
71762306a36Sopenharmony_ci
71862306a36Sopenharmony_ci	/* finally start device */
71962306a36Sopenharmony_ci	err = ems_usb_start(dev);
72062306a36Sopenharmony_ci	if (err) {
72162306a36Sopenharmony_ci		if (err == -ENODEV)
72262306a36Sopenharmony_ci			netif_device_detach(dev->netdev);
72362306a36Sopenharmony_ci
72462306a36Sopenharmony_ci		netdev_warn(netdev, "couldn't start device: %d\n", err);
72562306a36Sopenharmony_ci
72662306a36Sopenharmony_ci		close_candev(netdev);
72762306a36Sopenharmony_ci
72862306a36Sopenharmony_ci		return err;
72962306a36Sopenharmony_ci	}
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ci
73262306a36Sopenharmony_ci	netif_start_queue(netdev);
73362306a36Sopenharmony_ci
73462306a36Sopenharmony_ci	return 0;
73562306a36Sopenharmony_ci}
73662306a36Sopenharmony_ci
73762306a36Sopenharmony_cistatic netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *netdev)
73862306a36Sopenharmony_ci{
73962306a36Sopenharmony_ci	struct ems_usb *dev = netdev_priv(netdev);
74062306a36Sopenharmony_ci	struct ems_tx_urb_context *context = NULL;
74162306a36Sopenharmony_ci	struct net_device_stats *stats = &netdev->stats;
74262306a36Sopenharmony_ci	struct can_frame *cf = (struct can_frame *)skb->data;
74362306a36Sopenharmony_ci	struct ems_cpc_msg *msg;
74462306a36Sopenharmony_ci	struct urb *urb;
74562306a36Sopenharmony_ci	u8 *buf;
74662306a36Sopenharmony_ci	int i, err;
74762306a36Sopenharmony_ci	size_t size = CPC_HEADER_SIZE + CPC_MSG_HEADER_LEN
74862306a36Sopenharmony_ci			+ sizeof(struct cpc_can_msg);
74962306a36Sopenharmony_ci
75062306a36Sopenharmony_ci	if (can_dev_dropped_skb(netdev, skb))
75162306a36Sopenharmony_ci		return NETDEV_TX_OK;
75262306a36Sopenharmony_ci
75362306a36Sopenharmony_ci	/* create a URB, and a buffer for it, and copy the data to the URB */
75462306a36Sopenharmony_ci	urb = usb_alloc_urb(0, GFP_ATOMIC);
75562306a36Sopenharmony_ci	if (!urb)
75662306a36Sopenharmony_ci		goto nomem;
75762306a36Sopenharmony_ci
75862306a36Sopenharmony_ci	buf = usb_alloc_coherent(dev->udev, size, GFP_ATOMIC, &urb->transfer_dma);
75962306a36Sopenharmony_ci	if (!buf) {
76062306a36Sopenharmony_ci		netdev_err(netdev, "No memory left for USB buffer\n");
76162306a36Sopenharmony_ci		usb_free_urb(urb);
76262306a36Sopenharmony_ci		goto nomem;
76362306a36Sopenharmony_ci	}
76462306a36Sopenharmony_ci
76562306a36Sopenharmony_ci	msg = (struct ems_cpc_msg *)&buf[CPC_HEADER_SIZE];
76662306a36Sopenharmony_ci
76762306a36Sopenharmony_ci	msg->msg.can_msg.id = cpu_to_le32(cf->can_id & CAN_ERR_MASK);
76862306a36Sopenharmony_ci	msg->msg.can_msg.length = cf->len;
76962306a36Sopenharmony_ci
77062306a36Sopenharmony_ci	if (cf->can_id & CAN_RTR_FLAG) {
77162306a36Sopenharmony_ci		msg->type = cf->can_id & CAN_EFF_FLAG ?
77262306a36Sopenharmony_ci			CPC_CMD_TYPE_EXT_RTR_FRAME : CPC_CMD_TYPE_RTR_FRAME;
77362306a36Sopenharmony_ci
77462306a36Sopenharmony_ci		msg->length = CPC_CAN_MSG_MIN_SIZE;
77562306a36Sopenharmony_ci	} else {
77662306a36Sopenharmony_ci		msg->type = cf->can_id & CAN_EFF_FLAG ?
77762306a36Sopenharmony_ci			CPC_CMD_TYPE_EXT_CAN_FRAME : CPC_CMD_TYPE_CAN_FRAME;
77862306a36Sopenharmony_ci
77962306a36Sopenharmony_ci		for (i = 0; i < cf->len; i++)
78062306a36Sopenharmony_ci			msg->msg.can_msg.msg[i] = cf->data[i];
78162306a36Sopenharmony_ci
78262306a36Sopenharmony_ci		msg->length = CPC_CAN_MSG_MIN_SIZE + cf->len;
78362306a36Sopenharmony_ci	}
78462306a36Sopenharmony_ci
78562306a36Sopenharmony_ci	for (i = 0; i < MAX_TX_URBS; i++) {
78662306a36Sopenharmony_ci		if (dev->tx_contexts[i].echo_index == MAX_TX_URBS) {
78762306a36Sopenharmony_ci			context = &dev->tx_contexts[i];
78862306a36Sopenharmony_ci			break;
78962306a36Sopenharmony_ci		}
79062306a36Sopenharmony_ci	}
79162306a36Sopenharmony_ci
79262306a36Sopenharmony_ci	/*
79362306a36Sopenharmony_ci	 * May never happen! When this happens we'd more URBs in flight as
79462306a36Sopenharmony_ci	 * allowed (MAX_TX_URBS).
79562306a36Sopenharmony_ci	 */
79662306a36Sopenharmony_ci	if (!context) {
79762306a36Sopenharmony_ci		usb_free_coherent(dev->udev, size, buf, urb->transfer_dma);
79862306a36Sopenharmony_ci		usb_free_urb(urb);
79962306a36Sopenharmony_ci
80062306a36Sopenharmony_ci		netdev_warn(netdev, "couldn't find free context\n");
80162306a36Sopenharmony_ci
80262306a36Sopenharmony_ci		return NETDEV_TX_BUSY;
80362306a36Sopenharmony_ci	}
80462306a36Sopenharmony_ci
80562306a36Sopenharmony_ci	context->dev = dev;
80662306a36Sopenharmony_ci	context->echo_index = i;
80762306a36Sopenharmony_ci
80862306a36Sopenharmony_ci	usb_fill_bulk_urb(urb, dev->udev, usb_sndbulkpipe(dev->udev, 2), buf,
80962306a36Sopenharmony_ci			  size, ems_usb_write_bulk_callback, context);
81062306a36Sopenharmony_ci	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
81162306a36Sopenharmony_ci	usb_anchor_urb(urb, &dev->tx_submitted);
81262306a36Sopenharmony_ci
81362306a36Sopenharmony_ci	can_put_echo_skb(skb, netdev, context->echo_index, 0);
81462306a36Sopenharmony_ci
81562306a36Sopenharmony_ci	atomic_inc(&dev->active_tx_urbs);
81662306a36Sopenharmony_ci
81762306a36Sopenharmony_ci	err = usb_submit_urb(urb, GFP_ATOMIC);
81862306a36Sopenharmony_ci	if (unlikely(err)) {
81962306a36Sopenharmony_ci		can_free_echo_skb(netdev, context->echo_index, NULL);
82062306a36Sopenharmony_ci
82162306a36Sopenharmony_ci		usb_unanchor_urb(urb);
82262306a36Sopenharmony_ci		usb_free_coherent(dev->udev, size, buf, urb->transfer_dma);
82362306a36Sopenharmony_ci
82462306a36Sopenharmony_ci		atomic_dec(&dev->active_tx_urbs);
82562306a36Sopenharmony_ci
82662306a36Sopenharmony_ci		if (err == -ENODEV) {
82762306a36Sopenharmony_ci			netif_device_detach(netdev);
82862306a36Sopenharmony_ci		} else {
82962306a36Sopenharmony_ci			netdev_warn(netdev, "failed tx_urb %d\n", err);
83062306a36Sopenharmony_ci
83162306a36Sopenharmony_ci			stats->tx_dropped++;
83262306a36Sopenharmony_ci		}
83362306a36Sopenharmony_ci	} else {
83462306a36Sopenharmony_ci		netif_trans_update(netdev);
83562306a36Sopenharmony_ci
83662306a36Sopenharmony_ci		/* Slow down tx path */
83762306a36Sopenharmony_ci		if (atomic_read(&dev->active_tx_urbs) >= MAX_TX_URBS ||
83862306a36Sopenharmony_ci		    dev->free_slots < CPC_TX_QUEUE_TRIGGER_LOW) {
83962306a36Sopenharmony_ci			netif_stop_queue(netdev);
84062306a36Sopenharmony_ci		}
84162306a36Sopenharmony_ci	}
84262306a36Sopenharmony_ci
84362306a36Sopenharmony_ci	/*
84462306a36Sopenharmony_ci	 * Release our reference to this URB, the USB core will eventually free
84562306a36Sopenharmony_ci	 * it entirely.
84662306a36Sopenharmony_ci	 */
84762306a36Sopenharmony_ci	usb_free_urb(urb);
84862306a36Sopenharmony_ci
84962306a36Sopenharmony_ci	return NETDEV_TX_OK;
85062306a36Sopenharmony_ci
85162306a36Sopenharmony_cinomem:
85262306a36Sopenharmony_ci	dev_kfree_skb(skb);
85362306a36Sopenharmony_ci	stats->tx_dropped++;
85462306a36Sopenharmony_ci
85562306a36Sopenharmony_ci	return NETDEV_TX_OK;
85662306a36Sopenharmony_ci}
85762306a36Sopenharmony_ci
85862306a36Sopenharmony_cistatic int ems_usb_close(struct net_device *netdev)
85962306a36Sopenharmony_ci{
86062306a36Sopenharmony_ci	struct ems_usb *dev = netdev_priv(netdev);
86162306a36Sopenharmony_ci
86262306a36Sopenharmony_ci	/* Stop polling */
86362306a36Sopenharmony_ci	unlink_all_urbs(dev);
86462306a36Sopenharmony_ci
86562306a36Sopenharmony_ci	netif_stop_queue(netdev);
86662306a36Sopenharmony_ci
86762306a36Sopenharmony_ci	/* Set CAN controller to reset mode */
86862306a36Sopenharmony_ci	if (ems_usb_write_mode(dev, SJA1000_MOD_RM))
86962306a36Sopenharmony_ci		netdev_warn(netdev, "couldn't stop device");
87062306a36Sopenharmony_ci
87162306a36Sopenharmony_ci	close_candev(netdev);
87262306a36Sopenharmony_ci
87362306a36Sopenharmony_ci	return 0;
87462306a36Sopenharmony_ci}
87562306a36Sopenharmony_ci
87662306a36Sopenharmony_cistatic const struct net_device_ops ems_usb_netdev_ops = {
87762306a36Sopenharmony_ci	.ndo_open = ems_usb_open,
87862306a36Sopenharmony_ci	.ndo_stop = ems_usb_close,
87962306a36Sopenharmony_ci	.ndo_start_xmit = ems_usb_start_xmit,
88062306a36Sopenharmony_ci	.ndo_change_mtu = can_change_mtu,
88162306a36Sopenharmony_ci};
88262306a36Sopenharmony_ci
88362306a36Sopenharmony_cistatic const struct ethtool_ops ems_usb_ethtool_ops = {
88462306a36Sopenharmony_ci	.get_ts_info = ethtool_op_get_ts_info,
88562306a36Sopenharmony_ci};
88662306a36Sopenharmony_ci
88762306a36Sopenharmony_cistatic const struct can_bittiming_const ems_usb_bittiming_const = {
88862306a36Sopenharmony_ci	.name = KBUILD_MODNAME,
88962306a36Sopenharmony_ci	.tseg1_min = 1,
89062306a36Sopenharmony_ci	.tseg1_max = 16,
89162306a36Sopenharmony_ci	.tseg2_min = 1,
89262306a36Sopenharmony_ci	.tseg2_max = 8,
89362306a36Sopenharmony_ci	.sjw_max = 4,
89462306a36Sopenharmony_ci	.brp_min = 1,
89562306a36Sopenharmony_ci	.brp_max = 64,
89662306a36Sopenharmony_ci	.brp_inc = 1,
89762306a36Sopenharmony_ci};
89862306a36Sopenharmony_ci
89962306a36Sopenharmony_cistatic int ems_usb_set_mode(struct net_device *netdev, enum can_mode mode)
90062306a36Sopenharmony_ci{
90162306a36Sopenharmony_ci	struct ems_usb *dev = netdev_priv(netdev);
90262306a36Sopenharmony_ci
90362306a36Sopenharmony_ci	switch (mode) {
90462306a36Sopenharmony_ci	case CAN_MODE_START:
90562306a36Sopenharmony_ci		if (ems_usb_write_mode(dev, SJA1000_MOD_NORMAL))
90662306a36Sopenharmony_ci			netdev_warn(netdev, "couldn't start device");
90762306a36Sopenharmony_ci
90862306a36Sopenharmony_ci		if (netif_queue_stopped(netdev))
90962306a36Sopenharmony_ci			netif_wake_queue(netdev);
91062306a36Sopenharmony_ci		break;
91162306a36Sopenharmony_ci
91262306a36Sopenharmony_ci	default:
91362306a36Sopenharmony_ci		return -EOPNOTSUPP;
91462306a36Sopenharmony_ci	}
91562306a36Sopenharmony_ci
91662306a36Sopenharmony_ci	return 0;
91762306a36Sopenharmony_ci}
91862306a36Sopenharmony_ci
91962306a36Sopenharmony_cistatic int ems_usb_set_bittiming(struct net_device *netdev)
92062306a36Sopenharmony_ci{
92162306a36Sopenharmony_ci	struct ems_usb *dev = netdev_priv(netdev);
92262306a36Sopenharmony_ci	struct can_bittiming *bt = &dev->can.bittiming;
92362306a36Sopenharmony_ci	u8 btr0, btr1;
92462306a36Sopenharmony_ci
92562306a36Sopenharmony_ci	btr0 = ((bt->brp - 1) & 0x3f) | (((bt->sjw - 1) & 0x3) << 6);
92662306a36Sopenharmony_ci	btr1 = ((bt->prop_seg + bt->phase_seg1 - 1) & 0xf) |
92762306a36Sopenharmony_ci		(((bt->phase_seg2 - 1) & 0x7) << 4);
92862306a36Sopenharmony_ci	if (dev->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
92962306a36Sopenharmony_ci		btr1 |= 0x80;
93062306a36Sopenharmony_ci
93162306a36Sopenharmony_ci	netdev_info(netdev, "setting BTR0=0x%02x BTR1=0x%02x\n", btr0, btr1);
93262306a36Sopenharmony_ci
93362306a36Sopenharmony_ci	dev->active_params.msg.can_params.cc_params.sja1000.btr0 = btr0;
93462306a36Sopenharmony_ci	dev->active_params.msg.can_params.cc_params.sja1000.btr1 = btr1;
93562306a36Sopenharmony_ci
93662306a36Sopenharmony_ci	return ems_usb_command_msg(dev, &dev->active_params);
93762306a36Sopenharmony_ci}
93862306a36Sopenharmony_ci
93962306a36Sopenharmony_cistatic void init_params_sja1000(struct ems_cpc_msg *msg)
94062306a36Sopenharmony_ci{
94162306a36Sopenharmony_ci	struct cpc_sja1000_params *sja1000 =
94262306a36Sopenharmony_ci		&msg->msg.can_params.cc_params.sja1000;
94362306a36Sopenharmony_ci
94462306a36Sopenharmony_ci	msg->type = CPC_CMD_TYPE_CAN_PARAMS;
94562306a36Sopenharmony_ci	msg->length = sizeof(struct cpc_can_params);
94662306a36Sopenharmony_ci	msg->msgid = 0;
94762306a36Sopenharmony_ci
94862306a36Sopenharmony_ci	msg->msg.can_params.cc_type = CPC_CC_TYPE_SJA1000;
94962306a36Sopenharmony_ci
95062306a36Sopenharmony_ci	/* Acceptance filter open */
95162306a36Sopenharmony_ci	sja1000->acc_code0 = 0x00;
95262306a36Sopenharmony_ci	sja1000->acc_code1 = 0x00;
95362306a36Sopenharmony_ci	sja1000->acc_code2 = 0x00;
95462306a36Sopenharmony_ci	sja1000->acc_code3 = 0x00;
95562306a36Sopenharmony_ci
95662306a36Sopenharmony_ci	/* Acceptance filter open */
95762306a36Sopenharmony_ci	sja1000->acc_mask0 = 0xFF;
95862306a36Sopenharmony_ci	sja1000->acc_mask1 = 0xFF;
95962306a36Sopenharmony_ci	sja1000->acc_mask2 = 0xFF;
96062306a36Sopenharmony_ci	sja1000->acc_mask3 = 0xFF;
96162306a36Sopenharmony_ci
96262306a36Sopenharmony_ci	sja1000->btr0 = 0;
96362306a36Sopenharmony_ci	sja1000->btr1 = 0;
96462306a36Sopenharmony_ci
96562306a36Sopenharmony_ci	sja1000->outp_contr = SJA1000_DEFAULT_OUTPUT_CONTROL;
96662306a36Sopenharmony_ci	sja1000->mode = SJA1000_MOD_RM;
96762306a36Sopenharmony_ci}
96862306a36Sopenharmony_ci
96962306a36Sopenharmony_ci/*
97062306a36Sopenharmony_ci * probe function for new CPC-USB devices
97162306a36Sopenharmony_ci */
97262306a36Sopenharmony_cistatic int ems_usb_probe(struct usb_interface *intf,
97362306a36Sopenharmony_ci			 const struct usb_device_id *id)
97462306a36Sopenharmony_ci{
97562306a36Sopenharmony_ci	struct net_device *netdev;
97662306a36Sopenharmony_ci	struct ems_usb *dev;
97762306a36Sopenharmony_ci	int i, err = -ENOMEM;
97862306a36Sopenharmony_ci
97962306a36Sopenharmony_ci	netdev = alloc_candev(sizeof(struct ems_usb), MAX_TX_URBS);
98062306a36Sopenharmony_ci	if (!netdev) {
98162306a36Sopenharmony_ci		dev_err(&intf->dev, "ems_usb: Couldn't alloc candev\n");
98262306a36Sopenharmony_ci		return -ENOMEM;
98362306a36Sopenharmony_ci	}
98462306a36Sopenharmony_ci
98562306a36Sopenharmony_ci	dev = netdev_priv(netdev);
98662306a36Sopenharmony_ci
98762306a36Sopenharmony_ci	dev->udev = interface_to_usbdev(intf);
98862306a36Sopenharmony_ci	dev->netdev = netdev;
98962306a36Sopenharmony_ci
99062306a36Sopenharmony_ci	dev->can.state = CAN_STATE_STOPPED;
99162306a36Sopenharmony_ci	dev->can.clock.freq = EMS_USB_ARM7_CLOCK;
99262306a36Sopenharmony_ci	dev->can.bittiming_const = &ems_usb_bittiming_const;
99362306a36Sopenharmony_ci	dev->can.do_set_bittiming = ems_usb_set_bittiming;
99462306a36Sopenharmony_ci	dev->can.do_set_mode = ems_usb_set_mode;
99562306a36Sopenharmony_ci	dev->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;
99662306a36Sopenharmony_ci
99762306a36Sopenharmony_ci	netdev->netdev_ops = &ems_usb_netdev_ops;
99862306a36Sopenharmony_ci	netdev->ethtool_ops = &ems_usb_ethtool_ops;
99962306a36Sopenharmony_ci
100062306a36Sopenharmony_ci	netdev->flags |= IFF_ECHO; /* we support local echo */
100162306a36Sopenharmony_ci
100262306a36Sopenharmony_ci	init_usb_anchor(&dev->rx_submitted);
100362306a36Sopenharmony_ci
100462306a36Sopenharmony_ci	init_usb_anchor(&dev->tx_submitted);
100562306a36Sopenharmony_ci	atomic_set(&dev->active_tx_urbs, 0);
100662306a36Sopenharmony_ci
100762306a36Sopenharmony_ci	for (i = 0; i < MAX_TX_URBS; i++)
100862306a36Sopenharmony_ci		dev->tx_contexts[i].echo_index = MAX_TX_URBS;
100962306a36Sopenharmony_ci
101062306a36Sopenharmony_ci	dev->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
101162306a36Sopenharmony_ci	if (!dev->intr_urb)
101262306a36Sopenharmony_ci		goto cleanup_candev;
101362306a36Sopenharmony_ci
101462306a36Sopenharmony_ci	dev->intr_in_buffer = kzalloc(INTR_IN_BUFFER_SIZE, GFP_KERNEL);
101562306a36Sopenharmony_ci	if (!dev->intr_in_buffer)
101662306a36Sopenharmony_ci		goto cleanup_intr_urb;
101762306a36Sopenharmony_ci
101862306a36Sopenharmony_ci	dev->tx_msg_buffer = kzalloc(CPC_HEADER_SIZE +
101962306a36Sopenharmony_ci				     sizeof(struct ems_cpc_msg), GFP_KERNEL);
102062306a36Sopenharmony_ci	if (!dev->tx_msg_buffer)
102162306a36Sopenharmony_ci		goto cleanup_intr_in_buffer;
102262306a36Sopenharmony_ci
102362306a36Sopenharmony_ci	usb_set_intfdata(intf, dev);
102462306a36Sopenharmony_ci
102562306a36Sopenharmony_ci	SET_NETDEV_DEV(netdev, &intf->dev);
102662306a36Sopenharmony_ci
102762306a36Sopenharmony_ci	init_params_sja1000(&dev->active_params);
102862306a36Sopenharmony_ci
102962306a36Sopenharmony_ci	err = ems_usb_command_msg(dev, &dev->active_params);
103062306a36Sopenharmony_ci	if (err) {
103162306a36Sopenharmony_ci		netdev_err(netdev, "couldn't initialize controller: %d\n", err);
103262306a36Sopenharmony_ci		goto cleanup_tx_msg_buffer;
103362306a36Sopenharmony_ci	}
103462306a36Sopenharmony_ci
103562306a36Sopenharmony_ci	err = register_candev(netdev);
103662306a36Sopenharmony_ci	if (err) {
103762306a36Sopenharmony_ci		netdev_err(netdev, "couldn't register CAN device: %d\n", err);
103862306a36Sopenharmony_ci		goto cleanup_tx_msg_buffer;
103962306a36Sopenharmony_ci	}
104062306a36Sopenharmony_ci
104162306a36Sopenharmony_ci	return 0;
104262306a36Sopenharmony_ci
104362306a36Sopenharmony_cicleanup_tx_msg_buffer:
104462306a36Sopenharmony_ci	kfree(dev->tx_msg_buffer);
104562306a36Sopenharmony_ci
104662306a36Sopenharmony_cicleanup_intr_in_buffer:
104762306a36Sopenharmony_ci	kfree(dev->intr_in_buffer);
104862306a36Sopenharmony_ci
104962306a36Sopenharmony_cicleanup_intr_urb:
105062306a36Sopenharmony_ci	usb_free_urb(dev->intr_urb);
105162306a36Sopenharmony_ci
105262306a36Sopenharmony_cicleanup_candev:
105362306a36Sopenharmony_ci	free_candev(netdev);
105462306a36Sopenharmony_ci
105562306a36Sopenharmony_ci	return err;
105662306a36Sopenharmony_ci}
105762306a36Sopenharmony_ci
105862306a36Sopenharmony_ci/*
105962306a36Sopenharmony_ci * called by the usb core when the device is removed from the system
106062306a36Sopenharmony_ci */
106162306a36Sopenharmony_cistatic void ems_usb_disconnect(struct usb_interface *intf)
106262306a36Sopenharmony_ci{
106362306a36Sopenharmony_ci	struct ems_usb *dev = usb_get_intfdata(intf);
106462306a36Sopenharmony_ci
106562306a36Sopenharmony_ci	usb_set_intfdata(intf, NULL);
106662306a36Sopenharmony_ci
106762306a36Sopenharmony_ci	if (dev) {
106862306a36Sopenharmony_ci		unregister_netdev(dev->netdev);
106962306a36Sopenharmony_ci
107062306a36Sopenharmony_ci		unlink_all_urbs(dev);
107162306a36Sopenharmony_ci
107262306a36Sopenharmony_ci		usb_free_urb(dev->intr_urb);
107362306a36Sopenharmony_ci
107462306a36Sopenharmony_ci		kfree(dev->intr_in_buffer);
107562306a36Sopenharmony_ci		kfree(dev->tx_msg_buffer);
107662306a36Sopenharmony_ci
107762306a36Sopenharmony_ci		free_candev(dev->netdev);
107862306a36Sopenharmony_ci	}
107962306a36Sopenharmony_ci}
108062306a36Sopenharmony_ci
108162306a36Sopenharmony_ci/* usb specific object needed to register this driver with the usb subsystem */
108262306a36Sopenharmony_cistatic struct usb_driver ems_usb_driver = {
108362306a36Sopenharmony_ci	.name = KBUILD_MODNAME,
108462306a36Sopenharmony_ci	.probe = ems_usb_probe,
108562306a36Sopenharmony_ci	.disconnect = ems_usb_disconnect,
108662306a36Sopenharmony_ci	.id_table = ems_usb_table,
108762306a36Sopenharmony_ci};
108862306a36Sopenharmony_ci
108962306a36Sopenharmony_cimodule_usb_driver(ems_usb_driver);
1090