Merge remote-tracking branches 'asoc/topic/rl6231', 'asoc/topic/rockchip', 'asoc...
[sfrench/cifs-2.6.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 inline int RT_usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd)
63 {
64         return (epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN;
65 }
66
67 static inline int RT_usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd)
68 {
69         return (epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT;
70 }
71
72 static inline int RT_usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd)
73 {
74         return (epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT;
75 }
76
77 static inline int RT_usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *epd)
78 {
79         return (epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK;
80 }
81
82 static inline int RT_usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd)
83 {
84         return RT_usb_endpoint_xfer_bulk(epd) && RT_usb_endpoint_dir_in(epd);
85 }
86
87 static inline int RT_usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd)
88 {
89         return RT_usb_endpoint_xfer_bulk(epd) && RT_usb_endpoint_dir_out(epd);
90 }
91
92 static inline int RT_usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd)
93 {
94         return RT_usb_endpoint_xfer_int(epd) && RT_usb_endpoint_dir_in(epd);
95 }
96
97 static inline int RT_usb_endpoint_num(const struct usb_endpoint_descriptor *epd)
98 {
99         return epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
100 }
101
102 static int rtw_init_intf_priv(struct dvobj_priv *dvobj)
103 {
104         int rst = _SUCCESS;
105
106         mutex_init(&dvobj->usb_vendor_req_mutex);
107         dvobj->usb_alloc_vendor_req_buf = kzalloc(MAX_USB_IO_CTL_SIZE,
108                                                   GFP_KERNEL);
109         if (dvobj->usb_alloc_vendor_req_buf == NULL) {
110                 DBG_8723A("alloc usb_vendor_req_buf failed...\n");
111                 rst = _FAIL;
112                 goto exit;
113         }
114         dvobj->usb_vendor_req_buf =
115                 PTR_ALIGN(dvobj->usb_alloc_vendor_req_buf, ALIGNMENT_UNIT);
116 exit:
117         return rst;
118 }
119
120 static int rtw_deinit_intf_priv(struct dvobj_priv *dvobj)
121 {
122         int rst = _SUCCESS;
123
124         kfree(dvobj->usb_alloc_vendor_req_buf);
125
126         mutex_destroy(&dvobj->usb_vendor_req_mutex);
127
128         return rst;
129 }
130
131 static struct dvobj_priv *usb_dvobj_init(struct usb_interface *usb_intf)
132 {
133         struct dvobj_priv *pdvobjpriv;
134         struct usb_device_descriptor *pdev_desc;
135         struct usb_host_config   *phost_conf;
136         struct usb_config_descriptor *pconf_desc;
137         struct usb_host_interface *phost_iface;
138         struct usb_interface_descriptor *piface_desc;
139         struct usb_host_endpoint *phost_endp;
140         struct usb_endpoint_descriptor *pendp_desc;
141         struct usb_device                *pusbd;
142         int     i;
143         int     status = _FAIL;
144
145         pdvobjpriv = kzalloc(sizeof(*pdvobjpriv), GFP_KERNEL);
146         if (!pdvobjpriv)
147                 goto exit;
148
149         mutex_init(&pdvobjpriv->hw_init_mutex);
150         mutex_init(&pdvobjpriv->h2c_fwcmd_mutex);
151         mutex_init(&pdvobjpriv->setch_mutex);
152         mutex_init(&pdvobjpriv->setbw_mutex);
153
154         pdvobjpriv->pusbintf = usb_intf;
155         pusbd = interface_to_usbdev(usb_intf);
156         pdvobjpriv->pusbdev = pusbd;
157         usb_set_intfdata(usb_intf, pdvobjpriv);
158
159         pdvobjpriv->RtNumInPipes = 0;
160         pdvobjpriv->RtNumOutPipes = 0;
161
162         pdev_desc = &pusbd->descriptor;
163
164         phost_conf = pusbd->actconfig;
165         pconf_desc = &phost_conf->desc;
166
167         phost_iface = &usb_intf->altsetting[0];
168         piface_desc = &phost_iface->desc;
169
170         pdvobjpriv->NumInterfaces = pconf_desc->bNumInterfaces;
171         pdvobjpriv->InterfaceNumber = piface_desc->bInterfaceNumber;
172         pdvobjpriv->nr_endpoint = piface_desc->bNumEndpoints;
173
174         for (i = 0; i < pdvobjpriv->nr_endpoint; i++) {
175                 phost_endp = phost_iface->endpoint + i;
176                 if (phost_endp) {
177                         pendp_desc = &phost_endp->desc;
178
179                         DBG_8723A("\nusb_endpoint_descriptor(%d):\n", i);
180                         DBG_8723A("bLength =%x\n", pendp_desc->bLength);
181                         DBG_8723A("bDescriptorType =%x\n",
182                                   pendp_desc->bDescriptorType);
183                         DBG_8723A("bEndpointAddress =%x\n",
184                                   pendp_desc->bEndpointAddress);
185                         DBG_8723A("wMaxPacketSize =%d\n",
186                                   le16_to_cpu(pendp_desc->wMaxPacketSize));
187                         DBG_8723A("bInterval =%x\n", pendp_desc->bInterval);
188
189                         if (RT_usb_endpoint_is_bulk_in(pendp_desc)) {
190                                 DBG_8723A("RT_usb_endpoint_is_bulk_in = %x\n",
191                                           RT_usb_endpoint_num(pendp_desc));
192                                 pdvobjpriv->RtInPipe[pdvobjpriv->RtNumInPipes] =
193                                         RT_usb_endpoint_num(pendp_desc);
194                                 pdvobjpriv->RtNumInPipes++;
195                         } else if (RT_usb_endpoint_is_int_in(pendp_desc)) {
196                                 DBG_8723A("RT_usb_endpoint_is_int_in = %x, Interval = %x\n",
197                                           RT_usb_endpoint_num(pendp_desc),
198                                           pendp_desc->bInterval);
199                                 pdvobjpriv->RtInPipe[pdvobjpriv->RtNumInPipes] =
200                                         RT_usb_endpoint_num(pendp_desc);
201                                 pdvobjpriv->RtNumInPipes++;
202                         } else if (RT_usb_endpoint_is_bulk_out(pendp_desc)) {
203                                 DBG_8723A("RT_usb_endpoint_is_bulk_out = %x\n",
204                                           RT_usb_endpoint_num(pendp_desc));
205                                 pdvobjpriv->RtOutPipe[pdvobjpriv->RtNumOutPipes] =
206                                         RT_usb_endpoint_num(pendp_desc);
207                                 pdvobjpriv->RtNumOutPipes++;
208                         }
209                         pdvobjpriv->ep_num[i] = RT_usb_endpoint_num(pendp_desc);
210                 }
211         }
212         DBG_8723A("nr_endpoint =%d, in_num =%d, out_num =%d\n\n",
213                   pdvobjpriv->nr_endpoint, pdvobjpriv->RtNumInPipes,
214                   pdvobjpriv->RtNumOutPipes);
215
216         if (pusbd->speed == USB_SPEED_HIGH) {
217                 pdvobjpriv->ishighspeed = true;
218                 DBG_8723A("USB_SPEED_HIGH\n");
219         } else {
220                 pdvobjpriv->ishighspeed = false;
221                 DBG_8723A("NON USB_SPEED_HIGH\n");
222         }
223
224         if (rtw_init_intf_priv(pdvobjpriv) == _FAIL) {
225                 RT_TRACE(_module_os_intfs_c_, _drv_err_,
226                          ("\n Can't INIT rtw_init_intf_priv\n"));
227                 goto free_dvobj;
228         }
229         /* 3 misc */
230         rtw_reset_continual_urb_error(pdvobjpriv);
231         usb_get_dev(pusbd);
232         status = _SUCCESS;
233 free_dvobj:
234         if (status != _SUCCESS && pdvobjpriv) {
235                 usb_set_intfdata(usb_intf, NULL);
236                 mutex_destroy(&pdvobjpriv->hw_init_mutex);
237                 mutex_destroy(&pdvobjpriv->h2c_fwcmd_mutex);
238                 mutex_destroy(&pdvobjpriv->setch_mutex);
239                 mutex_destroy(&pdvobjpriv->setbw_mutex);
240                 kfree(pdvobjpriv);
241                 pdvobjpriv = NULL;
242         }
243 exit:
244         return pdvobjpriv;
245 }
246
247 static void usb_dvobj_deinit(struct usb_interface *usb_intf)
248 {
249         struct dvobj_priv *dvobj = usb_get_intfdata(usb_intf);
250
251         usb_set_intfdata(usb_intf, NULL);
252         if (dvobj) {
253                 /* Modify condition for 92DU DMDP 2010.11.18, by Thomas */
254                 if ((dvobj->NumInterfaces != 2 && dvobj->NumInterfaces != 3) ||
255                     (dvobj->InterfaceNumber == 1)) {
256                         if (interface_to_usbdev(usb_intf)->state !=
257                             USB_STATE_NOTATTACHED) {
258                                 /* If we didn't unplug usb dongle and
259                                  * remove/insert module, driver fails on
260                                  * sitesurvey for the first time when
261                                  * device is up .
262                                  * Reset usb port for sitesurvey fail issue.
263                                  */
264                                 DBG_8723A("usb attached..., try to reset usb device\n");
265                                 usb_reset_device(interface_to_usbdev(usb_intf));
266                         }
267                 }
268                 rtw_deinit_intf_priv(dvobj);
269                 mutex_destroy(&dvobj->hw_init_mutex);
270                 mutex_destroy(&dvobj->h2c_fwcmd_mutex);
271                 mutex_destroy(&dvobj->setch_mutex);
272                 mutex_destroy(&dvobj->setbw_mutex);
273                 kfree(dvobj);
274         }
275         usb_put_dev(interface_to_usbdev(usb_intf));
276 }
277
278 void rtl8723a_usb_intf_stop(struct rtw_adapter *padapter)
279 {
280         RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+usb_intf_stop\n"));
281
282         /* disable_hw_interrupt */
283         if (!padapter->bSurpriseRemoved) {
284                 /* device still exists, so driver can do i/o operation
285                  * TODO:
286                  */
287                 RT_TRACE(_module_hci_intfs_c_, _drv_err_,
288                          ("SurpriseRemoved == false\n"));
289         }
290
291         /* cancel in irp */
292         rtl8723au_inirp_deinit(padapter);
293
294         /* cancel out irp */
295         rtl8723au_write_port_cancel(padapter);
296
297         /* todo:cancel other irps */
298         RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-usb_intf_stop\n"));
299 }
300
301 static void rtw_dev_unload(struct rtw_adapter *padapter)
302 {
303         RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+rtw_dev_unload\n"));
304
305         if (padapter->bup) {
306                 DBG_8723A("===> rtw_dev_unload\n");
307
308                 padapter->bDriverStopped = true;
309                 if (padapter->xmitpriv.ack_tx)
310                         rtw_ack_tx_done23a(&padapter->xmitpriv,
311                                         RTW_SCTX_DONE_DRV_STOP);
312
313                 /* s3. */
314                 rtl8723a_usb_intf_stop(padapter);
315
316                 /* s4. */
317                 flush_workqueue(padapter->cmdpriv.wq);
318
319                 /* s5. */
320                 if (!padapter->bSurpriseRemoved) {
321                         rtw_hal_deinit23a(padapter);
322                         padapter->bSurpriseRemoved = true;
323                 }
324                 padapter->bup = false;
325         } else {
326                 RT_TRACE(_module_hci_intfs_c_, _drv_err_,
327                          ("r871x_dev_unload():padapter->bup == false\n"));
328         }
329         DBG_8723A("<=== rtw_dev_unload\n");
330         RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-rtw_dev_unload\n"));
331 }
332
333 int rtw_hw_suspend23a(struct rtw_adapter *padapter)
334 {
335         struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
336         struct net_device *pnetdev = padapter->pnetdev;
337         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
338
339         if ((!padapter->bup) || (padapter->bDriverStopped) ||
340             (padapter->bSurpriseRemoved)) {
341                 DBG_8723A("padapter->bup =%d bDriverStopped =%d bSurpriseRemoved = %d\n",
342                           padapter->bup, padapter->bDriverStopped,
343                           padapter->bSurpriseRemoved);
344                 goto error_exit;
345         }
346
347         if (padapter) { /* system suspend */
348                 LeaveAllPowerSaveMode23a(padapter);
349
350                 DBG_8723A("==> rtw_hw_suspend23a\n");
351                 down(&pwrpriv->lock);
352                 pwrpriv->bips_processing = true;
353                 /* padapter->net_closed = true; */
354                 /* s1. */
355                 if (pnetdev) {
356                         netif_carrier_off(pnetdev);
357                         netif_tx_stop_all_queues(pnetdev);
358                 }
359
360                 /* s2. */
361                 rtw_disassoc_cmd23a(padapter, 500, false);
362
363                 /* s2-2.  indicate disconnect to os */
364                 /* rtw_indicate_disconnect23a(padapter); */
365                 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
366                         _clr_fwstate_(pmlmepriv, _FW_LINKED);
367
368                         rtw_led_control(padapter, LED_CTL_NO_LINK);
369
370                         rtw_os_indicate_disconnect23a(padapter);
371
372                         /* donnot enqueue cmd */
373                         rtw_lps_ctrl_wk_cmd23a(padapter,
374                                                LPS_CTRL_DISCONNECT, 0);
375                 }
376                 /* s2-3. */
377                 rtw_free_assoc_resources23a(padapter, 1);
378
379                 /* s2-4. */
380                 rtw_free_network_queue23a(padapter);
381                 rtw_ips_dev_unload23a(padapter);
382                 pwrpriv->rf_pwrstate = rf_off;
383                 pwrpriv->bips_processing = false;
384                 up(&pwrpriv->lock);
385         } else {
386                 goto error_exit;
387         }
388         return 0;
389 error_exit:
390         DBG_8723A("%s, failed\n", __func__);
391         return -1;
392 }
393
394 int rtw_hw_resume23a(struct rtw_adapter *padapter)
395 {
396         struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
397         struct net_device *pnetdev = padapter->pnetdev;
398
399         if (padapter) { /* system resume */
400                 DBG_8723A("==> rtw_hw_resume23a\n");
401                 down(&pwrpriv->lock);
402                 pwrpriv->bips_processing = true;
403                 rtw_reset_drv_sw23a(padapter);
404
405                 if (pm_netdev_open23a(pnetdev, false)) {
406                         up(&pwrpriv->lock);
407                         goto error_exit;
408                 }
409
410                 netif_device_attach(pnetdev);
411                 netif_carrier_on(pnetdev);
412
413                 if (!rtw_netif_queue_stopped(pnetdev))
414                         netif_tx_start_all_queues(pnetdev);
415                 else
416                         netif_tx_wake_all_queues(pnetdev);
417
418                 pwrpriv->bkeepfwalive = false;
419                 pwrpriv->brfoffbyhw = false;
420
421                 pwrpriv->rf_pwrstate = rf_on;
422                 pwrpriv->bips_processing = false;
423
424                 up(&pwrpriv->lock);
425         } else {
426                 goto error_exit;
427         }
428         return 0;
429 error_exit:
430         DBG_8723A("%s, Open net dev failed\n", __func__);
431         return -1;
432 }
433
434 static int rtw_suspend(struct usb_interface *pusb_intf, pm_message_t message)
435 {
436         struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf);
437         struct rtw_adapter *padapter = dvobj->if1;
438         struct net_device *pnetdev = padapter->pnetdev;
439         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
440         struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
441         int ret = 0;
442         unsigned long start_time = jiffies;
443
444         DBG_8723A("==> %s (%s:%d)\n", __func__, current->comm, current->pid);
445
446         if ((!padapter->bup) || (padapter->bDriverStopped) ||
447             (padapter->bSurpriseRemoved)) {
448                 DBG_8723A("padapter->bup =%d bDriverStopped =%d bSurpriseRemoved = %d\n",
449                           padapter->bup, padapter->bDriverStopped,
450                           padapter->bSurpriseRemoved);
451                 goto exit;
452         }
453         pwrpriv->bInSuspend = true;
454         rtw_cancel_all_timer23a(padapter);
455         LeaveAllPowerSaveMode23a(padapter);
456
457         down(&pwrpriv->lock);
458         /* padapter->net_closed = true; */
459         /* s1. */
460         if (pnetdev) {
461                 netif_carrier_off(pnetdev);
462                 netif_tx_stop_all_queues(pnetdev);
463         }
464
465         /* s2. */
466         rtw_disassoc_cmd23a(padapter, 0, false);
467
468         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) &&
469             check_fwstate(pmlmepriv, _FW_LINKED)) {
470                 DBG_8723A("%s:%d %s(%pM), length:%d assoc_ssid.length:%d\n",
471                           __func__, __LINE__,
472                           pmlmepriv->cur_network.network.Ssid.ssid,
473                           pmlmepriv->cur_network.network.MacAddress,
474                           pmlmepriv->cur_network.network.Ssid.ssid_len,
475                           pmlmepriv->assoc_ssid.ssid_len);
476
477                 rtw_set_roaming(padapter, 1);
478         }
479         /* s2-2.  indicate disconnect to os */
480         rtw_indicate_disconnect23a(padapter);
481         /* s2-3. */
482         rtw_free_assoc_resources23a(padapter, 1);
483         /* s2-4. */
484         rtw_free_network_queue23a(padapter);
485
486         rtw_dev_unload(padapter);
487         up(&pwrpriv->lock);
488
489         if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
490                 rtw_cfg80211_indicate_scan_done(
491                         wdev_to_priv(padapter->rtw_wdev), true);
492
493         if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
494                 rtw_indicate_disconnect23a(padapter);
495
496 exit:
497         DBG_8723A("<===  %s return %d.............. in %dms\n", __func__,
498                   ret, jiffies_to_msecs(jiffies - start_time));
499
500         return ret;
501 }
502
503 static int rtw_resume(struct usb_interface *pusb_intf)
504 {
505         struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf);
506         struct rtw_adapter *padapter = dvobj->if1;
507         int ret;
508
509         ret = rtw_resume_process23a(padapter);
510
511         return ret;
512 }
513
514 int rtw_resume_process23a(struct rtw_adapter *padapter)
515 {
516         struct net_device *pnetdev;
517         struct pwrctrl_priv *pwrpriv = NULL;
518         int ret = -1;
519         unsigned long start_time = jiffies;
520
521         DBG_8723A("==> %s (%s:%d)\n", __func__, current->comm, current->pid);
522
523         if (!padapter)
524                 goto exit;
525         pnetdev = padapter->pnetdev;
526         pwrpriv = &padapter->pwrctrlpriv;
527
528         down(&pwrpriv->lock);
529         rtw_reset_drv_sw23a(padapter);
530         pwrpriv->bkeepfwalive = false;
531
532         DBG_8723A("bkeepfwalive(%x)\n", pwrpriv->bkeepfwalive);
533         if (pm_netdev_open23a(pnetdev, true) != 0) {
534                 up(&pwrpriv->lock);
535                 goto exit;
536         }
537
538         netif_device_attach(pnetdev);
539         netif_carrier_on(pnetdev);
540
541         up(&pwrpriv->lock);
542
543         if (padapter->pid[1] != 0) {
544                 DBG_8723A("pid[1]:%d\n", padapter->pid[1]);
545                 kill_pid(find_vpid(padapter->pid[1]), SIGUSR2, 1);
546         }
547
548         rtw23a_roaming(padapter, NULL);
549
550         ret = 0;
551 exit:
552         if (pwrpriv)
553                 pwrpriv->bInSuspend = false;
554         DBG_8723A("<===  %s return %d.............. in %dms\n", __func__,
555                   ret, jiffies_to_msecs(jiffies - start_time));
556
557         return ret;
558 }
559
560 /*
561  * drv_init() - a device potentially for us
562  *
563  * notes: drv_init() is called when the bus driver has located a card
564  * for us to support.
565  *        We accept the new device by returning 0.
566  */
567 static struct rtw_adapter *rtw_usb_if1_init(struct dvobj_priv *dvobj,
568                                             struct usb_interface *pusb_intf,
569                                             const struct usb_device_id *pdid)
570 {
571         struct rtw_adapter *padapter = NULL;
572         struct net_device *pnetdev = NULL;
573         int status = _FAIL;
574
575         pnetdev = rtw_init_netdev23a(padapter);
576         if (!pnetdev)
577                 goto handle_dualmac;
578         padapter = netdev_priv(pnetdev);
579
580         padapter->dvobj = dvobj;
581         padapter->bDriverStopped = true;
582         dvobj->if1 = padapter;
583         dvobj->padapters[dvobj->iface_nums++] = padapter;
584         padapter->iface_id = IFACE_ID0;
585
586         rtl8723au_set_hw_type(padapter);
587
588         if (rtw_handle_dualmac23a(padapter, 1) != _SUCCESS)
589                 goto free_adapter;
590
591         SET_NETDEV_DEV(pnetdev, dvobj_to_dev(dvobj));
592
593         if (rtw_wdev_alloc(padapter, dvobj_to_dev(dvobj)))
594                 goto handle_dualmac;
595
596         /* step 2. allocate HalData */
597         padapter->HalData = kzalloc(sizeof(struct hal_data_8723a), GFP_KERNEL);
598         if (!padapter->HalData)
599                 goto free_wdev;
600
601         /* step read_chip_version */
602         rtl8723a_read_chip_version(padapter);
603
604         /* step usb endpoint mapping */
605         rtl8723au_chip_configure(padapter);
606
607         /* step read efuse/eeprom data and get mac_addr */
608         rtl8723a_read_adapter_info(padapter);
609
610         /* step 5. */
611         if (rtw_init_drv_sw23a(padapter) == _FAIL) {
612                 RT_TRACE(_module_hci_intfs_c_, _drv_err_,
613                          ("Initialize driver software resource Failed!\n"));
614                 goto free_hal_data;
615         }
616
617 #ifdef CONFIG_PM
618         if (padapter->pwrctrlpriv.bSupportRemoteWakeup) {
619                 dvobj->pusbdev->do_remote_wakeup = 1;
620                 pusb_intf->needs_remote_wakeup = 1;
621                 device_init_wakeup(&pusb_intf->dev, 1);
622                 DBG_8723A("\n  padapter->pwrctrlpriv.bSupportRemoteWakeup~~~~~~\n");
623                 DBG_8723A("\n  padapter->pwrctrlpriv.bSupportRemoteWakeup~~~[%d]~~~\n",
624                           device_may_wakeup(&pusb_intf->dev));
625         }
626 #endif
627         /* 2012-07-11 Move here to prevent the 8723AS-VAU BT
628          * auto suspend influence
629          */
630         if (usb_autopm_get_interface(pusb_intf) < 0)
631                 DBG_8723A("can't get autopm:\n");
632 #ifdef  CONFIG_8723AU_BT_COEXIST
633         padapter->pwrctrlpriv.autopm_cnt = 1;
634 #endif
635
636         /* If the eeprom mac address is corrupted, assign a random address */
637         if (is_broadcast_ether_addr(padapter->eeprompriv.mac_addr) ||
638             is_zero_ether_addr(padapter->eeprompriv.mac_addr))
639                 eth_random_addr(padapter->eeprompriv.mac_addr);
640
641         DBG_8723A("bDriverStopped:%d, bSurpriseRemoved:%d, bup:%d, hw_init_completed:%d\n",
642                   padapter->bDriverStopped, padapter->bSurpriseRemoved,
643                   padapter->bup, padapter->hw_init_completed
644         );
645         status = _SUCCESS;
646
647 free_hal_data:
648         if (status != _SUCCESS)
649                 kfree(padapter->HalData);
650 free_wdev:
651         if (status != _SUCCESS) {
652                 rtw_wdev_unregister(padapter->rtw_wdev);
653                 rtw_wdev_free(padapter->rtw_wdev);
654         }
655 handle_dualmac:
656         if (status != _SUCCESS)
657                 rtw_handle_dualmac23a(padapter, 0);
658 free_adapter:
659         if (status != _SUCCESS) {
660                 if (pnetdev)
661                         free_netdev(pnetdev);
662                 padapter = NULL;
663         }
664         return padapter;
665 }
666
667 static void rtw_usb_if1_deinit(struct rtw_adapter *if1)
668 {
669         struct net_device *pnetdev = if1->pnetdev;
670         struct mlme_priv *pmlmepriv = &if1->mlmepriv;
671
672         if (check_fwstate(pmlmepriv, _FW_LINKED))
673                 rtw_disassoc_cmd23a(if1, 0, false);
674
675 #ifdef CONFIG_8723AU_AP_MODE
676         free_mlme_ap_info23a(if1);
677 #endif
678
679         if (pnetdev)
680                 unregister_netdev(pnetdev); /* will call netdev_close() */
681
682         rtw_cancel_all_timer23a(if1);
683
684         rtw_dev_unload(if1);
685
686         DBG_8723A("+r871xu_dev_remove, hw_init_completed =%d\n",
687                   if1->hw_init_completed);
688
689         rtw_handle_dualmac23a(if1, 0);
690
691         if (if1->rtw_wdev) {
692                 rtw_wdev_unregister(if1->rtw_wdev);
693                 rtw_wdev_free(if1->rtw_wdev);
694         }
695
696 #ifdef CONFIG_8723AU_BT_COEXIST
697         if (1 == if1->pwrctrlpriv.autopm_cnt) {
698                 usb_autopm_put_interface(adapter_to_dvobj(if1)->pusbintf);
699                 if1->pwrctrlpriv.autopm_cnt--;
700         }
701 #endif
702
703         rtw_free_drv_sw23a(if1);
704
705         if (pnetdev)
706                 free_netdev(pnetdev);
707 }
708
709 static int rtw_drv_init(struct usb_interface *pusb_intf,
710                         const struct usb_device_id *pdid)
711 {
712         struct rtw_adapter *if1 = NULL;
713         struct dvobj_priv *dvobj;
714         int status = _FAIL;
715
716         RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+rtw_drv_init\n"));
717
718         /* Initialize dvobj_priv */
719         dvobj = usb_dvobj_init(pusb_intf);
720         if (!dvobj) {
721                 RT_TRACE(_module_hci_intfs_c_, _drv_err_,
722                          ("initialize device object priv Failed!\n"));
723                 goto exit;
724         }
725
726         if1 = rtw_usb_if1_init(dvobj, pusb_intf, pdid);
727         if (!if1) {
728                 DBG_8723A("rtw_init_primary_adapter Failed!\n");
729                 goto free_dvobj;
730         }
731
732         /* dev_alloc_name && register_netdev */
733         status = rtw_drv_register_netdev(if1);
734         if (status != _SUCCESS)
735                 goto free_if1;
736         RT_TRACE(_module_hci_intfs_c_, _drv_err_,
737                  ("-871x_drv - drv_init, success!\n"));
738
739         status = _SUCCESS;
740
741 free_if1:
742         if (status != _SUCCESS && if1)
743                 rtw_usb_if1_deinit(if1);
744 free_dvobj:
745         if (status != _SUCCESS)
746                 usb_dvobj_deinit(pusb_intf);
747 exit:
748         return status == _SUCCESS ? 0 : -ENODEV;
749 }
750
751 /* dev_remove() - our device is being removed */
752 static void rtw_disconnect(struct usb_interface *pusb_intf)
753 {
754         struct dvobj_priv *dvobj;
755         struct rtw_adapter *padapter;
756         struct net_device *pnetdev;
757         struct mlme_priv *pmlmepriv;
758
759         dvobj = usb_get_intfdata(pusb_intf);
760         if (!dvobj)
761                 return;
762
763         padapter = dvobj->if1;
764         pnetdev = padapter->pnetdev;
765         pmlmepriv = &padapter->mlmepriv;
766
767         usb_set_intfdata(pusb_intf, NULL);
768
769         RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+dev_remove()\n"));
770
771         rtw_pm_set_ips23a(padapter, IPS_NONE);
772         rtw_pm_set_lps23a(padapter, PS_MODE_ACTIVE);
773
774         LeaveAllPowerSaveMode23a(padapter);
775
776         rtw_usb_if1_deinit(padapter);
777
778         usb_dvobj_deinit(pusb_intf);
779
780         RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-dev_remove()\n"));
781         DBG_8723A("-r871xu_dev_remove, done\n");
782
783         return;
784 }
785
786 static int __init rtw_drv_entry(void)
787 {
788         RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+rtw_drv_entry\n"));
789         return usb_register(usb_drv);
790 }
791
792 static void __exit rtw_drv_halt(void)
793 {
794         RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+rtw_drv_halt\n"));
795         DBG_8723A("+rtw_drv_halt\n");
796
797         usb_deregister(usb_drv);
798
799         DBG_8723A("-rtw_drv_halt\n");
800 }
801
802 module_init(rtw_drv_entry);
803 module_exit(rtw_drv_halt);