root/drivers/staging/rtl8188eu/os_dep/usb_intf.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. usb_dvobj_init
  2. usb_dvobj_deinit
  3. usb_intf_stop
  4. rtw_dev_unload
  5. rtw_suspend
  6. rtw_resume_process
  7. rtw_resume
  8. rtw_usb_if1_init
  9. rtw_usb_if1_deinit
  10. rtw_drv_init
  11. rtw_dev_remove

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

/* [<][>][^][v][top][bottom][index][help] */