]> Git Repo - esp-hosted.git/blame - esp_hosted_ng/host/esp_cmd.c
esp_hosted_ng: Rebase on top of IDF release v5.1.1
[esp-hosted.git] / esp_hosted_ng / host / esp_cmd.c
CommitLineData
e8b168e8 1// SPDX-License-Identifier: GPL-2.0-only
774e9b2e
MM
2/*
3 * Espressif Systems Wireless LAN device driver
4 *
d7215282 5 * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
774e9b2e 6 *
774e9b2e 7 */
057d3956 8#include "utils.h"
774e9b2e
MM
9#include "esp_cmd.h"
10#include "esp_api.h"
11#include "esp_wpa_utils.h"
225e14eb
YM
12#include "esp.h"
13#include "esp_cfg80211.h"
aad2ae2e 14#include "esp_kernel_port.h"
774e9b2e 15
a3829bf3 16#define PRINT_HEXDUMP(STR, ARG, ARG_LEN, level) \
774e9b2e
MM
17 print_hex_dump(KERN_INFO, STR, DUMP_PREFIX_ADDRESS, 16, 1, ARG, ARG_LEN, 1);
18
19#define COMMAND_RESPONSE_TIMEOUT (5 * HZ)
20u8 ap_bssid[MAC_ADDR_LEN];
21
a3829bf3 22int internal_scan_request(struct esp_wifi_device *priv, char *ssid,
774e9b2e
MM
23 uint8_t channel, uint8_t is_blocking);
24
25struct beacon_probe_fixed_params {
26 __le64 timestamp;
27 __le16 beacon_interval;
28 __le16 cap_info;
29} __packed;
30
a3829bf3 31static struct command_node *get_free_cmd_node(struct esp_adapter *adapter)
774e9b2e
MM
32{
33 struct command_node *cmd_node;
34
35 spin_lock_bh(&adapter->cmd_free_queue_lock);
36
37 if (list_empty(&adapter->cmd_free_queue)) {
38 spin_unlock_bh(&adapter->cmd_free_queue_lock);
6f8fee57 39 esp_err("No free cmd node found\n");
774e9b2e
MM
40 return NULL;
41 }
42 cmd_node = list_first_entry(&adapter->cmd_free_queue,
43 struct command_node, list);
44 list_del(&cmd_node->list);
45 spin_unlock_bh(&adapter->cmd_free_queue_lock);
46
47 cmd_node->cmd_skb = esp_alloc_skb(ESP_SIZE_OF_CMD_NODE);
48 if (!cmd_node->cmd_skb) {
6f8fee57 49 esp_err("No free cmd node skb found\n");
774e9b2e
MM
50 }
51
52 return cmd_node;
53}
54
a3829bf3 55static inline void reset_cmd_node(struct esp_adapter *adapter, struct command_node *cmd_node)
774e9b2e
MM
56{
57 cmd_node->cmd_code = 0;
58
225e14eb 59 spin_lock_bh(&adapter->cmd_lock);
774e9b2e
MM
60 if (cmd_node->resp_skb) {
61 dev_kfree_skb_any(cmd_node->resp_skb);
62 cmd_node->resp_skb = NULL;
63 }
225e14eb 64 spin_unlock_bh(&adapter->cmd_lock);
774e9b2e
MM
65}
66
67static void queue_cmd_node(struct esp_adapter *adapter,
a3829bf3 68 struct command_node *cmd_node, u8 flag_high_prio)
774e9b2e
MM
69{
70 spin_lock_bh(&adapter->cmd_pending_queue_lock);
71
72 if (flag_high_prio)
225e14eb 73 list_add_rcu(&cmd_node->list, &adapter->cmd_pending_queue);
774e9b2e 74 else
225e14eb 75 list_add_tail_rcu(&cmd_node->list, &adapter->cmd_pending_queue);
774e9b2e
MM
76
77 spin_unlock_bh(&adapter->cmd_pending_queue_lock);
78}
79
9726a3d0 80static int decode_mac_addr(struct esp_wifi_device *priv,
774e9b2e
MM
81 struct command_node *cmd_node)
82{
83 int ret = 0;
84 struct cmd_config_mac_address *header;
85
86 if (!priv || !cmd_node ||
87 !cmd_node->resp_skb ||
88 !cmd_node->resp_skb->data) {
6f8fee57 89 esp_info("Invalid arg\n");
774e9b2e
MM
90 return -1;
91 }
92
93 header = (struct cmd_config_mac_address *) (cmd_node->resp_skb->data);
94
95 if (header->header.cmd_status != CMD_RESPONSE_SUCCESS) {
6f8fee57 96 esp_info("Command failed\n");
774e9b2e
MM
97 ret = -1;
98 }
99
100 if (priv)
101 memcpy(priv->mac_address, header->mac_addr, MAC_ADDR_LEN);
102 else
6f8fee57 103 esp_err("priv not updated\n");
774e9b2e
MM
104
105 return ret;
106}
107
9726a3d0
KG
108static int decode_tx_power(struct esp_wifi_device *priv,
109 struct command_node *cmd_node)
110{
111 int ret = 0;
112 struct cmd_set_get_val *header;
113
114 if (!priv || !cmd_node ||
115 !cmd_node->resp_skb ||
116 !cmd_node->resp_skb->data) {
117 esp_info("Invalid arg\n");
118 return -1;
119 }
120
121 header = (struct cmd_set_get_val *) (cmd_node->resp_skb->data);
122
123 if (header->header.cmd_status != CMD_RESPONSE_SUCCESS) {
124 esp_info("Command failed\n");
125 ret = -1;
126 }
127
128 if (priv)
129 priv->tx_pwr = header->value;
130 else
131 esp_err("priv not updated\n");
132
133 return ret;
134}
774e9b2e
MM
135
136static int decode_common_resp(struct command_node *cmd_node)
137{
138 int ret = 0;
139 struct command_header *cmd;
140
141
142 if (!cmd_node || !cmd_node->resp_skb || !cmd_node->resp_skb->data) {
225e14eb 143
a3829bf3 144 esp_info("Failed. cmd_node:%p\n", cmd_node);
225e14eb
YM
145
146 if (cmd_node)
a3829bf3 147 esp_info("code: %u resp_skb:%p\n",
6f8fee57 148 cmd_node->cmd_code, cmd_node->resp_skb);
225e14eb 149
774e9b2e
MM
150 return -1;
151 }
152
153 cmd = (struct command_header *) (cmd_node->resp_skb->data);
154
155 if (cmd->cmd_status != CMD_RESPONSE_SUCCESS) {
6f8fee57 156 esp_info("[0x%x] Command failed\n", cmd_node->cmd_code);
774e9b2e
MM
157 ret = -1;
158 }
159
160 return ret;
161}
162
163static void recycle_cmd_node(struct esp_adapter *adapter,
a3829bf3 164 struct command_node *cmd_node)
774e9b2e
MM
165{
166 if (!adapter || !cmd_node)
167 return;
168
225e14eb 169 reset_cmd_node(adapter, cmd_node);
774e9b2e
MM
170
171 spin_lock_bh(&adapter->cmd_free_queue_lock);
172 list_add_tail(&cmd_node->list, &adapter->cmd_free_queue);
173 spin_unlock_bh(&adapter->cmd_free_queue_lock);
174}
175
176
177static int wait_and_decode_cmd_resp(struct esp_wifi_device *priv,
178 struct command_node *cmd_node)
179{
180 struct esp_adapter *adapter = NULL;
181 int ret = 0;
182
183 if (!priv || !priv->adapter || !cmd_node) {
6f8fee57 184 esp_info("Invalid params\n");
774e9b2e
MM
185 if (priv->adapter) {
186 adapter = priv->adapter;
187 if (adapter && cmd_node)
188 recycle_cmd_node(adapter, cmd_node);
189 }
190 return -EINVAL;
191 }
192
193 adapter = priv->adapter;
194
195 /* wait for command response */
196 ret = wait_event_interruptible_timeout(adapter->wait_for_cmd_resp,
225e14eb
YM
197 adapter->cmd_resp == cmd_node->cmd_code, COMMAND_RESPONSE_TIMEOUT);
198
199 if (!test_bit(ESP_DRIVER_ACTIVE, &adapter->state_flags))
200 return 0;
774e9b2e
MM
201
202 if (ret == 0) {
6f8fee57 203 esp_err("Command[%u] timed out\n", cmd_node->cmd_code);
774e9b2e
MM
204 ret = -EINVAL;
205 } else {
6f8fee57 206 /*esp_dbg("Resp for command [%u]\n", cmd_node->cmd_code);*/
774e9b2e
MM
207 ret = 0;
208 }
209
210 spin_lock_bh(&adapter->cmd_lock);
211 adapter->cur_cmd = NULL;
212 adapter->cmd_resp = 0;
213 spin_unlock_bh(&adapter->cmd_lock);
214
215 switch (cmd_node->cmd_code) {
216
217 case CMD_SCAN_REQUEST:
218 if (ret == 0)
219 ret = decode_common_resp(cmd_node);
220
225e14eb 221 if (ret)
0af9c02e 222 ESP_MARK_SCAN_DONE(priv, false);
774e9b2e
MM
223 break;
224
225 case CMD_INIT_INTERFACE:
226 case CMD_DEINIT_INTERFACE:
7b6ed49e
MM
227 case CMD_STA_AUTH:
228 case CMD_STA_ASSOC:
774e9b2e
MM
229 case CMD_STA_CONNECT:
230 case CMD_STA_DISCONNECT:
231 case CMD_ADD_KEY:
232 case CMD_DEL_KEY:
233 case CMD_SET_DEFAULT_KEY:
7406fe82
MM
234 case CMD_SET_IP_ADDR:
235 case CMD_SET_MCAST_MAC_ADDR:
f7ac1df4
KG
236 case CMD_GET_REG_DOMAIN:
237 case CMD_SET_REG_DOMAIN:
774e9b2e
MM
238 /* intentional fallthrough */
239 if (ret == 0)
240 ret = decode_common_resp(cmd_node);
241 break;
242
243 case CMD_GET_MAC:
98f8ece9 244 case CMD_SET_MAC:
774e9b2e 245 if (ret == 0)
9726a3d0
KG
246 ret = decode_mac_addr(priv, cmd_node);
247 break;
248
249 case CMD_GET_TXPOWER:
250 case CMD_SET_TXPOWER:
251 if (ret == 0)
252 ret = decode_tx_power(priv, cmd_node);
774e9b2e
MM
253 break;
254
255 default:
6f8fee57 256 esp_info("Resp for [0x%x] ignored\n", cmd_node->cmd_code);
774e9b2e
MM
257 ret = -EINVAL;
258 break;
259 }
260
261 recycle_cmd_node(adapter, cmd_node);
262 return ret;
263}
264
265static void free_esp_cmd_pool(struct esp_adapter *adapter)
266{
267 int i;
a3829bf3 268 struct command_node *cmd_pool = NULL;
774e9b2e
MM
269
270 if (!adapter || !adapter->cmd_pool)
271 return;
272
273 cmd_pool = adapter->cmd_pool;
274
a3829bf3 275 for (i = 0; i < ESP_NUM_OF_CMD_NODES; i++) {
774e9b2e 276
225e14eb 277 spin_lock_bh(&adapter->cmd_lock);
774e9b2e
MM
278 if (cmd_pool[i].resp_skb) {
279 dev_kfree_skb_any(cmd_pool[i].resp_skb);
280 cmd_pool[i].resp_skb = NULL;
281 }
225e14eb 282 spin_unlock_bh(&adapter->cmd_lock);
774e9b2e
MM
283 }
284
285 kfree(adapter->cmd_pool);
286 adapter->cmd_pool = NULL;
287}
288
289static int alloc_esp_cmd_pool(struct esp_adapter *adapter)
290{
291 u16 i;
292
a3829bf3 293 struct command_node *cmd_pool = kcalloc(ESP_NUM_OF_CMD_NODES,
774e9b2e
MM
294 sizeof(struct command_node), GFP_KERNEL);
295
a3829bf3 296 if (!cmd_pool)
774e9b2e
MM
297 return -ENOMEM;
298
299 adapter->cmd_pool = cmd_pool;
300
a3829bf3 301 for (i = 0; i < ESP_NUM_OF_CMD_NODES; i++) {
774e9b2e
MM
302
303 cmd_pool[i].cmd_skb = NULL;
304 cmd_pool[i].resp_skb = NULL;
305 recycle_cmd_node(adapter, &cmd_pool[i]);
306 }
307
308 return 0;
309}
310
774e9b2e
MM
311static void esp_cmd_work(struct work_struct *work)
312{
313 int ret;
314 struct command_node *cmd_node = NULL;
a3829bf3 315 struct esp_adapter *adapter = NULL;
fadb81aa 316 struct esp_payload_header *payload_header = NULL;
774e9b2e
MM
317
318 adapter = esp_get_adapter();
319
320 if (!adapter)
321 return;
322
225e14eb
YM
323 if (!test_bit(ESP_DRIVER_ACTIVE, &adapter->state_flags))
324 return;
325
326 synchronize_rcu();
327 spin_lock_bh(&adapter->cmd_lock);
774e9b2e 328 if (adapter->cur_cmd) {
225e14eb 329 /* Busy in another command */
6f8fee57 330 /*esp_dbg("Busy in another cmd execution\n");*/
225e14eb 331 spin_unlock_bh(&adapter->cmd_lock);
774e9b2e
MM
332 return;
333 }
334
335 spin_lock_bh(&adapter->cmd_pending_queue_lock);
336
337 if (list_empty(&adapter->cmd_pending_queue)) {
225e14eb 338 /* No command to process */
6f8fee57 339 /*esp_dbg("No more command in queue.\n");*/
774e9b2e 340 spin_unlock_bh(&adapter->cmd_pending_queue_lock);
225e14eb 341 spin_unlock_bh(&adapter->cmd_lock);
774e9b2e
MM
342 return;
343 }
344
345 cmd_node = list_first_entry(&adapter->cmd_pending_queue,
346 struct command_node, list);
a3829bf3 347 if (!cmd_node) {
6f8fee57 348 esp_dbg("cmd node NULL\n");
774e9b2e 349 spin_unlock_bh(&adapter->cmd_pending_queue_lock);
225e14eb 350 spin_unlock_bh(&adapter->cmd_lock);
774e9b2e
MM
351 return;
352 }
6f8fee57 353 /*esp_dbg("Processing Command [0x%X]\n", cmd_node->cmd_code);*/
225e14eb 354
774e9b2e
MM
355 list_del(&cmd_node->list);
356
a3829bf3
KG
357 if (!cmd_node->cmd_skb) {
358 esp_dbg("cmd_node->cmd_skb NULL\n");
774e9b2e 359 spin_unlock_bh(&adapter->cmd_pending_queue_lock);
225e14eb 360 spin_unlock_bh(&adapter->cmd_lock);
774e9b2e
MM
361 return;
362 }
363
225e14eb 364 /* Set as current cmd */
774e9b2e 365 adapter->cur_cmd = cmd_node;
225e14eb 366
774e9b2e 367 adapter->cmd_resp = 0;
774e9b2e 368
fadb81aa 369 payload_header = (struct esp_payload_header *)cmd_node->cmd_skb->data;
bf3d6cb6
SR
370 if (adapter->capabilities & ESP_CHECKSUM_ENABLED)
371 payload_header->checksum = cpu_to_le16(compute_checksum(cmd_node->cmd_skb->data,
372 payload_header->len+payload_header->offset));
774e9b2e
MM
373
374 ret = esp_send_packet(adapter, cmd_node->cmd_skb);
225e14eb 375 spin_unlock_bh(&adapter->cmd_lock);
774e9b2e
MM
376
377 if (ret) {
a3829bf3 378 esp_err("Failed to send command [0x%X]\n", cmd_node->cmd_code);
774e9b2e 379 adapter->cur_cmd = NULL;
225e14eb 380 spin_unlock_bh(&adapter->cmd_pending_queue_lock);
774e9b2e
MM
381 recycle_cmd_node(adapter, cmd_node);
382 return;
383 }
225e14eb
YM
384
385 if (!list_empty(&adapter->cmd_pending_queue)) {
6f8fee57 386 /*esp_dbg("Ym2: Pending cmds, queue work again\n");*/
225e14eb
YM
387 spin_unlock_bh(&adapter->cmd_pending_queue_lock);
388 queue_work(adapter->cmd_wq, &adapter->cmd_work);
389 return;
390 }
391 spin_unlock_bh(&adapter->cmd_pending_queue_lock);
774e9b2e
MM
392}
393
394static int create_cmd_wq(struct esp_adapter *adapter)
395{
396 adapter->cmd_wq = alloc_workqueue("ESP_CMD_WORK_QUEUE", 0, 0);
397
398 RET_ON_FAIL(!adapter->cmd_wq);
399
400 INIT_WORK(&adapter->cmd_work, esp_cmd_work);
401
402 return 0;
403}
404
405static void destroy_cmd_wq(struct esp_adapter *adapter)
406{
407 if (adapter->cmd_wq) {
408 flush_scheduled_work();
409 destroy_workqueue(adapter->cmd_wq);
410 adapter->cmd_wq = NULL;
411 }
412}
413
a3829bf3 414struct command_node *prepare_command_request(struct esp_adapter *adapter, u8 cmd_code, u16 len)
774e9b2e
MM
415{
416 struct command_header *cmd;
417 struct esp_payload_header *payload_header;
418 struct command_node *node = NULL;
419
420 if (!adapter) {
6f8fee57 421 esp_info("%u null adapter\n", __LINE__);
774e9b2e
MM
422 return NULL;
423 }
424
425 if (!cmd_code || cmd_code >= CMD_MAX) {
6f8fee57 426 esp_err("unsupported command code\n");
774e9b2e
MM
427 return NULL;
428 }
429
430 node = get_free_cmd_node(adapter);
431
432 if (!node || !node->cmd_skb) {
6f8fee57 433 esp_err("Failed to get new free cmd node\n");
774e9b2e
MM
434 return NULL;
435 }
436
437 node->cmd_code = cmd_code;
438
439 len += sizeof(struct esp_payload_header);
440
aad2ae2e 441 payload_header = (struct esp_payload_header *)skb_put(node->cmd_skb, len);
774e9b2e
MM
442 memset(payload_header, 0, len);
443
444 payload_header->if_type = ESP_STA_IF;
445 payload_header->len = cpu_to_le16(len - sizeof(struct esp_payload_header));
446 payload_header->offset = cpu_to_le16(sizeof(struct esp_payload_header));
447 payload_header->packet_type = PACKET_TYPE_COMMAND_REQUEST;
448
449 cmd = (struct command_header *) (node->cmd_skb->data + payload_header->offset);
450 cmd->cmd_code = cmd_code;
451
452/* payload_header->checksum = cpu_to_le16(compute_checksum(skb->data, len));*/
774e9b2e
MM
453 return node;
454}
455
225e14eb 456int process_cmd_resp(struct esp_adapter *adapter, struct sk_buff *skb)
774e9b2e
MM
457{
458 if (!skb || !adapter) {
6f8fee57 459 esp_err("CMD resp: invalid!\n");
774e9b2e
MM
460
461 if (skb)
462 dev_kfree_skb_any(skb);
463
464 return -1;
465 }
466
467 if (!adapter->cur_cmd) {
6f8fee57 468 esp_err("Command response not expected\n");
774e9b2e
MM
469 dev_kfree_skb_any(skb);
470 return -1;
471 }
472
473 spin_lock_bh(&adapter->cmd_lock);
474 adapter->cur_cmd->resp_skb = skb;
225e14eb 475 adapter->cmd_resp = adapter->cur_cmd->cmd_code;
774e9b2e
MM
476 spin_unlock_bh(&adapter->cmd_lock);
477
774e9b2e
MM
478
479 wake_up_interruptible(&adapter->wait_for_cmd_resp);
480 queue_work(adapter->cmd_wq, &adapter->cmd_work);
481
482 return 0;
483}
484
485static void process_scan_result_event(struct esp_wifi_device *priv,
486 struct scan_event *scan_evt)
487{
225e14eb
YM
488 struct cfg80211_bss *bss = NULL;
489 struct beacon_probe_fixed_params *fixed_params = NULL;
490 struct ieee80211_channel *chan = NULL;
491 u8 *ie_buf = NULL;
774e9b2e
MM
492 u64 timestamp;
493 u16 beacon_interval;
494 u16 cap_info;
774e9b2e
MM
495 u32 ie_len;
496 int freq;
b1372379 497 int frame_type = CFG80211_BSS_FTYPE_UNKNOWN; /* int type for older compatibilty */
774e9b2e
MM
498
499 if (!priv || !scan_evt) {
6f8fee57 500 esp_err("Invalid arguments\n");
774e9b2e
MM
501 return;
502 }
503
225e14eb
YM
504 /*if (!priv->scan_in_progress) {
505 return;
506 }*/
507
774e9b2e
MM
508 /* End of scan; notify cfg80211 */
509 if (scan_evt->header.status == 0) {
774e9b2e 510
0af9c02e 511 ESP_MARK_SCAN_DONE(priv, false);
774e9b2e
MM
512 if (priv->waiting_for_scan_done) {
513 priv->waiting_for_scan_done = false;
514 wake_up_interruptible(&priv->wait_for_scan_completion);
515 }
516 return;
517 }
518
519 ie_buf = (u8 *) scan_evt->frame;
520 ie_len = le16_to_cpu(scan_evt->frame_len);
521
522 fixed_params = (struct beacon_probe_fixed_params *) ie_buf;
523
524 timestamp = le64_to_cpu(fixed_params->timestamp);
525 beacon_interval = le16_to_cpu(fixed_params->beacon_interval);
526 cap_info = le16_to_cpu(fixed_params->cap_info);
527
528 freq = ieee80211_channel_to_frequency(scan_evt->channel, NL80211_BAND_2GHZ);
529 chan = ieee80211_get_channel(priv->adapter->wiphy, freq);
530
531 ie_buf += sizeof(struct beacon_probe_fixed_params);
532 ie_len -= sizeof(struct beacon_probe_fixed_params);
533
b1372379
SS
534 if ((scan_evt->frame_type << 4) == IEEE80211_STYPE_BEACON) {
535 frame_type = CFG80211_BSS_FTYPE_BEACON;
536 } else if ((scan_evt->frame_type << 4) == IEEE80211_STYPE_PROBE_RESP) {
537 frame_type = CFG80211_BSS_FTYPE_PRESP;
538 }
539
774e9b2e 540 if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) {
aad2ae2e 541 bss = CFG80211_INFORM_BSS(priv->adapter->wiphy, chan,
b1372379 542 frame_type, scan_evt->bssid, timestamp,
774e9b2e 543 cap_info, beacon_interval, ie_buf, ie_len,
c13c46a9 544 (le32_to_cpu(scan_evt->rssi) * 100), GFP_ATOMIC);
774e9b2e
MM
545
546 if (bss)
547 cfg80211_put_bss(priv->adapter->wiphy, bss);
548 } else {
6f8fee57 549 esp_info("Scan report: Skip invalid or disabled channel\n");
774e9b2e
MM
550 }
551}
552
a3829bf3 553static void process_auth_event(struct esp_wifi_device *priv,
7b6ed49e
MM
554 struct auth_event *event)
555{
556 if (!priv || !event) {
6f8fee57 557 esp_err("Invalid arguments\n");
7b6ed49e
MM
558 return;
559 }
560
561#if 0
562 print_hex_dump(KERN_INFO, "Auth frame: ", DUMP_PREFIX_ADDRESS, 16, 1,
563 event->frame, event->frame_len, 1);
564#endif
565
566 cfg80211_rx_mlme_mgmt(priv->ndev, event->frame, event->frame_len);
567
568}
569
774e9b2e
MM
570static void process_disconnect_event(struct esp_wifi_device *priv,
571 struct disconnect_event *event)
572{
573 if (!priv || !event) {
6f8fee57 574 esp_err("Invalid arguments\n");
774e9b2e
MM
575 return;
576 }
577
6f8fee57 578 esp_info("Disconnect event for ssid %s [reason:%d]\n",
225e14eb 579 event->ssid, event->reason);
774e9b2e 580
aad2ae2e 581 esp_mark_disconnect(priv, event->reason, true);
774e9b2e
MM
582}
583
bd131325
YM
584static void process_assoc_event(struct esp_wifi_device *priv,
585 struct assoc_event *event)
774e9b2e
MM
586{
587 u8 mac[6];
588
589 if (!priv || !event) {
6f8fee57 590 esp_err("Invalid arguments\n");
774e9b2e
MM
591 return;
592 }
593
6f8fee57 594 esp_info("Connection status: %d\n", event->header.status);
774e9b2e 595
774e9b2e
MM
596 memcpy(mac, event->bssid, MAC_ADDR_LEN);
597
1294f8ac 598 CFG80211_RX_ASSOC_RESP(priv->ndev, priv->bss, event->frame, event->frame_len,
7b6ed49e
MM
599 0, priv->assoc_req_ie, priv->assoc_req_ie_len);
600
601#if 0
602 if (priv->bss) {
603 cfg80211_connect_bss(priv->ndev, mac, priv->bss, NULL, 0, NULL, 0,
604 0, GFP_KERNEL, NL80211_TIMEOUT_UNSPECIFIED);
605 } else {
606 cfg80211_connect_result(priv->ndev, mac, NULL, 0, NULL, 0,
607 0, GFP_KERNEL);
608 }
609#endif
774e9b2e
MM
610
611 esp_port_open(priv);
612}
613
225e14eb 614int process_cmd_event(struct esp_wifi_device *priv, struct sk_buff *skb)
774e9b2e
MM
615{
616 struct event_header *header;
617
618 if (!skb || !priv) {
6f8fee57 619 esp_err("CMD evnt: invalid!\n");
774e9b2e
MM
620 return -1;
621 }
622
623 header = (struct event_header *) (skb->data);
624
625 switch (header->event_code) {
626
627 case EVENT_SCAN_RESULT:
628 process_scan_result_event(priv,
629 (struct scan_event *)(skb->data));
630 break;
631
bd131325
YM
632 case EVENT_ASSOC_RX:
633 process_assoc_event(priv,
634 (struct assoc_event *)(skb->data));
774e9b2e
MM
635 break;
636
637 case EVENT_STA_DISCONNECT:
638 process_disconnect_event(priv,
639 (struct disconnect_event *)(skb->data));
640 break;
641
7b6ed49e
MM
642 case EVENT_AUTH_RX:
643 process_auth_event(priv, (struct auth_event *)(skb->data));
644 break;
645
774e9b2e 646 default:
6f8fee57
KG
647 esp_info("%u unhandled event[%u]\n",
648 __LINE__, header->event_code);
774e9b2e
MM
649 break;
650 }
651
652 return 0;
653}
654
7406fe82
MM
655int cmd_set_mcast_mac_list(struct esp_wifi_device *priv, struct multicast_list *list)
656{
657 struct command_node *cmd_node = NULL;
658 struct cmd_set_mcast_mac_addr *cmd_mcast_mac_list;
7406fe82
MM
659
660 if (!priv || !priv->adapter) {
6f8fee57 661 esp_err("Invalid argument\n");
7406fe82
MM
662 return -EINVAL;
663 }
664
665 if (test_bit(ESP_CLEANUP_IN_PROGRESS, &priv->adapter->state_flags))
666 return 0;
667
5a47b073
MM
668 cmd_node = prepare_command_request(priv->adapter, CMD_SET_MCAST_MAC_ADDR,
669 sizeof(struct cmd_set_mcast_mac_addr));
7406fe82 670
5a47b073 671 if (!cmd_node) {
6f8fee57 672 esp_err("Failed to get command node\n");
5a47b073
MM
673 return -ENOMEM;
674 }
7406fe82 675
5a47b073
MM
676 cmd_mcast_mac_list = (struct cmd_set_mcast_mac_addr *)
677 (cmd_node->cmd_skb->data + sizeof(struct esp_payload_header));
7406fe82 678
5a47b073
MM
679 cmd_mcast_mac_list->count = list->addr_count;
680 memcpy(cmd_mcast_mac_list->mcast_addr, list->mcast_addr,
681 sizeof(cmd_mcast_mac_list->mcast_addr));
7406fe82 682
5a47b073
MM
683 queue_cmd_node(priv->adapter, cmd_node, ESP_CMD_DFLT_PRIO);
684 queue_work(priv->adapter->cmd_wq, &priv->adapter->cmd_work);
7406fe82 685
5a47b073 686 RET_ON_FAIL(wait_and_decode_cmd_resp(priv, cmd_node));
7406fe82
MM
687 return 0;
688}
689
690int cmd_set_ip_address(struct esp_wifi_device *priv, u32 ip)
691{
692 struct command_node *cmd_node = NULL;
693 struct cmd_set_ip_addr *cmd_set_ip;
694
7406fe82 695 if (!priv || !priv->adapter) {
6f8fee57 696 esp_err("Invalid argument\n");
7406fe82
MM
697 return -EINVAL;
698 }
699
700 if (test_bit(ESP_CLEANUP_IN_PROGRESS, &priv->adapter->state_flags))
701 return 0;
702
703 cmd_node = prepare_command_request(priv->adapter, CMD_SET_IP_ADDR,
704 sizeof(struct cmd_set_ip_addr));
705
706 if (!cmd_node) {
6f8fee57 707 esp_err("Failed to get command node\n");
7406fe82
MM
708 return -ENOMEM;
709 }
710
711 cmd_set_ip = (struct cmd_set_ip_addr *)
712 (cmd_node->cmd_skb->data + sizeof(struct esp_payload_header));
713
714 cmd_set_ip->ip = cpu_to_le32(ip);
715
716 queue_cmd_node(priv->adapter, cmd_node, ESP_CMD_DFLT_PRIO);
717 queue_work(priv->adapter->cmd_wq, &priv->adapter->cmd_work);
718
719 RET_ON_FAIL(wait_and_decode_cmd_resp(priv, cmd_node));
720
721 return 0;
722}
723
774e9b2e
MM
724int cmd_disconnect_request(struct esp_wifi_device *priv, u16 reason_code)
725{
726 struct command_node *cmd_node = NULL;
727 struct cmd_sta_disconnect *cmd_disconnect;
728
729 if (!priv || !priv->adapter) {
6f8fee57 730 esp_err("Invalid argument\n");
774e9b2e
MM
731 return -EINVAL;
732 }
733
734 if (test_bit(ESP_CLEANUP_IN_PROGRESS, &priv->adapter->state_flags))
735 return 0;
736
737 cmd_node = prepare_command_request(priv->adapter, CMD_STA_DISCONNECT,
738 sizeof(struct cmd_sta_disconnect));
739
740 if (!cmd_node) {
6f8fee57 741 esp_err("Failed to get command node\n");
774e9b2e
MM
742 return -ENOMEM;
743 }
744
745 cmd_disconnect = (struct cmd_sta_disconnect *)
746 (cmd_node->cmd_skb->data + sizeof(struct esp_payload_header));
747
748 cmd_disconnect->reason_code = reason_code;
749
750 queue_cmd_node(priv->adapter, cmd_node, ESP_CMD_DFLT_PRIO);
751 queue_work(priv->adapter->cmd_wq, &priv->adapter->cmd_work);
752
753 RET_ON_FAIL(wait_and_decode_cmd_resp(priv, cmd_node));
754
755 return 0;
756}
757
bd131325 758#if 0
774e9b2e
MM
759int cmd_connect_request(struct esp_wifi_device *priv,
760 struct cfg80211_connect_params *params)
761{
762 u16 cmd_len;
763 struct command_node *cmd_node = NULL;
764 struct cmd_sta_connect *cmd;
765 struct ieee80211_channel *chan;
766 struct cfg80211_bss *bss;
767 struct esp_adapter *adapter = NULL;
774e9b2e
MM
768 u8 retry = 2;
769
770 if (!priv || !params || !priv->adapter) {
6f8fee57 771 esp_err("Invalid argument\n");
774e9b2e
MM
772 return -EINVAL;
773 }
774
775 if (test_bit(ESP_CLEANUP_IN_PROGRESS, &priv->adapter->state_flags)) {
6f8fee57 776 esp_err("%u cleanup in progress, return failure", __LINE__);
774e9b2e
MM
777 return -EFAULT;
778 }
779
780 adapter = priv->adapter;
781
782 cmd_len = sizeof(struct cmd_sta_connect) + params->ie_len;
783
784 cmd_node = prepare_command_request(adapter, CMD_STA_CONNECT, cmd_len);
785 if (!cmd_node) {
6f8fee57 786 esp_err("Failed to get command node\n");
774e9b2e
MM
787 return -ENOMEM;
788 }
789 cmd = (struct cmd_sta_connect *) (cmd_node->cmd_skb->data + sizeof(struct esp_payload_header));
790
791 if (params->ssid_len)
792 memcpy(cmd->ssid, params->ssid, MAX_SSID_LEN);
793 else
6f8fee57 794 esp_err("No ssid\n");
774e9b2e
MM
795
796 if (params->bssid) {
797 memcpy(ap_bssid, params->bssid, MAC_ADDR_LEN);
798 memcpy(cmd->bssid, params->bssid, MAC_ADDR_LEN);
799 }
800
801 if (params->channel) {
802 chan = params->channel;
803 cmd->channel = chan->hw_value;
804 }
805
806 if (params->ie_len) {
807 cmd->assoc_ie_len = cpu_to_le16(params->ie_len);
808 memcpy(cmd->assoc_ie, params->ie, params->ie_len);
809 }
810
811 if (params->privacy)
812 cmd->is_auth_open = 0;
813 else
814 cmd->is_auth_open = 1;
815
e58fd496 816 esp_info("Connection request: %s "MACSTR" %d\n",
817 cmd->ssid, MAC2STR(params->bssid), cmd->channel);
774e9b2e
MM
818
819 do {
820 bss = cfg80211_get_bss(adapter->wiphy, params->channel, params->bssid,
821 params->ssid, params->ssid_len, IEEE80211_BSS_TYPE_ESS, IEEE80211_PRIVACY_ANY);
822
823 if (bss) {
824 break;
825 } else {
6f8fee57 826 esp_info("No BSS in the list.. scanning..\n");
774e9b2e
MM
827 internal_scan_request(priv, cmd->ssid, cmd->channel, true);
828 }
829
830 retry--;
831 } while (retry);
832
833 if (retry) {
834 queue_cmd_node(adapter, cmd_node, ESP_CMD_DFLT_PRIO);
835 queue_work(adapter->cmd_wq, &adapter->cmd_work);
836
837 RET_ON_FAIL(wait_and_decode_cmd_resp(priv, cmd_node));
838 } else {
6f8fee57 839 esp_info("Failed to find %s\n", cmd->ssid);
774e9b2e
MM
840 return -EFAULT;
841 }
842
843 return 0;
844}
bd131325 845#endif
774e9b2e 846
7b6ed49e
MM
847
848int cmd_assoc_request(struct esp_wifi_device *priv,
849 struct cfg80211_assoc_request *req)
850{
851 struct command_node *cmd_node = NULL;
852 struct cmd_sta_assoc *cmd;
853 struct cfg80211_bss *bss;
854 struct esp_adapter *adapter = NULL;
855 u16 cmd_len;
856
857 if (!priv || !req || !req->bss || !priv->adapter) {
6f8fee57 858 esp_err("Invalid argument\n");
7b6ed49e
MM
859 return -EINVAL;
860 }
861
862 if (test_bit(ESP_CLEANUP_IN_PROGRESS, &priv->adapter->state_flags)) {
6f8fee57 863 esp_err("%u cleanup in progress, return failure", __LINE__);
7b6ed49e
MM
864 return -EFAULT;
865 }
866
867 bss = req->bss;
868 adapter = priv->adapter;
869
870 cmd_len = sizeof(struct cmd_sta_assoc) + req->ie_len;
871
872 cmd_node = prepare_command_request(adapter, CMD_STA_ASSOC, cmd_len);
873
874 if (!cmd_node) {
6f8fee57 875 esp_err("Failed to get command node\n");
7b6ed49e
MM
876 return -ENOMEM;
877 }
878
879 cmd = (struct cmd_sta_assoc *) (cmd_node->cmd_skb->data + sizeof(struct esp_payload_header));
880
881 cmd->assoc_ie_len = req->ie_len;
882 memcpy(cmd->assoc_ie, req->ie, req->ie_len);
883
884 /* Make a copy of assoc req IEs */
bd131325 885 if (priv->assoc_req_ie) {
7b6ed49e 886 kfree(priv->assoc_req_ie);
bd131325
YM
887 priv->assoc_req_ie = NULL;
888 }
7b6ed49e
MM
889
890 priv->assoc_req_ie = kmemdup(req->ie, req->ie_len, GFP_ATOMIC);
891
892 if (!priv->assoc_req_ie) {
a3829bf3 893 esp_err("Failed to allocate buffer for assoc request IEs\n");
7b6ed49e
MM
894 return -ENOMEM;
895 }
896
897 priv->assoc_req_ie_len = req->ie_len;
898
e58fd496 899 esp_info("Association request: "MACSTR" %d %d\n",
900 MAC2STR(bss->bssid), bss->channel->hw_value, cmd->assoc_ie_len);
7b6ed49e
MM
901
902 queue_cmd_node(adapter, cmd_node, ESP_CMD_DFLT_PRIO);
903 queue_work(adapter->cmd_wq, &adapter->cmd_work);
904
905 RET_ON_FAIL(wait_and_decode_cmd_resp(priv, cmd_node));
906
907 return 0;
908}
909
910int cmd_auth_request(struct esp_wifi_device *priv,
911 struct cfg80211_auth_request *req)
912{
913 struct command_node *cmd_node = NULL;
914 struct cmd_sta_auth *cmd;
bd131325
YM
915 struct cfg80211_bss *bss;
916 /*struct cfg80211_bss *bss1;*/
7b6ed49e
MM
917 struct esp_adapter *adapter = NULL;
918 u16 cmd_len;
bd131325 919 /* u8 retry = 2; */
7b6ed49e
MM
920
921 if (!priv || !req || !req->bss || !priv->adapter) {
6f8fee57 922 esp_err("Invalid argument\n");
7b6ed49e
MM
923 return -EINVAL;
924 }
925
926 if (test_bit(ESP_CLEANUP_IN_PROGRESS, &priv->adapter->state_flags)) {
6f8fee57 927 esp_err(":%u cleanup in progress, return failure", __LINE__);
7b6ed49e
MM
928 return -EFAULT;
929 }
930
931 bss = req->bss;
932
933 priv->bss = req->bss;
934
935 adapter = priv->adapter;
936
937 cmd_len = sizeof(struct cmd_sta_auth) + req->auth_data_len;
938
939 cmd_node = prepare_command_request(adapter, CMD_STA_AUTH, cmd_len);
940
941 if (!cmd_node) {
6f8fee57 942 esp_err("Failed to get command node\n");
7b6ed49e
MM
943 return -ENOMEM;
944 }
945 cmd = (struct cmd_sta_auth *) (cmd_node->cmd_skb->data + sizeof(struct esp_payload_header));
946
947 memcpy(cmd->bssid, bss->bssid, MAC_ADDR_LEN);
948 cmd->channel = bss->channel->hw_value;
949 cmd->auth_type = req->auth_type;
950 cmd->auth_data_len = req->auth_data_len;
951 memcpy(cmd->auth_data, req->auth_data, req->auth_data_len);
952
5d6c5617
KG
953 if (req->key_len) {
954 memcpy(cmd->key, req->key, req->key_len);
955 cmd->key_len = req->key_len;
956 }
e58fd496 957 esp_info("Authentication request: "MACSTR" %d %d %d %d\n",
958 MAC2STR(cmd->bssid), cmd->channel, cmd->auth_type, cmd->auth_data_len,
7b6ed49e
MM
959 (u32) req->ie_len);
960#if 0
961 do {
962 bss1 = cfg80211_get_bss(adapter->wiphy, bss->channel, bss->bssid,
963 NULL, 0, IEEE80211_BSS_TYPE_ESS, IEEE80211_PRIVACY_ANY);
964
965 if (bss1) {
966 break;
967 } else {
6f8fee57 968 esp_info("No BSS in the list.. scanning..\n");
7b6ed49e
MM
969 internal_scan_request(priv, cmd->ssid, cmd->channel, true);
970 }
971
972 retry--;
973 } while (retry);
974#endif
975 queue_cmd_node(adapter, cmd_node, ESP_CMD_DFLT_PRIO);
976 queue_work(adapter->cmd_wq, &adapter->cmd_work);
977
978 RET_ON_FAIL(wait_and_decode_cmd_resp(priv, cmd_node));
979
980 return 0;
981}
982
774e9b2e
MM
983int cmd_set_default_key(struct esp_wifi_device *priv, u8 key_index)
984{
985 u16 cmd_len;
986 struct command_node *cmd_node = NULL;
987 struct cmd_key_operation *cmd;
a3829bf3 988 struct wifi_sec_key *key = NULL;
774e9b2e
MM
989
990 if (!priv || !priv->adapter) {
6f8fee57 991 esp_err("Invalid argument\n");
774e9b2e
MM
992 return -EINVAL;
993 }
994
995#if 0
996 if (key_index > ESP_MAX_KEY_INDEX) {
6f8fee57 997 esp_err("invalid key index[%u] > max[%u]\n",
774e9b2e
MM
998 key_index, ESP_MAX_KEY_INDEX);
999 return -EINVAL;
1000 }
1001#endif
1002 if (test_bit(ESP_CLEANUP_IN_PROGRESS, &priv->adapter->state_flags)) {
6f8fee57 1003 esp_err(":%u cleanup in progress, return", __LINE__);
774e9b2e
MM
1004 return 0;
1005 }
1006
774e9b2e
MM
1007 cmd_len = sizeof(struct cmd_key_operation);
1008
1009 /* get new cmd node */
1010 cmd_node = prepare_command_request(priv->adapter, CMD_SET_DEFAULT_KEY, cmd_len);
1011 if (!cmd_node) {
6f8fee57 1012 esp_err("Failed to get command node\n");
774e9b2e
MM
1013 return -ENOMEM;
1014 }
1015
1016 /* cmd specific update */
1017 cmd = (struct cmd_key_operation *) (cmd_node->cmd_skb->data +
1018 sizeof(struct esp_payload_header));
1019 key = &cmd->key;
1020
1021 key->index = key_index;
1022 key->set_cur = 1;
1023
1024 queue_cmd_node(priv->adapter, cmd_node, ESP_CMD_DFLT_PRIO);
1025 queue_work(priv->adapter->cmd_wq, &priv->adapter->cmd_work);
1026
1027 RET_ON_FAIL(wait_and_decode_cmd_resp(priv, cmd_node));
1028
1029 return 0;
1030}
1031
1032int cmd_del_key(struct esp_wifi_device *priv, u8 key_index, bool pairwise,
1033 const u8 *mac_addr)
1034{
1035 u16 cmd_len;
1036 struct command_node *cmd_node = NULL;
1037 struct cmd_key_operation *cmd;
a3829bf3 1038 struct wifi_sec_key *key = NULL;
774e9b2e
MM
1039 const u8 *mac = NULL;
1040 const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
1041
1042 if (!priv || !priv->adapter) {
6f8fee57 1043 esp_err("Invalid argument\n");
774e9b2e
MM
1044 return -EINVAL;
1045 }
1046
1047 if (test_bit(ESP_CLEANUP_IN_PROGRESS, &priv->adapter->state_flags))
1048 return 0;
1049
1050#if 0
1051 if (key_index > ESP_MAX_KEY_INDEX) {
6f8fee57 1052 esp_err("invalid key index[%u] > max[%u]\n",
774e9b2e
MM
1053 key_index, ESP_MAX_KEY_INDEX);
1054 return -EINVAL;
1055 }
1056#endif
1057
1058 mac = pairwise ? mac_addr : bc_mac;
774e9b2e
MM
1059
1060 cmd_len = sizeof(struct cmd_key_operation);
1061
1062 /* get new cmd node */
1063 cmd_node = prepare_command_request(priv->adapter, CMD_DEL_KEY, cmd_len);
1064 if (!cmd_node) {
6f8fee57 1065 esp_err("Failed to get command node\n");
774e9b2e
MM
1066 return -ENOMEM;
1067 }
1068
1069 /* cmd specific update */
1070 cmd = (struct cmd_key_operation *) (cmd_node->cmd_skb->data +
1071 sizeof(struct esp_payload_header));
1072 key = &cmd->key;
1073
1074 if (mac && !is_multicast_ether_addr(mac))
1075 memcpy((char *)&key->mac_addr, (void *)mac, MAC_ADDR_LEN);
1076
1077 key->index = key_index;
1078 key->del = 1;
1079
1080 queue_cmd_node(priv->adapter, cmd_node, ESP_CMD_DFLT_PRIO);
1081 queue_work(priv->adapter->cmd_wq, &priv->adapter->cmd_work);
1082
1083 RET_ON_FAIL(wait_and_decode_cmd_resp(priv, cmd_node));
1084
1085 return 0;
1086}
1087
1088int cmd_add_key(struct esp_wifi_device *priv, u8 key_index, bool pairwise,
1089 const u8 *mac_addr, struct key_params *params)
1090{
1091 u16 cmd_len;
1092 struct command_node *cmd_node = NULL;
1093 struct cmd_key_operation *cmd;
a3829bf3 1094 struct wifi_sec_key *key = NULL;
774e9b2e
MM
1095 const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
1096 const u8 *mac = NULL;
1097
1098#if 0
e58fd496 1099 esp_info("%u key_idx: %u pairwise: %u params->key_len: %u\nparams->seq_len:%u params->mode: 0x%x\nparams->cipher: 0x%x\n",
6f8fee57 1100 __LINE__,
774e9b2e
MM
1101 key_index, pairwise, params->key_len, params->seq_len, params->mode, params->cipher);
1102#endif
1103 if (!priv || !priv->adapter || !params ||
1104 !params->key || !params->key_len || !params->seq_len) {
6f8fee57 1105 esp_err("Invalid argument\n");
774e9b2e
MM
1106 return -EINVAL;
1107 }
1108
1109#if 0
1110 if (key_index > ESP_MAX_KEY_INDEX) {
6f8fee57 1111 esp_err("invalid key index[%u] > max[%u]\n",
774e9b2e
MM
1112 key_index, ESP_MAX_KEY_INDEX);
1113 return -EINVAL;
1114 }
1115#endif
1116
1117 if (params->key_len > sizeof(key->data)) {
6f8fee57 1118 esp_err("Too long key length (%u)\n", params->key_len);
774e9b2e
MM
1119 return -EINVAL;
1120 }
1121
1122 if (params->seq_len > sizeof(key->seq)) {
6f8fee57 1123 esp_err("Too long key seq length (%u)\n", params->seq_len);
774e9b2e
MM
1124 return -EINVAL;
1125 }
1126
1127 if (test_bit(ESP_CLEANUP_IN_PROGRESS, &priv->adapter->state_flags)) {
6f8fee57 1128 esp_err("%u cleanup in progress, return failure", __LINE__);
774e9b2e
MM
1129 return -EFAULT;
1130 }
1131
1132 mac = pairwise ? mac_addr : bc_mac;
1133 if (mac) {
5a47b073 1134#if 0
774e9b2e
MM
1135 print_hex_dump(KERN_INFO, "mac: ", DUMP_PREFIX_ADDRESS, 16, 1,
1136 mac, MAC_ADDR_LEN, 1);
5a47b073 1137#endif
774e9b2e
MM
1138 }
1139
1140 cmd_len = sizeof(struct cmd_key_operation);
1141
1142 cmd_node = prepare_command_request(priv->adapter, CMD_ADD_KEY, cmd_len);
1143 if (!cmd_node) {
6f8fee57 1144 esp_err("Failed to get command node\n");
774e9b2e
MM
1145 return -ENOMEM;
1146 }
1147
1148 cmd = (struct cmd_key_operation *) (cmd_node->cmd_skb->data +
1149 sizeof(struct esp_payload_header));
1150 key = &cmd->key;
1151
1152 if (mac && !is_multicast_ether_addr(mac))
1153 memcpy((char *)&key->mac_addr, (void *)mac, MAC_ADDR_LEN);
1154
1155 key->index = key_index;
1156
1157 key->len = params->key_len;
1158 if (params->key && key->len)
1159 memcpy(key->data, params->key, key->len);
1160
1161 key->seq_len = params->seq_len;
1162 if (params->seq && key->seq_len)
1163 memcpy(key->seq, params->seq, key->seq_len);
1164
774e9b2e
MM
1165 key->algo = wpa_cipher_to_alg(params->cipher);
1166#if 0
1167 if (key->algo == WIFI_WPA_ALG_NONE) {
e58fd496 1168 esp_info("CIPHER NONE does not use pairwise keys\n");
774e9b2e
MM
1169 return 0;
1170 }
1171#endif
1172
99fc102b
SS
1173 /* Supplicant swaps tx/rx Mic keys whereas esp needs it normal format */
1174 if (key->algo == WIFI_WPA_ALG_TKIP && !key->index) {
1175 u8 buf[8];
1176 memcpy(buf, &key->data[16], 8);
1177 memcpy(&key->data[16], &key->data[24], 8);
1178 memcpy(&key->data[24], buf, 8);
1179 memset(buf, 0, 8);
1180 }
1181
774e9b2e 1182#if 0
a3829bf3 1183 esp_err("%u algo: %u idx: %u seq_len: %u len:%u\n", __LINE__,
9ea97217 1184 key->algo, key->index, key->seq_len, key->len);
774e9b2e
MM
1185 PRINT_HEXDUMP("mac", key->mac_addr, 6, ESP_LOG_INFO);
1186 PRINT_HEXDUMP("seq", key->seq, key->seq_len, ESP_LOG_INFO);
1187 PRINT_HEXDUMP("key_data", key->data, key->len, ESP_LOG_INFO);
1188#endif
1189
1190 queue_cmd_node(priv->adapter, cmd_node, ESP_CMD_DFLT_PRIO);
1191 queue_work(priv->adapter->cmd_wq, &priv->adapter->cmd_work);
1192
1193 RET_ON_FAIL(wait_and_decode_cmd_resp(priv, cmd_node));
1194
1195 return 0;
1196}
1197
1198int cmd_init_interface(struct esp_wifi_device *priv)
1199{
1200 u16 cmd_len;
1201 struct command_node *cmd_node = NULL;
1202
1203 if (!priv || !priv->adapter) {
6f8fee57 1204 esp_err("Invalid argument\n");
774e9b2e
MM
1205 return -EINVAL;
1206 }
1207
1208 cmd_len = sizeof(struct command_header);
1209
1210 cmd_node = prepare_command_request(priv->adapter, CMD_INIT_INTERFACE, cmd_len);
1211
1212 if (!cmd_node) {
6f8fee57 1213 esp_err("Failed to get command node\n");
774e9b2e
MM
1214 return -ENOMEM;
1215 }
1216
1217 queue_cmd_node(priv->adapter, cmd_node, ESP_CMD_DFLT_PRIO);
1218 queue_work(priv->adapter->cmd_wq, &priv->adapter->cmd_work);
1219
1220 RET_ON_FAIL(wait_and_decode_cmd_resp(priv, cmd_node));
1221
1222 return 0;
1223}
1224
1225int cmd_deinit_interface(struct esp_wifi_device *priv)
1226{
1227 u16 cmd_len;
1228 struct command_node *cmd_node = NULL;
1229
1230 if (!priv || !priv->adapter)
1231 return -EINVAL;
1232
1233 if (test_bit(ESP_CLEANUP_IN_PROGRESS, &priv->adapter->state_flags)) {
6f8fee57 1234 esp_err("%u cleanup in progress, return\n", __LINE__);
774e9b2e
MM
1235 return 0;
1236 }
1237
1238 cmd_len = sizeof(struct command_header);
1239
1240 cmd_node = prepare_command_request(priv->adapter, CMD_DEINIT_INTERFACE, cmd_len);
1241
1242 if (!cmd_node) {
6f8fee57 1243 esp_err("Failed to get command node\n");
774e9b2e
MM
1244 return -ENOMEM;
1245 }
1246
1247 queue_cmd_node(priv->adapter, cmd_node, ESP_CMD_DFLT_PRIO);
1248 queue_work(priv->adapter->cmd_wq, &priv->adapter->cmd_work);
1249
1250 RET_ON_FAIL(wait_and_decode_cmd_resp(priv, cmd_node));
1251
1252 return 0;
1253}
1254
a3829bf3 1255int internal_scan_request(struct esp_wifi_device *priv, char *ssid,
774e9b2e
MM
1256 uint8_t channel, uint8_t is_blocking)
1257{
1258 int ret = 0;
1259 u16 cmd_len;
1260 struct command_node *cmd_node = NULL;
1261 struct scan_request *scan_req;
1262
1263 if (!priv || !priv->adapter) {
6f8fee57 1264 esp_err("Invalid argument\n");
774e9b2e
MM
1265 return -EINVAL;
1266 }
1267
1268 if (priv->scan_in_progress) {
6f8fee57 1269 esp_err("Scan in progress.. return\n");
774e9b2e
MM
1270 return -EBUSY;
1271 }
1272
1273 if (test_bit(ESP_CLEANUP_IN_PROGRESS, &priv->adapter->state_flags)) {
6f8fee57 1274 esp_err("%u cleanup in progress, return", __LINE__);
059da5be 1275 return -EBUSY;
774e9b2e
MM
1276 }
1277
1278 cmd_len = sizeof(struct scan_request);
1279
1280 cmd_node = prepare_command_request(priv->adapter, CMD_SCAN_REQUEST, cmd_len);
1281
1282 if (!cmd_node) {
6f8fee57 1283 esp_err("Failed to get command node\n");
774e9b2e
MM
1284 return -ENOMEM;
1285 }
1286
1287 scan_req = (struct scan_request *) (cmd_node->cmd_skb->data +
1288 sizeof(struct esp_payload_header));
1289
1290 if (ssid) {
1291 memcpy(scan_req->ssid, ssid, MAX_SSID_LEN);
1292 }
1293
1294 scan_req->channel = channel;
1295
1296 priv->scan_in_progress = true;
1297
1298 if (is_blocking)
1299 priv->waiting_for_scan_done = true;
1300
1301 /* Enqueue command */
1302 queue_cmd_node(priv->adapter, cmd_node, ESP_CMD_DFLT_PRIO);
1303 queue_work(priv->adapter->cmd_wq, &priv->adapter->cmd_work);
1304
1305 ret = wait_and_decode_cmd_resp(priv, cmd_node);
1306
1307 if (!ret && is_blocking) {
1308 /* Wait for scan done */
1309 wait_event_interruptible_timeout(priv->wait_for_scan_completion,
1310 priv->waiting_for_scan_done != true, COMMAND_RESPONSE_TIMEOUT);
1311 }
1312
1313 return ret;
1314}
1315
1316int cmd_scan_request(struct esp_wifi_device *priv, struct cfg80211_scan_request *request)
1317{
1318 u16 cmd_len;
1319 struct command_node *cmd_node = NULL;
1320 struct scan_request *scan_req;
1321
1322 if (!priv || !priv->adapter || !request) {
6f8fee57 1323 esp_err("Invalid argument\n");
774e9b2e
MM
1324 return -EINVAL;
1325 }
1326
1327 if (test_bit(ESP_CLEANUP_IN_PROGRESS, &priv->adapter->state_flags)) {
6f8fee57 1328 esp_err("%u cleanup in progress, return", __LINE__);
059da5be 1329 return -EBUSY;
774e9b2e
MM
1330 }
1331
774e9b2e 1332 if (priv->scan_in_progress || priv->request) {
6f8fee57 1333 esp_err("Scan in progress.. return\n");
774e9b2e
MM
1334 return -EBUSY;
1335 }
1336
1337 cmd_len = sizeof(struct scan_request);
1338
1339 cmd_node = prepare_command_request(priv->adapter, CMD_SCAN_REQUEST, cmd_len);
1340
1341 if (!cmd_node) {
6f8fee57 1342 esp_err("Failed to get command node\n");
774e9b2e
MM
1343 return -ENOMEM;
1344 }
1345
1346 scan_req = (struct scan_request *) (cmd_node->cmd_skb->data +
1347 sizeof(struct esp_payload_header));
1348
1349 /* TODO: Handle case of multiple SSIDs or channels */
a3829bf3 1350 if (request->ssids && request->ssids[0].ssid_len) {
774e9b2e
MM
1351 memcpy(scan_req->ssid, request->ssids[0].ssid, MAX_SSID_LEN);
1352 }
1353
1354#if 0
1355 if (request->n_channels) {
1356 chan = request->channels[0];
1357 scan_req->channel = chan->hw_value;
1358 }
1359#endif
1360
aad2ae2e 1361#if LINUX_VERSION_CODE > KERNEL_VERSION(4, 8, 0)
774e9b2e 1362 scan_req->duration = request->duration;
aad2ae2e
YM
1363#endif
1364#if LINUX_VERSION_CODE > KERNEL_VERSION(4, 7, 0)
774e9b2e 1365 memcpy(scan_req->bssid, request->bssid, MAC_ADDR_LEN);
aad2ae2e 1366#endif
774e9b2e
MM
1367
1368 priv->scan_in_progress = true;
1369 priv->request = request;
1370
1371 queue_cmd_node(priv->adapter, cmd_node, ESP_CMD_DFLT_PRIO);
1372 queue_work(priv->adapter->cmd_wq, &priv->adapter->cmd_work);
1373
1374 RET_ON_FAIL(wait_and_decode_cmd_resp(priv, cmd_node));
1375
1376 return 0;
1377}
1378
1379
1380int cmd_get_mac(struct esp_wifi_device *priv)
1381{
1382 u16 cmd_len;
1383 struct command_node *cmd_node = NULL;
1384
1385 if (!priv || !priv->adapter) {
6f8fee57 1386 esp_err("Invalid argument\n");
774e9b2e
MM
1387 return -EINVAL;
1388 }
1389
1390 cmd_len = sizeof(struct command_header);
1391
1392 cmd_node = prepare_command_request(priv->adapter, CMD_GET_MAC, cmd_len);
1393
1394 if (!cmd_node) {
6f8fee57 1395 esp_err("Failed to get command node\n");
774e9b2e
MM
1396 return -ENOMEM;
1397 }
1398
1399 queue_cmd_node(priv->adapter, cmd_node, ESP_CMD_DFLT_PRIO);
1400 queue_work(priv->adapter->cmd_wq, &priv->adapter->cmd_work);
1401
1402 RET_ON_FAIL(wait_and_decode_cmd_resp(priv, cmd_node));
1403
1404 return 0;
1405}
1406
98f8ece9
KG
1407int cmd_set_mac(struct esp_wifi_device *priv, uint8_t *mac_addr)
1408{
1409 u16 cmd_len;
1410 struct command_node *cmd_node = NULL;
1411 struct cmd_config_mac_address *cmd;;
1412
1413 if (!priv || !priv->adapter) {
1414 esp_err("Invalid argument\n");
1415 return -EINVAL;
1416 }
1417
1418 cmd_len = sizeof(struct cmd_config_mac_address);
1419
1420 cmd_node = prepare_command_request(priv->adapter, CMD_SET_MAC, cmd_len);
1421
1422 if (!cmd_node) {
1423 esp_err("Failed to get command node\n");
1424 return -ENOMEM;
1425 }
1426
1427 cmd = (struct cmd_config_mac_address *) (cmd_node->cmd_skb->data +
1428 sizeof(struct esp_payload_header));
1429
1430 memcpy(cmd->mac_addr, mac_addr, MAC_ADDR_LEN);
1431 queue_cmd_node(priv->adapter, cmd_node, ESP_CMD_DFLT_PRIO);
1432 queue_work(priv->adapter->cmd_wq, &priv->adapter->cmd_work);
1433
1434 RET_ON_FAIL(wait_and_decode_cmd_resp(priv, cmd_node));
1435
1436 return 0;
1437}
774e9b2e 1438
225e14eb 1439int esp_commands_teardown(struct esp_adapter *adapter)
774e9b2e
MM
1440{
1441#define MAX_DEINIT_RETRY 5
1442 uint8_t iface_idx = 0;
225e14eb 1443 struct esp_wifi_device *priv = NULL;
774e9b2e 1444
a3829bf3
KG
1445 if (!adapter) {
1446 return -EINVAL;
774e9b2e
MM
1447 }
1448
1449 set_bit(ESP_CLEANUP_IN_PROGRESS, &adapter->state_flags);
1450
1451 if (!test_bit(ESP_CMD_INIT_DONE, &adapter->state_flags))
1452 return 0;
1453
774e9b2e 1454
a3829bf3 1455 for (iface_idx = 0; iface_idx < ESP_MAX_INTERFACE; iface_idx++) {
774e9b2e 1456
225e14eb 1457 priv = adapter->priv[iface_idx];
774e9b2e 1458
225e14eb
YM
1459 if (!priv)
1460 continue;
774e9b2e 1461
225e14eb
YM
1462 esp_mark_scan_done_and_disconnect(priv, false);
1463
1464 esp_port_close(priv);
1465 }
774e9b2e 1466
a3829bf3
KG
1467 destroy_cmd_wq(adapter);
1468 free_esp_cmd_pool(adapter);
774e9b2e 1469
a3829bf3 1470 return 0;
774e9b2e
MM
1471}
1472
225e14eb 1473int esp_commands_setup(struct esp_adapter *adapter)
774e9b2e
MM
1474{
1475 if (!adapter) {
6f8fee57 1476 esp_err("no adapter\n");
774e9b2e
MM
1477 return -EINVAL;
1478 }
1479
1480 init_waitqueue_head(&adapter->wait_for_cmd_resp);
1481
1482 spin_lock_init(&adapter->cmd_lock);
1483
1484 INIT_LIST_HEAD(&adapter->cmd_pending_queue);
1485 INIT_LIST_HEAD(&adapter->cmd_free_queue);
1486
1487 spin_lock_init(&adapter->cmd_pending_queue_lock);
1488 spin_lock_init(&adapter->cmd_free_queue_lock);
1489
1490 RET_ON_FAIL(create_cmd_wq(adapter));
1491
1492 RET_ON_FAIL(alloc_esp_cmd_pool(adapter));
1493
1494 set_bit(ESP_CMD_INIT_DONE, &adapter->state_flags);
1495 return 0;
1496}
1497
9726a3d0
KG
1498int cmd_set_tx_power(struct esp_wifi_device *priv, int power)
1499{
1500 u16 cmd_len;
1501 struct command_node *cmd_node = NULL;
1502 struct cmd_set_get_val *val;;
1503
1504 if (!priv || !priv->adapter) {
1505 esp_err("Invalid argument\n");
1506 return -EINVAL;
1507 }
1508
1509 cmd_len = sizeof(struct cmd_set_get_val);
1510
1511 cmd_node = prepare_command_request(priv->adapter, CMD_SET_TXPOWER, cmd_len);
1512
1513 if (!cmd_node) {
1514 esp_err("Failed to get command node\n");
1515 return -ENOMEM;
1516 }
1517
1518 val = (struct cmd_set_get_val *) (cmd_node->cmd_skb->data +
1519 sizeof(struct esp_payload_header));
1520
1521 val->value = power;
1522
1523 queue_cmd_node(priv->adapter, cmd_node, ESP_CMD_DFLT_PRIO);
1524 queue_work(priv->adapter->cmd_wq, &priv->adapter->cmd_work);
1525
1526 RET_ON_FAIL(wait_and_decode_cmd_resp(priv, cmd_node));
1527
1528 return 0;
1529}
1530
1531int cmd_get_tx_power(struct esp_wifi_device *priv)
1532{
1533 u16 cmd_len;
1534 struct command_node *cmd_node = NULL;
1535
1536 if (!priv || !priv->adapter) {
1537 esp_err("Invalid argument\n");
1538 return -EINVAL;
1539 }
1540
1541 cmd_len = sizeof(struct command_header) + sizeof(int32_t);
1542
1543 cmd_node = prepare_command_request(priv->adapter, CMD_GET_TXPOWER, cmd_len);
1544
1545 if (!cmd_node) {
1546 esp_err("Failed to get command node\n");
1547 return -ENOMEM;
1548 }
1549
1550 queue_cmd_node(priv->adapter, cmd_node, ESP_CMD_DFLT_PRIO);
1551 queue_work(priv->adapter->cmd_wq, &priv->adapter->cmd_work);
1552
1553 RET_ON_FAIL(wait_and_decode_cmd_resp(priv, cmd_node));
1554
1555 return 0;
1556}
f7ac1df4
KG
1557
1558int cmd_get_reg_domain(struct esp_wifi_device *priv)
1559{
1560 u16 cmd_len;
1561 struct command_node *cmd_node = NULL;
1562
1563 if (!priv || !priv->adapter) {
1564 esp_err("Invalid argument\n");
1565 return -EINVAL;
1566 }
1567
1568 cmd_len = sizeof(struct cmd_reg_domain);
1569
1570 cmd_node = prepare_command_request(priv->adapter, CMD_GET_REG_DOMAIN, cmd_len);
1571
1572 if (!cmd_node) {
1573 esp_err("Failed to get command node\n");
1574 return -ENOMEM;
1575 }
1576
1577 queue_cmd_node(priv->adapter, cmd_node, ESP_CMD_DFLT_PRIO);
1578 queue_work(priv->adapter->cmd_wq, &priv->adapter->cmd_work);
1579
1580 RET_ON_FAIL(wait_and_decode_cmd_resp(priv, cmd_node));
1581
1582 return 0;
1583}
1584
1585int cmd_set_reg_domain(struct esp_wifi_device *priv)
1586{
1587 u16 cmd_len;
1588 struct command_node *cmd_node = NULL;
1589 struct cmd_reg_domain *cmd;
1590
1591 if (!priv || !priv->adapter) {
1592 esp_err("Invalid argument\n");
1593 return -EINVAL;
1594 }
1595
1596 cmd_len = sizeof(struct cmd_reg_domain);
1597
1598 cmd_node = prepare_command_request(priv->adapter, CMD_SET_REG_DOMAIN, cmd_len);
1599
1600 if (!cmd_node) {
1601 esp_err("Failed to get command node\n");
1602 return -ENOMEM;
1603 }
1604
1605 cmd = (struct cmd_reg_domain *) (cmd_node->cmd_skb->data + sizeof(struct esp_payload_header));
1606
1607 strlcpy(cmd->country_code, priv->country_code, MAX_COUNTRY_LEN);
1608
1609 queue_cmd_node(priv->adapter, cmd_node, ESP_CMD_DFLT_PRIO);
1610 queue_work(priv->adapter->cmd_wq, &priv->adapter->cmd_work);
1611
1612 RET_ON_FAIL(wait_and_decode_cmd_resp(priv, cmd_node));
1613
1614 return 0;
1615}
This page took 0.270772 seconds and 4 git commands to generate.