1 // SPDX-License-Identifier: GPL-2.0+
2 /* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */
3
4 #include <linux/types.h>
5 #include <linux/skbuff.h>
6
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"
13
14 /* Let device itself to select best values for current conditions */
15 #define QTNF_SCAN_TIME_AUTO 0
16
17 #define QTNF_SCAN_DWELL_ACTIVE_DEFAULT 90
18 #define QTNF_SCAN_DWELL_PASSIVE_DEFAULT 100
19 #define QTNF_SCAN_SAMPLE_DURATION_DEFAULT QTNF_SCAN_TIME_AUTO
20
qtnf_cmd_check_reply_header(const struct qlink_resp * resp,u16 cmd_id,u8 mac_id,u8 vif_id,size_t resp_size)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)
24 {
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;
29 }
30
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;
35 }
36
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;
41 }
42
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;
48 }
49
50 return 0;
51 }
52
qtnf_cmd_resp_result_decode(enum qlink_cmd_result qcode)53 static int qtnf_cmd_resp_result_decode(enum qlink_cmd_result qcode)
54 {
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;
74 }
75 }
76
qtnf_cmd_send_with_reply(struct qtnf_bus * bus,struct sk_buff * cmd_skb,struct sk_buff ** response_skb,size_t const_resp_size,size_t * var_resp_size)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)
82 {
83 struct qlink_cmd *cmd;
84 struct qlink_resp *resp = NULL;
85 struct sk_buff *resp_skb = NULL;
86 int resp_res = 0;
87 u16 cmd_id;
88 u8 mac_id;
89 u8 vif_id;
90 int ret;
91
92 cmd = (struct qlink_cmd *)cmd_skb->data;
93 cmd_id = le16_to_cpu(cmd->cmd_id);
94 mac_id = cmd->macid;
95 vif_id = cmd->vifid;
96 cmd->mhdr.len = cpu_to_le16(cmd_skb->len);
97
98 pr_debug("VIF%u.%u cmd=0x%.4X\n", mac_id, vif_id, cmd_id);
99
100 if (!qtnf_fw_is_up(bus) && cmd_id != QLINK_CMD_FW_INIT) {
101 pr_warn("VIF%u.%u: drop cmd 0x%.4X in fw state %d\n",
102 mac_id, vif_id, cmd_id, bus->fw_state);
103 dev_kfree_skb(cmd_skb);
104 return -ENODEV;
105 }
106
107 ret = qtnf_trans_send_cmd_with_resp(bus, cmd_skb, &resp_skb);
108 if (ret)
109 goto out;
110
111 if (WARN_ON(!resp_skb || !resp_skb->data)) {
112 ret = -EFAULT;
113 goto out;
114 }
115
116 resp = (struct qlink_resp *)resp_skb->data;
117 resp_res = le16_to_cpu(resp->result);
118 ret = qtnf_cmd_check_reply_header(resp, cmd_id, mac_id, vif_id,
119 const_resp_size);
120 if (ret)
121 goto out;
122
123 /* Return length of variable part of response */
124 if (response_skb && var_resp_size)
125 *var_resp_size = le16_to_cpu(resp->mhdr.len) - const_resp_size;
126
127 out:
128 if (response_skb)
129 *response_skb = resp_skb;
130 else
131 consume_skb(resp_skb);
132
133 if (!ret)
134 return qtnf_cmd_resp_result_decode(resp_res);
135
136 pr_warn("VIF%u.%u: cmd 0x%.4X failed: %d\n",
137 mac_id, vif_id, cmd_id, ret);
138
139 return ret;
140 }
141
qtnf_cmd_send(struct qtnf_bus * bus,struct sk_buff * cmd_skb)142 static inline int qtnf_cmd_send(struct qtnf_bus *bus, struct sk_buff *cmd_skb)
143 {
144 return qtnf_cmd_send_with_reply(bus, cmd_skb, NULL,
145 sizeof(struct qlink_resp), NULL);
146 }
147
qtnf_cmd_alloc_new_cmdskb(u8 macid,u8 vifid,u16 cmd_no,size_t cmd_size)148 static struct sk_buff *qtnf_cmd_alloc_new_cmdskb(u8 macid, u8 vifid, u16 cmd_no,
149 size_t cmd_size)
150 {
151 struct qlink_cmd *cmd;
152 struct sk_buff *cmd_skb;
153
154 cmd_skb = __dev_alloc_skb(sizeof(*cmd) +
155 QTNF_MAX_CMD_BUF_SIZE, GFP_KERNEL);
156 if (unlikely(!cmd_skb)) {
157 pr_err("VIF%u.%u CMD %u: alloc failed\n", macid, vifid, cmd_no);
158 return NULL;
159 }
160
161 skb_put_zero(cmd_skb, cmd_size);
162
163 cmd = (struct qlink_cmd *)cmd_skb->data;
164 cmd->mhdr.len = cpu_to_le16(cmd_skb->len);
165 cmd->mhdr.type = cpu_to_le16(QLINK_MSG_TYPE_CMD);
166 cmd->cmd_id = cpu_to_le16(cmd_no);
167 cmd->macid = macid;
168 cmd->vifid = vifid;
169
170 return cmd_skb;
171 }
172
qtnf_cmd_tlv_ie_set_add(struct sk_buff * cmd_skb,u8 frame_type,const u8 * buf,size_t len)173 static void qtnf_cmd_tlv_ie_set_add(struct sk_buff *cmd_skb, u8 frame_type,
174 const u8 *buf, size_t len)
175 {
176 struct qlink_tlv_ie_set *tlv;
177
178 tlv = (struct qlink_tlv_ie_set *)skb_put(cmd_skb, sizeof(*tlv) +
179 round_up(len, QLINK_ALIGN));
180 tlv->hdr.type = cpu_to_le16(QTN_TLV_ID_IE_SET);
181 tlv->hdr.len = cpu_to_le16(len + sizeof(*tlv) - sizeof(tlv->hdr));
182 tlv->type = frame_type;
183 tlv->flags = 0;
184
185 if (len && buf)
186 memcpy(tlv->ie_data, buf, len);
187 }
188
qtnf_cmd_start_ap_can_fit(const struct qtnf_vif * vif,const struct cfg80211_ap_settings * s)189 static bool qtnf_cmd_start_ap_can_fit(const struct qtnf_vif *vif,
190 const struct cfg80211_ap_settings *s)
191 {
192 unsigned int len = sizeof(struct qlink_cmd_start_ap);
193
194 len += round_up(s->ssid_len, QLINK_ALIGN);
195 len += round_up(s->beacon.head_len, QLINK_ALIGN);
196 len += round_up(s->beacon.tail_len, QLINK_ALIGN);
197 len += round_up(s->beacon.beacon_ies_len, QLINK_ALIGN);
198 len += round_up(s->beacon.proberesp_ies_len, QLINK_ALIGN);
199 len += round_up(s->beacon.assocresp_ies_len, QLINK_ALIGN);
200 len += round_up(s->beacon.probe_resp_len, QLINK_ALIGN);
201
202 if (cfg80211_chandef_valid(&s->chandef))
203 len += sizeof(struct qlink_tlv_chandef);
204
205 if (s->acl) {
206 unsigned int acl_len = struct_size(s->acl, mac_addrs,
207 s->acl->n_acl_entries);
208
209 len += sizeof(struct qlink_tlv_hdr) +
210 round_up(acl_len, QLINK_ALIGN);
211 }
212
213 if (len > (sizeof(struct qlink_cmd) + QTNF_MAX_CMD_BUF_SIZE)) {
214 pr_err("VIF%u.%u: can not fit AP settings: %u\n",
215 vif->mac->macid, vif->vifid, len);
216 return false;
217 }
218
219 return true;
220 }
221
qtnf_cmd_tlv_ie_ext_add(struct sk_buff * cmd_skb,u8 eid_ext,const void * buf,size_t len)222 static void qtnf_cmd_tlv_ie_ext_add(struct sk_buff *cmd_skb, u8 eid_ext,
223 const void *buf, size_t len)
224 {
225 struct qlink_tlv_ext_ie *tlv;
226
227 tlv = (struct qlink_tlv_ext_ie *)skb_put(cmd_skb, sizeof(*tlv) + len);
228 tlv->hdr.type = cpu_to_le16(WLAN_EID_EXTENSION);
229 tlv->hdr.len = cpu_to_le16(sizeof(*tlv) + len - sizeof(tlv->hdr));
230 tlv->eid_ext = eid_ext;
231
232 if (len && buf)
233 memcpy(tlv->ie_data, buf, len);
234 }
235
qtnf_cmd_send_start_ap(struct qtnf_vif * vif,const struct cfg80211_ap_settings * s)236 int qtnf_cmd_send_start_ap(struct qtnf_vif *vif,
237 const struct cfg80211_ap_settings *s)
238 {
239 struct sk_buff *cmd_skb;
240 struct qlink_cmd_start_ap *cmd;
241 struct qlink_auth_encr *aen;
242 int ret;
243 int i;
244
245 if (!qtnf_cmd_start_ap_can_fit(vif, s))
246 return -E2BIG;
247
248 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
249 QLINK_CMD_START_AP,
250 sizeof(*cmd));
251 if (!cmd_skb)
252 return -ENOMEM;
253
254 cmd = (struct qlink_cmd_start_ap *)cmd_skb->data;
255 cmd->dtim_period = s->dtim_period;
256 cmd->beacon_interval = cpu_to_le16(s->beacon_interval);
257 cmd->hidden_ssid = qlink_hidden_ssid_nl2q(s->hidden_ssid);
258 cmd->inactivity_timeout = cpu_to_le16(s->inactivity_timeout);
259 cmd->smps_mode = s->smps_mode;
260 cmd->p2p_ctwindow = s->p2p_ctwindow;
261 cmd->p2p_opp_ps = s->p2p_opp_ps;
262 cmd->pbss = s->pbss;
263 cmd->ht_required = s->ht_required;
264 cmd->vht_required = s->vht_required;
265 cmd->twt_responder = s->twt_responder;
266 if (s->he_obss_pd.enable) {
267 cmd->sr_params.sr_control |= QLINK_SR_SRG_INFORMATION_PRESENT;
268 cmd->sr_params.srg_obss_pd_min_offset =
269 s->he_obss_pd.min_offset;
270 cmd->sr_params.srg_obss_pd_max_offset =
271 s->he_obss_pd.max_offset;
272 }
273
274 aen = &cmd->aen;
275 aen->auth_type = s->auth_type;
276 aen->privacy = !!s->privacy;
277 aen->wpa_versions = cpu_to_le32(s->crypto.wpa_versions);
278 aen->cipher_group = cpu_to_le32(s->crypto.cipher_group);
279 aen->n_ciphers_pairwise = cpu_to_le32(s->crypto.n_ciphers_pairwise);
280 for (i = 0; i < QLINK_MAX_NR_CIPHER_SUITES; i++)
281 aen->ciphers_pairwise[i] =
282 cpu_to_le32(s->crypto.ciphers_pairwise[i]);
283 aen->n_akm_suites = cpu_to_le32(s->crypto.n_akm_suites);
284 for (i = 0; i < QLINK_MAX_NR_AKM_SUITES; i++)
285 aen->akm_suites[i] = cpu_to_le32(s->crypto.akm_suites[i]);
286 aen->control_port = s->crypto.control_port;
287 aen->control_port_no_encrypt = s->crypto.control_port_no_encrypt;
288 aen->control_port_ethertype =
289 cpu_to_le16(be16_to_cpu(s->crypto.control_port_ethertype));
290
291 if (s->ssid && s->ssid_len > 0 && s->ssid_len <= IEEE80211_MAX_SSID_LEN)
292 qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID, s->ssid,
293 s->ssid_len);
294
295 if (cfg80211_chandef_valid(&s->chandef)) {
296 struct qlink_tlv_chandef *chtlv =
297 (struct qlink_tlv_chandef *)skb_put(cmd_skb,
298 sizeof(*chtlv));
299
300 chtlv->hdr.type = cpu_to_le16(QTN_TLV_ID_CHANDEF);
301 chtlv->hdr.len = cpu_to_le16(sizeof(*chtlv) -
302 sizeof(chtlv->hdr));
303 qlink_chandef_cfg2q(&s->chandef, &chtlv->chdef);
304 }
305
306 qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_BEACON_HEAD,
307 s->beacon.head, s->beacon.head_len);
308 qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_BEACON_TAIL,
309 s->beacon.tail, s->beacon.tail_len);
310 qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_BEACON_IES,
311 s->beacon.beacon_ies, s->beacon.beacon_ies_len);
312 qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_PROBE_RESP,
313 s->beacon.probe_resp, s->beacon.probe_resp_len);
314 qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_PROBE_RESP_IES,
315 s->beacon.proberesp_ies,
316 s->beacon.proberesp_ies_len);
317 qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_ASSOC_RESP,
318 s->beacon.assocresp_ies,
319 s->beacon.assocresp_ies_len);
320
321 if (s->ht_cap) {
322 struct qlink_tlv_hdr *tlv = (struct qlink_tlv_hdr *)
323 skb_put(cmd_skb, sizeof(*tlv) +
324 round_up(sizeof(*s->ht_cap), QLINK_ALIGN));
325
326 tlv->type = cpu_to_le16(WLAN_EID_HT_CAPABILITY);
327 tlv->len = cpu_to_le16(sizeof(*s->ht_cap));
328 memcpy(tlv->val, s->ht_cap, sizeof(*s->ht_cap));
329 }
330
331 if (s->vht_cap) {
332 struct qlink_tlv_hdr *tlv = (struct qlink_tlv_hdr *)
333 skb_put(cmd_skb, sizeof(*tlv) + sizeof(*s->vht_cap));
334
335 tlv->type = cpu_to_le16(WLAN_EID_VHT_CAPABILITY);
336 tlv->len = cpu_to_le16(sizeof(*s->vht_cap));
337 memcpy(tlv->val, s->vht_cap, sizeof(*s->vht_cap));
338 }
339
340 if (s->he_cap)
341 qtnf_cmd_tlv_ie_ext_add(cmd_skb, WLAN_EID_EXT_HE_CAPABILITY,
342 s->he_cap, sizeof(*s->he_cap));
343
344 if (s->acl) {
345 size_t acl_size = struct_size(s->acl, mac_addrs,
346 s->acl->n_acl_entries);
347 struct qlink_tlv_hdr *tlv =
348 skb_put(cmd_skb,
349 sizeof(*tlv) + round_up(acl_size, QLINK_ALIGN));
350
351 tlv->type = cpu_to_le16(QTN_TLV_ID_ACL_DATA);
352 tlv->len = cpu_to_le16(acl_size);
353 qlink_acl_data_cfg2q(s->acl, (struct qlink_acl_data *)tlv->val);
354 }
355
356 qtnf_bus_lock(vif->mac->bus);
357 ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
358 if (ret)
359 goto out;
360
361 netif_carrier_on(vif->netdev);
362
363 out:
364 qtnf_bus_unlock(vif->mac->bus);
365
366 return ret;
367 }
368
qtnf_cmd_send_stop_ap(struct qtnf_vif * vif)369 int qtnf_cmd_send_stop_ap(struct qtnf_vif *vif)
370 {
371 struct sk_buff *cmd_skb;
372 int ret;
373
374 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
375 QLINK_CMD_STOP_AP,
376 sizeof(struct qlink_cmd));
377 if (!cmd_skb)
378 return -ENOMEM;
379
380 qtnf_bus_lock(vif->mac->bus);
381 ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
382 if (ret)
383 goto out;
384
385 out:
386 qtnf_bus_unlock(vif->mac->bus);
387
388 return ret;
389 }
390
qtnf_cmd_send_register_mgmt(struct qtnf_vif * vif,u16 frame_type,bool reg)391 int qtnf_cmd_send_register_mgmt(struct qtnf_vif *vif, u16 frame_type, bool reg)
392 {
393 struct sk_buff *cmd_skb;
394 struct qlink_cmd_mgmt_frame_register *cmd;
395 int ret;
396
397 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
398 QLINK_CMD_REGISTER_MGMT,
399 sizeof(*cmd));
400 if (!cmd_skb)
401 return -ENOMEM;
402
403 qtnf_bus_lock(vif->mac->bus);
404
405 cmd = (struct qlink_cmd_mgmt_frame_register *)cmd_skb->data;
406 cmd->frame_type = cpu_to_le16(frame_type);
407 cmd->do_register = reg;
408
409 ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
410 if (ret)
411 goto out;
412
413 out:
414 qtnf_bus_unlock(vif->mac->bus);
415
416 return ret;
417 }
418
qtnf_cmd_send_frame(struct qtnf_vif * vif,u32 cookie,u16 flags,u16 freq,const u8 * buf,size_t len)419 int qtnf_cmd_send_frame(struct qtnf_vif *vif, u32 cookie, u16 flags,
420 u16 freq, const u8 *buf, size_t len)
421 {
422 struct sk_buff *cmd_skb;
423 struct qlink_cmd_frame_tx *cmd;
424 int ret;
425
426 if (sizeof(*cmd) + len > QTNF_MAX_CMD_BUF_SIZE) {
427 pr_warn("VIF%u.%u: frame is too big: %zu\n", vif->mac->macid,
428 vif->vifid, len);
429 return -E2BIG;
430 }
431
432 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
433 QLINK_CMD_SEND_FRAME,
434 sizeof(*cmd));
435 if (!cmd_skb)
436 return -ENOMEM;
437
438 qtnf_bus_lock(vif->mac->bus);
439
440 cmd = (struct qlink_cmd_frame_tx *)cmd_skb->data;
441 cmd->cookie = cpu_to_le32(cookie);
442 cmd->freq = cpu_to_le16(freq);
443 cmd->flags = cpu_to_le16(flags);
444
445 if (len && buf)
446 qtnf_cmd_skb_put_buffer(cmd_skb, buf, len);
447
448 ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
449 if (ret)
450 goto out;
451
452 out:
453 qtnf_bus_unlock(vif->mac->bus);
454
455 return ret;
456 }
457
qtnf_cmd_send_mgmt_set_appie(struct qtnf_vif * vif,u8 frame_type,const u8 * buf,size_t len)458 int qtnf_cmd_send_mgmt_set_appie(struct qtnf_vif *vif, u8 frame_type,
459 const u8 *buf, size_t len)
460 {
461 struct sk_buff *cmd_skb;
462 int ret;
463
464 if (len > QTNF_MAX_CMD_BUF_SIZE) {
465 pr_warn("VIF%u.%u: %u frame is too big: %zu\n", vif->mac->macid,
466 vif->vifid, frame_type, len);
467 return -E2BIG;
468 }
469
470 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
471 QLINK_CMD_MGMT_SET_APPIE,
472 sizeof(struct qlink_cmd));
473 if (!cmd_skb)
474 return -ENOMEM;
475
476 qtnf_cmd_tlv_ie_set_add(cmd_skb, frame_type, buf, len);
477
478 qtnf_bus_lock(vif->mac->bus);
479 ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
480 if (ret)
481 goto out;
482
483 out:
484 qtnf_bus_unlock(vif->mac->bus);
485
486 return ret;
487 }
488
489 static void
qtnf_sta_info_parse_rate(struct rate_info * rate_dst,const struct qlink_sta_info_rate * rate_src)490 qtnf_sta_info_parse_rate(struct rate_info *rate_dst,
491 const struct qlink_sta_info_rate *rate_src)
492 {
493 rate_dst->legacy = get_unaligned_le16(&rate_src->rate) * 10;
494
495 rate_dst->mcs = rate_src->mcs;
496 rate_dst->nss = rate_src->nss;
497 rate_dst->flags = 0;
498
499 switch (rate_src->bw) {
500 case QLINK_CHAN_WIDTH_5:
501 rate_dst->bw = RATE_INFO_BW_5;
502 break;
503 case QLINK_CHAN_WIDTH_10:
504 rate_dst->bw = RATE_INFO_BW_10;
505 break;
506 case QLINK_CHAN_WIDTH_20:
507 case QLINK_CHAN_WIDTH_20_NOHT:
508 rate_dst->bw = RATE_INFO_BW_20;
509 break;
510 case QLINK_CHAN_WIDTH_40:
511 rate_dst->bw = RATE_INFO_BW_40;
512 break;
513 case QLINK_CHAN_WIDTH_80:
514 rate_dst->bw = RATE_INFO_BW_80;
515 break;
516 case QLINK_CHAN_WIDTH_160:
517 rate_dst->bw = RATE_INFO_BW_160;
518 break;
519 default:
520 rate_dst->bw = 0;
521 break;
522 }
523
524 if (rate_src->flags & QLINK_STA_INFO_RATE_FLAG_HT_MCS)
525 rate_dst->flags |= RATE_INFO_FLAGS_MCS;
526 else if (rate_src->flags & QLINK_STA_INFO_RATE_FLAG_VHT_MCS)
527 rate_dst->flags |= RATE_INFO_FLAGS_VHT_MCS;
528 else if (rate_src->flags & QLINK_STA_INFO_RATE_FLAG_HE_MCS)
529 rate_dst->flags |= RATE_INFO_FLAGS_HE_MCS;
530
531 if (rate_src->flags & QLINK_STA_INFO_RATE_FLAG_SHORT_GI)
532 rate_dst->flags |= RATE_INFO_FLAGS_SHORT_GI;
533 }
534
535 static void
qtnf_sta_info_parse_flags(struct nl80211_sta_flag_update * dst,const struct qlink_sta_info_state * src)536 qtnf_sta_info_parse_flags(struct nl80211_sta_flag_update *dst,
537 const struct qlink_sta_info_state *src)
538 {
539 u32 mask, value;
540
541 dst->mask = 0;
542 dst->set = 0;
543
544 mask = le32_to_cpu(src->mask);
545 value = le32_to_cpu(src->value);
546
547 if (mask & QLINK_STA_FLAG_AUTHORIZED) {
548 dst->mask |= BIT(NL80211_STA_FLAG_AUTHORIZED);
549 if (value & QLINK_STA_FLAG_AUTHORIZED)
550 dst->set |= BIT(NL80211_STA_FLAG_AUTHORIZED);
551 }
552
553 if (mask & QLINK_STA_FLAG_SHORT_PREAMBLE) {
554 dst->mask |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE);
555 if (value & QLINK_STA_FLAG_SHORT_PREAMBLE)
556 dst->set |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE);
557 }
558
559 if (mask & QLINK_STA_FLAG_WME) {
560 dst->mask |= BIT(NL80211_STA_FLAG_WME);
561 if (value & QLINK_STA_FLAG_WME)
562 dst->set |= BIT(NL80211_STA_FLAG_WME);
563 }
564
565 if (mask & QLINK_STA_FLAG_MFP) {
566 dst->mask |= BIT(NL80211_STA_FLAG_MFP);
567 if (value & QLINK_STA_FLAG_MFP)
568 dst->set |= BIT(NL80211_STA_FLAG_MFP);
569 }
570
571 if (mask & QLINK_STA_FLAG_AUTHENTICATED) {
572 dst->mask |= BIT(NL80211_STA_FLAG_AUTHENTICATED);
573 if (value & QLINK_STA_FLAG_AUTHENTICATED)
574 dst->set |= BIT(NL80211_STA_FLAG_AUTHENTICATED);
575 }
576
577 if (mask & QLINK_STA_FLAG_TDLS_PEER) {
578 dst->mask |= BIT(NL80211_STA_FLAG_TDLS_PEER);
579 if (value & QLINK_STA_FLAG_TDLS_PEER)
580 dst->set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
581 }
582
583 if (mask & QLINK_STA_FLAG_ASSOCIATED) {
584 dst->mask |= BIT(NL80211_STA_FLAG_ASSOCIATED);
585 if (value & QLINK_STA_FLAG_ASSOCIATED)
586 dst->set |= BIT(NL80211_STA_FLAG_ASSOCIATED);
587 }
588 }
589
590 static void
qtnf_cmd_sta_info_parse(struct station_info * sinfo,const u8 * data,size_t resp_size)591 qtnf_cmd_sta_info_parse(struct station_info *sinfo, const u8 *data,
592 size_t resp_size)
593 {
594 const struct qlink_tlv_hdr *tlv;
595 const struct qlink_sta_stats *stats = NULL;
596 const u8 *map = NULL;
597 unsigned int map_len = 0;
598 unsigned int stats_len = 0;
599 u16 tlv_len;
600
601 #define qtnf_sta_stat_avail(stat_name, bitn) \
602 (qtnf_utils_is_bit_set(map, bitn, map_len) && \
603 (offsetofend(struct qlink_sta_stats, stat_name) <= stats_len))
604
605 qlink_for_each_tlv(tlv, data, resp_size) {
606 tlv_len = le16_to_cpu(tlv->len);
607
608 switch (le16_to_cpu(tlv->type)) {
609 case QTN_TLV_ID_BITMAP:
610 map_len = tlv_len;
611 map = tlv->val;
612 break;
613 case QTN_TLV_ID_STA_STATS:
614 stats_len = tlv_len;
615 stats = (const struct qlink_sta_stats *)tlv->val;
616 break;
617 default:
618 break;
619 }
620 }
621
622 if (!qlink_tlv_parsing_ok(tlv, data, resp_size)) {
623 pr_err("Malformed TLV buffer\n");
624 return;
625 }
626
627 if (!map || !stats)
628 return;
629
630 if (qtnf_sta_stat_avail(inactive_time, QLINK_STA_INFO_INACTIVE_TIME)) {
631 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_INACTIVE_TIME);
632 sinfo->inactive_time = le32_to_cpu(stats->inactive_time);
633 }
634
635 if (qtnf_sta_stat_avail(connected_time,
636 QLINK_STA_INFO_CONNECTED_TIME)) {
637 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_CONNECTED_TIME);
638 sinfo->connected_time = le32_to_cpu(stats->connected_time);
639 }
640
641 if (qtnf_sta_stat_avail(signal, QLINK_STA_INFO_SIGNAL)) {
642 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL);
643 sinfo->signal = stats->signal - QLINK_RSSI_OFFSET;
644 }
645
646 if (qtnf_sta_stat_avail(signal_avg, QLINK_STA_INFO_SIGNAL_AVG)) {
647 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG);
648 sinfo->signal_avg = stats->signal_avg - QLINK_RSSI_OFFSET;
649 }
650
651 if (qtnf_sta_stat_avail(rxrate, QLINK_STA_INFO_RX_BITRATE)) {
652 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE);
653 qtnf_sta_info_parse_rate(&sinfo->rxrate, &stats->rxrate);
654 }
655
656 if (qtnf_sta_stat_avail(txrate, QLINK_STA_INFO_TX_BITRATE)) {
657 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
658 qtnf_sta_info_parse_rate(&sinfo->txrate, &stats->txrate);
659 }
660
661 if (qtnf_sta_stat_avail(sta_flags, QLINK_STA_INFO_STA_FLAGS)) {
662 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_STA_FLAGS);
663 qtnf_sta_info_parse_flags(&sinfo->sta_flags, &stats->sta_flags);
664 }
665
666 if (qtnf_sta_stat_avail(rx_bytes, QLINK_STA_INFO_RX_BYTES)) {
667 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BYTES);
668 sinfo->rx_bytes = le64_to_cpu(stats->rx_bytes);
669 }
670
671 if (qtnf_sta_stat_avail(tx_bytes, QLINK_STA_INFO_TX_BYTES)) {
672 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES);
673 sinfo->tx_bytes = le64_to_cpu(stats->tx_bytes);
674 }
675
676 if (qtnf_sta_stat_avail(rx_bytes, QLINK_STA_INFO_RX_BYTES64)) {
677 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BYTES64);
678 sinfo->rx_bytes = le64_to_cpu(stats->rx_bytes);
679 }
680
681 if (qtnf_sta_stat_avail(tx_bytes, QLINK_STA_INFO_TX_BYTES64)) {
682 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES64);
683 sinfo->tx_bytes = le64_to_cpu(stats->tx_bytes);
684 }
685
686 if (qtnf_sta_stat_avail(rx_packets, QLINK_STA_INFO_RX_PACKETS)) {
687 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_PACKETS);
688 sinfo->rx_packets = le32_to_cpu(stats->rx_packets);
689 }
690
691 if (qtnf_sta_stat_avail(tx_packets, QLINK_STA_INFO_TX_PACKETS)) {
692 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS);
693 sinfo->tx_packets = le32_to_cpu(stats->tx_packets);
694 }
695
696 if (qtnf_sta_stat_avail(rx_beacon, QLINK_STA_INFO_BEACON_RX)) {
697 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_BEACON_RX);
698 sinfo->rx_beacon = le64_to_cpu(stats->rx_beacon);
699 }
700
701 if (qtnf_sta_stat_avail(rx_dropped_misc, QLINK_STA_INFO_RX_DROP_MISC)) {
702 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_DROP_MISC);
703 sinfo->rx_dropped_misc = le32_to_cpu(stats->rx_dropped_misc);
704 }
705
706 if (qtnf_sta_stat_avail(tx_failed, QLINK_STA_INFO_TX_FAILED)) {
707 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED);
708 sinfo->tx_failed = le32_to_cpu(stats->tx_failed);
709 }
710
711 #undef qtnf_sta_stat_avail
712 }
713
qtnf_cmd_get_sta_info(struct qtnf_vif * vif,const u8 * sta_mac,struct station_info * sinfo)714 int qtnf_cmd_get_sta_info(struct qtnf_vif *vif, const u8 *sta_mac,
715 struct station_info *sinfo)
716 {
717 struct sk_buff *cmd_skb, *resp_skb = NULL;
718 struct qlink_cmd_get_sta_info *cmd;
719 const struct qlink_resp_get_sta_info *resp;
720 size_t var_resp_len = 0;
721 int ret = 0;
722
723 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
724 QLINK_CMD_GET_STA_INFO,
725 sizeof(*cmd));
726 if (!cmd_skb)
727 return -ENOMEM;
728
729 qtnf_bus_lock(vif->mac->bus);
730
731 cmd = (struct qlink_cmd_get_sta_info *)cmd_skb->data;
732 ether_addr_copy(cmd->sta_addr, sta_mac);
733
734 ret = qtnf_cmd_send_with_reply(vif->mac->bus, cmd_skb, &resp_skb,
735 sizeof(*resp), &var_resp_len);
736 if (ret)
737 goto out;
738
739 resp = (const struct qlink_resp_get_sta_info *)resp_skb->data;
740
741 if (!ether_addr_equal(sta_mac, resp->sta_addr)) {
742 pr_err("VIF%u.%u: wrong mac in reply: %pM != %pM\n",
743 vif->mac->macid, vif->vifid, resp->sta_addr, sta_mac);
744 ret = -EINVAL;
745 goto out;
746 }
747
748 qtnf_cmd_sta_info_parse(sinfo, resp->info, var_resp_len);
749
750 out:
751 qtnf_bus_unlock(vif->mac->bus);
752 consume_skb(resp_skb);
753
754 return ret;
755 }
756
qtnf_cmd_send_add_change_intf(struct qtnf_vif * vif,enum nl80211_iftype iftype,int use4addr,u8 * mac_addr,enum qlink_cmd_type cmd_type)757 static int qtnf_cmd_send_add_change_intf(struct qtnf_vif *vif,
758 enum nl80211_iftype iftype,
759 int use4addr,
760 u8 *mac_addr,
761 enum qlink_cmd_type cmd_type)
762 {
763 struct sk_buff *cmd_skb, *resp_skb = NULL;
764 struct qlink_cmd_manage_intf *cmd;
765 const struct qlink_resp_manage_intf *resp;
766 int ret = 0;
767
768 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
769 cmd_type,
770 sizeof(*cmd));
771 if (!cmd_skb)
772 return -ENOMEM;
773
774 qtnf_bus_lock(vif->mac->bus);
775
776 cmd = (struct qlink_cmd_manage_intf *)cmd_skb->data;
777 cmd->intf_info.use4addr = use4addr;
778
779 switch (iftype) {
780 case NL80211_IFTYPE_AP:
781 cmd->intf_info.if_type = cpu_to_le16(QLINK_IFTYPE_AP);
782 break;
783 case NL80211_IFTYPE_STATION:
784 cmd->intf_info.if_type = cpu_to_le16(QLINK_IFTYPE_STATION);
785 break;
786 default:
787 pr_err("VIF%u.%u: unsupported type %d\n", vif->mac->macid,
788 vif->vifid, iftype);
789 ret = -EINVAL;
790 goto out;
791 }
792
793 if (mac_addr)
794 ether_addr_copy(cmd->intf_info.mac_addr, mac_addr);
795 else
796 eth_zero_addr(cmd->intf_info.mac_addr);
797
798 ret = qtnf_cmd_send_with_reply(vif->mac->bus, cmd_skb, &resp_skb,
799 sizeof(*resp), NULL);
800 if (ret)
801 goto out;
802
803 resp = (const struct qlink_resp_manage_intf *)resp_skb->data;
804 ether_addr_copy(vif->mac_addr, resp->intf_info.mac_addr);
805
806 out:
807 qtnf_bus_unlock(vif->mac->bus);
808 consume_skb(resp_skb);
809
810 return ret;
811 }
812
qtnf_cmd_send_add_intf(struct qtnf_vif * vif,enum nl80211_iftype iftype,int use4addr,u8 * mac_addr)813 int qtnf_cmd_send_add_intf(struct qtnf_vif *vif, enum nl80211_iftype iftype,
814 int use4addr, u8 *mac_addr)
815 {
816 return qtnf_cmd_send_add_change_intf(vif, iftype, use4addr, mac_addr,
817 QLINK_CMD_ADD_INTF);
818 }
819
qtnf_cmd_send_change_intf_type(struct qtnf_vif * vif,enum nl80211_iftype iftype,int use4addr,u8 * mac_addr)820 int qtnf_cmd_send_change_intf_type(struct qtnf_vif *vif,
821 enum nl80211_iftype iftype,
822 int use4addr,
823 u8 *mac_addr)
824 {
825 int ret;
826
827 ret = qtnf_cmd_send_add_change_intf(vif, iftype, use4addr, mac_addr,
828 QLINK_CMD_CHANGE_INTF);
829
830 /* Regulatory settings may be different for different interface types */
831 if (ret == 0 && vif->wdev.iftype != iftype) {
832 enum nl80211_band band;
833 struct wiphy *wiphy = priv_to_wiphy(vif->mac);
834
835 for (band = 0; band < NUM_NL80211_BANDS; ++band) {
836 if (!wiphy->bands[band])
837 continue;
838
839 qtnf_cmd_band_info_get(vif->mac, wiphy->bands[band]);
840 }
841 }
842
843 return ret;
844 }
845
qtnf_cmd_send_del_intf(struct qtnf_vif * vif)846 int qtnf_cmd_send_del_intf(struct qtnf_vif *vif)
847 {
848 struct sk_buff *cmd_skb;
849 struct qlink_cmd_manage_intf *cmd;
850 int ret = 0;
851
852 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
853 QLINK_CMD_DEL_INTF,
854 sizeof(*cmd));
855 if (!cmd_skb)
856 return -ENOMEM;
857
858 qtnf_bus_lock(vif->mac->bus);
859
860 cmd = (struct qlink_cmd_manage_intf *)cmd_skb->data;
861
862 switch (vif->wdev.iftype) {
863 case NL80211_IFTYPE_AP:
864 cmd->intf_info.if_type = cpu_to_le16(QLINK_IFTYPE_AP);
865 break;
866 case NL80211_IFTYPE_STATION:
867 cmd->intf_info.if_type = cpu_to_le16(QLINK_IFTYPE_STATION);
868 break;
869 default:
870 pr_warn("VIF%u.%u: unsupported iftype %d\n", vif->mac->macid,
871 vif->vifid, vif->wdev.iftype);
872 dev_kfree_skb(cmd_skb);
873 ret = -EINVAL;
874 goto out;
875 }
876
877 eth_zero_addr(cmd->intf_info.mac_addr);
878
879 ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
880 if (ret)
881 goto out;
882
883 out:
884 qtnf_bus_unlock(vif->mac->bus);
885 return ret;
886 }
887
888 static int
qtnf_cmd_resp_proc_hw_info(struct qtnf_bus * bus,const struct qlink_resp_get_hw_info * resp,size_t info_len)889 qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus,
890 const struct qlink_resp_get_hw_info *resp,
891 size_t info_len)
892 {
893 struct qtnf_hw_info *hwinfo = &bus->hw_info;
894 const struct qlink_tlv_hdr *tlv;
895 const char *bld_name = NULL;
896 const char *bld_rev = NULL;
897 const char *bld_type = NULL;
898 const char *bld_label = NULL;
899 u32 bld_tmstamp = 0;
900 u32 plat_id = 0;
901 const char *hw_id = NULL;
902 const char *calibration_ver = NULL;
903 const char *uboot_ver = NULL;
904 u32 hw_ver = 0;
905 u16 tlv_type;
906 u16 tlv_len;
907
908 hwinfo->num_mac = resp->num_mac;
909 hwinfo->mac_bitmap = resp->mac_bitmap;
910 hwinfo->fw_ver = le32_to_cpu(resp->fw_ver);
911 hwinfo->total_tx_chain = resp->total_tx_chain;
912 hwinfo->total_rx_chain = resp->total_rx_chain;
913
914 bld_tmstamp = le32_to_cpu(resp->bld_tmstamp);
915 plat_id = le32_to_cpu(resp->plat_id);
916 hw_ver = le32_to_cpu(resp->hw_ver);
917
918 qlink_for_each_tlv(tlv, resp->info, info_len) {
919 tlv_type = le16_to_cpu(tlv->type);
920 tlv_len = le16_to_cpu(tlv->len);
921
922 switch (tlv_type) {
923 case QTN_TLV_ID_BUILD_NAME:
924 bld_name = (const void *)tlv->val;
925 break;
926 case QTN_TLV_ID_BUILD_REV:
927 bld_rev = (const void *)tlv->val;
928 break;
929 case QTN_TLV_ID_BUILD_TYPE:
930 bld_type = (const void *)tlv->val;
931 break;
932 case QTN_TLV_ID_BUILD_LABEL:
933 bld_label = (const void *)tlv->val;
934 break;
935 case QTN_TLV_ID_HW_ID:
936 hw_id = (const void *)tlv->val;
937 break;
938 case QTN_TLV_ID_CALIBRATION_VER:
939 calibration_ver = (const void *)tlv->val;
940 break;
941 case QTN_TLV_ID_UBOOT_VER:
942 uboot_ver = (const void *)tlv->val;
943 break;
944 case QTN_TLV_ID_BITMAP:
945 memcpy(hwinfo->hw_capab, tlv->val,
946 min(sizeof(hwinfo->hw_capab), (size_t)tlv_len));
947 break;
948 default:
949 break;
950 }
951 }
952
953 if (!qlink_tlv_parsing_ok(tlv, resp->info, info_len)) {
954 pr_err("Malformed TLV buffer\n");
955 return -EINVAL;
956 }
957
958 pr_info("\nBuild name: %s\n"
959 "Build revision: %s\n"
960 "Build type: %s\n"
961 "Build label: %s\n"
962 "Build timestamp: %lu\n"
963 "Platform ID: %lu\n"
964 "Hardware ID: %s\n"
965 "Calibration version: %s\n"
966 "U-Boot version: %s\n"
967 "Hardware version: 0x%08x\n"
968 "Qlink ver: %u.%u\n"
969 "MACs map: %#x\n"
970 "Chains Rx-Tx: %ux%u\n"
971 "FW version: 0x%x\n",
972 bld_name, bld_rev, bld_type, bld_label,
973 (unsigned long)bld_tmstamp,
974 (unsigned long)plat_id,
975 hw_id, calibration_ver, uboot_ver, hw_ver,
976 QLINK_VER_MAJOR(bus->hw_info.ql_proto_ver),
977 QLINK_VER_MINOR(bus->hw_info.ql_proto_ver),
978 hwinfo->mac_bitmap,
979 hwinfo->total_rx_chain, hwinfo->total_tx_chain,
980 hwinfo->fw_ver);
981
982 strlcpy(hwinfo->fw_version, bld_label, sizeof(hwinfo->fw_version));
983 hwinfo->hw_version = hw_ver;
984
985 return 0;
986 }
987
988 static void
qtnf_parse_wowlan_info(struct qtnf_wmac * mac,const struct qlink_wowlan_capab_data * wowlan)989 qtnf_parse_wowlan_info(struct qtnf_wmac *mac,
990 const struct qlink_wowlan_capab_data *wowlan)
991 {
992 struct qtnf_mac_info *mac_info = &mac->macinfo;
993 const struct qlink_wowlan_support *data1;
994 struct wiphy_wowlan_support *supp;
995
996 supp = kzalloc(sizeof(*supp), GFP_KERNEL);
997 if (!supp)
998 return;
999
1000 switch (le16_to_cpu(wowlan->version)) {
1001 case 0x1:
1002 data1 = (struct qlink_wowlan_support *)wowlan->data;
1003
1004 supp->flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT;
1005 supp->n_patterns = le32_to_cpu(data1->n_patterns);
1006 supp->pattern_max_len = le32_to_cpu(data1->pattern_max_len);
1007 supp->pattern_min_len = le32_to_cpu(data1->pattern_min_len);
1008
1009 mac_info->wowlan = supp;
1010 break;
1011 default:
1012 pr_warn("MAC%u: unsupported WoWLAN version 0x%x\n",
1013 mac->macid, le16_to_cpu(wowlan->version));
1014 kfree(supp);
1015 break;
1016 }
1017 }
1018
1019 static int
qtnf_parse_variable_mac_info(struct qtnf_wmac * mac,const struct qlink_resp_get_mac_info * resp,size_t tlv_buf_size)1020 qtnf_parse_variable_mac_info(struct qtnf_wmac *mac,
1021 const struct qlink_resp_get_mac_info *resp,
1022 size_t tlv_buf_size)
1023 {
1024 struct ieee80211_iface_combination *comb = mac->macinfo.if_comb;
1025 size_t n_comb = 0;
1026 struct ieee80211_iface_limit *limits;
1027 const struct qlink_iface_limit_record *rec;
1028 const struct qlink_iface_limit *lim;
1029 const struct qlink_wowlan_capab_data *wowlan;
1030 u16 rec_len;
1031 u16 tlv_type;
1032 u16 tlv_value_len;
1033 const struct qlink_tlv_hdr *tlv;
1034 u8 *ext_capa = NULL;
1035 u8 *ext_capa_mask = NULL;
1036 u8 ext_capa_len = 0;
1037 u8 ext_capa_mask_len = 0;
1038 int i = 0;
1039 struct ieee80211_reg_rule *rule;
1040 unsigned int rule_idx = 0;
1041 const struct qlink_tlv_reg_rule *tlv_rule;
1042
1043 if (WARN_ON(resp->n_reg_rules > NL80211_MAX_SUPP_REG_RULES))
1044 return -E2BIG;
1045
1046 mac->rd = kzalloc(struct_size(mac->rd, reg_rules, resp->n_reg_rules),
1047 GFP_KERNEL);
1048 if (!mac->rd)
1049 return -ENOMEM;
1050
1051 mac->rd->n_reg_rules = resp->n_reg_rules;
1052 mac->rd->alpha2[0] = resp->alpha2[0];
1053 mac->rd->alpha2[1] = resp->alpha2[1];
1054
1055 switch (resp->dfs_region) {
1056 case QLINK_DFS_FCC:
1057 mac->rd->dfs_region = NL80211_DFS_FCC;
1058 break;
1059 case QLINK_DFS_ETSI:
1060 mac->rd->dfs_region = NL80211_DFS_ETSI;
1061 break;
1062 case QLINK_DFS_JP:
1063 mac->rd->dfs_region = NL80211_DFS_JP;
1064 break;
1065 case QLINK_DFS_UNSET:
1066 default:
1067 mac->rd->dfs_region = NL80211_DFS_UNSET;
1068 break;
1069 }
1070
1071 qlink_for_each_tlv(tlv, resp->var_info, tlv_buf_size) {
1072 tlv_type = le16_to_cpu(tlv->type);
1073 tlv_value_len = le16_to_cpu(tlv->len);
1074
1075 switch (tlv_type) {
1076 case QTN_TLV_ID_IFACE_LIMIT:
1077 if (unlikely(!comb)) {
1078 pr_warn("MAC%u: no combinations advertised\n",
1079 mac->macid);
1080 return -EINVAL;
1081 }
1082
1083 if (n_comb >= mac->macinfo.n_if_comb) {
1084 pr_warn("MAC%u: combinations count exceeded\n",
1085 mac->macid);
1086 n_comb++;
1087 break;
1088 }
1089
1090 rec = (void *)tlv->val;
1091 rec_len = sizeof(*rec) + rec->n_limits * sizeof(*lim);
1092
1093 if (unlikely(tlv_value_len != rec_len)) {
1094 pr_warn("MAC%u: record %zu size mismatch\n",
1095 mac->macid, n_comb);
1096 return -EINVAL;
1097 }
1098
1099 limits = kcalloc(rec->n_limits, sizeof(*limits),
1100 GFP_KERNEL);
1101 if (!limits)
1102 return -ENOMEM;
1103
1104 comb[n_comb].num_different_channels =
1105 rec->num_different_channels;
1106 comb[n_comb].max_interfaces =
1107 le16_to_cpu(rec->max_interfaces);
1108 comb[n_comb].n_limits = rec->n_limits;
1109 comb[n_comb].limits = limits;
1110
1111 for (i = 0; i < rec->n_limits; i++) {
1112 lim = &rec->limits[i];
1113 limits[i].max = le16_to_cpu(lim->max_num);
1114 limits[i].types =
1115 qlink_iface_type_to_nl_mask(le16_to_cpu(lim->type));
1116 pr_debug("MAC%u: comb[%zu]: MAX:%u TYPES:%.4X\n",
1117 mac->macid, n_comb,
1118 limits[i].max, limits[i].types);
1119 }
1120
1121 n_comb++;
1122 break;
1123 case WLAN_EID_EXT_CAPABILITY:
1124 if (unlikely(tlv_value_len > U8_MAX))
1125 return -EINVAL;
1126 ext_capa = (u8 *)tlv->val;
1127 ext_capa_len = tlv_value_len;
1128 break;
1129 case QTN_TLV_ID_EXT_CAPABILITY_MASK:
1130 if (unlikely(tlv_value_len > U8_MAX))
1131 return -EINVAL;
1132 ext_capa_mask = (u8 *)tlv->val;
1133 ext_capa_mask_len = tlv_value_len;
1134 break;
1135 case QTN_TLV_ID_WOWLAN_CAPAB:
1136 if (tlv_value_len < sizeof(*wowlan))
1137 return -EINVAL;
1138
1139 wowlan = (void *)tlv->val;
1140 if (!le16_to_cpu(wowlan->len)) {
1141 pr_warn("MAC%u: skip empty WoWLAN data\n",
1142 mac->macid);
1143 break;
1144 }
1145
1146 rec_len = sizeof(*wowlan) + le16_to_cpu(wowlan->len);
1147 if (unlikely(tlv_value_len != rec_len)) {
1148 pr_warn("MAC%u: WoWLAN data size mismatch\n",
1149 mac->macid);
1150 return -EINVAL;
1151 }
1152
1153 kfree(mac->macinfo.wowlan);
1154 mac->macinfo.wowlan = NULL;
1155 qtnf_parse_wowlan_info(mac, wowlan);
1156 break;
1157 case QTN_TLV_ID_REG_RULE:
1158 if (rule_idx >= resp->n_reg_rules) {
1159 pr_warn("unexpected number of rules: %u\n",
1160 resp->n_reg_rules);
1161 return -EINVAL;
1162 }
1163
1164 if (tlv_value_len != sizeof(*tlv_rule) - sizeof(*tlv)) {
1165 pr_warn("malformed TLV 0x%.2X; LEN: %u\n",
1166 tlv_type, tlv_value_len);
1167 return -EINVAL;
1168 }
1169
1170 tlv_rule = (const struct qlink_tlv_reg_rule *)tlv;
1171 rule = &mac->rd->reg_rules[rule_idx++];
1172 qlink_utils_regrule_q2nl(rule, tlv_rule);
1173 break;
1174 default:
1175 pr_warn("MAC%u: unknown TLV type %u\n",
1176 mac->macid, tlv_type);
1177 break;
1178 }
1179 }
1180
1181 if (!qlink_tlv_parsing_ok(tlv, resp->var_info, tlv_buf_size)) {
1182 pr_err("Malformed TLV buffer\n");
1183 return -EINVAL;
1184 }
1185
1186 if (mac->macinfo.n_if_comb != n_comb) {
1187 pr_err("MAC%u: combination mismatch: reported=%zu parsed=%zu\n",
1188 mac->macid, mac->macinfo.n_if_comb, n_comb);
1189 return -EINVAL;
1190 }
1191
1192 if (ext_capa_len != ext_capa_mask_len) {
1193 pr_err("MAC%u: ext_capa/_mask lengths mismatch: %u != %u\n",
1194 mac->macid, ext_capa_len, ext_capa_mask_len);
1195 return -EINVAL;
1196 }
1197
1198 if (rule_idx != resp->n_reg_rules) {
1199 pr_warn("unexpected number of rules: expected %u got %u\n",
1200 resp->n_reg_rules, rule_idx);
1201 return -EINVAL;
1202 }
1203
1204 if (ext_capa_len > 0) {
1205 ext_capa = kmemdup(ext_capa, ext_capa_len, GFP_KERNEL);
1206 if (!ext_capa)
1207 return -ENOMEM;
1208
1209 ext_capa_mask =
1210 kmemdup(ext_capa_mask, ext_capa_mask_len, GFP_KERNEL);
1211 if (!ext_capa_mask) {
1212 kfree(ext_capa);
1213 return -ENOMEM;
1214 }
1215 } else {
1216 ext_capa = NULL;
1217 ext_capa_mask = NULL;
1218 }
1219
1220 qtnf_mac_ext_caps_free(mac);
1221 mac->macinfo.extended_capabilities = ext_capa;
1222 mac->macinfo.extended_capabilities_mask = ext_capa_mask;
1223 mac->macinfo.extended_capabilities_len = ext_capa_len;
1224
1225 return 0;
1226 }
1227
1228 static int
qtnf_cmd_resp_proc_mac_info(struct qtnf_wmac * mac,const struct qlink_resp_get_mac_info * resp_info)1229 qtnf_cmd_resp_proc_mac_info(struct qtnf_wmac *mac,
1230 const struct qlink_resp_get_mac_info *resp_info)
1231 {
1232 struct qtnf_mac_info *mac_info;
1233 struct qtnf_vif *vif;
1234
1235 qtnf_mac_iface_comb_free(mac);
1236
1237 mac_info = &mac->macinfo;
1238
1239 mac_info->bands_cap = resp_info->bands_cap;
1240 ether_addr_copy(mac->macaddr, resp_info->dev_mac);
1241
1242 vif = qtnf_mac_get_base_vif(mac);
1243 if (vif)
1244 ether_addr_copy(vif->mac_addr, mac->macaddr);
1245 else
1246 pr_err("could not get valid base vif\n");
1247
1248 mac_info->num_tx_chain = resp_info->num_tx_chain;
1249 mac_info->num_rx_chain = resp_info->num_rx_chain;
1250
1251 mac_info->max_ap_assoc_sta = le16_to_cpu(resp_info->max_ap_assoc_sta);
1252 mac_info->radar_detect_widths =
1253 qlink_chan_width_mask_to_nl(le16_to_cpu(
1254 resp_info->radar_detect_widths));
1255 mac_info->max_acl_mac_addrs = le16_to_cpu(resp_info->max_acl_mac_addrs);
1256 mac_info->frag_thr = le32_to_cpu(resp_info->frag_threshold);
1257 mac_info->rts_thr = le32_to_cpu(resp_info->rts_threshold);
1258 mac_info->sretry_limit = resp_info->retry_short;
1259 mac_info->lretry_limit = resp_info->retry_long;
1260 mac_info->coverage_class = resp_info->coverage_class;
1261 mac_info->max_scan_ssids = resp_info->max_scan_ssids;
1262
1263 memcpy(&mac_info->ht_cap_mod_mask, &resp_info->ht_cap_mod_mask,
1264 sizeof(mac_info->ht_cap_mod_mask));
1265 memcpy(&mac_info->vht_cap_mod_mask, &resp_info->vht_cap_mod_mask,
1266 sizeof(mac_info->vht_cap_mod_mask));
1267
1268 mac_info->n_if_comb = resp_info->n_iface_combinations;
1269 mac_info->if_comb = kcalloc(mac->macinfo.n_if_comb,
1270 sizeof(*mac->macinfo.if_comb),
1271 GFP_KERNEL);
1272
1273 if (!mac->macinfo.if_comb)
1274 return -ENOMEM;
1275
1276 return 0;
1277 }
1278
qtnf_cmd_resp_band_fill_htcap(const u8 * info,struct ieee80211_sta_ht_cap * bcap)1279 static void qtnf_cmd_resp_band_fill_htcap(const u8 *info,
1280 struct ieee80211_sta_ht_cap *bcap)
1281 {
1282 const struct ieee80211_ht_cap *ht_cap =
1283 (const struct ieee80211_ht_cap *)info;
1284
1285 bcap->ht_supported = true;
1286 bcap->cap = le16_to_cpu(ht_cap->cap_info);
1287 bcap->ampdu_factor =
1288 ht_cap->ampdu_params_info & IEEE80211_HT_AMPDU_PARM_FACTOR;
1289 bcap->ampdu_density =
1290 (ht_cap->ampdu_params_info & IEEE80211_HT_AMPDU_PARM_DENSITY) >>
1291 IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT;
1292 memcpy(&bcap->mcs, &ht_cap->mcs, sizeof(bcap->mcs));
1293 }
1294
qtnf_cmd_resp_band_fill_vhtcap(const u8 * info,struct ieee80211_sta_vht_cap * bcap)1295 static void qtnf_cmd_resp_band_fill_vhtcap(const u8 *info,
1296 struct ieee80211_sta_vht_cap *bcap)
1297 {
1298 const struct ieee80211_vht_cap *vht_cap =
1299 (const struct ieee80211_vht_cap *)info;
1300
1301 bcap->vht_supported = true;
1302 bcap->cap = le32_to_cpu(vht_cap->vht_cap_info);
1303 memcpy(&bcap->vht_mcs, &vht_cap->supp_mcs, sizeof(bcap->vht_mcs));
1304 }
1305
qtnf_cmd_conv_iftype(struct ieee80211_sband_iftype_data * iftype_data,const struct qlink_sband_iftype_data * qlink_data)1306 static void qtnf_cmd_conv_iftype(struct ieee80211_sband_iftype_data
1307 *iftype_data,
1308 const struct qlink_sband_iftype_data
1309 *qlink_data)
1310 {
1311 iftype_data->types_mask = le16_to_cpu(qlink_data->types_mask);
1312
1313 iftype_data->he_cap.has_he = true;
1314 memcpy(&iftype_data->he_cap.he_cap_elem, &qlink_data->he_cap_elem,
1315 sizeof(qlink_data->he_cap_elem));
1316 memcpy(iftype_data->he_cap.ppe_thres, qlink_data->ppe_thres,
1317 ARRAY_SIZE(qlink_data->ppe_thres));
1318
1319 iftype_data->he_cap.he_mcs_nss_supp.rx_mcs_80 =
1320 qlink_data->he_mcs_nss_supp.rx_mcs_80;
1321 iftype_data->he_cap.he_mcs_nss_supp.tx_mcs_80 =
1322 qlink_data->he_mcs_nss_supp.tx_mcs_80;
1323 iftype_data->he_cap.he_mcs_nss_supp.rx_mcs_160 =
1324 qlink_data->he_mcs_nss_supp.rx_mcs_160;
1325 iftype_data->he_cap.he_mcs_nss_supp.tx_mcs_160 =
1326 qlink_data->he_mcs_nss_supp.tx_mcs_160;
1327 iftype_data->he_cap.he_mcs_nss_supp.rx_mcs_80p80 =
1328 qlink_data->he_mcs_nss_supp.rx_mcs_80p80;
1329 iftype_data->he_cap.he_mcs_nss_supp.tx_mcs_80p80 =
1330 qlink_data->he_mcs_nss_supp.tx_mcs_80p80;
1331 }
1332
qtnf_cmd_band_fill_iftype(const u8 * data,struct ieee80211_supported_band * band)1333 static int qtnf_cmd_band_fill_iftype(const u8 *data,
1334 struct ieee80211_supported_band *band)
1335 {
1336 unsigned int i;
1337 struct ieee80211_sband_iftype_data *iftype_data;
1338 const struct qlink_tlv_iftype_data *tlv =
1339 (const struct qlink_tlv_iftype_data *)data;
1340 size_t payload_len = tlv->n_iftype_data * sizeof(*tlv->iftype_data) +
1341 sizeof(*tlv) -
1342 sizeof(struct qlink_tlv_hdr);
1343
1344 if (tlv->hdr.len != cpu_to_le16(payload_len)) {
1345 pr_err("bad IFTYPE_DATA TLV len %u\n", tlv->hdr.len);
1346 return -EINVAL;
1347 }
1348
1349 kfree(band->iftype_data);
1350 band->iftype_data = NULL;
1351 band->n_iftype_data = tlv->n_iftype_data;
1352 if (band->n_iftype_data == 0)
1353 return 0;
1354
1355 iftype_data = kcalloc(band->n_iftype_data, sizeof(*iftype_data),
1356 GFP_KERNEL);
1357 if (!iftype_data) {
1358 band->n_iftype_data = 0;
1359 return -ENOMEM;
1360 }
1361 band->iftype_data = iftype_data;
1362
1363 for (i = 0; i < band->n_iftype_data; i++)
1364 qtnf_cmd_conv_iftype(iftype_data++, &tlv->iftype_data[i]);
1365
1366 return 0;
1367 }
1368
1369 static int
qtnf_cmd_resp_fill_band_info(struct ieee80211_supported_band * band,struct qlink_resp_band_info_get * resp,size_t payload_len)1370 qtnf_cmd_resp_fill_band_info(struct ieee80211_supported_band *band,
1371 struct qlink_resp_band_info_get *resp,
1372 size_t payload_len)
1373 {
1374 u16 tlv_type;
1375 size_t tlv_dlen;
1376 const struct qlink_tlv_hdr *tlv;
1377 const struct qlink_channel *qchan;
1378 struct ieee80211_channel *chan;
1379 unsigned int chidx = 0;
1380 u32 qflags;
1381 int ret = -EINVAL;
1382
1383 memset(&band->ht_cap, 0, sizeof(band->ht_cap));
1384 memset(&band->vht_cap, 0, sizeof(band->vht_cap));
1385
1386 if (band->channels) {
1387 if (band->n_channels == resp->num_chans) {
1388 memset(band->channels, 0,
1389 sizeof(*band->channels) * band->n_channels);
1390 } else {
1391 kfree(band->channels);
1392 band->n_channels = 0;
1393 band->channels = NULL;
1394 }
1395 }
1396
1397 band->n_channels = resp->num_chans;
1398 if (band->n_channels == 0)
1399 return 0;
1400
1401 if (!band->channels)
1402 band->channels = kcalloc(band->n_channels, sizeof(*chan),
1403 GFP_KERNEL);
1404 if (!band->channels) {
1405 band->n_channels = 0;
1406 return -ENOMEM;
1407 }
1408
1409 qlink_for_each_tlv(tlv, resp->info, payload_len) {
1410 tlv_type = le16_to_cpu(tlv->type);
1411 tlv_dlen = le16_to_cpu(tlv->len);
1412
1413 switch (tlv_type) {
1414 case QTN_TLV_ID_CHANNEL:
1415 if (unlikely(tlv_dlen != sizeof(*qchan))) {
1416 pr_err("invalid channel TLV len %zu\n",
1417 tlv_dlen);
1418 goto error_ret;
1419 }
1420
1421 if (chidx == band->n_channels) {
1422 pr_err("too many channel TLVs\n");
1423 goto error_ret;
1424 }
1425
1426 qchan = (const struct qlink_channel *)tlv->val;
1427 chan = &band->channels[chidx++];
1428 qflags = le32_to_cpu(qchan->flags);
1429
1430 chan->hw_value = le16_to_cpu(qchan->hw_value);
1431 chan->band = band->band;
1432 chan->center_freq = le16_to_cpu(qchan->center_freq);
1433 chan->max_antenna_gain = (int)qchan->max_antenna_gain;
1434 chan->max_power = (int)qchan->max_power;
1435 chan->max_reg_power = (int)qchan->max_reg_power;
1436 chan->beacon_found = qchan->beacon_found;
1437 chan->dfs_cac_ms = le32_to_cpu(qchan->dfs_cac_ms);
1438 chan->flags = 0;
1439
1440 if (qflags & QLINK_CHAN_DISABLED)
1441 chan->flags |= IEEE80211_CHAN_DISABLED;
1442
1443 if (qflags & QLINK_CHAN_NO_IR)
1444 chan->flags |= IEEE80211_CHAN_NO_IR;
1445
1446 if (qflags & QLINK_CHAN_NO_HT40PLUS)
1447 chan->flags |= IEEE80211_CHAN_NO_HT40PLUS;
1448
1449 if (qflags & QLINK_CHAN_NO_HT40MINUS)
1450 chan->flags |= IEEE80211_CHAN_NO_HT40MINUS;
1451
1452 if (qflags & QLINK_CHAN_NO_OFDM)
1453 chan->flags |= IEEE80211_CHAN_NO_OFDM;
1454
1455 if (qflags & QLINK_CHAN_NO_80MHZ)
1456 chan->flags |= IEEE80211_CHAN_NO_80MHZ;
1457
1458 if (qflags & QLINK_CHAN_NO_160MHZ)
1459 chan->flags |= IEEE80211_CHAN_NO_160MHZ;
1460
1461 if (qflags & QLINK_CHAN_INDOOR_ONLY)
1462 chan->flags |= IEEE80211_CHAN_INDOOR_ONLY;
1463
1464 if (qflags & QLINK_CHAN_IR_CONCURRENT)
1465 chan->flags |= IEEE80211_CHAN_IR_CONCURRENT;
1466
1467 if (qflags & QLINK_CHAN_NO_20MHZ)
1468 chan->flags |= IEEE80211_CHAN_NO_20MHZ;
1469
1470 if (qflags & QLINK_CHAN_NO_10MHZ)
1471 chan->flags |= IEEE80211_CHAN_NO_10MHZ;
1472
1473 if (qflags & QLINK_CHAN_RADAR) {
1474 chan->flags |= IEEE80211_CHAN_RADAR;
1475 chan->dfs_state_entered = jiffies;
1476
1477 if (qchan->dfs_state == QLINK_DFS_USABLE)
1478 chan->dfs_state = NL80211_DFS_USABLE;
1479 else if (qchan->dfs_state ==
1480 QLINK_DFS_AVAILABLE)
1481 chan->dfs_state = NL80211_DFS_AVAILABLE;
1482 else
1483 chan->dfs_state =
1484 NL80211_DFS_UNAVAILABLE;
1485 }
1486
1487 pr_debug("chan=%d flags=%#x max_pow=%d max_reg_pow=%d\n",
1488 chan->hw_value, chan->flags, chan->max_power,
1489 chan->max_reg_power);
1490 break;
1491 case WLAN_EID_HT_CAPABILITY:
1492 if (unlikely(tlv_dlen !=
1493 sizeof(struct ieee80211_ht_cap))) {
1494 pr_err("bad HTCAP TLV len %zu\n", tlv_dlen);
1495 goto error_ret;
1496 }
1497
1498 qtnf_cmd_resp_band_fill_htcap(tlv->val, &band->ht_cap);
1499 break;
1500 case WLAN_EID_VHT_CAPABILITY:
1501 if (unlikely(tlv_dlen !=
1502 sizeof(struct ieee80211_vht_cap))) {
1503 pr_err("bad VHTCAP TLV len %zu\n", tlv_dlen);
1504 goto error_ret;
1505 }
1506
1507 qtnf_cmd_resp_band_fill_vhtcap(tlv->val,
1508 &band->vht_cap);
1509 break;
1510 case QTN_TLV_ID_IFTYPE_DATA:
1511 ret = qtnf_cmd_band_fill_iftype((const uint8_t *)tlv,
1512 band);
1513 if (ret)
1514 goto error_ret;
1515 break;
1516 default:
1517 pr_warn("unknown TLV type: %#x\n", tlv_type);
1518 break;
1519 }
1520 }
1521
1522 if (!qlink_tlv_parsing_ok(tlv, resp->info, payload_len)) {
1523 pr_err("Malformed TLV buffer\n");
1524 goto error_ret;
1525 }
1526
1527 if (band->n_channels != chidx) {
1528 pr_err("channel count mismatch: reported=%d, parsed=%d\n",
1529 band->n_channels, chidx);
1530 goto error_ret;
1531 }
1532
1533 return 0;
1534
1535 error_ret:
1536 kfree(band->channels);
1537 band->channels = NULL;
1538 band->n_channels = 0;
1539
1540 return ret;
1541 }
1542
qtnf_cmd_get_mac_info(struct qtnf_wmac * mac)1543 int qtnf_cmd_get_mac_info(struct qtnf_wmac *mac)
1544 {
1545 struct sk_buff *cmd_skb, *resp_skb = NULL;
1546 const struct qlink_resp_get_mac_info *resp;
1547 size_t var_data_len = 0;
1548 int ret = 0;
1549
1550 cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, QLINK_VIFID_RSVD,
1551 QLINK_CMD_MAC_INFO,
1552 sizeof(struct qlink_cmd));
1553 if (!cmd_skb)
1554 return -ENOMEM;
1555
1556 qtnf_bus_lock(mac->bus);
1557 ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb,
1558 sizeof(*resp), &var_data_len);
1559 if (ret)
1560 goto out;
1561
1562 resp = (const struct qlink_resp_get_mac_info *)resp_skb->data;
1563 ret = qtnf_cmd_resp_proc_mac_info(mac, resp);
1564 if (ret)
1565 goto out;
1566
1567 ret = qtnf_parse_variable_mac_info(mac, resp, var_data_len);
1568
1569 out:
1570 qtnf_bus_unlock(mac->bus);
1571 consume_skb(resp_skb);
1572
1573 return ret;
1574 }
1575
qtnf_cmd_get_hw_info(struct qtnf_bus * bus)1576 int qtnf_cmd_get_hw_info(struct qtnf_bus *bus)
1577 {
1578 struct sk_buff *cmd_skb, *resp_skb = NULL;
1579 const struct qlink_resp_get_hw_info *resp;
1580 size_t info_len = 0;
1581 int ret = 0;
1582
1583 cmd_skb = qtnf_cmd_alloc_new_cmdskb(QLINK_MACID_RSVD, QLINK_VIFID_RSVD,
1584 QLINK_CMD_GET_HW_INFO,
1585 sizeof(struct qlink_cmd));
1586 if (!cmd_skb)
1587 return -ENOMEM;
1588
1589 qtnf_bus_lock(bus);
1590 ret = qtnf_cmd_send_with_reply(bus, cmd_skb, &resp_skb,
1591 sizeof(*resp), &info_len);
1592 if (ret)
1593 goto out;
1594
1595 resp = (const struct qlink_resp_get_hw_info *)resp_skb->data;
1596 ret = qtnf_cmd_resp_proc_hw_info(bus, resp, info_len);
1597
1598 out:
1599 qtnf_bus_unlock(bus);
1600 consume_skb(resp_skb);
1601
1602 return ret;
1603 }
1604
qtnf_cmd_band_info_get(struct qtnf_wmac * mac,struct ieee80211_supported_band * band)1605 int qtnf_cmd_band_info_get(struct qtnf_wmac *mac,
1606 struct ieee80211_supported_band *band)
1607 {
1608 struct sk_buff *cmd_skb, *resp_skb = NULL;
1609 struct qlink_cmd_band_info_get *cmd;
1610 struct qlink_resp_band_info_get *resp;
1611 size_t info_len = 0;
1612 int ret = 0;
1613 u8 qband = qlink_utils_band_cfg2q(band->band);
1614
1615 cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, 0,
1616 QLINK_CMD_BAND_INFO_GET,
1617 sizeof(*cmd));
1618 if (!cmd_skb)
1619 return -ENOMEM;
1620
1621 cmd = (struct qlink_cmd_band_info_get *)cmd_skb->data;
1622 cmd->band = qband;
1623
1624 qtnf_bus_lock(mac->bus);
1625 ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb,
1626 sizeof(*resp), &info_len);
1627 if (ret)
1628 goto out;
1629
1630 resp = (struct qlink_resp_band_info_get *)resp_skb->data;
1631 if (resp->band != qband) {
1632 pr_err("MAC%u: reply band %u != cmd band %u\n", mac->macid,
1633 resp->band, qband);
1634 ret = -EINVAL;
1635 goto out;
1636 }
1637
1638 ret = qtnf_cmd_resp_fill_band_info(band, resp, info_len);
1639
1640 out:
1641 qtnf_bus_unlock(mac->bus);
1642 consume_skb(resp_skb);
1643
1644 return ret;
1645 }
1646
qtnf_cmd_send_update_phy_params(struct qtnf_wmac * mac,u32 changed)1647 int qtnf_cmd_send_update_phy_params(struct qtnf_wmac *mac, u32 changed)
1648 {
1649 struct wiphy *wiphy = priv_to_wiphy(mac);
1650 struct sk_buff *cmd_skb;
1651 int ret = 0;
1652
1653 cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, 0,
1654 QLINK_CMD_PHY_PARAMS_SET,
1655 sizeof(struct qlink_cmd));
1656 if (!cmd_skb)
1657 return -ENOMEM;
1658
1659 qtnf_bus_lock(mac->bus);
1660
1661 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
1662 qtnf_cmd_skb_put_tlv_u32(cmd_skb, QTN_TLV_ID_FRAG_THRESH,
1663 wiphy->frag_threshold);
1664 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
1665 qtnf_cmd_skb_put_tlv_u32(cmd_skb, QTN_TLV_ID_RTS_THRESH,
1666 wiphy->rts_threshold);
1667 if (changed & WIPHY_PARAM_COVERAGE_CLASS)
1668 qtnf_cmd_skb_put_tlv_u32(cmd_skb, QTN_TLV_ID_COVERAGE_CLASS,
1669 wiphy->coverage_class);
1670
1671 if (changed & WIPHY_PARAM_RETRY_LONG)
1672 qtnf_cmd_skb_put_tlv_u32(cmd_skb, QTN_TLV_ID_LRETRY_LIMIT,
1673 wiphy->retry_long);
1674
1675 if (changed & WIPHY_PARAM_RETRY_SHORT)
1676 qtnf_cmd_skb_put_tlv_u32(cmd_skb, QTN_TLV_ID_SRETRY_LIMIT,
1677 wiphy->retry_short);
1678
1679 ret = qtnf_cmd_send(mac->bus, cmd_skb);
1680 if (ret)
1681 goto out;
1682
1683 out:
1684 qtnf_bus_unlock(mac->bus);
1685
1686 return ret;
1687 }
1688
qtnf_cmd_send_init_fw(struct qtnf_bus * bus)1689 int qtnf_cmd_send_init_fw(struct qtnf_bus *bus)
1690 {
1691 struct sk_buff *resp_skb = NULL;
1692 struct qlink_resp_init_fw *resp;
1693 struct qlink_cmd_init_fw *cmd;
1694 struct sk_buff *cmd_skb;
1695 size_t info_len = 0;
1696 int ret;
1697
1698 cmd_skb = qtnf_cmd_alloc_new_cmdskb(QLINK_MACID_RSVD, QLINK_VIFID_RSVD,
1699 QLINK_CMD_FW_INIT,
1700 sizeof(*cmd));
1701 if (!cmd_skb)
1702 return -ENOMEM;
1703
1704 cmd = (struct qlink_cmd_init_fw *)cmd_skb->data;
1705 cmd->qlink_proto_ver = cpu_to_le32(QLINK_PROTO_VER);
1706
1707 qtnf_bus_lock(bus);
1708 ret = qtnf_cmd_send_with_reply(bus, cmd_skb, &resp_skb,
1709 sizeof(*resp), &info_len);
1710 qtnf_bus_unlock(bus);
1711
1712 if (ret)
1713 goto out;
1714
1715 resp = (struct qlink_resp_init_fw *)resp_skb->data;
1716 bus->hw_info.ql_proto_ver = le32_to_cpu(resp->qlink_proto_ver);
1717
1718 out:
1719 consume_skb(resp_skb);
1720 return ret;
1721 }
1722
qtnf_cmd_send_deinit_fw(struct qtnf_bus * bus)1723 void qtnf_cmd_send_deinit_fw(struct qtnf_bus *bus)
1724 {
1725 struct sk_buff *cmd_skb;
1726
1727 cmd_skb = qtnf_cmd_alloc_new_cmdskb(QLINK_MACID_RSVD, QLINK_VIFID_RSVD,
1728 QLINK_CMD_FW_DEINIT,
1729 sizeof(struct qlink_cmd));
1730 if (!cmd_skb)
1731 return;
1732
1733 qtnf_bus_lock(bus);
1734 qtnf_cmd_send(bus, cmd_skb);
1735 qtnf_bus_unlock(bus);
1736 }
1737
qtnf_cmd_send_add_key(struct qtnf_vif * vif,u8 key_index,bool pairwise,const u8 * mac_addr,struct key_params * params)1738 int qtnf_cmd_send_add_key(struct qtnf_vif *vif, u8 key_index, bool pairwise,
1739 const u8 *mac_addr, struct key_params *params)
1740 {
1741 struct sk_buff *cmd_skb;
1742 struct qlink_cmd_add_key *cmd;
1743 int ret = 0;
1744
1745 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
1746 QLINK_CMD_ADD_KEY,
1747 sizeof(*cmd));
1748 if (!cmd_skb)
1749 return -ENOMEM;
1750
1751 qtnf_bus_lock(vif->mac->bus);
1752
1753 cmd = (struct qlink_cmd_add_key *)cmd_skb->data;
1754
1755 if (mac_addr)
1756 ether_addr_copy(cmd->addr, mac_addr);
1757 else
1758 eth_broadcast_addr(cmd->addr);
1759
1760 cmd->cipher = cpu_to_le32(params->cipher);
1761 cmd->key_index = key_index;
1762 cmd->pairwise = pairwise;
1763
1764 if (params->key && params->key_len > 0)
1765 qtnf_cmd_skb_put_tlv_arr(cmd_skb, QTN_TLV_ID_KEY,
1766 params->key,
1767 params->key_len);
1768
1769 if (params->seq && params->seq_len > 0)
1770 qtnf_cmd_skb_put_tlv_arr(cmd_skb, QTN_TLV_ID_SEQ,
1771 params->seq,
1772 params->seq_len);
1773
1774 ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
1775 if (ret)
1776 goto out;
1777
1778 out:
1779 qtnf_bus_unlock(vif->mac->bus);
1780
1781 return ret;
1782 }
1783
qtnf_cmd_send_del_key(struct qtnf_vif * vif,u8 key_index,bool pairwise,const u8 * mac_addr)1784 int qtnf_cmd_send_del_key(struct qtnf_vif *vif, u8 key_index, bool pairwise,
1785 const u8 *mac_addr)
1786 {
1787 struct sk_buff *cmd_skb;
1788 struct qlink_cmd_del_key *cmd;
1789 int ret = 0;
1790
1791 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
1792 QLINK_CMD_DEL_KEY,
1793 sizeof(*cmd));
1794 if (!cmd_skb)
1795 return -ENOMEM;
1796
1797 qtnf_bus_lock(vif->mac->bus);
1798
1799 cmd = (struct qlink_cmd_del_key *)cmd_skb->data;
1800
1801 if (mac_addr)
1802 ether_addr_copy(cmd->addr, mac_addr);
1803 else
1804 eth_broadcast_addr(cmd->addr);
1805
1806 cmd->key_index = key_index;
1807 cmd->pairwise = pairwise;
1808
1809 ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
1810 if (ret)
1811 goto out;
1812
1813 out:
1814 qtnf_bus_unlock(vif->mac->bus);
1815
1816 return ret;
1817 }
1818
qtnf_cmd_send_set_default_key(struct qtnf_vif * vif,u8 key_index,bool unicast,bool multicast)1819 int qtnf_cmd_send_set_default_key(struct qtnf_vif *vif, u8 key_index,
1820 bool unicast, bool multicast)
1821 {
1822 struct sk_buff *cmd_skb;
1823 struct qlink_cmd_set_def_key *cmd;
1824 int ret = 0;
1825
1826 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
1827 QLINK_CMD_SET_DEFAULT_KEY,
1828 sizeof(*cmd));
1829 if (!cmd_skb)
1830 return -ENOMEM;
1831
1832 qtnf_bus_lock(vif->mac->bus);
1833
1834 cmd = (struct qlink_cmd_set_def_key *)cmd_skb->data;
1835 cmd->key_index = key_index;
1836 cmd->unicast = unicast;
1837 cmd->multicast = multicast;
1838
1839 ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
1840 if (ret)
1841 goto out;
1842
1843 out:
1844 qtnf_bus_unlock(vif->mac->bus);
1845
1846 return ret;
1847 }
1848
qtnf_cmd_send_set_default_mgmt_key(struct qtnf_vif * vif,u8 key_index)1849 int qtnf_cmd_send_set_default_mgmt_key(struct qtnf_vif *vif, u8 key_index)
1850 {
1851 struct sk_buff *cmd_skb;
1852 struct qlink_cmd_set_def_mgmt_key *cmd;
1853 int ret = 0;
1854
1855 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
1856 QLINK_CMD_SET_DEFAULT_MGMT_KEY,
1857 sizeof(*cmd));
1858 if (!cmd_skb)
1859 return -ENOMEM;
1860
1861 qtnf_bus_lock(vif->mac->bus);
1862
1863 cmd = (struct qlink_cmd_set_def_mgmt_key *)cmd_skb->data;
1864 cmd->key_index = key_index;
1865
1866 ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
1867 if (ret)
1868 goto out;
1869
1870 out:
1871 qtnf_bus_unlock(vif->mac->bus);
1872
1873 return ret;
1874 }
1875
qtnf_encode_sta_flags(u32 flags)1876 static u32 qtnf_encode_sta_flags(u32 flags)
1877 {
1878 u32 code = 0;
1879
1880 if (flags & BIT(NL80211_STA_FLAG_AUTHORIZED))
1881 code |= QLINK_STA_FLAG_AUTHORIZED;
1882 if (flags & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE))
1883 code |= QLINK_STA_FLAG_SHORT_PREAMBLE;
1884 if (flags & BIT(NL80211_STA_FLAG_WME))
1885 code |= QLINK_STA_FLAG_WME;
1886 if (flags & BIT(NL80211_STA_FLAG_MFP))
1887 code |= QLINK_STA_FLAG_MFP;
1888 if (flags & BIT(NL80211_STA_FLAG_AUTHENTICATED))
1889 code |= QLINK_STA_FLAG_AUTHENTICATED;
1890 if (flags & BIT(NL80211_STA_FLAG_TDLS_PEER))
1891 code |= QLINK_STA_FLAG_TDLS_PEER;
1892 if (flags & BIT(NL80211_STA_FLAG_ASSOCIATED))
1893 code |= QLINK_STA_FLAG_ASSOCIATED;
1894 return code;
1895 }
1896
qtnf_cmd_send_change_sta(struct qtnf_vif * vif,const u8 * mac,struct station_parameters * params)1897 int qtnf_cmd_send_change_sta(struct qtnf_vif *vif, const u8 *mac,
1898 struct station_parameters *params)
1899 {
1900 struct sk_buff *cmd_skb;
1901 struct qlink_cmd_change_sta *cmd;
1902 int ret = 0;
1903
1904 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
1905 QLINK_CMD_CHANGE_STA,
1906 sizeof(*cmd));
1907 if (!cmd_skb)
1908 return -ENOMEM;
1909
1910 qtnf_bus_lock(vif->mac->bus);
1911
1912 cmd = (struct qlink_cmd_change_sta *)cmd_skb->data;
1913 ether_addr_copy(cmd->sta_addr, mac);
1914 cmd->flag_update.mask =
1915 cpu_to_le32(qtnf_encode_sta_flags(params->sta_flags_mask));
1916 cmd->flag_update.value =
1917 cpu_to_le32(qtnf_encode_sta_flags(params->sta_flags_set));
1918
1919 switch (vif->wdev.iftype) {
1920 case NL80211_IFTYPE_AP:
1921 cmd->if_type = cpu_to_le16(QLINK_IFTYPE_AP);
1922 break;
1923 case NL80211_IFTYPE_STATION:
1924 cmd->if_type = cpu_to_le16(QLINK_IFTYPE_STATION);
1925 break;
1926 default:
1927 pr_err("unsupported iftype %d\n", vif->wdev.iftype);
1928 dev_kfree_skb(cmd_skb);
1929 ret = -EINVAL;
1930 goto out;
1931 }
1932
1933 ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
1934 if (ret)
1935 goto out;
1936
1937 out:
1938 qtnf_bus_unlock(vif->mac->bus);
1939
1940 return ret;
1941 }
1942
qtnf_cmd_send_del_sta(struct qtnf_vif * vif,struct station_del_parameters * params)1943 int qtnf_cmd_send_del_sta(struct qtnf_vif *vif,
1944 struct station_del_parameters *params)
1945 {
1946 struct sk_buff *cmd_skb;
1947 struct qlink_cmd_del_sta *cmd;
1948 int ret = 0;
1949
1950 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
1951 QLINK_CMD_DEL_STA,
1952 sizeof(*cmd));
1953 if (!cmd_skb)
1954 return -ENOMEM;
1955
1956 qtnf_bus_lock(vif->mac->bus);
1957
1958 cmd = (struct qlink_cmd_del_sta *)cmd_skb->data;
1959
1960 if (params->mac)
1961 ether_addr_copy(cmd->sta_addr, params->mac);
1962 else
1963 eth_broadcast_addr(cmd->sta_addr); /* flush all stations */
1964
1965 cmd->subtype = params->subtype;
1966 cmd->reason_code = cpu_to_le16(params->reason_code);
1967
1968 ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
1969 if (ret)
1970 goto out;
1971
1972 out:
1973 qtnf_bus_unlock(vif->mac->bus);
1974
1975 return ret;
1976 }
1977
qtnf_cmd_channel_tlv_add(struct sk_buff * cmd_skb,const struct ieee80211_channel * sc)1978 static void qtnf_cmd_channel_tlv_add(struct sk_buff *cmd_skb,
1979 const struct ieee80211_channel *sc)
1980 {
1981 struct qlink_tlv_channel *tlv;
1982 struct qlink_channel *qch;
1983
1984 tlv = skb_put_zero(cmd_skb, sizeof(*tlv));
1985 qch = &tlv->chan;
1986 tlv->hdr.type = cpu_to_le16(QTN_TLV_ID_CHANNEL);
1987 tlv->hdr.len = cpu_to_le16(sizeof(*qch));
1988
1989 qch->center_freq = cpu_to_le16(sc->center_freq);
1990 qch->hw_value = cpu_to_le16(sc->hw_value);
1991 qch->band = qlink_utils_band_cfg2q(sc->band);
1992 qch->max_power = sc->max_power;
1993 qch->max_reg_power = sc->max_reg_power;
1994 qch->max_antenna_gain = sc->max_antenna_gain;
1995 qch->beacon_found = sc->beacon_found;
1996 qch->dfs_state = qlink_utils_dfs_state_cfg2q(sc->dfs_state);
1997 qch->flags = cpu_to_le32(qlink_utils_chflags_cfg2q(sc->flags));
1998 }
1999
qtnf_cmd_randmac_tlv_add(struct sk_buff * cmd_skb,const u8 * mac_addr,const u8 * mac_addr_mask)2000 static void qtnf_cmd_randmac_tlv_add(struct sk_buff *cmd_skb,
2001 const u8 *mac_addr,
2002 const u8 *mac_addr_mask)
2003 {
2004 struct qlink_random_mac_addr *randmac;
2005 struct qlink_tlv_hdr *hdr =
2006 skb_put(cmd_skb, sizeof(*hdr) + sizeof(*randmac));
2007
2008 hdr->type = cpu_to_le16(QTN_TLV_ID_RANDOM_MAC_ADDR);
2009 hdr->len = cpu_to_le16(sizeof(*randmac));
2010 randmac = (struct qlink_random_mac_addr *)hdr->val;
2011
2012 memcpy(randmac->mac_addr, mac_addr, ETH_ALEN);
2013 memcpy(randmac->mac_addr_mask, mac_addr_mask, ETH_ALEN);
2014 }
2015
qtnf_cmd_send_scan(struct qtnf_wmac * mac)2016 int qtnf_cmd_send_scan(struct qtnf_wmac *mac)
2017 {
2018 struct cfg80211_scan_request *scan_req = mac->scan_req;
2019 u16 dwell_passive = QTNF_SCAN_DWELL_PASSIVE_DEFAULT;
2020 u16 dwell_active = QTNF_SCAN_DWELL_ACTIVE_DEFAULT;
2021 struct wireless_dev *wdev = scan_req->wdev;
2022 struct ieee80211_channel *sc;
2023 struct qlink_cmd_scan *cmd;
2024 struct sk_buff *cmd_skb;
2025 int n_channels = 0;
2026 u64 flags = 0;
2027 int count;
2028 int ret;
2029
2030 cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, QLINK_VIFID_RSVD,
2031 QLINK_CMD_SCAN,
2032 sizeof(*cmd));
2033 if (!cmd_skb)
2034 return -ENOMEM;
2035
2036 cmd = (struct qlink_cmd_scan *)cmd_skb->data;
2037
2038 if (scan_req->duration) {
2039 dwell_active = scan_req->duration;
2040 dwell_passive = scan_req->duration;
2041 } else if (wdev->iftype == NL80211_IFTYPE_STATION &&
2042 wdev->current_bss) {
2043 /* let device select dwell based on traffic conditions */
2044 dwell_active = QTNF_SCAN_TIME_AUTO;
2045 dwell_passive = QTNF_SCAN_TIME_AUTO;
2046 }
2047
2048 cmd->n_ssids = cpu_to_le16(scan_req->n_ssids);
2049 for (count = 0; count < scan_req->n_ssids; ++count) {
2050 qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID,
2051 scan_req->ssids[count].ssid,
2052 scan_req->ssids[count].ssid_len);
2053 }
2054
2055 if (scan_req->ie_len != 0)
2056 qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_PROBE_REQ,
2057 scan_req->ie, scan_req->ie_len);
2058
2059 for (count = 0; count < scan_req->n_channels; ++count) {
2060 sc = scan_req->channels[count];
2061 if (sc->flags & IEEE80211_CHAN_DISABLED)
2062 continue;
2063
2064 pr_debug("[MAC%u] scan chan=%d, freq=%d, flags=%#x\n",
2065 mac->macid, sc->hw_value, sc->center_freq,
2066 sc->flags);
2067
2068 qtnf_cmd_channel_tlv_add(cmd_skb, sc);
2069 ++n_channels;
2070 }
2071
2072 if (scan_req->flags & NL80211_SCAN_FLAG_FLUSH)
2073 flags |= QLINK_SCAN_FLAG_FLUSH;
2074
2075 if (scan_req->duration_mandatory)
2076 flags |= QLINK_SCAN_FLAG_DURATION_MANDATORY;
2077
2078 cmd->n_channels = cpu_to_le16(n_channels);
2079 cmd->active_dwell = cpu_to_le16(dwell_active);
2080 cmd->passive_dwell = cpu_to_le16(dwell_passive);
2081 cmd->sample_duration = cpu_to_le16(QTNF_SCAN_SAMPLE_DURATION_DEFAULT);
2082 cmd->flags = cpu_to_le64(flags);
2083
2084 pr_debug("[MAC%u] %s scan dwell active=%u passive=%u duration=%u\n",
2085 mac->macid,
2086 scan_req->duration_mandatory ? "mandatory" : "max",
2087 dwell_active, dwell_passive,
2088 QTNF_SCAN_SAMPLE_DURATION_DEFAULT);
2089
2090 if (scan_req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
2091 pr_debug("[MAC%u] scan with random addr=%pM, mask=%pM\n",
2092 mac->macid,
2093 scan_req->mac_addr, scan_req->mac_addr_mask);
2094 qtnf_cmd_randmac_tlv_add(cmd_skb, scan_req->mac_addr,
2095 scan_req->mac_addr_mask);
2096 }
2097
2098 qtnf_bus_lock(mac->bus);
2099 ret = qtnf_cmd_send(mac->bus, cmd_skb);
2100 qtnf_bus_unlock(mac->bus);
2101
2102 return ret;
2103 }
2104
qtnf_cmd_send_connect(struct qtnf_vif * vif,struct cfg80211_connect_params * sme)2105 int qtnf_cmd_send_connect(struct qtnf_vif *vif,
2106 struct cfg80211_connect_params *sme)
2107 {
2108 struct sk_buff *cmd_skb;
2109 struct qlink_cmd_connect *cmd;
2110 struct qlink_auth_encr *aen;
2111 int ret;
2112 int i;
2113 u32 connect_flags = 0;
2114
2115 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
2116 QLINK_CMD_CONNECT,
2117 sizeof(*cmd));
2118 if (!cmd_skb)
2119 return -ENOMEM;
2120
2121 cmd = (struct qlink_cmd_connect *)cmd_skb->data;
2122
2123 ether_addr_copy(cmd->bssid, vif->bssid);
2124
2125 if (sme->bssid_hint)
2126 ether_addr_copy(cmd->bssid_hint, sme->bssid_hint);
2127 else
2128 eth_zero_addr(cmd->bssid_hint);
2129
2130 if (sme->prev_bssid)
2131 ether_addr_copy(cmd->prev_bssid, sme->prev_bssid);
2132 else
2133 eth_zero_addr(cmd->prev_bssid);
2134
2135 if ((sme->bg_scan_period >= 0) &&
2136 (sme->bg_scan_period <= SHRT_MAX))
2137 cmd->bg_scan_period = cpu_to_le16(sme->bg_scan_period);
2138 else
2139 cmd->bg_scan_period = cpu_to_le16(-1); /* use default value */
2140
2141 if (sme->flags & ASSOC_REQ_DISABLE_HT)
2142 connect_flags |= QLINK_STA_CONNECT_DISABLE_HT;
2143 if (sme->flags & ASSOC_REQ_DISABLE_VHT)
2144 connect_flags |= QLINK_STA_CONNECT_DISABLE_VHT;
2145 if (sme->flags & ASSOC_REQ_USE_RRM)
2146 connect_flags |= QLINK_STA_CONNECT_USE_RRM;
2147
2148 cmd->flags = cpu_to_le32(connect_flags);
2149 memcpy(&cmd->ht_capa, &sme->ht_capa, sizeof(cmd->ht_capa));
2150 memcpy(&cmd->ht_capa_mask, &sme->ht_capa_mask,
2151 sizeof(cmd->ht_capa_mask));
2152 memcpy(&cmd->vht_capa, &sme->vht_capa, sizeof(cmd->vht_capa));
2153 memcpy(&cmd->vht_capa_mask, &sme->vht_capa_mask,
2154 sizeof(cmd->vht_capa_mask));
2155 cmd->pbss = sme->pbss;
2156
2157 aen = &cmd->aen;
2158 aen->auth_type = sme->auth_type;
2159 aen->privacy = !!sme->privacy;
2160 cmd->mfp = sme->mfp;
2161 aen->wpa_versions = cpu_to_le32(sme->crypto.wpa_versions);
2162 aen->cipher_group = cpu_to_le32(sme->crypto.cipher_group);
2163 aen->n_ciphers_pairwise = cpu_to_le32(sme->crypto.n_ciphers_pairwise);
2164
2165 for (i = 0; i < QLINK_MAX_NR_CIPHER_SUITES; i++)
2166 aen->ciphers_pairwise[i] =
2167 cpu_to_le32(sme->crypto.ciphers_pairwise[i]);
2168
2169 aen->n_akm_suites = cpu_to_le32(sme->crypto.n_akm_suites);
2170
2171 for (i = 0; i < QLINK_MAX_NR_AKM_SUITES; i++)
2172 aen->akm_suites[i] = cpu_to_le32(sme->crypto.akm_suites[i]);
2173
2174 aen->control_port = sme->crypto.control_port;
2175 aen->control_port_no_encrypt =
2176 sme->crypto.control_port_no_encrypt;
2177 aen->control_port_ethertype =
2178 cpu_to_le16(be16_to_cpu(sme->crypto.control_port_ethertype));
2179
2180 qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID, sme->ssid,
2181 sme->ssid_len);
2182
2183 if (sme->ie_len != 0)
2184 qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_ASSOC_REQ,
2185 sme->ie, sme->ie_len);
2186
2187 if (sme->channel)
2188 qtnf_cmd_channel_tlv_add(cmd_skb, sme->channel);
2189
2190 qtnf_bus_lock(vif->mac->bus);
2191 ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
2192 if (ret)
2193 goto out;
2194
2195 out:
2196 qtnf_bus_unlock(vif->mac->bus);
2197
2198 return ret;
2199 }
2200
qtnf_cmd_send_external_auth(struct qtnf_vif * vif,struct cfg80211_external_auth_params * auth)2201 int qtnf_cmd_send_external_auth(struct qtnf_vif *vif,
2202 struct cfg80211_external_auth_params *auth)
2203 {
2204 struct sk_buff *cmd_skb;
2205 struct qlink_cmd_external_auth *cmd;
2206 int ret;
2207
2208 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
2209 QLINK_CMD_EXTERNAL_AUTH,
2210 sizeof(*cmd));
2211 if (!cmd_skb)
2212 return -ENOMEM;
2213
2214 cmd = (struct qlink_cmd_external_auth *)cmd_skb->data;
2215
2216 ether_addr_copy(cmd->peer, auth->bssid);
2217 cmd->status = cpu_to_le16(auth->status);
2218
2219 qtnf_bus_lock(vif->mac->bus);
2220 ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
2221 if (ret)
2222 goto out;
2223
2224 out:
2225 qtnf_bus_unlock(vif->mac->bus);
2226
2227 return ret;
2228 }
2229
qtnf_cmd_send_disconnect(struct qtnf_vif * vif,u16 reason_code)2230 int qtnf_cmd_send_disconnect(struct qtnf_vif *vif, u16 reason_code)
2231 {
2232 struct sk_buff *cmd_skb;
2233 struct qlink_cmd_disconnect *cmd;
2234 int ret;
2235
2236 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
2237 QLINK_CMD_DISCONNECT,
2238 sizeof(*cmd));
2239 if (!cmd_skb)
2240 return -ENOMEM;
2241
2242 qtnf_bus_lock(vif->mac->bus);
2243
2244 cmd = (struct qlink_cmd_disconnect *)cmd_skb->data;
2245 cmd->reason = cpu_to_le16(reason_code);
2246
2247 ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
2248 if (ret)
2249 goto out;
2250
2251 out:
2252 qtnf_bus_unlock(vif->mac->bus);
2253
2254 return ret;
2255 }
2256
qtnf_cmd_send_updown_intf(struct qtnf_vif * vif,bool up)2257 int qtnf_cmd_send_updown_intf(struct qtnf_vif *vif, bool up)
2258 {
2259 struct sk_buff *cmd_skb;
2260 struct qlink_cmd_updown *cmd;
2261 int ret;
2262
2263 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
2264 QLINK_CMD_UPDOWN_INTF,
2265 sizeof(*cmd));
2266 if (!cmd_skb)
2267 return -ENOMEM;
2268
2269 cmd = (struct qlink_cmd_updown *)cmd_skb->data;
2270 cmd->if_up = !!up;
2271
2272 qtnf_bus_lock(vif->mac->bus);
2273 ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
2274 if (ret)
2275 goto out;
2276
2277 out:
2278 qtnf_bus_unlock(vif->mac->bus);
2279
2280 return ret;
2281 }
2282
qtnf_cmd_reg_notify(struct qtnf_wmac * mac,struct regulatory_request * req,bool slave_radar,bool dfs_offload)2283 int qtnf_cmd_reg_notify(struct qtnf_wmac *mac, struct regulatory_request *req,
2284 bool slave_radar, bool dfs_offload)
2285 {
2286 struct wiphy *wiphy = priv_to_wiphy(mac);
2287 struct qtnf_bus *bus = mac->bus;
2288 struct sk_buff *cmd_skb;
2289 int ret;
2290 struct qlink_cmd_reg_notify *cmd;
2291 enum nl80211_band band;
2292 const struct ieee80211_supported_band *cfg_band;
2293
2294 cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, QLINK_VIFID_RSVD,
2295 QLINK_CMD_REG_NOTIFY,
2296 sizeof(*cmd));
2297 if (!cmd_skb)
2298 return -ENOMEM;
2299
2300 cmd = (struct qlink_cmd_reg_notify *)cmd_skb->data;
2301 cmd->alpha2[0] = req->alpha2[0];
2302 cmd->alpha2[1] = req->alpha2[1];
2303
2304 switch (req->initiator) {
2305 case NL80211_REGDOM_SET_BY_CORE:
2306 cmd->initiator = QLINK_REGDOM_SET_BY_CORE;
2307 break;
2308 case NL80211_REGDOM_SET_BY_USER:
2309 cmd->initiator = QLINK_REGDOM_SET_BY_USER;
2310 break;
2311 case NL80211_REGDOM_SET_BY_DRIVER:
2312 cmd->initiator = QLINK_REGDOM_SET_BY_DRIVER;
2313 break;
2314 case NL80211_REGDOM_SET_BY_COUNTRY_IE:
2315 cmd->initiator = QLINK_REGDOM_SET_BY_COUNTRY_IE;
2316 break;
2317 }
2318
2319 switch (req->user_reg_hint_type) {
2320 case NL80211_USER_REG_HINT_USER:
2321 cmd->user_reg_hint_type = QLINK_USER_REG_HINT_USER;
2322 break;
2323 case NL80211_USER_REG_HINT_CELL_BASE:
2324 cmd->user_reg_hint_type = QLINK_USER_REG_HINT_CELL_BASE;
2325 break;
2326 case NL80211_USER_REG_HINT_INDOOR:
2327 cmd->user_reg_hint_type = QLINK_USER_REG_HINT_INDOOR;
2328 break;
2329 }
2330
2331 switch (req->dfs_region) {
2332 case NL80211_DFS_FCC:
2333 cmd->dfs_region = QLINK_DFS_FCC;
2334 break;
2335 case NL80211_DFS_ETSI:
2336 cmd->dfs_region = QLINK_DFS_ETSI;
2337 break;
2338 case NL80211_DFS_JP:
2339 cmd->dfs_region = QLINK_DFS_JP;
2340 break;
2341 default:
2342 cmd->dfs_region = QLINK_DFS_UNSET;
2343 break;
2344 }
2345
2346 cmd->slave_radar = slave_radar;
2347 cmd->dfs_offload = dfs_offload;
2348 cmd->num_channels = 0;
2349
2350 for (band = 0; band < NUM_NL80211_BANDS; band++) {
2351 unsigned int i;
2352
2353 cfg_band = wiphy->bands[band];
2354 if (!cfg_band)
2355 continue;
2356
2357 cmd->num_channels += cfg_band->n_channels;
2358
2359 for (i = 0; i < cfg_band->n_channels; ++i) {
2360 qtnf_cmd_channel_tlv_add(cmd_skb,
2361 &cfg_band->channels[i]);
2362 }
2363 }
2364
2365 qtnf_bus_lock(bus);
2366 ret = qtnf_cmd_send(bus, cmd_skb);
2367 qtnf_bus_unlock(bus);
2368
2369 return ret;
2370 }
2371
2372 static int
qtnf_cmd_resp_proc_chan_stat_info(struct survey_info * survey,const u8 * payload,size_t payload_len)2373 qtnf_cmd_resp_proc_chan_stat_info(struct survey_info *survey,
2374 const u8 *payload, size_t payload_len)
2375 {
2376 const struct qlink_chan_stats *stats = NULL;
2377 const struct qlink_tlv_hdr *tlv;
2378 u16 tlv_value_len;
2379 u16 tlv_type;
2380 const u8 *map = NULL;
2381 unsigned int map_len = 0;
2382 unsigned int stats_len = 0;
2383
2384 qlink_for_each_tlv(tlv, payload, payload_len) {
2385 tlv_type = le16_to_cpu(tlv->type);
2386 tlv_value_len = le16_to_cpu(tlv->len);
2387
2388 switch (tlv_type) {
2389 case QTN_TLV_ID_BITMAP:
2390 map = tlv->val;
2391 map_len = tlv_value_len;
2392 break;
2393 case QTN_TLV_ID_CHANNEL_STATS:
2394 stats = (struct qlink_chan_stats *)tlv->val;
2395 stats_len = tlv_value_len;
2396 break;
2397 default:
2398 pr_info("Unknown TLV type: %#x\n", tlv_type);
2399 break;
2400 }
2401 }
2402
2403 if (!qlink_tlv_parsing_ok(tlv, payload, payload_len)) {
2404 pr_err("Malformed TLV buffer\n");
2405 return -EINVAL;
2406 }
2407
2408 if (!map || !stats)
2409 return 0;
2410
2411 #define qtnf_chan_stat_avail(stat_name, bitn) \
2412 (qtnf_utils_is_bit_set(map, bitn, map_len) && \
2413 (offsetofend(struct qlink_chan_stats, stat_name) <= stats_len))
2414
2415 if (qtnf_chan_stat_avail(time_on, QLINK_CHAN_STAT_TIME_ON)) {
2416 survey->filled |= SURVEY_INFO_TIME;
2417 survey->time = le64_to_cpu(stats->time_on);
2418 }
2419
2420 if (qtnf_chan_stat_avail(time_tx, QLINK_CHAN_STAT_TIME_TX)) {
2421 survey->filled |= SURVEY_INFO_TIME_TX;
2422 survey->time_tx = le64_to_cpu(stats->time_tx);
2423 }
2424
2425 if (qtnf_chan_stat_avail(time_rx, QLINK_CHAN_STAT_TIME_RX)) {
2426 survey->filled |= SURVEY_INFO_TIME_RX;
2427 survey->time_rx = le64_to_cpu(stats->time_rx);
2428 }
2429
2430 if (qtnf_chan_stat_avail(cca_busy, QLINK_CHAN_STAT_CCA_BUSY)) {
2431 survey->filled |= SURVEY_INFO_TIME_BUSY;
2432 survey->time_busy = le64_to_cpu(stats->cca_busy);
2433 }
2434
2435 if (qtnf_chan_stat_avail(cca_busy_ext, QLINK_CHAN_STAT_CCA_BUSY_EXT)) {
2436 survey->filled |= SURVEY_INFO_TIME_EXT_BUSY;
2437 survey->time_ext_busy = le64_to_cpu(stats->cca_busy_ext);
2438 }
2439
2440 if (qtnf_chan_stat_avail(time_scan, QLINK_CHAN_STAT_TIME_SCAN)) {
2441 survey->filled |= SURVEY_INFO_TIME_SCAN;
2442 survey->time_scan = le64_to_cpu(stats->time_scan);
2443 }
2444
2445 if (qtnf_chan_stat_avail(chan_noise, QLINK_CHAN_STAT_CHAN_NOISE)) {
2446 survey->filled |= SURVEY_INFO_NOISE_DBM;
2447 survey->noise = stats->chan_noise;
2448 }
2449
2450 #undef qtnf_chan_stat_avail
2451
2452 return 0;
2453 }
2454
qtnf_cmd_get_chan_stats(struct qtnf_wmac * mac,u32 chan_freq,struct survey_info * survey)2455 int qtnf_cmd_get_chan_stats(struct qtnf_wmac *mac, u32 chan_freq,
2456 struct survey_info *survey)
2457 {
2458 struct sk_buff *cmd_skb, *resp_skb = NULL;
2459 struct qlink_cmd_get_chan_stats *cmd;
2460 struct qlink_resp_get_chan_stats *resp;
2461 size_t var_data_len = 0;
2462 int ret = 0;
2463
2464 cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, QLINK_VIFID_RSVD,
2465 QLINK_CMD_CHAN_STATS,
2466 sizeof(*cmd));
2467 if (!cmd_skb)
2468 return -ENOMEM;
2469
2470 cmd = (struct qlink_cmd_get_chan_stats *)cmd_skb->data;
2471 cmd->channel_freq = cpu_to_le32(chan_freq);
2472
2473 qtnf_bus_lock(mac->bus);
2474 ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb,
2475 sizeof(*resp), &var_data_len);
2476 qtnf_bus_unlock(mac->bus);
2477
2478 if (ret)
2479 goto out;
2480
2481 resp = (struct qlink_resp_get_chan_stats *)resp_skb->data;
2482
2483 if (le32_to_cpu(resp->chan_freq) != chan_freq) {
2484 pr_err("[MAC%u] channel stats freq %u != requested %u\n",
2485 mac->macid, le32_to_cpu(resp->chan_freq), chan_freq);
2486 ret = -EINVAL;
2487 goto out;
2488 }
2489
2490 ret = qtnf_cmd_resp_proc_chan_stat_info(survey, resp->info,
2491 var_data_len);
2492
2493 out:
2494 consume_skb(resp_skb);
2495
2496 return ret;
2497 }
2498
qtnf_cmd_send_chan_switch(struct qtnf_vif * vif,struct cfg80211_csa_settings * params)2499 int qtnf_cmd_send_chan_switch(struct qtnf_vif *vif,
2500 struct cfg80211_csa_settings *params)
2501 {
2502 struct qtnf_wmac *mac = vif->mac;
2503 struct qlink_cmd_chan_switch *cmd;
2504 struct sk_buff *cmd_skb;
2505 int ret;
2506 u64 flags = 0;
2507
2508 cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, vif->vifid,
2509 QLINK_CMD_CHAN_SWITCH,
2510 sizeof(*cmd));
2511 if (!cmd_skb)
2512 return -ENOMEM;
2513
2514 if (params->radar_required)
2515 flags |= QLINK_CHAN_SW_RADAR_REQUIRED;
2516
2517 if (params->block_tx)
2518 flags |= QLINK_CHAN_SW_BLOCK_TX;
2519
2520 cmd = (struct qlink_cmd_chan_switch *)cmd_skb->data;
2521 qlink_chandef_cfg2q(¶ms->chandef, &cmd->channel);
2522 cmd->flags = cpu_to_le64(flags);
2523 cmd->beacon_count = params->count;
2524
2525 qtnf_bus_lock(mac->bus);
2526 ret = qtnf_cmd_send(mac->bus, cmd_skb);
2527 qtnf_bus_unlock(mac->bus);
2528
2529 return ret;
2530 }
2531
qtnf_cmd_get_channel(struct qtnf_vif * vif,struct cfg80211_chan_def * chdef)2532 int qtnf_cmd_get_channel(struct qtnf_vif *vif, struct cfg80211_chan_def *chdef)
2533 {
2534 struct qtnf_bus *bus = vif->mac->bus;
2535 const struct qlink_resp_channel_get *resp;
2536 struct sk_buff *cmd_skb;
2537 struct sk_buff *resp_skb = NULL;
2538 int ret;
2539
2540 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
2541 QLINK_CMD_CHAN_GET,
2542 sizeof(struct qlink_cmd));
2543 if (!cmd_skb)
2544 return -ENOMEM;
2545
2546 qtnf_bus_lock(bus);
2547 ret = qtnf_cmd_send_with_reply(bus, cmd_skb, &resp_skb,
2548 sizeof(*resp), NULL);
2549 if (ret)
2550 goto out;
2551
2552 resp = (const struct qlink_resp_channel_get *)resp_skb->data;
2553 qlink_chandef_q2cfg(priv_to_wiphy(vif->mac), &resp->chan, chdef);
2554
2555 out:
2556 qtnf_bus_unlock(bus);
2557 consume_skb(resp_skb);
2558
2559 return ret;
2560 }
2561
qtnf_cmd_start_cac(const struct qtnf_vif * vif,const struct cfg80211_chan_def * chdef,u32 cac_time_ms)2562 int qtnf_cmd_start_cac(const struct qtnf_vif *vif,
2563 const struct cfg80211_chan_def *chdef,
2564 u32 cac_time_ms)
2565 {
2566 struct qtnf_bus *bus = vif->mac->bus;
2567 struct sk_buff *cmd_skb;
2568 struct qlink_cmd_start_cac *cmd;
2569 int ret;
2570
2571 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
2572 QLINK_CMD_START_CAC,
2573 sizeof(*cmd));
2574 if (!cmd_skb)
2575 return -ENOMEM;
2576
2577 cmd = (struct qlink_cmd_start_cac *)cmd_skb->data;
2578 cmd->cac_time_ms = cpu_to_le32(cac_time_ms);
2579 qlink_chandef_cfg2q(chdef, &cmd->chan);
2580
2581 qtnf_bus_lock(bus);
2582 ret = qtnf_cmd_send(bus, cmd_skb);
2583 if (ret)
2584 goto out;
2585
2586 out:
2587 qtnf_bus_unlock(bus);
2588
2589 return ret;
2590 }
2591
qtnf_cmd_set_mac_acl(const struct qtnf_vif * vif,const struct cfg80211_acl_data * params)2592 int qtnf_cmd_set_mac_acl(const struct qtnf_vif *vif,
2593 const struct cfg80211_acl_data *params)
2594 {
2595 struct qtnf_bus *bus = vif->mac->bus;
2596 struct sk_buff *cmd_skb;
2597 struct qlink_tlv_hdr *tlv;
2598 size_t acl_size = struct_size(params, mac_addrs, params->n_acl_entries);
2599 int ret;
2600
2601 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
2602 QLINK_CMD_SET_MAC_ACL,
2603 sizeof(struct qlink_cmd));
2604 if (!cmd_skb)
2605 return -ENOMEM;
2606
2607 tlv = skb_put(cmd_skb, sizeof(*tlv) + round_up(acl_size, QLINK_ALIGN));
2608 tlv->type = cpu_to_le16(QTN_TLV_ID_ACL_DATA);
2609 tlv->len = cpu_to_le16(acl_size);
2610 qlink_acl_data_cfg2q(params, (struct qlink_acl_data *)tlv->val);
2611
2612 qtnf_bus_lock(bus);
2613 ret = qtnf_cmd_send(bus, cmd_skb);
2614 if (ret)
2615 goto out;
2616
2617 out:
2618 qtnf_bus_unlock(bus);
2619
2620 return ret;
2621 }
2622
qtnf_cmd_send_pm_set(const struct qtnf_vif * vif,u8 pm_mode,int timeout)2623 int qtnf_cmd_send_pm_set(const struct qtnf_vif *vif, u8 pm_mode, int timeout)
2624 {
2625 struct qtnf_bus *bus = vif->mac->bus;
2626 struct sk_buff *cmd_skb;
2627 struct qlink_cmd_pm_set *cmd;
2628 int ret = 0;
2629
2630 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
2631 QLINK_CMD_PM_SET, sizeof(*cmd));
2632 if (!cmd_skb)
2633 return -ENOMEM;
2634
2635 cmd = (struct qlink_cmd_pm_set *)cmd_skb->data;
2636 cmd->pm_mode = pm_mode;
2637 cmd->pm_standby_timer = cpu_to_le32(timeout);
2638
2639 qtnf_bus_lock(bus);
2640
2641 ret = qtnf_cmd_send(bus, cmd_skb);
2642 if (ret)
2643 goto out;
2644
2645 out:
2646 qtnf_bus_unlock(bus);
2647
2648 return ret;
2649 }
2650
qtnf_cmd_get_tx_power(const struct qtnf_vif * vif,int * dbm)2651 int qtnf_cmd_get_tx_power(const struct qtnf_vif *vif, int *dbm)
2652 {
2653 struct qtnf_bus *bus = vif->mac->bus;
2654 const struct qlink_resp_txpwr *resp;
2655 struct sk_buff *resp_skb = NULL;
2656 struct qlink_cmd_txpwr *cmd;
2657 struct sk_buff *cmd_skb;
2658 int ret = 0;
2659
2660 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
2661 QLINK_CMD_TXPWR, sizeof(*cmd));
2662 if (!cmd_skb)
2663 return -ENOMEM;
2664
2665 cmd = (struct qlink_cmd_txpwr *)cmd_skb->data;
2666 cmd->op_type = QLINK_TXPWR_GET;
2667
2668 qtnf_bus_lock(bus);
2669
2670 ret = qtnf_cmd_send_with_reply(bus, cmd_skb, &resp_skb,
2671 sizeof(*resp), NULL);
2672 if (ret)
2673 goto out;
2674
2675 resp = (const struct qlink_resp_txpwr *)resp_skb->data;
2676 *dbm = MBM_TO_DBM(le32_to_cpu(resp->txpwr));
2677
2678 out:
2679 qtnf_bus_unlock(bus);
2680 consume_skb(resp_skb);
2681
2682 return ret;
2683 }
2684
qtnf_cmd_set_tx_power(const struct qtnf_vif * vif,enum nl80211_tx_power_setting type,int mbm)2685 int qtnf_cmd_set_tx_power(const struct qtnf_vif *vif,
2686 enum nl80211_tx_power_setting type, int mbm)
2687 {
2688 struct qtnf_bus *bus = vif->mac->bus;
2689 const struct qlink_resp_txpwr *resp;
2690 struct sk_buff *resp_skb = NULL;
2691 struct qlink_cmd_txpwr *cmd;
2692 struct sk_buff *cmd_skb;
2693 int ret = 0;
2694
2695 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
2696 QLINK_CMD_TXPWR, sizeof(*cmd));
2697 if (!cmd_skb)
2698 return -ENOMEM;
2699
2700 cmd = (struct qlink_cmd_txpwr *)cmd_skb->data;
2701 cmd->op_type = QLINK_TXPWR_SET;
2702 cmd->txpwr_setting = type;
2703 cmd->txpwr = cpu_to_le32(mbm);
2704
2705 qtnf_bus_lock(bus);
2706
2707 ret = qtnf_cmd_send_with_reply(bus, cmd_skb, &resp_skb,
2708 sizeof(*resp), NULL);
2709
2710 qtnf_bus_unlock(bus);
2711 consume_skb(resp_skb);
2712
2713 return ret;
2714 }
2715
qtnf_cmd_send_wowlan_set(const struct qtnf_vif * vif,const struct cfg80211_wowlan * wowl)2716 int qtnf_cmd_send_wowlan_set(const struct qtnf_vif *vif,
2717 const struct cfg80211_wowlan *wowl)
2718 {
2719 struct qtnf_bus *bus = vif->mac->bus;
2720 struct sk_buff *cmd_skb;
2721 struct qlink_cmd_wowlan_set *cmd;
2722 u32 triggers = 0;
2723 int count = 0;
2724 int ret = 0;
2725
2726 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
2727 QLINK_CMD_WOWLAN_SET, sizeof(*cmd));
2728 if (!cmd_skb)
2729 return -ENOMEM;
2730
2731 qtnf_bus_lock(bus);
2732
2733 cmd = (struct qlink_cmd_wowlan_set *)cmd_skb->data;
2734
2735 if (wowl) {
2736 if (wowl->disconnect)
2737 triggers |= QLINK_WOWLAN_TRIG_DISCONNECT;
2738
2739 if (wowl->magic_pkt)
2740 triggers |= QLINK_WOWLAN_TRIG_MAGIC_PKT;
2741
2742 if (wowl->n_patterns && wowl->patterns) {
2743 triggers |= QLINK_WOWLAN_TRIG_PATTERN_PKT;
2744 while (count < wowl->n_patterns) {
2745 qtnf_cmd_skb_put_tlv_arr(cmd_skb,
2746 QTN_TLV_ID_WOWLAN_PATTERN,
2747 wowl->patterns[count].pattern,
2748 wowl->patterns[count].pattern_len);
2749 count++;
2750 }
2751 }
2752 }
2753
2754 cmd->triggers = cpu_to_le32(triggers);
2755
2756 ret = qtnf_cmd_send(bus, cmd_skb);
2757 if (ret)
2758 goto out;
2759
2760 out:
2761 qtnf_bus_unlock(bus);
2762 return ret;
2763 }
2764
qtnf_cmd_netdev_changeupper(const struct qtnf_vif * vif,int br_domain)2765 int qtnf_cmd_netdev_changeupper(const struct qtnf_vif *vif, int br_domain)
2766 {
2767 struct qtnf_bus *bus = vif->mac->bus;
2768 struct sk_buff *cmd_skb;
2769 struct qlink_cmd_ndev_changeupper *cmd;
2770 int ret;
2771
2772 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
2773 QLINK_CMD_NDEV_EVENT,
2774 sizeof(*cmd));
2775 if (!cmd_skb)
2776 return -ENOMEM;
2777
2778 pr_debug("[VIF%u.%u] set broadcast domain to %d\n",
2779 vif->mac->macid, vif->vifid, br_domain);
2780
2781 cmd = (struct qlink_cmd_ndev_changeupper *)cmd_skb->data;
2782 cmd->nehdr.event = cpu_to_le16(QLINK_NDEV_EVENT_CHANGEUPPER);
2783 cmd->upper_type = QLINK_NDEV_UPPER_TYPE_BRIDGE;
2784 cmd->br_domain = cpu_to_le32(br_domain);
2785
2786 qtnf_bus_lock(bus);
2787 ret = qtnf_cmd_send(bus, cmd_skb);
2788 qtnf_bus_unlock(bus);
2789
2790 if (ret)
2791 pr_err("[VIF%u.%u] failed to set broadcast domain\n",
2792 vif->mac->macid, vif->vifid);
2793
2794 return ret;
2795 }
2796
qtnf_cmd_send_update_owe(struct qtnf_vif * vif,struct cfg80211_update_owe_info * owe)2797 int qtnf_cmd_send_update_owe(struct qtnf_vif *vif,
2798 struct cfg80211_update_owe_info *owe)
2799 {
2800 struct qlink_cmd_update_owe *cmd;
2801 struct sk_buff *cmd_skb;
2802 int ret;
2803
2804 if (sizeof(*cmd) + owe->ie_len > QTNF_MAX_CMD_BUF_SIZE) {
2805 pr_warn("VIF%u.%u: OWE update IEs too big: %zu\n",
2806 vif->mac->macid, vif->vifid, owe->ie_len);
2807 return -E2BIG;
2808 }
2809
2810 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
2811 QLINK_CMD_UPDATE_OWE,
2812 sizeof(*cmd));
2813 if (!cmd_skb)
2814 return -ENOMEM;
2815
2816 cmd = (struct qlink_cmd_update_owe *)cmd_skb->data;
2817 ether_addr_copy(cmd->peer, owe->peer);
2818 cmd->status = cpu_to_le16(owe->status);
2819 if (owe->ie_len && owe->ie)
2820 qtnf_cmd_skb_put_buffer(cmd_skb, owe->ie, owe->ie_len);
2821
2822 qtnf_bus_lock(vif->mac->bus);
2823 ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
2824 if (ret)
2825 goto out;
2826
2827 out:
2828 qtnf_bus_unlock(vif->mac->bus);
2829
2830 return ret;
2831 }
2832