.. | .. |
---|
1 | | -/* |
---|
2 | | - * Copyright (c) 2015-2016 Quantenna Communications, Inc. |
---|
3 | | - * |
---|
4 | | - * This program is free software; you can redistribute it and/or |
---|
5 | | - * modify it under the terms of the GNU General Public License |
---|
6 | | - * as published by the Free Software Foundation; either version 2 |
---|
7 | | - * of the License, or (at your option) any later version. |
---|
8 | | - * |
---|
9 | | - * This program is distributed in the hope that it will be useful, |
---|
10 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
11 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
12 | | - * GNU General Public License for more details. |
---|
13 | | - * |
---|
14 | | - */ |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0+ |
---|
| 2 | +/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */ |
---|
15 | 3 | |
---|
16 | 4 | #include <linux/types.h> |
---|
17 | 5 | #include <linux/skbuff.h> |
---|
.. | .. |
---|
22 | 10 | #include "qlink_util.h" |
---|
23 | 11 | #include "bus.h" |
---|
24 | 12 | #include "commands.h" |
---|
| 13 | + |
---|
| 14 | +/* Let device itself to select best values for current conditions */ |
---|
| 15 | +#define QTNF_SCAN_TIME_AUTO 0 |
---|
| 16 | + |
---|
| 17 | +#define QTNF_SCAN_DWELL_ACTIVE_DEFAULT 90 |
---|
| 18 | +#define QTNF_SCAN_DWELL_PASSIVE_DEFAULT 100 |
---|
| 19 | +#define QTNF_SCAN_SAMPLE_DURATION_DEFAULT QTNF_SCAN_TIME_AUTO |
---|
25 | 20 | |
---|
26 | 21 | static int qtnf_cmd_check_reply_header(const struct qlink_resp *resp, |
---|
27 | 22 | u16 cmd_id, u8 mac_id, u8 vif_id, |
---|
.. | .. |
---|
72 | 67 | return -EADDRINUSE; |
---|
73 | 68 | case QLINK_CMD_RESULT_EADDRNOTAVAIL: |
---|
74 | 69 | return -EADDRNOTAVAIL; |
---|
| 70 | + case QLINK_CMD_RESULT_EBUSY: |
---|
| 71 | + return -EBUSY; |
---|
75 | 72 | default: |
---|
76 | 73 | return -EFAULT; |
---|
77 | 74 | } |
---|
.. | .. |
---|
80 | 77 | static int qtnf_cmd_send_with_reply(struct qtnf_bus *bus, |
---|
81 | 78 | struct sk_buff *cmd_skb, |
---|
82 | 79 | struct sk_buff **response_skb, |
---|
83 | | - u16 *result_code, |
---|
84 | 80 | size_t const_resp_size, |
---|
85 | 81 | size_t *var_resp_size) |
---|
86 | 82 | { |
---|
87 | 83 | struct qlink_cmd *cmd; |
---|
88 | | - const struct qlink_resp *resp; |
---|
| 84 | + struct qlink_resp *resp = NULL; |
---|
89 | 85 | struct sk_buff *resp_skb = NULL; |
---|
| 86 | + int resp_res = 0; |
---|
90 | 87 | u16 cmd_id; |
---|
91 | | - u8 mac_id, vif_id; |
---|
| 88 | + u8 mac_id; |
---|
| 89 | + u8 vif_id; |
---|
92 | 90 | int ret; |
---|
93 | 91 | |
---|
94 | 92 | cmd = (struct qlink_cmd *)cmd_skb->data; |
---|
.. | .. |
---|
97 | 95 | vif_id = cmd->vifid; |
---|
98 | 96 | cmd->mhdr.len = cpu_to_le16(cmd_skb->len); |
---|
99 | 97 | |
---|
100 | | - if (unlikely(bus->fw_state != QTNF_FW_STATE_ACTIVE && |
---|
101 | | - le16_to_cpu(cmd->cmd_id) != QLINK_CMD_FW_INIT)) { |
---|
| 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) { |
---|
102 | 101 | pr_warn("VIF%u.%u: drop cmd 0x%.4X in fw state %d\n", |
---|
103 | | - mac_id, vif_id, le16_to_cpu(cmd->cmd_id), |
---|
104 | | - bus->fw_state); |
---|
| 102 | + mac_id, vif_id, cmd_id, bus->fw_state); |
---|
105 | 103 | dev_kfree_skb(cmd_skb); |
---|
106 | 104 | return -ENODEV; |
---|
107 | 105 | } |
---|
108 | 106 | |
---|
109 | | - pr_debug("VIF%u.%u cmd=0x%.4X\n", mac_id, vif_id, |
---|
110 | | - le16_to_cpu(cmd->cmd_id)); |
---|
111 | | - |
---|
112 | 107 | ret = qtnf_trans_send_cmd_with_resp(bus, cmd_skb, &resp_skb); |
---|
113 | | - |
---|
114 | | - if (unlikely(ret)) |
---|
| 108 | + if (ret) |
---|
115 | 109 | goto out; |
---|
116 | 110 | |
---|
117 | | - resp = (const struct qlink_resp *)resp_skb->data; |
---|
| 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 | 118 | ret = qtnf_cmd_check_reply_header(resp, cmd_id, mac_id, vif_id, |
---|
119 | 119 | const_resp_size); |
---|
120 | | - |
---|
121 | | - if (unlikely(ret)) |
---|
| 120 | + if (ret) |
---|
122 | 121 | goto out; |
---|
123 | | - |
---|
124 | | - if (likely(result_code)) |
---|
125 | | - *result_code = le16_to_cpu(resp->result); |
---|
126 | 122 | |
---|
127 | 123 | /* Return length of variable part of response */ |
---|
128 | 124 | if (response_skb && var_resp_size) |
---|
.. | .. |
---|
134 | 130 | else |
---|
135 | 131 | consume_skb(resp_skb); |
---|
136 | 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 | + |
---|
137 | 139 | return ret; |
---|
138 | 140 | } |
---|
139 | 141 | |
---|
140 | | -static inline int qtnf_cmd_send(struct qtnf_bus *bus, |
---|
141 | | - struct sk_buff *cmd_skb, |
---|
142 | | - u16 *result_code) |
---|
| 142 | +static inline int qtnf_cmd_send(struct qtnf_bus *bus, struct sk_buff *cmd_skb) |
---|
143 | 143 | { |
---|
144 | | - return qtnf_cmd_send_with_reply(bus, cmd_skb, NULL, result_code, |
---|
| 144 | + return qtnf_cmd_send_with_reply(bus, cmd_skb, NULL, |
---|
145 | 145 | sizeof(struct qlink_resp), NULL); |
---|
146 | 146 | } |
---|
147 | 147 | |
---|
.. | .. |
---|
175 | 175 | { |
---|
176 | 176 | struct qlink_tlv_ie_set *tlv; |
---|
177 | 177 | |
---|
178 | | - tlv = (struct qlink_tlv_ie_set *)skb_put(cmd_skb, sizeof(*tlv) + len); |
---|
| 178 | + tlv = (struct qlink_tlv_ie_set *)skb_put(cmd_skb, sizeof(*tlv) + |
---|
| 179 | + round_up(len, QLINK_ALIGN)); |
---|
179 | 180 | tlv->hdr.type = cpu_to_le16(QTN_TLV_ID_IE_SET); |
---|
180 | 181 | tlv->hdr.len = cpu_to_le16(len + sizeof(*tlv) - sizeof(tlv->hdr)); |
---|
181 | 182 | tlv->type = frame_type; |
---|
.. | .. |
---|
185 | 186 | memcpy(tlv->ie_data, buf, len); |
---|
186 | 187 | } |
---|
187 | 188 | |
---|
188 | | -static inline size_t qtnf_cmd_acl_data_size(const struct cfg80211_acl_data *acl) |
---|
189 | | -{ |
---|
190 | | - size_t size = sizeof(struct qlink_acl_data) + |
---|
191 | | - acl->n_acl_entries * sizeof(struct qlink_mac_address); |
---|
192 | | - |
---|
193 | | - return size; |
---|
194 | | -} |
---|
195 | | - |
---|
196 | 189 | static bool qtnf_cmd_start_ap_can_fit(const struct qtnf_vif *vif, |
---|
197 | 190 | const struct cfg80211_ap_settings *s) |
---|
198 | 191 | { |
---|
199 | 192 | unsigned int len = sizeof(struct qlink_cmd_start_ap); |
---|
200 | 193 | |
---|
201 | | - len += s->ssid_len; |
---|
202 | | - len += s->beacon.head_len; |
---|
203 | | - len += s->beacon.tail_len; |
---|
204 | | - len += s->beacon.beacon_ies_len; |
---|
205 | | - len += s->beacon.proberesp_ies_len; |
---|
206 | | - len += s->beacon.assocresp_ies_len; |
---|
207 | | - len += s->beacon.probe_resp_len; |
---|
| 194 | + len += round_up(s->ssid_len, QLINK_ALIGN); |
---|
| 195 | + len += round_up(s->beacon.head_len, QLINK_ALIGN); |
---|
| 196 | + len += round_up(s->beacon.tail_len, QLINK_ALIGN); |
---|
| 197 | + len += round_up(s->beacon.beacon_ies_len, QLINK_ALIGN); |
---|
| 198 | + len += round_up(s->beacon.proberesp_ies_len, QLINK_ALIGN); |
---|
| 199 | + len += round_up(s->beacon.assocresp_ies_len, QLINK_ALIGN); |
---|
| 200 | + len += round_up(s->beacon.probe_resp_len, QLINK_ALIGN); |
---|
208 | 201 | |
---|
209 | 202 | if (cfg80211_chandef_valid(&s->chandef)) |
---|
210 | 203 | len += sizeof(struct qlink_tlv_chandef); |
---|
211 | 204 | |
---|
212 | | - if (s->acl) |
---|
| 205 | + if (s->acl) { |
---|
| 206 | + unsigned int acl_len = struct_size(s->acl, mac_addrs, |
---|
| 207 | + s->acl->n_acl_entries); |
---|
| 208 | + |
---|
213 | 209 | len += sizeof(struct qlink_tlv_hdr) + |
---|
214 | | - qtnf_cmd_acl_data_size(s->acl); |
---|
| 210 | + round_up(acl_len, QLINK_ALIGN); |
---|
| 211 | + } |
---|
215 | 212 | |
---|
216 | 213 | if (len > (sizeof(struct qlink_cmd) + QTNF_MAX_CMD_BUF_SIZE)) { |
---|
217 | 214 | pr_err("VIF%u.%u: can not fit AP settings: %u\n", |
---|
.. | .. |
---|
222 | 219 | return true; |
---|
223 | 220 | } |
---|
224 | 221 | |
---|
| 222 | +static void qtnf_cmd_tlv_ie_ext_add(struct sk_buff *cmd_skb, u8 eid_ext, |
---|
| 223 | + const void *buf, size_t len) |
---|
| 224 | +{ |
---|
| 225 | + struct qlink_tlv_ext_ie *tlv; |
---|
| 226 | + |
---|
| 227 | + tlv = (struct qlink_tlv_ext_ie *)skb_put(cmd_skb, sizeof(*tlv) + len); |
---|
| 228 | + tlv->hdr.type = cpu_to_le16(WLAN_EID_EXTENSION); |
---|
| 229 | + tlv->hdr.len = cpu_to_le16(sizeof(*tlv) + len - sizeof(tlv->hdr)); |
---|
| 230 | + tlv->eid_ext = eid_ext; |
---|
| 231 | + |
---|
| 232 | + if (len && buf) |
---|
| 233 | + memcpy(tlv->ie_data, buf, len); |
---|
| 234 | +} |
---|
| 235 | + |
---|
225 | 236 | int qtnf_cmd_send_start_ap(struct qtnf_vif *vif, |
---|
226 | 237 | const struct cfg80211_ap_settings *s) |
---|
227 | 238 | { |
---|
228 | 239 | struct sk_buff *cmd_skb; |
---|
229 | 240 | struct qlink_cmd_start_ap *cmd; |
---|
230 | 241 | struct qlink_auth_encr *aen; |
---|
231 | | - u16 res_code = QLINK_CMD_RESULT_OK; |
---|
232 | 242 | int ret; |
---|
233 | 243 | int i; |
---|
234 | 244 | |
---|
.. | .. |
---|
252 | 262 | cmd->pbss = s->pbss; |
---|
253 | 263 | cmd->ht_required = s->ht_required; |
---|
254 | 264 | cmd->vht_required = s->vht_required; |
---|
| 265 | + cmd->twt_responder = s->twt_responder; |
---|
| 266 | + if (s->he_obss_pd.enable) { |
---|
| 267 | + cmd->sr_params.sr_control |= QLINK_SR_SRG_INFORMATION_PRESENT; |
---|
| 268 | + cmd->sr_params.srg_obss_pd_min_offset = |
---|
| 269 | + s->he_obss_pd.min_offset; |
---|
| 270 | + cmd->sr_params.srg_obss_pd_max_offset = |
---|
| 271 | + s->he_obss_pd.max_offset; |
---|
| 272 | + } |
---|
255 | 273 | |
---|
256 | 274 | aen = &cmd->aen; |
---|
257 | 275 | aen->auth_type = s->auth_type; |
---|
.. | .. |
---|
302 | 320 | |
---|
303 | 321 | if (s->ht_cap) { |
---|
304 | 322 | struct qlink_tlv_hdr *tlv = (struct qlink_tlv_hdr *) |
---|
305 | | - skb_put(cmd_skb, sizeof(*tlv) + sizeof(*s->ht_cap)); |
---|
| 323 | + skb_put(cmd_skb, sizeof(*tlv) + |
---|
| 324 | + round_up(sizeof(*s->ht_cap), QLINK_ALIGN)); |
---|
306 | 325 | |
---|
307 | 326 | tlv->type = cpu_to_le16(WLAN_EID_HT_CAPABILITY); |
---|
308 | 327 | tlv->len = cpu_to_le16(sizeof(*s->ht_cap)); |
---|
.. | .. |
---|
318 | 337 | memcpy(tlv->val, s->vht_cap, sizeof(*s->vht_cap)); |
---|
319 | 338 | } |
---|
320 | 339 | |
---|
| 340 | + if (s->he_cap) |
---|
| 341 | + qtnf_cmd_tlv_ie_ext_add(cmd_skb, WLAN_EID_EXT_HE_CAPABILITY, |
---|
| 342 | + s->he_cap, sizeof(*s->he_cap)); |
---|
| 343 | + |
---|
321 | 344 | if (s->acl) { |
---|
322 | | - size_t acl_size = qtnf_cmd_acl_data_size(s->acl); |
---|
| 345 | + size_t acl_size = struct_size(s->acl, mac_addrs, |
---|
| 346 | + s->acl->n_acl_entries); |
---|
323 | 347 | struct qlink_tlv_hdr *tlv = |
---|
324 | | - skb_put(cmd_skb, sizeof(*tlv) + acl_size); |
---|
| 348 | + skb_put(cmd_skb, |
---|
| 349 | + sizeof(*tlv) + round_up(acl_size, QLINK_ALIGN)); |
---|
325 | 350 | |
---|
326 | 351 | tlv->type = cpu_to_le16(QTN_TLV_ID_ACL_DATA); |
---|
327 | 352 | tlv->len = cpu_to_le16(acl_size); |
---|
.. | .. |
---|
329 | 354 | } |
---|
330 | 355 | |
---|
331 | 356 | qtnf_bus_lock(vif->mac->bus); |
---|
332 | | - |
---|
333 | | - ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code); |
---|
334 | | - |
---|
335 | | - if (unlikely(ret)) |
---|
| 357 | + ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); |
---|
| 358 | + if (ret) |
---|
336 | 359 | goto out; |
---|
337 | | - |
---|
338 | | - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { |
---|
339 | | - pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid, |
---|
340 | | - vif->vifid, res_code); |
---|
341 | | - ret = -EFAULT; |
---|
342 | | - goto out; |
---|
343 | | - } |
---|
344 | 360 | |
---|
345 | 361 | netif_carrier_on(vif->netdev); |
---|
346 | 362 | |
---|
347 | 363 | out: |
---|
348 | 364 | qtnf_bus_unlock(vif->mac->bus); |
---|
| 365 | + |
---|
349 | 366 | return ret; |
---|
350 | 367 | } |
---|
351 | 368 | |
---|
352 | 369 | int qtnf_cmd_send_stop_ap(struct qtnf_vif *vif) |
---|
353 | 370 | { |
---|
354 | 371 | struct sk_buff *cmd_skb; |
---|
355 | | - u16 res_code = QLINK_CMD_RESULT_OK; |
---|
356 | 372 | int ret; |
---|
357 | 373 | |
---|
358 | 374 | cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, |
---|
.. | .. |
---|
362 | 378 | return -ENOMEM; |
---|
363 | 379 | |
---|
364 | 380 | qtnf_bus_lock(vif->mac->bus); |
---|
365 | | - |
---|
366 | | - ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code); |
---|
367 | | - |
---|
368 | | - if (unlikely(ret)) |
---|
| 381 | + ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); |
---|
| 382 | + if (ret) |
---|
369 | 383 | goto out; |
---|
370 | | - |
---|
371 | | - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { |
---|
372 | | - pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid, |
---|
373 | | - vif->vifid, res_code); |
---|
374 | | - ret = -EFAULT; |
---|
375 | | - goto out; |
---|
376 | | - } |
---|
377 | | - |
---|
378 | | - netif_carrier_off(vif->netdev); |
---|
379 | 384 | |
---|
380 | 385 | out: |
---|
381 | 386 | qtnf_bus_unlock(vif->mac->bus); |
---|
| 387 | + |
---|
382 | 388 | return ret; |
---|
383 | 389 | } |
---|
384 | 390 | |
---|
.. | .. |
---|
386 | 392 | { |
---|
387 | 393 | struct sk_buff *cmd_skb; |
---|
388 | 394 | struct qlink_cmd_mgmt_frame_register *cmd; |
---|
389 | | - u16 res_code = QLINK_CMD_RESULT_OK; |
---|
390 | 395 | int ret; |
---|
391 | 396 | |
---|
392 | 397 | cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, |
---|
.. | .. |
---|
401 | 406 | cmd->frame_type = cpu_to_le16(frame_type); |
---|
402 | 407 | cmd->do_register = reg; |
---|
403 | 408 | |
---|
404 | | - ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code); |
---|
405 | | - |
---|
406 | | - if (unlikely(ret)) |
---|
| 409 | + ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); |
---|
| 410 | + if (ret) |
---|
407 | 411 | goto out; |
---|
408 | | - |
---|
409 | | - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { |
---|
410 | | - pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid, |
---|
411 | | - vif->vifid, res_code); |
---|
412 | | - ret = -EFAULT; |
---|
413 | | - goto out; |
---|
414 | | - } |
---|
415 | 412 | |
---|
416 | 413 | out: |
---|
417 | 414 | qtnf_bus_unlock(vif->mac->bus); |
---|
| 415 | + |
---|
418 | 416 | return ret; |
---|
419 | 417 | } |
---|
420 | 418 | |
---|
421 | | -int qtnf_cmd_send_mgmt_frame(struct qtnf_vif *vif, u32 cookie, u16 flags, |
---|
422 | | - u16 freq, const u8 *buf, size_t len) |
---|
| 419 | +int qtnf_cmd_send_frame(struct qtnf_vif *vif, u32 cookie, u16 flags, |
---|
| 420 | + u16 freq, const u8 *buf, size_t len) |
---|
423 | 421 | { |
---|
424 | 422 | struct sk_buff *cmd_skb; |
---|
425 | | - struct qlink_cmd_mgmt_frame_tx *cmd; |
---|
426 | | - u16 res_code = QLINK_CMD_RESULT_OK; |
---|
| 423 | + struct qlink_cmd_frame_tx *cmd; |
---|
427 | 424 | int ret; |
---|
428 | 425 | |
---|
429 | 426 | if (sizeof(*cmd) + len > QTNF_MAX_CMD_BUF_SIZE) { |
---|
.. | .. |
---|
433 | 430 | } |
---|
434 | 431 | |
---|
435 | 432 | cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, |
---|
436 | | - QLINK_CMD_SEND_MGMT_FRAME, |
---|
| 433 | + QLINK_CMD_SEND_FRAME, |
---|
437 | 434 | sizeof(*cmd)); |
---|
438 | 435 | if (!cmd_skb) |
---|
439 | 436 | return -ENOMEM; |
---|
440 | 437 | |
---|
441 | 438 | qtnf_bus_lock(vif->mac->bus); |
---|
442 | 439 | |
---|
443 | | - cmd = (struct qlink_cmd_mgmt_frame_tx *)cmd_skb->data; |
---|
| 440 | + cmd = (struct qlink_cmd_frame_tx *)cmd_skb->data; |
---|
444 | 441 | cmd->cookie = cpu_to_le32(cookie); |
---|
445 | 442 | cmd->freq = cpu_to_le16(freq); |
---|
446 | 443 | cmd->flags = cpu_to_le16(flags); |
---|
.. | .. |
---|
448 | 445 | if (len && buf) |
---|
449 | 446 | qtnf_cmd_skb_put_buffer(cmd_skb, buf, len); |
---|
450 | 447 | |
---|
451 | | - ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code); |
---|
452 | | - |
---|
453 | | - if (unlikely(ret)) |
---|
| 448 | + ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); |
---|
| 449 | + if (ret) |
---|
454 | 450 | goto out; |
---|
455 | | - |
---|
456 | | - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { |
---|
457 | | - pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid, |
---|
458 | | - vif->vifid, res_code); |
---|
459 | | - ret = -EFAULT; |
---|
460 | | - goto out; |
---|
461 | | - } |
---|
462 | 451 | |
---|
463 | 452 | out: |
---|
464 | 453 | qtnf_bus_unlock(vif->mac->bus); |
---|
| 454 | + |
---|
465 | 455 | return ret; |
---|
466 | 456 | } |
---|
467 | 457 | |
---|
.. | .. |
---|
469 | 459 | const u8 *buf, size_t len) |
---|
470 | 460 | { |
---|
471 | 461 | struct sk_buff *cmd_skb; |
---|
472 | | - u16 res_code = QLINK_CMD_RESULT_OK; |
---|
473 | 462 | int ret; |
---|
474 | 463 | |
---|
475 | 464 | if (len > QTNF_MAX_CMD_BUF_SIZE) { |
---|
.. | .. |
---|
487 | 476 | qtnf_cmd_tlv_ie_set_add(cmd_skb, frame_type, buf, len); |
---|
488 | 477 | |
---|
489 | 478 | qtnf_bus_lock(vif->mac->bus); |
---|
490 | | - |
---|
491 | | - ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code); |
---|
492 | | - |
---|
493 | | - if (unlikely(ret)) |
---|
| 479 | + ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); |
---|
| 480 | + if (ret) |
---|
494 | 481 | goto out; |
---|
495 | | - |
---|
496 | | - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { |
---|
497 | | - pr_err("VIF%u.%u frame %u: CMD failed: %u\n", vif->mac->macid, |
---|
498 | | - vif->vifid, frame_type, res_code); |
---|
499 | | - ret = -EFAULT; |
---|
500 | | - goto out; |
---|
501 | | - } |
---|
502 | 482 | |
---|
503 | 483 | out: |
---|
504 | 484 | qtnf_bus_unlock(vif->mac->bus); |
---|
| 485 | + |
---|
505 | 486 | return ret; |
---|
506 | 487 | } |
---|
507 | 488 | |
---|
.. | .. |
---|
544 | 525 | rate_dst->flags |= RATE_INFO_FLAGS_MCS; |
---|
545 | 526 | else if (rate_src->flags & QLINK_STA_INFO_RATE_FLAG_VHT_MCS) |
---|
546 | 527 | rate_dst->flags |= RATE_INFO_FLAGS_VHT_MCS; |
---|
| 528 | + else if (rate_src->flags & QLINK_STA_INFO_RATE_FLAG_HE_MCS) |
---|
| 529 | + rate_dst->flags |= RATE_INFO_FLAGS_HE_MCS; |
---|
547 | 530 | |
---|
548 | 531 | if (rate_src->flags & QLINK_STA_INFO_RATE_FLAG_SHORT_GI) |
---|
549 | 532 | rate_dst->flags |= RATE_INFO_FLAGS_SHORT_GI; |
---|
.. | .. |
---|
605 | 588 | } |
---|
606 | 589 | |
---|
607 | 590 | static void |
---|
608 | | -qtnf_cmd_sta_info_parse(struct station_info *sinfo, |
---|
609 | | - const struct qlink_tlv_hdr *tlv, |
---|
| 591 | +qtnf_cmd_sta_info_parse(struct station_info *sinfo, const u8 *data, |
---|
610 | 592 | size_t resp_size) |
---|
611 | 593 | { |
---|
| 594 | + const struct qlink_tlv_hdr *tlv; |
---|
612 | 595 | const struct qlink_sta_stats *stats = NULL; |
---|
613 | 596 | const u8 *map = NULL; |
---|
614 | 597 | unsigned int map_len = 0; |
---|
.. | .. |
---|
619 | 602 | (qtnf_utils_is_bit_set(map, bitn, map_len) && \ |
---|
620 | 603 | (offsetofend(struct qlink_sta_stats, stat_name) <= stats_len)) |
---|
621 | 604 | |
---|
622 | | - while (resp_size >= sizeof(*tlv)) { |
---|
| 605 | + qlink_for_each_tlv(tlv, data, resp_size) { |
---|
623 | 606 | tlv_len = le16_to_cpu(tlv->len); |
---|
624 | 607 | |
---|
625 | 608 | switch (le16_to_cpu(tlv->type)) { |
---|
626 | | - case QTN_TLV_ID_STA_STATS_MAP: |
---|
| 609 | + case QTN_TLV_ID_BITMAP: |
---|
627 | 610 | map_len = tlv_len; |
---|
628 | 611 | map = tlv->val; |
---|
629 | 612 | break; |
---|
.. | .. |
---|
634 | 617 | default: |
---|
635 | 618 | break; |
---|
636 | 619 | } |
---|
| 620 | + } |
---|
637 | 621 | |
---|
638 | | - resp_size -= tlv_len + sizeof(*tlv); |
---|
639 | | - tlv = (const struct qlink_tlv_hdr *)(tlv->val + tlv_len); |
---|
| 622 | + if (!qlink_tlv_parsing_ok(tlv, data, resp_size)) { |
---|
| 623 | + pr_err("Malformed TLV buffer\n"); |
---|
| 624 | + return; |
---|
640 | 625 | } |
---|
641 | 626 | |
---|
642 | 627 | if (!map || !stats) |
---|
.. | .. |
---|
732 | 717 | struct sk_buff *cmd_skb, *resp_skb = NULL; |
---|
733 | 718 | struct qlink_cmd_get_sta_info *cmd; |
---|
734 | 719 | const struct qlink_resp_get_sta_info *resp; |
---|
735 | | - size_t var_resp_len; |
---|
736 | | - u16 res_code = QLINK_CMD_RESULT_OK; |
---|
| 720 | + size_t var_resp_len = 0; |
---|
737 | 721 | int ret = 0; |
---|
738 | 722 | |
---|
739 | 723 | cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, |
---|
.. | .. |
---|
748 | 732 | ether_addr_copy(cmd->sta_addr, sta_mac); |
---|
749 | 733 | |
---|
750 | 734 | ret = qtnf_cmd_send_with_reply(vif->mac->bus, cmd_skb, &resp_skb, |
---|
751 | | - &res_code, sizeof(*resp), |
---|
752 | | - &var_resp_len); |
---|
753 | | - |
---|
754 | | - if (unlikely(ret)) |
---|
| 735 | + sizeof(*resp), &var_resp_len); |
---|
| 736 | + if (ret) |
---|
755 | 737 | goto out; |
---|
756 | | - |
---|
757 | | - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { |
---|
758 | | - switch (res_code) { |
---|
759 | | - case QLINK_CMD_RESULT_ENOTFOUND: |
---|
760 | | - pr_warn("VIF%u.%u: %pM STA not found\n", |
---|
761 | | - vif->mac->macid, vif->vifid, sta_mac); |
---|
762 | | - ret = -ENOENT; |
---|
763 | | - break; |
---|
764 | | - default: |
---|
765 | | - pr_err("VIF%u.%u: can't get info for %pM: %u\n", |
---|
766 | | - vif->mac->macid, vif->vifid, sta_mac, res_code); |
---|
767 | | - ret = -EFAULT; |
---|
768 | | - break; |
---|
769 | | - } |
---|
770 | | - goto out; |
---|
771 | | - } |
---|
772 | 738 | |
---|
773 | 739 | resp = (const struct qlink_resp_get_sta_info *)resp_skb->data; |
---|
774 | 740 | |
---|
775 | | - if (unlikely(!ether_addr_equal(sta_mac, resp->sta_addr))) { |
---|
| 741 | + if (!ether_addr_equal(sta_mac, resp->sta_addr)) { |
---|
776 | 742 | pr_err("VIF%u.%u: wrong mac in reply: %pM != %pM\n", |
---|
777 | 743 | vif->mac->macid, vif->vifid, resp->sta_addr, sta_mac); |
---|
778 | 744 | ret = -EINVAL; |
---|
779 | 745 | goto out; |
---|
780 | 746 | } |
---|
781 | 747 | |
---|
782 | | - qtnf_cmd_sta_info_parse(sinfo, |
---|
783 | | - (const struct qlink_tlv_hdr *)resp->info, |
---|
784 | | - var_resp_len); |
---|
| 748 | + qtnf_cmd_sta_info_parse(sinfo, resp->info, var_resp_len); |
---|
785 | 749 | |
---|
786 | 750 | out: |
---|
787 | 751 | qtnf_bus_unlock(vif->mac->bus); |
---|
.. | .. |
---|
792 | 756 | |
---|
793 | 757 | static int qtnf_cmd_send_add_change_intf(struct qtnf_vif *vif, |
---|
794 | 758 | enum nl80211_iftype iftype, |
---|
| 759 | + int use4addr, |
---|
795 | 760 | u8 *mac_addr, |
---|
796 | 761 | enum qlink_cmd_type cmd_type) |
---|
797 | 762 | { |
---|
798 | 763 | struct sk_buff *cmd_skb, *resp_skb = NULL; |
---|
799 | 764 | struct qlink_cmd_manage_intf *cmd; |
---|
800 | 765 | const struct qlink_resp_manage_intf *resp; |
---|
801 | | - u16 res_code = QLINK_CMD_RESULT_OK; |
---|
802 | 766 | int ret = 0; |
---|
803 | 767 | |
---|
804 | 768 | cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, |
---|
.. | .. |
---|
810 | 774 | qtnf_bus_lock(vif->mac->bus); |
---|
811 | 775 | |
---|
812 | 776 | cmd = (struct qlink_cmd_manage_intf *)cmd_skb->data; |
---|
| 777 | + cmd->intf_info.use4addr = use4addr; |
---|
813 | 778 | |
---|
814 | 779 | switch (iftype) { |
---|
815 | 780 | case NL80211_IFTYPE_AP: |
---|
.. | .. |
---|
831 | 796 | eth_zero_addr(cmd->intf_info.mac_addr); |
---|
832 | 797 | |
---|
833 | 798 | ret = qtnf_cmd_send_with_reply(vif->mac->bus, cmd_skb, &resp_skb, |
---|
834 | | - &res_code, sizeof(*resp), NULL); |
---|
835 | | - |
---|
836 | | - if (unlikely(ret)) |
---|
| 799 | + sizeof(*resp), NULL); |
---|
| 800 | + if (ret) |
---|
837 | 801 | goto out; |
---|
838 | | - |
---|
839 | | - ret = qtnf_cmd_resp_result_decode(res_code); |
---|
840 | | - if (ret) { |
---|
841 | | - pr_err("VIF%u.%u: CMD %d failed: %u\n", vif->mac->macid, |
---|
842 | | - vif->vifid, cmd_type, res_code); |
---|
843 | | - goto out; |
---|
844 | | - } |
---|
845 | 802 | |
---|
846 | 803 | resp = (const struct qlink_resp_manage_intf *)resp_skb->data; |
---|
847 | 804 | ether_addr_copy(vif->mac_addr, resp->intf_info.mac_addr); |
---|
.. | .. |
---|
853 | 810 | return ret; |
---|
854 | 811 | } |
---|
855 | 812 | |
---|
856 | | -int qtnf_cmd_send_add_intf(struct qtnf_vif *vif, |
---|
857 | | - enum nl80211_iftype iftype, u8 *mac_addr) |
---|
| 813 | +int qtnf_cmd_send_add_intf(struct qtnf_vif *vif, enum nl80211_iftype iftype, |
---|
| 814 | + int use4addr, u8 *mac_addr) |
---|
858 | 815 | { |
---|
859 | | - return qtnf_cmd_send_add_change_intf(vif, iftype, mac_addr, |
---|
| 816 | + return qtnf_cmd_send_add_change_intf(vif, iftype, use4addr, mac_addr, |
---|
860 | 817 | QLINK_CMD_ADD_INTF); |
---|
861 | 818 | } |
---|
862 | 819 | |
---|
863 | 820 | int qtnf_cmd_send_change_intf_type(struct qtnf_vif *vif, |
---|
864 | | - enum nl80211_iftype iftype, u8 *mac_addr) |
---|
| 821 | + enum nl80211_iftype iftype, |
---|
| 822 | + int use4addr, |
---|
| 823 | + u8 *mac_addr) |
---|
865 | 824 | { |
---|
866 | | - return qtnf_cmd_send_add_change_intf(vif, iftype, mac_addr, |
---|
867 | | - QLINK_CMD_CHANGE_INTF); |
---|
| 825 | + int ret; |
---|
| 826 | + |
---|
| 827 | + ret = qtnf_cmd_send_add_change_intf(vif, iftype, use4addr, mac_addr, |
---|
| 828 | + QLINK_CMD_CHANGE_INTF); |
---|
| 829 | + |
---|
| 830 | + /* Regulatory settings may be different for different interface types */ |
---|
| 831 | + if (ret == 0 && vif->wdev.iftype != iftype) { |
---|
| 832 | + enum nl80211_band band; |
---|
| 833 | + struct wiphy *wiphy = priv_to_wiphy(vif->mac); |
---|
| 834 | + |
---|
| 835 | + for (band = 0; band < NUM_NL80211_BANDS; ++band) { |
---|
| 836 | + if (!wiphy->bands[band]) |
---|
| 837 | + continue; |
---|
| 838 | + |
---|
| 839 | + qtnf_cmd_band_info_get(vif->mac, wiphy->bands[band]); |
---|
| 840 | + } |
---|
| 841 | + } |
---|
| 842 | + |
---|
| 843 | + return ret; |
---|
868 | 844 | } |
---|
869 | 845 | |
---|
870 | 846 | int qtnf_cmd_send_del_intf(struct qtnf_vif *vif) |
---|
871 | 847 | { |
---|
872 | 848 | struct sk_buff *cmd_skb; |
---|
873 | 849 | struct qlink_cmd_manage_intf *cmd; |
---|
874 | | - u16 res_code = QLINK_CMD_RESULT_OK; |
---|
875 | 850 | int ret = 0; |
---|
876 | 851 | |
---|
877 | 852 | cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, |
---|
.. | .. |
---|
901 | 876 | |
---|
902 | 877 | eth_zero_addr(cmd->intf_info.mac_addr); |
---|
903 | 878 | |
---|
904 | | - ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code); |
---|
905 | | - |
---|
906 | | - if (unlikely(ret)) |
---|
| 879 | + ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); |
---|
| 880 | + if (ret) |
---|
907 | 881 | goto out; |
---|
908 | | - |
---|
909 | | - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { |
---|
910 | | - pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid, |
---|
911 | | - vif->vifid, res_code); |
---|
912 | | - ret = -EFAULT; |
---|
913 | | - goto out; |
---|
914 | | - } |
---|
915 | 882 | |
---|
916 | 883 | out: |
---|
917 | 884 | qtnf_bus_unlock(vif->mac->bus); |
---|
918 | 885 | return ret; |
---|
919 | | -} |
---|
920 | | - |
---|
921 | | -static u32 qtnf_cmd_resp_reg_rule_flags_parse(u32 qflags) |
---|
922 | | -{ |
---|
923 | | - u32 flags = 0; |
---|
924 | | - |
---|
925 | | - if (qflags & QLINK_RRF_NO_OFDM) |
---|
926 | | - flags |= NL80211_RRF_NO_OFDM; |
---|
927 | | - |
---|
928 | | - if (qflags & QLINK_RRF_NO_CCK) |
---|
929 | | - flags |= NL80211_RRF_NO_CCK; |
---|
930 | | - |
---|
931 | | - if (qflags & QLINK_RRF_NO_INDOOR) |
---|
932 | | - flags |= NL80211_RRF_NO_INDOOR; |
---|
933 | | - |
---|
934 | | - if (qflags & QLINK_RRF_NO_OUTDOOR) |
---|
935 | | - flags |= NL80211_RRF_NO_OUTDOOR; |
---|
936 | | - |
---|
937 | | - if (qflags & QLINK_RRF_DFS) |
---|
938 | | - flags |= NL80211_RRF_DFS; |
---|
939 | | - |
---|
940 | | - if (qflags & QLINK_RRF_PTP_ONLY) |
---|
941 | | - flags |= NL80211_RRF_PTP_ONLY; |
---|
942 | | - |
---|
943 | | - if (qflags & QLINK_RRF_PTMP_ONLY) |
---|
944 | | - flags |= NL80211_RRF_PTMP_ONLY; |
---|
945 | | - |
---|
946 | | - if (qflags & QLINK_RRF_NO_IR) |
---|
947 | | - flags |= NL80211_RRF_NO_IR; |
---|
948 | | - |
---|
949 | | - if (qflags & QLINK_RRF_AUTO_BW) |
---|
950 | | - flags |= NL80211_RRF_AUTO_BW; |
---|
951 | | - |
---|
952 | | - if (qflags & QLINK_RRF_IR_CONCURRENT) |
---|
953 | | - flags |= NL80211_RRF_IR_CONCURRENT; |
---|
954 | | - |
---|
955 | | - if (qflags & QLINK_RRF_NO_HT40MINUS) |
---|
956 | | - flags |= NL80211_RRF_NO_HT40MINUS; |
---|
957 | | - |
---|
958 | | - if (qflags & QLINK_RRF_NO_HT40PLUS) |
---|
959 | | - flags |= NL80211_RRF_NO_HT40PLUS; |
---|
960 | | - |
---|
961 | | - if (qflags & QLINK_RRF_NO_80MHZ) |
---|
962 | | - flags |= NL80211_RRF_NO_80MHZ; |
---|
963 | | - |
---|
964 | | - if (qflags & QLINK_RRF_NO_160MHZ) |
---|
965 | | - flags |= NL80211_RRF_NO_160MHZ; |
---|
966 | | - |
---|
967 | | - return flags; |
---|
968 | 886 | } |
---|
969 | 887 | |
---|
970 | 888 | static int |
---|
.. | .. |
---|
974 | 892 | { |
---|
975 | 893 | struct qtnf_hw_info *hwinfo = &bus->hw_info; |
---|
976 | 894 | const struct qlink_tlv_hdr *tlv; |
---|
977 | | - const struct qlink_tlv_reg_rule *tlv_rule; |
---|
978 | 895 | const char *bld_name = NULL; |
---|
979 | 896 | const char *bld_rev = NULL; |
---|
980 | 897 | const char *bld_type = NULL; |
---|
.. | .. |
---|
985 | 902 | const char *calibration_ver = NULL; |
---|
986 | 903 | const char *uboot_ver = NULL; |
---|
987 | 904 | u32 hw_ver = 0; |
---|
988 | | - struct ieee80211_reg_rule *rule; |
---|
989 | 905 | u16 tlv_type; |
---|
990 | | - u16 tlv_value_len; |
---|
991 | | - unsigned int rule_idx = 0; |
---|
992 | | - |
---|
993 | | - if (WARN_ON(resp->n_reg_rules > NL80211_MAX_SUPP_REG_RULES)) |
---|
994 | | - return -E2BIG; |
---|
995 | | - |
---|
996 | | - hwinfo->rd = kzalloc(sizeof(*hwinfo->rd) |
---|
997 | | - + sizeof(struct ieee80211_reg_rule) |
---|
998 | | - * resp->n_reg_rules, GFP_KERNEL); |
---|
999 | | - |
---|
1000 | | - if (!hwinfo->rd) |
---|
1001 | | - return -ENOMEM; |
---|
| 906 | + u16 tlv_len; |
---|
1002 | 907 | |
---|
1003 | 908 | hwinfo->num_mac = resp->num_mac; |
---|
1004 | 909 | hwinfo->mac_bitmap = resp->mac_bitmap; |
---|
1005 | 910 | hwinfo->fw_ver = le32_to_cpu(resp->fw_ver); |
---|
1006 | | - hwinfo->ql_proto_ver = le16_to_cpu(resp->ql_proto_ver); |
---|
1007 | 911 | hwinfo->total_tx_chain = resp->total_tx_chain; |
---|
1008 | 912 | hwinfo->total_rx_chain = resp->total_rx_chain; |
---|
1009 | | - hwinfo->hw_capab = le32_to_cpu(resp->hw_capab); |
---|
1010 | | - hwinfo->rd->n_reg_rules = resp->n_reg_rules; |
---|
1011 | | - hwinfo->rd->alpha2[0] = resp->alpha2[0]; |
---|
1012 | | - hwinfo->rd->alpha2[1] = resp->alpha2[1]; |
---|
1013 | 913 | |
---|
1014 | 914 | bld_tmstamp = le32_to_cpu(resp->bld_tmstamp); |
---|
1015 | 915 | plat_id = le32_to_cpu(resp->plat_id); |
---|
1016 | 916 | hw_ver = le32_to_cpu(resp->hw_ver); |
---|
1017 | 917 | |
---|
1018 | | - switch (resp->dfs_region) { |
---|
1019 | | - case QLINK_DFS_FCC: |
---|
1020 | | - hwinfo->rd->dfs_region = NL80211_DFS_FCC; |
---|
1021 | | - break; |
---|
1022 | | - case QLINK_DFS_ETSI: |
---|
1023 | | - hwinfo->rd->dfs_region = NL80211_DFS_ETSI; |
---|
1024 | | - break; |
---|
1025 | | - case QLINK_DFS_JP: |
---|
1026 | | - hwinfo->rd->dfs_region = NL80211_DFS_JP; |
---|
1027 | | - break; |
---|
1028 | | - case QLINK_DFS_UNSET: |
---|
1029 | | - default: |
---|
1030 | | - hwinfo->rd->dfs_region = NL80211_DFS_UNSET; |
---|
1031 | | - break; |
---|
1032 | | - } |
---|
1033 | | - |
---|
1034 | | - tlv = (const struct qlink_tlv_hdr *)resp->info; |
---|
1035 | | - |
---|
1036 | | - while (info_len >= sizeof(*tlv)) { |
---|
| 918 | + qlink_for_each_tlv(tlv, resp->info, info_len) { |
---|
1037 | 919 | tlv_type = le16_to_cpu(tlv->type); |
---|
1038 | | - tlv_value_len = le16_to_cpu(tlv->len); |
---|
1039 | | - |
---|
1040 | | - if (tlv_value_len + sizeof(*tlv) > info_len) { |
---|
1041 | | - pr_warn("malformed TLV 0x%.2X; LEN: %u\n", |
---|
1042 | | - tlv_type, tlv_value_len); |
---|
1043 | | - return -EINVAL; |
---|
1044 | | - } |
---|
| 920 | + tlv_len = le16_to_cpu(tlv->len); |
---|
1045 | 921 | |
---|
1046 | 922 | switch (tlv_type) { |
---|
1047 | | - case QTN_TLV_ID_REG_RULE: |
---|
1048 | | - if (rule_idx >= resp->n_reg_rules) { |
---|
1049 | | - pr_warn("unexpected number of rules: %u\n", |
---|
1050 | | - resp->n_reg_rules); |
---|
1051 | | - return -EINVAL; |
---|
1052 | | - } |
---|
1053 | | - |
---|
1054 | | - if (tlv_value_len != sizeof(*tlv_rule) - sizeof(*tlv)) { |
---|
1055 | | - pr_warn("malformed TLV 0x%.2X; LEN: %u\n", |
---|
1056 | | - tlv_type, tlv_value_len); |
---|
1057 | | - return -EINVAL; |
---|
1058 | | - } |
---|
1059 | | - |
---|
1060 | | - tlv_rule = (const struct qlink_tlv_reg_rule *)tlv; |
---|
1061 | | - rule = &hwinfo->rd->reg_rules[rule_idx++]; |
---|
1062 | | - |
---|
1063 | | - rule->freq_range.start_freq_khz = |
---|
1064 | | - le32_to_cpu(tlv_rule->start_freq_khz); |
---|
1065 | | - rule->freq_range.end_freq_khz = |
---|
1066 | | - le32_to_cpu(tlv_rule->end_freq_khz); |
---|
1067 | | - rule->freq_range.max_bandwidth_khz = |
---|
1068 | | - le32_to_cpu(tlv_rule->max_bandwidth_khz); |
---|
1069 | | - rule->power_rule.max_antenna_gain = |
---|
1070 | | - le32_to_cpu(tlv_rule->max_antenna_gain); |
---|
1071 | | - rule->power_rule.max_eirp = |
---|
1072 | | - le32_to_cpu(tlv_rule->max_eirp); |
---|
1073 | | - rule->dfs_cac_ms = |
---|
1074 | | - le32_to_cpu(tlv_rule->dfs_cac_ms); |
---|
1075 | | - rule->flags = qtnf_cmd_resp_reg_rule_flags_parse( |
---|
1076 | | - le32_to_cpu(tlv_rule->flags)); |
---|
1077 | | - break; |
---|
1078 | 923 | case QTN_TLV_ID_BUILD_NAME: |
---|
1079 | 924 | bld_name = (const void *)tlv->val; |
---|
1080 | 925 | break; |
---|
.. | .. |
---|
1096 | 941 | case QTN_TLV_ID_UBOOT_VER: |
---|
1097 | 942 | uboot_ver = (const void *)tlv->val; |
---|
1098 | 943 | break; |
---|
1099 | | - case QTN_TLV_ID_MAX_SCAN_SSIDS: |
---|
1100 | | - hwinfo->max_scan_ssids = *tlv->val; |
---|
| 944 | + case QTN_TLV_ID_BITMAP: |
---|
| 945 | + memcpy(hwinfo->hw_capab, tlv->val, |
---|
| 946 | + min(sizeof(hwinfo->hw_capab), (size_t)tlv_len)); |
---|
1101 | 947 | break; |
---|
1102 | 948 | default: |
---|
1103 | 949 | break; |
---|
1104 | 950 | } |
---|
1105 | | - |
---|
1106 | | - info_len -= tlv_value_len + sizeof(*tlv); |
---|
1107 | | - tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len); |
---|
1108 | 951 | } |
---|
1109 | 952 | |
---|
1110 | | - if (rule_idx != resp->n_reg_rules) { |
---|
1111 | | - pr_warn("unexpected number of rules: expected %u got %u\n", |
---|
1112 | | - resp->n_reg_rules, rule_idx); |
---|
1113 | | - kfree(hwinfo->rd); |
---|
1114 | | - hwinfo->rd = NULL; |
---|
| 953 | + if (!qlink_tlv_parsing_ok(tlv, resp->info, info_len)) { |
---|
| 954 | + pr_err("Malformed TLV buffer\n"); |
---|
1115 | 955 | return -EINVAL; |
---|
1116 | 956 | } |
---|
1117 | 957 | |
---|
1118 | | - pr_info("fw_version=%d, MACs map %#x, alpha2=\"%c%c\", chains Tx=%u Rx=%u, capab=0x%x\n", |
---|
1119 | | - hwinfo->fw_ver, hwinfo->mac_bitmap, |
---|
1120 | | - hwinfo->rd->alpha2[0], hwinfo->rd->alpha2[1], |
---|
1121 | | - hwinfo->total_tx_chain, hwinfo->total_rx_chain, |
---|
1122 | | - hwinfo->hw_capab); |
---|
1123 | | - |
---|
1124 | | - pr_info("\nBuild name: %s" \ |
---|
1125 | | - "\nBuild revision: %s" \ |
---|
1126 | | - "\nBuild type: %s" \ |
---|
1127 | | - "\nBuild label: %s" \ |
---|
1128 | | - "\nBuild timestamp: %lu" \ |
---|
1129 | | - "\nPlatform ID: %lu" \ |
---|
1130 | | - "\nHardware ID: %s" \ |
---|
1131 | | - "\nCalibration version: %s" \ |
---|
1132 | | - "\nU-Boot version: %s" \ |
---|
1133 | | - "\nHardware version: 0x%08x", |
---|
| 958 | + pr_info("\nBuild name: %s\n" |
---|
| 959 | + "Build revision: %s\n" |
---|
| 960 | + "Build type: %s\n" |
---|
| 961 | + "Build label: %s\n" |
---|
| 962 | + "Build timestamp: %lu\n" |
---|
| 963 | + "Platform ID: %lu\n" |
---|
| 964 | + "Hardware ID: %s\n" |
---|
| 965 | + "Calibration version: %s\n" |
---|
| 966 | + "U-Boot version: %s\n" |
---|
| 967 | + "Hardware version: 0x%08x\n" |
---|
| 968 | + "Qlink ver: %u.%u\n" |
---|
| 969 | + "MACs map: %#x\n" |
---|
| 970 | + "Chains Rx-Tx: %ux%u\n" |
---|
| 971 | + "FW version: 0x%x\n", |
---|
1134 | 972 | bld_name, bld_rev, bld_type, bld_label, |
---|
1135 | 973 | (unsigned long)bld_tmstamp, |
---|
1136 | 974 | (unsigned long)plat_id, |
---|
1137 | | - hw_id, calibration_ver, uboot_ver, hw_ver); |
---|
| 975 | + hw_id, calibration_ver, uboot_ver, hw_ver, |
---|
| 976 | + QLINK_VER_MAJOR(bus->hw_info.ql_proto_ver), |
---|
| 977 | + QLINK_VER_MINOR(bus->hw_info.ql_proto_ver), |
---|
| 978 | + hwinfo->mac_bitmap, |
---|
| 979 | + hwinfo->total_rx_chain, hwinfo->total_tx_chain, |
---|
| 980 | + hwinfo->fw_ver); |
---|
1138 | 981 | |
---|
1139 | 982 | strlcpy(hwinfo->fw_version, bld_label, sizeof(hwinfo->fw_version)); |
---|
1140 | 983 | hwinfo->hw_version = hw_ver; |
---|
.. | .. |
---|
1173 | 1016 | } |
---|
1174 | 1017 | } |
---|
1175 | 1018 | |
---|
1176 | | -static int qtnf_parse_variable_mac_info(struct qtnf_wmac *mac, |
---|
1177 | | - const u8 *tlv_buf, size_t tlv_buf_size) |
---|
| 1019 | +static int |
---|
| 1020 | +qtnf_parse_variable_mac_info(struct qtnf_wmac *mac, |
---|
| 1021 | + const struct qlink_resp_get_mac_info *resp, |
---|
| 1022 | + size_t tlv_buf_size) |
---|
1178 | 1023 | { |
---|
1179 | | - struct ieee80211_iface_combination *comb = NULL; |
---|
| 1024 | + struct ieee80211_iface_combination *comb = mac->macinfo.if_comb; |
---|
1180 | 1025 | size_t n_comb = 0; |
---|
1181 | 1026 | struct ieee80211_iface_limit *limits; |
---|
1182 | | - const struct qlink_iface_comb_num *comb_num; |
---|
1183 | 1027 | const struct qlink_iface_limit_record *rec; |
---|
1184 | 1028 | const struct qlink_iface_limit *lim; |
---|
1185 | 1029 | const struct qlink_wowlan_capab_data *wowlan; |
---|
1186 | 1030 | u16 rec_len; |
---|
1187 | 1031 | u16 tlv_type; |
---|
1188 | 1032 | u16 tlv_value_len; |
---|
1189 | | - size_t tlv_full_len; |
---|
1190 | 1033 | const struct qlink_tlv_hdr *tlv; |
---|
1191 | 1034 | u8 *ext_capa = NULL; |
---|
1192 | 1035 | u8 *ext_capa_mask = NULL; |
---|
1193 | 1036 | u8 ext_capa_len = 0; |
---|
1194 | 1037 | u8 ext_capa_mask_len = 0; |
---|
1195 | 1038 | int i = 0; |
---|
| 1039 | + struct ieee80211_reg_rule *rule; |
---|
| 1040 | + unsigned int rule_idx = 0; |
---|
| 1041 | + const struct qlink_tlv_reg_rule *tlv_rule; |
---|
1196 | 1042 | |
---|
1197 | | - tlv = (const struct qlink_tlv_hdr *)tlv_buf; |
---|
1198 | | - while (tlv_buf_size >= sizeof(struct qlink_tlv_hdr)) { |
---|
| 1043 | + if (WARN_ON(resp->n_reg_rules > NL80211_MAX_SUPP_REG_RULES)) |
---|
| 1044 | + return -E2BIG; |
---|
| 1045 | + |
---|
| 1046 | + mac->rd = kzalloc(struct_size(mac->rd, reg_rules, resp->n_reg_rules), |
---|
| 1047 | + GFP_KERNEL); |
---|
| 1048 | + if (!mac->rd) |
---|
| 1049 | + return -ENOMEM; |
---|
| 1050 | + |
---|
| 1051 | + mac->rd->n_reg_rules = resp->n_reg_rules; |
---|
| 1052 | + mac->rd->alpha2[0] = resp->alpha2[0]; |
---|
| 1053 | + mac->rd->alpha2[1] = resp->alpha2[1]; |
---|
| 1054 | + |
---|
| 1055 | + switch (resp->dfs_region) { |
---|
| 1056 | + case QLINK_DFS_FCC: |
---|
| 1057 | + mac->rd->dfs_region = NL80211_DFS_FCC; |
---|
| 1058 | + break; |
---|
| 1059 | + case QLINK_DFS_ETSI: |
---|
| 1060 | + mac->rd->dfs_region = NL80211_DFS_ETSI; |
---|
| 1061 | + break; |
---|
| 1062 | + case QLINK_DFS_JP: |
---|
| 1063 | + mac->rd->dfs_region = NL80211_DFS_JP; |
---|
| 1064 | + break; |
---|
| 1065 | + case QLINK_DFS_UNSET: |
---|
| 1066 | + default: |
---|
| 1067 | + mac->rd->dfs_region = NL80211_DFS_UNSET; |
---|
| 1068 | + break; |
---|
| 1069 | + } |
---|
| 1070 | + |
---|
| 1071 | + qlink_for_each_tlv(tlv, resp->var_info, tlv_buf_size) { |
---|
1199 | 1072 | tlv_type = le16_to_cpu(tlv->type); |
---|
1200 | 1073 | tlv_value_len = le16_to_cpu(tlv->len); |
---|
1201 | | - tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr); |
---|
1202 | | - if (tlv_full_len > tlv_buf_size) { |
---|
1203 | | - pr_warn("MAC%u: malformed TLV 0x%.2X; LEN: %u\n", |
---|
1204 | | - mac->macid, tlv_type, tlv_value_len); |
---|
1205 | | - return -EINVAL; |
---|
1206 | | - } |
---|
1207 | 1074 | |
---|
1208 | 1075 | switch (tlv_type) { |
---|
1209 | | - case QTN_TLV_ID_NUM_IFACE_COMB: |
---|
1210 | | - if (tlv_value_len != sizeof(*comb_num)) |
---|
1211 | | - return -EINVAL; |
---|
1212 | | - |
---|
1213 | | - comb_num = (void *)tlv->val; |
---|
1214 | | - |
---|
1215 | | - /* free earlier iface comb memory */ |
---|
1216 | | - qtnf_mac_iface_comb_free(mac); |
---|
1217 | | - |
---|
1218 | | - mac->macinfo.n_if_comb = |
---|
1219 | | - le32_to_cpu(comb_num->iface_comb_num); |
---|
1220 | | - |
---|
1221 | | - mac->macinfo.if_comb = |
---|
1222 | | - kcalloc(mac->macinfo.n_if_comb, |
---|
1223 | | - sizeof(*mac->macinfo.if_comb), |
---|
1224 | | - GFP_KERNEL); |
---|
1225 | | - |
---|
1226 | | - if (!mac->macinfo.if_comb) |
---|
1227 | | - return -ENOMEM; |
---|
1228 | | - |
---|
1229 | | - comb = mac->macinfo.if_comb; |
---|
1230 | | - |
---|
1231 | | - pr_debug("MAC%u: %zu iface combinations\n", |
---|
1232 | | - mac->macid, mac->macinfo.n_if_comb); |
---|
1233 | | - |
---|
1234 | | - break; |
---|
1235 | 1076 | case QTN_TLV_ID_IFACE_LIMIT: |
---|
1236 | 1077 | if (unlikely(!comb)) { |
---|
1237 | 1078 | pr_warn("MAC%u: no combinations advertised\n", |
---|
.. | .. |
---|
1313 | 1154 | mac->macinfo.wowlan = NULL; |
---|
1314 | 1155 | qtnf_parse_wowlan_info(mac, wowlan); |
---|
1315 | 1156 | break; |
---|
| 1157 | + case QTN_TLV_ID_REG_RULE: |
---|
| 1158 | + if (rule_idx >= resp->n_reg_rules) { |
---|
| 1159 | + pr_warn("unexpected number of rules: %u\n", |
---|
| 1160 | + resp->n_reg_rules); |
---|
| 1161 | + return -EINVAL; |
---|
| 1162 | + } |
---|
| 1163 | + |
---|
| 1164 | + if (tlv_value_len != sizeof(*tlv_rule) - sizeof(*tlv)) { |
---|
| 1165 | + pr_warn("malformed TLV 0x%.2X; LEN: %u\n", |
---|
| 1166 | + tlv_type, tlv_value_len); |
---|
| 1167 | + return -EINVAL; |
---|
| 1168 | + } |
---|
| 1169 | + |
---|
| 1170 | + tlv_rule = (const struct qlink_tlv_reg_rule *)tlv; |
---|
| 1171 | + rule = &mac->rd->reg_rules[rule_idx++]; |
---|
| 1172 | + qlink_utils_regrule_q2nl(rule, tlv_rule); |
---|
| 1173 | + break; |
---|
1316 | 1174 | default: |
---|
1317 | 1175 | pr_warn("MAC%u: unknown TLV type %u\n", |
---|
1318 | 1176 | mac->macid, tlv_type); |
---|
1319 | 1177 | break; |
---|
1320 | 1178 | } |
---|
1321 | | - |
---|
1322 | | - tlv_buf_size -= tlv_full_len; |
---|
1323 | | - tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len); |
---|
1324 | 1179 | } |
---|
1325 | 1180 | |
---|
1326 | | - if (tlv_buf_size) { |
---|
1327 | | - pr_warn("MAC%u: malformed TLV buf; bytes left: %zu\n", |
---|
1328 | | - mac->macid, tlv_buf_size); |
---|
| 1181 | + if (!qlink_tlv_parsing_ok(tlv, resp->var_info, tlv_buf_size)) { |
---|
| 1182 | + pr_err("Malformed TLV buffer\n"); |
---|
1329 | 1183 | return -EINVAL; |
---|
1330 | 1184 | } |
---|
1331 | 1185 | |
---|
.. | .. |
---|
1338 | 1192 | if (ext_capa_len != ext_capa_mask_len) { |
---|
1339 | 1193 | pr_err("MAC%u: ext_capa/_mask lengths mismatch: %u != %u\n", |
---|
1340 | 1194 | mac->macid, ext_capa_len, ext_capa_mask_len); |
---|
| 1195 | + return -EINVAL; |
---|
| 1196 | + } |
---|
| 1197 | + |
---|
| 1198 | + if (rule_idx != resp->n_reg_rules) { |
---|
| 1199 | + pr_warn("unexpected number of rules: expected %u got %u\n", |
---|
| 1200 | + resp->n_reg_rules, rule_idx); |
---|
1341 | 1201 | return -EINVAL; |
---|
1342 | 1202 | } |
---|
1343 | 1203 | |
---|
.. | .. |
---|
1365 | 1225 | return 0; |
---|
1366 | 1226 | } |
---|
1367 | 1227 | |
---|
1368 | | -static void |
---|
| 1228 | +static int |
---|
1369 | 1229 | qtnf_cmd_resp_proc_mac_info(struct qtnf_wmac *mac, |
---|
1370 | 1230 | const struct qlink_resp_get_mac_info *resp_info) |
---|
1371 | 1231 | { |
---|
1372 | 1232 | struct qtnf_mac_info *mac_info; |
---|
1373 | 1233 | struct qtnf_vif *vif; |
---|
1374 | 1234 | |
---|
| 1235 | + qtnf_mac_iface_comb_free(mac); |
---|
| 1236 | + |
---|
1375 | 1237 | mac_info = &mac->macinfo; |
---|
1376 | 1238 | |
---|
1377 | 1239 | mac_info->bands_cap = resp_info->bands_cap; |
---|
1378 | | - memcpy(&mac_info->dev_mac, &resp_info->dev_mac, |
---|
1379 | | - sizeof(mac_info->dev_mac)); |
---|
1380 | | - |
---|
1381 | | - ether_addr_copy(mac->macaddr, mac_info->dev_mac); |
---|
| 1240 | + ether_addr_copy(mac->macaddr, resp_info->dev_mac); |
---|
1382 | 1241 | |
---|
1383 | 1242 | vif = qtnf_mac_get_base_vif(mac); |
---|
1384 | 1243 | if (vif) |
---|
.. | .. |
---|
1393 | 1252 | mac_info->radar_detect_widths = |
---|
1394 | 1253 | qlink_chan_width_mask_to_nl(le16_to_cpu( |
---|
1395 | 1254 | resp_info->radar_detect_widths)); |
---|
1396 | | - mac_info->max_acl_mac_addrs = le32_to_cpu(resp_info->max_acl_mac_addrs); |
---|
| 1255 | + mac_info->max_acl_mac_addrs = le16_to_cpu(resp_info->max_acl_mac_addrs); |
---|
| 1256 | + mac_info->frag_thr = le32_to_cpu(resp_info->frag_threshold); |
---|
| 1257 | + mac_info->rts_thr = le32_to_cpu(resp_info->rts_threshold); |
---|
| 1258 | + mac_info->sretry_limit = resp_info->retry_short; |
---|
| 1259 | + mac_info->lretry_limit = resp_info->retry_long; |
---|
| 1260 | + mac_info->coverage_class = resp_info->coverage_class; |
---|
| 1261 | + mac_info->max_scan_ssids = resp_info->max_scan_ssids; |
---|
1397 | 1262 | |
---|
1398 | 1263 | memcpy(&mac_info->ht_cap_mod_mask, &resp_info->ht_cap_mod_mask, |
---|
1399 | 1264 | sizeof(mac_info->ht_cap_mod_mask)); |
---|
1400 | 1265 | memcpy(&mac_info->vht_cap_mod_mask, &resp_info->vht_cap_mod_mask, |
---|
1401 | 1266 | sizeof(mac_info->vht_cap_mod_mask)); |
---|
| 1267 | + |
---|
| 1268 | + mac_info->n_if_comb = resp_info->n_iface_combinations; |
---|
| 1269 | + mac_info->if_comb = kcalloc(mac->macinfo.n_if_comb, |
---|
| 1270 | + sizeof(*mac->macinfo.if_comb), |
---|
| 1271 | + GFP_KERNEL); |
---|
| 1272 | + |
---|
| 1273 | + if (!mac->macinfo.if_comb) |
---|
| 1274 | + return -ENOMEM; |
---|
| 1275 | + |
---|
| 1276 | + return 0; |
---|
1402 | 1277 | } |
---|
1403 | 1278 | |
---|
1404 | 1279 | static void qtnf_cmd_resp_band_fill_htcap(const u8 *info, |
---|
.. | .. |
---|
1428 | 1303 | memcpy(&bcap->vht_mcs, &vht_cap->supp_mcs, sizeof(bcap->vht_mcs)); |
---|
1429 | 1304 | } |
---|
1430 | 1305 | |
---|
| 1306 | +static void qtnf_cmd_conv_iftype(struct ieee80211_sband_iftype_data |
---|
| 1307 | + *iftype_data, |
---|
| 1308 | + const struct qlink_sband_iftype_data |
---|
| 1309 | + *qlink_data) |
---|
| 1310 | +{ |
---|
| 1311 | + iftype_data->types_mask = le16_to_cpu(qlink_data->types_mask); |
---|
| 1312 | + |
---|
| 1313 | + iftype_data->he_cap.has_he = true; |
---|
| 1314 | + memcpy(&iftype_data->he_cap.he_cap_elem, &qlink_data->he_cap_elem, |
---|
| 1315 | + sizeof(qlink_data->he_cap_elem)); |
---|
| 1316 | + memcpy(iftype_data->he_cap.ppe_thres, qlink_data->ppe_thres, |
---|
| 1317 | + ARRAY_SIZE(qlink_data->ppe_thres)); |
---|
| 1318 | + |
---|
| 1319 | + iftype_data->he_cap.he_mcs_nss_supp.rx_mcs_80 = |
---|
| 1320 | + qlink_data->he_mcs_nss_supp.rx_mcs_80; |
---|
| 1321 | + iftype_data->he_cap.he_mcs_nss_supp.tx_mcs_80 = |
---|
| 1322 | + qlink_data->he_mcs_nss_supp.tx_mcs_80; |
---|
| 1323 | + iftype_data->he_cap.he_mcs_nss_supp.rx_mcs_160 = |
---|
| 1324 | + qlink_data->he_mcs_nss_supp.rx_mcs_160; |
---|
| 1325 | + iftype_data->he_cap.he_mcs_nss_supp.tx_mcs_160 = |
---|
| 1326 | + qlink_data->he_mcs_nss_supp.tx_mcs_160; |
---|
| 1327 | + iftype_data->he_cap.he_mcs_nss_supp.rx_mcs_80p80 = |
---|
| 1328 | + qlink_data->he_mcs_nss_supp.rx_mcs_80p80; |
---|
| 1329 | + iftype_data->he_cap.he_mcs_nss_supp.tx_mcs_80p80 = |
---|
| 1330 | + qlink_data->he_mcs_nss_supp.tx_mcs_80p80; |
---|
| 1331 | +} |
---|
| 1332 | + |
---|
| 1333 | +static int qtnf_cmd_band_fill_iftype(const u8 *data, |
---|
| 1334 | + struct ieee80211_supported_band *band) |
---|
| 1335 | +{ |
---|
| 1336 | + unsigned int i; |
---|
| 1337 | + struct ieee80211_sband_iftype_data *iftype_data; |
---|
| 1338 | + const struct qlink_tlv_iftype_data *tlv = |
---|
| 1339 | + (const struct qlink_tlv_iftype_data *)data; |
---|
| 1340 | + size_t payload_len = tlv->n_iftype_data * sizeof(*tlv->iftype_data) + |
---|
| 1341 | + sizeof(*tlv) - |
---|
| 1342 | + sizeof(struct qlink_tlv_hdr); |
---|
| 1343 | + |
---|
| 1344 | + if (tlv->hdr.len != cpu_to_le16(payload_len)) { |
---|
| 1345 | + pr_err("bad IFTYPE_DATA TLV len %u\n", tlv->hdr.len); |
---|
| 1346 | + return -EINVAL; |
---|
| 1347 | + } |
---|
| 1348 | + |
---|
| 1349 | + kfree(band->iftype_data); |
---|
| 1350 | + band->iftype_data = NULL; |
---|
| 1351 | + band->n_iftype_data = tlv->n_iftype_data; |
---|
| 1352 | + if (band->n_iftype_data == 0) |
---|
| 1353 | + return 0; |
---|
| 1354 | + |
---|
| 1355 | + iftype_data = kcalloc(band->n_iftype_data, sizeof(*iftype_data), |
---|
| 1356 | + GFP_KERNEL); |
---|
| 1357 | + if (!iftype_data) { |
---|
| 1358 | + band->n_iftype_data = 0; |
---|
| 1359 | + return -ENOMEM; |
---|
| 1360 | + } |
---|
| 1361 | + band->iftype_data = iftype_data; |
---|
| 1362 | + |
---|
| 1363 | + for (i = 0; i < band->n_iftype_data; i++) |
---|
| 1364 | + qtnf_cmd_conv_iftype(iftype_data++, &tlv->iftype_data[i]); |
---|
| 1365 | + |
---|
| 1366 | + return 0; |
---|
| 1367 | +} |
---|
| 1368 | + |
---|
1431 | 1369 | static int |
---|
1432 | 1370 | qtnf_cmd_resp_fill_band_info(struct ieee80211_supported_band *band, |
---|
1433 | 1371 | struct qlink_resp_band_info_get *resp, |
---|
1434 | 1372 | size_t payload_len) |
---|
1435 | 1373 | { |
---|
1436 | 1374 | u16 tlv_type; |
---|
1437 | | - size_t tlv_len; |
---|
1438 | 1375 | size_t tlv_dlen; |
---|
1439 | 1376 | const struct qlink_tlv_hdr *tlv; |
---|
1440 | 1377 | const struct qlink_channel *qchan; |
---|
1441 | 1378 | struct ieee80211_channel *chan; |
---|
1442 | 1379 | unsigned int chidx = 0; |
---|
1443 | 1380 | u32 qflags; |
---|
| 1381 | + int ret = -EINVAL; |
---|
1444 | 1382 | |
---|
1445 | 1383 | memset(&band->ht_cap, 0, sizeof(band->ht_cap)); |
---|
1446 | 1384 | memset(&band->vht_cap, 0, sizeof(band->vht_cap)); |
---|
.. | .. |
---|
1468 | 1406 | return -ENOMEM; |
---|
1469 | 1407 | } |
---|
1470 | 1408 | |
---|
1471 | | - tlv = (struct qlink_tlv_hdr *)resp->info; |
---|
1472 | | - |
---|
1473 | | - while (payload_len >= sizeof(*tlv)) { |
---|
| 1409 | + qlink_for_each_tlv(tlv, resp->info, payload_len) { |
---|
1474 | 1410 | tlv_type = le16_to_cpu(tlv->type); |
---|
1475 | 1411 | tlv_dlen = le16_to_cpu(tlv->len); |
---|
1476 | | - tlv_len = tlv_dlen + sizeof(*tlv); |
---|
1477 | | - |
---|
1478 | | - if (tlv_len > payload_len) { |
---|
1479 | | - pr_warn("malformed TLV 0x%.2X; LEN: %zu\n", |
---|
1480 | | - tlv_type, tlv_len); |
---|
1481 | | - goto error_ret; |
---|
1482 | | - } |
---|
1483 | 1412 | |
---|
1484 | 1413 | switch (tlv_type) { |
---|
1485 | 1414 | case QTN_TLV_ID_CHANNEL: |
---|
1486 | 1415 | if (unlikely(tlv_dlen != sizeof(*qchan))) { |
---|
1487 | 1416 | pr_err("invalid channel TLV len %zu\n", |
---|
1488 | | - tlv_len); |
---|
| 1417 | + tlv_dlen); |
---|
1489 | 1418 | goto error_ret; |
---|
1490 | 1419 | } |
---|
1491 | 1420 | |
---|
.. | .. |
---|
1578 | 1507 | qtnf_cmd_resp_band_fill_vhtcap(tlv->val, |
---|
1579 | 1508 | &band->vht_cap); |
---|
1580 | 1509 | break; |
---|
| 1510 | + case QTN_TLV_ID_IFTYPE_DATA: |
---|
| 1511 | + ret = qtnf_cmd_band_fill_iftype((const uint8_t *)tlv, |
---|
| 1512 | + band); |
---|
| 1513 | + if (ret) |
---|
| 1514 | + goto error_ret; |
---|
| 1515 | + break; |
---|
1581 | 1516 | default: |
---|
1582 | 1517 | pr_warn("unknown TLV type: %#x\n", tlv_type); |
---|
1583 | 1518 | break; |
---|
1584 | 1519 | } |
---|
1585 | | - |
---|
1586 | | - payload_len -= tlv_len; |
---|
1587 | | - tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_dlen); |
---|
1588 | 1520 | } |
---|
1589 | 1521 | |
---|
1590 | | - if (payload_len) { |
---|
1591 | | - pr_err("malformed TLV buf; bytes left: %zu\n", payload_len); |
---|
| 1522 | + if (!qlink_tlv_parsing_ok(tlv, resp->info, payload_len)) { |
---|
| 1523 | + pr_err("Malformed TLV buffer\n"); |
---|
1592 | 1524 | goto error_ret; |
---|
1593 | 1525 | } |
---|
1594 | 1526 | |
---|
.. | .. |
---|
1605 | 1537 | band->channels = NULL; |
---|
1606 | 1538 | band->n_channels = 0; |
---|
1607 | 1539 | |
---|
1608 | | - return -EINVAL; |
---|
1609 | | -} |
---|
1610 | | - |
---|
1611 | | -static int qtnf_cmd_resp_proc_phy_params(struct qtnf_wmac *mac, |
---|
1612 | | - const u8 *payload, size_t payload_len) |
---|
1613 | | -{ |
---|
1614 | | - struct qtnf_mac_info *mac_info; |
---|
1615 | | - struct qlink_tlv_frag_rts_thr *phy_thr; |
---|
1616 | | - struct qlink_tlv_rlimit *limit; |
---|
1617 | | - struct qlink_tlv_cclass *class; |
---|
1618 | | - u16 tlv_type; |
---|
1619 | | - u16 tlv_value_len; |
---|
1620 | | - size_t tlv_full_len; |
---|
1621 | | - const struct qlink_tlv_hdr *tlv; |
---|
1622 | | - |
---|
1623 | | - mac_info = &mac->macinfo; |
---|
1624 | | - |
---|
1625 | | - tlv = (struct qlink_tlv_hdr *)payload; |
---|
1626 | | - while (payload_len >= sizeof(struct qlink_tlv_hdr)) { |
---|
1627 | | - tlv_type = le16_to_cpu(tlv->type); |
---|
1628 | | - tlv_value_len = le16_to_cpu(tlv->len); |
---|
1629 | | - tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr); |
---|
1630 | | - |
---|
1631 | | - if (tlv_full_len > payload_len) { |
---|
1632 | | - pr_warn("MAC%u: malformed TLV 0x%.2X; LEN: %u\n", |
---|
1633 | | - mac->macid, tlv_type, tlv_value_len); |
---|
1634 | | - return -EINVAL; |
---|
1635 | | - } |
---|
1636 | | - |
---|
1637 | | - switch (tlv_type) { |
---|
1638 | | - case QTN_TLV_ID_FRAG_THRESH: |
---|
1639 | | - phy_thr = (void *)tlv; |
---|
1640 | | - mac_info->frag_thr = (u32)le16_to_cpu(phy_thr->thr); |
---|
1641 | | - break; |
---|
1642 | | - case QTN_TLV_ID_RTS_THRESH: |
---|
1643 | | - phy_thr = (void *)tlv; |
---|
1644 | | - mac_info->rts_thr = (u32)le16_to_cpu(phy_thr->thr); |
---|
1645 | | - break; |
---|
1646 | | - case QTN_TLV_ID_SRETRY_LIMIT: |
---|
1647 | | - limit = (void *)tlv; |
---|
1648 | | - mac_info->sretry_limit = limit->rlimit; |
---|
1649 | | - break; |
---|
1650 | | - case QTN_TLV_ID_LRETRY_LIMIT: |
---|
1651 | | - limit = (void *)tlv; |
---|
1652 | | - mac_info->lretry_limit = limit->rlimit; |
---|
1653 | | - break; |
---|
1654 | | - case QTN_TLV_ID_COVERAGE_CLASS: |
---|
1655 | | - class = (void *)tlv; |
---|
1656 | | - mac_info->coverage_class = class->cclass; |
---|
1657 | | - break; |
---|
1658 | | - default: |
---|
1659 | | - pr_err("MAC%u: Unknown TLV type: %#x\n", mac->macid, |
---|
1660 | | - le16_to_cpu(tlv->type)); |
---|
1661 | | - break; |
---|
1662 | | - } |
---|
1663 | | - |
---|
1664 | | - payload_len -= tlv_full_len; |
---|
1665 | | - tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len); |
---|
1666 | | - } |
---|
1667 | | - |
---|
1668 | | - if (payload_len) { |
---|
1669 | | - pr_warn("MAC%u: malformed TLV buf; bytes left: %zu\n", |
---|
1670 | | - mac->macid, payload_len); |
---|
1671 | | - return -EINVAL; |
---|
1672 | | - } |
---|
1673 | | - |
---|
1674 | | - return 0; |
---|
1675 | | -} |
---|
1676 | | - |
---|
1677 | | -static int |
---|
1678 | | -qtnf_cmd_resp_proc_chan_stat_info(struct qtnf_chan_stats *stats, |
---|
1679 | | - const u8 *payload, size_t payload_len) |
---|
1680 | | -{ |
---|
1681 | | - struct qlink_chan_stats *qlink_stats; |
---|
1682 | | - const struct qlink_tlv_hdr *tlv; |
---|
1683 | | - size_t tlv_full_len; |
---|
1684 | | - u16 tlv_value_len; |
---|
1685 | | - u16 tlv_type; |
---|
1686 | | - |
---|
1687 | | - tlv = (struct qlink_tlv_hdr *)payload; |
---|
1688 | | - while (payload_len >= sizeof(struct qlink_tlv_hdr)) { |
---|
1689 | | - tlv_type = le16_to_cpu(tlv->type); |
---|
1690 | | - tlv_value_len = le16_to_cpu(tlv->len); |
---|
1691 | | - tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr); |
---|
1692 | | - if (tlv_full_len > payload_len) { |
---|
1693 | | - pr_warn("malformed TLV 0x%.2X; LEN: %u\n", |
---|
1694 | | - tlv_type, tlv_value_len); |
---|
1695 | | - return -EINVAL; |
---|
1696 | | - } |
---|
1697 | | - switch (tlv_type) { |
---|
1698 | | - case QTN_TLV_ID_CHANNEL_STATS: |
---|
1699 | | - if (unlikely(tlv_value_len != sizeof(*qlink_stats))) { |
---|
1700 | | - pr_err("invalid CHANNEL_STATS entry size\n"); |
---|
1701 | | - return -EINVAL; |
---|
1702 | | - } |
---|
1703 | | - |
---|
1704 | | - qlink_stats = (void *)tlv->val; |
---|
1705 | | - |
---|
1706 | | - stats->chan_num = le32_to_cpu(qlink_stats->chan_num); |
---|
1707 | | - stats->cca_tx = le32_to_cpu(qlink_stats->cca_tx); |
---|
1708 | | - stats->cca_rx = le32_to_cpu(qlink_stats->cca_rx); |
---|
1709 | | - stats->cca_busy = le32_to_cpu(qlink_stats->cca_busy); |
---|
1710 | | - stats->cca_try = le32_to_cpu(qlink_stats->cca_try); |
---|
1711 | | - stats->chan_noise = qlink_stats->chan_noise; |
---|
1712 | | - |
---|
1713 | | - pr_debug("chan(%u) try(%u) busy(%u) noise(%d)\n", |
---|
1714 | | - stats->chan_num, stats->cca_try, |
---|
1715 | | - stats->cca_busy, stats->chan_noise); |
---|
1716 | | - break; |
---|
1717 | | - default: |
---|
1718 | | - pr_warn("Unknown TLV type: %#x\n", |
---|
1719 | | - le16_to_cpu(tlv->type)); |
---|
1720 | | - } |
---|
1721 | | - payload_len -= tlv_full_len; |
---|
1722 | | - tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len); |
---|
1723 | | - } |
---|
1724 | | - |
---|
1725 | | - if (payload_len) { |
---|
1726 | | - pr_warn("malformed TLV buf; bytes left: %zu\n", payload_len); |
---|
1727 | | - return -EINVAL; |
---|
1728 | | - } |
---|
1729 | | - |
---|
1730 | | - return 0; |
---|
| 1540 | + return ret; |
---|
1731 | 1541 | } |
---|
1732 | 1542 | |
---|
1733 | 1543 | int qtnf_cmd_get_mac_info(struct qtnf_wmac *mac) |
---|
1734 | 1544 | { |
---|
1735 | 1545 | struct sk_buff *cmd_skb, *resp_skb = NULL; |
---|
1736 | 1546 | const struct qlink_resp_get_mac_info *resp; |
---|
1737 | | - size_t var_data_len; |
---|
1738 | | - u16 res_code = QLINK_CMD_RESULT_OK; |
---|
| 1547 | + size_t var_data_len = 0; |
---|
1739 | 1548 | int ret = 0; |
---|
1740 | 1549 | |
---|
1741 | 1550 | cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, QLINK_VIFID_RSVD, |
---|
.. | .. |
---|
1745 | 1554 | return -ENOMEM; |
---|
1746 | 1555 | |
---|
1747 | 1556 | qtnf_bus_lock(mac->bus); |
---|
1748 | | - |
---|
1749 | | - ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb, &res_code, |
---|
| 1557 | + ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb, |
---|
1750 | 1558 | sizeof(*resp), &var_data_len); |
---|
1751 | | - if (unlikely(ret)) |
---|
| 1559 | + if (ret) |
---|
1752 | 1560 | goto out; |
---|
1753 | | - |
---|
1754 | | - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { |
---|
1755 | | - pr_err("MAC%u: CMD failed: %u\n", mac->macid, res_code); |
---|
1756 | | - ret = -EFAULT; |
---|
1757 | | - goto out; |
---|
1758 | | - } |
---|
1759 | 1561 | |
---|
1760 | 1562 | resp = (const struct qlink_resp_get_mac_info *)resp_skb->data; |
---|
1761 | | - qtnf_cmd_resp_proc_mac_info(mac, resp); |
---|
1762 | | - ret = qtnf_parse_variable_mac_info(mac, resp->var_info, var_data_len); |
---|
| 1563 | + ret = qtnf_cmd_resp_proc_mac_info(mac, resp); |
---|
| 1564 | + if (ret) |
---|
| 1565 | + goto out; |
---|
| 1566 | + |
---|
| 1567 | + ret = qtnf_parse_variable_mac_info(mac, resp, var_data_len); |
---|
1763 | 1568 | |
---|
1764 | 1569 | out: |
---|
1765 | 1570 | qtnf_bus_unlock(mac->bus); |
---|
.. | .. |
---|
1772 | 1577 | { |
---|
1773 | 1578 | struct sk_buff *cmd_skb, *resp_skb = NULL; |
---|
1774 | 1579 | const struct qlink_resp_get_hw_info *resp; |
---|
1775 | | - u16 res_code = QLINK_CMD_RESULT_OK; |
---|
| 1580 | + size_t info_len = 0; |
---|
1776 | 1581 | int ret = 0; |
---|
1777 | | - size_t info_len; |
---|
1778 | 1582 | |
---|
1779 | 1583 | cmd_skb = qtnf_cmd_alloc_new_cmdskb(QLINK_MACID_RSVD, QLINK_VIFID_RSVD, |
---|
1780 | 1584 | QLINK_CMD_GET_HW_INFO, |
---|
.. | .. |
---|
1783 | 1587 | return -ENOMEM; |
---|
1784 | 1588 | |
---|
1785 | 1589 | qtnf_bus_lock(bus); |
---|
1786 | | - |
---|
1787 | | - ret = qtnf_cmd_send_with_reply(bus, cmd_skb, &resp_skb, &res_code, |
---|
| 1590 | + ret = qtnf_cmd_send_with_reply(bus, cmd_skb, &resp_skb, |
---|
1788 | 1591 | sizeof(*resp), &info_len); |
---|
1789 | | - |
---|
1790 | | - if (unlikely(ret)) |
---|
| 1592 | + if (ret) |
---|
1791 | 1593 | goto out; |
---|
1792 | | - |
---|
1793 | | - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { |
---|
1794 | | - pr_err("cmd exec failed: 0x%.4X\n", res_code); |
---|
1795 | | - ret = -EFAULT; |
---|
1796 | | - goto out; |
---|
1797 | | - } |
---|
1798 | 1594 | |
---|
1799 | 1595 | resp = (const struct qlink_resp_get_hw_info *)resp_skb->data; |
---|
1800 | 1596 | ret = qtnf_cmd_resp_proc_hw_info(bus, resp, info_len); |
---|
.. | .. |
---|
1810 | 1606 | struct ieee80211_supported_band *band) |
---|
1811 | 1607 | { |
---|
1812 | 1608 | struct sk_buff *cmd_skb, *resp_skb = NULL; |
---|
1813 | | - size_t info_len; |
---|
1814 | 1609 | struct qlink_cmd_band_info_get *cmd; |
---|
1815 | 1610 | struct qlink_resp_band_info_get *resp; |
---|
1816 | | - u16 res_code = QLINK_CMD_RESULT_OK; |
---|
| 1611 | + size_t info_len = 0; |
---|
1817 | 1612 | int ret = 0; |
---|
1818 | | - u8 qband; |
---|
1819 | | - |
---|
1820 | | - switch (band->band) { |
---|
1821 | | - case NL80211_BAND_2GHZ: |
---|
1822 | | - qband = QLINK_BAND_2GHZ; |
---|
1823 | | - break; |
---|
1824 | | - case NL80211_BAND_5GHZ: |
---|
1825 | | - qband = QLINK_BAND_5GHZ; |
---|
1826 | | - break; |
---|
1827 | | - case NL80211_BAND_60GHZ: |
---|
1828 | | - qband = QLINK_BAND_60GHZ; |
---|
1829 | | - break; |
---|
1830 | | - default: |
---|
1831 | | - return -EINVAL; |
---|
1832 | | - } |
---|
| 1613 | + u8 qband = qlink_utils_band_cfg2q(band->band); |
---|
1833 | 1614 | |
---|
1834 | 1615 | cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, 0, |
---|
1835 | 1616 | QLINK_CMD_BAND_INFO_GET, |
---|
.. | .. |
---|
1841 | 1622 | cmd->band = qband; |
---|
1842 | 1623 | |
---|
1843 | 1624 | qtnf_bus_lock(mac->bus); |
---|
1844 | | - |
---|
1845 | | - ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb, &res_code, |
---|
| 1625 | + ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb, |
---|
1846 | 1626 | sizeof(*resp), &info_len); |
---|
1847 | | - |
---|
1848 | | - if (unlikely(ret)) |
---|
| 1627 | + if (ret) |
---|
1849 | 1628 | goto out; |
---|
1850 | | - |
---|
1851 | | - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { |
---|
1852 | | - pr_err("MAC%u: CMD failed: %u\n", mac->macid, res_code); |
---|
1853 | | - ret = -EFAULT; |
---|
1854 | | - goto out; |
---|
1855 | | - } |
---|
1856 | 1629 | |
---|
1857 | 1630 | resp = (struct qlink_resp_band_info_get *)resp_skb->data; |
---|
1858 | 1631 | if (resp->band != qband) { |
---|
.. | .. |
---|
1871 | 1644 | return ret; |
---|
1872 | 1645 | } |
---|
1873 | 1646 | |
---|
1874 | | -int qtnf_cmd_send_get_phy_params(struct qtnf_wmac *mac) |
---|
1875 | | -{ |
---|
1876 | | - struct sk_buff *cmd_skb, *resp_skb = NULL; |
---|
1877 | | - size_t response_size; |
---|
1878 | | - struct qlink_resp_phy_params *resp; |
---|
1879 | | - u16 res_code = QLINK_CMD_RESULT_OK; |
---|
1880 | | - int ret = 0; |
---|
1881 | | - |
---|
1882 | | - cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, 0, |
---|
1883 | | - QLINK_CMD_PHY_PARAMS_GET, |
---|
1884 | | - sizeof(struct qlink_cmd)); |
---|
1885 | | - if (!cmd_skb) |
---|
1886 | | - return -ENOMEM; |
---|
1887 | | - |
---|
1888 | | - qtnf_bus_lock(mac->bus); |
---|
1889 | | - |
---|
1890 | | - ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb, &res_code, |
---|
1891 | | - sizeof(*resp), &response_size); |
---|
1892 | | - |
---|
1893 | | - if (unlikely(ret)) |
---|
1894 | | - goto out; |
---|
1895 | | - |
---|
1896 | | - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { |
---|
1897 | | - pr_err("MAC%u: CMD failed: %u\n", mac->macid, res_code); |
---|
1898 | | - ret = -EFAULT; |
---|
1899 | | - goto out; |
---|
1900 | | - } |
---|
1901 | | - |
---|
1902 | | - resp = (struct qlink_resp_phy_params *)resp_skb->data; |
---|
1903 | | - ret = qtnf_cmd_resp_proc_phy_params(mac, resp->info, response_size); |
---|
1904 | | - |
---|
1905 | | -out: |
---|
1906 | | - qtnf_bus_unlock(mac->bus); |
---|
1907 | | - consume_skb(resp_skb); |
---|
1908 | | - |
---|
1909 | | - return ret; |
---|
1910 | | -} |
---|
1911 | | - |
---|
1912 | 1647 | int qtnf_cmd_send_update_phy_params(struct qtnf_wmac *mac, u32 changed) |
---|
1913 | 1648 | { |
---|
1914 | 1649 | struct wiphy *wiphy = priv_to_wiphy(mac); |
---|
1915 | 1650 | struct sk_buff *cmd_skb; |
---|
1916 | | - u16 res_code = QLINK_CMD_RESULT_OK; |
---|
1917 | 1651 | int ret = 0; |
---|
1918 | 1652 | |
---|
1919 | 1653 | cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, 0, |
---|
.. | .. |
---|
1925 | 1659 | qtnf_bus_lock(mac->bus); |
---|
1926 | 1660 | |
---|
1927 | 1661 | if (changed & WIPHY_PARAM_FRAG_THRESHOLD) |
---|
1928 | | - qtnf_cmd_skb_put_tlv_u16(cmd_skb, QTN_TLV_ID_FRAG_THRESH, |
---|
| 1662 | + qtnf_cmd_skb_put_tlv_u32(cmd_skb, QTN_TLV_ID_FRAG_THRESH, |
---|
1929 | 1663 | wiphy->frag_threshold); |
---|
1930 | 1664 | if (changed & WIPHY_PARAM_RTS_THRESHOLD) |
---|
1931 | | - qtnf_cmd_skb_put_tlv_u16(cmd_skb, QTN_TLV_ID_RTS_THRESH, |
---|
| 1665 | + qtnf_cmd_skb_put_tlv_u32(cmd_skb, QTN_TLV_ID_RTS_THRESH, |
---|
1932 | 1666 | wiphy->rts_threshold); |
---|
1933 | 1667 | if (changed & WIPHY_PARAM_COVERAGE_CLASS) |
---|
1934 | | - qtnf_cmd_skb_put_tlv_u8(cmd_skb, QTN_TLV_ID_COVERAGE_CLASS, |
---|
1935 | | - wiphy->coverage_class); |
---|
| 1668 | + qtnf_cmd_skb_put_tlv_u32(cmd_skb, QTN_TLV_ID_COVERAGE_CLASS, |
---|
| 1669 | + wiphy->coverage_class); |
---|
1936 | 1670 | |
---|
1937 | | - ret = qtnf_cmd_send(mac->bus, cmd_skb, &res_code); |
---|
| 1671 | + if (changed & WIPHY_PARAM_RETRY_LONG) |
---|
| 1672 | + qtnf_cmd_skb_put_tlv_u32(cmd_skb, QTN_TLV_ID_LRETRY_LIMIT, |
---|
| 1673 | + wiphy->retry_long); |
---|
1938 | 1674 | |
---|
1939 | | - if (unlikely(ret)) |
---|
| 1675 | + if (changed & WIPHY_PARAM_RETRY_SHORT) |
---|
| 1676 | + qtnf_cmd_skb_put_tlv_u32(cmd_skb, QTN_TLV_ID_SRETRY_LIMIT, |
---|
| 1677 | + wiphy->retry_short); |
---|
| 1678 | + |
---|
| 1679 | + ret = qtnf_cmd_send(mac->bus, cmd_skb); |
---|
| 1680 | + if (ret) |
---|
1940 | 1681 | goto out; |
---|
1941 | | - |
---|
1942 | | - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { |
---|
1943 | | - pr_err("MAC%u: CMD failed: %u\n", mac->macid, res_code); |
---|
1944 | | - ret = -EFAULT; |
---|
1945 | | - goto out; |
---|
1946 | | - } |
---|
1947 | 1682 | |
---|
1948 | 1683 | out: |
---|
1949 | 1684 | qtnf_bus_unlock(mac->bus); |
---|
| 1685 | + |
---|
1950 | 1686 | return ret; |
---|
1951 | 1687 | } |
---|
1952 | 1688 | |
---|
1953 | 1689 | int qtnf_cmd_send_init_fw(struct qtnf_bus *bus) |
---|
1954 | 1690 | { |
---|
| 1691 | + struct sk_buff *resp_skb = NULL; |
---|
| 1692 | + struct qlink_resp_init_fw *resp; |
---|
| 1693 | + struct qlink_cmd_init_fw *cmd; |
---|
1955 | 1694 | struct sk_buff *cmd_skb; |
---|
1956 | | - u16 res_code = QLINK_CMD_RESULT_OK; |
---|
1957 | | - int ret = 0; |
---|
| 1695 | + size_t info_len = 0; |
---|
| 1696 | + int ret; |
---|
1958 | 1697 | |
---|
1959 | 1698 | cmd_skb = qtnf_cmd_alloc_new_cmdskb(QLINK_MACID_RSVD, QLINK_VIFID_RSVD, |
---|
1960 | 1699 | QLINK_CMD_FW_INIT, |
---|
1961 | | - sizeof(struct qlink_cmd)); |
---|
| 1700 | + sizeof(*cmd)); |
---|
1962 | 1701 | if (!cmd_skb) |
---|
1963 | 1702 | return -ENOMEM; |
---|
1964 | 1703 | |
---|
| 1704 | + cmd = (struct qlink_cmd_init_fw *)cmd_skb->data; |
---|
| 1705 | + cmd->qlink_proto_ver = cpu_to_le32(QLINK_PROTO_VER); |
---|
| 1706 | + |
---|
1965 | 1707 | qtnf_bus_lock(bus); |
---|
| 1708 | + ret = qtnf_cmd_send_with_reply(bus, cmd_skb, &resp_skb, |
---|
| 1709 | + sizeof(*resp), &info_len); |
---|
| 1710 | + qtnf_bus_unlock(bus); |
---|
1966 | 1711 | |
---|
1967 | | - ret = qtnf_cmd_send(bus, cmd_skb, &res_code); |
---|
1968 | | - |
---|
1969 | | - if (unlikely(ret)) |
---|
| 1712 | + if (ret) |
---|
1970 | 1713 | goto out; |
---|
1971 | 1714 | |
---|
1972 | | - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { |
---|
1973 | | - pr_err("cmd exec failed: 0x%.4X\n", res_code); |
---|
1974 | | - ret = -EFAULT; |
---|
1975 | | - goto out; |
---|
1976 | | - } |
---|
| 1715 | + resp = (struct qlink_resp_init_fw *)resp_skb->data; |
---|
| 1716 | + bus->hw_info.ql_proto_ver = le32_to_cpu(resp->qlink_proto_ver); |
---|
1977 | 1717 | |
---|
1978 | 1718 | out: |
---|
1979 | | - qtnf_bus_unlock(bus); |
---|
| 1719 | + consume_skb(resp_skb); |
---|
1980 | 1720 | return ret; |
---|
1981 | 1721 | } |
---|
1982 | 1722 | |
---|
.. | .. |
---|
1991 | 1731 | return; |
---|
1992 | 1732 | |
---|
1993 | 1733 | qtnf_bus_lock(bus); |
---|
1994 | | - |
---|
1995 | | - qtnf_cmd_send(bus, cmd_skb, NULL); |
---|
1996 | | - |
---|
| 1734 | + qtnf_cmd_send(bus, cmd_skb); |
---|
1997 | 1735 | qtnf_bus_unlock(bus); |
---|
1998 | 1736 | } |
---|
1999 | 1737 | |
---|
.. | .. |
---|
2002 | 1740 | { |
---|
2003 | 1741 | struct sk_buff *cmd_skb; |
---|
2004 | 1742 | struct qlink_cmd_add_key *cmd; |
---|
2005 | | - u16 res_code = QLINK_CMD_RESULT_OK; |
---|
2006 | 1743 | int ret = 0; |
---|
2007 | 1744 | |
---|
2008 | 1745 | cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, |
---|
.. | .. |
---|
2034 | 1771 | params->seq, |
---|
2035 | 1772 | params->seq_len); |
---|
2036 | 1773 | |
---|
2037 | | - ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code); |
---|
2038 | | - if (unlikely(ret)) |
---|
| 1774 | + ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); |
---|
| 1775 | + if (ret) |
---|
2039 | 1776 | goto out; |
---|
2040 | | - |
---|
2041 | | - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { |
---|
2042 | | - pr_err("VIF%u.%u: CMD failed: %u\n", |
---|
2043 | | - vif->mac->macid, vif->vifid, res_code); |
---|
2044 | | - ret = -EFAULT; |
---|
2045 | | - goto out; |
---|
2046 | | - } |
---|
2047 | 1777 | |
---|
2048 | 1778 | out: |
---|
2049 | 1779 | qtnf_bus_unlock(vif->mac->bus); |
---|
| 1780 | + |
---|
2050 | 1781 | return ret; |
---|
2051 | 1782 | } |
---|
2052 | 1783 | |
---|
.. | .. |
---|
2055 | 1786 | { |
---|
2056 | 1787 | struct sk_buff *cmd_skb; |
---|
2057 | 1788 | struct qlink_cmd_del_key *cmd; |
---|
2058 | | - u16 res_code = QLINK_CMD_RESULT_OK; |
---|
2059 | 1789 | int ret = 0; |
---|
2060 | 1790 | |
---|
2061 | 1791 | cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, |
---|
.. | .. |
---|
2075 | 1805 | |
---|
2076 | 1806 | cmd->key_index = key_index; |
---|
2077 | 1807 | cmd->pairwise = pairwise; |
---|
2078 | | - ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code); |
---|
2079 | | - if (unlikely(ret)) |
---|
2080 | | - goto out; |
---|
2081 | 1808 | |
---|
2082 | | - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { |
---|
2083 | | - pr_err("VIF%u.%u: CMD failed: %u\n", |
---|
2084 | | - vif->mac->macid, vif->vifid, res_code); |
---|
2085 | | - ret = -EFAULT; |
---|
| 1809 | + ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); |
---|
| 1810 | + if (ret) |
---|
2086 | 1811 | goto out; |
---|
2087 | | - } |
---|
2088 | 1812 | |
---|
2089 | 1813 | out: |
---|
2090 | 1814 | qtnf_bus_unlock(vif->mac->bus); |
---|
| 1815 | + |
---|
2091 | 1816 | return ret; |
---|
2092 | 1817 | } |
---|
2093 | 1818 | |
---|
.. | .. |
---|
2096 | 1821 | { |
---|
2097 | 1822 | struct sk_buff *cmd_skb; |
---|
2098 | 1823 | struct qlink_cmd_set_def_key *cmd; |
---|
2099 | | - u16 res_code = QLINK_CMD_RESULT_OK; |
---|
2100 | 1824 | int ret = 0; |
---|
2101 | 1825 | |
---|
2102 | 1826 | cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, |
---|
.. | .. |
---|
2111 | 1835 | cmd->key_index = key_index; |
---|
2112 | 1836 | cmd->unicast = unicast; |
---|
2113 | 1837 | cmd->multicast = multicast; |
---|
2114 | | - ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code); |
---|
2115 | | - if (unlikely(ret)) |
---|
2116 | | - goto out; |
---|
2117 | 1838 | |
---|
2118 | | - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { |
---|
2119 | | - pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid, |
---|
2120 | | - vif->vifid, res_code); |
---|
2121 | | - ret = -EFAULT; |
---|
| 1839 | + ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); |
---|
| 1840 | + if (ret) |
---|
2122 | 1841 | goto out; |
---|
2123 | | - } |
---|
2124 | 1842 | |
---|
2125 | 1843 | out: |
---|
2126 | 1844 | qtnf_bus_unlock(vif->mac->bus); |
---|
| 1845 | + |
---|
2127 | 1846 | return ret; |
---|
2128 | 1847 | } |
---|
2129 | 1848 | |
---|
.. | .. |
---|
2131 | 1850 | { |
---|
2132 | 1851 | struct sk_buff *cmd_skb; |
---|
2133 | 1852 | struct qlink_cmd_set_def_mgmt_key *cmd; |
---|
2134 | | - u16 res_code = QLINK_CMD_RESULT_OK; |
---|
2135 | 1853 | int ret = 0; |
---|
2136 | 1854 | |
---|
2137 | 1855 | cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, |
---|
.. | .. |
---|
2144 | 1862 | |
---|
2145 | 1863 | cmd = (struct qlink_cmd_set_def_mgmt_key *)cmd_skb->data; |
---|
2146 | 1864 | cmd->key_index = key_index; |
---|
2147 | | - ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code); |
---|
2148 | | - if (unlikely(ret)) |
---|
2149 | | - goto out; |
---|
2150 | 1865 | |
---|
2151 | | - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { |
---|
2152 | | - pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid, |
---|
2153 | | - vif->vifid, res_code); |
---|
2154 | | - ret = -EFAULT; |
---|
| 1866 | + ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); |
---|
| 1867 | + if (ret) |
---|
2155 | 1868 | goto out; |
---|
2156 | | - } |
---|
2157 | 1869 | |
---|
2158 | 1870 | out: |
---|
2159 | 1871 | qtnf_bus_unlock(vif->mac->bus); |
---|
| 1872 | + |
---|
2160 | 1873 | return ret; |
---|
2161 | 1874 | } |
---|
2162 | 1875 | |
---|
.. | .. |
---|
2186 | 1899 | { |
---|
2187 | 1900 | struct sk_buff *cmd_skb; |
---|
2188 | 1901 | struct qlink_cmd_change_sta *cmd; |
---|
2189 | | - u16 res_code = QLINK_CMD_RESULT_OK; |
---|
2190 | 1902 | int ret = 0; |
---|
2191 | 1903 | |
---|
2192 | 1904 | cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, |
---|
.. | .. |
---|
2218 | 1930 | goto out; |
---|
2219 | 1931 | } |
---|
2220 | 1932 | |
---|
2221 | | - ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code); |
---|
2222 | | - if (unlikely(ret)) |
---|
| 1933 | + ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); |
---|
| 1934 | + if (ret) |
---|
2223 | 1935 | goto out; |
---|
2224 | | - |
---|
2225 | | - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { |
---|
2226 | | - pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid, |
---|
2227 | | - vif->vifid, res_code); |
---|
2228 | | - ret = -EFAULT; |
---|
2229 | | - goto out; |
---|
2230 | | - } |
---|
2231 | 1936 | |
---|
2232 | 1937 | out: |
---|
2233 | 1938 | qtnf_bus_unlock(vif->mac->bus); |
---|
| 1939 | + |
---|
2234 | 1940 | return ret; |
---|
2235 | 1941 | } |
---|
2236 | 1942 | |
---|
.. | .. |
---|
2239 | 1945 | { |
---|
2240 | 1946 | struct sk_buff *cmd_skb; |
---|
2241 | 1947 | struct qlink_cmd_del_sta *cmd; |
---|
2242 | | - u16 res_code = QLINK_CMD_RESULT_OK; |
---|
2243 | 1948 | int ret = 0; |
---|
2244 | 1949 | |
---|
2245 | 1950 | cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, |
---|
.. | .. |
---|
2260 | 1965 | cmd->subtype = params->subtype; |
---|
2261 | 1966 | cmd->reason_code = cpu_to_le16(params->reason_code); |
---|
2262 | 1967 | |
---|
2263 | | - ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code); |
---|
2264 | | - if (unlikely(ret)) |
---|
| 1968 | + ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); |
---|
| 1969 | + if (ret) |
---|
2265 | 1970 | goto out; |
---|
2266 | | - |
---|
2267 | | - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { |
---|
2268 | | - pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid, |
---|
2269 | | - vif->vifid, res_code); |
---|
2270 | | - ret = -EFAULT; |
---|
2271 | | - goto out; |
---|
2272 | | - } |
---|
2273 | 1971 | |
---|
2274 | 1972 | out: |
---|
2275 | 1973 | qtnf_bus_unlock(vif->mac->bus); |
---|
| 1974 | + |
---|
2276 | 1975 | return ret; |
---|
2277 | 1976 | } |
---|
2278 | 1977 | |
---|
2279 | 1978 | static void qtnf_cmd_channel_tlv_add(struct sk_buff *cmd_skb, |
---|
2280 | 1979 | const struct ieee80211_channel *sc) |
---|
2281 | 1980 | { |
---|
2282 | | - struct qlink_tlv_channel *qchan; |
---|
2283 | | - u32 flags = 0; |
---|
| 1981 | + struct qlink_tlv_channel *tlv; |
---|
| 1982 | + struct qlink_channel *qch; |
---|
2284 | 1983 | |
---|
2285 | | - qchan = skb_put_zero(cmd_skb, sizeof(*qchan)); |
---|
2286 | | - qchan->hdr.type = cpu_to_le16(QTN_TLV_ID_CHANNEL); |
---|
2287 | | - qchan->hdr.len = cpu_to_le16(sizeof(*qchan) - sizeof(qchan->hdr)); |
---|
2288 | | - qchan->chan.center_freq = cpu_to_le16(sc->center_freq); |
---|
2289 | | - qchan->chan.hw_value = cpu_to_le16(sc->hw_value); |
---|
| 1984 | + tlv = skb_put_zero(cmd_skb, sizeof(*tlv)); |
---|
| 1985 | + qch = &tlv->chan; |
---|
| 1986 | + tlv->hdr.type = cpu_to_le16(QTN_TLV_ID_CHANNEL); |
---|
| 1987 | + tlv->hdr.len = cpu_to_le16(sizeof(*qch)); |
---|
2290 | 1988 | |
---|
2291 | | - if (sc->flags & IEEE80211_CHAN_NO_IR) |
---|
2292 | | - flags |= QLINK_CHAN_NO_IR; |
---|
2293 | | - |
---|
2294 | | - if (sc->flags & IEEE80211_CHAN_RADAR) |
---|
2295 | | - flags |= QLINK_CHAN_RADAR; |
---|
2296 | | - |
---|
2297 | | - qchan->chan.flags = cpu_to_le32(flags); |
---|
| 1989 | + qch->center_freq = cpu_to_le16(sc->center_freq); |
---|
| 1990 | + qch->hw_value = cpu_to_le16(sc->hw_value); |
---|
| 1991 | + qch->band = qlink_utils_band_cfg2q(sc->band); |
---|
| 1992 | + qch->max_power = sc->max_power; |
---|
| 1993 | + qch->max_reg_power = sc->max_reg_power; |
---|
| 1994 | + qch->max_antenna_gain = sc->max_antenna_gain; |
---|
| 1995 | + qch->beacon_found = sc->beacon_found; |
---|
| 1996 | + qch->dfs_state = qlink_utils_dfs_state_cfg2q(sc->dfs_state); |
---|
| 1997 | + qch->flags = cpu_to_le32(qlink_utils_chflags_cfg2q(sc->flags)); |
---|
2298 | 1998 | } |
---|
2299 | 1999 | |
---|
2300 | 2000 | static void qtnf_cmd_randmac_tlv_add(struct sk_buff *cmd_skb, |
---|
.. | .. |
---|
2315 | 2015 | |
---|
2316 | 2016 | int qtnf_cmd_send_scan(struct qtnf_wmac *mac) |
---|
2317 | 2017 | { |
---|
2318 | | - struct sk_buff *cmd_skb; |
---|
2319 | | - u16 res_code = QLINK_CMD_RESULT_OK; |
---|
2320 | | - struct ieee80211_channel *sc; |
---|
2321 | 2018 | struct cfg80211_scan_request *scan_req = mac->scan_req; |
---|
2322 | | - int n_channels; |
---|
2323 | | - int count = 0; |
---|
| 2019 | + u16 dwell_passive = QTNF_SCAN_DWELL_PASSIVE_DEFAULT; |
---|
| 2020 | + u16 dwell_active = QTNF_SCAN_DWELL_ACTIVE_DEFAULT; |
---|
| 2021 | + struct wireless_dev *wdev = scan_req->wdev; |
---|
| 2022 | + struct ieee80211_channel *sc; |
---|
| 2023 | + struct qlink_cmd_scan *cmd; |
---|
| 2024 | + struct sk_buff *cmd_skb; |
---|
| 2025 | + int n_channels = 0; |
---|
| 2026 | + u64 flags = 0; |
---|
| 2027 | + int count; |
---|
2324 | 2028 | int ret; |
---|
2325 | 2029 | |
---|
2326 | 2030 | cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, QLINK_VIFID_RSVD, |
---|
2327 | 2031 | QLINK_CMD_SCAN, |
---|
2328 | | - sizeof(struct qlink_cmd)); |
---|
| 2032 | + sizeof(*cmd)); |
---|
2329 | 2033 | if (!cmd_skb) |
---|
2330 | 2034 | return -ENOMEM; |
---|
2331 | 2035 | |
---|
2332 | | - qtnf_bus_lock(mac->bus); |
---|
| 2036 | + cmd = (struct qlink_cmd_scan *)cmd_skb->data; |
---|
2333 | 2037 | |
---|
2334 | | - if (scan_req->n_ssids != 0) { |
---|
2335 | | - while (count < scan_req->n_ssids) { |
---|
2336 | | - qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID, |
---|
2337 | | - scan_req->ssids[count].ssid, |
---|
2338 | | - scan_req->ssids[count].ssid_len); |
---|
2339 | | - count++; |
---|
2340 | | - } |
---|
| 2038 | + if (scan_req->duration) { |
---|
| 2039 | + dwell_active = scan_req->duration; |
---|
| 2040 | + dwell_passive = scan_req->duration; |
---|
| 2041 | + } else if (wdev->iftype == NL80211_IFTYPE_STATION && |
---|
| 2042 | + wdev->current_bss) { |
---|
| 2043 | + /* let device select dwell based on traffic conditions */ |
---|
| 2044 | + dwell_active = QTNF_SCAN_TIME_AUTO; |
---|
| 2045 | + dwell_passive = QTNF_SCAN_TIME_AUTO; |
---|
| 2046 | + } |
---|
| 2047 | + |
---|
| 2048 | + cmd->n_ssids = cpu_to_le16(scan_req->n_ssids); |
---|
| 2049 | + for (count = 0; count < scan_req->n_ssids; ++count) { |
---|
| 2050 | + qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID, |
---|
| 2051 | + scan_req->ssids[count].ssid, |
---|
| 2052 | + scan_req->ssids[count].ssid_len); |
---|
2341 | 2053 | } |
---|
2342 | 2054 | |
---|
2343 | 2055 | if (scan_req->ie_len != 0) |
---|
2344 | 2056 | qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_PROBE_REQ, |
---|
2345 | 2057 | scan_req->ie, scan_req->ie_len); |
---|
2346 | 2058 | |
---|
2347 | | - if (scan_req->n_channels) { |
---|
2348 | | - n_channels = scan_req->n_channels; |
---|
2349 | | - count = 0; |
---|
| 2059 | + for (count = 0; count < scan_req->n_channels; ++count) { |
---|
| 2060 | + sc = scan_req->channels[count]; |
---|
| 2061 | + if (sc->flags & IEEE80211_CHAN_DISABLED) |
---|
| 2062 | + continue; |
---|
2350 | 2063 | |
---|
2351 | | - while (n_channels != 0) { |
---|
2352 | | - sc = scan_req->channels[count]; |
---|
2353 | | - if (sc->flags & IEEE80211_CHAN_DISABLED) { |
---|
2354 | | - n_channels--; |
---|
2355 | | - continue; |
---|
2356 | | - } |
---|
| 2064 | + pr_debug("[MAC%u] scan chan=%d, freq=%d, flags=%#x\n", |
---|
| 2065 | + mac->macid, sc->hw_value, sc->center_freq, |
---|
| 2066 | + sc->flags); |
---|
2357 | 2067 | |
---|
2358 | | - pr_debug("MAC%u: scan chan=%d, freq=%d, flags=%#x\n", |
---|
2359 | | - mac->macid, sc->hw_value, sc->center_freq, |
---|
2360 | | - sc->flags); |
---|
2361 | | - |
---|
2362 | | - qtnf_cmd_channel_tlv_add(cmd_skb, sc); |
---|
2363 | | - n_channels--; |
---|
2364 | | - count++; |
---|
2365 | | - } |
---|
| 2068 | + qtnf_cmd_channel_tlv_add(cmd_skb, sc); |
---|
| 2069 | + ++n_channels; |
---|
2366 | 2070 | } |
---|
2367 | 2071 | |
---|
| 2072 | + if (scan_req->flags & NL80211_SCAN_FLAG_FLUSH) |
---|
| 2073 | + flags |= QLINK_SCAN_FLAG_FLUSH; |
---|
| 2074 | + |
---|
| 2075 | + if (scan_req->duration_mandatory) |
---|
| 2076 | + flags |= QLINK_SCAN_FLAG_DURATION_MANDATORY; |
---|
| 2077 | + |
---|
| 2078 | + cmd->n_channels = cpu_to_le16(n_channels); |
---|
| 2079 | + cmd->active_dwell = cpu_to_le16(dwell_active); |
---|
| 2080 | + cmd->passive_dwell = cpu_to_le16(dwell_passive); |
---|
| 2081 | + cmd->sample_duration = cpu_to_le16(QTNF_SCAN_SAMPLE_DURATION_DEFAULT); |
---|
| 2082 | + cmd->flags = cpu_to_le64(flags); |
---|
| 2083 | + |
---|
| 2084 | + pr_debug("[MAC%u] %s scan dwell active=%u passive=%u duration=%u\n", |
---|
| 2085 | + mac->macid, |
---|
| 2086 | + scan_req->duration_mandatory ? "mandatory" : "max", |
---|
| 2087 | + dwell_active, dwell_passive, |
---|
| 2088 | + QTNF_SCAN_SAMPLE_DURATION_DEFAULT); |
---|
| 2089 | + |
---|
2368 | 2090 | if (scan_req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) { |
---|
2369 | | - pr_debug("MAC%u: scan with random addr=%pM, mask=%pM\n", |
---|
| 2091 | + pr_debug("[MAC%u] scan with random addr=%pM, mask=%pM\n", |
---|
2370 | 2092 | mac->macid, |
---|
2371 | 2093 | scan_req->mac_addr, scan_req->mac_addr_mask); |
---|
2372 | | - |
---|
2373 | 2094 | qtnf_cmd_randmac_tlv_add(cmd_skb, scan_req->mac_addr, |
---|
2374 | 2095 | scan_req->mac_addr_mask); |
---|
2375 | 2096 | } |
---|
2376 | 2097 | |
---|
2377 | | - ret = qtnf_cmd_send(mac->bus, cmd_skb, &res_code); |
---|
2378 | | - |
---|
2379 | | - if (unlikely(ret)) |
---|
2380 | | - goto out; |
---|
2381 | | - |
---|
2382 | | - pr_debug("MAC%u: scan started\n", mac->macid); |
---|
2383 | | - |
---|
2384 | | - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { |
---|
2385 | | - pr_err("MAC%u: CMD failed: %u\n", mac->macid, res_code); |
---|
2386 | | - ret = -EFAULT; |
---|
2387 | | - goto out; |
---|
2388 | | - } |
---|
2389 | | -out: |
---|
| 2098 | + qtnf_bus_lock(mac->bus); |
---|
| 2099 | + ret = qtnf_cmd_send(mac->bus, cmd_skb); |
---|
2390 | 2100 | qtnf_bus_unlock(mac->bus); |
---|
| 2101 | + |
---|
2391 | 2102 | return ret; |
---|
2392 | 2103 | } |
---|
2393 | 2104 | |
---|
.. | .. |
---|
2397 | 2108 | struct sk_buff *cmd_skb; |
---|
2398 | 2109 | struct qlink_cmd_connect *cmd; |
---|
2399 | 2110 | struct qlink_auth_encr *aen; |
---|
2400 | | - u16 res_code = QLINK_CMD_RESULT_OK; |
---|
2401 | 2111 | int ret; |
---|
2402 | 2112 | int i; |
---|
2403 | 2113 | u32 connect_flags = 0; |
---|
.. | .. |
---|
2478 | 2188 | qtnf_cmd_channel_tlv_add(cmd_skb, sme->channel); |
---|
2479 | 2189 | |
---|
2480 | 2190 | qtnf_bus_lock(vif->mac->bus); |
---|
2481 | | - |
---|
2482 | | - ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code); |
---|
2483 | | - |
---|
2484 | | - if (unlikely(ret)) |
---|
| 2191 | + ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); |
---|
| 2192 | + if (ret) |
---|
2485 | 2193 | goto out; |
---|
2486 | 2194 | |
---|
2487 | | - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { |
---|
2488 | | - pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid, |
---|
2489 | | - vif->vifid, res_code); |
---|
2490 | | - ret = -EFAULT; |
---|
2491 | | - goto out; |
---|
2492 | | - } |
---|
2493 | 2195 | out: |
---|
2494 | 2196 | qtnf_bus_unlock(vif->mac->bus); |
---|
| 2197 | + |
---|
| 2198 | + return ret; |
---|
| 2199 | +} |
---|
| 2200 | + |
---|
| 2201 | +int qtnf_cmd_send_external_auth(struct qtnf_vif *vif, |
---|
| 2202 | + struct cfg80211_external_auth_params *auth) |
---|
| 2203 | +{ |
---|
| 2204 | + struct sk_buff *cmd_skb; |
---|
| 2205 | + struct qlink_cmd_external_auth *cmd; |
---|
| 2206 | + int ret; |
---|
| 2207 | + |
---|
| 2208 | + cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, |
---|
| 2209 | + QLINK_CMD_EXTERNAL_AUTH, |
---|
| 2210 | + sizeof(*cmd)); |
---|
| 2211 | + if (!cmd_skb) |
---|
| 2212 | + return -ENOMEM; |
---|
| 2213 | + |
---|
| 2214 | + cmd = (struct qlink_cmd_external_auth *)cmd_skb->data; |
---|
| 2215 | + |
---|
| 2216 | + ether_addr_copy(cmd->peer, auth->bssid); |
---|
| 2217 | + cmd->status = cpu_to_le16(auth->status); |
---|
| 2218 | + |
---|
| 2219 | + qtnf_bus_lock(vif->mac->bus); |
---|
| 2220 | + ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); |
---|
| 2221 | + if (ret) |
---|
| 2222 | + goto out; |
---|
| 2223 | + |
---|
| 2224 | +out: |
---|
| 2225 | + qtnf_bus_unlock(vif->mac->bus); |
---|
| 2226 | + |
---|
2495 | 2227 | return ret; |
---|
2496 | 2228 | } |
---|
2497 | 2229 | |
---|
.. | .. |
---|
2499 | 2231 | { |
---|
2500 | 2232 | struct sk_buff *cmd_skb; |
---|
2501 | 2233 | struct qlink_cmd_disconnect *cmd; |
---|
2502 | | - u16 res_code = QLINK_CMD_RESULT_OK; |
---|
2503 | 2234 | int ret; |
---|
2504 | 2235 | |
---|
2505 | 2236 | cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, |
---|
.. | .. |
---|
2513 | 2244 | cmd = (struct qlink_cmd_disconnect *)cmd_skb->data; |
---|
2514 | 2245 | cmd->reason = cpu_to_le16(reason_code); |
---|
2515 | 2246 | |
---|
2516 | | - ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code); |
---|
2517 | | - |
---|
2518 | | - if (unlikely(ret)) |
---|
| 2247 | + ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); |
---|
| 2248 | + if (ret) |
---|
2519 | 2249 | goto out; |
---|
2520 | 2250 | |
---|
2521 | | - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { |
---|
2522 | | - pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid, |
---|
2523 | | - vif->vifid, res_code); |
---|
2524 | | - ret = -EFAULT; |
---|
2525 | | - goto out; |
---|
2526 | | - } |
---|
2527 | 2251 | out: |
---|
2528 | 2252 | qtnf_bus_unlock(vif->mac->bus); |
---|
| 2253 | + |
---|
2529 | 2254 | return ret; |
---|
2530 | 2255 | } |
---|
2531 | 2256 | |
---|
.. | .. |
---|
2533 | 2258 | { |
---|
2534 | 2259 | struct sk_buff *cmd_skb; |
---|
2535 | 2260 | struct qlink_cmd_updown *cmd; |
---|
2536 | | - u16 res_code = QLINK_CMD_RESULT_OK; |
---|
2537 | 2261 | int ret; |
---|
2538 | 2262 | |
---|
2539 | 2263 | cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, |
---|
.. | .. |
---|
2546 | 2270 | cmd->if_up = !!up; |
---|
2547 | 2271 | |
---|
2548 | 2272 | qtnf_bus_lock(vif->mac->bus); |
---|
2549 | | - |
---|
2550 | | - ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code); |
---|
2551 | | - |
---|
2552 | | - if (unlikely(ret)) |
---|
| 2273 | + ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); |
---|
| 2274 | + if (ret) |
---|
2553 | 2275 | goto out; |
---|
2554 | 2276 | |
---|
2555 | | - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { |
---|
2556 | | - pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid, |
---|
2557 | | - vif->vifid, res_code); |
---|
2558 | | - ret = -EFAULT; |
---|
2559 | | - goto out; |
---|
2560 | | - } |
---|
2561 | 2277 | out: |
---|
2562 | 2278 | qtnf_bus_unlock(vif->mac->bus); |
---|
| 2279 | + |
---|
2563 | 2280 | return ret; |
---|
2564 | 2281 | } |
---|
2565 | 2282 | |
---|
2566 | | -int qtnf_cmd_reg_notify(struct qtnf_bus *bus, struct regulatory_request *req) |
---|
| 2283 | +int qtnf_cmd_reg_notify(struct qtnf_wmac *mac, struct regulatory_request *req, |
---|
| 2284 | + bool slave_radar, bool dfs_offload) |
---|
2567 | 2285 | { |
---|
| 2286 | + struct wiphy *wiphy = priv_to_wiphy(mac); |
---|
| 2287 | + struct qtnf_bus *bus = mac->bus; |
---|
2568 | 2288 | struct sk_buff *cmd_skb; |
---|
2569 | 2289 | int ret; |
---|
2570 | | - u16 res_code; |
---|
2571 | 2290 | struct qlink_cmd_reg_notify *cmd; |
---|
| 2291 | + enum nl80211_band band; |
---|
| 2292 | + const struct ieee80211_supported_band *cfg_band; |
---|
2572 | 2293 | |
---|
2573 | | - cmd_skb = qtnf_cmd_alloc_new_cmdskb(QLINK_MACID_RSVD, QLINK_VIFID_RSVD, |
---|
| 2294 | + cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, QLINK_VIFID_RSVD, |
---|
2574 | 2295 | QLINK_CMD_REG_NOTIFY, |
---|
2575 | 2296 | sizeof(*cmd)); |
---|
2576 | 2297 | if (!cmd_skb) |
---|
.. | .. |
---|
2607 | 2328 | break; |
---|
2608 | 2329 | } |
---|
2609 | 2330 | |
---|
2610 | | - qtnf_bus_lock(bus); |
---|
2611 | | - |
---|
2612 | | - ret = qtnf_cmd_send(bus, cmd_skb, &res_code); |
---|
2613 | | - if (ret) |
---|
2614 | | - goto out; |
---|
2615 | | - |
---|
2616 | | - switch (res_code) { |
---|
2617 | | - case QLINK_CMD_RESULT_ENOTSUPP: |
---|
2618 | | - pr_warn("reg update not supported\n"); |
---|
2619 | | - ret = -EOPNOTSUPP; |
---|
| 2331 | + switch (req->dfs_region) { |
---|
| 2332 | + case NL80211_DFS_FCC: |
---|
| 2333 | + cmd->dfs_region = QLINK_DFS_FCC; |
---|
2620 | 2334 | break; |
---|
2621 | | - case QLINK_CMD_RESULT_EALREADY: |
---|
2622 | | - pr_info("regulatory domain is already set to %c%c", |
---|
2623 | | - req->alpha2[0], req->alpha2[1]); |
---|
2624 | | - ret = -EALREADY; |
---|
| 2335 | + case NL80211_DFS_ETSI: |
---|
| 2336 | + cmd->dfs_region = QLINK_DFS_ETSI; |
---|
2625 | 2337 | break; |
---|
2626 | | - case QLINK_CMD_RESULT_OK: |
---|
2627 | | - ret = 0; |
---|
| 2338 | + case NL80211_DFS_JP: |
---|
| 2339 | + cmd->dfs_region = QLINK_DFS_JP; |
---|
2628 | 2340 | break; |
---|
2629 | 2341 | default: |
---|
2630 | | - ret = -EFAULT; |
---|
| 2342 | + cmd->dfs_region = QLINK_DFS_UNSET; |
---|
2631 | 2343 | break; |
---|
2632 | 2344 | } |
---|
2633 | 2345 | |
---|
2634 | | -out: |
---|
| 2346 | + cmd->slave_radar = slave_radar; |
---|
| 2347 | + cmd->dfs_offload = dfs_offload; |
---|
| 2348 | + cmd->num_channels = 0; |
---|
| 2349 | + |
---|
| 2350 | + for (band = 0; band < NUM_NL80211_BANDS; band++) { |
---|
| 2351 | + unsigned int i; |
---|
| 2352 | + |
---|
| 2353 | + cfg_band = wiphy->bands[band]; |
---|
| 2354 | + if (!cfg_band) |
---|
| 2355 | + continue; |
---|
| 2356 | + |
---|
| 2357 | + cmd->num_channels += cfg_band->n_channels; |
---|
| 2358 | + |
---|
| 2359 | + for (i = 0; i < cfg_band->n_channels; ++i) { |
---|
| 2360 | + qtnf_cmd_channel_tlv_add(cmd_skb, |
---|
| 2361 | + &cfg_band->channels[i]); |
---|
| 2362 | + } |
---|
| 2363 | + } |
---|
| 2364 | + |
---|
| 2365 | + qtnf_bus_lock(bus); |
---|
| 2366 | + ret = qtnf_cmd_send(bus, cmd_skb); |
---|
2635 | 2367 | qtnf_bus_unlock(bus); |
---|
2636 | 2368 | |
---|
2637 | 2369 | return ret; |
---|
2638 | 2370 | } |
---|
2639 | 2371 | |
---|
2640 | | -int qtnf_cmd_get_chan_stats(struct qtnf_wmac *mac, u16 channel, |
---|
2641 | | - struct qtnf_chan_stats *stats) |
---|
| 2372 | +static int |
---|
| 2373 | +qtnf_cmd_resp_proc_chan_stat_info(struct survey_info *survey, |
---|
| 2374 | + const u8 *payload, size_t payload_len) |
---|
| 2375 | +{ |
---|
| 2376 | + const struct qlink_chan_stats *stats = NULL; |
---|
| 2377 | + const struct qlink_tlv_hdr *tlv; |
---|
| 2378 | + u16 tlv_value_len; |
---|
| 2379 | + u16 tlv_type; |
---|
| 2380 | + const u8 *map = NULL; |
---|
| 2381 | + unsigned int map_len = 0; |
---|
| 2382 | + unsigned int stats_len = 0; |
---|
| 2383 | + |
---|
| 2384 | + qlink_for_each_tlv(tlv, payload, payload_len) { |
---|
| 2385 | + tlv_type = le16_to_cpu(tlv->type); |
---|
| 2386 | + tlv_value_len = le16_to_cpu(tlv->len); |
---|
| 2387 | + |
---|
| 2388 | + switch (tlv_type) { |
---|
| 2389 | + case QTN_TLV_ID_BITMAP: |
---|
| 2390 | + map = tlv->val; |
---|
| 2391 | + map_len = tlv_value_len; |
---|
| 2392 | + break; |
---|
| 2393 | + case QTN_TLV_ID_CHANNEL_STATS: |
---|
| 2394 | + stats = (struct qlink_chan_stats *)tlv->val; |
---|
| 2395 | + stats_len = tlv_value_len; |
---|
| 2396 | + break; |
---|
| 2397 | + default: |
---|
| 2398 | + pr_info("Unknown TLV type: %#x\n", tlv_type); |
---|
| 2399 | + break; |
---|
| 2400 | + } |
---|
| 2401 | + } |
---|
| 2402 | + |
---|
| 2403 | + if (!qlink_tlv_parsing_ok(tlv, payload, payload_len)) { |
---|
| 2404 | + pr_err("Malformed TLV buffer\n"); |
---|
| 2405 | + return -EINVAL; |
---|
| 2406 | + } |
---|
| 2407 | + |
---|
| 2408 | + if (!map || !stats) |
---|
| 2409 | + return 0; |
---|
| 2410 | + |
---|
| 2411 | +#define qtnf_chan_stat_avail(stat_name, bitn) \ |
---|
| 2412 | + (qtnf_utils_is_bit_set(map, bitn, map_len) && \ |
---|
| 2413 | + (offsetofend(struct qlink_chan_stats, stat_name) <= stats_len)) |
---|
| 2414 | + |
---|
| 2415 | + if (qtnf_chan_stat_avail(time_on, QLINK_CHAN_STAT_TIME_ON)) { |
---|
| 2416 | + survey->filled |= SURVEY_INFO_TIME; |
---|
| 2417 | + survey->time = le64_to_cpu(stats->time_on); |
---|
| 2418 | + } |
---|
| 2419 | + |
---|
| 2420 | + if (qtnf_chan_stat_avail(time_tx, QLINK_CHAN_STAT_TIME_TX)) { |
---|
| 2421 | + survey->filled |= SURVEY_INFO_TIME_TX; |
---|
| 2422 | + survey->time_tx = le64_to_cpu(stats->time_tx); |
---|
| 2423 | + } |
---|
| 2424 | + |
---|
| 2425 | + if (qtnf_chan_stat_avail(time_rx, QLINK_CHAN_STAT_TIME_RX)) { |
---|
| 2426 | + survey->filled |= SURVEY_INFO_TIME_RX; |
---|
| 2427 | + survey->time_rx = le64_to_cpu(stats->time_rx); |
---|
| 2428 | + } |
---|
| 2429 | + |
---|
| 2430 | + if (qtnf_chan_stat_avail(cca_busy, QLINK_CHAN_STAT_CCA_BUSY)) { |
---|
| 2431 | + survey->filled |= SURVEY_INFO_TIME_BUSY; |
---|
| 2432 | + survey->time_busy = le64_to_cpu(stats->cca_busy); |
---|
| 2433 | + } |
---|
| 2434 | + |
---|
| 2435 | + if (qtnf_chan_stat_avail(cca_busy_ext, QLINK_CHAN_STAT_CCA_BUSY_EXT)) { |
---|
| 2436 | + survey->filled |= SURVEY_INFO_TIME_EXT_BUSY; |
---|
| 2437 | + survey->time_ext_busy = le64_to_cpu(stats->cca_busy_ext); |
---|
| 2438 | + } |
---|
| 2439 | + |
---|
| 2440 | + if (qtnf_chan_stat_avail(time_scan, QLINK_CHAN_STAT_TIME_SCAN)) { |
---|
| 2441 | + survey->filled |= SURVEY_INFO_TIME_SCAN; |
---|
| 2442 | + survey->time_scan = le64_to_cpu(stats->time_scan); |
---|
| 2443 | + } |
---|
| 2444 | + |
---|
| 2445 | + if (qtnf_chan_stat_avail(chan_noise, QLINK_CHAN_STAT_CHAN_NOISE)) { |
---|
| 2446 | + survey->filled |= SURVEY_INFO_NOISE_DBM; |
---|
| 2447 | + survey->noise = stats->chan_noise; |
---|
| 2448 | + } |
---|
| 2449 | + |
---|
| 2450 | +#undef qtnf_chan_stat_avail |
---|
| 2451 | + |
---|
| 2452 | + return 0; |
---|
| 2453 | +} |
---|
| 2454 | + |
---|
| 2455 | +int qtnf_cmd_get_chan_stats(struct qtnf_wmac *mac, u32 chan_freq, |
---|
| 2456 | + struct survey_info *survey) |
---|
2642 | 2457 | { |
---|
2643 | 2458 | struct sk_buff *cmd_skb, *resp_skb = NULL; |
---|
2644 | 2459 | struct qlink_cmd_get_chan_stats *cmd; |
---|
2645 | 2460 | struct qlink_resp_get_chan_stats *resp; |
---|
2646 | | - size_t var_data_len; |
---|
2647 | | - u16 res_code = QLINK_CMD_RESULT_OK; |
---|
| 2461 | + size_t var_data_len = 0; |
---|
2648 | 2462 | int ret = 0; |
---|
2649 | 2463 | |
---|
2650 | 2464 | cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, QLINK_VIFID_RSVD, |
---|
.. | .. |
---|
2653 | 2467 | if (!cmd_skb) |
---|
2654 | 2468 | return -ENOMEM; |
---|
2655 | 2469 | |
---|
2656 | | - qtnf_bus_lock(mac->bus); |
---|
2657 | | - |
---|
2658 | 2470 | cmd = (struct qlink_cmd_get_chan_stats *)cmd_skb->data; |
---|
2659 | | - cmd->channel = cpu_to_le16(channel); |
---|
| 2471 | + cmd->channel_freq = cpu_to_le32(chan_freq); |
---|
2660 | 2472 | |
---|
2661 | | - ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb, &res_code, |
---|
| 2473 | + qtnf_bus_lock(mac->bus); |
---|
| 2474 | + ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb, |
---|
2662 | 2475 | sizeof(*resp), &var_data_len); |
---|
2663 | | - if (unlikely(ret)) { |
---|
2664 | | - qtnf_bus_unlock(mac->bus); |
---|
2665 | | - return ret; |
---|
2666 | | - } |
---|
| 2476 | + qtnf_bus_unlock(mac->bus); |
---|
2667 | 2477 | |
---|
2668 | | - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { |
---|
2669 | | - switch (res_code) { |
---|
2670 | | - case QLINK_CMD_RESULT_ENOTFOUND: |
---|
2671 | | - ret = -ENOENT; |
---|
2672 | | - break; |
---|
2673 | | - default: |
---|
2674 | | - pr_err("cmd exec failed: 0x%.4X\n", res_code); |
---|
2675 | | - ret = -EFAULT; |
---|
2676 | | - break; |
---|
2677 | | - } |
---|
| 2478 | + if (ret) |
---|
| 2479 | + goto out; |
---|
| 2480 | + |
---|
| 2481 | + resp = (struct qlink_resp_get_chan_stats *)resp_skb->data; |
---|
| 2482 | + |
---|
| 2483 | + if (le32_to_cpu(resp->chan_freq) != chan_freq) { |
---|
| 2484 | + pr_err("[MAC%u] channel stats freq %u != requested %u\n", |
---|
| 2485 | + mac->macid, le32_to_cpu(resp->chan_freq), chan_freq); |
---|
| 2486 | + ret = -EINVAL; |
---|
2678 | 2487 | goto out; |
---|
2679 | 2488 | } |
---|
2680 | 2489 | |
---|
2681 | | - resp = (struct qlink_resp_get_chan_stats *)resp_skb->data; |
---|
2682 | | - ret = qtnf_cmd_resp_proc_chan_stat_info(stats, resp->info, |
---|
| 2490 | + ret = qtnf_cmd_resp_proc_chan_stat_info(survey, resp->info, |
---|
2683 | 2491 | var_data_len); |
---|
2684 | 2492 | |
---|
2685 | 2493 | out: |
---|
2686 | | - qtnf_bus_unlock(mac->bus); |
---|
2687 | 2494 | consume_skb(resp_skb); |
---|
| 2495 | + |
---|
2688 | 2496 | return ret; |
---|
2689 | 2497 | } |
---|
2690 | 2498 | |
---|
.. | .. |
---|
2694 | 2502 | struct qtnf_wmac *mac = vif->mac; |
---|
2695 | 2503 | struct qlink_cmd_chan_switch *cmd; |
---|
2696 | 2504 | struct sk_buff *cmd_skb; |
---|
2697 | | - u16 res_code = QLINK_CMD_RESULT_OK; |
---|
2698 | 2505 | int ret; |
---|
| 2506 | + u64 flags = 0; |
---|
2699 | 2507 | |
---|
2700 | 2508 | cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, vif->vifid, |
---|
2701 | 2509 | QLINK_CMD_CHAN_SWITCH, |
---|
.. | .. |
---|
2703 | 2511 | if (!cmd_skb) |
---|
2704 | 2512 | return -ENOMEM; |
---|
2705 | 2513 | |
---|
2706 | | - qtnf_bus_lock(mac->bus); |
---|
| 2514 | + if (params->radar_required) |
---|
| 2515 | + flags |= QLINK_CHAN_SW_RADAR_REQUIRED; |
---|
| 2516 | + |
---|
| 2517 | + if (params->block_tx) |
---|
| 2518 | + flags |= QLINK_CHAN_SW_BLOCK_TX; |
---|
2707 | 2519 | |
---|
2708 | 2520 | cmd = (struct qlink_cmd_chan_switch *)cmd_skb->data; |
---|
2709 | | - cmd->channel = cpu_to_le16(params->chandef.chan->hw_value); |
---|
2710 | | - cmd->radar_required = params->radar_required; |
---|
2711 | | - cmd->block_tx = params->block_tx; |
---|
| 2521 | + qlink_chandef_cfg2q(¶ms->chandef, &cmd->channel); |
---|
| 2522 | + cmd->flags = cpu_to_le64(flags); |
---|
2712 | 2523 | cmd->beacon_count = params->count; |
---|
2713 | 2524 | |
---|
2714 | | - ret = qtnf_cmd_send(mac->bus, cmd_skb, &res_code); |
---|
2715 | | - |
---|
2716 | | - if (unlikely(ret)) |
---|
2717 | | - goto out; |
---|
2718 | | - |
---|
2719 | | - switch (res_code) { |
---|
2720 | | - case QLINK_CMD_RESULT_OK: |
---|
2721 | | - ret = 0; |
---|
2722 | | - break; |
---|
2723 | | - case QLINK_CMD_RESULT_ENOTFOUND: |
---|
2724 | | - ret = -ENOENT; |
---|
2725 | | - break; |
---|
2726 | | - case QLINK_CMD_RESULT_ENOTSUPP: |
---|
2727 | | - ret = -EOPNOTSUPP; |
---|
2728 | | - break; |
---|
2729 | | - case QLINK_CMD_RESULT_EALREADY: |
---|
2730 | | - ret = -EALREADY; |
---|
2731 | | - break; |
---|
2732 | | - case QLINK_CMD_RESULT_INVALID: |
---|
2733 | | - default: |
---|
2734 | | - ret = -EFAULT; |
---|
2735 | | - break; |
---|
2736 | | - } |
---|
2737 | | - |
---|
2738 | | -out: |
---|
| 2525 | + qtnf_bus_lock(mac->bus); |
---|
| 2526 | + ret = qtnf_cmd_send(mac->bus, cmd_skb); |
---|
2739 | 2527 | qtnf_bus_unlock(mac->bus); |
---|
| 2528 | + |
---|
2740 | 2529 | return ret; |
---|
2741 | 2530 | } |
---|
2742 | 2531 | |
---|
.. | .. |
---|
2746 | 2535 | const struct qlink_resp_channel_get *resp; |
---|
2747 | 2536 | struct sk_buff *cmd_skb; |
---|
2748 | 2537 | struct sk_buff *resp_skb = NULL; |
---|
2749 | | - u16 res_code = QLINK_CMD_RESULT_OK; |
---|
2750 | 2538 | int ret; |
---|
2751 | 2539 | |
---|
2752 | 2540 | cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, |
---|
.. | .. |
---|
2756 | 2544 | return -ENOMEM; |
---|
2757 | 2545 | |
---|
2758 | 2546 | qtnf_bus_lock(bus); |
---|
2759 | | - |
---|
2760 | | - ret = qtnf_cmd_send_with_reply(bus, cmd_skb, &resp_skb, &res_code, |
---|
| 2547 | + ret = qtnf_cmd_send_with_reply(bus, cmd_skb, &resp_skb, |
---|
2761 | 2548 | sizeof(*resp), NULL); |
---|
2762 | | - |
---|
2763 | | - qtnf_bus_unlock(bus); |
---|
2764 | | - |
---|
2765 | | - if (unlikely(ret)) |
---|
| 2549 | + if (ret) |
---|
2766 | 2550 | goto out; |
---|
2767 | | - |
---|
2768 | | - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { |
---|
2769 | | - ret = -ENODATA; |
---|
2770 | | - goto out; |
---|
2771 | | - } |
---|
2772 | 2551 | |
---|
2773 | 2552 | resp = (const struct qlink_resp_channel_get *)resp_skb->data; |
---|
2774 | 2553 | qlink_chandef_q2cfg(priv_to_wiphy(vif->mac), &resp->chan, chdef); |
---|
2775 | 2554 | |
---|
2776 | 2555 | out: |
---|
| 2556 | + qtnf_bus_unlock(bus); |
---|
2777 | 2557 | consume_skb(resp_skb); |
---|
| 2558 | + |
---|
2778 | 2559 | return ret; |
---|
2779 | 2560 | } |
---|
2780 | 2561 | |
---|
.. | .. |
---|
2786 | 2567 | struct sk_buff *cmd_skb; |
---|
2787 | 2568 | struct qlink_cmd_start_cac *cmd; |
---|
2788 | 2569 | int ret; |
---|
2789 | | - u16 res_code; |
---|
2790 | 2570 | |
---|
2791 | 2571 | cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, |
---|
2792 | 2572 | QLINK_CMD_START_CAC, |
---|
.. | .. |
---|
2799 | 2579 | qlink_chandef_cfg2q(chdef, &cmd->chan); |
---|
2800 | 2580 | |
---|
2801 | 2581 | qtnf_bus_lock(bus); |
---|
2802 | | - ret = qtnf_cmd_send(bus, cmd_skb, &res_code); |
---|
2803 | | - qtnf_bus_unlock(bus); |
---|
2804 | | - |
---|
| 2582 | + ret = qtnf_cmd_send(bus, cmd_skb); |
---|
2805 | 2583 | if (ret) |
---|
2806 | | - return ret; |
---|
| 2584 | + goto out; |
---|
2807 | 2585 | |
---|
2808 | | - switch (res_code) { |
---|
2809 | | - case QLINK_CMD_RESULT_OK: |
---|
2810 | | - break; |
---|
2811 | | - default: |
---|
2812 | | - ret = -EOPNOTSUPP; |
---|
2813 | | - break; |
---|
2814 | | - } |
---|
| 2586 | +out: |
---|
| 2587 | + qtnf_bus_unlock(bus); |
---|
2815 | 2588 | |
---|
2816 | 2589 | return ret; |
---|
2817 | 2590 | } |
---|
.. | .. |
---|
2822 | 2595 | struct qtnf_bus *bus = vif->mac->bus; |
---|
2823 | 2596 | struct sk_buff *cmd_skb; |
---|
2824 | 2597 | struct qlink_tlv_hdr *tlv; |
---|
2825 | | - size_t acl_size = qtnf_cmd_acl_data_size(params); |
---|
2826 | | - u16 res_code; |
---|
| 2598 | + size_t acl_size = struct_size(params, mac_addrs, params->n_acl_entries); |
---|
2827 | 2599 | int ret; |
---|
2828 | 2600 | |
---|
2829 | 2601 | cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, |
---|
.. | .. |
---|
2832 | 2604 | if (!cmd_skb) |
---|
2833 | 2605 | return -ENOMEM; |
---|
2834 | 2606 | |
---|
2835 | | - tlv = skb_put(cmd_skb, sizeof(*tlv) + acl_size); |
---|
| 2607 | + tlv = skb_put(cmd_skb, sizeof(*tlv) + round_up(acl_size, QLINK_ALIGN)); |
---|
2836 | 2608 | tlv->type = cpu_to_le16(QTN_TLV_ID_ACL_DATA); |
---|
2837 | 2609 | tlv->len = cpu_to_le16(acl_size); |
---|
2838 | 2610 | qlink_acl_data_cfg2q(params, (struct qlink_acl_data *)tlv->val); |
---|
2839 | 2611 | |
---|
2840 | 2612 | qtnf_bus_lock(bus); |
---|
2841 | | - ret = qtnf_cmd_send(bus, cmd_skb, &res_code); |
---|
| 2613 | + ret = qtnf_cmd_send(bus, cmd_skb); |
---|
| 2614 | + if (ret) |
---|
| 2615 | + goto out; |
---|
| 2616 | + |
---|
| 2617 | +out: |
---|
2842 | 2618 | qtnf_bus_unlock(bus); |
---|
2843 | | - |
---|
2844 | | - if (unlikely(ret)) |
---|
2845 | | - return ret; |
---|
2846 | | - |
---|
2847 | | - switch (res_code) { |
---|
2848 | | - case QLINK_CMD_RESULT_OK: |
---|
2849 | | - break; |
---|
2850 | | - case QLINK_CMD_RESULT_INVALID: |
---|
2851 | | - ret = -EINVAL; |
---|
2852 | | - break; |
---|
2853 | | - default: |
---|
2854 | | - ret = -EOPNOTSUPP; |
---|
2855 | | - break; |
---|
2856 | | - } |
---|
2857 | 2619 | |
---|
2858 | 2620 | return ret; |
---|
2859 | 2621 | } |
---|
.. | .. |
---|
2862 | 2624 | { |
---|
2863 | 2625 | struct qtnf_bus *bus = vif->mac->bus; |
---|
2864 | 2626 | struct sk_buff *cmd_skb; |
---|
2865 | | - u16 res_code = QLINK_CMD_RESULT_OK; |
---|
2866 | 2627 | struct qlink_cmd_pm_set *cmd; |
---|
2867 | 2628 | int ret = 0; |
---|
2868 | 2629 | |
---|
.. | .. |
---|
2877 | 2638 | |
---|
2878 | 2639 | qtnf_bus_lock(bus); |
---|
2879 | 2640 | |
---|
2880 | | - ret = qtnf_cmd_send(bus, cmd_skb, &res_code); |
---|
2881 | | - |
---|
2882 | | - if (unlikely(ret)) |
---|
| 2641 | + ret = qtnf_cmd_send(bus, cmd_skb); |
---|
| 2642 | + if (ret) |
---|
2883 | 2643 | goto out; |
---|
2884 | | - |
---|
2885 | | - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { |
---|
2886 | | - pr_err("cmd exec failed: 0x%.4X\n", res_code); |
---|
2887 | | - ret = -EFAULT; |
---|
2888 | | - } |
---|
2889 | 2644 | |
---|
2890 | 2645 | out: |
---|
2891 | 2646 | qtnf_bus_unlock(bus); |
---|
| 2647 | + |
---|
| 2648 | + return ret; |
---|
| 2649 | +} |
---|
| 2650 | + |
---|
| 2651 | +int qtnf_cmd_get_tx_power(const struct qtnf_vif *vif, int *dbm) |
---|
| 2652 | +{ |
---|
| 2653 | + struct qtnf_bus *bus = vif->mac->bus; |
---|
| 2654 | + const struct qlink_resp_txpwr *resp; |
---|
| 2655 | + struct sk_buff *resp_skb = NULL; |
---|
| 2656 | + struct qlink_cmd_txpwr *cmd; |
---|
| 2657 | + struct sk_buff *cmd_skb; |
---|
| 2658 | + int ret = 0; |
---|
| 2659 | + |
---|
| 2660 | + cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, |
---|
| 2661 | + QLINK_CMD_TXPWR, sizeof(*cmd)); |
---|
| 2662 | + if (!cmd_skb) |
---|
| 2663 | + return -ENOMEM; |
---|
| 2664 | + |
---|
| 2665 | + cmd = (struct qlink_cmd_txpwr *)cmd_skb->data; |
---|
| 2666 | + cmd->op_type = QLINK_TXPWR_GET; |
---|
| 2667 | + |
---|
| 2668 | + qtnf_bus_lock(bus); |
---|
| 2669 | + |
---|
| 2670 | + ret = qtnf_cmd_send_with_reply(bus, cmd_skb, &resp_skb, |
---|
| 2671 | + sizeof(*resp), NULL); |
---|
| 2672 | + if (ret) |
---|
| 2673 | + goto out; |
---|
| 2674 | + |
---|
| 2675 | + resp = (const struct qlink_resp_txpwr *)resp_skb->data; |
---|
| 2676 | + *dbm = MBM_TO_DBM(le32_to_cpu(resp->txpwr)); |
---|
| 2677 | + |
---|
| 2678 | +out: |
---|
| 2679 | + qtnf_bus_unlock(bus); |
---|
| 2680 | + consume_skb(resp_skb); |
---|
| 2681 | + |
---|
| 2682 | + return ret; |
---|
| 2683 | +} |
---|
| 2684 | + |
---|
| 2685 | +int qtnf_cmd_set_tx_power(const struct qtnf_vif *vif, |
---|
| 2686 | + enum nl80211_tx_power_setting type, int mbm) |
---|
| 2687 | +{ |
---|
| 2688 | + struct qtnf_bus *bus = vif->mac->bus; |
---|
| 2689 | + const struct qlink_resp_txpwr *resp; |
---|
| 2690 | + struct sk_buff *resp_skb = NULL; |
---|
| 2691 | + struct qlink_cmd_txpwr *cmd; |
---|
| 2692 | + struct sk_buff *cmd_skb; |
---|
| 2693 | + int ret = 0; |
---|
| 2694 | + |
---|
| 2695 | + cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, |
---|
| 2696 | + QLINK_CMD_TXPWR, sizeof(*cmd)); |
---|
| 2697 | + if (!cmd_skb) |
---|
| 2698 | + return -ENOMEM; |
---|
| 2699 | + |
---|
| 2700 | + cmd = (struct qlink_cmd_txpwr *)cmd_skb->data; |
---|
| 2701 | + cmd->op_type = QLINK_TXPWR_SET; |
---|
| 2702 | + cmd->txpwr_setting = type; |
---|
| 2703 | + cmd->txpwr = cpu_to_le32(mbm); |
---|
| 2704 | + |
---|
| 2705 | + qtnf_bus_lock(bus); |
---|
| 2706 | + |
---|
| 2707 | + ret = qtnf_cmd_send_with_reply(bus, cmd_skb, &resp_skb, |
---|
| 2708 | + sizeof(*resp), NULL); |
---|
| 2709 | + |
---|
| 2710 | + qtnf_bus_unlock(bus); |
---|
| 2711 | + consume_skb(resp_skb); |
---|
| 2712 | + |
---|
2892 | 2713 | return ret; |
---|
2893 | 2714 | } |
---|
2894 | 2715 | |
---|
.. | .. |
---|
2897 | 2718 | { |
---|
2898 | 2719 | struct qtnf_bus *bus = vif->mac->bus; |
---|
2899 | 2720 | struct sk_buff *cmd_skb; |
---|
2900 | | - u16 res_code = QLINK_CMD_RESULT_OK; |
---|
2901 | 2721 | struct qlink_cmd_wowlan_set *cmd; |
---|
2902 | 2722 | u32 triggers = 0; |
---|
2903 | 2723 | int count = 0; |
---|
.. | .. |
---|
2933 | 2753 | |
---|
2934 | 2754 | cmd->triggers = cpu_to_le32(triggers); |
---|
2935 | 2755 | |
---|
2936 | | - ret = qtnf_cmd_send(bus, cmd_skb, &res_code); |
---|
2937 | | - |
---|
2938 | | - if (unlikely(ret)) |
---|
| 2756 | + ret = qtnf_cmd_send(bus, cmd_skb); |
---|
| 2757 | + if (ret) |
---|
2939 | 2758 | goto out; |
---|
2940 | | - |
---|
2941 | | - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { |
---|
2942 | | - pr_err("cmd exec failed: 0x%.4X\n", res_code); |
---|
2943 | | - ret = -EFAULT; |
---|
2944 | | - } |
---|
2945 | 2759 | |
---|
2946 | 2760 | out: |
---|
2947 | 2761 | qtnf_bus_unlock(bus); |
---|
2948 | 2762 | return ret; |
---|
2949 | 2763 | } |
---|
| 2764 | + |
---|
| 2765 | +int qtnf_cmd_netdev_changeupper(const struct qtnf_vif *vif, int br_domain) |
---|
| 2766 | +{ |
---|
| 2767 | + struct qtnf_bus *bus = vif->mac->bus; |
---|
| 2768 | + struct sk_buff *cmd_skb; |
---|
| 2769 | + struct qlink_cmd_ndev_changeupper *cmd; |
---|
| 2770 | + int ret; |
---|
| 2771 | + |
---|
| 2772 | + cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, |
---|
| 2773 | + QLINK_CMD_NDEV_EVENT, |
---|
| 2774 | + sizeof(*cmd)); |
---|
| 2775 | + if (!cmd_skb) |
---|
| 2776 | + return -ENOMEM; |
---|
| 2777 | + |
---|
| 2778 | + pr_debug("[VIF%u.%u] set broadcast domain to %d\n", |
---|
| 2779 | + vif->mac->macid, vif->vifid, br_domain); |
---|
| 2780 | + |
---|
| 2781 | + cmd = (struct qlink_cmd_ndev_changeupper *)cmd_skb->data; |
---|
| 2782 | + cmd->nehdr.event = cpu_to_le16(QLINK_NDEV_EVENT_CHANGEUPPER); |
---|
| 2783 | + cmd->upper_type = QLINK_NDEV_UPPER_TYPE_BRIDGE; |
---|
| 2784 | + cmd->br_domain = cpu_to_le32(br_domain); |
---|
| 2785 | + |
---|
| 2786 | + qtnf_bus_lock(bus); |
---|
| 2787 | + ret = qtnf_cmd_send(bus, cmd_skb); |
---|
| 2788 | + qtnf_bus_unlock(bus); |
---|
| 2789 | + |
---|
| 2790 | + if (ret) |
---|
| 2791 | + pr_err("[VIF%u.%u] failed to set broadcast domain\n", |
---|
| 2792 | + vif->mac->macid, vif->vifid); |
---|
| 2793 | + |
---|
| 2794 | + return ret; |
---|
| 2795 | +} |
---|
| 2796 | + |
---|
| 2797 | +int qtnf_cmd_send_update_owe(struct qtnf_vif *vif, |
---|
| 2798 | + struct cfg80211_update_owe_info *owe) |
---|
| 2799 | +{ |
---|
| 2800 | + struct qlink_cmd_update_owe *cmd; |
---|
| 2801 | + struct sk_buff *cmd_skb; |
---|
| 2802 | + int ret; |
---|
| 2803 | + |
---|
| 2804 | + if (sizeof(*cmd) + owe->ie_len > QTNF_MAX_CMD_BUF_SIZE) { |
---|
| 2805 | + pr_warn("VIF%u.%u: OWE update IEs too big: %zu\n", |
---|
| 2806 | + vif->mac->macid, vif->vifid, owe->ie_len); |
---|
| 2807 | + return -E2BIG; |
---|
| 2808 | + } |
---|
| 2809 | + |
---|
| 2810 | + cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, |
---|
| 2811 | + QLINK_CMD_UPDATE_OWE, |
---|
| 2812 | + sizeof(*cmd)); |
---|
| 2813 | + if (!cmd_skb) |
---|
| 2814 | + return -ENOMEM; |
---|
| 2815 | + |
---|
| 2816 | + cmd = (struct qlink_cmd_update_owe *)cmd_skb->data; |
---|
| 2817 | + ether_addr_copy(cmd->peer, owe->peer); |
---|
| 2818 | + cmd->status = cpu_to_le16(owe->status); |
---|
| 2819 | + if (owe->ie_len && owe->ie) |
---|
| 2820 | + qtnf_cmd_skb_put_buffer(cmd_skb, owe->ie, owe->ie_len); |
---|
| 2821 | + |
---|
| 2822 | + qtnf_bus_lock(vif->mac->bus); |
---|
| 2823 | + ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); |
---|
| 2824 | + if (ret) |
---|
| 2825 | + goto out; |
---|
| 2826 | + |
---|
| 2827 | +out: |
---|
| 2828 | + qtnf_bus_unlock(vif->mac->bus); |
---|
| 2829 | + |
---|
| 2830 | + return ret; |
---|
| 2831 | +} |
---|