linux/drivers/staging/csr/sdio_events.c
<<
>>
Prefs
   1/*
   2 * ---------------------------------------------------------------------------
   3 * FILE:     sdio_events.c
   4 *
   5 * PURPOSE:
   6 *      Process the events received by the SDIO glue layer.
   7 *      Optional part of the porting exercise.
   8 *
   9 * Copyright (C) 2009 by Cambridge Silicon Radio Ltd.
  10 *
  11 * Refer to LICENSE.txt included with this source code for details on
  12 * the license terms.
  13 *
  14 * ---------------------------------------------------------------------------
  15 */
  16#include "unifi_priv.h"
  17
  18
  19/*
  20 * Porting Notes:
  21 * There are two ways to support the suspend/resume system events in a driver.
  22 * In some operating systems these events are delivered to the OS driver
  23 * directly from the system. In this case, the OS driver needs to pass these
  24 * events to the API described in the CSR SDIO Abstration API document.
  25 * In Linux, and other embedded operating systems, the suspend/resume events
  26 * come from the SDIO driver. In this case, simply get these events in the
  27 * SDIO glue layer and notify the OS layer.
  28 *
  29 * In either case, typically, the events are processed by the SME.
  30 * Use the unifi_sys_suspend_ind() and unifi_sys_resume_ind() to pass
  31 * the events to the SME.
  32 */
  33
  34/*
  35 * ---------------------------------------------------------------------------
  36 *  unifi_suspend
  37 *
  38 *      Handles a suspend request from the SDIO driver.
  39 *
  40 *  Arguments:
  41 *      ospriv          Pointer to OS driver context.
  42 *
  43 * ---------------------------------------------------------------------------
  44 */
  45void unifi_suspend(void *ospriv)
  46{
  47    unifi_priv_t *priv = ospriv;
  48    int interfaceTag=0;
  49
  50    /* For powered suspend, tell the resume's wifi_on() not to reinit UniFi */
  51    priv->wol_suspend = (enable_wol == UNIFI_WOL_OFF) ? FALSE : TRUE;
  52
  53    unifi_trace(priv, UDBG1, "unifi_suspend: wol_suspend %d, enable_wol %d",
  54                priv->wol_suspend, enable_wol );
  55
  56    /* Stop network traffic. */
  57    /* need to stop all the netdevices*/
  58    for( interfaceTag=0;interfaceTag<CSR_WIFI_NUM_INTERFACES;interfaceTag++)
  59    {
  60        netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag];
  61        if (interfacePriv->netdev_registered == 1)
  62        {
  63            if( priv->wol_suspend ) {
  64                unifi_trace(priv, UDBG1, "unifi_suspend: Don't netif_carrier_off");
  65            } else {
  66                unifi_trace(priv, UDBG1, "unifi_suspend: netif_carrier_off");
  67                netif_carrier_off(priv->netdev[interfaceTag]);
  68            }
  69            netif_tx_stop_all_queues(priv->netdev[interfaceTag]);
  70        }
  71    }
  72
  73    unifi_trace(priv, UDBG1, "unifi_suspend: suspend SME");
  74
  75    sme_sys_suspend(priv);
  76
  77} /* unifi_suspend() */
  78
  79
  80/*
  81 * ---------------------------------------------------------------------------
  82 *  unifi_resume
  83 *
  84 *      Handles a resume request from the SDIO driver.
  85 *
  86 *  Arguments:
  87 *      ospriv          Pointer to OS driver context.
  88 *
  89 * ---------------------------------------------------------------------------
  90 */
  91void unifi_resume(void *ospriv)
  92{
  93    unifi_priv_t *priv = ospriv;
  94    int interfaceTag=0;
  95    int r;
  96    int wol = priv->wol_suspend;
  97
  98    unifi_trace(priv, UDBG1, "unifi_resume: resume SME, enable_wol=%d", enable_wol);
  99
 100    /* The resume causes wifi-on which will re-enable the BH and reinstall the ISR */
 101    r = sme_sys_resume(priv);
 102    if (r) {
 103        unifi_error(priv, "Failed to resume UniFi\n");
 104    }
 105
 106    /* Resume the network interfaces. For the cold resume case, this will
 107     * happen upon reconnection.
 108     */
 109    if (wol) {
 110        unifi_trace(priv, UDBG1, "unifi_resume: try to enable carrier");
 111
 112        /* need to start all the netdevices*/
 113        for( interfaceTag=0;interfaceTag<CSR_WIFI_NUM_INTERFACES;interfaceTag++) {
 114            netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag];
 115
 116            unifi_trace(priv, UDBG1, "unifi_resume: interfaceTag %d netdev_registered %d mode %d\n",
 117                   interfaceTag, interfacePriv->netdev_registered, interfacePriv->interfaceMode);
 118
 119            if (interfacePriv->netdev_registered == 1)
 120            {
 121                netif_carrier_on(priv->netdev[interfaceTag]);
 122                netif_tx_start_all_queues(priv->netdev[interfaceTag]);
 123            }
 124        }
 125
 126        /* Kick the BH thread (with reason=host) to poll for data that may have
 127         * arrived during a powered suspend. This caters for the case where the SME
 128         * doesn't interact with the chip (e.g install autonomous scans) during resume.
 129         */
 130        unifi_send_signal(priv->card, NULL, 0, NULL);
 131    }
 132
 133} /* unifi_resume() */
 134
 135