blob: c925e3a4267274d824639b45b35a59773f3c88ca [file] [log] [blame]
Duncan Sandsc59bba72005-05-11 20:24:03 +02001/******************************************************************************
2 * usbatm.c - Generic USB xDSL driver core
3 *
4 * Copyright (C) 2001, Alcatel
5 * Copyright (C) 2003, Duncan Sands, SolNegro, Josep Comas
6 * Copyright (C) 2004, David Woodhouse, Roman Kagan
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the Free
10 * Software Foundation; either version 2 of the License, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 *
18 * You should have received a copy of the GNU General Public License along with
19 * this program; if not, write to the Free Software Foundation, Inc., 59
20 * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 *
22 ******************************************************************************/
23
24/*
25 * Written by Johan Verrept, Duncan Sands (duncan.sands@free.fr) and David Woodhouse
26 *
27 * 1.7+: - See the check-in logs
28 *
29 * 1.6: - No longer opens a connection if the firmware is not loaded
30 * - Added support for the speedtouch 330
31 * - Removed the limit on the number of devices
32 * - Module now autoloads on device plugin
33 * - Merged relevant parts of sarlib
34 * - Replaced the kernel thread with a tasklet
35 * - New packet transmission code
36 * - Changed proc file contents
37 * - Fixed all known SMP races
38 * - Many fixes and cleanups
39 * - Various fixes by Oliver Neukum (oliver@neukum.name)
40 *
41 * 1.5A: - Version for inclusion in 2.5 series kernel
42 * - Modifications by Richard Purdie (rpurdie@rpsys.net)
43 * - made compatible with kernel 2.5.6 onwards by changing
44 * usbatm_usb_send_data_context->urb to a pointer and adding code
45 * to alloc and free it
46 * - remove_wait_queue() added to usbatm_atm_processqueue_thread()
47 *
48 * 1.5: - fixed memory leak when atmsar_decode_aal5 returned NULL.
49 * (reported by stephen.robinson@zen.co.uk)
50 *
51 * 1.4: - changed the spin_lock() under interrupt to spin_lock_irqsave()
52 * - unlink all active send urbs of a vcc that is being closed.
53 *
54 * 1.3.1: - added the version number
55 *
56 * 1.3: - Added multiple send urb support
57 * - fixed memory leak and vcc->tx_inuse starvation bug
58 * when not enough memory left in vcc.
59 *
60 * 1.2: - Fixed race condition in usbatm_usb_send_data()
61 * 1.1: - Turned off packet debugging
62 *
63 */
64
65#include "usbatm.h"
66
67#include <asm/uaccess.h>
68#include <linux/crc32.h>
69#include <linux/errno.h>
70#include <linux/init.h>
71#include <linux/interrupt.h>
72#include <linux/kernel.h>
73#include <linux/module.h>
74#include <linux/moduleparam.h>
Duncan Sands227d7762006-01-13 10:13:19 +010075#include <linux/netdevice.h>
Duncan Sandsc59bba72005-05-11 20:24:03 +020076#include <linux/proc_fs.h>
77#include <linux/sched.h>
78#include <linux/signal.h>
79#include <linux/slab.h>
80#include <linux/smp_lock.h>
81#include <linux/stat.h>
82#include <linux/timer.h>
83#include <linux/wait.h>
84
85#ifdef VERBOSE_DEBUG
86static int usbatm_print_packet(const unsigned char *data, int len);
87#define PACKETDEBUG(arg...) usbatm_print_packet (arg)
88#define vdbg(arg...) dbg (arg)
89#else
90#define PACKETDEBUG(arg...)
91#define vdbg(arg...)
92#endif
93
94#define DRIVER_AUTHOR "Johan Verrept, Duncan Sands <duncan.sands@free.fr>"
Duncan Sands9b0e54a2006-01-13 11:08:05 +010095#define DRIVER_VERSION "1.10"
Duncan Sandsc59bba72005-05-11 20:24:03 +020096#define DRIVER_DESC "Generic USB ATM/DSL I/O, version " DRIVER_VERSION
97
98static const char usbatm_driver_name[] = "usbatm";
99
100#define UDSL_MAX_RCV_URBS 16
101#define UDSL_MAX_SND_URBS 16
Duncan Sands6f749472006-01-13 10:52:38 +0100102#define UDSL_MAX_BUF_SIZE 64 * 1024 /* bytes */
Duncan Sandsc59bba72005-05-11 20:24:03 +0200103#define UDSL_DEFAULT_RCV_URBS 4
104#define UDSL_DEFAULT_SND_URBS 4
Duncan Sands6f749472006-01-13 10:52:38 +0100105#define UDSL_DEFAULT_RCV_BUF_SIZE 64 * ATM_CELL_SIZE /* bytes */
106#define UDSL_DEFAULT_SND_BUF_SIZE 64 * ATM_CELL_SIZE /* bytes */
Duncan Sandsc59bba72005-05-11 20:24:03 +0200107
108#define ATM_CELL_HEADER (ATM_CELL_SIZE - ATM_CELL_PAYLOAD)
109
110#define THROTTLE_MSECS 100 /* delay to recover processing after urb submission fails */
111
112static unsigned int num_rcv_urbs = UDSL_DEFAULT_RCV_URBS;
113static unsigned int num_snd_urbs = UDSL_DEFAULT_SND_URBS;
Duncan Sands6f749472006-01-13 10:52:38 +0100114static unsigned int rcv_buf_bytes = UDSL_DEFAULT_RCV_BUF_SIZE;
115static unsigned int snd_buf_bytes = UDSL_DEFAULT_SND_BUF_SIZE;
Duncan Sandsc59bba72005-05-11 20:24:03 +0200116
117module_param(num_rcv_urbs, uint, S_IRUGO);
118MODULE_PARM_DESC(num_rcv_urbs,
119 "Number of urbs used for reception (range: 0-"
120 __MODULE_STRING(UDSL_MAX_RCV_URBS) ", default: "
121 __MODULE_STRING(UDSL_DEFAULT_RCV_URBS) ")");
122
123module_param(num_snd_urbs, uint, S_IRUGO);
124MODULE_PARM_DESC(num_snd_urbs,
125 "Number of urbs used for transmission (range: 0-"
126 __MODULE_STRING(UDSL_MAX_SND_URBS) ", default: "
127 __MODULE_STRING(UDSL_DEFAULT_SND_URBS) ")");
128
Duncan Sands6f749472006-01-13 10:52:38 +0100129module_param(rcv_buf_bytes, uint, S_IRUGO);
130MODULE_PARM_DESC(rcv_buf_bytes,
131 "Size of the buffers used for reception, in bytes (range: 1-"
132 __MODULE_STRING(UDSL_MAX_BUF_SIZE) ", default: "
Duncan Sandsc59bba72005-05-11 20:24:03 +0200133 __MODULE_STRING(UDSL_DEFAULT_RCV_BUF_SIZE) ")");
134
Duncan Sands6f749472006-01-13 10:52:38 +0100135module_param(snd_buf_bytes, uint, S_IRUGO);
136MODULE_PARM_DESC(snd_buf_bytes,
137 "Size of the buffers used for transmission, in bytes (range: 1-"
Duncan Sandsc59bba72005-05-11 20:24:03 +0200138 __MODULE_STRING(UDSL_MAX_SND_BUF_SIZE) ", default: "
139 __MODULE_STRING(UDSL_DEFAULT_SND_BUF_SIZE) ")");
140
141
142/* receive */
143
144struct usbatm_vcc_data {
145 /* vpi/vci lookup */
146 struct list_head list;
147 short vpi;
148 int vci;
149 struct atm_vcc *vcc;
150
151 /* raw cell reassembly */
152 struct sk_buff *sarb;
153};
154
155
156/* send */
157
158struct usbatm_control {
159 struct atm_skb_data atm;
160 u32 len;
161 u32 crc;
162};
163
164#define UDSL_SKB(x) ((struct usbatm_control *)(x)->cb)
165
166
167/* ATM */
168
Duncan Sands0ec3c7e2006-01-17 11:15:13 +0100169static void usbatm_atm_dev_close(struct atm_dev *atm_dev);
Duncan Sandsc59bba72005-05-11 20:24:03 +0200170static int usbatm_atm_open(struct atm_vcc *vcc);
171static void usbatm_atm_close(struct atm_vcc *vcc);
Duncan Sands0ec3c7e2006-01-17 11:15:13 +0100172static int usbatm_atm_ioctl(struct atm_dev *atm_dev, unsigned int cmd, void __user * arg);
Duncan Sandsc59bba72005-05-11 20:24:03 +0200173static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb);
174static int usbatm_atm_proc_read(struct atm_dev *atm_dev, loff_t * pos, char *page);
175
176static struct atmdev_ops usbatm_atm_devops = {
177 .dev_close = usbatm_atm_dev_close,
178 .open = usbatm_atm_open,
179 .close = usbatm_atm_close,
180 .ioctl = usbatm_atm_ioctl,
181 .send = usbatm_atm_send,
182 .proc_read = usbatm_atm_proc_read,
183 .owner = THIS_MODULE,
184};
185
186
187/***********
188** misc **
189***********/
190
191static inline unsigned int usbatm_pdu_length(unsigned int length)
192{
193 length += ATM_CELL_PAYLOAD - 1 + ATM_AAL5_TRAILER;
194 return length - length % ATM_CELL_PAYLOAD;
195}
196
197static inline void usbatm_pop(struct atm_vcc *vcc, struct sk_buff *skb)
198{
199 if (vcc->pop)
200 vcc->pop(vcc, skb);
201 else
Duncan Sands227d7762006-01-13 10:13:19 +0100202 dev_kfree_skb_any(skb);
Duncan Sandsc59bba72005-05-11 20:24:03 +0200203}
204
205
206/***********
207** urbs **
208************/
209
Arjan van de Ven858119e2006-01-14 13:20:43 -0800210static struct urb *usbatm_pop_urb(struct usbatm_channel *channel)
Duncan Sandsc59bba72005-05-11 20:24:03 +0200211{
212 struct urb *urb;
213
214 spin_lock_irq(&channel->lock);
215 if (list_empty(&channel->list)) {
216 spin_unlock_irq(&channel->lock);
217 return NULL;
218 }
219
220 urb = list_entry(channel->list.next, struct urb, urb_list);
221 list_del(&urb->urb_list);
222 spin_unlock_irq(&channel->lock);
223
224 return urb;
225}
226
Arjan van de Ven858119e2006-01-14 13:20:43 -0800227static int usbatm_submit_urb(struct urb *urb)
Duncan Sandsc59bba72005-05-11 20:24:03 +0200228{
229 struct usbatm_channel *channel = urb->context;
230 int ret;
231
232 vdbg("%s: submitting urb 0x%p, size %u",
233 __func__, urb, urb->transfer_buffer_length);
234
235 ret = usb_submit_urb(urb, GFP_ATOMIC);
236 if (ret) {
Duncan Sands0ec3c7e2006-01-17 11:15:13 +0100237 if (printk_ratelimit())
238 atm_warn(channel->usbatm, "%s: urb 0x%p submission failed (%d)!\n",
239 __func__, urb, ret);
Duncan Sandsc59bba72005-05-11 20:24:03 +0200240
241 /* consider all errors transient and return the buffer back to the queue */
242 urb->status = -EAGAIN;
243 spin_lock_irq(&channel->lock);
244
245 /* must add to the front when sending; doesn't matter when receiving */
246 list_add(&urb->urb_list, &channel->list);
247
248 spin_unlock_irq(&channel->lock);
249
250 /* make sure the channel doesn't stall */
251 mod_timer(&channel->delay, jiffies + msecs_to_jiffies(THROTTLE_MSECS));
252 }
253
254 return ret;
255}
256
257static void usbatm_complete(struct urb *urb, struct pt_regs *regs)
258{
259 struct usbatm_channel *channel = urb->context;
260 unsigned long flags;
261
262 vdbg("%s: urb 0x%p, status %d, actual_length %d",
263 __func__, urb, urb->status, urb->actual_length);
264
265 /* usually in_interrupt(), but not always */
266 spin_lock_irqsave(&channel->lock, flags);
267
268 /* must add to the back when receiving; doesn't matter when sending */
269 list_add_tail(&urb->urb_list, &channel->list);
270
271 spin_unlock_irqrestore(&channel->lock, flags);
272
Duncan Sands0ec3c7e2006-01-17 11:15:13 +0100273 if (unlikely(urb->status)) {
274 if (printk_ratelimit())
275 atm_warn(channel->usbatm, "%s: urb 0x%p failed (%d)!\n",
276 __func__, urb, urb->status);
Duncan Sandsc59bba72005-05-11 20:24:03 +0200277 /* throttle processing in case of an error */
278 mod_timer(&channel->delay, jiffies + msecs_to_jiffies(THROTTLE_MSECS));
Duncan Sands0ec3c7e2006-01-17 11:15:13 +0100279 } else
Duncan Sandsc59bba72005-05-11 20:24:03 +0200280 tasklet_schedule(&channel->tasklet);
281}
282
283
284/*************
285** decode **
286*************/
287
288static inline struct usbatm_vcc_data *usbatm_find_vcc(struct usbatm_data *instance,
289 short vpi, int vci)
290{
Duncan Sands0ec3c7e2006-01-17 11:15:13 +0100291 struct usbatm_vcc_data *vcc_data;
Duncan Sandsc59bba72005-05-11 20:24:03 +0200292
Duncan Sands0ec3c7e2006-01-17 11:15:13 +0100293 list_for_each_entry(vcc_data, &instance->vcc_list, list)
294 if ((vcc_data->vci == vci) && (vcc_data->vpi == vpi))
295 return vcc_data;
Duncan Sandsc59bba72005-05-11 20:24:03 +0200296 return NULL;
297}
298
Duncan Sandse3fb2f62006-01-13 11:06:46 +0100299static void usbatm_extract_one_cell(struct usbatm_data *instance, unsigned char *source)
Duncan Sandsc59bba72005-05-11 20:24:03 +0200300{
Duncan Sandsc59bba72005-05-11 20:24:03 +0200301 struct atm_vcc *vcc;
302 struct sk_buff *sarb;
Duncan Sandse3fb2f62006-01-13 11:06:46 +0100303 short vpi = ((source[0] & 0x0f) << 4) | (source[1] >> 4);
304 int vci = ((source[1] & 0x0f) << 12) | (source[2] << 4) | (source[3] >> 4);
305 u8 pti = ((source[3] & 0xe) >> 1);
Duncan Sandsc59bba72005-05-11 20:24:03 +0200306
Duncan Sandse3fb2f62006-01-13 11:06:46 +0100307 vdbg("%s: vpi %hd, vci %d, pti %d", __func__, vpi, vci, pti);
Duncan Sandsc59bba72005-05-11 20:24:03 +0200308
Duncan Sandse3fb2f62006-01-13 11:06:46 +0100309 if ((vci != instance->cached_vci) || (vpi != instance->cached_vpi)) {
310 instance->cached_vpi = vpi;
311 instance->cached_vci = vci;
Duncan Sandsc59bba72005-05-11 20:24:03 +0200312
Duncan Sandse3fb2f62006-01-13 11:06:46 +0100313 instance->cached_vcc = usbatm_find_vcc(instance, vpi, vci);
Duncan Sandse20d6642005-05-26 14:32:51 +0200314
Duncan Sandse3fb2f62006-01-13 11:06:46 +0100315 if (!instance->cached_vcc)
316 atm_rldbg(instance, "%s: unknown vpi/vci (%hd/%d)!\n", __func__, vpi, vci);
317 }
Duncan Sandse20d6642005-05-26 14:32:51 +0200318
Duncan Sandse3fb2f62006-01-13 11:06:46 +0100319 if (!instance->cached_vcc)
320 return;
Duncan Sandsc59bba72005-05-11 20:24:03 +0200321
Duncan Sandse3fb2f62006-01-13 11:06:46 +0100322 vcc = instance->cached_vcc->vcc;
Duncan Sandse20d6642005-05-26 14:32:51 +0200323
Duncan Sandse3fb2f62006-01-13 11:06:46 +0100324 /* OAM F5 end-to-end */
325 if (pti == ATM_PTI_E2EF5) {
326 if (printk_ratelimit())
327 atm_warn(instance, "%s: OAM not supported (vpi %d, vci %d)!\n",
328 __func__, vpi, vci);
329 atomic_inc(&vcc->stats->rx_err);
330 return;
331 }
Duncan Sandsc59bba72005-05-11 20:24:03 +0200332
Duncan Sandse3fb2f62006-01-13 11:06:46 +0100333 sarb = instance->cached_vcc->sarb;
334
335 if (sarb->tail + ATM_CELL_PAYLOAD > sarb->end) {
336 atm_rldbg(instance, "%s: buffer overrun (sarb->len %u, vcc: 0x%p)!\n",
337 __func__, sarb->len, vcc);
338 /* discard cells already received */
339 skb_trim(sarb, 0);
340 UDSL_ASSERT(sarb->tail + ATM_CELL_PAYLOAD <= sarb->end);
341 }
342
343 memcpy(sarb->tail, source + ATM_CELL_HEADER, ATM_CELL_PAYLOAD);
344 __skb_put(sarb, ATM_CELL_PAYLOAD);
345
346 if (pti & 1) {
347 struct sk_buff *skb;
348 unsigned int length;
349 unsigned int pdu_length;
350
351 length = (source[ATM_CELL_SIZE - 6] << 8) + source[ATM_CELL_SIZE - 5];
352
353 /* guard against overflow */
354 if (length > ATM_MAX_AAL5_PDU) {
355 atm_rldbg(instance, "%s: bogus length %u (vcc: 0x%p)!\n",
356 __func__, length, vcc);
Duncan Sandsc59bba72005-05-11 20:24:03 +0200357 atomic_inc(&vcc->stats->rx_err);
Duncan Sandse3fb2f62006-01-13 11:06:46 +0100358 goto out;
Duncan Sandsc59bba72005-05-11 20:24:03 +0200359 }
360
Duncan Sandse3fb2f62006-01-13 11:06:46 +0100361 pdu_length = usbatm_pdu_length(length);
Duncan Sandsc59bba72005-05-11 20:24:03 +0200362
Duncan Sandse3fb2f62006-01-13 11:06:46 +0100363 if (sarb->len < pdu_length) {
364 atm_rldbg(instance, "%s: bogus pdu_length %u (sarb->len: %u, vcc: 0x%p)!\n",
365 __func__, pdu_length, sarb->len, vcc);
366 atomic_inc(&vcc->stats->rx_err);
367 goto out;
Duncan Sandsc59bba72005-05-11 20:24:03 +0200368 }
369
Duncan Sandse3fb2f62006-01-13 11:06:46 +0100370 if (crc32_be(~0, sarb->tail - pdu_length, pdu_length) != 0xc704dd7b) {
371 atm_rldbg(instance, "%s: packet failed crc check (vcc: 0x%p)!\n",
372 __func__, vcc);
373 atomic_inc(&vcc->stats->rx_err);
374 goto out;
Duncan Sandsc59bba72005-05-11 20:24:03 +0200375 }
Duncan Sandse3fb2f62006-01-13 11:06:46 +0100376
377 vdbg("%s: got packet (length: %u, pdu_length: %u, vcc: 0x%p)", __func__, length, pdu_length, vcc);
378
379 if (!(skb = dev_alloc_skb(length))) {
380 if (printk_ratelimit())
381 atm_err(instance, "%s: no memory for skb (length: %u)!\n",
382 __func__, length);
383 atomic_inc(&vcc->stats->rx_drop);
384 goto out;
385 }
386
387 vdbg("%s: allocated new sk_buff (skb: 0x%p, skb->truesize: %u)", __func__, skb, skb->truesize);
388
389 if (!atm_charge(vcc, skb->truesize)) {
390 atm_rldbg(instance, "%s: failed atm_charge (skb->truesize: %u)!\n",
391 __func__, skb->truesize);
392 dev_kfree_skb_any(skb);
393 goto out; /* atm_charge increments rx_drop */
394 }
395
396 memcpy(skb->data, sarb->tail - pdu_length, length);
397 __skb_put(skb, length);
398
399 vdbg("%s: sending skb 0x%p, skb->len %u, skb->truesize %u",
400 __func__, skb, skb->len, skb->truesize);
401
402 PACKETDEBUG(skb->data, skb->len);
403
404 vcc->push(vcc, skb);
405
406 atomic_inc(&vcc->stats->rx);
407 out:
408 skb_trim(sarb, 0);
409 }
410}
411
412static void usbatm_extract_cells(struct usbatm_data *instance,
413 unsigned char *source, unsigned int avail_data)
414{
415 unsigned int stride = instance->rx_channel.stride;
416 unsigned int buf_usage = instance->buf_usage;
417
418 /* extract cells from incoming data, taking into account that
419 * the length of avail data may not be a multiple of stride */
420
421 if (buf_usage > 0) {
422 /* we have a partially received atm cell */
423 unsigned char *cell_buf = instance->cell_buf;
424 unsigned int space_left = stride - buf_usage;
425
426 UDSL_ASSERT(buf_usage <= stride);
427
428 if (avail_data >= space_left) {
429 /* add new data and process cell */
430 memcpy(cell_buf + buf_usage, source, space_left);
431 source += space_left;
432 avail_data -= space_left;
433 usbatm_extract_one_cell(instance, cell_buf);
434 instance->buf_usage = 0;
435 } else {
436 /* not enough data to fill the cell */
437 memcpy(cell_buf + buf_usage, source, avail_data);
438 instance->buf_usage = buf_usage + avail_data;
439 return;
440 }
441 }
442
443 for (; avail_data >= stride; avail_data -= stride, source += stride)
444 usbatm_extract_one_cell(instance, source);
445
446 if (avail_data > 0) {
447 /* length was not a multiple of stride -
448 * save remaining data for next call */
449 memcpy(instance->cell_buf, source, avail_data);
450 instance->buf_usage = avail_data;
Duncan Sandsc59bba72005-05-11 20:24:03 +0200451 }
452}
453
454
455/*************
456** encode **
457*************/
458
459static unsigned int usbatm_write_cells(struct usbatm_data *instance,
460 struct sk_buff *skb,
461 u8 *target, unsigned int avail_space)
462{
463 struct usbatm_control *ctrl = UDSL_SKB(skb);
464 struct atm_vcc *vcc = ctrl->atm.vcc;
Duncan Sands6f749472006-01-13 10:52:38 +0100465 unsigned int bytes_written;
Duncan Sandsc59bba72005-05-11 20:24:03 +0200466 unsigned int stride = instance->tx_channel.stride;
467
468 vdbg("%s: skb->len=%d, avail_space=%u", __func__, skb->len, avail_space);
469 UDSL_ASSERT(!(avail_space % stride));
470
Duncan Sands6f749472006-01-13 10:52:38 +0100471 for (bytes_written = 0; bytes_written < avail_space && ctrl->len;
472 bytes_written += stride, target += stride) {
Duncan Sandsc59bba72005-05-11 20:24:03 +0200473 unsigned int data_len = min_t(unsigned int, skb->len, ATM_CELL_PAYLOAD);
474 unsigned int left = ATM_CELL_PAYLOAD - data_len;
475 u8 *ptr = target;
476
477 ptr[0] = vcc->vpi >> 4;
478 ptr[1] = (vcc->vpi << 4) | (vcc->vci >> 12);
479 ptr[2] = vcc->vci >> 4;
480 ptr[3] = vcc->vci << 4;
481 ptr[4] = 0xec;
482 ptr += ATM_CELL_HEADER;
483
484 memcpy(ptr, skb->data, data_len);
485 ptr += data_len;
486 __skb_pull(skb, data_len);
487
488 if(!left)
489 continue;
490
491 memset(ptr, 0, left);
492
493 if (left >= ATM_AAL5_TRAILER) { /* trailer will go in this cell */
494 u8 *trailer = target + ATM_CELL_SIZE - ATM_AAL5_TRAILER;
495 /* trailer[0] = 0; UU = 0 */
496 /* trailer[1] = 0; CPI = 0 */
497 trailer[2] = ctrl->len >> 8;
498 trailer[3] = ctrl->len;
499
500 ctrl->crc = ~ crc32_be(ctrl->crc, ptr, left - 4);
501
502 trailer[4] = ctrl->crc >> 24;
503 trailer[5] = ctrl->crc >> 16;
504 trailer[6] = ctrl->crc >> 8;
505 trailer[7] = ctrl->crc;
506
507 target[3] |= 0x2; /* adjust PTI */
508
509 ctrl->len = 0; /* tag this skb finished */
510 }
511 else
512 ctrl->crc = crc32_be(ctrl->crc, ptr, left);
513 }
514
Duncan Sands6f749472006-01-13 10:52:38 +0100515 return bytes_written;
Duncan Sandsc59bba72005-05-11 20:24:03 +0200516}
517
518
519/**************
520** receive **
521**************/
522
523static void usbatm_rx_process(unsigned long data)
524{
525 struct usbatm_data *instance = (struct usbatm_data *)data;
526 struct urb *urb;
527
528 while ((urb = usbatm_pop_urb(&instance->rx_channel))) {
529 vdbg("%s: processing urb 0x%p", __func__, urb);
530
531 if (usb_pipeisoc(urb->pipe)) {
Duncan Sandse3fb2f62006-01-13 11:06:46 +0100532 unsigned char *merge_start = NULL;
533 unsigned int merge_length = 0;
534 const unsigned int packet_size = instance->rx_channel.packet_size;
Duncan Sandsc59bba72005-05-11 20:24:03 +0200535 int i;
Duncan Sandse3fb2f62006-01-13 11:06:46 +0100536
537 for (i = 0; i < urb->number_of_packets; i++) {
538 if (!urb->iso_frame_desc[i].status) {
539 unsigned int actual_length = urb->iso_frame_desc[i].actual_length;
540
541 UDSL_ASSERT(actual_length <= packet_size);
542
543 if (!merge_length)
544 merge_start = (unsigned char *)urb->transfer_buffer + urb->iso_frame_desc[i].offset;
545 merge_length += actual_length;
546 if (merge_length && (actual_length < packet_size)) {
547 usbatm_extract_cells(instance, merge_start, merge_length);
548 merge_length = 0;
549 }
550 } else {
551 atm_rldbg(instance, "%s: status %d in frame %d!\n", __func__, urb->status, i);
552 if (merge_length)
553 usbatm_extract_cells(instance, merge_start, merge_length);
554 merge_length = 0;
555 instance->buf_usage = 0;
556 }
557 }
558
559 if (merge_length)
560 usbatm_extract_cells(instance, merge_start, merge_length);
561 } else
Duncan Sandsc59bba72005-05-11 20:24:03 +0200562 if (!urb->status)
563 usbatm_extract_cells(instance, urb->transfer_buffer, urb->actual_length);
Duncan Sandse3fb2f62006-01-13 11:06:46 +0100564 else
565 instance->buf_usage = 0;
Duncan Sandsc59bba72005-05-11 20:24:03 +0200566
567 if (usbatm_submit_urb(urb))
568 return;
569 }
570}
571
572
573/***********
574** send **
575***********/
576
577static void usbatm_tx_process(unsigned long data)
578{
579 struct usbatm_data *instance = (struct usbatm_data *)data;
580 struct sk_buff *skb = instance->current_skb;
581 struct urb *urb = NULL;
582 const unsigned int buf_size = instance->tx_channel.buf_size;
Duncan Sands6f749472006-01-13 10:52:38 +0100583 unsigned int bytes_written = 0;
Duncan Sandsc59bba72005-05-11 20:24:03 +0200584 u8 *buffer = NULL;
585
586 if (!skb)
587 skb = skb_dequeue(&instance->sndqueue);
588
589 while (skb) {
590 if (!urb) {
591 urb = usbatm_pop_urb(&instance->tx_channel);
592 if (!urb)
593 break; /* no more senders */
594 buffer = urb->transfer_buffer;
Duncan Sands6f749472006-01-13 10:52:38 +0100595 bytes_written = (urb->status == -EAGAIN) ?
Duncan Sandsc59bba72005-05-11 20:24:03 +0200596 urb->transfer_buffer_length : 0;
597 }
598
Duncan Sands6f749472006-01-13 10:52:38 +0100599 bytes_written += usbatm_write_cells(instance, skb,
600 buffer + bytes_written,
601 buf_size - bytes_written);
Duncan Sandsc59bba72005-05-11 20:24:03 +0200602
603 vdbg("%s: wrote %u bytes from skb 0x%p to urb 0x%p",
Duncan Sands6f749472006-01-13 10:52:38 +0100604 __func__, bytes_written, skb, urb);
Duncan Sandsc59bba72005-05-11 20:24:03 +0200605
606 if (!UDSL_SKB(skb)->len) {
607 struct atm_vcc *vcc = UDSL_SKB(skb)->atm.vcc;
608
609 usbatm_pop(vcc, skb);
610 atomic_inc(&vcc->stats->tx);
611
612 skb = skb_dequeue(&instance->sndqueue);
613 }
614
Duncan Sands6f749472006-01-13 10:52:38 +0100615 if (bytes_written == buf_size || (!skb && bytes_written)) {
616 urb->transfer_buffer_length = bytes_written;
Duncan Sandsc59bba72005-05-11 20:24:03 +0200617
618 if (usbatm_submit_urb(urb))
619 break;
620 urb = NULL;
621 }
622 }
623
624 instance->current_skb = skb;
625}
626
627static void usbatm_cancel_send(struct usbatm_data *instance,
628 struct atm_vcc *vcc)
629{
630 struct sk_buff *skb, *n;
631
632 atm_dbg(instance, "%s entered\n", __func__);
633 spin_lock_irq(&instance->sndqueue.lock);
634 for (skb = instance->sndqueue.next, n = skb->next;
635 skb != (struct sk_buff *)&instance->sndqueue;
636 skb = n, n = skb->next)
637 if (UDSL_SKB(skb)->atm.vcc == vcc) {
638 atm_dbg(instance, "%s: popping skb 0x%p\n", __func__, skb);
639 __skb_unlink(skb, &instance->sndqueue);
640 usbatm_pop(vcc, skb);
641 }
642 spin_unlock_irq(&instance->sndqueue.lock);
643
644 tasklet_disable(&instance->tx_channel.tasklet);
645 if ((skb = instance->current_skb) && (UDSL_SKB(skb)->atm.vcc == vcc)) {
646 atm_dbg(instance, "%s: popping current skb (0x%p)\n", __func__, skb);
647 instance->current_skb = NULL;
648 usbatm_pop(vcc, skb);
649 }
650 tasklet_enable(&instance->tx_channel.tasklet);
651 atm_dbg(instance, "%s done\n", __func__);
652}
653
654static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
655{
656 struct usbatm_data *instance = vcc->dev->dev_data;
657 struct usbatm_control *ctrl = UDSL_SKB(skb);
658 int err;
659
660 vdbg("%s called (skb 0x%p, len %u)", __func__, skb, skb->len);
661
Duncan Sands0e42a622006-01-13 10:05:15 +0100662 /* racy disconnection check - fine */
663 if (!instance || instance->disconnected) {
664#ifdef DEBUG
665 if (printk_ratelimit())
666 printk(KERN_DEBUG "%s: %s!\n", __func__, instance ? "disconnected" : "NULL instance");
667#endif
Duncan Sandsc59bba72005-05-11 20:24:03 +0200668 err = -ENODEV;
669 goto fail;
670 }
671
672 if (vcc->qos.aal != ATM_AAL5) {
Duncan Sands0ec3c7e2006-01-17 11:15:13 +0100673 atm_rldbg(instance, "%s: unsupported ATM type %d!\n", __func__, vcc->qos.aal);
Duncan Sandsc59bba72005-05-11 20:24:03 +0200674 err = -EINVAL;
675 goto fail;
676 }
677
678 if (skb->len > ATM_MAX_AAL5_PDU) {
Duncan Sands0ec3c7e2006-01-17 11:15:13 +0100679 atm_rldbg(instance, "%s: packet too long (%d vs %d)!\n",
Duncan Sandsc59bba72005-05-11 20:24:03 +0200680 __func__, skb->len, ATM_MAX_AAL5_PDU);
681 err = -EINVAL;
682 goto fail;
683 }
684
685 PACKETDEBUG(skb->data, skb->len);
686
687 /* initialize the control block */
688 ctrl->atm.vcc = vcc;
689 ctrl->len = skb->len;
690 ctrl->crc = crc32_be(~0, skb->data, skb->len);
691
692 skb_queue_tail(&instance->sndqueue, skb);
693 tasklet_schedule(&instance->tx_channel.tasklet);
694
695 return 0;
696
697 fail:
698 usbatm_pop(vcc, skb);
699 return err;
700}
701
702
703/********************
704** bean counting **
705********************/
706
707static void usbatm_destroy_instance(struct kref *kref)
708{
709 struct usbatm_data *instance = container_of(kref, struct usbatm_data, refcount);
710
711 dbg("%s", __func__);
712
713 tasklet_kill(&instance->rx_channel.tasklet);
714 tasklet_kill(&instance->tx_channel.tasklet);
715 usb_put_dev(instance->usb_dev);
716 kfree(instance);
717}
718
Adrian Bunk3d485862005-11-20 23:56:11 +0100719static void usbatm_get_instance(struct usbatm_data *instance)
Duncan Sandsc59bba72005-05-11 20:24:03 +0200720{
721 dbg("%s", __func__);
722
723 kref_get(&instance->refcount);
724}
725
Adrian Bunk3d485862005-11-20 23:56:11 +0100726static void usbatm_put_instance(struct usbatm_data *instance)
Duncan Sandsc59bba72005-05-11 20:24:03 +0200727{
728 dbg("%s", __func__);
729
730 kref_put(&instance->refcount, usbatm_destroy_instance);
731}
732
733
734/**********
735** ATM **
736**********/
737
Duncan Sands0ec3c7e2006-01-17 11:15:13 +0100738static void usbatm_atm_dev_close(struct atm_dev *atm_dev)
Duncan Sandsc59bba72005-05-11 20:24:03 +0200739{
Duncan Sands0ec3c7e2006-01-17 11:15:13 +0100740 struct usbatm_data *instance = atm_dev->dev_data;
Duncan Sandsc59bba72005-05-11 20:24:03 +0200741
742 dbg("%s", __func__);
743
744 if (!instance)
745 return;
746
Duncan Sands0ec3c7e2006-01-17 11:15:13 +0100747 atm_dev->dev_data = NULL; /* catch bugs */
Duncan Sandsc59bba72005-05-11 20:24:03 +0200748 usbatm_put_instance(instance); /* taken in usbatm_atm_init */
749}
750
751static int usbatm_atm_proc_read(struct atm_dev *atm_dev, loff_t * pos, char *page)
752{
753 struct usbatm_data *instance = atm_dev->dev_data;
754 int left = *pos;
755
756 if (!instance) {
757 dbg("%s: NULL instance!", __func__);
758 return -ENODEV;
759 }
760
761 if (!left--)
762 return sprintf(page, "%s\n", instance->description);
763
764 if (!left--)
765 return sprintf(page, "MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
766 atm_dev->esi[0], atm_dev->esi[1],
767 atm_dev->esi[2], atm_dev->esi[3],
768 atm_dev->esi[4], atm_dev->esi[5]);
769
770 if (!left--)
771 return sprintf(page,
772 "AAL5: tx %d ( %d err ), rx %d ( %d err, %d drop )\n",
773 atomic_read(&atm_dev->stats.aal5.tx),
774 atomic_read(&atm_dev->stats.aal5.tx_err),
775 atomic_read(&atm_dev->stats.aal5.rx),
776 atomic_read(&atm_dev->stats.aal5.rx_err),
777 atomic_read(&atm_dev->stats.aal5.rx_drop));
778
Duncan Sands0e42a622006-01-13 10:05:15 +0100779 if (!left--) {
780 if (instance->disconnected)
781 return sprintf(page, "Disconnected\n");
782 else
783 switch (atm_dev->signal) {
784 case ATM_PHY_SIG_FOUND:
785 return sprintf(page, "Line up\n");
786 case ATM_PHY_SIG_LOST:
787 return sprintf(page, "Line down\n");
788 default:
789 return sprintf(page, "Line state unknown\n");
790 }
791 }
Duncan Sandsc59bba72005-05-11 20:24:03 +0200792
793 return 0;
794}
795
796static int usbatm_atm_open(struct atm_vcc *vcc)
797{
798 struct usbatm_data *instance = vcc->dev->dev_data;
799 struct usbatm_vcc_data *new = NULL;
800 int ret;
801 int vci = vcc->vci;
802 short vpi = vcc->vpi;
803
804 if (!instance) {
805 dbg("%s: NULL data!", __func__);
806 return -ENODEV;
807 }
808
809 atm_dbg(instance, "%s: vpi %hd, vci %d\n", __func__, vpi, vci);
810
811 /* only support AAL5 */
Duncan Sands0ec3c7e2006-01-17 11:15:13 +0100812 if ((vcc->qos.aal != ATM_AAL5)) {
813 atm_warn(instance, "%s: unsupported ATM type %d!\n", __func__, vcc->qos.aal);
Duncan Sandsc59bba72005-05-11 20:24:03 +0200814 return -EINVAL;
815 }
816
Duncan Sands0ec3c7e2006-01-17 11:15:13 +0100817 /* sanity checks */
818 if ((vcc->qos.rxtp.max_sdu < 0) || (vcc->qos.rxtp.max_sdu > ATM_MAX_AAL5_PDU)) {
819 atm_dbg(instance, "%s: max_sdu %d out of range!\n", __func__, vcc->qos.rxtp.max_sdu);
820 return -EINVAL;
821 }
822
823 down(&instance->serialize); /* vs self, usbatm_atm_close, usbatm_usb_disconnect */
Duncan Sandsc59bba72005-05-11 20:24:03 +0200824
Duncan Sands0e42a622006-01-13 10:05:15 +0100825 if (instance->disconnected) {
826 atm_dbg(instance, "%s: disconnected!\n", __func__);
827 ret = -ENODEV;
828 goto fail;
829 }
830
Duncan Sandsc59bba72005-05-11 20:24:03 +0200831 if (usbatm_find_vcc(instance, vpi, vci)) {
832 atm_dbg(instance, "%s: %hd/%d already in use!\n", __func__, vpi, vci);
833 ret = -EADDRINUSE;
834 goto fail;
835 }
836
Duncan Sands9a734ef2006-01-13 09:38:22 +0100837 if (!(new = kzalloc(sizeof(struct usbatm_vcc_data), GFP_KERNEL))) {
Duncan Sands0ec3c7e2006-01-17 11:15:13 +0100838 atm_err(instance, "%s: no memory for vcc_data!\n", __func__);
Duncan Sandsc59bba72005-05-11 20:24:03 +0200839 ret = -ENOMEM;
840 goto fail;
841 }
842
Duncan Sandsc59bba72005-05-11 20:24:03 +0200843 new->vcc = vcc;
844 new->vpi = vpi;
845 new->vci = vci;
846
847 new->sarb = alloc_skb(usbatm_pdu_length(vcc->qos.rxtp.max_sdu), GFP_KERNEL);
848 if (!new->sarb) {
Duncan Sands0ec3c7e2006-01-17 11:15:13 +0100849 atm_err(instance, "%s: no memory for SAR buffer!\n", __func__);
Duncan Sandsc59bba72005-05-11 20:24:03 +0200850 ret = -ENOMEM;
851 goto fail;
852 }
853
854 vcc->dev_data = new;
855
856 tasklet_disable(&instance->rx_channel.tasklet);
Duncan Sandse3fb2f62006-01-13 11:06:46 +0100857 instance->cached_vcc = new;
858 instance->cached_vpi = vpi;
859 instance->cached_vci = vci;
Duncan Sandsc59bba72005-05-11 20:24:03 +0200860 list_add(&new->list, &instance->vcc_list);
861 tasklet_enable(&instance->rx_channel.tasklet);
862
863 set_bit(ATM_VF_ADDR, &vcc->flags);
864 set_bit(ATM_VF_PARTIAL, &vcc->flags);
865 set_bit(ATM_VF_READY, &vcc->flags);
866
867 up(&instance->serialize);
868
869 atm_dbg(instance, "%s: allocated vcc data 0x%p\n", __func__, new);
870
871 return 0;
872
873fail:
874 kfree(new);
875 up(&instance->serialize);
876 return ret;
877}
878
879static void usbatm_atm_close(struct atm_vcc *vcc)
880{
881 struct usbatm_data *instance = vcc->dev->dev_data;
882 struct usbatm_vcc_data *vcc_data = vcc->dev_data;
883
884 if (!instance || !vcc_data) {
885 dbg("%s: NULL data!", __func__);
886 return;
887 }
888
889 atm_dbg(instance, "%s entered\n", __func__);
890
891 atm_dbg(instance, "%s: deallocating vcc 0x%p with vpi %d vci %d\n",
892 __func__, vcc_data, vcc_data->vpi, vcc_data->vci);
893
894 usbatm_cancel_send(instance, vcc);
895
Duncan Sands0ec3c7e2006-01-17 11:15:13 +0100896 down(&instance->serialize); /* vs self, usbatm_atm_open, usbatm_usb_disconnect */
Duncan Sandsc59bba72005-05-11 20:24:03 +0200897
898 tasklet_disable(&instance->rx_channel.tasklet);
Duncan Sandse3fb2f62006-01-13 11:06:46 +0100899 if (instance->cached_vcc == vcc_data) {
900 instance->cached_vcc = NULL;
901 instance->cached_vpi = ATM_VPI_UNSPEC;
902 instance->cached_vci = ATM_VCI_UNSPEC;
903 }
Duncan Sandsc59bba72005-05-11 20:24:03 +0200904 list_del(&vcc_data->list);
905 tasklet_enable(&instance->rx_channel.tasklet);
906
907 kfree_skb(vcc_data->sarb);
908 vcc_data->sarb = NULL;
909
910 kfree(vcc_data);
911 vcc->dev_data = NULL;
912
913 vcc->vpi = ATM_VPI_UNSPEC;
914 vcc->vci = ATM_VCI_UNSPEC;
915 clear_bit(ATM_VF_READY, &vcc->flags);
916 clear_bit(ATM_VF_PARTIAL, &vcc->flags);
917 clear_bit(ATM_VF_ADDR, &vcc->flags);
918
919 up(&instance->serialize);
920
921 atm_dbg(instance, "%s successful\n", __func__);
922}
923
Duncan Sands0ec3c7e2006-01-17 11:15:13 +0100924static int usbatm_atm_ioctl(struct atm_dev *atm_dev, unsigned int cmd,
Duncan Sandsc59bba72005-05-11 20:24:03 +0200925 void __user * arg)
926{
Duncan Sands0e42a622006-01-13 10:05:15 +0100927 struct usbatm_data *instance = atm_dev->dev_data;
928
929 if (!instance || instance->disconnected) {
930 dbg("%s: %s!", __func__, instance ? "disconnected" : "NULL instance");
931 return -ENODEV;
932 }
933
Duncan Sandsc59bba72005-05-11 20:24:03 +0200934 switch (cmd) {
935 case ATM_QUERYLOOP:
936 return put_user(ATM_LM_NONE, (int __user *)arg) ? -EFAULT : 0;
937 default:
938 return -ENOIOCTLCMD;
939 }
940}
941
942static int usbatm_atm_init(struct usbatm_data *instance)
943{
944 struct atm_dev *atm_dev;
945 int ret, i;
946
Duncan Sands0ec3c7e2006-01-17 11:15:13 +0100947 /* ATM init. The ATM initialization scheme suffers from an intrinsic race
948 * condition: callbacks we register can be executed at once, before we have
949 * initialized the struct atm_dev. To protect against this, all callbacks
950 * abort if atm_dev->dev_data is NULL. */
Duncan Sandsc59bba72005-05-11 20:24:03 +0200951 atm_dev = atm_dev_register(instance->driver_name, &usbatm_atm_devops, -1, NULL);
952 if (!atm_dev) {
Duncan Sands0ec3c7e2006-01-17 11:15:13 +0100953 usb_err(instance, "%s: failed to register ATM device!\n", __func__);
Duncan Sandsc59bba72005-05-11 20:24:03 +0200954 return -1;
955 }
956
957 instance->atm_dev = atm_dev;
958
959 atm_dev->ci_range.vpi_bits = ATM_CI_MAX;
960 atm_dev->ci_range.vci_bits = ATM_CI_MAX;
961 atm_dev->signal = ATM_PHY_SIG_UNKNOWN;
962
963 /* temp init ATM device, set to 128kbit */
964 atm_dev->link_rate = 128 * 1000 / 424;
965
966 if (instance->driver->atm_start && ((ret = instance->driver->atm_start(instance, atm_dev)) < 0)) {
Duncan Sands0ec3c7e2006-01-17 11:15:13 +0100967 atm_err(instance, "%s: atm_start failed: %d!\n", __func__, ret);
Duncan Sandsc59bba72005-05-11 20:24:03 +0200968 goto fail;
969 }
970
Duncan Sandsc59bba72005-05-11 20:24:03 +0200971 usbatm_get_instance(instance); /* dropped in usbatm_atm_dev_close */
Duncan Sands0ec3c7e2006-01-17 11:15:13 +0100972
973 /* ready for ATM callbacks */
Duncan Sandsc59bba72005-05-11 20:24:03 +0200974 mb();
975 atm_dev->dev_data = instance;
976
977 /* submit all rx URBs */
978 for (i = 0; i < num_rcv_urbs; i++)
979 usbatm_submit_urb(instance->urbs[i]);
980
981 return 0;
982
983 fail:
984 instance->atm_dev = NULL;
Stanislaw Gruszka64bf69d2005-11-29 16:16:41 -0800985 atm_dev_deregister(atm_dev); /* usbatm_atm_dev_close will eventually be called */
Duncan Sandsc59bba72005-05-11 20:24:03 +0200986 return ret;
987}
988
989
990/**********
991** USB **
992**********/
993
994static int usbatm_do_heavy_init(void *arg)
995{
996 struct usbatm_data *instance = arg;
997 int ret;
998
999 daemonize(instance->driver->driver_name);
1000 allow_signal(SIGTERM);
1001
1002 complete(&instance->thread_started);
1003
1004 ret = instance->driver->heavy_init(instance, instance->usb_intf);
1005
1006 if (!ret)
1007 ret = usbatm_atm_init(instance);
1008
1009 down(&instance->serialize);
1010 instance->thread_pid = -1;
1011 up(&instance->serialize);
1012
1013 complete_and_exit(&instance->thread_exited, ret);
1014}
1015
1016static int usbatm_heavy_init(struct usbatm_data *instance)
1017{
1018 int ret = kernel_thread(usbatm_do_heavy_init, instance, CLONE_KERNEL);
1019
1020 if (ret < 0) {
Duncan Sands0ec3c7e2006-01-17 11:15:13 +01001021 usb_err(instance, "%s: failed to create kernel_thread (%d)!\n", __func__, ret);
Duncan Sandsc59bba72005-05-11 20:24:03 +02001022 return ret;
1023 }
1024
1025 down(&instance->serialize);
1026 instance->thread_pid = ret;
1027 up(&instance->serialize);
1028
1029 wait_for_completion(&instance->thread_started);
1030
1031 return 0;
1032}
1033
1034static void usbatm_tasklet_schedule(unsigned long data)
1035{
1036 tasklet_schedule((struct tasklet_struct *) data);
1037}
1038
1039static inline void usbatm_init_channel(struct usbatm_channel *channel)
1040{
1041 spin_lock_init(&channel->lock);
1042 INIT_LIST_HEAD(&channel->list);
1043 channel->delay.function = usbatm_tasklet_schedule;
1044 channel->delay.data = (unsigned long) &channel->tasklet;
1045 init_timer(&channel->delay);
1046}
1047
1048int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id,
1049 struct usbatm_driver *driver)
1050{
1051 struct device *dev = &intf->dev;
1052 struct usb_device *usb_dev = interface_to_usbdev(intf);
1053 struct usbatm_data *instance;
1054 char *buf;
1055 int error = -ENOMEM;
1056 int i, length;
Duncan Sands6f749472006-01-13 10:52:38 +01001057 unsigned int maxpacket, num_packets;
Duncan Sandsc59bba72005-05-11 20:24:03 +02001058
Duncan Sands0ec3c7e2006-01-17 11:15:13 +01001059 dev_dbg(dev, "%s: trying driver %s with vendor=%04x, product=%04x, ifnum %2d\n",
Duncan Sandsc59bba72005-05-11 20:24:03 +02001060 __func__, driver->driver_name,
1061 le16_to_cpu(usb_dev->descriptor.idVendor),
1062 le16_to_cpu(usb_dev->descriptor.idProduct),
1063 intf->altsetting->desc.bInterfaceNumber);
1064
1065 /* instance init */
Pekka Enberg7b842b62005-09-06 15:18:34 -07001066 instance = kzalloc(sizeof(*instance) + sizeof(struct urb *) * (num_rcv_urbs + num_snd_urbs), GFP_KERNEL);
Duncan Sandsc59bba72005-05-11 20:24:03 +02001067 if (!instance) {
Duncan Sands0ec3c7e2006-01-17 11:15:13 +01001068 dev_err(dev, "%s: no memory for instance data!\n", __func__);
Duncan Sandsc59bba72005-05-11 20:24:03 +02001069 return -ENOMEM;
1070 }
1071
Duncan Sandsc59bba72005-05-11 20:24:03 +02001072 /* public fields */
1073
1074 instance->driver = driver;
1075 snprintf(instance->driver_name, sizeof(instance->driver_name), driver->driver_name);
1076
1077 instance->usb_dev = usb_dev;
1078 instance->usb_intf = intf;
1079
1080 buf = instance->description;
1081 length = sizeof(instance->description);
1082
1083 if ((i = usb_string(usb_dev, usb_dev->descriptor.iProduct, buf, length)) < 0)
1084 goto bind;
1085
1086 buf += i;
1087 length -= i;
1088
1089 i = scnprintf(buf, length, " (");
1090 buf += i;
1091 length -= i;
1092
1093 if (length <= 0 || (i = usb_make_path(usb_dev, buf, length)) < 0)
1094 goto bind;
1095
1096 buf += i;
1097 length -= i;
1098
1099 snprintf(buf, length, ")");
1100
1101 bind:
Duncan Sands35644b02006-01-17 11:16:13 +01001102 if (driver->bind && (error = driver->bind(instance, intf, id)) < 0) {
Duncan Sands0ec3c7e2006-01-17 11:15:13 +01001103 dev_err(dev, "%s: bind failed: %d!\n", __func__, error);
Duncan Sandsc59bba72005-05-11 20:24:03 +02001104 goto fail_free;
1105 }
1106
1107 /* private fields */
1108
1109 kref_init(&instance->refcount); /* dropped in usbatm_usb_disconnect */
1110 init_MUTEX(&instance->serialize);
1111
1112 instance->thread_pid = -1;
1113 init_completion(&instance->thread_started);
1114 init_completion(&instance->thread_exited);
1115
1116 INIT_LIST_HEAD(&instance->vcc_list);
Duncan Sands80aae7a2006-01-13 10:59:23 +01001117 skb_queue_head_init(&instance->sndqueue);
Duncan Sandsc59bba72005-05-11 20:24:03 +02001118
1119 usbatm_init_channel(&instance->rx_channel);
1120 usbatm_init_channel(&instance->tx_channel);
1121 tasklet_init(&instance->rx_channel.tasklet, usbatm_rx_process, (unsigned long)instance);
1122 tasklet_init(&instance->tx_channel.tasklet, usbatm_tx_process, (unsigned long)instance);
Duncan Sandsc59bba72005-05-11 20:24:03 +02001123 instance->rx_channel.stride = ATM_CELL_SIZE + driver->rx_padding;
1124 instance->tx_channel.stride = ATM_CELL_SIZE + driver->tx_padding;
Duncan Sandsc59bba72005-05-11 20:24:03 +02001125 instance->rx_channel.usbatm = instance->tx_channel.usbatm = instance;
1126
Duncan Sands80aae7a2006-01-13 10:59:23 +01001127 if ((instance->flags & UDSL_USE_ISOC) && driver->isoc_in)
1128 instance->rx_channel.endpoint = usb_rcvisocpipe(usb_dev, driver->isoc_in);
1129 else
1130 instance->rx_channel.endpoint = usb_rcvbulkpipe(usb_dev, driver->bulk_in);
1131
1132 instance->tx_channel.endpoint = usb_sndbulkpipe(usb_dev, driver->bulk_out);
1133
Duncan Sands6f749472006-01-13 10:52:38 +01001134 /* tx buffer size must be a positive multiple of the stride */
1135 instance->tx_channel.buf_size = max (instance->tx_channel.stride,
1136 snd_buf_bytes - (snd_buf_bytes % instance->tx_channel.stride));
1137
1138 /* rx buffer size must be a positive multiple of the endpoint maxpacket */
1139 maxpacket = usb_maxpacket(usb_dev, instance->rx_channel.endpoint, 0);
1140
1141 if ((maxpacket < 1) || (maxpacket > UDSL_MAX_BUF_SIZE)) {
1142 dev_err(dev, "%s: invalid endpoint %02x!\n", __func__,
1143 usb_pipeendpoint(instance->rx_channel.endpoint));
1144 error = -EINVAL;
1145 goto fail_unbind;
1146 }
1147
1148 num_packets = max (1U, (rcv_buf_bytes + maxpacket / 2) / maxpacket); /* round */
1149
1150 if (num_packets * maxpacket > UDSL_MAX_BUF_SIZE)
1151 num_packets--;
1152
1153 instance->rx_channel.buf_size = num_packets * maxpacket;
Duncan Sands80aae7a2006-01-13 10:59:23 +01001154 instance->rx_channel.packet_size = maxpacket;
Duncan Sands6f749472006-01-13 10:52:38 +01001155
1156#ifdef DEBUG
1157 for (i = 0; i < 2; i++) {
1158 struct usbatm_channel *channel = i ?
1159 &instance->tx_channel : &instance->rx_channel;
1160
1161 dev_dbg(dev, "%s: using %d byte buffer for %s channel 0x%p\n", __func__, channel->buf_size, i ? "tx" : "rx", channel);
1162 }
1163#endif
1164
Duncan Sands80aae7a2006-01-13 10:59:23 +01001165 /* initialize urbs */
Duncan Sandsc59bba72005-05-11 20:24:03 +02001166
1167 for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) {
Duncan Sandsc59bba72005-05-11 20:24:03 +02001168 u8 *buffer;
Duncan Sandsc59bba72005-05-11 20:24:03 +02001169 struct usbatm_channel *channel = i < num_rcv_urbs ?
1170 &instance->rx_channel : &instance->tx_channel;
Duncan Sands80aae7a2006-01-13 10:59:23 +01001171 struct urb *urb;
1172 unsigned int iso_packets = usb_pipeisoc(channel->endpoint) ? channel->buf_size / channel->packet_size : 0;
Duncan Sandsc59bba72005-05-11 20:24:03 +02001173
Duncan Sands80aae7a2006-01-13 10:59:23 +01001174 UDSL_ASSERT(!usb_pipeisoc(channel->endpoint) || usb_pipein(channel->endpoint));
Duncan Sandsc59bba72005-05-11 20:24:03 +02001175
1176 urb = usb_alloc_urb(iso_packets, GFP_KERNEL);
1177 if (!urb) {
Duncan Sands0ec3c7e2006-01-17 11:15:13 +01001178 dev_err(dev, "%s: no memory for urb %d!\n", __func__, i);
Duncan Sands72ef8ab2006-01-13 10:07:08 +01001179 error = -ENOMEM;
Duncan Sandsc59bba72005-05-11 20:24:03 +02001180 goto fail_unbind;
1181 }
1182
Duncan Sands65412e42005-05-27 10:00:08 +02001183 instance->urbs[i] = urb;
1184
Duncan Sands9a734ef2006-01-13 09:38:22 +01001185 /* zero the tx padding to avoid leaking information */
1186 buffer = kzalloc(channel->buf_size, GFP_KERNEL);
Duncan Sandsc59bba72005-05-11 20:24:03 +02001187 if (!buffer) {
Duncan Sands0ec3c7e2006-01-17 11:15:13 +01001188 dev_err(dev, "%s: no memory for buffer %d!\n", __func__, i);
Duncan Sands72ef8ab2006-01-13 10:07:08 +01001189 error = -ENOMEM;
Duncan Sandsc59bba72005-05-11 20:24:03 +02001190 goto fail_unbind;
1191 }
Duncan Sandsc59bba72005-05-11 20:24:03 +02001192
1193 usb_fill_bulk_urb(urb, instance->usb_dev, channel->endpoint,
1194 buffer, channel->buf_size, usbatm_complete, channel);
1195 if (iso_packets) {
1196 int j;
1197 urb->interval = 1;
1198 urb->transfer_flags = URB_ISO_ASAP;
1199 urb->number_of_packets = iso_packets;
1200 for (j = 0; j < iso_packets; j++) {
Duncan Sands80aae7a2006-01-13 10:59:23 +01001201 urb->iso_frame_desc[j].offset = channel->packet_size * j;
1202 urb->iso_frame_desc[j].length = channel->packet_size;
Duncan Sandsc59bba72005-05-11 20:24:03 +02001203 }
1204 }
1205
1206 /* put all tx URBs on the list of spares */
1207 if (i >= num_rcv_urbs)
1208 list_add_tail(&urb->urb_list, &channel->list);
1209
1210 vdbg("%s: alloced buffer 0x%p buf size %u urb 0x%p",
1211 __func__, urb->transfer_buffer, urb->transfer_buffer_length, urb);
Duncan Sandsc59bba72005-05-11 20:24:03 +02001212 }
1213
Duncan Sandse3fb2f62006-01-13 11:06:46 +01001214 instance->cached_vpi = ATM_VPI_UNSPEC;
1215 instance->cached_vci = ATM_VCI_UNSPEC;
1216 instance->cell_buf = kmalloc(instance->rx_channel.stride, GFP_KERNEL);
1217
1218 if (!instance->cell_buf) {
1219 dev_err(dev, "%s: no memory for cell buffer!\n", __func__);
1220 error = -ENOMEM;
1221 goto fail_unbind;
1222 }
1223
Duncan Sands35644b02006-01-17 11:16:13 +01001224 if (!(instance->flags & UDSL_SKIP_HEAVY_INIT) && driver->heavy_init) {
Duncan Sandsc59bba72005-05-11 20:24:03 +02001225 error = usbatm_heavy_init(instance);
1226 } else {
1227 complete(&instance->thread_exited); /* pretend that heavy_init was run */
1228 error = usbatm_atm_init(instance);
1229 }
1230
1231 if (error < 0)
1232 goto fail_unbind;
1233
1234 usb_get_dev(usb_dev);
1235 usb_set_intfdata(intf, instance);
1236
1237 return 0;
1238
1239 fail_unbind:
1240 if (instance->driver->unbind)
1241 instance->driver->unbind(instance, intf);
1242 fail_free:
Duncan Sandse3fb2f62006-01-13 11:06:46 +01001243 kfree(instance->cell_buf);
1244
Duncan Sandsc59bba72005-05-11 20:24:03 +02001245 for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) {
1246 if (instance->urbs[i])
1247 kfree(instance->urbs[i]->transfer_buffer);
1248 usb_free_urb(instance->urbs[i]);
1249 }
1250
1251 kfree (instance);
1252
1253 return error;
1254}
1255EXPORT_SYMBOL_GPL(usbatm_usb_probe);
1256
1257void usbatm_usb_disconnect(struct usb_interface *intf)
1258{
1259 struct device *dev = &intf->dev;
1260 struct usbatm_data *instance = usb_get_intfdata(intf);
Duncan Sands0e42a622006-01-13 10:05:15 +01001261 struct usbatm_vcc_data *vcc_data;
Duncan Sandsc59bba72005-05-11 20:24:03 +02001262 int i;
1263
1264 dev_dbg(dev, "%s entered\n", __func__);
1265
1266 if (!instance) {
1267 dev_dbg(dev, "%s: NULL instance!\n", __func__);
1268 return;
1269 }
1270
1271 usb_set_intfdata(intf, NULL);
1272
1273 down(&instance->serialize);
Duncan Sands0e42a622006-01-13 10:05:15 +01001274 instance->disconnected = 1;
Duncan Sandsc59bba72005-05-11 20:24:03 +02001275 if (instance->thread_pid >= 0)
1276 kill_proc(instance->thread_pid, SIGTERM, 1);
1277 up(&instance->serialize);
1278
1279 wait_for_completion(&instance->thread_exited);
1280
Duncan Sands0e42a622006-01-13 10:05:15 +01001281 down(&instance->serialize);
1282 list_for_each_entry(vcc_data, &instance->vcc_list, list)
1283 vcc_release_async(vcc_data->vcc, -EPIPE);
1284 up(&instance->serialize);
1285
Duncan Sandsc59bba72005-05-11 20:24:03 +02001286 tasklet_disable(&instance->rx_channel.tasklet);
1287 tasklet_disable(&instance->tx_channel.tasklet);
1288
1289 for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++)
1290 usb_kill_urb(instance->urbs[i]);
1291
1292 del_timer_sync(&instance->rx_channel.delay);
1293 del_timer_sync(&instance->tx_channel.delay);
1294
Duncan Sands0e42a622006-01-13 10:05:15 +01001295 /* turn usbatm_[rt]x_process into something close to a no-op */
1296 /* no need to take the spinlock */
1297 INIT_LIST_HEAD(&instance->rx_channel.list);
1298 INIT_LIST_HEAD(&instance->tx_channel.list);
1299
1300 tasklet_enable(&instance->rx_channel.tasklet);
1301 tasklet_enable(&instance->tx_channel.tasklet);
1302
Duncan Sandsc59bba72005-05-11 20:24:03 +02001303 if (instance->atm_dev && instance->driver->atm_stop)
1304 instance->driver->atm_stop(instance, instance->atm_dev);
1305
1306 if (instance->driver->unbind)
1307 instance->driver->unbind(instance, intf);
1308
1309 instance->driver_data = NULL;
1310
Duncan Sandsc59bba72005-05-11 20:24:03 +02001311 for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) {
1312 kfree(instance->urbs[i]->transfer_buffer);
1313 usb_free_urb(instance->urbs[i]);
1314 }
1315
Duncan Sandse3fb2f62006-01-13 11:06:46 +01001316 kfree(instance->cell_buf);
1317
Duncan Sandsc59bba72005-05-11 20:24:03 +02001318 /* ATM finalize */
1319 if (instance->atm_dev)
Stanislaw Gruszka64bf69d2005-11-29 16:16:41 -08001320 atm_dev_deregister(instance->atm_dev);
Duncan Sandsc59bba72005-05-11 20:24:03 +02001321
1322 usbatm_put_instance(instance); /* taken in usbatm_usb_probe */
1323}
1324EXPORT_SYMBOL_GPL(usbatm_usb_disconnect);
1325
1326
1327/***********
1328** init **
1329***********/
1330
1331static int __init usbatm_usb_init(void)
1332{
1333 dbg("%s: driver version %s", __func__, DRIVER_VERSION);
1334
1335 if (sizeof(struct usbatm_control) > sizeof(((struct sk_buff *) 0)->cb)) {
1336 printk(KERN_ERR "%s unusable with this kernel!\n", usbatm_driver_name);
1337 return -EIO;
1338 }
1339
1340 if ((num_rcv_urbs > UDSL_MAX_RCV_URBS)
1341 || (num_snd_urbs > UDSL_MAX_SND_URBS)
Duncan Sands6f749472006-01-13 10:52:38 +01001342 || (rcv_buf_bytes < 1)
1343 || (rcv_buf_bytes > UDSL_MAX_BUF_SIZE)
1344 || (snd_buf_bytes < 1)
1345 || (snd_buf_bytes > UDSL_MAX_BUF_SIZE))
Duncan Sandsc59bba72005-05-11 20:24:03 +02001346 return -EINVAL;
1347
1348 return 0;
1349}
1350module_init(usbatm_usb_init);
1351
1352static void __exit usbatm_usb_exit(void)
1353{
1354 dbg("%s", __func__);
1355}
1356module_exit(usbatm_usb_exit);
1357
1358MODULE_AUTHOR(DRIVER_AUTHOR);
1359MODULE_DESCRIPTION(DRIVER_DESC);
1360MODULE_LICENSE("GPL");
1361MODULE_VERSION(DRIVER_VERSION);
1362
1363/************
1364** debug **
1365************/
1366
1367#ifdef VERBOSE_DEBUG
1368static int usbatm_print_packet(const unsigned char *data, int len)
1369{
1370 unsigned char buffer[256];
1371 int i = 0, j = 0;
1372
1373 for (i = 0; i < len;) {
1374 buffer[0] = '\0';
1375 sprintf(buffer, "%.3d :", i);
1376 for (j = 0; (j < 16) && (i < len); j++, i++) {
1377 sprintf(buffer, "%s %2.2x", buffer, data[i]);
1378 }
1379 dbg("%s", buffer);
1380 }
1381 return i;
1382}
1383#endif