Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
usb_intf.c
Go to the documentation of this file.
1 /******************************************************************************
2  * usb_intf.c
3  *
4  * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
5  * Linux device driver for RTL8192SU
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of version 2 of the GNU General Public License as
9  * published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14  * more details.
15  *
16  * You should have received a copy of the GNU General Public License along with
17  * this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19  *
20  * Modifications for inclusion into the Linux staging tree are
21  * Copyright(c) 2010 Larry Finger. All rights reserved.
22  *
23  * Contact information:
24  * WLAN FAE <[email protected]>
25  * Larry Finger <[email protected]>
26  *
27  ******************************************************************************/
28 
29 #define _HCI_INTF_C_
30 
31 #include <linux/usb.h>
32 #include <linux/module.h>
33 #include <linux/firmware.h>
34 
35 #include "osdep_service.h"
36 #include "drv_types.h"
37 #include "recv_osdep.h"
38 #include "xmit_osdep.h"
39 #include "rtl8712_efuse.h"
40 #include "usb_ops.h"
41 #include "usb_osintf.h"
42 
43 static struct usb_interface *pintf;
44 
45 static int r871xu_drv_init(struct usb_interface *pusb_intf,
46  const struct usb_device_id *pdid);
47 
48 static void r871xu_dev_remove(struct usb_interface *pusb_intf);
49 
50 static struct usb_device_id rtl871x_usb_id_tbl[] = {
51 
52 /* RTL8188SU */
53  /* Realtek */
54  {USB_DEVICE(0x0BDA, 0x8171)},
55  {USB_DEVICE(0x0bda, 0x8173)},
56  {USB_DEVICE(0x0bda, 0x8712)},
57  {USB_DEVICE(0x0bda, 0x8713)},
58  {USB_DEVICE(0x0bda, 0xC512)},
59  /* Abocom */
60  {USB_DEVICE(0x07B8, 0x8188)},
61  /* ASUS */
62  {USB_DEVICE(0x0B05, 0x1786)},
63  {USB_DEVICE(0x0B05, 0x1791)}, /* 11n mode disable */
64  /* Belkin */
65  {USB_DEVICE(0x050D, 0x945A)},
66  /* Corega */
67  {USB_DEVICE(0x07AA, 0x0047)},
68  /* D-Link */
69  {USB_DEVICE(0x2001, 0x3306)},
70  {USB_DEVICE(0x07D1, 0x3306)}, /* 11n mode disable */
71  /* Edimax */
72  {USB_DEVICE(0x7392, 0x7611)},
73  /* EnGenius */
74  {USB_DEVICE(0x1740, 0x9603)},
75  /* Hawking */
76  {USB_DEVICE(0x0E66, 0x0016)},
77  /* Hercules */
78  {USB_DEVICE(0x06F8, 0xE034)},
79  {USB_DEVICE(0x06F8, 0xE032)},
80  /* Logitec */
81  {USB_DEVICE(0x0789, 0x0167)},
82  /* PCI */
83  {USB_DEVICE(0x2019, 0xAB28)},
84  {USB_DEVICE(0x2019, 0xED16)},
85  /* Sitecom */
86  {USB_DEVICE(0x0DF6, 0x0057)},
87  {USB_DEVICE(0x0DF6, 0x0045)},
88  {USB_DEVICE(0x0DF6, 0x0059)}, /* 11n mode disable */
89  {USB_DEVICE(0x0DF6, 0x004B)},
90  {USB_DEVICE(0x0DF6, 0x005B)},
91  {USB_DEVICE(0x0DF6, 0x005D)},
92  {USB_DEVICE(0x0DF6, 0x0063)},
93  /* Sweex */
94  {USB_DEVICE(0x177F, 0x0154)},
95  /* Thinkware */
96  {USB_DEVICE(0x0BDA, 0x5077)},
97  /* Toshiba */
98  {USB_DEVICE(0x1690, 0x0752)},
99  /* - */
100  {USB_DEVICE(0x20F4, 0x646B)},
101  {USB_DEVICE(0x083A, 0xC512)},
102  {USB_DEVICE(0x25D4, 0x4CA1)},
103  {USB_DEVICE(0x25D4, 0x4CAB)},
104 
105 /* RTL8191SU */
106  /* Realtek */
107  {USB_DEVICE(0x0BDA, 0x8172)},
108  {USB_DEVICE(0x0BDA, 0x8192)},
109  /* Amigo */
110  {USB_DEVICE(0x0EB0, 0x9061)},
111  /* ASUS/EKB */
112  {USB_DEVICE(0x13D3, 0x3323)},
113  {USB_DEVICE(0x13D3, 0x3311)}, /* 11n mode disable */
114  {USB_DEVICE(0x13D3, 0x3342)},
115  /* ASUS/EKBLenovo */
116  {USB_DEVICE(0x13D3, 0x3333)},
117  {USB_DEVICE(0x13D3, 0x3334)},
118  {USB_DEVICE(0x13D3, 0x3335)}, /* 11n mode disable */
119  {USB_DEVICE(0x13D3, 0x3336)}, /* 11n mode disable */
120  /* ASUS/Media BOX */
121  {USB_DEVICE(0x13D3, 0x3309)},
122  /* Belkin */
123  {USB_DEVICE(0x050D, 0x815F)},
124  /* D-Link */
125  {USB_DEVICE(0x07D1, 0x3302)},
126  {USB_DEVICE(0x07D1, 0x3300)},
127  {USB_DEVICE(0x07D1, 0x3303)},
128  /* Edimax */
129  {USB_DEVICE(0x7392, 0x7612)},
130  /* EnGenius */
131  {USB_DEVICE(0x1740, 0x9605)},
132  /* Guillemot */
133  {USB_DEVICE(0x06F8, 0xE031)},
134  /* Hawking */
135  {USB_DEVICE(0x0E66, 0x0015)},
136  /* Mediao */
137  {USB_DEVICE(0x13D3, 0x3306)},
138  /* PCI */
139  {USB_DEVICE(0x2019, 0xED18)},
140  {USB_DEVICE(0x2019, 0x4901)},
141  /* Sitecom */
142  {USB_DEVICE(0x0DF6, 0x0058)},
143  {USB_DEVICE(0x0DF6, 0x0049)},
144  {USB_DEVICE(0x0DF6, 0x004C)},
145  {USB_DEVICE(0x0DF6, 0x0064)},
146  /* Skyworth */
147  {USB_DEVICE(0x14b2, 0x3300)},
148  {USB_DEVICE(0x14b2, 0x3301)},
149  {USB_DEVICE(0x14B2, 0x3302)},
150  /* - */
151  {USB_DEVICE(0x04F2, 0xAFF2)},
152  {USB_DEVICE(0x04F2, 0xAFF5)},
153  {USB_DEVICE(0x04F2, 0xAFF6)},
154  {USB_DEVICE(0x13D3, 0x3339)},
155  {USB_DEVICE(0x13D3, 0x3340)}, /* 11n mode disable */
156  {USB_DEVICE(0x13D3, 0x3341)}, /* 11n mode disable */
157  {USB_DEVICE(0x13D3, 0x3310)},
158  {USB_DEVICE(0x13D3, 0x3325)},
159 
160 /* RTL8192SU */
161  /* Realtek */
162  {USB_DEVICE(0x0BDA, 0x8174)},
163  /* Belkin */
164  {USB_DEVICE(0x050D, 0x845A)},
165  /* Corega */
166  {USB_DEVICE(0x07AA, 0x0051)},
167  /* Edimax */
168  {USB_DEVICE(0x7392, 0x7622)},
169  /* NEC */
170  {USB_DEVICE(0x0409, 0x02B6)},
171  {}
172 };
173 
174 MODULE_DEVICE_TABLE(usb, rtl871x_usb_id_tbl);
175 
176 static struct specific_device_id specific_device_id_tbl[] = {
177  {.idVendor = 0x0b05, .idProduct = 0x1791,
178  .flags = SPEC_DEV_ID_DISABLE_HT},
179  {.idVendor = 0x0df6, .idProduct = 0x0059,
180  .flags = SPEC_DEV_ID_DISABLE_HT},
181  {.idVendor = 0x13d3, .idProduct = 0x3306,
182  .flags = SPEC_DEV_ID_DISABLE_HT},
183  {.idVendor = 0x13D3, .idProduct = 0x3311,
184  .flags = SPEC_DEV_ID_DISABLE_HT},
185  {.idVendor = 0x13d3, .idProduct = 0x3335,
186  .flags = SPEC_DEV_ID_DISABLE_HT},
187  {.idVendor = 0x13d3, .idProduct = 0x3336,
188  .flags = SPEC_DEV_ID_DISABLE_HT},
189  {.idVendor = 0x13d3, .idProduct = 0x3340,
190  .flags = SPEC_DEV_ID_DISABLE_HT},
191  {.idVendor = 0x13d3, .idProduct = 0x3341,
192  .flags = SPEC_DEV_ID_DISABLE_HT},
193  {}
194 };
195 
196 struct drv_priv {
197  struct usb_driver r871xu_drv;
199 };
200 
201 #ifdef CONFIG_PM
202 static int r871x_suspend(struct usb_interface *pusb_intf, pm_message_t state)
203 {
204  struct net_device *pnetdev = usb_get_intfdata(pusb_intf);
205 
206  printk(KERN_INFO "r8712: suspending...\n");
207  if (!pnetdev || !netif_running(pnetdev)) {
208  printk(KERN_INFO "r8712: unable to suspend\n");
209  return 0;
210  }
211  if (pnetdev->netdev_ops->ndo_stop)
212  pnetdev->netdev_ops->ndo_stop(pnetdev);
213  mdelay(10);
214  netif_device_detach(pnetdev);
215  return 0;
216 }
217 
218 static int r871x_resume(struct usb_interface *pusb_intf)
219 {
220  struct net_device *pnetdev = usb_get_intfdata(pusb_intf);
221 
222  printk(KERN_INFO "r8712: resuming...\n");
223  if (!pnetdev || !netif_running(pnetdev)) {
224  printk(KERN_INFO "r8712: unable to resume\n");
225  return 0;
226  }
227  netif_device_attach(pnetdev);
228  if (pnetdev->netdev_ops->ndo_open)
229  pnetdev->netdev_ops->ndo_open(pnetdev);
230  return 0;
231 }
232 
233 static int r871x_reset_resume(struct usb_interface *pusb_intf)
234 {
235  /* dummy routine */
236  return 0;
237 }
238 
239 #endif
240 
241 static struct drv_priv drvpriv = {
242  .r871xu_drv.name = "r8712u",
243  .r871xu_drv.id_table = rtl871x_usb_id_tbl,
244  .r871xu_drv.probe = r871xu_drv_init,
245  .r871xu_drv.disconnect = r871xu_dev_remove,
246 #ifdef CONFIG_PM
247  .r871xu_drv.suspend = r871x_suspend,
248  .r871xu_drv.resume = r871x_resume,
249  .r871xu_drv.reset_resume = r871x_reset_resume,
250 #endif
251 };
252 
253 static uint r8712_usb_dvobj_init(struct _adapter *padapter)
254 {
255  uint status = _SUCCESS;
256  struct usb_device_descriptor *pdev_desc;
257  struct usb_host_config *phost_conf;
258  struct usb_config_descriptor *pconf_desc;
259  struct usb_host_interface *phost_iface;
260  struct usb_interface_descriptor *piface_desc;
261  struct dvobj_priv *pdvobjpriv = &padapter->dvobjpriv;
262  struct usb_device *pusbd = pdvobjpriv->pusbdev;
263 
264  pdvobjpriv->padapter = padapter;
265  padapter->EepromAddressSize = 6;
266  pdev_desc = &pusbd->descriptor;
267  phost_conf = pusbd->actconfig;
268  pconf_desc = &phost_conf->desc;
269  phost_iface = &pintf->altsetting[0];
270  piface_desc = &phost_iface->desc;
271  pdvobjpriv->nr_endpoint = piface_desc->bNumEndpoints;
272  if (pusbd->speed == USB_SPEED_HIGH) {
273  pdvobjpriv->ishighspeed = true;
274  printk(KERN_INFO "r8712u: USB_SPEED_HIGH with %d endpoints\n",
275  pdvobjpriv->nr_endpoint);
276  } else {
277  pdvobjpriv->ishighspeed = false;
278  printk(KERN_INFO "r8712u: USB_SPEED_LOW with %d endpoints\n",
279  pdvobjpriv->nr_endpoint);
280  }
281  if ((r8712_alloc_io_queue(padapter)) == _FAIL)
282  status = _FAIL;
283  return status;
284 }
285 
286 static void r8712_usb_dvobj_deinit(struct _adapter *padapter)
287 {
288 }
289 
290 void rtl871x_intf_stop(struct _adapter *padapter)
291 {
292  /*disable_hw_interrupt*/
293  if (padapter->bSurpriseRemoved == false) {
294  /*device still exists, so driver can do i/o operation
295  * TODO: */
296  }
297 
298  /* cancel in irp */
299  if (padapter->dvobjpriv.inirp_deinit != NULL)
300  padapter->dvobjpriv.inirp_deinit(padapter);
301  /* cancel out irp */
302  r8712_usb_write_port_cancel(padapter);
303  /* TODO:cancel other irps */
304 }
305 
306 void r871x_dev_unload(struct _adapter *padapter)
307 {
308  if (padapter->bup == true) {
309  /*s1.*/
310  padapter->bDriverStopped = true;
311 
312  /*s3.*/
313  rtl871x_intf_stop(padapter);
314 
315  /*s4.*/
316  r8712_stop_drv_threads(padapter);
317 
318  /*s5.*/
319  if (padapter->bSurpriseRemoved == false) {
320  padapter->hw_init_completed = false;
321  rtl8712_hal_deinit(padapter);
322  }
323 
324  /*s6.*/
325  if (padapter->dvobj_deinit)
326  padapter->dvobj_deinit(padapter);
327  padapter->bup = false;
328  }
329 }
330 
331 static void disable_ht_for_spec_devid(const struct usb_device_id *pdid,
332  struct _adapter *padapter)
333 {
334  u16 vid, pid;
335  u32 flags;
336  int i;
337  int num = sizeof(specific_device_id_tbl) /
338  sizeof(struct specific_device_id);
339 
340  for (i = 0; i < num; i++) {
341  vid = specific_device_id_tbl[i].idVendor;
342  pid = specific_device_id_tbl[i].idProduct;
343  flags = specific_device_id_tbl[i].flags;
344 
345  if ((pdid->idVendor == vid) && (pdid->idProduct == pid) &&
346  (flags&SPEC_DEV_ID_DISABLE_HT)) {
347  padapter->registrypriv.ht_enable = 0;
348  padapter->registrypriv.cbw40_enable = 0;
349  padapter->registrypriv.ampdu_enable = 0;
350  }
351  }
352 }
353 
354 static u8 key_2char2num(u8 hch, u8 lch)
355 {
356  return (hex_to_bin(hch) << 4) | hex_to_bin(lch);
357 }
358 
359 /*
360  * drv_init() - a device potentially for us
361  *
362  * notes: drv_init() is called when the bus driver has located a card for us
363  * to support. We accept the new device by returning 0.
364 */
365 static int r871xu_drv_init(struct usb_interface *pusb_intf,
366  const struct usb_device_id *pdid)
367 {
368  uint status;
369  struct _adapter *padapter = NULL;
370  struct dvobj_priv *pdvobjpriv;
371  struct net_device *pnetdev;
372  struct usb_device *udev;
373 
374  printk(KERN_INFO "r8712u: Staging version\n");
375  /* In this probe function, O.S. will provide the usb interface pointer
376  * to driver. We have to increase the reference count of the usb device
377  * structure by using the usb_get_dev function.
378  */
379  udev = interface_to_usbdev(pusb_intf);
380  usb_get_dev(udev);
381  pintf = pusb_intf;
382  /* step 1. */
383  pnetdev = r8712_init_netdev();
384  if (!pnetdev)
385  goto error;
386  padapter = netdev_priv(pnetdev);
387  disable_ht_for_spec_devid(pdid, padapter);
388  pdvobjpriv = &padapter->dvobjpriv;
389  pdvobjpriv->padapter = padapter;
390  padapter->dvobjpriv.pusbdev = udev;
391  padapter->pusb_intf = pusb_intf;
392  usb_set_intfdata(pusb_intf, pnetdev);
393  SET_NETDEV_DEV(pnetdev, &pusb_intf->dev);
394  /* step 2. */
395  padapter->dvobj_init = &r8712_usb_dvobj_init;
396  padapter->dvobj_deinit = &r8712_usb_dvobj_deinit;
397  padapter->halpriv.hal_bus_init = &r8712_usb_hal_bus_init;
398  padapter->dvobjpriv.inirp_init = &r8712_usb_inirp_init;
399  padapter->dvobjpriv.inirp_deinit = &r8712_usb_inirp_deinit;
400  /* step 3.
401  * initialize the dvobj_priv
402  */
403  if (padapter->dvobj_init == NULL)
404  goto error;
405  else {
406  status = padapter->dvobj_init(padapter);
407  if (status != _SUCCESS)
408  goto error;
409  }
410  /* step 4. */
411  status = r8712_init_drv_sw(padapter);
412  if (status == _FAIL)
413  goto error;
414  /* step 5. read efuse/eeprom data and get mac_addr */
415  {
416  int i, offset;
417  u8 mac[6];
418  u8 tmpU1b, AutoloadFail, eeprom_CustomerID;
419  u8 *pdata = padapter->eeprompriv.efuse_eeprom_data;
420 
421  tmpU1b = r8712_read8(padapter, EE_9346CR);/*CR9346*/
422 
423  /* To check system boot selection.*/
424  printk(KERN_INFO "r8712u: Boot from %s: Autoload %s\n",
425  (tmpU1b & _9356SEL) ? "EEPROM" : "EFUSE",
426  (tmpU1b & _EEPROM_EN) ? "OK" : "Failed");
427 
428  /* To check autoload success or not.*/
429  if (tmpU1b & _EEPROM_EN) {
430  AutoloadFail = true;
431  /* The following operations prevent Efuse leakage by
432  * turning on 2.5V.
433  */
434  tmpU1b = r8712_read8(padapter, EFUSE_TEST+3);
435  r8712_write8(padapter, EFUSE_TEST + 3, tmpU1b | 0x80);
436  msleep(20);
437  r8712_write8(padapter, EFUSE_TEST + 3,
438  (tmpU1b & (~BIT(7))));
439 
440  /* Retrieve Chip version.
441  * Recognize IC version by Reg0x4 BIT15.
442  */
443  tmpU1b = (u8)((r8712_read32(padapter, PMC_FSM) >> 15) &
444  0x1F);
445  if (tmpU1b == 0x3)
446  padapter->registrypriv.chip_version =
448  else
449  padapter->registrypriv.chip_version =
450  (tmpU1b >> 1) + 1;
451  switch (padapter->registrypriv.chip_version) {
452  case RTL8712_1stCUT:
453  case RTL8712_2ndCUT:
454  case RTL8712_3rdCUT:
455  break;
456  default:
457  padapter->registrypriv.chip_version =
459  break;
460  }
461 
462  for (i = 0, offset = 0; i < 128; i += 8, offset++)
463  r8712_efuse_pg_packet_read(padapter, offset,
464  &pdata[i]);
465 
466  if (r8712_initmac) {
467  /* Users specify the mac address */
468  int jj, kk;
469 
470  for (jj = 0, kk = 0; jj < ETH_ALEN;
471  jj++, kk += 3)
472  mac[jj] =
473  key_2char2num(r8712_initmac[kk],
474  r8712_initmac[kk + 1]);
475  } else {
476  /* Use the mac address stored in the Efuse
477  * offset = 0x12 for usb in efuse
478  */
479  memcpy(mac, &pdata[0x12], ETH_ALEN);
480  }
481  eeprom_CustomerID = pdata[0x52];
482  switch (eeprom_CustomerID) {
483  case EEPROM_CID_ALPHA:
484  padapter->eeprompriv.CustomerID =
486  break;
487  case EEPROM_CID_CAMEO:
488  padapter->eeprompriv.CustomerID =
490  break;
491  case EEPROM_CID_SITECOM:
492  padapter->eeprompriv.CustomerID =
494  break;
495  case EEPROM_CID_COREGA:
496  padapter->eeprompriv.CustomerID =
498  break;
499  case EEPROM_CID_Senao:
500  padapter->eeprompriv.CustomerID =
502  break;
504  padapter->eeprompriv.CustomerID =
506  break;
508  padapter->eeprompriv.CustomerID =
510  break;
512  padapter->eeprompriv.CustomerID =
514  break;
515  case EEPROM_CID_WHQL:
516  break;
517  case EEPROM_CID_NetCore:
518  padapter->eeprompriv.CustomerID =
520  break;
521  case EEPROM_CID_CAMEO1:
522  padapter->eeprompriv.CustomerID =
524  break;
525  case EEPROM_CID_CLEVO:
526  padapter->eeprompriv.CustomerID =
528  break;
529  default:
530  padapter->eeprompriv.CustomerID =
532  break;
533  }
534  printk(KERN_INFO "r8712u: CustomerID = 0x%.4x\n",
535  padapter->eeprompriv.CustomerID);
536  /* Led mode */
537  switch (padapter->eeprompriv.CustomerID) {
538  case RT_CID_DEFAULT:
539  case RT_CID_819x_ALPHA:
540  case RT_CID_819x_CAMEO:
541  padapter->ledpriv.LedStrategy = SW_LED_MODE1;
542  padapter->ledpriv.bRegUseLed = true;
543  break;
544  case RT_CID_819x_Sitecom:
545  padapter->ledpriv.LedStrategy = SW_LED_MODE2;
546  padapter->ledpriv.bRegUseLed = true;
547  break;
548  case RT_CID_COREGA:
549  case RT_CID_819x_Senao:
550  padapter->ledpriv.LedStrategy = SW_LED_MODE3;
551  padapter->ledpriv.bRegUseLed = true;
552  break;
554  padapter->ledpriv.LedStrategy = SW_LED_MODE4;
555  padapter->ledpriv.bRegUseLed = true;
556  break;
558  padapter->ledpriv.LedStrategy = SW_LED_MODE5;
559  padapter->ledpriv.bRegUseLed = true;
560  break;
562  padapter->ledpriv.LedStrategy = SW_LED_MODE6;
563  padapter->ledpriv.bRegUseLed = true;
564  break;
565  default:
566  padapter->ledpriv.LedStrategy = SW_LED_MODE0;
567  padapter->ledpriv.bRegUseLed = false;
568  break;
569  }
570  } else
571  AutoloadFail = false;
572  if (((mac[0] == 0xff) && (mac[1] == 0xff) &&
573  (mac[2] == 0xff) && (mac[3] == 0xff) &&
574  (mac[4] == 0xff) && (mac[5] == 0xff)) ||
575  ((mac[0] == 0x00) && (mac[1] == 0x00) &&
576  (mac[2] == 0x00) && (mac[3] == 0x00) &&
577  (mac[4] == 0x00) && (mac[5] == 0x00)) ||
578  (AutoloadFail == false)) {
579  mac[0] = 0x00;
580  mac[1] = 0xe0;
581  mac[2] = 0x4c;
582  mac[3] = 0x87;
583  mac[4] = 0x00;
584  mac[5] = 0x00;
585  }
586  if (r8712_initmac) {
587  /* Make sure the user did not select a multicast
588  * address by setting bit 1 of first octet.
589  */
590  mac[0] &= 0xFE;
591  printk(KERN_INFO "r8712u: MAC Address from user = "
592  "%pM\n", mac);
593  } else
594  printk(KERN_INFO "r8712u: MAC Address from efuse = "
595  "%pM\n", mac);
596  memcpy(pnetdev->dev_addr, mac, ETH_ALEN);
597  }
598  /* step 6. Load the firmware asynchronously */
599  if (rtl871x_load_fw(padapter))
600  goto error;
601  spin_lock_init(&padapter->lockRxFF0Filter);
602  mutex_init(&padapter->mutex_start);
603  return 0;
604 error:
605  usb_put_dev(udev);
606  usb_set_intfdata(pusb_intf, NULL);
607  if (padapter->dvobj_deinit != NULL)
608  padapter->dvobj_deinit(padapter);
609  if (pnetdev)
610  free_netdev(pnetdev);
611  return -ENODEV;
612 }
613 
614 /* rmmod module & unplug(SurpriseRemoved) will call r871xu_dev_remove()
615  * => how to recognize both */
616 static void r871xu_dev_remove(struct usb_interface *pusb_intf)
617 {
618  struct net_device *pnetdev = usb_get_intfdata(pusb_intf);
619  struct _adapter *padapter = netdev_priv(pnetdev);
620  struct usb_device *udev = interface_to_usbdev(pusb_intf);
621 
622  usb_set_intfdata(pusb_intf, NULL);
623  if (padapter->fw_found)
624  release_firmware(padapter->fw);
625  /* never exit with a firmware callback pending */
627  if (drvpriv.drv_registered == true)
628  padapter->bSurpriseRemoved = true;
629  if (pnetdev != NULL) {
630  /* will call netdev_close() */
631  unregister_netdev(pnetdev);
632  }
634  udelay(1);
635  /*Stop driver mlme relation timer */
636  if (padapter->fw_found)
637  r8712_stop_drv_timers(padapter);
638  r871x_dev_unload(padapter);
639  r8712_free_drv_sw(padapter);
640  usb_set_intfdata(pusb_intf, NULL);
641  /* decrease the reference count of the usb device structure
642  * when disconnect */
643  usb_put_dev(udev);
644  /* If we didn't unplug usb dongle and remove/insert module, driver
645  * fails on sitesurvey for the first time when device is up.
646  * Reset usb port for sitesurvey fail issue. */
647  if (udev->state != USB_STATE_NOTATTACHED)
648  usb_reset_device(udev);
649  return;
650 }
651 
652 static int __init r8712u_drv_entry(void)
653 {
654  drvpriv.drv_registered = true;
655  return usb_register(&drvpriv.r871xu_drv);
656 }
657 
658 static void __exit r8712u_drv_halt(void)
659 {
660  drvpriv.drv_registered = false;
661  usb_deregister(&drvpriv.r871xu_drv);
662  printk(KERN_INFO "r8712u: Driver unloaded\n");
663 }
664 
665 module_init(r8712u_drv_entry);
666 module_exit(r8712u_drv_halt);