/** * \fn wlanDrvIf_Destroy * \brief Destroy the driver instance * * Destroy all driver modules. * Release driver OS resources (IRQ, workqueue, events socket) * Release driver network interface. * Free init files memory. * Free driver object. * * \note * \param drv - The driver object handle * \return void * \sa wlanDrvIf_Create */ static void wlanDrvIf_Destroy (TWlanDrvIfObj *drv) { if (!drv) return; /* Release the driver network interface */ if (drv->netdev) { netif_stop_queue (drv->netdev); if (drv->tCommon.eDriverState != DRV_STATE_IDLE) { wlanDrvIf_Stop (drv->netdev); } unregister_netdev (drv->netdev); free_netdev (drv->netdev); } destroy_workqueue (drv->pWorkQueue); /* Destroy all driver modules */ if (drv->tCommon.hDrvMain) { drvMain_Destroy (drv->tCommon.hDrvMain); } /* close the ipc_kernel socket*/ if (drv && drv->wl_sock) { sock_release (drv->wl_sock->sk_socket); } /* Release the driver interrupt (or polling timer) */ #ifdef PRIODIC_INTERRUPT os_timerDestroy (drv, drv->hPollTimer); #else if (drv->irq) { hPlatform_freeInterrupt (drv); } #endif #ifdef CONFIG_HAS_WAKELOCK wake_lock_destroy(&drv->wl_wifi); wake_lock_destroy(&drv->wl_rxwake); #endif /* * Free init files memory */ if (drv->tCommon.tFwImage.pImage) { os_memoryFree (drv, drv->tCommon.tFwImage.pImage, drv->tCommon.tFwImage.uSize); #ifdef TI_MEM_ALLOC_TRACE os_printf ("MTT:%s:%d ::kfree(0x%p) : %d\n", __FUNCTION__, __LINE__, drv->tCommon.tFwImage.uSize, -drv->tCommon.tFwImage.uSize); #endif } if (drv->tCommon.tNvsImage.pImage) { kfree (drv->tCommon.tNvsImage.pImage); #ifdef TI_MEM_ALLOC_TRACE os_printf ("MTT:%s:%d ::kfree(0x%p) : %d\n", __FUNCTION__, __LINE__, drv->tCommon.tNvsImage.uSize, -drv->tCommon.tNvsImage.uSize); #endif } if (drv->tCommon.tIniFile.pImage) { kfree (drv->tCommon.tIniFile.pImage); #ifdef TI_MEM_ALLOC_TRACE os_printf ("MTT:%s:%d ::kfree(0x%p) : %d\n", __FUNCTION__, __LINE__, drv->tCommon.tIniFile.uSize, -drv->tCommon.tIniFile.uSize); #endif } /* Free the driver object */ #ifdef TI_DBG tb_destroy(); #endif kfree (drv); #ifdef CONFIG_PM /* unregister PM hooks from SDIO driver */ sdioDrv_register_pm(NULL, NULL); #endif }
/** * \fn wlanDrvIf_SetupNetif * \brief Setup driver network interface * * Called in driver creation process. * Setup driver network interface. * * \note * \param drv - The driver object handle * \return 0 - OK, else - failure * \sa */ static int wlanDrvIf_SetupNetif (TWlanDrvIfObj *drv) { struct net_device *dev; int res; /* Allocate network interface structure for the driver */ dev = alloc_etherdev (0); if (dev == NULL) { ti_dprintf (TIWLAN_LOG_ERROR, "alloc_etherdev() failed\n"); return -ENOMEM; } /* Setup the network interface */ ether_setup (dev); /* the following is required on at least BSP 23.8 and higher. Without it, the Open function of the driver will not be called when trying to 'ifconfig up' the interface */ //#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23) // dev->validate_addr = NULL; //#endif NETDEV_SET_PRIVATE(dev,drv); drv->netdev = dev; strcpy (dev->name, TIWLAN_DRV_IF_NAME); netif_carrier_off (dev); /* #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) dev->open = wlanDrvIf_Start; dev->stop = wlanDrvIf_Stop; #else dev->open = wlanDrvIf_Open; dev->stop = wlanDrvIf_Release; #endif */ /*dev->hard_start_xmit = wlanDrvIf_XmitDummy;*/ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) dev->netdev_ops = &tiwlan_netdev_ops; #else dev->open = wlanDrvIf_Start; dev->stop = wlanDrvIf_Stop; dev->hard_start_xmit = wlanDrvIf_Xmit; dev->addr_len = MAC_ADDR_LEN; dev->get_stats = wlanDrvIf_NetGetStat; dev->tx_queue_len = 100; dev->do_ioctl = NULL; #endif /* Initialize Wireless Extensions interface (WEXT) */ wlanDrvWext_Init (dev); res = register_netdev (dev); if (res != 0) { ti_dprintf (TIWLAN_LOG_ERROR, "register_netdev() failed : %d\n", res); kfree (dev); return res; } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) #if defined HOST_PLATFORM_OMAP3430 || defined HOST_PLATFORM_ZOOM2 || defined HOST_PLATFORM_ZOOM1 || defined HOST_PLATFORM_MX25 sdioDrv_register_pm(wlanDrvIf_pm_resume, wlanDrvIf_pm_suspend); #endif #else #ifdef CONFIG_PM sdioDrv_register_pm(wlanDrvIf_pm_resume, wlanDrvIf_pm_suspend); #endif #endif /* On the latest Kernel there is no more support for the below macro. */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) SET_MODULE_OWNER (dev); #endif return 0; }
/** * \fn wlanDrvIf_Create * \brief Create the driver instance * * Allocate driver object. * Initialize driver OS resources (IRQ, workqueue, events socket) * Setup driver network interface. * Create and link all driver modules. * * \note * \param void * \return 0 - OK, else - failure * \sa wlanDrvIf_Destroy */ static int wlanDrvIf_Create (void) { TWlanDrvIfObj *drv; int rc; /* Allocate driver's structure */ drv = kmalloc (sizeof(TWlanDrvIfObj), GFP_KERNEL); if (!drv) { return -ENOMEM; } #ifdef TI_DBG tb_init(TB_OPTION_NONE); #endif pDrvStaticHandle = drv; /* save for module destroy */ #ifdef TI_MEM_ALLOC_TRACE os_printf ("MTT:%s:%d ::kmalloc(%lu, %x) : %lu\n", __FUNCTION__, __LINE__, sizeof(TWlanDrvIfObj), GFP_KERNEL, sizeof(TWlanDrvIfObj)); #endif memset (drv, 0, sizeof(TWlanDrvIfObj)); drv->tCommon.eDriverState = DRV_STATE_IDLE; drv->pWorkQueue = create_singlethread_workqueue(TIWLAN_WQ_NAME); if (!drv->pWorkQueue) { return -ENOMEM; } drv->wl_packet = 0; drv->wl_count = 0; #ifdef CONFIG_HAS_WAKELOCK wake_lock_init(&drv->wl_wifi, WAKE_LOCK_SUSPEND, "wifi_wake"); wake_lock_init(&drv->wl_rxwake, WAKE_LOCK_SUSPEND, "wifi_rx_wake"); #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) INIT_WORK(&drv->tWork, wlanDrvIf_DriverTask, (void *)drv); #else INIT_WORK(&drv->tWork, wlanDrvIf_DriverTask); #endif spin_lock_init (&drv->lock); /* Setup driver network interface. */ rc = wlanDrvIf_SetupNetif (drv); if (rc) { kfree (drv); return rc; } /* Create the events socket interface */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) drv->wl_sock = netlink_kernel_create( NETLINK_USERSOCK, 0, NULL, THIS_MODULE ); #else drv->wl_sock = netlink_kernel_create(&init_net, NETLINK_USERSOCK, 0, NULL, NULL, THIS_MODULE ); #endif if (drv->wl_sock == NULL) { ti_dprintf (TIWLAN_LOG_ERROR, "netlink_kernel_create() failed !\n"); return -EINVAL; } /* Create all driver modules and link their handles */ drvMain_Create (drv, &drv->tCommon.hDrvMain, &drv->tCommon.hCmdHndlr, &drv->tCommon.hContext, &drv->tCommon.hTxDataQ, &drv->tCommon.hTxMgmtQ, &drv->tCommon.hTxCtrl, &drv->tCommon.hTWD, &drv->tCommon.hEvHandler, &drv->tCommon.hCmdDispatch, &drv->tCommon.hReport); /* * Initialize interrupts (or polling mode for debug): */ #ifdef PRIODIC_INTERRUPT /* Debug mode: Polling (the timer is started by HwInit process) */ drv->hPollTimer = os_timerCreate ((TI_HANDLE)drv, wlanDrvIf_PollIrqHandler, (TI_HANDLE)drv); #else /* Normal mode: Interrupts (the default mode) */ rc = hPlatform_initInterrupt (drv, (void*)wlanDrvIf_HandleInterrupt); if (rc) { ti_dprintf (TIWLAN_LOG_ERROR, "wlanDrvIf_Create(): Failed to register interrupt handler!\n"); return rc; } #endif /* PRIODIC_INTERRUPT */ #ifdef CONFIG_PM /* register PM hooks in our SDIO driver */ sdioDrv_register_pm(wlanDrvIf_Resume, wlanDrvIf_Suspend); #endif return 0; }