2 * ---------------------------------------------------------------------------
6 * Process the events received by the SDIO glue layer.
7 * Optional part of the porting exercise.
9 * Copyright (C) 2009 by Cambridge Silicon Radio Ltd.
11 * Refer to LICENSE.txt included with this source code for details on
14 * ---------------------------------------------------------------------------
16 #include "unifi_priv.h"
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.
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.
35 * ---------------------------------------------------------------------------
38 * Handles a suspend request from the SDIO driver.
41 * ospriv Pointer to OS driver context.
43 * ---------------------------------------------------------------------------
45 void unifi_suspend(void *ospriv
)
47 unifi_priv_t
*priv
= ospriv
;
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
;
53 unifi_trace(priv
, UDBG1
, "unifi_suspend: wol_suspend %d, enable_wol %d",
54 priv
->wol_suspend
, enable_wol
);
56 /* Stop network traffic. */
57 /* need to stop all the netdevices*/
58 for( interfaceTag
=0;interfaceTag
<CSR_WIFI_NUM_INTERFACES
;interfaceTag
++)
60 netInterface_priv_t
*interfacePriv
= priv
->interfacePriv
[interfaceTag
];
61 if (interfacePriv
->netdev_registered
== 1)
63 if( priv
->wol_suspend
) {
64 unifi_trace(priv
, UDBG1
, "unifi_suspend: Don't netif_carrier_off");
66 unifi_trace(priv
, UDBG1
, "unifi_suspend: netif_carrier_off");
67 netif_carrier_off(priv
->netdev
[interfaceTag
]);
69 UF_NETIF_TX_STOP_ALL_QUEUES(priv
->netdev
[interfaceTag
]);
73 unifi_trace(priv
, UDBG1
, "unifi_suspend: suspend SME");
75 sme_sys_suspend(priv
);
77 } /* unifi_suspend() */
81 * ---------------------------------------------------------------------------
84 * Handles a resume request from the SDIO driver.
87 * ospriv Pointer to OS driver context.
89 * ---------------------------------------------------------------------------
91 void unifi_resume(void *ospriv
)
93 unifi_priv_t
*priv
= ospriv
;
96 int wol
= priv
->wol_suspend
;
98 unifi_trace(priv
, UDBG1
, "unifi_resume: resume SME, enable_wol=%d", enable_wol
);
100 /* The resume causes wifi-on which will re-enable the BH and reinstall the ISR */
101 r
= sme_sys_resume(priv
);
103 unifi_error(priv
, "Failed to resume UniFi\n");
106 /* Resume the network interfaces. For the cold resume case, this will
107 * happen upon reconnection.
110 unifi_trace(priv
, UDBG1
, "unifi_resume: try to enable carrier");
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
];
116 unifi_trace(priv
, UDBG1
, "unifi_resume: interfaceTag %d netdev_registered %d mode %d\n",
117 interfaceTag
, interfacePriv
->netdev_registered
, interfacePriv
->interfaceMode
);
119 if (interfacePriv
->netdev_registered
== 1)
121 netif_carrier_on(priv
->netdev
[interfaceTag
]);
122 UF_NETIF_TX_START_ALL_QUEUES(priv
->netdev
[interfaceTag
]);
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.
130 unifi_send_signal(priv
->card
, NULL
, 0, NULL
);
133 } /* unifi_resume() */