1935912c5SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2702171adSSebastian Haas /*
3702171adSSebastian Haas * CAN driver for EMS Dr. Thomas Wuensche CPC-USB/ARM7
4702171adSSebastian Haas *
5702171adSSebastian Haas * Copyright (C) 2004-2009 EMS Dr. Thomas Wuensche
6702171adSSebastian Haas */
7409c188cSVincent Mailhol #include <linux/ethtool.h>
8702171adSSebastian Haas #include <linux/signal.h>
9702171adSSebastian Haas #include <linux/slab.h>
10702171adSSebastian Haas #include <linux/module.h>
11702171adSSebastian Haas #include <linux/netdevice.h>
12702171adSSebastian Haas #include <linux/usb.h>
13702171adSSebastian Haas
14702171adSSebastian Haas #include <linux/can.h>
15702171adSSebastian Haas #include <linux/can/dev.h>
16702171adSSebastian Haas #include <linux/can/error.h>
17702171adSSebastian Haas
18702171adSSebastian Haas MODULE_AUTHOR("Sebastian Haas <haas@ems-wuensche.com>");
19702171adSSebastian Haas MODULE_DESCRIPTION("CAN driver for EMS Dr. Thomas Wuensche CAN/USB interfaces");
20702171adSSebastian Haas MODULE_LICENSE("GPL v2");
21702171adSSebastian Haas
22702171adSSebastian Haas /* Control-Values for CPC_Control() Command Subject Selection */
23702171adSSebastian Haas #define CONTR_CAN_MESSAGE 0x04
24702171adSSebastian Haas #define CONTR_CAN_STATE 0x0C
25702171adSSebastian Haas #define CONTR_BUS_ERROR 0x1C
26702171adSSebastian Haas
27702171adSSebastian Haas /* Control Command Actions */
28702171adSSebastian Haas #define CONTR_CONT_OFF 0
29702171adSSebastian Haas #define CONTR_CONT_ON 1
30702171adSSebastian Haas #define CONTR_ONCE 2
31702171adSSebastian Haas
32702171adSSebastian Haas /* Messages from CPC to PC */
33702171adSSebastian Haas #define CPC_MSG_TYPE_CAN_FRAME 1 /* CAN data frame */
34702171adSSebastian Haas #define CPC_MSG_TYPE_RTR_FRAME 8 /* CAN remote frame */
35702171adSSebastian Haas #define CPC_MSG_TYPE_CAN_PARAMS 12 /* Actual CAN parameters */
36702171adSSebastian Haas #define CPC_MSG_TYPE_CAN_STATE 14 /* CAN state message */
37702171adSSebastian Haas #define CPC_MSG_TYPE_EXT_CAN_FRAME 16 /* Extended CAN data frame */
38702171adSSebastian Haas #define CPC_MSG_TYPE_EXT_RTR_FRAME 17 /* Extended remote frame */
39702171adSSebastian Haas #define CPC_MSG_TYPE_CONTROL 19 /* change interface behavior */
40702171adSSebastian Haas #define CPC_MSG_TYPE_CONFIRM 20 /* command processed confirmation */
41702171adSSebastian Haas #define CPC_MSG_TYPE_OVERRUN 21 /* overrun events */
42702171adSSebastian Haas #define CPC_MSG_TYPE_CAN_FRAME_ERROR 23 /* detected bus errors */
43702171adSSebastian Haas #define CPC_MSG_TYPE_ERR_COUNTER 25 /* RX/TX error counter */
44702171adSSebastian Haas
45702171adSSebastian Haas /* Messages from the PC to the CPC interface */
46702171adSSebastian Haas #define CPC_CMD_TYPE_CAN_FRAME 1 /* CAN data frame */
47702171adSSebastian Haas #define CPC_CMD_TYPE_CONTROL 3 /* control of interface behavior */
48702171adSSebastian Haas #define CPC_CMD_TYPE_CAN_PARAMS 6 /* set CAN parameters */
49702171adSSebastian Haas #define CPC_CMD_TYPE_RTR_FRAME 13 /* CAN remote frame */
50702171adSSebastian Haas #define CPC_CMD_TYPE_CAN_STATE 14 /* CAN state message */
51702171adSSebastian Haas #define CPC_CMD_TYPE_EXT_CAN_FRAME 15 /* Extended CAN data frame */
52702171adSSebastian Haas #define CPC_CMD_TYPE_EXT_RTR_FRAME 16 /* Extended CAN remote frame */
53702171adSSebastian Haas #define CPC_CMD_TYPE_CAN_EXIT 200 /* exit the CAN */
54702171adSSebastian Haas
55702171adSSebastian Haas #define CPC_CMD_TYPE_INQ_ERR_COUNTER 25 /* request the CAN error counters */
56702171adSSebastian Haas #define CPC_CMD_TYPE_CLEAR_MSG_QUEUE 8 /* clear CPC_MSG queue */
57702171adSSebastian Haas #define CPC_CMD_TYPE_CLEAR_CMD_QUEUE 28 /* clear CPC_CMD queue */
58702171adSSebastian Haas
59702171adSSebastian Haas #define CPC_CC_TYPE_SJA1000 2 /* Philips basic CAN controller */
60702171adSSebastian Haas
61702171adSSebastian Haas #define CPC_CAN_ECODE_ERRFRAME 0x01 /* Ecode type */
62702171adSSebastian Haas
63702171adSSebastian Haas /* Overrun types */
64702171adSSebastian Haas #define CPC_OVR_EVENT_CAN 0x01
65702171adSSebastian Haas #define CPC_OVR_EVENT_CANSTATE 0x02
66702171adSSebastian Haas #define CPC_OVR_EVENT_BUSERROR 0x04
67702171adSSebastian Haas
68702171adSSebastian Haas /*
69702171adSSebastian Haas * If the CAN controller lost a message we indicate it with the highest bit
70702171adSSebastian Haas * set in the count field.
71702171adSSebastian Haas */
72702171adSSebastian Haas #define CPC_OVR_HW 0x80
73702171adSSebastian Haas
74702171adSSebastian Haas /* Size of the "struct ems_cpc_msg" without the union */
75702171adSSebastian Haas #define CPC_MSG_HEADER_LEN 11
76702171adSSebastian Haas #define CPC_CAN_MSG_MIN_SIZE 5
77702171adSSebastian Haas
78702171adSSebastian Haas /* Define these values to match your devices */
79702171adSSebastian Haas #define USB_CPCUSB_VENDOR_ID 0x12D6
80702171adSSebastian Haas
81702171adSSebastian Haas #define USB_CPCUSB_ARM7_PRODUCT_ID 0x0444
82702171adSSebastian Haas
83702171adSSebastian Haas /* Mode register NXP LPC2119/SJA1000 CAN Controller */
84702171adSSebastian Haas #define SJA1000_MOD_NORMAL 0x00
85702171adSSebastian Haas #define SJA1000_MOD_RM 0x01
86702171adSSebastian Haas
87702171adSSebastian Haas /* ECC register NXP LPC2119/SJA1000 CAN Controller */
88702171adSSebastian Haas #define SJA1000_ECC_SEG 0x1F
89702171adSSebastian Haas #define SJA1000_ECC_DIR 0x20
90702171adSSebastian Haas #define SJA1000_ECC_ERR 0x06
91702171adSSebastian Haas #define SJA1000_ECC_BIT 0x00
92702171adSSebastian Haas #define SJA1000_ECC_FORM 0x40
93702171adSSebastian Haas #define SJA1000_ECC_STUFF 0x80
94702171adSSebastian Haas #define SJA1000_ECC_MASK 0xc0
95702171adSSebastian Haas
96702171adSSebastian Haas /* Status register content */
97702171adSSebastian Haas #define SJA1000_SR_BS 0x80
98702171adSSebastian Haas #define SJA1000_SR_ES 0x40
99702171adSSebastian Haas
100702171adSSebastian Haas #define SJA1000_DEFAULT_OUTPUT_CONTROL 0xDA
101702171adSSebastian Haas
102702171adSSebastian Haas /*
103702171adSSebastian Haas * The device actually uses a 16MHz clock to generate the CAN clock
104702171adSSebastian Haas * but it expects SJA1000 bit settings based on 8MHz (is internally
105702171adSSebastian Haas * converted).
106702171adSSebastian Haas */
107702171adSSebastian Haas #define EMS_USB_ARM7_CLOCK 8000000
108702171adSSebastian Haas
10990cfde46SGerhard Uttenthaler #define CPC_TX_QUEUE_TRIGGER_LOW 25
11090cfde46SGerhard Uttenthaler #define CPC_TX_QUEUE_TRIGGER_HIGH 35
11190cfde46SGerhard Uttenthaler
112702171adSSebastian Haas /*
113702171adSSebastian Haas * CAN-Message representation in a CPC_MSG. Message object type is
114702171adSSebastian Haas * CPC_MSG_TYPE_CAN_FRAME or CPC_MSG_TYPE_RTR_FRAME or
115702171adSSebastian Haas * CPC_MSG_TYPE_EXT_CAN_FRAME or CPC_MSG_TYPE_EXT_RTR_FRAME.
116702171adSSebastian Haas */
117702171adSSebastian Haas struct cpc_can_msg {
1188a4b5b0fSGerhard Uttenthaler __le32 id;
119702171adSSebastian Haas u8 length;
120702171adSSebastian Haas u8 msg[8];
121702171adSSebastian Haas };
122702171adSSebastian Haas
123702171adSSebastian Haas /* Representation of the CAN parameters for the SJA1000 controller */
124702171adSSebastian Haas struct cpc_sja1000_params {
125702171adSSebastian Haas u8 mode;
126702171adSSebastian Haas u8 acc_code0;
127702171adSSebastian Haas u8 acc_code1;
128702171adSSebastian Haas u8 acc_code2;
129702171adSSebastian Haas u8 acc_code3;
130702171adSSebastian Haas u8 acc_mask0;
131702171adSSebastian Haas u8 acc_mask1;
132702171adSSebastian Haas u8 acc_mask2;
133702171adSSebastian Haas u8 acc_mask3;
134702171adSSebastian Haas u8 btr0;
135702171adSSebastian Haas u8 btr1;
136702171adSSebastian Haas u8 outp_contr;
137702171adSSebastian Haas };
138702171adSSebastian Haas
139702171adSSebastian Haas /* CAN params message representation */
140702171adSSebastian Haas struct cpc_can_params {
141702171adSSebastian Haas u8 cc_type;
142702171adSSebastian Haas
143702171adSSebastian Haas /* Will support M16C CAN controller in the future */
144702171adSSebastian Haas union {
145702171adSSebastian Haas struct cpc_sja1000_params sja1000;
146702171adSSebastian Haas } cc_params;
147702171adSSebastian Haas };
148702171adSSebastian Haas
149702171adSSebastian Haas /* Structure for confirmed message handling */
150702171adSSebastian Haas struct cpc_confirm {
151702171adSSebastian Haas u8 error; /* error code */
152702171adSSebastian Haas };
153702171adSSebastian Haas
154702171adSSebastian Haas /* Structure for overrun conditions */
155702171adSSebastian Haas struct cpc_overrun {
156702171adSSebastian Haas u8 event;
157702171adSSebastian Haas u8 count;
158702171adSSebastian Haas };
159702171adSSebastian Haas
160702171adSSebastian Haas /* SJA1000 CAN errors (compatible to NXP LPC2119) */
161702171adSSebastian Haas struct cpc_sja1000_can_error {
162702171adSSebastian Haas u8 ecc;
163702171adSSebastian Haas u8 rxerr;
164702171adSSebastian Haas u8 txerr;
165702171adSSebastian Haas };
166702171adSSebastian Haas
167702171adSSebastian Haas /* structure for CAN error conditions */
168702171adSSebastian Haas struct cpc_can_error {
169702171adSSebastian Haas u8 ecode;
170702171adSSebastian Haas
171702171adSSebastian Haas struct {
172702171adSSebastian Haas u8 cc_type;
173702171adSSebastian Haas
174702171adSSebastian Haas /* Other controllers may also provide error code capture regs */
175702171adSSebastian Haas union {
176702171adSSebastian Haas struct cpc_sja1000_can_error sja1000;
177702171adSSebastian Haas } regs;
178702171adSSebastian Haas } cc;
179702171adSSebastian Haas };
180702171adSSebastian Haas
181702171adSSebastian Haas /*
182702171adSSebastian Haas * Structure containing RX/TX error counter. This structure is used to request
183702171adSSebastian Haas * the values of the CAN controllers TX and RX error counter.
184702171adSSebastian Haas */
185702171adSSebastian Haas struct cpc_can_err_counter {
186702171adSSebastian Haas u8 rx;
187702171adSSebastian Haas u8 tx;
188702171adSSebastian Haas };
189702171adSSebastian Haas
190702171adSSebastian Haas /* Main message type used between library and application */
191ba2d3587SEric Dumazet struct __packed ems_cpc_msg {
192702171adSSebastian Haas u8 type; /* type of message */
193702171adSSebastian Haas u8 length; /* length of data within union 'msg' */
194702171adSSebastian Haas u8 msgid; /* confirmation handle */
195a0bc163aSMarc Kleine-Budde __le32 ts_sec; /* timestamp in seconds */
196a0bc163aSMarc Kleine-Budde __le32 ts_nsec; /* timestamp in nano seconds */
197702171adSSebastian Haas
198a4cb6e62SMarc Kleine-Budde union __packed {
199702171adSSebastian Haas u8 generic[64];
200702171adSSebastian Haas struct cpc_can_msg can_msg;
201702171adSSebastian Haas struct cpc_can_params can_params;
202702171adSSebastian Haas struct cpc_confirm confirmation;
203702171adSSebastian Haas struct cpc_overrun overrun;
204702171adSSebastian Haas struct cpc_can_error error;
205702171adSSebastian Haas struct cpc_can_err_counter err_counter;
206702171adSSebastian Haas u8 can_state;
207702171adSSebastian Haas } msg;
208702171adSSebastian Haas };
209702171adSSebastian Haas
210702171adSSebastian Haas /*
211702171adSSebastian Haas * Table of devices that work with this driver
212702171adSSebastian Haas * NOTE: This driver supports only CPC-USB/ARM7 (LPC2119) yet.
213702171adSSebastian Haas */
214702171adSSebastian Haas static struct usb_device_id ems_usb_table[] = {
215702171adSSebastian Haas {USB_DEVICE(USB_CPCUSB_VENDOR_ID, USB_CPCUSB_ARM7_PRODUCT_ID)},
216702171adSSebastian Haas {} /* Terminating entry */
217702171adSSebastian Haas };
218702171adSSebastian Haas
219702171adSSebastian Haas MODULE_DEVICE_TABLE(usb, ems_usb_table);
220702171adSSebastian Haas
221702171adSSebastian Haas #define RX_BUFFER_SIZE 64
222702171adSSebastian Haas #define CPC_HEADER_SIZE 4
223702171adSSebastian Haas #define INTR_IN_BUFFER_SIZE 4
224702171adSSebastian Haas
225702171adSSebastian Haas #define MAX_RX_URBS 10
226a6e4bc53SWolfgang Grandegger #define MAX_TX_URBS 10
227702171adSSebastian Haas
228702171adSSebastian Haas struct ems_usb;
229702171adSSebastian Haas
230702171adSSebastian Haas struct ems_tx_urb_context {
231702171adSSebastian Haas struct ems_usb *dev;
232702171adSSebastian Haas
233702171adSSebastian Haas u32 echo_index;
234702171adSSebastian Haas };
235702171adSSebastian Haas
236702171adSSebastian Haas struct ems_usb {
237702171adSSebastian Haas struct can_priv can; /* must be the first member */
238702171adSSebastian Haas
239702171adSSebastian Haas struct sk_buff *echo_skb[MAX_TX_URBS];
240702171adSSebastian Haas
241702171adSSebastian Haas struct usb_device *udev;
242702171adSSebastian Haas struct net_device *netdev;
243702171adSSebastian Haas
244702171adSSebastian Haas atomic_t active_tx_urbs;
245702171adSSebastian Haas struct usb_anchor tx_submitted;
246702171adSSebastian Haas struct ems_tx_urb_context tx_contexts[MAX_TX_URBS];
247702171adSSebastian Haas
248702171adSSebastian Haas struct usb_anchor rx_submitted;
249702171adSSebastian Haas
250702171adSSebastian Haas struct urb *intr_urb;
251702171adSSebastian Haas
252702171adSSebastian Haas u8 *tx_msg_buffer;
253702171adSSebastian Haas
254702171adSSebastian Haas u8 *intr_in_buffer;
255702171adSSebastian Haas unsigned int free_slots; /* remember number of available slots */
256702171adSSebastian Haas
257702171adSSebastian Haas struct ems_cpc_msg active_params; /* active controller parameters */
2589969e3c5SPavel Skripkin void *rxbuf[MAX_RX_URBS];
2599969e3c5SPavel Skripkin dma_addr_t rxbuf_dma[MAX_RX_URBS];
260702171adSSebastian Haas };
261702171adSSebastian Haas
ems_usb_read_interrupt_callback(struct urb * urb)262702171adSSebastian Haas static void ems_usb_read_interrupt_callback(struct urb *urb)
263702171adSSebastian Haas {
264702171adSSebastian Haas struct ems_usb *dev = urb->context;
265702171adSSebastian Haas struct net_device *netdev = dev->netdev;
266702171adSSebastian Haas int err;
267702171adSSebastian Haas
268702171adSSebastian Haas if (!netif_device_present(netdev))
269702171adSSebastian Haas return;
270702171adSSebastian Haas
271702171adSSebastian Haas switch (urb->status) {
272702171adSSebastian Haas case 0:
273702171adSSebastian Haas dev->free_slots = dev->intr_in_buffer[1];
27459097ac9SMarc Kleine-Budde if (dev->free_slots > CPC_TX_QUEUE_TRIGGER_HIGH &&
27559097ac9SMarc Kleine-Budde netif_queue_stopped(netdev))
27690cfde46SGerhard Uttenthaler netif_wake_queue(netdev);
277702171adSSebastian Haas break;
278702171adSSebastian Haas
279702171adSSebastian Haas case -ECONNRESET: /* unlink */
280702171adSSebastian Haas case -ENOENT:
281bd352e1aSMartin Kelly case -EPIPE:
282bd352e1aSMartin Kelly case -EPROTO:
283702171adSSebastian Haas case -ESHUTDOWN:
284702171adSSebastian Haas return;
285702171adSSebastian Haas
286702171adSSebastian Haas default:
287aabdfd6aSWolfgang Grandegger netdev_info(netdev, "Rx interrupt aborted %d\n", urb->status);
288702171adSSebastian Haas break;
289702171adSSebastian Haas }
290702171adSSebastian Haas
291702171adSSebastian Haas err = usb_submit_urb(urb, GFP_ATOMIC);
292702171adSSebastian Haas
293702171adSSebastian Haas if (err == -ENODEV)
294702171adSSebastian Haas netif_device_detach(netdev);
295702171adSSebastian Haas else if (err)
296aabdfd6aSWolfgang Grandegger netdev_err(netdev, "failed resubmitting intr urb: %d\n", err);
297702171adSSebastian Haas }
298702171adSSebastian Haas
ems_usb_rx_can_msg(struct ems_usb * dev,struct ems_cpc_msg * msg)299702171adSSebastian Haas static void ems_usb_rx_can_msg(struct ems_usb *dev, struct ems_cpc_msg *msg)
300702171adSSebastian Haas {
301702171adSSebastian Haas struct can_frame *cf;
302702171adSSebastian Haas struct sk_buff *skb;
303702171adSSebastian Haas int i;
304702171adSSebastian Haas struct net_device_stats *stats = &dev->netdev->stats;
305702171adSSebastian Haas
3067b6856a0SWolfgang Grandegger skb = alloc_can_skb(dev->netdev, &cf);
307702171adSSebastian Haas if (skb == NULL)
308702171adSSebastian Haas return;
309702171adSSebastian Haas
3102b2072e9SSebastian Haas cf->can_id = le32_to_cpu(msg->msg.can_msg.id);
311c7b74967SOliver Hartkopp cf->len = can_cc_dlc2len(msg->msg.can_msg.length & 0xF);
312702171adSSebastian Haas
3138e95a202SJoe Perches if (msg->type == CPC_MSG_TYPE_EXT_CAN_FRAME ||
3148e95a202SJoe Perches msg->type == CPC_MSG_TYPE_EXT_RTR_FRAME)
315702171adSSebastian Haas cf->can_id |= CAN_EFF_FLAG;
316702171adSSebastian Haas
3178e95a202SJoe Perches if (msg->type == CPC_MSG_TYPE_RTR_FRAME ||
3188e95a202SJoe Perches msg->type == CPC_MSG_TYPE_EXT_RTR_FRAME) {
319702171adSSebastian Haas cf->can_id |= CAN_RTR_FLAG;
320702171adSSebastian Haas } else {
321c7b74967SOliver Hartkopp for (i = 0; i < cf->len; i++)
322702171adSSebastian Haas cf->data[i] = msg->msg.can_msg.msg[i];
323702171adSSebastian Haas
324c7b74967SOliver Hartkopp stats->rx_bytes += cf->len;
3258e674ca7SVincent Mailhol }
3268e674ca7SVincent Mailhol stats->rx_packets++;
3278e674ca7SVincent Mailhol
32843c021e8SMarc Kleine-Budde netif_rx(skb);
329702171adSSebastian Haas }
330702171adSSebastian Haas
ems_usb_rx_err(struct ems_usb * dev,struct ems_cpc_msg * msg)331702171adSSebastian Haas static void ems_usb_rx_err(struct ems_usb *dev, struct ems_cpc_msg *msg)
332702171adSSebastian Haas {
333702171adSSebastian Haas struct can_frame *cf;
334702171adSSebastian Haas struct sk_buff *skb;
335702171adSSebastian Haas struct net_device_stats *stats = &dev->netdev->stats;
336702171adSSebastian Haas
3377b6856a0SWolfgang Grandegger skb = alloc_can_err_skb(dev->netdev, &cf);
338702171adSSebastian Haas
339702171adSSebastian Haas if (msg->type == CPC_MSG_TYPE_CAN_STATE) {
340702171adSSebastian Haas u8 state = msg->msg.can_state;
341702171adSSebastian Haas
342702171adSSebastian Haas if (state & SJA1000_SR_BS) {
343702171adSSebastian Haas dev->can.state = CAN_STATE_BUS_OFF;
344*c7f3a539SDario Binacchi if (skb)
345702171adSSebastian Haas cf->can_id |= CAN_ERR_BUSOFF;
346702171adSSebastian Haas
347be38a6f9SAndri Yngvason dev->can.can_stats.bus_off++;
348702171adSSebastian Haas can_bus_off(dev->netdev);
349702171adSSebastian Haas } else if (state & SJA1000_SR_ES) {
350702171adSSebastian Haas dev->can.state = CAN_STATE_ERROR_WARNING;
351702171adSSebastian Haas dev->can.can_stats.error_warning++;
352702171adSSebastian Haas } else {
353702171adSSebastian Haas dev->can.state = CAN_STATE_ERROR_ACTIVE;
354702171adSSebastian Haas dev->can.can_stats.error_passive++;
355702171adSSebastian Haas }
356702171adSSebastian Haas } else if (msg->type == CPC_MSG_TYPE_CAN_FRAME_ERROR) {
357702171adSSebastian Haas u8 ecc = msg->msg.error.cc.regs.sja1000.ecc;
358702171adSSebastian Haas u8 txerr = msg->msg.error.cc.regs.sja1000.txerr;
359702171adSSebastian Haas u8 rxerr = msg->msg.error.cc.regs.sja1000.rxerr;
360702171adSSebastian Haas
361702171adSSebastian Haas /* bus error interrupt */
362702171adSSebastian Haas dev->can.can_stats.bus_error++;
363702171adSSebastian Haas
364*c7f3a539SDario Binacchi if (skb) {
365702171adSSebastian Haas cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
366702171adSSebastian Haas
367702171adSSebastian Haas switch (ecc & SJA1000_ECC_MASK) {
368702171adSSebastian Haas case SJA1000_ECC_BIT:
369702171adSSebastian Haas cf->data[2] |= CAN_ERR_PROT_BIT;
370702171adSSebastian Haas break;
371702171adSSebastian Haas case SJA1000_ECC_FORM:
372702171adSSebastian Haas cf->data[2] |= CAN_ERR_PROT_FORM;
373702171adSSebastian Haas break;
374702171adSSebastian Haas case SJA1000_ECC_STUFF:
375702171adSSebastian Haas cf->data[2] |= CAN_ERR_PROT_STUFF;
376702171adSSebastian Haas break;
377702171adSSebastian Haas default:
378702171adSSebastian Haas cf->data[3] = ecc & SJA1000_ECC_SEG;
379702171adSSebastian Haas break;
380702171adSSebastian Haas }
381*c7f3a539SDario Binacchi }
382702171adSSebastian Haas
38325985edcSLucas De Marchi /* Error occurred during transmission? */
384*c7f3a539SDario Binacchi if ((ecc & SJA1000_ECC_DIR) == 0) {
385*c7f3a539SDario Binacchi stats->tx_errors++;
386*c7f3a539SDario Binacchi if (skb)
387702171adSSebastian Haas cf->data[2] |= CAN_ERR_PROT_TX;
388*c7f3a539SDario Binacchi } else {
389*c7f3a539SDario Binacchi stats->rx_errors++;
390*c7f3a539SDario Binacchi }
391702171adSSebastian Haas
392*c7f3a539SDario Binacchi if (skb && (dev->can.state == CAN_STATE_ERROR_WARNING ||
393*c7f3a539SDario Binacchi dev->can.state == CAN_STATE_ERROR_PASSIVE)) {
3946ebc5e8fSMartin Lederhilger cf->can_id |= CAN_ERR_CRTL;
395702171adSSebastian Haas cf->data[1] = (txerr > rxerr) ?
396702171adSSebastian Haas CAN_ERR_CRTL_TX_PASSIVE : CAN_ERR_CRTL_RX_PASSIVE;
397702171adSSebastian Haas }
398702171adSSebastian Haas } else if (msg->type == CPC_MSG_TYPE_OVERRUN) {
399*c7f3a539SDario Binacchi if (skb) {
400702171adSSebastian Haas cf->can_id |= CAN_ERR_CRTL;
401702171adSSebastian Haas cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
402*c7f3a539SDario Binacchi }
403702171adSSebastian Haas
404702171adSSebastian Haas stats->rx_over_errors++;
405702171adSSebastian Haas stats->rx_errors++;
406702171adSSebastian Haas }
407702171adSSebastian Haas
408*c7f3a539SDario Binacchi if (skb)
40943c021e8SMarc Kleine-Budde netif_rx(skb);
410702171adSSebastian Haas }
411702171adSSebastian Haas
412702171adSSebastian Haas /*
413702171adSSebastian Haas * callback for bulk IN urb
414702171adSSebastian Haas */
ems_usb_read_bulk_callback(struct urb * urb)415702171adSSebastian Haas static void ems_usb_read_bulk_callback(struct urb *urb)
416702171adSSebastian Haas {
417702171adSSebastian Haas struct ems_usb *dev = urb->context;
418702171adSSebastian Haas struct net_device *netdev;
419702171adSSebastian Haas int retval;
420702171adSSebastian Haas
421702171adSSebastian Haas netdev = dev->netdev;
422702171adSSebastian Haas
423702171adSSebastian Haas if (!netif_device_present(netdev))
424702171adSSebastian Haas return;
425702171adSSebastian Haas
426702171adSSebastian Haas switch (urb->status) {
427702171adSSebastian Haas case 0: /* success */
428702171adSSebastian Haas break;
429702171adSSebastian Haas
430702171adSSebastian Haas case -ENOENT:
431702171adSSebastian Haas return;
432702171adSSebastian Haas
433702171adSSebastian Haas default:
434aabdfd6aSWolfgang Grandegger netdev_info(netdev, "Rx URB aborted (%d)\n", urb->status);
435702171adSSebastian Haas goto resubmit_urb;
436702171adSSebastian Haas }
437702171adSSebastian Haas
438702171adSSebastian Haas if (urb->actual_length > CPC_HEADER_SIZE) {
439702171adSSebastian Haas struct ems_cpc_msg *msg;
440702171adSSebastian Haas u8 *ibuf = urb->transfer_buffer;
4414e2061b1SSudip Mukherjee u8 msg_count, start;
442702171adSSebastian Haas
443702171adSSebastian Haas msg_count = ibuf[0] & ~0x80;
444702171adSSebastian Haas
445702171adSSebastian Haas start = CPC_HEADER_SIZE;
446702171adSSebastian Haas
447702171adSSebastian Haas while (msg_count) {
448702171adSSebastian Haas msg = (struct ems_cpc_msg *)&ibuf[start];
449702171adSSebastian Haas
450702171adSSebastian Haas switch (msg->type) {
451702171adSSebastian Haas case CPC_MSG_TYPE_CAN_STATE:
452702171adSSebastian Haas /* Process CAN state changes */
453702171adSSebastian Haas ems_usb_rx_err(dev, msg);
454702171adSSebastian Haas break;
455702171adSSebastian Haas
456702171adSSebastian Haas case CPC_MSG_TYPE_CAN_FRAME:
457702171adSSebastian Haas case CPC_MSG_TYPE_EXT_CAN_FRAME:
458702171adSSebastian Haas case CPC_MSG_TYPE_RTR_FRAME:
459702171adSSebastian Haas case CPC_MSG_TYPE_EXT_RTR_FRAME:
460702171adSSebastian Haas ems_usb_rx_can_msg(dev, msg);
461702171adSSebastian Haas break;
462702171adSSebastian Haas
463702171adSSebastian Haas case CPC_MSG_TYPE_CAN_FRAME_ERROR:
464702171adSSebastian Haas /* Process errorframe */
465702171adSSebastian Haas ems_usb_rx_err(dev, msg);
466702171adSSebastian Haas break;
467702171adSSebastian Haas
468702171adSSebastian Haas case CPC_MSG_TYPE_OVERRUN:
469702171adSSebastian Haas /* Message lost while receiving */
470702171adSSebastian Haas ems_usb_rx_err(dev, msg);
471702171adSSebastian Haas break;
472702171adSSebastian Haas }
473702171adSSebastian Haas
474702171adSSebastian Haas start += CPC_MSG_HEADER_LEN + msg->length;
475702171adSSebastian Haas msg_count--;
476702171adSSebastian Haas
477702171adSSebastian Haas if (start > urb->transfer_buffer_length) {
478aabdfd6aSWolfgang Grandegger netdev_err(netdev, "format error\n");
479702171adSSebastian Haas break;
480702171adSSebastian Haas }
481702171adSSebastian Haas }
482702171adSSebastian Haas }
483702171adSSebastian Haas
484702171adSSebastian Haas resubmit_urb:
485702171adSSebastian Haas usb_fill_bulk_urb(urb, dev->udev, usb_rcvbulkpipe(dev->udev, 2),
486702171adSSebastian Haas urb->transfer_buffer, RX_BUFFER_SIZE,
487702171adSSebastian Haas ems_usb_read_bulk_callback, dev);
488702171adSSebastian Haas
489702171adSSebastian Haas retval = usb_submit_urb(urb, GFP_ATOMIC);
490702171adSSebastian Haas
491702171adSSebastian Haas if (retval == -ENODEV)
492702171adSSebastian Haas netif_device_detach(netdev);
493702171adSSebastian Haas else if (retval)
494aabdfd6aSWolfgang Grandegger netdev_err(netdev,
495702171adSSebastian Haas "failed resubmitting read bulk urb: %d\n", retval);
496702171adSSebastian Haas }
497702171adSSebastian Haas
498702171adSSebastian Haas /*
499702171adSSebastian Haas * callback for bulk IN urb
500702171adSSebastian Haas */
ems_usb_write_bulk_callback(struct urb * urb)501702171adSSebastian Haas static void ems_usb_write_bulk_callback(struct urb *urb)
502702171adSSebastian Haas {
503702171adSSebastian Haas struct ems_tx_urb_context *context = urb->context;
504702171adSSebastian Haas struct ems_usb *dev;
505702171adSSebastian Haas struct net_device *netdev;
506702171adSSebastian Haas
507702171adSSebastian Haas BUG_ON(!context);
508702171adSSebastian Haas
509702171adSSebastian Haas dev = context->dev;
510702171adSSebastian Haas netdev = dev->netdev;
511702171adSSebastian Haas
512702171adSSebastian Haas /* free up our allocated buffer */
513997ea58eSDaniel Mack usb_free_coherent(urb->dev, urb->transfer_buffer_length,
514702171adSSebastian Haas urb->transfer_buffer, urb->transfer_dma);
515702171adSSebastian Haas
516702171adSSebastian Haas atomic_dec(&dev->active_tx_urbs);
517702171adSSebastian Haas
518702171adSSebastian Haas if (!netif_device_present(netdev))
519702171adSSebastian Haas return;
520702171adSSebastian Haas
521702171adSSebastian Haas if (urb->status)
522aabdfd6aSWolfgang Grandegger netdev_info(netdev, "Tx URB aborted (%d)\n", urb->status);
523702171adSSebastian Haas
524860e9538SFlorian Westphal netif_trans_update(netdev);
525702171adSSebastian Haas
526702171adSSebastian Haas /* transmission complete interrupt */
527702171adSSebastian Haas netdev->stats.tx_packets++;
528cc4b08c3SVincent Mailhol netdev->stats.tx_bytes += can_get_echo_skb(netdev, context->echo_index,
529cc4b08c3SVincent Mailhol NULL);
530702171adSSebastian Haas
531702171adSSebastian Haas /* Release context */
532702171adSSebastian Haas context->echo_index = MAX_TX_URBS;
533702171adSSebastian Haas
534702171adSSebastian Haas }
535702171adSSebastian Haas
536702171adSSebastian Haas /*
537702171adSSebastian Haas * Send the given CPC command synchronously
538702171adSSebastian Haas */
ems_usb_command_msg(struct ems_usb * dev,struct ems_cpc_msg * msg)539702171adSSebastian Haas static int ems_usb_command_msg(struct ems_usb *dev, struct ems_cpc_msg *msg)
540702171adSSebastian Haas {
541702171adSSebastian Haas int actual_length;
542702171adSSebastian Haas
543702171adSSebastian Haas /* Copy payload */
544702171adSSebastian Haas memcpy(&dev->tx_msg_buffer[CPC_HEADER_SIZE], msg,
545702171adSSebastian Haas msg->length + CPC_MSG_HEADER_LEN);
546702171adSSebastian Haas
547702171adSSebastian Haas /* Clear header */
548702171adSSebastian Haas memset(&dev->tx_msg_buffer[0], 0, CPC_HEADER_SIZE);
549702171adSSebastian Haas
550702171adSSebastian Haas return usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 2),
551702171adSSebastian Haas &dev->tx_msg_buffer[0],
552702171adSSebastian Haas msg->length + CPC_MSG_HEADER_LEN + CPC_HEADER_SIZE,
553702171adSSebastian Haas &actual_length, 1000);
554702171adSSebastian Haas }
555702171adSSebastian Haas
556702171adSSebastian Haas /*
557702171adSSebastian Haas * Change CAN controllers' mode register
558702171adSSebastian Haas */
ems_usb_write_mode(struct ems_usb * dev,u8 mode)559702171adSSebastian Haas static int ems_usb_write_mode(struct ems_usb *dev, u8 mode)
560702171adSSebastian Haas {
561702171adSSebastian Haas dev->active_params.msg.can_params.cc_params.sja1000.mode = mode;
562702171adSSebastian Haas
563702171adSSebastian Haas return ems_usb_command_msg(dev, &dev->active_params);
564702171adSSebastian Haas }
565702171adSSebastian Haas
566702171adSSebastian Haas /*
567702171adSSebastian Haas * Send a CPC_Control command to change behaviour when interface receives a CAN
568702171adSSebastian Haas * message, bus error or CAN state changed notifications.
569702171adSSebastian Haas */
ems_usb_control_cmd(struct ems_usb * dev,u8 val)570702171adSSebastian Haas static int ems_usb_control_cmd(struct ems_usb *dev, u8 val)
571702171adSSebastian Haas {
572702171adSSebastian Haas struct ems_cpc_msg cmd;
573702171adSSebastian Haas
574702171adSSebastian Haas cmd.type = CPC_CMD_TYPE_CONTROL;
575702171adSSebastian Haas cmd.length = CPC_MSG_HEADER_LEN + 1;
576702171adSSebastian Haas
577702171adSSebastian Haas cmd.msgid = 0;
578702171adSSebastian Haas
579702171adSSebastian Haas cmd.msg.generic[0] = val;
580702171adSSebastian Haas
581702171adSSebastian Haas return ems_usb_command_msg(dev, &cmd);
582702171adSSebastian Haas }
583702171adSSebastian Haas
584702171adSSebastian Haas /*
585702171adSSebastian Haas * Start interface
586702171adSSebastian Haas */
ems_usb_start(struct ems_usb * dev)587702171adSSebastian Haas static int ems_usb_start(struct ems_usb *dev)
588702171adSSebastian Haas {
589702171adSSebastian Haas struct net_device *netdev = dev->netdev;
590702171adSSebastian Haas int err, i;
591702171adSSebastian Haas
592702171adSSebastian Haas dev->intr_in_buffer[0] = 0;
59390cfde46SGerhard Uttenthaler dev->free_slots = 50; /* initial size */
594702171adSSebastian Haas
595702171adSSebastian Haas for (i = 0; i < MAX_RX_URBS; i++) {
596702171adSSebastian Haas struct urb *urb = NULL;
597702171adSSebastian Haas u8 *buf = NULL;
5989969e3c5SPavel Skripkin dma_addr_t buf_dma;
599702171adSSebastian Haas
600702171adSSebastian Haas /* create a URB, and a buffer for it */
601702171adSSebastian Haas urb = usb_alloc_urb(0, GFP_KERNEL);
602702171adSSebastian Haas if (!urb) {
6032ee6850cSSebastian Haas err = -ENOMEM;
6042ee6850cSSebastian Haas break;
605702171adSSebastian Haas }
606702171adSSebastian Haas
607997ea58eSDaniel Mack buf = usb_alloc_coherent(dev->udev, RX_BUFFER_SIZE, GFP_KERNEL,
6089969e3c5SPavel Skripkin &buf_dma);
609702171adSSebastian Haas if (!buf) {
610aabdfd6aSWolfgang Grandegger netdev_err(netdev, "No memory left for USB buffer\n");
611702171adSSebastian Haas usb_free_urb(urb);
6122ee6850cSSebastian Haas err = -ENOMEM;
6132ee6850cSSebastian Haas break;
614702171adSSebastian Haas }
615702171adSSebastian Haas
6169969e3c5SPavel Skripkin urb->transfer_dma = buf_dma;
6179969e3c5SPavel Skripkin
618702171adSSebastian Haas usb_fill_bulk_urb(urb, dev->udev, usb_rcvbulkpipe(dev->udev, 2),
619702171adSSebastian Haas buf, RX_BUFFER_SIZE,
620702171adSSebastian Haas ems_usb_read_bulk_callback, dev);
621702171adSSebastian Haas urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
622702171adSSebastian Haas usb_anchor_urb(urb, &dev->rx_submitted);
623702171adSSebastian Haas
624702171adSSebastian Haas err = usb_submit_urb(urb, GFP_KERNEL);
625702171adSSebastian Haas if (err) {
626702171adSSebastian Haas usb_unanchor_urb(urb);
627997ea58eSDaniel Mack usb_free_coherent(dev->udev, RX_BUFFER_SIZE, buf,
628702171adSSebastian Haas urb->transfer_dma);
629a1c31f1dSAlexey Khoroshilov usb_free_urb(urb);
630702171adSSebastian Haas break;
631702171adSSebastian Haas }
632702171adSSebastian Haas
6339969e3c5SPavel Skripkin dev->rxbuf[i] = buf;
6349969e3c5SPavel Skripkin dev->rxbuf_dma[i] = buf_dma;
6359969e3c5SPavel Skripkin
636702171adSSebastian Haas /* Drop reference, USB core will take care of freeing it */
637702171adSSebastian Haas usb_free_urb(urb);
638702171adSSebastian Haas }
639702171adSSebastian Haas
640702171adSSebastian Haas /* Did we submit any URBs */
641702171adSSebastian Haas if (i == 0) {
642aabdfd6aSWolfgang Grandegger netdev_warn(netdev, "couldn't setup read URBs\n");
643702171adSSebastian Haas return err;
644702171adSSebastian Haas }
645702171adSSebastian Haas
646702171adSSebastian Haas /* Warn if we've couldn't transmit all the URBs */
647702171adSSebastian Haas if (i < MAX_RX_URBS)
648aabdfd6aSWolfgang Grandegger netdev_warn(netdev, "rx performance may be slow\n");
649702171adSSebastian Haas
650702171adSSebastian Haas /* Setup and start interrupt URB */
651702171adSSebastian Haas usb_fill_int_urb(dev->intr_urb, dev->udev,
652702171adSSebastian Haas usb_rcvintpipe(dev->udev, 1),
653702171adSSebastian Haas dev->intr_in_buffer,
654702171adSSebastian Haas INTR_IN_BUFFER_SIZE,
655702171adSSebastian Haas ems_usb_read_interrupt_callback, dev, 1);
656702171adSSebastian Haas
657702171adSSebastian Haas err = usb_submit_urb(dev->intr_urb, GFP_KERNEL);
658702171adSSebastian Haas if (err) {
659aabdfd6aSWolfgang Grandegger netdev_warn(netdev, "intr URB submit failed: %d\n", err);
660702171adSSebastian Haas
661702171adSSebastian Haas return err;
662702171adSSebastian Haas }
663702171adSSebastian Haas
664702171adSSebastian Haas /* CPC-USB will transfer received message to host */
665702171adSSebastian Haas err = ems_usb_control_cmd(dev, CONTR_CAN_MESSAGE | CONTR_CONT_ON);
666702171adSSebastian Haas if (err)
667702171adSSebastian Haas goto failed;
668702171adSSebastian Haas
669702171adSSebastian Haas /* CPC-USB will transfer CAN state changes to host */
670702171adSSebastian Haas err = ems_usb_control_cmd(dev, CONTR_CAN_STATE | CONTR_CONT_ON);
671702171adSSebastian Haas if (err)
672702171adSSebastian Haas goto failed;
673702171adSSebastian Haas
674702171adSSebastian Haas /* CPC-USB will transfer bus errors to host */
675702171adSSebastian Haas err = ems_usb_control_cmd(dev, CONTR_BUS_ERROR | CONTR_CONT_ON);
676702171adSSebastian Haas if (err)
677702171adSSebastian Haas goto failed;
678702171adSSebastian Haas
679702171adSSebastian Haas err = ems_usb_write_mode(dev, SJA1000_MOD_NORMAL);
680702171adSSebastian Haas if (err)
681702171adSSebastian Haas goto failed;
682702171adSSebastian Haas
683702171adSSebastian Haas dev->can.state = CAN_STATE_ERROR_ACTIVE;
684702171adSSebastian Haas
685702171adSSebastian Haas return 0;
686702171adSSebastian Haas
687702171adSSebastian Haas failed:
688aabdfd6aSWolfgang Grandegger netdev_warn(netdev, "couldn't submit control: %d\n", err);
689702171adSSebastian Haas
690702171adSSebastian Haas return err;
691702171adSSebastian Haas }
692702171adSSebastian Haas
unlink_all_urbs(struct ems_usb * dev)693702171adSSebastian Haas static void unlink_all_urbs(struct ems_usb *dev)
694702171adSSebastian Haas {
695702171adSSebastian Haas int i;
696702171adSSebastian Haas
697702171adSSebastian Haas usb_unlink_urb(dev->intr_urb);
698702171adSSebastian Haas
699702171adSSebastian Haas usb_kill_anchored_urbs(&dev->rx_submitted);
700702171adSSebastian Haas
7019969e3c5SPavel Skripkin for (i = 0; i < MAX_RX_URBS; ++i)
7029969e3c5SPavel Skripkin usb_free_coherent(dev->udev, RX_BUFFER_SIZE,
7039969e3c5SPavel Skripkin dev->rxbuf[i], dev->rxbuf_dma[i]);
7049969e3c5SPavel Skripkin
705702171adSSebastian Haas usb_kill_anchored_urbs(&dev->tx_submitted);
706702171adSSebastian Haas atomic_set(&dev->active_tx_urbs, 0);
707702171adSSebastian Haas
708702171adSSebastian Haas for (i = 0; i < MAX_TX_URBS; i++)
709702171adSSebastian Haas dev->tx_contexts[i].echo_index = MAX_TX_URBS;
710702171adSSebastian Haas }
711702171adSSebastian Haas
ems_usb_open(struct net_device * netdev)712702171adSSebastian Haas static int ems_usb_open(struct net_device *netdev)
713702171adSSebastian Haas {
714702171adSSebastian Haas struct ems_usb *dev = netdev_priv(netdev);
715702171adSSebastian Haas int err;
716702171adSSebastian Haas
717702171adSSebastian Haas err = ems_usb_write_mode(dev, SJA1000_MOD_RM);
718702171adSSebastian Haas if (err)
719702171adSSebastian Haas return err;
720702171adSSebastian Haas
721702171adSSebastian Haas /* common open */
722702171adSSebastian Haas err = open_candev(netdev);
723702171adSSebastian Haas if (err)
724702171adSSebastian Haas return err;
725702171adSSebastian Haas
726702171adSSebastian Haas /* finally start device */
727702171adSSebastian Haas err = ems_usb_start(dev);
728702171adSSebastian Haas if (err) {
729702171adSSebastian Haas if (err == -ENODEV)
730702171adSSebastian Haas netif_device_detach(dev->netdev);
731702171adSSebastian Haas
732aabdfd6aSWolfgang Grandegger netdev_warn(netdev, "couldn't start device: %d\n", err);
733702171adSSebastian Haas
734702171adSSebastian Haas close_candev(netdev);
735702171adSSebastian Haas
736702171adSSebastian Haas return err;
737702171adSSebastian Haas }
738702171adSSebastian Haas
739702171adSSebastian Haas
740702171adSSebastian Haas netif_start_queue(netdev);
741702171adSSebastian Haas
742702171adSSebastian Haas return 0;
743702171adSSebastian Haas }
744702171adSSebastian Haas
ems_usb_start_xmit(struct sk_buff * skb,struct net_device * netdev)745702171adSSebastian Haas static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *netdev)
746702171adSSebastian Haas {
747702171adSSebastian Haas struct ems_usb *dev = netdev_priv(netdev);
748702171adSSebastian Haas struct ems_tx_urb_context *context = NULL;
749702171adSSebastian Haas struct net_device_stats *stats = &netdev->stats;
750702171adSSebastian Haas struct can_frame *cf = (struct can_frame *)skb->data;
751702171adSSebastian Haas struct ems_cpc_msg *msg;
752702171adSSebastian Haas struct urb *urb;
753702171adSSebastian Haas u8 *buf;
754702171adSSebastian Haas int i, err;
755702171adSSebastian Haas size_t size = CPC_HEADER_SIZE + CPC_MSG_HEADER_LEN
756702171adSSebastian Haas + sizeof(struct cpc_can_msg);
757702171adSSebastian Haas
758ae64438bSOliver Hartkopp if (can_dev_dropped_skb(netdev, skb))
7593ccd4c61SOliver Hartkopp return NETDEV_TX_OK;
7603ccd4c61SOliver Hartkopp
761702171adSSebastian Haas /* create a URB, and a buffer for it, and copy the data to the URB */
762702171adSSebastian Haas urb = usb_alloc_urb(0, GFP_ATOMIC);
76387ced2f9SWolfram Sang if (!urb)
764702171adSSebastian Haas goto nomem;
765702171adSSebastian Haas
766997ea58eSDaniel Mack buf = usb_alloc_coherent(dev->udev, size, GFP_ATOMIC, &urb->transfer_dma);
767702171adSSebastian Haas if (!buf) {
768aabdfd6aSWolfgang Grandegger netdev_err(netdev, "No memory left for USB buffer\n");
769702171adSSebastian Haas usb_free_urb(urb);
770702171adSSebastian Haas goto nomem;
771702171adSSebastian Haas }
772702171adSSebastian Haas
773702171adSSebastian Haas msg = (struct ems_cpc_msg *)&buf[CPC_HEADER_SIZE];
774702171adSSebastian Haas
7758a4b5b0fSGerhard Uttenthaler msg->msg.can_msg.id = cpu_to_le32(cf->can_id & CAN_ERR_MASK);
776c7b74967SOliver Hartkopp msg->msg.can_msg.length = cf->len;
777702171adSSebastian Haas
778702171adSSebastian Haas if (cf->can_id & CAN_RTR_FLAG) {
779702171adSSebastian Haas msg->type = cf->can_id & CAN_EFF_FLAG ?
780702171adSSebastian Haas CPC_CMD_TYPE_EXT_RTR_FRAME : CPC_CMD_TYPE_RTR_FRAME;
781702171adSSebastian Haas
782702171adSSebastian Haas msg->length = CPC_CAN_MSG_MIN_SIZE;
783702171adSSebastian Haas } else {
784702171adSSebastian Haas msg->type = cf->can_id & CAN_EFF_FLAG ?
785702171adSSebastian Haas CPC_CMD_TYPE_EXT_CAN_FRAME : CPC_CMD_TYPE_CAN_FRAME;
786702171adSSebastian Haas
787c7b74967SOliver Hartkopp for (i = 0; i < cf->len; i++)
788702171adSSebastian Haas msg->msg.can_msg.msg[i] = cf->data[i];
789702171adSSebastian Haas
790c7b74967SOliver Hartkopp msg->length = CPC_CAN_MSG_MIN_SIZE + cf->len;
791702171adSSebastian Haas }
792702171adSSebastian Haas
793702171adSSebastian Haas for (i = 0; i < MAX_TX_URBS; i++) {
794702171adSSebastian Haas if (dev->tx_contexts[i].echo_index == MAX_TX_URBS) {
795702171adSSebastian Haas context = &dev->tx_contexts[i];
796702171adSSebastian Haas break;
797702171adSSebastian Haas }
798702171adSSebastian Haas }
799702171adSSebastian Haas
800702171adSSebastian Haas /*
801702171adSSebastian Haas * May never happen! When this happens we'd more URBs in flight as
802702171adSSebastian Haas * allowed (MAX_TX_URBS).
803702171adSSebastian Haas */
804702171adSSebastian Haas if (!context) {
805997ea58eSDaniel Mack usb_free_coherent(dev->udev, size, buf, urb->transfer_dma);
806a1c31f1dSAlexey Khoroshilov usb_free_urb(urb);
807702171adSSebastian Haas
808aabdfd6aSWolfgang Grandegger netdev_warn(netdev, "couldn't find free context\n");
809702171adSSebastian Haas
810702171adSSebastian Haas return NETDEV_TX_BUSY;
811702171adSSebastian Haas }
812702171adSSebastian Haas
813702171adSSebastian Haas context->dev = dev;
814702171adSSebastian Haas context->echo_index = i;
815702171adSSebastian Haas
816702171adSSebastian Haas usb_fill_bulk_urb(urb, dev->udev, usb_sndbulkpipe(dev->udev, 2), buf,
817702171adSSebastian Haas size, ems_usb_write_bulk_callback, context);
818702171adSSebastian Haas urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
819702171adSSebastian Haas usb_anchor_urb(urb, &dev->tx_submitted);
820702171adSSebastian Haas
8211dcb6e57SVincent Mailhol can_put_echo_skb(skb, netdev, context->echo_index, 0);
822702171adSSebastian Haas
823702171adSSebastian Haas atomic_inc(&dev->active_tx_urbs);
824702171adSSebastian Haas
825702171adSSebastian Haas err = usb_submit_urb(urb, GFP_ATOMIC);
826702171adSSebastian Haas if (unlikely(err)) {
827f318482aSMarc Kleine-Budde can_free_echo_skb(netdev, context->echo_index, NULL);
828702171adSSebastian Haas
829702171adSSebastian Haas usb_unanchor_urb(urb);
830997ea58eSDaniel Mack usb_free_coherent(dev->udev, size, buf, urb->transfer_dma);
831702171adSSebastian Haas
832702171adSSebastian Haas atomic_dec(&dev->active_tx_urbs);
833702171adSSebastian Haas
834702171adSSebastian Haas if (err == -ENODEV) {
835702171adSSebastian Haas netif_device_detach(netdev);
836702171adSSebastian Haas } else {
837aabdfd6aSWolfgang Grandegger netdev_warn(netdev, "failed tx_urb %d\n", err);
838702171adSSebastian Haas
839702171adSSebastian Haas stats->tx_dropped++;
840702171adSSebastian Haas }
841702171adSSebastian Haas } else {
842860e9538SFlorian Westphal netif_trans_update(netdev);
843702171adSSebastian Haas
844702171adSSebastian Haas /* Slow down tx path */
845702171adSSebastian Haas if (atomic_read(&dev->active_tx_urbs) >= MAX_TX_URBS ||
84690cfde46SGerhard Uttenthaler dev->free_slots < CPC_TX_QUEUE_TRIGGER_LOW) {
847702171adSSebastian Haas netif_stop_queue(netdev);
848702171adSSebastian Haas }
849702171adSSebastian Haas }
850702171adSSebastian Haas
851702171adSSebastian Haas /*
852702171adSSebastian Haas * Release our reference to this URB, the USB core will eventually free
853702171adSSebastian Haas * it entirely.
854702171adSSebastian Haas */
855702171adSSebastian Haas usb_free_urb(urb);
856702171adSSebastian Haas
857702171adSSebastian Haas return NETDEV_TX_OK;
858702171adSSebastian Haas
859702171adSSebastian Haas nomem:
860702171adSSebastian Haas dev_kfree_skb(skb);
861702171adSSebastian Haas stats->tx_dropped++;
862702171adSSebastian Haas
863702171adSSebastian Haas return NETDEV_TX_OK;
864702171adSSebastian Haas }
865702171adSSebastian Haas
ems_usb_close(struct net_device * netdev)866702171adSSebastian Haas static int ems_usb_close(struct net_device *netdev)
867702171adSSebastian Haas {
868702171adSSebastian Haas struct ems_usb *dev = netdev_priv(netdev);
869702171adSSebastian Haas
870702171adSSebastian Haas /* Stop polling */
871702171adSSebastian Haas unlink_all_urbs(dev);
872702171adSSebastian Haas
873702171adSSebastian Haas netif_stop_queue(netdev);
874702171adSSebastian Haas
875702171adSSebastian Haas /* Set CAN controller to reset mode */
876702171adSSebastian Haas if (ems_usb_write_mode(dev, SJA1000_MOD_RM))
877aabdfd6aSWolfgang Grandegger netdev_warn(netdev, "couldn't stop device");
878702171adSSebastian Haas
879702171adSSebastian Haas close_candev(netdev);
880702171adSSebastian Haas
881702171adSSebastian Haas return 0;
882702171adSSebastian Haas }
883702171adSSebastian Haas
884702171adSSebastian Haas static const struct net_device_ops ems_usb_netdev_ops = {
885702171adSSebastian Haas .ndo_open = ems_usb_open,
886702171adSSebastian Haas .ndo_stop = ems_usb_close,
887702171adSSebastian Haas .ndo_start_xmit = ems_usb_start_xmit,
888c971fa2aSOliver Hartkopp .ndo_change_mtu = can_change_mtu,
889702171adSSebastian Haas };
890702171adSSebastian Haas
891409c188cSVincent Mailhol static const struct ethtool_ops ems_usb_ethtool_ops = {
892409c188cSVincent Mailhol .get_ts_info = ethtool_op_get_ts_info,
893409c188cSVincent Mailhol };
894409c188cSVincent Mailhol
895194b9a4cSMarc Kleine-Budde static const struct can_bittiming_const ems_usb_bittiming_const = {
896f60df831SVincent Mailhol .name = KBUILD_MODNAME,
897702171adSSebastian Haas .tseg1_min = 1,
898702171adSSebastian Haas .tseg1_max = 16,
899702171adSSebastian Haas .tseg2_min = 1,
900702171adSSebastian Haas .tseg2_max = 8,
901702171adSSebastian Haas .sjw_max = 4,
902702171adSSebastian Haas .brp_min = 1,
903702171adSSebastian Haas .brp_max = 64,
904702171adSSebastian Haas .brp_inc = 1,
905702171adSSebastian Haas };
906702171adSSebastian Haas
ems_usb_set_mode(struct net_device * netdev,enum can_mode mode)907702171adSSebastian Haas static int ems_usb_set_mode(struct net_device *netdev, enum can_mode mode)
908702171adSSebastian Haas {
909702171adSSebastian Haas struct ems_usb *dev = netdev_priv(netdev);
910702171adSSebastian Haas
911702171adSSebastian Haas switch (mode) {
912702171adSSebastian Haas case CAN_MODE_START:
913702171adSSebastian Haas if (ems_usb_write_mode(dev, SJA1000_MOD_NORMAL))
914aabdfd6aSWolfgang Grandegger netdev_warn(netdev, "couldn't start device");
915702171adSSebastian Haas
916702171adSSebastian Haas if (netif_queue_stopped(netdev))
917702171adSSebastian Haas netif_wake_queue(netdev);
918702171adSSebastian Haas break;
919702171adSSebastian Haas
920702171adSSebastian Haas default:
921702171adSSebastian Haas return -EOPNOTSUPP;
922702171adSSebastian Haas }
923702171adSSebastian Haas
924702171adSSebastian Haas return 0;
925702171adSSebastian Haas }
926702171adSSebastian Haas
ems_usb_set_bittiming(struct net_device * netdev)927702171adSSebastian Haas static int ems_usb_set_bittiming(struct net_device *netdev)
928702171adSSebastian Haas {
929702171adSSebastian Haas struct ems_usb *dev = netdev_priv(netdev);
930702171adSSebastian Haas struct can_bittiming *bt = &dev->can.bittiming;
931702171adSSebastian Haas u8 btr0, btr1;
932702171adSSebastian Haas
933702171adSSebastian Haas btr0 = ((bt->brp - 1) & 0x3f) | (((bt->sjw - 1) & 0x3) << 6);
934702171adSSebastian Haas btr1 = ((bt->prop_seg + bt->phase_seg1 - 1) & 0xf) |
935702171adSSebastian Haas (((bt->phase_seg2 - 1) & 0x7) << 4);
936702171adSSebastian Haas if (dev->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
937702171adSSebastian Haas btr1 |= 0x80;
938702171adSSebastian Haas
939aabdfd6aSWolfgang Grandegger netdev_info(netdev, "setting BTR0=0x%02x BTR1=0x%02x\n", btr0, btr1);
940702171adSSebastian Haas
941702171adSSebastian Haas dev->active_params.msg.can_params.cc_params.sja1000.btr0 = btr0;
942702171adSSebastian Haas dev->active_params.msg.can_params.cc_params.sja1000.btr1 = btr1;
943702171adSSebastian Haas
944702171adSSebastian Haas return ems_usb_command_msg(dev, &dev->active_params);
945702171adSSebastian Haas }
946702171adSSebastian Haas
init_params_sja1000(struct ems_cpc_msg * msg)947702171adSSebastian Haas static void init_params_sja1000(struct ems_cpc_msg *msg)
948702171adSSebastian Haas {
949702171adSSebastian Haas struct cpc_sja1000_params *sja1000 =
950702171adSSebastian Haas &msg->msg.can_params.cc_params.sja1000;
951702171adSSebastian Haas
952702171adSSebastian Haas msg->type = CPC_CMD_TYPE_CAN_PARAMS;
953702171adSSebastian Haas msg->length = sizeof(struct cpc_can_params);
954702171adSSebastian Haas msg->msgid = 0;
955702171adSSebastian Haas
956702171adSSebastian Haas msg->msg.can_params.cc_type = CPC_CC_TYPE_SJA1000;
957702171adSSebastian Haas
958702171adSSebastian Haas /* Acceptance filter open */
959702171adSSebastian Haas sja1000->acc_code0 = 0x00;
960702171adSSebastian Haas sja1000->acc_code1 = 0x00;
961702171adSSebastian Haas sja1000->acc_code2 = 0x00;
962702171adSSebastian Haas sja1000->acc_code3 = 0x00;
963702171adSSebastian Haas
964702171adSSebastian Haas /* Acceptance filter open */
965702171adSSebastian Haas sja1000->acc_mask0 = 0xFF;
966702171adSSebastian Haas sja1000->acc_mask1 = 0xFF;
967702171adSSebastian Haas sja1000->acc_mask2 = 0xFF;
968702171adSSebastian Haas sja1000->acc_mask3 = 0xFF;
969702171adSSebastian Haas
970702171adSSebastian Haas sja1000->btr0 = 0;
971702171adSSebastian Haas sja1000->btr1 = 0;
972702171adSSebastian Haas
973702171adSSebastian Haas sja1000->outp_contr = SJA1000_DEFAULT_OUTPUT_CONTROL;
974702171adSSebastian Haas sja1000->mode = SJA1000_MOD_RM;
975702171adSSebastian Haas }
976702171adSSebastian Haas
977702171adSSebastian Haas /*
978702171adSSebastian Haas * probe function for new CPC-USB devices
979702171adSSebastian Haas */
ems_usb_probe(struct usb_interface * intf,const struct usb_device_id * id)980702171adSSebastian Haas static int ems_usb_probe(struct usb_interface *intf,
981702171adSSebastian Haas const struct usb_device_id *id)
982702171adSSebastian Haas {
983702171adSSebastian Haas struct net_device *netdev;
984702171adSSebastian Haas struct ems_usb *dev;
985702171adSSebastian Haas int i, err = -ENOMEM;
986702171adSSebastian Haas
987a6e4bc53SWolfgang Grandegger netdev = alloc_candev(sizeof(struct ems_usb), MAX_TX_URBS);
988702171adSSebastian Haas if (!netdev) {
9891c0b28b1SHans J. Koch dev_err(&intf->dev, "ems_usb: Couldn't alloc candev\n");
990702171adSSebastian Haas return -ENOMEM;
991702171adSSebastian Haas }
992702171adSSebastian Haas
993702171adSSebastian Haas dev = netdev_priv(netdev);
994702171adSSebastian Haas
995702171adSSebastian Haas dev->udev = interface_to_usbdev(intf);
996702171adSSebastian Haas dev->netdev = netdev;
997702171adSSebastian Haas
998702171adSSebastian Haas dev->can.state = CAN_STATE_STOPPED;
999702171adSSebastian Haas dev->can.clock.freq = EMS_USB_ARM7_CLOCK;
1000702171adSSebastian Haas dev->can.bittiming_const = &ems_usb_bittiming_const;
1001702171adSSebastian Haas dev->can.do_set_bittiming = ems_usb_set_bittiming;
1002702171adSSebastian Haas dev->can.do_set_mode = ems_usb_set_mode;
1003ad72c347SChristian Pellegrin dev->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;
1004702171adSSebastian Haas
1005702171adSSebastian Haas netdev->netdev_ops = &ems_usb_netdev_ops;
1006409c188cSVincent Mailhol netdev->ethtool_ops = &ems_usb_ethtool_ops;
1007702171adSSebastian Haas
1008702171adSSebastian Haas netdev->flags |= IFF_ECHO; /* we support local echo */
1009702171adSSebastian Haas
1010702171adSSebastian Haas init_usb_anchor(&dev->rx_submitted);
1011702171adSSebastian Haas
1012702171adSSebastian Haas init_usb_anchor(&dev->tx_submitted);
1013702171adSSebastian Haas atomic_set(&dev->active_tx_urbs, 0);
1014702171adSSebastian Haas
1015702171adSSebastian Haas for (i = 0; i < MAX_TX_URBS; i++)
1016702171adSSebastian Haas dev->tx_contexts[i].echo_index = MAX_TX_URBS;
1017702171adSSebastian Haas
1018702171adSSebastian Haas dev->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
101987ced2f9SWolfram Sang if (!dev->intr_urb)
1020702171adSSebastian Haas goto cleanup_candev;
1021702171adSSebastian Haas
1022702171adSSebastian Haas dev->intr_in_buffer = kzalloc(INTR_IN_BUFFER_SIZE, GFP_KERNEL);
102309da6c5fSJoe Perches if (!dev->intr_in_buffer)
1024702171adSSebastian Haas goto cleanup_intr_urb;
1025702171adSSebastian Haas
1026702171adSSebastian Haas dev->tx_msg_buffer = kzalloc(CPC_HEADER_SIZE +
1027702171adSSebastian Haas sizeof(struct ems_cpc_msg), GFP_KERNEL);
102814f8dc49SJoe Perches if (!dev->tx_msg_buffer)
1029702171adSSebastian Haas goto cleanup_intr_in_buffer;
1030702171adSSebastian Haas
1031702171adSSebastian Haas usb_set_intfdata(intf, dev);
1032702171adSSebastian Haas
1033702171adSSebastian Haas SET_NETDEV_DEV(netdev, &intf->dev);
1034702171adSSebastian Haas
1035702171adSSebastian Haas init_params_sja1000(&dev->active_params);
1036702171adSSebastian Haas
1037702171adSSebastian Haas err = ems_usb_command_msg(dev, &dev->active_params);
1038702171adSSebastian Haas if (err) {
1039aabdfd6aSWolfgang Grandegger netdev_err(netdev, "couldn't initialize controller: %d\n", err);
1040702171adSSebastian Haas goto cleanup_tx_msg_buffer;
1041702171adSSebastian Haas }
1042702171adSSebastian Haas
1043702171adSSebastian Haas err = register_candev(netdev);
1044702171adSSebastian Haas if (err) {
1045aabdfd6aSWolfgang Grandegger netdev_err(netdev, "couldn't register CAN device: %d\n", err);
1046702171adSSebastian Haas goto cleanup_tx_msg_buffer;
1047702171adSSebastian Haas }
1048702171adSSebastian Haas
1049702171adSSebastian Haas return 0;
1050702171adSSebastian Haas
1051702171adSSebastian Haas cleanup_tx_msg_buffer:
1052702171adSSebastian Haas kfree(dev->tx_msg_buffer);
1053702171adSSebastian Haas
1054702171adSSebastian Haas cleanup_intr_in_buffer:
1055702171adSSebastian Haas kfree(dev->intr_in_buffer);
1056702171adSSebastian Haas
1057702171adSSebastian Haas cleanup_intr_urb:
1058702171adSSebastian Haas usb_free_urb(dev->intr_urb);
1059702171adSSebastian Haas
1060702171adSSebastian Haas cleanup_candev:
1061702171adSSebastian Haas free_candev(netdev);
1062702171adSSebastian Haas
1063702171adSSebastian Haas return err;
1064702171adSSebastian Haas }
1065702171adSSebastian Haas
1066702171adSSebastian Haas /*
1067702171adSSebastian Haas * called by the usb core when the device is removed from the system
1068702171adSSebastian Haas */
ems_usb_disconnect(struct usb_interface * intf)1069702171adSSebastian Haas static void ems_usb_disconnect(struct usb_interface *intf)
1070702171adSSebastian Haas {
1071702171adSSebastian Haas struct ems_usb *dev = usb_get_intfdata(intf);
1072702171adSSebastian Haas
1073702171adSSebastian Haas usb_set_intfdata(intf, NULL);
1074702171adSSebastian Haas
1075702171adSSebastian Haas if (dev) {
1076702171adSSebastian Haas unregister_netdev(dev->netdev);
1077702171adSSebastian Haas
1078702171adSSebastian Haas unlink_all_urbs(dev);
1079702171adSSebastian Haas
1080702171adSSebastian Haas usb_free_urb(dev->intr_urb);
1081702171adSSebastian Haas
1082702171adSSebastian Haas kfree(dev->intr_in_buffer);
108372c05f32SAnton Vasilyev kfree(dev->tx_msg_buffer);
1084ab4a0b8fSPavel Skripkin
1085ab4a0b8fSPavel Skripkin free_candev(dev->netdev);
1086702171adSSebastian Haas }
1087702171adSSebastian Haas }
1088702171adSSebastian Haas
1089702171adSSebastian Haas /* usb specific object needed to register this driver with the usb subsystem */
1090702171adSSebastian Haas static struct usb_driver ems_usb_driver = {
1091f60df831SVincent Mailhol .name = KBUILD_MODNAME,
1092702171adSSebastian Haas .probe = ems_usb_probe,
1093702171adSSebastian Haas .disconnect = ems_usb_disconnect,
1094702171adSSebastian Haas .id_table = ems_usb_table,
1095702171adSSebastian Haas };
1096702171adSSebastian Haas
1097d632eb1bSGreg Kroah-Hartman module_usb_driver(ems_usb_driver);
1098