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