1/* 2 ************************************************************************* 3 * Ralink Tech Inc. 4 * 5F., No.36, Taiyuan St., Jhubei City, 5 * Hsinchu County 302, 6 * Taiwan, R.O.C. 7 * 8 * (c) Copyright 2002-2007, Ralink Technology, Inc. 9 * 10 * This program is free software; you can redistribute it and/or modify * 11 * it under the terms of the GNU General Public License as published by * 12 * the Free Software Foundation; either version 2 of the License, or * 13 * (at your option) any later version. * 14 * * 15 * This program is distributed in the hope that it will be useful, * 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 18 * GNU General Public License for more details. * 19 * * 20 * You should have received a copy of the GNU General Public License * 21 * along with this program; if not, write to the * 22 * Free Software Foundation, Inc., * 23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 24 * * 25 ************************************************************************* 26*/ 27 28#ifdef RTMP_MAC_PCI 29#include "../rt_config.h" 30 31/* 32 ======================================================================== 33 34 Routine Description: 35 Allocate DMA memory blocks for send, receive 36 37 Arguments: 38 Adapter Pointer to our adapter 39 40 Return Value: 41 NDIS_STATUS_SUCCESS 42 NDIS_STATUS_FAILURE 43 NDIS_STATUS_RESOURCES 44 45 IRQL = PASSIVE_LEVEL 46 47 Note: 48 49 ======================================================================== 50*/ 51int RTMPAllocTxRxRingMemory(struct rt_rtmp_adapter *pAd) 52{ 53 int Status = NDIS_STATUS_SUCCESS; 54 unsigned long RingBasePaHigh; 55 unsigned long RingBasePaLow; 56 void *RingBaseVa; 57 int index, num; 58 struct rt_txd * pTxD; 59 struct rt_rxd * pRxD; 60 unsigned long ErrorValue = 0; 61 struct rt_rtmp_tx_ring *pTxRing; 62 struct rt_rtmp_dmabuf *pDmaBuf; 63 void *pPacket; 64/* PRTMP_REORDERBUF pReorderBuf; */ 65 66 DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPAllocTxRxRingMemory\n")); 67 do { 68 /* */ 69 /* Allocate all ring descriptors, include TxD, RxD, MgmtD. */ 70 /* Although each size is different, to prevent cacheline and alignment */ 71 /* issue, I intentional set them all to 64 bytes. */ 72 /* */ 73 for (num = 0; num < NUM_OF_TX_RING; num++) { 74 unsigned long BufBasePaHigh; 75 unsigned long BufBasePaLow; 76 void *BufBaseVa; 77 78 /* */ 79 /* Allocate Tx ring descriptor's memory (5 TX rings = 4 ACs + 1 HCCA) */ 80 /* */ 81 pAd->TxDescRing[num].AllocSize = 82 TX_RING_SIZE * TXD_SIZE; 83 RTMP_AllocateTxDescMemory(pAd, num, 84 pAd->TxDescRing[num]. 85 AllocSize, FALSE, 86 &pAd->TxDescRing[num].AllocVa, 87 &pAd->TxDescRing[num]. 88 AllocPa); 89 90 if (pAd->TxDescRing[num].AllocVa == NULL) { 91 ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; 92 DBGPRINT_ERR(("Failed to allocate a big buffer\n")); 93 Status = NDIS_STATUS_RESOURCES; 94 break; 95 } 96 /* Zero init this memory block */ 97 NdisZeroMemory(pAd->TxDescRing[num].AllocVa, 98 pAd->TxDescRing[num].AllocSize); 99 100 /* Save PA & VA for further operation */ 101 RingBasePaHigh = 102 RTMP_GetPhysicalAddressHigh(pAd->TxDescRing[num]. 103 AllocPa); 104 RingBasePaLow = 105 RTMP_GetPhysicalAddressLow(pAd->TxDescRing[num]. 106 AllocPa); 107 RingBaseVa = pAd->TxDescRing[num].AllocVa; 108 109 /* */ 110 /* Allocate all 1st TXBuf's memory for this TxRing */ 111 /* */ 112 pAd->TxBufSpace[num].AllocSize = 113 TX_RING_SIZE * TX_DMA_1ST_BUFFER_SIZE; 114 RTMP_AllocateFirstTxBuffer(pAd, num, 115 pAd->TxBufSpace[num]. 116 AllocSize, FALSE, 117 &pAd->TxBufSpace[num]. 118 AllocVa, 119 &pAd->TxBufSpace[num]. 120 AllocPa); 121 122 if (pAd->TxBufSpace[num].AllocVa == NULL) { 123 ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; 124 DBGPRINT_ERR(("Failed to allocate a big buffer\n")); 125 Status = NDIS_STATUS_RESOURCES; 126 break; 127 } 128 /* Zero init this memory block */ 129 NdisZeroMemory(pAd->TxBufSpace[num].AllocVa, 130 pAd->TxBufSpace[num].AllocSize); 131 132 /* Save PA & VA for further operation */ 133 BufBasePaHigh = 134 RTMP_GetPhysicalAddressHigh(pAd->TxBufSpace[num]. 135 AllocPa); 136 BufBasePaLow = 137 RTMP_GetPhysicalAddressLow(pAd->TxBufSpace[num]. 138 AllocPa); 139 BufBaseVa = pAd->TxBufSpace[num].AllocVa; 140 141 /* */ 142 /* Initialize Tx Ring Descriptor and associated buffer memory */ 143 /* */ 144 pTxRing = &pAd->TxRing[num]; 145 for (index = 0; index < TX_RING_SIZE; index++) { 146 pTxRing->Cell[index].pNdisPacket = NULL; 147 pTxRing->Cell[index].pNextNdisPacket = NULL; 148 /* Init Tx Ring Size, Va, Pa variables */ 149 pTxRing->Cell[index].AllocSize = TXD_SIZE; 150 pTxRing->Cell[index].AllocVa = RingBaseVa; 151 RTMP_SetPhysicalAddressHigh(pTxRing-> 152 Cell[index].AllocPa, 153 RingBasePaHigh); 154 RTMP_SetPhysicalAddressLow(pTxRing->Cell[index]. 155 AllocPa, 156 RingBasePaLow); 157 158 /* Setup Tx Buffer size & address. only 802.11 header will store in this space */ 159 pDmaBuf = &pTxRing->Cell[index].DmaBuf; 160 pDmaBuf->AllocSize = TX_DMA_1ST_BUFFER_SIZE; 161 pDmaBuf->AllocVa = BufBaseVa; 162 RTMP_SetPhysicalAddressHigh(pDmaBuf->AllocPa, 163 BufBasePaHigh); 164 RTMP_SetPhysicalAddressLow(pDmaBuf->AllocPa, 165 BufBasePaLow); 166 167 /* link the pre-allocated TxBuf to TXD */ 168 pTxD = 169 (struct rt_txd *) pTxRing->Cell[index].AllocVa; 170 pTxD->SDPtr0 = BufBasePaLow; 171 /* advance to next ring descriptor address */ 172 pTxD->DMADONE = 1; 173 RingBasePaLow += TXD_SIZE; 174 RingBaseVa = (u8 *)RingBaseVa + TXD_SIZE; 175 176 /* advance to next TxBuf address */ 177 BufBasePaLow += TX_DMA_1ST_BUFFER_SIZE; 178 BufBaseVa = 179 (u8 *)BufBaseVa + TX_DMA_1ST_BUFFER_SIZE; 180 } 181 DBGPRINT(RT_DEBUG_TRACE, 182 ("TxRing[%d]: total %d entry allocated\n", num, 183 index)); 184 } 185 if (Status == NDIS_STATUS_RESOURCES) 186 break; 187 188 /* */ 189 /* Allocate MGMT ring descriptor's memory except Tx ring which allocated eariler */ 190 /* */ 191 pAd->MgmtDescRing.AllocSize = MGMT_RING_SIZE * TXD_SIZE; 192 RTMP_AllocateMgmtDescMemory(pAd, 193 pAd->MgmtDescRing.AllocSize, 194 FALSE, 195 &pAd->MgmtDescRing.AllocVa, 196 &pAd->MgmtDescRing.AllocPa); 197 198 if (pAd->MgmtDescRing.AllocVa == NULL) { 199 ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; 200 DBGPRINT_ERR(("Failed to allocate a big buffer\n")); 201 Status = NDIS_STATUS_RESOURCES; 202 break; 203 } 204 /* Zero init this memory block */ 205 NdisZeroMemory(pAd->MgmtDescRing.AllocVa, 206 pAd->MgmtDescRing.AllocSize); 207 208 /* Save PA & VA for further operation */ 209 RingBasePaHigh = 210 RTMP_GetPhysicalAddressHigh(pAd->MgmtDescRing.AllocPa); 211 RingBasePaLow = 212 RTMP_GetPhysicalAddressLow(pAd->MgmtDescRing.AllocPa); 213 RingBaseVa = pAd->MgmtDescRing.AllocVa; 214 215 /* */ 216 /* Initialize MGMT Ring and associated buffer memory */ 217 /* */ 218 for (index = 0; index < MGMT_RING_SIZE; index++) { 219 pAd->MgmtRing.Cell[index].pNdisPacket = NULL; 220 pAd->MgmtRing.Cell[index].pNextNdisPacket = NULL; 221 /* Init MGMT Ring Size, Va, Pa variables */ 222 pAd->MgmtRing.Cell[index].AllocSize = TXD_SIZE; 223 pAd->MgmtRing.Cell[index].AllocVa = RingBaseVa; 224 RTMP_SetPhysicalAddressHigh(pAd->MgmtRing.Cell[index]. 225 AllocPa, RingBasePaHigh); 226 RTMP_SetPhysicalAddressLow(pAd->MgmtRing.Cell[index]. 227 AllocPa, RingBasePaLow); 228 229 /* Offset to next ring descriptor address */ 230 RingBasePaLow += TXD_SIZE; 231 RingBaseVa = (u8 *)RingBaseVa + TXD_SIZE; 232 233 /* link the pre-allocated TxBuf to TXD */ 234 pTxD = (struct rt_txd *) pAd->MgmtRing.Cell[index].AllocVa; 235 pTxD->DMADONE = 1; 236 237 /* no pre-allocated buffer required in MgmtRing for scatter-gather case */ 238 } 239 DBGPRINT(RT_DEBUG_TRACE, 240 ("MGMT Ring: total %d entry allocated\n", index)); 241 242 /* */ 243 /* Allocate RX ring descriptor's memory except Tx ring which allocated eariler */ 244 /* */ 245 pAd->RxDescRing.AllocSize = RX_RING_SIZE * RXD_SIZE; 246 RTMP_AllocateRxDescMemory(pAd, 247 pAd->RxDescRing.AllocSize, 248 FALSE, 249 &pAd->RxDescRing.AllocVa, 250 &pAd->RxDescRing.AllocPa); 251 252 if (pAd->RxDescRing.AllocVa == NULL) { 253 ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; 254 DBGPRINT_ERR(("Failed to allocate a big buffer\n")); 255 Status = NDIS_STATUS_RESOURCES; 256 break; 257 } 258 /* Zero init this memory block */ 259 NdisZeroMemory(pAd->RxDescRing.AllocVa, 260 pAd->RxDescRing.AllocSize); 261 262 DBGPRINT(RT_DEBUG_OFF, 263 ("RX DESC %p size = %ld\n", pAd->RxDescRing.AllocVa, 264 pAd->RxDescRing.AllocSize)); 265 266 /* Save PA & VA for further operation */ 267 RingBasePaHigh = 268 RTMP_GetPhysicalAddressHigh(pAd->RxDescRing.AllocPa); 269 RingBasePaLow = 270 RTMP_GetPhysicalAddressLow(pAd->RxDescRing.AllocPa); 271 RingBaseVa = pAd->RxDescRing.AllocVa; 272 273 /* */ 274 /* Initialize Rx Ring and associated buffer memory */ 275 /* */ 276 for (index = 0; index < RX_RING_SIZE; index++) { 277 /* Init RX Ring Size, Va, Pa variables */ 278 pAd->RxRing.Cell[index].AllocSize = RXD_SIZE; 279 pAd->RxRing.Cell[index].AllocVa = RingBaseVa; 280 RTMP_SetPhysicalAddressHigh(pAd->RxRing.Cell[index]. 281 AllocPa, RingBasePaHigh); 282 RTMP_SetPhysicalAddressLow(pAd->RxRing.Cell[index]. 283 AllocPa, RingBasePaLow); 284 285 /*NdisZeroMemory(RingBaseVa, RXD_SIZE); */ 286 287 /* Offset to next ring descriptor address */ 288 RingBasePaLow += RXD_SIZE; 289 RingBaseVa = (u8 *)RingBaseVa + RXD_SIZE; 290 291 /* Setup Rx associated Buffer size & allocate share memory */ 292 pDmaBuf = &pAd->RxRing.Cell[index].DmaBuf; 293 pDmaBuf->AllocSize = RX_BUFFER_AGGRESIZE; 294 pPacket = RTMP_AllocateRxPacketBuffer(pAd, 295 pDmaBuf-> 296 AllocSize, FALSE, 297 &pDmaBuf->AllocVa, 298 &pDmaBuf-> 299 AllocPa); 300 301 /* keep allocated rx packet */ 302 pAd->RxRing.Cell[index].pNdisPacket = pPacket; 303 304 /* Error handling */ 305 if (pDmaBuf->AllocVa == NULL) { 306 ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; 307 DBGPRINT_ERR(("Failed to allocate RxRing's 1st buffer\n")); 308 Status = NDIS_STATUS_RESOURCES; 309 break; 310 } 311 /* Zero init this memory block */ 312 NdisZeroMemory(pDmaBuf->AllocVa, pDmaBuf->AllocSize); 313 314 /* Write RxD buffer address & allocated buffer length */ 315 pRxD = (struct rt_rxd *) pAd->RxRing.Cell[index].AllocVa; 316 pRxD->SDP0 = 317 RTMP_GetPhysicalAddressLow(pDmaBuf->AllocPa); 318 pRxD->DDONE = 0; 319 320 } 321 322 DBGPRINT(RT_DEBUG_TRACE, 323 ("Rx Ring: total %d entry allocated\n", index)); 324 325 } while (FALSE); 326 327 NdisZeroMemory(&pAd->FragFrame, sizeof(struct rt_fragment_frame)); 328 pAd->FragFrame.pFragPacket = 329 RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE); 330 331 if (pAd->FragFrame.pFragPacket == NULL) { 332 Status = NDIS_STATUS_RESOURCES; 333 } 334 335 if (Status != NDIS_STATUS_SUCCESS) { 336 /* Log error inforamtion */ 337 NdisWriteErrorLogEntry(pAd->AdapterHandle, 338 NDIS_ERROR_CODE_OUT_OF_RESOURCES, 339 1, ErrorValue); 340 } 341 /* Following code segment get from original func:NICInitTxRxRingAndBacklogQueue(), now should integrate it to here. */ 342 { 343 DBGPRINT(RT_DEBUG_TRACE, 344 ("--> NICInitTxRxRingAndBacklogQueue\n")); 345 346/* 347 // Disable DMA. 348 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); 349 GloCfg.word &= 0xff0; 350 GloCfg.field.EnTXWriteBackDDONE =1; 351 RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); 352*/ 353 354 /* Initialize all transmit related software queues */ 355 for (index = 0; index < NUM_OF_TX_RING; index++) { 356 InitializeQueueHeader(&pAd->TxSwQueue[index]); 357 /* Init TX rings index pointer */ 358 pAd->TxRing[index].TxSwFreeIdx = 0; 359 pAd->TxRing[index].TxCpuIdx = 0; 360 /*RTMP_IO_WRITE32(pAd, (TX_CTX_IDX0 + i * 0x10) , pAd->TxRing[i].TX_CTX_IDX); */ 361 } 362 363 /* Init RX Ring index pointer */ 364 pAd->RxRing.RxSwReadIdx = 0; 365 pAd->RxRing.RxCpuIdx = RX_RING_SIZE - 1; 366 /*RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RX_CRX_IDX0); */ 367 368 /* init MGMT ring index pointer */ 369 pAd->MgmtRing.TxSwFreeIdx = 0; 370 pAd->MgmtRing.TxCpuIdx = 0; 371 372 pAd->PrivateInfo.TxRingFullCnt = 0; 373 374 DBGPRINT(RT_DEBUG_TRACE, 375 ("<-- NICInitTxRxRingAndBacklogQueue\n")); 376 } 377 378 DBGPRINT_S(Status, 379 ("<-- RTMPAllocTxRxRingMemory, Status=%x\n", Status)); 380 return Status; 381} 382 383/* 384 ======================================================================== 385 386 Routine Description: 387 Reset NIC Asics. Call after rest DMA. So reset TX_CTX_IDX to zero. 388 389 Arguments: 390 Adapter Pointer to our adapter 391 392 Return Value: 393 None 394 395 IRQL = PASSIVE_LEVEL 396 IRQL = DISPATCH_LEVEL 397 398 Note: 399 Reset NIC to initial state AS IS system boot up time. 400 401 ======================================================================== 402*/ 403void RTMPRingCleanUp(struct rt_rtmp_adapter *pAd, u8 RingType) 404{ 405 struct rt_txd * pTxD; 406 struct rt_rxd * pRxD; 407 struct rt_queue_entry *pEntry; 408 void *pPacket; 409 int i; 410 struct rt_rtmp_tx_ring *pTxRing; 411 unsigned long IrqFlags; 412 /*u32 RxSwReadIdx; */ 413 414 DBGPRINT(RT_DEBUG_TRACE, 415 ("RTMPRingCleanUp(RingIdx=%d, Pending-NDIS=%ld)\n", RingType, 416 pAd->RalinkCounters.PendingNdisPacketCount)); 417 switch (RingType) { 418 case QID_AC_BK: 419 case QID_AC_BE: 420 case QID_AC_VI: 421 case QID_AC_VO: 422 423 pTxRing = &pAd->TxRing[RingType]; 424 425 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); 426 /* We have to clean all descriptors in case some error happened with reset */ 427 for (i = 0; i < TX_RING_SIZE; i++) /* We have to scan all TX ring */ 428 { 429 pTxD = (struct rt_txd *) pTxRing->Cell[i].AllocVa; 430 431 pPacket = (void *)pTxRing->Cell[i].pNdisPacket; 432 /* release scatter-and-gather char */ 433 if (pPacket) { 434 RELEASE_NDIS_PACKET(pAd, pPacket, 435 NDIS_STATUS_FAILURE); 436 pTxRing->Cell[i].pNdisPacket = NULL; 437 } 438 439 pPacket = 440 (void *)pTxRing->Cell[i].pNextNdisPacket; 441 /* release scatter-and-gather char */ 442 if (pPacket) { 443 RELEASE_NDIS_PACKET(pAd, pPacket, 444 NDIS_STATUS_FAILURE); 445 pTxRing->Cell[i].pNextNdisPacket = NULL; 446 } 447 } 448 449 RTMP_IO_READ32(pAd, TX_DTX_IDX0 + RingType * 0x10, 450 &pTxRing->TxDmaIdx); 451 pTxRing->TxSwFreeIdx = pTxRing->TxDmaIdx; 452 pTxRing->TxCpuIdx = pTxRing->TxDmaIdx; 453 RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + RingType * 0x10, 454 pTxRing->TxCpuIdx); 455 456 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); 457 458 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); 459 while (pAd->TxSwQueue[RingType].Head != NULL) { 460 pEntry = RemoveHeadQueue(&pAd->TxSwQueue[RingType]); 461 pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); 462 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); 463 DBGPRINT(RT_DEBUG_TRACE, 464 ("Release 1 NDIS packet from s/w backlog queue\n")); 465 } 466 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); 467 break; 468 469 case QID_MGMT: 470 /* We have to clean all descriptors in case some error happened with reset */ 471 NdisAcquireSpinLock(&pAd->MgmtRingLock); 472 473 for (i = 0; i < MGMT_RING_SIZE; i++) { 474 pTxD = (struct rt_txd *) pAd->MgmtRing.Cell[i].AllocVa; 475 476 pPacket = 477 (void *)pAd->MgmtRing.Cell[i].pNdisPacket; 478 /* rlease scatter-and-gather char */ 479 if (pPacket) { 480 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, 481 pTxD->SDLen0, 482 PCI_DMA_TODEVICE); 483 RELEASE_NDIS_PACKET(pAd, pPacket, 484 NDIS_STATUS_FAILURE); 485 } 486 pAd->MgmtRing.Cell[i].pNdisPacket = NULL; 487 488 pPacket = 489 (void *)pAd->MgmtRing.Cell[i]. 490 pNextNdisPacket; 491 /* release scatter-and-gather char */ 492 if (pPacket) { 493 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, 494 pTxD->SDLen1, 495 PCI_DMA_TODEVICE); 496 RELEASE_NDIS_PACKET(pAd, pPacket, 497 NDIS_STATUS_FAILURE); 498 } 499 pAd->MgmtRing.Cell[i].pNextNdisPacket = NULL; 500 501 } 502 503 RTMP_IO_READ32(pAd, TX_MGMTDTX_IDX, &pAd->MgmtRing.TxDmaIdx); 504 pAd->MgmtRing.TxSwFreeIdx = pAd->MgmtRing.TxDmaIdx; 505 pAd->MgmtRing.TxCpuIdx = pAd->MgmtRing.TxDmaIdx; 506 RTMP_IO_WRITE32(pAd, TX_MGMTCTX_IDX, pAd->MgmtRing.TxCpuIdx); 507 508 NdisReleaseSpinLock(&pAd->MgmtRingLock); 509 pAd->RalinkCounters.MgmtRingFullCount = 0; 510 break; 511 512 case QID_RX: 513 /* We have to clean all descriptors in case some error happened with reset */ 514 NdisAcquireSpinLock(&pAd->RxRingLock); 515 516 for (i = 0; i < RX_RING_SIZE; i++) { 517 pRxD = (struct rt_rxd *) pAd->RxRing.Cell[i].AllocVa; 518 pRxD->DDONE = 0; 519 } 520 521 RTMP_IO_READ32(pAd, RX_DRX_IDX, &pAd->RxRing.RxDmaIdx); 522 pAd->RxRing.RxSwReadIdx = pAd->RxRing.RxDmaIdx; 523 pAd->RxRing.RxCpuIdx = 524 ((pAd->RxRing.RxDmaIdx == 525 0) ? (RX_RING_SIZE - 1) : (pAd->RxRing.RxDmaIdx - 1)); 526 RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx); 527 528 NdisReleaseSpinLock(&pAd->RxRingLock); 529 break; 530 531 default: 532 break; 533 } 534} 535 536void RTMPFreeTxRxRingMemory(struct rt_rtmp_adapter *pAd) 537{ 538 int index, num, j; 539 struct rt_rtmp_tx_ring *pTxRing; 540 struct rt_txd * pTxD; 541 void *pPacket; 542 unsigned int IrqFlags; 543 544 /*struct os_cookie *pObj =(struct os_cookie *)pAd->OS_Cookie; */ 545 546 DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPFreeTxRxRingMemory\n")); 547 548 /* Free TxSwQueue Packet */ 549 for (index = 0; index < NUM_OF_TX_RING; index++) { 550 struct rt_queue_entry *pEntry; 551 void *pPacket; 552 struct rt_queue_header *pQueue; 553 554 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); 555 pQueue = &pAd->TxSwQueue[index]; 556 while (pQueue->Head) { 557 pEntry = RemoveHeadQueue(pQueue); 558 pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); 559 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); 560 } 561 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); 562 } 563 564 /* Free Tx Ring Packet */ 565 for (index = 0; index < NUM_OF_TX_RING; index++) { 566 pTxRing = &pAd->TxRing[index]; 567 568 for (j = 0; j < TX_RING_SIZE; j++) { 569 pTxD = (struct rt_txd *) (pTxRing->Cell[j].AllocVa); 570 pPacket = pTxRing->Cell[j].pNdisPacket; 571 572 if (pPacket) { 573 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, 574 pTxD->SDLen0, 575 PCI_DMA_TODEVICE); 576 RELEASE_NDIS_PACKET(pAd, pPacket, 577 NDIS_STATUS_SUCCESS); 578 } 579 /*Always assign pNdisPacket as NULL after clear */ 580 pTxRing->Cell[j].pNdisPacket = NULL; 581 582 pPacket = pTxRing->Cell[j].pNextNdisPacket; 583 584 if (pPacket) { 585 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, 586 pTxD->SDLen1, 587 PCI_DMA_TODEVICE); 588 RELEASE_NDIS_PACKET(pAd, pPacket, 589 NDIS_STATUS_SUCCESS); 590 } 591 /*Always assign pNextNdisPacket as NULL after clear */ 592 pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = 593 NULL; 594 595 } 596 } 597 598 for (index = RX_RING_SIZE - 1; index >= 0; index--) { 599 if ((pAd->RxRing.Cell[index].DmaBuf.AllocVa) 600 && (pAd->RxRing.Cell[index].pNdisPacket)) { 601 PCI_UNMAP_SINGLE(pAd, 602 pAd->RxRing.Cell[index].DmaBuf.AllocPa, 603 pAd->RxRing.Cell[index].DmaBuf. 604 AllocSize, PCI_DMA_FROMDEVICE); 605 RELEASE_NDIS_PACKET(pAd, 606 pAd->RxRing.Cell[index].pNdisPacket, 607 NDIS_STATUS_SUCCESS); 608 } 609 } 610 NdisZeroMemory(pAd->RxRing.Cell, RX_RING_SIZE * sizeof(struct rt_rtmp_dmacb)); 611 612 if (pAd->RxDescRing.AllocVa) { 613 RTMP_FreeDescMemory(pAd, pAd->RxDescRing.AllocSize, 614 pAd->RxDescRing.AllocVa, 615 pAd->RxDescRing.AllocPa); 616 } 617 NdisZeroMemory(&pAd->RxDescRing, sizeof(struct rt_rtmp_dmabuf)); 618 619 if (pAd->MgmtDescRing.AllocVa) { 620 RTMP_FreeDescMemory(pAd, pAd->MgmtDescRing.AllocSize, 621 pAd->MgmtDescRing.AllocVa, 622 pAd->MgmtDescRing.AllocPa); 623 } 624 NdisZeroMemory(&pAd->MgmtDescRing, sizeof(struct rt_rtmp_dmabuf)); 625 626 for (num = 0; num < NUM_OF_TX_RING; num++) { 627 if (pAd->TxBufSpace[num].AllocVa) { 628 RTMP_FreeFirstTxBuffer(pAd, 629 pAd->TxBufSpace[num].AllocSize, 630 FALSE, 631 pAd->TxBufSpace[num].AllocVa, 632 pAd->TxBufSpace[num].AllocPa); 633 } 634 NdisZeroMemory(&pAd->TxBufSpace[num], sizeof(struct rt_rtmp_dmabuf)); 635 636 if (pAd->TxDescRing[num].AllocVa) { 637 RTMP_FreeDescMemory(pAd, pAd->TxDescRing[num].AllocSize, 638 pAd->TxDescRing[num].AllocVa, 639 pAd->TxDescRing[num].AllocPa); 640 } 641 NdisZeroMemory(&pAd->TxDescRing[num], sizeof(struct rt_rtmp_dmabuf)); 642 } 643 644 if (pAd->FragFrame.pFragPacket) 645 RELEASE_NDIS_PACKET(pAd, pAd->FragFrame.pFragPacket, 646 NDIS_STATUS_SUCCESS); 647 648 DBGPRINT(RT_DEBUG_TRACE, ("<-- RTMPFreeTxRxRingMemory\n")); 649} 650 651/*************************************************************************** 652 * 653 * register related procedures. 654 * 655 **************************************************************************/ 656/* 657======================================================================== 658Routine Description: 659 Disable DMA. 660 661Arguments: 662 *pAd the raxx interface data pointer 663 664Return Value: 665 None 666 667Note: 668======================================================================== 669*/ 670void RT28XXDMADisable(struct rt_rtmp_adapter *pAd) 671{ 672 WPDMA_GLO_CFG_STRUC GloCfg; 673 674 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); 675 GloCfg.word &= 0xff0; 676 GloCfg.field.EnTXWriteBackDDONE = 1; 677 RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); 678} 679 680/* 681======================================================================== 682Routine Description: 683 Enable DMA. 684 685Arguments: 686 *pAd the raxx interface data pointer 687 688Return Value: 689 None 690 691Note: 692======================================================================== 693*/ 694void RT28XXDMAEnable(struct rt_rtmp_adapter *pAd) 695{ 696 WPDMA_GLO_CFG_STRUC GloCfg; 697 int i = 0; 698 699 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x4); 700 do { 701 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); 702 if ((GloCfg.field.TxDMABusy == 0) 703 && (GloCfg.field.RxDMABusy == 0)) 704 break; 705 706 DBGPRINT(RT_DEBUG_TRACE, ("==> DMABusy\n")); 707 RTMPusecDelay(1000); 708 i++; 709 } while (i < 200); 710 711 RTMPusecDelay(50); 712 713 GloCfg.field.EnTXWriteBackDDONE = 1; 714 GloCfg.field.WPDMABurstSIZE = 2; 715 GloCfg.field.EnableRxDMA = 1; 716 GloCfg.field.EnableTxDMA = 1; 717 718 DBGPRINT(RT_DEBUG_TRACE, 719 ("<== WRITE DMA offset 0x208 = 0x%x\n", GloCfg.word)); 720 RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); 721 722} 723 724BOOLEAN AsicCheckCommanOk(struct rt_rtmp_adapter *pAd, u8 Command) 725{ 726 u32 CmdStatus = 0, CID = 0, i; 727 u32 ThisCIDMask = 0; 728 729 i = 0; 730 do { 731 RTMP_IO_READ32(pAd, H2M_MAILBOX_CID, &CID); 732 /* Find where the command is. Because this is randomly specified by firmware. */ 733 if ((CID & CID0MASK) == Command) { 734 ThisCIDMask = CID0MASK; 735 break; 736 } else if ((((CID & CID1MASK) >> 8) & 0xff) == Command) { 737 ThisCIDMask = CID1MASK; 738 break; 739 } else if ((((CID & CID2MASK) >> 16) & 0xff) == Command) { 740 ThisCIDMask = CID2MASK; 741 break; 742 } else if ((((CID & CID3MASK) >> 24) & 0xff) == Command) { 743 ThisCIDMask = CID3MASK; 744 break; 745 } 746 747 RTMPusecDelay(100); 748 i++; 749 } while (i < 200); 750 751 /* Get CommandStatus Value */ 752 RTMP_IO_READ32(pAd, H2M_MAILBOX_STATUS, &CmdStatus); 753 754 /* This command's status is at the same position as command. So AND command position's bitmask to read status. */ 755 if (i < 200) { 756 /* If Status is 1, the comamnd is success. */ 757 if (((CmdStatus & ThisCIDMask) == 0x1) 758 || ((CmdStatus & ThisCIDMask) == 0x100) 759 || ((CmdStatus & ThisCIDMask) == 0x10000) 760 || ((CmdStatus & ThisCIDMask) == 0x1000000)) { 761 DBGPRINT(RT_DEBUG_TRACE, 762 ("--> AsicCheckCommanOk CID = 0x%x, CmdStatus= 0x%x \n", 763 CID, CmdStatus)); 764 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff); 765 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff); 766 return TRUE; 767 } 768 DBGPRINT(RT_DEBUG_TRACE, 769 ("--> AsicCheckCommanFail1 CID = 0x%x, CmdStatus= 0x%x \n", 770 CID, CmdStatus)); 771 } else { 772 DBGPRINT(RT_DEBUG_TRACE, 773 ("--> AsicCheckCommanFail2 Timeout Command = %d, CmdStatus= 0x%x \n", 774 Command, CmdStatus)); 775 } 776 /* Clear Command and Status. */ 777 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff); 778 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff); 779 780 return FALSE; 781} 782 783/* 784======================================================================== 785Routine Description: 786 Write Beacon buffer to Asic. 787 788Arguments: 789 *pAd the raxx interface data pointer 790 791Return Value: 792 None 793 794Note: 795======================================================================== 796*/ 797void RT28xx_UpdateBeaconToAsic(struct rt_rtmp_adapter *pAd, 798 int apidx, 799 unsigned long FrameLen, unsigned long UpdatePos) 800{ 801 unsigned long CapInfoPos = 0; 802 u8 *ptr, *ptr_update, *ptr_capinfo; 803 u32 i; 804 BOOLEAN bBcnReq = FALSE; 805 u8 bcn_idx = 0; 806 807 { 808 DBGPRINT(RT_DEBUG_ERROR, 809 ("%s() : No valid Interface be found.\n", __func__)); 810 return; 811 } 812 813 /*if ((pAd->WdsTab.Mode == WDS_BRIDGE_MODE) */ 814 /* || ((pAd->ApCfg.MBSSID[apidx].MSSIDDev == NULL) */ 815 /* || !(pAd->ApCfg.MBSSID[apidx].MSSIDDev->flags & IFF_UP)) */ 816 /* ) */ 817 if (bBcnReq == FALSE) { 818 /* when the ra interface is down, do not send its beacon frame */ 819 /* clear all zero */ 820 for (i = 0; i < TXWI_SIZE; i += 4) 821 RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[bcn_idx] + i, 822 0x00); 823 } else { 824 ptr = (u8 *)& pAd->BeaconTxWI; 825 for (i = 0; i < TXWI_SIZE; i += 4) /* 16-byte TXWI field */ 826 { 827 u32 longptr = 828 *ptr + (*(ptr + 1) << 8) + (*(ptr + 2) << 16) + 829 (*(ptr + 3) << 24); 830 RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[bcn_idx] + i, 831 longptr); 832 ptr += 4; 833 } 834 835 /* Update CapabilityInfo in Beacon */ 836 for (i = CapInfoPos; i < (CapInfoPos + 2); i++) { 837 RTMP_IO_WRITE8(pAd, 838 pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + 839 i, *ptr_capinfo); 840 ptr_capinfo++; 841 } 842 843 if (FrameLen > UpdatePos) { 844 for (i = UpdatePos; i < (FrameLen); i++) { 845 RTMP_IO_WRITE8(pAd, 846 pAd->BeaconOffset[bcn_idx] + 847 TXWI_SIZE + i, *ptr_update); 848 ptr_update++; 849 } 850 } 851 852 } 853 854} 855 856void RT28xxPciStaAsicForceWakeup(struct rt_rtmp_adapter *pAd, IN BOOLEAN bFromTx) 857{ 858 AUTO_WAKEUP_STRUC AutoWakeupCfg; 859 860 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) 861 return; 862 863 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WAKEUP_NOW)) { 864 DBGPRINT(RT_DEBUG_TRACE, ("waking up now!\n")); 865 return; 866 } 867 868 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WAKEUP_NOW); 869 870 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW); 871 872 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE) 873 && pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) { 874 /* Support PCIe Advance Power Save */ 875 if (bFromTx == TRUE && (pAd->Mlme.bPsPollTimerRunning == TRUE)) { 876 pAd->Mlme.bPsPollTimerRunning = FALSE; 877 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP); 878 RTMPusecDelay(3000); 879 DBGPRINT(RT_DEBUG_TRACE, 880 ("=======AsicForceWakeup===bFromTx\n")); 881 } 882 883 AutoWakeupCfg.word = 0; 884 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); 885 886 if (RT28xxPciAsicRadioOn(pAd, DOT11POWERSAVE)) { 887#ifdef PCIE_PS_SUPPORT 888 /* add by johnli, RF power sequence setup, load RF normal operation-mode setup */ 889 if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) 890 && IS_VERSION_AFTER_F(pAd)) { 891 struct rt_rtmp_chip_op *pChipOps = &pAd->chipOps; 892 893 if (pChipOps->AsicReverseRfFromSleepMode) 894 pChipOps-> 895 AsicReverseRfFromSleepMode(pAd); 896 } else 897#endif /* PCIE_PS_SUPPORT // */ 898 { 899 /* end johnli */ 900 /* In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again. */ 901 if (INFRA_ON(pAd) 902 && (pAd->CommonCfg.CentralChannel != 903 pAd->CommonCfg.Channel) 904 && (pAd->MlmeAux.HtCapability.HtCapInfo. 905 ChannelWidth == BW_40)) { 906 /* Must using 40MHz. */ 907 AsicSwitchChannel(pAd, 908 pAd->CommonCfg. 909 CentralChannel, 910 FALSE); 911 AsicLockChannel(pAd, 912 pAd->CommonCfg. 913 CentralChannel); 914 } else { 915 /* Must using 20MHz. */ 916 AsicSwitchChannel(pAd, 917 pAd->CommonCfg. 918 Channel, FALSE); 919 AsicLockChannel(pAd, 920 pAd->CommonCfg.Channel); 921 } 922 } 923 } 924#ifdef PCIE_PS_SUPPORT 925 /* 3090 MCU Wakeup command needs more time to be stable. */ 926 /* Before stable, don't issue other MCU command to prevent from firmware error. */ 927 if (((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) 928 && IS_VERSION_AFTER_F(pAd)) && IS_VERSION_AFTER_F(pAd) 929 && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3) 930 && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) { 931 DBGPRINT(RT_DEBUG_TRACE, 932 ("<==RT28xxPciStaAsicForceWakeup::Release the MCU Lock(3090)\n")); 933 RTMP_SEM_LOCK(&pAd->McuCmdLock); 934 pAd->brt30xxBanMcuCmd = FALSE; 935 RTMP_SEM_UNLOCK(&pAd->McuCmdLock); 936 } 937#endif /* PCIE_PS_SUPPORT // */ 938 } else { 939 /* PCI, 2860-PCIe */ 940 DBGPRINT(RT_DEBUG_TRACE, 941 ("<==RT28xxPciStaAsicForceWakeup::Original PCI Power Saving\n")); 942 AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x02); 943 AutoWakeupCfg.word = 0; 944 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); 945 } 946 947 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); 948 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WAKEUP_NOW); 949 DBGPRINT(RT_DEBUG_TRACE, ("<=======RT28xxPciStaAsicForceWakeup\n")); 950} 951 952void RT28xxPciStaAsicSleepThenAutoWakeup(struct rt_rtmp_adapter *pAd, 953 u16 TbttNumToNextWakeUp) 954{ 955 BOOLEAN brc; 956 957 if (pAd->StaCfg.bRadio == FALSE) { 958 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); 959 return; 960 } 961 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE) 962 && pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) { 963 unsigned long Now = 0; 964 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WAKEUP_NOW)) { 965 DBGPRINT(RT_DEBUG_TRACE, ("waking up now!\n")); 966 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); 967 return; 968 } 969 970 NdisGetSystemUpTime(&Now); 971 /* If last send NULL fram time is too close to this receiving beacon (within 8ms), don't go to sleep for this DTM. */ 972 /* Because Some AP can't queuing outgoing frames immediately. */ 973 if (((pAd->Mlme.LastSendNULLpsmTime + 8) >= Now) 974 && (pAd->Mlme.LastSendNULLpsmTime <= Now)) { 975 DBGPRINT(RT_DEBUG_TRACE, 976 ("Now = %lu, LastSendNULLpsmTime=%lu : RxCountSinceLastNULL = %lu. \n", 977 Now, pAd->Mlme.LastSendNULLpsmTime, 978 pAd->RalinkCounters.RxCountSinceLastNULL)); 979 return; 980 } else if ((pAd->RalinkCounters.RxCountSinceLastNULL > 0) 981 && 982 ((pAd->Mlme.LastSendNULLpsmTime + 983 pAd->CommonCfg.BeaconPeriod) >= Now)) { 984 DBGPRINT(RT_DEBUG_TRACE, 985 ("Now = %lu, LastSendNULLpsmTime=%lu: RxCountSinceLastNULL = %lu > 0 \n", 986 Now, pAd->Mlme.LastSendNULLpsmTime, 987 pAd->RalinkCounters.RxCountSinceLastNULL)); 988 return; 989 } 990 991 brc = 992 RT28xxPciAsicRadioOff(pAd, DOT11POWERSAVE, 993 TbttNumToNextWakeUp); 994 if (brc == TRUE) 995 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_DOZE); 996 } else { 997 AUTO_WAKEUP_STRUC AutoWakeupCfg; 998 /* we have decided to SLEEP, so at least do it for a BEACON period. */ 999 if (TbttNumToNextWakeUp == 0) 1000 TbttNumToNextWakeUp = 1; 1001 1002 /*RTMP_IO_WRITE32(pAd, INT_MASK_CSR, AutoWakeupInt); */ 1003 1004 AutoWakeupCfg.word = 0; 1005 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); 1006 AutoWakeupCfg.field.NumofSleepingTbtt = TbttNumToNextWakeUp - 1; 1007 AutoWakeupCfg.field.EnableAutoWakeup = 1; 1008 AutoWakeupCfg.field.AutoLeadTime = 5; 1009 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); 1010 AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x00); /* send POWER-SAVE command to MCU. Timeout 40us. */ 1011 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_DOZE); 1012 DBGPRINT(RT_DEBUG_TRACE, 1013 ("<-- %s, TbttNumToNextWakeUp=%d \n", __func__, 1014 TbttNumToNextWakeUp)); 1015 } 1016 1017} 1018 1019void PsPollWakeExec(void *SystemSpecific1, 1020 void *FunctionContext, 1021 void *SystemSpecific2, void *SystemSpecific3) 1022{ 1023 struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext; 1024 unsigned long flags; 1025 1026 DBGPRINT(RT_DEBUG_TRACE, ("-->PsPollWakeExec \n")); 1027 RTMP_INT_LOCK(&pAd->irq_lock, flags); 1028 if (pAd->Mlme.bPsPollTimerRunning) { 1029 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP); 1030 } 1031 pAd->Mlme.bPsPollTimerRunning = FALSE; 1032 RTMP_INT_UNLOCK(&pAd->irq_lock, flags); 1033#ifdef PCIE_PS_SUPPORT 1034 /* For rt30xx power solution 3, Use software timer to wake up in psm. So call */ 1035 /* AsicForceWakeup here instead of handling twakeup interrupt. */ 1036 if (((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) 1037 && IS_VERSION_AFTER_F(pAd)) 1038 && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3) 1039 && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) { 1040 DBGPRINT(RT_DEBUG_TRACE, 1041 ("<--PsPollWakeExec::3090 calls AsicForceWakeup(pAd, DOT11POWERSAVE) in advance \n")); 1042 AsicForceWakeup(pAd, DOT11POWERSAVE); 1043 } 1044#endif /* PCIE_PS_SUPPORT // */ 1045} 1046 1047void RadioOnExec(void *SystemSpecific1, 1048 void *FunctionContext, 1049 void *SystemSpecific2, void *SystemSpecific3) 1050{ 1051 struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext; 1052 struct rt_rtmp_chip_op *pChipOps = &pAd->chipOps; 1053 WPDMA_GLO_CFG_STRUC DmaCfg; 1054 BOOLEAN Cancelled; 1055 1056 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) { 1057 DBGPRINT(RT_DEBUG_TRACE, 1058 ("-->RadioOnExec() return on fOP_STATUS_DOZE == TRUE; \n")); 1059/*KH Debug: Add the compile flag "RT2860 and condition */ 1060#ifdef RTMP_PCI_SUPPORT 1061 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE) 1062 && pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) 1063 RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10); 1064#endif /* RTMP_PCI_SUPPORT // */ 1065 return; 1066 } 1067 1068 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) { 1069 DBGPRINT(RT_DEBUG_TRACE, 1070 ("-->RadioOnExec() return on SCAN_IN_PROGRESS; \n")); 1071#ifdef RTMP_PCI_SUPPORT 1072 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE) 1073 && pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) 1074 RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10); 1075#endif /* RTMP_PCI_SUPPORT // */ 1076 return; 1077 } 1078/*KH Debug: need to check. I add the compile flag "CONFIG_STA_SUPPORT" to enclose the following codes. */ 1079#ifdef RTMP_PCI_SUPPORT 1080 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE) 1081 && pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) { 1082 pAd->Mlme.bPsPollTimerRunning = FALSE; 1083 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); 1084 } 1085#endif /* RTMP_PCI_SUPPORT // */ 1086 if (pAd->StaCfg.bRadio == TRUE) { 1087 pAd->bPCIclkOff = FALSE; 1088 RTMPRingCleanUp(pAd, QID_AC_BK); 1089 RTMPRingCleanUp(pAd, QID_AC_BE); 1090 RTMPRingCleanUp(pAd, QID_AC_VI); 1091 RTMPRingCleanUp(pAd, QID_AC_VO); 1092 RTMPRingCleanUp(pAd, QID_MGMT); 1093 RTMPRingCleanUp(pAd, QID_RX); 1094 1095 /* 2. Send wake up command. */ 1096 AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x02); 1097 /* 2-1. wait command ok. */ 1098 AsicCheckCommanOk(pAd, PowerWakeCID); 1099 1100 /* When PCI clock is off, don't want to service interrupt. So when back to clock on, enable interrupt. */ 1101 /*RTMP_IO_WRITE32(pAd, INT_MASK_CSR, (DELAYINTMASK|RxINT)); */ 1102 RTMP_ASIC_INTERRUPT_ENABLE(pAd); 1103 1104 /* 3. Enable Tx DMA. */ 1105 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word); 1106 DmaCfg.field.EnableTxDMA = 1; 1107 RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, DmaCfg.word); 1108 1109 /* In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again. */ 1110 if (INFRA_ON(pAd) 1111 && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel) 1112 && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == 1113 BW_40)) { 1114 /* Must using 40MHz. */ 1115 AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, 1116 FALSE); 1117 AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); 1118 } else { 1119 /* Must using 20MHz. */ 1120 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); 1121 AsicLockChannel(pAd, pAd->CommonCfg.Channel); 1122 } 1123 1124/*KH Debug:The following codes should be enclosed by RT3090 compile flag */ 1125 if (pChipOps->AsicReverseRfFromSleepMode) 1126 pChipOps->AsicReverseRfFromSleepMode(pAd); 1127 1128#ifdef PCIE_PS_SUPPORT 1129/* 3090 MCU Wakeup command needs more time to be stable. */ 1130/* Before stable, don't issue other MCU command to prevent from firmware error. */ 1131 if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) 1132 && IS_VERSION_AFTER_F(pAd) 1133 && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3) 1134 && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) { 1135 RTMP_SEM_LOCK(&pAd->McuCmdLock); 1136 pAd->brt30xxBanMcuCmd = FALSE; 1137 RTMP_SEM_UNLOCK(&pAd->McuCmdLock); 1138 } 1139#endif /* PCIE_PS_SUPPORT // */ 1140 1141 /* Clear Radio off flag */ 1142 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); 1143 1144 /* Set LED */ 1145 RTMPSetLED(pAd, LED_RADIO_ON); 1146 1147 if (pAd->StaCfg.Psm == PWR_ACTIVE) { 1148 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, 1149 pAd->StaCfg.BBPR3); 1150 } 1151 } else { 1152 RT28xxPciAsicRadioOff(pAd, GUIRADIO_OFF, 0); 1153 } 1154} 1155 1156/* 1157 ========================================================================== 1158 Description: 1159 This routine sends command to firmware and turn our chip to wake up mode from power save mode. 1160 Both RadioOn and .11 power save function needs to call this routine. 1161 Input: 1162 Level = GUIRADIO_OFF : call this function is from Radio Off to Radio On. Need to restore PCI host value. 1163 Level = other value : normal wake up function. 1164 1165 ========================================================================== 1166 */ 1167BOOLEAN RT28xxPciAsicRadioOn(struct rt_rtmp_adapter *pAd, u8 Level) 1168{ 1169 /*WPDMA_GLO_CFG_STRUC DmaCfg; */ 1170 BOOLEAN Cancelled; 1171 /*u32 MACValue; */ 1172 1173 if (pAd->OpMode == OPMODE_AP && Level == DOT11POWERSAVE) 1174 return FALSE; 1175 1176 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) { 1177 if (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) { 1178 pAd->Mlme.bPsPollTimerRunning = FALSE; 1179 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); 1180 } 1181 if ((pAd->StaCfg.PSControl.field.EnableNewPS == TRUE && 1182 (Level == GUIRADIO_OFF || Level == GUI_IDLE_POWER_SAVE)) || 1183 RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND)) { 1184 /* Some chips don't need to delay 6ms, so copy RTMPPCIePowerLinkCtrlRestore */ 1185 /* return condition here. */ 1186 /* 1187 if (((pAd->MACVersion&0xffff0000) != 0x28600000) 1188 && ((pAd->DeviceID == NIC2860_PCIe_DEVICE_ID) 1189 ||(pAd->DeviceID == NIC2790_PCIe_DEVICE_ID))) 1190 */ 1191 { 1192 DBGPRINT(RT_DEBUG_TRACE, 1193 ("RT28xxPciAsicRadioOn ()\n")); 1194 /* 1. Set PCI Link Control in Configuration Space. */ 1195 RTMPPCIeLinkCtrlValueRestore(pAd, 1196 RESTORE_WAKEUP); 1197 RTMPusecDelay(6000); 1198 } 1199 } 1200 } 1201#ifdef PCIE_PS_SUPPORT 1202 if (! 1203 (((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) 1204 && IS_VERSION_AFTER_F(pAd) 1205 && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3) 1206 && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)))) 1207#endif /* PCIE_PS_SUPPORT // */ 1208 { 1209 pAd->bPCIclkOff = FALSE; 1210 DBGPRINT(RT_DEBUG_TRACE, 1211 ("PSM :309xbPCIclkOff == %d\n", pAd->bPCIclkOff)); 1212 } 1213 /* 2. Send wake up command. */ 1214 AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x02); 1215 pAd->bPCIclkOff = FALSE; 1216 /* 2-1. wait command ok. */ 1217 AsicCheckCommanOk(pAd, PowerWakeCID); 1218 RTMP_ASIC_INTERRUPT_ENABLE(pAd); 1219 1220 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF); 1221 if (Level == GUI_IDLE_POWER_SAVE) { 1222#ifdef PCIE_PS_SUPPORT 1223 1224 /* add by johnli, RF power sequence setup, load RF normal operation-mode setup */ 1225 if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd))) { 1226 struct rt_rtmp_chip_op *pChipOps = &pAd->chipOps; 1227 1228 if (pChipOps->AsicReverseRfFromSleepMode) 1229 pChipOps->AsicReverseRfFromSleepMode(pAd); 1230 /* 3090 MCU Wakeup command needs more time to be stable. */ 1231 /* Before stable, don't issue other MCU command to prevent from firmware error. */ 1232 if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) 1233 && IS_VERSION_AFTER_F(pAd) 1234 && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 1235 3) 1236 && (pAd->StaCfg.PSControl.field.EnableNewPS == 1237 TRUE)) { 1238 RTMP_SEM_LOCK(&pAd->McuCmdLock); 1239 pAd->brt30xxBanMcuCmd = FALSE; 1240 RTMP_SEM_UNLOCK(&pAd->McuCmdLock); 1241 } 1242 } else 1243 /* end johnli */ 1244#endif /* PCIE_PS_SUPPORT // */ 1245 { 1246 /* In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again. */ 1247 { 1248 if (INFRA_ON(pAd) 1249 && (pAd->CommonCfg.CentralChannel != 1250 pAd->CommonCfg.Channel) 1251 && (pAd->MlmeAux.HtCapability.HtCapInfo. 1252 ChannelWidth == BW_40)) { 1253 /* Must using 40MHz. */ 1254 AsicSwitchChannel(pAd, 1255 pAd->CommonCfg. 1256 CentralChannel, 1257 FALSE); 1258 AsicLockChannel(pAd, 1259 pAd->CommonCfg. 1260 CentralChannel); 1261 } else { 1262 /* Must using 20MHz. */ 1263 AsicSwitchChannel(pAd, 1264 pAd->CommonCfg. 1265 Channel, FALSE); 1266 AsicLockChannel(pAd, 1267 pAd->CommonCfg.Channel); 1268 } 1269 } 1270 1271 } 1272 } 1273 return TRUE; 1274 1275} 1276 1277/* 1278 ========================================================================== 1279 Description: 1280 This routine sends command to firmware and turn our chip to power save mode. 1281 Both RadioOff and .11 power save function needs to call this routine. 1282 Input: 1283 Level = GUIRADIO_OFF : GUI Radio Off mode 1284 Level = DOT11POWERSAVE : 802.11 power save mode 1285 Level = RTMP_HALT : When Disable device. 1286 1287 ========================================================================== 1288 */ 1289BOOLEAN RT28xxPciAsicRadioOff(struct rt_rtmp_adapter *pAd, 1290 u8 Level, u16 TbttNumToNextWakeUp) 1291{ 1292 WPDMA_GLO_CFG_STRUC DmaCfg; 1293 u8 i, tempBBP_R3 = 0; 1294 BOOLEAN brc = FALSE, Cancelled; 1295 u32 TbTTTime = 0; 1296 u32 PsPollTime = 0 /*, MACValue */ ; 1297 unsigned long BeaconPeriodTime; 1298 u32 RxDmaIdx, RxCpuIdx; 1299 DBGPRINT(RT_DEBUG_TRACE, 1300 ("AsicRadioOff ===> Lv= %d, TxCpuIdx = %d, TxDmaIdx = %d. RxCpuIdx = %d, RxDmaIdx = %d.\n", 1301 Level, pAd->TxRing[0].TxCpuIdx, pAd->TxRing[0].TxDmaIdx, 1302 pAd->RxRing.RxCpuIdx, pAd->RxRing.RxDmaIdx)); 1303 1304 if (pAd->OpMode == OPMODE_AP && Level == DOT11POWERSAVE) 1305 return FALSE; 1306 1307 /* Check Rx DMA busy status, if more than half is occupied, give up this radio off. */ 1308 RTMP_IO_READ32(pAd, RX_DRX_IDX, &RxDmaIdx); 1309 RTMP_IO_READ32(pAd, RX_CRX_IDX, &RxCpuIdx); 1310 if ((RxDmaIdx > RxCpuIdx) && ((RxDmaIdx - RxCpuIdx) > RX_RING_SIZE / 3)) { 1311 DBGPRINT(RT_DEBUG_TRACE, 1312 ("AsicRadioOff ===> return1. RxDmaIdx = %d , RxCpuIdx = %d. \n", 1313 RxDmaIdx, RxCpuIdx)); 1314 return FALSE; 1315 } else if ((RxCpuIdx >= RxDmaIdx) 1316 && ((RxCpuIdx - RxDmaIdx) < RX_RING_SIZE / 3)) { 1317 DBGPRINT(RT_DEBUG_TRACE, 1318 ("AsicRadioOff ===> return2. RxCpuIdx = %d. RxDmaIdx = %d , \n", 1319 RxCpuIdx, RxDmaIdx)); 1320 return FALSE; 1321 } 1322 /* Once go into this function, disable tx because don't want too many packets in queue to prevent HW stops. */ 1323 /*pAd->bPCIclkOffDisableTx = TRUE; */ 1324 RTMP_SET_PSFLAG(pAd, fRTMP_PS_DISABLE_TX); 1325 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE) 1326 && pAd->OpMode == OPMODE_STA 1327 && pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) { 1328 RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled); 1329 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); 1330 1331 if (Level == DOT11POWERSAVE) { 1332 RTMP_IO_READ32(pAd, TBTT_TIMER, &TbTTTime); 1333 TbTTTime &= 0x1ffff; 1334 /* 00. check if need to do sleep in this DTIM period. If next beacon will arrive within 30ms , ...doesn't necessarily sleep. */ 1335 /* TbTTTime uint = 64us, LEAD_TIME unit = 1024us, PsPollTime unit = 1ms */ 1336 if (((64 * TbTTTime) < ((LEAD_TIME * 1024) + 40000)) 1337 && (TbttNumToNextWakeUp == 0)) { 1338 DBGPRINT(RT_DEBUG_TRACE, 1339 ("TbTTTime = 0x%x , give up this sleep. \n", 1340 TbTTTime)); 1341 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); 1342 /*pAd->bPCIclkOffDisableTx = FALSE; */ 1343 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_DISABLE_TX); 1344 return FALSE; 1345 } else { 1346 PsPollTime = 1347 (64 * TbTTTime - LEAD_TIME * 1024) / 1000; 1348#ifdef PCIE_PS_SUPPORT 1349 if ((IS_RT3090(pAd) || IS_RT3572(pAd) 1350 || IS_RT3390(pAd)) 1351 && IS_VERSION_AFTER_F(pAd) 1352 && (pAd->StaCfg.PSControl.field. 1353 rt30xxPowerMode == 3) 1354 && (pAd->StaCfg.PSControl.field. 1355 EnableNewPS == TRUE)) { 1356 PsPollTime -= 5; 1357 } else 1358#endif /* PCIE_PS_SUPPORT // */ 1359 PsPollTime -= 3; 1360 1361 BeaconPeriodTime = 1362 pAd->CommonCfg.BeaconPeriod * 102 / 100; 1363 if (TbttNumToNextWakeUp > 0) 1364 PsPollTime += 1365 ((TbttNumToNextWakeUp - 1366 1) * BeaconPeriodTime); 1367 1368 pAd->Mlme.bPsPollTimerRunning = TRUE; 1369 RTMPSetTimer(&pAd->Mlme.PsPollTimer, 1370 PsPollTime); 1371 } 1372 } 1373 } else { 1374 DBGPRINT(RT_DEBUG_TRACE, 1375 ("RT28xxPciAsicRadioOff::Level!=DOT11POWERSAVE \n")); 1376 } 1377 1378 pAd->bPCIclkOffDisableTx = FALSE; 1379 1380 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF); 1381 1382 /* Set to 1R. */ 1383 if (pAd->Antenna.field.RxPath > 1 && pAd->OpMode == OPMODE_STA) { 1384 tempBBP_R3 = (pAd->StaCfg.BBPR3 & 0xE7); 1385 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, tempBBP_R3); 1386 } 1387 /* In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again. */ 1388 if ((INFRA_ON(pAd) || pAd->OpMode == OPMODE_AP) 1389 && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel) 1390 && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) { 1391 /* Must using 40MHz. */ 1392 AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel); 1393 } else { 1394 /* Must using 20MHz. */ 1395 AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel); 1396 } 1397 1398 if (Level != RTMP_HALT) { 1399 /* Change Interrupt bitmask. */ 1400 /* When PCI clock is off, don't want to service interrupt. */ 1401 RTMP_IO_WRITE32(pAd, INT_MASK_CSR, AutoWakeupInt); 1402 } else { 1403 RTMP_ASIC_INTERRUPT_DISABLE(pAd); 1404 } 1405 1406 RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx); 1407 /* 2. Send Sleep command */ 1408 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff); 1409 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff); 1410 /* send POWER-SAVE command to MCU. high-byte = 1 save power as much as possible. high byte = 0 save less power */ 1411 AsicSendCommandToMcu(pAd, 0x30, PowerSafeCID, 0xff, 0x1); 1412 /* 2-1. Wait command success */ 1413 /* Status = 1 : success, Status = 2, already sleep, Status = 3, Maybe MAC is busy so can't finish this task. */ 1414 brc = AsicCheckCommanOk(pAd, PowerSafeCID); 1415 1416 /* 3. After 0x30 command is ok, send radio off command. lowbyte = 0 for power safe. */ 1417 /* If 0x30 command is not ok this time, we can ignore 0x35 command. It will make sure not cause firmware'r problem. */ 1418 if ((Level == DOT11POWERSAVE) && (brc == TRUE)) { 1419 AsicSendCommandToMcu(pAd, 0x35, PowerRadioOffCID, 0, 0x00); /* lowbyte = 0 means to do power safe, NOT turn off radio. */ 1420 /* 3-1. Wait command success */ 1421 AsicCheckCommanOk(pAd, PowerRadioOffCID); 1422 } else if (brc == TRUE) { 1423 AsicSendCommandToMcu(pAd, 0x35, PowerRadioOffCID, 1, 0x00); /* lowbyte = 0 means to do power safe, NOT turn off radio. */ 1424 /* 3-1. Wait command success */ 1425 AsicCheckCommanOk(pAd, PowerRadioOffCID); 1426 } 1427 /* 1. Wait DMA not busy */ 1428 i = 0; 1429 do { 1430 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word); 1431 if ((DmaCfg.field.RxDMABusy == 0) 1432 && (DmaCfg.field.TxDMABusy == 0)) 1433 break; 1434 RTMPusecDelay(20); 1435 i++; 1436 } while (i < 50); 1437 1438 /* 1439 if (i >= 50) 1440 { 1441 pAd->CheckDmaBusyCount++; 1442 DBGPRINT(RT_DEBUG_TRACE, ("DMA Rx keeps busy. return on AsicRadioOff () CheckDmaBusyCount = %d \n", pAd->CheckDmaBusyCount)); 1443 } 1444 else 1445 { 1446 pAd->CheckDmaBusyCount = 0; 1447 } 1448 */ 1449/*KH Debug:My original codes have the follwoing codes, but currecnt codes do not have it. */ 1450/* Disable for stability. If PCIE Link Control is modified for advance power save, re-covery this code segment. */ 1451 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0x1280); 1452/*OPSTATUS_SET_FLAG(pAd, fOP_STATUS_CLKSELECT_40MHZ); */ 1453 1454#ifdef PCIE_PS_SUPPORT 1455 if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) 1456 && IS_VERSION_AFTER_F(pAd) 1457 && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3) 1458 && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) { 1459 DBGPRINT(RT_DEBUG_TRACE, 1460 ("RT28xxPciAsicRadioOff::3090 return to skip the following TbttNumToNextWakeUp setting for 279x\n")); 1461 pAd->bPCIclkOff = TRUE; 1462 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_DISABLE_TX); 1463 /* For this case, doesn't need to below actions, so return here. */ 1464 return brc; 1465 } 1466#endif /* PCIE_PS_SUPPORT // */ 1467 1468 if (Level == DOT11POWERSAVE) { 1469 AUTO_WAKEUP_STRUC AutoWakeupCfg; 1470 /*RTMPSetTimer(&pAd->Mlme.PsPollTimer, 90); */ 1471 1472 /* we have decided to SLEEP, so at least do it for a BEACON period. */ 1473 if (TbttNumToNextWakeUp == 0) 1474 TbttNumToNextWakeUp = 1; 1475 1476 AutoWakeupCfg.word = 0; 1477 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); 1478 1479 /* 1. Set auto wake up timer. */ 1480 AutoWakeupCfg.field.NumofSleepingTbtt = TbttNumToNextWakeUp - 1; 1481 AutoWakeupCfg.field.EnableAutoWakeup = 1; 1482 AutoWakeupCfg.field.AutoLeadTime = LEAD_TIME; 1483 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); 1484 } 1485 /* 4-1. If it's to disable our device. Need to restore PCI Configuration Space to its original value. */ 1486 if (Level == RTMP_HALT && pAd->OpMode == OPMODE_STA) { 1487 if ((brc == TRUE) && (i < 50)) 1488 RTMPPCIeLinkCtrlSetting(pAd, 1); 1489 } 1490 /* 4. Set PCI configuration Space Link Comtrol fields. Only Radio Off needs to call this function */ 1491 else if (pAd->OpMode == OPMODE_STA) { 1492 if ((brc == TRUE) && (i < 50)) 1493 RTMPPCIeLinkCtrlSetting(pAd, 3); 1494 } 1495 /*pAd->bPCIclkOffDisableTx = FALSE; */ 1496 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_DISABLE_TX); 1497 return TRUE; 1498} 1499 1500void RT28xxPciMlmeRadioOn(struct rt_rtmp_adapter *pAd) 1501{ 1502 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) 1503 return; 1504 1505 DBGPRINT(RT_DEBUG_TRACE, ("%s===>\n", __func__)); 1506 1507 if ((pAd->OpMode == OPMODE_AP) || ((pAd->OpMode == OPMODE_STA) 1508 && 1509 (!OPSTATUS_TEST_FLAG 1510 (pAd, fOP_STATUS_PCIE_DEVICE) 1511 || pAd->StaCfg.PSControl.field. 1512 EnableNewPS == FALSE))) { 1513 RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE); 1514 /*NICResetFromError(pAd); */ 1515 1516 RTMPRingCleanUp(pAd, QID_AC_BK); 1517 RTMPRingCleanUp(pAd, QID_AC_BE); 1518 RTMPRingCleanUp(pAd, QID_AC_VI); 1519 RTMPRingCleanUp(pAd, QID_AC_VO); 1520 RTMPRingCleanUp(pAd, QID_MGMT); 1521 RTMPRingCleanUp(pAd, QID_RX); 1522 1523 /* Enable Tx/Rx */ 1524 RTMPEnableRxTx(pAd); 1525 1526 /* Clear Radio off flag */ 1527 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); 1528 1529 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF); 1530 1531 /* Set LED */ 1532 RTMPSetLED(pAd, LED_RADIO_ON); 1533 } 1534 1535 if ((pAd->OpMode == OPMODE_STA) && 1536 (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) 1537 && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) { 1538 BOOLEAN Cancelled; 1539 1540 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP); 1541 1542 pAd->Mlme.bPsPollTimerRunning = FALSE; 1543 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); 1544 RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled); 1545 RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 40); 1546 } 1547} 1548 1549void RT28xxPciMlmeRadioOFF(struct rt_rtmp_adapter *pAd) 1550{ 1551 BOOLEAN brc = TRUE; 1552 1553 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) 1554 return; 1555 1556 /* Link down first if any association exists */ 1557 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) { 1558 if (INFRA_ON(pAd) || ADHOC_ON(pAd)) { 1559 struct rt_mlme_disassoc_req DisReq; 1560 struct rt_mlme_queue_elem *pMsgElem = 1561 kmalloc(sizeof(struct rt_mlme_queue_elem), 1562 MEM_ALLOC_FLAG); 1563 1564 if (pMsgElem) { 1565 COPY_MAC_ADDR(&DisReq.Addr, 1566 pAd->CommonCfg.Bssid); 1567 DisReq.Reason = REASON_DISASSOC_STA_LEAVING; 1568 1569 pMsgElem->Machine = ASSOC_STATE_MACHINE; 1570 pMsgElem->MsgType = MT2_MLME_DISASSOC_REQ; 1571 pMsgElem->MsgLen = 1572 sizeof(struct rt_mlme_disassoc_req); 1573 NdisMoveMemory(pMsgElem->Msg, &DisReq, 1574 sizeof 1575 (struct rt_mlme_disassoc_req)); 1576 1577 MlmeDisassocReqAction(pAd, pMsgElem); 1578 kfree(pMsgElem); 1579 1580 RTMPusecDelay(1000); 1581 } 1582 } 1583 } 1584 1585 DBGPRINT(RT_DEBUG_TRACE, ("%s===>\n", __func__)); 1586 1587 /* Set Radio off flag */ 1588 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); 1589 1590 { 1591 BOOLEAN Cancelled; 1592 if (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) { 1593 if (RTMP_TEST_FLAG 1594 (pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) { 1595 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, 1596 &Cancelled); 1597 RTMP_CLEAR_FLAG(pAd, 1598 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); 1599 } 1600 /* If during power safe mode. */ 1601 if (pAd->StaCfg.bRadio == TRUE) { 1602 DBGPRINT(RT_DEBUG_TRACE, 1603 ("-->MlmeRadioOff() return on bRadio == TRUE; \n")); 1604 return; 1605 } 1606 /* Always radio on since the NIC needs to set the MCU command (LED_RADIO_OFF). */ 1607 if (IDLE_ON(pAd) && 1608 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))) 1609 { 1610 RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE); 1611 } 1612 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) { 1613 BOOLEAN Cancelled; 1614 pAd->Mlme.bPsPollTimerRunning = FALSE; 1615 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, 1616 &Cancelled); 1617 RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, 1618 &Cancelled); 1619 } 1620 } 1621 /* Link down first if any association exists */ 1622 if (INFRA_ON(pAd) || ADHOC_ON(pAd)) 1623 LinkDown(pAd, FALSE); 1624 RTMPusecDelay(10000); 1625 /*========================================== */ 1626 /* Clean up old bss table */ 1627 BssTableInit(&pAd->ScanTab); 1628 1629 /* 1630 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) 1631 { 1632 RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10); 1633 return; 1634 } 1635 */ 1636 } 1637 1638 /* Set LED.Move to here for fixing LED bug. This flag must be called after LinkDown */ 1639 RTMPSetLED(pAd, LED_RADIO_OFF); 1640 1641/*KH Debug:All PCIe devices need to use timer to execute radio off function, or the PCIe&&EnableNewPS needs. */ 1642/*KH Ans:It is right, because only when the PCIe and EnableNewPs is true, we need to delay the RadioOffTimer */ 1643/*to avoid the deadlock with PCIe Power saving function. */ 1644 if (pAd->OpMode == OPMODE_STA && 1645 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE) && 1646 pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) { 1647 RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10); 1648 } else { 1649 brc = RT28xxPciAsicRadioOff(pAd, GUIRADIO_OFF, 0); 1650 1651 if (brc == FALSE) { 1652 DBGPRINT(RT_DEBUG_ERROR, 1653 ("%s call RT28xxPciAsicRadioOff fail!\n", 1654 __func__)); 1655 } 1656 } 1657/* 1658*/ 1659} 1660 1661#endif /* RTMP_MAC_PCI // */ 1662