PageRenderTime 57ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/drivers/staging/vt6656/power.c

https://bitbucket.org/wisechild/galaxy-nexus
C | 345 lines | 159 code | 62 blank | 124 comment | 42 complexity | 514bb36dfae5ded4c017d9c6dcb59fe5 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
  1. /*
  2. * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  3. * All rights reserved.
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along
  16. * with this program; if not, write to the Free Software Foundation, Inc.,
  17. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  18. *
  19. *
  20. * File: power.c
  21. *
  22. * Purpose: Handles 802.11 power management functions
  23. *
  24. * Author: Lyndon Chen
  25. *
  26. * Date: July 17, 2002
  27. *
  28. * Functions:
  29. * PSvEnablePowerSaving - Enable Power Saving Mode
  30. * PSvDiasblePowerSaving - Disable Power Saving Mode
  31. * PSbConsiderPowerDown - Decide if we can Power Down
  32. * PSvSendPSPOLL - Send PS-POLL packet
  33. * PSbSendNullPacket - Send Null packet
  34. * PSbIsNextTBTTWakeUp - Decide if we need to wake up at next Beacon
  35. *
  36. * Revision History:
  37. *
  38. */
  39. #include "ttype.h"
  40. #include "mac.h"
  41. #include "device.h"
  42. #include "wmgr.h"
  43. #include "power.h"
  44. #include "wcmd.h"
  45. #include "rxtx.h"
  46. #include "card.h"
  47. #include "control.h"
  48. #include "rndis.h"
  49. /*--------------------- Static Definitions -------------------------*/
  50. /*--------------------- Static Classes ----------------------------*/
  51. /*--------------------- Static Variables --------------------------*/
  52. static int msglevel = MSG_LEVEL_INFO;
  53. /*--------------------- Static Functions --------------------------*/
  54. /*--------------------- Export Variables --------------------------*/
  55. /*--------------------- Export Functions --------------------------*/
  56. /*
  57. *
  58. * Routine Description:
  59. * Enable hw power saving functions
  60. *
  61. * Return Value:
  62. * None.
  63. *
  64. */
  65. void PSvEnablePowerSaving(void *hDeviceContext,
  66. WORD wListenInterval)
  67. {
  68. PSDevice pDevice = (PSDevice)hDeviceContext;
  69. PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
  70. WORD wAID = pMgmt->wCurrAID | BIT14 | BIT15;
  71. /* set period of power up before TBTT */
  72. MACvWriteWord(pDevice, MAC_REG_PWBT, C_PWBT);
  73. if (pDevice->eOPMode != OP_MODE_ADHOC) {
  74. /* set AID */
  75. MACvWriteWord(pDevice, MAC_REG_AIDATIM, wAID);
  76. } else {
  77. /* set ATIM Window */
  78. /* MACvWriteATIMW(pDevice->PortOffset, pMgmt->wCurrATIMWindow); */
  79. }
  80. /* Warren:06-18-2004,the sequence must follow PSEN->AUTOSLEEP->GO2DOZE */
  81. /* enable power saving hw function */
  82. MACvRegBitsOn(pDevice, MAC_REG_PSCTL, PSCTL_PSEN);
  83. /* Set AutoSleep */
  84. MACvRegBitsOn(pDevice, MAC_REG_PSCFG, PSCFG_AUTOSLEEP);
  85. /* Warren:MUST turn on this once before turn on AUTOSLEEP ,or the AUTOSLEEP doesn't work */
  86. MACvRegBitsOn(pDevice, MAC_REG_PSCTL, PSCTL_GO2DOZE);
  87. if (wListenInterval >= 2) {
  88. /* clear always listen beacon */
  89. MACvRegBitsOff(pDevice, MAC_REG_PSCTL, PSCTL_ALBCN);
  90. /* first time set listen next beacon */
  91. MACvRegBitsOn(pDevice, MAC_REG_PSCTL, PSCTL_LNBCN);
  92. pMgmt->wCountToWakeUp = wListenInterval;
  93. } else {
  94. /* always listen beacon */
  95. MACvRegBitsOn(pDevice, MAC_REG_PSCTL, PSCTL_ALBCN);
  96. pMgmt->wCountToWakeUp = 0;
  97. }
  98. pDevice->bEnablePSMode = TRUE;
  99. /* We don't send null pkt in ad hoc mode since beacon will handle this. */
  100. if (pDevice->eOPMode == OP_MODE_INFRASTRUCTURE)
  101. PSbSendNullPacket(pDevice);
  102. pDevice->bPWBitOn = TRUE;
  103. DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "PS:Power Saving Mode Enable...\n");
  104. }
  105. /*
  106. *
  107. * Routine Description:
  108. * Disable hw power saving functions
  109. *
  110. * Return Value:
  111. * None.
  112. *
  113. */
  114. void PSvDisablePowerSaving(void *hDeviceContext)
  115. {
  116. PSDevice pDevice = (PSDevice)hDeviceContext;
  117. /* PSMgmtObject pMgmt = &(pDevice->sMgmtObj); */
  118. /* disable power saving hw function */
  119. CONTROLnsRequestOut(pDevice, MESSAGE_TYPE_DISABLE_PS, 0,
  120. 0, 0, NULL);
  121. /* clear AutoSleep */
  122. MACvRegBitsOff(pDevice, MAC_REG_PSCFG, PSCFG_AUTOSLEEP);
  123. /* set always listen beacon */
  124. MACvRegBitsOn(pDevice, MAC_REG_PSCTL, PSCTL_ALBCN);
  125. pDevice->bEnablePSMode = FALSE;
  126. if (pDevice->eOPMode == OP_MODE_INFRASTRUCTURE)
  127. PSbSendNullPacket(pDevice);
  128. pDevice->bPWBitOn = FALSE;
  129. }
  130. /*
  131. *
  132. * Routine Description:
  133. * Consider to power down when no more packets to tx or rx.
  134. *
  135. * Return Value:
  136. * TRUE, if power down success
  137. * FALSE, if fail
  138. */
  139. BOOL PSbConsiderPowerDown(void *hDeviceContext,
  140. BOOL bCheckRxDMA,
  141. BOOL bCheckCountToWakeUp)
  142. {
  143. PSDevice pDevice = (PSDevice)hDeviceContext;
  144. PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
  145. BYTE byData;
  146. /* check if already in Doze mode */
  147. ControlvReadByte(pDevice, MESSAGE_REQUEST_MACREG,
  148. MAC_REG_PSCTL, &byData);
  149. if ((byData & PSCTL_PS) != 0)
  150. return TRUE;
  151. if (pMgmt->eCurrMode != WMAC_MODE_IBSS_STA) {
  152. /* check if in TIM wake period */
  153. if (pMgmt->bInTIMWake)
  154. return FALSE;
  155. }
  156. /* check scan state */
  157. if (pDevice->bCmdRunning)
  158. return FALSE;
  159. /* Tx Burst */
  160. if (pDevice->bPSModeTxBurst)
  161. return FALSE;
  162. /* Froce PSEN on */
  163. MACvRegBitsOn(pDevice, MAC_REG_PSCTL, PSCTL_PSEN);
  164. if (pMgmt->eCurrMode != WMAC_MODE_IBSS_STA) {
  165. if (bCheckCountToWakeUp && (pMgmt->wCountToWakeUp == 0
  166. || pMgmt->wCountToWakeUp == 1)) {
  167. return FALSE;
  168. }
  169. }
  170. pDevice->bPSRxBeacon = TRUE;
  171. /* no Tx, no Rx isr, now go to Doze */
  172. MACvRegBitsOn(pDevice, MAC_REG_PSCTL, PSCTL_GO2DOZE);
  173. DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Go to Doze ZZZZZZZZZZZZZZZ\n");
  174. return TRUE;
  175. }
  176. /*
  177. *
  178. * Routine Description:
  179. * Send PS-POLL packet
  180. *
  181. * Return Value:
  182. * None.
  183. *
  184. */
  185. void PSvSendPSPOLL(void *hDeviceContext)
  186. {
  187. PSDevice pDevice = (PSDevice)hDeviceContext;
  188. PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
  189. PSTxMgmtPacket pTxPacket = NULL;
  190. memset(pMgmt->pbyPSPacketPool, 0, sizeof(STxMgmtPacket) + WLAN_HDR_ADDR2_LEN);
  191. pTxPacket = (PSTxMgmtPacket)pMgmt->pbyPSPacketPool;
  192. pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)pTxPacket + sizeof(STxMgmtPacket));
  193. pTxPacket->p80211Header->sA2.wFrameCtl = cpu_to_le16(
  194. (
  195. WLAN_SET_FC_FTYPE(WLAN_TYPE_CTL) |
  196. WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_PSPOLL) |
  197. WLAN_SET_FC_PWRMGT(0)
  198. ));
  199. pTxPacket->p80211Header->sA2.wDurationID = pMgmt->wCurrAID | BIT14 | BIT15;
  200. memcpy(pTxPacket->p80211Header->sA2.abyAddr1, pMgmt->abyCurrBSSID, WLAN_ADDR_LEN);
  201. memcpy(pTxPacket->p80211Header->sA2.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
  202. pTxPacket->cbMPDULen = WLAN_HDR_ADDR2_LEN;
  203. pTxPacket->cbPayloadLen = 0;
  204. /* log failure if sending failed */
  205. if (csMgmt_xmit(pDevice, pTxPacket) != CMD_STATUS_PENDING) {
  206. DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Send PS-Poll packet failed..\n");
  207. }
  208. }
  209. /*
  210. *
  211. * Routine Description:
  212. * Send NULL packet to AP for notification power state of STA
  213. *
  214. * Return Value:
  215. * None.
  216. *
  217. */
  218. BOOL PSbSendNullPacket(void *hDeviceContext)
  219. {
  220. PSDevice pDevice = (PSDevice)hDeviceContext;
  221. PSTxMgmtPacket pTxPacket = NULL;
  222. PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
  223. u16 flags = 0;
  224. if (pDevice->bLinkPass == FALSE)
  225. return FALSE;
  226. if ((pDevice->bEnablePSMode == FALSE) &&
  227. (pDevice->fTxDataInSleep == FALSE)) {
  228. return FALSE;
  229. }
  230. memset(pMgmt->pbyPSPacketPool, 0, sizeof(STxMgmtPacket) + WLAN_NULLDATA_FR_MAXLEN);
  231. pTxPacket = (PSTxMgmtPacket)pMgmt->pbyPSPacketPool;
  232. pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)pTxPacket + sizeof(STxMgmtPacket));
  233. flags = WLAN_SET_FC_FTYPE(WLAN_TYPE_DATA) |
  234. WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_NULL);
  235. if (pDevice->bEnablePSMode)
  236. flags |= WLAN_SET_FC_PWRMGT(1);
  237. else
  238. flags |= WLAN_SET_FC_PWRMGT(0);
  239. pTxPacket->p80211Header->sA3.wFrameCtl = cpu_to_le16(flags);
  240. if (pMgmt->eCurrMode != WMAC_MODE_IBSS_STA)
  241. pTxPacket->p80211Header->sA3.wFrameCtl |= cpu_to_le16((WORD)WLAN_SET_FC_TODS(1));
  242. memcpy(pTxPacket->p80211Header->sA3.abyAddr1, pMgmt->abyCurrBSSID, WLAN_ADDR_LEN);
  243. memcpy(pTxPacket->p80211Header->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
  244. memcpy(pTxPacket->p80211Header->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
  245. pTxPacket->cbMPDULen = WLAN_HDR_ADDR3_LEN;
  246. pTxPacket->cbPayloadLen = 0;
  247. /* log error if sending failed */
  248. if (csMgmt_xmit(pDevice, pTxPacket) != CMD_STATUS_PENDING) {
  249. DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Send Null Packet failed !\n");
  250. return FALSE;
  251. }
  252. return TRUE;
  253. }
  254. /*
  255. *
  256. * Routine Description:
  257. * Check if Next TBTT must wake up
  258. *
  259. * Return Value:
  260. * None.
  261. *
  262. */
  263. BOOL PSbIsNextTBTTWakeUp(void *hDeviceContext)
  264. {
  265. PSDevice pDevice = (PSDevice)hDeviceContext;
  266. PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
  267. BOOL bWakeUp = FALSE;
  268. if (pMgmt->wListenInterval >= 2) {
  269. if (pMgmt->wCountToWakeUp == 0)
  270. pMgmt->wCountToWakeUp = pMgmt->wListenInterval;
  271. pMgmt->wCountToWakeUp--;
  272. if (pMgmt->wCountToWakeUp == 1) {
  273. /* Turn on wake up to listen next beacon */
  274. MACvRegBitsOn(pDevice, MAC_REG_PSCTL, PSCTL_LNBCN);
  275. pDevice->bPSRxBeacon = FALSE;
  276. bWakeUp = TRUE;
  277. } else if (!pDevice->bPSRxBeacon) {
  278. /* Listen until RxBeacon */
  279. MACvRegBitsOn(pDevice, MAC_REG_PSCTL, PSCTL_LNBCN);
  280. }
  281. }
  282. return bWakeUp;
  283. }