Root/drivers/staging/csr/sdio_events.c

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            UF_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                UF_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

Archive Download this file



interactive