/** * \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; if (drv->tiwlan_wq) { cancel_work_sync(&drv->tWork); flush_workqueue(drv->tiwlan_wq); } /* Release the driver network interface */ if (drv->netdev) { netif_stop_queue (drv->netdev); wlanDrvIf_Stop (drv->netdev); unregister_netdev (drv->netdev); free_netdev (drv->netdev); } /* 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 if (drv->tiwlan_wq) destroy_workqueue(drv->tiwlan_wq); #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); }
/** * \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) { /* Release the driver network interface */ if (drv->netdev) { netif_stop_queue (drv->netdev); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) wlanDrvIf_Stop (drv->netdev); #endif unregister_netdev (drv->netdev); free_netdev(drv->netdev); } #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)) cancel_work_sync (&drv->tWork); #else cancel_delayed_work (&drv->tWork); #endif flush_workqueue (drv->pWorkQueue); 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) { free_irq (drv->irq, drv); drv->irq=NULL; hPlatform_freeInterrupt (); } #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); }
/** * \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; /* Dm: Failure is not cleaned properly !!! */ 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)); /* Dm: drv->irq = TNETW_IRQ; */ drv->tCommon.eDriverState = DRV_STATE_IDLE; drv->tiwlan_wq = create_freezeable_workqueue(DRIVERWQ_NAME); if (!drv->tiwlan_wq) { ti_dprintf (TIWLAN_LOG_ERROR, "wlanDrvIf_Create(): Failed to create workQ!\n"); rc = -EINVAL; goto drv_create_end_1; } 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) { goto drv_create_end_2; } /* 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"); rc = -EINVAL; goto drv_create_end_3; } /* Create all driver modules and link their handles */ rc = 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); if (rc != TI_OK) { ti_dprintf (TIWLAN_LOG_ERROR, "%s: Failed to dvrMain_Create!\n", __func__); rc = -EINVAL; goto drv_create_end_4; } /* * 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 1 //wait to debug if (rc) { ti_dprintf (TIWLAN_LOG_ERROR, "wlanDrvIf_Create(): Failed to register interrupt handler!\n"); goto drv_create_end_5; } #endif #endif /* PRIODIC_INTERRUPT */ return 0; #if 1 //wait to debug drv_create_end_5: /* Destroy all driver modules */ if (drv->tCommon.hDrvMain) { drvMain_Destroy (drv->tCommon.hDrvMain); } #endif drv_create_end_4: if (drv->wl_sock) { sock_release (drv->wl_sock->sk_socket); } drv_create_end_3: /* Release the driver network interface */ if (drv->netdev) { unregister_netdev (drv->netdev); free_netdev (drv->netdev); } drv_create_end_2: #ifdef CONFIG_HAS_WAKELOCK wake_lock_destroy(&drv->wl_wifi); wake_lock_destroy(&drv->wl_rxwake); #endif if (drv->tiwlan_wq) destroy_workqueue(drv->tiwlan_wq); drv_create_end_1: kfree(drv); printk("%s: Fail\n", __func__); return rc; }