| /* |
| * --------------------------------------------------------------------------- |
| * FILE: sdio_events.c |
| * |
| * PURPOSE: |
| * Process the events received by the SDIO glue layer. |
| * Optional part of the porting exercise. |
| * |
| * Copyright (C) 2009 by Cambridge Silicon Radio Ltd. |
| * |
| * Refer to LICENSE.txt included with this source code for details on |
| * the license terms. |
| * |
| * --------------------------------------------------------------------------- |
| */ |
| #include "unifi_priv.h" |
| |
| |
| /* |
| * Porting Notes: |
| * There are two ways to support the suspend/resume system events in a driver. |
| * In some operating systems these events are delivered to the OS driver |
| * directly from the system. In this case, the OS driver needs to pass these |
| * events to the API described in the CSR SDIO Abstration API document. |
| * In Linux, and other embedded operating systems, the suspend/resume events |
| * come from the SDIO driver. In this case, simply get these events in the |
| * SDIO glue layer and notify the OS layer. |
| * |
| * In either case, typically, the events are processed by the SME. |
| * Use the unifi_sys_suspend_ind() and unifi_sys_resume_ind() to pass |
| * the events to the SME. |
| */ |
| |
| /* |
| * --------------------------------------------------------------------------- |
| * 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]); |
| } |
| netif_tx_stop_all_queues(priv->netdev[interfaceTag]); |
| } |
| } |
| |
| unifi_trace(priv, UDBG1, "unifi_suspend: suspend SME"); |
| |
| sme_sys_suspend(priv); |
| |
| } /* unifi_suspend() */ |
| |
| |
| /* |
| * --------------------------------------------------------------------------- |
| * unifi_resume |
| * |
| * Handles a resume request from the SDIO driver. |
| * |
| * Arguments: |
| * ospriv Pointer to OS driver context. |
| * |
| * --------------------------------------------------------------------------- |
| */ |
| void unifi_resume(void *ospriv) |
| { |
| unifi_priv_t *priv = ospriv; |
| int interfaceTag=0; |
| int r; |
| int wol = priv->wol_suspend; |
| |
| unifi_trace(priv, UDBG1, "unifi_resume: resume SME, enable_wol=%d", enable_wol); |
| |
| /* The resume causes wifi-on which will re-enable the BH and reinstall the ISR */ |
| r = sme_sys_resume(priv); |
| if (r) { |
| unifi_error(priv, "Failed to resume UniFi\n"); |
| } |
| |
| /* Resume the network interfaces. For the cold resume case, this will |
| * happen upon reconnection. |
| */ |
| if (wol) { |
| unifi_trace(priv, UDBG1, "unifi_resume: try to enable carrier"); |
| |
| /* need to start all the netdevices*/ |
| for( interfaceTag=0;interfaceTag<CSR_WIFI_NUM_INTERFACES;interfaceTag++) { |
| netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; |
| |
| unifi_trace(priv, UDBG1, "unifi_resume: interfaceTag %d netdev_registered %d mode %d\n", |
| interfaceTag, interfacePriv->netdev_registered, interfacePriv->interfaceMode); |
| |
| if (interfacePriv->netdev_registered == 1) |
| { |
| netif_carrier_on(priv->netdev[interfaceTag]); |
| netif_tx_start_all_queues(priv->netdev[interfaceTag]); |
| } |
| } |
| |
| /* Kick the BH thread (with reason=host) to poll for data that may have |
| * arrived during a powered suspend. This caters for the case where the SME |
| * doesn't interact with the chip (e.g install autonomous scans) during resume. |
| */ |
| unifi_send_signal(priv->card, NULL, 0, NULL); |
| } |
| |
| } /* unifi_resume() */ |
| |