135 lines
4.5 KiB
C
135 lines
4.5 KiB
C
/*
|
|
* ---------------------------------------------------------------------------
|
|
* 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]);
|
|
}
|
|
UF_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]);
|
|
UF_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() */
|
|
|