zram: don't grab mutex in zram_slot_free_noity
[firefly-linux-kernel-4.4.55.git] / 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  */
45 void 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  */
91 void 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