/* * --------------------------------------------------------------------------- * unifi_suspend * * Handles a suspend request from the SDIO driver. * * Arguments: * ospriv Pointer to OS driver context. * * --------------------------------------------------------------------------- */ void unifi_suspend(void *ospriv) { unifi_priv_t *priv = ospriv; int interfaceTag=0; /* For powered suspend, tell the resume's wifi_on() not to reinit UniFi */ priv->wol_suspend = (enable_wol == UNIFI_WOL_OFF) ? FALSE : TRUE; unifi_trace(priv, UDBG1, "unifi_suspend: wol_suspend %d, enable_wol %d", priv->wol_suspend, enable_wol ); /* Stop network traffic. */ /* need to stop all the netdevices*/ for( interfaceTag=0;interfaceTag<CSR_WIFI_NUM_INTERFACES;interfaceTag++) { netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; if (interfacePriv->netdev_registered == 1) { if( priv->wol_suspend ) { unifi_trace(priv, UDBG1, "unifi_suspend: Don't netif_carrier_off"); } else { unifi_trace(priv, UDBG1, "unifi_suspend: netif_carrier_off"); netif_carrier_off(priv->netdev[interfaceTag]); } UF_NETIF_TX_STOP_ALL_QUEUES(priv->netdev[interfaceTag]); } } unifi_trace(priv, UDBG1, "unifi_suspend: suspend SME"); sme_sys_suspend(priv); } /* unifi_suspend() */
/* * --------------------------------------------------------------------------- * unregister_unifi_sdio * * Call from SDIO driver when it detects that UniFi has been removed. * * Arguments: * bus_id Number of the card that was ejected. * * Returns: * None. * --------------------------------------------------------------------------- */ static void unregister_unifi_sdio(int bus_id) { unifi_priv_t *priv; int interfaceTag=0; u8 reason = CONFIG_IND_EXIT; if ((bus_id < 0) || (bus_id >= MAX_UNIFI_DEVS)) { unifi_error(NULL, "unregister_unifi_sdio: invalid device %d\n", bus_id); return; } priv = Unifi_instances[bus_id]; if (priv == NULL) { unifi_error(priv, "unregister_unifi_sdio: device %d is not registered\n", bus_id); func_exit(); return; } /* Stop the network traffic before freeing the core. */ for(interfaceTag=0;interfaceTag<priv->totalInterfaceCount;interfaceTag++) { netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; if(interfacePriv->netdev_registered) { netif_carrier_off(priv->netdev[interfaceTag]); UF_NETIF_TX_STOP_ALL_QUEUES(priv->netdev[interfaceTag]); } } #ifdef CSR_NATIVE_LINUX /* * If the unifi thread was started, signal it to stop. This * should cause any userspace processes with open unifi device to * close them. */ uf_stop_thread(priv, &priv->bh_thread); /* Unregister the interrupt handler */ if (csr_sdio_linux_remove_irq(priv->sdio)) { unifi_notice(priv, "csr_sdio_linux_remove_irq failed to talk to card.\n"); } /* Ensure no MLME functions are waiting on a the mlme_event semaphore. */ uf_abort_mlme(priv); #endif /* CSR_NATIVE_LINUX */ #ifdef CSR_WIFI_NAPI_ENABLE { int i; for (i = 0; i < CSR_WIFI_NUM_INTERFACES; i++) { napi_deinit(&priv->interfacePriv[i]->napi, &priv->interfacePriv[i]->napi_skb_list); } } #endif ul_log_config_ind(priv, &reason, sizeof(u8)); /* Deregister the UDI hook from the core. */ unifi_remove_udi_hook(priv->card, logging_handler); uf_put_instance(bus_id); /* * Wait until the device is cleaned up. i.e., when all userspace * processes have closed any open unifi devices. */ wait_event(Unifi_cleanup_wq, In_use[bus_id] == UNIFI_DEV_CLEANUP); unifi_trace(NULL, UDBG5, "Received clean up event\n"); /* Now we can free the private context and the char device nodes */ cleanup_unifi_sdio(priv); } /* unregister_unifi_sdio() */