blob: d48d49c145eef6ade610ff51593ba3a816532cfb [file] [log] [blame]
Sage Ahn247e9cf2012-05-15 13:20:36 +09001/*
2 * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved.
3 *
4 * This software is licensed under the terms of the GNU General Public
5 * License version 2, as published by the Free Software Foundation, and
6 * may be copied, distributed, and modified under those terms.
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
14#include <linux/module.h>
Sage Ahn247e9cf2012-05-15 13:20:36 +090015#include <linux/kernel.h>
16#include <linux/usb.h>
17#include <asm/byteorder.h>
Adnan Aliff5e4a12012-05-31 11:32:48 +010018#include <linux/kthread.h>
Sage Ahn247e9cf2012-05-15 13:20:36 +090019
Sage Ahn247e9cf2012-05-15 13:20:36 +090020#include "gdm_usb.h"
21#include "gdm_wimax.h"
22#include "usb_boot.h"
23#include "hci.h"
24
25#include "usb_ids.h"
26
27MODULE_DEVICE_TABLE(usb, id_table);
28
29#define TX_BUF_SIZE 2048
30#if defined(CONFIG_WIMAX_GDM72XX_WIMAX2)
31#define RX_BUF_SIZE (128*1024) /* For packet aggregation */
32#else
33#define RX_BUF_SIZE 2048
34#endif
35
36#define GDM7205_PADDING 256
37
38#define H2B(x) __cpu_to_be16(x)
39#define B2H(x) __be16_to_cpu(x)
40#define DB2H(x) __be32_to_cpu(x)
41
42#define DOWNLOAD_CONF_VALUE 0x21
43
44#ifdef CONFIG_WIMAX_GDM72XX_K_MODE
45
46static DECLARE_WAIT_QUEUE_HEAD(k_wait);
47static LIST_HEAD(k_list);
48static DEFINE_SPINLOCK(k_lock);
49static int k_mode_stop;
50
51#define K_WAIT_TIME (2 * HZ / 100)
52
53#endif /* CONFIG_WIMAX_GDM72XX_K_MODE */
54
55static int init_usb(struct usbwm_dev *udev);
56static void release_usb(struct usbwm_dev *udev);
57
58/*#define DEBUG */
59#ifdef DEBUG
60static void hexdump(char *title, u8 *data, int len)
61{
62 int i;
63
64 printk(KERN_DEBUG "%s: length = %d\n", title, len);
65 for (i = 0; i < len; i++) {
66 printk(KERN_DEBUG "%02x ", data[i]);
67 if ((i & 0xf) == 0xf)
68 printk(KERN_DEBUG "\n");
69 }
70 printk(KERN_DEBUG "\n");
71}
72#endif
73
74static struct usb_tx *alloc_tx_struct(struct tx_cxt *tx)
75{
76 struct usb_tx *t = NULL;
77
78 t = kmalloc(sizeof(*t), GFP_ATOMIC);
79 if (t == NULL)
80 goto out;
81
82 memset(t, 0, sizeof(*t));
83
84 t->urb = usb_alloc_urb(0, GFP_ATOMIC);
85 t->buf = kmalloc(TX_BUF_SIZE, GFP_ATOMIC);
86 if (t->urb == NULL || t->buf == NULL)
87 goto out;
88
89 t->tx_cxt = tx;
90
91 return t;
92out:
93 if (t) {
94 usb_free_urb(t->urb);
95 kfree(t->buf);
96 kfree(t);
97 }
98 return NULL;
99}
100
101static void free_tx_struct(struct usb_tx *t)
102{
103 if (t) {
104 usb_free_urb(t->urb);
105 kfree(t->buf);
106 kfree(t);
107 }
108}
109
110static struct usb_rx *alloc_rx_struct(struct rx_cxt *rx)
111{
112 struct usb_rx *r = NULL;
113
114 r = kmalloc(sizeof(*r), GFP_ATOMIC);
115 if (r == NULL)
116 goto out;
117
118 memset(r, 0, sizeof(*r));
119
120 r->urb = usb_alloc_urb(0, GFP_ATOMIC);
121 r->buf = kmalloc(RX_BUF_SIZE, GFP_ATOMIC);
122 if (r->urb == NULL || r->buf == NULL)
123 goto out;
124
125 r->rx_cxt = rx;
126 return r;
127out:
128 if (r) {
129 usb_free_urb(r->urb);
130 kfree(r->buf);
131 kfree(r);
132 }
133 return NULL;
134}
135
136static void free_rx_struct(struct usb_rx *r)
137{
138 if (r) {
139 usb_free_urb(r->urb);
140 kfree(r->buf);
141 kfree(r);
142 }
143}
144
145/* Before this function is called, spin lock should be locked. */
146static struct usb_tx *get_tx_struct(struct tx_cxt *tx, int *no_spc)
147{
148 struct usb_tx *t;
149
150 if (list_empty(&tx->free_list)) {
151 *no_spc = 1;
152 return NULL;
153 }
154
155 t = list_entry(tx->free_list.next, struct usb_tx, list);
156 list_del(&t->list);
157
158 *no_spc = list_empty(&tx->free_list) ? 1 : 0;
159
160 return t;
161}
162
163/* Before this function is called, spin lock should be locked. */
164static void put_tx_struct(struct tx_cxt *tx, struct usb_tx *t)
165{
166 list_add_tail(&t->list, &tx->free_list);
167}
168
169/* Before this function is called, spin lock should be locked. */
170static struct usb_rx *get_rx_struct(struct rx_cxt *rx)
171{
172 struct usb_rx *r;
173
174 if (list_empty(&rx->free_list)) {
175 r = alloc_rx_struct(rx);
176 if (r == NULL)
177 return NULL;
178
179 list_add(&r->list, &rx->free_list);
180 }
181
182 r = list_entry(rx->free_list.next, struct usb_rx, list);
183 list_del(&r->list);
184 list_add_tail(&r->list, &rx->used_list);
185
186 return r;
187}
188
189/* Before this function is called, spin lock should be locked. */
190static void put_rx_struct(struct rx_cxt *rx, struct usb_rx *r)
191{
192 list_del(&r->list);
193 list_add(&r->list, &rx->free_list);
194}
195
196static int init_usb(struct usbwm_dev *udev)
197{
198 int ret = 0, i;
199 struct tx_cxt *tx = &udev->tx;
200 struct rx_cxt *rx = &udev->rx;
201 struct usb_tx *t;
202 struct usb_rx *r;
203
204 INIT_LIST_HEAD(&tx->free_list);
205 INIT_LIST_HEAD(&tx->sdu_list);
206 INIT_LIST_HEAD(&tx->hci_list);
207#if defined(CONFIG_WIMAX_GDM72XX_USB_PM) || defined(CONFIG_WIMAX_GDM72XX_K_MODE)
208 INIT_LIST_HEAD(&tx->pending_list);
209#endif
210
211 INIT_LIST_HEAD(&rx->free_list);
212 INIT_LIST_HEAD(&rx->used_list);
213
214 spin_lock_init(&tx->lock);
215 spin_lock_init(&rx->lock);
216
217 for (i = 0; i < MAX_NR_SDU_BUF; i++) {
218 t = alloc_tx_struct(tx);
219 if (t == NULL) {
220 ret = -ENOMEM;
221 goto fail;
222 }
223 list_add(&t->list, &tx->free_list);
224 }
225
226 r = alloc_rx_struct(rx);
227 if (r == NULL) {
228 ret = -ENOMEM;
229 goto fail;
230 }
231
232 list_add(&r->list, &rx->free_list);
233 return ret;
234
235fail:
236 release_usb(udev);
237 return ret;
238}
239
240static void release_usb(struct usbwm_dev *udev)
241{
242 struct tx_cxt *tx = &udev->tx;
243 struct rx_cxt *rx = &udev->rx;
244 struct usb_tx *t, *t_next;
245 struct usb_rx *r, *r_next;
246
247 list_for_each_entry_safe(t, t_next, &tx->sdu_list, list) {
248 list_del(&t->list);
249 free_tx_struct(t);
250 }
251
252 list_for_each_entry_safe(t, t_next, &tx->hci_list, list) {
253 list_del(&t->list);
254 free_tx_struct(t);
255 }
256
257 list_for_each_entry_safe(t, t_next, &tx->free_list, list) {
258 list_del(&t->list);
259 free_tx_struct(t);
260 }
261
262 list_for_each_entry_safe(r, r_next, &rx->free_list, list) {
263 list_del(&r->list);
264 free_rx_struct(r);
265 }
266
267 list_for_each_entry_safe(r, r_next, &rx->used_list, list) {
268 list_del(&r->list);
269 free_rx_struct(r);
270 }
271}
272
Ben Chan0c16ae72012-06-12 11:23:32 -0700273static void __gdm_usb_send_complete(struct urb *urb)
Sage Ahn247e9cf2012-05-15 13:20:36 +0900274{
275 struct usb_tx *t = urb->context;
276 struct tx_cxt *tx = t->tx_cxt;
277 u8 *pkt = t->buf;
278 u16 cmd_evt;
Sage Ahn247e9cf2012-05-15 13:20:36 +0900279
280 /* Completion by usb_unlink_urb */
281 if (urb->status == -ECONNRESET)
282 return;
283
Sage Ahn247e9cf2012-05-15 13:20:36 +0900284 if (t->callback)
285 t->callback(t->cb_data);
286
287 /* Delete from sdu list or hci list. */
288 list_del(&t->list);
289
290 cmd_evt = (pkt[0] << 8) | pkt[1];
291 if (cmd_evt == WIMAX_TX_SDU)
292 put_tx_struct(tx, t);
293 else
294 free_tx_struct(t);
Ben Chandd13c862012-06-06 23:01:26 -0700295}
296
297static void gdm_usb_send_complete(struct urb *urb)
298{
Ben Chan0c16ae72012-06-12 11:23:32 -0700299 struct usb_tx *t = urb->context;
300 struct tx_cxt *tx = t->tx_cxt;
301 unsigned long flags;
Ben Chandd13c862012-06-06 23:01:26 -0700302
Ben Chan0c16ae72012-06-12 11:23:32 -0700303 spin_lock_irqsave(&tx->lock, flags);
304 __gdm_usb_send_complete(urb);
305 spin_unlock_irqrestore(&tx->lock, flags);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900306}
307
308static int gdm_usb_send(void *priv_dev, void *data, int len,
309 void (*cb)(void *data), void *cb_data)
310{
311 struct usbwm_dev *udev = priv_dev;
312 struct usb_device *usbdev = udev->usbdev;
313 struct tx_cxt *tx = &udev->tx;
314 struct usb_tx *t;
315 int padding = udev->padding;
316 int no_spc = 0, ret;
317 u8 *pkt = data;
318 u16 cmd_evt;
319 unsigned long flags;
320
321 if (!udev->usbdev) {
322 printk(KERN_ERR "%s: No such device\n", __func__);
323 return -ENODEV;
324 }
325
326 BUG_ON(len > TX_BUF_SIZE - padding - 1);
327
328 spin_lock_irqsave(&tx->lock, flags);
329
330 cmd_evt = (pkt[0] << 8) | pkt[1];
331 if (cmd_evt == WIMAX_TX_SDU) {
332 t = get_tx_struct(tx, &no_spc);
333 if (t == NULL) {
334 /* This case must not happen. */
335 spin_unlock_irqrestore(&tx->lock, flags);
336 return -ENOSPC;
337 }
338 list_add_tail(&t->list, &tx->sdu_list);
339 } else {
340 t = alloc_tx_struct(tx);
341 if (t == NULL) {
342 spin_unlock_irqrestore(&tx->lock, flags);
343 return -ENOMEM;
344 }
345 list_add_tail(&t->list, &tx->hci_list);
346 }
347
348 memcpy(t->buf + padding, data, len);
349 t->callback = cb;
350 t->cb_data = cb_data;
351
352 /*
353 * In some cases, USB Module of WiMax is blocked when data size is
354 * the multiple of 512. So, increment length by one in that case.
355 */
356 if ((len % 512) == 0)
357 len++;
358
359 usb_fill_bulk_urb(t->urb,
360 usbdev,
361 usb_sndbulkpipe(usbdev, 1),
362 t->buf,
363 len + padding,
364 gdm_usb_send_complete,
365 t);
366
367#ifdef DEBUG
368 hexdump("usb_send", t->buf, len + padding);
369#endif
370#ifdef CONFIG_WIMAX_GDM72XX_USB_PM
371 if (usbdev->state & USB_STATE_SUSPENDED) {
372 list_add_tail(&t->p_list, &tx->pending_list);
373 schedule_work(&udev->pm_ws);
374 goto out;
375 }
376#endif /* CONFIG_WIMAX_GDM72XX_USB_PM */
377
378#ifdef CONFIG_WIMAX_GDM72XX_K_MODE
379 if (udev->bw_switch) {
380 list_add_tail(&t->p_list, &tx->pending_list);
381 goto out;
382 } else if (cmd_evt == WIMAX_SCAN) {
383 struct rx_cxt *rx;
384 struct usb_rx *r;
385
386 rx = &udev->rx;
387
388 list_for_each_entry(r, &rx->used_list, list)
389 usb_unlink_urb(r->urb);
390 udev->bw_switch = 1;
391
392 spin_lock(&k_lock);
393 list_add_tail(&udev->list, &k_list);
394 spin_unlock(&k_lock);
395
396 wake_up(&k_wait);
397 }
398#endif /* CONFIG_WIMAX_GDM72XX_K_MODE */
399
400 ret = usb_submit_urb(t->urb, GFP_ATOMIC);
401 if (ret)
402 goto send_fail;
403
404#ifdef CONFIG_WIMAX_GDM72XX_USB_PM
405 usb_mark_last_busy(usbdev);
406#endif /* CONFIG_WIMAX_GDM72XX_USB_PM */
407
408#if defined(CONFIG_WIMAX_GDM72XX_USB_PM) || defined(CONFIG_WIMAX_GDM72XX_K_MODE)
409out:
410#endif
411 spin_unlock_irqrestore(&tx->lock, flags);
412
413 if (no_spc)
414 return -ENOSPC;
415
416 return 0;
417
418send_fail:
419 t->callback = NULL;
Ben Chan0c16ae72012-06-12 11:23:32 -0700420 __gdm_usb_send_complete(t->urb);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900421 spin_unlock_irqrestore(&tx->lock, flags);
422 return ret;
423}
424
425static void gdm_usb_rcv_complete(struct urb *urb)
426{
427 struct usb_rx *r = urb->context;
428 struct rx_cxt *rx = r->rx_cxt;
429 struct usbwm_dev *udev = container_of(r->rx_cxt, struct usbwm_dev, rx);
430 struct tx_cxt *tx = &udev->tx;
431 struct usb_tx *t;
432 u16 cmd_evt;
433 unsigned long flags;
434
435#ifdef CONFIG_WIMAX_GDM72XX_USB_PM
436 struct usb_device *dev = urb->dev;
437#endif
438
439 /* Completion by usb_unlink_urb */
440 if (urb->status == -ECONNRESET)
441 return;
442
443 spin_lock_irqsave(&tx->lock, flags);
444
445 if (!urb->status) {
446 cmd_evt = (r->buf[0] << 8) | (r->buf[1]);
447#ifdef DEBUG
448 hexdump("usb_receive", r->buf, urb->actual_length);
449#endif
450 if (cmd_evt == WIMAX_SDU_TX_FLOW) {
451 if (r->buf[4] == 0) {
452#ifdef DEBUG
453 printk(KERN_DEBUG "WIMAX ==> STOP SDU TX\n");
454#endif
455 list_for_each_entry(t, &tx->sdu_list, list)
456 usb_unlink_urb(t->urb);
457 } else if (r->buf[4] == 1) {
458#ifdef DEBUG
459 printk(KERN_DEBUG "WIMAX ==> START SDU TX\n");
460#endif
461 list_for_each_entry(t, &tx->sdu_list, list) {
462 usb_submit_urb(t->urb, GFP_ATOMIC);
463 }
464 /*
465 * If free buffer for sdu tx doesn't
466 * exist, then tx queue should not be
467 * woken. For this reason, don't pass
468 * the command, START_SDU_TX.
469 */
470 if (list_empty(&tx->free_list))
471 urb->actual_length = 0;
472 }
473 }
474 }
475
476 if (!urb->status && r->callback)
477 r->callback(r->cb_data, r->buf, urb->actual_length);
478
479 spin_lock(&rx->lock);
480 put_rx_struct(rx, r);
481 spin_unlock(&rx->lock);
482
483 spin_unlock_irqrestore(&tx->lock, flags);
484
485#ifdef CONFIG_WIMAX_GDM72XX_USB_PM
486 usb_mark_last_busy(dev);
487#endif
488}
489
490static int gdm_usb_receive(void *priv_dev,
491 void (*cb)(void *cb_data, void *data, int len),
492 void *cb_data)
493{
494 struct usbwm_dev *udev = priv_dev;
495 struct usb_device *usbdev = udev->usbdev;
496 struct rx_cxt *rx = &udev->rx;
497 struct usb_rx *r;
498 unsigned long flags;
499
500 if (!udev->usbdev) {
501 printk(KERN_ERR "%s: No such device\n", __func__);
502 return -ENODEV;
503 }
504
505 spin_lock_irqsave(&rx->lock, flags);
506 r = get_rx_struct(rx);
507 spin_unlock_irqrestore(&rx->lock, flags);
508
509 if (r == NULL)
510 return -ENOMEM;
511
512 r->callback = cb;
513 r->cb_data = cb_data;
514
515 usb_fill_bulk_urb(r->urb,
516 usbdev,
517 usb_rcvbulkpipe(usbdev, 0x82),
518 r->buf,
519 RX_BUF_SIZE,
520 gdm_usb_rcv_complete,
521 r);
522
523 return usb_submit_urb(r->urb, GFP_ATOMIC);
524}
525
526#ifdef CONFIG_WIMAX_GDM72XX_USB_PM
527static void do_pm_control(struct work_struct *work)
528{
529 struct usbwm_dev *udev = container_of(work, struct usbwm_dev, pm_ws);
530 struct tx_cxt *tx = &udev->tx;
531 int ret;
532 unsigned long flags;
533
534 ret = usb_autopm_get_interface(udev->intf);
535 if (!ret)
536 usb_autopm_put_interface(udev->intf);
537
538 spin_lock_irqsave(&tx->lock, flags);
539 if (!(udev->usbdev->state & USB_STATE_SUSPENDED)
540 && (!list_empty(&tx->hci_list) || !list_empty(&tx->sdu_list))) {
541 struct usb_tx *t, *temp;
542
543 list_for_each_entry_safe(t, temp, &tx->pending_list, p_list) {
544 list_del(&t->p_list);
545 ret = usb_submit_urb(t->urb, GFP_ATOMIC);
546
547 if (ret) {
548 t->callback = NULL;
Ben Chan0c16ae72012-06-12 11:23:32 -0700549 __gdm_usb_send_complete(t->urb);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900550 }
551 }
552 }
553 spin_unlock_irqrestore(&tx->lock, flags);
554}
555#endif /* CONFIG_WIMAX_GDM72XX_USB_PM */
556
557static int gdm_usb_probe(struct usb_interface *intf,
558 const struct usb_device_id *id)
559{
560 int ret = 0;
561 u8 bConfigurationValue;
562 struct phy_dev *phy_dev = NULL;
563 struct usbwm_dev *udev = NULL;
564 u16 idVendor, idProduct, bcdDevice;
565
566 struct usb_device *usbdev = interface_to_usbdev(intf);
567
568 usb_get_dev(usbdev);
569 bConfigurationValue = usbdev->actconfig->desc.bConfigurationValue;
570
571 /*USB description is set up with Little-Endian*/
572 idVendor = L2H(usbdev->descriptor.idVendor);
573 idProduct = L2H(usbdev->descriptor.idProduct);
574 bcdDevice = L2H(usbdev->descriptor.bcdDevice);
575
576 printk(KERN_INFO "Found GDM USB VID = 0x%04x PID = 0x%04x...\n",
577 idVendor, idProduct);
578 printk(KERN_INFO "GCT WiMax driver version %s\n", DRIVER_VERSION);
579
580
581 if (idProduct == EMERGENCY_PID) {
582 ret = usb_emergency(usbdev);
583 goto out;
584 }
585
586 /* Support for EEPROM bootloader */
587 if (bConfigurationValue == DOWNLOAD_CONF_VALUE ||
588 idProduct & B_DOWNLOAD) {
589 ret = usb_boot(usbdev, bcdDevice);
590 goto out;
591 }
592
Devendra Naga7fc03ad2012-07-12 11:56:54 +0545593 phy_dev = kzalloc(sizeof(*phy_dev), GFP_KERNEL);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900594 if (phy_dev == NULL) {
595 ret = -ENOMEM;
596 goto out;
597 }
Devendra Naga7fc03ad2012-07-12 11:56:54 +0545598 udev = kzalloc(sizeof(*udev), GFP_KERNEL);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900599 if (udev == NULL) {
600 ret = -ENOMEM;
601 goto out;
602 }
603
Sage Ahn247e9cf2012-05-15 13:20:36 +0900604 if (idProduct == 0x7205 || idProduct == 0x7206)
605 udev->padding = GDM7205_PADDING;
606 else
607 udev->padding = 0;
608
609 phy_dev->priv_dev = (void *)udev;
610 phy_dev->send_func = gdm_usb_send;
611 phy_dev->rcv_func = gdm_usb_receive;
612
613 ret = init_usb(udev);
614 if (ret < 0)
615 goto out;
616
617 udev->usbdev = usbdev;
618
619#ifdef CONFIG_WIMAX_GDM72XX_USB_PM
620 udev->intf = intf;
621
622 intf->needs_remote_wakeup = 1;
623 device_init_wakeup(&intf->dev, 1);
624
625 pm_runtime_set_autosuspend_delay(&usbdev->dev, 10 * 1000); /* msec */
626
627 INIT_WORK(&udev->pm_ws, do_pm_control);
628#endif /* CONFIG_WIMAX_GDM72XX_USB_PM */
629
Paul Stewart54bc1ff2012-05-17 11:15:10 -0700630 ret = register_wimax_device(phy_dev, &intf->dev);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900631
632out:
633 if (ret) {
634 kfree(phy_dev);
635 kfree(udev);
636 }
637 usb_set_intfdata(intf, phy_dev);
638 return ret;
639}
640
641static void gdm_usb_disconnect(struct usb_interface *intf)
642{
643 u8 bConfigurationValue;
644 struct phy_dev *phy_dev;
645 struct usbwm_dev *udev;
646 u16 idProduct;
647 struct usb_device *usbdev = interface_to_usbdev(intf);
648
649 bConfigurationValue = usbdev->actconfig->desc.bConfigurationValue;
650 phy_dev = usb_get_intfdata(intf);
651
652 /*USB description is set up with Little-Endian*/
653 idProduct = L2H(usbdev->descriptor.idProduct);
654
655 if (idProduct != EMERGENCY_PID &&
656 bConfigurationValue != DOWNLOAD_CONF_VALUE &&
657 (idProduct & B_DOWNLOAD) == 0) {
658 udev = phy_dev->priv_dev;
659 udev->usbdev = NULL;
660
661 unregister_wimax_device(phy_dev);
662 release_usb(udev);
663 kfree(udev);
664 kfree(phy_dev);
665 }
666
667 usb_put_dev(usbdev);
668}
669
670#ifdef CONFIG_WIMAX_GDM72XX_USB_PM
671static int gdm_suspend(struct usb_interface *intf, pm_message_t pm_msg)
672{
673 struct phy_dev *phy_dev;
674 struct usbwm_dev *udev;
675 struct rx_cxt *rx;
676 struct usb_rx *r;
677
678 phy_dev = usb_get_intfdata(intf);
679 udev = phy_dev->priv_dev;
680 rx = &udev->rx;
681
682 list_for_each_entry(r, &rx->used_list, list)
683 usb_unlink_urb(r->urb);
684
685 return 0;
686}
687
688static int gdm_resume(struct usb_interface *intf)
689{
690 struct phy_dev *phy_dev;
691 struct usbwm_dev *udev;
692 struct rx_cxt *rx;
693 struct usb_rx *r;
694
695 phy_dev = usb_get_intfdata(intf);
696 udev = phy_dev->priv_dev;
697 rx = &udev->rx;
698
699 list_for_each_entry(r, &rx->used_list, list)
700 usb_submit_urb(r->urb, GFP_ATOMIC);
701
702 return 0;
703}
704
705#endif /* CONFIG_WIMAX_GDM72XX_USB_PM */
706
707#ifdef CONFIG_WIMAX_GDM72XX_K_MODE
708static int k_mode_thread(void *arg)
709{
710 struct usbwm_dev *udev;
711 struct tx_cxt *tx;
712 struct rx_cxt *rx;
713 struct usb_tx *t, *temp;
714 struct usb_rx *r;
715 unsigned long flags, flags2, expire;
716 int ret;
717
718 daemonize("k_mode_wimax");
719
720 while (!k_mode_stop) {
721
722 spin_lock_irqsave(&k_lock, flags2);
723 while (!list_empty(&k_list)) {
724
725 udev = list_entry(k_list.next, struct usbwm_dev, list);
726 tx = &udev->tx;
727 rx = &udev->rx;
728
729 list_del(&udev->list);
730 spin_unlock_irqrestore(&k_lock, flags2);
731
732 expire = jiffies + K_WAIT_TIME;
733 while (jiffies < expire)
734 schedule_timeout(K_WAIT_TIME);
735
736 list_for_each_entry(r, &rx->used_list, list)
737 usb_submit_urb(r->urb, GFP_ATOMIC);
738
739 spin_lock_irqsave(&tx->lock, flags);
740
741 list_for_each_entry_safe(t, temp, &tx->pending_list,
742 p_list) {
743 list_del(&t->p_list);
744 ret = usb_submit_urb(t->urb, GFP_ATOMIC);
745
746 if (ret) {
747 t->callback = NULL;
Ben Chan0c16ae72012-06-12 11:23:32 -0700748 __gdm_usb_send_complete(t->urb);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900749 }
750 }
751
752 udev->bw_switch = 0;
753 spin_unlock_irqrestore(&tx->lock, flags);
754
755 spin_lock_irqsave(&k_lock, flags2);
756 }
757 spin_unlock_irqrestore(&k_lock, flags2);
758
759 interruptible_sleep_on(&k_wait);
760 }
761 return 0;
762}
763#endif /* CONFIG_WIMAX_GDM72XX_K_MODE */
764
765static struct usb_driver gdm_usb_driver = {
766 .name = "gdm_wimax",
767 .probe = gdm_usb_probe,
768 .disconnect = gdm_usb_disconnect,
769 .id_table = id_table,
770#ifdef CONFIG_WIMAX_GDM72XX_USB_PM
771 .supports_autosuspend = 1,
772 .suspend = gdm_suspend,
773 .resume = gdm_resume,
774 .reset_resume = gdm_resume,
775#endif
776};
777
778static int __init usb_gdm_wimax_init(void)
779{
780#ifdef CONFIG_WIMAX_GDM72XX_K_MODE
Adnan Aliff5e4a12012-05-31 11:32:48 +0100781 kthread_run(k_mode_thread, NULL, "WiMax_thread");
Sage Ahn247e9cf2012-05-15 13:20:36 +0900782#endif /* CONFIG_WIMAX_GDM72XX_K_MODE */
783 return usb_register(&gdm_usb_driver);
784}
785
786static void __exit usb_gdm_wimax_exit(void)
787{
788#ifdef CONFIG_WIMAX_GDM72XX_K_MODE
789 k_mode_stop = 1;
790 wake_up(&k_wait);
791#endif
792 usb_deregister(&gdm_usb_driver);
793}
794
795module_init(usb_gdm_wimax_init);
796module_exit(usb_gdm_wimax_exit);
797
798MODULE_VERSION(DRIVER_VERSION);
799MODULE_DESCRIPTION("GCT WiMax Device Driver");
800MODULE_AUTHOR("Ethan Park");
801MODULE_LICENSE("GPL");