Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(90)

Side by Side Diff: drivers/net/usb/gobi/qmidevice.c

Issue 6822058: CHROMIUM: gobi: resubmit interrupt urb on failed reads (Closed) Base URL: ssh://gitrw.chromium.org:9222/kernel.git@11.1.241.B
Patch Set: Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « drivers/net/usb/gobi/qmidevice.h ('k') | drivers/net/usb/gobi/structs.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /* qmidevice.c - gobi QMI device
2 * Copyright (c) 2010, Code Aurora Forum. All rights reserved.
3
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 * 02110-1301, USA.
17 */
18
19 #include "qmidevice.h"
20 #include "qcusbnet.h"
21
22 struct readreq {
23 struct list_head node;
24 void *data;
25 u16 tid;
26 u16 size;
27 };
28
29 struct notifyreq {
30 struct list_head node;
31 void (*func)(struct qcusbnet *, u16, void *);
32 u16 tid;
33 void *data;
34 };
35
36 struct client {
37 struct list_head node;
38 u16 cid;
39 struct list_head reads;
40 struct list_head notifies;
41 struct list_head urbs;
42 };
43
44 struct urbsetup {
45 u8 type;
46 u8 code;
47 u16 value;
48 u16 index;
49 u16 len;
50 };
51
52 struct qmihandle {
53 u16 cid;
54 struct qcusbnet *dev;
55 };
56
57 extern int qcusbnet_debug;
58 static int qcusbnet2k_fwdelay;
59
60 static bool device_valid(struct qcusbnet *dev);
61 static struct client *client_bycid(struct qcusbnet *dev, u16 cid);
62 static bool client_addread(struct qcusbnet *dev, u16 cid, u16 tid, void *data, u 16 size);
63 static bool client_delread(struct qcusbnet *dev, u16 cid, u16 tid, void **data, u16 *size);
64 static bool client_addnotify(struct qcusbnet *dev, u16 cid, u16 tid,
65 void (*hook)(struct qcusbnet *, u16 cid, void *),
66 void *data);
67 static bool client_notify(struct qcusbnet *dev, u16 cid, u16 tid);
68 static bool client_addurb(struct qcusbnet *dev, u16 cid, struct urb *urb);
69 static struct urb *client_delurb(struct qcusbnet *dev, u16 cid);
70
71 static int resubmit_int_urb(struct urb *urb);
72
73 static int devqmi_open(struct inode *inode, struct file *file);
74 static int devqmi_ioctl(struct inode *inode, struct file *file, unsigned int cmd , unsigned long arg);
75 static int devqmi_release(struct inode *inode, struct file *file);
76 static ssize_t devqmi_read(struct file *file, char __user *buf, size_t size,
77 loff_t *pos);
78 static ssize_t devqmi_write(struct file *file, const char __user *buf,
79 size_t size, loff_t *pos);
80
81 static bool qmi_ready(struct qcusbnet *dev, u16 timeout);
82 static void wds_callback(struct qcusbnet *dev, u16 cid, void *data);
83 static int setup_wds_callback(struct qcusbnet *dev);
84 static int qmidms_getmeid(struct qcusbnet *dev);
85
86 #define IOCTL_QMI_GET_SERVICE_FILE (0x8BE0 + 1)
87 #define IOCTL_QMI_GET_DEVICE_VIDPID (0x8BE0 + 2)
88 #define IOCTL_QMI_GET_DEVICE_MEID (0x8BE0 + 3)
89 #define IOCTL_QMI_CLOSE (0x8BE0 + 4)
90 #define CDC_GET_ENCAPSULATED_RESPONSE 0x01A1ll
91 #define CDC_CONNECTION_SPEED_CHANGE 0x08000000002AA1ll
92
93 static const struct file_operations devqmi_fops = {
94 .owner = THIS_MODULE,
95 .read = devqmi_read,
96 .write = devqmi_write,
97 .ioctl = devqmi_ioctl,
98 .open = devqmi_open,
99 .release = devqmi_release,
100 };
101
102 #ifdef CONFIG_SMP
103 static inline void assert_locked(struct qcusbnet *dev)
104 {
105 BUG_ON(!spin_is_locked(&dev->qmi.clients_lock));
106 }
107 #else
108 static inline void assert_locked(struct qcusbnet *dev)
109 {
110
111 }
112 #endif
113
114 static bool device_valid(struct qcusbnet *dev)
115 {
116 return dev && dev->valid;
117 }
118
119 void qc_setdown(struct qcusbnet *dev, u8 reason)
120 {
121 set_bit(reason, &dev->down);
122 netif_carrier_off(dev->usbnet->net);
123 }
124
125 void qc_cleardown(struct qcusbnet *dev, u8 reason)
126 {
127 clear_bit(reason, &dev->down);
128 if (!dev->down)
129 netif_carrier_on(dev->usbnet->net);
130 }
131
132 bool qc_isdown(struct qcusbnet *dev, u8 reason)
133 {
134 return test_bit(reason, &dev->down);
135 }
136
137 static int resubmit_int_urb(struct urb *urb)
138 {
139 int status;
140 int interval;
141 if (!urb || !urb->dev)
142 return -EINVAL;
143 interval = urb->dev->speed == USB_SPEED_HIGH ? 7 : 3;
144 usb_fill_int_urb(urb, urb->dev, urb->pipe, urb->transfer_buffer,
145 urb->transfer_buffer_length, urb->complete,
146 urb->context, interval);
147 status = usb_submit_urb(urb, GFP_ATOMIC);
148 if (status)
149 DBG("status %d", status);
150 return status;
151 }
152
153 static void read_callback(struct urb *urb)
154 {
155 struct list_head *node;
156 int result;
157 u16 cid;
158 struct client *client;
159 void *data;
160 void *copy;
161 u16 size;
162 struct qcusbnet *dev;
163 unsigned long flags;
164 u16 tid;
165
166 if (!urb) {
167 DBG("bad read URB\n");
168 return;
169 }
170
171 dev = urb->context;
172 if (!device_valid(dev)) {
173 DBG("Invalid device!\n");
174 return;
175 }
176
177 if (urb->status) {
178 DBG("Read status = %d\n", urb->status);
179 resubmit_int_urb(dev->qmi.inturb);
180 return;
181 }
182
183 DBG("Read %d bytes\n", urb->actual_length);
184
185 data = urb->transfer_buffer;
186 size = urb->actual_length;
187
188 if (qcusbnet_debug)
189 print_hex_dump(KERN_INFO, "gobi-read: ", DUMP_PREFIX_OFFSET,
190 16, 1, data, size, true);
191
192 result = qmux_parse(&cid, data, size);
193 if (result < 0) {
194 DBG("Read error parsing QMUX %d\n", result);
195 resubmit_int_urb(dev->qmi.inturb);
196 return;
197 }
198
199 if (size < result + 3) {
200 DBG("Data buffer too small to parse\n");
201 resubmit_int_urb(dev->qmi.inturb);
202 return;
203 }
204
205 if (cid == QMICTL)
206 tid = *(u8 *)(data + result + 1);
207 else
208 tid = *(u16 *)(data + result + 1);
209 spin_lock_irqsave(&dev->qmi.clients_lock, flags);
210
211 list_for_each(node, &dev->qmi.clients) {
212 client = list_entry(node, struct client, node);
213 if (client->cid == cid || (client->cid | 0xff00) == cid) {
214 copy = kmalloc(size, GFP_ATOMIC);
215 memcpy(copy, data, size);
216 if (!client_addread(dev, client->cid, tid, copy, size)) {
217 DBG("Error allocating pReadMemListEntry "
218 "read will be discarded\n");
219 kfree(copy);
220 spin_unlock_irqrestore(&dev->qmi.clients_lock, f lags);
221 resubmit_int_urb(dev->qmi.inturb);
222 return;
223 }
224
225 DBG("Creating new readListEntry for client 0x%04X, TID % x\n",
226 cid, tid);
227
228 client_notify(dev, client->cid, tid);
229
230 if (cid >> 8 != 0xff)
231 break;
232 }
233 }
234
235 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
236 resubmit_int_urb(dev->qmi.inturb);
237 }
238
239 static void int_callback(struct urb *urb)
240 {
241 int status;
242 int interval;
243 struct qcusbnet *dev = (struct qcusbnet *)urb->context;
244
245 if (!device_valid(dev)) {
246 DBG("Invalid device!\n");
247 return;
248 }
249
250 if (urb->status) {
251 DBG("Int status = %d\n", urb->status);
252 if (urb->status != -EOVERFLOW)
253 return;
254 } else {
255 if ((urb->actual_length == 8) &&
256 (*(u64 *)urb->transfer_buffer == CDC_GET_ENCAPSULATED_RESPON SE)) {
257 usb_fill_control_urb(dev->qmi.readurb, dev->usbnet->udev ,
258 usb_rcvctrlpipe(dev->usbnet->udev, 0),
259 (unsigned char *)dev->qmi.readsetup ,
260 dev->qmi.readbuf,
261 DEFAULT_READ_URB_LENGTH,
262 read_callback, dev);
263 status = usb_submit_urb(dev->qmi.readurb, GFP_ATOMIC);
264 if (status) {
265 DBG("Error submitting Read URB %d\n", status);
266 return;
267 }
268 } else if ((urb->actual_length == 16) &&
269 (*(u64 *)urb->transfer_buffer == CDC_CONNECTION_SPEED _CHANGE)) {
270 /* if upstream or downstream is 0, stop traffic.
271 * Otherwise resume it */
272 if ((*(u32 *)(urb->transfer_buffer + 8) == 0) ||
273 (*(u32 *)(urb->transfer_buffer + 12) == 0)) {
274 qc_setdown(dev, DOWN_CDC_CONNECTION_SPEED);
275 DBG("traffic stopping due to CONNECTION_SPEED_CH ANGE\n");
276 } else {
277 qc_cleardown(dev, DOWN_CDC_CONNECTION_SPEED);
278 DBG("resuming traffic due to CONNECTION_SPEED_CH ANGE\n");
279 }
280 } else {
281 DBG("ignoring invalid interrupt in packet\n");
282 if (qcusbnet_debug)
283 print_hex_dump(KERN_INFO, "gobi-int: ",
284 DUMP_PREFIX_OFFSET, 16, 1,
285 urb->transfer_buffer,
286 urb->actual_length, true);
287 }
288 }
289
290 resubmit_int_urb(dev->qmi.inturb);
291 return;
292 }
293
294 int qc_startread(struct qcusbnet *dev)
295 {
296 int interval;
297
298 if (!device_valid(dev)) {
299 DBG("Invalid device!\n");
300 return -ENXIO;
301 }
302
303 dev->qmi.readurb = usb_alloc_urb(0, GFP_KERNEL);
304 if (!dev->qmi.readurb) {
305 DBG("Error allocating read urb\n");
306 return -ENOMEM;
307 }
308
309 dev->qmi.inturb = usb_alloc_urb(0, GFP_KERNEL);
310 if (!dev->qmi.inturb) {
311 usb_free_urb(dev->qmi.readurb);
312 DBG("Error allocating int urb\n");
313 return -ENOMEM;
314 }
315
316 dev->qmi.readbuf = kmalloc(DEFAULT_READ_URB_LENGTH, GFP_KERNEL);
317 if (!dev->qmi.readbuf) {
318 usb_free_urb(dev->qmi.readurb);
319 usb_free_urb(dev->qmi.inturb);
320 DBG("Error allocating read buffer\n");
321 return -ENOMEM;
322 }
323
324 dev->qmi.intbuf = kmalloc(DEFAULT_READ_URB_LENGTH, GFP_KERNEL);
325 if (!dev->qmi.intbuf) {
326 usb_free_urb(dev->qmi.readurb);
327 usb_free_urb(dev->qmi.inturb);
328 kfree(dev->qmi.readbuf);
329 DBG("Error allocating int buffer\n");
330 return -ENOMEM;
331 }
332
333 dev->qmi.readsetup = kmalloc(sizeof(*dev->qmi.readsetup), GFP_KERNEL);
334 if (!dev->qmi.readsetup) {
335 usb_free_urb(dev->qmi.readurb);
336 usb_free_urb(dev->qmi.inturb);
337 kfree(dev->qmi.readbuf);
338 kfree(dev->qmi.intbuf);
339 DBG("Error allocating setup packet buffer\n");
340 return -ENOMEM;
341 }
342
343 dev->qmi.readsetup->type = 0xA1;
344 dev->qmi.readsetup->code = 1;
345 dev->qmi.readsetup->value = 0;
346 dev->qmi.readsetup->index = 0;
347 dev->qmi.readsetup->len = DEFAULT_READ_URB_LENGTH;
348
349 interval = (dev->usbnet->udev->speed == USB_SPEED_HIGH) ? 7 : 3;
350
351 usb_fill_int_urb(dev->qmi.inturb, dev->usbnet->udev,
352 usb_rcvintpipe(dev->usbnet->udev, 0x81),
353 dev->qmi.intbuf, DEFAULT_READ_URB_LENGTH,
354 int_callback, dev, interval);
355 return usb_submit_urb(dev->qmi.inturb, GFP_KERNEL);
356 }
357
358 void qc_stopread(struct qcusbnet *dev)
359 {
360 if (dev->qmi.readurb) {
361 DBG("Killing read URB\n");
362 usb_kill_urb(dev->qmi.readurb);
363 }
364
365 if (dev->qmi.inturb) {
366 DBG("Killing int URB\n");
367 usb_kill_urb(dev->qmi.inturb);
368 }
369
370 kfree(dev->qmi.readsetup);
371 dev->qmi.readsetup = NULL;
372 kfree(dev->qmi.readbuf);
373 dev->qmi.readbuf = NULL;
374 kfree(dev->qmi.intbuf);
375 dev->qmi.intbuf = NULL;
376
377 usb_free_urb(dev->qmi.readurb);
378 dev->qmi.readurb = NULL;
379 usb_free_urb(dev->qmi.inturb);
380 dev->qmi.inturb = NULL;
381 }
382
383 static int read_async(struct qcusbnet *dev, u16 cid, u16 tid,
384 void (*hook)(struct qcusbnet *, u16, void *),
385 void *data)
386 {
387 struct list_head *node;
388 struct client *client;
389 struct readreq *readreq;
390
391 unsigned long flags;
392
393 if (!device_valid(dev)) {
394 DBG("Invalid device!\n");
395 return -ENXIO;
396 }
397
398 spin_lock_irqsave(&dev->qmi.clients_lock, flags);
399
400 client = client_bycid(dev, cid);
401 if (!client) {
402 DBG("Could not find matching client ID 0x%04X\n", cid);
403 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
404 return -ENXIO;
405 }
406
407 list_for_each(node, &client->reads) {
408 readreq = list_entry(node, struct readreq, node);
409 if (!tid || tid == readreq->tid) {
410 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
411 hook(dev, cid, data);
412 return 0;
413 }
414 }
415
416 if (!client_addnotify(dev, cid, tid, hook, data))
417 DBG("Unable to register for notification\n");
418
419 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
420 return 0;
421 }
422
423 static void upsem(struct qcusbnet *dev, u16 cid, void *data)
424 {
425 DBG("0x%04X\n", cid);
426 up((struct semaphore *)data);
427 }
428
429 static int read_sync(struct qcusbnet *dev, void **buf, u16 cid, u16 tid)
430 {
431 struct list_head *node;
432 int result;
433 struct client *client;
434 struct notifyreq *notify;
435 struct semaphore sem;
436 void *data;
437 unsigned long flags;
438 u16 size;
439
440 if (!device_valid(dev)) {
441 DBG("Invalid device!\n");
442 return -ENXIO;
443 }
444
445 spin_lock_irqsave(&dev->qmi.clients_lock, flags);
446
447 client = client_bycid(dev, cid);
448 if (!client) {
449 DBG("Could not find matching client ID 0x%04X\n", cid);
450 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
451 return -ENXIO;
452 }
453
454 while (!client_delread(dev, cid, tid, &data, &size)) {
455 sema_init(&sem, 0);
456 if (!client_addnotify(dev, cid, tid, upsem, &sem)) {
457 DBG("unable to register for notification\n");
458 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
459 return -EFAULT;
460 }
461
462 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
463
464 result = down_interruptible(&sem);
465 if (result) {
466 DBG("Interrupted %d\n", result);
467 spin_lock_irqsave(&dev->qmi.clients_lock, flags);
468 list_for_each(node, &client->notifies) {
469 notify = list_entry(node, struct notifyreq, node );
470 if (notify->data == &sem) {
471 list_del(&notify->node);
472 kfree(notify);
473 break;
474 }
475 }
476
477 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
478 return -EINTR;
479 }
480
481 if (!device_valid(dev)) {
482 DBG("Invalid device!\n");
483 return -ENXIO;
484 }
485
486 spin_lock_irqsave(&dev->qmi.clients_lock, flags);
487 }
488
489 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
490 *buf = data;
491 return size;
492 }
493
494 static void write_callback(struct urb *urb)
495 {
496 if (!urb) {
497 DBG("null urb\n");
498 return;
499 }
500
501 DBG("Write status/size %d/%d\n", urb->status, urb->actual_length);
502 up((struct semaphore *)urb->context);
503 }
504
505 static int write_sync(struct qcusbnet *dev, char *buf, int size, u16 cid)
506 {
507 int result;
508 struct semaphore sem;
509 struct urb *urb;
510 struct urbsetup setup;
511 unsigned long flags;
512
513 if (!device_valid(dev)) {
514 DBG("Invalid device!\n");
515 return -ENXIO;
516 }
517
518 urb = usb_alloc_urb(0, GFP_KERNEL);
519 if (!urb) {
520 DBG("URB mem error\n");
521 return -ENOMEM;
522 }
523
524 result = qmux_fill(cid, buf, size);
525 if (result < 0) {
526 usb_free_urb(urb);
527 return result;
528 }
529
530 /* CDC Send Encapsulated Request packet */
531 setup.type = 0x21;
532 setup.code = 0;
533 setup.value = 0;
534 setup.index = 0;
535 setup.len = 0;
536 setup.len = size;
537
538 usb_fill_control_urb(urb, dev->usbnet->udev,
539 usb_sndctrlpipe(dev->usbnet->udev, 0),
540 (unsigned char *)&setup, (void *)buf, size,
541 NULL, dev);
542
543 DBG("Actual Write:\n");
544 if (qcusbnet_debug)
545 print_hex_dump(KERN_INFO, "gobi-write: ", DUMP_PREFIX_OFFSET,
546 16, 1, buf, size, true);
547
548 sema_init(&sem, 0);
549
550 urb->complete = write_callback;
551 urb->context = &sem;
552
553 result = usb_autopm_get_interface(dev->iface);
554 if (result < 0) {
555 DBG("unable to resume interface: %d\n", result);
556 if (result == -EPERM) {
557 qc_suspend(dev->iface, PMSG_SUSPEND);
558 }
559 return result;
560 }
561
562 spin_lock_irqsave(&dev->qmi.clients_lock, flags);
563
564 if (!client_addurb(dev, cid, urb)) {
565 usb_free_urb(urb);
566 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
567 usb_autopm_put_interface(dev->iface);
568 return -EINVAL;
569 }
570
571 result = usb_submit_urb(urb, GFP_KERNEL);
572 if (result < 0) {
573 DBG("submit URB error %d\n", result);
574 if (client_delurb(dev, cid) != urb) {
575 DBG("Didn't get write URB back\n");
576 }
577
578 usb_free_urb(urb);
579
580 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
581 usb_autopm_put_interface(dev->iface);
582 return result;
583 }
584
585 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
586 result = down_interruptible(&sem);
587 if (!device_valid(dev)) {
588 DBG("Invalid device!\n");
589 return -ENXIO;
590 }
591
592 usb_autopm_put_interface(dev->iface);
593 spin_lock_irqsave(&dev->qmi.clients_lock, flags);
594 if (client_delurb(dev, cid) != urb) {
595 DBG("Didn't get write URB back\n");
596 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
597 return -EINVAL;
598 }
599 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
600
601 if (!result) {
602 if (!urb->status) {
603 result = size;
604 } else {
605 DBG("bad status = %d\n", urb->status);
606 result = urb->status;
607 }
608 } else {
609 DBG("Interrupted %d !!!\n", result);
610 DBG("Device may be in bad state and need reset !!!\n");
611 usb_kill_urb(urb);
612 }
613
614 usb_free_urb(urb);
615 return result;
616 }
617
618 static int client_alloc(struct qcusbnet *dev, u8 type)
619 {
620 u16 cid;
621 struct client *client;
622 int result;
623 void *wbuf;
624 size_t wbufsize;
625 void *rbuf;
626 u16 rbufsize;
627 unsigned long flags;
628 u8 tid;
629
630 if (!device_valid(dev)) {
631 DBG("Invalid device!\n");
632 return -ENXIO;
633 }
634
635 if (type) {
636 tid = atomic_add_return(1, &dev->qmi.qmitid);
637 if (!tid)
638 atomic_add_return(1, &dev->qmi.qmitid);
639 wbuf = qmictl_new_getcid(tid, type, &wbufsize);
640 if (!wbuf)
641 return -ENOMEM;
642 result = write_sync(dev, wbuf, wbufsize, QMICTL);
643 kfree(wbuf);
644
645 if (result < 0)
646 return result;
647
648 result = read_sync(dev, &rbuf, QMICTL, tid);
649 if (result < 0) {
650 DBG("bad read data %d\n", result);
651 return result;
652 }
653 rbufsize = result;
654
655 result = qmictl_alloccid_resp(rbuf, rbufsize, &cid);
656 kfree(rbuf);
657
658 if (result < 0)
659 return result;
660 } else {
661 cid = 0;
662 }
663
664 spin_lock_irqsave(&dev->qmi.clients_lock, flags);
665 if (client_bycid(dev, cid)) {
666 DBG("Client memory already exists\n");
667 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
668 return -ETOOMANYREFS;
669 }
670
671 client = kmalloc(sizeof(*client), GFP_ATOMIC);
672 if (!client) {
673 DBG("Error allocating read list\n");
674 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
675 return -ENOMEM;
676 }
677
678 list_add_tail(&client->node, &dev->qmi.clients);
679 client->cid = cid;
680 INIT_LIST_HEAD(&client->reads);
681 INIT_LIST_HEAD(&client->notifies);
682 INIT_LIST_HEAD(&client->urbs);
683 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
684 return cid;
685 }
686
687 static void client_free(struct qcusbnet *dev, u16 cid)
688 {
689 struct list_head *node, *tmp;
690 int result;
691 struct client *client;
692 struct urb *urb;
693 void *data;
694 u16 size;
695 void *wbuf;
696 size_t wbufsize;
697 void *rbuf;
698 u16 rbufsize;
699 unsigned long flags;
700 u8 tid;
701
702 DBG("releasing 0x%04X\n", cid);
703
704 if (cid != QMICTL) {
705 tid = atomic_add_return(1, &dev->qmi.qmitid);
706 if (!tid)
707 tid = atomic_add_return(1, &dev->qmi.qmitid);
708 wbuf = qmictl_new_releasecid(tid, cid, &wbufsize);
709 if (!wbuf) {
710 DBG("memory error\n");
711 } else {
712 result = write_sync(dev, wbuf, wbufsize, QMICTL);
713 kfree(wbuf);
714
715 if (result < 0) {
716 DBG("bad write status %d\n", result);
717 } else {
718 result = read_sync(dev, &rbuf, QMICTL, tid);
719 if (result < 0) {
720 DBG("bad read status %d\n", result);
721 } else {
722 rbufsize = result;
723 result = qmictl_freecid_resp(rbuf, rbufs ize);
724 kfree(rbuf);
725 if (result < 0)
726 DBG("error %d parsing response\n ", result);
727 }
728 }
729 }
730 }
731
732 spin_lock_irqsave(&dev->qmi.clients_lock, flags);
733 list_for_each_safe(node, tmp, &dev->qmi.clients) {
734 client = list_entry(node, struct client, node);
735 if (client->cid == cid) {
736 while (client_notify(dev, cid, 0)) {
737 ;
738 }
739
740 urb = client_delurb(dev, cid);
741 while (urb != NULL) {
742 usb_kill_urb(urb);
743 usb_free_urb(urb);
744 urb = client_delurb(dev, cid);
745 }
746
747 while (client_delread(dev, cid, 0, &data, &size))
748 kfree(data);
749
750 list_del(&client->node);
751 kfree(client);
752 }
753 }
754 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
755 }
756
757 struct client *client_bycid(struct qcusbnet *dev, u16 cid)
758 {
759 struct list_head *node;
760 struct client *client;
761
762 if (!device_valid(dev)) {
763 DBG("Invalid device\n");
764 return NULL;
765 }
766
767 assert_locked(dev);
768
769 list_for_each(node, &dev->qmi.clients) {
770 client = list_entry(node, struct client, node);
771 if (client->cid == cid)
772 return client;
773 }
774
775 DBG("Could not find client mem 0x%04X\n", cid);
776 return NULL;
777 }
778
779 static bool client_addread(struct qcusbnet *dev, u16 cid, u16 tid, void *data,
780 u16 size)
781 {
782 struct client *client;
783 struct readreq *req;
784
785 assert_locked(dev);
786
787 client = client_bycid(dev, cid);
788 if (!client) {
789 DBG("Could not find this client's memory 0x%04X\n", cid);
790 return false;
791 }
792
793 req = kmalloc(sizeof(*req), GFP_ATOMIC);
794 if (!req) {
795 DBG("Mem error\n");
796 return false;
797 }
798
799 req->data = data;
800 req->size = size;
801 req->tid = tid;
802
803 list_add_tail(&req->node, &client->reads);
804
805 return true;
806 }
807
808 static bool client_delread(struct qcusbnet *dev, u16 cid, u16 tid, void **data,
809 u16 *size)
810 {
811 struct client *client;
812 struct readreq *req;
813 struct list_head *node;
814
815 assert_locked(dev);
816
817 client = client_bycid(dev, cid);
818 if (!client) {
819 DBG("Could not find this client's memory 0x%04X\n", cid);
820 return false;
821 }
822
823 list_for_each(node, &client->reads) {
824 req = list_entry(node, struct readreq, node);
825 if (!tid || tid == req->tid) {
826 *data = req->data;
827 *size = req->size;
828 list_del(&req->node);
829 kfree(req);
830 return true;
831 }
832
833 DBG("skipping 0x%04X data TID = %x\n", cid, req->tid);
834 }
835
836 DBG("No read memory to pop, Client 0x%04X, TID = %x\n", cid, tid);
837 return false;
838 }
839
840 static bool client_addnotify(struct qcusbnet *dev, u16 cid, u16 tid,
841 void (*hook)(struct qcusbnet *, u16, void *),
842 void *data)
843 {
844 struct client *client;
845 struct notifyreq *req;
846
847 assert_locked(dev);
848
849 client = client_bycid(dev, cid);
850 if (!client) {
851 DBG("Could not find this client's memory 0x%04X\n", cid);
852 return false;
853 }
854
855 req = kmalloc(sizeof(*req), GFP_ATOMIC);
856 if (!req) {
857 DBG("Mem error\n");
858 return false;
859 }
860
861 list_add_tail(&req->node, &client->notifies);
862 req->func = hook;
863 req->data = data;
864 req->tid = tid;
865
866 return true;
867 }
868
869 static bool client_notify(struct qcusbnet *dev, u16 cid, u16 tid)
870 {
871 struct client *client;
872 struct notifyreq *delnotify, *notify;
873 struct list_head *node;
874
875 assert_locked(dev);
876
877 client = client_bycid(dev, cid);
878 if (!client) {
879 DBG("Could not find this client's memory 0x%04X\n", cid);
880 return false;
881 }
882
883 delnotify = NULL;
884
885 list_for_each(node, &client->notifies) {
886 notify = list_entry(node, struct notifyreq, node);
887 if (!tid || !notify->tid || tid == notify->tid) {
888 delnotify = notify;
889 break;
890 }
891
892 DBG("skipping data TID = %x\n", notify->tid);
893 }
894
895 if (delnotify) {
896 list_del(&delnotify->node);
897 if (delnotify->func) {
898 spin_unlock(&dev->qmi.clients_lock);
899 delnotify->func(dev, cid, delnotify->data);
900 spin_lock(&dev->qmi.clients_lock);
901 }
902 kfree(delnotify);
903 return true;
904 }
905
906 DBG("no one to notify for TID %x\n", tid);
907 return false;
908 }
909
910 static bool client_addurb(struct qcusbnet *dev, u16 cid, struct urb *urb)
911 {
912 struct client *client;
913 struct urbreq *req;
914
915 assert_locked(dev);
916
917 client = client_bycid(dev, cid);
918 if (!client) {
919 DBG("Could not find this client's memory 0x%04X\n", cid);
920 return false;
921 }
922
923 req = kmalloc(sizeof(*req), GFP_ATOMIC);
924 if (!req) {
925 DBG("Mem error\n");
926 return false;
927 }
928
929 req->urb = urb;
930 list_add_tail(&req->node, &client->urbs);
931
932 return true;
933 }
934
935 static struct urb *client_delurb(struct qcusbnet *dev, u16 cid)
936 {
937 struct client *client;
938 struct urbreq *req;
939 struct urb *urb;
940
941 assert_locked(dev);
942
943 client = client_bycid(dev, cid);
944 if (!client) {
945 DBG("Could not find this client's memory 0x%04X\n", cid);
946 return NULL;
947 }
948
949 if (list_empty(&client->urbs)) {
950 DBG("No URB's to pop\n");
951 return NULL;
952 }
953
954 req = list_first_entry(&client->urbs, struct urbreq, node);
955 list_del(&req->node);
956 urb = req->urb;
957 kfree(req);
958 return urb;
959 }
960
961 static int devqmi_open(struct inode *inode, struct file *file)
962 {
963 struct qmihandle *handle;
964 struct qmidev *qmidev = container_of(inode->i_cdev, struct qmidev, cdev) ;
965 struct qcusbnet *dev = container_of(qmidev, struct qcusbnet, qmi);
966
967 /* We need an extra ref on the device per fd, since we stash a ref
968 * inside the handle. If qcusbnet_get() returns NULL, that means the
969 * device has been removed from the list - no new refs for us. */
970 struct qcusbnet *ref = qcusbnet_get(dev);
971
972 if (!ref)
973 return -ENXIO;
974
975 file->private_data = kmalloc(sizeof(struct qmihandle), GFP_KERNEL);
976 if (!file->private_data) {
977 DBG("Mem error\n");
978 return -ENOMEM;
979 }
980
981 handle = (struct qmihandle *)file->private_data;
982 handle->cid = (u16)-1;
983 handle->dev = ref;
984
985 DBG("%p %04x", handle, handle->cid);
986
987 return 0;
988 }
989
990 static int devqmi_ioctl(struct inode *inode, struct file *file, unsigned int cmd , unsigned long arg)
991 {
992 int result;
993 u32 vidpid;
994
995 struct qmihandle *handle = (struct qmihandle *)file->private_data;
996
997 DBG("%p %04x %08x", handle, handle->cid, cmd);
998
999 if (!handle) {
1000 DBG("Bad file data\n");
1001 return -EBADF;
1002 }
1003
1004 if (handle->dev->dying) {
1005 DBG("Dying device");
1006 return -ENXIO;
1007 }
1008
1009 if (!device_valid(handle->dev)) {
1010 DBG("Invalid device!\n");
1011 return -ENXIO;
1012 }
1013
1014 switch (cmd) {
1015 case IOCTL_QMI_GET_SERVICE_FILE:
1016
1017 DBG("Setting up QMI for service %lu\n", arg);
1018 if (!(u8)arg) {
1019 DBG("Cannot use QMICTL from userspace\n");
1020 return -EINVAL;
1021 }
1022
1023 if (handle->cid != (u16)-1) {
1024 DBG("Close the current connection before opening a new o ne\n");
1025 return -EBADR;
1026 }
1027
1028 result = client_alloc(handle->dev, (u8)arg);
1029 if (result < 0)
1030 return result;
1031 handle->cid = result;
1032
1033 return 0;
1034 break;
1035
1036 /* Okay, all aboard the nasty hack express. If we don't have this
1037 * ioctl() (and we just rely on userspace to close() the file
1038 * descriptors), if userspace has any refs left to this fd (like, say, a
1039 * pending read()), then the read might hang around forever. Userspace
1040 * needs a way to cause us to kick people off those waitqueues before
1041 * closing the fd for good.
1042 *
1043 * If this driver used workqueues, the correct approach here would
1044 * instead be to make the file descriptor select()able, and then just
1045 * use select() instead of aio in userspace (thus allowing us to get
1046 * away with one thread total and avoiding the recounting mess
1047 * altogether).
1048 */
1049 case IOCTL_QMI_CLOSE:
1050 DBG("Tearing down QMI for service %lu", arg);
1051 if (handle->cid == (u16)-1) {
1052 DBG("no qmi cid");
1053 return -EBADR;
1054 }
1055
1056 file->private_data = NULL;
1057 client_free(handle->dev, handle->cid);
1058 kfree(handle);
1059 return 0;
1060 break;
1061
1062 case IOCTL_QMI_GET_DEVICE_VIDPID:
1063 if (!arg) {
1064 DBG("Bad VIDPID buffer\n");
1065 return -EINVAL;
1066 }
1067
1068 if (!handle->dev->usbnet) {
1069 DBG("Bad usbnet\n");
1070 return -ENOMEM;
1071 }
1072
1073 if (!handle->dev->usbnet->udev) {
1074 DBG("Bad udev\n");
1075 return -ENOMEM;
1076 }
1077
1078 vidpid = ((le16_to_cpu(handle->dev->usbnet->udev->descriptor.idV endor) << 16)
1079 + le16_to_cpu(handle->dev->usbnet->udev->descriptor.id Product));
1080
1081 result = copy_to_user((unsigned int *)arg, &vidpid, 4);
1082 if (result)
1083 DBG("Copy to userspace failure\n");
1084
1085 return result;
1086 break;
1087
1088 case IOCTL_QMI_GET_DEVICE_MEID:
1089 if (!arg) {
1090 DBG("Bad MEID buffer\n");
1091 return -EINVAL;
1092 }
1093
1094 result = copy_to_user((unsigned int *)arg, &handle->dev->meid[0] , 14);
1095 if (result)
1096 DBG("copy to userspace failure\n");
1097
1098 return result;
1099 break;
1100 default:
1101 return -EBADRQC;
1102 }
1103 }
1104
1105 static int devqmi_release(struct inode *inode, struct file *file)
1106 {
1107 struct qmihandle *handle = (struct qmihandle *)file->private_data;
1108 if (!handle)
1109 return 0;
1110 file->private_data = NULL;
1111 if (handle->cid != (u16)-1)
1112 client_free(handle->dev, handle->cid);
1113 qcusbnet_put(handle->dev);
1114 kfree(handle);
1115 return 0;
1116 }
1117
1118 static ssize_t devqmi_read(struct file *file, char __user *buf, size_t size,
1119 loff_t *pos)
1120 {
1121 int result;
1122 void *data = NULL;
1123 void *smalldata;
1124 struct qmihandle *handle = (struct qmihandle *)file->private_data;
1125
1126 if (!handle) {
1127 DBG("Bad file data\n");
1128 return -EBADF;
1129 }
1130
1131 if (handle->dev->dying) {
1132 DBG("Dying device");
1133 return -ENXIO;
1134 }
1135
1136 if (!device_valid(handle->dev)) {
1137 DBG("Invalid device!\n");
1138 return -ENXIO;
1139 }
1140
1141 if (handle->cid == (u16)-1) {
1142 DBG("Client ID must be set before reading 0x%04X\n",
1143 handle->cid);
1144 return -EBADR;
1145 }
1146
1147 result = read_sync(handle->dev, &data, handle->cid, 0);
1148 if (result <= 0)
1149 return result;
1150
1151 result -= qmux_size;
1152 smalldata = data + qmux_size;
1153
1154 if (result > size) {
1155 DBG("Read data is too large for amount user has requested\n");
1156 kfree(data);
1157 return -EOVERFLOW;
1158 }
1159
1160 if (copy_to_user(buf, smalldata, result)) {
1161 DBG("Error copying read data to user\n");
1162 result = -EFAULT;
1163 }
1164
1165 kfree(data);
1166 return result;
1167 }
1168
1169 static ssize_t devqmi_write(struct file *file, const char __user * buf,
1170 size_t size, loff_t *pos)
1171 {
1172 int status;
1173 void *wbuf;
1174 struct qmihandle *handle = (struct qmihandle *)file->private_data;
1175
1176 if (!handle) {
1177 DBG("Bad file data\n");
1178 return -EBADF;
1179 }
1180
1181 if (!device_valid(handle->dev)) {
1182 DBG("Invalid device! Updating f_ops\n");
1183 file->f_op = file->f_dentry->d_inode->i_fop;
1184 return -ENXIO;
1185 }
1186
1187 if (handle->cid == (u16)-1) {
1188 DBG("Client ID must be set before writing 0x%04X\n",
1189 handle->cid);
1190 return -EBADR;
1191 }
1192
1193 wbuf = kmalloc(size + qmux_size, GFP_KERNEL);
1194 if (!wbuf)
1195 return -ENOMEM;
1196 status = copy_from_user(wbuf + qmux_size, buf, size);
1197 if (status) {
1198 DBG("Unable to copy data from userspace %d\n", status);
1199 kfree(wbuf);
1200 return status;
1201 }
1202
1203 status = write_sync(handle->dev, wbuf, size + qmux_size,
1204 handle->cid);
1205
1206 kfree(wbuf);
1207 if (status == size + qmux_size)
1208 return size;
1209 return status;
1210 }
1211
1212 int qc_register(struct qcusbnet *dev)
1213 {
1214 int result;
1215 int qmiidx = 0;
1216 dev_t devno;
1217 char *name;
1218
1219 dev->valid = true;
1220 dev->dying = false;
1221 result = client_alloc(dev, QMICTL);
1222 if (result) {
1223 dev->valid = false;
1224 return result;
1225 }
1226 atomic_set(&dev->qmi.qmitid, 1);
1227
1228 result = qc_startread(dev);
1229 if (result) {
1230 dev->valid = false;
1231 return result;
1232 }
1233
1234 if (!qmi_ready(dev, 30000)) {
1235 DBG("Device unresponsive to QMI\n");
1236 return -ETIMEDOUT;
1237 }
1238
1239 result = setup_wds_callback(dev);
1240 if (result) {
1241 dev->valid = false;
1242 return result;
1243 }
1244
1245 result = qmidms_getmeid(dev);
1246 if (result) {
1247 dev->valid = false;
1248 return result;
1249 }
1250
1251 result = alloc_chrdev_region(&devno, 0, 1, "qcqmi");
1252 if (result < 0)
1253 return result;
1254
1255 cdev_init(&dev->qmi.cdev, &devqmi_fops);
1256 dev->qmi.cdev.owner = THIS_MODULE;
1257 dev->qmi.cdev.ops = &devqmi_fops;
1258
1259 result = cdev_add(&dev->qmi.cdev, devno, 1);
1260 if (result) {
1261 DBG("error adding cdev\n");
1262 return result;
1263 }
1264
1265 name = strstr(dev->usbnet->net->name, "usb");
1266 if (!name) {
1267 DBG("Bad net name: %s\n", dev->usbnet->net->name);
1268 return -ENXIO;
1269 }
1270 name += strlen("usb");
1271 qmiidx = simple_strtoul(name, NULL, 10);
1272 if (qmiidx < 0) {
1273 DBG("Bad minor number\n");
1274 return -ENXIO;
1275 }
1276
1277 printk(KERN_INFO "creating qcqmi%d\n", qmiidx);
1278 device_create(dev->qmi.devclass, &dev->iface->dev, devno, NULL, "qcqmi%d ", qmiidx);
1279
1280 dev->qmi.devnum = devno;
1281 return 0;
1282 }
1283
1284 void qc_deregister(struct qcusbnet *dev)
1285 {
1286 struct list_head *node, *tmp;
1287 struct client *client;
1288
1289 dev->dying = true;
1290 list_for_each_safe(node, tmp, &dev->qmi.clients) {
1291 client = list_entry(node, struct client, node);
1292 DBG("release 0x%04X\n", client->cid);
1293 client_free(dev, client->cid);
1294 }
1295
1296 qc_stopread(dev);
1297 dev->valid = false;
1298 if (!IS_ERR(dev->qmi.devclass))
1299 device_destroy(dev->qmi.devclass, dev->qmi.devnum);
1300 cdev_del(&dev->qmi.cdev);
1301 unregister_chrdev_region(dev->qmi.devnum, 1);
1302 }
1303
1304 static bool qmi_ready(struct qcusbnet *dev, u16 timeout)
1305 {
1306 int result;
1307 void *wbuf;
1308 size_t wbufsize;
1309 void *rbuf;
1310 u16 rbufsize;
1311 struct semaphore sem;
1312 u16 now;
1313 unsigned long flags;
1314 u8 tid;
1315
1316 if (!device_valid(dev)) {
1317 DBG("Invalid device\n");
1318 return -EFAULT;
1319 }
1320
1321
1322 for (now = 0; now < timeout; now += 100) {
1323 sema_init(&sem, 0);
1324
1325 tid = atomic_add_return(1, &dev->qmi.qmitid);
1326 if (!tid)
1327 tid = atomic_add_return(1, &dev->qmi.qmitid);
1328 kfree(wbuf);
1329 wbuf = qmictl_new_ready(tid, &wbufsize);
1330 if (!wbuf)
1331 return -ENOMEM;
1332
1333 result = read_async(dev, QMICTL, tid, upsem, &sem);
1334 if (result) {
1335 kfree(wbuf);
1336 return false;
1337 }
1338
1339 write_sync(dev, wbuf, wbufsize, QMICTL);
1340
1341 msleep(100);
1342 if (!down_trylock(&sem)) {
1343 spin_lock_irqsave(&dev->qmi.clients_lock, flags);
1344 if (client_delread(dev, QMICTL, tid, &rbuf, &rbufsize)) {
1345 spin_unlock_irqrestore(&dev->qmi.clients_lock, f lags);
1346 kfree(rbuf);
1347 break;
1348 } else {
1349 spin_unlock_irqrestore(&dev->qmi.clients_lock, f lags);
1350 }
1351 } else {
1352 spin_lock_irqsave(&dev->qmi.clients_lock, flags);
1353 client_notify(dev, QMICTL, tid);
1354 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
1355 }
1356 }
1357
1358 kfree(wbuf);
1359
1360 if (now >= timeout)
1361 return false;
1362
1363 DBG("QMI Ready after %u milliseconds\n", now);
1364
1365 /* 3580 and newer doesn't need a delay; older needs 5000ms */
1366 if (qcusbnet2k_fwdelay)
1367 msleep(qcusbnet2k_fwdelay * 1000);
1368
1369 return true;
1370 }
1371
1372 static void wds_callback(struct qcusbnet *dev, u16 cid, void *data)
1373 {
1374 bool ret;
1375 int result;
1376 void *rbuf;
1377 u16 rbufsize;
1378
1379 struct net_device_stats *stats = &(dev->usbnet->net->stats);
1380
1381 struct qmiwds_stats dstats = {
1382 .txok = (u32)-1,
1383 .rxok = (u32)-1,
1384 .txerr = (u32)-1,
1385 .rxerr = (u32)-1,
1386 .txofl = (u32)-1,
1387 .rxofl = (u32)-1,
1388 .txbytesok = (u64)-1,
1389 .rxbytesok = (u64)-1,
1390 };
1391 unsigned long flags;
1392
1393 if (!device_valid(dev)) {
1394 DBG("Invalid device\n");
1395 return;
1396 }
1397
1398 spin_lock_irqsave(&dev->qmi.clients_lock, flags);
1399 ret = client_delread(dev, cid, 0, &rbuf, &rbufsize);
1400 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
1401
1402 if (!ret) {
1403 DBG("WDS callback failed to get data\n");
1404 return;
1405 }
1406
1407 dstats.linkstate = !qc_isdown(dev, DOWN_NO_NDIS_CONNECTION);
1408 dstats.reconfigure = false;
1409
1410 result = qmiwds_event_resp(rbuf, rbufsize, &dstats);
1411 if (result < 0) {
1412 DBG("bad WDS packet\n");
1413 } else {
1414 if (dstats.txofl != (u32)-1)
1415 stats->tx_fifo_errors = dstats.txofl;
1416
1417 if (dstats.rxofl != (u32)-1)
1418 stats->rx_fifo_errors = dstats.rxofl;
1419
1420 if (dstats.txerr != (u32)-1)
1421 stats->tx_errors = dstats.txerr;
1422
1423 if (dstats.rxerr != (u32)-1)
1424 stats->rx_errors = dstats.rxerr;
1425
1426 if (dstats.txok != (u32)-1)
1427 stats->tx_packets = dstats.txok + stats->tx_errors;
1428
1429 if (dstats.rxok != (u32)-1)
1430 stats->rx_packets = dstats.rxok + stats->rx_errors;
1431
1432 if (dstats.txbytesok != (u64)-1)
1433 stats->tx_bytes = dstats.txbytesok;
1434
1435 if (dstats.rxbytesok != (u64)-1)
1436 stats->rx_bytes = dstats.rxbytesok;
1437
1438 if (dstats.reconfigure) {
1439 DBG("Net device link reset\n");
1440 qc_setdown(dev, DOWN_NO_NDIS_CONNECTION);
1441 qc_cleardown(dev, DOWN_NO_NDIS_CONNECTION);
1442 } else {
1443 if (dstats.linkstate) {
1444 DBG("Net device link is connected\n");
1445 qc_cleardown(dev, DOWN_NO_NDIS_CONNECTION);
1446 } else {
1447 DBG("Net device link is disconnected\n");
1448 qc_setdown(dev, DOWN_NO_NDIS_CONNECTION);
1449 }
1450 }
1451 }
1452
1453 kfree(rbuf);
1454
1455 result = read_async(dev, cid, 0, wds_callback, data);
1456 if (result != 0)
1457 DBG("unable to setup next async read\n");
1458 }
1459
1460 static int setup_wds_callback(struct qcusbnet *dev)
1461 {
1462 int result;
1463 void *buf;
1464 size_t size;
1465 u16 cid;
1466
1467 if (!device_valid(dev)) {
1468 DBG("Invalid device\n");
1469 return -EFAULT;
1470 }
1471
1472 result = client_alloc(dev, QMIWDS);
1473 if (result < 0)
1474 return result;
1475 cid = result;
1476
1477 buf = qmiwds_new_seteventreport(1, &size);
1478 if (!buf)
1479 return -ENOMEM;
1480
1481 result = write_sync(dev, buf, size, cid);
1482 kfree(buf);
1483
1484 if (result < 0) {
1485 return result;
1486 }
1487
1488 buf = qmiwds_new_getpkgsrvcstatus(2, &size);
1489 if (buf == NULL)
1490 return -ENOMEM;
1491
1492 result = write_sync(dev, buf, size, cid);
1493 kfree(buf);
1494
1495 if (result < 0)
1496 return result;
1497
1498 result = read_async(dev, cid, 0, wds_callback, NULL);
1499 if (result) {
1500 DBG("unable to setup async read\n");
1501 return result;
1502 }
1503
1504 result = usb_control_msg(dev->usbnet->udev,
1505 usb_sndctrlpipe(dev->usbnet->udev, 0),
1506 0x22, 0x21, 1, 0, NULL, 0, 100);
1507 if (result < 0) {
1508 DBG("Bad SetControlLineState status %d\n", result);
1509 return result;
1510 }
1511
1512 return 0;
1513 }
1514
1515 static int qmidms_getmeid(struct qcusbnet *dev)
1516 {
1517 int result;
1518 void *wbuf;
1519 size_t wbufsize;
1520 void *rbuf;
1521 u16 rbufsize;
1522 u16 cid;
1523
1524 if (!device_valid(dev)) {
1525 DBG("Invalid device\n");
1526 return -EFAULT;
1527 }
1528
1529 result = client_alloc(dev, QMIDMS);
1530 if (result < 0)
1531 return result;
1532 cid = result;
1533
1534 wbuf = qmidms_new_getmeid(1, &wbufsize);
1535 if (!wbuf)
1536 return -ENOMEM;
1537
1538 result = write_sync(dev, wbuf, wbufsize, cid);
1539 kfree(wbuf);
1540
1541 if (result < 0)
1542 return result;
1543
1544 result = read_sync(dev, &rbuf, cid, 1);
1545 if (result < 0)
1546 return result;
1547 rbufsize = result;
1548
1549 result = qmidms_meid_resp(rbuf, rbufsize, &dev->meid[0], 14);
1550 kfree(rbuf);
1551
1552 if (result < 0) {
1553 DBG("bad get MEID resp\n");
1554 memset(&dev->meid[0], '0', 14);
1555 }
1556
1557 client_free(dev, cid);
1558 return 0;
1559 }
1560
1561 module_param(qcusbnet2k_fwdelay, int, S_IRUGO | S_IWUSR);
1562 MODULE_PARM_DESC(qcusbnet2k_fwdelay, "Delay for old firmware");
OLDNEW
« no previous file with comments | « drivers/net/usb/gobi/qmidevice.h ('k') | drivers/net/usb/gobi/structs.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698