1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /****************************************************************************** |
3 | * usbatm.c - Generic USB xDSL driver core |
4 | * |
5 | * Copyright (C) 2001, Alcatel |
6 | * Copyright (C) 2003, Duncan Sands, SolNegro, Josep Comas |
7 | * Copyright (C) 2004, David Woodhouse, Roman Kagan |
8 | ******************************************************************************/ |
9 | |
10 | /* |
11 | * Written by Johan Verrept, Duncan Sands (duncan.sands@free.fr) and David Woodhouse |
12 | * |
13 | * 1.7+: - See the check-in logs |
14 | * |
15 | * 1.6: - No longer opens a connection if the firmware is not loaded |
16 | * - Added support for the speedtouch 330 |
17 | * - Removed the limit on the number of devices |
18 | * - Module now autoloads on device plugin |
19 | * - Merged relevant parts of sarlib |
20 | * - Replaced the kernel thread with a tasklet |
21 | * - New packet transmission code |
22 | * - Changed proc file contents |
23 | * - Fixed all known SMP races |
24 | * - Many fixes and cleanups |
25 | * - Various fixes by Oliver Neukum (oliver@neukum.name) |
26 | * |
27 | * 1.5A: - Version for inclusion in 2.5 series kernel |
28 | * - Modifications by Richard Purdie (rpurdie@rpsys.net) |
29 | * - made compatible with kernel 2.5.6 onwards by changing |
30 | * usbatm_usb_send_data_context->urb to a pointer and adding code |
31 | * to alloc and free it |
32 | * - remove_wait_queue() added to usbatm_atm_processqueue_thread() |
33 | * |
34 | * 1.5: - fixed memory leak when atmsar_decode_aal5 returned NULL. |
35 | * (reported by stephen.robinson@zen.co.uk) |
36 | * |
37 | * 1.4: - changed the spin_lock() under interrupt to spin_lock_irqsave() |
38 | * - unlink all active send urbs of a vcc that is being closed. |
39 | * |
40 | * 1.3.1: - added the version number |
41 | * |
42 | * 1.3: - Added multiple send urb support |
43 | * - fixed memory leak and vcc->tx_inuse starvation bug |
44 | * when not enough memory left in vcc. |
45 | * |
46 | * 1.2: - Fixed race condition in usbatm_usb_send_data() |
47 | * 1.1: - Turned off packet debugging |
48 | * |
49 | */ |
50 | |
51 | #include "usbatm.h" |
52 | |
53 | #include <linux/uaccess.h> |
54 | #include <linux/crc32.h> |
55 | #include <linux/errno.h> |
56 | #include <linux/init.h> |
57 | #include <linux/interrupt.h> |
58 | #include <linux/kernel.h> |
59 | #include <linux/module.h> |
60 | #include <linux/moduleparam.h> |
61 | #include <linux/netdevice.h> |
62 | #include <linux/proc_fs.h> |
63 | #include <linux/sched/signal.h> |
64 | #include <linux/signal.h> |
65 | #include <linux/slab.h> |
66 | #include <linux/stat.h> |
67 | #include <linux/timer.h> |
68 | #include <linux/wait.h> |
69 | #include <linux/kthread.h> |
70 | #include <linux/ratelimit.h> |
71 | |
72 | #ifdef VERBOSE_DEBUG |
73 | static int usbatm_print_packet(struct usbatm_data *instance, const unsigned char *data, int len); |
74 | #define PACKETDEBUG(arg...) usbatm_print_packet(arg) |
75 | #define vdbg(arg...) dev_dbg(arg) |
76 | #else |
77 | #define PACKETDEBUG(arg...) |
78 | #define vdbg(arg...) |
79 | #endif |
80 | |
81 | #define DRIVER_AUTHOR "Johan Verrept, Duncan Sands <duncan.sands@free.fr>" |
82 | #define DRIVER_DESC "Generic USB ATM/DSL I/O" |
83 | |
84 | static const char usbatm_driver_name[] = "usbatm" ; |
85 | |
86 | #define UDSL_MAX_RCV_URBS 16 |
87 | #define UDSL_MAX_SND_URBS 16 |
88 | #define UDSL_MAX_BUF_SIZE 65536 |
89 | #define UDSL_DEFAULT_RCV_URBS 4 |
90 | #define UDSL_DEFAULT_SND_URBS 4 |
91 | #define UDSL_DEFAULT_RCV_BUF_SIZE 3392 /* 64 * ATM_CELL_SIZE */ |
92 | #define UDSL_DEFAULT_SND_BUF_SIZE 3392 /* 64 * ATM_CELL_SIZE */ |
93 | |
94 | #define (ATM_CELL_SIZE - ATM_CELL_PAYLOAD) |
95 | |
96 | #define THROTTLE_MSECS 100 /* delay to recover processing after urb submission fails */ |
97 | |
98 | static unsigned int num_rcv_urbs = UDSL_DEFAULT_RCV_URBS; |
99 | static unsigned int num_snd_urbs = UDSL_DEFAULT_SND_URBS; |
100 | static unsigned int rcv_buf_bytes = UDSL_DEFAULT_RCV_BUF_SIZE; |
101 | static unsigned int snd_buf_bytes = UDSL_DEFAULT_SND_BUF_SIZE; |
102 | |
103 | module_param(num_rcv_urbs, uint, S_IRUGO); |
104 | MODULE_PARM_DESC(num_rcv_urbs, |
105 | "Number of urbs used for reception (range: 0-" |
106 | __MODULE_STRING(UDSL_MAX_RCV_URBS) ", default: " |
107 | __MODULE_STRING(UDSL_DEFAULT_RCV_URBS) ")" ); |
108 | |
109 | module_param(num_snd_urbs, uint, S_IRUGO); |
110 | MODULE_PARM_DESC(num_snd_urbs, |
111 | "Number of urbs used for transmission (range: 0-" |
112 | __MODULE_STRING(UDSL_MAX_SND_URBS) ", default: " |
113 | __MODULE_STRING(UDSL_DEFAULT_SND_URBS) ")" ); |
114 | |
115 | module_param(rcv_buf_bytes, uint, S_IRUGO); |
116 | MODULE_PARM_DESC(rcv_buf_bytes, |
117 | "Size of the buffers used for reception, in bytes (range: 1-" |
118 | __MODULE_STRING(UDSL_MAX_BUF_SIZE) ", default: " |
119 | __MODULE_STRING(UDSL_DEFAULT_RCV_BUF_SIZE) ")" ); |
120 | |
121 | module_param(snd_buf_bytes, uint, S_IRUGO); |
122 | MODULE_PARM_DESC(snd_buf_bytes, |
123 | "Size of the buffers used for transmission, in bytes (range: 1-" |
124 | __MODULE_STRING(UDSL_MAX_BUF_SIZE) ", default: " |
125 | __MODULE_STRING(UDSL_DEFAULT_SND_BUF_SIZE) ")" ); |
126 | |
127 | |
128 | /* receive */ |
129 | |
130 | struct usbatm_vcc_data { |
131 | /* vpi/vci lookup */ |
132 | struct list_head list; |
133 | short vpi; |
134 | int vci; |
135 | struct atm_vcc *vcc; |
136 | |
137 | /* raw cell reassembly */ |
138 | struct sk_buff *sarb; |
139 | }; |
140 | |
141 | |
142 | /* send */ |
143 | |
144 | struct usbatm_control { |
145 | struct atm_skb_data atm; |
146 | u32 len; |
147 | u32 crc; |
148 | }; |
149 | |
150 | #define UDSL_SKB(x) ((struct usbatm_control *)(x)->cb) |
151 | |
152 | |
153 | /* ATM */ |
154 | |
155 | static void usbatm_atm_dev_close(struct atm_dev *atm_dev); |
156 | static int usbatm_atm_open(struct atm_vcc *vcc); |
157 | static void usbatm_atm_close(struct atm_vcc *vcc); |
158 | static int usbatm_atm_ioctl(struct atm_dev *atm_dev, unsigned int cmd, void __user *arg); |
159 | static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb); |
160 | static int usbatm_atm_proc_read(struct atm_dev *atm_dev, loff_t *pos, char *page); |
161 | |
162 | static const struct atmdev_ops usbatm_atm_devops = { |
163 | .dev_close = usbatm_atm_dev_close, |
164 | .open = usbatm_atm_open, |
165 | .close = usbatm_atm_close, |
166 | .ioctl = usbatm_atm_ioctl, |
167 | .send = usbatm_atm_send, |
168 | .proc_read = usbatm_atm_proc_read, |
169 | .owner = THIS_MODULE, |
170 | }; |
171 | |
172 | |
173 | /*********** |
174 | ** misc ** |
175 | ***********/ |
176 | |
177 | static inline unsigned int usbatm_pdu_length(unsigned int length) |
178 | { |
179 | length += ATM_CELL_PAYLOAD - 1 + ATM_AAL5_TRAILER; |
180 | return length - length % ATM_CELL_PAYLOAD; |
181 | } |
182 | |
183 | static inline void usbatm_pop(struct atm_vcc *vcc, struct sk_buff *skb) |
184 | { |
185 | if (vcc->pop) |
186 | vcc->pop(vcc, skb); |
187 | else |
188 | dev_kfree_skb_any(skb); |
189 | } |
190 | |
191 | |
192 | /*********** |
193 | ** urbs ** |
194 | ************/ |
195 | |
196 | static struct urb *usbatm_pop_urb(struct usbatm_channel *channel) |
197 | { |
198 | struct urb *urb; |
199 | |
200 | spin_lock_irq(lock: &channel->lock); |
201 | if (list_empty(head: &channel->list)) { |
202 | spin_unlock_irq(lock: &channel->lock); |
203 | return NULL; |
204 | } |
205 | |
206 | urb = list_entry(channel->list.next, struct urb, urb_list); |
207 | list_del(entry: &urb->urb_list); |
208 | spin_unlock_irq(lock: &channel->lock); |
209 | |
210 | return urb; |
211 | } |
212 | |
213 | static int usbatm_submit_urb(struct urb *urb) |
214 | { |
215 | struct usbatm_channel *channel = urb->context; |
216 | int ret; |
217 | |
218 | /* vdbg("%s: submitting urb 0x%p, size %u", |
219 | __func__, urb, urb->transfer_buffer_length); */ |
220 | |
221 | ret = usb_submit_urb(urb, GFP_ATOMIC); |
222 | if (ret) { |
223 | if (printk_ratelimit()) |
224 | atm_warn(channel->usbatm, "%s: urb 0x%p submission failed (%d)!\n" , |
225 | __func__, urb, ret); |
226 | |
227 | /* consider all errors transient and return the buffer back to the queue */ |
228 | urb->status = -EAGAIN; |
229 | spin_lock_irq(lock: &channel->lock); |
230 | |
231 | /* must add to the front when sending; doesn't matter when receiving */ |
232 | list_add(new: &urb->urb_list, head: &channel->list); |
233 | |
234 | spin_unlock_irq(lock: &channel->lock); |
235 | |
236 | /* make sure the channel doesn't stall */ |
237 | mod_timer(timer: &channel->delay, expires: jiffies + msecs_to_jiffies(THROTTLE_MSECS)); |
238 | } |
239 | |
240 | return ret; |
241 | } |
242 | |
243 | static void usbatm_complete(struct urb *urb) |
244 | { |
245 | struct usbatm_channel *channel = urb->context; |
246 | unsigned long flags; |
247 | int status = urb->status; |
248 | |
249 | /* vdbg("%s: urb 0x%p, status %d, actual_length %d", |
250 | __func__, urb, status, urb->actual_length); */ |
251 | |
252 | /* Can be invoked from task context, protect against interrupts */ |
253 | spin_lock_irqsave(&channel->lock, flags); |
254 | |
255 | /* must add to the back when receiving; doesn't matter when sending */ |
256 | list_add_tail(new: &urb->urb_list, head: &channel->list); |
257 | |
258 | spin_unlock_irqrestore(lock: &channel->lock, flags); |
259 | |
260 | if (unlikely(status) && |
261 | (!(channel->usbatm->flags & UDSL_IGNORE_EILSEQ) || |
262 | status != -EILSEQ)) { |
263 | if (status == -ESHUTDOWN) |
264 | return; |
265 | |
266 | if (printk_ratelimit()) |
267 | atm_warn(channel->usbatm, "%s: urb 0x%p failed (%d)!\n" , |
268 | __func__, urb, status); |
269 | /* throttle processing in case of an error */ |
270 | mod_timer(timer: &channel->delay, expires: jiffies + msecs_to_jiffies(THROTTLE_MSECS)); |
271 | } else |
272 | tasklet_schedule(t: &channel->tasklet); |
273 | } |
274 | |
275 | |
276 | /************* |
277 | ** decode ** |
278 | *************/ |
279 | |
280 | static inline struct usbatm_vcc_data *usbatm_find_vcc(struct usbatm_data *instance, |
281 | short vpi, int vci) |
282 | { |
283 | struct usbatm_vcc_data *vcc_data; |
284 | |
285 | list_for_each_entry(vcc_data, &instance->vcc_list, list) |
286 | if ((vcc_data->vci == vci) && (vcc_data->vpi == vpi)) |
287 | return vcc_data; |
288 | return NULL; |
289 | } |
290 | |
291 | static void (struct usbatm_data *instance, unsigned char *source) |
292 | { |
293 | struct atm_vcc *vcc; |
294 | struct sk_buff *sarb; |
295 | short vpi = ((source[0] & 0x0f) << 4) | (source[1] >> 4); |
296 | int vci = ((source[1] & 0x0f) << 12) | (source[2] << 4) | (source[3] >> 4); |
297 | u8 pti = ((source[3] & 0xe) >> 1); |
298 | |
299 | if ((vci != instance->cached_vci) || (vpi != instance->cached_vpi)) { |
300 | instance->cached_vpi = vpi; |
301 | instance->cached_vci = vci; |
302 | |
303 | instance->cached_vcc = usbatm_find_vcc(instance, vpi, vci); |
304 | |
305 | if (!instance->cached_vcc) |
306 | atm_rldbg(instance, "%s: unknown vpi/vci (%hd/%d)!\n" , __func__, vpi, vci); |
307 | } |
308 | |
309 | if (!instance->cached_vcc) |
310 | return; |
311 | |
312 | vcc = instance->cached_vcc->vcc; |
313 | |
314 | /* OAM F5 end-to-end */ |
315 | if (pti == ATM_PTI_E2EF5) { |
316 | if (printk_ratelimit()) |
317 | atm_warn(instance, "%s: OAM not supported (vpi %d, vci %d)!\n" , |
318 | __func__, vpi, vci); |
319 | atomic_inc(v: &vcc->stats->rx_err); |
320 | return; |
321 | } |
322 | |
323 | sarb = instance->cached_vcc->sarb; |
324 | |
325 | if (sarb->tail + ATM_CELL_PAYLOAD > sarb->end) { |
326 | atm_rldbg(instance, "%s: buffer overrun (sarb->len %u, vcc: 0x%p)!\n" , |
327 | __func__, sarb->len, vcc); |
328 | /* discard cells already received */ |
329 | skb_trim(skb: sarb, len: 0); |
330 | } |
331 | |
332 | memcpy(skb_tail_pointer(sarb), source + ATM_CELL_HEADER, ATM_CELL_PAYLOAD); |
333 | __skb_put(skb: sarb, ATM_CELL_PAYLOAD); |
334 | |
335 | if (pti & 1) { |
336 | struct sk_buff *skb; |
337 | unsigned int length; |
338 | unsigned int pdu_length; |
339 | |
340 | length = (source[ATM_CELL_SIZE - 6] << 8) + source[ATM_CELL_SIZE - 5]; |
341 | |
342 | /* guard against overflow */ |
343 | if (length > ATM_MAX_AAL5_PDU) { |
344 | atm_rldbg(instance, "%s: bogus length %u (vcc: 0x%p)!\n" , |
345 | __func__, length, vcc); |
346 | atomic_inc(v: &vcc->stats->rx_err); |
347 | goto out; |
348 | } |
349 | |
350 | pdu_length = usbatm_pdu_length(length); |
351 | |
352 | if (sarb->len < pdu_length) { |
353 | atm_rldbg(instance, "%s: bogus pdu_length %u (sarb->len: %u, vcc: 0x%p)!\n" , |
354 | __func__, pdu_length, sarb->len, vcc); |
355 | atomic_inc(v: &vcc->stats->rx_err); |
356 | goto out; |
357 | } |
358 | |
359 | if (crc32_be(crc: ~0, p: skb_tail_pointer(skb: sarb) - pdu_length, len: pdu_length) != 0xc704dd7b) { |
360 | atm_rldbg(instance, "%s: packet failed crc check (vcc: 0x%p)!\n" , |
361 | __func__, vcc); |
362 | atomic_inc(v: &vcc->stats->rx_err); |
363 | goto out; |
364 | } |
365 | |
366 | vdbg(&instance->usb_intf->dev, |
367 | "%s: got packet (length: %u, pdu_length: %u, vcc: 0x%p)" , |
368 | __func__, length, pdu_length, vcc); |
369 | |
370 | skb = dev_alloc_skb(length); |
371 | if (!skb) { |
372 | if (printk_ratelimit()) |
373 | atm_err(instance, "%s: no memory for skb (length: %u)!\n" , |
374 | __func__, length); |
375 | atomic_inc(v: &vcc->stats->rx_drop); |
376 | goto out; |
377 | } |
378 | |
379 | vdbg(&instance->usb_intf->dev, |
380 | "%s: allocated new sk_buff (skb: 0x%p, skb->truesize: %u)" , |
381 | __func__, skb, skb->truesize); |
382 | |
383 | if (!atm_charge(vcc, truesize: skb->truesize)) { |
384 | atm_rldbg(instance, "%s: failed atm_charge (skb->truesize: %u)!\n" , |
385 | __func__, skb->truesize); |
386 | dev_kfree_skb_any(skb); |
387 | goto out; /* atm_charge increments rx_drop */ |
388 | } |
389 | |
390 | skb_copy_to_linear_data(skb, |
391 | from: skb_tail_pointer(skb: sarb) - pdu_length, |
392 | len: length); |
393 | __skb_put(skb, len: length); |
394 | |
395 | vdbg(&instance->usb_intf->dev, |
396 | "%s: sending skb 0x%p, skb->len %u, skb->truesize %u" , |
397 | __func__, skb, skb->len, skb->truesize); |
398 | |
399 | PACKETDEBUG(instance, skb->data, skb->len); |
400 | |
401 | vcc->push(vcc, skb); |
402 | |
403 | atomic_inc(v: &vcc->stats->rx); |
404 | out: |
405 | skb_trim(skb: sarb, len: 0); |
406 | } |
407 | } |
408 | |
409 | static void (struct usbatm_data *instance, |
410 | unsigned char *source, unsigned int avail_data) |
411 | { |
412 | unsigned int stride = instance->rx_channel.stride; |
413 | unsigned int buf_usage = instance->buf_usage; |
414 | |
415 | /* extract cells from incoming data, taking into account that |
416 | * the length of avail data may not be a multiple of stride */ |
417 | |
418 | if (buf_usage > 0) { |
419 | /* we have a partially received atm cell */ |
420 | unsigned char *cell_buf = instance->cell_buf; |
421 | unsigned int space_left = stride - buf_usage; |
422 | |
423 | if (avail_data >= space_left) { |
424 | /* add new data and process cell */ |
425 | memcpy(cell_buf + buf_usage, source, space_left); |
426 | source += space_left; |
427 | avail_data -= space_left; |
428 | usbatm_extract_one_cell(instance, source: cell_buf); |
429 | instance->buf_usage = 0; |
430 | } else { |
431 | /* not enough data to fill the cell */ |
432 | memcpy(cell_buf + buf_usage, source, avail_data); |
433 | instance->buf_usage = buf_usage + avail_data; |
434 | return; |
435 | } |
436 | } |
437 | |
438 | for (; avail_data >= stride; avail_data -= stride, source += stride) |
439 | usbatm_extract_one_cell(instance, source); |
440 | |
441 | if (avail_data > 0) { |
442 | /* length was not a multiple of stride - |
443 | * save remaining data for next call */ |
444 | memcpy(instance->cell_buf, source, avail_data); |
445 | instance->buf_usage = avail_data; |
446 | } |
447 | } |
448 | |
449 | |
450 | /************* |
451 | ** encode ** |
452 | *************/ |
453 | |
454 | static unsigned int usbatm_write_cells(struct usbatm_data *instance, |
455 | struct sk_buff *skb, |
456 | u8 *target, unsigned int avail_space) |
457 | { |
458 | struct usbatm_control *ctrl = UDSL_SKB(skb); |
459 | struct atm_vcc *vcc = ctrl->atm.vcc; |
460 | unsigned int bytes_written; |
461 | unsigned int stride = instance->tx_channel.stride; |
462 | |
463 | for (bytes_written = 0; bytes_written < avail_space && ctrl->len; |
464 | bytes_written += stride, target += stride) { |
465 | unsigned int data_len = min_t(unsigned int, skb->len, ATM_CELL_PAYLOAD); |
466 | unsigned int left = ATM_CELL_PAYLOAD - data_len; |
467 | u8 *ptr = target; |
468 | |
469 | ptr[0] = vcc->vpi >> 4; |
470 | ptr[1] = (vcc->vpi << 4) | (vcc->vci >> 12); |
471 | ptr[2] = vcc->vci >> 4; |
472 | ptr[3] = vcc->vci << 4; |
473 | ptr[4] = 0xec; |
474 | ptr += ATM_CELL_HEADER; |
475 | |
476 | skb_copy_from_linear_data(skb, to: ptr, len: data_len); |
477 | ptr += data_len; |
478 | __skb_pull(skb, len: data_len); |
479 | |
480 | if (!left) |
481 | continue; |
482 | |
483 | memset(ptr, 0, left); |
484 | |
485 | if (left >= ATM_AAL5_TRAILER) { /* trailer will go in this cell */ |
486 | u8 *trailer = target + ATM_CELL_SIZE - ATM_AAL5_TRAILER; |
487 | /* trailer[0] = 0; UU = 0 */ |
488 | /* trailer[1] = 0; CPI = 0 */ |
489 | trailer[2] = ctrl->len >> 8; |
490 | trailer[3] = ctrl->len; |
491 | |
492 | ctrl->crc = ~crc32_be(crc: ctrl->crc, p: ptr, len: left - 4); |
493 | |
494 | trailer[4] = ctrl->crc >> 24; |
495 | trailer[5] = ctrl->crc >> 16; |
496 | trailer[6] = ctrl->crc >> 8; |
497 | trailer[7] = ctrl->crc; |
498 | |
499 | target[3] |= 0x2; /* adjust PTI */ |
500 | |
501 | ctrl->len = 0; /* tag this skb finished */ |
502 | } else |
503 | ctrl->crc = crc32_be(crc: ctrl->crc, p: ptr, len: left); |
504 | } |
505 | |
506 | return bytes_written; |
507 | } |
508 | |
509 | |
510 | /************** |
511 | ** receive ** |
512 | **************/ |
513 | |
514 | static void usbatm_rx_process(struct tasklet_struct *t) |
515 | { |
516 | struct usbatm_data *instance = from_tasklet(instance, t, |
517 | rx_channel.tasklet); |
518 | struct urb *urb; |
519 | |
520 | while ((urb = usbatm_pop_urb(channel: &instance->rx_channel))) { |
521 | vdbg(&instance->usb_intf->dev, |
522 | "%s: processing urb 0x%p" , __func__, urb); |
523 | |
524 | if (usb_pipeisoc(urb->pipe)) { |
525 | unsigned char *merge_start = NULL; |
526 | unsigned int merge_length = 0; |
527 | const unsigned int packet_size = instance->rx_channel.packet_size; |
528 | int i; |
529 | |
530 | for (i = 0; i < urb->number_of_packets; i++) { |
531 | if (!urb->iso_frame_desc[i].status) { |
532 | unsigned int actual_length = urb->iso_frame_desc[i].actual_length; |
533 | |
534 | if (!merge_length) |
535 | merge_start = (unsigned char *)urb->transfer_buffer + urb->iso_frame_desc[i].offset; |
536 | merge_length += actual_length; |
537 | if (merge_length && (actual_length < packet_size)) { |
538 | usbatm_extract_cells(instance, source: merge_start, avail_data: merge_length); |
539 | merge_length = 0; |
540 | } |
541 | } else { |
542 | atm_rldbg(instance, "%s: status %d in frame %d!\n" , __func__, urb->status, i); |
543 | if (merge_length) |
544 | usbatm_extract_cells(instance, source: merge_start, avail_data: merge_length); |
545 | merge_length = 0; |
546 | instance->buf_usage = 0; |
547 | } |
548 | } |
549 | |
550 | if (merge_length) |
551 | usbatm_extract_cells(instance, source: merge_start, avail_data: merge_length); |
552 | } else |
553 | if (!urb->status) |
554 | usbatm_extract_cells(instance, source: urb->transfer_buffer, avail_data: urb->actual_length); |
555 | else |
556 | instance->buf_usage = 0; |
557 | |
558 | if (usbatm_submit_urb(urb)) |
559 | return; |
560 | } |
561 | } |
562 | |
563 | |
564 | /*********** |
565 | ** send ** |
566 | ***********/ |
567 | |
568 | static void usbatm_tx_process(struct tasklet_struct *t) |
569 | { |
570 | struct usbatm_data *instance = from_tasklet(instance, t, |
571 | tx_channel.tasklet); |
572 | struct sk_buff *skb = instance->current_skb; |
573 | struct urb *urb = NULL; |
574 | const unsigned int buf_size = instance->tx_channel.buf_size; |
575 | unsigned int bytes_written = 0; |
576 | u8 *buffer = NULL; |
577 | |
578 | if (!skb) |
579 | skb = skb_dequeue(list: &instance->sndqueue); |
580 | |
581 | while (skb) { |
582 | if (!urb) { |
583 | urb = usbatm_pop_urb(channel: &instance->tx_channel); |
584 | if (!urb) |
585 | break; /* no more senders */ |
586 | buffer = urb->transfer_buffer; |
587 | bytes_written = (urb->status == -EAGAIN) ? |
588 | urb->transfer_buffer_length : 0; |
589 | } |
590 | |
591 | bytes_written += usbatm_write_cells(instance, skb, |
592 | target: buffer + bytes_written, |
593 | avail_space: buf_size - bytes_written); |
594 | |
595 | vdbg(&instance->usb_intf->dev, |
596 | "%s: wrote %u bytes from skb 0x%p to urb 0x%p" , |
597 | __func__, bytes_written, skb, urb); |
598 | |
599 | if (!UDSL_SKB(skb)->len) { |
600 | struct atm_vcc *vcc = UDSL_SKB(skb)->atm.vcc; |
601 | |
602 | usbatm_pop(vcc, skb); |
603 | atomic_inc(v: &vcc->stats->tx); |
604 | |
605 | skb = skb_dequeue(list: &instance->sndqueue); |
606 | } |
607 | |
608 | if (bytes_written == buf_size || (!skb && bytes_written)) { |
609 | urb->transfer_buffer_length = bytes_written; |
610 | |
611 | if (usbatm_submit_urb(urb)) |
612 | break; |
613 | urb = NULL; |
614 | } |
615 | } |
616 | |
617 | instance->current_skb = skb; |
618 | } |
619 | |
620 | static void usbatm_cancel_send(struct usbatm_data *instance, |
621 | struct atm_vcc *vcc) |
622 | { |
623 | struct sk_buff *skb, *n; |
624 | |
625 | spin_lock_irq(lock: &instance->sndqueue.lock); |
626 | skb_queue_walk_safe(&instance->sndqueue, skb, n) { |
627 | if (UDSL_SKB(skb)->atm.vcc == vcc) { |
628 | atm_dbg(instance, "%s: popping skb 0x%p\n" , __func__, skb); |
629 | __skb_unlink(skb, list: &instance->sndqueue); |
630 | usbatm_pop(vcc, skb); |
631 | } |
632 | } |
633 | spin_unlock_irq(lock: &instance->sndqueue.lock); |
634 | |
635 | tasklet_disable(t: &instance->tx_channel.tasklet); |
636 | if ((skb = instance->current_skb) && (UDSL_SKB(skb)->atm.vcc == vcc)) { |
637 | atm_dbg(instance, "%s: popping current skb (0x%p)\n" , __func__, skb); |
638 | instance->current_skb = NULL; |
639 | usbatm_pop(vcc, skb); |
640 | } |
641 | tasklet_enable(t: &instance->tx_channel.tasklet); |
642 | } |
643 | |
644 | static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) |
645 | { |
646 | struct usbatm_data *instance = vcc->dev->dev_data; |
647 | struct usbatm_control *ctrl = UDSL_SKB(skb); |
648 | int err; |
649 | |
650 | /* racy disconnection check - fine */ |
651 | if (!instance || instance->disconnected) { |
652 | #ifdef VERBOSE_DEBUG |
653 | printk_ratelimited(KERN_DEBUG "%s: %s!\n" , __func__, instance ? "disconnected" : "NULL instance" ); |
654 | #endif |
655 | err = -ENODEV; |
656 | goto fail; |
657 | } |
658 | |
659 | if (vcc->qos.aal != ATM_AAL5) { |
660 | atm_rldbg(instance, "%s: unsupported ATM type %d!\n" , __func__, vcc->qos.aal); |
661 | err = -EINVAL; |
662 | goto fail; |
663 | } |
664 | |
665 | if (skb->len > ATM_MAX_AAL5_PDU) { |
666 | atm_rldbg(instance, "%s: packet too long (%d vs %d)!\n" , |
667 | __func__, skb->len, ATM_MAX_AAL5_PDU); |
668 | err = -EINVAL; |
669 | goto fail; |
670 | } |
671 | |
672 | PACKETDEBUG(instance, skb->data, skb->len); |
673 | |
674 | /* initialize the control block */ |
675 | ctrl->atm.vcc = vcc; |
676 | ctrl->len = skb->len; |
677 | ctrl->crc = crc32_be(crc: ~0, p: skb->data, len: skb->len); |
678 | |
679 | skb_queue_tail(list: &instance->sndqueue, newsk: skb); |
680 | tasklet_schedule(t: &instance->tx_channel.tasklet); |
681 | |
682 | return 0; |
683 | |
684 | fail: |
685 | usbatm_pop(vcc, skb); |
686 | return err; |
687 | } |
688 | |
689 | |
690 | /******************** |
691 | ** bean counting ** |
692 | ********************/ |
693 | |
694 | static void usbatm_destroy_instance(struct kref *kref) |
695 | { |
696 | struct usbatm_data *instance = container_of(kref, struct usbatm_data, refcount); |
697 | |
698 | tasklet_kill(t: &instance->rx_channel.tasklet); |
699 | tasklet_kill(t: &instance->tx_channel.tasklet); |
700 | usb_put_dev(dev: instance->usb_dev); |
701 | kfree(objp: instance); |
702 | } |
703 | |
704 | static void usbatm_get_instance(struct usbatm_data *instance) |
705 | { |
706 | kref_get(kref: &instance->refcount); |
707 | } |
708 | |
709 | static void usbatm_put_instance(struct usbatm_data *instance) |
710 | { |
711 | kref_put(kref: &instance->refcount, release: usbatm_destroy_instance); |
712 | } |
713 | |
714 | |
715 | /********** |
716 | ** ATM ** |
717 | **********/ |
718 | |
719 | static void usbatm_atm_dev_close(struct atm_dev *atm_dev) |
720 | { |
721 | struct usbatm_data *instance = atm_dev->dev_data; |
722 | |
723 | if (!instance) |
724 | return; |
725 | |
726 | atm_dev->dev_data = NULL; /* catch bugs */ |
727 | usbatm_put_instance(instance); /* taken in usbatm_atm_init */ |
728 | } |
729 | |
730 | static int usbatm_atm_proc_read(struct atm_dev *atm_dev, loff_t *pos, char *page) |
731 | { |
732 | struct usbatm_data *instance = atm_dev->dev_data; |
733 | int left = *pos; |
734 | |
735 | if (!instance) |
736 | return -ENODEV; |
737 | |
738 | if (!left--) |
739 | return sprintf(buf: page, fmt: "%s\n" , instance->description); |
740 | |
741 | if (!left--) |
742 | return sprintf(buf: page, fmt: "MAC: %pM\n" , atm_dev->esi); |
743 | |
744 | if (!left--) |
745 | return sprintf(buf: page, |
746 | fmt: "AAL5: tx %d ( %d err ), rx %d ( %d err, %d drop )\n" , |
747 | atomic_read(v: &atm_dev->stats.aal5.tx), |
748 | atomic_read(v: &atm_dev->stats.aal5.tx_err), |
749 | atomic_read(v: &atm_dev->stats.aal5.rx), |
750 | atomic_read(v: &atm_dev->stats.aal5.rx_err), |
751 | atomic_read(v: &atm_dev->stats.aal5.rx_drop)); |
752 | |
753 | if (!left--) { |
754 | if (instance->disconnected) |
755 | return sprintf(buf: page, fmt: "Disconnected\n" ); |
756 | else |
757 | switch (atm_dev->signal) { |
758 | case ATM_PHY_SIG_FOUND: |
759 | return sprintf(buf: page, fmt: "Line up\n" ); |
760 | case ATM_PHY_SIG_LOST: |
761 | return sprintf(buf: page, fmt: "Line down\n" ); |
762 | default: |
763 | return sprintf(buf: page, fmt: "Line state unknown\n" ); |
764 | } |
765 | } |
766 | |
767 | return 0; |
768 | } |
769 | |
770 | static int usbatm_atm_open(struct atm_vcc *vcc) |
771 | { |
772 | struct usbatm_data *instance = vcc->dev->dev_data; |
773 | struct usbatm_vcc_data *new = NULL; |
774 | int ret; |
775 | int vci = vcc->vci; |
776 | short vpi = vcc->vpi; |
777 | |
778 | if (!instance) |
779 | return -ENODEV; |
780 | |
781 | /* only support AAL5 */ |
782 | if ((vcc->qos.aal != ATM_AAL5)) { |
783 | atm_warn(instance, "%s: unsupported ATM type %d!\n" , __func__, vcc->qos.aal); |
784 | return -EINVAL; |
785 | } |
786 | |
787 | /* sanity checks */ |
788 | if ((vcc->qos.rxtp.max_sdu < 0) || (vcc->qos.rxtp.max_sdu > ATM_MAX_AAL5_PDU)) { |
789 | atm_dbg(instance, "%s: max_sdu %d out of range!\n" , __func__, vcc->qos.rxtp.max_sdu); |
790 | return -EINVAL; |
791 | } |
792 | |
793 | mutex_lock(&instance->serialize); /* vs self, usbatm_atm_close, usbatm_usb_disconnect */ |
794 | |
795 | if (instance->disconnected) { |
796 | atm_dbg(instance, "%s: disconnected!\n" , __func__); |
797 | ret = -ENODEV; |
798 | goto fail; |
799 | } |
800 | |
801 | if (usbatm_find_vcc(instance, vpi, vci)) { |
802 | atm_dbg(instance, "%s: %hd/%d already in use!\n" , __func__, vpi, vci); |
803 | ret = -EADDRINUSE; |
804 | goto fail; |
805 | } |
806 | |
807 | new = kzalloc(size: sizeof(struct usbatm_vcc_data), GFP_KERNEL); |
808 | if (!new) { |
809 | ret = -ENOMEM; |
810 | goto fail; |
811 | } |
812 | |
813 | new->vcc = vcc; |
814 | new->vpi = vpi; |
815 | new->vci = vci; |
816 | |
817 | new->sarb = alloc_skb(size: usbatm_pdu_length(length: vcc->qos.rxtp.max_sdu), GFP_KERNEL); |
818 | if (!new->sarb) { |
819 | atm_err(instance, "%s: no memory for SAR buffer!\n" , __func__); |
820 | ret = -ENOMEM; |
821 | goto fail; |
822 | } |
823 | |
824 | vcc->dev_data = new; |
825 | |
826 | tasklet_disable(t: &instance->rx_channel.tasklet); |
827 | instance->cached_vcc = new; |
828 | instance->cached_vpi = vpi; |
829 | instance->cached_vci = vci; |
830 | list_add(new: &new->list, head: &instance->vcc_list); |
831 | tasklet_enable(t: &instance->rx_channel.tasklet); |
832 | |
833 | set_bit(nr: ATM_VF_ADDR, addr: &vcc->flags); |
834 | set_bit(nr: ATM_VF_PARTIAL, addr: &vcc->flags); |
835 | set_bit(nr: ATM_VF_READY, addr: &vcc->flags); |
836 | |
837 | mutex_unlock(lock: &instance->serialize); |
838 | |
839 | atm_dbg(instance, "%s: allocated vcc data 0x%p\n" , __func__, new); |
840 | |
841 | return 0; |
842 | |
843 | fail: |
844 | kfree(objp: new); |
845 | mutex_unlock(lock: &instance->serialize); |
846 | return ret; |
847 | } |
848 | |
849 | static void usbatm_atm_close(struct atm_vcc *vcc) |
850 | { |
851 | struct usbatm_data *instance = vcc->dev->dev_data; |
852 | struct usbatm_vcc_data *vcc_data = vcc->dev_data; |
853 | |
854 | if (!instance || !vcc_data) |
855 | return; |
856 | |
857 | usbatm_cancel_send(instance, vcc); |
858 | |
859 | mutex_lock(&instance->serialize); /* vs self, usbatm_atm_open, usbatm_usb_disconnect */ |
860 | |
861 | tasklet_disable(t: &instance->rx_channel.tasklet); |
862 | if (instance->cached_vcc == vcc_data) { |
863 | instance->cached_vcc = NULL; |
864 | instance->cached_vpi = ATM_VPI_UNSPEC; |
865 | instance->cached_vci = ATM_VCI_UNSPEC; |
866 | } |
867 | list_del(entry: &vcc_data->list); |
868 | tasklet_enable(t: &instance->rx_channel.tasklet); |
869 | |
870 | kfree_skb(skb: vcc_data->sarb); |
871 | vcc_data->sarb = NULL; |
872 | |
873 | kfree(objp: vcc_data); |
874 | vcc->dev_data = NULL; |
875 | |
876 | vcc->vpi = ATM_VPI_UNSPEC; |
877 | vcc->vci = ATM_VCI_UNSPEC; |
878 | clear_bit(nr: ATM_VF_READY, addr: &vcc->flags); |
879 | clear_bit(nr: ATM_VF_PARTIAL, addr: &vcc->flags); |
880 | clear_bit(nr: ATM_VF_ADDR, addr: &vcc->flags); |
881 | |
882 | mutex_unlock(lock: &instance->serialize); |
883 | } |
884 | |
885 | static int usbatm_atm_ioctl(struct atm_dev *atm_dev, unsigned int cmd, |
886 | void __user *arg) |
887 | { |
888 | struct usbatm_data *instance = atm_dev->dev_data; |
889 | |
890 | if (!instance || instance->disconnected) |
891 | return -ENODEV; |
892 | |
893 | switch (cmd) { |
894 | case ATM_QUERYLOOP: |
895 | return put_user(ATM_LM_NONE, (int __user *)arg) ? -EFAULT : 0; |
896 | default: |
897 | return -ENOIOCTLCMD; |
898 | } |
899 | } |
900 | |
901 | static int usbatm_atm_init(struct usbatm_data *instance) |
902 | { |
903 | struct atm_dev *atm_dev; |
904 | int ret, i; |
905 | |
906 | /* ATM init. The ATM initialization scheme suffers from an intrinsic race |
907 | * condition: callbacks we register can be executed at once, before we have |
908 | * initialized the struct atm_dev. To protect against this, all callbacks |
909 | * abort if atm_dev->dev_data is NULL. */ |
910 | atm_dev = atm_dev_register(type: instance->driver_name, |
911 | parent: &instance->usb_intf->dev, ops: &usbatm_atm_devops, |
912 | number: -1, NULL); |
913 | if (!atm_dev) { |
914 | usb_err(instance, "%s: failed to register ATM device!\n" , __func__); |
915 | return -1; |
916 | } |
917 | |
918 | instance->atm_dev = atm_dev; |
919 | |
920 | atm_dev->ci_range.vpi_bits = ATM_CI_MAX; |
921 | atm_dev->ci_range.vci_bits = ATM_CI_MAX; |
922 | atm_dev->signal = ATM_PHY_SIG_UNKNOWN; |
923 | |
924 | /* temp init ATM device, set to 128kbit */ |
925 | atm_dev->link_rate = 128 * 1000 / 424; |
926 | |
927 | if (instance->driver->atm_start && ((ret = instance->driver->atm_start(instance, atm_dev)) < 0)) { |
928 | atm_err(instance, "%s: atm_start failed: %d!\n" , __func__, ret); |
929 | goto fail; |
930 | } |
931 | |
932 | usbatm_get_instance(instance); /* dropped in usbatm_atm_dev_close */ |
933 | |
934 | /* ready for ATM callbacks */ |
935 | mb(); |
936 | atm_dev->dev_data = instance; |
937 | |
938 | /* submit all rx URBs */ |
939 | for (i = 0; i < num_rcv_urbs; i++) |
940 | usbatm_submit_urb(urb: instance->urbs[i]); |
941 | |
942 | return 0; |
943 | |
944 | fail: |
945 | instance->atm_dev = NULL; |
946 | atm_dev_deregister(dev: atm_dev); /* usbatm_atm_dev_close will eventually be called */ |
947 | return ret; |
948 | } |
949 | |
950 | |
951 | /********** |
952 | ** USB ** |
953 | **********/ |
954 | |
955 | static int usbatm_do_heavy_init(void *arg) |
956 | { |
957 | struct usbatm_data *instance = arg; |
958 | int ret; |
959 | |
960 | allow_signal(SIGTERM); |
961 | complete(&instance->thread_started); |
962 | |
963 | ret = instance->driver->heavy_init(instance, instance->usb_intf); |
964 | |
965 | if (!ret) |
966 | ret = usbatm_atm_init(instance); |
967 | |
968 | mutex_lock(&instance->serialize); |
969 | instance->thread = NULL; |
970 | mutex_unlock(lock: &instance->serialize); |
971 | |
972 | kthread_complete_and_exit(&instance->thread_exited, ret); |
973 | } |
974 | |
975 | static int usbatm_heavy_init(struct usbatm_data *instance) |
976 | { |
977 | struct task_struct *t; |
978 | |
979 | t = kthread_create(usbatm_do_heavy_init, instance, "%s" , |
980 | instance->driver->driver_name); |
981 | if (IS_ERR(ptr: t)) { |
982 | usb_err(instance, "%s: failed to create kernel_thread (%ld)!\n" , |
983 | __func__, PTR_ERR(t)); |
984 | return PTR_ERR(ptr: t); |
985 | } |
986 | |
987 | instance->thread = t; |
988 | wake_up_process(tsk: t); |
989 | wait_for_completion(&instance->thread_started); |
990 | |
991 | return 0; |
992 | } |
993 | |
994 | static void usbatm_tasklet_schedule(struct timer_list *t) |
995 | { |
996 | struct usbatm_channel *channel = from_timer(channel, t, delay); |
997 | |
998 | tasklet_schedule(t: &channel->tasklet); |
999 | } |
1000 | |
1001 | static void usbatm_init_channel(struct usbatm_channel *channel) |
1002 | { |
1003 | spin_lock_init(&channel->lock); |
1004 | INIT_LIST_HEAD(list: &channel->list); |
1005 | timer_setup(&channel->delay, usbatm_tasklet_schedule, 0); |
1006 | } |
1007 | |
1008 | int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id, |
1009 | struct usbatm_driver *driver) |
1010 | { |
1011 | struct device *dev = &intf->dev; |
1012 | struct usb_device *usb_dev = interface_to_usbdev(intf); |
1013 | struct usbatm_data *instance; |
1014 | char *buf; |
1015 | int error = -ENOMEM; |
1016 | int i, length; |
1017 | unsigned int maxpacket, num_packets; |
1018 | size_t size; |
1019 | |
1020 | /* instance init */ |
1021 | size = struct_size(instance, urbs, |
1022 | size_add(num_rcv_urbs, num_snd_urbs)); |
1023 | instance = kzalloc(size, GFP_KERNEL); |
1024 | if (!instance) |
1025 | return -ENOMEM; |
1026 | |
1027 | /* public fields */ |
1028 | |
1029 | instance->driver = driver; |
1030 | strscpy(p: instance->driver_name, q: driver->driver_name, |
1031 | size: sizeof(instance->driver_name)); |
1032 | |
1033 | instance->usb_dev = usb_dev; |
1034 | instance->usb_intf = intf; |
1035 | |
1036 | buf = instance->description; |
1037 | length = sizeof(instance->description); |
1038 | |
1039 | if ((i = usb_string(dev: usb_dev, index: usb_dev->descriptor.iProduct, buf, size: length)) < 0) |
1040 | goto bind; |
1041 | |
1042 | buf += i; |
1043 | length -= i; |
1044 | |
1045 | i = scnprintf(buf, size: length, fmt: " (" ); |
1046 | buf += i; |
1047 | length -= i; |
1048 | |
1049 | if (length <= 0 || (i = usb_make_path(dev: usb_dev, buf, size: length)) < 0) |
1050 | goto bind; |
1051 | |
1052 | buf += i; |
1053 | length -= i; |
1054 | |
1055 | snprintf(buf, size: length, fmt: ")" ); |
1056 | |
1057 | bind: |
1058 | if (driver->bind && (error = driver->bind(instance, intf, id)) < 0) { |
1059 | dev_err(dev, "%s: bind failed: %d!\n" , __func__, error); |
1060 | goto fail_free; |
1061 | } |
1062 | |
1063 | /* private fields */ |
1064 | |
1065 | kref_init(kref: &instance->refcount); /* dropped in usbatm_usb_disconnect */ |
1066 | mutex_init(&instance->serialize); |
1067 | |
1068 | instance->thread = NULL; |
1069 | init_completion(x: &instance->thread_started); |
1070 | init_completion(x: &instance->thread_exited); |
1071 | |
1072 | INIT_LIST_HEAD(list: &instance->vcc_list); |
1073 | skb_queue_head_init(list: &instance->sndqueue); |
1074 | |
1075 | usbatm_init_channel(channel: &instance->rx_channel); |
1076 | usbatm_init_channel(channel: &instance->tx_channel); |
1077 | tasklet_setup(t: &instance->rx_channel.tasklet, callback: usbatm_rx_process); |
1078 | tasklet_setup(t: &instance->tx_channel.tasklet, callback: usbatm_tx_process); |
1079 | instance->rx_channel.stride = ATM_CELL_SIZE + driver->rx_padding; |
1080 | instance->tx_channel.stride = ATM_CELL_SIZE + driver->tx_padding; |
1081 | instance->rx_channel.usbatm = instance->tx_channel.usbatm = instance; |
1082 | |
1083 | if ((instance->flags & UDSL_USE_ISOC) && driver->isoc_in) |
1084 | instance->rx_channel.endpoint = usb_rcvisocpipe(usb_dev, driver->isoc_in); |
1085 | else |
1086 | instance->rx_channel.endpoint = usb_rcvbulkpipe(usb_dev, driver->bulk_in); |
1087 | |
1088 | instance->tx_channel.endpoint = usb_sndbulkpipe(usb_dev, driver->bulk_out); |
1089 | |
1090 | /* tx buffer size must be a positive multiple of the stride */ |
1091 | instance->tx_channel.buf_size = max(instance->tx_channel.stride, |
1092 | snd_buf_bytes - (snd_buf_bytes % instance->tx_channel.stride)); |
1093 | |
1094 | /* rx buffer size must be a positive multiple of the endpoint maxpacket */ |
1095 | maxpacket = usb_maxpacket(udev: usb_dev, pipe: instance->rx_channel.endpoint); |
1096 | |
1097 | if ((maxpacket < 1) || (maxpacket > UDSL_MAX_BUF_SIZE)) { |
1098 | dev_err(dev, "%s: invalid endpoint %02x!\n" , __func__, |
1099 | usb_pipeendpoint(instance->rx_channel.endpoint)); |
1100 | error = -EINVAL; |
1101 | goto fail_unbind; |
1102 | } |
1103 | |
1104 | num_packets = max(1U, (rcv_buf_bytes + maxpacket / 2) / maxpacket); /* round */ |
1105 | |
1106 | if (num_packets * maxpacket > UDSL_MAX_BUF_SIZE) |
1107 | num_packets--; |
1108 | |
1109 | instance->rx_channel.buf_size = num_packets * maxpacket; |
1110 | instance->rx_channel.packet_size = maxpacket; |
1111 | |
1112 | for (i = 0; i < 2; i++) { |
1113 | struct usbatm_channel *channel = i ? |
1114 | &instance->tx_channel : &instance->rx_channel; |
1115 | |
1116 | dev_dbg(dev, "%s: using %d byte buffer for %s channel 0x%p\n" , |
1117 | __func__, channel->buf_size, i ? "tx" : "rx" , channel); |
1118 | } |
1119 | |
1120 | /* initialize urbs */ |
1121 | |
1122 | for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) { |
1123 | u8 *buffer; |
1124 | struct usbatm_channel *channel = i < num_rcv_urbs ? |
1125 | &instance->rx_channel : &instance->tx_channel; |
1126 | struct urb *urb; |
1127 | unsigned int iso_packets = usb_pipeisoc(channel->endpoint) ? channel->buf_size / channel->packet_size : 0; |
1128 | |
1129 | urb = usb_alloc_urb(iso_packets, GFP_KERNEL); |
1130 | if (!urb) { |
1131 | error = -ENOMEM; |
1132 | goto fail_unbind; |
1133 | } |
1134 | |
1135 | instance->urbs[i] = urb; |
1136 | |
1137 | /* zero the tx padding to avoid leaking information */ |
1138 | buffer = kzalloc(size: channel->buf_size, GFP_KERNEL); |
1139 | if (!buffer) { |
1140 | error = -ENOMEM; |
1141 | goto fail_unbind; |
1142 | } |
1143 | |
1144 | usb_fill_bulk_urb(urb, dev: instance->usb_dev, pipe: channel->endpoint, |
1145 | transfer_buffer: buffer, buffer_length: channel->buf_size, complete_fn: usbatm_complete, context: channel); |
1146 | if (iso_packets) { |
1147 | int j; |
1148 | urb->interval = 1; |
1149 | urb->transfer_flags = URB_ISO_ASAP; |
1150 | urb->number_of_packets = iso_packets; |
1151 | for (j = 0; j < iso_packets; j++) { |
1152 | urb->iso_frame_desc[j].offset = channel->packet_size * j; |
1153 | urb->iso_frame_desc[j].length = channel->packet_size; |
1154 | } |
1155 | } |
1156 | |
1157 | /* put all tx URBs on the list of spares */ |
1158 | if (i >= num_rcv_urbs) |
1159 | list_add_tail(new: &urb->urb_list, head: &channel->list); |
1160 | |
1161 | vdbg(&intf->dev, "%s: alloced buffer 0x%p buf size %u urb 0x%p" , |
1162 | __func__, urb->transfer_buffer, urb->transfer_buffer_length, urb); |
1163 | } |
1164 | |
1165 | instance->cached_vpi = ATM_VPI_UNSPEC; |
1166 | instance->cached_vci = ATM_VCI_UNSPEC; |
1167 | instance->cell_buf = kmalloc(size: instance->rx_channel.stride, GFP_KERNEL); |
1168 | |
1169 | if (!instance->cell_buf) { |
1170 | error = -ENOMEM; |
1171 | goto fail_unbind; |
1172 | } |
1173 | |
1174 | if (!(instance->flags & UDSL_SKIP_HEAVY_INIT) && driver->heavy_init) { |
1175 | error = usbatm_heavy_init(instance); |
1176 | } else { |
1177 | complete(&instance->thread_exited); /* pretend that heavy_init was run */ |
1178 | error = usbatm_atm_init(instance); |
1179 | } |
1180 | |
1181 | if (error < 0) |
1182 | goto fail_unbind; |
1183 | |
1184 | usb_get_dev(dev: usb_dev); |
1185 | usb_set_intfdata(intf, data: instance); |
1186 | |
1187 | return 0; |
1188 | |
1189 | fail_unbind: |
1190 | if (instance->driver->unbind) |
1191 | instance->driver->unbind(instance, intf); |
1192 | fail_free: |
1193 | kfree(objp: instance->cell_buf); |
1194 | |
1195 | for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) { |
1196 | if (instance->urbs[i]) |
1197 | kfree(objp: instance->urbs[i]->transfer_buffer); |
1198 | usb_free_urb(urb: instance->urbs[i]); |
1199 | } |
1200 | |
1201 | kfree(objp: instance); |
1202 | |
1203 | return error; |
1204 | } |
1205 | EXPORT_SYMBOL_GPL(usbatm_usb_probe); |
1206 | |
1207 | void usbatm_usb_disconnect(struct usb_interface *intf) |
1208 | { |
1209 | struct device *dev = &intf->dev; |
1210 | struct usbatm_data *instance = usb_get_intfdata(intf); |
1211 | struct usbatm_vcc_data *vcc_data; |
1212 | int i; |
1213 | |
1214 | if (!instance) { |
1215 | dev_dbg(dev, "%s: NULL instance!\n" , __func__); |
1216 | return; |
1217 | } |
1218 | |
1219 | usb_set_intfdata(intf, NULL); |
1220 | |
1221 | mutex_lock(&instance->serialize); |
1222 | instance->disconnected = 1; |
1223 | if (instance->thread != NULL) |
1224 | send_sig(SIGTERM, instance->thread, 1); |
1225 | mutex_unlock(lock: &instance->serialize); |
1226 | |
1227 | wait_for_completion(&instance->thread_exited); |
1228 | |
1229 | mutex_lock(&instance->serialize); |
1230 | list_for_each_entry(vcc_data, &instance->vcc_list, list) |
1231 | vcc_release_async(vcc: vcc_data->vcc, reply: -EPIPE); |
1232 | mutex_unlock(lock: &instance->serialize); |
1233 | |
1234 | tasklet_disable(t: &instance->rx_channel.tasklet); |
1235 | tasklet_disable(t: &instance->tx_channel.tasklet); |
1236 | |
1237 | for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) |
1238 | usb_kill_urb(urb: instance->urbs[i]); |
1239 | |
1240 | del_timer_sync(timer: &instance->rx_channel.delay); |
1241 | del_timer_sync(timer: &instance->tx_channel.delay); |
1242 | |
1243 | /* turn usbatm_[rt]x_process into something close to a no-op */ |
1244 | /* no need to take the spinlock */ |
1245 | INIT_LIST_HEAD(list: &instance->rx_channel.list); |
1246 | INIT_LIST_HEAD(list: &instance->tx_channel.list); |
1247 | |
1248 | tasklet_enable(t: &instance->rx_channel.tasklet); |
1249 | tasklet_enable(t: &instance->tx_channel.tasklet); |
1250 | |
1251 | if (instance->atm_dev && instance->driver->atm_stop) |
1252 | instance->driver->atm_stop(instance, instance->atm_dev); |
1253 | |
1254 | if (instance->driver->unbind) |
1255 | instance->driver->unbind(instance, intf); |
1256 | |
1257 | instance->driver_data = NULL; |
1258 | |
1259 | for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) { |
1260 | kfree(objp: instance->urbs[i]->transfer_buffer); |
1261 | usb_free_urb(urb: instance->urbs[i]); |
1262 | } |
1263 | |
1264 | kfree(objp: instance->cell_buf); |
1265 | |
1266 | /* ATM finalize */ |
1267 | if (instance->atm_dev) { |
1268 | atm_dev_deregister(dev: instance->atm_dev); |
1269 | instance->atm_dev = NULL; |
1270 | } |
1271 | |
1272 | usbatm_put_instance(instance); /* taken in usbatm_usb_probe */ |
1273 | } |
1274 | EXPORT_SYMBOL_GPL(usbatm_usb_disconnect); |
1275 | |
1276 | |
1277 | /*********** |
1278 | ** init ** |
1279 | ***********/ |
1280 | |
1281 | static int __init usbatm_usb_init(void) |
1282 | { |
1283 | if (sizeof(struct usbatm_control) > sizeof_field(struct sk_buff, cb)) { |
1284 | pr_err("%s unusable with this kernel!\n" , usbatm_driver_name); |
1285 | return -EIO; |
1286 | } |
1287 | |
1288 | if ((num_rcv_urbs > UDSL_MAX_RCV_URBS) |
1289 | || (num_snd_urbs > UDSL_MAX_SND_URBS) |
1290 | || (rcv_buf_bytes < 1) |
1291 | || (rcv_buf_bytes > UDSL_MAX_BUF_SIZE) |
1292 | || (snd_buf_bytes < 1) |
1293 | || (snd_buf_bytes > UDSL_MAX_BUF_SIZE)) |
1294 | return -EINVAL; |
1295 | |
1296 | return 0; |
1297 | } |
1298 | module_init(usbatm_usb_init); |
1299 | |
1300 | static void __exit usbatm_usb_exit(void) |
1301 | { |
1302 | } |
1303 | module_exit(usbatm_usb_exit); |
1304 | |
1305 | MODULE_AUTHOR(DRIVER_AUTHOR); |
1306 | MODULE_DESCRIPTION(DRIVER_DESC); |
1307 | MODULE_LICENSE("GPL" ); |
1308 | |
1309 | /************ |
1310 | ** debug ** |
1311 | ************/ |
1312 | |
1313 | #ifdef VERBOSE_DEBUG |
1314 | static int usbatm_print_packet(struct usbatm_data *instance, |
1315 | const unsigned char *data, int len) |
1316 | { |
1317 | unsigned char buffer[256]; |
1318 | int i = 0, j = 0; |
1319 | |
1320 | for (i = 0; i < len;) { |
1321 | buffer[0] = '\0'; |
1322 | sprintf(buffer, "%.3d :" , i); |
1323 | for (j = 0; (j < 16) && (i < len); j++, i++) |
1324 | sprintf(buffer, "%s %2.2x" , buffer, data[i]); |
1325 | dev_dbg(&instance->usb_intf->dev, "%s" , buffer); |
1326 | } |
1327 | return i; |
1328 | } |
1329 | #endif |
1330 | |