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