]>
Commit | Line | Data |
---|---|---|
8dba599d FS |
1 | /* |
2 | * (c) Copyright 2008, RealTEK Technologies Inc. All Rights Reserved. | |
3 | * | |
4 | * Module: r819xusb_cmdpkt.c | |
5 | * (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, command packet. | |
10 | */ | |
5f53d8ca JC |
11 | #include "r8192U.h" |
12 | #include "r819xU_cmdpkt.h" | |
8dba599d FS |
13 | |
14 | bool SendTxCommandPacket(struct net_device *dev, void *pData, u32 DataLen) | |
5f53d8ca JC |
15 | { |
16 | bool rtStatus = true; | |
17 | struct r8192_priv *priv = ieee80211_priv(dev); | |
18 | struct sk_buff *skb; | |
19 | cb_desc *tcb_desc; | |
20 | unsigned char *ptr_buf; | |
5f53d8ca | 21 | |
8dba599d | 22 | /* PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK); */ |
5f53d8ca | 23 | |
8dba599d FS |
24 | /* |
25 | * Get TCB and local buffer from common pool. | |
26 | * (It is shared by CmdQ, MgntQ, and USB coalesce DataQ) | |
27 | */ | |
5f53d8ca | 28 | skb = dev_alloc_skb(USB_HWDESC_HEADER_LEN + DataLen + 4); |
8dba599d FS |
29 | memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev)); |
30 | tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); | |
5f53d8ca JC |
31 | tcb_desc->queue_index = TXCMD_QUEUE; |
32 | tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_NORMAL; | |
33 | tcb_desc->bLastIniPkt = 0; | |
34 | skb_reserve(skb, USB_HWDESC_HEADER_LEN); | |
35 | ptr_buf = skb_put(skb, DataLen); | |
8dba599d FS |
36 | memcpy(ptr_buf, pData, DataLen); |
37 | tcb_desc->txbuf_size = (u16)DataLen; | |
38 | ||
39 | if (!priv->ieee80211->check_nic_enough_desc(dev, tcb_desc->queue_index) || | |
40 | (!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index])) || | |
41 | (priv->ieee80211->queue_stop)) { | |
42 | RT_TRACE(COMP_FIRMWARE, "NULL packet => tx full\n"); | |
5f53d8ca JC |
43 | skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb); |
44 | } else { | |
8dba599d | 45 | priv->ieee80211->softmac_hard_start_xmit(skb, dev); |
5f53d8ca JC |
46 | } |
47 | ||
48 | //PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK); | |
49 | return rtStatus; | |
50 | } | |
51 | ||
8dba599d | 52 | /* |
5f53d8ca JC |
53 | * Function: cmpk_message_handle_tx() |
54 | * | |
55 | * Overview: Driver internal module can call the API to send message to | |
8dba599d FS |
56 | * firmware side. For example, you can send a debug command packet. |
57 | * Or you can send a request for FW to modify RLX4181 LBUS HW bank. | |
58 | * Otherwise, you can change MAC/PHT/RF register by firmware at | |
59 | * run time. We do not support message more than one segment now. | |
5f53d8ca JC |
60 | * |
61 | * Input: NONE | |
62 | * | |
63 | * Output: NONE | |
64 | * | |
65 | * Return: NONE | |
8dba599d | 66 | */ |
5f53d8ca JC |
67 | extern bool cmpk_message_handle_tx( |
68 | struct net_device *dev, | |
8dba599d | 69 | u8 *codevirtualaddress, |
5f53d8ca JC |
70 | u32 packettype, |
71 | u32 buffer_len) | |
72 | { | |
8dba599d | 73 | bool rt_status = true; |
5f53d8ca | 74 | return rt_status; |
8dba599d | 75 | } |
5f53d8ca | 76 | |
8dba599d FS |
77 | /* |
78 | * Function: cmpk_counttxstatistic() | |
79 | */ | |
5f53d8ca | 80 | static void |
8dba599d | 81 | cmpk_count_txstatistic(struct net_device *dev, cmpk_txfb_t *pstx_fb) |
5f53d8ca JC |
82 | { |
83 | struct r8192_priv *priv = ieee80211_priv(dev); | |
84 | #ifdef ENABLE_PS | |
8dba599d | 85 | RT_RF_POWER_STATE rtState; |
5f53d8ca | 86 | |
8dba599d FS |
87 | pAdapter->HalFunc.GetHwRegHandler(pAdapter, |
88 | HW_VAR_RF_STATE, | |
89 | (pu1Byte)(&rtState)); | |
5f53d8ca | 90 | |
8dba599d FS |
91 | /* |
92 | * When RF is off, we should not count the packet for hw/sw synchronize | |
93 | * reason, ie. there may be a duration while sw switch is changed and hw | |
94 | * switch is being changed. | |
95 | */ | |
5f53d8ca | 96 | if (rtState == eRfOff) |
5f53d8ca | 97 | return; |
5f53d8ca JC |
98 | #endif |
99 | ||
100 | #ifdef TODO | |
8dba599d | 101 | if (pAdapter->bInHctTest) |
5f53d8ca JC |
102 | return; |
103 | #endif | |
8dba599d FS |
104 | /* |
105 | * We can not know the packet length and transmit type: | |
106 | * broadcast or uni or multicast. | |
107 | * So the relative statistics must be collected in tx feedback info | |
108 | */ | |
109 | if (pstx_fb->tok) { | |
5f53d8ca JC |
110 | priv->stats.txfeedbackok++; |
111 | priv->stats.txoktotal++; | |
112 | priv->stats.txokbytestotal += pstx_fb->pkt_length; | |
113 | priv->stats.txokinperiod++; | |
5f53d8ca | 114 | /* We can not make sure broadcast/multicast or unicast mode. */ |
8dba599d | 115 | if (pstx_fb->pkt_type == PACKET_MULTICAST) { |
5f53d8ca JC |
116 | priv->stats.txmulticast++; |
117 | priv->stats.txbytesmulticast += pstx_fb->pkt_length; | |
8dba599d | 118 | } else if (pstx_fb->pkt_type == PACKET_BROADCAST) { |
5f53d8ca JC |
119 | priv->stats.txbroadcast++; |
120 | priv->stats.txbytesbroadcast += pstx_fb->pkt_length; | |
8dba599d | 121 | } else { |
5f53d8ca JC |
122 | priv->stats.txunicast++; |
123 | priv->stats.txbytesunicast += pstx_fb->pkt_length; | |
124 | } | |
8dba599d | 125 | } else { |
5f53d8ca JC |
126 | priv->stats.txfeedbackfail++; |
127 | priv->stats.txerrtotal++; | |
128 | priv->stats.txerrbytestotal += pstx_fb->pkt_length; | |
5f53d8ca JC |
129 | /* We can not make sure broadcast/multicast or unicast mode. */ |
130 | if (pstx_fb->pkt_type == PACKET_MULTICAST) | |
5f53d8ca | 131 | priv->stats.txerrmulticast++; |
5f53d8ca | 132 | else if (pstx_fb->pkt_type == PACKET_BROADCAST) |
5f53d8ca | 133 | priv->stats.txerrbroadcast++; |
5f53d8ca | 134 | else |
5f53d8ca | 135 | priv->stats.txerrunicast++; |
5f53d8ca | 136 | } |
5f53d8ca JC |
137 | priv->stats.txretrycount += pstx_fb->retry_cnt; |
138 | priv->stats.txfeedbackretry += pstx_fb->retry_cnt; | |
8dba599d | 139 | } |
5f53d8ca | 140 | |
8dba599d | 141 | /* |
5f53d8ca JC |
142 | * Function: cmpk_handle_tx_feedback() |
143 | * | |
144 | * Overview: The function is responsible for extract the message inside TX | |
8dba599d FS |
145 | * feedbck message from firmware. It will contain dedicated info in |
146 | * ws-06-0063-rtl8190-command-packet-specification. Please | |
147 | * refer to chapter "TX Feedback Element". We have to read 20 bytes | |
148 | * in the command packet. | |
5f53d8ca JC |
149 | * |
150 | * Input: struct net_device * dev | |
8dba599d | 151 | * u8 *pmsg - Msg Ptr of the command packet. |
5f53d8ca JC |
152 | * |
153 | * Output: NONE | |
154 | * | |
155 | * Return: NONE | |
8dba599d FS |
156 | */ |
157 | static void cmpk_handle_tx_feedback(struct net_device *dev, u8 *pmsg) | |
5f53d8ca JC |
158 | { |
159 | struct r8192_priv *priv = ieee80211_priv(dev); | |
8dba599d | 160 | cmpk_txfb_t rx_tx_fb; |
5f53d8ca JC |
161 | |
162 | priv->stats.txfeedback++; | |
163 | ||
5f53d8ca | 164 | /* 1. Extract TX feedback info from RFD to temp structure buffer. */ |
8dba599d | 165 | memcpy((u8 *)&rx_tx_fb, pmsg, sizeof(cmpk_txfb_t)); |
35c1b462 | 166 | |
5f53d8ca JC |
167 | /* 2. Use tx feedback info to count TX statistics. */ |
168 | cmpk_count_txstatistic(dev, &rx_tx_fb); | |
8dba599d | 169 | } |
35c1b462 | 170 | |
8dba599d | 171 | void cmdpkt_beacontimerinterrupt_819xusb(struct net_device *dev) |
5f53d8ca JC |
172 | { |
173 | struct r8192_priv *priv = ieee80211_priv(dev); | |
174 | u16 tx_rate; | |
5f53d8ca | 175 | |
8dba599d FS |
176 | if (priv->ieee80211->current_network.mode == IEEE_A || |
177 | priv->ieee80211->current_network.mode == IEEE_N_5G || | |
178 | (priv->ieee80211->current_network.mode == IEEE_N_24G && | |
179 | (!priv->ieee80211->pHTInfo->bCurSuppCCK))) { | |
180 | tx_rate = 60; | |
181 | DMESG("send beacon frame tx rate is 6Mbpm\n"); | |
182 | } else { | |
183 | tx_rate = 10; | |
184 | DMESG("send beacon frame tx rate is 1Mbpm\n"); | |
5f53d8ca | 185 | } |
8dba599d | 186 | rtl819xusb_beacon_tx(dev, tx_rate); /* HW Beacon */ |
5f53d8ca JC |
187 | } |
188 | ||
8dba599d | 189 | /* |
5f53d8ca JC |
190 | * Function: cmpk_handle_interrupt_status() |
191 | * | |
192 | * Overview: The function is responsible for extract the message from | |
8dba599d FS |
193 | * firmware. It will contain dedicated info in |
194 | * ws-07-0063-v06-rtl819x-command-packet-specification-070315.doc. | |
195 | * Please refer to chapter "Interrupt Status Element". | |
5f53d8ca JC |
196 | * |
197 | * Input: struct net_device *dev, | |
8dba599d | 198 | * u8* pmsg - Message Pointer of the command packet. |
5f53d8ca JC |
199 | * |
200 | * Output: NONE | |
201 | * | |
202 | * Return: NONE | |
8dba599d FS |
203 | */ |
204 | static void cmpk_handle_interrupt_status(struct net_device *dev, u8 *pmsg) | |
5f53d8ca JC |
205 | { |
206 | cmpk_intr_sta_t rx_intr_status; /* */ | |
207 | struct r8192_priv *priv = ieee80211_priv(dev); | |
208 | ||
209 | DMESG("---> cmpk_Handle_Interrupt_Status()\n"); | |
210 | ||
5f53d8ca | 211 | /* 1. Extract TX feedback info from RFD to temp structure buffer. */ |
5f53d8ca | 212 | rx_intr_status.length = pmsg[1]; |
8dba599d | 213 | if (rx_intr_status.length != (sizeof(cmpk_intr_sta_t) - 2)) { |
5f53d8ca JC |
214 | DMESG("cmpk_Handle_Interrupt_Status: wrong length!\n"); |
215 | return; | |
216 | } | |
8dba599d FS |
217 | /* Statistics of beacon for ad-hoc mode. */ |
218 | if (priv->ieee80211->iw_mode == IW_MODE_ADHOC) { | |
5f53d8ca JC |
219 | //2 maybe need endian transform? |
220 | rx_intr_status.interrupt_status = *((u32 *)(pmsg + 4)); | |
221 | //rx_intr_status.InterruptStatus = N2H4BYTE(*((UINT32 *)(pMsg + 4))); | |
222 | ||
223 | DMESG("interrupt status = 0x%x\n", rx_intr_status.interrupt_status); | |
224 | ||
8dba599d | 225 | if (rx_intr_status.interrupt_status & ISR_TxBcnOk) { |
5f53d8ca JC |
226 | priv->ieee80211->bibsscoordinator = true; |
227 | priv->stats.txbeaconokint++; | |
8dba599d | 228 | } else if (rx_intr_status.interrupt_status & ISR_TxBcnErr) { |
5f53d8ca JC |
229 | priv->ieee80211->bibsscoordinator = false; |
230 | priv->stats.txbeaconerr++; | |
231 | } | |
232 | ||
233 | if (rx_intr_status.interrupt_status & ISR_BcnTimerIntr) | |
5f53d8ca | 234 | cmdpkt_beacontimerinterrupt_819xusb(dev); |
5f53d8ca | 235 | } |
8dba599d | 236 | /* Other informations in interrupt status we need? */ |
5f53d8ca | 237 | DMESG("<---- cmpk_handle_interrupt_status()\n"); |
8dba599d | 238 | } |
5f53d8ca | 239 | |
8dba599d | 240 | /* |
5f53d8ca JC |
241 | * Function: cmpk_handle_query_config_rx() |
242 | * | |
243 | * Overview: The function is responsible for extract the message from | |
244 | * firmware. It will contain dedicated info in | |
8dba599d FS |
245 | * ws-06-0063-rtl8190-command-packet-specification |
246 | * Please refer to chapter "Beacon State Element". | |
5f53d8ca JC |
247 | * |
248 | * Input: u8 * pmsg - Message Pointer of the command packet. | |
249 | * | |
250 | * Output: NONE | |
251 | * | |
252 | * Return: NONE | |
253 | * | |
8dba599d FS |
254 | */ |
255 | static void cmpk_handle_query_config_rx(struct net_device *dev, u8 *pmsg) | |
5f53d8ca | 256 | { |
8dba599d FS |
257 | cmpk_query_cfg_t rx_query_cfg; |
258 | /* | |
259 | * Extract TX feedback info from RFD to temp structure buffer. | |
260 | */ | |
261 | rx_query_cfg.cfg_action = (pmsg[4] & 0x80000000) >> 31; | |
262 | rx_query_cfg.cfg_type = (pmsg[4] & 0x60) >> 5; | |
263 | rx_query_cfg.cfg_size = (pmsg[4] & 0x18) >> 3; | |
264 | rx_query_cfg.cfg_page = (pmsg[6] & 0x0F) >> 0; | |
265 | rx_query_cfg.cfg_offset = pmsg[7]; | |
266 | rx_query_cfg.value = (pmsg[8] << 24) | (pmsg[9] << 16) | | |
267 | (pmsg[10] << 8) | (pmsg[11] << 0); | |
268 | rx_query_cfg.mask = (pmsg[12] << 24) | (pmsg[13] << 16) | | |
269 | (pmsg[14] << 8) | (pmsg[15] << 0); | |
270 | } | |
5f53d8ca | 271 | |
8dba599d | 272 | /* |
5f53d8ca JC |
273 | * Function: cmpk_count_tx_status() |
274 | * | |
8dba599d | 275 | * Overview: Count aggregated tx status from firmware of one type rx command |
5f53d8ca JC |
276 | * packet element id = RX_TX_STATUS. |
277 | * | |
278 | * Input: NONE | |
279 | * | |
280 | * Output: NONE | |
281 | * | |
282 | * Return: NONE | |
8dba599d FS |
283 | */ |
284 | static void cmpk_count_tx_status(struct net_device *dev, | |
285 | cmpk_tx_status_t *pstx_status) | |
5f53d8ca JC |
286 | { |
287 | struct r8192_priv *priv = ieee80211_priv(dev); | |
288 | ||
289 | #ifdef ENABLE_PS | |
290 | ||
291 | RT_RF_POWER_STATE rtstate; | |
292 | ||
293 | pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE, (pu1Byte)(&rtState)); | |
294 | ||
8dba599d FS |
295 | /* |
296 | * When RF is off, we should not count the packet for hw/sw synchronize | |
297 | * reason, ie. there may be a duration while sw switch is changed and hw | |
298 | * switch is being changed. | |
299 | */ | |
5f53d8ca | 300 | if (rtState == eRfOff) |
5f53d8ca | 301 | return; |
5f53d8ca JC |
302 | #endif |
303 | ||
304 | priv->stats.txfeedbackok += pstx_status->txok; | |
305 | priv->stats.txoktotal += pstx_status->txok; | |
306 | ||
307 | priv->stats.txfeedbackfail += pstx_status->txfail; | |
308 | priv->stats.txerrtotal += pstx_status->txfail; | |
309 | ||
8dba599d | 310 | priv->stats.txretrycount += pstx_status->txretry; |
5f53d8ca JC |
311 | priv->stats.txfeedbackretry += pstx_status->txretry; |
312 | ||
8dba599d FS |
313 | priv->stats.txmulticast += pstx_status->txmcok; |
314 | priv->stats.txbroadcast += pstx_status->txbcok; | |
5f53d8ca JC |
315 | priv->stats.txunicast += pstx_status->txucok; |
316 | ||
317 | priv->stats.txerrmulticast += pstx_status->txmcfail; | |
318 | priv->stats.txerrbroadcast += pstx_status->txbcfail; | |
319 | priv->stats.txerrunicast += pstx_status->txucfail; | |
320 | ||
321 | priv->stats.txbytesmulticast += pstx_status->txmclength; | |
322 | priv->stats.txbytesbroadcast += pstx_status->txbclength; | |
8dba599d | 323 | priv->stats.txbytesunicast += pstx_status->txuclength; |
5f53d8ca | 324 | |
8dba599d FS |
325 | priv->stats.last_packet_rate = pstx_status->rate; |
326 | } | |
5f53d8ca | 327 | |
8dba599d | 328 | /* |
5f53d8ca JC |
329 | * Function: cmpk_handle_tx_status() |
330 | * | |
331 | * Overview: Firmware add a new tx feedback status to reduce rx command | |
332 | * packet buffer operation load. | |
333 | * | |
334 | * Input: NONE | |
335 | * | |
336 | * Output: NONE | |
337 | * | |
338 | * Return: NONE | |
8dba599d | 339 | */ |
5f53d8ca | 340 | static void |
8dba599d | 341 | cmpk_handle_tx_status(struct net_device *dev, u8 *pmsg) |
5f53d8ca | 342 | { |
8dba599d | 343 | cmpk_tx_status_t rx_tx_sts; |
5f53d8ca | 344 | |
8dba599d | 345 | memcpy((void *)&rx_tx_sts, (void *)pmsg, sizeof(cmpk_tx_status_t)); |
5f53d8ca JC |
346 | /* 2. Use tx feedback info to count TX statistics. */ |
347 | cmpk_count_tx_status(dev, &rx_tx_sts); | |
8dba599d | 348 | } |
5f53d8ca | 349 | |
8dba599d | 350 | /* |
5f53d8ca JC |
351 | * Function: cmpk_handle_tx_rate_history() |
352 | * | |
353 | * Overview: Firmware add a new tx rate history | |
354 | * | |
355 | * Input: NONE | |
356 | * | |
357 | * Output: NONE | |
358 | * | |
359 | * Return: NONE | |
8dba599d FS |
360 | */ |
361 | static void cmpk_handle_tx_rate_history(struct net_device *dev, u8 *pmsg) | |
5f53d8ca JC |
362 | { |
363 | cmpk_tx_rahis_t *ptxrate; | |
8dba599d FS |
364 | u8 i, j; |
365 | u16 length = sizeof(cmpk_tx_rahis_t); | |
366 | u32 *ptemp; | |
5f53d8ca JC |
367 | struct r8192_priv *priv = ieee80211_priv(dev); |
368 | ||
5f53d8ca | 369 | #ifdef ENABLE_PS |
8dba599d FS |
370 | pAdapter->HalFunc.GetHwRegHandler(pAdapter, |
371 | HW_VAR_RF_STATE, | |
372 | (pu1Byte)(&rtState)); | |
373 | /* | |
374 | * When RF is off, we should not count the packet for hw/sw synchronize | |
375 | * reason, ie. there may be a duration while sw switch is changed and hw | |
376 | * switch is being changed. | |
377 | */ | |
5f53d8ca | 378 | if (rtState == eRfOff) |
5f53d8ca | 379 | return; |
5f53d8ca | 380 | #endif |
5f53d8ca JC |
381 | ptemp = (u32 *)pmsg; |
382 | ||
8dba599d FS |
383 | /* |
384 | * Do endian transfer to word alignment(16 bits) for windows system. | |
385 | * You must do different endian transfer for linux and MAC OS | |
386 | */ | |
387 | for (i = 0; i < (length/4); i++) { | |
388 | u16 temp1, temp2; | |
389 | temp1 = ptemp[i] & 0x0000FFFF; | |
390 | temp2 = ptemp[i] >> 16; | |
391 | ptemp[i] = (temp1 << 16) | temp2; | |
5f53d8ca JC |
392 | } |
393 | ||
394 | ptxrate = (cmpk_tx_rahis_t *)pmsg; | |
395 | ||
8dba599d | 396 | if (ptxrate == NULL) |
5f53d8ca | 397 | return; |
5f53d8ca | 398 | |
8dba599d FS |
399 | for (i = 0; i < 16; i++) { |
400 | /* Collect CCK rate packet num */ | |
5f53d8ca JC |
401 | if (i < 4) |
402 | priv->stats.txrate.cck[i] += ptxrate->cck[i]; | |
8dba599d FS |
403 | /* Collect OFDM rate packet num */ |
404 | if (i < 8) | |
5f53d8ca | 405 | priv->stats.txrate.ofdm[i] += ptxrate->ofdm[i]; |
5f53d8ca JC |
406 | for (j = 0; j < 4; j++) |
407 | priv->stats.txrate.ht_mcs[j][i] += ptxrate->ht_mcs[j][i]; | |
408 | } | |
409 | ||
8dba599d | 410 | } |
5f53d8ca | 411 | |
8dba599d | 412 | /* |
5f53d8ca JC |
413 | * Function: cmpk_message_handle_rx() |
414 | * | |
415 | * Overview: In the function, we will capture different RX command packet | |
8dba599d FS |
416 | * info. Every RX command packet element has different message |
417 | * length and meaning in content. We only support three type of RX | |
418 | * command packet now. Please refer to document | |
419 | * ws-06-0063-rtl8190-command-packet-specification. | |
5f53d8ca JC |
420 | * |
421 | * Input: NONE | |
422 | * | |
423 | * Output: NONE | |
424 | * | |
425 | * Return: NONE | |
8dba599d | 426 | */ |
5f53d8ca JC |
427 | extern u32 |
428 | cmpk_message_handle_rx( | |
429 | struct net_device *dev, | |
430 | struct ieee80211_rx_stats *pstats) | |
431 | { | |
5f53d8ca JC |
432 | struct r8192_priv *priv = ieee80211_priv(dev); |
433 | int total_length; | |
434 | u8 cmd_length, exe_cnt = 0; | |
435 | u8 element_id; | |
436 | u8 *pcmd_buff; | |
437 | ||
8dba599d FS |
438 | /* |
439 | * 0. Check input arguments. | |
440 | * If is is a command queue message or pointer is null | |
441 | */ | |
442 | if ((pstats == NULL)) | |
5f53d8ca | 443 | return 0; /* This is not a command packet. */ |
5f53d8ca JC |
444 | |
445 | /* 1. Read received command packet message length from RFD. */ | |
446 | total_length = pstats->Length; | |
447 | ||
448 | /* 2. Read virtual address from RFD. */ | |
449 | pcmd_buff = pstats->virtual_address; | |
450 | ||
451 | /* 3. Read command pakcet element id and length. */ | |
452 | element_id = pcmd_buff[0]; | |
5f53d8ca | 453 | |
8dba599d FS |
454 | /* |
455 | * 4. Check every received command packet conent according to different | |
456 | * element type. Because FW may aggregate RX command packet to minimize | |
457 | * transmit time between DRV and FW. | |
458 | */ | |
5f53d8ca | 459 | |
8dba599d FS |
460 | /* Add a counter to prevent to locked in the loop too long */ |
461 | while (total_length > 0 || exe_cnt++ > 100) { | |
462 | /* We support aggregation of different cmd in the same packet */ | |
463 | element_id = pcmd_buff[0]; | |
464 | switch (element_id) { | |
465 | case RX_TX_FEEDBACK: | |
466 | cmpk_handle_tx_feedback(dev, pcmd_buff); | |
467 | cmd_length = CMPK_RX_TX_FB_SIZE; | |
468 | break; | |
469 | case RX_INTERRUPT_STATUS: | |
470 | cmpk_handle_interrupt_status(dev, pcmd_buff); | |
471 | cmd_length = sizeof(cmpk_intr_sta_t); | |
472 | break; | |
473 | case BOTH_QUERY_CONFIG: | |
474 | cmpk_handle_query_config_rx(dev, pcmd_buff); | |
475 | cmd_length = CMPK_BOTH_QUERY_CONFIG_SIZE; | |
476 | break; | |
477 | case RX_TX_STATUS: | |
478 | cmpk_handle_tx_status(dev, pcmd_buff); | |
479 | cmd_length = CMPK_RX_TX_STS_SIZE; | |
480 | break; | |
481 | case RX_TX_PER_PKT_FEEDBACK: | |
482 | cmd_length = CMPK_RX_TX_FB_SIZE; | |
483 | break; | |
484 | case RX_TX_RATE_HISTORY: | |
485 | cmpk_handle_tx_rate_history(dev, pcmd_buff); | |
486 | cmd_length = CMPK_TX_RAHIS_SIZE; | |
487 | break; | |
488 | default: | |
489 | RT_TRACE(COMP_ERR, "(%s): unknown CMD Element\n", | |
490 | __func__); | |
491 | return 1; /* This is a command packet. */ | |
492 | } | |
5f53d8ca | 493 | priv->stats.rxcmdpkt[element_id]++; |
5f53d8ca JC |
494 | total_length -= cmd_length; |
495 | pcmd_buff += cmd_length; | |
8dba599d FS |
496 | } |
497 | return 1; /* This is a command packet. */ | |
498 | } |