Commit | Line | Data |
---|---|---|
c2478d39 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 | * | |
c2478d39 | 14 | ******************************************************************************/ |
c2478d39 | 15 | |
9aa39bc4 | 16 | #define pr_fmt(fmt) "R8188EU: " fmt |
c2478d39 LF |
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> | |
c2478d39 | 22 | #include <linux/usb.h> |
d249db9e | 23 | #include <linux/vmalloc.h> |
0a0796eb | 24 | #include <mon.h> |
c2478d39 LF |
25 | #include <osdep_intf.h> |
26 | ||
17452ee9 | 27 | #include <usb_ops_linux.h> |
c2478d39 LF |
28 | #include <usb_hal.h> |
29 | #include <rtw_ioctl.h> | |
30 | ||
c2478d39 LF |
31 | #define USB_VENDER_ID_REALTEK 0x0bda |
32 | ||
33 | /* DID_USB_v916_20130116 */ | |
34 | static struct usb_device_id rtw_usb_id_tbl[] = { | |
35 | /*=== Realtek demoboard ===*/ | |
36 | {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8179)}, /* 8188EUS */ | |
37 | {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x0179)}, /* 8188ETV */ | |
38 | /*=== Customer ID ===*/ | |
39 | /****** 8188EUS ********/ | |
a2fa6721 | 40 | {USB_DEVICE(0x056e, 0x4008)}, /* Elecom WDC-150SU2M */ |
08951f10 | 41 | {USB_DEVICE(0x07b8, 0x8179)}, /* Abocom - Abocom */ |
df3f4edc | 42 | {USB_DEVICE(0x2001, 0x330F)}, /* DLink DWA-125 REV D1 */ |
260ea9c2 | 43 | {USB_DEVICE(0x2001, 0x3310)}, /* Dlink DWA-123 REV D1 */ |
6d4556fc | 44 | {USB_DEVICE(0x2001, 0x3311)}, /* DLink GO-USB-N150 REV B1 */ |
8626d524 | 45 | {USB_DEVICE(0x0df6, 0x0076)}, /* Sitecom N150 v2 */ |
c2478d39 LF |
46 | {} /* Terminating entry */ |
47 | }; | |
48 | ||
49 | MODULE_DEVICE_TABLE(usb, rtw_usb_id_tbl); | |
50 | ||
c2478d39 LF |
51 | static struct dvobj_priv *usb_dvobj_init(struct usb_interface *usb_intf) |
52 | { | |
53 | int i; | |
c2478d39 LF |
54 | struct dvobj_priv *pdvobjpriv; |
55 | struct usb_host_config *phost_conf; | |
56 | struct usb_config_descriptor *pconf_desc; | |
57 | struct usb_host_interface *phost_iface; | |
58 | struct usb_interface_descriptor *piface_desc; | |
c2478d39 LF |
59 | struct usb_endpoint_descriptor *pendp_desc; |
60 | struct usb_device *pusbd; | |
61 | ||
fadbe0cd | 62 | pdvobjpriv = kzalloc(sizeof(*pdvobjpriv), GFP_KERNEL); |
574502ca | 63 | if (!pdvobjpriv) |
586b0632 | 64 | return NULL; |
c2478d39 LF |
65 | |
66 | pdvobjpriv->pusbintf = usb_intf; | |
67 | pusbd = interface_to_usbdev(usb_intf); | |
68 | pdvobjpriv->pusbdev = pusbd; | |
69 | usb_set_intfdata(usb_intf, pdvobjpriv); | |
70 | ||
71 | pdvobjpriv->RtNumInPipes = 0; | |
72 | pdvobjpriv->RtNumOutPipes = 0; | |
73 | ||
74 | phost_conf = pusbd->actconfig; | |
75 | pconf_desc = &phost_conf->desc; | |
76 | ||
77 | phost_iface = &usb_intf->altsetting[0]; | |
78 | piface_desc = &phost_iface->desc; | |
79 | ||
80 | pdvobjpriv->NumInterfaces = pconf_desc->bNumInterfaces; | |
81 | pdvobjpriv->InterfaceNumber = piface_desc->bInterfaceNumber; | |
c2478d39 | 82 | |
c6724919 | 83 | for (i = 0; i < piface_desc->bNumEndpoints; i++) { |
73fbfbfe | 84 | int ep_num; |
6179ed59 JS |
85 | pendp_desc = &phost_iface->endpoint[i].desc; |
86 | ||
87 | ep_num = usb_endpoint_num(pendp_desc); | |
88 | ||
89 | if (usb_endpoint_is_bulk_in(pendp_desc)) { | |
90 | pdvobjpriv->RtInPipe[pdvobjpriv->RtNumInPipes] = ep_num; | |
91 | pdvobjpriv->RtNumInPipes++; | |
92 | } else if (usb_endpoint_is_int_in(pendp_desc)) { | |
93 | pdvobjpriv->RtInPipe[pdvobjpriv->RtNumInPipes] = ep_num; | |
94 | pdvobjpriv->RtNumInPipes++; | |
95 | } else if (usb_endpoint_is_bulk_out(pendp_desc)) { | |
96 | pdvobjpriv->RtOutPipe[pdvobjpriv->RtNumOutPipes] = | |
97 | ep_num; | |
98 | pdvobjpriv->RtNumOutPipes++; | |
c2478d39 LF |
99 | } |
100 | } | |
101 | ||
21335144 | 102 | if (pusbd->speed == USB_SPEED_HIGH) |
c2478d39 | 103 | pdvobjpriv->ishighspeed = true; |
21335144 | 104 | else |
c2478d39 | 105 | pdvobjpriv->ishighspeed = false; |
c2478d39 | 106 | |
418f9642 | 107 | mutex_init(&pdvobjpriv->usb_vendor_req_mutex); |
705a3136 | 108 | usb_get_dev(pusbd); |
586b0632 | 109 | |
c2478d39 LF |
110 | return pdvobjpriv; |
111 | } | |
112 | ||
113 | static void usb_dvobj_deinit(struct usb_interface *usb_intf) | |
114 | { | |
115 | struct dvobj_priv *dvobj = usb_get_intfdata(usb_intf); | |
116 | ||
c2478d39 LF |
117 | usb_set_intfdata(usb_intf, NULL); |
118 | if (dvobj) { | |
119 | /* Modify condition for 92DU DMDP 2010.11.18, by Thomas */ | |
120 | if ((dvobj->NumInterfaces != 2 && | |
121 | dvobj->NumInterfaces != 3) || | |
122 | (dvobj->InterfaceNumber == 1)) { | |
123 | if (interface_to_usbdev(usb_intf)->state != | |
124 | USB_STATE_NOTATTACHED) { | |
125 | /* If we didn't unplug usb dongle and | |
126 | * remove/insert module, driver fails | |
127 | * on sitesurvey for the first time when | |
128 | * device is up . Reset usb port for sitesurvey | |
129 | * fail issue. */ | |
9aa39bc4 | 130 | pr_debug("usb attached..., try to reset usb device\n"); |
c2478d39 LF |
131 | usb_reset_device(interface_to_usbdev(usb_intf)); |
132 | } | |
133 | } | |
f0e7a514 | 134 | |
f0e7a514 | 135 | mutex_destroy(&dvobj->usb_vendor_req_mutex); |
c2478d39 LF |
136 | kfree(dvobj); |
137 | } | |
138 | ||
139 | usb_put_dev(interface_to_usbdev(usb_intf)); | |
140 | ||
c2478d39 LF |
141 | } |
142 | ||
c2478d39 LF |
143 | static void usb_intf_start(struct adapter *padapter) |
144 | { | |
145 | RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+usb_intf_start\n")); | |
146 | ||
147 | rtw_hal_inirp_init(padapter); | |
148 | ||
149 | RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-usb_intf_start\n")); | |
150 | } | |
151 | ||
152 | static void usb_intf_stop(struct adapter *padapter) | |
153 | { | |
154 | RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+usb_intf_stop\n")); | |
155 | ||
8895f04b | 156 | /* disable_hw_interrupt */ |
c2478d39 LF |
157 | if (!padapter->bSurpriseRemoved) { |
158 | /* device still exists, so driver can do i/o operation */ | |
159 | /* TODO: */ | |
160 | RT_TRACE(_module_hci_intfs_c_, _drv_err_, | |
161 | ("SurpriseRemoved == false\n")); | |
162 | } | |
163 | ||
164 | /* cancel in irp */ | |
165 | rtw_hal_inirp_deinit(padapter); | |
166 | ||
167 | /* cancel out irp */ | |
14af3550 | 168 | usb_write_port_cancel(padapter); |
c2478d39 LF |
169 | |
170 | /* todo:cancel other irps */ | |
171 | ||
172 | RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-usb_intf_stop\n")); | |
173 | } | |
174 | ||
175 | static void rtw_dev_unload(struct adapter *padapter) | |
176 | { | |
177 | RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+rtw_dev_unload\n")); | |
178 | ||
179 | if (padapter->bup) { | |
9aa39bc4 | 180 | pr_debug("===> rtw_dev_unload\n"); |
c2478d39 LF |
181 | padapter->bDriverStopped = true; |
182 | if (padapter->xmitpriv.ack_tx) | |
183 | rtw_ack_tx_done(&padapter->xmitpriv, RTW_SCTX_DONE_DRV_STOP); | |
184 | /* s3. */ | |
185 | if (padapter->intf_stop) | |
186 | padapter->intf_stop(padapter); | |
187 | /* s4. */ | |
188 | if (!padapter->pwrctrlpriv.bInternalAutoSuspend) | |
189 | rtw_stop_drv_threads(padapter); | |
190 | ||
191 | /* s5. */ | |
192 | if (!padapter->bSurpriseRemoved) { | |
193 | rtw_hal_deinit(padapter); | |
194 | padapter->bSurpriseRemoved = true; | |
195 | } | |
196 | ||
197 | padapter->bup = false; | |
198 | } else { | |
199 | RT_TRACE(_module_hci_intfs_c_, _drv_err_, | |
200 | ("r871x_dev_unload():padapter->bup == false\n")); | |
201 | } | |
202 | ||
9aa39bc4 | 203 | pr_debug("<=== rtw_dev_unload\n"); |
c2478d39 LF |
204 | |
205 | RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-rtw_dev_unload\n")); | |
206 | } | |
207 | ||
c2478d39 LF |
208 | static int rtw_suspend(struct usb_interface *pusb_intf, pm_message_t message) |
209 | { | |
210 | struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf); | |
211 | struct adapter *padapter = dvobj->if1; | |
212 | struct net_device *pnetdev = padapter->pnetdev; | |
213 | struct mlme_priv *pmlmepriv = &padapter->mlmepriv; | |
214 | struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; | |
ed737494 | 215 | unsigned long start_time = jiffies; |
c2478d39 | 216 | |
9aa39bc4 | 217 | pr_debug("==> %s (%s:%d)\n", __func__, current->comm, current->pid); |
c2478d39 LF |
218 | |
219 | if ((!padapter->bup) || (padapter->bDriverStopped) || | |
220 | (padapter->bSurpriseRemoved)) { | |
9aa39bc4 | 221 | pr_debug("padapter->bup=%d bDriverStopped=%d bSurpriseRemoved = %d\n", |
c2478d39 LF |
222 | padapter->bup, padapter->bDriverStopped, |
223 | padapter->bSurpriseRemoved); | |
224 | goto exit; | |
225 | } | |
226 | ||
227 | pwrpriv->bInSuspend = true; | |
228 | rtw_cancel_all_timer(padapter); | |
229 | LeaveAllPowerSaveMode(padapter); | |
230 | ||
f18c566e | 231 | mutex_lock(&pwrpriv->mutex_lock); |
c2478d39 LF |
232 | /* s1. */ |
233 | if (pnetdev) { | |
234 | netif_carrier_off(pnetdev); | |
945c0972 | 235 | netif_tx_stop_all_queues(pnetdev); |
c2478d39 LF |
236 | } |
237 | ||
238 | /* s2. */ | |
239 | rtw_disassoc_cmd(padapter, 0, false); | |
240 | ||
241 | if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) && | |
242 | check_fwstate(pmlmepriv, _FW_LINKED)) { | |
9aa39bc4 | 243 | pr_debug("%s:%d %s(%pM), length:%d assoc_ssid.length:%d\n", |
c2478d39 LF |
244 | __func__, __LINE__, |
245 | pmlmepriv->cur_network.network.Ssid.Ssid, | |
246 | pmlmepriv->cur_network.network.MacAddress, | |
247 | pmlmepriv->cur_network.network.Ssid.SsidLength, | |
248 | pmlmepriv->assoc_ssid.SsidLength); | |
249 | ||
250 | pmlmepriv->to_roaming = 1; | |
251 | } | |
252 | /* s2-2. indicate disconnect to os */ | |
253 | rtw_indicate_disconnect(padapter); | |
254 | /* s2-3. */ | |
b4ba3b57 | 255 | rtw_free_assoc_resources(padapter); |
c2478d39 LF |
256 | /* s2-4. */ |
257 | rtw_free_network_queue(padapter, true); | |
258 | ||
259 | rtw_dev_unload(padapter); | |
f18c566e | 260 | mutex_unlock(&pwrpriv->mutex_lock); |
c2478d39 LF |
261 | |
262 | if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) | |
263 | rtw_indicate_scan_done(padapter, 1); | |
264 | ||
265 | if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) | |
266 | rtw_indicate_disconnect(padapter); | |
267 | ||
268 | exit: | |
7d708e52 | 269 | pr_debug("<=== %s .............. in %dms\n", __func__, |
ed737494 | 270 | jiffies_to_msecs(jiffies - start_time)); |
c2478d39 | 271 | |
7d708e52 | 272 | return 0; |
c2478d39 LF |
273 | } |
274 | ||
0aba3f41 | 275 | static int rtw_resume_process(struct adapter *padapter) |
c2478d39 LF |
276 | { |
277 | struct net_device *pnetdev; | |
278 | struct pwrctrl_priv *pwrpriv = NULL; | |
279 | int ret = -1; | |
ed737494 | 280 | unsigned long start_time = jiffies; |
c2478d39 | 281 | |
9aa39bc4 | 282 | pr_debug("==> %s (%s:%d)\n", __func__, current->comm, current->pid); |
c2478d39 LF |
283 | |
284 | if (padapter) { | |
285 | pnetdev = padapter->pnetdev; | |
286 | pwrpriv = &padapter->pwrctrlpriv; | |
287 | } else { | |
288 | goto exit; | |
289 | } | |
290 | ||
f18c566e | 291 | mutex_lock(&pwrpriv->mutex_lock); |
c2478d39 | 292 | rtw_reset_drv_sw(padapter); |
89b90c68 | 293 | pwrpriv->bkeepfwalive = false; |
c2478d39 | 294 | |
9aa39bc4 | 295 | pr_debug("bkeepfwalive(%x)\n", pwrpriv->bkeepfwalive); |
c2478d39 LF |
296 | if (pm_netdev_open(pnetdev, true) != 0) |
297 | goto exit; | |
298 | ||
299 | netif_device_attach(pnetdev); | |
300 | netif_carrier_on(pnetdev); | |
301 | ||
f18c566e | 302 | mutex_unlock(&pwrpriv->mutex_lock); |
c2478d39 | 303 | |
c2478d39 LF |
304 | rtw_roaming(padapter, NULL); |
305 | ||
306 | ret = 0; | |
307 | exit: | |
eaf47b71 | 308 | if (pwrpriv) { |
c2478d39 | 309 | pwrpriv->bInSuspend = false; |
eaf47b71 WY |
310 | mutex_unlock(&pwrpriv->mutex_lock); |
311 | } | |
9aa39bc4 | 312 | pr_debug("<=== %s return %d.............. in %dms\n", __func__, |
ed737494 | 313 | ret, jiffies_to_msecs(jiffies - start_time)); |
c2478d39 | 314 | |
c2478d39 LF |
315 | return ret; |
316 | } | |
317 | ||
0aba3f41 | 318 | static int rtw_resume(struct usb_interface *pusb_intf) |
319 | { | |
320 | struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf); | |
321 | struct adapter *padapter = dvobj->if1; | |
322 | ||
323 | return rtw_resume_process(padapter); | |
324 | } | |
325 | ||
c2478d39 LF |
326 | /* |
327 | * drv_init() - a device potentially for us | |
328 | * | |
329 | * notes: drv_init() is called when the bus driver has located | |
330 | * a card for us to support. | |
331 | * We accept the new device by returning 0. | |
332 | */ | |
333 | ||
334 | static struct adapter *rtw_usb_if1_init(struct dvobj_priv *dvobj, | |
335 | struct usb_interface *pusb_intf, const struct usb_device_id *pdid) | |
336 | { | |
337 | struct adapter *padapter = NULL; | |
338 | struct net_device *pnetdev = NULL; | |
0a0796eb | 339 | struct net_device *pmondev; |
c2478d39 LF |
340 | int status = _FAIL; |
341 | ||
2397c6e0 | 342 | padapter = (struct adapter *)vzalloc(sizeof(*padapter)); |
c2478d39 LF |
343 | if (padapter == NULL) |
344 | goto exit; | |
345 | padapter->dvobj = dvobj; | |
346 | dvobj->if1 = padapter; | |
347 | ||
348 | padapter->bDriverStopped = true; | |
fc8b5ae9 | 349 | mutex_init(&padapter->hw_init_mutex); |
c2478d39 | 350 | |
c2478d39 LF |
351 | pnetdev = rtw_init_netdev(padapter); |
352 | if (pnetdev == NULL) | |
0f56c6e9 | 353 | goto free_adapter; |
c2478d39 LF |
354 | SET_NETDEV_DEV(pnetdev, dvobj_to_dev(dvobj)); |
355 | padapter = rtw_netdev_priv(pnetdev); | |
356 | ||
0a0796eb JS |
357 | if (padapter->registrypriv.monitor_enable) { |
358 | pmondev = rtl88eu_mon_init(); | |
359 | if (pmondev == NULL) | |
360 | netdev_warn(pnetdev, "Failed to initialize monitor interface"); | |
361 | padapter->pmondev = pmondev; | |
362 | } | |
363 | ||
c2478d39 | 364 | /* step 2. hook HalFunc, allocate HalData */ |
6559b8b5 | 365 | rtl8188eu_set_hal_ops(padapter); |
c2478d39 LF |
366 | |
367 | padapter->intf_start = &usb_intf_start; | |
368 | padapter->intf_stop = &usb_intf_stop; | |
369 | ||
c2478d39 LF |
370 | /* step read_chip_version */ |
371 | rtw_hal_read_chip_version(padapter); | |
372 | ||
373 | /* step usb endpoint mapping */ | |
374 | rtw_hal_chip_configure(padapter); | |
375 | ||
376 | /* step read efuse/eeprom data and get mac_addr */ | |
377 | rtw_hal_read_chip_info(padapter); | |
378 | ||
379 | /* step 5. */ | |
380 | if (rtw_init_drv_sw(padapter) == _FAIL) { | |
381 | RT_TRACE(_module_hci_intfs_c_, _drv_err_, | |
382 | ("Initialize driver software resource Failed!\n")); | |
383 | goto free_hal_data; | |
384 | } | |
385 | ||
386 | #ifdef CONFIG_PM | |
387 | if (padapter->pwrctrlpriv.bSupportRemoteWakeup) { | |
388 | dvobj->pusbdev->do_remote_wakeup = 1; | |
389 | pusb_intf->needs_remote_wakeup = 1; | |
390 | device_init_wakeup(&pusb_intf->dev, 1); | |
9aa39bc4 SM |
391 | pr_debug("\n padapter->pwrctrlpriv.bSupportRemoteWakeup~~~~~~\n"); |
392 | pr_debug("\n padapter->pwrctrlpriv.bSupportRemoteWakeup~~~[%d]~~~\n", | |
c2478d39 LF |
393 | device_may_wakeup(&pusb_intf->dev)); |
394 | } | |
395 | #endif | |
396 | ||
397 | /* 2012-07-11 Move here to prevent the 8723AS-VAU BT auto | |
398 | * suspend influence */ | |
399 | if (usb_autopm_get_interface(pusb_intf) < 0) | |
9aa39bc4 | 400 | pr_debug("can't get autopm:\n"); |
c2478d39 LF |
401 | |
402 | /* alloc dev name after read efuse. */ | |
403 | rtw_init_netdev_name(pnetdev, padapter->registrypriv.ifname); | |
404 | rtw_macaddr_cfg(padapter->eeprompriv.mac_addr); | |
c2478d39 | 405 | memcpy(pnetdev->dev_addr, padapter->eeprompriv.mac_addr, ETH_ALEN); |
9aa39bc4 | 406 | pr_debug("MAC Address from pnetdev->dev_addr = %pM\n", |
c2478d39 LF |
407 | pnetdev->dev_addr); |
408 | ||
409 | /* step 6. Tell the network stack we exist */ | |
410 | if (register_netdev(pnetdev) != 0) { | |
411 | RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("register_netdev() failed\n")); | |
412 | goto free_hal_data; | |
413 | } | |
414 | ||
9aa39bc4 | 415 | pr_debug("bDriverStopped:%d, bSurpriseRemoved:%d, bup:%d, hw_init_completed:%d\n" |
c2478d39 LF |
416 | , padapter->bDriverStopped |
417 | , padapter->bSurpriseRemoved | |
418 | , padapter->bup | |
419 | , padapter->hw_init_completed | |
420 | ); | |
421 | ||
422 | status = _SUCCESS; | |
423 | ||
424 | free_hal_data: | |
dc2f9db9 | 425 | if (status != _SUCCESS) |
c2478d39 | 426 | kfree(padapter->HalData); |
c2478d39 LF |
427 | free_adapter: |
428 | if (status != _SUCCESS) { | |
429 | if (pnetdev) | |
430 | rtw_free_netdev(pnetdev); | |
2c10efbd | 431 | else |
03bd6aea | 432 | vfree(padapter); |
c2478d39 LF |
433 | padapter = NULL; |
434 | } | |
435 | exit: | |
436 | return padapter; | |
437 | } | |
438 | ||
439 | static void rtw_usb_if1_deinit(struct adapter *if1) | |
440 | { | |
441 | struct net_device *pnetdev = if1->pnetdev; | |
442 | struct mlme_priv *pmlmepriv = &if1->mlmepriv; | |
443 | ||
444 | if (check_fwstate(pmlmepriv, _FW_LINKED)) | |
445 | rtw_disassoc_cmd(if1, 0, false); | |
446 | ||
447 | #ifdef CONFIG_88EU_AP_MODE | |
448 | free_mlme_ap_info(if1); | |
449 | #endif | |
450 | ||
ac66b628 LC |
451 | if (pnetdev) |
452 | unregister_netdev(pnetdev); /* will call netdev_close() */ | |
453 | ||
0a0796eb | 454 | rtl88eu_mon_deinit(if1->pmondev); |
c2478d39 LF |
455 | rtw_cancel_all_timer(if1); |
456 | ||
457 | rtw_dev_unload(if1); | |
9aa39bc4 | 458 | pr_debug("+r871xu_dev_remove, hw_init_completed=%d\n", |
c2478d39 | 459 | if1->hw_init_completed); |
c2478d39 | 460 | rtw_free_drv_sw(if1); |
a4e320b7 | 461 | rtw_free_netdev(pnetdev); |
c2478d39 LF |
462 | } |
463 | ||
464 | static int rtw_drv_init(struct usb_interface *pusb_intf, const struct usb_device_id *pdid) | |
465 | { | |
466 | struct adapter *if1 = NULL; | |
c2478d39 LF |
467 | struct dvobj_priv *dvobj; |
468 | ||
c2478d39 LF |
469 | /* Initialize dvobj_priv */ |
470 | dvobj = usb_dvobj_init(pusb_intf); | |
2e48f0df | 471 | if (!dvobj) { |
c2478d39 LF |
472 | RT_TRACE(_module_hci_intfs_c_, _drv_err_, |
473 | ("initialize device object priv Failed!\n")); | |
474 | goto exit; | |
475 | } | |
476 | ||
477 | if1 = rtw_usb_if1_init(dvobj, pusb_intf, pdid); | |
2e48f0df | 478 | if (!if1) { |
9aa39bc4 | 479 | pr_debug("rtw_init_primarystruct adapter Failed!\n"); |
c2478d39 LF |
480 | goto free_dvobj; |
481 | } | |
482 | ||
e0732f84 | 483 | return 0; |
c2478d39 | 484 | |
c2478d39 | 485 | free_dvobj: |
e0732f84 | 486 | usb_dvobj_deinit(pusb_intf); |
c2478d39 | 487 | exit: |
e0732f84 | 488 | return -ENODEV; |
c2478d39 LF |
489 | } |
490 | ||
491 | /* | |
492 | * dev_remove() - our device is being removed | |
493 | */ | |
494 | /* rmmod module & unplug(SurpriseRemoved) will call r871xu_dev_remove() => how to recognize both */ | |
495 | static void rtw_dev_remove(struct usb_interface *pusb_intf) | |
496 | { | |
497 | struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf); | |
498 | struct adapter *padapter = dvobj->if1; | |
499 | ||
9aa39bc4 | 500 | pr_debug("+rtw_dev_remove\n"); |
c2478d39 LF |
501 | RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+dev_remove()\n")); |
502 | ||
c824795c | 503 | if (!pusb_intf->unregistering) |
c2478d39 LF |
504 | padapter->bSurpriseRemoved = true; |
505 | ||
506 | rtw_pm_set_ips(padapter, IPS_NONE); | |
507 | rtw_pm_set_lps(padapter, PS_MODE_ACTIVE); | |
508 | ||
509 | LeaveAllPowerSaveMode(padapter); | |
510 | ||
511 | rtw_usb_if1_deinit(padapter); | |
512 | ||
513 | usb_dvobj_deinit(pusb_intf); | |
514 | ||
515 | RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-dev_remove()\n")); | |
9aa39bc4 | 516 | pr_debug("-r871xu_dev_remove, done\n"); |
c2478d39 LF |
517 | } |
518 | ||
5e2b1f15 | 519 | static struct usb_driver rtl8188e_usb_drv = { |
520 | .name = "r8188eu", | |
521 | .probe = rtw_drv_init, | |
522 | .disconnect = rtw_dev_remove, | |
523 | .id_table = rtw_usb_id_tbl, | |
524 | .suspend = rtw_suspend, | |
525 | .resume = rtw_resume, | |
526 | .reset_resume = rtw_resume, | |
527 | }; | |
528 | ||
774cce1e | 529 | module_usb_driver(rtl8188e_usb_drv) |