diff options
Diffstat (limited to 'drivers/net/wireless/mwifiex/sta_cmdresp.c')
-rw-r--r-- | drivers/net/wireless/mwifiex/sta_cmdresp.c | 986 |
1 files changed, 986 insertions, 0 deletions
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c new file mode 100644 index 000000000000..ae960ddf2bd4 --- /dev/null +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c | |||
@@ -0,0 +1,986 @@ | |||
1 | /* | ||
2 | * Marvell Wireless LAN device driver: station command response handling | ||
3 | * | ||
4 | * Copyright (C) 2011, Marvell International Ltd. | ||
5 | * | ||
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. | ||
13 | * | ||
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. | ||
18 | */ | ||
19 | |||
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" | ||
27 | |||
28 | |||
29 | /* | ||
30 | * This function handles the command response error case. | ||
31 | * | ||
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. | ||
35 | * | ||
36 | * For Power Save command failure, we do not retry enter PS | ||
37 | * command in case of Ad-hoc mode. | ||
38 | * | ||
39 | * For all other response errors, the current command buffer is freed | ||
40 | * and returned to the free command queue. | ||
41 | */ | ||
42 | static void | ||
43 | mwifiex_process_cmdresp_error(struct mwifiex_private *priv, | ||
44 | struct host_cmd_ds_command *resp, | ||
45 | struct mwifiex_wait_queue *wq_buf) | ||
46 | { | ||
47 | struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL; | ||
48 | struct mwifiex_adapter *adapter = priv->adapter; | ||
49 | unsigned long flags; | ||
50 | |||
51 | dev_err(adapter->dev, "CMD_RESP: cmd %#x error, result=%#x\n", | ||
52 | resp->command, resp->result); | ||
53 | if (wq_buf) | ||
54 | wq_buf->status = MWIFIEX_ERROR_FW_CMDRESP; | ||
55 | |||
56 | switch (le16_to_cpu(resp->command)) { | ||
57 | case HostCmd_CMD_802_11_PS_MODE_ENH: | ||
58 | { | ||
59 | struct host_cmd_ds_802_11_ps_mode_enh *pm = | ||
60 | &resp->params.psmode_enh; | ||
61 | dev_err(adapter->dev, "PS_MODE_ENH cmd failed: " | ||
62 | "result=0x%x action=0x%X\n", | ||
63 | resp->result, le16_to_cpu(pm->action)); | ||
64 | /* We do not re-try enter-ps command in ad-hoc mode. */ | ||
65 | if (le16_to_cpu(pm->action) == EN_AUTO_PS && | ||
66 | (le16_to_cpu(pm->params.auto_ps.ps_bitmap) & | ||
67 | BITMAP_STA_PS) | ||
68 | && priv->bss_mode == MWIFIEX_BSS_MODE_IBSS) | ||
69 | adapter->ps_mode = | ||
70 | MWIFIEX_802_11_POWER_MODE_CAM; | ||
71 | } | ||
72 | break; | ||
73 | case HostCmd_CMD_802_11_SCAN: | ||
74 | /* Cancel all pending scan command */ | ||
75 | spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); | ||
76 | list_for_each_entry_safe(cmd_node, tmp_node, | ||
77 | &adapter->scan_pending_q, list) { | ||
78 | list_del(&cmd_node->list); | ||
79 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, | ||
80 | flags); | ||
81 | mwifiex_insert_cmd_to_free_q(adapter, cmd_node); | ||
82 | spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); | ||
83 | } | ||
84 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); | ||
85 | |||
86 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); | ||
87 | adapter->scan_processing = false; | ||
88 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); | ||
89 | if (priv->report_scan_result) | ||
90 | priv->report_scan_result = false; | ||
91 | if (priv->scan_pending_on_block) { | ||
92 | priv->scan_pending_on_block = false; | ||
93 | up(&priv->async_sem); | ||
94 | } | ||
95 | break; | ||
96 | |||
97 | case HostCmd_CMD_MAC_CONTROL: | ||
98 | break; | ||
99 | |||
100 | default: | ||
101 | break; | ||
102 | } | ||
103 | /* Handling errors here */ | ||
104 | mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd); | ||
105 | |||
106 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); | ||
107 | adapter->curr_cmd = NULL; | ||
108 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); | ||
109 | |||
110 | return; | ||
111 | } | ||
112 | |||
113 | /* | ||
114 | * This function handles the command response of get RSSI info. | ||
115 | * | ||
116 | * Handling includes changing the header fields into CPU format | ||
117 | * and saving the following parameters in driver - | ||
118 | * - Last data and beacon RSSI value | ||
119 | * - Average data and beacon RSSI value | ||
120 | * - Last data and beacon NF value | ||
121 | * - Average data and beacon NF value | ||
122 | * | ||
123 | * The parameters are send to the application as well, along with | ||
124 | * calculated SNR values. | ||
125 | */ | ||
126 | static int mwifiex_ret_802_11_rssi_info(struct mwifiex_private *priv, | ||
127 | struct host_cmd_ds_command *resp, | ||
128 | void *data_buf) | ||
129 | { | ||
130 | struct host_cmd_ds_802_11_rssi_info_rsp *rssi_info_rsp = | ||
131 | &resp->params.rssi_info_rsp; | ||
132 | struct mwifiex_ds_get_signal *signal = NULL; | ||
133 | |||
134 | priv->data_rssi_last = le16_to_cpu(rssi_info_rsp->data_rssi_last); | ||
135 | priv->data_nf_last = le16_to_cpu(rssi_info_rsp->data_nf_last); | ||
136 | |||
137 | priv->data_rssi_avg = le16_to_cpu(rssi_info_rsp->data_rssi_avg); | ||
138 | priv->data_nf_avg = le16_to_cpu(rssi_info_rsp->data_nf_avg); | ||
139 | |||
140 | priv->bcn_rssi_last = le16_to_cpu(rssi_info_rsp->bcn_rssi_last); | ||
141 | priv->bcn_nf_last = le16_to_cpu(rssi_info_rsp->bcn_nf_last); | ||
142 | |||
143 | priv->bcn_rssi_avg = le16_to_cpu(rssi_info_rsp->bcn_rssi_avg); | ||
144 | priv->bcn_nf_avg = le16_to_cpu(rssi_info_rsp->bcn_nf_avg); | ||
145 | |||
146 | /* Need to indicate IOCTL complete */ | ||
147 | if (data_buf) { | ||
148 | signal = (struct mwifiex_ds_get_signal *) data_buf; | ||
149 | memset(signal, 0, sizeof(struct mwifiex_ds_get_signal)); | ||
150 | |||
151 | signal->selector = ALL_RSSI_INFO_MASK; | ||
152 | |||
153 | /* RSSI */ | ||
154 | signal->bcn_rssi_last = priv->bcn_rssi_last; | ||
155 | signal->bcn_rssi_avg = priv->bcn_rssi_avg; | ||
156 | signal->data_rssi_last = priv->data_rssi_last; | ||
157 | signal->data_rssi_avg = priv->data_rssi_avg; | ||
158 | |||
159 | /* SNR */ | ||
160 | signal->bcn_snr_last = | ||
161 | CAL_SNR(priv->bcn_rssi_last, priv->bcn_nf_last); | ||
162 | signal->bcn_snr_avg = | ||
163 | CAL_SNR(priv->bcn_rssi_avg, priv->bcn_nf_avg); | ||
164 | signal->data_snr_last = | ||
165 | CAL_SNR(priv->data_rssi_last, priv->data_nf_last); | ||
166 | signal->data_snr_avg = | ||
167 | CAL_SNR(priv->data_rssi_avg, priv->data_nf_avg); | ||
168 | |||
169 | /* NF */ | ||
170 | signal->bcn_nf_last = priv->bcn_nf_last; | ||
171 | signal->bcn_nf_avg = priv->bcn_nf_avg; | ||
172 | signal->data_nf_last = priv->data_nf_last; | ||
173 | signal->data_nf_avg = priv->data_nf_avg; | ||
174 | } | ||
175 | |||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | /* | ||
180 | * This function handles the command response of set/get SNMP | ||
181 | * MIB parameters. | ||
182 | * | ||
183 | * Handling includes changing the header fields into CPU format | ||
184 | * and saving the parameter in driver. | ||
185 | * | ||
186 | * The following parameters are supported - | ||
187 | * - Fragmentation threshold | ||
188 | * - RTS threshold | ||
189 | * - Short retry limit | ||
190 | */ | ||
191 | static int mwifiex_ret_802_11_snmp_mib(struct mwifiex_private *priv, | ||
192 | struct host_cmd_ds_command *resp, | ||
193 | void *data_buf) | ||
194 | { | ||
195 | struct host_cmd_ds_802_11_snmp_mib *smib = &resp->params.smib; | ||
196 | u16 oid = le16_to_cpu(smib->oid); | ||
197 | u16 query_type = le16_to_cpu(smib->query_type); | ||
198 | u32 ul_temp; | ||
199 | |||
200 | dev_dbg(priv->adapter->dev, "info: SNMP_RESP: oid value = %#x," | ||
201 | " query_type = %#x, buf size = %#x\n", | ||
202 | oid, query_type, le16_to_cpu(smib->buf_size)); | ||
203 | if (query_type == HostCmd_ACT_GEN_GET) { | ||
204 | ul_temp = le16_to_cpu(*((__le16 *) (smib->value))); | ||
205 | if (data_buf) | ||
206 | *(u32 *)data_buf = ul_temp; | ||
207 | switch (oid) { | ||
208 | case FRAG_THRESH_I: | ||
209 | dev_dbg(priv->adapter->dev, | ||
210 | "info: SNMP_RESP: FragThsd =%u\n", ul_temp); | ||
211 | break; | ||
212 | case RTS_THRESH_I: | ||
213 | dev_dbg(priv->adapter->dev, | ||
214 | "info: SNMP_RESP: RTSThsd =%u\n", ul_temp); | ||
215 | break; | ||
216 | case SHORT_RETRY_LIM_I: | ||
217 | dev_dbg(priv->adapter->dev, | ||
218 | "info: SNMP_RESP: TxRetryCount=%u\n", ul_temp); | ||
219 | break; | ||
220 | default: | ||
221 | break; | ||
222 | } | ||
223 | } | ||
224 | |||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | /* | ||
229 | * This function handles the command response of get log request | ||
230 | * | ||
231 | * Handling includes changing the header fields into CPU format | ||
232 | * and sending the received parameters to application. | ||
233 | */ | ||
234 | static int mwifiex_ret_get_log(struct mwifiex_private *priv, | ||
235 | struct host_cmd_ds_command *resp, | ||
236 | void *data_buf) | ||
237 | { | ||
238 | struct host_cmd_ds_802_11_get_log *get_log = | ||
239 | (struct host_cmd_ds_802_11_get_log *) &resp->params.get_log; | ||
240 | struct mwifiex_ds_get_stats *stats = NULL; | ||
241 | |||
242 | if (data_buf) { | ||
243 | stats = (struct mwifiex_ds_get_stats *) data_buf; | ||
244 | stats->mcast_tx_frame = le32_to_cpu(get_log->mcast_tx_frame); | ||
245 | stats->failed = le32_to_cpu(get_log->failed); | ||
246 | stats->retry = le32_to_cpu(get_log->retry); | ||
247 | stats->multi_retry = le32_to_cpu(get_log->multi_retry); | ||
248 | stats->frame_dup = le32_to_cpu(get_log->frame_dup); | ||
249 | stats->rts_success = le32_to_cpu(get_log->rts_success); | ||
250 | stats->rts_failure = le32_to_cpu(get_log->rts_failure); | ||
251 | stats->ack_failure = le32_to_cpu(get_log->ack_failure); | ||
252 | stats->rx_frag = le32_to_cpu(get_log->rx_frag); | ||
253 | stats->mcast_rx_frame = le32_to_cpu(get_log->mcast_rx_frame); | ||
254 | stats->fcs_error = le32_to_cpu(get_log->fcs_error); | ||
255 | stats->tx_frame = le32_to_cpu(get_log->tx_frame); | ||
256 | stats->wep_icv_error[0] = | ||
257 | le32_to_cpu(get_log->wep_icv_err_cnt[0]); | ||
258 | stats->wep_icv_error[1] = | ||
259 | le32_to_cpu(get_log->wep_icv_err_cnt[1]); | ||
260 | stats->wep_icv_error[2] = | ||
261 | le32_to_cpu(get_log->wep_icv_err_cnt[2]); | ||
262 | stats->wep_icv_error[3] = | ||
263 | le32_to_cpu(get_log->wep_icv_err_cnt[3]); | ||
264 | } | ||
265 | |||
266 | return 0; | ||
267 | } | ||
268 | |||
269 | /* | ||
270 | * This function handles the command response of set/get Tx rate | ||
271 | * configurations. | ||
272 | * | ||
273 | * Handling includes changing the header fields into CPU format | ||
274 | * and saving the following parameters in driver - | ||
275 | * - DSSS rate bitmap | ||
276 | * - OFDM rate bitmap | ||
277 | * - HT MCS rate bitmaps | ||
278 | * | ||
279 | * Based on the new rate bitmaps, the function re-evaluates if | ||
280 | * auto data rate has been activated. If not, it sends another | ||
281 | * query to the firmware to get the current Tx data rate and updates | ||
282 | * the driver value. | ||
283 | */ | ||
284 | static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv, | ||
285 | struct host_cmd_ds_command *resp, | ||
286 | void *data_buf) | ||
287 | { | ||
288 | struct mwifiex_adapter *adapter = priv->adapter; | ||
289 | struct mwifiex_rate_cfg *ds_rate = NULL; | ||
290 | struct host_cmd_ds_tx_rate_cfg *rate_cfg = &resp->params.tx_rate_cfg; | ||
291 | struct mwifiex_rate_scope *rate_scope; | ||
292 | struct mwifiex_ie_types_header *head = NULL; | ||
293 | u16 tlv, tlv_buf_len; | ||
294 | u8 *tlv_buf; | ||
295 | u32 i; | ||
296 | int ret = 0; | ||
297 | |||
298 | tlv_buf = (u8 *) ((u8 *) rate_cfg) + | ||
299 | sizeof(struct host_cmd_ds_tx_rate_cfg); | ||
300 | tlv_buf_len = *(u16 *) (tlv_buf + sizeof(u16)); | ||
301 | |||
302 | while (tlv_buf && tlv_buf_len > 0) { | ||
303 | tlv = (*tlv_buf); | ||
304 | tlv = tlv | (*(tlv_buf + 1) << 8); | ||
305 | |||
306 | switch (tlv) { | ||
307 | case TLV_TYPE_RATE_SCOPE: | ||
308 | rate_scope = (struct mwifiex_rate_scope *) tlv_buf; | ||
309 | priv->bitmap_rates[0] = | ||
310 | le16_to_cpu(rate_scope->hr_dsss_rate_bitmap); | ||
311 | priv->bitmap_rates[1] = | ||
312 | le16_to_cpu(rate_scope->ofdm_rate_bitmap); | ||
313 | for (i = 0; | ||
314 | i < | ||
315 | sizeof(rate_scope->ht_mcs_rate_bitmap) / | ||
316 | sizeof(u16); i++) | ||
317 | priv->bitmap_rates[2 + i] = | ||
318 | le16_to_cpu(rate_scope-> | ||
319 | ht_mcs_rate_bitmap[i]); | ||
320 | break; | ||
321 | /* Add RATE_DROP tlv here */ | ||
322 | } | ||
323 | |||
324 | head = (struct mwifiex_ie_types_header *) tlv_buf; | ||
325 | tlv_buf += le16_to_cpu(head->len) + sizeof(*head); | ||
326 | tlv_buf_len -= le16_to_cpu(head->len); | ||
327 | } | ||
328 | |||
329 | priv->is_data_rate_auto = mwifiex_is_rate_auto(priv); | ||
330 | |||
331 | if (priv->is_data_rate_auto) | ||
332 | priv->data_rate = 0; | ||
333 | else | ||
334 | ret = mwifiex_prepare_cmd(priv, | ||
335 | HostCmd_CMD_802_11_TX_RATE_QUERY, | ||
336 | HostCmd_ACT_GEN_GET, 0, NULL, NULL); | ||
337 | |||
338 | if (data_buf) { | ||
339 | ds_rate = (struct mwifiex_rate_cfg *) data_buf; | ||
340 | if (le16_to_cpu(rate_cfg->action) == HostCmd_ACT_GEN_GET) { | ||
341 | if (priv->is_data_rate_auto) { | ||
342 | ds_rate->is_rate_auto = 1; | ||
343 | } else { | ||
344 | ds_rate->rate = | ||
345 | mwifiex_get_rate_index(adapter, | ||
346 | priv-> | ||
347 | bitmap_rates, | ||
348 | sizeof(priv-> | ||
349 | bitmap_rates)); | ||
350 | if (ds_rate->rate >= | ||
351 | MWIFIEX_RATE_BITMAP_OFDM0 | ||
352 | && ds_rate->rate <= | ||
353 | MWIFIEX_RATE_BITMAP_OFDM7) | ||
354 | ds_rate->rate -= | ||
355 | (MWIFIEX_RATE_BITMAP_OFDM0 - | ||
356 | MWIFIEX_RATE_INDEX_OFDM0); | ||
357 | if (ds_rate->rate >= | ||
358 | MWIFIEX_RATE_BITMAP_MCS0 | ||
359 | && ds_rate->rate <= | ||
360 | MWIFIEX_RATE_BITMAP_MCS127) | ||
361 | ds_rate->rate -= | ||
362 | (MWIFIEX_RATE_BITMAP_MCS0 - | ||
363 | MWIFIEX_RATE_INDEX_MCS0); | ||
364 | } | ||
365 | } | ||
366 | } | ||
367 | |||
368 | return ret; | ||
369 | } | ||
370 | |||
371 | /* | ||
372 | * This function handles the command response of get Tx power level. | ||
373 | * | ||
374 | * Handling includes saving the maximum and minimum Tx power levels | ||
375 | * in driver, as well as sending the values to user. | ||
376 | */ | ||
377 | static int mwifiex_get_power_level(struct mwifiex_private *priv, void *data_buf) | ||
378 | { | ||
379 | int length = -1, max_power = -1, min_power = -1; | ||
380 | struct mwifiex_types_power_group *pg_tlv_hdr = NULL; | ||
381 | struct mwifiex_power_group *pg = NULL; | ||
382 | |||
383 | if (data_buf) { | ||
384 | pg_tlv_hdr = | ||
385 | (struct mwifiex_types_power_group *) ((u8 *) data_buf | ||
386 | + sizeof(struct host_cmd_ds_txpwr_cfg)); | ||
387 | pg = (struct mwifiex_power_group *) ((u8 *) pg_tlv_hdr + | ||
388 | sizeof(struct mwifiex_types_power_group)); | ||
389 | length = pg_tlv_hdr->length; | ||
390 | if (length > 0) { | ||
391 | max_power = pg->power_max; | ||
392 | min_power = pg->power_min; | ||
393 | length -= sizeof(struct mwifiex_power_group); | ||
394 | } | ||
395 | while (length) { | ||
396 | pg++; | ||
397 | if (max_power < pg->power_max) | ||
398 | max_power = pg->power_max; | ||
399 | |||
400 | if (min_power > pg->power_min) | ||
401 | min_power = pg->power_min; | ||
402 | |||
403 | length -= sizeof(struct mwifiex_power_group); | ||
404 | } | ||
405 | if (pg_tlv_hdr->length > 0) { | ||
406 | priv->min_tx_power_level = (u8) min_power; | ||
407 | priv->max_tx_power_level = (u8) max_power; | ||
408 | } | ||
409 | } else { | ||
410 | return -1; | ||
411 | } | ||
412 | |||
413 | return 0; | ||
414 | } | ||
415 | |||
416 | /* | ||
417 | * This function handles the command response of set/get Tx power | ||
418 | * configurations. | ||
419 | * | ||
420 | * Handling includes changing the header fields into CPU format | ||
421 | * and saving the current Tx power level in driver. | ||
422 | */ | ||
423 | static int mwifiex_ret_tx_power_cfg(struct mwifiex_private *priv, | ||
424 | struct host_cmd_ds_command *resp, | ||
425 | void *data_buf) | ||
426 | { | ||
427 | struct mwifiex_adapter *adapter = priv->adapter; | ||
428 | struct host_cmd_ds_txpwr_cfg *txp_cfg = &resp->params.txp_cfg; | ||
429 | struct mwifiex_types_power_group *pg_tlv_hdr = NULL; | ||
430 | struct mwifiex_power_group *pg = NULL; | ||
431 | u16 action = le16_to_cpu(txp_cfg->action); | ||
432 | |||
433 | switch (action) { | ||
434 | case HostCmd_ACT_GEN_GET: | ||
435 | { | ||
436 | pg_tlv_hdr = | ||
437 | (struct mwifiex_types_power_group *) ((u8 *) | ||
438 | txp_cfg + | ||
439 | sizeof | ||
440 | (struct | ||
441 | host_cmd_ds_txpwr_cfg)); | ||
442 | pg = (struct mwifiex_power_group *) ((u8 *) | ||
443 | pg_tlv_hdr + | ||
444 | sizeof(struct | ||
445 | mwifiex_types_power_group)); | ||
446 | if (adapter->hw_status == | ||
447 | MWIFIEX_HW_STATUS_INITIALIZING) | ||
448 | mwifiex_get_power_level(priv, txp_cfg); | ||
449 | priv->tx_power_level = (u16) pg->power_min; | ||
450 | break; | ||
451 | } | ||
452 | case HostCmd_ACT_GEN_SET: | ||
453 | if (le32_to_cpu(txp_cfg->mode)) { | ||
454 | pg_tlv_hdr = | ||
455 | (struct mwifiex_types_power_group *) ((u8 *) | ||
456 | txp_cfg + | ||
457 | sizeof | ||
458 | (struct | ||
459 | host_cmd_ds_txpwr_cfg)); | ||
460 | pg = (struct mwifiex_power_group *) ((u8 *) pg_tlv_hdr | ||
461 | + | ||
462 | sizeof(struct | ||
463 | mwifiex_types_power_group)); | ||
464 | if (pg->power_max == pg->power_min) | ||
465 | priv->tx_power_level = (u16) pg->power_min; | ||
466 | } | ||
467 | break; | ||
468 | default: | ||
469 | dev_err(adapter->dev, "CMD_RESP: unknown cmd action %d\n", | ||
470 | action); | ||
471 | return 0; | ||
472 | } | ||
473 | dev_dbg(adapter->dev, | ||
474 | "info: Current TxPower Level = %d, Max Power=%d, Min Power=%d\n", | ||
475 | priv->tx_power_level, priv->max_tx_power_level, | ||
476 | priv->min_tx_power_level); | ||
477 | |||
478 | return 0; | ||
479 | } | ||
480 | |||
481 | /* | ||
482 | * This function handles the command response of set/get MAC address. | ||
483 | * | ||
484 | * Handling includes saving the MAC address in driver. | ||
485 | */ | ||
486 | static int mwifiex_ret_802_11_mac_address(struct mwifiex_private *priv, | ||
487 | struct host_cmd_ds_command *resp) | ||
488 | { | ||
489 | struct host_cmd_ds_802_11_mac_address *cmd_mac_addr = | ||
490 | &resp->params.mac_addr; | ||
491 | |||
492 | memcpy(priv->curr_addr, cmd_mac_addr->mac_addr, ETH_ALEN); | ||
493 | |||
494 | dev_dbg(priv->adapter->dev, | ||
495 | "info: set mac address: %pM\n", priv->curr_addr); | ||
496 | |||
497 | return 0; | ||
498 | } | ||
499 | |||
500 | /* | ||
501 | * This function handles the command response of set/get MAC multicast | ||
502 | * address. | ||
503 | */ | ||
504 | static int mwifiex_ret_mac_multicast_adr(struct mwifiex_private *priv, | ||
505 | struct host_cmd_ds_command *resp) | ||
506 | { | ||
507 | return 0; | ||
508 | } | ||
509 | |||
510 | /* | ||
511 | * This function handles the command response of get Tx rate query. | ||
512 | * | ||
513 | * Handling includes changing the header fields into CPU format | ||
514 | * and saving the Tx rate and HT information parameters in driver. | ||
515 | * | ||
516 | * Both rate configuration and current data rate can be retrieved | ||
517 | * with this request. | ||
518 | */ | ||
519 | static int mwifiex_ret_802_11_tx_rate_query(struct mwifiex_private *priv, | ||
520 | struct host_cmd_ds_command *resp) | ||
521 | { | ||
522 | struct mwifiex_adapter *adapter = priv->adapter; | ||
523 | |||
524 | priv->tx_rate = resp->params.tx_rate.tx_rate; | ||
525 | priv->tx_htinfo = resp->params.tx_rate.ht_info; | ||
526 | if (!priv->is_data_rate_auto) | ||
527 | priv->data_rate = | ||
528 | mwifiex_index_to_data_rate(adapter, priv->tx_rate, | ||
529 | priv->tx_htinfo); | ||
530 | |||
531 | return 0; | ||
532 | } | ||
533 | |||
534 | /* | ||
535 | * This function handles the command response of a deauthenticate | ||
536 | * command. | ||
537 | * | ||
538 | * If the deauthenticated MAC matches the current BSS MAC, the connection | ||
539 | * state is reset. | ||
540 | */ | ||
541 | static int mwifiex_ret_802_11_deauthenticate(struct mwifiex_private *priv, | ||
542 | struct host_cmd_ds_command *resp) | ||
543 | { | ||
544 | struct mwifiex_adapter *adapter = priv->adapter; | ||
545 | |||
546 | adapter->dbg.num_cmd_deauth++; | ||
547 | if (!memcmp(resp->params.deauth.mac_addr, | ||
548 | &priv->curr_bss_params.bss_descriptor.mac_address, | ||
549 | sizeof(resp->params.deauth.mac_addr))) | ||
550 | mwifiex_reset_connect_state(priv); | ||
551 | |||
552 | return 0; | ||
553 | } | ||
554 | |||
555 | /* | ||
556 | * This function handles the command response of ad-hoc stop. | ||
557 | * | ||
558 | * The function resets the connection state in driver. | ||
559 | */ | ||
560 | static int mwifiex_ret_802_11_ad_hoc_stop(struct mwifiex_private *priv, | ||
561 | struct host_cmd_ds_command *resp) | ||
562 | { | ||
563 | mwifiex_reset_connect_state(priv); | ||
564 | return 0; | ||
565 | } | ||
566 | |||
567 | /* | ||
568 | * This function handles the command response of set/get key material. | ||
569 | * | ||
570 | * Handling includes updating the driver parameters to reflect the | ||
571 | * changes. | ||
572 | */ | ||
573 | static int mwifiex_ret_802_11_key_material(struct mwifiex_private *priv, | ||
574 | struct host_cmd_ds_command *resp) | ||
575 | { | ||
576 | struct host_cmd_ds_802_11_key_material *key = | ||
577 | &resp->params.key_material; | ||
578 | |||
579 | if (le16_to_cpu(key->action) == HostCmd_ACT_GEN_SET) { | ||
580 | if ((le16_to_cpu(key->key_param_set.key_info) & | ||
581 | KEY_INFO_TKIP_MCAST)) { | ||
582 | dev_dbg(priv->adapter->dev, "info: key: GTK is set\n"); | ||
583 | priv->wpa_is_gtk_set = true; | ||
584 | priv->scan_block = false; | ||
585 | } | ||
586 | } | ||
587 | |||
588 | memset(priv->aes_key.key_param_set.key, 0, | ||
589 | sizeof(key->key_param_set.key)); | ||
590 | priv->aes_key.key_param_set.key_len = key->key_param_set.key_len; | ||
591 | memcpy(priv->aes_key.key_param_set.key, key->key_param_set.key, | ||
592 | le16_to_cpu(priv->aes_key.key_param_set.key_len)); | ||
593 | |||
594 | return 0; | ||
595 | } | ||
596 | |||
597 | /* | ||
598 | * This function handles the command response of get 11d domain information. | ||
599 | */ | ||
600 | static int mwifiex_ret_802_11d_domain_info(struct mwifiex_private *priv, | ||
601 | struct host_cmd_ds_command *resp) | ||
602 | { | ||
603 | struct host_cmd_ds_802_11d_domain_info_rsp *domain_info = | ||
604 | &resp->params.domain_info_resp; | ||
605 | struct mwifiex_ietypes_domain_param_set *domain = &domain_info->domain; | ||
606 | u16 action = le16_to_cpu(domain_info->action); | ||
607 | u8 no_of_triplet = 0; | ||
608 | |||
609 | no_of_triplet = (u8) ((le16_to_cpu(domain->header.len) - | ||
610 | IEEE80211_COUNTRY_STRING_LEN) / | ||
611 | sizeof(struct ieee80211_country_ie_triplet)); | ||
612 | |||
613 | dev_dbg(priv->adapter->dev, "info: 11D Domain Info Resp:" | ||
614 | " no_of_triplet=%d\n", no_of_triplet); | ||
615 | |||
616 | if (no_of_triplet > MWIFIEX_MAX_TRIPLET_802_11D) { | ||
617 | dev_warn(priv->adapter->dev, | ||
618 | "11D: invalid number of triplets %d " | ||
619 | "returned!!\n", no_of_triplet); | ||
620 | return -1; | ||
621 | } | ||
622 | |||
623 | switch (action) { | ||
624 | case HostCmd_ACT_GEN_SET: /* Proc Set Action */ | ||
625 | break; | ||
626 | case HostCmd_ACT_GEN_GET: | ||
627 | break; | ||
628 | default: | ||
629 | dev_err(priv->adapter->dev, | ||
630 | "11D: invalid action:%d\n", domain_info->action); | ||
631 | return -1; | ||
632 | } | ||
633 | |||
634 | return 0; | ||
635 | } | ||
636 | |||
637 | /* | ||
638 | * This function handles the command response of get RF channel. | ||
639 | * | ||
640 | * Handling includes changing the header fields into CPU format | ||
641 | * and saving the new channel in driver. | ||
642 | */ | ||
643 | static int mwifiex_ret_802_11_rf_channel(struct mwifiex_private *priv, | ||
644 | struct host_cmd_ds_command *resp, | ||
645 | void *data_buf) | ||
646 | { | ||
647 | struct host_cmd_ds_802_11_rf_channel *rf_channel = | ||
648 | &resp->params.rf_channel; | ||
649 | u16 new_channel = le16_to_cpu(rf_channel->current_channel); | ||
650 | |||
651 | if (priv->curr_bss_params.bss_descriptor.channel != new_channel) { | ||
652 | dev_dbg(priv->adapter->dev, "cmd: Channel Switch: %d to %d\n", | ||
653 | priv->curr_bss_params.bss_descriptor.channel, | ||
654 | new_channel); | ||
655 | /* Update the channel again */ | ||
656 | priv->curr_bss_params.bss_descriptor.channel = new_channel; | ||
657 | } | ||
658 | if (data_buf) | ||
659 | *((u16 *)data_buf) = new_channel; | ||
660 | |||
661 | return 0; | ||
662 | } | ||
663 | |||
664 | /* | ||
665 | * This function handles the command response of get extended version. | ||
666 | * | ||
667 | * Handling includes forming the extended version string and sending it | ||
668 | * to application. | ||
669 | */ | ||
670 | static int mwifiex_ret_ver_ext(struct mwifiex_private *priv, | ||
671 | struct host_cmd_ds_command *resp, | ||
672 | void *data_buf) | ||
673 | { | ||
674 | struct host_cmd_ds_version_ext *ver_ext = &resp->params.verext; | ||
675 | struct host_cmd_ds_version_ext *version_ext = NULL; | ||
676 | |||
677 | if (data_buf) { | ||
678 | version_ext = (struct host_cmd_ds_version_ext *)data_buf; | ||
679 | version_ext->version_str_sel = ver_ext->version_str_sel; | ||
680 | memcpy(version_ext->version_str, ver_ext->version_str, | ||
681 | sizeof(char) * 128); | ||
682 | memcpy(priv->version_str, ver_ext->version_str, 128); | ||
683 | } | ||
684 | return 0; | ||
685 | } | ||
686 | |||
687 | /* | ||
688 | * This function handles the command response of register access. | ||
689 | * | ||
690 | * The register value and offset are returned to the user. For EEPROM | ||
691 | * access, the byte count is also returned. | ||
692 | */ | ||
693 | static int mwifiex_ret_reg_access(u16 type, struct host_cmd_ds_command *resp, | ||
694 | void *data_buf) | ||
695 | { | ||
696 | struct mwifiex_ds_reg_rw *reg_rw = NULL; | ||
697 | struct mwifiex_ds_read_eeprom *eeprom = NULL; | ||
698 | |||
699 | if (data_buf) { | ||
700 | reg_rw = (struct mwifiex_ds_reg_rw *) data_buf; | ||
701 | eeprom = (struct mwifiex_ds_read_eeprom *) data_buf; | ||
702 | switch (type) { | ||
703 | case HostCmd_CMD_MAC_REG_ACCESS: | ||
704 | { | ||
705 | struct host_cmd_ds_mac_reg_access *reg; | ||
706 | reg = (struct host_cmd_ds_mac_reg_access *) | ||
707 | &resp->params.mac_reg; | ||
708 | reg_rw->offset = cpu_to_le32( | ||
709 | (u32) le16_to_cpu(reg->offset)); | ||
710 | reg_rw->value = reg->value; | ||
711 | break; | ||
712 | } | ||
713 | case HostCmd_CMD_BBP_REG_ACCESS: | ||
714 | { | ||
715 | struct host_cmd_ds_bbp_reg_access *reg; | ||
716 | reg = (struct host_cmd_ds_bbp_reg_access *) | ||
717 | &resp->params.bbp_reg; | ||
718 | reg_rw->offset = cpu_to_le32( | ||
719 | (u32) le16_to_cpu(reg->offset)); | ||
720 | reg_rw->value = cpu_to_le32((u32) reg->value); | ||
721 | break; | ||
722 | } | ||
723 | |||
724 | case HostCmd_CMD_RF_REG_ACCESS: | ||
725 | { | ||
726 | struct host_cmd_ds_rf_reg_access *reg; | ||
727 | reg = (struct host_cmd_ds_rf_reg_access *) | ||
728 | &resp->params.rf_reg; | ||
729 | reg_rw->offset = cpu_to_le32( | ||
730 | (u32) le16_to_cpu(reg->offset)); | ||
731 | reg_rw->value = cpu_to_le32((u32) reg->value); | ||
732 | break; | ||
733 | } | ||
734 | case HostCmd_CMD_PMIC_REG_ACCESS: | ||
735 | { | ||
736 | struct host_cmd_ds_pmic_reg_access *reg; | ||
737 | reg = (struct host_cmd_ds_pmic_reg_access *) | ||
738 | &resp->params.pmic_reg; | ||
739 | reg_rw->offset = cpu_to_le32( | ||
740 | (u32) le16_to_cpu(reg->offset)); | ||
741 | reg_rw->value = cpu_to_le32((u32) reg->value); | ||
742 | break; | ||
743 | } | ||
744 | case HostCmd_CMD_CAU_REG_ACCESS: | ||
745 | { | ||
746 | struct host_cmd_ds_rf_reg_access *reg; | ||
747 | reg = (struct host_cmd_ds_rf_reg_access *) | ||
748 | &resp->params.rf_reg; | ||
749 | reg_rw->offset = cpu_to_le32( | ||
750 | (u32) le16_to_cpu(reg->offset)); | ||
751 | reg_rw->value = cpu_to_le32((u32) reg->value); | ||
752 | break; | ||
753 | } | ||
754 | case HostCmd_CMD_802_11_EEPROM_ACCESS: | ||
755 | { | ||
756 | struct host_cmd_ds_802_11_eeprom_access | ||
757 | *cmd_eeprom = | ||
758 | (struct host_cmd_ds_802_11_eeprom_access | ||
759 | *) &resp->params.eeprom; | ||
760 | pr_debug("info: EEPROM read len=%x\n", | ||
761 | cmd_eeprom->byte_count); | ||
762 | if (le16_to_cpu(eeprom->byte_count) < | ||
763 | le16_to_cpu( | ||
764 | cmd_eeprom->byte_count)) { | ||
765 | eeprom->byte_count = cpu_to_le16(0); | ||
766 | pr_debug("info: EEPROM read " | ||
767 | "length is too big\n"); | ||
768 | return -1; | ||
769 | } | ||
770 | eeprom->offset = cmd_eeprom->offset; | ||
771 | eeprom->byte_count = cmd_eeprom->byte_count; | ||
772 | if (le16_to_cpu(eeprom->byte_count) > 0) | ||
773 | memcpy(&eeprom->value, | ||
774 | &cmd_eeprom->value, | ||
775 | le16_to_cpu(eeprom->byte_count)); | ||
776 | |||
777 | break; | ||
778 | } | ||
779 | default: | ||
780 | return -1; | ||
781 | } | ||
782 | } | ||
783 | return 0; | ||
784 | } | ||
785 | |||
786 | /* | ||
787 | * This function handles the command response of get IBSS coalescing status. | ||
788 | * | ||
789 | * If the received BSSID is different than the current one, the current BSSID, | ||
790 | * beacon interval, ATIM window and ERP information are updated, along with | ||
791 | * changing the ad-hoc state accordingly. | ||
792 | */ | ||
793 | static int mwifiex_ret_ibss_coalescing_status(struct mwifiex_private *priv, | ||
794 | struct host_cmd_ds_command *resp) | ||
795 | { | ||
796 | struct host_cmd_ds_802_11_ibss_status *ibss_coal_resp = | ||
797 | &(resp->params.ibss_coalescing); | ||
798 | u8 zero_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; | ||
799 | |||
800 | if (le16_to_cpu(ibss_coal_resp->action) == HostCmd_ACT_GEN_SET) | ||
801 | return 0; | ||
802 | |||
803 | dev_dbg(priv->adapter->dev, | ||
804 | "info: new BSSID %pM\n", ibss_coal_resp->bssid); | ||
805 | |||
806 | /* If rsp has NULL BSSID, Just return..... No Action */ | ||
807 | if (!memcmp(ibss_coal_resp->bssid, zero_mac, ETH_ALEN)) { | ||
808 | dev_warn(priv->adapter->dev, "new BSSID is NULL\n"); | ||
809 | return 0; | ||
810 | } | ||
811 | |||
812 | /* If BSSID is diff, modify current BSS parameters */ | ||
813 | if (memcmp(priv->curr_bss_params.bss_descriptor.mac_address, | ||
814 | ibss_coal_resp->bssid, ETH_ALEN)) { | ||
815 | /* BSSID */ | ||
816 | memcpy(priv->curr_bss_params.bss_descriptor.mac_address, | ||
817 | ibss_coal_resp->bssid, ETH_ALEN); | ||
818 | |||
819 | /* Beacon Interval */ | ||
820 | priv->curr_bss_params.bss_descriptor.beacon_period | ||
821 | = le16_to_cpu(ibss_coal_resp->beacon_interval); | ||
822 | |||
823 | /* ERP Information */ | ||
824 | priv->curr_bss_params.bss_descriptor.erp_flags = | ||
825 | (u8) le16_to_cpu(ibss_coal_resp->use_g_rate_protect); | ||
826 | |||
827 | priv->adhoc_state = ADHOC_COALESCED; | ||
828 | } | ||
829 | |||
830 | return 0; | ||
831 | } | ||
832 | |||
833 | /* | ||
834 | * This function handles the command responses. | ||
835 | * | ||
836 | * This is a generic function, which calls command specific | ||
837 | * response handlers based on the command ID. | ||
838 | */ | ||
839 | int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, | ||
840 | u16 cmdresp_no, void *cmd_buf, void *wq_buf) | ||
841 | { | ||
842 | int ret = 0; | ||
843 | struct mwifiex_adapter *adapter = priv->adapter; | ||
844 | struct host_cmd_ds_command *resp = | ||
845 | (struct host_cmd_ds_command *) cmd_buf; | ||
846 | struct mwifiex_wait_queue *wait_queue = | ||
847 | (struct mwifiex_wait_queue *) wq_buf; | ||
848 | void *data_buf = adapter->curr_cmd->data_buf; | ||
849 | |||
850 | /* If the command is not successful, cleanup and return failure */ | ||
851 | if (resp->result != HostCmd_RESULT_OK) { | ||
852 | mwifiex_process_cmdresp_error(priv, resp, wait_queue); | ||
853 | return -1; | ||
854 | } | ||
855 | /* Command successful, handle response */ | ||
856 | switch (cmdresp_no) { | ||
857 | case HostCmd_CMD_GET_HW_SPEC: | ||
858 | ret = mwifiex_ret_get_hw_spec(priv, resp); | ||
859 | break; | ||
860 | case HostCmd_CMD_MAC_CONTROL: | ||
861 | break; | ||
862 | case HostCmd_CMD_802_11_MAC_ADDRESS: | ||
863 | ret = mwifiex_ret_802_11_mac_address(priv, resp); | ||
864 | break; | ||
865 | case HostCmd_CMD_MAC_MULTICAST_ADR: | ||
866 | ret = mwifiex_ret_mac_multicast_adr(priv, resp); | ||
867 | break; | ||
868 | case HostCmd_CMD_TX_RATE_CFG: | ||
869 | ret = mwifiex_ret_tx_rate_cfg(priv, resp, data_buf); | ||
870 | break; | ||
871 | case HostCmd_CMD_802_11_SCAN: | ||
872 | ret = mwifiex_ret_802_11_scan(priv, resp, wait_queue); | ||
873 | wait_queue = NULL; | ||
874 | adapter->curr_cmd->wq_buf = NULL; | ||
875 | break; | ||
876 | case HostCmd_CMD_802_11_BG_SCAN_QUERY: | ||
877 | ret = mwifiex_ret_802_11_scan(priv, resp, wait_queue); | ||
878 | dev_dbg(adapter->dev, | ||
879 | "info: CMD_RESP: BG_SCAN result is ready!\n"); | ||
880 | break; | ||
881 | case HostCmd_CMD_TXPWR_CFG: | ||
882 | ret = mwifiex_ret_tx_power_cfg(priv, resp, data_buf); | ||
883 | break; | ||
884 | case HostCmd_CMD_802_11_PS_MODE_ENH: | ||
885 | ret = mwifiex_ret_enh_power_mode(priv, resp, data_buf); | ||
886 | break; | ||
887 | case HostCmd_CMD_802_11_HS_CFG_ENH: | ||
888 | ret = mwifiex_ret_802_11_hs_cfg(priv, resp); | ||
889 | break; | ||
890 | case HostCmd_CMD_802_11_ASSOCIATE: | ||
891 | ret = mwifiex_ret_802_11_associate(priv, resp, wait_queue); | ||
892 | break; | ||
893 | case HostCmd_CMD_802_11_DEAUTHENTICATE: | ||
894 | ret = mwifiex_ret_802_11_deauthenticate(priv, resp); | ||
895 | break; | ||
896 | case HostCmd_CMD_802_11_AD_HOC_START: | ||
897 | case HostCmd_CMD_802_11_AD_HOC_JOIN: | ||
898 | ret = mwifiex_ret_802_11_ad_hoc(priv, resp, wait_queue); | ||
899 | break; | ||
900 | case HostCmd_CMD_802_11_AD_HOC_STOP: | ||
901 | ret = mwifiex_ret_802_11_ad_hoc_stop(priv, resp); | ||
902 | break; | ||
903 | case HostCmd_CMD_802_11_GET_LOG: | ||
904 | ret = mwifiex_ret_get_log(priv, resp, data_buf); | ||
905 | break; | ||
906 | case HostCmd_CMD_RSSI_INFO: | ||
907 | ret = mwifiex_ret_802_11_rssi_info(priv, resp, data_buf); | ||
908 | break; | ||
909 | case HostCmd_CMD_802_11_SNMP_MIB: | ||
910 | ret = mwifiex_ret_802_11_snmp_mib(priv, resp, data_buf); | ||
911 | break; | ||
912 | case HostCmd_CMD_802_11_TX_RATE_QUERY: | ||
913 | ret = mwifiex_ret_802_11_tx_rate_query(priv, resp); | ||
914 | break; | ||
915 | case HostCmd_CMD_802_11_RF_CHANNEL: | ||
916 | ret = mwifiex_ret_802_11_rf_channel(priv, resp, data_buf); | ||
917 | break; | ||
918 | case HostCmd_CMD_VERSION_EXT: | ||
919 | ret = mwifiex_ret_ver_ext(priv, resp, data_buf); | ||
920 | break; | ||
921 | case HostCmd_CMD_FUNC_INIT: | ||
922 | case HostCmd_CMD_FUNC_SHUTDOWN: | ||
923 | break; | ||
924 | case HostCmd_CMD_802_11_KEY_MATERIAL: | ||
925 | ret = mwifiex_ret_802_11_key_material(priv, resp); | ||
926 | break; | ||
927 | case HostCmd_CMD_802_11D_DOMAIN_INFO: | ||
928 | ret = mwifiex_ret_802_11d_domain_info(priv, resp); | ||
929 | break; | ||
930 | case HostCmd_CMD_11N_ADDBA_REQ: | ||
931 | ret = mwifiex_ret_11n_addba_req(priv, resp); | ||
932 | break; | ||
933 | case HostCmd_CMD_11N_DELBA: | ||
934 | ret = mwifiex_ret_11n_delba(priv, resp); | ||
935 | break; | ||
936 | case HostCmd_CMD_11N_ADDBA_RSP: | ||
937 | ret = mwifiex_ret_11n_addba_resp(priv, resp); | ||
938 | break; | ||
939 | case HostCmd_CMD_RECONFIGURE_TX_BUFF: | ||
940 | adapter->tx_buf_size = (u16) le16_to_cpu(resp->params. | ||
941 | tx_buf.buff_size); | ||
942 | adapter->tx_buf_size = (adapter->tx_buf_size / | ||
943 | MWIFIEX_SDIO_BLOCK_SIZE) * | ||
944 | MWIFIEX_SDIO_BLOCK_SIZE; | ||
945 | adapter->curr_tx_buf_size = adapter->tx_buf_size; | ||
946 | dev_dbg(adapter->dev, | ||
947 | "cmd: max_tx_buf_size=%d, tx_buf_size=%d\n", | ||
948 | adapter->max_tx_buf_size, adapter->tx_buf_size); | ||
949 | |||
950 | if (adapter->if_ops.update_mp_end_port) | ||
951 | adapter->if_ops.update_mp_end_port(adapter, | ||
952 | le16_to_cpu(resp-> | ||
953 | params. | ||
954 | tx_buf. | ||
955 | mp_end_port)); | ||
956 | break; | ||
957 | case HostCmd_CMD_AMSDU_AGGR_CTRL: | ||
958 | ret = mwifiex_ret_amsdu_aggr_ctrl(priv, resp, data_buf); | ||
959 | break; | ||
960 | case HostCmd_CMD_WMM_GET_STATUS: | ||
961 | ret = mwifiex_ret_wmm_get_status(priv, resp); | ||
962 | break; | ||
963 | case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS: | ||
964 | ret = mwifiex_ret_ibss_coalescing_status(priv, resp); | ||
965 | break; | ||
966 | case HostCmd_CMD_MAC_REG_ACCESS: | ||
967 | case HostCmd_CMD_BBP_REG_ACCESS: | ||
968 | case HostCmd_CMD_RF_REG_ACCESS: | ||
969 | case HostCmd_CMD_PMIC_REG_ACCESS: | ||
970 | case HostCmd_CMD_CAU_REG_ACCESS: | ||
971 | case HostCmd_CMD_802_11_EEPROM_ACCESS: | ||
972 | ret = mwifiex_ret_reg_access(cmdresp_no, resp, data_buf); | ||
973 | break; | ||
974 | case HostCmd_CMD_SET_BSS_MODE: | ||
975 | break; | ||
976 | case HostCmd_CMD_11N_CFG: | ||
977 | ret = mwifiex_ret_11n_cfg(priv, resp, data_buf); | ||
978 | break; | ||
979 | default: | ||
980 | dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n", | ||
981 | resp->command); | ||
982 | break; | ||
983 | } | ||
984 | |||
985 | return ret; | ||
986 | } | ||