/** 
 * \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);
}
Exemple #2
0
/** 
 * \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;
}