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