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