]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/rtl8723au/os_dep/usb_intf.c
Merge remote-tracking branch 'usb-gadget/next'
[karo-tx-linux.git] / drivers / staging / rtl8723au / os_dep / usb_intf.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  ******************************************************************************/
15 #define _HCI_INTF_C_
16
17 #include <osdep_service.h>
18 #include <drv_types.h>
19 #include <recv_osdep.h>
20 #include <xmit_osdep.h>
21 #include <hal_intf.h>
22 #include <rtw_version.h>
23 #include <osdep_intf.h>
24 #include <usb_ops.h>
25 #include <rtl8723a_hal.h>
26
27 static int rtw_suspend(struct usb_interface *intf, pm_message_t message);
28 static int rtw_resume(struct usb_interface *intf);
29 static int rtw_drv_init(struct usb_interface *pusb_intf,
30                         const struct usb_device_id *pdid);
31 static void rtw_disconnect(struct usb_interface *pusb_intf);
32
33 #define USB_VENDER_ID_REALTEK           0x0BDA
34
35 #define RTL8723A_USB_IDS \
36         {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDER_ID_REALTEK, 0x8724,   \
37          0xff, 0xff, 0xff)}, /* 8723AU 1*1 */ \
38         {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDER_ID_REALTEK, 0x1724,   \
39          0xff, 0xff, 0xff)}, /* 8723AU 1*1 */ \
40         {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDER_ID_REALTEK, 0x0724,   \
41          0xff, 0xff, 0xff)}, /* 8723AU 1*1 */
42
43 static struct usb_device_id rtl8723a_usb_id_tbl[] = {
44         RTL8723A_USB_IDS
45         {}      /* Terminating entry */
46 };
47
48 MODULE_DEVICE_TABLE(usb, rtl8723a_usb_id_tbl);
49
50 static struct usb_driver rtl8723a_usb_drv = {
51         .name = (char *)"rtl8723au",
52         .probe = rtw_drv_init,
53         .disconnect = rtw_disconnect,
54         .id_table = rtl8723a_usb_id_tbl,
55         .suspend = rtw_suspend,
56         .resume = rtw_resume,
57         .reset_resume  = rtw_resume,
58 };
59
60 static struct usb_driver *usb_drv = &rtl8723a_usb_drv;
61
62 static int rtw_init_intf_priv(struct dvobj_priv *dvobj)
63 {
64         mutex_init(&dvobj->usb_vendor_req_mutex);
65
66         return _SUCCESS;
67 }
68
69 static int rtw_deinit_intf_priv(struct dvobj_priv *dvobj)
70 {
71         mutex_destroy(&dvobj->usb_vendor_req_mutex);
72
73         return _SUCCESS;
74 }
75
76 static struct dvobj_priv *usb_dvobj_init(struct usb_interface *usb_intf)
77 {
78         struct dvobj_priv *pdvobjpriv;
79         struct usb_host_config   *phost_conf;
80         struct usb_config_descriptor *pconf_desc;
81         struct usb_host_interface *phost_iface;
82         struct usb_interface_descriptor *piface_desc;
83         struct usb_endpoint_descriptor *pendp_desc;
84         struct usb_device *pusbd;
85         int i, status = _FAIL;
86
87         pdvobjpriv = kzalloc(sizeof(*pdvobjpriv), GFP_KERNEL);
88         if (!pdvobjpriv)
89                 goto exit;
90
91         mutex_init(&pdvobjpriv->hw_init_mutex);
92         mutex_init(&pdvobjpriv->h2c_fwcmd_mutex);
93         mutex_init(&pdvobjpriv->setch_mutex);
94         mutex_init(&pdvobjpriv->setbw_mutex);
95
96         pdvobjpriv->pusbintf = usb_intf;
97         pusbd = interface_to_usbdev(usb_intf);
98         pdvobjpriv->pusbdev = pusbd;
99         usb_set_intfdata(usb_intf, pdvobjpriv);
100
101         pdvobjpriv->RtNumInPipes = 0;
102         pdvobjpriv->RtNumOutPipes = 0;
103
104         phost_conf = pusbd->actconfig;
105         pconf_desc = &phost_conf->desc;
106
107         phost_iface = &usb_intf->altsetting[0];
108         piface_desc = &phost_iface->desc;
109
110         pdvobjpriv->NumInterfaces = pconf_desc->bNumInterfaces;
111         pdvobjpriv->InterfaceNumber = piface_desc->bInterfaceNumber;
112         pdvobjpriv->nr_endpoint = piface_desc->bNumEndpoints;
113
114         for (i = 0; i < pdvobjpriv->nr_endpoint; i++) {
115                 pendp_desc = &phost_iface->endpoint[i].desc;
116
117                 DBG_8723A("\nusb_endpoint_descriptor(%d):\n", i);
118                 DBG_8723A("bLength =%x\n", pendp_desc->bLength);
119                 DBG_8723A("bDescriptorType =%x\n", pendp_desc->bDescriptorType);
120                 DBG_8723A("bEndpointAddress =%x\n",
121                           pendp_desc->bEndpointAddress);
122                 DBG_8723A("wMaxPacketSize =%d\n",
123                           le16_to_cpu(pendp_desc->wMaxPacketSize));
124                 DBG_8723A("bInterval =%x\n", pendp_desc->bInterval);
125
126                 if (usb_endpoint_is_bulk_in(pendp_desc)) {
127                         DBG_8723A("usb_endpoint_is_bulk_in = %x\n",
128                                   usb_endpoint_num(pendp_desc));
129                         pdvobjpriv->RtInPipe[pdvobjpriv->RtNumInPipes] =
130                                 usb_endpoint_num(pendp_desc);
131                         pdvobjpriv->RtNumInPipes++;
132                 } else if (usb_endpoint_is_int_in(pendp_desc)) {
133                         DBG_8723A("usb_endpoint_is_int_in = %x, Interval = "
134                                   "%x\n", usb_endpoint_num(pendp_desc),
135                                   pendp_desc->bInterval);
136                         pdvobjpriv->RtInPipe[pdvobjpriv->RtNumInPipes] =
137                                 usb_endpoint_num(pendp_desc);
138                         pdvobjpriv->RtNumInPipes++;
139                 } else if (usb_endpoint_is_bulk_out(pendp_desc)) {
140                         DBG_8723A("usb_endpoint_is_bulk_out = %x\n",
141                                   usb_endpoint_num(pendp_desc));
142                         pdvobjpriv->RtOutPipe[pdvobjpriv->RtNumOutPipes] =
143                                 usb_endpoint_num(pendp_desc);
144                         pdvobjpriv->RtNumOutPipes++;
145                 }
146                 pdvobjpriv->ep_num[i] = usb_endpoint_num(pendp_desc);
147         }
148         DBG_8723A("nr_endpoint =%d, in_num =%d, out_num =%d\n\n",
149                   pdvobjpriv->nr_endpoint, pdvobjpriv->RtNumInPipes,
150                   pdvobjpriv->RtNumOutPipes);
151
152         if (pusbd->speed == USB_SPEED_HIGH) {
153                 pdvobjpriv->ishighspeed = true;
154                 DBG_8723A("USB_SPEED_HIGH\n");
155         } else {
156                 pdvobjpriv->ishighspeed = false;
157                 DBG_8723A("NON USB_SPEED_HIGH\n");
158         }
159
160         if (rtw_init_intf_priv(pdvobjpriv) == _FAIL) {
161                 RT_TRACE(_module_os_intfs_c_, _drv_err_,
162                          ("\n Can't INIT rtw_init_intf_priv\n"));
163                 goto free_dvobj;
164         }
165         /* 3 misc */
166         rtw_reset_continual_urb_error(pdvobjpriv);
167         usb_get_dev(pusbd);
168         status = _SUCCESS;
169 free_dvobj:
170         if (status != _SUCCESS && pdvobjpriv) {
171                 usb_set_intfdata(usb_intf, NULL);
172                 mutex_destroy(&pdvobjpriv->hw_init_mutex);
173                 mutex_destroy(&pdvobjpriv->h2c_fwcmd_mutex);
174                 mutex_destroy(&pdvobjpriv->setch_mutex);
175                 mutex_destroy(&pdvobjpriv->setbw_mutex);
176                 kfree(pdvobjpriv);
177                 pdvobjpriv = NULL;
178         }
179 exit:
180         return pdvobjpriv;
181 }
182
183 static void usb_dvobj_deinit(struct usb_interface *usb_intf)
184 {
185         struct dvobj_priv *dvobj = usb_get_intfdata(usb_intf);
186
187         usb_set_intfdata(usb_intf, NULL);
188         if (dvobj) {
189                 /* Modify condition for 92DU DMDP 2010.11.18, by Thomas */
190                 if ((dvobj->NumInterfaces != 2 && dvobj->NumInterfaces != 3) ||
191                     (dvobj->InterfaceNumber == 1)) {
192                         if (interface_to_usbdev(usb_intf)->state !=
193                             USB_STATE_NOTATTACHED) {
194                                 /* If we didn't unplug usb dongle and
195                                  * remove/insert module, driver fails on
196                                  * sitesurvey for the first time when
197                                  * device is up .
198                                  * Reset usb port for sitesurvey fail issue.
199                                  */
200                                 DBG_8723A("usb attached..., try to reset usb device\n");
201                                 usb_reset_device(interface_to_usbdev(usb_intf));
202                         }
203                 }
204                 rtw_deinit_intf_priv(dvobj);
205                 mutex_destroy(&dvobj->hw_init_mutex);
206                 mutex_destroy(&dvobj->h2c_fwcmd_mutex);
207                 mutex_destroy(&dvobj->setch_mutex);
208                 mutex_destroy(&dvobj->setbw_mutex);
209                 kfree(dvobj);
210         }
211         usb_put_dev(interface_to_usbdev(usb_intf));
212 }
213
214 void rtl8723a_usb_intf_stop(struct rtw_adapter *padapter)
215 {
216         RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+usb_intf_stop\n"));
217
218         /* disable_hw_interrupt */
219         if (!padapter->bSurpriseRemoved) {
220                 /* device still exists, so driver can do i/o operation
221                  * TODO:
222                  */
223                 RT_TRACE(_module_hci_intfs_c_, _drv_err_,
224                          ("SurpriseRemoved == false\n"));
225         }
226
227         /* cancel in irp */
228         rtl8723au_inirp_deinit(padapter);
229
230         /* cancel out irp */
231         rtl8723au_write_port_cancel(padapter);
232
233         /* todo:cancel other irps */
234         RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-usb_intf_stop\n"));
235 }
236
237 static void rtw_dev_unload(struct rtw_adapter *padapter)
238 {
239         struct submit_ctx *pack_tx_ops = &padapter->xmitpriv.ack_tx_ops;
240         RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+rtw_dev_unload\n"));
241
242         if (padapter->bup) {
243                 DBG_8723A("===> rtw_dev_unload\n");
244
245                 padapter->bDriverStopped = true;
246                 if (padapter->xmitpriv.ack_tx)
247                         rtw23a_sctx_done_err(&pack_tx_ops,
248                                              RTW_SCTX_DONE_DRV_STOP);
249
250                 /* s3. */
251                 rtl8723a_usb_intf_stop(padapter);
252
253                 /* s4. */
254                 flush_workqueue(padapter->cmdpriv.wq);
255
256                 /* s5. */
257                 if (!padapter->bSurpriseRemoved) {
258                         rtl8723au_hal_deinit(padapter);
259                         padapter->bSurpriseRemoved = true;
260                 }
261                 padapter->bup = false;
262         } else {
263                 RT_TRACE(_module_hci_intfs_c_, _drv_err_,
264                          ("r871x_dev_unload():padapter->bup == false\n"));
265         }
266         DBG_8723A("<=== rtw_dev_unload\n");
267         RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-rtw_dev_unload\n"));
268 }
269
270 static int rtw_suspend(struct usb_interface *pusb_intf, pm_message_t message)
271 {
272         struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf);
273         struct rtw_adapter *padapter = dvobj->if1;
274         struct net_device *pnetdev = padapter->pnetdev;
275         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
276         struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
277         int ret = 0;
278         unsigned long start_time = jiffies;
279
280         DBG_8723A("==> %s (%s:%d)\n", __func__, current->comm, current->pid);
281
282         if ((!padapter->bup) || (padapter->bDriverStopped) ||
283             (padapter->bSurpriseRemoved)) {
284                 DBG_8723A("padapter->bup =%d bDriverStopped =%d bSurpriseRemoved = %d\n",
285                           padapter->bup, padapter->bDriverStopped,
286                           padapter->bSurpriseRemoved);
287                 goto exit;
288         }
289         pwrpriv->bInSuspend = true;
290         rtw_cancel_all_timer23a(padapter);
291         LeaveAllPowerSaveMode23a(padapter);
292
293         down(&pwrpriv->lock);
294         /* padapter->net_closed = true; */
295         /* s1. */
296         if (pnetdev) {
297                 netif_carrier_off(pnetdev);
298                 netif_tx_stop_all_queues(pnetdev);
299         }
300
301         /* s2. */
302         rtw_disassoc_cmd23a(padapter, 0, false);
303
304         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) &&
305             check_fwstate(pmlmepriv, _FW_LINKED)) {
306                 DBG_8723A("%s:%d %s(%pM), length:%d assoc_ssid.length:%d\n",
307                           __func__, __LINE__,
308                           pmlmepriv->cur_network.network.Ssid.ssid,
309                           pmlmepriv->cur_network.network.MacAddress,
310                           pmlmepriv->cur_network.network.Ssid.ssid_len,
311                           pmlmepriv->assoc_ssid.ssid_len);
312
313                 rtw_set_roaming(padapter, 1);
314         }
315         /* s2-2.  indicate disconnect to os */
316         rtw_indicate_disconnect23a(padapter);
317         /* s2-3. */
318         rtw_free_assoc_resources23a(padapter, 1);
319         /* s2-4. */
320         rtw_free_network_queue23a(padapter);
321
322         rtw_dev_unload(padapter);
323         up(&pwrpriv->lock);
324
325         if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
326                 rtw_cfg80211_indicate_scan_done(
327                         wdev_to_priv(padapter->rtw_wdev), true);
328
329         if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
330                 rtw_indicate_disconnect23a(padapter);
331
332 exit:
333         DBG_8723A("<===  %s return %d.............. in %dms\n", __func__,
334                   ret, jiffies_to_msecs(jiffies - start_time));
335
336         return ret;
337 }
338
339 static int rtw_resume(struct usb_interface *pusb_intf)
340 {
341         struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf);
342         struct rtw_adapter *padapter = dvobj->if1;
343         struct net_device *pnetdev;
344         struct pwrctrl_priv *pwrpriv = NULL;
345         int ret = -1;
346         unsigned long start_time = jiffies;
347
348         DBG_8723A("==> %s (%s:%d)\n", __func__, current->comm, current->pid);
349
350         if (!padapter)
351                 goto exit;
352         pnetdev = padapter->pnetdev;
353         pwrpriv = &padapter->pwrctrlpriv;
354
355         down(&pwrpriv->lock);
356         rtw_reset_drv_sw23a(padapter);
357         pwrpriv->bkeepfwalive = false;
358
359         DBG_8723A("bkeepfwalive(%x)\n", pwrpriv->bkeepfwalive);
360         if (pm_netdev_open23a(pnetdev, true) != 0) {
361                 up(&pwrpriv->lock);
362                 goto exit;
363         }
364
365         netif_device_attach(pnetdev);
366         netif_carrier_on(pnetdev);
367
368         up(&pwrpriv->lock);
369
370         if (padapter->pid[1] != 0) {
371                 DBG_8723A("pid[1]:%d\n", padapter->pid[1]);
372                 kill_pid(find_vpid(padapter->pid[1]), SIGUSR2, 1);
373         }
374
375         rtw23a_roaming(padapter, NULL);
376
377         ret = 0;
378 exit:
379         if (pwrpriv)
380                 pwrpriv->bInSuspend = false;
381         DBG_8723A("<===  %s return %d.............. in %dms\n", __func__,
382                   ret, jiffies_to_msecs(jiffies - start_time));
383
384         return ret;
385 }
386
387 /*
388  * drv_init() - a device potentially for us
389  *
390  * notes: drv_init() is called when the bus driver has located a card
391  * for us to support.
392  *        We accept the new device by returning 0.
393  */
394 static struct rtw_adapter *rtw_usb_if1_init(struct dvobj_priv *dvobj,
395                                             struct usb_interface *pusb_intf,
396                                             const struct usb_device_id *pdid)
397 {
398         struct rtw_adapter *padapter = NULL;
399         struct net_device *pnetdev = NULL;
400         int status = _FAIL;
401
402         pnetdev = rtw_init_netdev23a(padapter);
403         if (!pnetdev)
404                 goto free_adapter;
405         padapter = netdev_priv(pnetdev);
406
407         padapter->dvobj = dvobj;
408         padapter->bDriverStopped = true;
409         dvobj->if1 = padapter;
410         dvobj->padapters[dvobj->iface_nums++] = padapter;
411         padapter->iface_id = IFACE_ID0;
412
413         rtl8723au_set_hw_type(padapter);
414
415         SET_NETDEV_DEV(pnetdev, dvobj_to_dev(dvobj));
416
417         if (rtw_wdev_alloc(padapter, dvobj_to_dev(dvobj)))
418                 goto free_adapter;
419
420         /* step 2. allocate HalData */
421         padapter->HalData = kzalloc(sizeof(struct hal_data_8723a), GFP_KERNEL);
422         if (!padapter->HalData)
423                 goto free_wdev;
424
425         /* step read_chip_version */
426         rtl8723a_read_chip_version(padapter);
427
428         /* step usb endpoint mapping */
429         if (!rtl8723au_chip_configure(padapter))
430                 goto free_hal_data;
431
432         /* step read efuse/eeprom data and get mac_addr */
433         rtl8723a_read_adapter_info(padapter);
434
435         /* step 5. */
436         if (rtw_init_drv_sw23a(padapter) == _FAIL) {
437                 RT_TRACE(_module_hci_intfs_c_, _drv_err_,
438                          ("Initialize driver software resource Failed!\n"));
439                 goto free_hal_data;
440         }
441
442 #ifdef CONFIG_PM
443         if (padapter->pwrctrlpriv.bSupportRemoteWakeup) {
444                 dvobj->pusbdev->do_remote_wakeup = 1;
445                 pusb_intf->needs_remote_wakeup = 1;
446                 device_init_wakeup(&pusb_intf->dev, 1);
447                 DBG_8723A("\n  padapter->pwrctrlpriv.bSupportRemoteWakeup~~~~~~\n");
448                 DBG_8723A("\n  padapter->pwrctrlpriv.bSupportRemoteWakeup~~~[%d]~~~\n",
449                           device_may_wakeup(&pusb_intf->dev));
450         }
451 #endif
452         /* 2012-07-11 Move here to prevent the 8723AS-VAU BT
453          * auto suspend influence
454          */
455         if (usb_autopm_get_interface(pusb_intf) < 0)
456                 DBG_8723A("can't get autopm:\n");
457 #ifdef  CONFIG_8723AU_BT_COEXIST
458         padapter->pwrctrlpriv.autopm_cnt = 1;
459 #endif
460
461         /* If the eeprom mac address is corrupted, assign a random address */
462         if (is_broadcast_ether_addr(padapter->eeprompriv.mac_addr) ||
463             is_zero_ether_addr(padapter->eeprompriv.mac_addr))
464                 eth_random_addr(padapter->eeprompriv.mac_addr);
465
466         DBG_8723A("bDriverStopped:%d, bSurpriseRemoved:%d, bup:%d, hw_init_completed:%d\n",
467                   padapter->bDriverStopped, padapter->bSurpriseRemoved,
468                   padapter->bup, padapter->hw_init_completed
469         );
470         status = _SUCCESS;
471
472 free_hal_data:
473         if (status != _SUCCESS)
474                 kfree(padapter->HalData);
475 free_wdev:
476         if (status != _SUCCESS) {
477                 rtw_wdev_unregister(padapter->rtw_wdev);
478                 rtw_wdev_free(padapter->rtw_wdev);
479         }
480 free_adapter:
481         if (status != _SUCCESS) {
482                 if (pnetdev)
483                         free_netdev(pnetdev);
484                 padapter = NULL;
485         }
486         return padapter;
487 }
488
489 static void rtw_usb_if1_deinit(struct rtw_adapter *if1)
490 {
491         struct net_device *pnetdev = if1->pnetdev;
492         struct mlme_priv *pmlmepriv = &if1->mlmepriv;
493
494         if (check_fwstate(pmlmepriv, _FW_LINKED))
495                 rtw_disassoc_cmd23a(if1, 0, false);
496
497 #ifdef CONFIG_8723AU_AP_MODE
498         free_mlme_ap_info23a(if1);
499 #endif
500
501         if (pnetdev)
502                 unregister_netdev(pnetdev); /* will call netdev_close() */
503
504         rtw_cancel_all_timer23a(if1);
505
506         rtw_dev_unload(if1);
507
508         DBG_8723A("+r871xu_dev_remove, hw_init_completed =%d\n",
509                   if1->hw_init_completed);
510
511         if (if1->rtw_wdev) {
512                 rtw_wdev_unregister(if1->rtw_wdev);
513                 rtw_wdev_free(if1->rtw_wdev);
514         }
515
516 #ifdef CONFIG_8723AU_BT_COEXIST
517         if (1 == if1->pwrctrlpriv.autopm_cnt) {
518                 usb_autopm_put_interface(adapter_to_dvobj(if1)->pusbintf);
519                 if1->pwrctrlpriv.autopm_cnt--;
520         }
521 #endif
522
523         rtw_free_drv_sw23a(if1);
524
525         if (pnetdev)
526                 free_netdev(pnetdev);
527 }
528
529 static int rtw_drv_init(struct usb_interface *pusb_intf,
530                         const struct usb_device_id *pdid)
531 {
532         struct rtw_adapter *if1 = NULL;
533         struct dvobj_priv *dvobj;
534         int status = _FAIL;
535
536         RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+rtw_drv_init\n"));
537
538         /* Initialize dvobj_priv */
539         dvobj = usb_dvobj_init(pusb_intf);
540         if (!dvobj) {
541                 RT_TRACE(_module_hci_intfs_c_, _drv_err_,
542                          ("initialize device object priv Failed!\n"));
543                 goto exit;
544         }
545
546         if1 = rtw_usb_if1_init(dvobj, pusb_intf, pdid);
547         if (!if1) {
548                 DBG_8723A("rtw_init_primary_adapter Failed!\n");
549                 goto free_dvobj;
550         }
551
552         /* dev_alloc_name && register_netdev */
553         status = rtw_drv_register_netdev(if1);
554         if (status != _SUCCESS)
555                 goto free_if1;
556         RT_TRACE(_module_hci_intfs_c_, _drv_err_,
557                  ("-871x_drv - drv_init, success!\n"));
558
559         status = _SUCCESS;
560
561 free_if1:
562         if (status != _SUCCESS && if1)
563                 rtw_usb_if1_deinit(if1);
564 free_dvobj:
565         if (status != _SUCCESS)
566                 usb_dvobj_deinit(pusb_intf);
567 exit:
568         return status == _SUCCESS ? 0 : -ENODEV;
569 }
570
571 /* dev_remove() - our device is being removed */
572 static void rtw_disconnect(struct usb_interface *pusb_intf)
573 {
574         struct dvobj_priv *dvobj;
575         struct rtw_adapter *padapter;
576         struct net_device *pnetdev;
577         struct mlme_priv *pmlmepriv;
578
579         dvobj = usb_get_intfdata(pusb_intf);
580         if (!dvobj)
581                 return;
582
583         padapter = dvobj->if1;
584         pnetdev = padapter->pnetdev;
585         pmlmepriv = &padapter->mlmepriv;
586
587         usb_set_intfdata(pusb_intf, NULL);
588
589         RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+dev_remove()\n"));
590
591         rtw_pm_set_ips23a(padapter, IPS_NONE);
592         rtw_pm_set_lps23a(padapter, PS_MODE_ACTIVE);
593
594         LeaveAllPowerSaveMode23a(padapter);
595
596         rtw_usb_if1_deinit(padapter);
597
598         usb_dvobj_deinit(pusb_intf);
599
600         RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-dev_remove()\n"));
601         DBG_8723A("-r871xu_dev_remove, done\n");
602
603         return;
604 }
605
606 static int __init rtw_drv_entry(void)
607 {
608         RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+rtw_drv_entry\n"));
609         return usb_register(usb_drv);
610 }
611
612 static void __exit rtw_drv_halt(void)
613 {
614         RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+rtw_drv_halt\n"));
615         DBG_8723A("+rtw_drv_halt\n");
616
617         usb_deregister(usb_drv);
618
619         DBG_8723A("-rtw_drv_halt\n");
620 }
621
622 module_init(rtw_drv_entry);
623 module_exit(rtw_drv_halt);