mwifiex: cleanup ioctl wait queue and abstraction layer
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / net / wireless / mwifiex / sta_cmdresp.c
blob8743c116bee539026619c71bd7077a0ff343406f
1 /*
2 * Marvell Wireless LAN device driver: station command response handling
4 * Copyright (C) 2011, Marvell International Ltd.
6 * This software file (the "File") is distributed by Marvell International
7 * Ltd. under the terms of the GNU General Public License Version 2, June 1991
8 * (the "License"). You may use, redistribute and/or modify this File in
9 * accordance with the terms and conditions of the License, a copy of which
10 * is available by writing to the Free Software Foundation, Inc.,
11 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
12 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
14 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
16 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
17 * this warranty disclaimer.
20 #include "decl.h"
21 #include "ioctl.h"
22 #include "util.h"
23 #include "fw.h"
24 #include "main.h"
25 #include "wmm.h"
26 #include "11n.h"
30 * This function handles the command response error case.
32 * For scan response error, the function cancels all the pending
33 * scan commands and generates an event to inform the applications
34 * of the scan completion.
36 * For Power Save command failure, we do not retry enter PS
37 * command in case of Ad-hoc mode.
39 * For all other response errors, the current command buffer is freed
40 * and returned to the free command queue.
42 static void
43 mwifiex_process_cmdresp_error(struct mwifiex_private *priv,
44 struct host_cmd_ds_command *resp)
46 struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL;
47 struct mwifiex_adapter *adapter = priv->adapter;
48 struct host_cmd_ds_802_11_ps_mode_enh *pm;
49 unsigned long flags;
51 dev_err(adapter->dev, "CMD_RESP: cmd %#x error, result=%#x\n",
52 resp->command, resp->result);
54 if (adapter->curr_cmd->wait_q_enabled)
55 adapter->cmd_wait_q.status = -1;
57 switch (le16_to_cpu(resp->command)) {
58 case HostCmd_CMD_802_11_PS_MODE_ENH:
59 pm = &resp->params.psmode_enh;
60 dev_err(adapter->dev, "PS_MODE_ENH cmd failed: "
61 "result=0x%x action=0x%X\n",
62 resp->result, le16_to_cpu(pm->action));
63 /* We do not re-try enter-ps command in ad-hoc mode. */
64 if (le16_to_cpu(pm->action) == EN_AUTO_PS &&
65 (le16_to_cpu(pm->params.ps_bitmap) & BITMAP_STA_PS) &&
66 priv->bss_mode == NL80211_IFTYPE_ADHOC)
67 adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM;
69 break;
70 case HostCmd_CMD_802_11_SCAN:
71 /* Cancel all pending scan command */
72 spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
73 list_for_each_entry_safe(cmd_node, tmp_node,
74 &adapter->scan_pending_q, list) {
75 list_del(&cmd_node->list);
76 spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
77 flags);
78 mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
79 spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
81 spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
83 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
84 adapter->scan_processing = false;
85 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
86 if (priv->report_scan_result)
87 priv->report_scan_result = false;
88 if (priv->scan_pending_on_block) {
89 priv->scan_pending_on_block = false;
90 up(&priv->async_sem);
92 break;
94 case HostCmd_CMD_MAC_CONTROL:
95 break;
97 default:
98 break;
100 /* Handling errors here */
101 mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd);
103 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
104 adapter->curr_cmd = NULL;
105 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
107 return;
111 * This function handles the command response of get RSSI info.
113 * Handling includes changing the header fields into CPU format
114 * and saving the following parameters in driver -
115 * - Last data and beacon RSSI value
116 * - Average data and beacon RSSI value
117 * - Last data and beacon NF value
118 * - Average data and beacon NF value
120 * The parameters are send to the application as well, along with
121 * calculated SNR values.
123 static int mwifiex_ret_802_11_rssi_info(struct mwifiex_private *priv,
124 struct host_cmd_ds_command *resp,
125 void *data_buf)
127 struct host_cmd_ds_802_11_rssi_info_rsp *rssi_info_rsp =
128 &resp->params.rssi_info_rsp;
129 struct mwifiex_ds_get_signal *signal = NULL;
131 priv->data_rssi_last = le16_to_cpu(rssi_info_rsp->data_rssi_last);
132 priv->data_nf_last = le16_to_cpu(rssi_info_rsp->data_nf_last);
134 priv->data_rssi_avg = le16_to_cpu(rssi_info_rsp->data_rssi_avg);
135 priv->data_nf_avg = le16_to_cpu(rssi_info_rsp->data_nf_avg);
137 priv->bcn_rssi_last = le16_to_cpu(rssi_info_rsp->bcn_rssi_last);
138 priv->bcn_nf_last = le16_to_cpu(rssi_info_rsp->bcn_nf_last);
140 priv->bcn_rssi_avg = le16_to_cpu(rssi_info_rsp->bcn_rssi_avg);
141 priv->bcn_nf_avg = le16_to_cpu(rssi_info_rsp->bcn_nf_avg);
143 /* Need to indicate IOCTL complete */
144 if (data_buf) {
145 signal = (struct mwifiex_ds_get_signal *) data_buf;
146 memset(signal, 0, sizeof(struct mwifiex_ds_get_signal));
148 signal->selector = ALL_RSSI_INFO_MASK;
150 /* RSSI */
151 signal->bcn_rssi_last = priv->bcn_rssi_last;
152 signal->bcn_rssi_avg = priv->bcn_rssi_avg;
153 signal->data_rssi_last = priv->data_rssi_last;
154 signal->data_rssi_avg = priv->data_rssi_avg;
156 /* SNR */
157 signal->bcn_snr_last =
158 CAL_SNR(priv->bcn_rssi_last, priv->bcn_nf_last);
159 signal->bcn_snr_avg =
160 CAL_SNR(priv->bcn_rssi_avg, priv->bcn_nf_avg);
161 signal->data_snr_last =
162 CAL_SNR(priv->data_rssi_last, priv->data_nf_last);
163 signal->data_snr_avg =
164 CAL_SNR(priv->data_rssi_avg, priv->data_nf_avg);
166 /* NF */
167 signal->bcn_nf_last = priv->bcn_nf_last;
168 signal->bcn_nf_avg = priv->bcn_nf_avg;
169 signal->data_nf_last = priv->data_nf_last;
170 signal->data_nf_avg = priv->data_nf_avg;
173 return 0;
177 * This function handles the command response of set/get SNMP
178 * MIB parameters.
180 * Handling includes changing the header fields into CPU format
181 * and saving the parameter in driver.
183 * The following parameters are supported -
184 * - Fragmentation threshold
185 * - RTS threshold
186 * - Short retry limit
188 static int mwifiex_ret_802_11_snmp_mib(struct mwifiex_private *priv,
189 struct host_cmd_ds_command *resp,
190 void *data_buf)
192 struct host_cmd_ds_802_11_snmp_mib *smib = &resp->params.smib;
193 u16 oid = le16_to_cpu(smib->oid);
194 u16 query_type = le16_to_cpu(smib->query_type);
195 u32 ul_temp;
197 dev_dbg(priv->adapter->dev, "info: SNMP_RESP: oid value = %#x,"
198 " query_type = %#x, buf size = %#x\n",
199 oid, query_type, le16_to_cpu(smib->buf_size));
200 if (query_type == HostCmd_ACT_GEN_GET) {
201 ul_temp = le16_to_cpu(*((__le16 *) (smib->value)));
202 if (data_buf)
203 *(u32 *)data_buf = ul_temp;
204 switch (oid) {
205 case FRAG_THRESH_I:
206 dev_dbg(priv->adapter->dev,
207 "info: SNMP_RESP: FragThsd =%u\n", ul_temp);
208 break;
209 case RTS_THRESH_I:
210 dev_dbg(priv->adapter->dev,
211 "info: SNMP_RESP: RTSThsd =%u\n", ul_temp);
212 break;
213 case SHORT_RETRY_LIM_I:
214 dev_dbg(priv->adapter->dev,
215 "info: SNMP_RESP: TxRetryCount=%u\n", ul_temp);
216 break;
217 default:
218 break;
222 return 0;
226 * This function handles the command response of get log request
228 * Handling includes changing the header fields into CPU format
229 * and sending the received parameters to application.
231 static int mwifiex_ret_get_log(struct mwifiex_private *priv,
232 struct host_cmd_ds_command *resp,
233 void *data_buf)
235 struct host_cmd_ds_802_11_get_log *get_log =
236 (struct host_cmd_ds_802_11_get_log *) &resp->params.get_log;
237 struct mwifiex_ds_get_stats *stats = NULL;
239 if (data_buf) {
240 stats = (struct mwifiex_ds_get_stats *) data_buf;
241 stats->mcast_tx_frame = le32_to_cpu(get_log->mcast_tx_frame);
242 stats->failed = le32_to_cpu(get_log->failed);
243 stats->retry = le32_to_cpu(get_log->retry);
244 stats->multi_retry = le32_to_cpu(get_log->multi_retry);
245 stats->frame_dup = le32_to_cpu(get_log->frame_dup);
246 stats->rts_success = le32_to_cpu(get_log->rts_success);
247 stats->rts_failure = le32_to_cpu(get_log->rts_failure);
248 stats->ack_failure = le32_to_cpu(get_log->ack_failure);
249 stats->rx_frag = le32_to_cpu(get_log->rx_frag);
250 stats->mcast_rx_frame = le32_to_cpu(get_log->mcast_rx_frame);
251 stats->fcs_error = le32_to_cpu(get_log->fcs_error);
252 stats->tx_frame = le32_to_cpu(get_log->tx_frame);
253 stats->wep_icv_error[0] =
254 le32_to_cpu(get_log->wep_icv_err_cnt[0]);
255 stats->wep_icv_error[1] =
256 le32_to_cpu(get_log->wep_icv_err_cnt[1]);
257 stats->wep_icv_error[2] =
258 le32_to_cpu(get_log->wep_icv_err_cnt[2]);
259 stats->wep_icv_error[3] =
260 le32_to_cpu(get_log->wep_icv_err_cnt[3]);
263 return 0;
267 * This function handles the command response of set/get Tx rate
268 * configurations.
270 * Handling includes changing the header fields into CPU format
271 * and saving the following parameters in driver -
272 * - DSSS rate bitmap
273 * - OFDM rate bitmap
274 * - HT MCS rate bitmaps
276 * Based on the new rate bitmaps, the function re-evaluates if
277 * auto data rate has been activated. If not, it sends another
278 * query to the firmware to get the current Tx data rate and updates
279 * the driver value.
281 static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv,
282 struct host_cmd_ds_command *resp,
283 void *data_buf)
285 struct mwifiex_adapter *adapter = priv->adapter;
286 struct mwifiex_rate_cfg *ds_rate = NULL;
287 struct host_cmd_ds_tx_rate_cfg *rate_cfg = &resp->params.tx_rate_cfg;
288 struct mwifiex_rate_scope *rate_scope;
289 struct mwifiex_ie_types_header *head = NULL;
290 u16 tlv, tlv_buf_len;
291 u8 *tlv_buf;
292 u32 i;
293 int ret = 0;
295 tlv_buf = (u8 *) ((u8 *) rate_cfg) +
296 sizeof(struct host_cmd_ds_tx_rate_cfg);
297 tlv_buf_len = *(u16 *) (tlv_buf + sizeof(u16));
299 while (tlv_buf && tlv_buf_len > 0) {
300 tlv = (*tlv_buf);
301 tlv = tlv | (*(tlv_buf + 1) << 8);
303 switch (tlv) {
304 case TLV_TYPE_RATE_SCOPE:
305 rate_scope = (struct mwifiex_rate_scope *) tlv_buf;
306 priv->bitmap_rates[0] =
307 le16_to_cpu(rate_scope->hr_dsss_rate_bitmap);
308 priv->bitmap_rates[1] =
309 le16_to_cpu(rate_scope->ofdm_rate_bitmap);
310 for (i = 0;
312 sizeof(rate_scope->ht_mcs_rate_bitmap) /
313 sizeof(u16); i++)
314 priv->bitmap_rates[2 + i] =
315 le16_to_cpu(rate_scope->
316 ht_mcs_rate_bitmap[i]);
317 break;
318 /* Add RATE_DROP tlv here */
321 head = (struct mwifiex_ie_types_header *) tlv_buf;
322 tlv_buf += le16_to_cpu(head->len) + sizeof(*head);
323 tlv_buf_len -= le16_to_cpu(head->len);
326 priv->is_data_rate_auto = mwifiex_is_rate_auto(priv);
328 if (priv->is_data_rate_auto)
329 priv->data_rate = 0;
330 else
331 ret = mwifiex_send_cmd_async(priv,
332 HostCmd_CMD_802_11_TX_RATE_QUERY,
333 HostCmd_ACT_GEN_GET, 0, NULL);
335 if (data_buf) {
336 ds_rate = (struct mwifiex_rate_cfg *) data_buf;
337 if (le16_to_cpu(rate_cfg->action) == HostCmd_ACT_GEN_GET) {
338 if (priv->is_data_rate_auto) {
339 ds_rate->is_rate_auto = 1;
340 } else {
341 ds_rate->rate =
342 mwifiex_get_rate_index(adapter,
343 priv->
344 bitmap_rates,
345 sizeof(priv->
346 bitmap_rates));
347 if (ds_rate->rate >=
348 MWIFIEX_RATE_BITMAP_OFDM0
349 && ds_rate->rate <=
350 MWIFIEX_RATE_BITMAP_OFDM7)
351 ds_rate->rate -=
352 (MWIFIEX_RATE_BITMAP_OFDM0 -
353 MWIFIEX_RATE_INDEX_OFDM0);
354 if (ds_rate->rate >=
355 MWIFIEX_RATE_BITMAP_MCS0
356 && ds_rate->rate <=
357 MWIFIEX_RATE_BITMAP_MCS127)
358 ds_rate->rate -=
359 (MWIFIEX_RATE_BITMAP_MCS0 -
360 MWIFIEX_RATE_INDEX_MCS0);
365 return ret;
369 * This function handles the command response of get Tx power level.
371 * Handling includes saving the maximum and minimum Tx power levels
372 * in driver, as well as sending the values to user.
374 static int mwifiex_get_power_level(struct mwifiex_private *priv, void *data_buf)
376 int length = -1, max_power = -1, min_power = -1;
377 struct mwifiex_types_power_group *pg_tlv_hdr = NULL;
378 struct mwifiex_power_group *pg = NULL;
380 if (data_buf) {
381 pg_tlv_hdr =
382 (struct mwifiex_types_power_group *) ((u8 *) data_buf
383 + sizeof(struct host_cmd_ds_txpwr_cfg));
384 pg = (struct mwifiex_power_group *) ((u8 *) pg_tlv_hdr +
385 sizeof(struct mwifiex_types_power_group));
386 length = pg_tlv_hdr->length;
387 if (length > 0) {
388 max_power = pg->power_max;
389 min_power = pg->power_min;
390 length -= sizeof(struct mwifiex_power_group);
392 while (length) {
393 pg++;
394 if (max_power < pg->power_max)
395 max_power = pg->power_max;
397 if (min_power > pg->power_min)
398 min_power = pg->power_min;
400 length -= sizeof(struct mwifiex_power_group);
402 if (pg_tlv_hdr->length > 0) {
403 priv->min_tx_power_level = (u8) min_power;
404 priv->max_tx_power_level = (u8) max_power;
406 } else {
407 return -1;
410 return 0;
414 * This function handles the command response of set/get Tx power
415 * configurations.
417 * Handling includes changing the header fields into CPU format
418 * and saving the current Tx power level in driver.
420 static int mwifiex_ret_tx_power_cfg(struct mwifiex_private *priv,
421 struct host_cmd_ds_command *resp,
422 void *data_buf)
424 struct mwifiex_adapter *adapter = priv->adapter;
425 struct host_cmd_ds_txpwr_cfg *txp_cfg = &resp->params.txp_cfg;
426 struct mwifiex_types_power_group *pg_tlv_hdr = NULL;
427 struct mwifiex_power_group *pg = NULL;
428 u16 action = le16_to_cpu(txp_cfg->action);
430 switch (action) {
431 case HostCmd_ACT_GEN_GET:
433 pg_tlv_hdr =
434 (struct mwifiex_types_power_group *) ((u8 *)
435 txp_cfg +
436 sizeof
437 (struct
438 host_cmd_ds_txpwr_cfg));
439 pg = (struct mwifiex_power_group *) ((u8 *)
440 pg_tlv_hdr +
441 sizeof(struct
442 mwifiex_types_power_group));
443 if (adapter->hw_status ==
444 MWIFIEX_HW_STATUS_INITIALIZING)
445 mwifiex_get_power_level(priv, txp_cfg);
446 priv->tx_power_level = (u16) pg->power_min;
447 break;
449 case HostCmd_ACT_GEN_SET:
450 if (le32_to_cpu(txp_cfg->mode)) {
451 pg_tlv_hdr =
452 (struct mwifiex_types_power_group *) ((u8 *)
453 txp_cfg +
454 sizeof
455 (struct
456 host_cmd_ds_txpwr_cfg));
457 pg = (struct mwifiex_power_group *) ((u8 *) pg_tlv_hdr
459 sizeof(struct
460 mwifiex_types_power_group));
461 if (pg->power_max == pg->power_min)
462 priv->tx_power_level = (u16) pg->power_min;
464 break;
465 default:
466 dev_err(adapter->dev, "CMD_RESP: unknown cmd action %d\n",
467 action);
468 return 0;
470 dev_dbg(adapter->dev,
471 "info: Current TxPower Level = %d, Max Power=%d, Min Power=%d\n",
472 priv->tx_power_level, priv->max_tx_power_level,
473 priv->min_tx_power_level);
475 return 0;
479 * This function handles the command response of set/get MAC address.
481 * Handling includes saving the MAC address in driver.
483 static int mwifiex_ret_802_11_mac_address(struct mwifiex_private *priv,
484 struct host_cmd_ds_command *resp)
486 struct host_cmd_ds_802_11_mac_address *cmd_mac_addr =
487 &resp->params.mac_addr;
489 memcpy(priv->curr_addr, cmd_mac_addr->mac_addr, ETH_ALEN);
491 dev_dbg(priv->adapter->dev,
492 "info: set mac address: %pM\n", priv->curr_addr);
494 return 0;
498 * This function handles the command response of set/get MAC multicast
499 * address.
501 static int mwifiex_ret_mac_multicast_adr(struct mwifiex_private *priv,
502 struct host_cmd_ds_command *resp)
504 return 0;
508 * This function handles the command response of get Tx rate query.
510 * Handling includes changing the header fields into CPU format
511 * and saving the Tx rate and HT information parameters in driver.
513 * Both rate configuration and current data rate can be retrieved
514 * with this request.
516 static int mwifiex_ret_802_11_tx_rate_query(struct mwifiex_private *priv,
517 struct host_cmd_ds_command *resp)
519 struct mwifiex_adapter *adapter = priv->adapter;
521 priv->tx_rate = resp->params.tx_rate.tx_rate;
522 priv->tx_htinfo = resp->params.tx_rate.ht_info;
523 if (!priv->is_data_rate_auto)
524 priv->data_rate =
525 mwifiex_index_to_data_rate(adapter, priv->tx_rate,
526 priv->tx_htinfo);
528 return 0;
532 * This function handles the command response of a deauthenticate
533 * command.
535 * If the deauthenticated MAC matches the current BSS MAC, the connection
536 * state is reset.
538 static int mwifiex_ret_802_11_deauthenticate(struct mwifiex_private *priv,
539 struct host_cmd_ds_command *resp)
541 struct mwifiex_adapter *adapter = priv->adapter;
543 adapter->dbg.num_cmd_deauth++;
544 if (!memcmp(resp->params.deauth.mac_addr,
545 &priv->curr_bss_params.bss_descriptor.mac_address,
546 sizeof(resp->params.deauth.mac_addr)))
547 mwifiex_reset_connect_state(priv);
549 return 0;
553 * This function handles the command response of ad-hoc stop.
555 * The function resets the connection state in driver.
557 static int mwifiex_ret_802_11_ad_hoc_stop(struct mwifiex_private *priv,
558 struct host_cmd_ds_command *resp)
560 mwifiex_reset_connect_state(priv);
561 return 0;
565 * This function handles the command response of set/get key material.
567 * Handling includes updating the driver parameters to reflect the
568 * changes.
570 static int mwifiex_ret_802_11_key_material(struct mwifiex_private *priv,
571 struct host_cmd_ds_command *resp)
573 struct host_cmd_ds_802_11_key_material *key =
574 &resp->params.key_material;
576 if (le16_to_cpu(key->action) == HostCmd_ACT_GEN_SET) {
577 if ((le16_to_cpu(key->key_param_set.key_info) & KEY_MCAST)) {
578 dev_dbg(priv->adapter->dev, "info: key: GTK is set\n");
579 priv->wpa_is_gtk_set = true;
580 priv->scan_block = false;
584 memset(priv->aes_key.key_param_set.key, 0,
585 sizeof(key->key_param_set.key));
586 priv->aes_key.key_param_set.key_len = key->key_param_set.key_len;
587 memcpy(priv->aes_key.key_param_set.key, key->key_param_set.key,
588 le16_to_cpu(priv->aes_key.key_param_set.key_len));
590 return 0;
594 * This function handles the command response of get 11d domain information.
596 static int mwifiex_ret_802_11d_domain_info(struct mwifiex_private *priv,
597 struct host_cmd_ds_command *resp)
599 struct host_cmd_ds_802_11d_domain_info_rsp *domain_info =
600 &resp->params.domain_info_resp;
601 struct mwifiex_ietypes_domain_param_set *domain = &domain_info->domain;
602 u16 action = le16_to_cpu(domain_info->action);
603 u8 no_of_triplet = 0;
605 no_of_triplet = (u8) ((le16_to_cpu(domain->header.len) -
606 IEEE80211_COUNTRY_STRING_LEN) /
607 sizeof(struct ieee80211_country_ie_triplet));
609 dev_dbg(priv->adapter->dev, "info: 11D Domain Info Resp:"
610 " no_of_triplet=%d\n", no_of_triplet);
612 if (no_of_triplet > MWIFIEX_MAX_TRIPLET_802_11D) {
613 dev_warn(priv->adapter->dev,
614 "11D: invalid number of triplets %d "
615 "returned!!\n", no_of_triplet);
616 return -1;
619 switch (action) {
620 case HostCmd_ACT_GEN_SET: /* Proc Set Action */
621 break;
622 case HostCmd_ACT_GEN_GET:
623 break;
624 default:
625 dev_err(priv->adapter->dev,
626 "11D: invalid action:%d\n", domain_info->action);
627 return -1;
630 return 0;
634 * This function handles the command response of get RF channel.
636 * Handling includes changing the header fields into CPU format
637 * and saving the new channel in driver.
639 static int mwifiex_ret_802_11_rf_channel(struct mwifiex_private *priv,
640 struct host_cmd_ds_command *resp,
641 void *data_buf)
643 struct host_cmd_ds_802_11_rf_channel *rf_channel =
644 &resp->params.rf_channel;
645 u16 new_channel = le16_to_cpu(rf_channel->current_channel);
647 if (priv->curr_bss_params.bss_descriptor.channel != new_channel) {
648 dev_dbg(priv->adapter->dev, "cmd: Channel Switch: %d to %d\n",
649 priv->curr_bss_params.bss_descriptor.channel,
650 new_channel);
651 /* Update the channel again */
652 priv->curr_bss_params.bss_descriptor.channel = new_channel;
654 if (data_buf)
655 *((u16 *)data_buf) = new_channel;
657 return 0;
661 * This function handles the command response of get extended version.
663 * Handling includes forming the extended version string and sending it
664 * to application.
666 static int mwifiex_ret_ver_ext(struct mwifiex_private *priv,
667 struct host_cmd_ds_command *resp,
668 void *data_buf)
670 struct host_cmd_ds_version_ext *ver_ext = &resp->params.verext;
671 struct host_cmd_ds_version_ext *version_ext = NULL;
673 if (data_buf) {
674 version_ext = (struct host_cmd_ds_version_ext *)data_buf;
675 version_ext->version_str_sel = ver_ext->version_str_sel;
676 memcpy(version_ext->version_str, ver_ext->version_str,
677 sizeof(char) * 128);
678 memcpy(priv->version_str, ver_ext->version_str, 128);
680 return 0;
684 * This function handles the command response of register access.
686 * The register value and offset are returned to the user. For EEPROM
687 * access, the byte count is also returned.
689 static int mwifiex_ret_reg_access(u16 type, struct host_cmd_ds_command *resp,
690 void *data_buf)
692 struct mwifiex_ds_reg_rw *reg_rw = NULL;
693 struct mwifiex_ds_read_eeprom *eeprom = NULL;
695 if (data_buf) {
696 reg_rw = (struct mwifiex_ds_reg_rw *) data_buf;
697 eeprom = (struct mwifiex_ds_read_eeprom *) data_buf;
698 switch (type) {
699 case HostCmd_CMD_MAC_REG_ACCESS:
701 struct host_cmd_ds_mac_reg_access *reg;
702 reg = (struct host_cmd_ds_mac_reg_access *)
703 &resp->params.mac_reg;
704 reg_rw->offset = cpu_to_le32(
705 (u32) le16_to_cpu(reg->offset));
706 reg_rw->value = reg->value;
707 break;
709 case HostCmd_CMD_BBP_REG_ACCESS:
711 struct host_cmd_ds_bbp_reg_access *reg;
712 reg = (struct host_cmd_ds_bbp_reg_access *)
713 &resp->params.bbp_reg;
714 reg_rw->offset = cpu_to_le32(
715 (u32) le16_to_cpu(reg->offset));
716 reg_rw->value = cpu_to_le32((u32) reg->value);
717 break;
720 case HostCmd_CMD_RF_REG_ACCESS:
722 struct host_cmd_ds_rf_reg_access *reg;
723 reg = (struct host_cmd_ds_rf_reg_access *)
724 &resp->params.rf_reg;
725 reg_rw->offset = cpu_to_le32(
726 (u32) le16_to_cpu(reg->offset));
727 reg_rw->value = cpu_to_le32((u32) reg->value);
728 break;
730 case HostCmd_CMD_PMIC_REG_ACCESS:
732 struct host_cmd_ds_pmic_reg_access *reg;
733 reg = (struct host_cmd_ds_pmic_reg_access *)
734 &resp->params.pmic_reg;
735 reg_rw->offset = cpu_to_le32(
736 (u32) le16_to_cpu(reg->offset));
737 reg_rw->value = cpu_to_le32((u32) reg->value);
738 break;
740 case HostCmd_CMD_CAU_REG_ACCESS:
742 struct host_cmd_ds_rf_reg_access *reg;
743 reg = (struct host_cmd_ds_rf_reg_access *)
744 &resp->params.rf_reg;
745 reg_rw->offset = cpu_to_le32(
746 (u32) le16_to_cpu(reg->offset));
747 reg_rw->value = cpu_to_le32((u32) reg->value);
748 break;
750 case HostCmd_CMD_802_11_EEPROM_ACCESS:
752 struct host_cmd_ds_802_11_eeprom_access
753 *cmd_eeprom =
754 (struct host_cmd_ds_802_11_eeprom_access
755 *) &resp->params.eeprom;
756 pr_debug("info: EEPROM read len=%x\n",
757 cmd_eeprom->byte_count);
758 if (le16_to_cpu(eeprom->byte_count) <
759 le16_to_cpu(
760 cmd_eeprom->byte_count)) {
761 eeprom->byte_count = cpu_to_le16(0);
762 pr_debug("info: EEPROM read "
763 "length is too big\n");
764 return -1;
766 eeprom->offset = cmd_eeprom->offset;
767 eeprom->byte_count = cmd_eeprom->byte_count;
768 if (le16_to_cpu(eeprom->byte_count) > 0)
769 memcpy(&eeprom->value,
770 &cmd_eeprom->value,
771 le16_to_cpu(eeprom->byte_count));
773 break;
775 default:
776 return -1;
779 return 0;
783 * This function handles the command response of get IBSS coalescing status.
785 * If the received BSSID is different than the current one, the current BSSID,
786 * beacon interval, ATIM window and ERP information are updated, along with
787 * changing the ad-hoc state accordingly.
789 static int mwifiex_ret_ibss_coalescing_status(struct mwifiex_private *priv,
790 struct host_cmd_ds_command *resp)
792 struct host_cmd_ds_802_11_ibss_status *ibss_coal_resp =
793 &(resp->params.ibss_coalescing);
794 u8 zero_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
796 if (le16_to_cpu(ibss_coal_resp->action) == HostCmd_ACT_GEN_SET)
797 return 0;
799 dev_dbg(priv->adapter->dev,
800 "info: new BSSID %pM\n", ibss_coal_resp->bssid);
802 /* If rsp has NULL BSSID, Just return..... No Action */
803 if (!memcmp(ibss_coal_resp->bssid, zero_mac, ETH_ALEN)) {
804 dev_warn(priv->adapter->dev, "new BSSID is NULL\n");
805 return 0;
808 /* If BSSID is diff, modify current BSS parameters */
809 if (memcmp(priv->curr_bss_params.bss_descriptor.mac_address,
810 ibss_coal_resp->bssid, ETH_ALEN)) {
811 /* BSSID */
812 memcpy(priv->curr_bss_params.bss_descriptor.mac_address,
813 ibss_coal_resp->bssid, ETH_ALEN);
815 /* Beacon Interval */
816 priv->curr_bss_params.bss_descriptor.beacon_period
817 = le16_to_cpu(ibss_coal_resp->beacon_interval);
819 /* ERP Information */
820 priv->curr_bss_params.bss_descriptor.erp_flags =
821 (u8) le16_to_cpu(ibss_coal_resp->use_g_rate_protect);
823 priv->adhoc_state = ADHOC_COALESCED;
826 return 0;
830 * This function handles the command responses.
832 * This is a generic function, which calls command specific
833 * response handlers based on the command ID.
835 int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv,
836 u16 cmdresp_no, void *cmd_buf)
838 int ret = 0;
839 struct mwifiex_adapter *adapter = priv->adapter;
840 struct host_cmd_ds_command *resp =
841 (struct host_cmd_ds_command *) cmd_buf;
842 void *data_buf = adapter->curr_cmd->data_buf;
844 /* If the command is not successful, cleanup and return failure */
845 if (resp->result != HostCmd_RESULT_OK) {
846 mwifiex_process_cmdresp_error(priv, resp);
847 return -1;
849 /* Command successful, handle response */
850 switch (cmdresp_no) {
851 case HostCmd_CMD_GET_HW_SPEC:
852 ret = mwifiex_ret_get_hw_spec(priv, resp);
853 break;
854 case HostCmd_CMD_MAC_CONTROL:
855 break;
856 case HostCmd_CMD_802_11_MAC_ADDRESS:
857 ret = mwifiex_ret_802_11_mac_address(priv, resp);
858 break;
859 case HostCmd_CMD_MAC_MULTICAST_ADR:
860 ret = mwifiex_ret_mac_multicast_adr(priv, resp);
861 break;
862 case HostCmd_CMD_TX_RATE_CFG:
863 ret = mwifiex_ret_tx_rate_cfg(priv, resp, data_buf);
864 break;
865 case HostCmd_CMD_802_11_SCAN:
866 ret = mwifiex_ret_802_11_scan(priv, resp);
867 adapter->curr_cmd->wait_q_enabled = false;
868 break;
869 case HostCmd_CMD_802_11_BG_SCAN_QUERY:
870 ret = mwifiex_ret_802_11_scan(priv, resp);
871 dev_dbg(adapter->dev,
872 "info: CMD_RESP: BG_SCAN result is ready!\n");
873 break;
874 case HostCmd_CMD_TXPWR_CFG:
875 ret = mwifiex_ret_tx_power_cfg(priv, resp, data_buf);
876 break;
877 case HostCmd_CMD_802_11_PS_MODE_ENH:
878 ret = mwifiex_ret_enh_power_mode(priv, resp, data_buf);
879 break;
880 case HostCmd_CMD_802_11_HS_CFG_ENH:
881 ret = mwifiex_ret_802_11_hs_cfg(priv, resp);
882 break;
883 case HostCmd_CMD_802_11_ASSOCIATE:
884 ret = mwifiex_ret_802_11_associate(priv, resp);
885 break;
886 case HostCmd_CMD_802_11_DEAUTHENTICATE:
887 ret = mwifiex_ret_802_11_deauthenticate(priv, resp);
888 break;
889 case HostCmd_CMD_802_11_AD_HOC_START:
890 case HostCmd_CMD_802_11_AD_HOC_JOIN:
891 ret = mwifiex_ret_802_11_ad_hoc(priv, resp);
892 break;
893 case HostCmd_CMD_802_11_AD_HOC_STOP:
894 ret = mwifiex_ret_802_11_ad_hoc_stop(priv, resp);
895 break;
896 case HostCmd_CMD_802_11_GET_LOG:
897 ret = mwifiex_ret_get_log(priv, resp, data_buf);
898 break;
899 case HostCmd_CMD_RSSI_INFO:
900 ret = mwifiex_ret_802_11_rssi_info(priv, resp, data_buf);
901 break;
902 case HostCmd_CMD_802_11_SNMP_MIB:
903 ret = mwifiex_ret_802_11_snmp_mib(priv, resp, data_buf);
904 break;
905 case HostCmd_CMD_802_11_TX_RATE_QUERY:
906 ret = mwifiex_ret_802_11_tx_rate_query(priv, resp);
907 break;
908 case HostCmd_CMD_802_11_RF_CHANNEL:
909 ret = mwifiex_ret_802_11_rf_channel(priv, resp, data_buf);
910 break;
911 case HostCmd_CMD_VERSION_EXT:
912 ret = mwifiex_ret_ver_ext(priv, resp, data_buf);
913 break;
914 case HostCmd_CMD_FUNC_INIT:
915 case HostCmd_CMD_FUNC_SHUTDOWN:
916 break;
917 case HostCmd_CMD_802_11_KEY_MATERIAL:
918 ret = mwifiex_ret_802_11_key_material(priv, resp);
919 break;
920 case HostCmd_CMD_802_11D_DOMAIN_INFO:
921 ret = mwifiex_ret_802_11d_domain_info(priv, resp);
922 break;
923 case HostCmd_CMD_11N_ADDBA_REQ:
924 ret = mwifiex_ret_11n_addba_req(priv, resp);
925 break;
926 case HostCmd_CMD_11N_DELBA:
927 ret = mwifiex_ret_11n_delba(priv, resp);
928 break;
929 case HostCmd_CMD_11N_ADDBA_RSP:
930 ret = mwifiex_ret_11n_addba_resp(priv, resp);
931 break;
932 case HostCmd_CMD_RECONFIGURE_TX_BUFF:
933 adapter->tx_buf_size = (u16) le16_to_cpu(resp->params.
934 tx_buf.buff_size);
935 adapter->tx_buf_size = (adapter->tx_buf_size /
936 MWIFIEX_SDIO_BLOCK_SIZE) *
937 MWIFIEX_SDIO_BLOCK_SIZE;
938 adapter->curr_tx_buf_size = adapter->tx_buf_size;
939 dev_dbg(adapter->dev,
940 "cmd: max_tx_buf_size=%d, tx_buf_size=%d\n",
941 adapter->max_tx_buf_size, adapter->tx_buf_size);
943 if (adapter->if_ops.update_mp_end_port)
944 adapter->if_ops.update_mp_end_port(adapter,
945 le16_to_cpu(resp->
946 params.
947 tx_buf.
948 mp_end_port));
949 break;
950 case HostCmd_CMD_AMSDU_AGGR_CTRL:
951 ret = mwifiex_ret_amsdu_aggr_ctrl(priv, resp, data_buf);
952 break;
953 case HostCmd_CMD_WMM_GET_STATUS:
954 ret = mwifiex_ret_wmm_get_status(priv, resp);
955 break;
956 case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS:
957 ret = mwifiex_ret_ibss_coalescing_status(priv, resp);
958 break;
959 case HostCmd_CMD_MAC_REG_ACCESS:
960 case HostCmd_CMD_BBP_REG_ACCESS:
961 case HostCmd_CMD_RF_REG_ACCESS:
962 case HostCmd_CMD_PMIC_REG_ACCESS:
963 case HostCmd_CMD_CAU_REG_ACCESS:
964 case HostCmd_CMD_802_11_EEPROM_ACCESS:
965 ret = mwifiex_ret_reg_access(cmdresp_no, resp, data_buf);
966 break;
967 case HostCmd_CMD_SET_BSS_MODE:
968 break;
969 case HostCmd_CMD_11N_CFG:
970 ret = mwifiex_ret_11n_cfg(priv, resp, data_buf);
971 break;
972 default:
973 dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n",
974 resp->command);
975 break;
978 return ret;