staging: rtl8192u: remove commented-out code in r819xU_cmdpkt.c
[firefly-linux-kernel-4.4.55.git] / drivers / staging / rtl8192u / r819xU_cmdpkt.c
1 /******************************************************************************
2
3      (c) Copyright 2008, RealTEK Technologies Inc. All Rights Reserved.
4
5  Module:        r819xusb_cmdpkt.c       (RTL8190 TX/RX command packet handler Source C File)
6
7  Note:      The module is responsible for handling TX and RX command packet.
8                         1. TX : Send set and query configuration command packet.
9                         2. RX : Receive tx feedback, beacon state, query configuration
10                                 command packet.
11
12  Function:
13
14  Export:
15
16  Abbrev:
17
18  History:
19         Data            Who             Remark
20
21         05/06/2008  amy         Create initial version porting from windows driver.
22
23 ******************************************************************************/
24 #include "r8192U.h"
25 #include "r819xU_cmdpkt.h"
26 /*---------------------------Define Local Constant---------------------------*/
27 /* Debug constant*/
28 #define         CMPK_DEBOUNCE_CNT                       1
29 /* 2007/10/24 MH Add for printing a range of data. */
30 #define         CMPK_PRINT(Address)\
31 {\
32         unsigned char   i;\
33         u32     temp[10];\
34         \
35         memcpy(temp, Address, 40);\
36         for (i = 0; i <40; i+=4)\
37                 printk("\r\n %08x", temp[i]);\
38 }\
39 /*---------------------------Define functions---------------------------------*/
40
41 rt_status
42 SendTxCommandPacket(
43         struct net_device *dev,
44         void                    *pData,
45         u32                             DataLen
46         )
47 {
48         rt_status       rtStatus = RT_STATUS_SUCCESS;
49         struct r8192_priv   *priv = ieee80211_priv(dev);
50         struct sk_buff      *skb;
51         cb_desc             *tcb_desc;
52         unsigned char       *ptr_buf;
53
54         //Get TCB and local buffer from common pool. (It is shared by CmdQ, MgntQ, and USB coalesce DataQ)
55         skb  = dev_alloc_skb(USB_HWDESC_HEADER_LEN + DataLen + 4);
56         memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev));
57         tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
58         tcb_desc->queue_index = TXCMD_QUEUE;
59         tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_NORMAL;
60         tcb_desc->bLastIniPkt = 0;
61         skb_reserve(skb, USB_HWDESC_HEADER_LEN);
62         ptr_buf = skb_put(skb, DataLen);
63         memcpy(ptr_buf,pData,DataLen);
64         tcb_desc->txbuf_size= (u16)DataLen;
65
66         if (!priv->ieee80211->check_nic_enough_desc(dev,tcb_desc->queue_index)||
67                         (!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index]))||\
68                         (priv->ieee80211->queue_stop) ) {
69                         RT_TRACE(COMP_FIRMWARE,"===================NULL packet==================================> tx full!\n");
70                         skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb);
71                 } else {
72                         priv->ieee80211->softmac_hard_start_xmit(skb,dev);
73                 }
74
75         return rtStatus;
76 }
77
78 /*-----------------------------------------------------------------------------
79  * Function:    cmpk_message_handle_tx()
80  *
81  * Overview:    Driver internal module can call the API to send message to
82  *                              firmware side. For example, you can send a debug command packet.
83  *                              Or you can send a request for FW to modify RLX4181 LBUS HW bank.
84  *                              Otherwise, you can change MAC/PHT/RF register by firmware at
85  *                              run time. We do not support message more than one segment now.
86  *
87  * Input:               NONE
88  *
89  * Output:              NONE
90  *
91  * Return:              NONE
92  *
93  * Revised History:
94  *      When            Who             Remark
95  *      05/06/2008      amy             porting from windows code.
96  *
97  *---------------------------------------------------------------------------*/
98  extern rt_status       cmpk_message_handle_tx(
99         struct net_device *dev,
100         u8      *codevirtualaddress,
101         u32     packettype,
102         u32     buffer_len)
103 {
104
105         bool        rt_status = true;
106 #ifdef RTL8192U
107         return rt_status;
108 #else
109         struct r8192_priv   *priv = ieee80211_priv(dev);
110         u16                 frag_threshold;
111         u16                 frag_length, frag_offset = 0;
112
113         rt_firmware         *pfirmware = priv->pFirmware;
114         struct sk_buff      *skb;
115         unsigned char       *seg_ptr;
116         cb_desc             *tcb_desc;
117         u8                  bLastIniPkt;
118
119         firmware_init_param(dev);
120         //Fragmentation might be required
121         frag_threshold = pfirmware->cmdpacket_frag_thresold;
122         do {
123                 if ((buffer_len - frag_offset) > frag_threshold) {
124                         frag_length = frag_threshold ;
125                         bLastIniPkt = 0;
126
127                 } else {
128                         frag_length = buffer_len - frag_offset;
129                         bLastIniPkt = 1;
130
131                 }
132
133                 /* Allocate skb buffer to contain firmware info and tx descriptor info
134                  * add 4 to avoid packet appending overflow.
135                  * */
136                 #ifdef RTL8192U
137                 skb  = dev_alloc_skb(USB_HWDESC_HEADER_LEN + frag_length + 4);
138                 #else
139                 skb  = dev_alloc_skb(frag_length + 4);
140                 #endif
141                 memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev));
142                 tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
143                 tcb_desc->queue_index = TXCMD_QUEUE;
144                 tcb_desc->bCmdOrInit = packettype;
145                 tcb_desc->bLastIniPkt = bLastIniPkt;
146
147                 #ifdef RTL8192U
148                 skb_reserve(skb, USB_HWDESC_HEADER_LEN);
149                 #endif
150
151                 seg_ptr = skb_put(skb, buffer_len);
152                 /*
153                  * Transform from little endian to big endian
154                  * and pending zero
155                  */
156                 memcpy(seg_ptr,codevirtualaddress,buffer_len);
157                 tcb_desc->txbuf_size= (u16)buffer_len;
158
159
160                 if (!priv->ieee80211->check_nic_enough_desc(dev,tcb_desc->queue_index)||
161                         (!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index]))||\
162                         (priv->ieee80211->queue_stop) ) {
163                         RT_TRACE(COMP_FIRMWARE,"=====================================================> tx full!\n");
164                         skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb);
165                 } else {
166                         priv->ieee80211->softmac_hard_start_xmit(skb,dev);
167                 }
168
169                 codevirtualaddress += frag_length;
170                 frag_offset += frag_length;
171
172         }while(frag_offset < buffer_len);
173
174         return rt_status;
175
176
177 #endif
178 }       /* CMPK_Message_Handle_Tx */
179
180 /*-----------------------------------------------------------------------------
181  * Function:    cmpk_counttxstatistic()
182  *
183  * Overview:
184  *
185  * Input:       PADAPTER        pAdapter                -       .
186  *                              CMPK_TXFB_T *psTx_FB    -       .
187  *
188  * Output:      NONE
189  *
190  * Return:      NONE
191  *
192  * Revised History:
193  *  When                Who             Remark
194  *  05/12/2008  amy     Create Version 0 porting from windows code.
195  *
196  *---------------------------------------------------------------------------*/
197 static  void
198 cmpk_count_txstatistic(
199         struct net_device *dev,
200         cmpk_txfb_t     *pstx_fb)
201 {
202         struct r8192_priv *priv = ieee80211_priv(dev);
203 #ifdef ENABLE_PS
204         RT_RF_POWER_STATE       rtState;
205
206         pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE, (pu1Byte)(&rtState));
207
208         // When RF is off, we should not count the packet for hw/sw synchronize
209         // reason, ie. there may be a duration while sw switch is changed and hw
210         // switch is being changed. 2006.12.04, by shien chang.
211         if (rtState == eRfOff)
212         {
213                 return;
214         }
215 #endif
216
217 #ifdef TODO
218         if (pAdapter->bInHctTest)
219                 return;
220 #endif
221         /* We can not know the packet length and transmit type: broadcast or uni
222            or multicast. So the relative statistics must be collected in tx
223            feedback info. */
224         if (pstx_fb->tok)
225         {
226                 priv->stats.txfeedbackok++;
227                 priv->stats.txoktotal++;
228                 priv->stats.txokbytestotal += pstx_fb->pkt_length;
229                 priv->stats.txokinperiod++;
230
231                 /* We can not make sure broadcast/multicast or unicast mode. */
232                 if (pstx_fb->pkt_type == PACKET_MULTICAST)
233                 {
234                         priv->stats.txmulticast++;
235                         priv->stats.txbytesmulticast += pstx_fb->pkt_length;
236                 }
237                 else if (pstx_fb->pkt_type == PACKET_BROADCAST)
238                 {
239                         priv->stats.txbroadcast++;
240                         priv->stats.txbytesbroadcast += pstx_fb->pkt_length;
241                 }
242                 else
243                 {
244                         priv->stats.txunicast++;
245                         priv->stats.txbytesunicast += pstx_fb->pkt_length;
246                 }
247         }
248         else
249         {
250                 priv->stats.txfeedbackfail++;
251                 priv->stats.txerrtotal++;
252                 priv->stats.txerrbytestotal += pstx_fb->pkt_length;
253
254                 /* We can not make sure broadcast/multicast or unicast mode. */
255                 if (pstx_fb->pkt_type == PACKET_MULTICAST)
256                 {
257                         priv->stats.txerrmulticast++;
258                 }
259                 else if (pstx_fb->pkt_type == PACKET_BROADCAST)
260                 {
261                         priv->stats.txerrbroadcast++;
262                 }
263                 else
264                 {
265                         priv->stats.txerrunicast++;
266                 }
267         }
268
269         priv->stats.txretrycount += pstx_fb->retry_cnt;
270         priv->stats.txfeedbackretry += pstx_fb->retry_cnt;
271
272 }       /* cmpk_CountTxStatistic */
273
274
275
276 /*-----------------------------------------------------------------------------
277  * Function:    cmpk_handle_tx_feedback()
278  *
279  * Overview:    The function is responsible for extract the message inside TX
280  *                              feedbck message from firmware. It will contain dedicated info in
281  *                              ws-06-0063-rtl8190-command-packet-specification. Please
282  *                              refer to chapter "TX Feedback Element". We have to read 20 bytes
283  *                              in the command packet.
284  *
285  * Input:       struct net_device *    dev
286  *                              u8      *       pmsg            -       Msg Ptr of the command packet.
287  *
288  * Output:      NONE
289  *
290  * Return:      NONE
291  *
292  * Revised History:
293  *  When                Who             Remark
294  *  05/08/2008  amy             Create Version 0 porting from windows code.
295  *
296  *---------------------------------------------------------------------------*/
297 static  void
298 cmpk_handle_tx_feedback(
299         struct net_device *dev,
300         u8      *pmsg)
301 {
302         struct r8192_priv *priv = ieee80211_priv(dev);
303         cmpk_txfb_t             rx_tx_fb;       /* */
304
305         priv->stats.txfeedback++;
306
307         /* 1. Extract TX feedback info from RFD to temp structure buffer. */
308         /* It seems that FW use big endian(MIPS) and DRV use little endian in
309            windows OS. So we have to read the content byte by byte or transfer
310            endian type before copy the message copy. */
311         /* 2007/07/05 MH Use pointer to transfer structure memory. */
312         memcpy((u8 *)&rx_tx_fb, pmsg, sizeof(cmpk_txfb_t));
313         /* 2. Use tx feedback info to count TX statistics. */
314         cmpk_count_txstatistic(dev, &rx_tx_fb);
315         /* 2007/01/17 MH Comment previous method for TX statistic function. */
316         /* Collect info TX feedback packet to fill TCB. */
317         /* We can not know the packet length and transmit type: broadcast or uni
318            or multicast. */
319
320 }       /* cmpk_Handle_Tx_Feedback */
321
322 void
323 cmdpkt_beacontimerinterrupt_819xusb(
324         struct net_device *dev
325 )
326 {
327         struct r8192_priv *priv = ieee80211_priv(dev);
328         u16 tx_rate;
329         {
330                 //
331                 // 070117, rcnjko: 87B have to S/W beacon for DTM encryption_cmn.
332                 //
333                 if (priv->ieee80211->current_network.mode == IEEE_A  ||
334                         priv->ieee80211->current_network.mode == IEEE_N_5G ||
335                         (priv->ieee80211->current_network.mode == IEEE_N_24G  && (!priv->ieee80211->pHTInfo->bCurSuppCCK)))
336                 {
337                         tx_rate = 60;
338                         DMESG("send beacon frame  tx rate is 6Mbpm\n");
339                 }
340                 else
341                 {
342                         tx_rate =10;
343                         DMESG("send beacon frame  tx rate is 1Mbpm\n");
344                 }
345
346                 rtl819xusb_beacon_tx(dev,tx_rate); // HW Beacon
347
348         }
349
350 }
351
352
353
354
355 /*-----------------------------------------------------------------------------
356  * Function:    cmpk_handle_interrupt_status()
357  *
358  * Overview:    The function is responsible for extract the message from
359  *                              firmware. It will contain dedicated info in
360  *                              ws-07-0063-v06-rtl819x-command-packet-specification-070315.doc.
361  *                              Please refer to chapter "Interrupt Status Element".
362  *
363  * Input:       struct net_device *dev,
364  *                      u8*     pmsg            -       Message Pointer of the command packet.
365  *
366  * Output:      NONE
367  *
368  * Return:      NONE
369  *
370  * Revised History:
371  *  When                        Who                     Remark
372  *  05/12/2008  amy             Add this for rtl8192 porting from windows code.
373  *
374  *---------------------------------------------------------------------------*/
375 static  void
376 cmpk_handle_interrupt_status(
377         struct net_device *dev,
378         u8      *pmsg)
379 {
380         cmpk_intr_sta_t         rx_intr_status; /* */
381         struct r8192_priv *priv = ieee80211_priv(dev);
382
383         DMESG("---> cmpk_Handle_Interrupt_Status()\n");
384
385         /* 1. Extract TX feedback info from RFD to temp structure buffer. */
386         /* It seems that FW use big endian(MIPS) and DRV use little endian in
387            windows OS. So we have to read the content byte by byte or transfer
388            endian type before copy the message copy. */
389         rx_intr_status.length = pmsg[1];
390         if (rx_intr_status.length != (sizeof(cmpk_intr_sta_t) - 2))
391         {
392                 DMESG("cmpk_Handle_Interrupt_Status: wrong length!\n");
393                 return;
394         }
395
396
397         // Statistics of beacon for ad-hoc mode.
398         if (    priv->ieee80211->iw_mode == IW_MODE_ADHOC)
399         {
400                 //2 maybe need endian transform?
401                 rx_intr_status.interrupt_status = *((u32 *)(pmsg + 4));
402
403                 DMESG("interrupt status = 0x%x\n", rx_intr_status.interrupt_status);
404
405                 if (rx_intr_status.interrupt_status & ISR_TxBcnOk)
406                 {
407                         priv->ieee80211->bibsscoordinator = true;
408                         priv->stats.txbeaconokint++;
409                 }
410                 else if (rx_intr_status.interrupt_status & ISR_TxBcnErr)
411                 {
412                         priv->ieee80211->bibsscoordinator = false;
413                         priv->stats.txbeaconerr++;
414                 }
415
416                 if (rx_intr_status.interrupt_status & ISR_BcnTimerIntr)
417                 {
418                         cmdpkt_beacontimerinterrupt_819xusb(dev);
419                 }
420
421         }
422
423          // Other informations in interrupt status we need?
424
425
426         DMESG("<---- cmpk_handle_interrupt_status()\n");
427
428 }       /* cmpk_handle_interrupt_status */
429
430
431 /*-----------------------------------------------------------------------------
432  * Function:    cmpk_handle_query_config_rx()
433  *
434  * Overview:    The function is responsible for extract the message from
435  *                              firmware. It will contain dedicated info in
436  *                              ws-06-0063-rtl8190-command-packet-specification. Please
437  *                              refer to chapter "Beacon State Element".
438  *
439  * Input:       u8 *  pmsg      -       Message Pointer of the command packet.
440  *
441  * Output:      NONE
442  *
443  * Return:      NONE
444  *
445  * Revised History:
446  *  When                Who             Remark
447  *  05/12/2008  amy             Create Version 0 porting from windows code.
448  *
449  *---------------------------------------------------------------------------*/
450 static  void
451 cmpk_handle_query_config_rx(
452         struct net_device *dev,
453         u8         *pmsg)
454 {
455         cmpk_query_cfg_t        rx_query_cfg;   /* */
456
457
458         /* 1. Extract TX feedback info from RFD to temp structure buffer. */
459         /* It seems that FW use big endian(MIPS) and DRV use little endian in
460            windows OS. So we have to read the content byte by byte or transfer
461            endian type before copy the message copy. */
462         rx_query_cfg.cfg_action         = (pmsg[4] & 0x80000000)>>31;
463         rx_query_cfg.cfg_type           = (pmsg[4] & 0x60) >> 5;
464         rx_query_cfg.cfg_size           = (pmsg[4] & 0x18) >> 3;
465         rx_query_cfg.cfg_page           = (pmsg[6] & 0x0F) >> 0;
466         rx_query_cfg.cfg_offset                 = pmsg[7];
467         rx_query_cfg.value                      = (pmsg[8] << 24) | (pmsg[9] << 16) |
468                                                                   (pmsg[10] << 8) | (pmsg[11] << 0);
469         rx_query_cfg.mask                       = (pmsg[12] << 24) | (pmsg[13] << 16) |
470                                                                   (pmsg[14] << 8) | (pmsg[15] << 0);
471
472 }       /* cmpk_Handle_Query_Config_Rx */
473
474
475 /*-----------------------------------------------------------------------------
476  * Function:    cmpk_count_tx_status()
477  *
478  * Overview:    Count aggregated tx status from firmwar of one type rx command
479  *                              packet element id = RX_TX_STATUS.
480  *
481  * Input:               NONE
482  *
483  * Output:              NONE
484  *
485  * Return:              NONE
486  *
487  * Revised History:
488  *      When            Who             Remark
489  *      05/12/2008      amy             Create Version 0 porting from windows code.
490  *
491  *---------------------------------------------------------------------------*/
492 static  void    cmpk_count_tx_status(   struct net_device *dev,
493                                                                         cmpk_tx_status_t        *pstx_status)
494 {
495         struct r8192_priv *priv = ieee80211_priv(dev);
496
497 #ifdef ENABLE_PS
498
499         RT_RF_POWER_STATE       rtstate;
500
501         pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE, (pu1Byte)(&rtState));
502
503         // When RF is off, we should not count the packet for hw/sw synchronize
504         // reason, ie. there may be a duration while sw switch is changed and hw
505         // switch is being changed. 2006.12.04, by shien chang.
506         if (rtState == eRfOff)
507         {
508                 return;
509         }
510 #endif
511
512         priv->stats.txfeedbackok        += pstx_status->txok;
513         priv->stats.txoktotal           += pstx_status->txok;
514
515         priv->stats.txfeedbackfail      += pstx_status->txfail;
516         priv->stats.txerrtotal          += pstx_status->txfail;
517
518         priv->stats.txretrycount                += pstx_status->txretry;
519         priv->stats.txfeedbackretry     += pstx_status->txretry;
520
521
522         priv->stats.txmulticast += pstx_status->txmcok;
523         priv->stats.txbroadcast += pstx_status->txbcok;
524         priv->stats.txunicast           += pstx_status->txucok;
525
526         priv->stats.txerrmulticast      += pstx_status->txmcfail;
527         priv->stats.txerrbroadcast      += pstx_status->txbcfail;
528         priv->stats.txerrunicast        += pstx_status->txucfail;
529
530         priv->stats.txbytesmulticast    += pstx_status->txmclength;
531         priv->stats.txbytesbroadcast    += pstx_status->txbclength;
532         priv->stats.txbytesunicast              += pstx_status->txuclength;
533
534         priv->stats.last_packet_rate            = pstx_status->rate;
535 }       /* cmpk_CountTxStatus */
536
537
538
539 /*-----------------------------------------------------------------------------
540  * Function:    cmpk_handle_tx_status()
541  *
542  * Overview:    Firmware add a new tx feedback status to reduce rx command
543  *                              packet buffer operation load.
544  *
545  * Input:               NONE
546  *
547  * Output:              NONE
548  *
549  * Return:              NONE
550  *
551  * Revised History:
552  *      When            Who             Remark
553  *      05/12/2008      amy             Create Version 0 porting from windows code.
554  *
555  *---------------------------------------------------------------------------*/
556 static  void
557 cmpk_handle_tx_status(
558         struct net_device *dev,
559         u8         *pmsg)
560 {
561         cmpk_tx_status_t        rx_tx_sts;      /* */
562
563         memcpy((void *)&rx_tx_sts, (void *)pmsg, sizeof(cmpk_tx_status_t));
564         /* 2. Use tx feedback info to count TX statistics. */
565         cmpk_count_tx_status(dev, &rx_tx_sts);
566
567 }       /* cmpk_Handle_Tx_Status */
568
569
570 /*-----------------------------------------------------------------------------
571  * Function:    cmpk_handle_tx_rate_history()
572  *
573  * Overview:    Firmware add a new tx rate history
574  *
575  * Input:               NONE
576  *
577  * Output:              NONE
578  *
579  * Return:              NONE
580  *
581  * Revised History:
582  *      When            Who             Remark
583  *      05/12/2008      amy             Create Version 0 porting from windows code.
584  *
585  *---------------------------------------------------------------------------*/
586 static  void
587 cmpk_handle_tx_rate_history(
588         struct net_device *dev,
589         u8         *pmsg)
590 {
591         cmpk_tx_rahis_t *ptxrate;
592         u8                              i, j;
593         u16                             length = sizeof(cmpk_tx_rahis_t);
594         u32                             *ptemp;
595         struct r8192_priv *priv = ieee80211_priv(dev);
596
597
598 #ifdef ENABLE_PS
599         pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE, (pu1Byte)(&rtState));
600
601         // When RF is off, we should not count the packet for hw/sw synchronize
602         // reason, ie. there may be a duration while sw switch is changed and hw
603         // switch is being changed. 2006.12.04, by shien chang.
604         if (rtState == eRfOff)
605         {
606                 return;
607         }
608 #endif
609
610         ptemp = (u32 *)pmsg;
611
612         //
613         // Do endian transfer to word alignment(16 bits) for windows system.
614         // You must do different endian transfer for linux and MAC OS
615         //
616         for (i = 0; i < (length/4); i++)
617         {
618                 u16      temp1, temp2;
619
620                 temp1 = ptemp[i]&0x0000FFFF;
621                 temp2 = ptemp[i]>>16;
622                 ptemp[i] = (temp1<<16)|temp2;
623         }
624
625         ptxrate = (cmpk_tx_rahis_t *)pmsg;
626
627         if (ptxrate == NULL )
628         {
629                 return;
630         }
631
632         for (i = 0; i < 16; i++)
633         {
634                 // Collect CCK rate packet num
635                 if (i < 4)
636                         priv->stats.txrate.cck[i] += ptxrate->cck[i];
637
638                 // Collect OFDM rate packet num
639                 if (i< 8)
640                         priv->stats.txrate.ofdm[i] += ptxrate->ofdm[i];
641
642                 for (j = 0; j < 4; j++)
643                         priv->stats.txrate.ht_mcs[j][i] += ptxrate->ht_mcs[j][i];
644         }
645
646 }       /* cmpk_Handle_Tx_Rate_History */
647
648
649 /*-----------------------------------------------------------------------------
650  * Function:    cmpk_message_handle_rx()
651  *
652  * Overview:    In the function, we will capture different RX command packet
653  *                              info. Every RX command packet element has different message
654  *                              length and meaning in content. We only support three type of RX
655  *                              command packet now. Please refer to document
656  *                              ws-06-0063-rtl8190-command-packet-specification.
657  *
658  * Input:       NONE
659  *
660  * Output:      NONE
661  *
662  * Return:      NONE
663  *
664  * Revised History:
665  *  When                Who             Remark
666  *  05/06/2008  amy             Create Version 0 porting from windows code.
667  *
668  *---------------------------------------------------------------------------*/
669 extern  u32
670 cmpk_message_handle_rx(
671         struct net_device *dev,
672         struct ieee80211_rx_stats *pstats)
673 {
674         int                     total_length;
675         u8                      cmd_length, exe_cnt = 0;
676         u8                      element_id;
677         u8                      *pcmd_buff;
678
679         /* 0. Check inpt arguments. If is is a command queue message or pointer is
680               null. */
681         if (pstats== NULL)
682         {
683                 return 0;       /* This is not a command packet. */
684         }
685
686         /* 1. Read received command packet message length from RFD. */
687         total_length = pstats->Length;
688
689         /* 2. Read virtual address from RFD. */
690         pcmd_buff = pstats->virtual_address;
691
692         /* 3. Read command packet element id and length. */
693         element_id = pcmd_buff[0];
694
695         /* 4. Check every received command packet content according to different
696               element type. Because FW may aggregate RX command packet to minimize
697               transmit time between DRV and FW.*/
698         // Add a counter to prevent the lock in the loop from being held too long
699         while (total_length > 0 && exe_cnt++ < 100)
700         {
701                 /* 2007/01/17 MH We support aggregation of different cmd in the same packet. */
702                 element_id = pcmd_buff[0];
703
704                 switch (element_id)
705                 {
706                         case RX_TX_FEEDBACK:
707                                 cmpk_handle_tx_feedback (dev, pcmd_buff);
708                                 cmd_length = CMPK_RX_TX_FB_SIZE;
709                                 break;
710
711                         case RX_INTERRUPT_STATUS:
712                                 cmpk_handle_interrupt_status(dev, pcmd_buff);
713                                 cmd_length = sizeof(cmpk_intr_sta_t);
714                                 break;
715
716                         case BOTH_QUERY_CONFIG:
717                                 cmpk_handle_query_config_rx(dev, pcmd_buff);
718                                 cmd_length = CMPK_BOTH_QUERY_CONFIG_SIZE;
719                                 break;
720
721                         case RX_TX_STATUS:
722                                 cmpk_handle_tx_status(dev, pcmd_buff);
723                                 cmd_length = CMPK_RX_TX_STS_SIZE;
724                                 break;
725
726                         case RX_TX_PER_PKT_FEEDBACK:
727                                 // You must at lease add a switch case element here,
728                                 // Otherwise, we will jump to default case.
729                                 cmd_length = CMPK_RX_TX_FB_SIZE;
730                                 break;
731
732                         case RX_TX_RATE_HISTORY:
733                                 cmpk_handle_tx_rate_history(dev, pcmd_buff);
734                                 cmd_length = CMPK_TX_RAHIS_SIZE;
735                                 break;
736
737                         default:
738
739                                 RT_TRACE(COMP_ERR, "---->cmpk_message_handle_rx():unknow CMD Element\n");
740                                 return 1;       /* This is a command packet. */
741                 }
742
743                 total_length -= cmd_length;
744                 pcmd_buff    += cmd_length;
745         }
746         return  1;      /* This is a command packet. */
747
748 }       /* CMPK_Message_Handle_Rx */