Merge branch 'trivial' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild
[firefly-linux-kernel-4.4.55.git] / drivers / staging / rtl8192e / r8192E_cmdpkt.c
1 /******************************************************************************
2  * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
3  *
4  * This program is distributed in the hope that it will be useful, but WITHOUT
5  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
6  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
7  * more details.
8  *
9  * You should have received a copy of the GNU General Public License along with
10  * this program; if not, write to the Free Software Foundation, Inc.,
11  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
12  *
13  * The full GNU General Public License is included in this distribution in the
14  * file called LICENSE.
15  *
16  * Contact Information:
17  * wlanfae <wlanfae@realtek.com>
18 ******************************************************************************/
19
20 #include "rtl_core.h"
21 #include "r8192E_hw.h"
22 #include "r8192E_cmdpkt.h"
23 /*---------------------------Define Local Constant---------------------------*/
24 /* Debug constant*/
25 #define         CMPK_DEBOUNCE_CNT                       1
26 #define         CMPK_PRINT(Address)\
27 {\
28         unsigned char   i;\
29         u32     temp[10];\
30         \
31         memcpy(temp, Address, 40);\
32         for (i = 0; i < 40; i += 4)\
33                 printk(KERN_INFO "\r\n %08x", temp[i]);\
34 }
35
36 /*---------------------------Define functions---------------------------------*/
37 bool cmpk_message_handle_tx(
38         struct net_device *dev,
39         u8      *code_virtual_address,
40         u32     packettype,
41         u32     buffer_len)
42 {
43
44         bool                            rt_status = true;
45         struct r8192_priv *priv = rtllib_priv(dev);
46         u16                             frag_threshold;
47         u16                             frag_length = 0, frag_offset = 0;
48         struct rt_firmware *pfirmware = priv->pFirmware;
49         struct sk_buff          *skb;
50         unsigned char           *seg_ptr;
51         struct cb_desc *tcb_desc;
52         u8                              bLastIniPkt;
53
54         struct tx_fwinfo_8190pci *pTxFwInfo = NULL;
55
56         RT_TRACE(COMP_CMDPKT, "%s(),buffer_len is %d\n", __func__, buffer_len);
57         firmware_init_param(dev);
58         frag_threshold = pfirmware->cmdpacket_frag_thresold;
59
60         do {
61                 if ((buffer_len - frag_offset) > frag_threshold) {
62                         frag_length = frag_threshold ;
63                         bLastIniPkt = 0;
64
65                 } else {
66                         frag_length = (u16)(buffer_len - frag_offset);
67                         bLastIniPkt = 1;
68                 }
69
70                 skb  = dev_alloc_skb(frag_length +
71                                      priv->rtllib->tx_headroom + 4);
72
73                 if (skb == NULL) {
74                         rt_status = false;
75                         goto Failed;
76                 }
77
78                 memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
79                 tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
80                 tcb_desc->queue_index = TXCMD_QUEUE;
81                 tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_NORMAL;
82                 tcb_desc->bLastIniPkt = bLastIniPkt;
83                 tcb_desc->pkt_size = frag_length;
84
85                 seg_ptr = skb_put(skb, priv->rtllib->tx_headroom);
86                 pTxFwInfo = (struct tx_fwinfo_8190pci *)seg_ptr;
87                 memset(pTxFwInfo, 0, sizeof(struct tx_fwinfo_8190pci));
88                 memset(pTxFwInfo, 0x12, 8);
89
90                 seg_ptr = skb_put(skb, frag_length);
91                 memcpy(seg_ptr, code_virtual_address, (u32)frag_length);
92
93                 priv->rtllib->softmac_hard_start_xmit(skb, dev);
94
95                 code_virtual_address += frag_length;
96                 frag_offset += frag_length;
97
98         } while (frag_offset < buffer_len);
99
100         write_nic_byte(dev, TPPoll, TPPoll_CQ);
101 Failed:
102         return rt_status;
103 }       /* CMPK_Message_Handle_Tx */
104
105 static  void
106 cmpk_count_txstatistic(
107         struct net_device *dev,
108         struct cmpk_txfb *pstx_fb)
109 {
110         struct r8192_priv *priv = rtllib_priv(dev);
111 #ifdef ENABLE_PS
112         enum rt_rf_power_state rtState;
113
114         pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE,
115                                           (pu1Byte)(&rtState));
116
117         if (rtState == eRfOff)
118                 return;
119 #endif
120
121         if (pstx_fb->tok) {
122                 priv->stats.txfeedbackok++;
123                 priv->stats.txoktotal++;
124                 priv->stats.txokbytestotal += pstx_fb->pkt_length;
125                 priv->stats.txokinperiod++;
126
127                 if (pstx_fb->pkt_type == PACKET_MULTICAST) {
128                         priv->stats.txmulticast++;
129                         priv->stats.txbytesmulticast += pstx_fb->pkt_length;
130                 } else if (pstx_fb->pkt_type == PACKET_BROADCAST) {
131                         priv->stats.txbroadcast++;
132                         priv->stats.txbytesbroadcast += pstx_fb->pkt_length;
133                 } else {
134                         priv->stats.txunicast++;
135                         priv->stats.txbytesunicast += pstx_fb->pkt_length;
136                 }
137         } else {
138                 priv->stats.txfeedbackfail++;
139                 priv->stats.txerrtotal++;
140                 priv->stats.txerrbytestotal += pstx_fb->pkt_length;
141
142                 if (pstx_fb->pkt_type == PACKET_MULTICAST)
143                         priv->stats.txerrmulticast++;
144                 else if (pstx_fb->pkt_type == PACKET_BROADCAST)
145                         priv->stats.txerrbroadcast++;
146                 else
147                         priv->stats.txerrunicast++;
148         }
149
150         priv->stats.txretrycount += pstx_fb->retry_cnt;
151         priv->stats.txfeedbackretry += pstx_fb->retry_cnt;
152
153 }       /* cmpk_CountTxStatistic */
154
155
156
157 static void cmpk_handle_tx_feedback(struct net_device *dev, u8 *pmsg)
158 {
159         struct r8192_priv *priv = rtllib_priv(dev);
160         struct cmpk_txfb rx_tx_fb;      /* */
161
162         priv->stats.txfeedback++;
163
164
165         memcpy((u8 *)&rx_tx_fb, pmsg, sizeof(struct cmpk_txfb));
166         cmpk_count_txstatistic(dev, &rx_tx_fb);
167
168 }       /* cmpk_Handle_Tx_Feedback */
169
170 static void cmdpkt_beacontimerinterrupt_819xusb(struct net_device *dev)
171 {
172         struct r8192_priv *priv = rtllib_priv(dev);
173         u16 tx_rate;
174
175         if ((priv->rtllib->current_network.mode == IEEE_A)  ||
176             (priv->rtllib->current_network.mode == IEEE_N_5G) ||
177             ((priv->rtllib->current_network.mode == IEEE_N_24G)  &&
178             (!priv->rtllib->pHTInfo->bCurSuppCCK))) {
179                 tx_rate = 60;
180                 DMESG("send beacon frame  tx rate is 6Mbpm\n");
181         } else {
182                 tx_rate = 10;
183                 DMESG("send beacon frame  tx rate is 1Mbpm\n");
184         }
185
186 }
187
188 static void cmpk_handle_interrupt_status(struct net_device *dev, u8 *pmsg)
189 {
190         struct cmpk_intr_sta rx_intr_status;    /* */
191         struct r8192_priv *priv = rtllib_priv(dev);
192
193         DMESG("---> cmpk_Handle_Interrupt_Status()\n");
194
195
196         rx_intr_status.length = pmsg[1];
197         if (rx_intr_status.length != (sizeof(struct cmpk_intr_sta) - 2)) {
198                 DMESG("cmpk_Handle_Interrupt_Status: wrong length!\n");
199                 return;
200         }
201
202
203         if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
204                 rx_intr_status.interrupt_status = *((u32 *)(pmsg + 4));
205
206                 DMESG("interrupt status = 0x%x\n",
207                       rx_intr_status.interrupt_status);
208
209                 if (rx_intr_status.interrupt_status & ISR_TxBcnOk) {
210                         priv->rtllib->bibsscoordinator = true;
211                         priv->stats.txbeaconokint++;
212                 } else if (rx_intr_status.interrupt_status & ISR_TxBcnErr) {
213                         priv->rtllib->bibsscoordinator = false;
214                         priv->stats.txbeaconerr++;
215                 }
216
217                 if (rx_intr_status.interrupt_status & ISR_BcnTimerIntr)
218                         cmdpkt_beacontimerinterrupt_819xusb(dev);
219         }
220
221         DMESG("<---- cmpk_handle_interrupt_status()\n");
222
223 }       /* cmpk_handle_interrupt_status */
224
225
226 static  void cmpk_handle_query_config_rx(struct net_device *dev, u8 *pmsg)
227 {
228         cmpk_query_cfg_t        rx_query_cfg;   /* */
229
230
231         rx_query_cfg.cfg_action = (pmsg[4] & 0x80000000)>>31;
232         rx_query_cfg.cfg_type = (pmsg[4] & 0x60) >> 5;
233         rx_query_cfg.cfg_size = (pmsg[4] & 0x18) >> 3;
234         rx_query_cfg.cfg_page = (pmsg[6] & 0x0F) >> 0;
235         rx_query_cfg.cfg_offset  = pmsg[7];
236         rx_query_cfg.value = (pmsg[8] << 24) | (pmsg[9] << 16) |
237                              (pmsg[10] << 8) | (pmsg[11] << 0);
238         rx_query_cfg.mask = (pmsg[12] << 24) | (pmsg[13] << 16) |
239                             (pmsg[14] << 8) | (pmsg[15] << 0);
240
241 }       /* cmpk_Handle_Query_Config_Rx */
242
243
244 static void cmpk_count_tx_status(struct net_device *dev,
245                                  struct cmpk_tx_status *pstx_status)
246 {
247         struct r8192_priv *priv = rtllib_priv(dev);
248
249 #ifdef ENABLE_PS
250
251         enum rt_rf_power_state rtstate;
252
253         pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE,
254                                           (pu1Byte)(&rtState));
255
256         if (rtState == eRfOff)
257                 return;
258 #endif
259
260         priv->stats.txfeedbackok        += pstx_status->txok;
261         priv->stats.txoktotal           += pstx_status->txok;
262
263         priv->stats.txfeedbackfail      += pstx_status->txfail;
264         priv->stats.txerrtotal          += pstx_status->txfail;
265
266         priv->stats.txretrycount                += pstx_status->txretry;
267         priv->stats.txfeedbackretry     += pstx_status->txretry;
268
269
270         priv->stats.txmulticast += pstx_status->txmcok;
271         priv->stats.txbroadcast += pstx_status->txbcok;
272         priv->stats.txunicast           += pstx_status->txucok;
273
274         priv->stats.txerrmulticast      += pstx_status->txmcfail;
275         priv->stats.txerrbroadcast      += pstx_status->txbcfail;
276         priv->stats.txerrunicast        += pstx_status->txucfail;
277
278         priv->stats.txbytesmulticast    += pstx_status->txmclength;
279         priv->stats.txbytesbroadcast    += pstx_status->txbclength;
280         priv->stats.txbytesunicast              += pstx_status->txuclength;
281
282         priv->stats.last_packet_rate            = pstx_status->rate;
283 }       /* cmpk_CountTxStatus */
284
285
286
287 static  void cmpk_handle_tx_status(struct net_device *dev, u8 *pmsg)
288 {
289         struct cmpk_tx_status rx_tx_sts;        /* */
290
291         memcpy((void *)&rx_tx_sts, (void *)pmsg, sizeof(struct cmpk_tx_status));
292         cmpk_count_tx_status(dev, &rx_tx_sts);
293 }
294
295 static  void cmpk_handle_tx_rate_history(struct net_device *dev, u8 *pmsg)
296 {
297         struct cmpk_tx_rahis *ptxrate;
298         u8 i, j;
299         u16                             length = sizeof(struct cmpk_tx_rahis);
300         u32 *ptemp;
301         struct r8192_priv *priv = rtllib_priv(dev);
302
303
304 #ifdef ENABLE_PS
305         pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE,
306                                          (pu1Byte)(&rtState));
307
308         if (rtState == eRfOff)
309                 return;
310 #endif
311
312         ptemp = (u32 *)pmsg;
313
314         for (i = 0; i < (length / 4); i++) {
315                 u16      temp1, temp2;
316
317                 temp1 = ptemp[i] & 0x0000FFFF;
318                 temp2 = ptemp[i] >> 16;
319                 ptemp[i] = (temp1 << 16) | temp2;
320         }
321
322         ptxrate = (struct cmpk_tx_rahis *)pmsg;
323
324         if (ptxrate == NULL)
325                 return;
326
327         for (i = 0; i < 16; i++) {
328                 if (i < 4)
329                         priv->stats.txrate.cck[i] += ptxrate->cck[i];
330
331                 if (i < 8)
332                         priv->stats.txrate.ofdm[i] += ptxrate->ofdm[i];
333
334                 for (j = 0; j < 4; j++)
335                         priv->stats.txrate.ht_mcs[j][i] +=
336                                                          ptxrate->ht_mcs[j][i];
337         }
338
339 }
340
341
342 u32 cmpk_message_handle_rx(struct net_device *dev,
343                            struct rtllib_rx_stats *pstats)
344 {
345         struct r8192_priv *priv = rtllib_priv(dev);
346         int                     total_length;
347         u8                      cmd_length, exe_cnt = 0;
348         u8                      element_id;
349         u8                      *pcmd_buff;
350
351         RT_TRACE(COMP_CMDPKT, "---->cmpk_message_handle_rx()\n");
352
353         if (pstats == NULL) {
354                 /* Print error message. */
355                 /*RT_TRACE(COMP_SEND, DebugLevel,
356                                 ("\n\r[CMPK]-->Err queue id or pointer"));*/
357                 return 0;
358         }
359
360         total_length = pstats->Length;
361
362         pcmd_buff = pstats->virtual_address;
363
364         element_id = pcmd_buff[0];
365
366         while (total_length > 0 || exe_cnt++ > 100) {
367                 element_id = pcmd_buff[0];
368
369                 switch (element_id) {
370                 case RX_TX_FEEDBACK:
371                         RT_TRACE(COMP_CMDPKT, "---->cmpk_message_handle_rx():"
372                                  "RX_TX_FEEDBACK\n");
373                         cmpk_handle_tx_feedback(dev, pcmd_buff);
374                         cmd_length = CMPK_RX_TX_FB_SIZE;
375                         break;
376                 case RX_INTERRUPT_STATUS:
377                         RT_TRACE(COMP_CMDPKT, "---->cmpk_message_handle_rx():"
378                                  "RX_INTERRUPT_STATUS\n");
379                         cmpk_handle_interrupt_status(dev, pcmd_buff);
380                         cmd_length = sizeof(struct cmpk_intr_sta);
381                         break;
382                 case BOTH_QUERY_CONFIG:
383                         RT_TRACE(COMP_CMDPKT, "---->cmpk_message_handle_rx():"
384                                  "BOTH_QUERY_CONFIG\n");
385                         cmpk_handle_query_config_rx(dev, pcmd_buff);
386                         cmd_length = CMPK_BOTH_QUERY_CONFIG_SIZE;
387                         break;
388                 case RX_TX_STATUS:
389                         RT_TRACE(COMP_CMDPKT, "---->cmpk_message_handle_rx():"
390                                  "RX_TX_STATUS\n");
391                         cmpk_handle_tx_status(dev, pcmd_buff);
392                         cmd_length = CMPK_RX_TX_STS_SIZE;
393                         break;
394                 case RX_TX_PER_PKT_FEEDBACK:
395                         RT_TRACE(COMP_CMDPKT, "---->cmpk_message_handle_rx():"
396                                  "RX_TX_PER_PKT_FEEDBACK\n");
397                         cmd_length = CMPK_RX_TX_FB_SIZE;
398                         break;
399                 case RX_TX_RATE_HISTORY:
400                         RT_TRACE(COMP_CMDPKT, "---->cmpk_message_handle_rx():"
401                                  "RX_TX_HISTORY\n");
402                         cmpk_handle_tx_rate_history(dev, pcmd_buff);
403                         cmd_length = CMPK_TX_RAHIS_SIZE;
404                         break;
405                 default:
406
407                         RT_TRACE(COMP_CMDPKT, "---->cmpk_message_handle_rx():"
408                                  "unknow CMD Element\n");
409                         return 1;
410                 }
411
412                 priv->stats.rxcmdpkt[element_id]++;
413
414                 total_length -= cmd_length;
415                 pcmd_buff    += cmd_length;
416         }
417         return  1;
418 }