root/drivers/staging/rtl8723bs/os_dep/sdio_intf.c

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

DEFINITIONS

This source file includes following definitions.
  1. sd_sync_int_hdl
  2. sdio_alloc_irq
  3. sdio_free_irq
  4. gpio_hostwakeup_irq_thread
  5. gpio_hostwakeup_alloc_irq
  6. gpio_hostwakeup_free_irq
  7. sdio_init
  8. sdio_deinit
  9. sdio_dvobj_init
  10. sdio_dvobj_deinit
  11. rtw_set_hal_ops
  12. sd_intf_start
  13. sd_intf_stop
  14. rtw_sdio_if1_init
  15. rtw_sdio_if1_deinit
  16. rtw_drv_init
  17. rtw_dev_remove
  18. rtw_sdio_suspend
  19. rtw_resume_process
  20. rtw_sdio_resume
  21. rtw_drv_entry
  22. rtw_drv_halt

   1 // SPDX-License-Identifier: GPL-2.0
   2 /******************************************************************************
   3  *
   4  * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
   5  *
   6  ******************************************************************************/
   7 #define _HCI_INTF_C_
   8 
   9 #include <drv_types.h>
  10 #include <rtw_debug.h>
  11 #include <hal_btcoex.h>
  12 #include <linux/jiffies.h>
  13 
  14 #ifndef dev_to_sdio_func
  15 #define dev_to_sdio_func(d)     container_of(d, struct sdio_func, dev)
  16 #endif
  17 
  18 static const struct sdio_device_id sdio_ids[] =
  19 {
  20         { SDIO_DEVICE(0x024c, 0x0523), },
  21         { SDIO_DEVICE(0x024c, 0x0525), },
  22         { SDIO_DEVICE(0x024c, 0x0623), },
  23         { SDIO_DEVICE(0x024c, 0x0626), },
  24         { SDIO_DEVICE(0x024c, 0xb723), },
  25         { /* end: all zeroes */                         },
  26 };
  27 MODULE_DEVICE_TABLE(sdio, sdio_ids);
  28 
  29 static int rtw_drv_init(struct sdio_func *func, const struct sdio_device_id *id);
  30 static void rtw_dev_remove(struct sdio_func *func);
  31 static int rtw_sdio_resume(struct device *dev);
  32 static int rtw_sdio_suspend(struct device *dev);
  33 
  34 static const struct dev_pm_ops rtw_sdio_pm_ops = {
  35         .suspend        = rtw_sdio_suspend,
  36         .resume = rtw_sdio_resume,
  37 };
  38 
  39 struct sdio_drv_priv {
  40         struct sdio_driver r871xs_drv;
  41         int drv_registered;
  42 };
  43 
  44 static struct sdio_drv_priv sdio_drvpriv = {
  45         .r871xs_drv.probe = rtw_drv_init,
  46         .r871xs_drv.remove = rtw_dev_remove,
  47         .r871xs_drv.name = "rtl8723bs",
  48         .r871xs_drv.id_table = sdio_ids,
  49         .r871xs_drv.drv = {
  50                 .pm = &rtw_sdio_pm_ops,
  51         }
  52 };
  53 
  54 static void sd_sync_int_hdl(struct sdio_func *func)
  55 {
  56         struct dvobj_priv *psdpriv;
  57 
  58 
  59         psdpriv = sdio_get_drvdata(func);
  60 
  61         if (!psdpriv->if1) {
  62                 DBG_871X("%s if1 == NULL\n", __func__);
  63                 return;
  64         }
  65 
  66         rtw_sdio_set_irq_thd(psdpriv, current);
  67         sd_int_hdl(psdpriv->if1);
  68         rtw_sdio_set_irq_thd(psdpriv, NULL);
  69 }
  70 
  71 static int sdio_alloc_irq(struct dvobj_priv *dvobj)
  72 {
  73         struct sdio_data *psdio_data;
  74         struct sdio_func *func;
  75         int err;
  76 
  77         psdio_data = &dvobj->intf_data;
  78         func = psdio_data->func;
  79 
  80         sdio_claim_host(func);
  81 
  82         err = sdio_claim_irq(func, &sd_sync_int_hdl);
  83         if (err) {
  84                 dvobj->drv_dbg.dbg_sdio_alloc_irq_error_cnt++;
  85                 printk(KERN_CRIT "%s: sdio_claim_irq FAIL(%d)!\n", __func__, err);
  86         } else {
  87                 dvobj->drv_dbg.dbg_sdio_alloc_irq_cnt++;
  88                 dvobj->irq_alloc = 1;
  89         }
  90 
  91         sdio_release_host(func);
  92 
  93         return err?_FAIL:_SUCCESS;
  94 }
  95 
  96 static void sdio_free_irq(struct dvobj_priv *dvobj)
  97 {
  98         struct sdio_data *psdio_data;
  99         struct sdio_func *func;
 100         int err;
 101 
 102         if (dvobj->irq_alloc) {
 103                 psdio_data = &dvobj->intf_data;
 104                 func = psdio_data->func;
 105 
 106                 if (func) {
 107                         sdio_claim_host(func);
 108                         err = sdio_release_irq(func);
 109                         if (err) {
 110                                 dvobj->drv_dbg.dbg_sdio_free_irq_error_cnt++;
 111                                 DBG_871X_LEVEL(_drv_err_,"%s: sdio_release_irq FAIL(%d)!\n", __func__, err);
 112                         } else
 113                                 dvobj->drv_dbg.dbg_sdio_free_irq_cnt++;
 114                         sdio_release_host(func);
 115                 }
 116                 dvobj->irq_alloc = 0;
 117         }
 118 }
 119 
 120 #ifdef CONFIG_GPIO_WAKEUP
 121 extern unsigned int oob_irq;
 122 static irqreturn_t gpio_hostwakeup_irq_thread(int irq, void *data)
 123 {
 124         struct adapter *padapter = data;
 125         DBG_871X_LEVEL(_drv_always_, "gpio_hostwakeup_irq_thread\n");
 126         /* Disable interrupt before calling handler */
 127         /* disable_irq_nosync(oob_irq); */
 128         rtw_lock_suspend_timeout(HZ/2);
 129         return IRQ_HANDLED;
 130 }
 131 
 132 static u8 gpio_hostwakeup_alloc_irq(struct adapter *padapter)
 133 {
 134         int err;
 135         if (oob_irq == 0) {
 136                 DBG_871X("oob_irq ZERO!\n");
 137                 return _FAIL;
 138         }
 139         /* dont set it IRQF_TRIGGER_LOW, or wowlan */
 140         /* power is high after suspend */
 141         /* and failing can prevent can not sleep issue if */
 142         /* wifi gpio12 pin is not linked with CPU */
 143         err = request_threaded_irq(oob_irq, gpio_hostwakeup_irq_thread, NULL,
 144                 /* IRQF_TRIGGER_LOW | IRQF_ONESHOT, */
 145                 IRQF_TRIGGER_FALLING,
 146                 "rtw_wifi_gpio_wakeup", padapter);
 147         if (err < 0) {
 148                 DBG_871X("Oops: can't allocate gpio irq %d err:%d\n", oob_irq, err);
 149                 return false;
 150         } else {
 151                 DBG_871X("allocate gpio irq %d ok\n", oob_irq);
 152         }
 153 
 154         enable_irq_wake(oob_irq);
 155         return _SUCCESS;
 156 }
 157 
 158 static void gpio_hostwakeup_free_irq(struct adapter *padapter)
 159 {
 160         if (oob_irq == 0)
 161                 return;
 162 
 163         disable_irq_wake(oob_irq);
 164         free_irq(oob_irq, padapter);
 165 }
 166 #endif
 167 
 168 static u32 sdio_init(struct dvobj_priv *dvobj)
 169 {
 170         struct sdio_data *psdio_data;
 171         struct sdio_func *func;
 172         int err;
 173 
 174         psdio_data = &dvobj->intf_data;
 175         func = psdio_data->func;
 176 
 177         /* 3 1. init SDIO bus */
 178         sdio_claim_host(func);
 179 
 180         err = sdio_enable_func(func);
 181         if (err) {
 182                 dvobj->drv_dbg.dbg_sdio_init_error_cnt++;
 183                 DBG_8192C(KERN_CRIT "%s: sdio_enable_func FAIL(%d)!\n", __func__, err);
 184                 goto release;
 185         }
 186 
 187         err = sdio_set_block_size(func, 512);
 188         if (err) {
 189                 dvobj->drv_dbg.dbg_sdio_init_error_cnt++;
 190                 DBG_8192C(KERN_CRIT "%s: sdio_set_block_size FAIL(%d)!\n", __func__, err);
 191                 goto release;
 192         }
 193         psdio_data->block_transfer_len = 512;
 194         psdio_data->tx_block_mode = 1;
 195         psdio_data->rx_block_mode = 1;
 196 
 197 release:
 198         sdio_release_host(func);
 199 
 200         if (err)
 201                 return _FAIL;
 202         return _SUCCESS;
 203 }
 204 
 205 static void sdio_deinit(struct dvobj_priv *dvobj)
 206 {
 207         struct sdio_func *func;
 208         int err;
 209 
 210 
 211         RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("+sdio_deinit\n"));
 212 
 213         func = dvobj->intf_data.func;
 214 
 215         if (func) {
 216                 sdio_claim_host(func);
 217                 err = sdio_disable_func(func);
 218                 if (err) {
 219                         dvobj->drv_dbg.dbg_sdio_deinit_error_cnt++;
 220                         DBG_8192C(KERN_ERR "%s: sdio_disable_func(%d)\n", __func__, err);
 221                 }
 222 
 223                 if (dvobj->irq_alloc) {
 224                         err = sdio_release_irq(func);
 225                         if (err) {
 226                                 dvobj->drv_dbg.dbg_sdio_free_irq_error_cnt++;
 227                                 DBG_8192C(KERN_ERR "%s: sdio_release_irq(%d)\n", __func__, err);
 228                         } else
 229                                 dvobj->drv_dbg.dbg_sdio_free_irq_cnt++;
 230                 }
 231 
 232                 sdio_release_host(func);
 233         }
 234 }
 235 static struct dvobj_priv *sdio_dvobj_init(struct sdio_func *func)
 236 {
 237         int status = _FAIL;
 238         struct dvobj_priv *dvobj = NULL;
 239         struct sdio_data *psdio;
 240 
 241         dvobj = devobj_init();
 242         if (dvobj == NULL) {
 243                 goto exit;
 244         }
 245 
 246         sdio_set_drvdata(func, dvobj);
 247 
 248         psdio = &dvobj->intf_data;
 249         psdio->func = func;
 250 
 251         if (sdio_init(dvobj) != _SUCCESS) {
 252                 RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("%s: initialize SDIO Failed!\n", __func__));
 253                 goto free_dvobj;
 254         }
 255         rtw_reset_continual_io_error(dvobj);
 256         status = _SUCCESS;
 257 
 258 free_dvobj:
 259         if (status != _SUCCESS && dvobj) {
 260                 sdio_set_drvdata(func, NULL);
 261 
 262                 devobj_deinit(dvobj);
 263 
 264                 dvobj = NULL;
 265         }
 266 exit:
 267         return dvobj;
 268 }
 269 
 270 static void sdio_dvobj_deinit(struct sdio_func *func)
 271 {
 272         struct dvobj_priv *dvobj = sdio_get_drvdata(func);
 273 
 274         sdio_set_drvdata(func, NULL);
 275         if (dvobj) {
 276                 sdio_deinit(dvobj);
 277                 devobj_deinit(dvobj);
 278         }
 279         return;
 280 }
 281 
 282 void rtw_set_hal_ops(struct adapter *padapter)
 283 {
 284         /* alloc memory for HAL DATA */
 285         rtw_hal_data_init(padapter);
 286 
 287         rtl8723bs_set_hal_ops(padapter);
 288 }
 289 
 290 static void sd_intf_start(struct adapter *padapter)
 291 {
 292         if (padapter == NULL) {
 293                 DBG_8192C(KERN_ERR "%s: padapter is NULL!\n", __func__);
 294                 return;
 295         }
 296 
 297         /*  hal dep */
 298         rtw_hal_enable_interrupt(padapter);
 299 }
 300 
 301 static void sd_intf_stop(struct adapter *padapter)
 302 {
 303         if (padapter == NULL) {
 304                 DBG_8192C(KERN_ERR "%s: padapter is NULL!\n", __func__);
 305                 return;
 306         }
 307 
 308         /*  hal dep */
 309         rtw_hal_disable_interrupt(padapter);
 310 }
 311 
 312 
 313 static struct adapter *rtw_sdio_if1_init(struct dvobj_priv *dvobj, const struct sdio_device_id  *pdid)
 314 {
 315         int status = _FAIL;
 316         struct net_device *pnetdev;
 317         struct adapter *padapter = NULL;
 318         struct sdio_data *psdio = &dvobj->intf_data;
 319 
 320         padapter = vzalloc(sizeof(*padapter));
 321         if (padapter == NULL) {
 322                 goto exit;
 323         }
 324 
 325         padapter->dvobj = dvobj;
 326         dvobj->if1 = padapter;
 327 
 328         padapter->bDriverStopped =true;
 329 
 330         dvobj->padapters = padapter;
 331         padapter->iface_id = 0;
 332 
 333         /* 3 1. init network device data */
 334         pnetdev = rtw_init_netdev(padapter);
 335         if (!pnetdev)
 336                 goto free_adapter;
 337 
 338         SET_NETDEV_DEV(pnetdev, dvobj_to_dev(dvobj));
 339 
 340         padapter = rtw_netdev_priv(pnetdev);
 341 
 342         rtw_wdev_alloc(padapter, dvobj_to_dev(dvobj));
 343 
 344         /* 3 3. init driver special setting, interface, OS and hardware relative */
 345 
 346         /* 4 3.1 set hardware operation functions */
 347         rtw_set_hal_ops(padapter);
 348 
 349 
 350         /* 3 5. initialize Chip version */
 351         padapter->intf_start = &sd_intf_start;
 352         padapter->intf_stop = &sd_intf_stop;
 353 
 354         padapter->intf_init = &sdio_init;
 355         padapter->intf_deinit = &sdio_deinit;
 356         padapter->intf_alloc_irq = &sdio_alloc_irq;
 357         padapter->intf_free_irq = &sdio_free_irq;
 358 
 359         if (rtw_init_io_priv(padapter, sdio_set_intf_ops) == _FAIL) {
 360                 RT_TRACE(_module_hci_intfs_c_, _drv_err_,
 361                         ("rtw_drv_init: Can't init io_priv\n"));
 362                 goto free_hal_data;
 363         }
 364 
 365         rtw_hal_read_chip_version(padapter);
 366 
 367         rtw_hal_chip_configure(padapter);
 368 
 369         hal_btcoex_Initialize((void *) padapter);
 370 
 371         /* 3 6. read efuse/eeprom data */
 372         rtw_hal_read_chip_info(padapter);
 373 
 374         /* 3 7. init driver common data */
 375         if (rtw_init_drv_sw(padapter) == _FAIL) {
 376                 RT_TRACE(_module_hci_intfs_c_, _drv_err_,
 377                          ("rtw_drv_init: Initialize driver software resource Failed!\n"));
 378                 goto free_hal_data;
 379         }
 380 
 381         /* 3 8. get WLan MAC address */
 382         /*  set mac addr */
 383         rtw_macaddr_cfg(&psdio->func->dev, padapter->eeprompriv.mac_addr);
 384 
 385         rtw_hal_disable_interrupt(padapter);
 386 
 387         DBG_871X("bDriverStopped:%d, bSurpriseRemoved:%d, bup:%d, hw_init_completed:%d\n"
 388                 , padapter->bDriverStopped
 389                 , padapter->bSurpriseRemoved
 390                 , padapter->bup
 391                 , padapter->hw_init_completed
 392         );
 393 
 394         status = _SUCCESS;
 395 
 396 free_hal_data:
 397         if (status != _SUCCESS && padapter->HalData)
 398                 kfree(padapter->HalData);
 399 
 400         if (status != _SUCCESS) {
 401                 rtw_wdev_unregister(padapter->rtw_wdev);
 402                 rtw_wdev_free(padapter->rtw_wdev);
 403         }
 404 
 405 free_adapter:
 406         if (status != _SUCCESS) {
 407                 if (pnetdev)
 408                         rtw_free_netdev(pnetdev);
 409                 else
 410                         vfree((u8 *)padapter);
 411                 padapter = NULL;
 412         }
 413 exit:
 414         return padapter;
 415 }
 416 
 417 static void rtw_sdio_if1_deinit(struct adapter *if1)
 418 {
 419         struct net_device *pnetdev = if1->pnetdev;
 420         struct mlme_priv *pmlmepriv = &if1->mlmepriv;
 421 
 422         if (check_fwstate(pmlmepriv, _FW_LINKED))
 423                 rtw_disassoc_cmd(if1, 0, false);
 424 
 425         free_mlme_ap_info(if1);
 426 
 427 #ifdef CONFIG_GPIO_WAKEUP
 428         gpio_hostwakeup_free_irq(if1);
 429 #endif
 430 
 431         rtw_cancel_all_timer(if1);
 432 
 433 #ifdef CONFIG_WOWLAN
 434         adapter_to_pwrctl(if1)->wowlan_mode =false;
 435         DBG_871X_LEVEL(_drv_always_, "%s wowlan_mode:%d\n", __func__, adapter_to_pwrctl(if1)->wowlan_mode);
 436 #endif /* CONFIG_WOWLAN */
 437 
 438         rtw_dev_unload(if1);
 439         DBG_871X("+r871xu_dev_remove, hw_init_completed =%d\n", if1->hw_init_completed);
 440 
 441         if (if1->rtw_wdev) {
 442                 rtw_wdev_free(if1->rtw_wdev);
 443         }
 444 
 445         rtw_free_drv_sw(if1);
 446 
 447         if (pnetdev)
 448                 rtw_free_netdev(pnetdev);
 449 }
 450 
 451 /*
 452  * drv_init() - a device potentially for us
 453  *
 454  * notes: drv_init() is called when the bus driver has located a card for us to support.
 455  *        We accept the new device by returning 0.
 456  */
 457 static int rtw_drv_init(
 458         struct sdio_func *func,
 459         const struct sdio_device_id *id)
 460 {
 461         int status = _FAIL;
 462         struct adapter *if1 = NULL, *if2 = NULL;
 463         struct dvobj_priv *dvobj;
 464 
 465         dvobj = sdio_dvobj_init(func);
 466         if (dvobj == NULL) {
 467                 RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("initialize device object priv Failed!\n"));
 468                 goto exit;
 469         }
 470 
 471         if1 = rtw_sdio_if1_init(dvobj, id);
 472         if (if1 == NULL) {
 473                 DBG_871X("rtw_init_primarystruct adapter Failed!\n");
 474                 goto free_dvobj;
 475         }
 476 
 477         /* dev_alloc_name && register_netdev */
 478         status = rtw_drv_register_netdev(if1);
 479         if (status != _SUCCESS)
 480                 goto free_if2;
 481 
 482         if (sdio_alloc_irq(dvobj) != _SUCCESS)
 483                 goto free_if2;
 484 
 485 #ifdef  CONFIG_GPIO_WAKEUP
 486         gpio_hostwakeup_alloc_irq(if1);
 487 #endif
 488 
 489         RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-871x_drv - drv_init, success!\n"));
 490 
 491         rtw_ndev_notifier_register();
 492         status = _SUCCESS;
 493 
 494 free_if2:
 495         if (status != _SUCCESS && if2) {
 496         }
 497         if (status != _SUCCESS && if1) {
 498                 rtw_sdio_if1_deinit(if1);
 499         }
 500 free_dvobj:
 501         if (status != _SUCCESS)
 502                 sdio_dvobj_deinit(func);
 503 exit:
 504         return status == _SUCCESS?0:-ENODEV;
 505 }
 506 
 507 static void rtw_dev_remove(struct sdio_func *func)
 508 {
 509         struct dvobj_priv *dvobj = sdio_get_drvdata(func);
 510         struct adapter *padapter = dvobj->if1;
 511 
 512         RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("+rtw_dev_remove\n"));
 513 
 514         dvobj->processing_dev_remove = true;
 515 
 516         rtw_unregister_netdevs(dvobj);
 517 
 518         if (padapter->bSurpriseRemoved == false) {
 519                 int err;
 520 
 521                 /* test surprise remove */
 522                 sdio_claim_host(func);
 523                 sdio_readb(func, 0, &err);
 524                 sdio_release_host(func);
 525                 if (err == -ENOMEDIUM) {
 526                         padapter->bSurpriseRemoved = true;
 527                         DBG_871X(KERN_NOTICE "%s: device had been removed!\n", __func__);
 528                 }
 529         }
 530 
 531         rtw_ps_deny(padapter, PS_DENY_DRV_REMOVE);
 532 
 533         rtw_pm_set_ips(padapter, IPS_NONE);
 534         rtw_pm_set_lps(padapter, PS_MODE_ACTIVE);
 535 
 536         LeaveAllPowerSaveMode(padapter);
 537 
 538         rtw_btcoex_HaltNotify(padapter);
 539 
 540         rtw_sdio_if1_deinit(padapter);
 541 
 542         sdio_dvobj_deinit(func);
 543 
 544         RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("-rtw_dev_remove\n"));
 545 }
 546 
 547 extern int pm_netdev_open(struct net_device *pnetdev, u8 bnormal);
 548 extern int pm_netdev_close(struct net_device *pnetdev, u8 bnormal);
 549 
 550 static int rtw_sdio_suspend(struct device *dev)
 551 {
 552         struct sdio_func *func =dev_to_sdio_func(dev);
 553         struct dvobj_priv *psdpriv = sdio_get_drvdata(func);
 554         struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(psdpriv);
 555         struct adapter *padapter = psdpriv->if1;
 556         struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
 557 
 558         if (padapter->bDriverStopped == true) {
 559                 DBG_871X("%s bDriverStopped = %d\n", __func__, padapter->bDriverStopped);
 560                 return 0;
 561         }
 562 
 563         if (pwrpriv->bInSuspend == true) {
 564                 DBG_871X("%s bInSuspend = %d\n", __func__, pwrpriv->bInSuspend);
 565                 pdbgpriv->dbg_suspend_error_cnt++;
 566                 return 0;
 567         }
 568 
 569         return rtw_suspend_common(padapter);
 570 }
 571 
 572 static int rtw_resume_process(struct adapter *padapter)
 573 {
 574         struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
 575         struct dvobj_priv *psdpriv = padapter->dvobj;
 576         struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
 577 
 578         if (pwrpriv->bInSuspend == false) {
 579                 pdbgpriv->dbg_resume_error_cnt++;
 580                 DBG_871X("%s bInSuspend = %d\n", __func__, pwrpriv->bInSuspend);
 581                 return -1;
 582         }
 583 
 584         return rtw_resume_common(padapter);
 585 }
 586 
 587 static int rtw_sdio_resume(struct device *dev)
 588 {
 589         struct sdio_func *func =dev_to_sdio_func(dev);
 590         struct dvobj_priv *psdpriv = sdio_get_drvdata(func);
 591         struct adapter *padapter = psdpriv->if1;
 592         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 593         int ret = 0;
 594         struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
 595 
 596         DBG_871X("==> %s (%s:%d)\n", __func__, current->comm, current->pid);
 597 
 598         pdbgpriv->dbg_resume_cnt++;
 599 
 600         ret = rtw_resume_process(padapter);
 601 
 602         pmlmeext->last_scan_time = jiffies;
 603         DBG_871X("<========  %s return %d\n", __func__, ret);
 604         return ret;
 605 }
 606 
 607 static int __init rtw_drv_entry(void)
 608 {
 609         int ret = 0;
 610 
 611         DBG_871X_LEVEL(_drv_always_, "module init start\n");
 612         dump_drv_version(RTW_DBGDUMP);
 613 #ifdef BTCOEXVERSION
 614         DBG_871X_LEVEL(_drv_always_, "rtl8723bs BT-Coex version = %s\n", BTCOEXVERSION);
 615 #endif /*  BTCOEXVERSION */
 616 
 617         sdio_drvpriv.drv_registered = true;
 618 
 619         ret = sdio_register_driver(&sdio_drvpriv.r871xs_drv);
 620         if (ret != 0) {
 621                 sdio_drvpriv.drv_registered = false;
 622                 rtw_ndev_notifier_unregister();
 623                 DBG_871X("%s: register driver failed!!(%d)\n", __func__, ret);
 624                 goto exit;
 625         }
 626 
 627         goto exit;
 628 
 629 exit:
 630         DBG_871X_LEVEL(_drv_always_, "module init ret =%d\n", ret);
 631         return ret;
 632 }
 633 
 634 static void __exit rtw_drv_halt(void)
 635 {
 636         DBG_871X_LEVEL(_drv_always_, "module exit start\n");
 637 
 638         sdio_drvpriv.drv_registered = false;
 639 
 640         sdio_unregister_driver(&sdio_drvpriv.r871xs_drv);
 641 
 642         rtw_ndev_notifier_unregister();
 643 
 644         DBG_871X_LEVEL(_drv_always_, "module exit success\n");
 645 
 646         rtw_mstat_dump(RTW_DBGDUMP);
 647 }
 648 
 649 
 650 module_init(rtw_drv_entry);
 651 module_exit(rtw_drv_halt);

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