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