Fix common misspellings
[deliverable/linux.git] / drivers / staging / rt2860 / common / cmm_mac_pci.c
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 */
51 int 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 */
403 void 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
536 void 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 ========================================================================
658 Routine Description:
659 Disable DMA.
660
661 Arguments:
662 *pAd the raxx interface data pointer
663
664 Return Value:
665 None
666
667 Note:
668 ========================================================================
669 */
670 void 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 ========================================================================
682 Routine Description:
683 Enable DMA.
684
685 Arguments:
686 *pAd the raxx interface data pointer
687
688 Return Value:
689 None
690
691 Note:
692 ========================================================================
693 */
694 void 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
724 BOOLEAN 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 command 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 ========================================================================
785 Routine Description:
786 Write Beacon buffer to Asic.
787
788 Arguments:
789 *pAd the raxx interface data pointer
790
791 Return Value:
792 None
793
794 Note:
795 ========================================================================
796 */
797 void 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
856 void 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
952 void 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
1019 void 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
1047 void 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 */
1167 BOOLEAN 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 */
1289 BOOLEAN 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 following 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
1500 void 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
1549 void 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 // */
This page took 0.078673 seconds and 5 git commands to generate.