blob: 3709824e7ca32c6044f3b08de660ab7ac95bc00b [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
Macpaul Lin0d660022012-09-12 17:49:24 +080029#define TX_BUF_SIZE 2048
Sage Ahn247e9cf2012-05-15 13:20:36 +090030#if defined(CONFIG_WIMAX_GDM72XX_WIMAX2)
Macpaul Lin0d660022012-09-12 17:49:24 +080031#define RX_BUF_SIZE (128*1024) /* For packet aggregation */
Sage Ahn247e9cf2012-05-15 13:20:36 +090032#else
Macpaul Lin0d660022012-09-12 17:49:24 +080033#define RX_BUF_SIZE 2048
Sage Ahn247e9cf2012-05-15 13:20:36 +090034#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
Macpaul Lin0d660022012-09-12 17:49:24 +080042#define DOWNLOAD_CONF_VALUE 0x21
Sage Ahn247e9cf2012-05-15 13:20:36 +090043
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
Macpaul Lin0d660022012-09-12 17:49:24 +080051#define K_WAIT_TIME (2 * HZ / 100)
Sage Ahn247e9cf2012-05-15 13:20:36 +090052
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{
Ben Chan129575f2012-09-12 11:43:41 -070076 struct usb_tx *t = kzalloc(sizeof(*t), GFP_ATOMIC);
Sage Ahn247e9cf2012-05-15 13:20:36 +090077
Ben Chan129575f2012-09-12 11:43:41 -070078 if (!t)
79 return NULL;
Sage Ahn247e9cf2012-05-15 13:20:36 +090080
Sage Ahn247e9cf2012-05-15 13:20:36 +090081 t->urb = usb_alloc_urb(0, GFP_ATOMIC);
82 t->buf = kmalloc(TX_BUF_SIZE, GFP_ATOMIC);
Ben Chan129575f2012-09-12 11:43:41 -070083 if (!t->urb || !t->buf) {
84 usb_free_urb(t->urb);
85 kfree(t->buf);
86 kfree(t);
87 return NULL;
88 }
Sage Ahn247e9cf2012-05-15 13:20:36 +090089
90 t->tx_cxt = tx;
91
92 return t;
Sage Ahn247e9cf2012-05-15 13:20:36 +090093}
94
95static void free_tx_struct(struct usb_tx *t)
96{
97 if (t) {
98 usb_free_urb(t->urb);
99 kfree(t->buf);
100 kfree(t);
101 }
102}
103
104static struct usb_rx *alloc_rx_struct(struct rx_cxt *rx)
105{
Ben Chan129575f2012-09-12 11:43:41 -0700106 struct usb_rx *r = kzalloc(sizeof(*r), GFP_ATOMIC);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900107
Ben Chan129575f2012-09-12 11:43:41 -0700108 if (!r)
109 return NULL;
Sage Ahn247e9cf2012-05-15 13:20:36 +0900110
111 r->urb = usb_alloc_urb(0, GFP_ATOMIC);
112 r->buf = kmalloc(RX_BUF_SIZE, GFP_ATOMIC);
Ben Chan129575f2012-09-12 11:43:41 -0700113 if (!r->urb || !r->buf) {
Sage Ahn247e9cf2012-05-15 13:20:36 +0900114 usb_free_urb(r->urb);
115 kfree(r->buf);
116 kfree(r);
Ben Chan129575f2012-09-12 11:43:41 -0700117 return NULL;
Sage Ahn247e9cf2012-05-15 13:20:36 +0900118 }
Ben Chan129575f2012-09-12 11:43:41 -0700119
120 r->rx_cxt = rx;
121 return r;
Sage Ahn247e9cf2012-05-15 13:20:36 +0900122}
123
124static void free_rx_struct(struct usb_rx *r)
125{
126 if (r) {
127 usb_free_urb(r->urb);
128 kfree(r->buf);
129 kfree(r);
130 }
131}
132
133/* Before this function is called, spin lock should be locked. */
134static struct usb_tx *get_tx_struct(struct tx_cxt *tx, int *no_spc)
135{
136 struct usb_tx *t;
137
138 if (list_empty(&tx->free_list)) {
139 *no_spc = 1;
140 return NULL;
141 }
142
143 t = list_entry(tx->free_list.next, struct usb_tx, list);
144 list_del(&t->list);
145
146 *no_spc = list_empty(&tx->free_list) ? 1 : 0;
147
148 return t;
149}
150
151/* Before this function is called, spin lock should be locked. */
152static void put_tx_struct(struct tx_cxt *tx, struct usb_tx *t)
153{
154 list_add_tail(&t->list, &tx->free_list);
155}
156
157/* Before this function is called, spin lock should be locked. */
158static struct usb_rx *get_rx_struct(struct rx_cxt *rx)
159{
160 struct usb_rx *r;
161
162 if (list_empty(&rx->free_list)) {
163 r = alloc_rx_struct(rx);
164 if (r == NULL)
165 return NULL;
166
167 list_add(&r->list, &rx->free_list);
168 }
169
170 r = list_entry(rx->free_list.next, struct usb_rx, list);
Wei Yongjune5d2cb42012-09-05 14:49:15 +0800171 list_move_tail(&r->list, &rx->used_list);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900172
173 return r;
174}
175
176/* Before this function is called, spin lock should be locked. */
177static void put_rx_struct(struct rx_cxt *rx, struct usb_rx *r)
178{
Wei Yongjun73295fe2012-09-06 12:36:49 +0800179 list_move(&r->list, &rx->free_list);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900180}
181
182static int init_usb(struct usbwm_dev *udev)
183{
184 int ret = 0, i;
185 struct tx_cxt *tx = &udev->tx;
186 struct rx_cxt *rx = &udev->rx;
187 struct usb_tx *t;
188 struct usb_rx *r;
Ben Chan1a276b82012-11-24 19:35:36 -0800189 unsigned long flags;
Sage Ahn247e9cf2012-05-15 13:20:36 +0900190
191 INIT_LIST_HEAD(&tx->free_list);
192 INIT_LIST_HEAD(&tx->sdu_list);
193 INIT_LIST_HEAD(&tx->hci_list);
194#if defined(CONFIG_WIMAX_GDM72XX_USB_PM) || defined(CONFIG_WIMAX_GDM72XX_K_MODE)
195 INIT_LIST_HEAD(&tx->pending_list);
196#endif
197
198 INIT_LIST_HEAD(&rx->free_list);
199 INIT_LIST_HEAD(&rx->used_list);
200
201 spin_lock_init(&tx->lock);
202 spin_lock_init(&rx->lock);
203
Ben Chan1a276b82012-11-24 19:35:36 -0800204 spin_lock_irqsave(&tx->lock, flags);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900205 for (i = 0; i < MAX_NR_SDU_BUF; i++) {
206 t = alloc_tx_struct(tx);
207 if (t == NULL) {
208 ret = -ENOMEM;
209 goto fail;
210 }
211 list_add(&t->list, &tx->free_list);
212 }
Ben Chan1a276b82012-11-24 19:35:36 -0800213 spin_unlock_irqrestore(&tx->lock, flags);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900214
215 r = alloc_rx_struct(rx);
216 if (r == NULL) {
217 ret = -ENOMEM;
218 goto fail;
219 }
220
Ben Chan1a276b82012-11-24 19:35:36 -0800221 spin_lock_irqsave(&rx->lock, flags);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900222 list_add(&r->list, &rx->free_list);
Ben Chan1a276b82012-11-24 19:35:36 -0800223 spin_unlock_irqrestore(&rx->lock, flags);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900224 return ret;
225
226fail:
227 release_usb(udev);
228 return ret;
229}
230
231static void release_usb(struct usbwm_dev *udev)
232{
233 struct tx_cxt *tx = &udev->tx;
234 struct rx_cxt *rx = &udev->rx;
235 struct usb_tx *t, *t_next;
236 struct usb_rx *r, *r_next;
Ben Chan1a276b82012-11-24 19:35:36 -0800237 unsigned long flags;
238
239 spin_lock_irqsave(&tx->lock, flags);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900240
241 list_for_each_entry_safe(t, t_next, &tx->sdu_list, list) {
242 list_del(&t->list);
243 free_tx_struct(t);
244 }
245
246 list_for_each_entry_safe(t, t_next, &tx->hci_list, list) {
247 list_del(&t->list);
248 free_tx_struct(t);
249 }
250
251 list_for_each_entry_safe(t, t_next, &tx->free_list, list) {
252 list_del(&t->list);
253 free_tx_struct(t);
254 }
255
Ben Chan1a276b82012-11-24 19:35:36 -0800256 spin_unlock_irqrestore(&tx->lock, flags);
257
258 spin_lock_irqsave(&rx->lock, flags);
259
Sage Ahn247e9cf2012-05-15 13:20:36 +0900260 list_for_each_entry_safe(r, r_next, &rx->free_list, list) {
261 list_del(&r->list);
262 free_rx_struct(r);
263 }
264
265 list_for_each_entry_safe(r, r_next, &rx->used_list, list) {
266 list_del(&r->list);
267 free_rx_struct(r);
268 }
Ben Chan1a276b82012-11-24 19:35:36 -0800269
270 spin_unlock_irqrestore(&rx->lock, flags);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900271}
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;
Ben Chana7e4a982012-11-26 20:18:45 -0800319 unsigned long flags;
320#ifdef CONFIG_WIMAX_GDM72XX_K_MODE
321 unsigned long flags2;
322#endif /* CONFIG_WIMAX_GDM72XX_K_MODE */
Sage Ahn247e9cf2012-05-15 13:20:36 +0900323
324 if (!udev->usbdev) {
YAMANE Toshiakia7d46832012-10-29 20:05:43 +0900325 dev_err(&usbdev->dev, "%s: No such device\n", __func__);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900326 return -ENODEV;
327 }
328
329 BUG_ON(len > TX_BUF_SIZE - padding - 1);
330
331 spin_lock_irqsave(&tx->lock, flags);
332
333 cmd_evt = (pkt[0] << 8) | pkt[1];
334 if (cmd_evt == WIMAX_TX_SDU) {
335 t = get_tx_struct(tx, &no_spc);
336 if (t == NULL) {
337 /* This case must not happen. */
338 spin_unlock_irqrestore(&tx->lock, flags);
339 return -ENOSPC;
340 }
341 list_add_tail(&t->list, &tx->sdu_list);
342 } else {
343 t = alloc_tx_struct(tx);
344 if (t == NULL) {
345 spin_unlock_irqrestore(&tx->lock, flags);
346 return -ENOMEM;
347 }
348 list_add_tail(&t->list, &tx->hci_list);
349 }
350
351 memcpy(t->buf + padding, data, len);
352 t->callback = cb;
353 t->cb_data = cb_data;
354
355 /*
356 * In some cases, USB Module of WiMax is blocked when data size is
357 * the multiple of 512. So, increment length by one in that case.
358 */
359 if ((len % 512) == 0)
360 len++;
361
362 usb_fill_bulk_urb(t->urb,
363 usbdev,
364 usb_sndbulkpipe(usbdev, 1),
365 t->buf,
366 len + padding,
367 gdm_usb_send_complete,
368 t);
369
370#ifdef DEBUG
371 hexdump("usb_send", t->buf, len + padding);
372#endif
373#ifdef CONFIG_WIMAX_GDM72XX_USB_PM
374 if (usbdev->state & USB_STATE_SUSPENDED) {
375 list_add_tail(&t->p_list, &tx->pending_list);
376 schedule_work(&udev->pm_ws);
377 goto out;
378 }
379#endif /* CONFIG_WIMAX_GDM72XX_USB_PM */
380
381#ifdef CONFIG_WIMAX_GDM72XX_K_MODE
382 if (udev->bw_switch) {
383 list_add_tail(&t->p_list, &tx->pending_list);
384 goto out;
385 } else if (cmd_evt == WIMAX_SCAN) {
386 struct rx_cxt *rx;
387 struct usb_rx *r;
388
389 rx = &udev->rx;
390
Ben Chan1a276b82012-11-24 19:35:36 -0800391 spin_lock_irqsave(&rx->lock, flags2);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900392 list_for_each_entry(r, &rx->used_list, list)
393 usb_unlink_urb(r->urb);
Ben Chan1a276b82012-11-24 19:35:36 -0800394 spin_unlock_irqrestore(&rx->lock, flags2);
395
Sage Ahn247e9cf2012-05-15 13:20:36 +0900396 udev->bw_switch = 1;
397
Ben Chan1a276b82012-11-24 19:35:36 -0800398 spin_lock_irqsave(&k_lock, flags2);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900399 list_add_tail(&udev->list, &k_list);
Ben Chan1a276b82012-11-24 19:35:36 -0800400 spin_unlock_irqrestore(&k_lock, flags2);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900401
402 wake_up(&k_wait);
403 }
404#endif /* CONFIG_WIMAX_GDM72XX_K_MODE */
405
406 ret = usb_submit_urb(t->urb, GFP_ATOMIC);
407 if (ret)
408 goto send_fail;
409
410#ifdef CONFIG_WIMAX_GDM72XX_USB_PM
411 usb_mark_last_busy(usbdev);
412#endif /* CONFIG_WIMAX_GDM72XX_USB_PM */
413
414#if defined(CONFIG_WIMAX_GDM72XX_USB_PM) || defined(CONFIG_WIMAX_GDM72XX_K_MODE)
415out:
416#endif
417 spin_unlock_irqrestore(&tx->lock, flags);
418
419 if (no_spc)
420 return -ENOSPC;
421
422 return 0;
423
424send_fail:
425 t->callback = NULL;
Ben Chan0c16ae72012-06-12 11:23:32 -0700426 __gdm_usb_send_complete(t->urb);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900427 spin_unlock_irqrestore(&tx->lock, flags);
428 return ret;
429}
430
431static void gdm_usb_rcv_complete(struct urb *urb)
432{
433 struct usb_rx *r = urb->context;
434 struct rx_cxt *rx = r->rx_cxt;
435 struct usbwm_dev *udev = container_of(r->rx_cxt, struct usbwm_dev, rx);
436 struct tx_cxt *tx = &udev->tx;
437 struct usb_tx *t;
438 u16 cmd_evt;
Ben Chan1a276b82012-11-24 19:35:36 -0800439 unsigned long flags, flags2;
Sage Ahn247e9cf2012-05-15 13:20:36 +0900440
441#ifdef CONFIG_WIMAX_GDM72XX_USB_PM
442 struct usb_device *dev = urb->dev;
443#endif
444
445 /* Completion by usb_unlink_urb */
446 if (urb->status == -ECONNRESET)
447 return;
448
449 spin_lock_irqsave(&tx->lock, flags);
450
451 if (!urb->status) {
452 cmd_evt = (r->buf[0] << 8) | (r->buf[1]);
453#ifdef DEBUG
454 hexdump("usb_receive", r->buf, urb->actual_length);
455#endif
456 if (cmd_evt == WIMAX_SDU_TX_FLOW) {
457 if (r->buf[4] == 0) {
458#ifdef DEBUG
459 printk(KERN_DEBUG "WIMAX ==> STOP SDU TX\n");
460#endif
461 list_for_each_entry(t, &tx->sdu_list, list)
462 usb_unlink_urb(t->urb);
463 } else if (r->buf[4] == 1) {
464#ifdef DEBUG
465 printk(KERN_DEBUG "WIMAX ==> START SDU TX\n");
466#endif
467 list_for_each_entry(t, &tx->sdu_list, list) {
468 usb_submit_urb(t->urb, GFP_ATOMIC);
469 }
470 /*
471 * If free buffer for sdu tx doesn't
472 * exist, then tx queue should not be
473 * woken. For this reason, don't pass
474 * the command, START_SDU_TX.
475 */
476 if (list_empty(&tx->free_list))
477 urb->actual_length = 0;
478 }
479 }
480 }
481
482 if (!urb->status && r->callback)
483 r->callback(r->cb_data, r->buf, urb->actual_length);
484
Ben Chan1a276b82012-11-24 19:35:36 -0800485 spin_lock_irqsave(&rx->lock, flags2);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900486 put_rx_struct(rx, r);
Ben Chan1a276b82012-11-24 19:35:36 -0800487 spin_unlock_irqrestore(&rx->lock, flags2);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900488
489 spin_unlock_irqrestore(&tx->lock, flags);
490
491#ifdef CONFIG_WIMAX_GDM72XX_USB_PM
492 usb_mark_last_busy(dev);
493#endif
494}
495
496static int gdm_usb_receive(void *priv_dev,
497 void (*cb)(void *cb_data, void *data, int len),
498 void *cb_data)
499{
500 struct usbwm_dev *udev = priv_dev;
501 struct usb_device *usbdev = udev->usbdev;
502 struct rx_cxt *rx = &udev->rx;
503 struct usb_rx *r;
504 unsigned long flags;
505
506 if (!udev->usbdev) {
YAMANE Toshiakia7d46832012-10-29 20:05:43 +0900507 dev_err(&usbdev->dev, "%s: No such device\n", __func__);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900508 return -ENODEV;
509 }
510
511 spin_lock_irqsave(&rx->lock, flags);
512 r = get_rx_struct(rx);
513 spin_unlock_irqrestore(&rx->lock, flags);
514
515 if (r == NULL)
516 return -ENOMEM;
517
518 r->callback = cb;
519 r->cb_data = cb_data;
520
521 usb_fill_bulk_urb(r->urb,
522 usbdev,
523 usb_rcvbulkpipe(usbdev, 0x82),
524 r->buf,
525 RX_BUF_SIZE,
526 gdm_usb_rcv_complete,
527 r);
528
529 return usb_submit_urb(r->urb, GFP_ATOMIC);
530}
531
532#ifdef CONFIG_WIMAX_GDM72XX_USB_PM
533static void do_pm_control(struct work_struct *work)
534{
535 struct usbwm_dev *udev = container_of(work, struct usbwm_dev, pm_ws);
536 struct tx_cxt *tx = &udev->tx;
537 int ret;
538 unsigned long flags;
539
540 ret = usb_autopm_get_interface(udev->intf);
541 if (!ret)
542 usb_autopm_put_interface(udev->intf);
543
544 spin_lock_irqsave(&tx->lock, flags);
545 if (!(udev->usbdev->state & USB_STATE_SUSPENDED)
546 && (!list_empty(&tx->hci_list) || !list_empty(&tx->sdu_list))) {
547 struct usb_tx *t, *temp;
548
549 list_for_each_entry_safe(t, temp, &tx->pending_list, p_list) {
550 list_del(&t->p_list);
551 ret = usb_submit_urb(t->urb, GFP_ATOMIC);
552
553 if (ret) {
554 t->callback = NULL;
Ben Chan0c16ae72012-06-12 11:23:32 -0700555 __gdm_usb_send_complete(t->urb);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900556 }
557 }
558 }
559 spin_unlock_irqrestore(&tx->lock, flags);
560}
561#endif /* CONFIG_WIMAX_GDM72XX_USB_PM */
562
563static int gdm_usb_probe(struct usb_interface *intf,
564 const struct usb_device_id *id)
565{
566 int ret = 0;
567 u8 bConfigurationValue;
568 struct phy_dev *phy_dev = NULL;
569 struct usbwm_dev *udev = NULL;
570 u16 idVendor, idProduct, bcdDevice;
571
572 struct usb_device *usbdev = interface_to_usbdev(intf);
573
574 usb_get_dev(usbdev);
575 bConfigurationValue = usbdev->actconfig->desc.bConfigurationValue;
576
577 /*USB description is set up with Little-Endian*/
578 idVendor = L2H(usbdev->descriptor.idVendor);
579 idProduct = L2H(usbdev->descriptor.idProduct);
580 bcdDevice = L2H(usbdev->descriptor.bcdDevice);
581
YAMANE Toshiakia7d46832012-10-29 20:05:43 +0900582 dev_info(&intf->dev, "Found GDM USB VID = 0x%04x PID = 0x%04x...\n",
583 idVendor, idProduct);
584 dev_info(&intf->dev, "GCT WiMax driver version %s\n", DRIVER_VERSION);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900585
586
587 if (idProduct == EMERGENCY_PID) {
588 ret = usb_emergency(usbdev);
589 goto out;
590 }
591
592 /* Support for EEPROM bootloader */
593 if (bConfigurationValue == DOWNLOAD_CONF_VALUE ||
594 idProduct & B_DOWNLOAD) {
595 ret = usb_boot(usbdev, bcdDevice);
596 goto out;
597 }
598
Devendra Naga7fc03ad2012-07-12 11:56:54 +0545599 phy_dev = kzalloc(sizeof(*phy_dev), GFP_KERNEL);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900600 if (phy_dev == NULL) {
601 ret = -ENOMEM;
602 goto out;
603 }
Devendra Naga7fc03ad2012-07-12 11:56:54 +0545604 udev = kzalloc(sizeof(*udev), GFP_KERNEL);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900605 if (udev == NULL) {
606 ret = -ENOMEM;
607 goto out;
608 }
609
Sage Ahn247e9cf2012-05-15 13:20:36 +0900610 if (idProduct == 0x7205 || idProduct == 0x7206)
611 udev->padding = GDM7205_PADDING;
612 else
613 udev->padding = 0;
614
615 phy_dev->priv_dev = (void *)udev;
616 phy_dev->send_func = gdm_usb_send;
617 phy_dev->rcv_func = gdm_usb_receive;
618
619 ret = init_usb(udev);
620 if (ret < 0)
621 goto out;
622
623 udev->usbdev = usbdev;
624
625#ifdef CONFIG_WIMAX_GDM72XX_USB_PM
626 udev->intf = intf;
627
628 intf->needs_remote_wakeup = 1;
629 device_init_wakeup(&intf->dev, 1);
630
631 pm_runtime_set_autosuspend_delay(&usbdev->dev, 10 * 1000); /* msec */
632
633 INIT_WORK(&udev->pm_ws, do_pm_control);
634#endif /* CONFIG_WIMAX_GDM72XX_USB_PM */
635
Paul Stewart54bc1ff2012-05-17 11:15:10 -0700636 ret = register_wimax_device(phy_dev, &intf->dev);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900637
638out:
639 if (ret) {
640 kfree(phy_dev);
641 kfree(udev);
Ben Chan1a276b82012-11-24 19:35:36 -0800642 } else {
643 usb_set_intfdata(intf, phy_dev);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900644 }
Sage Ahn247e9cf2012-05-15 13:20:36 +0900645 return ret;
646}
647
648static void gdm_usb_disconnect(struct usb_interface *intf)
649{
650 u8 bConfigurationValue;
651 struct phy_dev *phy_dev;
652 struct usbwm_dev *udev;
653 u16 idProduct;
654 struct usb_device *usbdev = interface_to_usbdev(intf);
655
656 bConfigurationValue = usbdev->actconfig->desc.bConfigurationValue;
657 phy_dev = usb_get_intfdata(intf);
658
659 /*USB description is set up with Little-Endian*/
660 idProduct = L2H(usbdev->descriptor.idProduct);
661
662 if (idProduct != EMERGENCY_PID &&
663 bConfigurationValue != DOWNLOAD_CONF_VALUE &&
664 (idProduct & B_DOWNLOAD) == 0) {
665 udev = phy_dev->priv_dev;
666 udev->usbdev = NULL;
667
668 unregister_wimax_device(phy_dev);
669 release_usb(udev);
670 kfree(udev);
671 kfree(phy_dev);
672 }
673
674 usb_put_dev(usbdev);
675}
676
677#ifdef CONFIG_WIMAX_GDM72XX_USB_PM
678static int gdm_suspend(struct usb_interface *intf, pm_message_t pm_msg)
679{
680 struct phy_dev *phy_dev;
681 struct usbwm_dev *udev;
682 struct rx_cxt *rx;
683 struct usb_rx *r;
Ben Chan1a276b82012-11-24 19:35:36 -0800684 unsigned long flags;
Sage Ahn247e9cf2012-05-15 13:20:36 +0900685
686 phy_dev = usb_get_intfdata(intf);
Ben Chan1a276b82012-11-24 19:35:36 -0800687 if (!phy_dev)
688 return 0;
689
Sage Ahn247e9cf2012-05-15 13:20:36 +0900690 udev = phy_dev->priv_dev;
691 rx = &udev->rx;
692
Ben Chan1a276b82012-11-24 19:35:36 -0800693 spin_lock_irqsave(&rx->lock, flags);
694
Sage Ahn247e9cf2012-05-15 13:20:36 +0900695 list_for_each_entry(r, &rx->used_list, list)
696 usb_unlink_urb(r->urb);
697
Ben Chan1a276b82012-11-24 19:35:36 -0800698 spin_unlock_irqrestore(&rx->lock, flags);
699
Sage Ahn247e9cf2012-05-15 13:20:36 +0900700 return 0;
701}
702
703static int gdm_resume(struct usb_interface *intf)
704{
705 struct phy_dev *phy_dev;
706 struct usbwm_dev *udev;
707 struct rx_cxt *rx;
708 struct usb_rx *r;
Ben Chan1a276b82012-11-24 19:35:36 -0800709 unsigned long flags;
Sage Ahn247e9cf2012-05-15 13:20:36 +0900710
711 phy_dev = usb_get_intfdata(intf);
Ben Chan1a276b82012-11-24 19:35:36 -0800712 if (!phy_dev)
713 return 0;
714
Sage Ahn247e9cf2012-05-15 13:20:36 +0900715 udev = phy_dev->priv_dev;
716 rx = &udev->rx;
717
Ben Chan1a276b82012-11-24 19:35:36 -0800718 spin_lock_irqsave(&rx->lock, flags);
719
Sage Ahn247e9cf2012-05-15 13:20:36 +0900720 list_for_each_entry(r, &rx->used_list, list)
721 usb_submit_urb(r->urb, GFP_ATOMIC);
722
Ben Chan1a276b82012-11-24 19:35:36 -0800723 spin_unlock_irqrestore(&rx->lock, flags);
724
Sage Ahn247e9cf2012-05-15 13:20:36 +0900725 return 0;
726}
727
728#endif /* CONFIG_WIMAX_GDM72XX_USB_PM */
729
730#ifdef CONFIG_WIMAX_GDM72XX_K_MODE
731static int k_mode_thread(void *arg)
732{
733 struct usbwm_dev *udev;
734 struct tx_cxt *tx;
735 struct rx_cxt *rx;
736 struct usb_tx *t, *temp;
737 struct usb_rx *r;
738 unsigned long flags, flags2, expire;
739 int ret;
740
741 daemonize("k_mode_wimax");
742
743 while (!k_mode_stop) {
744
745 spin_lock_irqsave(&k_lock, flags2);
746 while (!list_empty(&k_list)) {
747
748 udev = list_entry(k_list.next, struct usbwm_dev, list);
749 tx = &udev->tx;
750 rx = &udev->rx;
751
752 list_del(&udev->list);
753 spin_unlock_irqrestore(&k_lock, flags2);
754
755 expire = jiffies + K_WAIT_TIME;
756 while (jiffies < expire)
757 schedule_timeout(K_WAIT_TIME);
758
Ben Chan1a276b82012-11-24 19:35:36 -0800759 spin_lock_irqsave(&rx->lock, flags);
760
Sage Ahn247e9cf2012-05-15 13:20:36 +0900761 list_for_each_entry(r, &rx->used_list, list)
762 usb_submit_urb(r->urb, GFP_ATOMIC);
763
Ben Chan1a276b82012-11-24 19:35:36 -0800764 spin_unlock_irqrestore(&rx->lock, flags);
765
Sage Ahn247e9cf2012-05-15 13:20:36 +0900766 spin_lock_irqsave(&tx->lock, flags);
767
768 list_for_each_entry_safe(t, temp, &tx->pending_list,
769 p_list) {
770 list_del(&t->p_list);
771 ret = usb_submit_urb(t->urb, GFP_ATOMIC);
772
773 if (ret) {
774 t->callback = NULL;
Ben Chan0c16ae72012-06-12 11:23:32 -0700775 __gdm_usb_send_complete(t->urb);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900776 }
777 }
778
779 udev->bw_switch = 0;
780 spin_unlock_irqrestore(&tx->lock, flags);
781
782 spin_lock_irqsave(&k_lock, flags2);
783 }
784 spin_unlock_irqrestore(&k_lock, flags2);
785
786 interruptible_sleep_on(&k_wait);
787 }
788 return 0;
789}
790#endif /* CONFIG_WIMAX_GDM72XX_K_MODE */
791
792static struct usb_driver gdm_usb_driver = {
793 .name = "gdm_wimax",
794 .probe = gdm_usb_probe,
795 .disconnect = gdm_usb_disconnect,
796 .id_table = id_table,
797#ifdef CONFIG_WIMAX_GDM72XX_USB_PM
798 .supports_autosuspend = 1,
799 .suspend = gdm_suspend,
800 .resume = gdm_resume,
801 .reset_resume = gdm_resume,
802#endif
803};
804
805static int __init usb_gdm_wimax_init(void)
806{
807#ifdef CONFIG_WIMAX_GDM72XX_K_MODE
Adnan Aliff5e4a12012-05-31 11:32:48 +0100808 kthread_run(k_mode_thread, NULL, "WiMax_thread");
Sage Ahn247e9cf2012-05-15 13:20:36 +0900809#endif /* CONFIG_WIMAX_GDM72XX_K_MODE */
810 return usb_register(&gdm_usb_driver);
811}
812
813static void __exit usb_gdm_wimax_exit(void)
814{
815#ifdef CONFIG_WIMAX_GDM72XX_K_MODE
816 k_mode_stop = 1;
817 wake_up(&k_wait);
818#endif
819 usb_deregister(&gdm_usb_driver);
820}
821
822module_init(usb_gdm_wimax_init);
823module_exit(usb_gdm_wimax_exit);
824
825MODULE_VERSION(DRIVER_VERSION);
826MODULE_DESCRIPTION("GCT WiMax Device Driver");
827MODULE_AUTHOR("Ethan Park");
828MODULE_LICENSE("GPL");