blob: 16e497d9d0cf424de81f40d7baca97d5a74493a8 [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
Michalis Pappasac1a3bf2014-05-09 18:08:28 +080030
Sage Ahn247e9cf2012-05-15 13:20:36 +090031#if defined(CONFIG_WIMAX_GDM72XX_WIMAX2)
Macpaul Lin0d660022012-09-12 17:49:24 +080032#define RX_BUF_SIZE (128*1024) /* For packet aggregation */
Sage Ahn247e9cf2012-05-15 13:20:36 +090033#else
Macpaul Lin0d660022012-09-12 17:49:24 +080034#define RX_BUF_SIZE 2048
Sage Ahn247e9cf2012-05-15 13:20:36 +090035#endif
36
37#define GDM7205_PADDING 256
38
Macpaul Lin0d660022012-09-12 17:49:24 +080039#define DOWNLOAD_CONF_VALUE 0x21
Sage Ahn247e9cf2012-05-15 13:20:36 +090040
41#ifdef CONFIG_WIMAX_GDM72XX_K_MODE
42
43static DECLARE_WAIT_QUEUE_HEAD(k_wait);
44static LIST_HEAD(k_list);
45static DEFINE_SPINLOCK(k_lock);
46static int k_mode_stop;
47
Macpaul Lin0d660022012-09-12 17:49:24 +080048#define K_WAIT_TIME (2 * HZ / 100)
Sage Ahn247e9cf2012-05-15 13:20:36 +090049
50#endif /* CONFIG_WIMAX_GDM72XX_K_MODE */
51
Sage Ahn247e9cf2012-05-15 13:20:36 +090052static struct usb_tx *alloc_tx_struct(struct tx_cxt *tx)
53{
Ben Chan129575f2012-09-12 11:43:41 -070054 struct usb_tx *t = kzalloc(sizeof(*t), GFP_ATOMIC);
Sage Ahn247e9cf2012-05-15 13:20:36 +090055
Ben Chan129575f2012-09-12 11:43:41 -070056 if (!t)
57 return NULL;
Sage Ahn247e9cf2012-05-15 13:20:36 +090058
Sage Ahn247e9cf2012-05-15 13:20:36 +090059 t->urb = usb_alloc_urb(0, GFP_ATOMIC);
60 t->buf = kmalloc(TX_BUF_SIZE, GFP_ATOMIC);
Ben Chan129575f2012-09-12 11:43:41 -070061 if (!t->urb || !t->buf) {
62 usb_free_urb(t->urb);
63 kfree(t->buf);
64 kfree(t);
65 return NULL;
66 }
Sage Ahn247e9cf2012-05-15 13:20:36 +090067
68 t->tx_cxt = tx;
69
70 return t;
Sage Ahn247e9cf2012-05-15 13:20:36 +090071}
72
73static void free_tx_struct(struct usb_tx *t)
74{
75 if (t) {
76 usb_free_urb(t->urb);
77 kfree(t->buf);
78 kfree(t);
79 }
80}
81
82static struct usb_rx *alloc_rx_struct(struct rx_cxt *rx)
83{
Ben Chan129575f2012-09-12 11:43:41 -070084 struct usb_rx *r = kzalloc(sizeof(*r), GFP_ATOMIC);
Sage Ahn247e9cf2012-05-15 13:20:36 +090085
Ben Chan129575f2012-09-12 11:43:41 -070086 if (!r)
87 return NULL;
Sage Ahn247e9cf2012-05-15 13:20:36 +090088
89 r->urb = usb_alloc_urb(0, GFP_ATOMIC);
90 r->buf = kmalloc(RX_BUF_SIZE, GFP_ATOMIC);
Ben Chan129575f2012-09-12 11:43:41 -070091 if (!r->urb || !r->buf) {
Sage Ahn247e9cf2012-05-15 13:20:36 +090092 usb_free_urb(r->urb);
93 kfree(r->buf);
94 kfree(r);
Ben Chan129575f2012-09-12 11:43:41 -070095 return NULL;
Sage Ahn247e9cf2012-05-15 13:20:36 +090096 }
Ben Chan129575f2012-09-12 11:43:41 -070097
98 r->rx_cxt = rx;
99 return r;
Sage Ahn247e9cf2012-05-15 13:20:36 +0900100}
101
102static void free_rx_struct(struct usb_rx *r)
103{
104 if (r) {
105 usb_free_urb(r->urb);
106 kfree(r->buf);
107 kfree(r);
108 }
109}
110
111/* Before this function is called, spin lock should be locked. */
112static struct usb_tx *get_tx_struct(struct tx_cxt *tx, int *no_spc)
113{
114 struct usb_tx *t;
115
116 if (list_empty(&tx->free_list)) {
117 *no_spc = 1;
118 return NULL;
119 }
120
121 t = list_entry(tx->free_list.next, struct usb_tx, list);
122 list_del(&t->list);
123
124 *no_spc = list_empty(&tx->free_list) ? 1 : 0;
125
126 return t;
127}
128
129/* Before this function is called, spin lock should be locked. */
130static void put_tx_struct(struct tx_cxt *tx, struct usb_tx *t)
131{
132 list_add_tail(&t->list, &tx->free_list);
133}
134
135/* Before this function is called, spin lock should be locked. */
136static struct usb_rx *get_rx_struct(struct rx_cxt *rx)
137{
138 struct usb_rx *r;
139
140 if (list_empty(&rx->free_list)) {
141 r = alloc_rx_struct(rx);
Sudip Mukherjeec32bb252015-09-07 18:08:22 +0530142 if (!r)
Sage Ahn247e9cf2012-05-15 13:20:36 +0900143 return NULL;
144
145 list_add(&r->list, &rx->free_list);
146 }
147
148 r = list_entry(rx->free_list.next, struct usb_rx, list);
Wei Yongjune5d2cb42012-09-05 14:49:15 +0800149 list_move_tail(&r->list, &rx->used_list);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900150
151 return r;
152}
153
154/* Before this function is called, spin lock should be locked. */
155static void put_rx_struct(struct rx_cxt *rx, struct usb_rx *r)
156{
Wei Yongjun73295fe2012-09-06 12:36:49 +0800157 list_move(&r->list, &rx->free_list);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900158}
159
Michalis Pappas1aa8ae72014-07-09 20:44:18 +0100160static void release_usb(struct usbwm_dev *udev)
161{
162 struct tx_cxt *tx = &udev->tx;
163 struct rx_cxt *rx = &udev->rx;
164 struct usb_tx *t, *t_next;
165 struct usb_rx *r, *r_next;
166 unsigned long flags;
167
168 spin_lock_irqsave(&tx->lock, flags);
169
170 list_for_each_entry_safe(t, t_next, &tx->sdu_list, list) {
171 list_del(&t->list);
172 free_tx_struct(t);
173 }
174
175 list_for_each_entry_safe(t, t_next, &tx->hci_list, list) {
176 list_del(&t->list);
177 free_tx_struct(t);
178 }
179
180 list_for_each_entry_safe(t, t_next, &tx->free_list, list) {
181 list_del(&t->list);
182 free_tx_struct(t);
183 }
184
185 spin_unlock_irqrestore(&tx->lock, flags);
186
187 spin_lock_irqsave(&rx->lock, flags);
188
189 list_for_each_entry_safe(r, r_next, &rx->free_list, list) {
190 list_del(&r->list);
191 free_rx_struct(r);
192 }
193
194 list_for_each_entry_safe(r, r_next, &rx->used_list, list) {
195 list_del(&r->list);
196 free_rx_struct(r);
197 }
198
199 spin_unlock_irqrestore(&rx->lock, flags);
200}
201
Sage Ahn247e9cf2012-05-15 13:20:36 +0900202static int init_usb(struct usbwm_dev *udev)
203{
204 int ret = 0, i;
Michalis Pappasac1a3bf2014-05-09 18:08:28 +0800205 struct tx_cxt *tx = &udev->tx;
206 struct rx_cxt *rx = &udev->rx;
207 struct usb_tx *t;
208 struct usb_rx *r;
Ben Chan1a276b82012-11-24 19:35:36 -0800209 unsigned long flags;
Sage Ahn247e9cf2012-05-15 13:20:36 +0900210
211 INIT_LIST_HEAD(&tx->free_list);
212 INIT_LIST_HEAD(&tx->sdu_list);
213 INIT_LIST_HEAD(&tx->hci_list);
214#if defined(CONFIG_WIMAX_GDM72XX_USB_PM) || defined(CONFIG_WIMAX_GDM72XX_K_MODE)
215 INIT_LIST_HEAD(&tx->pending_list);
216#endif
217
218 INIT_LIST_HEAD(&rx->free_list);
219 INIT_LIST_HEAD(&rx->used_list);
220
221 spin_lock_init(&tx->lock);
222 spin_lock_init(&rx->lock);
223
Ben Chan1a276b82012-11-24 19:35:36 -0800224 spin_lock_irqsave(&tx->lock, flags);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900225 for (i = 0; i < MAX_NR_SDU_BUF; i++) {
226 t = alloc_tx_struct(tx);
Sudip Mukherjeec32bb252015-09-07 18:08:22 +0530227 if (!t) {
Dan Carpentere143ef82012-11-29 17:17:25 +0300228 spin_unlock_irqrestore(&tx->lock, flags);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900229 ret = -ENOMEM;
230 goto fail;
231 }
232 list_add(&t->list, &tx->free_list);
233 }
Ben Chan1a276b82012-11-24 19:35:36 -0800234 spin_unlock_irqrestore(&tx->lock, flags);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900235
236 r = alloc_rx_struct(rx);
Sudip Mukherjeec32bb252015-09-07 18:08:22 +0530237 if (!r) {
Sage Ahn247e9cf2012-05-15 13:20:36 +0900238 ret = -ENOMEM;
239 goto fail;
240 }
241
Ben Chan1a276b82012-11-24 19:35:36 -0800242 spin_lock_irqsave(&rx->lock, flags);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900243 list_add(&r->list, &rx->free_list);
Ben Chan1a276b82012-11-24 19:35:36 -0800244 spin_unlock_irqrestore(&rx->lock, flags);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900245 return ret;
246
247fail:
248 release_usb(udev);
249 return ret;
250}
251
Ben Chan0c16ae72012-06-12 11:23:32 -0700252static void __gdm_usb_send_complete(struct urb *urb)
Sage Ahn247e9cf2012-05-15 13:20:36 +0900253{
254 struct usb_tx *t = urb->context;
255 struct tx_cxt *tx = t->tx_cxt;
256 u8 *pkt = t->buf;
257 u16 cmd_evt;
Sage Ahn247e9cf2012-05-15 13:20:36 +0900258
259 /* Completion by usb_unlink_urb */
260 if (urb->status == -ECONNRESET)
261 return;
262
Sage Ahn247e9cf2012-05-15 13:20:36 +0900263 if (t->callback)
264 t->callback(t->cb_data);
265
266 /* Delete from sdu list or hci list. */
267 list_del(&t->list);
268
269 cmd_evt = (pkt[0] << 8) | pkt[1];
270 if (cmd_evt == WIMAX_TX_SDU)
271 put_tx_struct(tx, t);
272 else
273 free_tx_struct(t);
Ben Chandd13c862012-06-06 23:01:26 -0700274}
275
276static void gdm_usb_send_complete(struct urb *urb)
277{
Ben Chan0c16ae72012-06-12 11:23:32 -0700278 struct usb_tx *t = urb->context;
279 struct tx_cxt *tx = t->tx_cxt;
280 unsigned long flags;
Ben Chandd13c862012-06-06 23:01:26 -0700281
Ben Chan0c16ae72012-06-12 11:23:32 -0700282 spin_lock_irqsave(&tx->lock, flags);
283 __gdm_usb_send_complete(urb);
284 spin_unlock_irqrestore(&tx->lock, flags);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900285}
286
287static int gdm_usb_send(void *priv_dev, void *data, int len,
288 void (*cb)(void *data), void *cb_data)
289{
290 struct usbwm_dev *udev = priv_dev;
291 struct usb_device *usbdev = udev->usbdev;
292 struct tx_cxt *tx = &udev->tx;
293 struct usb_tx *t;
294 int padding = udev->padding;
295 int no_spc = 0, ret;
296 u8 *pkt = data;
297 u16 cmd_evt;
Ben Chana7e4a982012-11-26 20:18:45 -0800298 unsigned long flags;
299#ifdef CONFIG_WIMAX_GDM72XX_K_MODE
300 unsigned long flags2;
301#endif /* CONFIG_WIMAX_GDM72XX_K_MODE */
Sage Ahn247e9cf2012-05-15 13:20:36 +0900302
303 if (!udev->usbdev) {
YAMANE Toshiakia7d46832012-10-29 20:05:43 +0900304 dev_err(&usbdev->dev, "%s: No such device\n", __func__);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900305 return -ENODEV;
306 }
307
Ben Chan0fbce842014-06-27 23:17:24 -0700308 if (len > TX_BUF_SIZE - padding - 1)
309 return -EINVAL;
Sage Ahn247e9cf2012-05-15 13:20:36 +0900310
311 spin_lock_irqsave(&tx->lock, flags);
312
313 cmd_evt = (pkt[0] << 8) | pkt[1];
314 if (cmd_evt == WIMAX_TX_SDU) {
315 t = get_tx_struct(tx, &no_spc);
Sudip Mukherjeec32bb252015-09-07 18:08:22 +0530316 if (!t) {
Sage Ahn247e9cf2012-05-15 13:20:36 +0900317 /* This case must not happen. */
318 spin_unlock_irqrestore(&tx->lock, flags);
319 return -ENOSPC;
320 }
321 list_add_tail(&t->list, &tx->sdu_list);
322 } else {
323 t = alloc_tx_struct(tx);
Sudip Mukherjeec32bb252015-09-07 18:08:22 +0530324 if (!t) {
Sage Ahn247e9cf2012-05-15 13:20:36 +0900325 spin_unlock_irqrestore(&tx->lock, flags);
326 return -ENOMEM;
327 }
328 list_add_tail(&t->list, &tx->hci_list);
329 }
330
331 memcpy(t->buf + padding, data, len);
332 t->callback = cb;
333 t->cb_data = cb_data;
334
Ben Chane7d374e2014-06-24 00:55:58 -0700335 /* In some cases, USB Module of WiMax is blocked when data size is
Sage Ahn247e9cf2012-05-15 13:20:36 +0900336 * the multiple of 512. So, increment length by one in that case.
337 */
338 if ((len % 512) == 0)
339 len++;
340
Michalis Pappas39c511f2014-05-09 18:08:27 +0800341 usb_fill_bulk_urb(t->urb, usbdev, usb_sndbulkpipe(usbdev, 1), t->buf,
342 len + padding, gdm_usb_send_complete, t);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900343
Michalis Pappasf5439c62014-07-17 17:09:39 +0100344 dev_dbg(&usbdev->dev, "usb_send: %*ph\n", len + padding, t->buf);
345
Sage Ahn247e9cf2012-05-15 13:20:36 +0900346#ifdef CONFIG_WIMAX_GDM72XX_USB_PM
347 if (usbdev->state & USB_STATE_SUSPENDED) {
348 list_add_tail(&t->p_list, &tx->pending_list);
349 schedule_work(&udev->pm_ws);
350 goto out;
351 }
352#endif /* CONFIG_WIMAX_GDM72XX_USB_PM */
353
354#ifdef CONFIG_WIMAX_GDM72XX_K_MODE
355 if (udev->bw_switch) {
356 list_add_tail(&t->p_list, &tx->pending_list);
357 goto out;
358 } else if (cmd_evt == WIMAX_SCAN) {
359 struct rx_cxt *rx;
360 struct usb_rx *r;
361
362 rx = &udev->rx;
363
Ben Chan1a276b82012-11-24 19:35:36 -0800364 spin_lock_irqsave(&rx->lock, flags2);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900365 list_for_each_entry(r, &rx->used_list, list)
366 usb_unlink_urb(r->urb);
Ben Chan1a276b82012-11-24 19:35:36 -0800367 spin_unlock_irqrestore(&rx->lock, flags2);
368
Sage Ahn247e9cf2012-05-15 13:20:36 +0900369 udev->bw_switch = 1;
370
Ben Chan1a276b82012-11-24 19:35:36 -0800371 spin_lock_irqsave(&k_lock, flags2);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900372 list_add_tail(&udev->list, &k_list);
Ben Chan1a276b82012-11-24 19:35:36 -0800373 spin_unlock_irqrestore(&k_lock, flags2);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900374
375 wake_up(&k_wait);
376 }
377#endif /* CONFIG_WIMAX_GDM72XX_K_MODE */
378
379 ret = usb_submit_urb(t->urb, GFP_ATOMIC);
380 if (ret)
381 goto send_fail;
382
383#ifdef CONFIG_WIMAX_GDM72XX_USB_PM
384 usb_mark_last_busy(usbdev);
385#endif /* CONFIG_WIMAX_GDM72XX_USB_PM */
386
387#if defined(CONFIG_WIMAX_GDM72XX_USB_PM) || defined(CONFIG_WIMAX_GDM72XX_K_MODE)
388out:
389#endif
390 spin_unlock_irqrestore(&tx->lock, flags);
391
392 if (no_spc)
393 return -ENOSPC;
394
395 return 0;
396
397send_fail:
398 t->callback = NULL;
Ben Chan0c16ae72012-06-12 11:23:32 -0700399 __gdm_usb_send_complete(t->urb);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900400 spin_unlock_irqrestore(&tx->lock, flags);
401 return ret;
402}
403
404static void gdm_usb_rcv_complete(struct urb *urb)
405{
406 struct usb_rx *r = urb->context;
407 struct rx_cxt *rx = r->rx_cxt;
408 struct usbwm_dev *udev = container_of(r->rx_cxt, struct usbwm_dev, rx);
409 struct tx_cxt *tx = &udev->tx;
410 struct usb_tx *t;
411 u16 cmd_evt;
Ben Chan1a276b82012-11-24 19:35:36 -0800412 unsigned long flags, flags2;
Sage Ahn247e9cf2012-05-15 13:20:36 +0900413 struct usb_device *dev = urb->dev;
Sage Ahn247e9cf2012-05-15 13:20:36 +0900414
415 /* Completion by usb_unlink_urb */
416 if (urb->status == -ECONNRESET)
417 return;
418
419 spin_lock_irqsave(&tx->lock, flags);
420
421 if (!urb->status) {
422 cmd_evt = (r->buf[0] << 8) | (r->buf[1]);
Michalis Pappasf5439c62014-07-17 17:09:39 +0100423
424 dev_dbg(&dev->dev, "usb_receive: %*ph\n", urb->actual_length,
425 r->buf);
426
Sage Ahn247e9cf2012-05-15 13:20:36 +0900427 if (cmd_evt == WIMAX_SDU_TX_FLOW) {
428 if (r->buf[4] == 0) {
Kristina Martšenko8943a922014-03-15 01:10:05 +0200429 dev_dbg(&dev->dev, "WIMAX ==> STOP SDU TX\n");
Sage Ahn247e9cf2012-05-15 13:20:36 +0900430 list_for_each_entry(t, &tx->sdu_list, list)
431 usb_unlink_urb(t->urb);
432 } else if (r->buf[4] == 1) {
Kristina Martšenko8943a922014-03-15 01:10:05 +0200433 dev_dbg(&dev->dev, "WIMAX ==> START SDU TX\n");
Sage Ahn247e9cf2012-05-15 13:20:36 +0900434 list_for_each_entry(t, &tx->sdu_list, list) {
435 usb_submit_urb(t->urb, GFP_ATOMIC);
436 }
Ben Chane7d374e2014-06-24 00:55:58 -0700437 /* If free buffer for sdu tx doesn't
Sage Ahn247e9cf2012-05-15 13:20:36 +0900438 * exist, then tx queue should not be
439 * woken. For this reason, don't pass
440 * the command, START_SDU_TX.
441 */
442 if (list_empty(&tx->free_list))
443 urb->actual_length = 0;
444 }
445 }
446 }
447
448 if (!urb->status && r->callback)
449 r->callback(r->cb_data, r->buf, urb->actual_length);
450
Ben Chan1a276b82012-11-24 19:35:36 -0800451 spin_lock_irqsave(&rx->lock, flags2);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900452 put_rx_struct(rx, r);
Ben Chan1a276b82012-11-24 19:35:36 -0800453 spin_unlock_irqrestore(&rx->lock, flags2);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900454
455 spin_unlock_irqrestore(&tx->lock, flags);
456
457#ifdef CONFIG_WIMAX_GDM72XX_USB_PM
458 usb_mark_last_busy(dev);
459#endif
460}
461
462static int gdm_usb_receive(void *priv_dev,
Michalis Pappas39c511f2014-05-09 18:08:27 +0800463 void (*cb)(void *cb_data, void *data, int len),
464 void *cb_data)
Sage Ahn247e9cf2012-05-15 13:20:36 +0900465{
466 struct usbwm_dev *udev = priv_dev;
467 struct usb_device *usbdev = udev->usbdev;
468 struct rx_cxt *rx = &udev->rx;
469 struct usb_rx *r;
470 unsigned long flags;
471
472 if (!udev->usbdev) {
YAMANE Toshiakia7d46832012-10-29 20:05:43 +0900473 dev_err(&usbdev->dev, "%s: No such device\n", __func__);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900474 return -ENODEV;
475 }
476
477 spin_lock_irqsave(&rx->lock, flags);
478 r = get_rx_struct(rx);
479 spin_unlock_irqrestore(&rx->lock, flags);
480
Sudip Mukherjeec32bb252015-09-07 18:08:22 +0530481 if (!r)
Sage Ahn247e9cf2012-05-15 13:20:36 +0900482 return -ENOMEM;
483
484 r->callback = cb;
485 r->cb_data = cb_data;
486
Michalis Pappas39c511f2014-05-09 18:08:27 +0800487 usb_fill_bulk_urb(r->urb, usbdev, usb_rcvbulkpipe(usbdev, 0x82), r->buf,
488 RX_BUF_SIZE, gdm_usb_rcv_complete, r);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900489
490 return usb_submit_urb(r->urb, GFP_ATOMIC);
491}
492
493#ifdef CONFIG_WIMAX_GDM72XX_USB_PM
494static void do_pm_control(struct work_struct *work)
495{
496 struct usbwm_dev *udev = container_of(work, struct usbwm_dev, pm_ws);
497 struct tx_cxt *tx = &udev->tx;
498 int ret;
499 unsigned long flags;
500
501 ret = usb_autopm_get_interface(udev->intf);
502 if (!ret)
503 usb_autopm_put_interface(udev->intf);
504
505 spin_lock_irqsave(&tx->lock, flags);
Michalis Pappas522c6ff2014-05-09 18:08:23 +0800506 if (!(udev->usbdev->state & USB_STATE_SUSPENDED) &&
Michalis Pappas39c511f2014-05-09 18:08:27 +0800507 (!list_empty(&tx->hci_list) || !list_empty(&tx->sdu_list))) {
Sage Ahn247e9cf2012-05-15 13:20:36 +0900508 struct usb_tx *t, *temp;
509
510 list_for_each_entry_safe(t, temp, &tx->pending_list, p_list) {
511 list_del(&t->p_list);
512 ret = usb_submit_urb(t->urb, GFP_ATOMIC);
513
514 if (ret) {
515 t->callback = NULL;
Ben Chan0c16ae72012-06-12 11:23:32 -0700516 __gdm_usb_send_complete(t->urb);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900517 }
518 }
519 }
520 spin_unlock_irqrestore(&tx->lock, flags);
521}
522#endif /* CONFIG_WIMAX_GDM72XX_USB_PM */
523
Davide Gianfortea3709f72014-05-23 22:06:44 +0200524static int gdm_usb_probe(struct usb_interface *intf,
525 const struct usb_device_id *id)
Sage Ahn247e9cf2012-05-15 13:20:36 +0900526{
527 int ret = 0;
528 u8 bConfigurationValue;
529 struct phy_dev *phy_dev = NULL;
530 struct usbwm_dev *udev = NULL;
531 u16 idVendor, idProduct, bcdDevice;
532
533 struct usb_device *usbdev = interface_to_usbdev(intf);
534
535 usb_get_dev(usbdev);
536 bConfigurationValue = usbdev->actconfig->desc.bConfigurationValue;
537
538 /*USB description is set up with Little-Endian*/
Ben Chana8a175d2014-06-30 23:32:27 -0700539 idVendor = le16_to_cpu(usbdev->descriptor.idVendor);
540 idProduct = le16_to_cpu(usbdev->descriptor.idProduct);
541 bcdDevice = le16_to_cpu(usbdev->descriptor.bcdDevice);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900542
YAMANE Toshiakia7d46832012-10-29 20:05:43 +0900543 dev_info(&intf->dev, "Found GDM USB VID = 0x%04x PID = 0x%04x...\n",
544 idVendor, idProduct);
545 dev_info(&intf->dev, "GCT WiMax driver version %s\n", DRIVER_VERSION);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900546
547
548 if (idProduct == EMERGENCY_PID) {
549 ret = usb_emergency(usbdev);
550 goto out;
551 }
552
553 /* Support for EEPROM bootloader */
Davide Gianfortea3709f72014-05-23 22:06:44 +0200554 if (bConfigurationValue == DOWNLOAD_CONF_VALUE ||
555 idProduct & B_DOWNLOAD) {
Sage Ahn247e9cf2012-05-15 13:20:36 +0900556 ret = usb_boot(usbdev, bcdDevice);
557 goto out;
558 }
559
Devendra Naga7fc03ad2012-07-12 11:56:54 +0545560 phy_dev = kzalloc(sizeof(*phy_dev), GFP_KERNEL);
Sudip Mukherjeec32bb252015-09-07 18:08:22 +0530561 if (!phy_dev) {
Sage Ahn247e9cf2012-05-15 13:20:36 +0900562 ret = -ENOMEM;
563 goto out;
564 }
Devendra Naga7fc03ad2012-07-12 11:56:54 +0545565 udev = kzalloc(sizeof(*udev), GFP_KERNEL);
Sudip Mukherjeec32bb252015-09-07 18:08:22 +0530566 if (!udev) {
Sage Ahn247e9cf2012-05-15 13:20:36 +0900567 ret = -ENOMEM;
568 goto out;
569 }
570
Sage Ahn247e9cf2012-05-15 13:20:36 +0900571 if (idProduct == 0x7205 || idProduct == 0x7206)
572 udev->padding = GDM7205_PADDING;
573 else
574 udev->padding = 0;
575
576 phy_dev->priv_dev = (void *)udev;
577 phy_dev->send_func = gdm_usb_send;
578 phy_dev->rcv_func = gdm_usb_receive;
579
580 ret = init_usb(udev);
581 if (ret < 0)
582 goto out;
583
584 udev->usbdev = usbdev;
585
586#ifdef CONFIG_WIMAX_GDM72XX_USB_PM
587 udev->intf = intf;
588
589 intf->needs_remote_wakeup = 1;
590 device_init_wakeup(&intf->dev, 1);
591
592 pm_runtime_set_autosuspend_delay(&usbdev->dev, 10 * 1000); /* msec */
593
594 INIT_WORK(&udev->pm_ws, do_pm_control);
595#endif /* CONFIG_WIMAX_GDM72XX_USB_PM */
596
Paul Stewart54bc1ff2012-05-17 11:15:10 -0700597 ret = register_wimax_device(phy_dev, &intf->dev);
Alexey Khoroshilovd3a874e2014-02-06 01:47:13 +0100598 if (ret)
599 release_usb(udev);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900600
601out:
602 if (ret) {
603 kfree(phy_dev);
604 kfree(udev);
Alexey Khoroshilovd3a874e2014-02-06 01:47:13 +0100605 usb_put_dev(usbdev);
Ben Chan1a276b82012-11-24 19:35:36 -0800606 } else {
607 usb_set_intfdata(intf, phy_dev);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900608 }
Sage Ahn247e9cf2012-05-15 13:20:36 +0900609 return ret;
610}
611
612static void gdm_usb_disconnect(struct usb_interface *intf)
613{
614 u8 bConfigurationValue;
615 struct phy_dev *phy_dev;
616 struct usbwm_dev *udev;
617 u16 idProduct;
618 struct usb_device *usbdev = interface_to_usbdev(intf);
619
620 bConfigurationValue = usbdev->actconfig->desc.bConfigurationValue;
621 phy_dev = usb_get_intfdata(intf);
622
623 /*USB description is set up with Little-Endian*/
Ben Chana8a175d2014-06-30 23:32:27 -0700624 idProduct = le16_to_cpu(usbdev->descriptor.idProduct);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900625
626 if (idProduct != EMERGENCY_PID &&
Davide Gianfortea3709f72014-05-23 22:06:44 +0200627 bConfigurationValue != DOWNLOAD_CONF_VALUE &&
628 (idProduct & B_DOWNLOAD) == 0) {
Sage Ahn247e9cf2012-05-15 13:20:36 +0900629 udev = phy_dev->priv_dev;
630 udev->usbdev = NULL;
631
632 unregister_wimax_device(phy_dev);
633 release_usb(udev);
634 kfree(udev);
635 kfree(phy_dev);
636 }
637
638 usb_put_dev(usbdev);
639}
640
641#ifdef CONFIG_WIMAX_GDM72XX_USB_PM
642static int gdm_suspend(struct usb_interface *intf, pm_message_t pm_msg)
643{
644 struct phy_dev *phy_dev;
645 struct usbwm_dev *udev;
646 struct rx_cxt *rx;
647 struct usb_rx *r;
Ben Chan1a276b82012-11-24 19:35:36 -0800648 unsigned long flags;
Sage Ahn247e9cf2012-05-15 13:20:36 +0900649
650 phy_dev = usb_get_intfdata(intf);
Ben Chan1a276b82012-11-24 19:35:36 -0800651 if (!phy_dev)
652 return 0;
653
Sage Ahn247e9cf2012-05-15 13:20:36 +0900654 udev = phy_dev->priv_dev;
655 rx = &udev->rx;
656
Ben Chan1a276b82012-11-24 19:35:36 -0800657 spin_lock_irqsave(&rx->lock, flags);
658
Sage Ahn247e9cf2012-05-15 13:20:36 +0900659 list_for_each_entry(r, &rx->used_list, list)
660 usb_unlink_urb(r->urb);
661
Ben Chan1a276b82012-11-24 19:35:36 -0800662 spin_unlock_irqrestore(&rx->lock, flags);
663
Sage Ahn247e9cf2012-05-15 13:20:36 +0900664 return 0;
665}
666
667static int gdm_resume(struct usb_interface *intf)
668{
669 struct phy_dev *phy_dev;
670 struct usbwm_dev *udev;
671 struct rx_cxt *rx;
672 struct usb_rx *r;
Ben Chan1a276b82012-11-24 19:35:36 -0800673 unsigned long flags;
Sage Ahn247e9cf2012-05-15 13:20:36 +0900674
675 phy_dev = usb_get_intfdata(intf);
Ben Chan1a276b82012-11-24 19:35:36 -0800676 if (!phy_dev)
677 return 0;
678
Sage Ahn247e9cf2012-05-15 13:20:36 +0900679 udev = phy_dev->priv_dev;
680 rx = &udev->rx;
681
Ben Chan1a276b82012-11-24 19:35:36 -0800682 spin_lock_irqsave(&rx->lock, flags);
683
Sage Ahn247e9cf2012-05-15 13:20:36 +0900684 list_for_each_entry(r, &rx->used_list, list)
685 usb_submit_urb(r->urb, GFP_ATOMIC);
686
Ben Chan1a276b82012-11-24 19:35:36 -0800687 spin_unlock_irqrestore(&rx->lock, flags);
688
Sage Ahn247e9cf2012-05-15 13:20:36 +0900689 return 0;
690}
691
692#endif /* CONFIG_WIMAX_GDM72XX_USB_PM */
693
694#ifdef CONFIG_WIMAX_GDM72XX_K_MODE
695static int k_mode_thread(void *arg)
696{
697 struct usbwm_dev *udev;
698 struct tx_cxt *tx;
699 struct rx_cxt *rx;
700 struct usb_tx *t, *temp;
701 struct usb_rx *r;
702 unsigned long flags, flags2, expire;
703 int ret;
704
Sage Ahn247e9cf2012-05-15 13:20:36 +0900705 while (!k_mode_stop) {
Sage Ahn247e9cf2012-05-15 13:20:36 +0900706 spin_lock_irqsave(&k_lock, flags2);
707 while (!list_empty(&k_list)) {
Sage Ahn247e9cf2012-05-15 13:20:36 +0900708 udev = list_entry(k_list.next, struct usbwm_dev, list);
709 tx = &udev->tx;
710 rx = &udev->rx;
711
712 list_del(&udev->list);
713 spin_unlock_irqrestore(&k_lock, flags2);
714
715 expire = jiffies + K_WAIT_TIME;
Michalis Pappas917ab472014-05-09 18:08:21 +0800716 while (time_before(jiffies, expire))
Sage Ahn247e9cf2012-05-15 13:20:36 +0900717 schedule_timeout(K_WAIT_TIME);
718
Ben Chan1a276b82012-11-24 19:35:36 -0800719 spin_lock_irqsave(&rx->lock, flags);
720
Sage Ahn247e9cf2012-05-15 13:20:36 +0900721 list_for_each_entry(r, &rx->used_list, list)
722 usb_submit_urb(r->urb, GFP_ATOMIC);
723
Ben Chan1a276b82012-11-24 19:35:36 -0800724 spin_unlock_irqrestore(&rx->lock, flags);
725
Sage Ahn247e9cf2012-05-15 13:20:36 +0900726 spin_lock_irqsave(&tx->lock, flags);
727
Davide Gianfortea3709f72014-05-23 22:06:44 +0200728 list_for_each_entry_safe(t, temp, &tx->pending_list,
729 p_list) {
Sage Ahn247e9cf2012-05-15 13:20:36 +0900730 list_del(&t->p_list);
731 ret = usb_submit_urb(t->urb, GFP_ATOMIC);
732
733 if (ret) {
734 t->callback = NULL;
Ben Chan0c16ae72012-06-12 11:23:32 -0700735 __gdm_usb_send_complete(t->urb);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900736 }
737 }
738
739 udev->bw_switch = 0;
740 spin_unlock_irqrestore(&tx->lock, flags);
741
742 spin_lock_irqsave(&k_lock, flags2);
743 }
Arnd Bergmann4b266e52014-01-02 13:07:34 +0100744 wait_event_interruptible_lock_irq(k_wait,
Davide Gianfortea3709f72014-05-23 22:06:44 +0200745 !list_empty(&k_list) ||
746 k_mode_stop, k_lock);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900747 spin_unlock_irqrestore(&k_lock, flags2);
Sage Ahn247e9cf2012-05-15 13:20:36 +0900748 }
749 return 0;
750}
751#endif /* CONFIG_WIMAX_GDM72XX_K_MODE */
752
753static struct usb_driver gdm_usb_driver = {
754 .name = "gdm_wimax",
755 .probe = gdm_usb_probe,
756 .disconnect = gdm_usb_disconnect,
757 .id_table = id_table,
758#ifdef CONFIG_WIMAX_GDM72XX_USB_PM
759 .supports_autosuspend = 1,
760 .suspend = gdm_suspend,
761 .resume = gdm_resume,
762 .reset_resume = gdm_resume,
763#endif
764};
765
766static int __init usb_gdm_wimax_init(void)
767{
768#ifdef CONFIG_WIMAX_GDM72XX_K_MODE
Al Viroc4144672012-10-02 16:34:38 -0400769 kthread_run(k_mode_thread, NULL, "k_mode_wimax");
Sage Ahn247e9cf2012-05-15 13:20:36 +0900770#endif /* CONFIG_WIMAX_GDM72XX_K_MODE */
771 return usb_register(&gdm_usb_driver);
772}
773
774static void __exit usb_gdm_wimax_exit(void)
775{
776#ifdef CONFIG_WIMAX_GDM72XX_K_MODE
777 k_mode_stop = 1;
778 wake_up(&k_wait);
779#endif
780 usb_deregister(&gdm_usb_driver);
781}
782
783module_init(usb_gdm_wimax_init);
784module_exit(usb_gdm_wimax_exit);
785
786MODULE_VERSION(DRIVER_VERSION);
787MODULE_DESCRIPTION("GCT WiMax Device Driver");
788MODULE_AUTHOR("Ethan Park");
789MODULE_LICENSE("GPL");