2 * Marvell Wireless LAN device driver: utility functions
4 * Copyright (C) 2011-2014, 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.
28 static struct mwifiex_debug_data items
[] = {
29 {"debug_mask", item_size(debug_mask
),
30 item_addr(debug_mask
), 1},
31 {"int_counter", item_size(int_counter
),
32 item_addr(int_counter
), 1},
33 {"wmm_ac_vo", item_size(packets_out
[WMM_AC_VO
]),
34 item_addr(packets_out
[WMM_AC_VO
]), 1},
35 {"wmm_ac_vi", item_size(packets_out
[WMM_AC_VI
]),
36 item_addr(packets_out
[WMM_AC_VI
]), 1},
37 {"wmm_ac_be", item_size(packets_out
[WMM_AC_BE
]),
38 item_addr(packets_out
[WMM_AC_BE
]), 1},
39 {"wmm_ac_bk", item_size(packets_out
[WMM_AC_BK
]),
40 item_addr(packets_out
[WMM_AC_BK
]), 1},
41 {"tx_buf_size", item_size(tx_buf_size
),
42 item_addr(tx_buf_size
), 1},
43 {"curr_tx_buf_size", item_size(curr_tx_buf_size
),
44 item_addr(curr_tx_buf_size
), 1},
45 {"ps_mode", item_size(ps_mode
),
46 item_addr(ps_mode
), 1},
47 {"ps_state", item_size(ps_state
),
48 item_addr(ps_state
), 1},
49 {"is_deep_sleep", item_size(is_deep_sleep
),
50 item_addr(is_deep_sleep
), 1},
51 {"wakeup_dev_req", item_size(pm_wakeup_card_req
),
52 item_addr(pm_wakeup_card_req
), 1},
53 {"wakeup_tries", item_size(pm_wakeup_fw_try
),
54 item_addr(pm_wakeup_fw_try
), 1},
55 {"hs_configured", item_size(is_hs_configured
),
56 item_addr(is_hs_configured
), 1},
57 {"hs_activated", item_size(hs_activated
),
58 item_addr(hs_activated
), 1},
59 {"num_tx_timeout", item_size(num_tx_timeout
),
60 item_addr(num_tx_timeout
), 1},
61 {"is_cmd_timedout", item_size(is_cmd_timedout
),
62 item_addr(is_cmd_timedout
), 1},
63 {"timeout_cmd_id", item_size(timeout_cmd_id
),
64 item_addr(timeout_cmd_id
), 1},
65 {"timeout_cmd_act", item_size(timeout_cmd_act
),
66 item_addr(timeout_cmd_act
), 1},
67 {"last_cmd_id", item_size(last_cmd_id
),
68 item_addr(last_cmd_id
), DBG_CMD_NUM
},
69 {"last_cmd_act", item_size(last_cmd_act
),
70 item_addr(last_cmd_act
), DBG_CMD_NUM
},
71 {"last_cmd_index", item_size(last_cmd_index
),
72 item_addr(last_cmd_index
), 1},
73 {"last_cmd_resp_id", item_size(last_cmd_resp_id
),
74 item_addr(last_cmd_resp_id
), DBG_CMD_NUM
},
75 {"last_cmd_resp_index", item_size(last_cmd_resp_index
),
76 item_addr(last_cmd_resp_index
), 1},
77 {"last_event", item_size(last_event
),
78 item_addr(last_event
), DBG_CMD_NUM
},
79 {"last_event_index", item_size(last_event_index
),
80 item_addr(last_event_index
), 1},
81 {"last_mp_wr_bitmap", item_size(last_mp_wr_bitmap
),
82 item_addr(last_mp_wr_bitmap
), MWIFIEX_DBG_SDIO_MP_NUM
},
83 {"last_mp_wr_ports", item_size(last_mp_wr_ports
),
84 item_addr(last_mp_wr_ports
), MWIFIEX_DBG_SDIO_MP_NUM
},
85 {"last_mp_wr_len", item_size(last_mp_wr_len
),
86 item_addr(last_mp_wr_len
), MWIFIEX_DBG_SDIO_MP_NUM
},
87 {"last_mp_curr_wr_port", item_size(last_mp_curr_wr_port
),
88 item_addr(last_mp_curr_wr_port
), MWIFIEX_DBG_SDIO_MP_NUM
},
89 {"last_sdio_mp_index", item_size(last_sdio_mp_index
),
90 item_addr(last_sdio_mp_index
), 1},
91 {"num_cmd_h2c_fail", item_size(num_cmd_host_to_card_failure
),
92 item_addr(num_cmd_host_to_card_failure
), 1},
93 {"num_cmd_sleep_cfm_fail",
94 item_size(num_cmd_sleep_cfm_host_to_card_failure
),
95 item_addr(num_cmd_sleep_cfm_host_to_card_failure
), 1},
96 {"num_tx_h2c_fail", item_size(num_tx_host_to_card_failure
),
97 item_addr(num_tx_host_to_card_failure
), 1},
98 {"num_evt_deauth", item_size(num_event_deauth
),
99 item_addr(num_event_deauth
), 1},
100 {"num_evt_disassoc", item_size(num_event_disassoc
),
101 item_addr(num_event_disassoc
), 1},
102 {"num_evt_link_lost", item_size(num_event_link_lost
),
103 item_addr(num_event_link_lost
), 1},
104 {"num_cmd_deauth", item_size(num_cmd_deauth
),
105 item_addr(num_cmd_deauth
), 1},
106 {"num_cmd_assoc_ok", item_size(num_cmd_assoc_success
),
107 item_addr(num_cmd_assoc_success
), 1},
108 {"num_cmd_assoc_fail", item_size(num_cmd_assoc_failure
),
109 item_addr(num_cmd_assoc_failure
), 1},
110 {"cmd_sent", item_size(cmd_sent
),
111 item_addr(cmd_sent
), 1},
112 {"data_sent", item_size(data_sent
),
113 item_addr(data_sent
), 1},
114 {"cmd_resp_received", item_size(cmd_resp_received
),
115 item_addr(cmd_resp_received
), 1},
116 {"event_received", item_size(event_received
),
117 item_addr(event_received
), 1},
119 /* variables defined in struct mwifiex_adapter */
120 {"cmd_pending", adapter_item_size(cmd_pending
),
121 adapter_item_addr(cmd_pending
), 1},
122 {"tx_pending", adapter_item_size(tx_pending
),
123 adapter_item_addr(tx_pending
), 1},
124 {"rx_pending", adapter_item_size(rx_pending
),
125 adapter_item_addr(rx_pending
), 1},
128 static int num_of_items
= ARRAY_SIZE(items
);
131 * Firmware initialization complete callback handler.
133 * This function wakes up the function waiting on the init
134 * wait queue for the firmware initialization to complete.
136 int mwifiex_init_fw_complete(struct mwifiex_adapter
*adapter
)
139 if (adapter
->hw_status
== MWIFIEX_HW_STATUS_READY
)
140 if (adapter
->if_ops
.init_fw_port
)
141 adapter
->if_ops
.init_fw_port(adapter
);
143 adapter
->init_wait_q_woken
= true;
144 wake_up_interruptible(&adapter
->init_wait_q
);
149 * This function sends init/shutdown command
152 int mwifiex_init_shutdown_fw(struct mwifiex_private
*priv
,
153 u32 func_init_shutdown
)
157 if (func_init_shutdown
== MWIFIEX_FUNC_INIT
) {
158 cmd
= HostCmd_CMD_FUNC_INIT
;
159 } else if (func_init_shutdown
== MWIFIEX_FUNC_SHUTDOWN
) {
160 cmd
= HostCmd_CMD_FUNC_SHUTDOWN
;
162 mwifiex_dbg(priv
->adapter
, ERROR
,
163 "unsupported parameter\n");
167 return mwifiex_send_cmd(priv
, cmd
, HostCmd_ACT_GEN_SET
, 0, NULL
, true);
169 EXPORT_SYMBOL_GPL(mwifiex_init_shutdown_fw
);
172 * IOCTL request handler to set/get debug information.
174 * This function collates/sets the information from/to different driver
177 int mwifiex_get_debug_info(struct mwifiex_private
*priv
,
178 struct mwifiex_debug_info
*info
)
180 struct mwifiex_adapter
*adapter
= priv
->adapter
;
183 info
->debug_mask
= adapter
->debug_mask
;
184 memcpy(info
->packets_out
,
185 priv
->wmm
.packets_out
,
186 sizeof(priv
->wmm
.packets_out
));
187 info
->curr_tx_buf_size
= (u32
) adapter
->curr_tx_buf_size
;
188 info
->tx_buf_size
= (u32
) adapter
->tx_buf_size
;
189 info
->rx_tbl_num
= mwifiex_get_rx_reorder_tbl(priv
,
191 info
->tx_tbl_num
= mwifiex_get_tx_ba_stream_tbl(priv
,
193 info
->tdls_peer_num
= mwifiex_get_tdls_list(priv
,
195 info
->ps_mode
= adapter
->ps_mode
;
196 info
->ps_state
= adapter
->ps_state
;
197 info
->is_deep_sleep
= adapter
->is_deep_sleep
;
198 info
->pm_wakeup_card_req
= adapter
->pm_wakeup_card_req
;
199 info
->pm_wakeup_fw_try
= adapter
->pm_wakeup_fw_try
;
200 info
->is_hs_configured
= adapter
->is_hs_configured
;
201 info
->hs_activated
= adapter
->hs_activated
;
202 info
->is_cmd_timedout
= adapter
->is_cmd_timedout
;
203 info
->num_cmd_host_to_card_failure
204 = adapter
->dbg
.num_cmd_host_to_card_failure
;
205 info
->num_cmd_sleep_cfm_host_to_card_failure
206 = adapter
->dbg
.num_cmd_sleep_cfm_host_to_card_failure
;
207 info
->num_tx_host_to_card_failure
208 = adapter
->dbg
.num_tx_host_to_card_failure
;
209 info
->num_event_deauth
= adapter
->dbg
.num_event_deauth
;
210 info
->num_event_disassoc
= adapter
->dbg
.num_event_disassoc
;
211 info
->num_event_link_lost
= adapter
->dbg
.num_event_link_lost
;
212 info
->num_cmd_deauth
= adapter
->dbg
.num_cmd_deauth
;
213 info
->num_cmd_assoc_success
=
214 adapter
->dbg
.num_cmd_assoc_success
;
215 info
->num_cmd_assoc_failure
=
216 adapter
->dbg
.num_cmd_assoc_failure
;
217 info
->num_tx_timeout
= adapter
->dbg
.num_tx_timeout
;
218 info
->timeout_cmd_id
= adapter
->dbg
.timeout_cmd_id
;
219 info
->timeout_cmd_act
= adapter
->dbg
.timeout_cmd_act
;
220 memcpy(info
->last_cmd_id
, adapter
->dbg
.last_cmd_id
,
221 sizeof(adapter
->dbg
.last_cmd_id
));
222 memcpy(info
->last_cmd_act
, adapter
->dbg
.last_cmd_act
,
223 sizeof(adapter
->dbg
.last_cmd_act
));
224 info
->last_cmd_index
= adapter
->dbg
.last_cmd_index
;
225 memcpy(info
->last_cmd_resp_id
, adapter
->dbg
.last_cmd_resp_id
,
226 sizeof(adapter
->dbg
.last_cmd_resp_id
));
227 info
->last_cmd_resp_index
= adapter
->dbg
.last_cmd_resp_index
;
228 memcpy(info
->last_event
, adapter
->dbg
.last_event
,
229 sizeof(adapter
->dbg
.last_event
));
230 info
->last_event_index
= adapter
->dbg
.last_event_index
;
231 memcpy(info
->last_mp_wr_bitmap
, adapter
->dbg
.last_mp_wr_bitmap
,
232 sizeof(adapter
->dbg
.last_mp_wr_bitmap
));
233 memcpy(info
->last_mp_wr_ports
, adapter
->dbg
.last_mp_wr_ports
,
234 sizeof(adapter
->dbg
.last_mp_wr_ports
));
235 memcpy(info
->last_mp_curr_wr_port
,
236 adapter
->dbg
.last_mp_curr_wr_port
,
237 sizeof(adapter
->dbg
.last_mp_curr_wr_port
));
238 memcpy(info
->last_mp_wr_len
, adapter
->dbg
.last_mp_wr_len
,
239 sizeof(adapter
->dbg
.last_mp_wr_len
));
240 info
->last_sdio_mp_index
= adapter
->dbg
.last_sdio_mp_index
;
241 info
->data_sent
= adapter
->data_sent
;
242 info
->cmd_sent
= adapter
->cmd_sent
;
243 info
->cmd_resp_received
= adapter
->cmd_resp_received
;
249 int mwifiex_debug_info_to_buffer(struct mwifiex_private
*priv
, char *buf
,
250 struct mwifiex_debug_info
*info
)
253 struct mwifiex_debug_data
*d
= &items
[0];
261 for (i
= 0; i
< num_of_items
; i
++) {
262 p
+= sprintf(p
, "%s=", d
[i
].name
);
264 size
= d
[i
].size
/ d
[i
].num
;
266 if (i
< (num_of_items
- 3))
267 addr
= d
[i
].addr
+ (size_t)info
;
268 else /* The last 3 items are struct mwifiex_adapter variables */
269 addr
= d
[i
].addr
+ (size_t)priv
->adapter
;
271 for (j
= 0; j
< d
[i
].num
; j
++) {
277 val
= get_unaligned((u16
*)addr
);
280 val
= get_unaligned((u32
*)addr
);
283 val
= get_unaligned((long long *)addr
);
290 p
+= sprintf(p
, "%#lx ", val
);
294 p
+= sprintf(p
, "\n");
297 if (info
->tx_tbl_num
) {
298 p
+= sprintf(p
, "Tx BA stream table:\n");
299 for (i
= 0; i
< info
->tx_tbl_num
; i
++)
300 p
+= sprintf(p
, "tid = %d, ra = %pM\n",
301 info
->tx_tbl
[i
].tid
, info
->tx_tbl
[i
].ra
);
304 if (info
->rx_tbl_num
) {
305 p
+= sprintf(p
, "Rx reorder table:\n");
306 for (i
= 0; i
< info
->rx_tbl_num
; i
++) {
307 p
+= sprintf(p
, "tid = %d, ta = %pM, ",
310 p
+= sprintf(p
, "start_win = %d, ",
311 info
->rx_tbl
[i
].start_win
);
312 p
+= sprintf(p
, "win_size = %d, buffer: ",
313 info
->rx_tbl
[i
].win_size
);
315 for (j
= 0; j
< info
->rx_tbl
[i
].win_size
; j
++)
316 p
+= sprintf(p
, "%c ",
317 info
->rx_tbl
[i
].buffer
[j
] ?
320 p
+= sprintf(p
, "\n");
324 if (info
->tdls_peer_num
) {
325 p
+= sprintf(p
, "TDLS peer table:\n");
326 for (i
= 0; i
< info
->tdls_peer_num
; i
++) {
327 p
+= sprintf(p
, "peer = %pM",
328 info
->tdls_list
[i
].peer_addr
);
329 p
+= sprintf(p
, "\n");
337 mwifiex_parse_mgmt_packet(struct mwifiex_private
*priv
, u8
*payload
, u16 len
,
341 u8 category
, action_code
, *addr2
;
342 struct ieee80211_hdr
*ieee_hdr
= (void *)payload
;
344 stype
= (le16_to_cpu(ieee_hdr
->frame_control
) & IEEE80211_FCTL_STYPE
);
347 case IEEE80211_STYPE_ACTION
:
348 category
= *(payload
+ sizeof(struct ieee80211_hdr
));
350 case WLAN_CATEGORY_PUBLIC
:
351 action_code
= *(payload
+ sizeof(struct ieee80211_hdr
)
353 if (action_code
== WLAN_PUB_ACTION_TDLS_DISCOVER_RES
) {
354 addr2
= ieee_hdr
->addr2
;
355 mwifiex_dbg(priv
->adapter
, INFO
,
356 "TDLS discovery response %pM nf=%d, snr=%d\n",
357 addr2
, rx_pd
->nf
, rx_pd
->snr
);
358 mwifiex_auto_tdls_update_peer_signal(priv
,
364 case WLAN_CATEGORY_BACK
:
365 /*we dont indicate BACK action frames to cfg80211*/
366 mwifiex_dbg(priv
->adapter
, INFO
,
367 "drop BACK action frames");
370 mwifiex_dbg(priv
->adapter
, INFO
,
371 "unknown public action frame category %d\n",
376 mwifiex_dbg(priv
->adapter
, INFO
,
377 "unknown mgmt frame subtype %#x\n", stype
);
384 * This function processes the received management packet and send it
388 mwifiex_process_mgmt_packet(struct mwifiex_private
*priv
,
393 struct ieee80211_hdr
*ieee_hdr
;
398 if (!priv
->mgmt_frame_mask
||
399 priv
->wdev
.iftype
== NL80211_IFTYPE_UNSPECIFIED
) {
400 mwifiex_dbg(priv
->adapter
, ERROR
,
401 "do not receive mgmt frames on uninitialized intf");
405 rx_pd
= (struct rxpd
*)skb
->data
;
407 skb_pull(skb
, le16_to_cpu(rx_pd
->rx_pkt_offset
));
408 skb_pull(skb
, sizeof(pkt_len
));
410 pkt_len
= le16_to_cpu(rx_pd
->rx_pkt_length
);
412 ieee_hdr
= (void *)skb
->data
;
413 if (ieee80211_is_mgmt(ieee_hdr
->frame_control
)) {
414 if (mwifiex_parse_mgmt_packet(priv
, (u8
*)ieee_hdr
,
418 /* Remove address4 */
419 memmove(skb
->data
+ sizeof(struct ieee80211_hdr_3addr
),
420 skb
->data
+ sizeof(struct ieee80211_hdr
),
421 pkt_len
- sizeof(struct ieee80211_hdr
));
423 pkt_len
-= ETH_ALEN
+ sizeof(pkt_len
);
424 rx_pd
->rx_pkt_length
= cpu_to_le16(pkt_len
);
426 cfg80211_rx_mgmt(&priv
->wdev
, priv
->roc_cfg
.chan
.center_freq
,
427 CAL_RSSI(rx_pd
->snr
, rx_pd
->nf
), skb
->data
, pkt_len
,
434 * This function processes the received packet before sending it to the
437 * It extracts the SKB from the received buffer and sends it to kernel.
438 * In case the received buffer does not contain the data in SKB format,
439 * the function creates a blank SKB, fills it with the data from the
440 * received buffer and then sends this new SKB to the kernel.
442 int mwifiex_recv_packet(struct mwifiex_private
*priv
, struct sk_buff
*skb
)
444 struct mwifiex_sta_node
*src_node
;
445 struct ethhdr
*p_ethhdr
;
450 priv
->stats
.rx_bytes
+= skb
->len
;
451 priv
->stats
.rx_packets
++;
453 if (GET_BSS_ROLE(priv
) == MWIFIEX_BSS_ROLE_UAP
) {
454 p_ethhdr
= (void *)skb
->data
;
455 src_node
= mwifiex_get_sta_entry(priv
, p_ethhdr
->h_source
);
457 src_node
->stats
.last_rx
= jiffies
;
458 src_node
->stats
.rx_bytes
+= skb
->len
;
459 src_node
->stats
.rx_packets
++;
463 skb
->dev
= priv
->netdev
;
464 skb
->protocol
= eth_type_trans(skb
, priv
->netdev
);
465 skb
->ip_summed
= CHECKSUM_NONE
;
467 /* This is required only in case of 11n and USB/PCIE as we alloc
468 * a buffer of 4K only if its 11N (to be able to receive 4K
469 * AMSDU packets). In case of SD we allocate buffers based
470 * on the size of packet and hence this is not needed.
472 * Modifying the truesize here as our allocation for each
473 * skb is 4K but we only receive 2K packets and this cause
474 * the kernel to start dropping packets in case where
475 * application has allocated buffer based on 2K size i.e.
476 * if there a 64K packet received (in IP fragments and
477 * application allocates 64K to receive this packet but
478 * this packet would almost double up because we allocate
479 * each 1.5K fragment in 4K and pass it up. As soon as the
480 * 64K limit hits kernel will start to drop rest of the
481 * fragments. Currently we fail the Filesndl-ht.scr script
482 * for UDP, hence this fix
484 if ((priv
->adapter
->iface_type
== MWIFIEX_USB
||
485 priv
->adapter
->iface_type
== MWIFIEX_PCIE
) &&
486 (skb
->truesize
> MWIFIEX_RX_DATA_BUF_SIZE
))
487 skb
->truesize
+= (skb
->len
- MWIFIEX_RX_DATA_BUF_SIZE
);
498 * IOCTL completion callback handler.
500 * This function is called when a pending IOCTL is completed.
502 * If work queue support is enabled, the function wakes up the
503 * corresponding waiting function. Otherwise, it processes the
504 * IOCTL response and frees the response buffer.
506 int mwifiex_complete_cmd(struct mwifiex_adapter
*adapter
,
507 struct cmd_ctrl_node
*cmd_node
)
509 WARN_ON(!cmd_node
->wait_q_enabled
);
510 mwifiex_dbg(adapter
, CMD
, "cmd completed: status=%d\n",
511 adapter
->cmd_wait_q
.status
);
513 *cmd_node
->condition
= true;
514 wake_up_interruptible(&adapter
->cmd_wait_q
.wait
);
519 /* This function will return the pointer to station entry in station list
520 * table which matches specified mac address.
521 * This function should be called after acquiring RA list spinlock.
522 * NULL is returned if station entry is not found in associated STA list.
524 struct mwifiex_sta_node
*
525 mwifiex_get_sta_entry(struct mwifiex_private
*priv
, const u8
*mac
)
527 struct mwifiex_sta_node
*node
;
532 list_for_each_entry(node
, &priv
->sta_list
, list
) {
533 if (!memcmp(node
->mac_addr
, mac
, ETH_ALEN
))
540 static struct mwifiex_sta_node
*
541 mwifiex_get_tdls_sta_entry(struct mwifiex_private
*priv
, u8 status
)
543 struct mwifiex_sta_node
*node
;
545 list_for_each_entry(node
, &priv
->sta_list
, list
) {
546 if (node
->tdls_status
== status
)
553 /* If tdls channel switching is on-going, tx data traffic should be
554 * blocked until the switching stage completed.
556 u8
mwifiex_is_tdls_chan_switching(struct mwifiex_private
*priv
)
558 struct mwifiex_sta_node
*sta_ptr
;
560 if (!priv
|| !ISSUPP_TDLS_ENABLED(priv
->adapter
->fw_cap_info
))
563 sta_ptr
= mwifiex_get_tdls_sta_entry(priv
, TDLS_CHAN_SWITCHING
);
570 u8
mwifiex_is_tdls_off_chan(struct mwifiex_private
*priv
)
572 struct mwifiex_sta_node
*sta_ptr
;
574 if (!priv
|| !ISSUPP_TDLS_ENABLED(priv
->adapter
->fw_cap_info
))
577 sta_ptr
= mwifiex_get_tdls_sta_entry(priv
, TDLS_IN_OFF_CHAN
);
584 /* If tdls channel switching is on-going or tdls operate on off-channel,
585 * cmd path should be blocked until tdls switched to base-channel.
587 u8
mwifiex_is_send_cmd_allowed(struct mwifiex_private
*priv
)
589 if (!priv
|| !ISSUPP_TDLS_ENABLED(priv
->adapter
->fw_cap_info
))
592 if (mwifiex_is_tdls_chan_switching(priv
) ||
593 mwifiex_is_tdls_off_chan(priv
))
599 /* This function will add a sta_node entry to associated station list
600 * table with the given mac address.
601 * If entry exist already, existing entry is returned.
602 * If received mac address is NULL, NULL is returned.
604 struct mwifiex_sta_node
*
605 mwifiex_add_sta_entry(struct mwifiex_private
*priv
, const u8
*mac
)
607 struct mwifiex_sta_node
*node
;
613 spin_lock_irqsave(&priv
->sta_list_spinlock
, flags
);
614 node
= mwifiex_get_sta_entry(priv
, mac
);
618 node
= kzalloc(sizeof(*node
), GFP_ATOMIC
);
622 memcpy(node
->mac_addr
, mac
, ETH_ALEN
);
623 list_add_tail(&node
->list
, &priv
->sta_list
);
626 spin_unlock_irqrestore(&priv
->sta_list_spinlock
, flags
);
630 /* This function will search for HT IE in association request IEs
631 * and set station HT parameters accordingly.
634 mwifiex_set_sta_ht_cap(struct mwifiex_private
*priv
, const u8
*ies
,
635 int ies_len
, struct mwifiex_sta_node
*node
)
637 struct ieee_types_header
*ht_cap_ie
;
638 const struct ieee80211_ht_cap
*ht_cap
;
643 ht_cap_ie
= (void *)cfg80211_find_ie(WLAN_EID_HT_CAPABILITY
, ies
,
646 ht_cap
= (void *)(ht_cap_ie
+ 1);
647 node
->is_11n_enabled
= 1;
648 node
->max_amsdu
= le16_to_cpu(ht_cap
->cap_info
) &
649 IEEE80211_HT_CAP_MAX_AMSDU
?
650 MWIFIEX_TX_DATA_BUF_SIZE_8K
:
651 MWIFIEX_TX_DATA_BUF_SIZE_4K
;
653 node
->is_11n_enabled
= 0;
659 /* This function will delete a station entry from station list */
660 void mwifiex_del_sta_entry(struct mwifiex_private
*priv
, const u8
*mac
)
662 struct mwifiex_sta_node
*node
;
665 spin_lock_irqsave(&priv
->sta_list_spinlock
, flags
);
667 node
= mwifiex_get_sta_entry(priv
, mac
);
669 list_del(&node
->list
);
673 spin_unlock_irqrestore(&priv
->sta_list_spinlock
, flags
);
677 /* This function will delete all stations from associated station list. */
678 void mwifiex_del_all_sta_list(struct mwifiex_private
*priv
)
680 struct mwifiex_sta_node
*node
, *tmp
;
683 spin_lock_irqsave(&priv
->sta_list_spinlock
, flags
);
685 list_for_each_entry_safe(node
, tmp
, &priv
->sta_list
, list
) {
686 list_del(&node
->list
);
690 INIT_LIST_HEAD(&priv
->sta_list
);
691 spin_unlock_irqrestore(&priv
->sta_list_spinlock
, flags
);
695 /* This function adds histogram data to histogram array*/
696 void mwifiex_hist_data_add(struct mwifiex_private
*priv
,
697 u8 rx_rate
, s8 snr
, s8 nflr
)
699 struct mwifiex_histogram_data
*phist_data
= priv
->hist_data
;
701 if (atomic_read(&phist_data
->num_samples
) > MWIFIEX_HIST_MAX_SAMPLES
)
702 mwifiex_hist_data_reset(priv
);
703 mwifiex_hist_data_set(priv
, rx_rate
, snr
, nflr
);
706 /* function to add histogram record */
707 void mwifiex_hist_data_set(struct mwifiex_private
*priv
, u8 rx_rate
, s8 snr
,
710 struct mwifiex_histogram_data
*phist_data
= priv
->hist_data
;
712 s8 rssi
= snr
- nflr
;
714 atomic_inc(&phist_data
->num_samples
);
715 atomic_inc(&phist_data
->rx_rate
[rx_rate
]);
716 atomic_inc(&phist_data
->snr
[snr
+ 128]);
717 atomic_inc(&phist_data
->noise_flr
[nf
+ 128]);
718 atomic_inc(&phist_data
->sig_str
[rssi
+ 128]);
721 /* function to reset histogram data during init/reset */
722 void mwifiex_hist_data_reset(struct mwifiex_private
*priv
)
725 struct mwifiex_histogram_data
*phist_data
= priv
->hist_data
;
727 atomic_set(&phist_data
->num_samples
, 0);
728 for (ix
= 0; ix
< MWIFIEX_MAX_AC_RX_RATES
; ix
++)
729 atomic_set(&phist_data
->rx_rate
[ix
], 0);
730 for (ix
= 0; ix
< MWIFIEX_MAX_SNR
; ix
++)
731 atomic_set(&phist_data
->snr
[ix
], 0);
732 for (ix
= 0; ix
< MWIFIEX_MAX_NOISE_FLR
; ix
++)
733 atomic_set(&phist_data
->noise_flr
[ix
], 0);
734 for (ix
= 0; ix
< MWIFIEX_MAX_SIG_STRENGTH
; ix
++)
735 atomic_set(&phist_data
->sig_str
[ix
], 0);
738 void *mwifiex_alloc_dma_align_buf(int rx_len
, gfp_t flags
)
743 buf_len
= rx_len
+ MWIFIEX_RX_HEADROOM
+ MWIFIEX_DMA_ALIGN_SZ
;
745 skb
= __dev_alloc_skb(buf_len
, flags
);
750 skb_reserve(skb
, MWIFIEX_RX_HEADROOM
);
752 pad
= MWIFIEX_ALIGN_ADDR(skb
->data
, MWIFIEX_DMA_ALIGN_SZ
) -
755 skb_reserve(skb
, pad
);
759 EXPORT_SYMBOL_GPL(mwifiex_alloc_dma_align_buf
);
761 void mwifiex_fw_dump_event(struct mwifiex_private
*priv
)
763 mwifiex_send_cmd(priv
, HostCmd_CMD_FW_DUMP_EVENT
, HostCmd_ACT_GEN_SET
,
766 EXPORT_SYMBOL_GPL(mwifiex_fw_dump_event
);