dmaengine: imx-sdma: Let the core do the device node validation
[linux/fpc-iii.git] / drivers / net / wireless / quantenna / qtnfmac / commands.c
blob459f6b81d2eb027b05cfbcf78bf64d5fd2d6e8c5
1 // SPDX-License-Identifier: GPL-2.0+
2 /* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */
4 #include <linux/types.h>
5 #include <linux/skbuff.h>
7 #include "cfg80211.h"
8 #include "core.h"
9 #include "qlink.h"
10 #include "qlink_util.h"
11 #include "bus.h"
12 #include "commands.h"
14 #define QTNF_SCAN_TIME_AUTO 0
16 /* Let device itself to select best values for current conditions */
17 #define QTNF_SCAN_DWELL_ACTIVE_DEFAULT QTNF_SCAN_TIME_AUTO
18 #define QTNF_SCAN_DWELL_PASSIVE_DEFAULT QTNF_SCAN_TIME_AUTO
19 #define QTNF_SCAN_SAMPLE_DURATION_DEFAULT QTNF_SCAN_TIME_AUTO
21 static int qtnf_cmd_check_reply_header(const struct qlink_resp *resp,
22 u16 cmd_id, u8 mac_id, u8 vif_id,
23 size_t resp_size)
25 if (unlikely(le16_to_cpu(resp->cmd_id) != cmd_id)) {
26 pr_warn("VIF%u.%u CMD%x: bad cmd_id in response: 0x%.4X\n",
27 mac_id, vif_id, cmd_id, le16_to_cpu(resp->cmd_id));
28 return -EINVAL;
31 if (unlikely(resp->macid != mac_id)) {
32 pr_warn("VIF%u.%u CMD%x: bad MAC in response: %u\n",
33 mac_id, vif_id, cmd_id, resp->macid);
34 return -EINVAL;
37 if (unlikely(resp->vifid != vif_id)) {
38 pr_warn("VIF%u.%u CMD%x: bad VIF in response: %u\n",
39 mac_id, vif_id, cmd_id, resp->vifid);
40 return -EINVAL;
43 if (unlikely(le16_to_cpu(resp->mhdr.len) < resp_size)) {
44 pr_warn("VIF%u.%u CMD%x: bad response size %u < %zu\n",
45 mac_id, vif_id, cmd_id,
46 le16_to_cpu(resp->mhdr.len), resp_size);
47 return -ENOSPC;
50 return 0;
53 static int qtnf_cmd_resp_result_decode(enum qlink_cmd_result qcode)
55 switch (qcode) {
56 case QLINK_CMD_RESULT_OK:
57 return 0;
58 case QLINK_CMD_RESULT_INVALID:
59 return -EINVAL;
60 case QLINK_CMD_RESULT_ENOTSUPP:
61 return -ENOTSUPP;
62 case QLINK_CMD_RESULT_ENOTFOUND:
63 return -ENOENT;
64 case QLINK_CMD_RESULT_EALREADY:
65 return -EALREADY;
66 case QLINK_CMD_RESULT_EADDRINUSE:
67 return -EADDRINUSE;
68 case QLINK_CMD_RESULT_EADDRNOTAVAIL:
69 return -EADDRNOTAVAIL;
70 case QLINK_CMD_RESULT_EBUSY:
71 return -EBUSY;
72 default:
73 return -EFAULT;
77 static int qtnf_cmd_send_with_reply(struct qtnf_bus *bus,
78 struct sk_buff *cmd_skb,
79 struct sk_buff **response_skb,
80 size_t const_resp_size,
81 size_t *var_resp_size)
83 struct qlink_cmd *cmd;
84 struct qlink_resp *resp = NULL;
85 struct sk_buff *resp_skb = NULL;
86 u16 cmd_id;
87 u8 mac_id;
88 u8 vif_id;
89 int ret;
91 cmd = (struct qlink_cmd *)cmd_skb->data;
92 cmd_id = le16_to_cpu(cmd->cmd_id);
93 mac_id = cmd->macid;
94 vif_id = cmd->vifid;
95 cmd->mhdr.len = cpu_to_le16(cmd_skb->len);
97 pr_debug("VIF%u.%u cmd=0x%.4X\n", mac_id, vif_id, cmd_id);
99 if (!qtnf_fw_is_up(bus) && cmd_id != QLINK_CMD_FW_INIT) {
100 pr_warn("VIF%u.%u: drop cmd 0x%.4X in fw state %d\n",
101 mac_id, vif_id, cmd_id, bus->fw_state);
102 dev_kfree_skb(cmd_skb);
103 return -ENODEV;
106 ret = qtnf_trans_send_cmd_with_resp(bus, cmd_skb, &resp_skb);
107 if (ret)
108 goto out;
110 if (WARN_ON(!resp_skb || !resp_skb->data)) {
111 ret = -EFAULT;
112 goto out;
115 resp = (struct qlink_resp *)resp_skb->data;
116 ret = qtnf_cmd_check_reply_header(resp, cmd_id, mac_id, vif_id,
117 const_resp_size);
118 if (ret)
119 goto out;
121 /* Return length of variable part of response */
122 if (response_skb && var_resp_size)
123 *var_resp_size = le16_to_cpu(resp->mhdr.len) - const_resp_size;
125 out:
126 if (response_skb)
127 *response_skb = resp_skb;
128 else
129 consume_skb(resp_skb);
131 if (!ret && resp)
132 return qtnf_cmd_resp_result_decode(le16_to_cpu(resp->result));
134 pr_warn("VIF%u.%u: cmd 0x%.4X failed: %d\n",
135 mac_id, vif_id, cmd_id, ret);
137 return ret;
140 static inline int qtnf_cmd_send(struct qtnf_bus *bus, struct sk_buff *cmd_skb)
142 return qtnf_cmd_send_with_reply(bus, cmd_skb, NULL,
143 sizeof(struct qlink_resp), NULL);
146 static struct sk_buff *qtnf_cmd_alloc_new_cmdskb(u8 macid, u8 vifid, u16 cmd_no,
147 size_t cmd_size)
149 struct qlink_cmd *cmd;
150 struct sk_buff *cmd_skb;
152 cmd_skb = __dev_alloc_skb(sizeof(*cmd) +
153 QTNF_MAX_CMD_BUF_SIZE, GFP_KERNEL);
154 if (unlikely(!cmd_skb)) {
155 pr_err("VIF%u.%u CMD %u: alloc failed\n", macid, vifid, cmd_no);
156 return NULL;
159 skb_put_zero(cmd_skb, cmd_size);
161 cmd = (struct qlink_cmd *)cmd_skb->data;
162 cmd->mhdr.len = cpu_to_le16(cmd_skb->len);
163 cmd->mhdr.type = cpu_to_le16(QLINK_MSG_TYPE_CMD);
164 cmd->cmd_id = cpu_to_le16(cmd_no);
165 cmd->macid = macid;
166 cmd->vifid = vifid;
168 return cmd_skb;
171 static void qtnf_cmd_tlv_ie_set_add(struct sk_buff *cmd_skb, u8 frame_type,
172 const u8 *buf, size_t len)
174 struct qlink_tlv_ie_set *tlv;
176 tlv = (struct qlink_tlv_ie_set *)skb_put(cmd_skb, sizeof(*tlv) + len);
177 tlv->hdr.type = cpu_to_le16(QTN_TLV_ID_IE_SET);
178 tlv->hdr.len = cpu_to_le16(len + sizeof(*tlv) - sizeof(tlv->hdr));
179 tlv->type = frame_type;
180 tlv->flags = 0;
182 if (len && buf)
183 memcpy(tlv->ie_data, buf, len);
186 static bool qtnf_cmd_start_ap_can_fit(const struct qtnf_vif *vif,
187 const struct cfg80211_ap_settings *s)
189 unsigned int len = sizeof(struct qlink_cmd_start_ap);
191 len += s->ssid_len;
192 len += s->beacon.head_len;
193 len += s->beacon.tail_len;
194 len += s->beacon.beacon_ies_len;
195 len += s->beacon.proberesp_ies_len;
196 len += s->beacon.assocresp_ies_len;
197 len += s->beacon.probe_resp_len;
199 if (cfg80211_chandef_valid(&s->chandef))
200 len += sizeof(struct qlink_tlv_chandef);
202 if (s->acl)
203 len += sizeof(struct qlink_tlv_hdr) +
204 struct_size(s->acl, mac_addrs, s->acl->n_acl_entries);
206 if (len > (sizeof(struct qlink_cmd) + QTNF_MAX_CMD_BUF_SIZE)) {
207 pr_err("VIF%u.%u: can not fit AP settings: %u\n",
208 vif->mac->macid, vif->vifid, len);
209 return false;
212 return true;
215 int qtnf_cmd_send_start_ap(struct qtnf_vif *vif,
216 const struct cfg80211_ap_settings *s)
218 struct sk_buff *cmd_skb;
219 struct qlink_cmd_start_ap *cmd;
220 struct qlink_auth_encr *aen;
221 int ret;
222 int i;
224 if (!qtnf_cmd_start_ap_can_fit(vif, s))
225 return -E2BIG;
227 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
228 QLINK_CMD_START_AP,
229 sizeof(*cmd));
230 if (!cmd_skb)
231 return -ENOMEM;
233 cmd = (struct qlink_cmd_start_ap *)cmd_skb->data;
234 cmd->dtim_period = s->dtim_period;
235 cmd->beacon_interval = cpu_to_le16(s->beacon_interval);
236 cmd->hidden_ssid = qlink_hidden_ssid_nl2q(s->hidden_ssid);
237 cmd->inactivity_timeout = cpu_to_le16(s->inactivity_timeout);
238 cmd->smps_mode = s->smps_mode;
239 cmd->p2p_ctwindow = s->p2p_ctwindow;
240 cmd->p2p_opp_ps = s->p2p_opp_ps;
241 cmd->pbss = s->pbss;
242 cmd->ht_required = s->ht_required;
243 cmd->vht_required = s->vht_required;
245 aen = &cmd->aen;
246 aen->auth_type = s->auth_type;
247 aen->privacy = !!s->privacy;
248 aen->wpa_versions = cpu_to_le32(s->crypto.wpa_versions);
249 aen->cipher_group = cpu_to_le32(s->crypto.cipher_group);
250 aen->n_ciphers_pairwise = cpu_to_le32(s->crypto.n_ciphers_pairwise);
251 for (i = 0; i < QLINK_MAX_NR_CIPHER_SUITES; i++)
252 aen->ciphers_pairwise[i] =
253 cpu_to_le32(s->crypto.ciphers_pairwise[i]);
254 aen->n_akm_suites = cpu_to_le32(s->crypto.n_akm_suites);
255 for (i = 0; i < QLINK_MAX_NR_AKM_SUITES; i++)
256 aen->akm_suites[i] = cpu_to_le32(s->crypto.akm_suites[i]);
257 aen->control_port = s->crypto.control_port;
258 aen->control_port_no_encrypt = s->crypto.control_port_no_encrypt;
259 aen->control_port_ethertype =
260 cpu_to_le16(be16_to_cpu(s->crypto.control_port_ethertype));
262 if (s->ssid && s->ssid_len > 0 && s->ssid_len <= IEEE80211_MAX_SSID_LEN)
263 qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID, s->ssid,
264 s->ssid_len);
266 if (cfg80211_chandef_valid(&s->chandef)) {
267 struct qlink_tlv_chandef *chtlv =
268 (struct qlink_tlv_chandef *)skb_put(cmd_skb,
269 sizeof(*chtlv));
271 chtlv->hdr.type = cpu_to_le16(QTN_TLV_ID_CHANDEF);
272 chtlv->hdr.len = cpu_to_le16(sizeof(*chtlv) -
273 sizeof(chtlv->hdr));
274 qlink_chandef_cfg2q(&s->chandef, &chtlv->chdef);
277 qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_BEACON_HEAD,
278 s->beacon.head, s->beacon.head_len);
279 qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_BEACON_TAIL,
280 s->beacon.tail, s->beacon.tail_len);
281 qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_BEACON_IES,
282 s->beacon.beacon_ies, s->beacon.beacon_ies_len);
283 qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_PROBE_RESP,
284 s->beacon.probe_resp, s->beacon.probe_resp_len);
285 qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_PROBE_RESP_IES,
286 s->beacon.proberesp_ies,
287 s->beacon.proberesp_ies_len);
288 qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_ASSOC_RESP,
289 s->beacon.assocresp_ies,
290 s->beacon.assocresp_ies_len);
292 if (s->ht_cap) {
293 struct qlink_tlv_hdr *tlv = (struct qlink_tlv_hdr *)
294 skb_put(cmd_skb, sizeof(*tlv) + sizeof(*s->ht_cap));
296 tlv->type = cpu_to_le16(WLAN_EID_HT_CAPABILITY);
297 tlv->len = cpu_to_le16(sizeof(*s->ht_cap));
298 memcpy(tlv->val, s->ht_cap, sizeof(*s->ht_cap));
301 if (s->vht_cap) {
302 struct qlink_tlv_hdr *tlv = (struct qlink_tlv_hdr *)
303 skb_put(cmd_skb, sizeof(*tlv) + sizeof(*s->vht_cap));
305 tlv->type = cpu_to_le16(WLAN_EID_VHT_CAPABILITY);
306 tlv->len = cpu_to_le16(sizeof(*s->vht_cap));
307 memcpy(tlv->val, s->vht_cap, sizeof(*s->vht_cap));
310 if (s->acl) {
311 size_t acl_size = struct_size(s->acl, mac_addrs,
312 s->acl->n_acl_entries);
313 struct qlink_tlv_hdr *tlv =
314 skb_put(cmd_skb, sizeof(*tlv) + acl_size);
316 tlv->type = cpu_to_le16(QTN_TLV_ID_ACL_DATA);
317 tlv->len = cpu_to_le16(acl_size);
318 qlink_acl_data_cfg2q(s->acl, (struct qlink_acl_data *)tlv->val);
321 qtnf_bus_lock(vif->mac->bus);
322 ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
323 if (ret)
324 goto out;
326 netif_carrier_on(vif->netdev);
328 out:
329 qtnf_bus_unlock(vif->mac->bus);
331 return ret;
334 int qtnf_cmd_send_stop_ap(struct qtnf_vif *vif)
336 struct sk_buff *cmd_skb;
337 int ret;
339 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
340 QLINK_CMD_STOP_AP,
341 sizeof(struct qlink_cmd));
342 if (!cmd_skb)
343 return -ENOMEM;
345 qtnf_bus_lock(vif->mac->bus);
346 ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
347 if (ret)
348 goto out;
350 out:
351 qtnf_bus_unlock(vif->mac->bus);
353 return ret;
356 int qtnf_cmd_send_register_mgmt(struct qtnf_vif *vif, u16 frame_type, bool reg)
358 struct sk_buff *cmd_skb;
359 struct qlink_cmd_mgmt_frame_register *cmd;
360 int ret;
362 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
363 QLINK_CMD_REGISTER_MGMT,
364 sizeof(*cmd));
365 if (!cmd_skb)
366 return -ENOMEM;
368 qtnf_bus_lock(vif->mac->bus);
370 cmd = (struct qlink_cmd_mgmt_frame_register *)cmd_skb->data;
371 cmd->frame_type = cpu_to_le16(frame_type);
372 cmd->do_register = reg;
374 ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
375 if (ret)
376 goto out;
378 out:
379 qtnf_bus_unlock(vif->mac->bus);
381 return ret;
384 int qtnf_cmd_send_frame(struct qtnf_vif *vif, u32 cookie, u16 flags,
385 u16 freq, const u8 *buf, size_t len)
387 struct sk_buff *cmd_skb;
388 struct qlink_cmd_frame_tx *cmd;
389 int ret;
391 if (sizeof(*cmd) + len > QTNF_MAX_CMD_BUF_SIZE) {
392 pr_warn("VIF%u.%u: frame is too big: %zu\n", vif->mac->macid,
393 vif->vifid, len);
394 return -E2BIG;
397 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
398 QLINK_CMD_SEND_FRAME,
399 sizeof(*cmd));
400 if (!cmd_skb)
401 return -ENOMEM;
403 qtnf_bus_lock(vif->mac->bus);
405 cmd = (struct qlink_cmd_frame_tx *)cmd_skb->data;
406 cmd->cookie = cpu_to_le32(cookie);
407 cmd->freq = cpu_to_le16(freq);
408 cmd->flags = cpu_to_le16(flags);
410 if (len && buf)
411 qtnf_cmd_skb_put_buffer(cmd_skb, buf, len);
413 ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
414 if (ret)
415 goto out;
417 out:
418 qtnf_bus_unlock(vif->mac->bus);
420 return ret;
423 int qtnf_cmd_send_mgmt_set_appie(struct qtnf_vif *vif, u8 frame_type,
424 const u8 *buf, size_t len)
426 struct sk_buff *cmd_skb;
427 int ret;
429 if (len > QTNF_MAX_CMD_BUF_SIZE) {
430 pr_warn("VIF%u.%u: %u frame is too big: %zu\n", vif->mac->macid,
431 vif->vifid, frame_type, len);
432 return -E2BIG;
435 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
436 QLINK_CMD_MGMT_SET_APPIE,
437 sizeof(struct qlink_cmd));
438 if (!cmd_skb)
439 return -ENOMEM;
441 qtnf_cmd_tlv_ie_set_add(cmd_skb, frame_type, buf, len);
443 qtnf_bus_lock(vif->mac->bus);
444 ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
445 if (ret)
446 goto out;
448 out:
449 qtnf_bus_unlock(vif->mac->bus);
451 return ret;
454 static void
455 qtnf_sta_info_parse_rate(struct rate_info *rate_dst,
456 const struct qlink_sta_info_rate *rate_src)
458 rate_dst->legacy = get_unaligned_le16(&rate_src->rate) * 10;
460 rate_dst->mcs = rate_src->mcs;
461 rate_dst->nss = rate_src->nss;
462 rate_dst->flags = 0;
464 switch (rate_src->bw) {
465 case QLINK_CHAN_WIDTH_5:
466 rate_dst->bw = RATE_INFO_BW_5;
467 break;
468 case QLINK_CHAN_WIDTH_10:
469 rate_dst->bw = RATE_INFO_BW_10;
470 break;
471 case QLINK_CHAN_WIDTH_20:
472 case QLINK_CHAN_WIDTH_20_NOHT:
473 rate_dst->bw = RATE_INFO_BW_20;
474 break;
475 case QLINK_CHAN_WIDTH_40:
476 rate_dst->bw = RATE_INFO_BW_40;
477 break;
478 case QLINK_CHAN_WIDTH_80:
479 rate_dst->bw = RATE_INFO_BW_80;
480 break;
481 case QLINK_CHAN_WIDTH_160:
482 rate_dst->bw = RATE_INFO_BW_160;
483 break;
484 default:
485 rate_dst->bw = 0;
486 break;
489 if (rate_src->flags & QLINK_STA_INFO_RATE_FLAG_HT_MCS)
490 rate_dst->flags |= RATE_INFO_FLAGS_MCS;
491 else if (rate_src->flags & QLINK_STA_INFO_RATE_FLAG_VHT_MCS)
492 rate_dst->flags |= RATE_INFO_FLAGS_VHT_MCS;
494 if (rate_src->flags & QLINK_STA_INFO_RATE_FLAG_SHORT_GI)
495 rate_dst->flags |= RATE_INFO_FLAGS_SHORT_GI;
498 static void
499 qtnf_sta_info_parse_flags(struct nl80211_sta_flag_update *dst,
500 const struct qlink_sta_info_state *src)
502 u32 mask, value;
504 dst->mask = 0;
505 dst->set = 0;
507 mask = le32_to_cpu(src->mask);
508 value = le32_to_cpu(src->value);
510 if (mask & QLINK_STA_FLAG_AUTHORIZED) {
511 dst->mask |= BIT(NL80211_STA_FLAG_AUTHORIZED);
512 if (value & QLINK_STA_FLAG_AUTHORIZED)
513 dst->set |= BIT(NL80211_STA_FLAG_AUTHORIZED);
516 if (mask & QLINK_STA_FLAG_SHORT_PREAMBLE) {
517 dst->mask |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE);
518 if (value & QLINK_STA_FLAG_SHORT_PREAMBLE)
519 dst->set |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE);
522 if (mask & QLINK_STA_FLAG_WME) {
523 dst->mask |= BIT(NL80211_STA_FLAG_WME);
524 if (value & QLINK_STA_FLAG_WME)
525 dst->set |= BIT(NL80211_STA_FLAG_WME);
528 if (mask & QLINK_STA_FLAG_MFP) {
529 dst->mask |= BIT(NL80211_STA_FLAG_MFP);
530 if (value & QLINK_STA_FLAG_MFP)
531 dst->set |= BIT(NL80211_STA_FLAG_MFP);
534 if (mask & QLINK_STA_FLAG_AUTHENTICATED) {
535 dst->mask |= BIT(NL80211_STA_FLAG_AUTHENTICATED);
536 if (value & QLINK_STA_FLAG_AUTHENTICATED)
537 dst->set |= BIT(NL80211_STA_FLAG_AUTHENTICATED);
540 if (mask & QLINK_STA_FLAG_TDLS_PEER) {
541 dst->mask |= BIT(NL80211_STA_FLAG_TDLS_PEER);
542 if (value & QLINK_STA_FLAG_TDLS_PEER)
543 dst->set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
546 if (mask & QLINK_STA_FLAG_ASSOCIATED) {
547 dst->mask |= BIT(NL80211_STA_FLAG_ASSOCIATED);
548 if (value & QLINK_STA_FLAG_ASSOCIATED)
549 dst->set |= BIT(NL80211_STA_FLAG_ASSOCIATED);
553 static void
554 qtnf_cmd_sta_info_parse(struct station_info *sinfo,
555 const struct qlink_tlv_hdr *tlv,
556 size_t resp_size)
558 const struct qlink_sta_stats *stats = NULL;
559 const u8 *map = NULL;
560 unsigned int map_len = 0;
561 unsigned int stats_len = 0;
562 u16 tlv_len;
564 #define qtnf_sta_stat_avail(stat_name, bitn) \
565 (qtnf_utils_is_bit_set(map, bitn, map_len) && \
566 (offsetofend(struct qlink_sta_stats, stat_name) <= stats_len))
568 while (resp_size >= sizeof(*tlv)) {
569 tlv_len = le16_to_cpu(tlv->len);
571 switch (le16_to_cpu(tlv->type)) {
572 case QTN_TLV_ID_STA_STATS_MAP:
573 map_len = tlv_len;
574 map = tlv->val;
575 break;
576 case QTN_TLV_ID_STA_STATS:
577 stats_len = tlv_len;
578 stats = (const struct qlink_sta_stats *)tlv->val;
579 break;
580 default:
581 break;
584 resp_size -= tlv_len + sizeof(*tlv);
585 tlv = (const struct qlink_tlv_hdr *)(tlv->val + tlv_len);
588 if (!map || !stats)
589 return;
591 if (qtnf_sta_stat_avail(inactive_time, QLINK_STA_INFO_INACTIVE_TIME)) {
592 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_INACTIVE_TIME);
593 sinfo->inactive_time = le32_to_cpu(stats->inactive_time);
596 if (qtnf_sta_stat_avail(connected_time,
597 QLINK_STA_INFO_CONNECTED_TIME)) {
598 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_CONNECTED_TIME);
599 sinfo->connected_time = le32_to_cpu(stats->connected_time);
602 if (qtnf_sta_stat_avail(signal, QLINK_STA_INFO_SIGNAL)) {
603 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL);
604 sinfo->signal = stats->signal - QLINK_RSSI_OFFSET;
607 if (qtnf_sta_stat_avail(signal_avg, QLINK_STA_INFO_SIGNAL_AVG)) {
608 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG);
609 sinfo->signal_avg = stats->signal_avg - QLINK_RSSI_OFFSET;
612 if (qtnf_sta_stat_avail(rxrate, QLINK_STA_INFO_RX_BITRATE)) {
613 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE);
614 qtnf_sta_info_parse_rate(&sinfo->rxrate, &stats->rxrate);
617 if (qtnf_sta_stat_avail(txrate, QLINK_STA_INFO_TX_BITRATE)) {
618 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
619 qtnf_sta_info_parse_rate(&sinfo->txrate, &stats->txrate);
622 if (qtnf_sta_stat_avail(sta_flags, QLINK_STA_INFO_STA_FLAGS)) {
623 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_STA_FLAGS);
624 qtnf_sta_info_parse_flags(&sinfo->sta_flags, &stats->sta_flags);
627 if (qtnf_sta_stat_avail(rx_bytes, QLINK_STA_INFO_RX_BYTES)) {
628 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BYTES);
629 sinfo->rx_bytes = le64_to_cpu(stats->rx_bytes);
632 if (qtnf_sta_stat_avail(tx_bytes, QLINK_STA_INFO_TX_BYTES)) {
633 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES);
634 sinfo->tx_bytes = le64_to_cpu(stats->tx_bytes);
637 if (qtnf_sta_stat_avail(rx_bytes, QLINK_STA_INFO_RX_BYTES64)) {
638 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BYTES64);
639 sinfo->rx_bytes = le64_to_cpu(stats->rx_bytes);
642 if (qtnf_sta_stat_avail(tx_bytes, QLINK_STA_INFO_TX_BYTES64)) {
643 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES64);
644 sinfo->tx_bytes = le64_to_cpu(stats->tx_bytes);
647 if (qtnf_sta_stat_avail(rx_packets, QLINK_STA_INFO_RX_PACKETS)) {
648 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_PACKETS);
649 sinfo->rx_packets = le32_to_cpu(stats->rx_packets);
652 if (qtnf_sta_stat_avail(tx_packets, QLINK_STA_INFO_TX_PACKETS)) {
653 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS);
654 sinfo->tx_packets = le32_to_cpu(stats->tx_packets);
657 if (qtnf_sta_stat_avail(rx_beacon, QLINK_STA_INFO_BEACON_RX)) {
658 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_BEACON_RX);
659 sinfo->rx_beacon = le64_to_cpu(stats->rx_beacon);
662 if (qtnf_sta_stat_avail(rx_dropped_misc, QLINK_STA_INFO_RX_DROP_MISC)) {
663 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_DROP_MISC);
664 sinfo->rx_dropped_misc = le32_to_cpu(stats->rx_dropped_misc);
667 if (qtnf_sta_stat_avail(tx_failed, QLINK_STA_INFO_TX_FAILED)) {
668 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED);
669 sinfo->tx_failed = le32_to_cpu(stats->tx_failed);
672 #undef qtnf_sta_stat_avail
675 int qtnf_cmd_get_sta_info(struct qtnf_vif *vif, const u8 *sta_mac,
676 struct station_info *sinfo)
678 struct sk_buff *cmd_skb, *resp_skb = NULL;
679 struct qlink_cmd_get_sta_info *cmd;
680 const struct qlink_resp_get_sta_info *resp;
681 size_t var_resp_len = 0;
682 int ret = 0;
684 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
685 QLINK_CMD_GET_STA_INFO,
686 sizeof(*cmd));
687 if (!cmd_skb)
688 return -ENOMEM;
690 qtnf_bus_lock(vif->mac->bus);
692 cmd = (struct qlink_cmd_get_sta_info *)cmd_skb->data;
693 ether_addr_copy(cmd->sta_addr, sta_mac);
695 ret = qtnf_cmd_send_with_reply(vif->mac->bus, cmd_skb, &resp_skb,
696 sizeof(*resp), &var_resp_len);
697 if (ret)
698 goto out;
700 resp = (const struct qlink_resp_get_sta_info *)resp_skb->data;
702 if (!ether_addr_equal(sta_mac, resp->sta_addr)) {
703 pr_err("VIF%u.%u: wrong mac in reply: %pM != %pM\n",
704 vif->mac->macid, vif->vifid, resp->sta_addr, sta_mac);
705 ret = -EINVAL;
706 goto out;
709 qtnf_cmd_sta_info_parse(sinfo,
710 (const struct qlink_tlv_hdr *)resp->info,
711 var_resp_len);
713 out:
714 qtnf_bus_unlock(vif->mac->bus);
715 consume_skb(resp_skb);
717 return ret;
720 static int qtnf_cmd_send_add_change_intf(struct qtnf_vif *vif,
721 enum nl80211_iftype iftype,
722 int use4addr,
723 u8 *mac_addr,
724 enum qlink_cmd_type cmd_type)
726 struct sk_buff *cmd_skb, *resp_skb = NULL;
727 struct qlink_cmd_manage_intf *cmd;
728 const struct qlink_resp_manage_intf *resp;
729 int ret = 0;
731 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
732 cmd_type,
733 sizeof(*cmd));
734 if (!cmd_skb)
735 return -ENOMEM;
737 qtnf_bus_lock(vif->mac->bus);
739 cmd = (struct qlink_cmd_manage_intf *)cmd_skb->data;
740 cmd->intf_info.use4addr = use4addr;
742 switch (iftype) {
743 case NL80211_IFTYPE_AP:
744 cmd->intf_info.if_type = cpu_to_le16(QLINK_IFTYPE_AP);
745 break;
746 case NL80211_IFTYPE_STATION:
747 cmd->intf_info.if_type = cpu_to_le16(QLINK_IFTYPE_STATION);
748 break;
749 default:
750 pr_err("VIF%u.%u: unsupported type %d\n", vif->mac->macid,
751 vif->vifid, iftype);
752 ret = -EINVAL;
753 goto out;
756 if (mac_addr)
757 ether_addr_copy(cmd->intf_info.mac_addr, mac_addr);
758 else
759 eth_zero_addr(cmd->intf_info.mac_addr);
761 ret = qtnf_cmd_send_with_reply(vif->mac->bus, cmd_skb, &resp_skb,
762 sizeof(*resp), NULL);
763 if (ret)
764 goto out;
766 resp = (const struct qlink_resp_manage_intf *)resp_skb->data;
767 ether_addr_copy(vif->mac_addr, resp->intf_info.mac_addr);
769 out:
770 qtnf_bus_unlock(vif->mac->bus);
771 consume_skb(resp_skb);
773 return ret;
776 int qtnf_cmd_send_add_intf(struct qtnf_vif *vif, enum nl80211_iftype iftype,
777 int use4addr, u8 *mac_addr)
779 return qtnf_cmd_send_add_change_intf(vif, iftype, use4addr, mac_addr,
780 QLINK_CMD_ADD_INTF);
783 int qtnf_cmd_send_change_intf_type(struct qtnf_vif *vif,
784 enum nl80211_iftype iftype,
785 int use4addr,
786 u8 *mac_addr)
788 int ret;
790 ret = qtnf_cmd_send_add_change_intf(vif, iftype, use4addr, mac_addr,
791 QLINK_CMD_CHANGE_INTF);
793 /* Regulatory settings may be different for different interface types */
794 if (ret == 0 && vif->wdev.iftype != iftype) {
795 enum nl80211_band band;
796 struct wiphy *wiphy = priv_to_wiphy(vif->mac);
798 for (band = 0; band < NUM_NL80211_BANDS; ++band) {
799 if (!wiphy->bands[band])
800 continue;
802 qtnf_cmd_band_info_get(vif->mac, wiphy->bands[band]);
806 return ret;
809 int qtnf_cmd_send_del_intf(struct qtnf_vif *vif)
811 struct sk_buff *cmd_skb;
812 struct qlink_cmd_manage_intf *cmd;
813 int ret = 0;
815 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
816 QLINK_CMD_DEL_INTF,
817 sizeof(*cmd));
818 if (!cmd_skb)
819 return -ENOMEM;
821 qtnf_bus_lock(vif->mac->bus);
823 cmd = (struct qlink_cmd_manage_intf *)cmd_skb->data;
825 switch (vif->wdev.iftype) {
826 case NL80211_IFTYPE_AP:
827 cmd->intf_info.if_type = cpu_to_le16(QLINK_IFTYPE_AP);
828 break;
829 case NL80211_IFTYPE_STATION:
830 cmd->intf_info.if_type = cpu_to_le16(QLINK_IFTYPE_STATION);
831 break;
832 default:
833 pr_warn("VIF%u.%u: unsupported iftype %d\n", vif->mac->macid,
834 vif->vifid, vif->wdev.iftype);
835 ret = -EINVAL;
836 goto out;
839 eth_zero_addr(cmd->intf_info.mac_addr);
841 ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
842 if (ret)
843 goto out;
845 out:
846 qtnf_bus_unlock(vif->mac->bus);
847 return ret;
850 static int
851 qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus,
852 const struct qlink_resp_get_hw_info *resp,
853 size_t info_len)
855 struct qtnf_hw_info *hwinfo = &bus->hw_info;
856 const struct qlink_tlv_hdr *tlv;
857 const char *bld_name = NULL;
858 const char *bld_rev = NULL;
859 const char *bld_type = NULL;
860 const char *bld_label = NULL;
861 u32 bld_tmstamp = 0;
862 u32 plat_id = 0;
863 const char *hw_id = NULL;
864 const char *calibration_ver = NULL;
865 const char *uboot_ver = NULL;
866 u32 hw_ver = 0;
867 u16 tlv_type;
868 u16 tlv_value_len;
870 hwinfo->num_mac = resp->num_mac;
871 hwinfo->mac_bitmap = resp->mac_bitmap;
872 hwinfo->fw_ver = le32_to_cpu(resp->fw_ver);
873 hwinfo->ql_proto_ver = le16_to_cpu(resp->ql_proto_ver);
874 hwinfo->total_tx_chain = resp->total_tx_chain;
875 hwinfo->total_rx_chain = resp->total_rx_chain;
876 hwinfo->hw_capab = le32_to_cpu(resp->hw_capab);
878 bld_tmstamp = le32_to_cpu(resp->bld_tmstamp);
879 plat_id = le32_to_cpu(resp->plat_id);
880 hw_ver = le32_to_cpu(resp->hw_ver);
882 tlv = (const struct qlink_tlv_hdr *)resp->info;
884 while (info_len >= sizeof(*tlv)) {
885 tlv_type = le16_to_cpu(tlv->type);
886 tlv_value_len = le16_to_cpu(tlv->len);
888 if (tlv_value_len + sizeof(*tlv) > info_len) {
889 pr_warn("malformed TLV 0x%.2X; LEN: %u\n",
890 tlv_type, tlv_value_len);
891 return -EINVAL;
894 switch (tlv_type) {
895 case QTN_TLV_ID_BUILD_NAME:
896 bld_name = (const void *)tlv->val;
897 break;
898 case QTN_TLV_ID_BUILD_REV:
899 bld_rev = (const void *)tlv->val;
900 break;
901 case QTN_TLV_ID_BUILD_TYPE:
902 bld_type = (const void *)tlv->val;
903 break;
904 case QTN_TLV_ID_BUILD_LABEL:
905 bld_label = (const void *)tlv->val;
906 break;
907 case QTN_TLV_ID_HW_ID:
908 hw_id = (const void *)tlv->val;
909 break;
910 case QTN_TLV_ID_CALIBRATION_VER:
911 calibration_ver = (const void *)tlv->val;
912 break;
913 case QTN_TLV_ID_UBOOT_VER:
914 uboot_ver = (const void *)tlv->val;
915 break;
916 case QTN_TLV_ID_MAX_SCAN_SSIDS:
917 hwinfo->max_scan_ssids = *tlv->val;
918 break;
919 default:
920 break;
923 info_len -= tlv_value_len + sizeof(*tlv);
924 tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len);
927 pr_info("fw_version=%d, MACs map %#x, chains Tx=%u Rx=%u, capab=0x%x\n",
928 hwinfo->fw_ver, hwinfo->mac_bitmap,
929 hwinfo->total_tx_chain, hwinfo->total_rx_chain,
930 hwinfo->hw_capab);
932 pr_info("\nBuild name: %s" \
933 "\nBuild revision: %s" \
934 "\nBuild type: %s" \
935 "\nBuild label: %s" \
936 "\nBuild timestamp: %lu" \
937 "\nPlatform ID: %lu" \
938 "\nHardware ID: %s" \
939 "\nCalibration version: %s" \
940 "\nU-Boot version: %s" \
941 "\nHardware version: 0x%08x\n",
942 bld_name, bld_rev, bld_type, bld_label,
943 (unsigned long)bld_tmstamp,
944 (unsigned long)plat_id,
945 hw_id, calibration_ver, uboot_ver, hw_ver);
947 strlcpy(hwinfo->fw_version, bld_label, sizeof(hwinfo->fw_version));
948 hwinfo->hw_version = hw_ver;
950 return 0;
953 static void
954 qtnf_parse_wowlan_info(struct qtnf_wmac *mac,
955 const struct qlink_wowlan_capab_data *wowlan)
957 struct qtnf_mac_info *mac_info = &mac->macinfo;
958 const struct qlink_wowlan_support *data1;
959 struct wiphy_wowlan_support *supp;
961 supp = kzalloc(sizeof(*supp), GFP_KERNEL);
962 if (!supp)
963 return;
965 switch (le16_to_cpu(wowlan->version)) {
966 case 0x1:
967 data1 = (struct qlink_wowlan_support *)wowlan->data;
969 supp->flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT;
970 supp->n_patterns = le32_to_cpu(data1->n_patterns);
971 supp->pattern_max_len = le32_to_cpu(data1->pattern_max_len);
972 supp->pattern_min_len = le32_to_cpu(data1->pattern_min_len);
974 mac_info->wowlan = supp;
975 break;
976 default:
977 pr_warn("MAC%u: unsupported WoWLAN version 0x%x\n",
978 mac->macid, le16_to_cpu(wowlan->version));
979 kfree(supp);
980 break;
984 static int
985 qtnf_parse_variable_mac_info(struct qtnf_wmac *mac,
986 const struct qlink_resp_get_mac_info *resp,
987 size_t tlv_buf_size)
989 const u8 *tlv_buf = resp->var_info;
990 struct ieee80211_iface_combination *comb = NULL;
991 size_t n_comb = 0;
992 struct ieee80211_iface_limit *limits;
993 const struct qlink_iface_comb_num *comb_num;
994 const struct qlink_iface_limit_record *rec;
995 const struct qlink_iface_limit *lim;
996 const struct qlink_wowlan_capab_data *wowlan;
997 u16 rec_len;
998 u16 tlv_type;
999 u16 tlv_value_len;
1000 size_t tlv_full_len;
1001 const struct qlink_tlv_hdr *tlv;
1002 u8 *ext_capa = NULL;
1003 u8 *ext_capa_mask = NULL;
1004 u8 ext_capa_len = 0;
1005 u8 ext_capa_mask_len = 0;
1006 int i = 0;
1007 struct ieee80211_reg_rule *rule;
1008 unsigned int rule_idx = 0;
1009 const struct qlink_tlv_reg_rule *tlv_rule;
1011 if (WARN_ON(resp->n_reg_rules > NL80211_MAX_SUPP_REG_RULES))
1012 return -E2BIG;
1014 mac->rd = kzalloc(sizeof(*mac->rd) +
1015 sizeof(struct ieee80211_reg_rule) *
1016 resp->n_reg_rules, GFP_KERNEL);
1017 if (!mac->rd)
1018 return -ENOMEM;
1020 mac->rd->n_reg_rules = resp->n_reg_rules;
1021 mac->rd->alpha2[0] = resp->alpha2[0];
1022 mac->rd->alpha2[1] = resp->alpha2[1];
1024 switch (resp->dfs_region) {
1025 case QLINK_DFS_FCC:
1026 mac->rd->dfs_region = NL80211_DFS_FCC;
1027 break;
1028 case QLINK_DFS_ETSI:
1029 mac->rd->dfs_region = NL80211_DFS_ETSI;
1030 break;
1031 case QLINK_DFS_JP:
1032 mac->rd->dfs_region = NL80211_DFS_JP;
1033 break;
1034 case QLINK_DFS_UNSET:
1035 default:
1036 mac->rd->dfs_region = NL80211_DFS_UNSET;
1037 break;
1040 tlv = (const struct qlink_tlv_hdr *)tlv_buf;
1041 while (tlv_buf_size >= sizeof(struct qlink_tlv_hdr)) {
1042 tlv_type = le16_to_cpu(tlv->type);
1043 tlv_value_len = le16_to_cpu(tlv->len);
1044 tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr);
1045 if (tlv_full_len > tlv_buf_size) {
1046 pr_warn("MAC%u: malformed TLV 0x%.2X; LEN: %u\n",
1047 mac->macid, tlv_type, tlv_value_len);
1048 return -EINVAL;
1051 switch (tlv_type) {
1052 case QTN_TLV_ID_NUM_IFACE_COMB:
1053 if (tlv_value_len != sizeof(*comb_num))
1054 return -EINVAL;
1056 comb_num = (void *)tlv->val;
1058 /* free earlier iface comb memory */
1059 qtnf_mac_iface_comb_free(mac);
1061 mac->macinfo.n_if_comb =
1062 le32_to_cpu(comb_num->iface_comb_num);
1064 mac->macinfo.if_comb =
1065 kcalloc(mac->macinfo.n_if_comb,
1066 sizeof(*mac->macinfo.if_comb),
1067 GFP_KERNEL);
1069 if (!mac->macinfo.if_comb)
1070 return -ENOMEM;
1072 comb = mac->macinfo.if_comb;
1074 pr_debug("MAC%u: %zu iface combinations\n",
1075 mac->macid, mac->macinfo.n_if_comb);
1077 break;
1078 case QTN_TLV_ID_IFACE_LIMIT:
1079 if (unlikely(!comb)) {
1080 pr_warn("MAC%u: no combinations advertised\n",
1081 mac->macid);
1082 return -EINVAL;
1085 if (n_comb >= mac->macinfo.n_if_comb) {
1086 pr_warn("MAC%u: combinations count exceeded\n",
1087 mac->macid);
1088 n_comb++;
1089 break;
1092 rec = (void *)tlv->val;
1093 rec_len = sizeof(*rec) + rec->n_limits * sizeof(*lim);
1095 if (unlikely(tlv_value_len != rec_len)) {
1096 pr_warn("MAC%u: record %zu size mismatch\n",
1097 mac->macid, n_comb);
1098 return -EINVAL;
1101 limits = kcalloc(rec->n_limits, sizeof(*limits),
1102 GFP_KERNEL);
1103 if (!limits)
1104 return -ENOMEM;
1106 comb[n_comb].num_different_channels =
1107 rec->num_different_channels;
1108 comb[n_comb].max_interfaces =
1109 le16_to_cpu(rec->max_interfaces);
1110 comb[n_comb].n_limits = rec->n_limits;
1111 comb[n_comb].limits = limits;
1113 for (i = 0; i < rec->n_limits; i++) {
1114 lim = &rec->limits[i];
1115 limits[i].max = le16_to_cpu(lim->max_num);
1116 limits[i].types =
1117 qlink_iface_type_to_nl_mask(le16_to_cpu(lim->type));
1118 pr_debug("MAC%u: comb[%zu]: MAX:%u TYPES:%.4X\n",
1119 mac->macid, n_comb,
1120 limits[i].max, limits[i].types);
1123 n_comb++;
1124 break;
1125 case WLAN_EID_EXT_CAPABILITY:
1126 if (unlikely(tlv_value_len > U8_MAX))
1127 return -EINVAL;
1128 ext_capa = (u8 *)tlv->val;
1129 ext_capa_len = tlv_value_len;
1130 break;
1131 case QTN_TLV_ID_EXT_CAPABILITY_MASK:
1132 if (unlikely(tlv_value_len > U8_MAX))
1133 return -EINVAL;
1134 ext_capa_mask = (u8 *)tlv->val;
1135 ext_capa_mask_len = tlv_value_len;
1136 break;
1137 case QTN_TLV_ID_WOWLAN_CAPAB:
1138 if (tlv_value_len < sizeof(*wowlan))
1139 return -EINVAL;
1141 wowlan = (void *)tlv->val;
1142 if (!le16_to_cpu(wowlan->len)) {
1143 pr_warn("MAC%u: skip empty WoWLAN data\n",
1144 mac->macid);
1145 break;
1148 rec_len = sizeof(*wowlan) + le16_to_cpu(wowlan->len);
1149 if (unlikely(tlv_value_len != rec_len)) {
1150 pr_warn("MAC%u: WoWLAN data size mismatch\n",
1151 mac->macid);
1152 return -EINVAL;
1155 kfree(mac->macinfo.wowlan);
1156 mac->macinfo.wowlan = NULL;
1157 qtnf_parse_wowlan_info(mac, wowlan);
1158 break;
1159 case QTN_TLV_ID_REG_RULE:
1160 if (rule_idx >= resp->n_reg_rules) {
1161 pr_warn("unexpected number of rules: %u\n",
1162 resp->n_reg_rules);
1163 return -EINVAL;
1166 if (tlv_value_len != sizeof(*tlv_rule) - sizeof(*tlv)) {
1167 pr_warn("malformed TLV 0x%.2X; LEN: %u\n",
1168 tlv_type, tlv_value_len);
1169 return -EINVAL;
1172 tlv_rule = (const struct qlink_tlv_reg_rule *)tlv;
1173 rule = &mac->rd->reg_rules[rule_idx++];
1174 qlink_utils_regrule_q2nl(rule, tlv_rule);
1175 break;
1176 default:
1177 pr_warn("MAC%u: unknown TLV type %u\n",
1178 mac->macid, tlv_type);
1179 break;
1182 tlv_buf_size -= tlv_full_len;
1183 tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len);
1186 if (tlv_buf_size) {
1187 pr_warn("MAC%u: malformed TLV buf; bytes left: %zu\n",
1188 mac->macid, tlv_buf_size);
1189 return -EINVAL;
1192 if (mac->macinfo.n_if_comb != n_comb) {
1193 pr_err("MAC%u: combination mismatch: reported=%zu parsed=%zu\n",
1194 mac->macid, mac->macinfo.n_if_comb, n_comb);
1195 return -EINVAL;
1198 if (ext_capa_len != ext_capa_mask_len) {
1199 pr_err("MAC%u: ext_capa/_mask lengths mismatch: %u != %u\n",
1200 mac->macid, ext_capa_len, ext_capa_mask_len);
1201 return -EINVAL;
1204 if (rule_idx != resp->n_reg_rules) {
1205 pr_warn("unexpected number of rules: expected %u got %u\n",
1206 resp->n_reg_rules, rule_idx);
1207 return -EINVAL;
1210 if (ext_capa_len > 0) {
1211 ext_capa = kmemdup(ext_capa, ext_capa_len, GFP_KERNEL);
1212 if (!ext_capa)
1213 return -ENOMEM;
1215 ext_capa_mask =
1216 kmemdup(ext_capa_mask, ext_capa_mask_len, GFP_KERNEL);
1217 if (!ext_capa_mask) {
1218 kfree(ext_capa);
1219 return -ENOMEM;
1221 } else {
1222 ext_capa = NULL;
1223 ext_capa_mask = NULL;
1226 qtnf_mac_ext_caps_free(mac);
1227 mac->macinfo.extended_capabilities = ext_capa;
1228 mac->macinfo.extended_capabilities_mask = ext_capa_mask;
1229 mac->macinfo.extended_capabilities_len = ext_capa_len;
1231 return 0;
1234 static void
1235 qtnf_cmd_resp_proc_mac_info(struct qtnf_wmac *mac,
1236 const struct qlink_resp_get_mac_info *resp_info)
1238 struct qtnf_mac_info *mac_info;
1239 struct qtnf_vif *vif;
1241 mac_info = &mac->macinfo;
1243 mac_info->bands_cap = resp_info->bands_cap;
1244 memcpy(&mac_info->dev_mac, &resp_info->dev_mac,
1245 sizeof(mac_info->dev_mac));
1247 ether_addr_copy(mac->macaddr, mac_info->dev_mac);
1249 vif = qtnf_mac_get_base_vif(mac);
1250 if (vif)
1251 ether_addr_copy(vif->mac_addr, mac->macaddr);
1252 else
1253 pr_err("could not get valid base vif\n");
1255 mac_info->num_tx_chain = resp_info->num_tx_chain;
1256 mac_info->num_rx_chain = resp_info->num_rx_chain;
1258 mac_info->max_ap_assoc_sta = le16_to_cpu(resp_info->max_ap_assoc_sta);
1259 mac_info->radar_detect_widths =
1260 qlink_chan_width_mask_to_nl(le16_to_cpu(
1261 resp_info->radar_detect_widths));
1262 mac_info->max_acl_mac_addrs = le32_to_cpu(resp_info->max_acl_mac_addrs);
1264 memcpy(&mac_info->ht_cap_mod_mask, &resp_info->ht_cap_mod_mask,
1265 sizeof(mac_info->ht_cap_mod_mask));
1266 memcpy(&mac_info->vht_cap_mod_mask, &resp_info->vht_cap_mod_mask,
1267 sizeof(mac_info->vht_cap_mod_mask));
1270 static void qtnf_cmd_resp_band_fill_htcap(const u8 *info,
1271 struct ieee80211_sta_ht_cap *bcap)
1273 const struct ieee80211_ht_cap *ht_cap =
1274 (const struct ieee80211_ht_cap *)info;
1276 bcap->ht_supported = true;
1277 bcap->cap = le16_to_cpu(ht_cap->cap_info);
1278 bcap->ampdu_factor =
1279 ht_cap->ampdu_params_info & IEEE80211_HT_AMPDU_PARM_FACTOR;
1280 bcap->ampdu_density =
1281 (ht_cap->ampdu_params_info & IEEE80211_HT_AMPDU_PARM_DENSITY) >>
1282 IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT;
1283 memcpy(&bcap->mcs, &ht_cap->mcs, sizeof(bcap->mcs));
1286 static void qtnf_cmd_resp_band_fill_vhtcap(const u8 *info,
1287 struct ieee80211_sta_vht_cap *bcap)
1289 const struct ieee80211_vht_cap *vht_cap =
1290 (const struct ieee80211_vht_cap *)info;
1292 bcap->vht_supported = true;
1293 bcap->cap = le32_to_cpu(vht_cap->vht_cap_info);
1294 memcpy(&bcap->vht_mcs, &vht_cap->supp_mcs, sizeof(bcap->vht_mcs));
1297 static int
1298 qtnf_cmd_resp_fill_band_info(struct ieee80211_supported_band *band,
1299 struct qlink_resp_band_info_get *resp,
1300 size_t payload_len)
1302 u16 tlv_type;
1303 size_t tlv_len;
1304 size_t tlv_dlen;
1305 const struct qlink_tlv_hdr *tlv;
1306 const struct qlink_channel *qchan;
1307 struct ieee80211_channel *chan;
1308 unsigned int chidx = 0;
1309 u32 qflags;
1311 memset(&band->ht_cap, 0, sizeof(band->ht_cap));
1312 memset(&band->vht_cap, 0, sizeof(band->vht_cap));
1314 if (band->channels) {
1315 if (band->n_channels == resp->num_chans) {
1316 memset(band->channels, 0,
1317 sizeof(*band->channels) * band->n_channels);
1318 } else {
1319 kfree(band->channels);
1320 band->n_channels = 0;
1321 band->channels = NULL;
1325 band->n_channels = resp->num_chans;
1326 if (band->n_channels == 0)
1327 return 0;
1329 if (!band->channels)
1330 band->channels = kcalloc(band->n_channels, sizeof(*chan),
1331 GFP_KERNEL);
1332 if (!band->channels) {
1333 band->n_channels = 0;
1334 return -ENOMEM;
1337 tlv = (struct qlink_tlv_hdr *)resp->info;
1339 while (payload_len >= sizeof(*tlv)) {
1340 tlv_type = le16_to_cpu(tlv->type);
1341 tlv_dlen = le16_to_cpu(tlv->len);
1342 tlv_len = tlv_dlen + sizeof(*tlv);
1344 if (tlv_len > payload_len) {
1345 pr_warn("malformed TLV 0x%.2X; LEN: %zu\n",
1346 tlv_type, tlv_len);
1347 goto error_ret;
1350 switch (tlv_type) {
1351 case QTN_TLV_ID_CHANNEL:
1352 if (unlikely(tlv_dlen != sizeof(*qchan))) {
1353 pr_err("invalid channel TLV len %zu\n",
1354 tlv_len);
1355 goto error_ret;
1358 if (chidx == band->n_channels) {
1359 pr_err("too many channel TLVs\n");
1360 goto error_ret;
1363 qchan = (const struct qlink_channel *)tlv->val;
1364 chan = &band->channels[chidx++];
1365 qflags = le32_to_cpu(qchan->flags);
1367 chan->hw_value = le16_to_cpu(qchan->hw_value);
1368 chan->band = band->band;
1369 chan->center_freq = le16_to_cpu(qchan->center_freq);
1370 chan->max_antenna_gain = (int)qchan->max_antenna_gain;
1371 chan->max_power = (int)qchan->max_power;
1372 chan->max_reg_power = (int)qchan->max_reg_power;
1373 chan->beacon_found = qchan->beacon_found;
1374 chan->dfs_cac_ms = le32_to_cpu(qchan->dfs_cac_ms);
1375 chan->flags = 0;
1377 if (qflags & QLINK_CHAN_DISABLED)
1378 chan->flags |= IEEE80211_CHAN_DISABLED;
1380 if (qflags & QLINK_CHAN_NO_IR)
1381 chan->flags |= IEEE80211_CHAN_NO_IR;
1383 if (qflags & QLINK_CHAN_NO_HT40PLUS)
1384 chan->flags |= IEEE80211_CHAN_NO_HT40PLUS;
1386 if (qflags & QLINK_CHAN_NO_HT40MINUS)
1387 chan->flags |= IEEE80211_CHAN_NO_HT40MINUS;
1389 if (qflags & QLINK_CHAN_NO_OFDM)
1390 chan->flags |= IEEE80211_CHAN_NO_OFDM;
1392 if (qflags & QLINK_CHAN_NO_80MHZ)
1393 chan->flags |= IEEE80211_CHAN_NO_80MHZ;
1395 if (qflags & QLINK_CHAN_NO_160MHZ)
1396 chan->flags |= IEEE80211_CHAN_NO_160MHZ;
1398 if (qflags & QLINK_CHAN_INDOOR_ONLY)
1399 chan->flags |= IEEE80211_CHAN_INDOOR_ONLY;
1401 if (qflags & QLINK_CHAN_IR_CONCURRENT)
1402 chan->flags |= IEEE80211_CHAN_IR_CONCURRENT;
1404 if (qflags & QLINK_CHAN_NO_20MHZ)
1405 chan->flags |= IEEE80211_CHAN_NO_20MHZ;
1407 if (qflags & QLINK_CHAN_NO_10MHZ)
1408 chan->flags |= IEEE80211_CHAN_NO_10MHZ;
1410 if (qflags & QLINK_CHAN_RADAR) {
1411 chan->flags |= IEEE80211_CHAN_RADAR;
1412 chan->dfs_state_entered = jiffies;
1414 if (qchan->dfs_state == QLINK_DFS_USABLE)
1415 chan->dfs_state = NL80211_DFS_USABLE;
1416 else if (qchan->dfs_state ==
1417 QLINK_DFS_AVAILABLE)
1418 chan->dfs_state = NL80211_DFS_AVAILABLE;
1419 else
1420 chan->dfs_state =
1421 NL80211_DFS_UNAVAILABLE;
1424 pr_debug("chan=%d flags=%#x max_pow=%d max_reg_pow=%d\n",
1425 chan->hw_value, chan->flags, chan->max_power,
1426 chan->max_reg_power);
1427 break;
1428 case WLAN_EID_HT_CAPABILITY:
1429 if (unlikely(tlv_dlen !=
1430 sizeof(struct ieee80211_ht_cap))) {
1431 pr_err("bad HTCAP TLV len %zu\n", tlv_dlen);
1432 goto error_ret;
1435 qtnf_cmd_resp_band_fill_htcap(tlv->val, &band->ht_cap);
1436 break;
1437 case WLAN_EID_VHT_CAPABILITY:
1438 if (unlikely(tlv_dlen !=
1439 sizeof(struct ieee80211_vht_cap))) {
1440 pr_err("bad VHTCAP TLV len %zu\n", tlv_dlen);
1441 goto error_ret;
1444 qtnf_cmd_resp_band_fill_vhtcap(tlv->val,
1445 &band->vht_cap);
1446 break;
1447 default:
1448 pr_warn("unknown TLV type: %#x\n", tlv_type);
1449 break;
1452 payload_len -= tlv_len;
1453 tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_dlen);
1456 if (payload_len) {
1457 pr_err("malformed TLV buf; bytes left: %zu\n", payload_len);
1458 goto error_ret;
1461 if (band->n_channels != chidx) {
1462 pr_err("channel count mismatch: reported=%d, parsed=%d\n",
1463 band->n_channels, chidx);
1464 goto error_ret;
1467 return 0;
1469 error_ret:
1470 kfree(band->channels);
1471 band->channels = NULL;
1472 band->n_channels = 0;
1474 return -EINVAL;
1477 static int qtnf_cmd_resp_proc_phy_params(struct qtnf_wmac *mac,
1478 const u8 *payload, size_t payload_len)
1480 struct qtnf_mac_info *mac_info;
1481 struct qlink_tlv_frag_rts_thr *phy_thr;
1482 struct qlink_tlv_rlimit *limit;
1483 struct qlink_tlv_cclass *class;
1484 u16 tlv_type;
1485 u16 tlv_value_len;
1486 size_t tlv_full_len;
1487 const struct qlink_tlv_hdr *tlv;
1489 mac_info = &mac->macinfo;
1491 tlv = (struct qlink_tlv_hdr *)payload;
1492 while (payload_len >= sizeof(struct qlink_tlv_hdr)) {
1493 tlv_type = le16_to_cpu(tlv->type);
1494 tlv_value_len = le16_to_cpu(tlv->len);
1495 tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr);
1497 if (tlv_full_len > payload_len) {
1498 pr_warn("MAC%u: malformed TLV 0x%.2X; LEN: %u\n",
1499 mac->macid, tlv_type, tlv_value_len);
1500 return -EINVAL;
1503 switch (tlv_type) {
1504 case QTN_TLV_ID_FRAG_THRESH:
1505 phy_thr = (void *)tlv;
1506 mac_info->frag_thr = le32_to_cpu(phy_thr->thr);
1507 break;
1508 case QTN_TLV_ID_RTS_THRESH:
1509 phy_thr = (void *)tlv;
1510 mac_info->rts_thr = le32_to_cpu(phy_thr->thr);
1511 break;
1512 case QTN_TLV_ID_SRETRY_LIMIT:
1513 limit = (void *)tlv;
1514 mac_info->sretry_limit = limit->rlimit;
1515 break;
1516 case QTN_TLV_ID_LRETRY_LIMIT:
1517 limit = (void *)tlv;
1518 mac_info->lretry_limit = limit->rlimit;
1519 break;
1520 case QTN_TLV_ID_COVERAGE_CLASS:
1521 class = (void *)tlv;
1522 mac_info->coverage_class = class->cclass;
1523 break;
1524 default:
1525 pr_err("MAC%u: Unknown TLV type: %#x\n", mac->macid,
1526 le16_to_cpu(tlv->type));
1527 break;
1530 payload_len -= tlv_full_len;
1531 tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len);
1534 if (payload_len) {
1535 pr_warn("MAC%u: malformed TLV buf; bytes left: %zu\n",
1536 mac->macid, payload_len);
1537 return -EINVAL;
1540 return 0;
1543 static int
1544 qtnf_cmd_resp_proc_chan_stat_info(struct qtnf_chan_stats *stats,
1545 const u8 *payload, size_t payload_len)
1547 struct qlink_chan_stats *qlink_stats;
1548 const struct qlink_tlv_hdr *tlv;
1549 size_t tlv_full_len;
1550 u16 tlv_value_len;
1551 u16 tlv_type;
1553 tlv = (struct qlink_tlv_hdr *)payload;
1554 while (payload_len >= sizeof(struct qlink_tlv_hdr)) {
1555 tlv_type = le16_to_cpu(tlv->type);
1556 tlv_value_len = le16_to_cpu(tlv->len);
1557 tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr);
1558 if (tlv_full_len > payload_len) {
1559 pr_warn("malformed TLV 0x%.2X; LEN: %u\n",
1560 tlv_type, tlv_value_len);
1561 return -EINVAL;
1563 switch (tlv_type) {
1564 case QTN_TLV_ID_CHANNEL_STATS:
1565 if (unlikely(tlv_value_len != sizeof(*qlink_stats))) {
1566 pr_err("invalid CHANNEL_STATS entry size\n");
1567 return -EINVAL;
1570 qlink_stats = (void *)tlv->val;
1572 stats->chan_num = le32_to_cpu(qlink_stats->chan_num);
1573 stats->cca_tx = le32_to_cpu(qlink_stats->cca_tx);
1574 stats->cca_rx = le32_to_cpu(qlink_stats->cca_rx);
1575 stats->cca_busy = le32_to_cpu(qlink_stats->cca_busy);
1576 stats->cca_try = le32_to_cpu(qlink_stats->cca_try);
1577 stats->chan_noise = qlink_stats->chan_noise;
1579 pr_debug("chan(%u) try(%u) busy(%u) noise(%d)\n",
1580 stats->chan_num, stats->cca_try,
1581 stats->cca_busy, stats->chan_noise);
1582 break;
1583 default:
1584 pr_warn("Unknown TLV type: %#x\n",
1585 le16_to_cpu(tlv->type));
1587 payload_len -= tlv_full_len;
1588 tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len);
1591 if (payload_len) {
1592 pr_warn("malformed TLV buf; bytes left: %zu\n", payload_len);
1593 return -EINVAL;
1596 return 0;
1599 int qtnf_cmd_get_mac_info(struct qtnf_wmac *mac)
1601 struct sk_buff *cmd_skb, *resp_skb = NULL;
1602 const struct qlink_resp_get_mac_info *resp;
1603 size_t var_data_len = 0;
1604 int ret = 0;
1606 cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, QLINK_VIFID_RSVD,
1607 QLINK_CMD_MAC_INFO,
1608 sizeof(struct qlink_cmd));
1609 if (!cmd_skb)
1610 return -ENOMEM;
1612 qtnf_bus_lock(mac->bus);
1613 ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb,
1614 sizeof(*resp), &var_data_len);
1615 if (ret)
1616 goto out;
1618 resp = (const struct qlink_resp_get_mac_info *)resp_skb->data;
1619 qtnf_cmd_resp_proc_mac_info(mac, resp);
1620 ret = qtnf_parse_variable_mac_info(mac, resp, var_data_len);
1622 out:
1623 qtnf_bus_unlock(mac->bus);
1624 consume_skb(resp_skb);
1626 return ret;
1629 int qtnf_cmd_get_hw_info(struct qtnf_bus *bus)
1631 struct sk_buff *cmd_skb, *resp_skb = NULL;
1632 const struct qlink_resp_get_hw_info *resp;
1633 size_t info_len = 0;
1634 int ret = 0;
1636 cmd_skb = qtnf_cmd_alloc_new_cmdskb(QLINK_MACID_RSVD, QLINK_VIFID_RSVD,
1637 QLINK_CMD_GET_HW_INFO,
1638 sizeof(struct qlink_cmd));
1639 if (!cmd_skb)
1640 return -ENOMEM;
1642 qtnf_bus_lock(bus);
1643 ret = qtnf_cmd_send_with_reply(bus, cmd_skb, &resp_skb,
1644 sizeof(*resp), &info_len);
1645 if (ret)
1646 goto out;
1648 resp = (const struct qlink_resp_get_hw_info *)resp_skb->data;
1649 ret = qtnf_cmd_resp_proc_hw_info(bus, resp, info_len);
1651 out:
1652 qtnf_bus_unlock(bus);
1653 consume_skb(resp_skb);
1655 return ret;
1658 int qtnf_cmd_band_info_get(struct qtnf_wmac *mac,
1659 struct ieee80211_supported_band *band)
1661 struct sk_buff *cmd_skb, *resp_skb = NULL;
1662 struct qlink_cmd_band_info_get *cmd;
1663 struct qlink_resp_band_info_get *resp;
1664 size_t info_len = 0;
1665 int ret = 0;
1666 u8 qband = qlink_utils_band_cfg2q(band->band);
1668 cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, 0,
1669 QLINK_CMD_BAND_INFO_GET,
1670 sizeof(*cmd));
1671 if (!cmd_skb)
1672 return -ENOMEM;
1674 cmd = (struct qlink_cmd_band_info_get *)cmd_skb->data;
1675 cmd->band = qband;
1677 qtnf_bus_lock(mac->bus);
1678 ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb,
1679 sizeof(*resp), &info_len);
1680 if (ret)
1681 goto out;
1683 resp = (struct qlink_resp_band_info_get *)resp_skb->data;
1684 if (resp->band != qband) {
1685 pr_err("MAC%u: reply band %u != cmd band %u\n", mac->macid,
1686 resp->band, qband);
1687 ret = -EINVAL;
1688 goto out;
1691 ret = qtnf_cmd_resp_fill_band_info(band, resp, info_len);
1693 out:
1694 qtnf_bus_unlock(mac->bus);
1695 consume_skb(resp_skb);
1697 return ret;
1700 int qtnf_cmd_send_get_phy_params(struct qtnf_wmac *mac)
1702 struct sk_buff *cmd_skb, *resp_skb = NULL;
1703 struct qlink_resp_phy_params *resp;
1704 size_t response_size = 0;
1705 int ret = 0;
1707 cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, 0,
1708 QLINK_CMD_PHY_PARAMS_GET,
1709 sizeof(struct qlink_cmd));
1710 if (!cmd_skb)
1711 return -ENOMEM;
1713 qtnf_bus_lock(mac->bus);
1714 ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb,
1715 sizeof(*resp), &response_size);
1716 if (ret)
1717 goto out;
1719 resp = (struct qlink_resp_phy_params *)resp_skb->data;
1720 ret = qtnf_cmd_resp_proc_phy_params(mac, resp->info, response_size);
1722 out:
1723 qtnf_bus_unlock(mac->bus);
1724 consume_skb(resp_skb);
1726 return ret;
1729 int qtnf_cmd_send_update_phy_params(struct qtnf_wmac *mac, u32 changed)
1731 struct wiphy *wiphy = priv_to_wiphy(mac);
1732 struct sk_buff *cmd_skb;
1733 int ret = 0;
1735 cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, 0,
1736 QLINK_CMD_PHY_PARAMS_SET,
1737 sizeof(struct qlink_cmd));
1738 if (!cmd_skb)
1739 return -ENOMEM;
1741 qtnf_bus_lock(mac->bus);
1743 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
1744 qtnf_cmd_skb_put_tlv_u32(cmd_skb, QTN_TLV_ID_FRAG_THRESH,
1745 wiphy->frag_threshold);
1746 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
1747 qtnf_cmd_skb_put_tlv_u32(cmd_skb, QTN_TLV_ID_RTS_THRESH,
1748 wiphy->rts_threshold);
1749 if (changed & WIPHY_PARAM_COVERAGE_CLASS)
1750 qtnf_cmd_skb_put_tlv_u8(cmd_skb, QTN_TLV_ID_COVERAGE_CLASS,
1751 wiphy->coverage_class);
1753 if (changed & WIPHY_PARAM_RETRY_LONG)
1754 qtnf_cmd_skb_put_tlv_u8(cmd_skb, QTN_TLV_ID_LRETRY_LIMIT,
1755 wiphy->retry_long);
1757 if (changed & WIPHY_PARAM_RETRY_SHORT)
1758 qtnf_cmd_skb_put_tlv_u8(cmd_skb, QTN_TLV_ID_SRETRY_LIMIT,
1759 wiphy->retry_short);
1761 ret = qtnf_cmd_send(mac->bus, cmd_skb);
1762 if (ret)
1763 goto out;
1765 out:
1766 qtnf_bus_unlock(mac->bus);
1768 return ret;
1771 int qtnf_cmd_send_init_fw(struct qtnf_bus *bus)
1773 struct sk_buff *cmd_skb;
1774 int ret = 0;
1776 cmd_skb = qtnf_cmd_alloc_new_cmdskb(QLINK_MACID_RSVD, QLINK_VIFID_RSVD,
1777 QLINK_CMD_FW_INIT,
1778 sizeof(struct qlink_cmd));
1779 if (!cmd_skb)
1780 return -ENOMEM;
1782 qtnf_bus_lock(bus);
1783 ret = qtnf_cmd_send(bus, cmd_skb);
1784 if (ret)
1785 goto out;
1787 out:
1788 qtnf_bus_unlock(bus);
1790 return ret;
1793 void qtnf_cmd_send_deinit_fw(struct qtnf_bus *bus)
1795 struct sk_buff *cmd_skb;
1797 cmd_skb = qtnf_cmd_alloc_new_cmdskb(QLINK_MACID_RSVD, QLINK_VIFID_RSVD,
1798 QLINK_CMD_FW_DEINIT,
1799 sizeof(struct qlink_cmd));
1800 if (!cmd_skb)
1801 return;
1803 qtnf_bus_lock(bus);
1804 qtnf_cmd_send(bus, cmd_skb);
1805 qtnf_bus_unlock(bus);
1808 int qtnf_cmd_send_add_key(struct qtnf_vif *vif, u8 key_index, bool pairwise,
1809 const u8 *mac_addr, struct key_params *params)
1811 struct sk_buff *cmd_skb;
1812 struct qlink_cmd_add_key *cmd;
1813 int ret = 0;
1815 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
1816 QLINK_CMD_ADD_KEY,
1817 sizeof(*cmd));
1818 if (!cmd_skb)
1819 return -ENOMEM;
1821 qtnf_bus_lock(vif->mac->bus);
1823 cmd = (struct qlink_cmd_add_key *)cmd_skb->data;
1825 if (mac_addr)
1826 ether_addr_copy(cmd->addr, mac_addr);
1827 else
1828 eth_broadcast_addr(cmd->addr);
1830 cmd->cipher = cpu_to_le32(params->cipher);
1831 cmd->key_index = key_index;
1832 cmd->pairwise = pairwise;
1834 if (params->key && params->key_len > 0)
1835 qtnf_cmd_skb_put_tlv_arr(cmd_skb, QTN_TLV_ID_KEY,
1836 params->key,
1837 params->key_len);
1839 if (params->seq && params->seq_len > 0)
1840 qtnf_cmd_skb_put_tlv_arr(cmd_skb, QTN_TLV_ID_SEQ,
1841 params->seq,
1842 params->seq_len);
1844 ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
1845 if (ret)
1846 goto out;
1848 out:
1849 qtnf_bus_unlock(vif->mac->bus);
1851 return ret;
1854 int qtnf_cmd_send_del_key(struct qtnf_vif *vif, u8 key_index, bool pairwise,
1855 const u8 *mac_addr)
1857 struct sk_buff *cmd_skb;
1858 struct qlink_cmd_del_key *cmd;
1859 int ret = 0;
1861 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
1862 QLINK_CMD_DEL_KEY,
1863 sizeof(*cmd));
1864 if (!cmd_skb)
1865 return -ENOMEM;
1867 qtnf_bus_lock(vif->mac->bus);
1869 cmd = (struct qlink_cmd_del_key *)cmd_skb->data;
1871 if (mac_addr)
1872 ether_addr_copy(cmd->addr, mac_addr);
1873 else
1874 eth_broadcast_addr(cmd->addr);
1876 cmd->key_index = key_index;
1877 cmd->pairwise = pairwise;
1879 ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
1880 if (ret)
1881 goto out;
1883 out:
1884 qtnf_bus_unlock(vif->mac->bus);
1886 return ret;
1889 int qtnf_cmd_send_set_default_key(struct qtnf_vif *vif, u8 key_index,
1890 bool unicast, bool multicast)
1892 struct sk_buff *cmd_skb;
1893 struct qlink_cmd_set_def_key *cmd;
1894 int ret = 0;
1896 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
1897 QLINK_CMD_SET_DEFAULT_KEY,
1898 sizeof(*cmd));
1899 if (!cmd_skb)
1900 return -ENOMEM;
1902 qtnf_bus_lock(vif->mac->bus);
1904 cmd = (struct qlink_cmd_set_def_key *)cmd_skb->data;
1905 cmd->key_index = key_index;
1906 cmd->unicast = unicast;
1907 cmd->multicast = multicast;
1909 ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
1910 if (ret)
1911 goto out;
1913 out:
1914 qtnf_bus_unlock(vif->mac->bus);
1916 return ret;
1919 int qtnf_cmd_send_set_default_mgmt_key(struct qtnf_vif *vif, u8 key_index)
1921 struct sk_buff *cmd_skb;
1922 struct qlink_cmd_set_def_mgmt_key *cmd;
1923 int ret = 0;
1925 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
1926 QLINK_CMD_SET_DEFAULT_MGMT_KEY,
1927 sizeof(*cmd));
1928 if (!cmd_skb)
1929 return -ENOMEM;
1931 qtnf_bus_lock(vif->mac->bus);
1933 cmd = (struct qlink_cmd_set_def_mgmt_key *)cmd_skb->data;
1934 cmd->key_index = key_index;
1936 ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
1937 if (ret)
1938 goto out;
1940 out:
1941 qtnf_bus_unlock(vif->mac->bus);
1943 return ret;
1946 static u32 qtnf_encode_sta_flags(u32 flags)
1948 u32 code = 0;
1950 if (flags & BIT(NL80211_STA_FLAG_AUTHORIZED))
1951 code |= QLINK_STA_FLAG_AUTHORIZED;
1952 if (flags & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE))
1953 code |= QLINK_STA_FLAG_SHORT_PREAMBLE;
1954 if (flags & BIT(NL80211_STA_FLAG_WME))
1955 code |= QLINK_STA_FLAG_WME;
1956 if (flags & BIT(NL80211_STA_FLAG_MFP))
1957 code |= QLINK_STA_FLAG_MFP;
1958 if (flags & BIT(NL80211_STA_FLAG_AUTHENTICATED))
1959 code |= QLINK_STA_FLAG_AUTHENTICATED;
1960 if (flags & BIT(NL80211_STA_FLAG_TDLS_PEER))
1961 code |= QLINK_STA_FLAG_TDLS_PEER;
1962 if (flags & BIT(NL80211_STA_FLAG_ASSOCIATED))
1963 code |= QLINK_STA_FLAG_ASSOCIATED;
1964 return code;
1967 int qtnf_cmd_send_change_sta(struct qtnf_vif *vif, const u8 *mac,
1968 struct station_parameters *params)
1970 struct sk_buff *cmd_skb;
1971 struct qlink_cmd_change_sta *cmd;
1972 int ret = 0;
1974 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
1975 QLINK_CMD_CHANGE_STA,
1976 sizeof(*cmd));
1977 if (!cmd_skb)
1978 return -ENOMEM;
1980 qtnf_bus_lock(vif->mac->bus);
1982 cmd = (struct qlink_cmd_change_sta *)cmd_skb->data;
1983 ether_addr_copy(cmd->sta_addr, mac);
1984 cmd->flag_update.mask =
1985 cpu_to_le32(qtnf_encode_sta_flags(params->sta_flags_mask));
1986 cmd->flag_update.value =
1987 cpu_to_le32(qtnf_encode_sta_flags(params->sta_flags_set));
1989 switch (vif->wdev.iftype) {
1990 case NL80211_IFTYPE_AP:
1991 cmd->if_type = cpu_to_le16(QLINK_IFTYPE_AP);
1992 break;
1993 case NL80211_IFTYPE_STATION:
1994 cmd->if_type = cpu_to_le16(QLINK_IFTYPE_STATION);
1995 break;
1996 default:
1997 pr_err("unsupported iftype %d\n", vif->wdev.iftype);
1998 ret = -EINVAL;
1999 goto out;
2002 ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
2003 if (ret)
2004 goto out;
2006 out:
2007 qtnf_bus_unlock(vif->mac->bus);
2009 return ret;
2012 int qtnf_cmd_send_del_sta(struct qtnf_vif *vif,
2013 struct station_del_parameters *params)
2015 struct sk_buff *cmd_skb;
2016 struct qlink_cmd_del_sta *cmd;
2017 int ret = 0;
2019 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
2020 QLINK_CMD_DEL_STA,
2021 sizeof(*cmd));
2022 if (!cmd_skb)
2023 return -ENOMEM;
2025 qtnf_bus_lock(vif->mac->bus);
2027 cmd = (struct qlink_cmd_del_sta *)cmd_skb->data;
2029 if (params->mac)
2030 ether_addr_copy(cmd->sta_addr, params->mac);
2031 else
2032 eth_broadcast_addr(cmd->sta_addr); /* flush all stations */
2034 cmd->subtype = params->subtype;
2035 cmd->reason_code = cpu_to_le16(params->reason_code);
2037 ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
2038 if (ret)
2039 goto out;
2041 out:
2042 qtnf_bus_unlock(vif->mac->bus);
2044 return ret;
2047 static void qtnf_cmd_channel_tlv_add(struct sk_buff *cmd_skb,
2048 const struct ieee80211_channel *sc)
2050 struct qlink_tlv_channel *tlv;
2051 struct qlink_channel *qch;
2053 tlv = skb_put_zero(cmd_skb, sizeof(*tlv));
2054 qch = &tlv->chan;
2055 tlv->hdr.type = cpu_to_le16(QTN_TLV_ID_CHANNEL);
2056 tlv->hdr.len = cpu_to_le16(sizeof(*qch));
2058 qch->center_freq = cpu_to_le16(sc->center_freq);
2059 qch->hw_value = cpu_to_le16(sc->hw_value);
2060 qch->band = qlink_utils_band_cfg2q(sc->band);
2061 qch->max_power = sc->max_power;
2062 qch->max_reg_power = sc->max_reg_power;
2063 qch->max_antenna_gain = sc->max_antenna_gain;
2064 qch->beacon_found = sc->beacon_found;
2065 qch->dfs_state = qlink_utils_dfs_state_cfg2q(sc->dfs_state);
2066 qch->flags = cpu_to_le32(qlink_utils_chflags_cfg2q(sc->flags));
2069 static void qtnf_cmd_randmac_tlv_add(struct sk_buff *cmd_skb,
2070 const u8 *mac_addr,
2071 const u8 *mac_addr_mask)
2073 struct qlink_random_mac_addr *randmac;
2074 struct qlink_tlv_hdr *hdr =
2075 skb_put(cmd_skb, sizeof(*hdr) + sizeof(*randmac));
2077 hdr->type = cpu_to_le16(QTN_TLV_ID_RANDOM_MAC_ADDR);
2078 hdr->len = cpu_to_le16(sizeof(*randmac));
2079 randmac = (struct qlink_random_mac_addr *)hdr->val;
2081 memcpy(randmac->mac_addr, mac_addr, ETH_ALEN);
2082 memcpy(randmac->mac_addr_mask, mac_addr_mask, ETH_ALEN);
2085 static void qtnf_cmd_scan_set_dwell(struct qtnf_wmac *mac,
2086 struct sk_buff *cmd_skb)
2088 struct cfg80211_scan_request *scan_req = mac->scan_req;
2089 u16 dwell_active = QTNF_SCAN_DWELL_ACTIVE_DEFAULT;
2090 u16 dwell_passive = QTNF_SCAN_DWELL_PASSIVE_DEFAULT;
2091 u16 duration = QTNF_SCAN_SAMPLE_DURATION_DEFAULT;
2093 if (scan_req->duration) {
2094 dwell_active = scan_req->duration;
2095 dwell_passive = scan_req->duration;
2098 pr_debug("MAC%u: %s scan dwell active=%u, passive=%u, duration=%u\n",
2099 mac->macid,
2100 scan_req->duration_mandatory ? "mandatory" : "max",
2101 dwell_active, dwell_passive, duration);
2103 qtnf_cmd_skb_put_tlv_u16(cmd_skb,
2104 QTN_TLV_ID_SCAN_DWELL_ACTIVE,
2105 dwell_active);
2106 qtnf_cmd_skb_put_tlv_u16(cmd_skb,
2107 QTN_TLV_ID_SCAN_DWELL_PASSIVE,
2108 dwell_passive);
2109 qtnf_cmd_skb_put_tlv_u16(cmd_skb,
2110 QTN_TLV_ID_SCAN_SAMPLE_DURATION,
2111 duration);
2114 int qtnf_cmd_send_scan(struct qtnf_wmac *mac)
2116 struct sk_buff *cmd_skb;
2117 struct ieee80211_channel *sc;
2118 struct cfg80211_scan_request *scan_req = mac->scan_req;
2119 int n_channels;
2120 int count = 0;
2121 int ret;
2123 cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, QLINK_VIFID_RSVD,
2124 QLINK_CMD_SCAN,
2125 sizeof(struct qlink_cmd));
2126 if (!cmd_skb)
2127 return -ENOMEM;
2129 qtnf_bus_lock(mac->bus);
2131 if (scan_req->n_ssids != 0) {
2132 while (count < scan_req->n_ssids) {
2133 qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID,
2134 scan_req->ssids[count].ssid,
2135 scan_req->ssids[count].ssid_len);
2136 count++;
2140 if (scan_req->ie_len != 0)
2141 qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_PROBE_REQ,
2142 scan_req->ie, scan_req->ie_len);
2144 if (scan_req->n_channels) {
2145 n_channels = scan_req->n_channels;
2146 count = 0;
2148 while (n_channels != 0) {
2149 sc = scan_req->channels[count];
2150 if (sc->flags & IEEE80211_CHAN_DISABLED) {
2151 n_channels--;
2152 continue;
2155 pr_debug("MAC%u: scan chan=%d, freq=%d, flags=%#x\n",
2156 mac->macid, sc->hw_value, sc->center_freq,
2157 sc->flags);
2159 qtnf_cmd_channel_tlv_add(cmd_skb, sc);
2160 n_channels--;
2161 count++;
2165 qtnf_cmd_scan_set_dwell(mac, cmd_skb);
2167 if (scan_req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
2168 pr_debug("MAC%u: scan with random addr=%pM, mask=%pM\n",
2169 mac->macid,
2170 scan_req->mac_addr, scan_req->mac_addr_mask);
2172 qtnf_cmd_randmac_tlv_add(cmd_skb, scan_req->mac_addr,
2173 scan_req->mac_addr_mask);
2176 if (scan_req->flags & NL80211_SCAN_FLAG_FLUSH) {
2177 pr_debug("MAC%u: flush cache before scan\n", mac->macid);
2179 qtnf_cmd_skb_put_tlv_tag(cmd_skb, QTN_TLV_ID_SCAN_FLUSH);
2182 ret = qtnf_cmd_send(mac->bus, cmd_skb);
2183 if (ret)
2184 goto out;
2186 out:
2187 qtnf_bus_unlock(mac->bus);
2189 return ret;
2192 int qtnf_cmd_send_connect(struct qtnf_vif *vif,
2193 struct cfg80211_connect_params *sme)
2195 struct sk_buff *cmd_skb;
2196 struct qlink_cmd_connect *cmd;
2197 struct qlink_auth_encr *aen;
2198 int ret;
2199 int i;
2200 u32 connect_flags = 0;
2202 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
2203 QLINK_CMD_CONNECT,
2204 sizeof(*cmd));
2205 if (!cmd_skb)
2206 return -ENOMEM;
2208 cmd = (struct qlink_cmd_connect *)cmd_skb->data;
2210 ether_addr_copy(cmd->bssid, vif->bssid);
2212 if (sme->bssid_hint)
2213 ether_addr_copy(cmd->bssid_hint, sme->bssid_hint);
2214 else
2215 eth_zero_addr(cmd->bssid_hint);
2217 if (sme->prev_bssid)
2218 ether_addr_copy(cmd->prev_bssid, sme->prev_bssid);
2219 else
2220 eth_zero_addr(cmd->prev_bssid);
2222 if ((sme->bg_scan_period >= 0) &&
2223 (sme->bg_scan_period <= SHRT_MAX))
2224 cmd->bg_scan_period = cpu_to_le16(sme->bg_scan_period);
2225 else
2226 cmd->bg_scan_period = cpu_to_le16(-1); /* use default value */
2228 if (sme->flags & ASSOC_REQ_DISABLE_HT)
2229 connect_flags |= QLINK_STA_CONNECT_DISABLE_HT;
2230 if (sme->flags & ASSOC_REQ_DISABLE_VHT)
2231 connect_flags |= QLINK_STA_CONNECT_DISABLE_VHT;
2232 if (sme->flags & ASSOC_REQ_USE_RRM)
2233 connect_flags |= QLINK_STA_CONNECT_USE_RRM;
2235 cmd->flags = cpu_to_le32(connect_flags);
2236 memcpy(&cmd->ht_capa, &sme->ht_capa, sizeof(cmd->ht_capa));
2237 memcpy(&cmd->ht_capa_mask, &sme->ht_capa_mask,
2238 sizeof(cmd->ht_capa_mask));
2239 memcpy(&cmd->vht_capa, &sme->vht_capa, sizeof(cmd->vht_capa));
2240 memcpy(&cmd->vht_capa_mask, &sme->vht_capa_mask,
2241 sizeof(cmd->vht_capa_mask));
2242 cmd->pbss = sme->pbss;
2244 aen = &cmd->aen;
2245 aen->auth_type = sme->auth_type;
2246 aen->privacy = !!sme->privacy;
2247 cmd->mfp = sme->mfp;
2248 aen->wpa_versions = cpu_to_le32(sme->crypto.wpa_versions);
2249 aen->cipher_group = cpu_to_le32(sme->crypto.cipher_group);
2250 aen->n_ciphers_pairwise = cpu_to_le32(sme->crypto.n_ciphers_pairwise);
2252 for (i = 0; i < QLINK_MAX_NR_CIPHER_SUITES; i++)
2253 aen->ciphers_pairwise[i] =
2254 cpu_to_le32(sme->crypto.ciphers_pairwise[i]);
2256 aen->n_akm_suites = cpu_to_le32(sme->crypto.n_akm_suites);
2258 for (i = 0; i < QLINK_MAX_NR_AKM_SUITES; i++)
2259 aen->akm_suites[i] = cpu_to_le32(sme->crypto.akm_suites[i]);
2261 aen->control_port = sme->crypto.control_port;
2262 aen->control_port_no_encrypt =
2263 sme->crypto.control_port_no_encrypt;
2264 aen->control_port_ethertype =
2265 cpu_to_le16(be16_to_cpu(sme->crypto.control_port_ethertype));
2267 qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID, sme->ssid,
2268 sme->ssid_len);
2270 if (sme->ie_len != 0)
2271 qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_ASSOC_REQ,
2272 sme->ie, sme->ie_len);
2274 if (sme->channel)
2275 qtnf_cmd_channel_tlv_add(cmd_skb, sme->channel);
2277 qtnf_bus_lock(vif->mac->bus);
2278 ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
2279 if (ret)
2280 goto out;
2282 out:
2283 qtnf_bus_unlock(vif->mac->bus);
2285 return ret;
2288 int qtnf_cmd_send_external_auth(struct qtnf_vif *vif,
2289 struct cfg80211_external_auth_params *auth)
2291 struct sk_buff *cmd_skb;
2292 struct qlink_cmd_external_auth *cmd;
2293 int ret;
2295 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
2296 QLINK_CMD_EXTERNAL_AUTH,
2297 sizeof(*cmd));
2298 if (!cmd_skb)
2299 return -ENOMEM;
2301 cmd = (struct qlink_cmd_external_auth *)cmd_skb->data;
2303 ether_addr_copy(cmd->bssid, auth->bssid);
2304 cmd->status = cpu_to_le16(auth->status);
2306 qtnf_bus_lock(vif->mac->bus);
2307 ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
2308 if (ret)
2309 goto out;
2311 out:
2312 qtnf_bus_unlock(vif->mac->bus);
2314 return ret;
2317 int qtnf_cmd_send_disconnect(struct qtnf_vif *vif, u16 reason_code)
2319 struct sk_buff *cmd_skb;
2320 struct qlink_cmd_disconnect *cmd;
2321 int ret;
2323 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
2324 QLINK_CMD_DISCONNECT,
2325 sizeof(*cmd));
2326 if (!cmd_skb)
2327 return -ENOMEM;
2329 qtnf_bus_lock(vif->mac->bus);
2331 cmd = (struct qlink_cmd_disconnect *)cmd_skb->data;
2332 cmd->reason = cpu_to_le16(reason_code);
2334 ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
2335 if (ret)
2336 goto out;
2338 out:
2339 qtnf_bus_unlock(vif->mac->bus);
2341 return ret;
2344 int qtnf_cmd_send_updown_intf(struct qtnf_vif *vif, bool up)
2346 struct sk_buff *cmd_skb;
2347 struct qlink_cmd_updown *cmd;
2348 int ret;
2350 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
2351 QLINK_CMD_UPDOWN_INTF,
2352 sizeof(*cmd));
2353 if (!cmd_skb)
2354 return -ENOMEM;
2356 cmd = (struct qlink_cmd_updown *)cmd_skb->data;
2357 cmd->if_up = !!up;
2359 qtnf_bus_lock(vif->mac->bus);
2360 ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
2361 if (ret)
2362 goto out;
2364 out:
2365 qtnf_bus_unlock(vif->mac->bus);
2367 return ret;
2370 int qtnf_cmd_reg_notify(struct qtnf_wmac *mac, struct regulatory_request *req,
2371 bool slave_radar)
2373 struct wiphy *wiphy = priv_to_wiphy(mac);
2374 struct qtnf_bus *bus = mac->bus;
2375 struct sk_buff *cmd_skb;
2376 int ret;
2377 struct qlink_cmd_reg_notify *cmd;
2378 enum nl80211_band band;
2379 const struct ieee80211_supported_band *cfg_band;
2381 cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, QLINK_VIFID_RSVD,
2382 QLINK_CMD_REG_NOTIFY,
2383 sizeof(*cmd));
2384 if (!cmd_skb)
2385 return -ENOMEM;
2387 cmd = (struct qlink_cmd_reg_notify *)cmd_skb->data;
2388 cmd->alpha2[0] = req->alpha2[0];
2389 cmd->alpha2[1] = req->alpha2[1];
2391 switch (req->initiator) {
2392 case NL80211_REGDOM_SET_BY_CORE:
2393 cmd->initiator = QLINK_REGDOM_SET_BY_CORE;
2394 break;
2395 case NL80211_REGDOM_SET_BY_USER:
2396 cmd->initiator = QLINK_REGDOM_SET_BY_USER;
2397 break;
2398 case NL80211_REGDOM_SET_BY_DRIVER:
2399 cmd->initiator = QLINK_REGDOM_SET_BY_DRIVER;
2400 break;
2401 case NL80211_REGDOM_SET_BY_COUNTRY_IE:
2402 cmd->initiator = QLINK_REGDOM_SET_BY_COUNTRY_IE;
2403 break;
2406 switch (req->user_reg_hint_type) {
2407 case NL80211_USER_REG_HINT_USER:
2408 cmd->user_reg_hint_type = QLINK_USER_REG_HINT_USER;
2409 break;
2410 case NL80211_USER_REG_HINT_CELL_BASE:
2411 cmd->user_reg_hint_type = QLINK_USER_REG_HINT_CELL_BASE;
2412 break;
2413 case NL80211_USER_REG_HINT_INDOOR:
2414 cmd->user_reg_hint_type = QLINK_USER_REG_HINT_INDOOR;
2415 break;
2418 switch (req->dfs_region) {
2419 case NL80211_DFS_FCC:
2420 cmd->dfs_region = QLINK_DFS_FCC;
2421 break;
2422 case NL80211_DFS_ETSI:
2423 cmd->dfs_region = QLINK_DFS_ETSI;
2424 break;
2425 case NL80211_DFS_JP:
2426 cmd->dfs_region = QLINK_DFS_JP;
2427 break;
2428 default:
2429 cmd->dfs_region = QLINK_DFS_UNSET;
2430 break;
2433 cmd->slave_radar = slave_radar;
2434 cmd->num_channels = 0;
2436 for (band = 0; band < NUM_NL80211_BANDS; band++) {
2437 unsigned int i;
2439 cfg_band = wiphy->bands[band];
2440 if (!cfg_band)
2441 continue;
2443 cmd->num_channels += cfg_band->n_channels;
2445 for (i = 0; i < cfg_band->n_channels; ++i) {
2446 qtnf_cmd_channel_tlv_add(cmd_skb,
2447 &cfg_band->channels[i]);
2451 qtnf_bus_lock(bus);
2452 ret = qtnf_cmd_send(bus, cmd_skb);
2453 qtnf_bus_unlock(bus);
2455 return ret;
2458 int qtnf_cmd_get_chan_stats(struct qtnf_wmac *mac, u16 channel,
2459 struct qtnf_chan_stats *stats)
2461 struct sk_buff *cmd_skb, *resp_skb = NULL;
2462 struct qlink_cmd_get_chan_stats *cmd;
2463 struct qlink_resp_get_chan_stats *resp;
2464 size_t var_data_len = 0;
2465 int ret = 0;
2467 cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, QLINK_VIFID_RSVD,
2468 QLINK_CMD_CHAN_STATS,
2469 sizeof(*cmd));
2470 if (!cmd_skb)
2471 return -ENOMEM;
2473 qtnf_bus_lock(mac->bus);
2475 cmd = (struct qlink_cmd_get_chan_stats *)cmd_skb->data;
2476 cmd->channel = cpu_to_le16(channel);
2478 ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb,
2479 sizeof(*resp), &var_data_len);
2480 if (ret)
2481 goto out;
2483 resp = (struct qlink_resp_get_chan_stats *)resp_skb->data;
2484 ret = qtnf_cmd_resp_proc_chan_stat_info(stats, resp->info,
2485 var_data_len);
2487 out:
2488 qtnf_bus_unlock(mac->bus);
2489 consume_skb(resp_skb);
2491 return ret;
2494 int qtnf_cmd_send_chan_switch(struct qtnf_vif *vif,
2495 struct cfg80211_csa_settings *params)
2497 struct qtnf_wmac *mac = vif->mac;
2498 struct qlink_cmd_chan_switch *cmd;
2499 struct sk_buff *cmd_skb;
2500 int ret;
2502 cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, vif->vifid,
2503 QLINK_CMD_CHAN_SWITCH,
2504 sizeof(*cmd));
2505 if (!cmd_skb)
2506 return -ENOMEM;
2508 qtnf_bus_lock(mac->bus);
2510 cmd = (struct qlink_cmd_chan_switch *)cmd_skb->data;
2511 cmd->channel = cpu_to_le16(params->chandef.chan->hw_value);
2512 cmd->radar_required = params->radar_required;
2513 cmd->block_tx = params->block_tx;
2514 cmd->beacon_count = params->count;
2516 ret = qtnf_cmd_send(mac->bus, cmd_skb);
2517 if (ret)
2518 goto out;
2520 out:
2521 qtnf_bus_unlock(mac->bus);
2523 return ret;
2526 int qtnf_cmd_get_channel(struct qtnf_vif *vif, struct cfg80211_chan_def *chdef)
2528 struct qtnf_bus *bus = vif->mac->bus;
2529 const struct qlink_resp_channel_get *resp;
2530 struct sk_buff *cmd_skb;
2531 struct sk_buff *resp_skb = NULL;
2532 int ret;
2534 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
2535 QLINK_CMD_CHAN_GET,
2536 sizeof(struct qlink_cmd));
2537 if (!cmd_skb)
2538 return -ENOMEM;
2540 qtnf_bus_lock(bus);
2541 ret = qtnf_cmd_send_with_reply(bus, cmd_skb, &resp_skb,
2542 sizeof(*resp), NULL);
2543 if (ret)
2544 goto out;
2546 resp = (const struct qlink_resp_channel_get *)resp_skb->data;
2547 qlink_chandef_q2cfg(priv_to_wiphy(vif->mac), &resp->chan, chdef);
2549 out:
2550 qtnf_bus_unlock(bus);
2551 consume_skb(resp_skb);
2553 return ret;
2556 int qtnf_cmd_start_cac(const struct qtnf_vif *vif,
2557 const struct cfg80211_chan_def *chdef,
2558 u32 cac_time_ms)
2560 struct qtnf_bus *bus = vif->mac->bus;
2561 struct sk_buff *cmd_skb;
2562 struct qlink_cmd_start_cac *cmd;
2563 int ret;
2565 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
2566 QLINK_CMD_START_CAC,
2567 sizeof(*cmd));
2568 if (!cmd_skb)
2569 return -ENOMEM;
2571 cmd = (struct qlink_cmd_start_cac *)cmd_skb->data;
2572 cmd->cac_time_ms = cpu_to_le32(cac_time_ms);
2573 qlink_chandef_cfg2q(chdef, &cmd->chan);
2575 qtnf_bus_lock(bus);
2576 ret = qtnf_cmd_send(bus, cmd_skb);
2577 if (ret)
2578 goto out;
2580 out:
2581 qtnf_bus_unlock(bus);
2583 return ret;
2586 int qtnf_cmd_set_mac_acl(const struct qtnf_vif *vif,
2587 const struct cfg80211_acl_data *params)
2589 struct qtnf_bus *bus = vif->mac->bus;
2590 struct sk_buff *cmd_skb;
2591 struct qlink_tlv_hdr *tlv;
2592 size_t acl_size = struct_size(params, mac_addrs, params->n_acl_entries);
2593 int ret;
2595 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
2596 QLINK_CMD_SET_MAC_ACL,
2597 sizeof(struct qlink_cmd));
2598 if (!cmd_skb)
2599 return -ENOMEM;
2601 tlv = skb_put(cmd_skb, sizeof(*tlv) + acl_size);
2602 tlv->type = cpu_to_le16(QTN_TLV_ID_ACL_DATA);
2603 tlv->len = cpu_to_le16(acl_size);
2604 qlink_acl_data_cfg2q(params, (struct qlink_acl_data *)tlv->val);
2606 qtnf_bus_lock(bus);
2607 ret = qtnf_cmd_send(bus, cmd_skb);
2608 if (ret)
2609 goto out;
2611 out:
2612 qtnf_bus_unlock(bus);
2614 return ret;
2617 int qtnf_cmd_send_pm_set(const struct qtnf_vif *vif, u8 pm_mode, int timeout)
2619 struct qtnf_bus *bus = vif->mac->bus;
2620 struct sk_buff *cmd_skb;
2621 struct qlink_cmd_pm_set *cmd;
2622 int ret = 0;
2624 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
2625 QLINK_CMD_PM_SET, sizeof(*cmd));
2626 if (!cmd_skb)
2627 return -ENOMEM;
2629 cmd = (struct qlink_cmd_pm_set *)cmd_skb->data;
2630 cmd->pm_mode = pm_mode;
2631 cmd->pm_standby_timer = cpu_to_le32(timeout);
2633 qtnf_bus_lock(bus);
2635 ret = qtnf_cmd_send(bus, cmd_skb);
2636 if (ret)
2637 goto out;
2639 out:
2640 qtnf_bus_unlock(bus);
2642 return ret;
2645 int qtnf_cmd_send_wowlan_set(const struct qtnf_vif *vif,
2646 const struct cfg80211_wowlan *wowl)
2648 struct qtnf_bus *bus = vif->mac->bus;
2649 struct sk_buff *cmd_skb;
2650 struct qlink_cmd_wowlan_set *cmd;
2651 u32 triggers = 0;
2652 int count = 0;
2653 int ret = 0;
2655 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
2656 QLINK_CMD_WOWLAN_SET, sizeof(*cmd));
2657 if (!cmd_skb)
2658 return -ENOMEM;
2660 qtnf_bus_lock(bus);
2662 cmd = (struct qlink_cmd_wowlan_set *)cmd_skb->data;
2664 if (wowl) {
2665 if (wowl->disconnect)
2666 triggers |= QLINK_WOWLAN_TRIG_DISCONNECT;
2668 if (wowl->magic_pkt)
2669 triggers |= QLINK_WOWLAN_TRIG_MAGIC_PKT;
2671 if (wowl->n_patterns && wowl->patterns) {
2672 triggers |= QLINK_WOWLAN_TRIG_PATTERN_PKT;
2673 while (count < wowl->n_patterns) {
2674 qtnf_cmd_skb_put_tlv_arr(cmd_skb,
2675 QTN_TLV_ID_WOWLAN_PATTERN,
2676 wowl->patterns[count].pattern,
2677 wowl->patterns[count].pattern_len);
2678 count++;
2683 cmd->triggers = cpu_to_le32(triggers);
2685 ret = qtnf_cmd_send(bus, cmd_skb);
2686 if (ret)
2687 goto out;
2689 out:
2690 qtnf_bus_unlock(bus);
2691 return ret;