03ca63942920122743d628bca91fe8c24ff0787b
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / esp8089 / esp_driver / esp_ctrl.c
1 /*
2  * Copyright (c) 2009 - 2012 Espressif System.
3  */
4
5 #include <net/mac80211.h>
6 #include <net/cfg80211.h>
7 #include <linux/skbuff.h>
8 #include <linux/bitops.h>
9 #include <linux/firmware.h>
10
11 #include "esp_pub.h"
12 #include "esp_sip.h"
13 #include "esp_ctrl.h"
14 #include "esp_sif.h"
15 #include "esp_debug.h"
16 #include "slc_host_register.h"
17 #include "esp_wmac.h"
18 #include "esp_utils.h"
19 #include "esp_wl.h"
20 #ifdef ANDROID
21 #include "esp_android.h"
22 #include "esp_path.h"
23 #endif /* ANDROID */
24 #ifdef TEST_MODE
25 #include "testmode.h"
26 #endif /* TEST_MODE */
27 #include "esp_version.h"
28
29 extern struct completion *gl_bootup_cplx; 
30
31 #ifdef ESP_RX_COPYBACK_TEST
32 static void sip_show_copyback_buf(void)
33 {
34         //show_buf(copyback_buf, copyback_offset);
35 }
36 #endif /* ESP_RX_COPYBACK_TEST */
37
38 static void esp_tx_ba_session_op(struct esp_sip *sip, struct esp_node *node, trc_ampdu_state_t state, u8 tid )
39 {
40         struct esp_tx_tid *txtid;
41
42         txtid = &node->tid[tid];
43         if (state == TRC_TX_AMPDU_STOPPED) {
44                 if (txtid->state == ESP_TID_STATE_OPERATIONAL) {
45                         esp_dbg(ESP_DBG_TXAMPDU, "%s tid %d TXAMPDU GOT STOP EVT\n", __func__, tid);
46
47                         spin_lock_bh(&sip->epub->tx_ampdu_lock);
48                         txtid->state = ESP_TID_STATE_WAIT_STOP;
49                         spin_unlock_bh(&sip->epub->tx_ampdu_lock);
50 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28))
51                         ieee80211_stop_tx_ba_session(sip->epub->hw, node->addr, (u16)tid, WLAN_BACK_INITIATOR);
52 #elif (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32))
53                         ieee80211_stop_tx_ba_session(sip->epub->hw, node->sta->addr, (u16)tid, WLAN_BACK_INITIATOR);
54 #elif (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35))
55                         ieee80211_stop_tx_ba_session(node->sta, (u16)tid, WLAN_BACK_INITIATOR);
56 #else
57                         ieee80211_stop_tx_ba_session(node->sta, (u16)tid);
58 #endif /* KERNEL_VERSION 2.6.39 */
59                 } else {
60                         esp_dbg(ESP_DBG_TXAMPDU, "%s tid %d TXAMPDU GOT STOP EVT IN WRONG STATE %d\n", __func__, tid, txtid->state);
61                 }
62         } else if (state == TRC_TX_AMPDU_OPERATIONAL) {
63                 if (txtid->state == ESP_TID_STATE_STOP) {
64                         esp_dbg(ESP_DBG_TXAMPDU, "%s tid %d TXAMPDU GOT OPERATIONAL\n", __func__, tid);
65
66                         spin_lock_bh(&sip->epub->tx_ampdu_lock);
67                         txtid->state = ESP_TID_STATE_TRIGGER;
68                         spin_unlock_bh(&sip->epub->tx_ampdu_lock);
69 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28))
70                         ieee80211_start_tx_ba_session(sip->epub->hw, node->addr, tid);
71 #elif (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32))
72                         ieee80211_start_tx_ba_session(sip->epub->hw, node->sta->addr, tid);
73 #elif (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 37))
74                         ieee80211_start_tx_ba_session(node->sta, (u16)tid);
75 #else
76                         ieee80211_start_tx_ba_session(node->sta, (u16)tid, 0);
77 #endif /* KERNEL_VERSION 2.6.39 */
78
79                 } else if(txtid->state == ESP_TID_STATE_OPERATIONAL) {
80 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28))
81                         sip_send_ampdu_action(sip->epub, SIP_AMPDU_TX_OPERATIONAL, node->addr, tid, node->ifidx, 0);
82 #else
83                         sip_send_ampdu_action(sip->epub, SIP_AMPDU_TX_OPERATIONAL, node->sta->addr, tid, node->ifidx, 0);
84 #endif
85                 } else {
86                         esp_dbg(ESP_DBG_TXAMPDU, "%s tid %d TXAMPDU GOT OPERATIONAL EVT IN WRONG STATE %d\n", __func__, tid, txtid->state);
87                 }
88         }
89 }
90
91 int sip_parse_events(struct esp_sip *sip, u8 *buf)
92 {
93         struct sip_hdr *hdr = (struct sip_hdr *)buf;
94
95         switch (hdr->c_evtid) {
96         case SIP_EVT_TARGET_ON: {
97                 /* use rx work queue to send... */
98                 if (atomic_read(&sip->state) == SIP_PREPARE_BOOT || atomic_read(&sip->state) == SIP_BOOT) {
99                         atomic_set(&sip->state, SIP_SEND_INIT);
100                         queue_work(sip->epub->esp_wkq, &sip->rx_process_work);
101                 } else {
102                         esp_dbg(ESP_DBG_ERROR, "%s boot during wrong state %d\n", __func__, atomic_read(&sip->state));
103                 }
104                 break;
105         }
106
107         case SIP_EVT_BOOTUP: {
108                 struct sip_evt_bootup2 *bootup_evt = (struct sip_evt_bootup2 *)(buf + SIP_CTRL_HDR_LEN);
109                 if (sip->rawbuf)
110                         kfree(sip->rawbuf);
111                 
112                 sip_post_init(sip, bootup_evt);
113                 
114                 if (gl_bootup_cplx)     
115                         complete(gl_bootup_cplx);
116                 
117                 break;
118         }
119         case SIP_EVT_RESETTING:{
120         sip->epub->wait_reset = 1;                       
121         if (gl_bootup_cplx)     
122                         complete(gl_bootup_cplx);
123                 break;
124         }
125         case SIP_EVT_SLEEP:{
126                 //atomic_set(&sip->epub->ps.state, ESP_PM_ON);
127                 break;
128         }
129         case SIP_EVT_TXIDLE:{
130                 //struct sip_evt_txidle *txidle = (struct sip_evt_txidle *)(buf + SIP_CTRL_HDR_LEN);
131                 //sip_txdone_clear(sip, txidle->last_seq);
132                 break;
133         }
134 #ifndef FAST_TX_STATUS
135         case SIP_EVT_TX_STATUS: {
136                 struct sip_evt_tx_report *report = (struct sip_evt_tx_report *)(buf + SIP_CTRL_HDR_LEN);
137                 sip_txdoneq_process(sip, report);
138
139                 break;
140         }
141 #endif /* FAST_TX_STATUS */
142
143         case SIP_EVT_SCAN_RESULT: {
144                 struct sip_evt_scan_report *report = (struct sip_evt_scan_report *)(buf + SIP_CTRL_HDR_LEN);
145                 if (atomic_read(&sip->epub->wl.off)) {
146                         esp_dbg(ESP_DBG_ERROR, "%s scan result while wlan off\n", __func__);
147                         return 0;
148                 }
149                 sip_scandone_process(sip, report);
150
151                 break;
152         }
153
154                 case SIP_EVT_ROC: {
155                 struct sip_evt_roc* report = (struct sip_evt_roc *)(buf + SIP_CTRL_HDR_LEN);
156                 esp_rocdone_process(sip->epub->hw, report);
157                 break;
158         }
159
160
161 #ifdef ESP_RX_COPYBACK_TEST
162
163         case SIP_EVT_COPYBACK: {
164                 u32 len = hdr->len - SIP_CTRL_HDR_LEN;
165
166                 esp_dbg(ESP_DBG_TRACE, "%s copyback len %d   seq %u\n", __func__, len, hdr->seq);
167
168                 memcpy(copyback_buf + copyback_offset, pkt->buf + SIP_CTRL_HDR_LEN, len);
169                 copyback_offset += len;
170
171                 //show_buf(pkt->buf, 256);
172
173                 //how about totlen % 256 == 0??
174                 if (hdr->hdr.len < 256) {
175                         //sip_show_copyback_buf();
176                         kfree(copyback_buf);
177                 }
178         }
179         break;
180 #endif /* ESP_RX_COPYBACK_TEST */
181         case SIP_EVT_CREDIT_RPT:
182                 break;
183
184 #ifdef TEST_MODE
185         case SIP_EVT_WAKEUP: {
186                 u8 check_str[12];
187                 struct sip_evt_wakeup* wakeup_evt=  (struct sip_evt_wakeup *)(buf + SIP_CTRL_HDR_LEN);
188                 sprintf((char *)&check_str, "%d", wakeup_evt->check_data);
189                 esp_test_cmd_event(TEST_CMD_WAKEUP, (char *)&check_str);
190                 break;
191         }
192
193         case SIP_EVT_DEBUG: {
194                 u8 check_str[100];
195                 int i;
196                 char * ptr_str = (char *)& check_str;
197                 struct sip_evt_debug* debug_evt =  (struct sip_evt_debug *)(buf + SIP_CTRL_HDR_LEN);
198                 for(i = 0; i < debug_evt->len; i++)
199                         ptr_str += sprintf(ptr_str, "0x%x%s", debug_evt->results[i], i == debug_evt->len -1 ? "":" " );
200                 esp_test_cmd_event(TEST_CMD_DEBUG, (char *)&check_str);
201                 break;
202         }
203
204         case SIP_EVT_LOOPBACK: {
205                 u8 check_str[12];
206                 struct sip_evt_loopback *loopback_evt = (struct sip_evt_loopback *)(buf + SIP_CTRL_HDR_LEN);
207                 esp_dbg(ESP_DBG_LOG, "%s loopback len %d seq %u\n", __func__,hdr->len, hdr->seq);
208
209                 if(loopback_evt->pack_id!=get_loopback_id()) {
210                         sprintf((char *)&check_str, "seq id error %d, expect %d", loopback_evt->pack_id, get_loopback_id());
211                         esp_test_cmd_event(TEST_CMD_LOOPBACK, (char *)&check_str);
212                 }
213
214                 if((loopback_evt->pack_id+1) <get_loopback_num()) {
215                         inc_loopback_id();
216                         sip_send_loopback_mblk(sip, loopback_evt->txlen, loopback_evt->rxlen, get_loopback_id());
217                 } else {
218                         sprintf((char *)&check_str, "test over!");
219                         esp_test_cmd_event(TEST_CMD_LOOPBACK, (char *)&check_str);
220                 }
221                 break;
222         }
223 #endif  /*TEST_MODE*/
224
225         case SIP_EVT_SNPRINTF_TO_HOST: {
226                 u8 *p = (buf + sizeof(struct sip_hdr) + sizeof(u16));
227                 u16 *len = (u16 *)(buf + sizeof(struct sip_hdr));
228                 char test_res_str[560];
229                 sprintf(test_res_str, "esp_host:%llx\nesp_target: %.*s", DRIVER_VER, *len, p);
230                 
231                 esp_dbg(ESP_SHOW, "%s\n", test_res_str);
232 #ifdef ANDROID
233                 if(*len && sip->epub->sdio_state == ESP_SDIO_STATE_FIRST_INIT){
234                         char filename[256];
235                         if (mod_eagle_path_get() == NULL)
236                                 sprintf(filename, "%s/%s", FWPATH, "test_results");
237                         else
238                                 sprintf(filename, "%s/%s", mod_eagle_path_get(), "test_results");
239                         android_readwrite_file(filename, NULL, test_res_str, strlen(test_res_str));
240                 }
241 #endif
242                 break;
243         }
244         case SIP_EVT_TRC_AMPDU: {
245                 struct sip_evt_trc_ampdu *ep = (struct sip_evt_trc_ampdu*)(buf + SIP_CTRL_HDR_LEN);
246                 struct esp_node *node = NULL;
247                 int i = 0;
248
249                 if (atomic_read(&sip->epub->wl.off)) {
250                         esp_dbg(ESP_DBG_ERROR, "%s scan result while wlan off\n", __func__);
251                         return 0;
252                 }
253                 
254                 node = esp_get_node_by_addr(sip->epub, ep->addr);
255                 if(node == NULL)
256                         break;
257 #if 0
258                 esp_tx_ba_session_op(sip, node, ep->state, ep->tid);
259 #else
260                 for (i = 0; i < 8; i++) {
261                         if (ep->tid & (1<<i)) {
262                                 esp_tx_ba_session_op(sip, node, ep->state, i);
263                         }
264                 }
265 #endif
266                 break;
267         }
268
269             case SIP_EVT_EP: {
270                                  char *ep = (char *)(buf + SIP_CTRL_HDR_LEN);
271                                  static int counter = 0;
272                                  
273                                  esp_dbg(ESP_ATE, "%s EVT_EP \n\n", __func__);
274                                  if (counter++ < 2) {
275                                          esp_dbg(ESP_ATE, "ATE: %s \n", ep);
276                                  }
277
278                                  esp_test_ate_done_cb(ep);
279
280                                  break;
281                          }
282         case SIP_EVT_INIT_EP: {
283                                  char *ep = (char *)(buf + SIP_CTRL_HDR_LEN);
284                                  esp_dbg(ESP_ATE, "Phy Init: %s \n", ep);
285                                  break;
286                               }
287
288         case SIP_EVT_NOISEFLOOR:{
289                                         struct sip_evt_noisefloor *ep = (struct sip_evt_noisefloor *)(buf + SIP_CTRL_HDR_LEN);                                        
290                                         atomic_set(&sip->noise_floor, ep->noise_floor);
291                                         break;
292                                 }
293         default:
294                 break;
295         }
296
297         return 0;
298 }
299
300 #ifdef HAS_INIT_DATA
301 #include "esp_init_data.h"
302 #else
303 #define ESP_INIT_NAME "esp_init_data.bin"
304 #endif /* HAS_INIT_DATA */
305
306 void sip_send_chip_init(struct esp_sip *sip)
307 {
308         size_t size = 0;
309 #ifndef HAS_INIT_DATA
310         const struct firmware *fw_entry;
311         u8 * esp_init_data = NULL;
312         int ret = 0;
313   #ifdef ANDROID
314         ret = android_request_firmware(&fw_entry, ESP_INIT_NAME, sip->epub->dev);
315   #else
316         ret = request_firmware(&fw_entry, ESP_INIT_NAME, sip->epub->dev);
317   #endif /* ANDROID */
318         
319         if (ret) {
320                 esp_dbg(ESP_DBG_ERROR, "%s =============ERROR! NO INIT DATA!!=================\n", __func__);
321                 return;
322         }
323         esp_init_data = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
324
325         size = fw_entry->size;
326
327   #ifdef ANDROID
328         android_release_firmware(fw_entry);
329   #else
330         release_firmware(fw_entry);
331   #endif /* ANDROID */
332
333         if (esp_init_data == NULL) {
334                 esp_dbg(ESP_DBG_ERROR, "%s =============ERROR! NO MEMORY!!=================\n", __func__);
335                 return;
336         }
337 #else
338         size = sizeof(esp_init_data);
339
340 #endif /* !HAS_INIT_DATA */
341
342 #ifdef ANDROID
343         //show_init_buf(esp_init_data,size); 
344         fix_init_data(esp_init_data, size);
345         //show_init_buf(esp_init_data,size);
346 #endif
347         atomic_sub(1, &sip->tx_credits);
348         
349         sip_send_cmd(sip, SIP_CMD_INIT, size, (void *)esp_init_data);
350
351 #ifndef HAS_INIT_DATA
352         kfree(esp_init_data);
353 #endif /* !HAS_INIT_DATA */
354 }
355
356 int sip_send_config(struct esp_pub *epub, struct ieee80211_conf * conf)
357 {
358         struct sk_buff *skb = NULL;
359         struct sip_cmd_config *configcmd;
360
361         skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_config) + sizeof(struct sip_hdr), SIP_CMD_CONFIG);
362         if (!skb)
363                 return -EINVAL;
364 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
365         esp_dbg(ESP_DBG_TRACE, "%s config center freq %d\n", __func__, conf->chandef.chan->center_freq);
366 #else
367         esp_dbg(ESP_DBG_TRACE, "%s config center freq %d\n", __func__, conf->channel->center_freq);
368 #endif
369         configcmd = (struct sip_cmd_config *)(skb->data + sizeof(struct sip_hdr));
370 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
371         configcmd->center_freq= conf->chandef.chan->center_freq;
372 #else
373         configcmd->center_freq= conf->channel->center_freq;
374 #endif
375                 configcmd->duration= 0;
376         return sip_cmd_enqueue(epub->sip, skb);
377 }
378
379 int  sip_send_bss_info_update(struct esp_pub *epub, struct esp_vif *evif, u8 *bssid, int assoc)
380 {
381         struct sk_buff *skb = NULL;
382         struct sip_cmd_bss_info_update*bsscmd;
383
384         skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_bss_info_update) + sizeof(struct sip_hdr), SIP_CMD_BSS_INFO_UPDATE);
385         if (!skb)
386                 return -EINVAL;
387
388         bsscmd = (struct sip_cmd_bss_info_update *)(skb->data + sizeof(struct sip_hdr));
389         if (assoc == 2) { //hack for softAP mode
390                         bsscmd->beacon_int = evif->beacon_interval;
391                 } else if (assoc == 1) {
392                         set_bit(ESP_WL_FLAG_CONNECT, &epub->wl.flags);
393         } else {
394                         clear_bit(ESP_WL_FLAG_CONNECT, &epub->wl.flags);
395         }
396                 bsscmd->bssid_no = evif->index;
397                 bsscmd->isassoc= assoc;
398                 bsscmd->beacon_int = evif->beacon_interval;
399         memcpy(bsscmd->bssid, bssid, ETH_ALEN);
400         return sip_cmd_enqueue(epub->sip, skb);
401 }
402
403 int  sip_send_wmm_params(struct esp_pub *epub, u8 aci, const struct ieee80211_tx_queue_params *params)
404 {
405         struct sk_buff *skb = NULL;
406         struct sip_cmd_set_wmm_params* bsscmd;
407         skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_set_wmm_params) + sizeof(struct sip_hdr), SIP_CMD_SET_WMM_PARAM);
408         if (!skb)
409                 return -EINVAL;
410
411         bsscmd = (struct sip_cmd_set_wmm_params *)(skb->data + sizeof(struct sip_hdr));
412         bsscmd->aci= aci;
413         bsscmd->aifs=params->aifs;
414         bsscmd->txop_us=params->txop*32;
415
416         bsscmd->ecw_min = 32 - __builtin_clz(params->cw_min);
417         bsscmd->ecw_max= 32 -__builtin_clz(params->cw_max);
418
419         return sip_cmd_enqueue(epub->sip, skb);
420 }
421
422 int sip_send_ampdu_action(struct esp_pub *epub, u8 action_num, const u8 * addr, u16 tid, u16 ssn, u8 buf_size)
423 {
424         int index = 0;
425         struct sk_buff *skb = NULL;
426         struct sip_cmd_ampdu_action * action;
427         if(action_num == SIP_AMPDU_RX_START){
428                 index = esp_get_empty_rxampdu(epub, addr, tid);
429         } else if(action_num == SIP_AMPDU_RX_STOP){
430                 index = esp_get_exist_rxampdu(epub, addr, tid);
431         }
432         if(index < 0)
433                 return -EACCES;
434         skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_ampdu_action) + sizeof(struct sip_hdr), SIP_CMD_AMPDU_ACTION);
435         if(!skb)
436                 return -EINVAL;
437
438         action = (struct sip_cmd_ampdu_action *)(skb->data + sizeof(struct sip_hdr));
439         action->action = action_num;
440         //for TX, it means interface index
441         action->index = ssn;
442
443         switch(action_num) {
444         case SIP_AMPDU_RX_START:
445                 action->ssn = ssn;
446         case SIP_AMPDU_RX_STOP:
447                 action->index = index;
448         case SIP_AMPDU_TX_OPERATIONAL:
449         case SIP_AMPDU_TX_STOP:
450                 action->win_size = buf_size;
451                 action->tid = tid;
452                 memcpy(action->addr, addr, ETH_ALEN);
453                 break;
454         }
455
456         return sip_cmd_enqueue(epub->sip, skb);
457 }
458
459 #ifdef HW_SCAN
460 /*send cmd to target, if aborted is true, inform target stop scan, report scan complete imediately
461   return 1: complete over, 0: success, still have next scan, -1: hardware failure
462   */
463 int sip_send_scan(struct esp_pub *epub)
464 {
465         struct cfg80211_scan_request *scan_req = epub->wl.scan_req;
466         struct sk_buff *skb = NULL;
467         struct sip_cmd_scan *scancmd;
468         u8 *ptr = NULL;
469         int i;
470         u8 append_len, ssid_len;
471
472         ESSERT(scan_req != NULL);
473         ssid_len = scan_req->n_ssids == 0 ? 0:
474                 (scan_req->n_ssids == 1 ? scan_req->ssids->ssid_len: scan_req->ssids->ssid_len + (scan_req->ssids + 1)->ssid_len);
475         append_len = ssid_len + scan_req->n_channels + scan_req->ie_len;
476
477         skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_scan) + sizeof(struct sip_hdr) + append_len, SIP_CMD_SCAN);
478
479         if (!skb)
480                 return -EINVAL;
481
482         ptr = skb->data;
483         scancmd = (struct sip_cmd_scan *)(ptr + sizeof(struct sip_hdr));
484         ptr += sizeof(struct sip_hdr);
485
486         scancmd->aborted= false;
487
488         if (scancmd->aborted==false) {
489                 ptr += sizeof(struct sip_cmd_scan);
490                 if (scan_req->n_ssids <=0 || (scan_req->n_ssids == 1&& ssid_len == 0)) {
491                         scancmd->ssid_len = 0;
492                 } else { 
493                         scancmd->ssid_len = ssid_len;
494                         if(scan_req->ssids->ssid_len == ssid_len)
495                                 memcpy(ptr, scan_req->ssids->ssid, scancmd->ssid_len);
496                         else
497                                 memcpy(ptr, (scan_req->ssids + 1)->ssid, scancmd->ssid_len);
498                 }
499
500                 ptr += scancmd->ssid_len;
501                 scancmd->n_channels=scan_req->n_channels;
502                 for (i=0; i<scan_req->n_channels; i++)
503                         ptr[i] = scan_req->channels[i]->hw_value;
504                 
505                 ptr += scancmd->n_channels;
506                 if (scan_req->ie_len && scan_req->ie != NULL) {
507                         scancmd->ie_len=scan_req->ie_len;
508                         memcpy(ptr, scan_req->ie, scan_req->ie_len);
509                 } else {
510                         scancmd->ie_len = 0;
511                 }
512                 //add a flag that support two ssids,
513                 if(scan_req->n_ssids > 1)
514                         scancmd->ssid_len |= 0x80;
515
516         }
517         
518         return sip_cmd_enqueue(epub->sip, skb);
519 }
520 #endif
521
522 int sip_send_suspend_config(struct esp_pub *epub, u8 suspend)
523 {
524         struct sip_cmd_suspend *cmd = NULL;
525         struct sk_buff *skb = NULL;
526
527         skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_suspend) + sizeof(struct sip_hdr), SIP_CMD_SUSPEND);
528
529         if (!skb)
530                 return -EINVAL;
531
532         cmd = (struct sip_cmd_suspend *)(skb->data + sizeof(struct sip_hdr));
533         cmd->suspend = suspend;
534         return sip_cmd_enqueue(epub->sip, skb);
535 }
536
537 int sip_send_ps_config(struct esp_pub *epub, struct esp_ps *ps)
538 {
539         struct sip_cmd_ps *pscmd = NULL;
540         struct sk_buff *skb = NULL;
541         struct sip_hdr *shdr = NULL;
542
543         skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_ps) + sizeof(struct sip_hdr), SIP_CMD_PS);
544
545         if (!skb)
546                 return -EINVAL;
547
548
549         shdr = (struct sip_hdr *)skb->data;
550         pscmd = (struct sip_cmd_ps *)(skb->data + sizeof(struct sip_hdr));
551
552         pscmd->dtim_period = ps->dtim_period;
553         pscmd->max_sleep_period = ps->max_sleep_period;
554
555         return sip_cmd_enqueue(epub->sip, skb);
556 }
557
558 void sip_scandone_process(struct esp_sip *sip, struct sip_evt_scan_report *scan_report)
559 {
560         struct esp_pub *epub = sip->epub;
561
562         esp_dbg(ESP_DBG_TRACE, "eagle hw scan report\n");
563
564         if (epub->wl.scan_req) {
565                 hw_scan_done(epub, scan_report->aborted);
566                 epub->wl.scan_req = NULL;
567         }
568 }
569
570 int sip_send_setkey(struct esp_pub *epub, u8 bssid_no, u8 *peer_addr, struct ieee80211_key_conf *key, u8 isvalid)
571 {
572         struct sip_cmd_setkey *setkeycmd;
573         struct sk_buff *skb = NULL;
574
575         skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_setkey) + sizeof(struct sip_hdr), SIP_CMD_SETKEY);
576
577         if (!skb)
578                 return -EINVAL;
579
580         setkeycmd = (struct sip_cmd_setkey *)(skb->data + sizeof(struct sip_hdr));
581
582         if (peer_addr) {
583                 memcpy(setkeycmd->addr, peer_addr, ETH_ALEN);
584         } else {
585                 memset(setkeycmd->addr, 0, ETH_ALEN);
586         }
587
588                 setkeycmd->bssid_no = bssid_no;
589         setkeycmd->hw_key_idx= key->hw_key_idx;
590
591         if (isvalid) {
592 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39))
593                 setkeycmd->alg= key->alg;
594 #else
595                 setkeycmd->alg= esp_cipher2alg(key->cipher);
596 #endif /* NEW_KERNEL */
597                 setkeycmd->keyidx = key->keyidx;
598                 setkeycmd->keylen = key->keylen;
599 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39))
600                 if (key->alg == ALG_TKIP) {
601 #else
602                 if (key->cipher == WLAN_CIPHER_SUITE_TKIP) {
603 #endif /* NEW_KERNEL */
604                         memcpy(setkeycmd->key, key->key, 16);
605                         memcpy(setkeycmd->key+16,key->key+24,8);
606                         memcpy(setkeycmd->key+24,key->key+16,8);
607                 } else {
608                         memcpy(setkeycmd->key, key->key, key->keylen);
609                 }
610
611                 setkeycmd->flags=1;
612         } else {
613                 setkeycmd->flags=0;
614         }
615         return sip_cmd_enqueue(epub->sip, skb);
616 }
617
618 #ifdef FPGA_LOOPBACK
619 #define LOOPBACK_PKT_LEN 200
620 int sip_send_loopback_cmd_mblk(struct esp_sip *sip)
621 {
622         int cnt, ret;
623
624         for (cnt = 0; cnt < 4; cnt++) {
625                 if (0!=(ret=sip_send_loopback_mblk(sip, LOOPBACK_PKT_LEN, LOOPBACK_PKT_LEN, 0)))
626                         return ret;
627         }
628         return 0;
629 }
630 #endif /* FPGA_LOOPBACK */
631
632 int sip_send_loopback_mblk(struct esp_sip *sip, int txpacket_len, int rxpacket_len, int packet_id)
633 {
634         struct sk_buff *skb = NULL;
635         struct sip_cmd_loopback *cmd;
636         u8 *ptr = NULL;
637         int i, ret;
638
639         //send 100 loopback pkt
640         if(txpacket_len)
641                 skb = sip_alloc_ctrl_skbuf(sip, sizeof(struct sip_cmd_loopback) + sizeof(struct sip_hdr) +  txpacket_len, SIP_CMD_LOOPBACK);
642         else
643                 skb = sip_alloc_ctrl_skbuf(sip, sizeof(struct sip_cmd_loopback) + sizeof(struct sip_hdr), SIP_CMD_LOOPBACK);
644
645         if (!skb)
646                 return -ENOMEM;
647
648         ptr = skb->data;
649         cmd = (struct sip_cmd_loopback *)(ptr + sizeof(struct sip_hdr));
650         ptr += sizeof(struct sip_hdr);
651         cmd->txlen = txpacket_len;
652         cmd->rxlen = rxpacket_len;
653         cmd->pack_id = packet_id;
654
655         if (txpacket_len) {
656                 ptr += sizeof(struct sip_cmd_loopback);
657                 /* fill up pkt payload */
658                 for (i = 0; i < txpacket_len; i++) {
659                         ptr[i] = i;
660                 }
661         }
662
663         ret = sip_cmd_enqueue(sip, skb);
664         if (ret <0)
665                 return ret;
666
667         return 0;
668 }
669
670 //remain_on_channel 
671 int sip_send_roc(struct esp_pub *epub, u16 center_freq, u16 duration)
672 {
673         struct sk_buff *skb = NULL;
674         struct sip_cmd_config *configcmd;
675
676         skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_config) + sizeof(struct sip_hdr), SIP_CMD_CONFIG);
677         if (!skb)
678                 return -EINVAL;
679
680         configcmd = (struct sip_cmd_config *)(skb->data + sizeof(struct sip_hdr));
681         configcmd->center_freq= center_freq;
682         configcmd->duration= duration;
683         return sip_cmd_enqueue(epub->sip, skb);
684 }
685
686 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
687 int sip_send_set_sta(struct esp_pub *epub, u8 ifidx, u8 set, struct ieee80211_sta *sta, struct ieee80211_vif *vif, u8 index)
688 #else
689 int sip_send_set_sta(struct esp_pub *epub, u8 ifidx, u8 set, struct esp_node *node, struct ieee80211_vif *vif, u8 index)
690 #endif
691 {
692         struct sk_buff *skb = NULL;
693         struct sip_cmd_setsta *setstacmd;
694 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28))
695         struct ieee80211_ht_info ht_info = node->ht_info;
696 #endif
697         skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_setsta) + sizeof(struct sip_hdr), SIP_CMD_SETSTA);
698         if (!skb)
699         return -EINVAL;
700
701         setstacmd = (struct sip_cmd_setsta *)(skb->data + sizeof(struct sip_hdr));
702         setstacmd->ifidx = ifidx;
703         setstacmd->index = index;
704         setstacmd->set = set;
705 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
706         if(sta->aid == 0)
707                 setstacmd->aid = vif->bss_conf.aid;
708         else
709                 setstacmd->aid = sta->aid;
710         memcpy(setstacmd->mac, sta->addr, ETH_ALEN);
711         if(set){
712                 if(sta->ht_cap.ht_supported){
713                         if(sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20)
714                                 setstacmd->phymode = ESP_IEEE80211_T_HT20_S;
715                         else
716                                 setstacmd->phymode = ESP_IEEE80211_T_HT20_L;
717                         setstacmd->ampdu_factor = sta->ht_cap.ampdu_factor;
718                         setstacmd->ampdu_density = sta->ht_cap.ampdu_density;
719                 } else {
720                         if(sta->supp_rates[IEEE80211_BAND_2GHZ] & (~(u32)CONF_HW_BIT_RATE_11B_MASK)){
721                                 setstacmd->phymode = ESP_IEEE80211_T_OFDM;
722                         } else {
723                                 setstacmd->phymode = ESP_IEEE80211_T_CCK;
724                         }
725                 }
726         }
727 #else
728     setstacmd->aid = node->aid;
729     memcpy(setstacmd->mac, node->addr, ETH_ALEN);
730     if(set){
731         if(ht_info.ht_supported){
732             if(ht_info.cap & IEEE80211_HT_CAP_SGI_20)
733                 setstacmd->phymode = ESP_IEEE80211_T_HT20_S;
734             else
735                 setstacmd->phymode = ESP_IEEE80211_T_HT20_L;
736             setstacmd->ampdu_factor = ht_info.ampdu_factor;
737             setstacmd->ampdu_density = ht_info.ampdu_density;
738         } else {
739             //note supp_rates is u64[] in 2.6.27
740             if(node->supp_rates[IEEE80211_BAND_2GHZ] & (~(u64)CONF_HW_BIT_RATE_11B_MASK)){
741                 setstacmd->phymode = ESP_IEEE80211_T_OFDM;
742             } else {
743                 setstacmd->phymode = ESP_IEEE80211_T_CCK;
744             }   
745         }   
746     }   
747 #endif
748         return sip_cmd_enqueue(epub->sip, skb);
749 }
750
751 int sip_cmd(struct esp_pub *epub, enum sip_cmd_id cmd_id, u8 *cmd_buf, u8 cmd_len)
752 {
753         struct sk_buff *skb = NULL;
754
755         skb = sip_alloc_ctrl_skbuf(epub->sip, cmd_len + sizeof(struct sip_hdr), cmd_id);
756         if (!skb)
757                 return -ENOMEM;
758
759         memcpy(skb->data + sizeof(struct sip_hdr), cmd_buf, cmd_len);
760
761         return sip_cmd_enqueue(epub->sip, skb);
762 }