diff options
author | John W. Linville <linville@tuxdriver.com> | 2012-11-28 10:56:03 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-11-28 10:56:03 -0500 |
commit | 79d38f7d6cf545ff838dd5227869f3916d1d100d (patch) | |
tree | 859c8071aab68fd32f36ffb9ebc04cf12db6e5e0 /net | |
parent | 03f52a0a554210d5049eeed9f1bb29047dc807cb (diff) | |
parent | 0751f8654602e4255f0b9c17784d8100d5896010 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
Conflicts:
drivers/net/wireless/iwlwifi/pcie/tx.c
Diffstat (limited to 'net')
66 files changed, 3960 insertions, 1521 deletions
diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig index 1c11d0dcd86..d3f3f7b1d32 100644 --- a/net/bluetooth/Kconfig +++ b/net/bluetooth/Kconfig | |||
@@ -48,4 +48,3 @@ source "net/bluetooth/cmtp/Kconfig" | |||
48 | source "net/bluetooth/hidp/Kconfig" | 48 | source "net/bluetooth/hidp/Kconfig" |
49 | 49 | ||
50 | source "drivers/bluetooth/Kconfig" | 50 | source "drivers/bluetooth/Kconfig" |
51 | |||
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index d5136cfb57e..2f67d5ecc90 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c | |||
@@ -423,7 +423,7 @@ static int a2mp_getampassoc_rsp(struct amp_mgr *mgr, struct sk_buff *skb, | |||
423 | 423 | ||
424 | BT_DBG("Created hcon %p: loc:%d -> rem:%d", hcon, hdev->id, rsp->id); | 424 | BT_DBG("Created hcon %p: loc:%d -> rem:%d", hcon, hdev->id, rsp->id); |
425 | 425 | ||
426 | mgr->bredr_chan->ctrl_id = rsp->id; | 426 | mgr->bredr_chan->remote_amp_id = rsp->id; |
427 | 427 | ||
428 | amp_create_phylink(hdev, mgr, hcon); | 428 | amp_create_phylink(hdev, mgr, hcon); |
429 | 429 | ||
@@ -939,7 +939,7 @@ void a2mp_send_create_phy_link_req(struct hci_dev *hdev, u8 status) | |||
939 | goto clean; | 939 | goto clean; |
940 | 940 | ||
941 | req->local_id = hdev->id; | 941 | req->local_id = hdev->id; |
942 | req->remote_id = bredr_chan->ctrl_id; | 942 | req->remote_id = bredr_chan->remote_amp_id; |
943 | memcpy(req->amp_assoc, loc_assoc->data, loc_assoc->len); | 943 | memcpy(req->amp_assoc, loc_assoc->data, loc_assoc->len); |
944 | 944 | ||
945 | a2mp_send(mgr, A2MP_CREATEPHYSLINK_REQ, __next_ident(mgr), len, req); | 945 | a2mp_send(mgr, A2MP_CREATEPHYSLINK_REQ, __next_ident(mgr), len, req); |
diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c index 231d7ef53ec..1b0d92c0643 100644 --- a/net/bluetooth/amp.c +++ b/net/bluetooth/amp.c | |||
@@ -372,3 +372,100 @@ void amp_accept_phylink(struct hci_dev *hdev, struct amp_mgr *mgr, | |||
372 | 372 | ||
373 | hci_send_cmd(hdev, HCI_OP_ACCEPT_PHY_LINK, sizeof(cp), &cp); | 373 | hci_send_cmd(hdev, HCI_OP_ACCEPT_PHY_LINK, sizeof(cp), &cp); |
374 | } | 374 | } |
375 | |||
376 | void amp_physical_cfm(struct hci_conn *bredr_hcon, struct hci_conn *hs_hcon) | ||
377 | { | ||
378 | struct hci_dev *bredr_hdev = hci_dev_hold(bredr_hcon->hdev); | ||
379 | struct amp_mgr *mgr = hs_hcon->amp_mgr; | ||
380 | struct l2cap_chan *bredr_chan; | ||
381 | |||
382 | BT_DBG("bredr_hcon %p hs_hcon %p mgr %p", bredr_hcon, hs_hcon, mgr); | ||
383 | |||
384 | if (!bredr_hdev || !mgr || !mgr->bredr_chan) | ||
385 | return; | ||
386 | |||
387 | bredr_chan = mgr->bredr_chan; | ||
388 | |||
389 | l2cap_chan_lock(bredr_chan); | ||
390 | |||
391 | set_bit(FLAG_EFS_ENABLE, &bredr_chan->flags); | ||
392 | bredr_chan->remote_amp_id = hs_hcon->remote_id; | ||
393 | bredr_chan->local_amp_id = hs_hcon->hdev->id; | ||
394 | bredr_chan->hs_hcon = hs_hcon; | ||
395 | bredr_chan->conn->mtu = hs_hcon->hdev->block_mtu; | ||
396 | |||
397 | __l2cap_physical_cfm(bredr_chan, 0); | ||
398 | |||
399 | l2cap_chan_unlock(bredr_chan); | ||
400 | |||
401 | hci_dev_put(bredr_hdev); | ||
402 | } | ||
403 | |||
404 | void amp_create_logical_link(struct l2cap_chan *chan) | ||
405 | { | ||
406 | struct hci_cp_create_accept_logical_link cp; | ||
407 | struct hci_conn *hcon; | ||
408 | struct hci_dev *hdev; | ||
409 | |||
410 | BT_DBG("chan %p", chan); | ||
411 | |||
412 | if (!chan->hs_hcon) | ||
413 | return; | ||
414 | |||
415 | hdev = hci_dev_hold(chan->hs_hcon->hdev); | ||
416 | if (!hdev) | ||
417 | return; | ||
418 | |||
419 | BT_DBG("chan %p dst %pMR", chan, chan->conn->dst); | ||
420 | |||
421 | hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK, chan->conn->dst); | ||
422 | if (!hcon) | ||
423 | goto done; | ||
424 | |||
425 | cp.phy_handle = hcon->handle; | ||
426 | |||
427 | cp.tx_flow_spec.id = chan->local_id; | ||
428 | cp.tx_flow_spec.stype = chan->local_stype; | ||
429 | cp.tx_flow_spec.msdu = cpu_to_le16(chan->local_msdu); | ||
430 | cp.tx_flow_spec.sdu_itime = cpu_to_le32(chan->local_sdu_itime); | ||
431 | cp.tx_flow_spec.acc_lat = cpu_to_le32(chan->local_acc_lat); | ||
432 | cp.tx_flow_spec.flush_to = cpu_to_le32(chan->local_flush_to); | ||
433 | |||
434 | cp.rx_flow_spec.id = chan->remote_id; | ||
435 | cp.rx_flow_spec.stype = chan->remote_stype; | ||
436 | cp.rx_flow_spec.msdu = cpu_to_le16(chan->remote_msdu); | ||
437 | cp.rx_flow_spec.sdu_itime = cpu_to_le32(chan->remote_sdu_itime); | ||
438 | cp.rx_flow_spec.acc_lat = cpu_to_le32(chan->remote_acc_lat); | ||
439 | cp.rx_flow_spec.flush_to = cpu_to_le32(chan->remote_flush_to); | ||
440 | |||
441 | if (hcon->out) | ||
442 | hci_send_cmd(hdev, HCI_OP_CREATE_LOGICAL_LINK, sizeof(cp), | ||
443 | &cp); | ||
444 | else | ||
445 | hci_send_cmd(hdev, HCI_OP_ACCEPT_LOGICAL_LINK, sizeof(cp), | ||
446 | &cp); | ||
447 | |||
448 | done: | ||
449 | hci_dev_put(hdev); | ||
450 | } | ||
451 | |||
452 | void amp_disconnect_logical_link(struct hci_chan *hchan) | ||
453 | { | ||
454 | struct hci_conn *hcon = hchan->conn; | ||
455 | struct hci_cp_disconn_logical_link cp; | ||
456 | |||
457 | if (hcon->state != BT_CONNECTED) { | ||
458 | BT_DBG("hchan %p not connected", hchan); | ||
459 | return; | ||
460 | } | ||
461 | |||
462 | cp.log_handle = cpu_to_le16(hchan->handle); | ||
463 | hci_send_cmd(hcon->hdev, HCI_OP_DISCONN_LOGICAL_LINK, sizeof(cp), &cp); | ||
464 | } | ||
465 | |||
466 | void amp_destroy_logical_link(struct hci_chan *hchan, u8 reason) | ||
467 | { | ||
468 | BT_DBG("hchan %p", hchan); | ||
469 | |||
470 | hci_chan_del(hchan); | ||
471 | } | ||
diff --git a/net/bluetooth/bnep/netdev.c b/net/bluetooth/bnep/netdev.c index 98f86f91d47..e58c8b32589 100644 --- a/net/bluetooth/bnep/netdev.c +++ b/net/bluetooth/bnep/netdev.c | |||
@@ -25,7 +25,6 @@ | |||
25 | SOFTWARE IS DISCLAIMED. | 25 | SOFTWARE IS DISCLAIMED. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | #include <linux/export.h> | ||
29 | #include <linux/etherdevice.h> | 28 | #include <linux/etherdevice.h> |
30 | 29 | ||
31 | #include <net/bluetooth/bluetooth.h> | 30 | #include <net/bluetooth/bluetooth.h> |
diff --git a/net/bluetooth/cmtp/capi.c b/net/bluetooth/cmtp/capi.c index 50f0d135eb8..a4a9d4b6816 100644 --- a/net/bluetooth/cmtp/capi.c +++ b/net/bluetooth/cmtp/capi.c | |||
@@ -20,7 +20,7 @@ | |||
20 | SOFTWARE IS DISCLAIMED. | 20 | SOFTWARE IS DISCLAIMED. |
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <linux/module.h> | 23 | #include <linux/export.h> |
24 | #include <linux/proc_fs.h> | 24 | #include <linux/proc_fs.h> |
25 | #include <linux/seq_file.h> | 25 | #include <linux/seq_file.h> |
26 | #include <linux/types.h> | 26 | #include <linux/types.h> |
diff --git a/net/bluetooth/cmtp/sock.c b/net/bluetooth/cmtp/sock.c index aacb802d1ee..1c57482112b 100644 --- a/net/bluetooth/cmtp/sock.c +++ b/net/bluetooth/cmtp/sock.c | |||
@@ -20,7 +20,7 @@ | |||
20 | SOFTWARE IS DISCLAIMED. | 20 | SOFTWARE IS DISCLAIMED. |
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <linux/module.h> | 23 | #include <linux/export.h> |
24 | 24 | ||
25 | #include <linux/types.h> | 25 | #include <linux/types.h> |
26 | #include <linux/capability.h> | 26 | #include <linux/capability.h> |
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index fe646211c61..25bfce0666e 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -502,6 +502,9 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, | |||
502 | { | 502 | { |
503 | struct hci_conn *le; | 503 | struct hci_conn *le; |
504 | 504 | ||
505 | if (test_bit(HCI_LE_PERIPHERAL, &hdev->flags)) | ||
506 | return ERR_PTR(-ENOTSUPP); | ||
507 | |||
505 | le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst); | 508 | le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst); |
506 | if (!le) { | 509 | if (!le) { |
507 | le = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); | 510 | le = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); |
@@ -959,6 +962,7 @@ struct hci_chan *hci_chan_create(struct hci_conn *conn) | |||
959 | 962 | ||
960 | chan->conn = conn; | 963 | chan->conn = conn; |
961 | skb_queue_head_init(&chan->data_q); | 964 | skb_queue_head_init(&chan->data_q); |
965 | chan->state = BT_CONNECTED; | ||
962 | 966 | ||
963 | list_add_rcu(&chan->list, &conn->chan_list); | 967 | list_add_rcu(&chan->list, &conn->chan_list); |
964 | 968 | ||
@@ -976,6 +980,8 @@ void hci_chan_del(struct hci_chan *chan) | |||
976 | 980 | ||
977 | synchronize_rcu(); | 981 | synchronize_rcu(); |
978 | 982 | ||
983 | hci_conn_put(conn); | ||
984 | |||
979 | skb_queue_purge(&chan->data_q); | 985 | skb_queue_purge(&chan->data_q); |
980 | kfree(chan); | 986 | kfree(chan); |
981 | } | 987 | } |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index f01e5e135b9..7140f83328a 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -178,48 +178,13 @@ static void hci_reset_req(struct hci_dev *hdev, unsigned long opt) | |||
178 | 178 | ||
179 | static void bredr_init(struct hci_dev *hdev) | 179 | static void bredr_init(struct hci_dev *hdev) |
180 | { | 180 | { |
181 | struct hci_cp_delete_stored_link_key cp; | ||
182 | __le16 param; | ||
183 | __u8 flt_type; | ||
184 | |||
185 | hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_PACKET_BASED; | 181 | hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_PACKET_BASED; |
186 | 182 | ||
187 | /* Mandatory initialization */ | ||
188 | |||
189 | /* Read Local Supported Features */ | 183 | /* Read Local Supported Features */ |
190 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_FEATURES, 0, NULL); | 184 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_FEATURES, 0, NULL); |
191 | 185 | ||
192 | /* Read Local Version */ | 186 | /* Read Local Version */ |
193 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL); | 187 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL); |
194 | |||
195 | /* Read Buffer Size (ACL mtu, max pkt, etc.) */ | ||
196 | hci_send_cmd(hdev, HCI_OP_READ_BUFFER_SIZE, 0, NULL); | ||
197 | |||
198 | /* Read BD Address */ | ||
199 | hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL); | ||
200 | |||
201 | /* Read Class of Device */ | ||
202 | hci_send_cmd(hdev, HCI_OP_READ_CLASS_OF_DEV, 0, NULL); | ||
203 | |||
204 | /* Read Local Name */ | ||
205 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL); | ||
206 | |||
207 | /* Read Voice Setting */ | ||
208 | hci_send_cmd(hdev, HCI_OP_READ_VOICE_SETTING, 0, NULL); | ||
209 | |||
210 | /* Optional initialization */ | ||
211 | |||
212 | /* Clear Event Filters */ | ||
213 | flt_type = HCI_FLT_CLEAR_ALL; | ||
214 | hci_send_cmd(hdev, HCI_OP_SET_EVENT_FLT, 1, &flt_type); | ||
215 | |||
216 | /* Connection accept timeout ~20 secs */ | ||
217 | param = __constant_cpu_to_le16(0x7d00); | ||
218 | hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, ¶m); | ||
219 | |||
220 | bacpy(&cp.bdaddr, BDADDR_ANY); | ||
221 | cp.delete_all = 1; | ||
222 | hci_send_cmd(hdev, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp); | ||
223 | } | 188 | } |
224 | 189 | ||
225 | static void amp_init(struct hci_dev *hdev) | 190 | static void amp_init(struct hci_dev *hdev) |
@@ -273,14 +238,6 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt) | |||
273 | } | 238 | } |
274 | } | 239 | } |
275 | 240 | ||
276 | static void hci_le_init_req(struct hci_dev *hdev, unsigned long opt) | ||
277 | { | ||
278 | BT_DBG("%s", hdev->name); | ||
279 | |||
280 | /* Read LE buffer size */ | ||
281 | hci_send_cmd(hdev, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL); | ||
282 | } | ||
283 | |||
284 | static void hci_scan_req(struct hci_dev *hdev, unsigned long opt) | 241 | static void hci_scan_req(struct hci_dev *hdev, unsigned long opt) |
285 | { | 242 | { |
286 | __u8 scan = opt; | 243 | __u8 scan = opt; |
@@ -477,6 +434,8 @@ bool hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data, | |||
477 | 434 | ||
478 | BT_DBG("cache %p, %pMR", cache, &data->bdaddr); | 435 | BT_DBG("cache %p, %pMR", cache, &data->bdaddr); |
479 | 436 | ||
437 | hci_remove_remote_oob_data(hdev, &data->bdaddr); | ||
438 | |||
480 | if (ssp) | 439 | if (ssp) |
481 | *ssp = data->ssp_mode; | 440 | *ssp = data->ssp_mode; |
482 | 441 | ||
@@ -637,6 +596,99 @@ done: | |||
637 | return err; | 596 | return err; |
638 | } | 597 | } |
639 | 598 | ||
599 | static u8 create_ad(struct hci_dev *hdev, u8 *ptr) | ||
600 | { | ||
601 | u8 ad_len = 0, flags = 0; | ||
602 | size_t name_len; | ||
603 | |||
604 | if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags)) | ||
605 | flags |= LE_AD_GENERAL; | ||
606 | |||
607 | if (!lmp_bredr_capable(hdev)) | ||
608 | flags |= LE_AD_NO_BREDR; | ||
609 | |||
610 | if (lmp_le_br_capable(hdev)) | ||
611 | flags |= LE_AD_SIM_LE_BREDR_CTRL; | ||
612 | |||
613 | if (lmp_host_le_br_capable(hdev)) | ||
614 | flags |= LE_AD_SIM_LE_BREDR_HOST; | ||
615 | |||
616 | if (flags) { | ||
617 | BT_DBG("adv flags 0x%02x", flags); | ||
618 | |||
619 | ptr[0] = 2; | ||
620 | ptr[1] = EIR_FLAGS; | ||
621 | ptr[2] = flags; | ||
622 | |||
623 | ad_len += 3; | ||
624 | ptr += 3; | ||
625 | } | ||
626 | |||
627 | if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) { | ||
628 | ptr[0] = 2; | ||
629 | ptr[1] = EIR_TX_POWER; | ||
630 | ptr[2] = (u8) hdev->adv_tx_power; | ||
631 | |||
632 | ad_len += 3; | ||
633 | ptr += 3; | ||
634 | } | ||
635 | |||
636 | name_len = strlen(hdev->dev_name); | ||
637 | if (name_len > 0) { | ||
638 | size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2; | ||
639 | |||
640 | if (name_len > max_len) { | ||
641 | name_len = max_len; | ||
642 | ptr[1] = EIR_NAME_SHORT; | ||
643 | } else | ||
644 | ptr[1] = EIR_NAME_COMPLETE; | ||
645 | |||
646 | ptr[0] = name_len + 1; | ||
647 | |||
648 | memcpy(ptr + 2, hdev->dev_name, name_len); | ||
649 | |||
650 | ad_len += (name_len + 2); | ||
651 | ptr += (name_len + 2); | ||
652 | } | ||
653 | |||
654 | return ad_len; | ||
655 | } | ||
656 | |||
657 | int hci_update_ad(struct hci_dev *hdev) | ||
658 | { | ||
659 | struct hci_cp_le_set_adv_data cp; | ||
660 | u8 len; | ||
661 | int err; | ||
662 | |||
663 | hci_dev_lock(hdev); | ||
664 | |||
665 | if (!lmp_le_capable(hdev)) { | ||
666 | err = -EINVAL; | ||
667 | goto unlock; | ||
668 | } | ||
669 | |||
670 | memset(&cp, 0, sizeof(cp)); | ||
671 | |||
672 | len = create_ad(hdev, cp.data); | ||
673 | |||
674 | if (hdev->adv_data_len == len && | ||
675 | memcmp(cp.data, hdev->adv_data, len) == 0) { | ||
676 | err = 0; | ||
677 | goto unlock; | ||
678 | } | ||
679 | |||
680 | memcpy(hdev->adv_data, cp.data, sizeof(cp.data)); | ||
681 | hdev->adv_data_len = len; | ||
682 | |||
683 | cp.length = len; | ||
684 | err = hci_send_cmd(hdev, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp); | ||
685 | |||
686 | unlock: | ||
687 | hci_dev_unlock(hdev); | ||
688 | |||
689 | return err; | ||
690 | } | ||
691 | |||
640 | /* ---- HCI ioctl helpers ---- */ | 692 | /* ---- HCI ioctl helpers ---- */ |
641 | 693 | ||
642 | int hci_dev_open(__u16 dev) | 694 | int hci_dev_open(__u16 dev) |
@@ -687,10 +739,6 @@ int hci_dev_open(__u16 dev) | |||
687 | 739 | ||
688 | ret = __hci_request(hdev, hci_init_req, 0, HCI_INIT_TIMEOUT); | 740 | ret = __hci_request(hdev, hci_init_req, 0, HCI_INIT_TIMEOUT); |
689 | 741 | ||
690 | if (lmp_host_le_capable(hdev)) | ||
691 | ret = __hci_request(hdev, hci_le_init_req, 0, | ||
692 | HCI_INIT_TIMEOUT); | ||
693 | |||
694 | clear_bit(HCI_INIT, &hdev->flags); | 742 | clear_bit(HCI_INIT, &hdev->flags); |
695 | } | 743 | } |
696 | 744 | ||
@@ -698,6 +746,7 @@ int hci_dev_open(__u16 dev) | |||
698 | hci_dev_hold(hdev); | 746 | hci_dev_hold(hdev); |
699 | set_bit(HCI_UP, &hdev->flags); | 747 | set_bit(HCI_UP, &hdev->flags); |
700 | hci_notify(hdev, HCI_DEV_UP); | 748 | hci_notify(hdev, HCI_DEV_UP); |
749 | hci_update_ad(hdev); | ||
701 | if (!test_bit(HCI_SETUP, &hdev->dev_flags) && | 750 | if (!test_bit(HCI_SETUP, &hdev->dev_flags) && |
702 | mgmt_valid_hdev(hdev)) { | 751 | mgmt_valid_hdev(hdev)) { |
703 | hci_dev_lock(hdev); | 752 | hci_dev_lock(hdev); |
@@ -1039,10 +1088,17 @@ int hci_get_dev_info(void __user *arg) | |||
1039 | di.type = (hdev->bus & 0x0f) | (hdev->dev_type << 4); | 1088 | di.type = (hdev->bus & 0x0f) | (hdev->dev_type << 4); |
1040 | di.flags = hdev->flags; | 1089 | di.flags = hdev->flags; |
1041 | di.pkt_type = hdev->pkt_type; | 1090 | di.pkt_type = hdev->pkt_type; |
1042 | di.acl_mtu = hdev->acl_mtu; | 1091 | if (lmp_bredr_capable(hdev)) { |
1043 | di.acl_pkts = hdev->acl_pkts; | 1092 | di.acl_mtu = hdev->acl_mtu; |
1044 | di.sco_mtu = hdev->sco_mtu; | 1093 | di.acl_pkts = hdev->acl_pkts; |
1045 | di.sco_pkts = hdev->sco_pkts; | 1094 | di.sco_mtu = hdev->sco_mtu; |
1095 | di.sco_pkts = hdev->sco_pkts; | ||
1096 | } else { | ||
1097 | di.acl_mtu = hdev->le_mtu; | ||
1098 | di.acl_pkts = hdev->le_pkts; | ||
1099 | di.sco_mtu = 0; | ||
1100 | di.sco_pkts = 0; | ||
1101 | } | ||
1046 | di.link_policy = hdev->link_policy; | 1102 | di.link_policy = hdev->link_policy; |
1047 | di.link_mode = hdev->link_mode; | 1103 | di.link_mode = hdev->link_mode; |
1048 | 1104 | ||
@@ -1617,6 +1673,9 @@ int hci_le_scan(struct hci_dev *hdev, u8 type, u16 interval, u16 window, | |||
1617 | 1673 | ||
1618 | BT_DBG("%s", hdev->name); | 1674 | BT_DBG("%s", hdev->name); |
1619 | 1675 | ||
1676 | if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags)) | ||
1677 | return -ENOTSUPP; | ||
1678 | |||
1620 | if (work_busy(&hdev->le_scan)) | 1679 | if (work_busy(&hdev->le_scan)) |
1621 | return -EINPROGRESS; | 1680 | return -EINPROGRESS; |
1622 | 1681 | ||
@@ -1643,6 +1702,8 @@ struct hci_dev *hci_alloc_dev(void) | |||
1643 | hdev->esco_type = (ESCO_HV1); | 1702 | hdev->esco_type = (ESCO_HV1); |
1644 | hdev->link_mode = (HCI_LM_ACCEPT); | 1703 | hdev->link_mode = (HCI_LM_ACCEPT); |
1645 | hdev->io_capability = 0x03; /* No Input No Output */ | 1704 | hdev->io_capability = 0x03; /* No Input No Output */ |
1705 | hdev->inq_tx_power = HCI_TX_POWER_INVALID; | ||
1706 | hdev->adv_tx_power = HCI_TX_POWER_INVALID; | ||
1646 | 1707 | ||
1647 | hdev->sniff_max_interval = 800; | 1708 | hdev->sniff_max_interval = 800; |
1648 | hdev->sniff_min_interval = 80; | 1709 | hdev->sniff_min_interval = 80; |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 0383635f91f..9f5c5f24450 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -24,7 +24,6 @@ | |||
24 | 24 | ||
25 | /* Bluetooth HCI event handling. */ | 25 | /* Bluetooth HCI event handling. */ |
26 | 26 | ||
27 | #include <linux/export.h> | ||
28 | #include <asm/unaligned.h> | 27 | #include <asm/unaligned.h> |
29 | 28 | ||
30 | #include <net/bluetooth/bluetooth.h> | 29 | #include <net/bluetooth/bluetooth.h> |
@@ -203,6 +202,11 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) | |||
203 | BIT(HCI_PERIODIC_INQ)); | 202 | BIT(HCI_PERIODIC_INQ)); |
204 | 203 | ||
205 | hdev->discovery.state = DISCOVERY_STOPPED; | 204 | hdev->discovery.state = DISCOVERY_STOPPED; |
205 | hdev->inq_tx_power = HCI_TX_POWER_INVALID; | ||
206 | hdev->adv_tx_power = HCI_TX_POWER_INVALID; | ||
207 | |||
208 | memset(hdev->adv_data, 0, sizeof(hdev->adv_data)); | ||
209 | hdev->adv_data_len = 0; | ||
206 | } | 210 | } |
207 | 211 | ||
208 | static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) | 212 | static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -225,6 +229,9 @@ static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) | |||
225 | 229 | ||
226 | hci_dev_unlock(hdev); | 230 | hci_dev_unlock(hdev); |
227 | 231 | ||
232 | if (!status && !test_bit(HCI_INIT, &hdev->flags)) | ||
233 | hci_update_ad(hdev); | ||
234 | |||
228 | hci_req_complete(hdev, HCI_OP_WRITE_LOCAL_NAME, status); | 235 | hci_req_complete(hdev, HCI_OP_WRITE_LOCAL_NAME, status); |
229 | } | 236 | } |
230 | 237 | ||
@@ -440,7 +447,7 @@ static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) | |||
440 | static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) | 447 | static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) |
441 | { | 448 | { |
442 | __u8 status = *((__u8 *) skb->data); | 449 | __u8 status = *((__u8 *) skb->data); |
443 | void *sent; | 450 | struct hci_cp_write_ssp_mode *sent; |
444 | 451 | ||
445 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | 452 | BT_DBG("%s status 0x%2.2x", hdev->name, status); |
446 | 453 | ||
@@ -448,10 +455,17 @@ static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) | |||
448 | if (!sent) | 455 | if (!sent) |
449 | return; | 456 | return; |
450 | 457 | ||
458 | if (!status) { | ||
459 | if (sent->mode) | ||
460 | hdev->host_features[0] |= LMP_HOST_SSP; | ||
461 | else | ||
462 | hdev->host_features[0] &= ~LMP_HOST_SSP; | ||
463 | } | ||
464 | |||
451 | if (test_bit(HCI_MGMT, &hdev->dev_flags)) | 465 | if (test_bit(HCI_MGMT, &hdev->dev_flags)) |
452 | mgmt_ssp_enable_complete(hdev, *((u8 *) sent), status); | 466 | mgmt_ssp_enable_complete(hdev, sent->mode, status); |
453 | else if (!status) { | 467 | else if (!status) { |
454 | if (*((u8 *) sent)) | 468 | if (sent->mode) |
455 | set_bit(HCI_SSP_ENABLED, &hdev->dev_flags); | 469 | set_bit(HCI_SSP_ENABLED, &hdev->dev_flags); |
456 | else | 470 | else |
457 | clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags); | 471 | clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags); |
@@ -460,10 +474,10 @@ static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) | |||
460 | 474 | ||
461 | static u8 hci_get_inquiry_mode(struct hci_dev *hdev) | 475 | static u8 hci_get_inquiry_mode(struct hci_dev *hdev) |
462 | { | 476 | { |
463 | if (hdev->features[6] & LMP_EXT_INQ) | 477 | if (lmp_ext_inq_capable(hdev)) |
464 | return 2; | 478 | return 2; |
465 | 479 | ||
466 | if (hdev->features[3] & LMP_RSSI_INQ) | 480 | if (lmp_inq_rssi_capable(hdev)) |
467 | return 1; | 481 | return 1; |
468 | 482 | ||
469 | if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 && | 483 | if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 && |
@@ -507,28 +521,30 @@ static void hci_setup_event_mask(struct hci_dev *hdev) | |||
507 | if (hdev->hci_ver < BLUETOOTH_VER_1_2) | 521 | if (hdev->hci_ver < BLUETOOTH_VER_1_2) |
508 | return; | 522 | return; |
509 | 523 | ||
510 | events[4] |= 0x01; /* Flow Specification Complete */ | 524 | if (lmp_bredr_capable(hdev)) { |
511 | events[4] |= 0x02; /* Inquiry Result with RSSI */ | 525 | events[4] |= 0x01; /* Flow Specification Complete */ |
512 | events[4] |= 0x04; /* Read Remote Extended Features Complete */ | 526 | events[4] |= 0x02; /* Inquiry Result with RSSI */ |
513 | events[5] |= 0x08; /* Synchronous Connection Complete */ | 527 | events[4] |= 0x04; /* Read Remote Extended Features Complete */ |
514 | events[5] |= 0x10; /* Synchronous Connection Changed */ | 528 | events[5] |= 0x08; /* Synchronous Connection Complete */ |
529 | events[5] |= 0x10; /* Synchronous Connection Changed */ | ||
530 | } | ||
515 | 531 | ||
516 | if (hdev->features[3] & LMP_RSSI_INQ) | 532 | if (lmp_inq_rssi_capable(hdev)) |
517 | events[4] |= 0x02; /* Inquiry Result with RSSI */ | 533 | events[4] |= 0x02; /* Inquiry Result with RSSI */ |
518 | 534 | ||
519 | if (lmp_sniffsubr_capable(hdev)) | 535 | if (lmp_sniffsubr_capable(hdev)) |
520 | events[5] |= 0x20; /* Sniff Subrating */ | 536 | events[5] |= 0x20; /* Sniff Subrating */ |
521 | 537 | ||
522 | if (hdev->features[5] & LMP_PAUSE_ENC) | 538 | if (lmp_pause_enc_capable(hdev)) |
523 | events[5] |= 0x80; /* Encryption Key Refresh Complete */ | 539 | events[5] |= 0x80; /* Encryption Key Refresh Complete */ |
524 | 540 | ||
525 | if (hdev->features[6] & LMP_EXT_INQ) | 541 | if (lmp_ext_inq_capable(hdev)) |
526 | events[5] |= 0x40; /* Extended Inquiry Result */ | 542 | events[5] |= 0x40; /* Extended Inquiry Result */ |
527 | 543 | ||
528 | if (lmp_no_flush_capable(hdev)) | 544 | if (lmp_no_flush_capable(hdev)) |
529 | events[7] |= 0x01; /* Enhanced Flush Complete */ | 545 | events[7] |= 0x01; /* Enhanced Flush Complete */ |
530 | 546 | ||
531 | if (hdev->features[7] & LMP_LSTO) | 547 | if (lmp_lsto_capable(hdev)) |
532 | events[6] |= 0x80; /* Link Supervision Timeout Changed */ | 548 | events[6] |= 0x80; /* Link Supervision Timeout Changed */ |
533 | 549 | ||
534 | if (lmp_ssp_capable(hdev)) { | 550 | if (lmp_ssp_capable(hdev)) { |
@@ -548,6 +564,53 @@ static void hci_setup_event_mask(struct hci_dev *hdev) | |||
548 | events[7] |= 0x20; /* LE Meta-Event */ | 564 | events[7] |= 0x20; /* LE Meta-Event */ |
549 | 565 | ||
550 | hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events); | 566 | hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events); |
567 | |||
568 | if (lmp_le_capable(hdev)) { | ||
569 | memset(events, 0, sizeof(events)); | ||
570 | events[0] = 0x1f; | ||
571 | hci_send_cmd(hdev, HCI_OP_LE_SET_EVENT_MASK, | ||
572 | sizeof(events), events); | ||
573 | } | ||
574 | } | ||
575 | |||
576 | static void bredr_setup(struct hci_dev *hdev) | ||
577 | { | ||
578 | struct hci_cp_delete_stored_link_key cp; | ||
579 | __le16 param; | ||
580 | __u8 flt_type; | ||
581 | |||
582 | /* Read Buffer Size (ACL mtu, max pkt, etc.) */ | ||
583 | hci_send_cmd(hdev, HCI_OP_READ_BUFFER_SIZE, 0, NULL); | ||
584 | |||
585 | /* Read Class of Device */ | ||
586 | hci_send_cmd(hdev, HCI_OP_READ_CLASS_OF_DEV, 0, NULL); | ||
587 | |||
588 | /* Read Local Name */ | ||
589 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL); | ||
590 | |||
591 | /* Read Voice Setting */ | ||
592 | hci_send_cmd(hdev, HCI_OP_READ_VOICE_SETTING, 0, NULL); | ||
593 | |||
594 | /* Clear Event Filters */ | ||
595 | flt_type = HCI_FLT_CLEAR_ALL; | ||
596 | hci_send_cmd(hdev, HCI_OP_SET_EVENT_FLT, 1, &flt_type); | ||
597 | |||
598 | /* Connection accept timeout ~20 secs */ | ||
599 | param = __constant_cpu_to_le16(0x7d00); | ||
600 | hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, ¶m); | ||
601 | |||
602 | bacpy(&cp.bdaddr, BDADDR_ANY); | ||
603 | cp.delete_all = 1; | ||
604 | hci_send_cmd(hdev, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp); | ||
605 | } | ||
606 | |||
607 | static void le_setup(struct hci_dev *hdev) | ||
608 | { | ||
609 | /* Read LE Buffer Size */ | ||
610 | hci_send_cmd(hdev, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL); | ||
611 | |||
612 | /* Read LE Advertising Channel TX Power */ | ||
613 | hci_send_cmd(hdev, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL); | ||
551 | } | 614 | } |
552 | 615 | ||
553 | static void hci_setup(struct hci_dev *hdev) | 616 | static void hci_setup(struct hci_dev *hdev) |
@@ -555,6 +618,15 @@ static void hci_setup(struct hci_dev *hdev) | |||
555 | if (hdev->dev_type != HCI_BREDR) | 618 | if (hdev->dev_type != HCI_BREDR) |
556 | return; | 619 | return; |
557 | 620 | ||
621 | /* Read BD Address */ | ||
622 | hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL); | ||
623 | |||
624 | if (lmp_bredr_capable(hdev)) | ||
625 | bredr_setup(hdev); | ||
626 | |||
627 | if (lmp_le_capable(hdev)) | ||
628 | le_setup(hdev); | ||
629 | |||
558 | hci_setup_event_mask(hdev); | 630 | hci_setup_event_mask(hdev); |
559 | 631 | ||
560 | if (hdev->hci_ver > BLUETOOTH_VER_1_1) | 632 | if (hdev->hci_ver > BLUETOOTH_VER_1_1) |
@@ -575,13 +647,13 @@ static void hci_setup(struct hci_dev *hdev) | |||
575 | } | 647 | } |
576 | } | 648 | } |
577 | 649 | ||
578 | if (hdev->features[3] & LMP_RSSI_INQ) | 650 | if (lmp_inq_rssi_capable(hdev)) |
579 | hci_setup_inquiry_mode(hdev); | 651 | hci_setup_inquiry_mode(hdev); |
580 | 652 | ||
581 | if (hdev->features[7] & LMP_INQ_TX_PWR) | 653 | if (lmp_inq_tx_pwr_capable(hdev)) |
582 | hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL); | 654 | hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL); |
583 | 655 | ||
584 | if (hdev->features[7] & LMP_EXTFEATURES) { | 656 | if (lmp_ext_feat_capable(hdev)) { |
585 | struct hci_cp_read_local_ext_features cp; | 657 | struct hci_cp_read_local_ext_features cp; |
586 | 658 | ||
587 | cp.page = 0x01; | 659 | cp.page = 0x01; |
@@ -628,11 +700,11 @@ static void hci_setup_link_policy(struct hci_dev *hdev) | |||
628 | 700 | ||
629 | if (lmp_rswitch_capable(hdev)) | 701 | if (lmp_rswitch_capable(hdev)) |
630 | link_policy |= HCI_LP_RSWITCH; | 702 | link_policy |= HCI_LP_RSWITCH; |
631 | if (hdev->features[0] & LMP_HOLD) | 703 | if (lmp_hold_capable(hdev)) |
632 | link_policy |= HCI_LP_HOLD; | 704 | link_policy |= HCI_LP_HOLD; |
633 | if (lmp_sniff_capable(hdev)) | 705 | if (lmp_sniff_capable(hdev)) |
634 | link_policy |= HCI_LP_SNIFF; | 706 | link_policy |= HCI_LP_SNIFF; |
635 | if (hdev->features[1] & LMP_PARK) | 707 | if (lmp_park_capable(hdev)) |
636 | link_policy |= HCI_LP_PARK; | 708 | link_policy |= HCI_LP_PARK; |
637 | 709 | ||
638 | cp.policy = cpu_to_le16(link_policy); | 710 | cp.policy = cpu_to_le16(link_policy); |
@@ -722,10 +794,10 @@ static void hci_set_le_support(struct hci_dev *hdev) | |||
722 | 794 | ||
723 | if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { | 795 | if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { |
724 | cp.le = 1; | 796 | cp.le = 1; |
725 | cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR); | 797 | cp.simul = !!lmp_le_br_capable(hdev); |
726 | } | 798 | } |
727 | 799 | ||
728 | if (cp.le != !!(hdev->host_features[0] & LMP_HOST_LE)) | 800 | if (cp.le != !!lmp_host_le_capable(hdev)) |
729 | hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), | 801 | hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), |
730 | &cp); | 802 | &cp); |
731 | } | 803 | } |
@@ -1018,6 +1090,31 @@ static void hci_cc_le_read_buffer_size(struct hci_dev *hdev, | |||
1018 | hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status); | 1090 | hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status); |
1019 | } | 1091 | } |
1020 | 1092 | ||
1093 | static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev, | ||
1094 | struct sk_buff *skb) | ||
1095 | { | ||
1096 | struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data; | ||
1097 | |||
1098 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | ||
1099 | |||
1100 | if (!rp->status) { | ||
1101 | hdev->adv_tx_power = rp->tx_power; | ||
1102 | if (!test_bit(HCI_INIT, &hdev->flags)) | ||
1103 | hci_update_ad(hdev); | ||
1104 | } | ||
1105 | |||
1106 | hci_req_complete(hdev, HCI_OP_LE_READ_ADV_TX_POWER, rp->status); | ||
1107 | } | ||
1108 | |||
1109 | static void hci_cc_le_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb) | ||
1110 | { | ||
1111 | __u8 status = *((__u8 *) skb->data); | ||
1112 | |||
1113 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
1114 | |||
1115 | hci_req_complete(hdev, HCI_OP_LE_SET_EVENT_MASK, status); | ||
1116 | } | ||
1117 | |||
1021 | static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) | 1118 | static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) |
1022 | { | 1119 | { |
1023 | struct hci_rp_user_confirm_reply *rp = (void *) skb->data; | 1120 | struct hci_rp_user_confirm_reply *rp = (void *) skb->data; |
@@ -1093,6 +1190,33 @@ static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, | |||
1093 | hci_dev_unlock(hdev); | 1190 | hci_dev_unlock(hdev); |
1094 | } | 1191 | } |
1095 | 1192 | ||
1193 | static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb) | ||
1194 | { | ||
1195 | __u8 *sent, status = *((__u8 *) skb->data); | ||
1196 | |||
1197 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
1198 | |||
1199 | sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE); | ||
1200 | if (!sent) | ||
1201 | return; | ||
1202 | |||
1203 | hci_dev_lock(hdev); | ||
1204 | |||
1205 | if (!status) { | ||
1206 | if (*sent) | ||
1207 | set_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags); | ||
1208 | else | ||
1209 | clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags); | ||
1210 | } | ||
1211 | |||
1212 | hci_dev_unlock(hdev); | ||
1213 | |||
1214 | if (!test_bit(HCI_INIT, &hdev->flags)) | ||
1215 | hci_update_ad(hdev); | ||
1216 | |||
1217 | hci_req_complete(hdev, HCI_OP_LE_SET_ADV_ENABLE, status); | ||
1218 | } | ||
1219 | |||
1096 | static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) | 1220 | static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) |
1097 | { | 1221 | { |
1098 | __u8 status = *((__u8 *) skb->data); | 1222 | __u8 status = *((__u8 *) skb->data); |
@@ -1207,6 +1331,11 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev, | |||
1207 | hdev->host_features[0] |= LMP_HOST_LE; | 1331 | hdev->host_features[0] |= LMP_HOST_LE; |
1208 | else | 1332 | else |
1209 | hdev->host_features[0] &= ~LMP_HOST_LE; | 1333 | hdev->host_features[0] &= ~LMP_HOST_LE; |
1334 | |||
1335 | if (sent->simul) | ||
1336 | hdev->host_features[0] |= LMP_HOST_LE_BREDR; | ||
1337 | else | ||
1338 | hdev->host_features[0] &= ~LMP_HOST_LE_BREDR; | ||
1210 | } | 1339 | } |
1211 | 1340 | ||
1212 | if (test_bit(HCI_MGMT, &hdev->dev_flags) && | 1341 | if (test_bit(HCI_MGMT, &hdev->dev_flags) && |
@@ -1718,14 +1847,23 @@ static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status) | |||
1718 | 1847 | ||
1719 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | 1848 | BT_DBG("%s status 0x%2.2x", hdev->name, status); |
1720 | 1849 | ||
1721 | if (status) | ||
1722 | return; | ||
1723 | |||
1724 | cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK); | 1850 | cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK); |
1725 | if (!cp) | 1851 | if (!cp) |
1726 | return; | 1852 | return; |
1727 | 1853 | ||
1728 | amp_write_remote_assoc(hdev, cp->phy_handle); | 1854 | hci_dev_lock(hdev); |
1855 | |||
1856 | if (status) { | ||
1857 | struct hci_conn *hcon; | ||
1858 | |||
1859 | hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle); | ||
1860 | if (hcon) | ||
1861 | hci_conn_del(hcon); | ||
1862 | } else { | ||
1863 | amp_write_remote_assoc(hdev, cp->phy_handle); | ||
1864 | } | ||
1865 | |||
1866 | hci_dev_unlock(hdev); | ||
1729 | } | 1867 | } |
1730 | 1868 | ||
1731 | static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status) | 1869 | static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status) |
@@ -1744,6 +1882,11 @@ static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status) | |||
1744 | amp_write_remote_assoc(hdev, cp->phy_handle); | 1882 | amp_write_remote_assoc(hdev, cp->phy_handle); |
1745 | } | 1883 | } |
1746 | 1884 | ||
1885 | static void hci_cs_create_logical_link(struct hci_dev *hdev, u8 status) | ||
1886 | { | ||
1887 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
1888 | } | ||
1889 | |||
1747 | static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | 1890 | static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) |
1748 | { | 1891 | { |
1749 | __u8 status = *((__u8 *) skb->data); | 1892 | __u8 status = *((__u8 *) skb->data); |
@@ -2441,6 +2584,14 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2441 | hci_cc_le_read_buffer_size(hdev, skb); | 2584 | hci_cc_le_read_buffer_size(hdev, skb); |
2442 | break; | 2585 | break; |
2443 | 2586 | ||
2587 | case HCI_OP_LE_READ_ADV_TX_POWER: | ||
2588 | hci_cc_le_read_adv_tx_power(hdev, skb); | ||
2589 | break; | ||
2590 | |||
2591 | case HCI_OP_LE_SET_EVENT_MASK: | ||
2592 | hci_cc_le_set_event_mask(hdev, skb); | ||
2593 | break; | ||
2594 | |||
2444 | case HCI_OP_USER_CONFIRM_REPLY: | 2595 | case HCI_OP_USER_CONFIRM_REPLY: |
2445 | hci_cc_user_confirm_reply(hdev, skb); | 2596 | hci_cc_user_confirm_reply(hdev, skb); |
2446 | break; | 2597 | break; |
@@ -2461,6 +2612,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2461 | hci_cc_le_set_scan_param(hdev, skb); | 2612 | hci_cc_le_set_scan_param(hdev, skb); |
2462 | break; | 2613 | break; |
2463 | 2614 | ||
2615 | case HCI_OP_LE_SET_ADV_ENABLE: | ||
2616 | hci_cc_le_set_adv_enable(hdev, skb); | ||
2617 | break; | ||
2618 | |||
2464 | case HCI_OP_LE_SET_SCAN_ENABLE: | 2619 | case HCI_OP_LE_SET_SCAN_ENABLE: |
2465 | hci_cc_le_set_scan_enable(hdev, skb); | 2620 | hci_cc_le_set_scan_enable(hdev, skb); |
2466 | break; | 2621 | break; |
@@ -2570,6 +2725,10 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2570 | hci_cs_accept_phylink(hdev, ev->status); | 2725 | hci_cs_accept_phylink(hdev, ev->status); |
2571 | break; | 2726 | break; |
2572 | 2727 | ||
2728 | case HCI_OP_CREATE_LOGICAL_LINK: | ||
2729 | hci_cs_create_logical_link(hdev, ev->status); | ||
2730 | break; | ||
2731 | |||
2573 | default: | 2732 | default: |
2574 | BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); | 2733 | BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); |
2575 | break; | 2734 | break; |
@@ -3544,6 +3703,130 @@ unlock: | |||
3544 | hci_dev_unlock(hdev); | 3703 | hci_dev_unlock(hdev); |
3545 | } | 3704 | } |
3546 | 3705 | ||
3706 | static void hci_phy_link_complete_evt(struct hci_dev *hdev, | ||
3707 | struct sk_buff *skb) | ||
3708 | { | ||
3709 | struct hci_ev_phy_link_complete *ev = (void *) skb->data; | ||
3710 | struct hci_conn *hcon, *bredr_hcon; | ||
3711 | |||
3712 | BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle, | ||
3713 | ev->status); | ||
3714 | |||
3715 | hci_dev_lock(hdev); | ||
3716 | |||
3717 | hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); | ||
3718 | if (!hcon) { | ||
3719 | hci_dev_unlock(hdev); | ||
3720 | return; | ||
3721 | } | ||
3722 | |||
3723 | if (ev->status) { | ||
3724 | hci_conn_del(hcon); | ||
3725 | hci_dev_unlock(hdev); | ||
3726 | return; | ||
3727 | } | ||
3728 | |||
3729 | bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon; | ||
3730 | |||
3731 | hcon->state = BT_CONNECTED; | ||
3732 | bacpy(&hcon->dst, &bredr_hcon->dst); | ||
3733 | |||
3734 | hci_conn_hold(hcon); | ||
3735 | hcon->disc_timeout = HCI_DISCONN_TIMEOUT; | ||
3736 | hci_conn_put(hcon); | ||
3737 | |||
3738 | hci_conn_hold_device(hcon); | ||
3739 | hci_conn_add_sysfs(hcon); | ||
3740 | |||
3741 | amp_physical_cfm(bredr_hcon, hcon); | ||
3742 | |||
3743 | hci_dev_unlock(hdev); | ||
3744 | } | ||
3745 | |||
3746 | static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||
3747 | { | ||
3748 | struct hci_ev_logical_link_complete *ev = (void *) skb->data; | ||
3749 | struct hci_conn *hcon; | ||
3750 | struct hci_chan *hchan; | ||
3751 | struct amp_mgr *mgr; | ||
3752 | |||
3753 | BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x", | ||
3754 | hdev->name, le16_to_cpu(ev->handle), ev->phy_handle, | ||
3755 | ev->status); | ||
3756 | |||
3757 | hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); | ||
3758 | if (!hcon) | ||
3759 | return; | ||
3760 | |||
3761 | /* Create AMP hchan */ | ||
3762 | hchan = hci_chan_create(hcon); | ||
3763 | if (!hchan) | ||
3764 | return; | ||
3765 | |||
3766 | hchan->handle = le16_to_cpu(ev->handle); | ||
3767 | |||
3768 | BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan); | ||
3769 | |||
3770 | mgr = hcon->amp_mgr; | ||
3771 | if (mgr && mgr->bredr_chan) { | ||
3772 | struct l2cap_chan *bredr_chan = mgr->bredr_chan; | ||
3773 | |||
3774 | l2cap_chan_lock(bredr_chan); | ||
3775 | |||
3776 | bredr_chan->conn->mtu = hdev->block_mtu; | ||
3777 | l2cap_logical_cfm(bredr_chan, hchan, 0); | ||
3778 | hci_conn_hold(hcon); | ||
3779 | |||
3780 | l2cap_chan_unlock(bredr_chan); | ||
3781 | } | ||
3782 | } | ||
3783 | |||
3784 | static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev, | ||
3785 | struct sk_buff *skb) | ||
3786 | { | ||
3787 | struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data; | ||
3788 | struct hci_chan *hchan; | ||
3789 | |||
3790 | BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name, | ||
3791 | le16_to_cpu(ev->handle), ev->status); | ||
3792 | |||
3793 | if (ev->status) | ||
3794 | return; | ||
3795 | |||
3796 | hci_dev_lock(hdev); | ||
3797 | |||
3798 | hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle)); | ||
3799 | if (!hchan) | ||
3800 | goto unlock; | ||
3801 | |||
3802 | amp_destroy_logical_link(hchan, ev->reason); | ||
3803 | |||
3804 | unlock: | ||
3805 | hci_dev_unlock(hdev); | ||
3806 | } | ||
3807 | |||
3808 | static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev, | ||
3809 | struct sk_buff *skb) | ||
3810 | { | ||
3811 | struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data; | ||
3812 | struct hci_conn *hcon; | ||
3813 | |||
3814 | BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); | ||
3815 | |||
3816 | if (ev->status) | ||
3817 | return; | ||
3818 | |||
3819 | hci_dev_lock(hdev); | ||
3820 | |||
3821 | hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); | ||
3822 | if (hcon) { | ||
3823 | hcon->state = BT_CLOSED; | ||
3824 | hci_conn_del(hcon); | ||
3825 | } | ||
3826 | |||
3827 | hci_dev_unlock(hdev); | ||
3828 | } | ||
3829 | |||
3547 | static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | 3830 | static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) |
3548 | { | 3831 | { |
3549 | struct hci_ev_le_conn_complete *ev = (void *) skb->data; | 3832 | struct hci_ev_le_conn_complete *ev = (void *) skb->data; |
@@ -3871,6 +4154,22 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) | |||
3871 | hci_remote_oob_data_request_evt(hdev, skb); | 4154 | hci_remote_oob_data_request_evt(hdev, skb); |
3872 | break; | 4155 | break; |
3873 | 4156 | ||
4157 | case HCI_EV_PHY_LINK_COMPLETE: | ||
4158 | hci_phy_link_complete_evt(hdev, skb); | ||
4159 | break; | ||
4160 | |||
4161 | case HCI_EV_LOGICAL_LINK_COMPLETE: | ||
4162 | hci_loglink_complete_evt(hdev, skb); | ||
4163 | break; | ||
4164 | |||
4165 | case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE: | ||
4166 | hci_disconn_loglink_complete_evt(hdev, skb); | ||
4167 | break; | ||
4168 | |||
4169 | case HCI_EV_DISCONN_PHY_LINK_COMPLETE: | ||
4170 | hci_disconn_phylink_complete_evt(hdev, skb); | ||
4171 | break; | ||
4172 | |||
3874 | case HCI_EV_NUM_COMP_BLOCKS: | 4173 | case HCI_EV_NUM_COMP_BLOCKS: |
3875 | hci_num_comp_blocks_evt(hdev, skb); | 4174 | hci_num_comp_blocks_evt(hdev, skb); |
3876 | break; | 4175 | break; |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 08efc256c93..b52f66d2243 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <net/bluetooth/l2cap.h> | 38 | #include <net/bluetooth/l2cap.h> |
39 | #include <net/bluetooth/smp.h> | 39 | #include <net/bluetooth/smp.h> |
40 | #include <net/bluetooth/a2mp.h> | 40 | #include <net/bluetooth/a2mp.h> |
41 | #include <net/bluetooth/amp.h> | ||
41 | 42 | ||
42 | bool disable_ertm; | 43 | bool disable_ertm; |
43 | 44 | ||
@@ -100,6 +101,23 @@ static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, | |||
100 | return c; | 101 | return c; |
101 | } | 102 | } |
102 | 103 | ||
104 | /* Find channel with given DCID. | ||
105 | * Returns locked channel. | ||
106 | */ | ||
107 | static struct l2cap_chan *l2cap_get_chan_by_dcid(struct l2cap_conn *conn, | ||
108 | u16 cid) | ||
109 | { | ||
110 | struct l2cap_chan *c; | ||
111 | |||
112 | mutex_lock(&conn->chan_lock); | ||
113 | c = __l2cap_get_chan_by_dcid(conn, cid); | ||
114 | if (c) | ||
115 | l2cap_chan_lock(c); | ||
116 | mutex_unlock(&conn->chan_lock); | ||
117 | |||
118 | return c; | ||
119 | } | ||
120 | |||
103 | static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, | 121 | static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, |
104 | u8 ident) | 122 | u8 ident) |
105 | { | 123 | { |
@@ -112,6 +130,20 @@ static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, | |||
112 | return NULL; | 130 | return NULL; |
113 | } | 131 | } |
114 | 132 | ||
133 | static struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, | ||
134 | u8 ident) | ||
135 | { | ||
136 | struct l2cap_chan *c; | ||
137 | |||
138 | mutex_lock(&conn->chan_lock); | ||
139 | c = __l2cap_get_chan_by_ident(conn, ident); | ||
140 | if (c) | ||
141 | l2cap_chan_lock(c); | ||
142 | mutex_unlock(&conn->chan_lock); | ||
143 | |||
144 | return c; | ||
145 | } | ||
146 | |||
115 | static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src) | 147 | static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src) |
116 | { | 148 | { |
117 | struct l2cap_chan *c; | 149 | struct l2cap_chan *c; |
@@ -546,6 +578,13 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) | |||
546 | mgr->bredr_chan = NULL; | 578 | mgr->bredr_chan = NULL; |
547 | } | 579 | } |
548 | 580 | ||
581 | if (chan->hs_hchan) { | ||
582 | struct hci_chan *hs_hchan = chan->hs_hchan; | ||
583 | |||
584 | BT_DBG("chan %p disconnect hs_hchan %p", chan, hs_hchan); | ||
585 | amp_disconnect_logical_link(hs_hchan); | ||
586 | } | ||
587 | |||
549 | chan->ops->teardown(chan, err); | 588 | chan->ops->teardown(chan, err); |
550 | 589 | ||
551 | if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state)) | 590 | if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state)) |
@@ -718,6 +757,12 @@ static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, | |||
718 | hci_send_acl(conn->hchan, skb, flags); | 757 | hci_send_acl(conn->hchan, skb, flags); |
719 | } | 758 | } |
720 | 759 | ||
760 | static bool __chan_is_moving(struct l2cap_chan *chan) | ||
761 | { | ||
762 | return chan->move_state != L2CAP_MOVE_STABLE && | ||
763 | chan->move_state != L2CAP_MOVE_WAIT_PREPARE; | ||
764 | } | ||
765 | |||
721 | static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb) | 766 | static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb) |
722 | { | 767 | { |
723 | struct hci_conn *hcon = chan->conn->hcon; | 768 | struct hci_conn *hcon = chan->conn->hcon; |
@@ -726,6 +771,15 @@ static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb) | |||
726 | BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len, | 771 | BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len, |
727 | skb->priority); | 772 | skb->priority); |
728 | 773 | ||
774 | if (chan->hs_hcon && !__chan_is_moving(chan)) { | ||
775 | if (chan->hs_hchan) | ||
776 | hci_send_acl(chan->hs_hchan, skb, ACL_COMPLETE); | ||
777 | else | ||
778 | kfree_skb(skb); | ||
779 | |||
780 | return; | ||
781 | } | ||
782 | |||
729 | if (!test_bit(FLAG_FLUSHABLE, &chan->flags) && | 783 | if (!test_bit(FLAG_FLUSHABLE, &chan->flags) && |
730 | lmp_no_flush_capable(hcon->hdev)) | 784 | lmp_no_flush_capable(hcon->hdev)) |
731 | flags = ACL_START_NO_FLUSH; | 785 | flags = ACL_START_NO_FLUSH; |
@@ -901,6 +955,9 @@ static void l2cap_send_sframe(struct l2cap_chan *chan, | |||
901 | if (!control->sframe) | 955 | if (!control->sframe) |
902 | return; | 956 | return; |
903 | 957 | ||
958 | if (__chan_is_moving(chan)) | ||
959 | return; | ||
960 | |||
904 | if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) && | 961 | if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) && |
905 | !control->poll) | 962 | !control->poll) |
906 | control->final = 1; | 963 | control->final = 1; |
@@ -964,6 +1021,12 @@ static bool __amp_capable(struct l2cap_chan *chan) | |||
964 | return false; | 1021 | return false; |
965 | } | 1022 | } |
966 | 1023 | ||
1024 | static bool l2cap_check_efs(struct l2cap_chan *chan) | ||
1025 | { | ||
1026 | /* Check EFS parameters */ | ||
1027 | return true; | ||
1028 | } | ||
1029 | |||
967 | void l2cap_send_conn_req(struct l2cap_chan *chan) | 1030 | void l2cap_send_conn_req(struct l2cap_chan *chan) |
968 | { | 1031 | { |
969 | struct l2cap_conn *conn = chan->conn; | 1032 | struct l2cap_conn *conn = chan->conn; |
@@ -979,6 +1042,76 @@ void l2cap_send_conn_req(struct l2cap_chan *chan) | |||
979 | l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req); | 1042 | l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req); |
980 | } | 1043 | } |
981 | 1044 | ||
1045 | static void l2cap_send_create_chan_req(struct l2cap_chan *chan, u8 amp_id) | ||
1046 | { | ||
1047 | struct l2cap_create_chan_req req; | ||
1048 | req.scid = cpu_to_le16(chan->scid); | ||
1049 | req.psm = chan->psm; | ||
1050 | req.amp_id = amp_id; | ||
1051 | |||
1052 | chan->ident = l2cap_get_ident(chan->conn); | ||
1053 | |||
1054 | l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_REQ, | ||
1055 | sizeof(req), &req); | ||
1056 | } | ||
1057 | |||
1058 | static void l2cap_move_setup(struct l2cap_chan *chan) | ||
1059 | { | ||
1060 | struct sk_buff *skb; | ||
1061 | |||
1062 | BT_DBG("chan %p", chan); | ||
1063 | |||
1064 | if (chan->mode != L2CAP_MODE_ERTM) | ||
1065 | return; | ||
1066 | |||
1067 | __clear_retrans_timer(chan); | ||
1068 | __clear_monitor_timer(chan); | ||
1069 | __clear_ack_timer(chan); | ||
1070 | |||
1071 | chan->retry_count = 0; | ||
1072 | skb_queue_walk(&chan->tx_q, skb) { | ||
1073 | if (bt_cb(skb)->control.retries) | ||
1074 | bt_cb(skb)->control.retries = 1; | ||
1075 | else | ||
1076 | break; | ||
1077 | } | ||
1078 | |||
1079 | chan->expected_tx_seq = chan->buffer_seq; | ||
1080 | |||
1081 | clear_bit(CONN_REJ_ACT, &chan->conn_state); | ||
1082 | clear_bit(CONN_SREJ_ACT, &chan->conn_state); | ||
1083 | l2cap_seq_list_clear(&chan->retrans_list); | ||
1084 | l2cap_seq_list_clear(&chan->srej_list); | ||
1085 | skb_queue_purge(&chan->srej_q); | ||
1086 | |||
1087 | chan->tx_state = L2CAP_TX_STATE_XMIT; | ||
1088 | chan->rx_state = L2CAP_RX_STATE_MOVE; | ||
1089 | |||
1090 | set_bit(CONN_REMOTE_BUSY, &chan->conn_state); | ||
1091 | } | ||
1092 | |||
1093 | static void l2cap_move_done(struct l2cap_chan *chan) | ||
1094 | { | ||
1095 | u8 move_role = chan->move_role; | ||
1096 | BT_DBG("chan %p", chan); | ||
1097 | |||
1098 | chan->move_state = L2CAP_MOVE_STABLE; | ||
1099 | chan->move_role = L2CAP_MOVE_ROLE_NONE; | ||
1100 | |||
1101 | if (chan->mode != L2CAP_MODE_ERTM) | ||
1102 | return; | ||
1103 | |||
1104 | switch (move_role) { | ||
1105 | case L2CAP_MOVE_ROLE_INITIATOR: | ||
1106 | l2cap_tx(chan, NULL, NULL, L2CAP_EV_EXPLICIT_POLL); | ||
1107 | chan->rx_state = L2CAP_RX_STATE_WAIT_F; | ||
1108 | break; | ||
1109 | case L2CAP_MOVE_ROLE_RESPONDER: | ||
1110 | chan->rx_state = L2CAP_RX_STATE_WAIT_P; | ||
1111 | break; | ||
1112 | } | ||
1113 | } | ||
1114 | |||
982 | static void l2cap_chan_ready(struct l2cap_chan *chan) | 1115 | static void l2cap_chan_ready(struct l2cap_chan *chan) |
983 | { | 1116 | { |
984 | /* This clears all conf flags, including CONF_NOT_COMPLETE */ | 1117 | /* This clears all conf flags, including CONF_NOT_COMPLETE */ |
@@ -1695,6 +1828,9 @@ static void l2cap_streaming_send(struct l2cap_chan *chan, | |||
1695 | 1828 | ||
1696 | BT_DBG("chan %p, skbs %p", chan, skbs); | 1829 | BT_DBG("chan %p, skbs %p", chan, skbs); |
1697 | 1830 | ||
1831 | if (__chan_is_moving(chan)) | ||
1832 | return; | ||
1833 | |||
1698 | skb_queue_splice_tail_init(skbs, &chan->tx_q); | 1834 | skb_queue_splice_tail_init(skbs, &chan->tx_q); |
1699 | 1835 | ||
1700 | while (!skb_queue_empty(&chan->tx_q)) { | 1836 | while (!skb_queue_empty(&chan->tx_q)) { |
@@ -1737,6 +1873,9 @@ static int l2cap_ertm_send(struct l2cap_chan *chan) | |||
1737 | if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) | 1873 | if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) |
1738 | return 0; | 1874 | return 0; |
1739 | 1875 | ||
1876 | if (__chan_is_moving(chan)) | ||
1877 | return 0; | ||
1878 | |||
1740 | while (chan->tx_send_head && | 1879 | while (chan->tx_send_head && |
1741 | chan->unacked_frames < chan->remote_tx_win && | 1880 | chan->unacked_frames < chan->remote_tx_win && |
1742 | chan->tx_state == L2CAP_TX_STATE_XMIT) { | 1881 | chan->tx_state == L2CAP_TX_STATE_XMIT) { |
@@ -1802,6 +1941,9 @@ static void l2cap_ertm_resend(struct l2cap_chan *chan) | |||
1802 | if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) | 1941 | if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) |
1803 | return; | 1942 | return; |
1804 | 1943 | ||
1944 | if (__chan_is_moving(chan)) | ||
1945 | return; | ||
1946 | |||
1805 | while (chan->retrans_list.head != L2CAP_SEQ_LIST_CLEAR) { | 1947 | while (chan->retrans_list.head != L2CAP_SEQ_LIST_CLEAR) { |
1806 | seq = l2cap_seq_list_pop(&chan->retrans_list); | 1948 | seq = l2cap_seq_list_pop(&chan->retrans_list); |
1807 | 1949 | ||
@@ -2144,7 +2286,9 @@ static int l2cap_segment_sdu(struct l2cap_chan *chan, | |||
2144 | /* PDU size is derived from the HCI MTU */ | 2286 | /* PDU size is derived from the HCI MTU */ |
2145 | pdu_len = chan->conn->mtu; | 2287 | pdu_len = chan->conn->mtu; |
2146 | 2288 | ||
2147 | pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD); | 2289 | /* Constrain PDU size for BR/EDR connections */ |
2290 | if (!chan->hs_hcon) | ||
2291 | pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD); | ||
2148 | 2292 | ||
2149 | /* Adjust for largest possible L2CAP overhead. */ | 2293 | /* Adjust for largest possible L2CAP overhead. */ |
2150 | if (chan->fcs) | 2294 | if (chan->fcs) |
@@ -2788,6 +2932,11 @@ int l2cap_ertm_init(struct l2cap_chan *chan) | |||
2788 | 2932 | ||
2789 | skb_queue_head_init(&chan->tx_q); | 2933 | skb_queue_head_init(&chan->tx_q); |
2790 | 2934 | ||
2935 | chan->local_amp_id = 0; | ||
2936 | chan->move_id = 0; | ||
2937 | chan->move_state = L2CAP_MOVE_STABLE; | ||
2938 | chan->move_role = L2CAP_MOVE_ROLE_NONE; | ||
2939 | |||
2791 | if (chan->mode != L2CAP_MODE_ERTM) | 2940 | if (chan->mode != L2CAP_MODE_ERTM) |
2792 | return 0; | 2941 | return 0; |
2793 | 2942 | ||
@@ -2834,6 +2983,44 @@ static inline bool __l2cap_efs_supported(struct l2cap_chan *chan) | |||
2834 | return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW; | 2983 | return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW; |
2835 | } | 2984 | } |
2836 | 2985 | ||
2986 | static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan, | ||
2987 | struct l2cap_conf_rfc *rfc) | ||
2988 | { | ||
2989 | if (chan->local_amp_id && chan->hs_hcon) { | ||
2990 | u64 ertm_to = chan->hs_hcon->hdev->amp_be_flush_to; | ||
2991 | |||
2992 | /* Class 1 devices have must have ERTM timeouts | ||
2993 | * exceeding the Link Supervision Timeout. The | ||
2994 | * default Link Supervision Timeout for AMP | ||
2995 | * controllers is 10 seconds. | ||
2996 | * | ||
2997 | * Class 1 devices use 0xffffffff for their | ||
2998 | * best-effort flush timeout, so the clamping logic | ||
2999 | * will result in a timeout that meets the above | ||
3000 | * requirement. ERTM timeouts are 16-bit values, so | ||
3001 | * the maximum timeout is 65.535 seconds. | ||
3002 | */ | ||
3003 | |||
3004 | /* Convert timeout to milliseconds and round */ | ||
3005 | ertm_to = DIV_ROUND_UP_ULL(ertm_to, 1000); | ||
3006 | |||
3007 | /* This is the recommended formula for class 2 devices | ||
3008 | * that start ERTM timers when packets are sent to the | ||
3009 | * controller. | ||
3010 | */ | ||
3011 | ertm_to = 3 * ertm_to + 500; | ||
3012 | |||
3013 | if (ertm_to > 0xffff) | ||
3014 | ertm_to = 0xffff; | ||
3015 | |||
3016 | rfc->retrans_timeout = cpu_to_le16((u16) ertm_to); | ||
3017 | rfc->monitor_timeout = rfc->retrans_timeout; | ||
3018 | } else { | ||
3019 | rfc->retrans_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO); | ||
3020 | rfc->monitor_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO); | ||
3021 | } | ||
3022 | } | ||
3023 | |||
2837 | static inline void l2cap_txwin_setup(struct l2cap_chan *chan) | 3024 | static inline void l2cap_txwin_setup(struct l2cap_chan *chan) |
2838 | { | 3025 | { |
2839 | if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW && | 3026 | if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW && |
@@ -2900,8 +3087,8 @@ done: | |||
2900 | case L2CAP_MODE_ERTM: | 3087 | case L2CAP_MODE_ERTM: |
2901 | rfc.mode = L2CAP_MODE_ERTM; | 3088 | rfc.mode = L2CAP_MODE_ERTM; |
2902 | rfc.max_transmit = chan->max_tx; | 3089 | rfc.max_transmit = chan->max_tx; |
2903 | rfc.retrans_timeout = 0; | 3090 | |
2904 | rfc.monitor_timeout = 0; | 3091 | __l2cap_set_ertm_timeouts(chan, &rfc); |
2905 | 3092 | ||
2906 | size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - | 3093 | size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - |
2907 | L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE - | 3094 | L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE - |
@@ -3129,10 +3316,7 @@ done: | |||
3129 | rfc.max_pdu_size = cpu_to_le16(size); | 3316 | rfc.max_pdu_size = cpu_to_le16(size); |
3130 | chan->remote_mps = size; | 3317 | chan->remote_mps = size; |
3131 | 3318 | ||
3132 | rfc.retrans_timeout = | 3319 | __l2cap_set_ertm_timeouts(chan, &rfc); |
3133 | __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO); | ||
3134 | rfc.monitor_timeout = | ||
3135 | __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO); | ||
3136 | 3320 | ||
3137 | set_bit(CONF_MODE_DONE, &chan->conf_state); | 3321 | set_bit(CONF_MODE_DONE, &chan->conf_state); |
3138 | 3322 | ||
@@ -3308,12 +3492,21 @@ void __l2cap_connect_rsp_defer(struct l2cap_chan *chan) | |||
3308 | struct l2cap_conn_rsp rsp; | 3492 | struct l2cap_conn_rsp rsp; |
3309 | struct l2cap_conn *conn = chan->conn; | 3493 | struct l2cap_conn *conn = chan->conn; |
3310 | u8 buf[128]; | 3494 | u8 buf[128]; |
3495 | u8 rsp_code; | ||
3311 | 3496 | ||
3312 | rsp.scid = cpu_to_le16(chan->dcid); | 3497 | rsp.scid = cpu_to_le16(chan->dcid); |
3313 | rsp.dcid = cpu_to_le16(chan->scid); | 3498 | rsp.dcid = cpu_to_le16(chan->scid); |
3314 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); | 3499 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); |
3315 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); | 3500 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); |
3316 | l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); | 3501 | |
3502 | if (chan->hs_hcon) | ||
3503 | rsp_code = L2CAP_CREATE_CHAN_RSP; | ||
3504 | else | ||
3505 | rsp_code = L2CAP_CONN_RSP; | ||
3506 | |||
3507 | BT_DBG("chan %p rsp_code %u", chan, rsp_code); | ||
3508 | |||
3509 | l2cap_send_cmd(conn, chan->ident, rsp_code, sizeof(rsp), &rsp); | ||
3317 | 3510 | ||
3318 | if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) | 3511 | if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) |
3319 | return; | 3512 | return; |
@@ -3395,8 +3588,9 @@ static inline int l2cap_command_rej(struct l2cap_conn *conn, | |||
3395 | return 0; | 3588 | return 0; |
3396 | } | 3589 | } |
3397 | 3590 | ||
3398 | static void l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, | 3591 | static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, |
3399 | u8 *data, u8 rsp_code, u8 amp_id) | 3592 | struct l2cap_cmd_hdr *cmd, |
3593 | u8 *data, u8 rsp_code, u8 amp_id) | ||
3400 | { | 3594 | { |
3401 | struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; | 3595 | struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; |
3402 | struct l2cap_conn_rsp rsp; | 3596 | struct l2cap_conn_rsp rsp; |
@@ -3447,6 +3641,7 @@ static void l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, | |||
3447 | bacpy(&bt_sk(sk)->dst, conn->dst); | 3641 | bacpy(&bt_sk(sk)->dst, conn->dst); |
3448 | chan->psm = psm; | 3642 | chan->psm = psm; |
3449 | chan->dcid = scid; | 3643 | chan->dcid = scid; |
3644 | chan->local_amp_id = amp_id; | ||
3450 | 3645 | ||
3451 | __l2cap_chan_add(conn, chan); | 3646 | __l2cap_chan_add(conn, chan); |
3452 | 3647 | ||
@@ -3464,8 +3659,17 @@ static void l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, | |||
3464 | status = L2CAP_CS_AUTHOR_PEND; | 3659 | status = L2CAP_CS_AUTHOR_PEND; |
3465 | chan->ops->defer(chan); | 3660 | chan->ops->defer(chan); |
3466 | } else { | 3661 | } else { |
3467 | __l2cap_state_change(chan, BT_CONFIG); | 3662 | /* Force pending result for AMP controllers. |
3468 | result = L2CAP_CR_SUCCESS; | 3663 | * The connection will succeed after the |
3664 | * physical link is up. | ||
3665 | */ | ||
3666 | if (amp_id) { | ||
3667 | __l2cap_state_change(chan, BT_CONNECT2); | ||
3668 | result = L2CAP_CR_PEND; | ||
3669 | } else { | ||
3670 | __l2cap_state_change(chan, BT_CONFIG); | ||
3671 | result = L2CAP_CR_SUCCESS; | ||
3672 | } | ||
3469 | status = L2CAP_CS_NO_INFO; | 3673 | status = L2CAP_CS_NO_INFO; |
3470 | } | 3674 | } |
3471 | } else { | 3675 | } else { |
@@ -3511,6 +3715,8 @@ sendresp: | |||
3511 | l2cap_build_conf_req(chan, buf), buf); | 3715 | l2cap_build_conf_req(chan, buf), buf); |
3512 | chan->num_conf_req++; | 3716 | chan->num_conf_req++; |
3513 | } | 3717 | } |
3718 | |||
3719 | return chan; | ||
3514 | } | 3720 | } |
3515 | 3721 | ||
3516 | static int l2cap_connect_req(struct l2cap_conn *conn, | 3722 | static int l2cap_connect_req(struct l2cap_conn *conn, |
@@ -3520,7 +3726,7 @@ static int l2cap_connect_req(struct l2cap_conn *conn, | |||
3520 | return 0; | 3726 | return 0; |
3521 | } | 3727 | } |
3522 | 3728 | ||
3523 | static inline int l2cap_connect_rsp(struct l2cap_conn *conn, | 3729 | static int l2cap_connect_create_rsp(struct l2cap_conn *conn, |
3524 | struct l2cap_cmd_hdr *cmd, u8 *data) | 3730 | struct l2cap_cmd_hdr *cmd, u8 *data) |
3525 | { | 3731 | { |
3526 | struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data; | 3732 | struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data; |
@@ -3675,6 +3881,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, | |||
3675 | goto unlock; | 3881 | goto unlock; |
3676 | } | 3882 | } |
3677 | 3883 | ||
3884 | chan->ident = cmd->ident; | ||
3678 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp); | 3885 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp); |
3679 | chan->num_conf_rsp++; | 3886 | chan->num_conf_rsp++; |
3680 | 3887 | ||
@@ -3714,7 +3921,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, | |||
3714 | /* check compatibility */ | 3921 | /* check compatibility */ |
3715 | 3922 | ||
3716 | /* Send rsp for BR/EDR channel */ | 3923 | /* Send rsp for BR/EDR channel */ |
3717 | if (!chan->ctrl_id) | 3924 | if (!chan->hs_hcon) |
3718 | l2cap_send_efs_conf_rsp(chan, rsp, cmd->ident, flags); | 3925 | l2cap_send_efs_conf_rsp(chan, rsp, cmd->ident, flags); |
3719 | else | 3926 | else |
3720 | chan->ident = cmd->ident; | 3927 | chan->ident = cmd->ident; |
@@ -3764,13 +3971,15 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, | |||
3764 | goto done; | 3971 | goto done; |
3765 | } | 3972 | } |
3766 | 3973 | ||
3767 | /* check compatibility */ | 3974 | if (!chan->hs_hcon) { |
3768 | |||
3769 | if (!chan->ctrl_id) | ||
3770 | l2cap_send_efs_conf_rsp(chan, buf, cmd->ident, | 3975 | l2cap_send_efs_conf_rsp(chan, buf, cmd->ident, |
3771 | 0); | 3976 | 0); |
3772 | else | 3977 | } else { |
3773 | chan->ident = cmd->ident; | 3978 | if (l2cap_check_efs(chan)) { |
3979 | amp_create_logical_link(chan); | ||
3980 | chan->ident = cmd->ident; | ||
3981 | } | ||
3982 | } | ||
3774 | } | 3983 | } |
3775 | goto done; | 3984 | goto done; |
3776 | 3985 | ||
@@ -4023,12 +4232,14 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, | |||
4023 | return 0; | 4232 | return 0; |
4024 | } | 4233 | } |
4025 | 4234 | ||
4026 | static inline int l2cap_create_channel_req(struct l2cap_conn *conn, | 4235 | static int l2cap_create_channel_req(struct l2cap_conn *conn, |
4027 | struct l2cap_cmd_hdr *cmd, | 4236 | struct l2cap_cmd_hdr *cmd, |
4028 | u16 cmd_len, void *data) | 4237 | u16 cmd_len, void *data) |
4029 | { | 4238 | { |
4030 | struct l2cap_create_chan_req *req = data; | 4239 | struct l2cap_create_chan_req *req = data; |
4031 | struct l2cap_create_chan_rsp rsp; | 4240 | struct l2cap_create_chan_rsp rsp; |
4241 | struct l2cap_chan *chan; | ||
4242 | struct hci_dev *hdev; | ||
4032 | u16 psm, scid; | 4243 | u16 psm, scid; |
4033 | 4244 | ||
4034 | if (cmd_len != sizeof(*req)) | 4245 | if (cmd_len != sizeof(*req)) |
@@ -4042,57 +4253,119 @@ static inline int l2cap_create_channel_req(struct l2cap_conn *conn, | |||
4042 | 4253 | ||
4043 | BT_DBG("psm 0x%2.2x, scid 0x%4.4x, amp_id %d", psm, scid, req->amp_id); | 4254 | BT_DBG("psm 0x%2.2x, scid 0x%4.4x, amp_id %d", psm, scid, req->amp_id); |
4044 | 4255 | ||
4045 | /* Placeholder: Always reject */ | 4256 | /* For controller id 0 make BR/EDR connection */ |
4257 | if (req->amp_id == HCI_BREDR_ID) { | ||
4258 | l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP, | ||
4259 | req->amp_id); | ||
4260 | return 0; | ||
4261 | } | ||
4262 | |||
4263 | /* Validate AMP controller id */ | ||
4264 | hdev = hci_dev_get(req->amp_id); | ||
4265 | if (!hdev) | ||
4266 | goto error; | ||
4267 | |||
4268 | if (hdev->dev_type != HCI_AMP || !test_bit(HCI_UP, &hdev->flags)) { | ||
4269 | hci_dev_put(hdev); | ||
4270 | goto error; | ||
4271 | } | ||
4272 | |||
4273 | chan = l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP, | ||
4274 | req->amp_id); | ||
4275 | if (chan) { | ||
4276 | struct amp_mgr *mgr = conn->hcon->amp_mgr; | ||
4277 | struct hci_conn *hs_hcon; | ||
4278 | |||
4279 | hs_hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK, conn->dst); | ||
4280 | if (!hs_hcon) { | ||
4281 | hci_dev_put(hdev); | ||
4282 | return -EFAULT; | ||
4283 | } | ||
4284 | |||
4285 | BT_DBG("mgr %p bredr_chan %p hs_hcon %p", mgr, chan, hs_hcon); | ||
4286 | |||
4287 | mgr->bredr_chan = chan; | ||
4288 | chan->hs_hcon = hs_hcon; | ||
4289 | chan->fcs = L2CAP_FCS_NONE; | ||
4290 | conn->mtu = hdev->block_mtu; | ||
4291 | } | ||
4292 | |||
4293 | hci_dev_put(hdev); | ||
4294 | |||
4295 | return 0; | ||
4296 | |||
4297 | error: | ||
4046 | rsp.dcid = 0; | 4298 | rsp.dcid = 0; |
4047 | rsp.scid = cpu_to_le16(scid); | 4299 | rsp.scid = cpu_to_le16(scid); |
4048 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM); | 4300 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_BAD_AMP); |
4049 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); | 4301 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); |
4050 | 4302 | ||
4051 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP, | 4303 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP, |
4052 | sizeof(rsp), &rsp); | 4304 | sizeof(rsp), &rsp); |
4053 | 4305 | ||
4054 | return 0; | 4306 | return -EFAULT; |
4055 | } | 4307 | } |
4056 | 4308 | ||
4057 | static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn, | 4309 | static void l2cap_send_move_chan_req(struct l2cap_chan *chan, u8 dest_amp_id) |
4058 | struct l2cap_cmd_hdr *cmd, | ||
4059 | void *data) | ||
4060 | { | 4310 | { |
4061 | BT_DBG("conn %p", conn); | 4311 | struct l2cap_move_chan_req req; |
4312 | u8 ident; | ||
4313 | |||
4314 | BT_DBG("chan %p, dest_amp_id %d", chan, dest_amp_id); | ||
4315 | |||
4316 | ident = l2cap_get_ident(chan->conn); | ||
4317 | chan->ident = ident; | ||
4062 | 4318 | ||
4063 | return l2cap_connect_rsp(conn, cmd, data); | 4319 | req.icid = cpu_to_le16(chan->scid); |
4320 | req.dest_amp_id = dest_amp_id; | ||
4321 | |||
4322 | l2cap_send_cmd(chan->conn, ident, L2CAP_MOVE_CHAN_REQ, sizeof(req), | ||
4323 | &req); | ||
4324 | |||
4325 | __set_chan_timer(chan, L2CAP_MOVE_TIMEOUT); | ||
4064 | } | 4326 | } |
4065 | 4327 | ||
4066 | static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident, | 4328 | static void l2cap_send_move_chan_rsp(struct l2cap_chan *chan, u16 result) |
4067 | u16 icid, u16 result) | ||
4068 | { | 4329 | { |
4069 | struct l2cap_move_chan_rsp rsp; | 4330 | struct l2cap_move_chan_rsp rsp; |
4070 | 4331 | ||
4071 | BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result); | 4332 | BT_DBG("chan %p, result 0x%4.4x", chan, result); |
4072 | 4333 | ||
4073 | rsp.icid = cpu_to_le16(icid); | 4334 | rsp.icid = cpu_to_le16(chan->dcid); |
4074 | rsp.result = cpu_to_le16(result); | 4335 | rsp.result = cpu_to_le16(result); |
4075 | 4336 | ||
4076 | l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp); | 4337 | l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_RSP, |
4338 | sizeof(rsp), &rsp); | ||
4077 | } | 4339 | } |
4078 | 4340 | ||
4079 | static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn, | 4341 | static void l2cap_send_move_chan_cfm(struct l2cap_chan *chan, u16 result) |
4080 | struct l2cap_chan *chan, | ||
4081 | u16 icid, u16 result) | ||
4082 | { | 4342 | { |
4083 | struct l2cap_move_chan_cfm cfm; | 4343 | struct l2cap_move_chan_cfm cfm; |
4084 | u8 ident; | ||
4085 | 4344 | ||
4086 | BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result); | 4345 | BT_DBG("chan %p, result 0x%4.4x", chan, result); |
4087 | 4346 | ||
4088 | ident = l2cap_get_ident(conn); | 4347 | chan->ident = l2cap_get_ident(chan->conn); |
4089 | if (chan) | ||
4090 | chan->ident = ident; | ||
4091 | 4348 | ||
4092 | cfm.icid = cpu_to_le16(icid); | 4349 | cfm.icid = cpu_to_le16(chan->scid); |
4093 | cfm.result = cpu_to_le16(result); | 4350 | cfm.result = cpu_to_le16(result); |
4094 | 4351 | ||
4095 | l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm); | 4352 | l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_CFM, |
4353 | sizeof(cfm), &cfm); | ||
4354 | |||
4355 | __set_chan_timer(chan, L2CAP_MOVE_TIMEOUT); | ||
4356 | } | ||
4357 | |||
4358 | static void l2cap_send_move_chan_cfm_icid(struct l2cap_conn *conn, u16 icid) | ||
4359 | { | ||
4360 | struct l2cap_move_chan_cfm cfm; | ||
4361 | |||
4362 | BT_DBG("conn %p, icid 0x%4.4x", conn, icid); | ||
4363 | |||
4364 | cfm.icid = cpu_to_le16(icid); | ||
4365 | cfm.result = __constant_cpu_to_le16(L2CAP_MC_UNCONFIRMED); | ||
4366 | |||
4367 | l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_MOVE_CHAN_CFM, | ||
4368 | sizeof(cfm), &cfm); | ||
4096 | } | 4369 | } |
4097 | 4370 | ||
4098 | static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident, | 4371 | static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident, |
@@ -4106,11 +4379,289 @@ static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident, | |||
4106 | l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp); | 4379 | l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp); |
4107 | } | 4380 | } |
4108 | 4381 | ||
4382 | static void __release_logical_link(struct l2cap_chan *chan) | ||
4383 | { | ||
4384 | chan->hs_hchan = NULL; | ||
4385 | chan->hs_hcon = NULL; | ||
4386 | |||
4387 | /* Placeholder - release the logical link */ | ||
4388 | } | ||
4389 | |||
4390 | static void l2cap_logical_fail(struct l2cap_chan *chan) | ||
4391 | { | ||
4392 | /* Logical link setup failed */ | ||
4393 | if (chan->state != BT_CONNECTED) { | ||
4394 | /* Create channel failure, disconnect */ | ||
4395 | l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); | ||
4396 | return; | ||
4397 | } | ||
4398 | |||
4399 | switch (chan->move_role) { | ||
4400 | case L2CAP_MOVE_ROLE_RESPONDER: | ||
4401 | l2cap_move_done(chan); | ||
4402 | l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_SUPP); | ||
4403 | break; | ||
4404 | case L2CAP_MOVE_ROLE_INITIATOR: | ||
4405 | if (chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_COMP || | ||
4406 | chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_CFM) { | ||
4407 | /* Remote has only sent pending or | ||
4408 | * success responses, clean up | ||
4409 | */ | ||
4410 | l2cap_move_done(chan); | ||
4411 | } | ||
4412 | |||
4413 | /* Other amp move states imply that the move | ||
4414 | * has already aborted | ||
4415 | */ | ||
4416 | l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); | ||
4417 | break; | ||
4418 | } | ||
4419 | } | ||
4420 | |||
4421 | static void l2cap_logical_finish_create(struct l2cap_chan *chan, | ||
4422 | struct hci_chan *hchan) | ||
4423 | { | ||
4424 | struct l2cap_conf_rsp rsp; | ||
4425 | |||
4426 | chan->hs_hchan = hchan; | ||
4427 | chan->hs_hcon->l2cap_data = chan->conn; | ||
4428 | |||
4429 | l2cap_send_efs_conf_rsp(chan, &rsp, chan->ident, 0); | ||
4430 | |||
4431 | if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { | ||
4432 | int err; | ||
4433 | |||
4434 | set_default_fcs(chan); | ||
4435 | |||
4436 | err = l2cap_ertm_init(chan); | ||
4437 | if (err < 0) | ||
4438 | l2cap_send_disconn_req(chan->conn, chan, -err); | ||
4439 | else | ||
4440 | l2cap_chan_ready(chan); | ||
4441 | } | ||
4442 | } | ||
4443 | |||
4444 | static void l2cap_logical_finish_move(struct l2cap_chan *chan, | ||
4445 | struct hci_chan *hchan) | ||
4446 | { | ||
4447 | chan->hs_hcon = hchan->conn; | ||
4448 | chan->hs_hcon->l2cap_data = chan->conn; | ||
4449 | |||
4450 | BT_DBG("move_state %d", chan->move_state); | ||
4451 | |||
4452 | switch (chan->move_state) { | ||
4453 | case L2CAP_MOVE_WAIT_LOGICAL_COMP: | ||
4454 | /* Move confirm will be sent after a success | ||
4455 | * response is received | ||
4456 | */ | ||
4457 | chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS; | ||
4458 | break; | ||
4459 | case L2CAP_MOVE_WAIT_LOGICAL_CFM: | ||
4460 | if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { | ||
4461 | chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY; | ||
4462 | } else if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) { | ||
4463 | chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP; | ||
4464 | l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED); | ||
4465 | } else if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) { | ||
4466 | chan->move_state = L2CAP_MOVE_WAIT_CONFIRM; | ||
4467 | l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS); | ||
4468 | } | ||
4469 | break; | ||
4470 | default: | ||
4471 | /* Move was not in expected state, free the channel */ | ||
4472 | __release_logical_link(chan); | ||
4473 | |||
4474 | chan->move_state = L2CAP_MOVE_STABLE; | ||
4475 | } | ||
4476 | } | ||
4477 | |||
4478 | /* Call with chan locked */ | ||
4479 | void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan, | ||
4480 | u8 status) | ||
4481 | { | ||
4482 | BT_DBG("chan %p, hchan %p, status %d", chan, hchan, status); | ||
4483 | |||
4484 | if (status) { | ||
4485 | l2cap_logical_fail(chan); | ||
4486 | __release_logical_link(chan); | ||
4487 | return; | ||
4488 | } | ||
4489 | |||
4490 | if (chan->state != BT_CONNECTED) { | ||
4491 | /* Ignore logical link if channel is on BR/EDR */ | ||
4492 | if (chan->local_amp_id) | ||
4493 | l2cap_logical_finish_create(chan, hchan); | ||
4494 | } else { | ||
4495 | l2cap_logical_finish_move(chan, hchan); | ||
4496 | } | ||
4497 | } | ||
4498 | |||
4499 | void l2cap_move_start(struct l2cap_chan *chan) | ||
4500 | { | ||
4501 | BT_DBG("chan %p", chan); | ||
4502 | |||
4503 | if (chan->local_amp_id == HCI_BREDR_ID) { | ||
4504 | if (chan->chan_policy != BT_CHANNEL_POLICY_AMP_PREFERRED) | ||
4505 | return; | ||
4506 | chan->move_role = L2CAP_MOVE_ROLE_INITIATOR; | ||
4507 | chan->move_state = L2CAP_MOVE_WAIT_PREPARE; | ||
4508 | /* Placeholder - start physical link setup */ | ||
4509 | } else { | ||
4510 | chan->move_role = L2CAP_MOVE_ROLE_INITIATOR; | ||
4511 | chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS; | ||
4512 | chan->move_id = 0; | ||
4513 | l2cap_move_setup(chan); | ||
4514 | l2cap_send_move_chan_req(chan, 0); | ||
4515 | } | ||
4516 | } | ||
4517 | |||
4518 | static void l2cap_do_create(struct l2cap_chan *chan, int result, | ||
4519 | u8 local_amp_id, u8 remote_amp_id) | ||
4520 | { | ||
4521 | BT_DBG("chan %p state %s %u -> %u", chan, state_to_string(chan->state), | ||
4522 | local_amp_id, remote_amp_id); | ||
4523 | |||
4524 | chan->fcs = L2CAP_FCS_NONE; | ||
4525 | |||
4526 | /* Outgoing channel on AMP */ | ||
4527 | if (chan->state == BT_CONNECT) { | ||
4528 | if (result == L2CAP_CR_SUCCESS) { | ||
4529 | chan->local_amp_id = local_amp_id; | ||
4530 | l2cap_send_create_chan_req(chan, remote_amp_id); | ||
4531 | } else { | ||
4532 | /* Revert to BR/EDR connect */ | ||
4533 | l2cap_send_conn_req(chan); | ||
4534 | } | ||
4535 | |||
4536 | return; | ||
4537 | } | ||
4538 | |||
4539 | /* Incoming channel on AMP */ | ||
4540 | if (__l2cap_no_conn_pending(chan)) { | ||
4541 | struct l2cap_conn_rsp rsp; | ||
4542 | char buf[128]; | ||
4543 | rsp.scid = cpu_to_le16(chan->dcid); | ||
4544 | rsp.dcid = cpu_to_le16(chan->scid); | ||
4545 | |||
4546 | if (result == L2CAP_CR_SUCCESS) { | ||
4547 | /* Send successful response */ | ||
4548 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); | ||
4549 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); | ||
4550 | } else { | ||
4551 | /* Send negative response */ | ||
4552 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM); | ||
4553 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); | ||
4554 | } | ||
4555 | |||
4556 | l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_RSP, | ||
4557 | sizeof(rsp), &rsp); | ||
4558 | |||
4559 | if (result == L2CAP_CR_SUCCESS) { | ||
4560 | __l2cap_state_change(chan, BT_CONFIG); | ||
4561 | set_bit(CONF_REQ_SENT, &chan->conf_state); | ||
4562 | l2cap_send_cmd(chan->conn, l2cap_get_ident(chan->conn), | ||
4563 | L2CAP_CONF_REQ, | ||
4564 | l2cap_build_conf_req(chan, buf), buf); | ||
4565 | chan->num_conf_req++; | ||
4566 | } | ||
4567 | } | ||
4568 | } | ||
4569 | |||
4570 | static void l2cap_do_move_initiate(struct l2cap_chan *chan, u8 local_amp_id, | ||
4571 | u8 remote_amp_id) | ||
4572 | { | ||
4573 | l2cap_move_setup(chan); | ||
4574 | chan->move_id = local_amp_id; | ||
4575 | chan->move_state = L2CAP_MOVE_WAIT_RSP; | ||
4576 | |||
4577 | l2cap_send_move_chan_req(chan, remote_amp_id); | ||
4578 | } | ||
4579 | |||
4580 | static void l2cap_do_move_respond(struct l2cap_chan *chan, int result) | ||
4581 | { | ||
4582 | struct hci_chan *hchan = NULL; | ||
4583 | |||
4584 | /* Placeholder - get hci_chan for logical link */ | ||
4585 | |||
4586 | if (hchan) { | ||
4587 | if (hchan->state == BT_CONNECTED) { | ||
4588 | /* Logical link is ready to go */ | ||
4589 | chan->hs_hcon = hchan->conn; | ||
4590 | chan->hs_hcon->l2cap_data = chan->conn; | ||
4591 | chan->move_state = L2CAP_MOVE_WAIT_CONFIRM; | ||
4592 | l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS); | ||
4593 | |||
4594 | l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS); | ||
4595 | } else { | ||
4596 | /* Wait for logical link to be ready */ | ||
4597 | chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM; | ||
4598 | } | ||
4599 | } else { | ||
4600 | /* Logical link not available */ | ||
4601 | l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_ALLOWED); | ||
4602 | } | ||
4603 | } | ||
4604 | |||
4605 | static void l2cap_do_move_cancel(struct l2cap_chan *chan, int result) | ||
4606 | { | ||
4607 | if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) { | ||
4608 | u8 rsp_result; | ||
4609 | if (result == -EINVAL) | ||
4610 | rsp_result = L2CAP_MR_BAD_ID; | ||
4611 | else | ||
4612 | rsp_result = L2CAP_MR_NOT_ALLOWED; | ||
4613 | |||
4614 | l2cap_send_move_chan_rsp(chan, rsp_result); | ||
4615 | } | ||
4616 | |||
4617 | chan->move_role = L2CAP_MOVE_ROLE_NONE; | ||
4618 | chan->move_state = L2CAP_MOVE_STABLE; | ||
4619 | |||
4620 | /* Restart data transmission */ | ||
4621 | l2cap_ertm_send(chan); | ||
4622 | } | ||
4623 | |||
4624 | /* Invoke with locked chan */ | ||
4625 | void __l2cap_physical_cfm(struct l2cap_chan *chan, int result) | ||
4626 | { | ||
4627 | u8 local_amp_id = chan->local_amp_id; | ||
4628 | u8 remote_amp_id = chan->remote_amp_id; | ||
4629 | |||
4630 | BT_DBG("chan %p, result %d, local_amp_id %d, remote_amp_id %d", | ||
4631 | chan, result, local_amp_id, remote_amp_id); | ||
4632 | |||
4633 | if (chan->state == BT_DISCONN || chan->state == BT_CLOSED) { | ||
4634 | l2cap_chan_unlock(chan); | ||
4635 | return; | ||
4636 | } | ||
4637 | |||
4638 | if (chan->state != BT_CONNECTED) { | ||
4639 | l2cap_do_create(chan, result, local_amp_id, remote_amp_id); | ||
4640 | } else if (result != L2CAP_MR_SUCCESS) { | ||
4641 | l2cap_do_move_cancel(chan, result); | ||
4642 | } else { | ||
4643 | switch (chan->move_role) { | ||
4644 | case L2CAP_MOVE_ROLE_INITIATOR: | ||
4645 | l2cap_do_move_initiate(chan, local_amp_id, | ||
4646 | remote_amp_id); | ||
4647 | break; | ||
4648 | case L2CAP_MOVE_ROLE_RESPONDER: | ||
4649 | l2cap_do_move_respond(chan, result); | ||
4650 | break; | ||
4651 | default: | ||
4652 | l2cap_do_move_cancel(chan, result); | ||
4653 | break; | ||
4654 | } | ||
4655 | } | ||
4656 | } | ||
4657 | |||
4109 | static inline int l2cap_move_channel_req(struct l2cap_conn *conn, | 4658 | static inline int l2cap_move_channel_req(struct l2cap_conn *conn, |
4110 | struct l2cap_cmd_hdr *cmd, | 4659 | struct l2cap_cmd_hdr *cmd, |
4111 | u16 cmd_len, void *data) | 4660 | u16 cmd_len, void *data) |
4112 | { | 4661 | { |
4113 | struct l2cap_move_chan_req *req = data; | 4662 | struct l2cap_move_chan_req *req = data; |
4663 | struct l2cap_move_chan_rsp rsp; | ||
4664 | struct l2cap_chan *chan; | ||
4114 | u16 icid = 0; | 4665 | u16 icid = 0; |
4115 | u16 result = L2CAP_MR_NOT_ALLOWED; | 4666 | u16 result = L2CAP_MR_NOT_ALLOWED; |
4116 | 4667 | ||
@@ -4124,15 +4675,206 @@ static inline int l2cap_move_channel_req(struct l2cap_conn *conn, | |||
4124 | if (!enable_hs) | 4675 | if (!enable_hs) |
4125 | return -EINVAL; | 4676 | return -EINVAL; |
4126 | 4677 | ||
4127 | /* Placeholder: Always refuse */ | 4678 | chan = l2cap_get_chan_by_dcid(conn, icid); |
4128 | l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result); | 4679 | if (!chan) { |
4680 | rsp.icid = cpu_to_le16(icid); | ||
4681 | rsp.result = __constant_cpu_to_le16(L2CAP_MR_NOT_ALLOWED); | ||
4682 | l2cap_send_cmd(conn, cmd->ident, L2CAP_MOVE_CHAN_RSP, | ||
4683 | sizeof(rsp), &rsp); | ||
4684 | return 0; | ||
4685 | } | ||
4686 | |||
4687 | chan->ident = cmd->ident; | ||
4688 | |||
4689 | if (chan->scid < L2CAP_CID_DYN_START || | ||
4690 | chan->chan_policy == BT_CHANNEL_POLICY_BREDR_ONLY || | ||
4691 | (chan->mode != L2CAP_MODE_ERTM && | ||
4692 | chan->mode != L2CAP_MODE_STREAMING)) { | ||
4693 | result = L2CAP_MR_NOT_ALLOWED; | ||
4694 | goto send_move_response; | ||
4695 | } | ||
4696 | |||
4697 | if (chan->local_amp_id == req->dest_amp_id) { | ||
4698 | result = L2CAP_MR_SAME_ID; | ||
4699 | goto send_move_response; | ||
4700 | } | ||
4701 | |||
4702 | if (req->dest_amp_id) { | ||
4703 | struct hci_dev *hdev; | ||
4704 | hdev = hci_dev_get(req->dest_amp_id); | ||
4705 | if (!hdev || hdev->dev_type != HCI_AMP || | ||
4706 | !test_bit(HCI_UP, &hdev->flags)) { | ||
4707 | if (hdev) | ||
4708 | hci_dev_put(hdev); | ||
4709 | |||
4710 | result = L2CAP_MR_BAD_ID; | ||
4711 | goto send_move_response; | ||
4712 | } | ||
4713 | hci_dev_put(hdev); | ||
4714 | } | ||
4715 | |||
4716 | /* Detect a move collision. Only send a collision response | ||
4717 | * if this side has "lost", otherwise proceed with the move. | ||
4718 | * The winner has the larger bd_addr. | ||
4719 | */ | ||
4720 | if ((__chan_is_moving(chan) || | ||
4721 | chan->move_role != L2CAP_MOVE_ROLE_NONE) && | ||
4722 | bacmp(conn->src, conn->dst) > 0) { | ||
4723 | result = L2CAP_MR_COLLISION; | ||
4724 | goto send_move_response; | ||
4725 | } | ||
4726 | |||
4727 | chan->move_role = L2CAP_MOVE_ROLE_RESPONDER; | ||
4728 | l2cap_move_setup(chan); | ||
4729 | chan->move_id = req->dest_amp_id; | ||
4730 | icid = chan->dcid; | ||
4731 | |||
4732 | if (!req->dest_amp_id) { | ||
4733 | /* Moving to BR/EDR */ | ||
4734 | if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { | ||
4735 | chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY; | ||
4736 | result = L2CAP_MR_PEND; | ||
4737 | } else { | ||
4738 | chan->move_state = L2CAP_MOVE_WAIT_CONFIRM; | ||
4739 | result = L2CAP_MR_SUCCESS; | ||
4740 | } | ||
4741 | } else { | ||
4742 | chan->move_state = L2CAP_MOVE_WAIT_PREPARE; | ||
4743 | /* Placeholder - uncomment when amp functions are available */ | ||
4744 | /*amp_accept_physical(chan, req->dest_amp_id);*/ | ||
4745 | result = L2CAP_MR_PEND; | ||
4746 | } | ||
4747 | |||
4748 | send_move_response: | ||
4749 | l2cap_send_move_chan_rsp(chan, result); | ||
4750 | |||
4751 | l2cap_chan_unlock(chan); | ||
4129 | 4752 | ||
4130 | return 0; | 4753 | return 0; |
4131 | } | 4754 | } |
4132 | 4755 | ||
4133 | static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn, | 4756 | static void l2cap_move_continue(struct l2cap_conn *conn, u16 icid, u16 result) |
4134 | struct l2cap_cmd_hdr *cmd, | 4757 | { |
4135 | u16 cmd_len, void *data) | 4758 | struct l2cap_chan *chan; |
4759 | struct hci_chan *hchan = NULL; | ||
4760 | |||
4761 | chan = l2cap_get_chan_by_scid(conn, icid); | ||
4762 | if (!chan) { | ||
4763 | l2cap_send_move_chan_cfm_icid(conn, icid); | ||
4764 | return; | ||
4765 | } | ||
4766 | |||
4767 | __clear_chan_timer(chan); | ||
4768 | if (result == L2CAP_MR_PEND) | ||
4769 | __set_chan_timer(chan, L2CAP_MOVE_ERTX_TIMEOUT); | ||
4770 | |||
4771 | switch (chan->move_state) { | ||
4772 | case L2CAP_MOVE_WAIT_LOGICAL_COMP: | ||
4773 | /* Move confirm will be sent when logical link | ||
4774 | * is complete. | ||
4775 | */ | ||
4776 | chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM; | ||
4777 | break; | ||
4778 | case L2CAP_MOVE_WAIT_RSP_SUCCESS: | ||
4779 | if (result == L2CAP_MR_PEND) { | ||
4780 | break; | ||
4781 | } else if (test_bit(CONN_LOCAL_BUSY, | ||
4782 | &chan->conn_state)) { | ||
4783 | chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY; | ||
4784 | } else { | ||
4785 | /* Logical link is up or moving to BR/EDR, | ||
4786 | * proceed with move | ||
4787 | */ | ||
4788 | chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP; | ||
4789 | l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED); | ||
4790 | } | ||
4791 | break; | ||
4792 | case L2CAP_MOVE_WAIT_RSP: | ||
4793 | /* Moving to AMP */ | ||
4794 | if (result == L2CAP_MR_SUCCESS) { | ||
4795 | /* Remote is ready, send confirm immediately | ||
4796 | * after logical link is ready | ||
4797 | */ | ||
4798 | chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM; | ||
4799 | } else { | ||
4800 | /* Both logical link and move success | ||
4801 | * are required to confirm | ||
4802 | */ | ||
4803 | chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_COMP; | ||
4804 | } | ||
4805 | |||
4806 | /* Placeholder - get hci_chan for logical link */ | ||
4807 | if (!hchan) { | ||
4808 | /* Logical link not available */ | ||
4809 | l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); | ||
4810 | break; | ||
4811 | } | ||
4812 | |||
4813 | /* If the logical link is not yet connected, do not | ||
4814 | * send confirmation. | ||
4815 | */ | ||
4816 | if (hchan->state != BT_CONNECTED) | ||
4817 | break; | ||
4818 | |||
4819 | /* Logical link is already ready to go */ | ||
4820 | |||
4821 | chan->hs_hcon = hchan->conn; | ||
4822 | chan->hs_hcon->l2cap_data = chan->conn; | ||
4823 | |||
4824 | if (result == L2CAP_MR_SUCCESS) { | ||
4825 | /* Can confirm now */ | ||
4826 | l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED); | ||
4827 | } else { | ||
4828 | /* Now only need move success | ||
4829 | * to confirm | ||
4830 | */ | ||
4831 | chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS; | ||
4832 | } | ||
4833 | |||
4834 | l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS); | ||
4835 | break; | ||
4836 | default: | ||
4837 | /* Any other amp move state means the move failed. */ | ||
4838 | chan->move_id = chan->local_amp_id; | ||
4839 | l2cap_move_done(chan); | ||
4840 | l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); | ||
4841 | } | ||
4842 | |||
4843 | l2cap_chan_unlock(chan); | ||
4844 | } | ||
4845 | |||
4846 | static void l2cap_move_fail(struct l2cap_conn *conn, u8 ident, u16 icid, | ||
4847 | u16 result) | ||
4848 | { | ||
4849 | struct l2cap_chan *chan; | ||
4850 | |||
4851 | chan = l2cap_get_chan_by_ident(conn, ident); | ||
4852 | if (!chan) { | ||
4853 | /* Could not locate channel, icid is best guess */ | ||
4854 | l2cap_send_move_chan_cfm_icid(conn, icid); | ||
4855 | return; | ||
4856 | } | ||
4857 | |||
4858 | __clear_chan_timer(chan); | ||
4859 | |||
4860 | if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) { | ||
4861 | if (result == L2CAP_MR_COLLISION) { | ||
4862 | chan->move_role = L2CAP_MOVE_ROLE_RESPONDER; | ||
4863 | } else { | ||
4864 | /* Cleanup - cancel move */ | ||
4865 | chan->move_id = chan->local_amp_id; | ||
4866 | l2cap_move_done(chan); | ||
4867 | } | ||
4868 | } | ||
4869 | |||
4870 | l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED); | ||
4871 | |||
4872 | l2cap_chan_unlock(chan); | ||
4873 | } | ||
4874 | |||
4875 | static int l2cap_move_channel_rsp(struct l2cap_conn *conn, | ||
4876 | struct l2cap_cmd_hdr *cmd, | ||
4877 | u16 cmd_len, void *data) | ||
4136 | { | 4878 | { |
4137 | struct l2cap_move_chan_rsp *rsp = data; | 4879 | struct l2cap_move_chan_rsp *rsp = data; |
4138 | u16 icid, result; | 4880 | u16 icid, result; |
@@ -4145,17 +4887,20 @@ static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn, | |||
4145 | 4887 | ||
4146 | BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result); | 4888 | BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result); |
4147 | 4889 | ||
4148 | /* Placeholder: Always unconfirmed */ | 4890 | if (result == L2CAP_MR_SUCCESS || result == L2CAP_MR_PEND) |
4149 | l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED); | 4891 | l2cap_move_continue(conn, icid, result); |
4892 | else | ||
4893 | l2cap_move_fail(conn, cmd->ident, icid, result); | ||
4150 | 4894 | ||
4151 | return 0; | 4895 | return 0; |
4152 | } | 4896 | } |
4153 | 4897 | ||
4154 | static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn, | 4898 | static int l2cap_move_channel_confirm(struct l2cap_conn *conn, |
4155 | struct l2cap_cmd_hdr *cmd, | 4899 | struct l2cap_cmd_hdr *cmd, |
4156 | u16 cmd_len, void *data) | 4900 | u16 cmd_len, void *data) |
4157 | { | 4901 | { |
4158 | struct l2cap_move_chan_cfm *cfm = data; | 4902 | struct l2cap_move_chan_cfm *cfm = data; |
4903 | struct l2cap_chan *chan; | ||
4159 | u16 icid, result; | 4904 | u16 icid, result; |
4160 | 4905 | ||
4161 | if (cmd_len != sizeof(*cfm)) | 4906 | if (cmd_len != sizeof(*cfm)) |
@@ -4166,8 +4911,29 @@ static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn, | |||
4166 | 4911 | ||
4167 | BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result); | 4912 | BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result); |
4168 | 4913 | ||
4914 | chan = l2cap_get_chan_by_dcid(conn, icid); | ||
4915 | if (!chan) { | ||
4916 | /* Spec requires a response even if the icid was not found */ | ||
4917 | l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid); | ||
4918 | return 0; | ||
4919 | } | ||
4920 | |||
4921 | if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM) { | ||
4922 | if (result == L2CAP_MC_CONFIRMED) { | ||
4923 | chan->local_amp_id = chan->move_id; | ||
4924 | if (!chan->local_amp_id) | ||
4925 | __release_logical_link(chan); | ||
4926 | } else { | ||
4927 | chan->move_id = chan->local_amp_id; | ||
4928 | } | ||
4929 | |||
4930 | l2cap_move_done(chan); | ||
4931 | } | ||
4932 | |||
4169 | l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid); | 4933 | l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid); |
4170 | 4934 | ||
4935 | l2cap_chan_unlock(chan); | ||
4936 | |||
4171 | return 0; | 4937 | return 0; |
4172 | } | 4938 | } |
4173 | 4939 | ||
@@ -4176,6 +4942,7 @@ static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn, | |||
4176 | u16 cmd_len, void *data) | 4942 | u16 cmd_len, void *data) |
4177 | { | 4943 | { |
4178 | struct l2cap_move_chan_cfm_rsp *rsp = data; | 4944 | struct l2cap_move_chan_cfm_rsp *rsp = data; |
4945 | struct l2cap_chan *chan; | ||
4179 | u16 icid; | 4946 | u16 icid; |
4180 | 4947 | ||
4181 | if (cmd_len != sizeof(*rsp)) | 4948 | if (cmd_len != sizeof(*rsp)) |
@@ -4185,6 +4952,23 @@ static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn, | |||
4185 | 4952 | ||
4186 | BT_DBG("icid 0x%4.4x", icid); | 4953 | BT_DBG("icid 0x%4.4x", icid); |
4187 | 4954 | ||
4955 | chan = l2cap_get_chan_by_scid(conn, icid); | ||
4956 | if (!chan) | ||
4957 | return 0; | ||
4958 | |||
4959 | __clear_chan_timer(chan); | ||
4960 | |||
4961 | if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM_RSP) { | ||
4962 | chan->local_amp_id = chan->move_id; | ||
4963 | |||
4964 | if (!chan->local_amp_id && chan->hs_hchan) | ||
4965 | __release_logical_link(chan); | ||
4966 | |||
4967 | l2cap_move_done(chan); | ||
4968 | } | ||
4969 | |||
4970 | l2cap_chan_unlock(chan); | ||
4971 | |||
4188 | return 0; | 4972 | return 0; |
4189 | } | 4973 | } |
4190 | 4974 | ||
@@ -4269,7 +5053,7 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, | |||
4269 | 5053 | ||
4270 | case L2CAP_CONN_RSP: | 5054 | case L2CAP_CONN_RSP: |
4271 | case L2CAP_CREATE_CHAN_RSP: | 5055 | case L2CAP_CREATE_CHAN_RSP: |
4272 | err = l2cap_connect_rsp(conn, cmd, data); | 5056 | err = l2cap_connect_create_rsp(conn, cmd, data); |
4273 | break; | 5057 | break; |
4274 | 5058 | ||
4275 | case L2CAP_CONF_REQ: | 5059 | case L2CAP_CONF_REQ: |
@@ -4556,6 +5340,12 @@ static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, | |||
4556 | return err; | 5340 | return err; |
4557 | } | 5341 | } |
4558 | 5342 | ||
5343 | static int l2cap_resegment(struct l2cap_chan *chan) | ||
5344 | { | ||
5345 | /* Placeholder */ | ||
5346 | return 0; | ||
5347 | } | ||
5348 | |||
4559 | void l2cap_chan_busy(struct l2cap_chan *chan, int busy) | 5349 | void l2cap_chan_busy(struct l2cap_chan *chan, int busy) |
4560 | { | 5350 | { |
4561 | u8 event; | 5351 | u8 event; |
@@ -4871,8 +5661,8 @@ static int l2cap_rx_state_recv(struct l2cap_chan *chan, | |||
4871 | if (control->final) { | 5661 | if (control->final) { |
4872 | clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); | 5662 | clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); |
4873 | 5663 | ||
4874 | if (!test_and_clear_bit(CONN_REJ_ACT, | 5664 | if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state) && |
4875 | &chan->conn_state)) { | 5665 | !__chan_is_moving(chan)) { |
4876 | control->final = 0; | 5666 | control->final = 0; |
4877 | l2cap_retransmit_all(chan, control); | 5667 | l2cap_retransmit_all(chan, control); |
4878 | } | 5668 | } |
@@ -5061,6 +5851,96 @@ static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan, | |||
5061 | return err; | 5851 | return err; |
5062 | } | 5852 | } |
5063 | 5853 | ||
5854 | static int l2cap_finish_move(struct l2cap_chan *chan) | ||
5855 | { | ||
5856 | BT_DBG("chan %p", chan); | ||
5857 | |||
5858 | chan->rx_state = L2CAP_RX_STATE_RECV; | ||
5859 | |||
5860 | if (chan->hs_hcon) | ||
5861 | chan->conn->mtu = chan->hs_hcon->hdev->block_mtu; | ||
5862 | else | ||
5863 | chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu; | ||
5864 | |||
5865 | return l2cap_resegment(chan); | ||
5866 | } | ||
5867 | |||
5868 | static int l2cap_rx_state_wait_p(struct l2cap_chan *chan, | ||
5869 | struct l2cap_ctrl *control, | ||
5870 | struct sk_buff *skb, u8 event) | ||
5871 | { | ||
5872 | int err; | ||
5873 | |||
5874 | BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, | ||
5875 | event); | ||
5876 | |||
5877 | if (!control->poll) | ||
5878 | return -EPROTO; | ||
5879 | |||
5880 | l2cap_process_reqseq(chan, control->reqseq); | ||
5881 | |||
5882 | if (!skb_queue_empty(&chan->tx_q)) | ||
5883 | chan->tx_send_head = skb_peek(&chan->tx_q); | ||
5884 | else | ||
5885 | chan->tx_send_head = NULL; | ||
5886 | |||
5887 | /* Rewind next_tx_seq to the point expected | ||
5888 | * by the receiver. | ||
5889 | */ | ||
5890 | chan->next_tx_seq = control->reqseq; | ||
5891 | chan->unacked_frames = 0; | ||
5892 | |||
5893 | err = l2cap_finish_move(chan); | ||
5894 | if (err) | ||
5895 | return err; | ||
5896 | |||
5897 | set_bit(CONN_SEND_FBIT, &chan->conn_state); | ||
5898 | l2cap_send_i_or_rr_or_rnr(chan); | ||
5899 | |||
5900 | if (event == L2CAP_EV_RECV_IFRAME) | ||
5901 | return -EPROTO; | ||
5902 | |||
5903 | return l2cap_rx_state_recv(chan, control, NULL, event); | ||
5904 | } | ||
5905 | |||
5906 | static int l2cap_rx_state_wait_f(struct l2cap_chan *chan, | ||
5907 | struct l2cap_ctrl *control, | ||
5908 | struct sk_buff *skb, u8 event) | ||
5909 | { | ||
5910 | int err; | ||
5911 | |||
5912 | if (!control->final) | ||
5913 | return -EPROTO; | ||
5914 | |||
5915 | clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); | ||
5916 | |||
5917 | chan->rx_state = L2CAP_RX_STATE_RECV; | ||
5918 | l2cap_process_reqseq(chan, control->reqseq); | ||
5919 | |||
5920 | if (!skb_queue_empty(&chan->tx_q)) | ||
5921 | chan->tx_send_head = skb_peek(&chan->tx_q); | ||
5922 | else | ||
5923 | chan->tx_send_head = NULL; | ||
5924 | |||
5925 | /* Rewind next_tx_seq to the point expected | ||
5926 | * by the receiver. | ||
5927 | */ | ||
5928 | chan->next_tx_seq = control->reqseq; | ||
5929 | chan->unacked_frames = 0; | ||
5930 | |||
5931 | if (chan->hs_hcon) | ||
5932 | chan->conn->mtu = chan->hs_hcon->hdev->block_mtu; | ||
5933 | else | ||
5934 | chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu; | ||
5935 | |||
5936 | err = l2cap_resegment(chan); | ||
5937 | |||
5938 | if (!err) | ||
5939 | err = l2cap_rx_state_recv(chan, control, skb, event); | ||
5940 | |||
5941 | return err; | ||
5942 | } | ||
5943 | |||
5064 | static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq) | 5944 | static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq) |
5065 | { | 5945 | { |
5066 | /* Make sure reqseq is for a packet that has been sent but not acked */ | 5946 | /* Make sure reqseq is for a packet that has been sent but not acked */ |
@@ -5087,6 +5967,12 @@ static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, | |||
5087 | err = l2cap_rx_state_srej_sent(chan, control, skb, | 5967 | err = l2cap_rx_state_srej_sent(chan, control, skb, |
5088 | event); | 5968 | event); |
5089 | break; | 5969 | break; |
5970 | case L2CAP_RX_STATE_WAIT_P: | ||
5971 | err = l2cap_rx_state_wait_p(chan, control, skb, event); | ||
5972 | break; | ||
5973 | case L2CAP_RX_STATE_WAIT_F: | ||
5974 | err = l2cap_rx_state_wait_f(chan, control, skb, event); | ||
5975 | break; | ||
5090 | default: | 5976 | default: |
5091 | /* shut it down */ | 5977 | /* shut it down */ |
5092 | break; | 5978 | break; |
@@ -5206,7 +6092,7 @@ static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) | |||
5206 | control->super); | 6092 | control->super); |
5207 | 6093 | ||
5208 | if (len != 0) { | 6094 | if (len != 0) { |
5209 | BT_ERR("%d", len); | 6095 | BT_ERR("Trailing bytes: %d in sframe", len); |
5210 | l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); | 6096 | l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); |
5211 | goto drop; | 6097 | goto drop; |
5212 | } | 6098 | } |
@@ -5422,9 +6308,9 @@ void l2cap_connect_cfm(struct hci_conn *hcon, u8 status) | |||
5422 | conn = l2cap_conn_add(hcon, status); | 6308 | conn = l2cap_conn_add(hcon, status); |
5423 | if (conn) | 6309 | if (conn) |
5424 | l2cap_conn_ready(conn); | 6310 | l2cap_conn_ready(conn); |
5425 | } else | 6311 | } else { |
5426 | l2cap_conn_del(hcon, bt_to_errno(status)); | 6312 | l2cap_conn_del(hcon, bt_to_errno(status)); |
5427 | 6313 | } | |
5428 | } | 6314 | } |
5429 | 6315 | ||
5430 | int l2cap_disconn_ind(struct hci_conn *hcon) | 6316 | int l2cap_disconn_ind(struct hci_conn *hcon) |
@@ -5500,7 +6386,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) | |||
5500 | continue; | 6386 | continue; |
5501 | } | 6387 | } |
5502 | 6388 | ||
5503 | if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) { | 6389 | if (!__l2cap_no_conn_pending(chan)) { |
5504 | l2cap_chan_unlock(chan); | 6390 | l2cap_chan_unlock(chan); |
5505 | continue; | 6391 | continue; |
5506 | } | 6392 | } |
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 89f1472939e..1bcfb8422fd 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -736,6 +736,11 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, | |||
736 | } | 736 | } |
737 | 737 | ||
738 | chan->chan_policy = (u8) opt; | 738 | chan->chan_policy = (u8) opt; |
739 | |||
740 | if (sk->sk_state == BT_CONNECTED && | ||
741 | chan->move_role == L2CAP_MOVE_ROLE_NONE) | ||
742 | l2cap_move_start(chan); | ||
743 | |||
739 | break; | 744 | break; |
740 | 745 | ||
741 | default: | 746 | default: |
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 158a87bb0c0..142764aec2a 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -222,7 +222,7 @@ static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status) | |||
222 | 222 | ||
223 | hdr = (void *) skb_put(skb, sizeof(*hdr)); | 223 | hdr = (void *) skb_put(skb, sizeof(*hdr)); |
224 | 224 | ||
225 | hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS); | 225 | hdr->opcode = __constant_cpu_to_le16(MGMT_EV_CMD_STATUS); |
226 | hdr->index = cpu_to_le16(index); | 226 | hdr->index = cpu_to_le16(index); |
227 | hdr->len = cpu_to_le16(sizeof(*ev)); | 227 | hdr->len = cpu_to_le16(sizeof(*ev)); |
228 | 228 | ||
@@ -253,7 +253,7 @@ static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status, | |||
253 | 253 | ||
254 | hdr = (void *) skb_put(skb, sizeof(*hdr)); | 254 | hdr = (void *) skb_put(skb, sizeof(*hdr)); |
255 | 255 | ||
256 | hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE); | 256 | hdr->opcode = __constant_cpu_to_le16(MGMT_EV_CMD_COMPLETE); |
257 | hdr->index = cpu_to_le16(index); | 257 | hdr->index = cpu_to_le16(index); |
258 | hdr->len = cpu_to_le16(sizeof(*ev) + rp_len); | 258 | hdr->len = cpu_to_le16(sizeof(*ev) + rp_len); |
259 | 259 | ||
@@ -377,15 +377,15 @@ static u32 get_supported_settings(struct hci_dev *hdev) | |||
377 | u32 settings = 0; | 377 | u32 settings = 0; |
378 | 378 | ||
379 | settings |= MGMT_SETTING_POWERED; | 379 | settings |= MGMT_SETTING_POWERED; |
380 | settings |= MGMT_SETTING_CONNECTABLE; | ||
381 | settings |= MGMT_SETTING_FAST_CONNECTABLE; | ||
382 | settings |= MGMT_SETTING_DISCOVERABLE; | ||
383 | settings |= MGMT_SETTING_PAIRABLE; | 380 | settings |= MGMT_SETTING_PAIRABLE; |
384 | 381 | ||
385 | if (lmp_ssp_capable(hdev)) | 382 | if (lmp_ssp_capable(hdev)) |
386 | settings |= MGMT_SETTING_SSP; | 383 | settings |= MGMT_SETTING_SSP; |
387 | 384 | ||
388 | if (lmp_bredr_capable(hdev)) { | 385 | if (lmp_bredr_capable(hdev)) { |
386 | settings |= MGMT_SETTING_CONNECTABLE; | ||
387 | settings |= MGMT_SETTING_FAST_CONNECTABLE; | ||
388 | settings |= MGMT_SETTING_DISCOVERABLE; | ||
389 | settings |= MGMT_SETTING_BREDR; | 389 | settings |= MGMT_SETTING_BREDR; |
390 | settings |= MGMT_SETTING_LINK_SECURITY; | 390 | settings |= MGMT_SETTING_LINK_SECURITY; |
391 | } | 391 | } |
@@ -485,7 +485,7 @@ static void create_eir(struct hci_dev *hdev, u8 *data) | |||
485 | ptr += (name_len + 2); | 485 | ptr += (name_len + 2); |
486 | } | 486 | } |
487 | 487 | ||
488 | if (hdev->inq_tx_power) { | 488 | if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) { |
489 | ptr[0] = 2; | 489 | ptr[0] = 2; |
490 | ptr[1] = EIR_TX_POWER; | 490 | ptr[1] = EIR_TX_POWER; |
491 | ptr[2] = (u8) hdev->inq_tx_power; | 491 | ptr[2] = (u8) hdev->inq_tx_power; |
@@ -566,7 +566,7 @@ static int update_eir(struct hci_dev *hdev) | |||
566 | if (!hdev_is_powered(hdev)) | 566 | if (!hdev_is_powered(hdev)) |
567 | return 0; | 567 | return 0; |
568 | 568 | ||
569 | if (!(hdev->features[6] & LMP_EXT_INQ)) | 569 | if (!lmp_ext_inq_capable(hdev)) |
570 | return 0; | 570 | return 0; |
571 | 571 | ||
572 | if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) | 572 | if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) |
@@ -833,7 +833,7 @@ static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len, | |||
833 | if (hdev) | 833 | if (hdev) |
834 | hdr->index = cpu_to_le16(hdev->id); | 834 | hdr->index = cpu_to_le16(hdev->id); |
835 | else | 835 | else |
836 | hdr->index = cpu_to_le16(MGMT_INDEX_NONE); | 836 | hdr->index = __constant_cpu_to_le16(MGMT_INDEX_NONE); |
837 | hdr->len = cpu_to_le16(data_len); | 837 | hdr->len = cpu_to_le16(data_len); |
838 | 838 | ||
839 | if (data) | 839 | if (data) |
@@ -868,6 +868,10 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
868 | 868 | ||
869 | BT_DBG("request for %s", hdev->name); | 869 | BT_DBG("request for %s", hdev->name); |
870 | 870 | ||
871 | if (!lmp_bredr_capable(hdev)) | ||
872 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE, | ||
873 | MGMT_STATUS_NOT_SUPPORTED); | ||
874 | |||
871 | timeout = __le16_to_cpu(cp->timeout); | 875 | timeout = __le16_to_cpu(cp->timeout); |
872 | if (!cp->val && timeout > 0) | 876 | if (!cp->val && timeout > 0) |
873 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE, | 877 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE, |
@@ -963,6 +967,10 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
963 | 967 | ||
964 | BT_DBG("request for %s", hdev->name); | 968 | BT_DBG("request for %s", hdev->name); |
965 | 969 | ||
970 | if (!lmp_bredr_capable(hdev)) | ||
971 | return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE, | ||
972 | MGMT_STATUS_NOT_SUPPORTED); | ||
973 | |||
966 | hci_dev_lock(hdev); | 974 | hci_dev_lock(hdev); |
967 | 975 | ||
968 | if (!hdev_is_powered(hdev)) { | 976 | if (!hdev_is_powered(hdev)) { |
@@ -1061,6 +1069,10 @@ static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1061 | 1069 | ||
1062 | BT_DBG("request for %s", hdev->name); | 1070 | BT_DBG("request for %s", hdev->name); |
1063 | 1071 | ||
1072 | if (!lmp_bredr_capable(hdev)) | ||
1073 | return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY, | ||
1074 | MGMT_STATUS_NOT_SUPPORTED); | ||
1075 | |||
1064 | hci_dev_lock(hdev); | 1076 | hci_dev_lock(hdev); |
1065 | 1077 | ||
1066 | if (!hdev_is_powered(hdev)) { | 1078 | if (!hdev_is_powered(hdev)) { |
@@ -1214,7 +1226,7 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
1214 | } | 1226 | } |
1215 | 1227 | ||
1216 | val = !!cp->val; | 1228 | val = !!cp->val; |
1217 | enabled = !!(hdev->host_features[0] & LMP_HOST_LE); | 1229 | enabled = !!lmp_host_le_capable(hdev); |
1218 | 1230 | ||
1219 | if (!hdev_is_powered(hdev) || val == enabled) { | 1231 | if (!hdev_is_powered(hdev) || val == enabled) { |
1220 | bool changed = false; | 1232 | bool changed = false; |
@@ -1250,7 +1262,7 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
1250 | 1262 | ||
1251 | if (val) { | 1263 | if (val) { |
1252 | hci_cp.le = val; | 1264 | hci_cp.le = val; |
1253 | hci_cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR); | 1265 | hci_cp.simul = !!lmp_le_br_capable(hdev); |
1254 | } | 1266 | } |
1255 | 1267 | ||
1256 | err = hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp), | 1268 | err = hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp), |
@@ -2596,6 +2608,10 @@ static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev, | |||
2596 | 2608 | ||
2597 | BT_DBG("%s", hdev->name); | 2609 | BT_DBG("%s", hdev->name); |
2598 | 2610 | ||
2611 | if (!lmp_bredr_capable(hdev)) | ||
2612 | return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, | ||
2613 | MGMT_STATUS_NOT_SUPPORTED); | ||
2614 | |||
2599 | if (!hdev_is_powered(hdev)) | 2615 | if (!hdev_is_powered(hdev)) |
2600 | return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, | 2616 | return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, |
2601 | MGMT_STATUS_NOT_POWERED); | 2617 | MGMT_STATUS_NOT_POWERED); |
@@ -2873,6 +2889,21 @@ static void settings_rsp(struct pending_cmd *cmd, void *data) | |||
2873 | mgmt_pending_free(cmd); | 2889 | mgmt_pending_free(cmd); |
2874 | } | 2890 | } |
2875 | 2891 | ||
2892 | static int set_bredr_scan(struct hci_dev *hdev) | ||
2893 | { | ||
2894 | u8 scan = 0; | ||
2895 | |||
2896 | if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) | ||
2897 | scan |= SCAN_PAGE; | ||
2898 | if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) | ||
2899 | scan |= SCAN_INQUIRY; | ||
2900 | |||
2901 | if (!scan) | ||
2902 | return 0; | ||
2903 | |||
2904 | return hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); | ||
2905 | } | ||
2906 | |||
2876 | int mgmt_powered(struct hci_dev *hdev, u8 powered) | 2907 | int mgmt_powered(struct hci_dev *hdev, u8 powered) |
2877 | { | 2908 | { |
2878 | struct cmd_lookup match = { NULL, hdev }; | 2909 | struct cmd_lookup match = { NULL, hdev }; |
@@ -2884,17 +2915,8 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered) | |||
2884 | mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); | 2915 | mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); |
2885 | 2916 | ||
2886 | if (powered) { | 2917 | if (powered) { |
2887 | u8 scan = 0; | 2918 | if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) && |
2888 | 2919 | !lmp_host_ssp_capable(hdev)) { | |
2889 | if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) | ||
2890 | scan |= SCAN_PAGE; | ||
2891 | if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) | ||
2892 | scan |= SCAN_INQUIRY; | ||
2893 | |||
2894 | if (scan) | ||
2895 | hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); | ||
2896 | |||
2897 | if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) { | ||
2898 | u8 ssp = 1; | 2920 | u8 ssp = 1; |
2899 | 2921 | ||
2900 | hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &ssp); | 2922 | hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &ssp); |
@@ -2904,15 +2926,24 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered) | |||
2904 | struct hci_cp_write_le_host_supported cp; | 2926 | struct hci_cp_write_le_host_supported cp; |
2905 | 2927 | ||
2906 | cp.le = 1; | 2928 | cp.le = 1; |
2907 | cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR); | 2929 | cp.simul = !!lmp_le_br_capable(hdev); |
2908 | 2930 | ||
2909 | hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, | 2931 | /* Check first if we already have the right |
2910 | sizeof(cp), &cp); | 2932 | * host state (host features set) |
2933 | */ | ||
2934 | if (cp.le != !!lmp_host_le_capable(hdev) || | ||
2935 | cp.simul != !!lmp_host_le_br_capable(hdev)) | ||
2936 | hci_send_cmd(hdev, | ||
2937 | HCI_OP_WRITE_LE_HOST_SUPPORTED, | ||
2938 | sizeof(cp), &cp); | ||
2911 | } | 2939 | } |
2912 | 2940 | ||
2913 | update_class(hdev); | 2941 | if (lmp_bredr_capable(hdev)) { |
2914 | update_name(hdev, hdev->dev_name); | 2942 | set_bredr_scan(hdev); |
2915 | update_eir(hdev); | 2943 | update_class(hdev); |
2944 | update_name(hdev, hdev->dev_name); | ||
2945 | update_eir(hdev); | ||
2946 | } | ||
2916 | } else { | 2947 | } else { |
2917 | u8 status = MGMT_STATUS_NOT_POWERED; | 2948 | u8 status = MGMT_STATUS_NOT_POWERED; |
2918 | mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status); | 2949 | mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status); |
@@ -3361,7 +3392,7 @@ static int clear_eir(struct hci_dev *hdev) | |||
3361 | { | 3392 | { |
3362 | struct hci_cp_write_eir cp; | 3393 | struct hci_cp_write_eir cp; |
3363 | 3394 | ||
3364 | if (!(hdev->features[6] & LMP_EXT_INQ)) | 3395 | if (!lmp_ext_inq_capable(hdev)) |
3365 | return 0; | 3396 | return 0; |
3366 | 3397 | ||
3367 | memset(hdev->eir, 0, sizeof(hdev->eir)); | 3398 | memset(hdev->eir, 0, sizeof(hdev->eir)); |
@@ -3493,7 +3524,12 @@ send_event: | |||
3493 | err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, | 3524 | err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, |
3494 | sizeof(ev), cmd ? cmd->sk : NULL); | 3525 | sizeof(ev), cmd ? cmd->sk : NULL); |
3495 | 3526 | ||
3496 | update_eir(hdev); | 3527 | /* EIR is taken care of separately when powering on the |
3528 | * adapter so only update them here if this is a name change | ||
3529 | * unrelated to power on. | ||
3530 | */ | ||
3531 | if (!test_bit(HCI_INIT, &hdev->flags)) | ||
3532 | update_eir(hdev); | ||
3497 | 3533 | ||
3498 | failed: | 3534 | failed: |
3499 | if (cmd) | 3535 | if (cmd) |
@@ -3588,9 +3624,9 @@ int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | |||
3588 | ev->addr.type = link_to_bdaddr(link_type, addr_type); | 3624 | ev->addr.type = link_to_bdaddr(link_type, addr_type); |
3589 | ev->rssi = rssi; | 3625 | ev->rssi = rssi; |
3590 | if (cfm_name) | 3626 | if (cfm_name) |
3591 | ev->flags |= cpu_to_le32(MGMT_DEV_FOUND_CONFIRM_NAME); | 3627 | ev->flags |= __constant_cpu_to_le32(MGMT_DEV_FOUND_CONFIRM_NAME); |
3592 | if (!ssp) | 3628 | if (!ssp) |
3593 | ev->flags |= cpu_to_le32(MGMT_DEV_FOUND_LEGACY_PAIRING); | 3629 | ev->flags |= __constant_cpu_to_le32(MGMT_DEV_FOUND_LEGACY_PAIRING); |
3594 | 3630 | ||
3595 | if (eir_len > 0) | 3631 | if (eir_len > 0) |
3596 | memcpy(ev->eir, eir, eir_len); | 3632 | memcpy(ev->eir, eir, eir_len); |
diff --git a/net/mac80211/aes_cmac.c b/net/mac80211/aes_cmac.c index 493353534a0..537488cbf94 100644 --- a/net/mac80211/aes_cmac.c +++ b/net/mac80211/aes_cmac.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
11 | #include <linux/types.h> | 11 | #include <linux/types.h> |
12 | #include <linux/crypto.h> | 12 | #include <linux/crypto.h> |
13 | #include <linux/export.h> | ||
13 | #include <linux/err.h> | 14 | #include <linux/err.h> |
14 | #include <crypto/aes.h> | 15 | #include <crypto/aes.h> |
15 | 16 | ||
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 186d9919b04..808338a1bce 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c | |||
@@ -118,7 +118,7 @@ void ieee80211_stop_rx_ba_session(struct ieee80211_vif *vif, u16 ba_rx_bitmap, | |||
118 | return; | 118 | return; |
119 | } | 119 | } |
120 | 120 | ||
121 | for (i = 0; i < STA_TID_NUM; i++) | 121 | for (i = 0; i < IEEE80211_NUM_TIDS; i++) |
122 | if (ba_rx_bitmap & BIT(i)) | 122 | if (ba_rx_bitmap & BIT(i)) |
123 | set_bit(i, sta->ampdu_mlme.tid_rx_stop_requested); | 123 | set_bit(i, sta->ampdu_mlme.tid_rx_stop_requested); |
124 | 124 | ||
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 3195a6307f5..4152ed1034b 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -448,7 +448,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, | |||
448 | if (WARN_ON(!local->ops->ampdu_action)) | 448 | if (WARN_ON(!local->ops->ampdu_action)) |
449 | return -EINVAL; | 449 | return -EINVAL; |
450 | 450 | ||
451 | if ((tid >= STA_TID_NUM) || | 451 | if ((tid >= IEEE80211_NUM_TIDS) || |
452 | !(local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION) || | 452 | !(local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION) || |
453 | (local->hw.flags & IEEE80211_HW_TX_AMPDU_SETUP_IN_HW)) | 453 | (local->hw.flags & IEEE80211_HW_TX_AMPDU_SETUP_IN_HW)) |
454 | return -EINVAL; | 454 | return -EINVAL; |
@@ -605,9 +605,9 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid) | |||
605 | 605 | ||
606 | trace_api_start_tx_ba_cb(sdata, ra, tid); | 606 | trace_api_start_tx_ba_cb(sdata, ra, tid); |
607 | 607 | ||
608 | if (tid >= STA_TID_NUM) { | 608 | if (tid >= IEEE80211_NUM_TIDS) { |
609 | ht_dbg(sdata, "Bad TID value: tid = %d (>= %d)\n", | 609 | ht_dbg(sdata, "Bad TID value: tid = %d (>= %d)\n", |
610 | tid, STA_TID_NUM); | 610 | tid, IEEE80211_NUM_TIDS); |
611 | return; | 611 | return; |
612 | } | 612 | } |
613 | 613 | ||
@@ -687,7 +687,7 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid) | |||
687 | if (!local->ops->ampdu_action) | 687 | if (!local->ops->ampdu_action) |
688 | return -EINVAL; | 688 | return -EINVAL; |
689 | 689 | ||
690 | if (tid >= STA_TID_NUM) | 690 | if (tid >= IEEE80211_NUM_TIDS) |
691 | return -EINVAL; | 691 | return -EINVAL; |
692 | 692 | ||
693 | spin_lock_bh(&sta->lock); | 693 | spin_lock_bh(&sta->lock); |
@@ -722,9 +722,9 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid) | |||
722 | 722 | ||
723 | trace_api_stop_tx_ba_cb(sdata, ra, tid); | 723 | trace_api_stop_tx_ba_cb(sdata, ra, tid); |
724 | 724 | ||
725 | if (tid >= STA_TID_NUM) { | 725 | if (tid >= IEEE80211_NUM_TIDS) { |
726 | ht_dbg(sdata, "Bad TID value: tid = %d (>= %d)\n", | 726 | ht_dbg(sdata, "Bad TID value: tid = %d (>= %d)\n", |
727 | tid, STA_TID_NUM); | 727 | tid, IEEE80211_NUM_TIDS); |
728 | return; | 728 | return; |
729 | } | 729 | } |
730 | 730 | ||
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 76690020d60..4965aa6424e 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -370,30 +370,32 @@ static int ieee80211_config_default_mgmt_key(struct wiphy *wiphy, | |||
370 | return 0; | 370 | return 0; |
371 | } | 371 | } |
372 | 372 | ||
373 | static void rate_idx_to_bitrate(struct rate_info *rate, struct sta_info *sta, int idx) | ||
374 | { | ||
375 | enum ieee80211_band band = ieee80211_get_sdata_band(sta->sdata); | ||
376 | |||
377 | if (!(rate->flags & RATE_INFO_FLAGS_MCS)) { | ||
378 | struct ieee80211_supported_band *sband; | ||
379 | sband = sta->local->hw.wiphy->bands[band]; | ||
380 | rate->legacy = sband->bitrates[idx].bitrate; | ||
381 | } else | ||
382 | rate->mcs = idx; | ||
383 | } | ||
384 | |||
385 | void sta_set_rate_info_tx(struct sta_info *sta, | 373 | void sta_set_rate_info_tx(struct sta_info *sta, |
386 | const struct ieee80211_tx_rate *rate, | 374 | const struct ieee80211_tx_rate *rate, |
387 | struct rate_info *rinfo) | 375 | struct rate_info *rinfo) |
388 | { | 376 | { |
389 | rinfo->flags = 0; | 377 | rinfo->flags = 0; |
390 | if (rate->flags & IEEE80211_TX_RC_MCS) | 378 | if (rate->flags & IEEE80211_TX_RC_MCS) { |
391 | rinfo->flags |= RATE_INFO_FLAGS_MCS; | 379 | rinfo->flags |= RATE_INFO_FLAGS_MCS; |
380 | rinfo->mcs = rate->idx; | ||
381 | } else if (rate->flags & IEEE80211_TX_RC_VHT_MCS) { | ||
382 | rinfo->flags |= RATE_INFO_FLAGS_VHT_MCS; | ||
383 | rinfo->mcs = ieee80211_rate_get_vht_mcs(rate); | ||
384 | rinfo->nss = ieee80211_rate_get_vht_nss(rate); | ||
385 | } else { | ||
386 | struct ieee80211_supported_band *sband; | ||
387 | sband = sta->local->hw.wiphy->bands[ | ||
388 | ieee80211_get_sdata_band(sta->sdata)]; | ||
389 | rinfo->legacy = sband->bitrates[rate->idx].bitrate; | ||
390 | } | ||
392 | if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) | 391 | if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) |
393 | rinfo->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | 392 | rinfo->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; |
393 | if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH) | ||
394 | rinfo->flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; | ||
395 | if (rate->flags & IEEE80211_TX_RC_160_MHZ_WIDTH) | ||
396 | rinfo->flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH; | ||
394 | if (rate->flags & IEEE80211_TX_RC_SHORT_GI) | 397 | if (rate->flags & IEEE80211_TX_RC_SHORT_GI) |
395 | rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI; | 398 | rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI; |
396 | rate_idx_to_bitrate(rinfo, sta, rate->idx); | ||
397 | } | 399 | } |
398 | 400 | ||
399 | static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | 401 | static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) |
@@ -444,13 +446,32 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
444 | sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate); | 446 | sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate); |
445 | 447 | ||
446 | sinfo->rxrate.flags = 0; | 448 | sinfo->rxrate.flags = 0; |
447 | if (sta->last_rx_rate_flag & RX_FLAG_HT) | 449 | if (sta->last_rx_rate_flag & RX_FLAG_HT) { |
448 | sinfo->rxrate.flags |= RATE_INFO_FLAGS_MCS; | 450 | sinfo->rxrate.flags |= RATE_INFO_FLAGS_MCS; |
451 | sinfo->rxrate.mcs = sta->last_rx_rate_idx; | ||
452 | } else if (sta->last_rx_rate_flag & RX_FLAG_VHT) { | ||
453 | sinfo->rxrate.flags |= RATE_INFO_FLAGS_VHT_MCS; | ||
454 | sinfo->rxrate.nss = sta->last_rx_rate_vht_nss; | ||
455 | sinfo->rxrate.mcs = sta->last_rx_rate_idx; | ||
456 | } else { | ||
457 | struct ieee80211_supported_band *sband; | ||
458 | |||
459 | sband = sta->local->hw.wiphy->bands[ | ||
460 | ieee80211_get_sdata_band(sta->sdata)]; | ||
461 | sinfo->rxrate.legacy = | ||
462 | sband->bitrates[sta->last_rx_rate_idx].bitrate; | ||
463 | } | ||
464 | |||
449 | if (sta->last_rx_rate_flag & RX_FLAG_40MHZ) | 465 | if (sta->last_rx_rate_flag & RX_FLAG_40MHZ) |
450 | sinfo->rxrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | 466 | sinfo->rxrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; |
451 | if (sta->last_rx_rate_flag & RX_FLAG_SHORT_GI) | 467 | if (sta->last_rx_rate_flag & RX_FLAG_SHORT_GI) |
452 | sinfo->rxrate.flags |= RATE_INFO_FLAGS_SHORT_GI; | 468 | sinfo->rxrate.flags |= RATE_INFO_FLAGS_SHORT_GI; |
453 | rate_idx_to_bitrate(&sinfo->rxrate, sta, sta->last_rx_rate_idx); | 469 | if (sta->last_rx_rate_flag & RX_FLAG_80MHZ) |
470 | sinfo->rxrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; | ||
471 | if (sta->last_rx_rate_flag & RX_FLAG_80P80MHZ) | ||
472 | sinfo->rxrate.flags |= RATE_INFO_FLAGS_80P80_MHZ_WIDTH; | ||
473 | if (sta->last_rx_rate_flag & RX_FLAG_160MHZ) | ||
474 | sinfo->rxrate.flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH; | ||
454 | 475 | ||
455 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 476 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
456 | #ifdef CONFIG_MAC80211_MESH | 477 | #ifdef CONFIG_MAC80211_MESH |
@@ -615,7 +636,7 @@ do_survey: | |||
615 | rcu_read_lock(); | 636 | rcu_read_lock(); |
616 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 637 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
617 | if (chanctx_conf) | 638 | if (chanctx_conf) |
618 | channel = chanctx_conf->channel; | 639 | channel = chanctx_conf->def.chan; |
619 | else | 640 | else |
620 | channel = NULL; | 641 | channel = NULL; |
621 | rcu_read_unlock(); | 642 | rcu_read_unlock(); |
@@ -735,15 +756,13 @@ static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, | |||
735 | } | 756 | } |
736 | 757 | ||
737 | static int ieee80211_set_monitor_channel(struct wiphy *wiphy, | 758 | static int ieee80211_set_monitor_channel(struct wiphy *wiphy, |
738 | struct ieee80211_channel *chan, | 759 | struct cfg80211_chan_def *chandef) |
739 | enum nl80211_channel_type channel_type) | ||
740 | { | 760 | { |
741 | struct ieee80211_local *local = wiphy_priv(wiphy); | 761 | struct ieee80211_local *local = wiphy_priv(wiphy); |
742 | struct ieee80211_sub_if_data *sdata; | 762 | struct ieee80211_sub_if_data *sdata; |
743 | int ret = 0; | 763 | int ret = 0; |
744 | 764 | ||
745 | if (local->monitor_channel == chan && | 765 | if (cfg80211_chandef_identical(&local->monitor_chandef, chandef)) |
746 | local->monitor_channel_type == channel_type) | ||
747 | return 0; | 766 | return 0; |
748 | 767 | ||
749 | mutex_lock(&local->iflist_mtx); | 768 | mutex_lock(&local->iflist_mtx); |
@@ -753,20 +772,17 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy, | |||
753 | lockdep_is_held(&local->iflist_mtx)); | 772 | lockdep_is_held(&local->iflist_mtx)); |
754 | if (sdata) { | 773 | if (sdata) { |
755 | ieee80211_vif_release_channel(sdata); | 774 | ieee80211_vif_release_channel(sdata); |
756 | ret = ieee80211_vif_use_channel( | 775 | ret = ieee80211_vif_use_channel(sdata, chandef, |
757 | sdata, chan, channel_type, | ||
758 | IEEE80211_CHANCTX_EXCLUSIVE); | 776 | IEEE80211_CHANCTX_EXCLUSIVE); |
759 | } | 777 | } |
760 | } else if (local->open_count == local->monitors) { | 778 | } else if (local->open_count == local->monitors) { |
761 | local->_oper_channel = chan; | 779 | local->_oper_channel = chandef->chan; |
762 | local->_oper_channel_type = channel_type; | 780 | local->_oper_channel_type = cfg80211_get_chandef_type(chandef); |
763 | ieee80211_hw_config(local, 0); | 781 | ieee80211_hw_config(local, 0); |
764 | } | 782 | } |
765 | 783 | ||
766 | if (ret == 0) { | 784 | if (ret == 0) |
767 | local->monitor_channel = chan; | 785 | local->monitor_chandef = *chandef; |
768 | local->monitor_channel_type = channel_type; | ||
769 | } | ||
770 | mutex_unlock(&local->iflist_mtx); | 786 | mutex_unlock(&local->iflist_mtx); |
771 | 787 | ||
772 | return ret; | 788 | return ret; |
@@ -888,8 +904,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
888 | sdata->smps_mode = IEEE80211_SMPS_OFF; | 904 | sdata->smps_mode = IEEE80211_SMPS_OFF; |
889 | sdata->needed_rx_chains = sdata->local->rx_chains; | 905 | sdata->needed_rx_chains = sdata->local->rx_chains; |
890 | 906 | ||
891 | err = ieee80211_vif_use_channel(sdata, params->channel, | 907 | err = ieee80211_vif_use_channel(sdata, ¶ms->chandef, |
892 | params->channel_type, | ||
893 | IEEE80211_CHANCTX_SHARED); | 908 | IEEE80211_CHANCTX_SHARED); |
894 | if (err) | 909 | if (err) |
895 | return err; | 910 | return err; |
@@ -922,6 +937,15 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
922 | return err; | 937 | return err; |
923 | changed |= err; | 938 | changed |= err; |
924 | 939 | ||
940 | err = drv_start_ap(sdata->local, sdata); | ||
941 | if (err) { | ||
942 | old = rtnl_dereference(sdata->u.ap.beacon); | ||
943 | if (old) | ||
944 | kfree_rcu(old, rcu_head); | ||
945 | RCU_INIT_POINTER(sdata->u.ap.beacon, NULL); | ||
946 | return err; | ||
947 | } | ||
948 | |||
925 | ieee80211_bss_info_change_notify(sdata, changed); | 949 | ieee80211_bss_info_change_notify(sdata, changed); |
926 | 950 | ||
927 | netif_carrier_on(dev); | 951 | netif_carrier_on(dev); |
@@ -953,26 +977,38 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, | |||
953 | 977 | ||
954 | static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | 978 | static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) |
955 | { | 979 | { |
956 | struct ieee80211_sub_if_data *sdata, *vlan; | 980 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
957 | struct beacon_data *old; | 981 | struct ieee80211_sub_if_data *vlan; |
958 | 982 | struct ieee80211_local *local = sdata->local; | |
959 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 983 | struct beacon_data *old_beacon; |
984 | struct probe_resp *old_probe_resp; | ||
960 | 985 | ||
961 | old = rtnl_dereference(sdata->u.ap.beacon); | 986 | old_beacon = rtnl_dereference(sdata->u.ap.beacon); |
962 | if (!old) | 987 | if (!old_beacon) |
963 | return -ENOENT; | 988 | return -ENOENT; |
989 | old_probe_resp = rtnl_dereference(sdata->u.ap.probe_resp); | ||
964 | 990 | ||
991 | /* turn off carrier for this interface and dependent VLANs */ | ||
965 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) | 992 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) |
966 | netif_carrier_off(vlan->dev); | 993 | netif_carrier_off(vlan->dev); |
967 | netif_carrier_off(dev); | 994 | netif_carrier_off(dev); |
968 | 995 | ||
996 | /* remove beacon and probe response */ | ||
969 | RCU_INIT_POINTER(sdata->u.ap.beacon, NULL); | 997 | RCU_INIT_POINTER(sdata->u.ap.beacon, NULL); |
998 | RCU_INIT_POINTER(sdata->u.ap.probe_resp, NULL); | ||
999 | kfree_rcu(old_beacon, rcu_head); | ||
1000 | if (old_probe_resp) | ||
1001 | kfree_rcu(old_probe_resp, rcu_head); | ||
970 | 1002 | ||
971 | kfree_rcu(old, rcu_head); | 1003 | sta_info_flush(local, sdata); |
972 | |||
973 | sta_info_flush(sdata->local, sdata); | ||
974 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); | 1004 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); |
975 | 1005 | ||
1006 | drv_stop_ap(sdata->local, sdata); | ||
1007 | |||
1008 | /* free all potentially still buffered bcast frames */ | ||
1009 | local->total_ps_buffered -= skb_queue_len(&sdata->u.ap.ps.bc_buf); | ||
1010 | skb_queue_purge(&sdata->u.ap.ps.bc_buf); | ||
1011 | |||
976 | ieee80211_vif_release_channel(sdata); | 1012 | ieee80211_vif_release_channel(sdata); |
977 | 1013 | ||
978 | return 0; | 1014 | return 0; |
@@ -1686,8 +1722,7 @@ static int ieee80211_join_mesh(struct wiphy *wiphy, struct net_device *dev, | |||
1686 | sdata->smps_mode = IEEE80211_SMPS_OFF; | 1722 | sdata->smps_mode = IEEE80211_SMPS_OFF; |
1687 | sdata->needed_rx_chains = sdata->local->rx_chains; | 1723 | sdata->needed_rx_chains = sdata->local->rx_chains; |
1688 | 1724 | ||
1689 | err = ieee80211_vif_use_channel(sdata, setup->channel, | 1725 | err = ieee80211_vif_use_channel(sdata, &setup->chandef, |
1690 | setup->channel_type, | ||
1691 | IEEE80211_CHANCTX_SHARED); | 1726 | IEEE80211_CHANCTX_SHARED); |
1692 | if (err) | 1727 | if (err) |
1693 | return err; | 1728 | return err; |
@@ -1933,6 +1968,16 @@ static int ieee80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) | |||
1933 | return ieee80211_ibss_leave(IEEE80211_DEV_TO_SUB_IF(dev)); | 1968 | return ieee80211_ibss_leave(IEEE80211_DEV_TO_SUB_IF(dev)); |
1934 | } | 1969 | } |
1935 | 1970 | ||
1971 | static int ieee80211_set_mcast_rate(struct wiphy *wiphy, struct net_device *dev, | ||
1972 | int rate[IEEE80211_NUM_BANDS]) | ||
1973 | { | ||
1974 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1975 | |||
1976 | memcpy(sdata->vif.bss_conf.mcast_rate, rate, sizeof(rate)); | ||
1977 | |||
1978 | return 0; | ||
1979 | } | ||
1980 | |||
1936 | static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) | 1981 | static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) |
1937 | { | 1982 | { |
1938 | struct ieee80211_local *local = wiphy_priv(wiphy); | 1983 | struct ieee80211_local *local = wiphy_priv(wiphy); |
@@ -1959,10 +2004,16 @@ static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) | |||
1959 | return err; | 2004 | return err; |
1960 | } | 2005 | } |
1961 | 2006 | ||
1962 | if (changed & WIPHY_PARAM_RETRY_SHORT) | 2007 | if (changed & WIPHY_PARAM_RETRY_SHORT) { |
2008 | if (wiphy->retry_short > IEEE80211_MAX_TX_RETRY) | ||
2009 | return -EINVAL; | ||
1963 | local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; | 2010 | local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; |
1964 | if (changed & WIPHY_PARAM_RETRY_LONG) | 2011 | } |
2012 | if (changed & WIPHY_PARAM_RETRY_LONG) { | ||
2013 | if (wiphy->retry_long > IEEE80211_MAX_TX_RETRY) | ||
2014 | return -EINVAL; | ||
1965 | local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; | 2015 | local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; |
2016 | } | ||
1966 | if (changed & | 2017 | if (changed & |
1967 | (WIPHY_PARAM_RETRY_SHORT | WIPHY_PARAM_RETRY_LONG)) | 2018 | (WIPHY_PARAM_RETRY_SHORT | WIPHY_PARAM_RETRY_LONG)) |
1968 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_RETRY_LIMITS); | 2019 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_RETRY_LIMITS); |
@@ -1971,45 +2022,65 @@ static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) | |||
1971 | } | 2022 | } |
1972 | 2023 | ||
1973 | static int ieee80211_set_tx_power(struct wiphy *wiphy, | 2024 | static int ieee80211_set_tx_power(struct wiphy *wiphy, |
2025 | struct wireless_dev *wdev, | ||
1974 | enum nl80211_tx_power_setting type, int mbm) | 2026 | enum nl80211_tx_power_setting type, int mbm) |
1975 | { | 2027 | { |
1976 | struct ieee80211_local *local = wiphy_priv(wiphy); | 2028 | struct ieee80211_local *local = wiphy_priv(wiphy); |
1977 | struct ieee80211_channel *chan = local->_oper_channel; | 2029 | struct ieee80211_sub_if_data *sdata; |
1978 | u32 changes = 0; | ||
1979 | 2030 | ||
1980 | /* FIXME */ | 2031 | if (wdev) { |
1981 | if (local->use_chanctx) | 2032 | sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); |
1982 | return -EOPNOTSUPP; | 2033 | |
2034 | switch (type) { | ||
2035 | case NL80211_TX_POWER_AUTOMATIC: | ||
2036 | sdata->user_power_level = IEEE80211_UNSET_POWER_LEVEL; | ||
2037 | break; | ||
2038 | case NL80211_TX_POWER_LIMITED: | ||
2039 | case NL80211_TX_POWER_FIXED: | ||
2040 | if (mbm < 0 || (mbm % 100)) | ||
2041 | return -EOPNOTSUPP; | ||
2042 | sdata->user_power_level = MBM_TO_DBM(mbm); | ||
2043 | break; | ||
2044 | } | ||
2045 | |||
2046 | ieee80211_recalc_txpower(sdata); | ||
2047 | |||
2048 | return 0; | ||
2049 | } | ||
1983 | 2050 | ||
1984 | switch (type) { | 2051 | switch (type) { |
1985 | case NL80211_TX_POWER_AUTOMATIC: | 2052 | case NL80211_TX_POWER_AUTOMATIC: |
1986 | local->user_power_level = -1; | 2053 | local->user_power_level = IEEE80211_UNSET_POWER_LEVEL; |
1987 | break; | 2054 | break; |
1988 | case NL80211_TX_POWER_LIMITED: | 2055 | case NL80211_TX_POWER_LIMITED: |
1989 | if (mbm < 0 || (mbm % 100)) | ||
1990 | return -EOPNOTSUPP; | ||
1991 | local->user_power_level = MBM_TO_DBM(mbm); | ||
1992 | break; | ||
1993 | case NL80211_TX_POWER_FIXED: | 2056 | case NL80211_TX_POWER_FIXED: |
1994 | if (mbm < 0 || (mbm % 100)) | 2057 | if (mbm < 0 || (mbm % 100)) |
1995 | return -EOPNOTSUPP; | 2058 | return -EOPNOTSUPP; |
1996 | /* TODO: move to cfg80211 when it knows the channel */ | ||
1997 | if (MBM_TO_DBM(mbm) > chan->max_power) | ||
1998 | return -EINVAL; | ||
1999 | local->user_power_level = MBM_TO_DBM(mbm); | 2059 | local->user_power_level = MBM_TO_DBM(mbm); |
2000 | break; | 2060 | break; |
2001 | } | 2061 | } |
2002 | 2062 | ||
2003 | ieee80211_hw_config(local, changes); | 2063 | mutex_lock(&local->iflist_mtx); |
2064 | list_for_each_entry(sdata, &local->interfaces, list) | ||
2065 | sdata->user_power_level = local->user_power_level; | ||
2066 | list_for_each_entry(sdata, &local->interfaces, list) | ||
2067 | ieee80211_recalc_txpower(sdata); | ||
2068 | mutex_unlock(&local->iflist_mtx); | ||
2004 | 2069 | ||
2005 | return 0; | 2070 | return 0; |
2006 | } | 2071 | } |
2007 | 2072 | ||
2008 | static int ieee80211_get_tx_power(struct wiphy *wiphy, int *dbm) | 2073 | static int ieee80211_get_tx_power(struct wiphy *wiphy, |
2074 | struct wireless_dev *wdev, | ||
2075 | int *dbm) | ||
2009 | { | 2076 | { |
2010 | struct ieee80211_local *local = wiphy_priv(wiphy); | 2077 | struct ieee80211_local *local = wiphy_priv(wiphy); |
2078 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); | ||
2011 | 2079 | ||
2012 | *dbm = local->hw.conf.power_level; | 2080 | if (!local->use_chanctx) |
2081 | *dbm = local->hw.conf.power_level; | ||
2082 | else | ||
2083 | *dbm = sdata->vif.bss_conf.txpower; | ||
2013 | 2084 | ||
2014 | return 0; | 2085 | return 0; |
2015 | } | 2086 | } |
@@ -2078,7 +2149,7 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, | |||
2078 | * the new value until we associate. | 2149 | * the new value until we associate. |
2079 | */ | 2150 | */ |
2080 | if (!sdata->u.mgd.associated || | 2151 | if (!sdata->u.mgd.associated || |
2081 | sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) | 2152 | sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT) |
2082 | return 0; | 2153 | return 0; |
2083 | 2154 | ||
2084 | ap = sdata->u.mgd.associated->bssid; | 2155 | ap = sdata->u.mgd.associated->bssid; |
@@ -2185,7 +2256,6 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, | |||
2185 | static int ieee80211_start_roc_work(struct ieee80211_local *local, | 2256 | static int ieee80211_start_roc_work(struct ieee80211_local *local, |
2186 | struct ieee80211_sub_if_data *sdata, | 2257 | struct ieee80211_sub_if_data *sdata, |
2187 | struct ieee80211_channel *channel, | 2258 | struct ieee80211_channel *channel, |
2188 | enum nl80211_channel_type channel_type, | ||
2189 | unsigned int duration, u64 *cookie, | 2259 | unsigned int duration, u64 *cookie, |
2190 | struct sk_buff *txskb) | 2260 | struct sk_buff *txskb) |
2191 | { | 2261 | { |
@@ -2203,7 +2273,6 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2203 | return -ENOMEM; | 2273 | return -ENOMEM; |
2204 | 2274 | ||
2205 | roc->chan = channel; | 2275 | roc->chan = channel; |
2206 | roc->chan_type = channel_type; | ||
2207 | roc->duration = duration; | 2276 | roc->duration = duration; |
2208 | roc->req_duration = duration; | 2277 | roc->req_duration = duration; |
2209 | roc->frame = txskb; | 2278 | roc->frame = txskb; |
@@ -2236,7 +2305,7 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2236 | if (!duration) | 2305 | if (!duration) |
2237 | duration = 10; | 2306 | duration = 10; |
2238 | 2307 | ||
2239 | ret = drv_remain_on_channel(local, channel, channel_type, duration); | 2308 | ret = drv_remain_on_channel(local, sdata, channel, duration); |
2240 | if (ret) { | 2309 | if (ret) { |
2241 | kfree(roc); | 2310 | kfree(roc); |
2242 | return ret; | 2311 | return ret; |
@@ -2247,7 +2316,7 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2247 | 2316 | ||
2248 | out_check_combine: | 2317 | out_check_combine: |
2249 | list_for_each_entry(tmp, &local->roc_list, list) { | 2318 | list_for_each_entry(tmp, &local->roc_list, list) { |
2250 | if (tmp->chan != channel || tmp->chan_type != channel_type) | 2319 | if (tmp->chan != channel || tmp->sdata != sdata) |
2251 | continue; | 2320 | continue; |
2252 | 2321 | ||
2253 | /* | 2322 | /* |
@@ -2341,13 +2410,22 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2341 | list_add_tail(&roc->list, &local->roc_list); | 2410 | list_add_tail(&roc->list, &local->roc_list); |
2342 | 2411 | ||
2343 | /* | 2412 | /* |
2344 | * cookie is either the roc (for normal roc) | 2413 | * cookie is either the roc cookie (for normal roc) |
2345 | * or the SKB (for mgmt TX) | 2414 | * or the SKB (for mgmt TX) |
2346 | */ | 2415 | */ |
2347 | if (txskb) | 2416 | if (!txskb) { |
2417 | /* local->mtx protects this */ | ||
2418 | local->roc_cookie_counter++; | ||
2419 | roc->cookie = local->roc_cookie_counter; | ||
2420 | /* wow, you wrapped 64 bits ... more likely a bug */ | ||
2421 | if (WARN_ON(roc->cookie == 0)) { | ||
2422 | roc->cookie = 1; | ||
2423 | local->roc_cookie_counter++; | ||
2424 | } | ||
2425 | *cookie = roc->cookie; | ||
2426 | } else { | ||
2348 | *cookie = (unsigned long)txskb; | 2427 | *cookie = (unsigned long)txskb; |
2349 | else | 2428 | } |
2350 | *cookie = (unsigned long)roc; | ||
2351 | 2429 | ||
2352 | return 0; | 2430 | return 0; |
2353 | } | 2431 | } |
@@ -2355,7 +2433,6 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2355 | static int ieee80211_remain_on_channel(struct wiphy *wiphy, | 2433 | static int ieee80211_remain_on_channel(struct wiphy *wiphy, |
2356 | struct wireless_dev *wdev, | 2434 | struct wireless_dev *wdev, |
2357 | struct ieee80211_channel *chan, | 2435 | struct ieee80211_channel *chan, |
2358 | enum nl80211_channel_type channel_type, | ||
2359 | unsigned int duration, | 2436 | unsigned int duration, |
2360 | u64 *cookie) | 2437 | u64 *cookie) |
2361 | { | 2438 | { |
@@ -2364,7 +2441,7 @@ static int ieee80211_remain_on_channel(struct wiphy *wiphy, | |||
2364 | int ret; | 2441 | int ret; |
2365 | 2442 | ||
2366 | mutex_lock(&local->mtx); | 2443 | mutex_lock(&local->mtx); |
2367 | ret = ieee80211_start_roc_work(local, sdata, chan, channel_type, | 2444 | ret = ieee80211_start_roc_work(local, sdata, chan, |
2368 | duration, cookie, NULL); | 2445 | duration, cookie, NULL); |
2369 | mutex_unlock(&local->mtx); | 2446 | mutex_unlock(&local->mtx); |
2370 | 2447 | ||
@@ -2382,7 +2459,7 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local, | |||
2382 | struct ieee80211_roc_work *dep, *tmp2; | 2459 | struct ieee80211_roc_work *dep, *tmp2; |
2383 | 2460 | ||
2384 | list_for_each_entry_safe(dep, tmp2, &roc->dependents, list) { | 2461 | list_for_each_entry_safe(dep, tmp2, &roc->dependents, list) { |
2385 | if (!mgmt_tx && (unsigned long)dep != cookie) | 2462 | if (!mgmt_tx && dep->cookie != cookie) |
2386 | continue; | 2463 | continue; |
2387 | else if (mgmt_tx && dep->mgmt_tx_cookie != cookie) | 2464 | else if (mgmt_tx && dep->mgmt_tx_cookie != cookie) |
2388 | continue; | 2465 | continue; |
@@ -2394,7 +2471,7 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local, | |||
2394 | return 0; | 2471 | return 0; |
2395 | } | 2472 | } |
2396 | 2473 | ||
2397 | if (!mgmt_tx && (unsigned long)roc != cookie) | 2474 | if (!mgmt_tx && roc->cookie != cookie) |
2398 | continue; | 2475 | continue; |
2399 | else if (mgmt_tx && roc->mgmt_tx_cookie != cookie) | 2476 | else if (mgmt_tx && roc->mgmt_tx_cookie != cookie) |
2400 | continue; | 2477 | continue; |
@@ -2457,10 +2534,8 @@ static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy, | |||
2457 | 2534 | ||
2458 | static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | 2535 | static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, |
2459 | struct ieee80211_channel *chan, bool offchan, | 2536 | struct ieee80211_channel *chan, bool offchan, |
2460 | enum nl80211_channel_type channel_type, | 2537 | unsigned int wait, const u8 *buf, size_t len, |
2461 | bool channel_type_valid, unsigned int wait, | 2538 | bool no_cck, bool dont_wait_for_ack, u64 *cookie) |
2462 | const u8 *buf, size_t len, bool no_cck, | ||
2463 | bool dont_wait_for_ack, u64 *cookie) | ||
2464 | { | 2539 | { |
2465 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); | 2540 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); |
2466 | struct ieee80211_local *local = sdata->local; | 2541 | struct ieee80211_local *local = sdata->local; |
@@ -2529,14 +2604,10 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
2529 | rcu_read_lock(); | 2604 | rcu_read_lock(); |
2530 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 2605 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
2531 | 2606 | ||
2532 | if (chanctx_conf) { | 2607 | if (chanctx_conf) |
2533 | need_offchan = chan != chanctx_conf->channel; | 2608 | need_offchan = chan != chanctx_conf->def.chan; |
2534 | if (channel_type_valid && | 2609 | else |
2535 | channel_type != chanctx_conf->channel_type) | ||
2536 | need_offchan = true; | ||
2537 | } else { | ||
2538 | need_offchan = true; | 2610 | need_offchan = true; |
2539 | } | ||
2540 | rcu_read_unlock(); | 2611 | rcu_read_unlock(); |
2541 | } | 2612 | } |
2542 | 2613 | ||
@@ -2571,7 +2642,7 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
2571 | local->hw.offchannel_tx_hw_queue; | 2642 | local->hw.offchannel_tx_hw_queue; |
2572 | 2643 | ||
2573 | /* This will handle all kinds of coalescing and immediate TX */ | 2644 | /* This will handle all kinds of coalescing and immediate TX */ |
2574 | ret = ieee80211_start_roc_work(local, sdata, chan, channel_type, | 2645 | ret = ieee80211_start_roc_work(local, sdata, chan, |
2575 | wait, cookie, skb); | 2646 | wait, cookie, skb); |
2576 | if (ret) | 2647 | if (ret) |
2577 | kfree_skb(skb); | 2648 | kfree_skb(skb); |
@@ -3005,7 +3076,7 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev, | |||
3005 | rcu_read_unlock(); | 3076 | rcu_read_unlock(); |
3006 | return -EINVAL; | 3077 | return -EINVAL; |
3007 | } | 3078 | } |
3008 | band = chanctx_conf->channel->band; | 3079 | band = chanctx_conf->def.chan->band; |
3009 | sta = sta_info_get(sdata, peer); | 3080 | sta = sta_info_get(sdata, peer); |
3010 | if (sta) { | 3081 | if (sta) { |
3011 | qos = test_sta_flag(sta, WLAN_STA_WME); | 3082 | qos = test_sta_flag(sta, WLAN_STA_WME); |
@@ -3062,23 +3133,23 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev, | |||
3062 | return 0; | 3133 | return 0; |
3063 | } | 3134 | } |
3064 | 3135 | ||
3065 | static struct ieee80211_channel * | 3136 | static int ieee80211_cfg_get_channel(struct wiphy *wiphy, |
3066 | ieee80211_cfg_get_channel(struct wiphy *wiphy, struct wireless_dev *wdev, | 3137 | struct wireless_dev *wdev, |
3067 | enum nl80211_channel_type *type) | 3138 | struct cfg80211_chan_def *chandef) |
3068 | { | 3139 | { |
3069 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); | 3140 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); |
3070 | struct ieee80211_chanctx_conf *chanctx_conf; | 3141 | struct ieee80211_chanctx_conf *chanctx_conf; |
3071 | struct ieee80211_channel *chan = NULL; | 3142 | int ret = -ENODATA; |
3072 | 3143 | ||
3073 | rcu_read_lock(); | 3144 | rcu_read_lock(); |
3074 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 3145 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
3075 | if (chanctx_conf) { | 3146 | if (chanctx_conf) { |
3076 | *type = chanctx_conf->channel_type; | 3147 | *chandef = chanctx_conf->def; |
3077 | chan = chanctx_conf->channel; | 3148 | ret = 0; |
3078 | } | 3149 | } |
3079 | rcu_read_unlock(); | 3150 | rcu_read_unlock(); |
3080 | 3151 | ||
3081 | return chan; | 3152 | return ret; |
3082 | } | 3153 | } |
3083 | 3154 | ||
3084 | #ifdef CONFIG_PM | 3155 | #ifdef CONFIG_PM |
@@ -3133,6 +3204,7 @@ struct cfg80211_ops mac80211_config_ops = { | |||
3133 | .disassoc = ieee80211_disassoc, | 3204 | .disassoc = ieee80211_disassoc, |
3134 | .join_ibss = ieee80211_join_ibss, | 3205 | .join_ibss = ieee80211_join_ibss, |
3135 | .leave_ibss = ieee80211_leave_ibss, | 3206 | .leave_ibss = ieee80211_leave_ibss, |
3207 | .set_mcast_rate = ieee80211_set_mcast_rate, | ||
3136 | .set_wiphy_params = ieee80211_set_wiphy_params, | 3208 | .set_wiphy_params = ieee80211_set_wiphy_params, |
3137 | .set_tx_power = ieee80211_set_tx_power, | 3209 | .set_tx_power = ieee80211_set_tx_power, |
3138 | .get_tx_power = ieee80211_get_tx_power, | 3210 | .get_tx_power = ieee80211_get_tx_power, |
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index f84b86028a9..53f03120db5 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c | |||
@@ -8,93 +8,47 @@ | |||
8 | #include "ieee80211_i.h" | 8 | #include "ieee80211_i.h" |
9 | #include "driver-ops.h" | 9 | #include "driver-ops.h" |
10 | 10 | ||
11 | static bool | 11 | static void ieee80211_change_chandef(struct ieee80211_local *local, |
12 | ieee80211_channel_types_are_compatible(enum nl80211_channel_type chantype1, | 12 | struct ieee80211_chanctx *ctx, |
13 | enum nl80211_channel_type chantype2, | 13 | const struct cfg80211_chan_def *chandef) |
14 | enum nl80211_channel_type *compat) | ||
15 | { | 14 | { |
16 | /* | 15 | if (cfg80211_chandef_identical(&ctx->conf.def, chandef)) |
17 | * start out with chantype1 being the result, | ||
18 | * overwriting later if needed | ||
19 | */ | ||
20 | if (compat) | ||
21 | *compat = chantype1; | ||
22 | |||
23 | switch (chantype1) { | ||
24 | case NL80211_CHAN_NO_HT: | ||
25 | if (compat) | ||
26 | *compat = chantype2; | ||
27 | break; | ||
28 | case NL80211_CHAN_HT20: | ||
29 | /* | ||
30 | * allow any change that doesn't go to no-HT | ||
31 | * (if it already is no-HT no change is needed) | ||
32 | */ | ||
33 | if (chantype2 == NL80211_CHAN_NO_HT) | ||
34 | break; | ||
35 | if (compat) | ||
36 | *compat = chantype2; | ||
37 | break; | ||
38 | case NL80211_CHAN_HT40PLUS: | ||
39 | case NL80211_CHAN_HT40MINUS: | ||
40 | /* allow smaller bandwidth and same */ | ||
41 | if (chantype2 == NL80211_CHAN_NO_HT) | ||
42 | break; | ||
43 | if (chantype2 == NL80211_CHAN_HT20) | ||
44 | break; | ||
45 | if (chantype2 == chantype1) | ||
46 | break; | ||
47 | return false; | ||
48 | } | ||
49 | |||
50 | return true; | ||
51 | } | ||
52 | |||
53 | static void ieee80211_change_chantype(struct ieee80211_local *local, | ||
54 | struct ieee80211_chanctx *ctx, | ||
55 | enum nl80211_channel_type chantype) | ||
56 | { | ||
57 | if (chantype == ctx->conf.channel_type) | ||
58 | return; | 16 | return; |
59 | 17 | ||
60 | ctx->conf.channel_type = chantype; | 18 | WARN_ON(!cfg80211_chandef_compatible(&ctx->conf.def, chandef)); |
61 | drv_change_chanctx(local, ctx, IEEE80211_CHANCTX_CHANGE_CHANNEL_TYPE); | 19 | |
20 | ctx->conf.def = *chandef; | ||
21 | drv_change_chanctx(local, ctx, IEEE80211_CHANCTX_CHANGE_WIDTH); | ||
62 | 22 | ||
63 | if (!local->use_chanctx) { | 23 | if (!local->use_chanctx) { |
64 | local->_oper_channel_type = chantype; | 24 | local->_oper_channel_type = cfg80211_get_chandef_type(chandef); |
65 | ieee80211_hw_config(local, 0); | 25 | ieee80211_hw_config(local, 0); |
66 | } | 26 | } |
67 | } | 27 | } |
68 | 28 | ||
69 | static struct ieee80211_chanctx * | 29 | static struct ieee80211_chanctx * |
70 | ieee80211_find_chanctx(struct ieee80211_local *local, | 30 | ieee80211_find_chanctx(struct ieee80211_local *local, |
71 | struct ieee80211_channel *channel, | 31 | const struct cfg80211_chan_def *chandef, |
72 | enum nl80211_channel_type channel_type, | ||
73 | enum ieee80211_chanctx_mode mode) | 32 | enum ieee80211_chanctx_mode mode) |
74 | { | 33 | { |
75 | struct ieee80211_chanctx *ctx; | 34 | struct ieee80211_chanctx *ctx; |
76 | enum nl80211_channel_type compat_type; | ||
77 | 35 | ||
78 | lockdep_assert_held(&local->chanctx_mtx); | 36 | lockdep_assert_held(&local->chanctx_mtx); |
79 | 37 | ||
80 | if (mode == IEEE80211_CHANCTX_EXCLUSIVE) | 38 | if (mode == IEEE80211_CHANCTX_EXCLUSIVE) |
81 | return NULL; | 39 | return NULL; |
82 | if (WARN_ON(!channel)) | ||
83 | return NULL; | ||
84 | 40 | ||
85 | list_for_each_entry(ctx, &local->chanctx_list, list) { | 41 | list_for_each_entry(ctx, &local->chanctx_list, list) { |
86 | compat_type = ctx->conf.channel_type; | 42 | const struct cfg80211_chan_def *compat; |
87 | 43 | ||
88 | if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE) | 44 | if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE) |
89 | continue; | 45 | continue; |
90 | if (ctx->conf.channel != channel) | 46 | |
91 | continue; | 47 | compat = cfg80211_chandef_compatible(&ctx->conf.def, chandef); |
92 | if (!ieee80211_channel_types_are_compatible(ctx->conf.channel_type, | 48 | if (!compat) |
93 | channel_type, | ||
94 | &compat_type)) | ||
95 | continue; | 49 | continue; |
96 | 50 | ||
97 | ieee80211_change_chantype(local, ctx, compat_type); | 51 | ieee80211_change_chandef(local, ctx, compat); |
98 | 52 | ||
99 | return ctx; | 53 | return ctx; |
100 | } | 54 | } |
@@ -104,8 +58,7 @@ ieee80211_find_chanctx(struct ieee80211_local *local, | |||
104 | 58 | ||
105 | static struct ieee80211_chanctx * | 59 | static struct ieee80211_chanctx * |
106 | ieee80211_new_chanctx(struct ieee80211_local *local, | 60 | ieee80211_new_chanctx(struct ieee80211_local *local, |
107 | struct ieee80211_channel *channel, | 61 | const struct cfg80211_chan_def *chandef, |
108 | enum nl80211_channel_type channel_type, | ||
109 | enum ieee80211_chanctx_mode mode) | 62 | enum ieee80211_chanctx_mode mode) |
110 | { | 63 | { |
111 | struct ieee80211_chanctx *ctx; | 64 | struct ieee80211_chanctx *ctx; |
@@ -117,15 +70,15 @@ ieee80211_new_chanctx(struct ieee80211_local *local, | |||
117 | if (!ctx) | 70 | if (!ctx) |
118 | return ERR_PTR(-ENOMEM); | 71 | return ERR_PTR(-ENOMEM); |
119 | 72 | ||
120 | ctx->conf.channel = channel; | 73 | ctx->conf.def = *chandef; |
121 | ctx->conf.channel_type = channel_type; | ||
122 | ctx->conf.rx_chains_static = 1; | 74 | ctx->conf.rx_chains_static = 1; |
123 | ctx->conf.rx_chains_dynamic = 1; | 75 | ctx->conf.rx_chains_dynamic = 1; |
124 | ctx->mode = mode; | 76 | ctx->mode = mode; |
125 | 77 | ||
126 | if (!local->use_chanctx) { | 78 | if (!local->use_chanctx) { |
127 | local->_oper_channel_type = channel_type; | 79 | local->_oper_channel_type = |
128 | local->_oper_channel = channel; | 80 | cfg80211_get_chandef_type(chandef); |
81 | local->_oper_channel = chandef->chan; | ||
129 | ieee80211_hw_config(local, 0); | 82 | ieee80211_hw_config(local, 0); |
130 | } else { | 83 | } else { |
131 | err = drv_add_chanctx(local, ctx); | 84 | err = drv_add_chanctx(local, ctx); |
@@ -173,44 +126,42 @@ static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata, | |||
173 | rcu_assign_pointer(sdata->vif.chanctx_conf, &ctx->conf); | 126 | rcu_assign_pointer(sdata->vif.chanctx_conf, &ctx->conf); |
174 | ctx->refcount++; | 127 | ctx->refcount++; |
175 | 128 | ||
129 | ieee80211_recalc_txpower(sdata); | ||
130 | |||
176 | return 0; | 131 | return 0; |
177 | } | 132 | } |
178 | 133 | ||
179 | static enum nl80211_channel_type | 134 | static void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local, |
180 | ieee80211_calc_chantype(struct ieee80211_local *local, | 135 | struct ieee80211_chanctx *ctx) |
181 | struct ieee80211_chanctx *ctx) | ||
182 | { | 136 | { |
183 | struct ieee80211_chanctx_conf *conf = &ctx->conf; | 137 | struct ieee80211_chanctx_conf *conf = &ctx->conf; |
184 | struct ieee80211_sub_if_data *sdata; | 138 | struct ieee80211_sub_if_data *sdata; |
185 | enum nl80211_channel_type result = NL80211_CHAN_NO_HT; | 139 | const struct cfg80211_chan_def *compat = NULL; |
186 | 140 | ||
187 | lockdep_assert_held(&local->chanctx_mtx); | 141 | lockdep_assert_held(&local->chanctx_mtx); |
188 | 142 | ||
189 | rcu_read_lock(); | 143 | rcu_read_lock(); |
190 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 144 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
145 | |||
191 | if (!ieee80211_sdata_running(sdata)) | 146 | if (!ieee80211_sdata_running(sdata)) |
192 | continue; | 147 | continue; |
193 | if (rcu_access_pointer(sdata->vif.chanctx_conf) != conf) | 148 | if (rcu_access_pointer(sdata->vif.chanctx_conf) != conf) |
194 | continue; | 149 | continue; |
195 | 150 | ||
196 | WARN_ON_ONCE(!ieee80211_channel_types_are_compatible( | 151 | if (!compat) |
197 | sdata->vif.bss_conf.channel_type, | 152 | compat = &sdata->vif.bss_conf.chandef; |
198 | result, &result)); | 153 | |
154 | compat = cfg80211_chandef_compatible( | ||
155 | &sdata->vif.bss_conf.chandef, compat); | ||
156 | if (!compat) | ||
157 | break; | ||
199 | } | 158 | } |
200 | rcu_read_unlock(); | 159 | rcu_read_unlock(); |
201 | 160 | ||
202 | return result; | 161 | if (WARN_ON_ONCE(!compat)) |
203 | } | 162 | return; |
204 | |||
205 | static void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local, | ||
206 | struct ieee80211_chanctx *ctx) | ||
207 | { | ||
208 | enum nl80211_channel_type chantype; | ||
209 | |||
210 | lockdep_assert_held(&local->chanctx_mtx); | ||
211 | 163 | ||
212 | chantype = ieee80211_calc_chantype(local, ctx); | 164 | ieee80211_change_chandef(local, ctx, compat); |
213 | ieee80211_change_chantype(local, ctx, chantype); | ||
214 | } | 165 | } |
215 | 166 | ||
216 | static void ieee80211_unassign_vif_chanctx(struct ieee80211_sub_if_data *sdata, | 167 | static void ieee80211_unassign_vif_chanctx(struct ieee80211_sub_if_data *sdata, |
@@ -335,8 +286,7 @@ void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local, | |||
335 | } | 286 | } |
336 | 287 | ||
337 | int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, | 288 | int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, |
338 | struct ieee80211_channel *channel, | 289 | const struct cfg80211_chan_def *chandef, |
339 | enum nl80211_channel_type channel_type, | ||
340 | enum ieee80211_chanctx_mode mode) | 290 | enum ieee80211_chanctx_mode mode) |
341 | { | 291 | { |
342 | struct ieee80211_local *local = sdata->local; | 292 | struct ieee80211_local *local = sdata->local; |
@@ -348,15 +298,15 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, | |||
348 | mutex_lock(&local->chanctx_mtx); | 298 | mutex_lock(&local->chanctx_mtx); |
349 | __ieee80211_vif_release_channel(sdata); | 299 | __ieee80211_vif_release_channel(sdata); |
350 | 300 | ||
351 | ctx = ieee80211_find_chanctx(local, channel, channel_type, mode); | 301 | ctx = ieee80211_find_chanctx(local, chandef, mode); |
352 | if (!ctx) | 302 | if (!ctx) |
353 | ctx = ieee80211_new_chanctx(local, channel, channel_type, mode); | 303 | ctx = ieee80211_new_chanctx(local, chandef, mode); |
354 | if (IS_ERR(ctx)) { | 304 | if (IS_ERR(ctx)) { |
355 | ret = PTR_ERR(ctx); | 305 | ret = PTR_ERR(ctx); |
356 | goto out; | 306 | goto out; |
357 | } | 307 | } |
358 | 308 | ||
359 | sdata->vif.bss_conf.channel_type = channel_type; | 309 | sdata->vif.bss_conf.chandef = *chandef; |
360 | 310 | ||
361 | ret = ieee80211_assign_vif_chanctx(sdata, ctx); | 311 | ret = ieee80211_assign_vif_chanctx(sdata, ctx); |
362 | if (ret) { | 312 | if (ret) { |
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c index 090d08ff22c..2d4235497f1 100644 --- a/net/mac80211/debugfs_key.c +++ b/net/mac80211/debugfs_key.c | |||
@@ -116,7 +116,7 @@ static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf, | |||
116 | size_t count, loff_t *ppos) | 116 | size_t count, loff_t *ppos) |
117 | { | 117 | { |
118 | struct ieee80211_key *key = file->private_data; | 118 | struct ieee80211_key *key = file->private_data; |
119 | char buf[14*NUM_RX_DATA_QUEUES+1], *p = buf; | 119 | char buf[14*IEEE80211_NUM_TIDS+1], *p = buf; |
120 | int i, len; | 120 | int i, len; |
121 | const u8 *rpn; | 121 | const u8 *rpn; |
122 | 122 | ||
@@ -126,7 +126,7 @@ static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf, | |||
126 | len = scnprintf(buf, sizeof(buf), "\n"); | 126 | len = scnprintf(buf, sizeof(buf), "\n"); |
127 | break; | 127 | break; |
128 | case WLAN_CIPHER_SUITE_TKIP: | 128 | case WLAN_CIPHER_SUITE_TKIP: |
129 | for (i = 0; i < NUM_RX_DATA_QUEUES; i++) | 129 | for (i = 0; i < IEEE80211_NUM_TIDS; i++) |
130 | p += scnprintf(p, sizeof(buf)+buf-p, | 130 | p += scnprintf(p, sizeof(buf)+buf-p, |
131 | "%08x %04x\n", | 131 | "%08x %04x\n", |
132 | key->u.tkip.rx[i].iv32, | 132 | key->u.tkip.rx[i].iv32, |
@@ -134,7 +134,7 @@ static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf, | |||
134 | len = p - buf; | 134 | len = p - buf; |
135 | break; | 135 | break; |
136 | case WLAN_CIPHER_SUITE_CCMP: | 136 | case WLAN_CIPHER_SUITE_CCMP: |
137 | for (i = 0; i < NUM_RX_DATA_QUEUES + 1; i++) { | 137 | for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) { |
138 | rpn = key->u.ccmp.rx_pn[i]; | 138 | rpn = key->u.ccmp.rx_pn[i]; |
139 | p += scnprintf(p, sizeof(buf)+buf-p, | 139 | p += scnprintf(p, sizeof(buf)+buf-p, |
140 | "%02x%02x%02x%02x%02x%02x\n", | 140 | "%02x%02x%02x%02x%02x%02x\n", |
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 3393ad5b8ab..cbde5cc49a4 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
11 | #include <linux/device.h> | 11 | #include <linux/device.h> |
12 | #include <linux/if.h> | 12 | #include <linux/if.h> |
13 | #include <linux/if_ether.h> | ||
13 | #include <linux/interrupt.h> | 14 | #include <linux/interrupt.h> |
14 | #include <linux/netdevice.h> | 15 | #include <linux/netdevice.h> |
15 | #include <linux/rtnetlink.h> | 16 | #include <linux/rtnetlink.h> |
@@ -167,7 +168,29 @@ IEEE80211_IF_FILE(rc_rateidx_mcs_mask_5ghz, | |||
167 | 168 | ||
168 | IEEE80211_IF_FILE(flags, flags, HEX); | 169 | IEEE80211_IF_FILE(flags, flags, HEX); |
169 | IEEE80211_IF_FILE(state, state, LHEX); | 170 | IEEE80211_IF_FILE(state, state, LHEX); |
170 | IEEE80211_IF_FILE(channel_type, vif.bss_conf.channel_type, DEC); | 171 | IEEE80211_IF_FILE(txpower, vif.bss_conf.txpower, DEC); |
172 | IEEE80211_IF_FILE(ap_power_level, ap_power_level, DEC); | ||
173 | IEEE80211_IF_FILE(user_power_level, user_power_level, DEC); | ||
174 | |||
175 | static ssize_t | ||
176 | ieee80211_if_fmt_hw_queues(const struct ieee80211_sub_if_data *sdata, | ||
177 | char *buf, int buflen) | ||
178 | { | ||
179 | int len; | ||
180 | |||
181 | len = scnprintf(buf, buflen, "AC queues: VO:%d VI:%d BE:%d BK:%d\n", | ||
182 | sdata->vif.hw_queue[IEEE80211_AC_VO], | ||
183 | sdata->vif.hw_queue[IEEE80211_AC_VI], | ||
184 | sdata->vif.hw_queue[IEEE80211_AC_BE], | ||
185 | sdata->vif.hw_queue[IEEE80211_AC_BK]); | ||
186 | |||
187 | if (sdata->vif.type == NL80211_IFTYPE_AP) | ||
188 | len += scnprintf(buf + len, buflen - len, "cab queue: %d\n", | ||
189 | sdata->vif.cab_queue); | ||
190 | |||
191 | return len; | ||
192 | } | ||
193 | __IEEE80211_IF_FILE(hw_queues, NULL); | ||
171 | 194 | ||
172 | /* STA attributes */ | 195 | /* STA attributes */ |
173 | IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC); | 196 | IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC); |
@@ -245,27 +268,6 @@ static ssize_t ieee80211_if_fmt_tkip_mic_test( | |||
245 | return -EOPNOTSUPP; | 268 | return -EOPNOTSUPP; |
246 | } | 269 | } |
247 | 270 | ||
248 | static int hwaddr_aton(const char *txt, u8 *addr) | ||
249 | { | ||
250 | int i; | ||
251 | |||
252 | for (i = 0; i < ETH_ALEN; i++) { | ||
253 | int a, b; | ||
254 | |||
255 | a = hex_to_bin(*txt++); | ||
256 | if (a < 0) | ||
257 | return -1; | ||
258 | b = hex_to_bin(*txt++); | ||
259 | if (b < 0) | ||
260 | return -1; | ||
261 | *addr++ = (a << 4) | b; | ||
262 | if (i < 5 && *txt++ != ':') | ||
263 | return -1; | ||
264 | } | ||
265 | |||
266 | return 0; | ||
267 | } | ||
268 | |||
269 | static ssize_t ieee80211_if_parse_tkip_mic_test( | 271 | static ssize_t ieee80211_if_parse_tkip_mic_test( |
270 | struct ieee80211_sub_if_data *sdata, const char *buf, int buflen) | 272 | struct ieee80211_sub_if_data *sdata, const char *buf, int buflen) |
271 | { | 273 | { |
@@ -275,13 +277,7 @@ static ssize_t ieee80211_if_parse_tkip_mic_test( | |||
275 | struct ieee80211_hdr *hdr; | 277 | struct ieee80211_hdr *hdr; |
276 | __le16 fc; | 278 | __le16 fc; |
277 | 279 | ||
278 | /* | 280 | if (!mac_pton(buf, addr)) |
279 | * Assume colon-delimited MAC address with possible white space | ||
280 | * following. | ||
281 | */ | ||
282 | if (buflen < 3 * ETH_ALEN - 1) | ||
283 | return -EINVAL; | ||
284 | if (hwaddr_aton(buf, addr) < 0) | ||
285 | return -EINVAL; | 281 | return -EINVAL; |
286 | 282 | ||
287 | if (!ieee80211_sdata_running(sdata)) | 283 | if (!ieee80211_sdata_running(sdata)) |
@@ -307,13 +303,16 @@ static ssize_t ieee80211_if_parse_tkip_mic_test( | |||
307 | case NL80211_IFTYPE_STATION: | 303 | case NL80211_IFTYPE_STATION: |
308 | fc |= cpu_to_le16(IEEE80211_FCTL_TODS); | 304 | fc |= cpu_to_le16(IEEE80211_FCTL_TODS); |
309 | /* BSSID SA DA */ | 305 | /* BSSID SA DA */ |
310 | if (sdata->vif.bss_conf.bssid == NULL) { | 306 | mutex_lock(&sdata->u.mgd.mtx); |
307 | if (!sdata->u.mgd.associated) { | ||
308 | mutex_unlock(&sdata->u.mgd.mtx); | ||
311 | dev_kfree_skb(skb); | 309 | dev_kfree_skb(skb); |
312 | return -ENOTCONN; | 310 | return -ENOTCONN; |
313 | } | 311 | } |
314 | memcpy(hdr->addr1, sdata->vif.bss_conf.bssid, ETH_ALEN); | 312 | memcpy(hdr->addr1, sdata->u.mgd.associated->bssid, ETH_ALEN); |
315 | memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN); | 313 | memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN); |
316 | memcpy(hdr->addr3, addr, ETH_ALEN); | 314 | memcpy(hdr->addr3, addr, ETH_ALEN); |
315 | mutex_unlock(&sdata->u.mgd.mtx); | ||
317 | break; | 316 | break; |
318 | default: | 317 | default: |
319 | dev_kfree_skb(skb); | 318 | dev_kfree_skb(skb); |
@@ -443,7 +442,7 @@ static ssize_t ieee80211_if_parse_tsf( | |||
443 | } | 442 | } |
444 | ret = kstrtoull(buf, 10, &tsf); | 443 | ret = kstrtoull(buf, 10, &tsf); |
445 | if (ret < 0) | 444 | if (ret < 0) |
446 | return -EINVAL; | 445 | return ret; |
447 | if (tsf_is_delta) | 446 | if (tsf_is_delta) |
448 | tsf = drv_get_tsf(local, sdata) + tsf_is_delta * tsf; | 447 | tsf = drv_get_tsf(local, sdata) + tsf_is_delta * tsf; |
449 | if (local->ops->set_tsf) { | 448 | if (local->ops->set_tsf) { |
@@ -531,6 +530,7 @@ static void add_common_files(struct ieee80211_sub_if_data *sdata) | |||
531 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); | 530 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); |
532 | DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz); | 531 | DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz); |
533 | DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz); | 532 | DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz); |
533 | DEBUGFS_ADD(hw_queues); | ||
534 | } | 534 | } |
535 | 535 | ||
536 | static void add_sta_files(struct ieee80211_sub_if_data *sdata) | 536 | static void add_sta_files(struct ieee80211_sub_if_data *sdata) |
@@ -631,7 +631,9 @@ static void add_files(struct ieee80211_sub_if_data *sdata) | |||
631 | 631 | ||
632 | DEBUGFS_ADD(flags); | 632 | DEBUGFS_ADD(flags); |
633 | DEBUGFS_ADD(state); | 633 | DEBUGFS_ADD(state); |
634 | DEBUGFS_ADD(channel_type); | 634 | DEBUGFS_ADD(txpower); |
635 | DEBUGFS_ADD(user_power_level); | ||
636 | DEBUGFS_ADD(ap_power_level); | ||
635 | 637 | ||
636 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) | 638 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) |
637 | add_common_files(sdata); | 639 | add_common_files(sdata); |
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 5ccec2c1e9f..89281d24b09 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include "debugfs.h" | 14 | #include "debugfs.h" |
15 | #include "debugfs_sta.h" | 15 | #include "debugfs_sta.h" |
16 | #include "sta_info.h" | 16 | #include "sta_info.h" |
17 | #include "driver-ops.h" | ||
17 | 18 | ||
18 | /* sta attributtes */ | 19 | /* sta attributtes */ |
19 | 20 | ||
@@ -131,10 +132,10 @@ STA_OPS(connected_time); | |||
131 | static ssize_t sta_last_seq_ctrl_read(struct file *file, char __user *userbuf, | 132 | static ssize_t sta_last_seq_ctrl_read(struct file *file, char __user *userbuf, |
132 | size_t count, loff_t *ppos) | 133 | size_t count, loff_t *ppos) |
133 | { | 134 | { |
134 | char buf[15*NUM_RX_DATA_QUEUES], *p = buf; | 135 | char buf[15*IEEE80211_NUM_TIDS], *p = buf; |
135 | int i; | 136 | int i; |
136 | struct sta_info *sta = file->private_data; | 137 | struct sta_info *sta = file->private_data; |
137 | for (i = 0; i < NUM_RX_DATA_QUEUES; i++) | 138 | for (i = 0; i < IEEE80211_NUM_TIDS; i++) |
138 | p += scnprintf(p, sizeof(buf)+buf-p, "%x ", | 139 | p += scnprintf(p, sizeof(buf)+buf-p, "%x ", |
139 | le16_to_cpu(sta->last_seq_ctrl[i])); | 140 | le16_to_cpu(sta->last_seq_ctrl[i])); |
140 | p += scnprintf(p, sizeof(buf)+buf-p, "\n"); | 141 | p += scnprintf(p, sizeof(buf)+buf-p, "\n"); |
@@ -145,7 +146,7 @@ STA_OPS(last_seq_ctrl); | |||
145 | static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, | 146 | static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, |
146 | size_t count, loff_t *ppos) | 147 | size_t count, loff_t *ppos) |
147 | { | 148 | { |
148 | char buf[71 + STA_TID_NUM * 40], *p = buf; | 149 | char buf[71 + IEEE80211_NUM_TIDS * 40], *p = buf; |
149 | int i; | 150 | int i; |
150 | struct sta_info *sta = file->private_data; | 151 | struct sta_info *sta = file->private_data; |
151 | struct tid_ampdu_rx *tid_rx; | 152 | struct tid_ampdu_rx *tid_rx; |
@@ -158,7 +159,7 @@ static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, | |||
158 | p += scnprintf(p, sizeof(buf) + buf - p, | 159 | p += scnprintf(p, sizeof(buf) + buf - p, |
159 | "TID\t\tRX active\tDTKN\tSSN\t\tTX\tDTKN\tpending\n"); | 160 | "TID\t\tRX active\tDTKN\tSSN\t\tTX\tDTKN\tpending\n"); |
160 | 161 | ||
161 | for (i = 0; i < STA_TID_NUM; i++) { | 162 | for (i = 0; i < IEEE80211_NUM_TIDS; i++) { |
162 | tid_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[i]); | 163 | tid_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[i]); |
163 | tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[i]); | 164 | tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[i]); |
164 | 165 | ||
@@ -220,7 +221,7 @@ static ssize_t sta_agg_status_write(struct file *file, const char __user *userbu | |||
220 | 221 | ||
221 | tid = simple_strtoul(buf, NULL, 0); | 222 | tid = simple_strtoul(buf, NULL, 0); |
222 | 223 | ||
223 | if (tid >= STA_TID_NUM) | 224 | if (tid >= IEEE80211_NUM_TIDS) |
224 | return -EINVAL; | 225 | return -EINVAL; |
225 | 226 | ||
226 | if (tx) { | 227 | if (tx) { |
@@ -334,6 +335,8 @@ STA_OPS(ht_capa); | |||
334 | 335 | ||
335 | void ieee80211_sta_debugfs_add(struct sta_info *sta) | 336 | void ieee80211_sta_debugfs_add(struct sta_info *sta) |
336 | { | 337 | { |
338 | struct ieee80211_local *local = sta->local; | ||
339 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
337 | struct dentry *stations_dir = sta->sdata->debugfs.subdir_stations; | 340 | struct dentry *stations_dir = sta->sdata->debugfs.subdir_stations; |
338 | u8 mac[3*ETH_ALEN]; | 341 | u8 mac[3*ETH_ALEN]; |
339 | 342 | ||
@@ -379,10 +382,16 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta) | |||
379 | DEBUGFS_ADD_COUNTER(tx_retry_failed, tx_retry_failed); | 382 | DEBUGFS_ADD_COUNTER(tx_retry_failed, tx_retry_failed); |
380 | DEBUGFS_ADD_COUNTER(tx_retry_count, tx_retry_count); | 383 | DEBUGFS_ADD_COUNTER(tx_retry_count, tx_retry_count); |
381 | DEBUGFS_ADD_COUNTER(wep_weak_iv_count, wep_weak_iv_count); | 384 | DEBUGFS_ADD_COUNTER(wep_weak_iv_count, wep_weak_iv_count); |
385 | |||
386 | drv_sta_add_debugfs(local, sdata, &sta->sta, sta->debugfs.dir); | ||
382 | } | 387 | } |
383 | 388 | ||
384 | void ieee80211_sta_debugfs_remove(struct sta_info *sta) | 389 | void ieee80211_sta_debugfs_remove(struct sta_info *sta) |
385 | { | 390 | { |
391 | struct ieee80211_local *local = sta->local; | ||
392 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
393 | |||
394 | drv_sta_remove_debugfs(local, sdata, &sta->sta, sta->debugfs.dir); | ||
386 | debugfs_remove_recursive(sta->debugfs.dir); | 395 | debugfs_remove_recursive(sta->debugfs.dir); |
387 | sta->debugfs.dir = NULL; | 396 | sta->debugfs.dir = NULL; |
388 | } | 397 | } |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 77407b31e1f..c6560cc7a9d 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -490,6 +490,38 @@ static inline void drv_sta_remove(struct ieee80211_local *local, | |||
490 | trace_drv_return_void(local); | 490 | trace_drv_return_void(local); |
491 | } | 491 | } |
492 | 492 | ||
493 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
494 | static inline void drv_sta_add_debugfs(struct ieee80211_local *local, | ||
495 | struct ieee80211_sub_if_data *sdata, | ||
496 | struct ieee80211_sta *sta, | ||
497 | struct dentry *dir) | ||
498 | { | ||
499 | might_sleep(); | ||
500 | |||
501 | sdata = get_bss_sdata(sdata); | ||
502 | check_sdata_in_driver(sdata); | ||
503 | |||
504 | if (local->ops->sta_add_debugfs) | ||
505 | local->ops->sta_add_debugfs(&local->hw, &sdata->vif, | ||
506 | sta, dir); | ||
507 | } | ||
508 | |||
509 | static inline void drv_sta_remove_debugfs(struct ieee80211_local *local, | ||
510 | struct ieee80211_sub_if_data *sdata, | ||
511 | struct ieee80211_sta *sta, | ||
512 | struct dentry *dir) | ||
513 | { | ||
514 | might_sleep(); | ||
515 | |||
516 | sdata = get_bss_sdata(sdata); | ||
517 | check_sdata_in_driver(sdata); | ||
518 | |||
519 | if (local->ops->sta_remove_debugfs) | ||
520 | local->ops->sta_remove_debugfs(&local->hw, &sdata->vif, | ||
521 | sta, dir); | ||
522 | } | ||
523 | #endif | ||
524 | |||
493 | static inline __must_check | 525 | static inline __must_check |
494 | int drv_sta_state(struct ieee80211_local *local, | 526 | int drv_sta_state(struct ieee80211_local *local, |
495 | struct ieee80211_sub_if_data *sdata, | 527 | struct ieee80211_sub_if_data *sdata, |
@@ -704,17 +736,17 @@ static inline int drv_get_antenna(struct ieee80211_local *local, | |||
704 | } | 736 | } |
705 | 737 | ||
706 | static inline int drv_remain_on_channel(struct ieee80211_local *local, | 738 | static inline int drv_remain_on_channel(struct ieee80211_local *local, |
739 | struct ieee80211_sub_if_data *sdata, | ||
707 | struct ieee80211_channel *chan, | 740 | struct ieee80211_channel *chan, |
708 | enum nl80211_channel_type chantype, | ||
709 | unsigned int duration) | 741 | unsigned int duration) |
710 | { | 742 | { |
711 | int ret; | 743 | int ret; |
712 | 744 | ||
713 | might_sleep(); | 745 | might_sleep(); |
714 | 746 | ||
715 | trace_drv_remain_on_channel(local, chan, chantype, duration); | 747 | trace_drv_remain_on_channel(local, sdata, chan, duration); |
716 | ret = local->ops->remain_on_channel(&local->hw, chan, chantype, | 748 | ret = local->ops->remain_on_channel(&local->hw, &sdata->vif, |
717 | duration); | 749 | chan, duration); |
718 | trace_drv_return_int(local, ret); | 750 | trace_drv_return_int(local, ret); |
719 | 751 | ||
720 | return ret; | 752 | return ret; |
@@ -936,4 +968,39 @@ static inline void drv_unassign_vif_chanctx(struct ieee80211_local *local, | |||
936 | trace_drv_return_void(local); | 968 | trace_drv_return_void(local); |
937 | } | 969 | } |
938 | 970 | ||
971 | static inline int drv_start_ap(struct ieee80211_local *local, | ||
972 | struct ieee80211_sub_if_data *sdata) | ||
973 | { | ||
974 | int ret = 0; | ||
975 | |||
976 | check_sdata_in_driver(sdata); | ||
977 | |||
978 | trace_drv_start_ap(local, sdata, &sdata->vif.bss_conf); | ||
979 | if (local->ops->start_ap) | ||
980 | ret = local->ops->start_ap(&local->hw, &sdata->vif); | ||
981 | trace_drv_return_int(local, ret); | ||
982 | return ret; | ||
983 | } | ||
984 | |||
985 | static inline void drv_stop_ap(struct ieee80211_local *local, | ||
986 | struct ieee80211_sub_if_data *sdata) | ||
987 | { | ||
988 | check_sdata_in_driver(sdata); | ||
989 | |||
990 | trace_drv_stop_ap(local, sdata); | ||
991 | if (local->ops->stop_ap) | ||
992 | local->ops->stop_ap(&local->hw, &sdata->vif); | ||
993 | trace_drv_return_void(local); | ||
994 | } | ||
995 | |||
996 | static inline void drv_restart_complete(struct ieee80211_local *local) | ||
997 | { | ||
998 | might_sleep(); | ||
999 | |||
1000 | trace_drv_restart_complete(local); | ||
1001 | if (local->ops->restart_complete) | ||
1002 | local->ops->restart_complete(&local->hw); | ||
1003 | trace_drv_return_void(local); | ||
1004 | } | ||
1005 | |||
939 | #endif /* __MAC80211_DRIVER_OPS */ | 1006 | #endif /* __MAC80211_DRIVER_OPS */ |
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 4b4538d6392..a71d891794a 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -185,7 +185,7 @@ void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, bool tx) | |||
185 | 185 | ||
186 | cancel_work_sync(&sta->ampdu_mlme.work); | 186 | cancel_work_sync(&sta->ampdu_mlme.work); |
187 | 187 | ||
188 | for (i = 0; i < STA_TID_NUM; i++) { | 188 | for (i = 0; i < IEEE80211_NUM_TIDS; i++) { |
189 | __ieee80211_stop_tx_ba_session(sta, i, WLAN_BACK_INITIATOR, tx); | 189 | __ieee80211_stop_tx_ba_session(sta, i, WLAN_BACK_INITIATOR, tx); |
190 | __ieee80211_stop_rx_ba_session(sta, i, WLAN_BACK_RECIPIENT, | 190 | __ieee80211_stop_rx_ba_session(sta, i, WLAN_BACK_RECIPIENT, |
191 | WLAN_REASON_QSTA_LEAVE_QBSS, tx); | 191 | WLAN_REASON_QSTA_LEAVE_QBSS, tx); |
@@ -209,7 +209,7 @@ void ieee80211_ba_session_work(struct work_struct *work) | |||
209 | return; | 209 | return; |
210 | 210 | ||
211 | mutex_lock(&sta->ampdu_mlme.mtx); | 211 | mutex_lock(&sta->ampdu_mlme.mtx); |
212 | for (tid = 0; tid < STA_TID_NUM; tid++) { | 212 | for (tid = 0; tid < IEEE80211_NUM_TIDS; tid++) { |
213 | if (test_and_clear_bit(tid, sta->ampdu_mlme.tid_rx_timer_expired)) | 213 | if (test_and_clear_bit(tid, sta->ampdu_mlme.tid_rx_timer_expired)) |
214 | ___ieee80211_stop_rx_ba_session( | 214 | ___ieee80211_stop_rx_ba_session( |
215 | sta, tid, WLAN_BACK_RECIPIENT, | 215 | sta, tid, WLAN_BACK_RECIPIENT, |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 67774b05353..fa862b24a7e 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -51,7 +51,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
51 | struct cfg80211_bss *bss; | 51 | struct cfg80211_bss *bss; |
52 | u32 bss_change; | 52 | u32 bss_change; |
53 | u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; | 53 | u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; |
54 | enum nl80211_channel_type channel_type; | 54 | struct cfg80211_chan_def chandef; |
55 | 55 | ||
56 | lockdep_assert_held(&ifibss->mtx); | 56 | lockdep_assert_held(&ifibss->mtx); |
57 | 57 | ||
@@ -79,12 +79,14 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
79 | 79 | ||
80 | sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; | 80 | sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; |
81 | 81 | ||
82 | channel_type = ifibss->channel_type; | 82 | cfg80211_chandef_create(&chandef, chan, ifibss->channel_type); |
83 | if (!cfg80211_can_beacon_sec_chan(local->hw.wiphy, chan, channel_type)) | 83 | if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef)) { |
84 | channel_type = NL80211_CHAN_HT20; | 84 | chandef.width = NL80211_CHAN_WIDTH_20; |
85 | chandef.center_freq1 = chan->center_freq; | ||
86 | } | ||
85 | 87 | ||
86 | ieee80211_vif_release_channel(sdata); | 88 | ieee80211_vif_release_channel(sdata); |
87 | if (ieee80211_vif_use_channel(sdata, chan, channel_type, | 89 | if (ieee80211_vif_use_channel(sdata, &chandef, |
88 | ifibss->fixed_channel ? | 90 | ifibss->fixed_channel ? |
89 | IEEE80211_CHANCTX_SHARED : | 91 | IEEE80211_CHANCTX_SHARED : |
90 | IEEE80211_CHANCTX_EXCLUSIVE)) { | 92 | IEEE80211_CHANCTX_EXCLUSIVE)) { |
@@ -158,7 +160,8 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
158 | ifibss->ie, ifibss->ie_len); | 160 | ifibss->ie, ifibss->ie_len); |
159 | 161 | ||
160 | /* add HT capability and information IEs */ | 162 | /* add HT capability and information IEs */ |
161 | if (channel_type && sband->ht_cap.ht_supported) { | 163 | if (chandef.width != NL80211_CHAN_WIDTH_20_NOHT && |
164 | sband->ht_cap.ht_supported) { | ||
162 | pos = skb_put(skb, 4 + | 165 | pos = skb_put(skb, 4 + |
163 | sizeof(struct ieee80211_ht_cap) + | 166 | sizeof(struct ieee80211_ht_cap) + |
164 | sizeof(struct ieee80211_ht_operation)); | 167 | sizeof(struct ieee80211_ht_operation)); |
@@ -170,7 +173,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
170 | * keep them at 0 | 173 | * keep them at 0 |
171 | */ | 174 | */ |
172 | pos = ieee80211_ie_build_ht_oper(pos, &sband->ht_cap, | 175 | pos = ieee80211_ie_build_ht_oper(pos, &sband->ht_cap, |
173 | chan, channel_type, 0); | 176 | &chandef, 0); |
174 | } | 177 | } |
175 | 178 | ||
176 | if (local->hw.queues >= IEEE80211_NUM_ACS) { | 179 | if (local->hw.queues >= IEEE80211_NUM_ACS) { |
@@ -326,7 +329,7 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | |||
326 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 329 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
327 | if (WARN_ON_ONCE(!chanctx_conf)) | 330 | if (WARN_ON_ONCE(!chanctx_conf)) |
328 | return NULL; | 331 | return NULL; |
329 | band = chanctx_conf->channel->band; | 332 | band = chanctx_conf->def.chan->band; |
330 | rcu_read_unlock(); | 333 | rcu_read_unlock(); |
331 | 334 | ||
332 | sta = sta_info_alloc(sdata, addr, GFP_KERNEL); | 335 | sta = sta_info_alloc(sdata, addr, GFP_KERNEL); |
@@ -374,11 +377,13 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata, | |||
374 | auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg); | 377 | auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg); |
375 | auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); | 378 | auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); |
376 | 379 | ||
377 | if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) | ||
378 | return; | ||
379 | ibss_dbg(sdata, | 380 | ibss_dbg(sdata, |
380 | "RX Auth SA=%pM DA=%pM BSSID=%pM (auth_transaction=%d)\n", | 381 | "RX Auth SA=%pM DA=%pM BSSID=%pM (auth_transaction=%d)\n", |
381 | mgmt->sa, mgmt->da, mgmt->bssid, auth_transaction); | 382 | mgmt->sa, mgmt->da, mgmt->bssid, auth_transaction); |
383 | |||
384 | if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) | ||
385 | return; | ||
386 | |||
382 | sta_info_destroy_addr(sdata, mgmt->sa); | 387 | sta_info_destroy_addr(sdata, mgmt->sa); |
383 | sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, 0, false); | 388 | sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, 0, false); |
384 | rcu_read_unlock(); | 389 | rcu_read_unlock(); |
@@ -473,9 +478,11 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
473 | sdata->u.ibss.channel_type != NL80211_CHAN_NO_HT) { | 478 | sdata->u.ibss.channel_type != NL80211_CHAN_NO_HT) { |
474 | /* we both use HT */ | 479 | /* we both use HT */ |
475 | struct ieee80211_sta_ht_cap sta_ht_cap_new; | 480 | struct ieee80211_sta_ht_cap sta_ht_cap_new; |
476 | enum nl80211_channel_type channel_type = | 481 | struct cfg80211_chan_def chandef; |
477 | ieee80211_ht_oper_to_channel_type( | 482 | |
478 | elems->ht_operation); | 483 | ieee80211_ht_oper_to_chandef(channel, |
484 | elems->ht_operation, | ||
485 | &chandef); | ||
479 | 486 | ||
480 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, | 487 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, |
481 | elems->ht_cap_elem, | 488 | elems->ht_cap_elem, |
@@ -485,9 +492,9 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
485 | * fall back to HT20 if we don't use or use | 492 | * fall back to HT20 if we don't use or use |
486 | * the other extension channel | 493 | * the other extension channel |
487 | */ | 494 | */ |
488 | if (!(channel_type == NL80211_CHAN_HT40MINUS || | 495 | if (chandef.width != NL80211_CHAN_WIDTH_40 || |
489 | channel_type == NL80211_CHAN_HT40PLUS) || | 496 | cfg80211_get_chandef_type(&chandef) != |
490 | channel_type != sdata->u.ibss.channel_type) | 497 | sdata->u.ibss.channel_type) |
491 | sta_ht_cap_new.cap &= | 498 | sta_ht_cap_new.cap &= |
492 | ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | 499 | ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; |
493 | 500 | ||
@@ -543,30 +550,11 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
543 | if (ether_addr_equal(cbss->bssid, sdata->u.ibss.bssid)) | 550 | if (ether_addr_equal(cbss->bssid, sdata->u.ibss.bssid)) |
544 | goto put_bss; | 551 | goto put_bss; |
545 | 552 | ||
546 | if (rx_status->flag & RX_FLAG_MACTIME_MPDU) { | 553 | if (ieee80211_have_rx_timestamp(rx_status)) { |
547 | /* | 554 | /* time when timestamp field was received */ |
548 | * For correct IBSS merging we need mactime; since mactime is | 555 | rx_timestamp = |
549 | * defined as the time the first data symbol of the frame hits | 556 | ieee80211_calculate_rx_timestamp(local, rx_status, |
550 | * the PHY, and the timestamp of the beacon is defined as "the | 557 | len + FCS_LEN, 24); |
551 | * time that the data symbol containing the first bit of the | ||
552 | * timestamp is transmitted to the PHY plus the transmitting | ||
553 | * STA's delays through its local PHY from the MAC-PHY | ||
554 | * interface to its interface with the WM" (802.11 11.1.2) | ||
555 | * - equals the time this bit arrives at the receiver - we have | ||
556 | * to take into account the offset between the two. | ||
557 | * | ||
558 | * E.g. at 1 MBit that means mactime is 192 usec earlier | ||
559 | * (=24 bytes * 8 usecs/byte) than the beacon timestamp. | ||
560 | */ | ||
561 | int rate; | ||
562 | |||
563 | if (rx_status->flag & RX_FLAG_HT) | ||
564 | rate = 65; /* TODO: HT rates */ | ||
565 | else | ||
566 | rate = local->hw.wiphy->bands[band]-> | ||
567 | bitrates[rx_status->rate_idx].bitrate; | ||
568 | |||
569 | rx_timestamp = rx_status->mactime + (24 * 8 * 10 / rate); | ||
570 | } else { | 558 | } else { |
571 | /* | 559 | /* |
572 | * second best option: get current TSF | 560 | * second best option: get current TSF |
@@ -630,7 +618,7 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata, | |||
630 | rcu_read_unlock(); | 618 | rcu_read_unlock(); |
631 | return; | 619 | return; |
632 | } | 620 | } |
633 | band = chanctx_conf->channel->band; | 621 | band = chanctx_conf->def.chan->band; |
634 | rcu_read_unlock(); | 622 | rcu_read_unlock(); |
635 | 623 | ||
636 | sta = sta_info_alloc(sdata, addr, GFP_ATOMIC); | 624 | sta = sta_info_alloc(sdata, addr, GFP_ATOMIC); |
@@ -1095,8 +1083,9 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
1095 | 1083 | ||
1096 | sdata->vif.bss_conf.beacon_int = params->beacon_interval; | 1084 | sdata->vif.bss_conf.beacon_int = params->beacon_interval; |
1097 | 1085 | ||
1098 | sdata->u.ibss.channel = params->channel; | 1086 | sdata->u.ibss.channel = params->chandef.chan; |
1099 | sdata->u.ibss.channel_type = params->channel_type; | 1087 | sdata->u.ibss.channel_type = |
1088 | cfg80211_get_chandef_type(¶ms->chandef); | ||
1100 | sdata->u.ibss.fixed_channel = params->channel_fixed; | 1089 | sdata->u.ibss.fixed_channel = params->channel_fixed; |
1101 | 1090 | ||
1102 | if (params->ie) { | 1091 | if (params->ie) { |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 32e47853f32..5c0d5a6946c 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -56,6 +56,9 @@ struct ieee80211_local; | |||
56 | #define TU_TO_JIFFIES(x) (usecs_to_jiffies((x) * 1024)) | 56 | #define TU_TO_JIFFIES(x) (usecs_to_jiffies((x) * 1024)) |
57 | #define TU_TO_EXP_TIME(x) (jiffies + TU_TO_JIFFIES(x)) | 57 | #define TU_TO_EXP_TIME(x) (jiffies + TU_TO_JIFFIES(x)) |
58 | 58 | ||
59 | /* power level hasn't been configured (or set to automatic) */ | ||
60 | #define IEEE80211_UNSET_POWER_LEVEL INT_MIN | ||
61 | |||
59 | /* | 62 | /* |
60 | * Some APs experience problems when working with U-APSD. Decrease the | 63 | * Some APs experience problems when working with U-APSD. Decrease the |
61 | * probability of that happening by using legacy mode for all ACs but VO. | 64 | * probability of that happening by using legacy mode for all ACs but VO. |
@@ -345,7 +348,6 @@ struct ieee80211_roc_work { | |||
345 | struct ieee80211_sub_if_data *sdata; | 348 | struct ieee80211_sub_if_data *sdata; |
346 | 349 | ||
347 | struct ieee80211_channel *chan; | 350 | struct ieee80211_channel *chan; |
348 | enum nl80211_channel_type chan_type; | ||
349 | 351 | ||
350 | bool started, abort, hw_begun, notified; | 352 | bool started, abort, hw_begun, notified; |
351 | 353 | ||
@@ -353,7 +355,7 @@ struct ieee80211_roc_work { | |||
353 | 355 | ||
354 | u32 duration, req_duration; | 356 | u32 duration, req_duration; |
355 | struct sk_buff *frame; | 357 | struct sk_buff *frame; |
356 | u64 mgmt_tx_cookie; | 358 | u64 cookie, mgmt_tx_cookie; |
357 | }; | 359 | }; |
358 | 360 | ||
359 | /* flags used in struct ieee80211_if_managed.flags */ | 361 | /* flags used in struct ieee80211_if_managed.flags */ |
@@ -361,7 +363,7 @@ enum ieee80211_sta_flags { | |||
361 | IEEE80211_STA_BEACON_POLL = BIT(0), | 363 | IEEE80211_STA_BEACON_POLL = BIT(0), |
362 | IEEE80211_STA_CONNECTION_POLL = BIT(1), | 364 | IEEE80211_STA_CONNECTION_POLL = BIT(1), |
363 | IEEE80211_STA_CONTROL_PORT = BIT(2), | 365 | IEEE80211_STA_CONTROL_PORT = BIT(2), |
364 | IEEE80211_STA_DISABLE_11N = BIT(4), | 366 | IEEE80211_STA_DISABLE_HT = BIT(4), |
365 | IEEE80211_STA_CSA_RECEIVED = BIT(5), | 367 | IEEE80211_STA_CSA_RECEIVED = BIT(5), |
366 | IEEE80211_STA_MFP_ENABLED = BIT(6), | 368 | IEEE80211_STA_MFP_ENABLED = BIT(6), |
367 | IEEE80211_STA_UAPSD_ENABLED = BIT(7), | 369 | IEEE80211_STA_UAPSD_ENABLED = BIT(7), |
@@ -470,6 +472,8 @@ struct ieee80211_if_managed { | |||
470 | 472 | ||
471 | u8 use_4addr; | 473 | u8 use_4addr; |
472 | 474 | ||
475 | u8 p2p_noa_index; | ||
476 | |||
473 | /* Signal strength from the last Beacon frame in the current BSS. */ | 477 | /* Signal strength from the last Beacon frame in the current BSS. */ |
474 | int last_beacon_signal; | 478 | int last_beacon_signal; |
475 | 479 | ||
@@ -743,6 +747,9 @@ struct ieee80211_sub_if_data { | |||
743 | u8 needed_rx_chains; | 747 | u8 needed_rx_chains; |
744 | enum ieee80211_smps_mode smps_mode; | 748 | enum ieee80211_smps_mode smps_mode; |
745 | 749 | ||
750 | int user_power_level; /* in dBm */ | ||
751 | int ap_power_level; /* in dBm */ | ||
752 | |||
746 | /* | 753 | /* |
747 | * AP this belongs to: self in AP mode and | 754 | * AP this belongs to: self in AP mode and |
748 | * corresponding AP in VLAN mode, NULL for | 755 | * corresponding AP in VLAN mode, NULL for |
@@ -792,7 +799,7 @@ ieee80211_get_sdata_band(struct ieee80211_sub_if_data *sdata) | |||
792 | rcu_read_lock(); | 799 | rcu_read_lock(); |
793 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 800 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
794 | if (!WARN_ON(!chanctx_conf)) | 801 | if (!WARN_ON(!chanctx_conf)) |
795 | band = chanctx_conf->channel->band; | 802 | band = chanctx_conf->def.chan->band; |
796 | rcu_read_unlock(); | 803 | rcu_read_unlock(); |
797 | 804 | ||
798 | return band; | 805 | return band; |
@@ -1040,7 +1047,6 @@ struct ieee80211_local { | |||
1040 | 1047 | ||
1041 | /* Temporary remain-on-channel for off-channel operations */ | 1048 | /* Temporary remain-on-channel for off-channel operations */ |
1042 | struct ieee80211_channel *tmp_channel; | 1049 | struct ieee80211_channel *tmp_channel; |
1043 | enum nl80211_channel_type tmp_channel_type; | ||
1044 | 1050 | ||
1045 | /* channel contexts */ | 1051 | /* channel contexts */ |
1046 | struct list_head chanctx_list; | 1052 | struct list_head chanctx_list; |
@@ -1117,8 +1123,7 @@ struct ieee80211_local { | |||
1117 | int dynamic_ps_user_timeout; | 1123 | int dynamic_ps_user_timeout; |
1118 | bool disable_dynamic_ps; | 1124 | bool disable_dynamic_ps; |
1119 | 1125 | ||
1120 | int user_power_level; /* in dBm */ | 1126 | int user_power_level; /* in dBm, for all interfaces */ |
1121 | int ap_power_level; /* in dBm */ | ||
1122 | 1127 | ||
1123 | enum ieee80211_smps_mode smps_mode; | 1128 | enum ieee80211_smps_mode smps_mode; |
1124 | 1129 | ||
@@ -1137,6 +1142,7 @@ struct ieee80211_local { | |||
1137 | struct list_head roc_list; | 1142 | struct list_head roc_list; |
1138 | struct work_struct hw_roc_start, hw_roc_done; | 1143 | struct work_struct hw_roc_start, hw_roc_done; |
1139 | unsigned long hw_roc_start_time; | 1144 | unsigned long hw_roc_start_time; |
1145 | u64 roc_cookie_counter; | ||
1140 | 1146 | ||
1141 | struct idr ack_status_frames; | 1147 | struct idr ack_status_frames; |
1142 | spinlock_t ack_status_lock; | 1148 | spinlock_t ack_status_lock; |
@@ -1150,8 +1156,7 @@ struct ieee80211_local { | |||
1150 | 1156 | ||
1151 | /* virtual monitor interface */ | 1157 | /* virtual monitor interface */ |
1152 | struct ieee80211_sub_if_data __rcu *monitor_sdata; | 1158 | struct ieee80211_sub_if_data __rcu *monitor_sdata; |
1153 | struct ieee80211_channel *monitor_channel; | 1159 | struct cfg80211_chan_def monitor_chandef; |
1154 | enum nl80211_channel_type monitor_channel_type; | ||
1155 | }; | 1160 | }; |
1156 | 1161 | ||
1157 | static inline struct ieee80211_sub_if_data * | 1162 | static inline struct ieee80211_sub_if_data * |
@@ -1251,7 +1256,18 @@ static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr) | |||
1251 | is_broadcast_ether_addr(raddr); | 1256 | is_broadcast_ether_addr(raddr); |
1252 | } | 1257 | } |
1253 | 1258 | ||
1259 | static inline bool | ||
1260 | ieee80211_have_rx_timestamp(struct ieee80211_rx_status *status) | ||
1261 | { | ||
1262 | WARN_ON_ONCE(status->flag & RX_FLAG_MACTIME_START && | ||
1263 | status->flag & RX_FLAG_MACTIME_END); | ||
1264 | return status->flag & (RX_FLAG_MACTIME_START | RX_FLAG_MACTIME_END); | ||
1265 | } | ||
1254 | 1266 | ||
1267 | u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local, | ||
1268 | struct ieee80211_rx_status *status, | ||
1269 | unsigned int mpdu_len, | ||
1270 | unsigned int mpdu_offset); | ||
1255 | int ieee80211_hw_config(struct ieee80211_local *local, u32 changed); | 1271 | int ieee80211_hw_config(struct ieee80211_local *local, u32 changed); |
1256 | void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx); | 1272 | void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx); |
1257 | void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | 1273 | void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, |
@@ -1365,6 +1381,9 @@ void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata, | |||
1365 | int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up); | 1381 | int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up); |
1366 | void ieee80211_sdata_stop(struct ieee80211_sub_if_data *sdata); | 1382 | void ieee80211_sdata_stop(struct ieee80211_sub_if_data *sdata); |
1367 | 1383 | ||
1384 | bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata); | ||
1385 | void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata); | ||
1386 | |||
1368 | static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata) | 1387 | static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata) |
1369 | { | 1388 | { |
1370 | return test_bit(SDATA_STATE_RUNNING, &sdata->state); | 1389 | return test_bit(SDATA_STATE_RUNNING, &sdata->state); |
@@ -1496,7 +1515,7 @@ static inline void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata, | |||
1496 | } | 1515 | } |
1497 | 1516 | ||
1498 | __ieee80211_tx_skb_tid_band(sdata, skb, tid, | 1517 | __ieee80211_tx_skb_tid_band(sdata, skb, tid, |
1499 | chanctx_conf->channel->band); | 1518 | chanctx_conf->def.chan->band); |
1500 | rcu_read_unlock(); | 1519 | rcu_read_unlock(); |
1501 | } | 1520 | } |
1502 | 1521 | ||
@@ -1585,8 +1604,7 @@ size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset); | |||
1585 | u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, | 1604 | u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, |
1586 | u16 cap); | 1605 | u16 cap); |
1587 | u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, | 1606 | u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, |
1588 | struct ieee80211_channel *channel, | 1607 | const struct cfg80211_chan_def *chandef, |
1589 | enum nl80211_channel_type channel_type, | ||
1590 | u16 prot_mode); | 1608 | u16 prot_mode); |
1591 | u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, | 1609 | u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, |
1592 | u32 cap); | 1610 | u32 cap); |
@@ -1598,13 +1616,13 @@ int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata, | |||
1598 | enum ieee80211_band band); | 1616 | enum ieee80211_band band); |
1599 | 1617 | ||
1600 | /* channel management */ | 1618 | /* channel management */ |
1601 | enum nl80211_channel_type | 1619 | void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan, |
1602 | ieee80211_ht_oper_to_channel_type(struct ieee80211_ht_operation *ht_oper); | 1620 | struct ieee80211_ht_operation *ht_oper, |
1621 | struct cfg80211_chan_def *chandef); | ||
1603 | 1622 | ||
1604 | int __must_check | 1623 | int __must_check |
1605 | ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, | 1624 | ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, |
1606 | struct ieee80211_channel *channel, | 1625 | const struct cfg80211_chan_def *chandef, |
1607 | enum nl80211_channel_type channel_type, | ||
1608 | enum ieee80211_chanctx_mode mode); | 1626 | enum ieee80211_chanctx_mode mode); |
1609 | void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata); | 1627 | void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata); |
1610 | 1628 | ||
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index bc3e3e1db09..5331662489f 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -42,6 +42,41 @@ | |||
42 | * by either the RTNL, the iflist_mtx or RCU. | 42 | * by either the RTNL, the iflist_mtx or RCU. |
43 | */ | 43 | */ |
44 | 44 | ||
45 | bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata) | ||
46 | { | ||
47 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
48 | int power; | ||
49 | |||
50 | rcu_read_lock(); | ||
51 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
52 | if (!chanctx_conf) { | ||
53 | rcu_read_unlock(); | ||
54 | return false; | ||
55 | } | ||
56 | |||
57 | power = chanctx_conf->def.chan->max_power; | ||
58 | rcu_read_unlock(); | ||
59 | |||
60 | if (sdata->user_power_level != IEEE80211_UNSET_POWER_LEVEL) | ||
61 | power = min(power, sdata->user_power_level); | ||
62 | |||
63 | if (sdata->ap_power_level != IEEE80211_UNSET_POWER_LEVEL) | ||
64 | power = min(power, sdata->ap_power_level); | ||
65 | |||
66 | if (power != sdata->vif.bss_conf.txpower) { | ||
67 | sdata->vif.bss_conf.txpower = power; | ||
68 | ieee80211_hw_config(sdata->local, 0); | ||
69 | return true; | ||
70 | } | ||
71 | |||
72 | return false; | ||
73 | } | ||
74 | |||
75 | void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata) | ||
76 | { | ||
77 | if (__ieee80211_recalc_txpower(sdata)) | ||
78 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_TXPOWER); | ||
79 | } | ||
45 | 80 | ||
46 | static u32 ieee80211_idle_off(struct ieee80211_local *local, | 81 | static u32 ieee80211_idle_off(struct ieee80211_local *local, |
47 | const char *reason) | 82 | const char *reason) |
@@ -380,8 +415,7 @@ static int ieee80211_add_virtual_monitor(struct ieee80211_local *local) | |||
380 | goto out_unlock; | 415 | goto out_unlock; |
381 | } | 416 | } |
382 | 417 | ||
383 | ret = ieee80211_vif_use_channel(sdata, local->monitor_channel, | 418 | ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef, |
384 | local->monitor_channel_type, | ||
385 | IEEE80211_CHANCTX_EXCLUSIVE); | 419 | IEEE80211_CHANCTX_EXCLUSIVE); |
386 | if (ret) { | 420 | if (ret) { |
387 | drv_remove_interface(local, sdata); | 421 | drv_remove_interface(local, sdata); |
@@ -744,31 +778,12 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
744 | /* APs need special treatment */ | 778 | /* APs need special treatment */ |
745 | if (sdata->vif.type == NL80211_IFTYPE_AP) { | 779 | if (sdata->vif.type == NL80211_IFTYPE_AP) { |
746 | struct ieee80211_sub_if_data *vlan, *tmpsdata; | 780 | struct ieee80211_sub_if_data *vlan, *tmpsdata; |
747 | struct beacon_data *old_beacon = | ||
748 | rtnl_dereference(sdata->u.ap.beacon); | ||
749 | struct probe_resp *old_probe_resp = | ||
750 | rtnl_dereference(sdata->u.ap.probe_resp); | ||
751 | |||
752 | /* sdata_running will return false, so this will disable */ | ||
753 | ieee80211_bss_info_change_notify(sdata, | ||
754 | BSS_CHANGED_BEACON_ENABLED); | ||
755 | |||
756 | /* remove beacon and probe response */ | ||
757 | RCU_INIT_POINTER(sdata->u.ap.beacon, NULL); | ||
758 | RCU_INIT_POINTER(sdata->u.ap.probe_resp, NULL); | ||
759 | synchronize_rcu(); | ||
760 | kfree(old_beacon); | ||
761 | kfree(old_probe_resp); | ||
762 | 781 | ||
763 | /* down all dependent devices, that is VLANs */ | 782 | /* down all dependent devices, that is VLANs */ |
764 | list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans, | 783 | list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans, |
765 | u.vlan.list) | 784 | u.vlan.list) |
766 | dev_close(vlan->dev); | 785 | dev_close(vlan->dev); |
767 | WARN_ON(!list_empty(&sdata->u.ap.vlans)); | 786 | WARN_ON(!list_empty(&sdata->u.ap.vlans)); |
768 | |||
769 | /* free all potentially still buffered bcast frames */ | ||
770 | local->total_ps_buffered -= skb_queue_len(&sdata->u.ap.ps.bc_buf); | ||
771 | skb_queue_purge(&sdata->u.ap.ps.bc_buf); | ||
772 | } else if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 787 | } else if (sdata->vif.type == NL80211_IFTYPE_STATION) { |
773 | ieee80211_mgd_stop(sdata); | 788 | ieee80211_mgd_stop(sdata); |
774 | } | 789 | } |
@@ -1529,6 +1544,9 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1529 | 1544 | ||
1530 | ieee80211_set_default_queues(sdata); | 1545 | ieee80211_set_default_queues(sdata); |
1531 | 1546 | ||
1547 | sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL; | ||
1548 | sdata->user_power_level = local->user_power_level; | ||
1549 | |||
1532 | /* setup type-dependent data */ | 1550 | /* setup type-dependent data */ |
1533 | ieee80211_setup_sdata(sdata, type); | 1551 | ieee80211_setup_sdata(sdata, type); |
1534 | 1552 | ||
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index d27e61aaa71..619c5d69799 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -339,7 +339,7 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, | |||
339 | key->conf.iv_len = TKIP_IV_LEN; | 339 | key->conf.iv_len = TKIP_IV_LEN; |
340 | key->conf.icv_len = TKIP_ICV_LEN; | 340 | key->conf.icv_len = TKIP_ICV_LEN; |
341 | if (seq) { | 341 | if (seq) { |
342 | for (i = 0; i < NUM_RX_DATA_QUEUES; i++) { | 342 | for (i = 0; i < IEEE80211_NUM_TIDS; i++) { |
343 | key->u.tkip.rx[i].iv32 = | 343 | key->u.tkip.rx[i].iv32 = |
344 | get_unaligned_le32(&seq[2]); | 344 | get_unaligned_le32(&seq[2]); |
345 | key->u.tkip.rx[i].iv16 = | 345 | key->u.tkip.rx[i].iv16 = |
@@ -352,7 +352,7 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, | |||
352 | key->conf.iv_len = CCMP_HDR_LEN; | 352 | key->conf.iv_len = CCMP_HDR_LEN; |
353 | key->conf.icv_len = CCMP_MIC_LEN; | 353 | key->conf.icv_len = CCMP_MIC_LEN; |
354 | if (seq) { | 354 | if (seq) { |
355 | for (i = 0; i < NUM_RX_DATA_QUEUES + 1; i++) | 355 | for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) |
356 | for (j = 0; j < CCMP_PN_LEN; j++) | 356 | for (j = 0; j < CCMP_PN_LEN; j++) |
357 | key->u.ccmp.rx_pn[i][j] = | 357 | key->u.ccmp.rx_pn[i][j] = |
358 | seq[CCMP_PN_LEN - j - 1]; | 358 | seq[CCMP_PN_LEN - j - 1]; |
@@ -372,8 +372,9 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, | |||
372 | key->conf.iv_len = 0; | 372 | key->conf.iv_len = 0; |
373 | key->conf.icv_len = sizeof(struct ieee80211_mmie); | 373 | key->conf.icv_len = sizeof(struct ieee80211_mmie); |
374 | if (seq) | 374 | if (seq) |
375 | for (j = 0; j < 6; j++) | 375 | for (j = 0; j < CMAC_PN_LEN; j++) |
376 | key->u.aes_cmac.rx_pn[j] = seq[6 - j - 1]; | 376 | key->u.aes_cmac.rx_pn[j] = |
377 | seq[CMAC_PN_LEN - j - 1]; | ||
377 | /* | 378 | /* |
378 | * Initialize AES key state here as an optimization so that | 379 | * Initialize AES key state here as an optimization so that |
379 | * it does not need to be initialized for every packet. | 380 | * it does not need to be initialized for every packet. |
@@ -654,16 +655,16 @@ void ieee80211_get_key_rx_seq(struct ieee80211_key_conf *keyconf, | |||
654 | 655 | ||
655 | switch (key->conf.cipher) { | 656 | switch (key->conf.cipher) { |
656 | case WLAN_CIPHER_SUITE_TKIP: | 657 | case WLAN_CIPHER_SUITE_TKIP: |
657 | if (WARN_ON(tid < 0 || tid >= NUM_RX_DATA_QUEUES)) | 658 | if (WARN_ON(tid < 0 || tid >= IEEE80211_NUM_TIDS)) |
658 | return; | 659 | return; |
659 | seq->tkip.iv32 = key->u.tkip.rx[tid].iv32; | 660 | seq->tkip.iv32 = key->u.tkip.rx[tid].iv32; |
660 | seq->tkip.iv16 = key->u.tkip.rx[tid].iv16; | 661 | seq->tkip.iv16 = key->u.tkip.rx[tid].iv16; |
661 | break; | 662 | break; |
662 | case WLAN_CIPHER_SUITE_CCMP: | 663 | case WLAN_CIPHER_SUITE_CCMP: |
663 | if (WARN_ON(tid < -1 || tid >= NUM_RX_DATA_QUEUES)) | 664 | if (WARN_ON(tid < -1 || tid >= IEEE80211_NUM_TIDS)) |
664 | return; | 665 | return; |
665 | if (tid < 0) | 666 | if (tid < 0) |
666 | pn = key->u.ccmp.rx_pn[NUM_RX_DATA_QUEUES]; | 667 | pn = key->u.ccmp.rx_pn[IEEE80211_NUM_TIDS]; |
667 | else | 668 | else |
668 | pn = key->u.ccmp.rx_pn[tid]; | 669 | pn = key->u.ccmp.rx_pn[tid]; |
669 | memcpy(seq->ccmp.pn, pn, CCMP_PN_LEN); | 670 | memcpy(seq->ccmp.pn, pn, CCMP_PN_LEN); |
diff --git a/net/mac80211/key.h b/net/mac80211/key.h index 7d4e31f037d..7cff0d3a519 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h | |||
@@ -30,8 +30,6 @@ | |||
30 | #define TKIP_ICV_LEN 4 | 30 | #define TKIP_ICV_LEN 4 |
31 | #define CMAC_PN_LEN 6 | 31 | #define CMAC_PN_LEN 6 |
32 | 32 | ||
33 | #define NUM_RX_DATA_QUEUES 16 | ||
34 | |||
35 | struct ieee80211_local; | 33 | struct ieee80211_local; |
36 | struct ieee80211_sub_if_data; | 34 | struct ieee80211_sub_if_data; |
37 | struct sta_info; | 35 | struct sta_info; |
@@ -82,17 +80,17 @@ struct ieee80211_key { | |||
82 | struct tkip_ctx tx; | 80 | struct tkip_ctx tx; |
83 | 81 | ||
84 | /* last received RSC */ | 82 | /* last received RSC */ |
85 | struct tkip_ctx rx[NUM_RX_DATA_QUEUES]; | 83 | struct tkip_ctx rx[IEEE80211_NUM_TIDS]; |
86 | } tkip; | 84 | } tkip; |
87 | struct { | 85 | struct { |
88 | atomic64_t tx_pn; | 86 | atomic64_t tx_pn; |
89 | /* | 87 | /* |
90 | * Last received packet number. The first | 88 | * Last received packet number. The first |
91 | * NUM_RX_DATA_QUEUES counters are used with Data | 89 | * IEEE80211_NUM_TIDS counters are used with Data |
92 | * frames and the last counter is used with Robust | 90 | * frames and the last counter is used with Robust |
93 | * Management frames. | 91 | * Management frames. |
94 | */ | 92 | */ |
95 | u8 rx_pn[NUM_RX_DATA_QUEUES + 1][CCMP_PN_LEN]; | 93 | u8 rx_pn[IEEE80211_NUM_TIDS + 1][CCMP_PN_LEN]; |
96 | struct crypto_cipher *tfm; | 94 | struct crypto_cipher *tfm; |
97 | u32 replays; /* dot11RSNAStatsCCMPReplays */ | 95 | u32 replays; /* dot11RSNAStatsCCMPReplays */ |
98 | } ccmp; | 96 | } ccmp; |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index d6e43b08d62..f5e4c1f24bf 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -95,11 +95,13 @@ static void ieee80211_reconfig_filter(struct work_struct *work) | |||
95 | 95 | ||
96 | static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local) | 96 | static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local) |
97 | { | 97 | { |
98 | struct ieee80211_sub_if_data *sdata; | ||
98 | struct ieee80211_channel *chan; | 99 | struct ieee80211_channel *chan; |
99 | u32 changed = 0; | 100 | u32 changed = 0; |
100 | int power; | 101 | int power; |
101 | enum nl80211_channel_type channel_type; | 102 | enum nl80211_channel_type channel_type; |
102 | u32 offchannel_flag; | 103 | u32 offchannel_flag; |
104 | bool scanning = false; | ||
103 | 105 | ||
104 | offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; | 106 | offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; |
105 | if (local->scan_channel) { | 107 | if (local->scan_channel) { |
@@ -113,7 +115,7 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local) | |||
113 | channel_type = NL80211_CHAN_NO_HT; | 115 | channel_type = NL80211_CHAN_NO_HT; |
114 | } else if (local->tmp_channel) { | 116 | } else if (local->tmp_channel) { |
115 | chan = local->tmp_channel; | 117 | chan = local->tmp_channel; |
116 | channel_type = local->tmp_channel_type; | 118 | channel_type = NL80211_CHAN_NO_HT; |
117 | } else { | 119 | } else { |
118 | chan = local->_oper_channel; | 120 | chan = local->_oper_channel; |
119 | channel_type = local->_oper_channel_type; | 121 | channel_type = local->_oper_channel_type; |
@@ -146,16 +148,18 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local) | |||
146 | changed |= IEEE80211_CONF_CHANGE_SMPS; | 148 | changed |= IEEE80211_CONF_CHANGE_SMPS; |
147 | } | 149 | } |
148 | 150 | ||
149 | if (test_bit(SCAN_SW_SCANNING, &local->scanning) || | 151 | scanning = test_bit(SCAN_SW_SCANNING, &local->scanning) || |
150 | test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning) || | 152 | test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning) || |
151 | test_bit(SCAN_HW_SCANNING, &local->scanning) || | 153 | test_bit(SCAN_HW_SCANNING, &local->scanning); |
152 | !local->ap_power_level) | 154 | power = chan->max_power; |
153 | power = chan->max_power; | ||
154 | else | ||
155 | power = min(chan->max_power, local->ap_power_level); | ||
156 | 155 | ||
157 | if (local->user_power_level >= 0) | 156 | rcu_read_lock(); |
158 | power = min(power, local->user_power_level); | 157 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
158 | if (!rcu_access_pointer(sdata->vif.chanctx_conf)) | ||
159 | continue; | ||
160 | power = min(power, sdata->vif.bss_conf.txpower); | ||
161 | } | ||
162 | rcu_read_unlock(); | ||
159 | 163 | ||
160 | if (local->hw.conf.power_level != power) { | 164 | if (local->hw.conf.power_level != power) { |
161 | changed |= IEEE80211_CONF_CHANGE_POWER; | 165 | changed |= IEEE80211_CONF_CHANGE_POWER; |
@@ -600,7 +604,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
600 | 604 | ||
601 | wiphy->features |= NL80211_FEATURE_SK_TX_STATUS | | 605 | wiphy->features |= NL80211_FEATURE_SK_TX_STATUS | |
602 | NL80211_FEATURE_SAE | | 606 | NL80211_FEATURE_SAE | |
603 | NL80211_FEATURE_HT_IBSS; | 607 | NL80211_FEATURE_HT_IBSS | |
608 | NL80211_FEATURE_VIF_TXPOWER; | ||
604 | 609 | ||
605 | if (!ops->hw_scan) | 610 | if (!ops->hw_scan) |
606 | wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN | | 611 | wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN | |
@@ -633,7 +638,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
633 | local->hw.radiotap_mcs_details = IEEE80211_RADIOTAP_MCS_HAVE_MCS | | 638 | local->hw.radiotap_mcs_details = IEEE80211_RADIOTAP_MCS_HAVE_MCS | |
634 | IEEE80211_RADIOTAP_MCS_HAVE_GI | | 639 | IEEE80211_RADIOTAP_MCS_HAVE_GI | |
635 | IEEE80211_RADIOTAP_MCS_HAVE_BW; | 640 | IEEE80211_RADIOTAP_MCS_HAVE_BW; |
636 | local->user_power_level = -1; | 641 | local->user_power_level = IEEE80211_UNSET_POWER_LEVEL; |
637 | wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask; | 642 | wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask; |
638 | 643 | ||
639 | INIT_LIST_HEAD(&local->interfaces); | 644 | INIT_LIST_HEAD(&local->interfaces); |
@@ -793,10 +798,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
793 | local->_oper_channel = &sband->channels[0]; | 798 | local->_oper_channel = &sband->channels[0]; |
794 | local->hw.conf.channel_type = NL80211_CHAN_NO_HT; | 799 | local->hw.conf.channel_type = NL80211_CHAN_NO_HT; |
795 | } | 800 | } |
796 | if (!local->monitor_channel) { | 801 | cfg80211_chandef_create(&local->monitor_chandef, |
797 | local->monitor_channel = &sband->channels[0]; | 802 | &sband->channels[0], |
798 | local->monitor_channel_type = NL80211_CHAN_NO_HT; | 803 | NL80211_CHAN_NO_HT); |
799 | } | ||
800 | channels += sband->n_channels; | 804 | channels += sband->n_channels; |
801 | 805 | ||
802 | if (max_bitrates < sband->n_bitrates) | 806 | if (max_bitrates < sband->n_bitrates) |
@@ -879,10 +883,22 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
879 | if (supp_ht) | 883 | if (supp_ht) |
880 | local->scan_ies_len += 2 + sizeof(struct ieee80211_ht_cap); | 884 | local->scan_ies_len += 2 + sizeof(struct ieee80211_ht_cap); |
881 | 885 | ||
882 | if (supp_vht) | 886 | if (supp_vht) { |
883 | local->scan_ies_len += | 887 | local->scan_ies_len += |
884 | 2 + sizeof(struct ieee80211_vht_cap); | 888 | 2 + sizeof(struct ieee80211_vht_cap); |
885 | 889 | ||
890 | /* | ||
891 | * (for now at least), drivers wanting to use VHT must | ||
892 | * support channel contexts, as they contain all the | ||
893 | * necessary VHT information and the global hw config | ||
894 | * doesn't (yet) | ||
895 | */ | ||
896 | if (WARN_ON(!local->use_chanctx)) { | ||
897 | result = -EINVAL; | ||
898 | goto fail_wiphy_register; | ||
899 | } | ||
900 | } | ||
901 | |||
886 | if (!local->ops->hw_scan) { | 902 | if (!local->ops->hw_scan) { |
887 | /* For hw_scan, driver needs to set these up. */ | 903 | /* For hw_scan, driver needs to set these up. */ |
888 | local->hw.wiphy->max_scan_ssids = 4; | 904 | local->hw.wiphy->max_scan_ssids = 4; |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index a350cab4b33..1bf03f9ff3b 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -76,7 +76,7 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata, | |||
76 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 76 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
77 | struct ieee80211_local *local = sdata->local; | 77 | struct ieee80211_local *local = sdata->local; |
78 | u32 basic_rates = 0; | 78 | u32 basic_rates = 0; |
79 | enum nl80211_channel_type sta_channel_type = NL80211_CHAN_NO_HT; | 79 | struct cfg80211_chan_def sta_chan_def; |
80 | 80 | ||
81 | /* | 81 | /* |
82 | * As support for each feature is added, check for matching | 82 | * As support for each feature is added, check for matching |
@@ -103,17 +103,11 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata, | |||
103 | if (sdata->vif.bss_conf.basic_rates != basic_rates) | 103 | if (sdata->vif.bss_conf.basic_rates != basic_rates) |
104 | goto mismatch; | 104 | goto mismatch; |
105 | 105 | ||
106 | if (ie->ht_operation) | 106 | ieee80211_ht_oper_to_chandef(sdata->vif.bss_conf.chandef.chan, |
107 | sta_channel_type = | 107 | ie->ht_operation, &sta_chan_def); |
108 | ieee80211_ht_oper_to_channel_type(ie->ht_operation); | 108 | |
109 | 109 | if (!cfg80211_chandef_compatible(&sdata->vif.bss_conf.chandef, | |
110 | /* Disallow HT40+/- mismatch */ | 110 | &sta_chan_def)) |
111 | if (ie->ht_operation && | ||
112 | (sdata->vif.bss_conf.channel_type == NL80211_CHAN_HT40MINUS || | ||
113 | sdata->vif.bss_conf.channel_type == NL80211_CHAN_HT40PLUS) && | ||
114 | (sta_channel_type == NL80211_CHAN_HT40MINUS || | ||
115 | sta_channel_type == NL80211_CHAN_HT40PLUS) && | ||
116 | sdata->vif.bss_conf.channel_type != sta_channel_type) | ||
117 | goto mismatch; | 111 | goto mismatch; |
118 | 112 | ||
119 | return true; | 113 | return true; |
@@ -129,7 +123,7 @@ mismatch: | |||
129 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie) | 123 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie) |
130 | { | 124 | { |
131 | return (ie->mesh_config->meshconf_cap & | 125 | return (ie->mesh_config->meshconf_cap & |
132 | MESHCONF_CAPAB_ACCEPT_PLINKS) != 0; | 126 | IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS) != 0; |
133 | } | 127 | } |
134 | 128 | ||
135 | /** | 129 | /** |
@@ -269,11 +263,11 @@ mesh_add_meshconf_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) | |||
269 | neighbors = (neighbors > 15) ? 15 : neighbors; | 263 | neighbors = (neighbors > 15) ? 15 : neighbors; |
270 | *pos++ = neighbors << 1; | 264 | *pos++ = neighbors << 1; |
271 | /* Mesh capability */ | 265 | /* Mesh capability */ |
272 | *pos = MESHCONF_CAPAB_FORWARDING; | 266 | *pos = IEEE80211_MESHCONF_CAPAB_FORWARDING; |
273 | *pos |= ifmsh->accepting_plinks ? | 267 | *pos |= ifmsh->accepting_plinks ? |
274 | MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; | 268 | IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; |
275 | *pos++ |= ifmsh->adjusting_tbtt ? | 269 | *pos++ |= ifmsh->adjusting_tbtt ? |
276 | MESHCONF_CAPAB_TBTT_ADJUSTING : 0x00; | 270 | IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING : 0x00; |
277 | *pos++ = 0x00; | 271 | *pos++ = 0x00; |
278 | 272 | ||
279 | return 0; | 273 | return 0; |
@@ -368,7 +362,7 @@ int mesh_add_ds_params_ie(struct sk_buff *skb, | |||
368 | rcu_read_unlock(); | 362 | rcu_read_unlock(); |
369 | return -EINVAL; | 363 | return -EINVAL; |
370 | } | 364 | } |
371 | chan = chanctx_conf->channel; | 365 | chan = chanctx_conf->def.chan; |
372 | rcu_read_unlock(); | 366 | rcu_read_unlock(); |
373 | 367 | ||
374 | sband = local->hw.wiphy->bands[chan->band]; | 368 | sband = local->hw.wiphy->bands[chan->band]; |
@@ -392,7 +386,7 @@ int mesh_add_ht_cap_ie(struct sk_buff *skb, | |||
392 | 386 | ||
393 | sband = local->hw.wiphy->bands[band]; | 387 | sband = local->hw.wiphy->bands[band]; |
394 | if (!sband->ht_cap.ht_supported || | 388 | if (!sband->ht_cap.ht_supported || |
395 | sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) | 389 | sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT) |
396 | return 0; | 390 | return 0; |
397 | 391 | ||
398 | if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_cap)) | 392 | if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_cap)) |
@@ -411,7 +405,7 @@ int mesh_add_ht_oper_ie(struct sk_buff *skb, | |||
411 | struct ieee80211_chanctx_conf *chanctx_conf; | 405 | struct ieee80211_chanctx_conf *chanctx_conf; |
412 | struct ieee80211_channel *channel; | 406 | struct ieee80211_channel *channel; |
413 | enum nl80211_channel_type channel_type = | 407 | enum nl80211_channel_type channel_type = |
414 | sdata->vif.bss_conf.channel_type; | 408 | cfg80211_get_chandef_type(&sdata->vif.bss_conf.chandef); |
415 | struct ieee80211_supported_band *sband; | 409 | struct ieee80211_supported_band *sband; |
416 | struct ieee80211_sta_ht_cap *ht_cap; | 410 | struct ieee80211_sta_ht_cap *ht_cap; |
417 | u8 *pos; | 411 | u8 *pos; |
@@ -422,7 +416,7 @@ int mesh_add_ht_oper_ie(struct sk_buff *skb, | |||
422 | rcu_read_unlock(); | 416 | rcu_read_unlock(); |
423 | return -EINVAL; | 417 | return -EINVAL; |
424 | } | 418 | } |
425 | channel = chanctx_conf->channel; | 419 | channel = chanctx_conf->def.chan; |
426 | rcu_read_unlock(); | 420 | rcu_read_unlock(); |
427 | 421 | ||
428 | sband = local->hw.wiphy->bands[channel->band]; | 422 | sband = local->hw.wiphy->bands[channel->band]; |
@@ -435,7 +429,7 @@ int mesh_add_ht_oper_ie(struct sk_buff *skb, | |||
435 | return -ENOMEM; | 429 | return -ENOMEM; |
436 | 430 | ||
437 | pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_operation)); | 431 | pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_operation)); |
438 | ieee80211_ie_build_ht_oper(pos, ht_cap, channel, channel_type, | 432 | ieee80211_ie_build_ht_oper(pos, ht_cap, &sdata->vif.bss_conf.chandef, |
439 | sdata->vif.bss_conf.ht_operation_mode); | 433 | sdata->vif.bss_conf.ht_operation_mode); |
440 | 434 | ||
441 | return 0; | 435 | return 0; |
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 9285f3f67e6..7c9215fb2ac 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -19,20 +19,6 @@ | |||
19 | /* Data structures */ | 19 | /* Data structures */ |
20 | 20 | ||
21 | /** | 21 | /** |
22 | * enum mesh_config_capab_flags - mesh config IE capability flags | ||
23 | * | ||
24 | * @MESHCONF_CAPAB_ACCEPT_PLINKS: STA is willing to establish | ||
25 | * additional mesh peerings with other mesh STAs | ||
26 | * @MESHCONF_CAPAB_FORWARDING: the STA forwards MSDUs | ||
27 | * @MESHCONF_CAPAB_TBTT_ADJUSTING: TBTT adjustment procedure is ongoing | ||
28 | */ | ||
29 | enum mesh_config_capab_flags { | ||
30 | MESHCONF_CAPAB_ACCEPT_PLINKS = BIT(0), | ||
31 | MESHCONF_CAPAB_FORWARDING = BIT(3), | ||
32 | MESHCONF_CAPAB_TBTT_ADJUSTING = BIT(5), | ||
33 | }; | ||
34 | |||
35 | /** | ||
36 | * enum mesh_path_flags - mac80211 mesh path flags | 22 | * enum mesh_path_flags - mac80211 mesh path flags |
37 | * | 23 | * |
38 | * | 24 | * |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 234fe755968..ca52dfdd537 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -19,12 +19,6 @@ | |||
19 | #define mod_plink_timer(s, t) (mod_timer(&s->plink_timer, \ | 19 | #define mod_plink_timer(s, t) (mod_timer(&s->plink_timer, \ |
20 | jiffies + HZ * t / 1000)) | 20 | jiffies + HZ * t / 1000)) |
21 | 21 | ||
22 | #define dot11MeshMaxRetries(s) (s->u.mesh.mshcfg.dot11MeshMaxRetries) | ||
23 | #define dot11MeshRetryTimeout(s) (s->u.mesh.mshcfg.dot11MeshRetryTimeout) | ||
24 | #define dot11MeshConfirmTimeout(s) (s->u.mesh.mshcfg.dot11MeshConfirmTimeout) | ||
25 | #define dot11MeshHoldingTimeout(s) (s->u.mesh.mshcfg.dot11MeshHoldingTimeout) | ||
26 | #define dot11MeshMaxPeerLinks(s) (s->u.mesh.mshcfg.dot11MeshMaxPeerLinks) | ||
27 | |||
28 | /* We only need a valid sta if user configured a minimum rssi_threshold. */ | 22 | /* We only need a valid sta if user configured a minimum rssi_threshold. */ |
29 | #define rssi_threshold_check(sta, sdata) \ | 23 | #define rssi_threshold_check(sta, sdata) \ |
30 | (sdata->u.mesh.mshcfg.rssi_threshold == 0 ||\ | 24 | (sdata->u.mesh.mshcfg.rssi_threshold == 0 ||\ |
@@ -117,7 +111,7 @@ static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata) | |||
117 | u16 ht_opmode; | 111 | u16 ht_opmode; |
118 | bool non_ht_sta = false, ht20_sta = false; | 112 | bool non_ht_sta = false, ht20_sta = false; |
119 | 113 | ||
120 | if (sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) | 114 | if (sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT) |
121 | return 0; | 115 | return 0; |
122 | 116 | ||
123 | rcu_read_lock(); | 117 | rcu_read_lock(); |
@@ -126,14 +120,14 @@ static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata) | |||
126 | sta->plink_state != NL80211_PLINK_ESTAB) | 120 | sta->plink_state != NL80211_PLINK_ESTAB) |
127 | continue; | 121 | continue; |
128 | 122 | ||
129 | switch (sta->ch_type) { | 123 | switch (sta->ch_width) { |
130 | case NL80211_CHAN_NO_HT: | 124 | case NL80211_CHAN_WIDTH_20_NOHT: |
131 | mpl_dbg(sdata, | 125 | mpl_dbg(sdata, |
132 | "mesh_plink %pM: nonHT sta (%pM) is present\n", | 126 | "mesh_plink %pM: nonHT sta (%pM) is present\n", |
133 | sdata->vif.addr, sta->sta.addr); | 127 | sdata->vif.addr, sta->sta.addr); |
134 | non_ht_sta = true; | 128 | non_ht_sta = true; |
135 | goto out; | 129 | goto out; |
136 | case NL80211_CHAN_HT20: | 130 | case NL80211_CHAN_WIDTH_20: |
137 | mpl_dbg(sdata, | 131 | mpl_dbg(sdata, |
138 | "mesh_plink %pM: HT20 sta (%pM) is present\n", | 132 | "mesh_plink %pM: HT20 sta (%pM) is present\n", |
139 | sdata->vif.addr, sta->sta.addr); | 133 | sdata->vif.addr, sta->sta.addr); |
@@ -148,7 +142,7 @@ out: | |||
148 | if (non_ht_sta) | 142 | if (non_ht_sta) |
149 | ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED; | 143 | ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED; |
150 | else if (ht20_sta && | 144 | else if (ht20_sta && |
151 | sdata->vif.bss_conf.channel_type > NL80211_CHAN_HT20) | 145 | sdata->vif.bss_conf.chandef.width > NL80211_CHAN_WIDTH_20) |
152 | ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_20MHZ; | 146 | ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_20MHZ; |
153 | else | 147 | else |
154 | ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONE; | 148 | ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONE; |
@@ -378,7 +372,7 @@ static struct sta_info *mesh_peer_init(struct ieee80211_sub_if_data *sdata, | |||
378 | 372 | ||
379 | sta->sta.supp_rates[band] = rates; | 373 | sta->sta.supp_rates[band] = rates; |
380 | if (elems->ht_cap_elem && | 374 | if (elems->ht_cap_elem && |
381 | sdata->vif.bss_conf.channel_type != NL80211_CHAN_NO_HT) | 375 | sdata->vif.bss_conf.chandef.width != NL80211_CHAN_WIDTH_20_NOHT) |
382 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, | 376 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, |
383 | elems->ht_cap_elem, | 377 | elems->ht_cap_elem, |
384 | &sta->sta.ht_cap); | 378 | &sta->sta.ht_cap); |
@@ -386,12 +380,15 @@ static struct sta_info *mesh_peer_init(struct ieee80211_sub_if_data *sdata, | |||
386 | memset(&sta->sta.ht_cap, 0, sizeof(sta->sta.ht_cap)); | 380 | memset(&sta->sta.ht_cap, 0, sizeof(sta->sta.ht_cap)); |
387 | 381 | ||
388 | if (elems->ht_operation) { | 382 | if (elems->ht_operation) { |
383 | struct cfg80211_chan_def chandef; | ||
384 | |||
389 | if (!(elems->ht_operation->ht_param & | 385 | if (!(elems->ht_operation->ht_param & |
390 | IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) | 386 | IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) |
391 | sta->sta.ht_cap.cap &= | 387 | sta->sta.ht_cap.cap &= |
392 | ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | 388 | ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; |
393 | sta->ch_type = | 389 | ieee80211_ht_oper_to_chandef(sdata->vif.bss_conf.chandef.chan, |
394 | ieee80211_ht_oper_to_channel_type(elems->ht_operation); | 390 | elems->ht_operation, &chandef); |
391 | sta->ch_width = chandef.width; | ||
395 | } | 392 | } |
396 | 393 | ||
397 | rate_control_rate_init(sta); | 394 | rate_control_rate_init(sta); |
@@ -430,6 +427,7 @@ static void mesh_plink_timer(unsigned long data) | |||
430 | struct sta_info *sta; | 427 | struct sta_info *sta; |
431 | __le16 llid, plid, reason; | 428 | __le16 llid, plid, reason; |
432 | struct ieee80211_sub_if_data *sdata; | 429 | struct ieee80211_sub_if_data *sdata; |
430 | struct mesh_config *mshcfg; | ||
433 | 431 | ||
434 | /* | 432 | /* |
435 | * This STA is valid because sta_info_destroy() will | 433 | * This STA is valid because sta_info_destroy() will |
@@ -456,12 +454,13 @@ static void mesh_plink_timer(unsigned long data) | |||
456 | llid = sta->llid; | 454 | llid = sta->llid; |
457 | plid = sta->plid; | 455 | plid = sta->plid; |
458 | sdata = sta->sdata; | 456 | sdata = sta->sdata; |
457 | mshcfg = &sdata->u.mesh.mshcfg; | ||
459 | 458 | ||
460 | switch (sta->plink_state) { | 459 | switch (sta->plink_state) { |
461 | case NL80211_PLINK_OPN_RCVD: | 460 | case NL80211_PLINK_OPN_RCVD: |
462 | case NL80211_PLINK_OPN_SNT: | 461 | case NL80211_PLINK_OPN_SNT: |
463 | /* retry timer */ | 462 | /* retry timer */ |
464 | if (sta->plink_retries < dot11MeshMaxRetries(sdata)) { | 463 | if (sta->plink_retries < mshcfg->dot11MeshMaxRetries) { |
465 | u32 rand; | 464 | u32 rand; |
466 | mpl_dbg(sta->sdata, | 465 | mpl_dbg(sta->sdata, |
467 | "Mesh plink for %pM (retry, timeout): %d %d\n", | 466 | "Mesh plink for %pM (retry, timeout): %d %d\n", |
@@ -484,7 +483,7 @@ static void mesh_plink_timer(unsigned long data) | |||
484 | if (!reason) | 483 | if (!reason) |
485 | reason = cpu_to_le16(WLAN_REASON_MESH_CONFIRM_TIMEOUT); | 484 | reason = cpu_to_le16(WLAN_REASON_MESH_CONFIRM_TIMEOUT); |
486 | sta->plink_state = NL80211_PLINK_HOLDING; | 485 | sta->plink_state = NL80211_PLINK_HOLDING; |
487 | mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); | 486 | mod_plink_timer(sta, mshcfg->dot11MeshHoldingTimeout); |
488 | spin_unlock_bh(&sta->lock); | 487 | spin_unlock_bh(&sta->lock); |
489 | mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, | 488 | mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, |
490 | sta->sta.addr, llid, plid, reason); | 489 | sta->sta.addr, llid, plid, reason); |
@@ -543,7 +542,7 @@ int mesh_plink_open(struct sta_info *sta) | |||
543 | return -EBUSY; | 542 | return -EBUSY; |
544 | } | 543 | } |
545 | sta->plink_state = NL80211_PLINK_OPN_SNT; | 544 | sta->plink_state = NL80211_PLINK_OPN_SNT; |
546 | mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata)); | 545 | mesh_plink_timer_set(sta, sdata->u.mesh.mshcfg.dot11MeshRetryTimeout); |
547 | spin_unlock_bh(&sta->lock); | 546 | spin_unlock_bh(&sta->lock); |
548 | mpl_dbg(sdata, | 547 | mpl_dbg(sdata, |
549 | "Mesh plink: starting establishment with %pM\n", | 548 | "Mesh plink: starting establishment with %pM\n", |
@@ -570,6 +569,7 @@ void mesh_plink_block(struct sta_info *sta) | |||
570 | void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, | 569 | void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, |
571 | size_t len, struct ieee80211_rx_status *rx_status) | 570 | size_t len, struct ieee80211_rx_status *rx_status) |
572 | { | 571 | { |
572 | struct mesh_config *mshcfg = &sdata->u.mesh.mshcfg; | ||
573 | struct ieee802_11_elems elems; | 573 | struct ieee802_11_elems elems; |
574 | struct sta_info *sta; | 574 | struct sta_info *sta; |
575 | enum plink_event event; | 575 | enum plink_event event; |
@@ -777,7 +777,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
777 | sta->plid = plid; | 777 | sta->plid = plid; |
778 | get_random_bytes(&llid, 2); | 778 | get_random_bytes(&llid, 2); |
779 | sta->llid = llid; | 779 | sta->llid = llid; |
780 | mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata)); | 780 | mesh_plink_timer_set(sta, |
781 | mshcfg->dot11MeshRetryTimeout); | ||
781 | spin_unlock_bh(&sta->lock); | 782 | spin_unlock_bh(&sta->lock); |
782 | mesh_plink_frame_tx(sdata, | 783 | mesh_plink_frame_tx(sdata, |
783 | WLAN_SP_MESH_PEERING_OPEN, | 784 | WLAN_SP_MESH_PEERING_OPEN, |
@@ -803,7 +804,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
803 | sta->reason = reason; | 804 | sta->reason = reason; |
804 | sta->plink_state = NL80211_PLINK_HOLDING; | 805 | sta->plink_state = NL80211_PLINK_HOLDING; |
805 | if (!mod_plink_timer(sta, | 806 | if (!mod_plink_timer(sta, |
806 | dot11MeshHoldingTimeout(sdata))) | 807 | mshcfg->dot11MeshHoldingTimeout)) |
807 | sta->ignore_plink_timer = true; | 808 | sta->ignore_plink_timer = true; |
808 | 809 | ||
809 | llid = sta->llid; | 810 | llid = sta->llid; |
@@ -825,7 +826,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
825 | case CNF_ACPT: | 826 | case CNF_ACPT: |
826 | sta->plink_state = NL80211_PLINK_CNF_RCVD; | 827 | sta->plink_state = NL80211_PLINK_CNF_RCVD; |
827 | if (!mod_plink_timer(sta, | 828 | if (!mod_plink_timer(sta, |
828 | dot11MeshConfirmTimeout(sdata))) | 829 | mshcfg->dot11MeshConfirmTimeout)) |
829 | sta->ignore_plink_timer = true; | 830 | sta->ignore_plink_timer = true; |
830 | 831 | ||
831 | spin_unlock_bh(&sta->lock); | 832 | spin_unlock_bh(&sta->lock); |
@@ -847,7 +848,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
847 | sta->reason = reason; | 848 | sta->reason = reason; |
848 | sta->plink_state = NL80211_PLINK_HOLDING; | 849 | sta->plink_state = NL80211_PLINK_HOLDING; |
849 | if (!mod_plink_timer(sta, | 850 | if (!mod_plink_timer(sta, |
850 | dot11MeshHoldingTimeout(sdata))) | 851 | mshcfg->dot11MeshHoldingTimeout)) |
851 | sta->ignore_plink_timer = true; | 852 | sta->ignore_plink_timer = true; |
852 | 853 | ||
853 | llid = sta->llid; | 854 | llid = sta->llid; |
@@ -888,7 +889,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
888 | sta->reason = reason; | 889 | sta->reason = reason; |
889 | sta->plink_state = NL80211_PLINK_HOLDING; | 890 | sta->plink_state = NL80211_PLINK_HOLDING; |
890 | if (!mod_plink_timer(sta, | 891 | if (!mod_plink_timer(sta, |
891 | dot11MeshHoldingTimeout(sdata))) | 892 | mshcfg->dot11MeshHoldingTimeout)) |
892 | sta->ignore_plink_timer = true; | 893 | sta->ignore_plink_timer = true; |
893 | 894 | ||
894 | llid = sta->llid; | 895 | llid = sta->llid; |
@@ -923,7 +924,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
923 | changed |= __mesh_plink_deactivate(sta); | 924 | changed |= __mesh_plink_deactivate(sta); |
924 | sta->plink_state = NL80211_PLINK_HOLDING; | 925 | sta->plink_state = NL80211_PLINK_HOLDING; |
925 | llid = sta->llid; | 926 | llid = sta->llid; |
926 | mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); | 927 | mod_plink_timer(sta, mshcfg->dot11MeshHoldingTimeout); |
927 | spin_unlock_bh(&sta->lock); | 928 | spin_unlock_bh(&sta->lock); |
928 | changed |= mesh_set_ht_prot_mode(sdata); | 929 | changed |= mesh_set_ht_prot_mode(sdata); |
929 | mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, | 930 | mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, |
diff --git a/net/mac80211/mesh_sync.c b/net/mac80211/mesh_sync.c index 407c8705e10..0f40086cce1 100644 --- a/net/mac80211/mesh_sync.c +++ b/net/mac80211/mesh_sync.c | |||
@@ -43,7 +43,7 @@ struct sync_method { | |||
43 | static bool mesh_peer_tbtt_adjusting(struct ieee802_11_elems *ie) | 43 | static bool mesh_peer_tbtt_adjusting(struct ieee802_11_elems *ie) |
44 | { | 44 | { |
45 | return (ie->mesh_config->meshconf_cap & | 45 | return (ie->mesh_config->meshconf_cap & |
46 | MESHCONF_CAPAB_TBTT_ADJUSTING) != 0; | 46 | IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING) != 0; |
47 | } | 47 | } |
48 | 48 | ||
49 | void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata) | 49 | void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata) |
@@ -116,43 +116,13 @@ static void mesh_sync_offset_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | |||
116 | goto no_sync; | 116 | goto no_sync; |
117 | } | 117 | } |
118 | 118 | ||
119 | if (rx_status->flag & RX_FLAG_MACTIME_MPDU && rx_status->mactime) { | 119 | if (ieee80211_have_rx_timestamp(rx_status)) |
120 | /* | 120 | /* time when timestamp field was received */ |
121 | * The mactime is defined as the time the first data symbol | 121 | t_r = ieee80211_calculate_rx_timestamp(local, rx_status, |
122 | * of the frame hits the PHY, and the timestamp of the beacon | 122 | 24 + 12 + |
123 | * is defined as "the time that the data symbol containing the | 123 | elems->total_len + |
124 | * first bit of the timestamp is transmitted to the PHY plus | 124 | FCS_LEN, |
125 | * the transmitting STA's delays through its local PHY from the | 125 | 24); |
126 | * MAC-PHY interface to its interface with the WM" (802.11 | ||
127 | * 11.1.2) | ||
128 | * | ||
129 | * T_r, in 13.13.2.2.2, is just defined as "the frame reception | ||
130 | * time" but we unless we interpret that time to be the same | ||
131 | * time of the beacon timestamp, the offset calculation will be | ||
132 | * off. Below we adjust t_r to be "the time at which the first | ||
133 | * symbol of the timestamp element in the beacon is received". | ||
134 | * This correction depends on the rate. | ||
135 | * | ||
136 | * Based on similar code in ibss.c | ||
137 | */ | ||
138 | int rate; | ||
139 | |||
140 | if (rx_status->flag & RX_FLAG_HT) { | ||
141 | /* TODO: | ||
142 | * In principle there could be HT-beacons (Dual Beacon | ||
143 | * HT Operation options), but for now ignore them and | ||
144 | * just use the primary (i.e. non-HT) beacons for | ||
145 | * synchronization. | ||
146 | * */ | ||
147 | goto no_sync; | ||
148 | } else | ||
149 | rate = local->hw.wiphy->bands[rx_status->band]-> | ||
150 | bitrates[rx_status->rate_idx].bitrate; | ||
151 | |||
152 | /* 24 bytes of header * 8 bits/byte * | ||
153 | * 10*(100 Kbps)/Mbps / rate (100 Kbps)*/ | ||
154 | t_r = rx_status->mactime + (24 * 8 * 10 / rate); | ||
155 | } | ||
156 | 126 | ||
157 | /* Timing offset calculation (see 13.13.2.2.2) */ | 127 | /* Timing offset calculation (see 13.13.2.2.2) */ |
158 | t_t = le64_to_cpu(mgmt->u.beacon.timestamp); | 128 | t_t = le64_to_cpu(mgmt->u.beacon.timestamp); |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 1d1fdf0791f..d2a4f78b4b0 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -191,17 +191,19 @@ static u32 ieee80211_config_ht_tx(struct ieee80211_sub_if_data *sdata, | |||
191 | rcu_read_unlock(); | 191 | rcu_read_unlock(); |
192 | return 0; | 192 | return 0; |
193 | } | 193 | } |
194 | chan = chanctx_conf->channel; | 194 | chan = chanctx_conf->def.chan; |
195 | rcu_read_unlock(); | 195 | rcu_read_unlock(); |
196 | sband = local->hw.wiphy->bands[chan->band]; | 196 | sband = local->hw.wiphy->bands[chan->band]; |
197 | 197 | ||
198 | switch (sdata->vif.bss_conf.channel_type) { | 198 | switch (sdata->vif.bss_conf.chandef.width) { |
199 | case NL80211_CHAN_HT40PLUS: | 199 | case NL80211_CHAN_WIDTH_40: |
200 | if (chan->flags & IEEE80211_CHAN_NO_HT40PLUS) | 200 | if (sdata->vif.bss_conf.chandef.chan->center_freq > |
201 | sdata->vif.bss_conf.chandef.center_freq1 && | ||
202 | chan->flags & IEEE80211_CHAN_NO_HT40PLUS) | ||
201 | disable_40 = true; | 203 | disable_40 = true; |
202 | break; | 204 | if (sdata->vif.bss_conf.chandef.chan->center_freq < |
203 | case NL80211_CHAN_HT40MINUS: | 205 | sdata->vif.bss_conf.chandef.center_freq1 && |
204 | if (chan->flags & IEEE80211_CHAN_NO_HT40MINUS) | 206 | chan->flags & IEEE80211_CHAN_NO_HT40MINUS) |
205 | disable_40 = true; | 207 | disable_40 = true; |
206 | break; | 208 | break; |
207 | default: | 209 | default: |
@@ -381,7 +383,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
381 | rcu_read_unlock(); | 383 | rcu_read_unlock(); |
382 | return; | 384 | return; |
383 | } | 385 | } |
384 | chan = chanctx_conf->channel; | 386 | chan = chanctx_conf->def.chan; |
385 | rcu_read_unlock(); | 387 | rcu_read_unlock(); |
386 | sband = local->hw.wiphy->bands[chan->band]; | 388 | sband = local->hw.wiphy->bands[chan->band]; |
387 | 389 | ||
@@ -541,7 +543,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
541 | offset = noffset; | 543 | offset = noffset; |
542 | } | 544 | } |
543 | 545 | ||
544 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) | 546 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) |
545 | ieee80211_add_ht_ie(sdata, skb, assoc_data->ap_ht_param, | 547 | ieee80211_add_ht_ie(sdata, skb, assoc_data->ap_ht_param, |
546 | sband, chan, sdata->smps_mode); | 548 | sband, chan, sdata->smps_mode); |
547 | 549 | ||
@@ -820,10 +822,10 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
820 | cbss->beacon_interval)); | 822 | cbss->beacon_interval)); |
821 | } | 823 | } |
822 | 824 | ||
823 | static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, | 825 | static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, |
824 | struct ieee80211_channel *channel, | 826 | struct ieee80211_channel *channel, |
825 | const u8 *country_ie, u8 country_ie_len, | 827 | const u8 *country_ie, u8 country_ie_len, |
826 | const u8 *pwr_constr_elem) | 828 | const u8 *pwr_constr_elem) |
827 | { | 829 | { |
828 | struct ieee80211_country_ie_triplet *triplet; | 830 | struct ieee80211_country_ie_triplet *triplet; |
829 | int chan = ieee80211_frequency_to_channel(channel->center_freq); | 831 | int chan = ieee80211_frequency_to_channel(channel->center_freq); |
@@ -832,7 +834,7 @@ static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, | |||
832 | 834 | ||
833 | /* Invalid IE */ | 835 | /* Invalid IE */ |
834 | if (country_ie_len % 2 || country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN) | 836 | if (country_ie_len % 2 || country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN) |
835 | return; | 837 | return 0; |
836 | 838 | ||
837 | triplet = (void *)(country_ie + 3); | 839 | triplet = (void *)(country_ie + 3); |
838 | country_ie_len -= 3; | 840 | country_ie_len -= 3; |
@@ -873,19 +875,21 @@ static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, | |||
873 | } | 875 | } |
874 | 876 | ||
875 | if (!have_chan_pwr) | 877 | if (!have_chan_pwr) |
876 | return; | 878 | return 0; |
877 | 879 | ||
878 | new_ap_level = max_t(int, 0, chan_pwr - *pwr_constr_elem); | 880 | new_ap_level = max_t(int, 0, chan_pwr - *pwr_constr_elem); |
879 | 881 | ||
880 | if (sdata->local->ap_power_level == new_ap_level) | 882 | if (sdata->ap_power_level == new_ap_level) |
881 | return; | 883 | return 0; |
882 | 884 | ||
883 | sdata_info(sdata, | 885 | sdata_info(sdata, |
884 | "Limiting TX power to %d (%d - %d) dBm as advertised by %pM\n", | 886 | "Limiting TX power to %d (%d - %d) dBm as advertised by %pM\n", |
885 | new_ap_level, chan_pwr, *pwr_constr_elem, | 887 | new_ap_level, chan_pwr, *pwr_constr_elem, |
886 | sdata->u.mgd.bssid); | 888 | sdata->u.mgd.bssid); |
887 | sdata->local->ap_power_level = new_ap_level; | 889 | sdata->ap_power_level = new_ap_level; |
888 | ieee80211_hw_config(sdata->local, 0); | 890 | if (__ieee80211_recalc_txpower(sdata)) |
891 | return BSS_CHANGED_TXPOWER; | ||
892 | return 0; | ||
889 | } | 893 | } |
890 | 894 | ||
891 | void ieee80211_enable_dyn_ps(struct ieee80211_vif *vif) | 895 | void ieee80211_enable_dyn_ps(struct ieee80211_vif *vif) |
@@ -1363,6 +1367,22 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
1363 | 1367 | ||
1364 | sdata->u.mgd.flags |= IEEE80211_STA_RESET_SIGNAL_AVE; | 1368 | sdata->u.mgd.flags |= IEEE80211_STA_RESET_SIGNAL_AVE; |
1365 | 1369 | ||
1370 | if (sdata->vif.p2p) { | ||
1371 | u8 noa[2]; | ||
1372 | int ret; | ||
1373 | |||
1374 | ret = cfg80211_get_p2p_attr(cbss->information_elements, | ||
1375 | cbss->len_information_elements, | ||
1376 | IEEE80211_P2P_ATTR_ABSENCE_NOTICE, | ||
1377 | noa, sizeof(noa)); | ||
1378 | if (ret >= 2) { | ||
1379 | bss_conf->p2p_oppps = noa[1] & 0x80; | ||
1380 | bss_conf->p2p_ctwindow = noa[1] & 0x7f; | ||
1381 | bss_info_changed |= BSS_CHANGED_P2P_PS; | ||
1382 | sdata->u.mgd.p2p_noa_index = noa[0]; | ||
1383 | } | ||
1384 | } | ||
1385 | |||
1366 | /* just to be sure */ | 1386 | /* just to be sure */ |
1367 | ieee80211_stop_poll(sdata); | 1387 | ieee80211_stop_poll(sdata); |
1368 | 1388 | ||
@@ -1485,11 +1505,14 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1485 | changed |= BSS_CHANGED_ASSOC; | 1505 | changed |= BSS_CHANGED_ASSOC; |
1486 | sdata->vif.bss_conf.assoc = false; | 1506 | sdata->vif.bss_conf.assoc = false; |
1487 | 1507 | ||
1508 | sdata->vif.bss_conf.p2p_ctwindow = 0; | ||
1509 | sdata->vif.bss_conf.p2p_oppps = false; | ||
1510 | |||
1488 | /* on the next assoc, re-program HT parameters */ | 1511 | /* on the next assoc, re-program HT parameters */ |
1489 | memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa)); | 1512 | memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa)); |
1490 | memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask)); | 1513 | memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask)); |
1491 | 1514 | ||
1492 | local->ap_power_level = 0; | 1515 | sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL; |
1493 | 1516 | ||
1494 | del_timer_sync(&local->dynamic_ps_timer); | 1517 | del_timer_sync(&local->dynamic_ps_timer); |
1495 | cancel_work_sync(&local->dynamic_ps_enable_work); | 1518 | cancel_work_sync(&local->dynamic_ps_enable_work); |
@@ -1507,8 +1530,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1507 | changed |= BSS_CHANGED_BSSID | BSS_CHANGED_HT; | 1530 | changed |= BSS_CHANGED_BSSID | BSS_CHANGED_HT; |
1508 | ieee80211_bss_info_change_notify(sdata, changed); | 1531 | ieee80211_bss_info_change_notify(sdata, changed); |
1509 | 1532 | ||
1510 | ieee80211_vif_release_channel(sdata); | ||
1511 | |||
1512 | /* disassociated - set to defaults now */ | 1533 | /* disassociated - set to defaults now */ |
1513 | ieee80211_set_wmm_default(sdata, false); | 1534 | ieee80211_set_wmm_default(sdata, false); |
1514 | 1535 | ||
@@ -1518,6 +1539,9 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1518 | del_timer_sync(&sdata->u.mgd.chswitch_timer); | 1539 | del_timer_sync(&sdata->u.mgd.chswitch_timer); |
1519 | 1540 | ||
1520 | sdata->u.mgd.timers_running = 0; | 1541 | sdata->u.mgd.timers_running = 0; |
1542 | |||
1543 | ifmgd->flags = 0; | ||
1544 | ieee80211_vif_release_channel(sdata); | ||
1521 | } | 1545 | } |
1522 | 1546 | ||
1523 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, | 1547 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, |
@@ -1843,6 +1867,7 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata, | |||
1843 | 1867 | ||
1844 | memset(sdata->u.mgd.bssid, 0, ETH_ALEN); | 1868 | memset(sdata->u.mgd.bssid, 0, ETH_ALEN); |
1845 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); | 1869 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); |
1870 | sdata->u.mgd.flags = 0; | ||
1846 | ieee80211_vif_release_channel(sdata); | 1871 | ieee80211_vif_release_channel(sdata); |
1847 | } | 1872 | } |
1848 | 1873 | ||
@@ -2085,6 +2110,7 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata, | |||
2085 | 2110 | ||
2086 | memset(sdata->u.mgd.bssid, 0, ETH_ALEN); | 2111 | memset(sdata->u.mgd.bssid, 0, ETH_ALEN); |
2087 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); | 2112 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); |
2113 | sdata->u.mgd.flags = 0; | ||
2088 | ieee80211_vif_release_channel(sdata); | 2114 | ieee80211_vif_release_channel(sdata); |
2089 | } | 2115 | } |
2090 | 2116 | ||
@@ -2149,7 +2175,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
2149 | 2175 | ||
2150 | sband = local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)]; | 2176 | sband = local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)]; |
2151 | 2177 | ||
2152 | if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) | 2178 | if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) |
2153 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, | 2179 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, |
2154 | elems.ht_cap_elem, &sta->sta.ht_cap); | 2180 | elems.ht_cap_elem, &sta->sta.ht_cap); |
2155 | 2181 | ||
@@ -2201,7 +2227,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
2201 | changed |= BSS_CHANGED_QOS; | 2227 | changed |= BSS_CHANGED_QOS; |
2202 | 2228 | ||
2203 | if (elems.ht_operation && elems.wmm_param && | 2229 | if (elems.ht_operation && elems.wmm_param && |
2204 | !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) | 2230 | !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) |
2205 | changed |= ieee80211_config_ht_tx(sdata, elems.ht_operation, | 2231 | changed |= ieee80211_config_ht_tx(sdata, elems.ht_operation, |
2206 | cbss->bssid, false); | 2232 | cbss->bssid, false); |
2207 | 2233 | ||
@@ -2452,11 +2478,11 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
2452 | return; | 2478 | return; |
2453 | } | 2479 | } |
2454 | 2480 | ||
2455 | if (rx_status->freq != chanctx_conf->channel->center_freq) { | 2481 | if (rx_status->freq != chanctx_conf->def.chan->center_freq) { |
2456 | rcu_read_unlock(); | 2482 | rcu_read_unlock(); |
2457 | return; | 2483 | return; |
2458 | } | 2484 | } |
2459 | chan = chanctx_conf->channel; | 2485 | chan = chanctx_conf->def.chan; |
2460 | rcu_read_unlock(); | 2486 | rcu_read_unlock(); |
2461 | 2487 | ||
2462 | if (ifmgd->assoc_data && !ifmgd->assoc_data->have_beacon && | 2488 | if (ifmgd->assoc_data && !ifmgd->assoc_data->have_beacon && |
@@ -2592,6 +2618,27 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
2592 | } | 2618 | } |
2593 | } | 2619 | } |
2594 | 2620 | ||
2621 | if (sdata->vif.p2p) { | ||
2622 | u8 noa[2]; | ||
2623 | int ret; | ||
2624 | |||
2625 | ret = cfg80211_get_p2p_attr(mgmt->u.beacon.variable, | ||
2626 | len - baselen, | ||
2627 | IEEE80211_P2P_ATTR_ABSENCE_NOTICE, | ||
2628 | noa, sizeof(noa)); | ||
2629 | if (ret >= 2 && sdata->u.mgd.p2p_noa_index != noa[0]) { | ||
2630 | bss_conf->p2p_oppps = noa[1] & 0x80; | ||
2631 | bss_conf->p2p_ctwindow = noa[1] & 0x7f; | ||
2632 | changed |= BSS_CHANGED_P2P_PS; | ||
2633 | sdata->u.mgd.p2p_noa_index = noa[0]; | ||
2634 | /* | ||
2635 | * make sure we update all information, the CRC | ||
2636 | * mechanism doesn't look at P2P attributes. | ||
2637 | */ | ||
2638 | ifmgd->beacon_crc_valid = false; | ||
2639 | } | ||
2640 | } | ||
2641 | |||
2595 | if (ncrc == ifmgd->beacon_crc && ifmgd->beacon_crc_valid) | 2642 | if (ncrc == ifmgd->beacon_crc && ifmgd->beacon_crc_valid) |
2596 | return; | 2643 | return; |
2597 | ifmgd->beacon_crc = ncrc; | 2644 | ifmgd->beacon_crc = ncrc; |
@@ -2616,17 +2663,17 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
2616 | 2663 | ||
2617 | 2664 | ||
2618 | if (elems.ht_cap_elem && elems.ht_operation && elems.wmm_param && | 2665 | if (elems.ht_cap_elem && elems.ht_operation && elems.wmm_param && |
2619 | !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) | 2666 | !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) |
2620 | changed |= ieee80211_config_ht_tx(sdata, elems.ht_operation, | 2667 | changed |= ieee80211_config_ht_tx(sdata, elems.ht_operation, |
2621 | bssid, true); | 2668 | bssid, true); |
2622 | 2669 | ||
2623 | if (elems.country_elem && elems.pwr_constr_elem && | 2670 | if (elems.country_elem && elems.pwr_constr_elem && |
2624 | mgmt->u.probe_resp.capab_info & | 2671 | mgmt->u.probe_resp.capab_info & |
2625 | cpu_to_le16(WLAN_CAPABILITY_SPECTRUM_MGMT)) | 2672 | cpu_to_le16(WLAN_CAPABILITY_SPECTRUM_MGMT)) |
2626 | ieee80211_handle_pwr_constr(sdata, chan, | 2673 | changed |= ieee80211_handle_pwr_constr(sdata, chan, |
2627 | elems.country_elem, | 2674 | elems.country_elem, |
2628 | elems.country_elem_len, | 2675 | elems.country_elem_len, |
2629 | elems.pwr_constr_elem); | 2676 | elems.pwr_constr_elem); |
2630 | 2677 | ||
2631 | ieee80211_bss_info_change_notify(sdata, changed); | 2678 | ieee80211_bss_info_change_notify(sdata, changed); |
2632 | } | 2679 | } |
@@ -3146,6 +3193,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, | |||
3146 | const u8 *ht_oper_ie; | 3193 | const u8 *ht_oper_ie; |
3147 | const struct ieee80211_ht_operation *ht_oper = NULL; | 3194 | const struct ieee80211_ht_operation *ht_oper = NULL; |
3148 | struct ieee80211_supported_band *sband; | 3195 | struct ieee80211_supported_band *sband; |
3196 | struct cfg80211_chan_def chandef; | ||
3149 | 3197 | ||
3150 | sband = local->hw.wiphy->bands[cbss->channel->band]; | 3198 | sband = local->hw.wiphy->bands[cbss->channel->band]; |
3151 | 3199 | ||
@@ -3177,12 +3225,10 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, | |||
3177 | ht_cfreq, ht_oper->primary_chan, | 3225 | ht_cfreq, ht_oper->primary_chan, |
3178 | cbss->channel->band); | 3226 | cbss->channel->band); |
3179 | ht_oper = NULL; | 3227 | ht_oper = NULL; |
3180 | } else { | ||
3181 | channel_type = NL80211_CHAN_HT20; | ||
3182 | } | 3228 | } |
3183 | } | 3229 | } |
3184 | 3230 | ||
3185 | if (ht_oper && sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { | 3231 | if (ht_oper) { |
3186 | /* | 3232 | /* |
3187 | * cfg80211 already verified that the channel itself can | 3233 | * cfg80211 already verified that the channel itself can |
3188 | * be used, but it didn't check that we can do the right | 3234 | * be used, but it didn't check that we can do the right |
@@ -3195,19 +3241,26 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, | |||
3195 | 3241 | ||
3196 | channel_type = NL80211_CHAN_HT20; | 3242 | channel_type = NL80211_CHAN_HT20; |
3197 | 3243 | ||
3198 | switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { | 3244 | if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { |
3199 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | 3245 | switch (ht_oper->ht_param & |
3200 | if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40PLUS) | 3246 | IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { |
3201 | ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; | 3247 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: |
3202 | else | 3248 | if (cbss->channel->flags & |
3203 | channel_type = NL80211_CHAN_HT40PLUS; | 3249 | IEEE80211_CHAN_NO_HT40PLUS) |
3204 | break; | 3250 | ifmgd->flags |= |
3205 | case IEEE80211_HT_PARAM_CHA_SEC_BELOW: | 3251 | IEEE80211_STA_DISABLE_40MHZ; |
3206 | if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40MINUS) | 3252 | else |
3207 | ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; | 3253 | channel_type = NL80211_CHAN_HT40PLUS; |
3208 | else | 3254 | break; |
3209 | channel_type = NL80211_CHAN_HT40MINUS; | 3255 | case IEEE80211_HT_PARAM_CHA_SEC_BELOW: |
3210 | break; | 3256 | if (cbss->channel->flags & |
3257 | IEEE80211_CHAN_NO_HT40MINUS) | ||
3258 | ifmgd->flags |= | ||
3259 | IEEE80211_STA_DISABLE_40MHZ; | ||
3260 | else | ||
3261 | channel_type = NL80211_CHAN_HT40MINUS; | ||
3262 | break; | ||
3263 | } | ||
3211 | } | 3264 | } |
3212 | 3265 | ||
3213 | ht_cap_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, | 3266 | ht_cap_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, |
@@ -3220,13 +3273,15 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, | |||
3220 | sdata->needed_rx_chains = min(chains, local->rx_chains); | 3273 | sdata->needed_rx_chains = min(chains, local->rx_chains); |
3221 | } else { | 3274 | } else { |
3222 | sdata->needed_rx_chains = 1; | 3275 | sdata->needed_rx_chains = 1; |
3276 | sdata->u.mgd.flags |= IEEE80211_STA_DISABLE_HT; | ||
3223 | } | 3277 | } |
3224 | 3278 | ||
3225 | /* will change later if needed */ | 3279 | /* will change later if needed */ |
3226 | sdata->smps_mode = IEEE80211_SMPS_OFF; | 3280 | sdata->smps_mode = IEEE80211_SMPS_OFF; |
3227 | 3281 | ||
3228 | ieee80211_vif_release_channel(sdata); | 3282 | ieee80211_vif_release_channel(sdata); |
3229 | return ieee80211_vif_use_channel(sdata, cbss->channel, channel_type, | 3283 | cfg80211_chandef_create(&chandef, cbss->channel, channel_type); |
3284 | return ieee80211_vif_use_channel(sdata, &chandef, | ||
3230 | IEEE80211_CHANCTX_SHARED); | 3285 | IEEE80211_CHANCTX_SHARED); |
3231 | } | 3286 | } |
3232 | 3287 | ||
@@ -3488,13 +3543,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3488 | 3543 | ||
3489 | /* prepare assoc data */ | 3544 | /* prepare assoc data */ |
3490 | 3545 | ||
3491 | /* | ||
3492 | * keep only the 40 MHz disable bit set as it might have | ||
3493 | * been set during authentication already, all other bits | ||
3494 | * should be reset for a new connection | ||
3495 | */ | ||
3496 | ifmgd->flags &= IEEE80211_STA_DISABLE_40MHZ; | ||
3497 | |||
3498 | ifmgd->beacon_crc_valid = false; | 3546 | ifmgd->beacon_crc_valid = false; |
3499 | 3547 | ||
3500 | /* | 3548 | /* |
@@ -3508,7 +3556,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3508 | if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 || | 3556 | if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 || |
3509 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP || | 3557 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP || |
3510 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) { | 3558 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) { |
3511 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; | 3559 | ifmgd->flags |= IEEE80211_STA_DISABLE_HT; |
3512 | ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; | 3560 | ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; |
3513 | netdev_info(sdata->dev, | 3561 | netdev_info(sdata->dev, |
3514 | "disabling HT/VHT due to WEP/TKIP use\n"); | 3562 | "disabling HT/VHT due to WEP/TKIP use\n"); |
@@ -3516,7 +3564,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3516 | } | 3564 | } |
3517 | 3565 | ||
3518 | if (req->flags & ASSOC_REQ_DISABLE_HT) { | 3566 | if (req->flags & ASSOC_REQ_DISABLE_HT) { |
3519 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; | 3567 | ifmgd->flags |= IEEE80211_STA_DISABLE_HT; |
3520 | ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; | 3568 | ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; |
3521 | } | 3569 | } |
3522 | 3570 | ||
@@ -3524,7 +3572,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3524 | sband = local->hw.wiphy->bands[req->bss->channel->band]; | 3572 | sband = local->hw.wiphy->bands[req->bss->channel->band]; |
3525 | if (!sband->ht_cap.ht_supported || | 3573 | if (!sband->ht_cap.ht_supported || |
3526 | local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) { | 3574 | local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) { |
3527 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; | 3575 | ifmgd->flags |= IEEE80211_STA_DISABLE_HT; |
3528 | if (!bss->wmm_used) | 3576 | if (!bss->wmm_used) |
3529 | netdev_info(sdata->dev, | 3577 | netdev_info(sdata->dev, |
3530 | "disabling HT as WMM/QoS is not supported by the AP\n"); | 3578 | "disabling HT as WMM/QoS is not supported by the AP\n"); |
@@ -3569,7 +3617,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3569 | assoc_data->ap_ht_param = | 3617 | assoc_data->ap_ht_param = |
3570 | ((struct ieee80211_ht_operation *)(ht_ie + 2))->ht_param; | 3618 | ((struct ieee80211_ht_operation *)(ht_ie + 2))->ht_param; |
3571 | else | 3619 | else |
3572 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; | 3620 | ifmgd->flags |= IEEE80211_STA_DISABLE_HT; |
3573 | 3621 | ||
3574 | if (bss->wmm_used && bss->uapsd_supported && | 3622 | if (bss->wmm_used && bss->uapsd_supported && |
3575 | (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) { | 3623 | (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) { |
@@ -3660,40 +3708,44 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
3660 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 3708 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
3661 | u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; | 3709 | u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; |
3662 | bool tx = !req->local_state_change; | 3710 | bool tx = !req->local_state_change; |
3711 | bool sent_frame = false; | ||
3663 | 3712 | ||
3664 | mutex_lock(&ifmgd->mtx); | 3713 | mutex_lock(&ifmgd->mtx); |
3665 | 3714 | ||
3666 | if (ifmgd->auth_data) { | ||
3667 | ieee80211_destroy_auth_data(sdata, false); | ||
3668 | mutex_unlock(&ifmgd->mtx); | ||
3669 | return 0; | ||
3670 | } | ||
3671 | |||
3672 | sdata_info(sdata, | 3715 | sdata_info(sdata, |
3673 | "deauthenticating from %pM by local choice (reason=%d)\n", | 3716 | "deauthenticating from %pM by local choice (reason=%d)\n", |
3674 | req->bssid, req->reason_code); | 3717 | req->bssid, req->reason_code); |
3675 | 3718 | ||
3676 | if (ifmgd->associated && | 3719 | if (ifmgd->auth_data) { |
3677 | ether_addr_equal(ifmgd->associated->bssid, req->bssid)) { | ||
3678 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, | ||
3679 | req->reason_code, tx, frame_buf); | ||
3680 | } else { | ||
3681 | drv_mgd_prepare_tx(sdata->local, sdata); | 3720 | drv_mgd_prepare_tx(sdata->local, sdata); |
3682 | ieee80211_send_deauth_disassoc(sdata, req->bssid, | 3721 | ieee80211_send_deauth_disassoc(sdata, req->bssid, |
3683 | IEEE80211_STYPE_DEAUTH, | 3722 | IEEE80211_STYPE_DEAUTH, |
3684 | req->reason_code, tx, | 3723 | req->reason_code, tx, |
3685 | frame_buf); | 3724 | frame_buf); |
3725 | ieee80211_destroy_auth_data(sdata, false); | ||
3726 | mutex_unlock(&ifmgd->mtx); | ||
3727 | |||
3728 | sent_frame = tx; | ||
3729 | goto out; | ||
3686 | } | 3730 | } |
3687 | 3731 | ||
3732 | if (ifmgd->associated && | ||
3733 | ether_addr_equal(ifmgd->associated->bssid, req->bssid)) { | ||
3734 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, | ||
3735 | req->reason_code, tx, frame_buf); | ||
3736 | sent_frame = tx; | ||
3737 | } | ||
3688 | mutex_unlock(&ifmgd->mtx); | 3738 | mutex_unlock(&ifmgd->mtx); |
3689 | 3739 | ||
3690 | __cfg80211_send_deauth(sdata->dev, frame_buf, | 3740 | out: |
3691 | IEEE80211_DEAUTH_FRAME_LEN); | ||
3692 | |||
3693 | mutex_lock(&sdata->local->mtx); | 3741 | mutex_lock(&sdata->local->mtx); |
3694 | ieee80211_recalc_idle(sdata->local); | 3742 | ieee80211_recalc_idle(sdata->local); |
3695 | mutex_unlock(&sdata->local->mtx); | 3743 | mutex_unlock(&sdata->local->mtx); |
3696 | 3744 | ||
3745 | if (sent_frame) | ||
3746 | __cfg80211_send_deauth(sdata->dev, frame_buf, | ||
3747 | IEEE80211_DEAUTH_FRAME_LEN); | ||
3748 | |||
3697 | return 0; | 3749 | return 0; |
3698 | } | 3750 | } |
3699 | 3751 | ||
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index c349f3aaf59..5abddfe3e10 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c | |||
@@ -204,9 +204,9 @@ void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc) | |||
204 | roc->frame = NULL; | 204 | roc->frame = NULL; |
205 | } | 205 | } |
206 | } else { | 206 | } else { |
207 | cfg80211_ready_on_channel(&roc->sdata->wdev, (unsigned long)roc, | 207 | cfg80211_ready_on_channel(&roc->sdata->wdev, roc->cookie, |
208 | roc->chan, roc->chan_type, | 208 | roc->chan, roc->req_duration, |
209 | roc->req_duration, GFP_KERNEL); | 209 | GFP_KERNEL); |
210 | } | 210 | } |
211 | 211 | ||
212 | roc->notified = true; | 212 | roc->notified = true; |
@@ -283,8 +283,7 @@ void ieee80211_start_next_roc(struct ieee80211_local *local) | |||
283 | if (!duration) | 283 | if (!duration) |
284 | duration = 10; | 284 | duration = 10; |
285 | 285 | ||
286 | ret = drv_remain_on_channel(local, roc->chan, | 286 | ret = drv_remain_on_channel(local, roc->sdata, roc->chan, |
287 | roc->chan_type, | ||
288 | duration); | 287 | duration); |
289 | 288 | ||
290 | roc->started = true; | 289 | roc->started = true; |
@@ -320,8 +319,7 @@ void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc) | |||
320 | 319 | ||
321 | if (!roc->mgmt_tx_cookie) | 320 | if (!roc->mgmt_tx_cookie) |
322 | cfg80211_remain_on_channel_expired(&roc->sdata->wdev, | 321 | cfg80211_remain_on_channel_expired(&roc->sdata->wdev, |
323 | (unsigned long)roc, | 322 | roc->cookie, roc->chan, |
324 | roc->chan, roc->chan_type, | ||
325 | GFP_KERNEL); | 323 | GFP_KERNEL); |
326 | 324 | ||
327 | list_for_each_entry_safe(dep, tmp, &roc->dependents, list) | 325 | list_for_each_entry_safe(dep, tmp, &roc->dependents, list) |
@@ -360,7 +358,6 @@ void ieee80211_sw_roc_work(struct work_struct *work) | |||
360 | ieee80211_recalc_idle(local); | 358 | ieee80211_recalc_idle(local); |
361 | 359 | ||
362 | local->tmp_channel = roc->chan; | 360 | local->tmp_channel = roc->chan; |
363 | local->tmp_channel_type = roc->chan_type; | ||
364 | ieee80211_hw_config(local, 0); | 361 | ieee80211_hw_config(local, 0); |
365 | 362 | ||
366 | /* tell userspace or send frame */ | 363 | /* tell userspace or send frame */ |
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 9f404ac901a..79a48f37d40 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
@@ -33,6 +33,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
33 | struct ieee80211_local *local = hw_to_local(hw); | 33 | struct ieee80211_local *local = hw_to_local(hw); |
34 | struct ieee80211_sub_if_data *sdata; | 34 | struct ieee80211_sub_if_data *sdata; |
35 | struct sta_info *sta; | 35 | struct sta_info *sta; |
36 | struct ieee80211_chanctx *ctx; | ||
36 | 37 | ||
37 | if (!local->open_count) | 38 | if (!local->open_count) |
38 | goto suspend; | 39 | goto suspend; |
@@ -135,14 +136,55 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
135 | ieee80211_bss_info_change_notify(sdata, | 136 | ieee80211_bss_info_change_notify(sdata, |
136 | BSS_CHANGED_BEACON_ENABLED); | 137 | BSS_CHANGED_BEACON_ENABLED); |
137 | 138 | ||
138 | /* the interface is leaving the channel and is removed */ | 139 | if (sdata->vif.type == NL80211_IFTYPE_AP && |
139 | ieee80211_vif_release_channel(sdata); | 140 | rcu_access_pointer(sdata->u.ap.beacon)) |
141 | drv_stop_ap(local, sdata); | ||
142 | |||
143 | if (local->use_chanctx) { | ||
144 | struct ieee80211_chanctx_conf *conf; | ||
145 | |||
146 | mutex_lock(&local->chanctx_mtx); | ||
147 | conf = rcu_dereference_protected( | ||
148 | sdata->vif.chanctx_conf, | ||
149 | lockdep_is_held(&local->chanctx_mtx)); | ||
150 | if (conf) { | ||
151 | ctx = container_of(conf, | ||
152 | struct ieee80211_chanctx, | ||
153 | conf); | ||
154 | drv_unassign_vif_chanctx(local, sdata, ctx); | ||
155 | } | ||
156 | |||
157 | mutex_unlock(&local->chanctx_mtx); | ||
158 | } | ||
140 | drv_remove_interface(local, sdata); | 159 | drv_remove_interface(local, sdata); |
141 | } | 160 | } |
142 | 161 | ||
143 | sdata = rtnl_dereference(local->monitor_sdata); | 162 | sdata = rtnl_dereference(local->monitor_sdata); |
144 | if (sdata) | 163 | if (sdata) { |
164 | if (local->use_chanctx) { | ||
165 | struct ieee80211_chanctx_conf *conf; | ||
166 | |||
167 | mutex_lock(&local->chanctx_mtx); | ||
168 | conf = rcu_dereference_protected( | ||
169 | sdata->vif.chanctx_conf, | ||
170 | lockdep_is_held(&local->chanctx_mtx)); | ||
171 | if (conf) { | ||
172 | ctx = container_of(conf, | ||
173 | struct ieee80211_chanctx, | ||
174 | conf); | ||
175 | drv_unassign_vif_chanctx(local, sdata, ctx); | ||
176 | } | ||
177 | |||
178 | mutex_unlock(&local->chanctx_mtx); | ||
179 | } | ||
180 | |||
145 | drv_remove_interface(local, sdata); | 181 | drv_remove_interface(local, sdata); |
182 | } | ||
183 | |||
184 | mutex_lock(&local->chanctx_mtx); | ||
185 | list_for_each_entry(ctx, &local->chanctx_list, list) | ||
186 | drv_remove_chanctx(local, ctx); | ||
187 | mutex_unlock(&local->chanctx_mtx); | ||
146 | 188 | ||
147 | /* stop hardware - this must stop RX */ | 189 | /* stop hardware - this must stop RX */ |
148 | if (local->open_count) | 190 | if (local->open_count) |
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 3313c117b32..dd88381c53b 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -391,7 +391,7 @@ static void rate_idx_match_mask(struct ieee80211_tx_rate *rate, | |||
391 | return; | 391 | return; |
392 | 392 | ||
393 | /* if HT BSS, and we handle a data frame, also try HT rates */ | 393 | /* if HT BSS, and we handle a data frame, also try HT rates */ |
394 | if (txrc->bss_conf->channel_type == NL80211_CHAN_NO_HT) | 394 | if (txrc->bss_conf->chandef.width == NL80211_CHAN_WIDTH_20_NOHT) |
395 | return; | 395 | return; |
396 | 396 | ||
397 | fc = hdr->frame_control; | 397 | fc = hdr->frame_control; |
@@ -408,8 +408,7 @@ static void rate_idx_match_mask(struct ieee80211_tx_rate *rate, | |||
408 | 408 | ||
409 | alt_rate.flags |= IEEE80211_TX_RC_MCS; | 409 | alt_rate.flags |= IEEE80211_TX_RC_MCS; |
410 | 410 | ||
411 | if ((txrc->bss_conf->channel_type == NL80211_CHAN_HT40MINUS) || | 411 | if (txrc->bss_conf->chandef.width == NL80211_CHAN_WIDTH_40) |
412 | (txrc->bss_conf->channel_type == NL80211_CHAN_HT40PLUS)) | ||
413 | alt_rate.flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; | 412 | alt_rate.flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; |
414 | 413 | ||
415 | if (rate_idx_match_mcs_mask(&alt_rate, mcs_mask)) { | 414 | if (rate_idx_match_mcs_mask(&alt_rate, mcs_mask)) { |
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index ec198ef6aa8..301386dabf8 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h | |||
@@ -65,7 +65,7 @@ static inline void rate_control_rate_init(struct sta_info *sta) | |||
65 | return; | 65 | return; |
66 | } | 66 | } |
67 | 67 | ||
68 | sband = local->hw.wiphy->bands[chanctx_conf->channel->band]; | 68 | sband = local->hw.wiphy->bands[chanctx_conf->def.chan->band]; |
69 | rcu_read_unlock(); | 69 | rcu_read_unlock(); |
70 | 70 | ||
71 | ref->ops->rate_init(ref->priv, sband, ista, priv_sta); | 71 | ref->ops->rate_init(ref->priv, sband, ista, priv_sta); |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 8c1f1527d67..825f33cf7bb 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -40,6 +40,8 @@ | |||
40 | static struct sk_buff *remove_monitor_info(struct ieee80211_local *local, | 40 | static struct sk_buff *remove_monitor_info(struct ieee80211_local *local, |
41 | struct sk_buff *skb) | 41 | struct sk_buff *skb) |
42 | { | 42 | { |
43 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | ||
44 | |||
43 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) { | 45 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) { |
44 | if (likely(skb->len > FCS_LEN)) | 46 | if (likely(skb->len > FCS_LEN)) |
45 | __pskb_trim(skb, skb->len - FCS_LEN); | 47 | __pskb_trim(skb, skb->len - FCS_LEN); |
@@ -51,20 +53,25 @@ static struct sk_buff *remove_monitor_info(struct ieee80211_local *local, | |||
51 | } | 53 | } |
52 | } | 54 | } |
53 | 55 | ||
56 | if (status->vendor_radiotap_len) | ||
57 | __pskb_pull(skb, status->vendor_radiotap_len); | ||
58 | |||
54 | return skb; | 59 | return skb; |
55 | } | 60 | } |
56 | 61 | ||
57 | static inline int should_drop_frame(struct sk_buff *skb, | 62 | static inline int should_drop_frame(struct sk_buff *skb, int present_fcs_len) |
58 | int present_fcs_len) | ||
59 | { | 63 | { |
60 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 64 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
61 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 65 | struct ieee80211_hdr *hdr; |
66 | |||
67 | hdr = (void *)(skb->data + status->vendor_radiotap_len); | ||
62 | 68 | ||
63 | if (status->flag & (RX_FLAG_FAILED_FCS_CRC | | 69 | if (status->flag & (RX_FLAG_FAILED_FCS_CRC | |
64 | RX_FLAG_FAILED_PLCP_CRC | | 70 | RX_FLAG_FAILED_PLCP_CRC | |
65 | RX_FLAG_AMPDU_IS_ZEROLEN)) | 71 | RX_FLAG_AMPDU_IS_ZEROLEN)) |
66 | return 1; | 72 | return 1; |
67 | if (unlikely(skb->len < 16 + present_fcs_len)) | 73 | if (unlikely(skb->len < 16 + present_fcs_len + |
74 | status->vendor_radiotap_len)) | ||
68 | return 1; | 75 | return 1; |
69 | if (ieee80211_is_ctl(hdr->frame_control) && | 76 | if (ieee80211_is_ctl(hdr->frame_control) && |
70 | !ieee80211_is_pspoll(hdr->frame_control) && | 77 | !ieee80211_is_pspoll(hdr->frame_control) && |
@@ -74,32 +81,48 @@ static inline int should_drop_frame(struct sk_buff *skb, | |||
74 | } | 81 | } |
75 | 82 | ||
76 | static int | 83 | static int |
77 | ieee80211_rx_radiotap_len(struct ieee80211_local *local, | 84 | ieee80211_rx_radiotap_space(struct ieee80211_local *local, |
78 | struct ieee80211_rx_status *status) | 85 | struct ieee80211_rx_status *status) |
79 | { | 86 | { |
80 | int len; | 87 | int len; |
81 | 88 | ||
82 | /* always present fields */ | 89 | /* always present fields */ |
83 | len = sizeof(struct ieee80211_radiotap_header) + 9; | 90 | len = sizeof(struct ieee80211_radiotap_header) + 9; |
84 | 91 | ||
85 | if (status->flag & RX_FLAG_MACTIME_MPDU) | 92 | /* allocate extra bitmap */ |
93 | if (status->vendor_radiotap_len) | ||
94 | len += 4; | ||
95 | |||
96 | if (ieee80211_have_rx_timestamp(status)) { | ||
97 | len = ALIGN(len, 8); | ||
86 | len += 8; | 98 | len += 8; |
99 | } | ||
87 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) | 100 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) |
88 | len += 1; | 101 | len += 1; |
89 | 102 | ||
90 | if (len & 1) /* padding for RX_FLAGS if necessary */ | 103 | /* padding for RX_FLAGS if necessary */ |
91 | len++; | 104 | len = ALIGN(len, 2); |
92 | 105 | ||
93 | if (status->flag & RX_FLAG_HT) /* HT info */ | 106 | if (status->flag & RX_FLAG_HT) /* HT info */ |
94 | len += 3; | 107 | len += 3; |
95 | 108 | ||
96 | if (status->flag & RX_FLAG_AMPDU_DETAILS) { | 109 | if (status->flag & RX_FLAG_AMPDU_DETAILS) { |
97 | /* padding */ | 110 | len = ALIGN(len, 4); |
98 | while (len & 3) | ||
99 | len++; | ||
100 | len += 8; | 111 | len += 8; |
101 | } | 112 | } |
102 | 113 | ||
114 | if (status->vendor_radiotap_len) { | ||
115 | if (WARN_ON_ONCE(status->vendor_radiotap_align == 0)) | ||
116 | status->vendor_radiotap_align = 1; | ||
117 | /* align standard part of vendor namespace */ | ||
118 | len = ALIGN(len, 2); | ||
119 | /* allocate standard part of vendor namespace */ | ||
120 | len += 6; | ||
121 | /* align vendor-defined part */ | ||
122 | len = ALIGN(len, status->vendor_radiotap_align); | ||
123 | /* vendor-defined part is already in skb */ | ||
124 | } | ||
125 | |||
103 | return len; | 126 | return len; |
104 | } | 127 | } |
105 | 128 | ||
@@ -118,6 +141,11 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
118 | struct ieee80211_radiotap_header *rthdr; | 141 | struct ieee80211_radiotap_header *rthdr; |
119 | unsigned char *pos; | 142 | unsigned char *pos; |
120 | u16 rx_flags = 0; | 143 | u16 rx_flags = 0; |
144 | int mpdulen; | ||
145 | |||
146 | mpdulen = skb->len; | ||
147 | if (!(has_fcs && (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS))) | ||
148 | mpdulen += FCS_LEN; | ||
121 | 149 | ||
122 | rthdr = (struct ieee80211_radiotap_header *)skb_push(skb, rtap_len); | 150 | rthdr = (struct ieee80211_radiotap_header *)skb_push(skb, rtap_len); |
123 | memset(rthdr, 0, rtap_len); | 151 | memset(rthdr, 0, rtap_len); |
@@ -128,17 +156,30 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
128 | (1 << IEEE80211_RADIOTAP_CHANNEL) | | 156 | (1 << IEEE80211_RADIOTAP_CHANNEL) | |
129 | (1 << IEEE80211_RADIOTAP_ANTENNA) | | 157 | (1 << IEEE80211_RADIOTAP_ANTENNA) | |
130 | (1 << IEEE80211_RADIOTAP_RX_FLAGS)); | 158 | (1 << IEEE80211_RADIOTAP_RX_FLAGS)); |
131 | rthdr->it_len = cpu_to_le16(rtap_len); | 159 | rthdr->it_len = cpu_to_le16(rtap_len + status->vendor_radiotap_len); |
132 | 160 | ||
133 | pos = (unsigned char *)(rthdr+1); | 161 | pos = (unsigned char *)(rthdr + 1); |
162 | |||
163 | if (status->vendor_radiotap_len) { | ||
164 | rthdr->it_present |= | ||
165 | cpu_to_le32(BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE)) | | ||
166 | cpu_to_le32(BIT(IEEE80211_RADIOTAP_EXT)); | ||
167 | put_unaligned_le32(status->vendor_radiotap_bitmap, pos); | ||
168 | pos += 4; | ||
169 | } | ||
134 | 170 | ||
135 | /* the order of the following fields is important */ | 171 | /* the order of the following fields is important */ |
136 | 172 | ||
137 | /* IEEE80211_RADIOTAP_TSFT */ | 173 | /* IEEE80211_RADIOTAP_TSFT */ |
138 | if (status->flag & RX_FLAG_MACTIME_MPDU) { | 174 | if (ieee80211_have_rx_timestamp(status)) { |
139 | put_unaligned_le64(status->mactime, pos); | 175 | /* padding */ |
140 | rthdr->it_present |= | 176 | while ((pos - (u8 *)rthdr) & 7) |
141 | cpu_to_le32(1 << IEEE80211_RADIOTAP_TSFT); | 177 | *pos++ = 0; |
178 | put_unaligned_le64( | ||
179 | ieee80211_calculate_rx_timestamp(local, status, | ||
180 | mpdulen, 0), | ||
181 | pos); | ||
182 | rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_TSFT); | ||
142 | pos += 8; | 183 | pos += 8; |
143 | } | 184 | } |
144 | 185 | ||
@@ -152,7 +193,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
152 | pos++; | 193 | pos++; |
153 | 194 | ||
154 | /* IEEE80211_RADIOTAP_RATE */ | 195 | /* IEEE80211_RADIOTAP_RATE */ |
155 | if (!rate || status->flag & RX_FLAG_HT) { | 196 | if (!rate || status->flag & (RX_FLAG_HT | RX_FLAG_VHT)) { |
156 | /* | 197 | /* |
157 | * Without rate information don't add it. If we have, | 198 | * Without rate information don't add it. If we have, |
158 | * MCS information is a separate field in radiotap, | 199 | * MCS information is a separate field in radiotap, |
@@ -172,7 +213,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
172 | if (status->band == IEEE80211_BAND_5GHZ) | 213 | if (status->band == IEEE80211_BAND_5GHZ) |
173 | put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ, | 214 | put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ, |
174 | pos); | 215 | pos); |
175 | else if (status->flag & RX_FLAG_HT) | 216 | else if (status->flag & (RX_FLAG_HT | RX_FLAG_VHT)) |
176 | put_unaligned_le16(IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ, | 217 | put_unaligned_le16(IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ, |
177 | pos); | 218 | pos); |
178 | else if (rate && rate->flags & IEEE80211_RATE_ERP_G) | 219 | else if (rate && rate->flags & IEEE80211_RATE_ERP_G) |
@@ -205,7 +246,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
205 | /* IEEE80211_RADIOTAP_RX_FLAGS */ | 246 | /* IEEE80211_RADIOTAP_RX_FLAGS */ |
206 | /* ensure 2 byte alignment for the 2 byte field as required */ | 247 | /* ensure 2 byte alignment for the 2 byte field as required */ |
207 | if ((pos - (u8 *)rthdr) & 1) | 248 | if ((pos - (u8 *)rthdr) & 1) |
208 | pos++; | 249 | *pos++ = 0; |
209 | if (status->flag & RX_FLAG_FAILED_PLCP_CRC) | 250 | if (status->flag & RX_FLAG_FAILED_PLCP_CRC) |
210 | rx_flags |= IEEE80211_RADIOTAP_F_RX_BADPLCP; | 251 | rx_flags |= IEEE80211_RADIOTAP_F_RX_BADPLCP; |
211 | put_unaligned_le16(rx_flags, pos); | 252 | put_unaligned_le16(rx_flags, pos); |
@@ -255,6 +296,21 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
255 | *pos++ = 0; | 296 | *pos++ = 0; |
256 | *pos++ = 0; | 297 | *pos++ = 0; |
257 | } | 298 | } |
299 | |||
300 | if (status->vendor_radiotap_len) { | ||
301 | /* ensure 2 byte alignment for the vendor field as required */ | ||
302 | if ((pos - (u8 *)rthdr) & 1) | ||
303 | *pos++ = 0; | ||
304 | *pos++ = status->vendor_radiotap_oui[0]; | ||
305 | *pos++ = status->vendor_radiotap_oui[1]; | ||
306 | *pos++ = status->vendor_radiotap_oui[2]; | ||
307 | *pos++ = status->vendor_radiotap_subns; | ||
308 | put_unaligned_le16(status->vendor_radiotap_len, pos); | ||
309 | pos += 2; | ||
310 | /* align the actual payload as requested */ | ||
311 | while ((pos - (u8 *)rthdr) & (status->vendor_radiotap_align - 1)) | ||
312 | *pos++ = 0; | ||
313 | } | ||
258 | } | 314 | } |
259 | 315 | ||
260 | /* | 316 | /* |
@@ -283,13 +339,13 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, | |||
283 | */ | 339 | */ |
284 | 340 | ||
285 | /* room for the radiotap header based on driver features */ | 341 | /* room for the radiotap header based on driver features */ |
286 | needed_headroom = ieee80211_rx_radiotap_len(local, status); | 342 | needed_headroom = ieee80211_rx_radiotap_space(local, status); |
287 | 343 | ||
288 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) | 344 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) |
289 | present_fcs_len = FCS_LEN; | 345 | present_fcs_len = FCS_LEN; |
290 | 346 | ||
291 | /* make sure hdr->frame_control is on the linear part */ | 347 | /* ensure hdr->frame_control and vendor radiotap data are in skb head */ |
292 | if (!pskb_may_pull(origskb, 2)) { | 348 | if (!pskb_may_pull(origskb, 2 + status->vendor_radiotap_len)) { |
293 | dev_kfree_skb(origskb); | 349 | dev_kfree_skb(origskb); |
294 | return NULL; | 350 | return NULL; |
295 | } | 351 | } |
@@ -374,7 +430,6 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, | |||
374 | return origskb; | 430 | return origskb; |
375 | } | 431 | } |
376 | 432 | ||
377 | |||
378 | static void ieee80211_parse_qos(struct ieee80211_rx_data *rx) | 433 | static void ieee80211_parse_qos(struct ieee80211_rx_data *rx) |
379 | { | 434 | { |
380 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 435 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
@@ -403,10 +458,10 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx) | |||
403 | * | 458 | * |
404 | * We also use that counter for non-QoS STAs. | 459 | * We also use that counter for non-QoS STAs. |
405 | */ | 460 | */ |
406 | seqno_idx = NUM_RX_DATA_QUEUES; | 461 | seqno_idx = IEEE80211_NUM_TIDS; |
407 | security_idx = 0; | 462 | security_idx = 0; |
408 | if (ieee80211_is_mgmt(hdr->frame_control)) | 463 | if (ieee80211_is_mgmt(hdr->frame_control)) |
409 | security_idx = NUM_RX_DATA_QUEUES; | 464 | security_idx = IEEE80211_NUM_TIDS; |
410 | tid = 0; | 465 | tid = 0; |
411 | } | 466 | } |
412 | 467 | ||
@@ -481,8 +536,7 @@ static int ieee80211_get_mmie_keyidx(struct sk_buff *skb) | |||
481 | struct ieee80211_mgmt *hdr = (struct ieee80211_mgmt *) skb->data; | 536 | struct ieee80211_mgmt *hdr = (struct ieee80211_mgmt *) skb->data; |
482 | struct ieee80211_mmie *mmie; | 537 | struct ieee80211_mmie *mmie; |
483 | 538 | ||
484 | if (skb->len < 24 + sizeof(*mmie) || | 539 | if (skb->len < 24 + sizeof(*mmie) || !is_multicast_ether_addr(hdr->da)) |
485 | !is_multicast_ether_addr(hdr->da)) | ||
486 | return -1; | 540 | return -1; |
487 | 541 | ||
488 | if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *) hdr)) | 542 | if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *) hdr)) |
@@ -497,9 +551,7 @@ static int ieee80211_get_mmie_keyidx(struct sk_buff *skb) | |||
497 | return le16_to_cpu(mmie->key_id); | 551 | return le16_to_cpu(mmie->key_id); |
498 | } | 552 | } |
499 | 553 | ||
500 | 554 | static ieee80211_rx_result ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) | |
501 | static ieee80211_rx_result | ||
502 | ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) | ||
503 | { | 555 | { |
504 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 556 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
505 | char *dev_addr = rx->sdata->vif.addr; | 557 | char *dev_addr = rx->sdata->vif.addr; |
@@ -507,7 +559,7 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) | |||
507 | if (ieee80211_is_data(hdr->frame_control)) { | 559 | if (ieee80211_is_data(hdr->frame_control)) { |
508 | if (is_multicast_ether_addr(hdr->addr1)) { | 560 | if (is_multicast_ether_addr(hdr->addr1)) { |
509 | if (ieee80211_has_tods(hdr->frame_control) || | 561 | if (ieee80211_has_tods(hdr->frame_control) || |
510 | !ieee80211_has_fromds(hdr->frame_control)) | 562 | !ieee80211_has_fromds(hdr->frame_control)) |
511 | return RX_DROP_MONITOR; | 563 | return RX_DROP_MONITOR; |
512 | if (ether_addr_equal(hdr->addr3, dev_addr)) | 564 | if (ether_addr_equal(hdr->addr3, dev_addr)) |
513 | return RX_DROP_MONITOR; | 565 | return RX_DROP_MONITOR; |
@@ -539,7 +591,7 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) | |||
539 | mgmt = (struct ieee80211_mgmt *)hdr; | 591 | mgmt = (struct ieee80211_mgmt *)hdr; |
540 | category = mgmt->u.action.category; | 592 | category = mgmt->u.action.category; |
541 | if (category != WLAN_CATEGORY_MESH_ACTION && | 593 | if (category != WLAN_CATEGORY_MESH_ACTION && |
542 | category != WLAN_CATEGORY_SELF_PROTECTED) | 594 | category != WLAN_CATEGORY_SELF_PROTECTED) |
543 | return RX_DROP_MONITOR; | 595 | return RX_DROP_MONITOR; |
544 | return RX_CONTINUE; | 596 | return RX_CONTINUE; |
545 | } | 597 | } |
@@ -551,7 +603,6 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) | |||
551 | return RX_CONTINUE; | 603 | return RX_CONTINUE; |
552 | 604 | ||
553 | return RX_DROP_MONITOR; | 605 | return RX_DROP_MONITOR; |
554 | |||
555 | } | 606 | } |
556 | 607 | ||
557 | return RX_CONTINUE; | 608 | return RX_CONTINUE; |
@@ -575,7 +626,6 @@ static inline u16 seq_sub(u16 sq1, u16 sq2) | |||
575 | return (sq1 - sq2) & SEQ_MASK; | 626 | return (sq1 - sq2) & SEQ_MASK; |
576 | } | 627 | } |
577 | 628 | ||
578 | |||
579 | static void ieee80211_release_reorder_frame(struct ieee80211_sub_if_data *sdata, | 629 | static void ieee80211_release_reorder_frame(struct ieee80211_sub_if_data *sdata, |
580 | struct tid_ampdu_rx *tid_agg_rx, | 630 | struct tid_ampdu_rx *tid_agg_rx, |
581 | int index) | 631 | int index) |
@@ -1291,17 +1341,22 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
1291 | 1341 | ||
1292 | /* | 1342 | /* |
1293 | * Update last_rx only for IBSS packets which are for the current | 1343 | * Update last_rx only for IBSS packets which are for the current |
1294 | * BSSID to avoid keeping the current IBSS network alive in cases | 1344 | * BSSID and for station already AUTHORIZED to avoid keeping the |
1295 | * where other STAs start using different BSSID. | 1345 | * current IBSS network alive in cases where other STAs start |
1346 | * using different BSSID. This will also give the station another | ||
1347 | * chance to restart the authentication/authorization in case | ||
1348 | * something went wrong the first time. | ||
1296 | */ | 1349 | */ |
1297 | if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) { | 1350 | if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) { |
1298 | u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len, | 1351 | u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len, |
1299 | NL80211_IFTYPE_ADHOC); | 1352 | NL80211_IFTYPE_ADHOC); |
1300 | if (ether_addr_equal(bssid, rx->sdata->u.ibss.bssid)) { | 1353 | if (ether_addr_equal(bssid, rx->sdata->u.ibss.bssid) && |
1354 | test_sta_flag(sta, WLAN_STA_AUTHORIZED)) { | ||
1301 | sta->last_rx = jiffies; | 1355 | sta->last_rx = jiffies; |
1302 | if (ieee80211_is_data(hdr->frame_control)) { | 1356 | if (ieee80211_is_data(hdr->frame_control)) { |
1303 | sta->last_rx_rate_idx = status->rate_idx; | 1357 | sta->last_rx_rate_idx = status->rate_idx; |
1304 | sta->last_rx_rate_flag = status->flag; | 1358 | sta->last_rx_rate_flag = status->flag; |
1359 | sta->last_rx_rate_vht_nss = status->vht_nss; | ||
1305 | } | 1360 | } |
1306 | } | 1361 | } |
1307 | } else if (!is_multicast_ether_addr(hdr->addr1)) { | 1362 | } else if (!is_multicast_ether_addr(hdr->addr1)) { |
@@ -1313,6 +1368,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
1313 | if (ieee80211_is_data(hdr->frame_control)) { | 1368 | if (ieee80211_is_data(hdr->frame_control)) { |
1314 | sta->last_rx_rate_idx = status->rate_idx; | 1369 | sta->last_rx_rate_idx = status->rate_idx; |
1315 | sta->last_rx_rate_flag = status->flag; | 1370 | sta->last_rx_rate_flag = status->flag; |
1371 | sta->last_rx_rate_vht_nss = status->vht_nss; | ||
1316 | } | 1372 | } |
1317 | } | 1373 | } |
1318 | 1374 | ||
@@ -1585,18 +1641,15 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
1585 | return RX_CONTINUE; | 1641 | return RX_CONTINUE; |
1586 | } | 1642 | } |
1587 | 1643 | ||
1588 | static int | 1644 | static int ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx) |
1589 | ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx) | ||
1590 | { | 1645 | { |
1591 | if (unlikely(!rx->sta || | 1646 | if (unlikely(!rx->sta || !test_sta_flag(rx->sta, WLAN_STA_AUTHORIZED))) |
1592 | !test_sta_flag(rx->sta, WLAN_STA_AUTHORIZED))) | ||
1593 | return -EACCES; | 1647 | return -EACCES; |
1594 | 1648 | ||
1595 | return 0; | 1649 | return 0; |
1596 | } | 1650 | } |
1597 | 1651 | ||
1598 | static int | 1652 | static int ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc) |
1599 | ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc) | ||
1600 | { | 1653 | { |
1601 | struct sk_buff *skb = rx->skb; | 1654 | struct sk_buff *skb = rx->skb; |
1602 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 1655 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
@@ -1618,8 +1671,7 @@ ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc) | |||
1618 | return 0; | 1671 | return 0; |
1619 | } | 1672 | } |
1620 | 1673 | ||
1621 | static int | 1674 | static int ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx) |
1622 | ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx) | ||
1623 | { | 1675 | { |
1624 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 1676 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
1625 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); | 1677 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); |
@@ -2003,7 +2055,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
2003 | } else { | 2055 | } else { |
2004 | /* unable to resolve next hop */ | 2056 | /* unable to resolve next hop */ |
2005 | mesh_path_error_tx(ifmsh->mshcfg.element_ttl, fwd_hdr->addr3, | 2057 | mesh_path_error_tx(ifmsh->mshcfg.element_ttl, fwd_hdr->addr3, |
2006 | 0, reason, fwd_hdr->addr2, sdata); | 2058 | 0, reason, fwd_hdr->addr2, sdata); |
2007 | IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_no_route); | 2059 | IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_no_route); |
2008 | kfree_skb(fwd_skb); | 2060 | kfree_skb(fwd_skb); |
2009 | return RX_DROP_MONITOR; | 2061 | return RX_DROP_MONITOR; |
@@ -2212,7 +2264,7 @@ ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx) | |||
2212 | 2264 | ||
2213 | cfg80211_report_obss_beacon(rx->local->hw.wiphy, | 2265 | cfg80211_report_obss_beacon(rx->local->hw.wiphy, |
2214 | rx->skb->data, rx->skb->len, | 2266 | rx->skb->data, rx->skb->len, |
2215 | status->freq, sig, GFP_ATOMIC); | 2267 | status->freq, sig); |
2216 | rx->flags |= IEEE80211_RX_BEACON_REPORTED; | 2268 | rx->flags |= IEEE80211_RX_BEACON_REPORTED; |
2217 | } | 2269 | } |
2218 | 2270 | ||
@@ -2412,7 +2464,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2412 | if (!ieee80211_vif_is_mesh(&sdata->vif)) | 2464 | if (!ieee80211_vif_is_mesh(&sdata->vif)) |
2413 | break; | 2465 | break; |
2414 | if (mesh_action_is_path_sel(mgmt) && | 2466 | if (mesh_action_is_path_sel(mgmt) && |
2415 | (!mesh_path_sel_is_hwmp(sdata))) | 2467 | !mesh_path_sel_is_hwmp(sdata)) |
2416 | break; | 2468 | break; |
2417 | goto queue; | 2469 | goto queue; |
2418 | } | 2470 | } |
@@ -2468,7 +2520,6 @@ ieee80211_rx_h_userspace_mgmt(struct ieee80211_rx_data *rx) | |||
2468 | return RX_QUEUED; | 2520 | return RX_QUEUED; |
2469 | } | 2521 | } |
2470 | 2522 | ||
2471 | |||
2472 | return RX_CONTINUE; | 2523 | return RX_CONTINUE; |
2473 | } | 2524 | } |
2474 | 2525 | ||
@@ -2598,7 +2649,7 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx, | |||
2598 | goto out_free_skb; | 2649 | goto out_free_skb; |
2599 | 2650 | ||
2600 | /* room for the radiotap header based on driver features */ | 2651 | /* room for the radiotap header based on driver features */ |
2601 | needed_headroom = ieee80211_rx_radiotap_len(local, status); | 2652 | needed_headroom = ieee80211_rx_radiotap_space(local, status); |
2602 | 2653 | ||
2603 | if (skb_headroom(skb) < needed_headroom && | 2654 | if (skb_headroom(skb) < needed_headroom && |
2604 | pskb_expand_head(skb, needed_headroom, 0, GFP_ATOMIC)) | 2655 | pskb_expand_head(skb, needed_headroom, 0, GFP_ATOMIC)) |
@@ -2661,7 +2712,8 @@ static void ieee80211_rx_handlers_result(struct ieee80211_rx_data *rx, | |||
2661 | status = IEEE80211_SKB_RXCB((rx->skb)); | 2712 | status = IEEE80211_SKB_RXCB((rx->skb)); |
2662 | 2713 | ||
2663 | sband = rx->local->hw.wiphy->bands[status->band]; | 2714 | sband = rx->local->hw.wiphy->bands[status->band]; |
2664 | if (!(status->flag & RX_FLAG_HT)) | 2715 | if (!(status->flag & RX_FLAG_HT) && |
2716 | !(status->flag & RX_FLAG_VHT)) | ||
2665 | rate = &sband->bitrates[status->rate_idx]; | 2717 | rate = &sband->bitrates[status->rate_idx]; |
2666 | 2718 | ||
2667 | ieee80211_rx_cooked_monitor(rx, rate); | 2719 | ieee80211_rx_cooked_monitor(rx, rate); |
@@ -2828,8 +2880,8 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx, | |||
2828 | status->rx_flags &= ~IEEE80211_RX_RA_MATCH; | 2880 | status->rx_flags &= ~IEEE80211_RX_RA_MATCH; |
2829 | } else if (!rx->sta) { | 2881 | } else if (!rx->sta) { |
2830 | int rate_idx; | 2882 | int rate_idx; |
2831 | if (status->flag & RX_FLAG_HT) | 2883 | if (status->flag & (RX_FLAG_HT | RX_FLAG_VHT)) |
2832 | rate_idx = 0; /* TODO: HT rates */ | 2884 | rate_idx = 0; /* TODO: HT/VHT rates */ |
2833 | else | 2885 | else |
2834 | rate_idx = status->rate_idx; | 2886 | rate_idx = status->rate_idx; |
2835 | ieee80211_ibss_rx_no_sta(sdata, bssid, hdr->addr2, | 2887 | ieee80211_ibss_rx_no_sta(sdata, bssid, hdr->addr2, |
@@ -3105,6 +3157,13 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
3105 | status->rate_idx, | 3157 | status->rate_idx, |
3106 | status->rate_idx)) | 3158 | status->rate_idx)) |
3107 | goto drop; | 3159 | goto drop; |
3160 | } else if (status->flag & RX_FLAG_VHT) { | ||
3161 | if (WARN_ONCE(status->rate_idx > 9 || | ||
3162 | !status->vht_nss || | ||
3163 | status->vht_nss > 8, | ||
3164 | "Rate marked as a VHT rate but data is invalid: MCS: %d, NSS: %d\n", | ||
3165 | status->rate_idx, status->vht_nss)) | ||
3166 | goto drop; | ||
3108 | } else { | 3167 | } else { |
3109 | if (WARN_ON(status->rate_idx >= sband->n_bitrates)) | 3168 | if (WARN_ON(status->rate_idx >= sband->n_bitrates)) |
3110 | goto drop; | 3169 | goto drop; |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 8e9bb168b73..f3340279aba 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -174,7 +174,6 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb) | |||
174 | u8 *elements; | 174 | u8 *elements; |
175 | struct ieee80211_channel *channel; | 175 | struct ieee80211_channel *channel; |
176 | size_t baselen; | 176 | size_t baselen; |
177 | int freq; | ||
178 | bool beacon; | 177 | bool beacon; |
179 | struct ieee802_11_elems elems; | 178 | struct ieee802_11_elems elems; |
180 | 179 | ||
@@ -209,13 +208,7 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb) | |||
209 | 208 | ||
210 | ieee802_11_parse_elems(elements, skb->len - baselen, &elems); | 209 | ieee802_11_parse_elems(elements, skb->len - baselen, &elems); |
211 | 210 | ||
212 | if (elems.ds_params && elems.ds_params_len == 1) | 211 | channel = ieee80211_get_channel(local->hw.wiphy, rx_status->freq); |
213 | freq = ieee80211_channel_to_frequency(elems.ds_params[0], | ||
214 | rx_status->band); | ||
215 | else | ||
216 | freq = rx_status->freq; | ||
217 | |||
218 | channel = ieee80211_get_channel(local->hw.wiphy, freq); | ||
219 | 212 | ||
220 | if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) | 213 | if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) |
221 | return; | 214 | return; |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index e9d57689c05..f3e502502fe 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -142,7 +142,7 @@ static void free_sta_work(struct work_struct *wk) | |||
142 | * drivers have to handle aggregation stop being requested, followed | 142 | * drivers have to handle aggregation stop being requested, followed |
143 | * directly by station destruction. | 143 | * directly by station destruction. |
144 | */ | 144 | */ |
145 | for (i = 0; i < STA_TID_NUM; i++) { | 145 | for (i = 0; i < IEEE80211_NUM_TIDS; i++) { |
146 | tid_tx = rcu_dereference_raw(sta->ampdu_mlme.tid_tx[i]); | 146 | tid_tx = rcu_dereference_raw(sta->ampdu_mlme.tid_tx[i]); |
147 | if (!tid_tx) | 147 | if (!tid_tx) |
148 | continue; | 148 | continue; |
@@ -330,7 +330,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
330 | return NULL; | 330 | return NULL; |
331 | } | 331 | } |
332 | 332 | ||
333 | for (i = 0; i < STA_TID_NUM; i++) { | 333 | for (i = 0; i < IEEE80211_NUM_TIDS; i++) { |
334 | /* | 334 | /* |
335 | * timer_to_tid must be initialized with identity mapping | 335 | * timer_to_tid must be initialized with identity mapping |
336 | * to enable session_timer's data differentiation. See | 336 | * to enable session_timer's data differentiation. See |
@@ -343,7 +343,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
343 | skb_queue_head_init(&sta->tx_filtered[i]); | 343 | skb_queue_head_init(&sta->tx_filtered[i]); |
344 | } | 344 | } |
345 | 345 | ||
346 | for (i = 0; i < NUM_RX_DATA_QUEUES; i++) | 346 | for (i = 0; i < IEEE80211_NUM_TIDS; i++) |
347 | sta->last_seq_ctrl[i] = cpu_to_le16(USHRT_MAX); | 347 | sta->last_seq_ctrl[i] = cpu_to_le16(USHRT_MAX); |
348 | 348 | ||
349 | sta_dbg(sdata, "Allocated STA %pM\n", sta->sta.addr); | 349 | sta_dbg(sdata, "Allocated STA %pM\n", sta->sta.addr); |
@@ -986,7 +986,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) | |||
986 | 986 | ||
987 | clear_sta_flag(sta, WLAN_STA_SP); | 987 | clear_sta_flag(sta, WLAN_STA_SP); |
988 | 988 | ||
989 | BUILD_BUG_ON(BITS_TO_LONGS(STA_TID_NUM) > 1); | 989 | BUILD_BUG_ON(BITS_TO_LONGS(IEEE80211_NUM_TIDS) > 1); |
990 | sta->driver_buffered_tids = 0; | 990 | sta->driver_buffered_tids = 0; |
991 | 991 | ||
992 | if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS)) | 992 | if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS)) |
@@ -1092,7 +1092,7 @@ static void ieee80211_send_null_response(struct ieee80211_sub_if_data *sdata, | |||
1092 | return; | 1092 | return; |
1093 | } | 1093 | } |
1094 | 1094 | ||
1095 | ieee80211_xmit(sdata, skb, chanctx_conf->channel->band); | 1095 | ieee80211_xmit(sdata, skb, chanctx_conf->def.chan->band); |
1096 | rcu_read_unlock(); | 1096 | rcu_read_unlock(); |
1097 | } | 1097 | } |
1098 | 1098 | ||
@@ -1374,7 +1374,7 @@ void ieee80211_sta_set_buffered(struct ieee80211_sta *pubsta, | |||
1374 | { | 1374 | { |
1375 | struct sta_info *sta = container_of(pubsta, struct sta_info, sta); | 1375 | struct sta_info *sta = container_of(pubsta, struct sta_info, sta); |
1376 | 1376 | ||
1377 | if (WARN_ON(tid >= STA_TID_NUM)) | 1377 | if (WARN_ON(tid >= IEEE80211_NUM_TIDS)) |
1378 | return; | 1378 | return; |
1379 | 1379 | ||
1380 | if (buffered) | 1380 | if (buffered) |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index c88f161f811..6835cea4e40 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -80,7 +80,6 @@ enum ieee80211_sta_info_flags { | |||
80 | WLAN_STA_TOFFSET_KNOWN, | 80 | WLAN_STA_TOFFSET_KNOWN, |
81 | }; | 81 | }; |
82 | 82 | ||
83 | #define STA_TID_NUM 16 | ||
84 | #define ADDBA_RESP_INTERVAL HZ | 83 | #define ADDBA_RESP_INTERVAL HZ |
85 | #define HT_AGG_MAX_RETRIES 15 | 84 | #define HT_AGG_MAX_RETRIES 15 |
86 | #define HT_AGG_BURST_RETRIES 3 | 85 | #define HT_AGG_BURST_RETRIES 3 |
@@ -197,15 +196,15 @@ struct tid_ampdu_rx { | |||
197 | struct sta_ampdu_mlme { | 196 | struct sta_ampdu_mlme { |
198 | struct mutex mtx; | 197 | struct mutex mtx; |
199 | /* rx */ | 198 | /* rx */ |
200 | struct tid_ampdu_rx __rcu *tid_rx[STA_TID_NUM]; | 199 | struct tid_ampdu_rx __rcu *tid_rx[IEEE80211_NUM_TIDS]; |
201 | unsigned long tid_rx_timer_expired[BITS_TO_LONGS(STA_TID_NUM)]; | 200 | unsigned long tid_rx_timer_expired[BITS_TO_LONGS(IEEE80211_NUM_TIDS)]; |
202 | unsigned long tid_rx_stop_requested[BITS_TO_LONGS(STA_TID_NUM)]; | 201 | unsigned long tid_rx_stop_requested[BITS_TO_LONGS(IEEE80211_NUM_TIDS)]; |
203 | /* tx */ | 202 | /* tx */ |
204 | struct work_struct work; | 203 | struct work_struct work; |
205 | struct tid_ampdu_tx __rcu *tid_tx[STA_TID_NUM]; | 204 | struct tid_ampdu_tx __rcu *tid_tx[IEEE80211_NUM_TIDS]; |
206 | struct tid_ampdu_tx *tid_start_tx[STA_TID_NUM]; | 205 | struct tid_ampdu_tx *tid_start_tx[IEEE80211_NUM_TIDS]; |
207 | unsigned long last_addba_req_time[STA_TID_NUM]; | 206 | unsigned long last_addba_req_time[IEEE80211_NUM_TIDS]; |
208 | u8 addba_req_num[STA_TID_NUM]; | 207 | u8 addba_req_num[IEEE80211_NUM_TIDS]; |
209 | u8 dialog_token_allocator; | 208 | u8 dialog_token_allocator; |
210 | }; | 209 | }; |
211 | 210 | ||
@@ -228,6 +227,7 @@ struct sta_ampdu_mlme { | |||
228 | * "the" transmit rate | 227 | * "the" transmit rate |
229 | * @last_rx_rate_idx: rx status rate index of the last data packet | 228 | * @last_rx_rate_idx: rx status rate index of the last data packet |
230 | * @last_rx_rate_flag: rx status flag of the last data packet | 229 | * @last_rx_rate_flag: rx status flag of the last data packet |
230 | * @last_rx_rate_vht_nss: rx status nss of last data packet | ||
231 | * @lock: used for locking all fields that require locking, see comments | 231 | * @lock: used for locking all fields that require locking, see comments |
232 | * in the header file. | 232 | * in the header file. |
233 | * @drv_unblock_wk: used for driver PS unblocking | 233 | * @drv_unblock_wk: used for driver PS unblocking |
@@ -273,7 +273,7 @@ struct sta_ampdu_mlme { | |||
273 | * @t_offset: timing offset relative to this host | 273 | * @t_offset: timing offset relative to this host |
274 | * @t_offset_setpoint: reference timing offset of this sta to be used when | 274 | * @t_offset_setpoint: reference timing offset of this sta to be used when |
275 | * calculating clockdrift | 275 | * calculating clockdrift |
276 | * @ch_type: peer's channel type | 276 | * @ch_width: peer's channel width |
277 | * @debugfs: debug filesystem info | 277 | * @debugfs: debug filesystem info |
278 | * @dead: set to true when sta is unlinked | 278 | * @dead: set to true when sta is unlinked |
279 | * @uploaded: set to true when sta is uploaded to the driver | 279 | * @uploaded: set to true when sta is uploaded to the driver |
@@ -330,7 +330,7 @@ struct sta_info { | |||
330 | int last_signal; | 330 | int last_signal; |
331 | struct ewma avg_signal; | 331 | struct ewma avg_signal; |
332 | /* Plus 1 for non-QoS frames */ | 332 | /* Plus 1 for non-QoS frames */ |
333 | __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES + 1]; | 333 | __le16 last_seq_ctrl[IEEE80211_NUM_TIDS + 1]; |
334 | 334 | ||
335 | /* Updated from TX status path only, no locking requirements */ | 335 | /* Updated from TX status path only, no locking requirements */ |
336 | unsigned long tx_filtered_count; | 336 | unsigned long tx_filtered_count; |
@@ -344,14 +344,15 @@ struct sta_info { | |||
344 | unsigned long tx_fragments; | 344 | unsigned long tx_fragments; |
345 | struct ieee80211_tx_rate last_tx_rate; | 345 | struct ieee80211_tx_rate last_tx_rate; |
346 | int last_rx_rate_idx; | 346 | int last_rx_rate_idx; |
347 | int last_rx_rate_flag; | 347 | u32 last_rx_rate_flag; |
348 | u8 last_rx_rate_vht_nss; | ||
348 | u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1]; | 349 | u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1]; |
349 | 350 | ||
350 | /* | 351 | /* |
351 | * Aggregation information, locked with lock. | 352 | * Aggregation information, locked with lock. |
352 | */ | 353 | */ |
353 | struct sta_ampdu_mlme ampdu_mlme; | 354 | struct sta_ampdu_mlme ampdu_mlme; |
354 | u8 timer_to_tid[STA_TID_NUM]; | 355 | u8 timer_to_tid[IEEE80211_NUM_TIDS]; |
355 | 356 | ||
356 | #ifdef CONFIG_MAC80211_MESH | 357 | #ifdef CONFIG_MAC80211_MESH |
357 | /* | 358 | /* |
@@ -369,7 +370,7 @@ struct sta_info { | |||
369 | struct timer_list plink_timer; | 370 | struct timer_list plink_timer; |
370 | s64 t_offset; | 371 | s64 t_offset; |
371 | s64 t_offset_setpoint; | 372 | s64 t_offset_setpoint; |
372 | enum nl80211_channel_type ch_type; | 373 | enum nl80211_chan_width ch_width; |
373 | #endif | 374 | #endif |
374 | 375 | ||
375 | #ifdef CONFIG_MAC80211_DEBUGFS | 376 | #ifdef CONFIG_MAC80211_DEBUGFS |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 248247877eb..ab63237107c 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -325,6 +325,75 @@ static void ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band | |||
325 | 325 | ||
326 | } | 326 | } |
327 | 327 | ||
328 | static void ieee80211_report_used_skb(struct ieee80211_local *local, | ||
329 | struct sk_buff *skb, bool dropped) | ||
330 | { | ||
331 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
332 | struct ieee80211_hdr *hdr = (void *)skb->data; | ||
333 | bool acked = info->flags & IEEE80211_TX_STAT_ACK; | ||
334 | |||
335 | if (dropped) | ||
336 | acked = false; | ||
337 | |||
338 | if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) { | ||
339 | struct ieee80211_sub_if_data *sdata = NULL; | ||
340 | struct ieee80211_sub_if_data *iter_sdata; | ||
341 | u64 cookie = (unsigned long)skb; | ||
342 | |||
343 | rcu_read_lock(); | ||
344 | |||
345 | if (skb->dev) { | ||
346 | list_for_each_entry_rcu(iter_sdata, &local->interfaces, | ||
347 | list) { | ||
348 | if (!iter_sdata->dev) | ||
349 | continue; | ||
350 | |||
351 | if (skb->dev == iter_sdata->dev) { | ||
352 | sdata = iter_sdata; | ||
353 | break; | ||
354 | } | ||
355 | } | ||
356 | } else { | ||
357 | sdata = rcu_dereference(local->p2p_sdata); | ||
358 | } | ||
359 | |||
360 | if (!sdata) | ||
361 | skb->dev = NULL; | ||
362 | else if (ieee80211_is_nullfunc(hdr->frame_control) || | ||
363 | ieee80211_is_qos_nullfunc(hdr->frame_control)) { | ||
364 | cfg80211_probe_status(sdata->dev, hdr->addr1, | ||
365 | cookie, acked, GFP_ATOMIC); | ||
366 | } else { | ||
367 | cfg80211_mgmt_tx_status(&sdata->wdev, cookie, skb->data, | ||
368 | skb->len, acked, GFP_ATOMIC); | ||
369 | } | ||
370 | |||
371 | rcu_read_unlock(); | ||
372 | } | ||
373 | |||
374 | if (unlikely(info->ack_frame_id)) { | ||
375 | struct sk_buff *ack_skb; | ||
376 | unsigned long flags; | ||
377 | |||
378 | spin_lock_irqsave(&local->ack_status_lock, flags); | ||
379 | ack_skb = idr_find(&local->ack_status_frames, | ||
380 | info->ack_frame_id); | ||
381 | if (ack_skb) | ||
382 | idr_remove(&local->ack_status_frames, | ||
383 | info->ack_frame_id); | ||
384 | spin_unlock_irqrestore(&local->ack_status_lock, flags); | ||
385 | |||
386 | if (ack_skb) { | ||
387 | if (!dropped) { | ||
388 | /* consumes ack_skb */ | ||
389 | skb_complete_wifi_ack(ack_skb, acked); | ||
390 | } else { | ||
391 | dev_kfree_skb_any(ack_skb); | ||
392 | } | ||
393 | } | ||
394 | } | ||
395 | } | ||
396 | |||
328 | /* | 397 | /* |
329 | * Use a static threshold for now, best value to be determined | 398 | * Use a static threshold for now, best value to be determined |
330 | * by testing ... | 399 | * by testing ... |
@@ -516,62 +585,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
516 | msecs_to_jiffies(10)); | 585 | msecs_to_jiffies(10)); |
517 | } | 586 | } |
518 | 587 | ||
519 | if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) { | 588 | ieee80211_report_used_skb(local, skb, false); |
520 | u64 cookie = (unsigned long)skb; | ||
521 | bool found = false; | ||
522 | |||
523 | acked = info->flags & IEEE80211_TX_STAT_ACK; | ||
524 | |||
525 | rcu_read_lock(); | ||
526 | |||
527 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | ||
528 | if (!sdata->dev) | ||
529 | continue; | ||
530 | |||
531 | if (skb->dev != sdata->dev) | ||
532 | continue; | ||
533 | |||
534 | found = true; | ||
535 | break; | ||
536 | } | ||
537 | |||
538 | if (!skb->dev) { | ||
539 | sdata = rcu_dereference(local->p2p_sdata); | ||
540 | if (sdata) | ||
541 | found = true; | ||
542 | } | ||
543 | |||
544 | if (!found) | ||
545 | skb->dev = NULL; | ||
546 | else if (ieee80211_is_nullfunc(hdr->frame_control) || | ||
547 | ieee80211_is_qos_nullfunc(hdr->frame_control)) { | ||
548 | cfg80211_probe_status(sdata->dev, hdr->addr1, | ||
549 | cookie, acked, GFP_ATOMIC); | ||
550 | } else { | ||
551 | cfg80211_mgmt_tx_status(&sdata->wdev, cookie, skb->data, | ||
552 | skb->len, acked, GFP_ATOMIC); | ||
553 | } | ||
554 | |||
555 | rcu_read_unlock(); | ||
556 | } | ||
557 | |||
558 | if (unlikely(info->ack_frame_id)) { | ||
559 | struct sk_buff *ack_skb; | ||
560 | unsigned long flags; | ||
561 | |||
562 | spin_lock_irqsave(&local->ack_status_lock, flags); | ||
563 | ack_skb = idr_find(&local->ack_status_frames, | ||
564 | info->ack_frame_id); | ||
565 | if (ack_skb) | ||
566 | idr_remove(&local->ack_status_frames, | ||
567 | info->ack_frame_id); | ||
568 | spin_unlock_irqrestore(&local->ack_status_lock, flags); | ||
569 | |||
570 | /* consumes ack_skb */ | ||
571 | if (ack_skb) | ||
572 | skb_complete_wifi_ack(ack_skb, | ||
573 | info->flags & IEEE80211_TX_STAT_ACK); | ||
574 | } | ||
575 | 589 | ||
576 | /* this was a transmitted frame, but now we want to reuse it */ | 590 | /* this was a transmitted frame, but now we want to reuse it */ |
577 | skb_orphan(skb); | 591 | skb_orphan(skb); |
@@ -647,25 +661,8 @@ EXPORT_SYMBOL(ieee80211_report_low_ack); | |||
647 | void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb) | 661 | void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb) |
648 | { | 662 | { |
649 | struct ieee80211_local *local = hw_to_local(hw); | 663 | struct ieee80211_local *local = hw_to_local(hw); |
650 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
651 | |||
652 | if (unlikely(info->ack_frame_id)) { | ||
653 | struct sk_buff *ack_skb; | ||
654 | unsigned long flags; | ||
655 | |||
656 | spin_lock_irqsave(&local->ack_status_lock, flags); | ||
657 | ack_skb = idr_find(&local->ack_status_frames, | ||
658 | info->ack_frame_id); | ||
659 | if (ack_skb) | ||
660 | idr_remove(&local->ack_status_frames, | ||
661 | info->ack_frame_id); | ||
662 | spin_unlock_irqrestore(&local->ack_status_lock, flags); | ||
663 | |||
664 | /* consumes ack_skb */ | ||
665 | if (ack_skb) | ||
666 | dev_kfree_skb_any(ack_skb); | ||
667 | } | ||
668 | 664 | ||
665 | ieee80211_report_used_skb(local, skb, true); | ||
669 | dev_kfree_skb_any(skb); | 666 | dev_kfree_skb_any(skb); |
670 | } | 667 | } |
671 | EXPORT_SYMBOL(ieee80211_free_txskb); | 668 | EXPORT_SYMBOL(ieee80211_free_txskb); |
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index 0638541b625..a8270b441a6 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h | |||
@@ -28,16 +28,21 @@ | |||
28 | #define VIF_PR_FMT " vif:%s(%d%s)" | 28 | #define VIF_PR_FMT " vif:%s(%d%s)" |
29 | #define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : "" | 29 | #define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : "" |
30 | 30 | ||
31 | #define CHANCTX_ENTRY __field(int, freq) \ | 31 | #define CHANCTX_ENTRY __field(u32, control_freq) \ |
32 | __field(int, chantype) \ | 32 | __field(u32, chan_width) \ |
33 | __field(u32, center_freq1) \ | ||
34 | __field(u32, center_freq2) \ | ||
33 | __field(u8, rx_chains_static) \ | 35 | __field(u8, rx_chains_static) \ |
34 | __field(u8, rx_chains_dynamic) | 36 | __field(u8, rx_chains_dynamic) |
35 | #define CHANCTX_ASSIGN __entry->freq = ctx->conf.channel->center_freq; \ | 37 | #define CHANCTX_ASSIGN __entry->control_freq = ctx->conf.def.chan->center_freq;\ |
36 | __entry->chantype = ctx->conf.channel_type; \ | 38 | __entry->chan_width = ctx->conf.def.width; \ |
39 | __entry->center_freq1 = ctx->conf.def.center_freq1; \ | ||
40 | __entry->center_freq2 = ctx->conf.def.center_freq2; \ | ||
37 | __entry->rx_chains_static = ctx->conf.rx_chains_static; \ | 41 | __entry->rx_chains_static = ctx->conf.rx_chains_static; \ |
38 | __entry->rx_chains_dynamic = ctx->conf.rx_chains_dynamic | 42 | __entry->rx_chains_dynamic = ctx->conf.rx_chains_dynamic |
39 | #define CHANCTX_PR_FMT " freq:%d MHz chantype:%d chains:%d/%d" | 43 | #define CHANCTX_PR_FMT " control:%d MHz width:%d center: %d/%d MHz chains:%d/%d" |
40 | #define CHANCTX_PR_ARG __entry->freq, __entry->chantype, \ | 44 | #define CHANCTX_PR_ARG __entry->control_freq, __entry->chan_width, \ |
45 | __entry->center_freq1, __entry->center_freq2, \ | ||
41 | __entry->rx_chains_static, __entry->rx_chains_dynamic | 46 | __entry->rx_chains_static, __entry->rx_chains_dynamic |
42 | 47 | ||
43 | 48 | ||
@@ -334,7 +339,8 @@ TRACE_EVENT(drv_bss_info_changed, | |||
334 | __field(u16, ht_operation_mode) | 339 | __field(u16, ht_operation_mode) |
335 | __field(s32, cqm_rssi_thold); | 340 | __field(s32, cqm_rssi_thold); |
336 | __field(s32, cqm_rssi_hyst); | 341 | __field(s32, cqm_rssi_hyst); |
337 | __field(u32, channel_type); | 342 | __field(u32, channel_width); |
343 | __field(u32, channel_cfreq1); | ||
338 | __dynamic_array(u32, arp_addr_list, info->arp_addr_cnt); | 344 | __dynamic_array(u32, arp_addr_list, info->arp_addr_cnt); |
339 | __field(bool, arp_filter_enabled); | 345 | __field(bool, arp_filter_enabled); |
340 | __field(bool, qos); | 346 | __field(bool, qos); |
@@ -342,6 +348,9 @@ TRACE_EVENT(drv_bss_info_changed, | |||
342 | __field(bool, ps); | 348 | __field(bool, ps); |
343 | __dynamic_array(u8, ssid, info->ssid_len); | 349 | __dynamic_array(u8, ssid, info->ssid_len); |
344 | __field(bool, hidden_ssid); | 350 | __field(bool, hidden_ssid); |
351 | __field(int, txpower) | ||
352 | __field(u8, p2p_ctwindow) | ||
353 | __field(bool, p2p_oppps) | ||
345 | ), | 354 | ), |
346 | 355 | ||
347 | TP_fast_assign( | 356 | TP_fast_assign( |
@@ -367,7 +376,8 @@ TRACE_EVENT(drv_bss_info_changed, | |||
367 | __entry->ht_operation_mode = info->ht_operation_mode; | 376 | __entry->ht_operation_mode = info->ht_operation_mode; |
368 | __entry->cqm_rssi_thold = info->cqm_rssi_thold; | 377 | __entry->cqm_rssi_thold = info->cqm_rssi_thold; |
369 | __entry->cqm_rssi_hyst = info->cqm_rssi_hyst; | 378 | __entry->cqm_rssi_hyst = info->cqm_rssi_hyst; |
370 | __entry->channel_type = info->channel_type; | 379 | __entry->channel_width = info->chandef.width; |
380 | __entry->channel_cfreq1 = info->chandef.center_freq1; | ||
371 | memcpy(__get_dynamic_array(arp_addr_list), info->arp_addr_list, | 381 | memcpy(__get_dynamic_array(arp_addr_list), info->arp_addr_list, |
372 | sizeof(u32) * info->arp_addr_cnt); | 382 | sizeof(u32) * info->arp_addr_cnt); |
373 | __entry->arp_filter_enabled = info->arp_filter_enabled; | 383 | __entry->arp_filter_enabled = info->arp_filter_enabled; |
@@ -376,6 +386,9 @@ TRACE_EVENT(drv_bss_info_changed, | |||
376 | __entry->ps = info->ps; | 386 | __entry->ps = info->ps; |
377 | memcpy(__get_dynamic_array(ssid), info->ssid, info->ssid_len); | 387 | memcpy(__get_dynamic_array(ssid), info->ssid, info->ssid_len); |
378 | __entry->hidden_ssid = info->hidden_ssid; | 388 | __entry->hidden_ssid = info->hidden_ssid; |
389 | __entry->txpower = info->txpower; | ||
390 | __entry->p2p_ctwindow = info->p2p_ctwindow; | ||
391 | __entry->p2p_oppps = info->p2p_oppps; | ||
379 | ), | 392 | ), |
380 | 393 | ||
381 | TP_printk( | 394 | TP_printk( |
@@ -1013,28 +1026,31 @@ TRACE_EVENT(drv_get_antenna, | |||
1013 | ); | 1026 | ); |
1014 | 1027 | ||
1015 | TRACE_EVENT(drv_remain_on_channel, | 1028 | TRACE_EVENT(drv_remain_on_channel, |
1016 | TP_PROTO(struct ieee80211_local *local, struct ieee80211_channel *chan, | 1029 | TP_PROTO(struct ieee80211_local *local, |
1017 | enum nl80211_channel_type chantype, unsigned int duration), | 1030 | struct ieee80211_sub_if_data *sdata, |
1031 | struct ieee80211_channel *chan, | ||
1032 | unsigned int duration), | ||
1018 | 1033 | ||
1019 | TP_ARGS(local, chan, chantype, duration), | 1034 | TP_ARGS(local, sdata, chan, duration), |
1020 | 1035 | ||
1021 | TP_STRUCT__entry( | 1036 | TP_STRUCT__entry( |
1022 | LOCAL_ENTRY | 1037 | LOCAL_ENTRY |
1038 | VIF_ENTRY | ||
1023 | __field(int, center_freq) | 1039 | __field(int, center_freq) |
1024 | __field(int, channel_type) | ||
1025 | __field(unsigned int, duration) | 1040 | __field(unsigned int, duration) |
1026 | ), | 1041 | ), |
1027 | 1042 | ||
1028 | TP_fast_assign( | 1043 | TP_fast_assign( |
1029 | LOCAL_ASSIGN; | 1044 | LOCAL_ASSIGN; |
1045 | VIF_ASSIGN; | ||
1030 | __entry->center_freq = chan->center_freq; | 1046 | __entry->center_freq = chan->center_freq; |
1031 | __entry->channel_type = chantype; | ||
1032 | __entry->duration = duration; | 1047 | __entry->duration = duration; |
1033 | ), | 1048 | ), |
1034 | 1049 | ||
1035 | TP_printk( | 1050 | TP_printk( |
1036 | LOCAL_PR_FMT " freq:%dMHz duration:%dms", | 1051 | LOCAL_PR_FMT VIF_PR_FMT " freq:%dMHz duration:%dms", |
1037 | LOCAL_PR_ARG, __entry->center_freq, __entry->duration | 1052 | LOCAL_PR_ARG, VIF_PR_ARG, |
1053 | __entry->center_freq, __entry->duration | ||
1038 | ) | 1054 | ) |
1039 | ); | 1055 | ); |
1040 | 1056 | ||
@@ -1043,34 +1059,6 @@ DEFINE_EVENT(local_only_evt, drv_cancel_remain_on_channel, | |||
1043 | TP_ARGS(local) | 1059 | TP_ARGS(local) |
1044 | ); | 1060 | ); |
1045 | 1061 | ||
1046 | TRACE_EVENT(drv_offchannel_tx, | ||
1047 | TP_PROTO(struct ieee80211_local *local, struct sk_buff *skb, | ||
1048 | struct ieee80211_channel *chan, | ||
1049 | enum nl80211_channel_type channel_type, | ||
1050 | unsigned int wait), | ||
1051 | |||
1052 | TP_ARGS(local, skb, chan, channel_type, wait), | ||
1053 | |||
1054 | TP_STRUCT__entry( | ||
1055 | LOCAL_ENTRY | ||
1056 | __field(int, center_freq) | ||
1057 | __field(int, channel_type) | ||
1058 | __field(unsigned int, wait) | ||
1059 | ), | ||
1060 | |||
1061 | TP_fast_assign( | ||
1062 | LOCAL_ASSIGN; | ||
1063 | __entry->center_freq = chan->center_freq; | ||
1064 | __entry->channel_type = channel_type; | ||
1065 | __entry->wait = wait; | ||
1066 | ), | ||
1067 | |||
1068 | TP_printk( | ||
1069 | LOCAL_PR_FMT " freq:%dMHz, wait:%dms", | ||
1070 | LOCAL_PR_ARG, __entry->center_freq, __entry->wait | ||
1071 | ) | ||
1072 | ); | ||
1073 | |||
1074 | TRACE_EVENT(drv_set_ringparam, | 1062 | TRACE_EVENT(drv_set_ringparam, |
1075 | TP_PROTO(struct ieee80211_local *local, u32 tx, u32 rx), | 1063 | TP_PROTO(struct ieee80211_local *local, u32 tx, u32 rx), |
1076 | 1064 | ||
@@ -1396,6 +1384,48 @@ DEFINE_EVENT(local_sdata_chanctx, drv_unassign_vif_chanctx, | |||
1396 | TP_ARGS(local, sdata, ctx) | 1384 | TP_ARGS(local, sdata, ctx) |
1397 | ); | 1385 | ); |
1398 | 1386 | ||
1387 | TRACE_EVENT(drv_start_ap, | ||
1388 | TP_PROTO(struct ieee80211_local *local, | ||
1389 | struct ieee80211_sub_if_data *sdata, | ||
1390 | struct ieee80211_bss_conf *info), | ||
1391 | |||
1392 | TP_ARGS(local, sdata, info), | ||
1393 | |||
1394 | TP_STRUCT__entry( | ||
1395 | LOCAL_ENTRY | ||
1396 | VIF_ENTRY | ||
1397 | __field(u8, dtimper) | ||
1398 | __field(u16, bcnint) | ||
1399 | __dynamic_array(u8, ssid, info->ssid_len); | ||
1400 | __field(bool, hidden_ssid); | ||
1401 | ), | ||
1402 | |||
1403 | TP_fast_assign( | ||
1404 | LOCAL_ASSIGN; | ||
1405 | VIF_ASSIGN; | ||
1406 | __entry->dtimper = info->dtim_period; | ||
1407 | __entry->bcnint = info->beacon_int; | ||
1408 | memcpy(__get_dynamic_array(ssid), info->ssid, info->ssid_len); | ||
1409 | __entry->hidden_ssid = info->hidden_ssid; | ||
1410 | ), | ||
1411 | |||
1412 | TP_printk( | ||
1413 | LOCAL_PR_FMT VIF_PR_FMT, | ||
1414 | LOCAL_PR_ARG, VIF_PR_ARG | ||
1415 | ) | ||
1416 | ); | ||
1417 | |||
1418 | DEFINE_EVENT(local_sdata_evt, drv_stop_ap, | ||
1419 | TP_PROTO(struct ieee80211_local *local, | ||
1420 | struct ieee80211_sub_if_data *sdata), | ||
1421 | TP_ARGS(local, sdata) | ||
1422 | ); | ||
1423 | |||
1424 | DEFINE_EVENT(local_only_evt, drv_restart_complete, | ||
1425 | TP_PROTO(struct ieee80211_local *local), | ||
1426 | TP_ARGS(local) | ||
1427 | ); | ||
1428 | |||
1399 | /* | 1429 | /* |
1400 | * Tracing for API calls that drivers call. | 1430 | * Tracing for API calls that drivers call. |
1401 | */ | 1431 | */ |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 6f1981816dc..d287a4f2c01 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1676,7 +1676,7 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, | |||
1676 | if (!chanctx_conf) | 1676 | if (!chanctx_conf) |
1677 | goto fail_rcu; | 1677 | goto fail_rcu; |
1678 | 1678 | ||
1679 | chan = chanctx_conf->channel; | 1679 | chan = chanctx_conf->def.chan; |
1680 | 1680 | ||
1681 | /* | 1681 | /* |
1682 | * Frame injection is not allowed if beaconing is not allowed | 1682 | * Frame injection is not allowed if beaconing is not allowed |
@@ -1779,7 +1779,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1779 | chanctx_conf = rcu_dereference(ap_sdata->vif.chanctx_conf); | 1779 | chanctx_conf = rcu_dereference(ap_sdata->vif.chanctx_conf); |
1780 | if (!chanctx_conf) | 1780 | if (!chanctx_conf) |
1781 | goto fail_rcu; | 1781 | goto fail_rcu; |
1782 | band = chanctx_conf->channel->band; | 1782 | band = chanctx_conf->def.chan->band; |
1783 | if (sta) | 1783 | if (sta) |
1784 | break; | 1784 | break; |
1785 | /* fall through */ | 1785 | /* fall through */ |
@@ -1794,7 +1794,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1794 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 1794 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
1795 | if (!chanctx_conf) | 1795 | if (!chanctx_conf) |
1796 | goto fail_rcu; | 1796 | goto fail_rcu; |
1797 | band = chanctx_conf->channel->band; | 1797 | band = chanctx_conf->def.chan->band; |
1798 | break; | 1798 | break; |
1799 | case NL80211_IFTYPE_WDS: | 1799 | case NL80211_IFTYPE_WDS: |
1800 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); | 1800 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); |
@@ -1871,7 +1871,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1871 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 1871 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
1872 | if (!chanctx_conf) | 1872 | if (!chanctx_conf) |
1873 | goto fail_rcu; | 1873 | goto fail_rcu; |
1874 | band = chanctx_conf->channel->band; | 1874 | band = chanctx_conf->def.chan->band; |
1875 | break; | 1875 | break; |
1876 | #endif | 1876 | #endif |
1877 | case NL80211_IFTYPE_STATION: | 1877 | case NL80211_IFTYPE_STATION: |
@@ -1930,7 +1930,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1930 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 1930 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
1931 | if (!chanctx_conf) | 1931 | if (!chanctx_conf) |
1932 | goto fail_rcu; | 1932 | goto fail_rcu; |
1933 | band = chanctx_conf->channel->band; | 1933 | band = chanctx_conf->def.chan->band; |
1934 | break; | 1934 | break; |
1935 | case NL80211_IFTYPE_ADHOC: | 1935 | case NL80211_IFTYPE_ADHOC: |
1936 | /* DA SA BSSID */ | 1936 | /* DA SA BSSID */ |
@@ -1941,7 +1941,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1941 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 1941 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
1942 | if (!chanctx_conf) | 1942 | if (!chanctx_conf) |
1943 | goto fail_rcu; | 1943 | goto fail_rcu; |
1944 | band = chanctx_conf->channel->band; | 1944 | band = chanctx_conf->def.chan->band; |
1945 | break; | 1945 | break; |
1946 | default: | 1946 | default: |
1947 | goto fail_rcu; | 1947 | goto fail_rcu; |
@@ -2089,6 +2089,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
2089 | head_need = max_t(int, 0, head_need); | 2089 | head_need = max_t(int, 0, head_need); |
2090 | if (ieee80211_skb_resize(sdata, skb, head_need, true)) { | 2090 | if (ieee80211_skb_resize(sdata, skb, head_need, true)) { |
2091 | ieee80211_free_txskb(&local->hw, skb); | 2091 | ieee80211_free_txskb(&local->hw, skb); |
2092 | skb = NULL; | ||
2092 | goto fail_rcu; | 2093 | goto fail_rcu; |
2093 | } | 2094 | } |
2094 | } | 2095 | } |
@@ -2193,7 +2194,7 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local, | |||
2193 | return true; | 2194 | return true; |
2194 | } | 2195 | } |
2195 | result = ieee80211_tx(sdata, skb, true, | 2196 | result = ieee80211_tx(sdata, skb, true, |
2196 | chanctx_conf->channel->band); | 2197 | chanctx_conf->def.chan->band); |
2197 | } else { | 2198 | } else { |
2198 | struct sk_buff_head skbs; | 2199 | struct sk_buff_head skbs; |
2199 | 2200 | ||
@@ -2457,7 +2458,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2457 | *pos++ = WLAN_EID_SSID; | 2458 | *pos++ = WLAN_EID_SSID; |
2458 | *pos++ = 0x0; | 2459 | *pos++ = 0x0; |
2459 | 2460 | ||
2460 | band = chanctx_conf->channel->band; | 2461 | band = chanctx_conf->def.chan->band; |
2461 | 2462 | ||
2462 | if (ieee80211_add_srates_ie(sdata, skb, true, band) || | 2463 | if (ieee80211_add_srates_ie(sdata, skb, true, band) || |
2463 | mesh_add_ds_params_ie(skb, sdata) || | 2464 | mesh_add_ds_params_ie(skb, sdata) || |
@@ -2476,7 +2477,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2476 | goto out; | 2477 | goto out; |
2477 | } | 2478 | } |
2478 | 2479 | ||
2479 | band = chanctx_conf->channel->band; | 2480 | band = chanctx_conf->def.chan->band; |
2480 | 2481 | ||
2481 | info = IEEE80211_SKB_CB(skb); | 2482 | info = IEEE80211_SKB_CB(skb); |
2482 | 2483 | ||
@@ -2756,7 +2757,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | |||
2756 | info = IEEE80211_SKB_CB(skb); | 2757 | info = IEEE80211_SKB_CB(skb); |
2757 | 2758 | ||
2758 | tx.flags |= IEEE80211_TX_PS_BUFFERED; | 2759 | tx.flags |= IEEE80211_TX_PS_BUFFERED; |
2759 | info->band = chanctx_conf->channel->band; | 2760 | info->band = chanctx_conf->def.chan->band; |
2760 | 2761 | ||
2761 | if (invoke_tx_handlers(&tx)) | 2762 | if (invoke_tx_handlers(&tx)) |
2762 | skb = NULL; | 2763 | skb = NULL; |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index acbb8c9bae2..08132ff9815 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -512,7 +512,7 @@ void ieee80211_wake_queues(struct ieee80211_hw *hw) | |||
512 | EXPORT_SYMBOL(ieee80211_wake_queues); | 512 | EXPORT_SYMBOL(ieee80211_wake_queues); |
513 | 513 | ||
514 | void ieee80211_iterate_active_interfaces( | 514 | void ieee80211_iterate_active_interfaces( |
515 | struct ieee80211_hw *hw, | 515 | struct ieee80211_hw *hw, u32 iter_flags, |
516 | void (*iterator)(void *data, u8 *mac, | 516 | void (*iterator)(void *data, u8 *mac, |
517 | struct ieee80211_vif *vif), | 517 | struct ieee80211_vif *vif), |
518 | void *data) | 518 | void *data) |
@@ -530,6 +530,9 @@ void ieee80211_iterate_active_interfaces( | |||
530 | default: | 530 | default: |
531 | break; | 531 | break; |
532 | } | 532 | } |
533 | if (!(iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL) && | ||
534 | !(sdata->flags & IEEE80211_SDATA_IN_DRIVER)) | ||
535 | continue; | ||
533 | if (ieee80211_sdata_running(sdata)) | 536 | if (ieee80211_sdata_running(sdata)) |
534 | iterator(data, sdata->vif.addr, | 537 | iterator(data, sdata->vif.addr, |
535 | &sdata->vif); | 538 | &sdata->vif); |
@@ -537,7 +540,9 @@ void ieee80211_iterate_active_interfaces( | |||
537 | 540 | ||
538 | sdata = rcu_dereference_protected(local->monitor_sdata, | 541 | sdata = rcu_dereference_protected(local->monitor_sdata, |
539 | lockdep_is_held(&local->iflist_mtx)); | 542 | lockdep_is_held(&local->iflist_mtx)); |
540 | if (sdata) | 543 | if (sdata && |
544 | (iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL || | ||
545 | sdata->flags & IEEE80211_SDATA_IN_DRIVER)) | ||
541 | iterator(data, sdata->vif.addr, &sdata->vif); | 546 | iterator(data, sdata->vif.addr, &sdata->vif); |
542 | 547 | ||
543 | mutex_unlock(&local->iflist_mtx); | 548 | mutex_unlock(&local->iflist_mtx); |
@@ -545,7 +550,7 @@ void ieee80211_iterate_active_interfaces( | |||
545 | EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces); | 550 | EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces); |
546 | 551 | ||
547 | void ieee80211_iterate_active_interfaces_atomic( | 552 | void ieee80211_iterate_active_interfaces_atomic( |
548 | struct ieee80211_hw *hw, | 553 | struct ieee80211_hw *hw, u32 iter_flags, |
549 | void (*iterator)(void *data, u8 *mac, | 554 | void (*iterator)(void *data, u8 *mac, |
550 | struct ieee80211_vif *vif), | 555 | struct ieee80211_vif *vif), |
551 | void *data) | 556 | void *data) |
@@ -563,13 +568,18 @@ void ieee80211_iterate_active_interfaces_atomic( | |||
563 | default: | 568 | default: |
564 | break; | 569 | break; |
565 | } | 570 | } |
571 | if (!(iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL) && | ||
572 | !(sdata->flags & IEEE80211_SDATA_IN_DRIVER)) | ||
573 | continue; | ||
566 | if (ieee80211_sdata_running(sdata)) | 574 | if (ieee80211_sdata_running(sdata)) |
567 | iterator(data, sdata->vif.addr, | 575 | iterator(data, sdata->vif.addr, |
568 | &sdata->vif); | 576 | &sdata->vif); |
569 | } | 577 | } |
570 | 578 | ||
571 | sdata = rcu_dereference(local->monitor_sdata); | 579 | sdata = rcu_dereference(local->monitor_sdata); |
572 | if (sdata) | 580 | if (sdata && |
581 | (iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL || | ||
582 | sdata->flags & IEEE80211_SDATA_IN_DRIVER)) | ||
573 | iterator(data, sdata->vif.addr, &sdata->vif); | 583 | iterator(data, sdata->vif.addr, &sdata->vif); |
574 | 584 | ||
575 | rcu_read_unlock(); | 585 | rcu_read_unlock(); |
@@ -888,7 +898,7 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, | |||
888 | rcu_read_lock(); | 898 | rcu_read_lock(); |
889 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 899 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
890 | use_11b = (chanctx_conf && | 900 | use_11b = (chanctx_conf && |
891 | chanctx_conf->channel->band == IEEE80211_BAND_2GHZ) && | 901 | chanctx_conf->def.chan->band == IEEE80211_BAND_2GHZ) && |
892 | !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE); | 902 | !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE); |
893 | rcu_read_unlock(); | 903 | rcu_read_unlock(); |
894 | 904 | ||
@@ -981,7 +991,7 @@ void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, | |||
981 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 991 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
982 | 992 | ||
983 | if (chanctx_conf && | 993 | if (chanctx_conf && |
984 | chanctx_conf->channel->band == IEEE80211_BAND_2GHZ && | 994 | chanctx_conf->def.chan->band == IEEE80211_BAND_2GHZ && |
985 | have_higher_than_11mbit) | 995 | have_higher_than_11mbit) |
986 | sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; | 996 | sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; |
987 | else | 997 | else |
@@ -1407,10 +1417,44 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1407 | } | 1417 | } |
1408 | 1418 | ||
1409 | /* add channel contexts */ | 1419 | /* add channel contexts */ |
1410 | mutex_lock(&local->chanctx_mtx); | 1420 | if (local->use_chanctx) { |
1411 | list_for_each_entry(ctx, &local->chanctx_list, list) | 1421 | mutex_lock(&local->chanctx_mtx); |
1412 | WARN_ON(drv_add_chanctx(local, ctx)); | 1422 | list_for_each_entry(ctx, &local->chanctx_list, list) |
1413 | mutex_unlock(&local->chanctx_mtx); | 1423 | WARN_ON(drv_add_chanctx(local, ctx)); |
1424 | mutex_unlock(&local->chanctx_mtx); | ||
1425 | } | ||
1426 | |||
1427 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
1428 | struct ieee80211_chanctx_conf *ctx_conf; | ||
1429 | |||
1430 | if (!ieee80211_sdata_running(sdata)) | ||
1431 | continue; | ||
1432 | |||
1433 | mutex_lock(&local->chanctx_mtx); | ||
1434 | ctx_conf = rcu_dereference_protected(sdata->vif.chanctx_conf, | ||
1435 | lockdep_is_held(&local->chanctx_mtx)); | ||
1436 | if (ctx_conf) { | ||
1437 | ctx = container_of(ctx_conf, struct ieee80211_chanctx, | ||
1438 | conf); | ||
1439 | drv_assign_vif_chanctx(local, sdata, ctx); | ||
1440 | } | ||
1441 | mutex_unlock(&local->chanctx_mtx); | ||
1442 | } | ||
1443 | |||
1444 | sdata = rtnl_dereference(local->monitor_sdata); | ||
1445 | if (sdata && local->use_chanctx && ieee80211_sdata_running(sdata)) { | ||
1446 | struct ieee80211_chanctx_conf *ctx_conf; | ||
1447 | |||
1448 | mutex_lock(&local->chanctx_mtx); | ||
1449 | ctx_conf = rcu_dereference_protected(sdata->vif.chanctx_conf, | ||
1450 | lockdep_is_held(&local->chanctx_mtx)); | ||
1451 | if (ctx_conf) { | ||
1452 | ctx = container_of(ctx_conf, struct ieee80211_chanctx, | ||
1453 | conf); | ||
1454 | drv_assign_vif_chanctx(local, sdata, ctx); | ||
1455 | } | ||
1456 | mutex_unlock(&local->chanctx_mtx); | ||
1457 | } | ||
1414 | 1458 | ||
1415 | /* add STAs back */ | 1459 | /* add STAs back */ |
1416 | mutex_lock(&local->sta_mtx); | 1460 | mutex_lock(&local->sta_mtx); |
@@ -1452,22 +1496,11 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1452 | 1496 | ||
1453 | /* Finally also reconfigure all the BSS information */ | 1497 | /* Finally also reconfigure all the BSS information */ |
1454 | list_for_each_entry(sdata, &local->interfaces, list) { | 1498 | list_for_each_entry(sdata, &local->interfaces, list) { |
1455 | struct ieee80211_chanctx_conf *ctx_conf; | ||
1456 | u32 changed; | 1499 | u32 changed; |
1457 | 1500 | ||
1458 | if (!ieee80211_sdata_running(sdata)) | 1501 | if (!ieee80211_sdata_running(sdata)) |
1459 | continue; | 1502 | continue; |
1460 | 1503 | ||
1461 | mutex_lock(&local->chanctx_mtx); | ||
1462 | ctx_conf = rcu_dereference_protected(sdata->vif.chanctx_conf, | ||
1463 | lockdep_is_held(&local->chanctx_mtx)); | ||
1464 | if (ctx_conf) { | ||
1465 | ctx = container_of(ctx_conf, struct ieee80211_chanctx, | ||
1466 | conf); | ||
1467 | drv_assign_vif_chanctx(local, sdata, ctx); | ||
1468 | } | ||
1469 | mutex_unlock(&local->chanctx_mtx); | ||
1470 | |||
1471 | /* common change flags for all interface types */ | 1504 | /* common change flags for all interface types */ |
1472 | changed = BSS_CHANGED_ERP_CTS_PROT | | 1505 | changed = BSS_CHANGED_ERP_CTS_PROT | |
1473 | BSS_CHANGED_ERP_PREAMBLE | | 1506 | BSS_CHANGED_ERP_PREAMBLE | |
@@ -1478,7 +1511,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1478 | BSS_CHANGED_BSSID | | 1511 | BSS_CHANGED_BSSID | |
1479 | BSS_CHANGED_CQM | | 1512 | BSS_CHANGED_CQM | |
1480 | BSS_CHANGED_QOS | | 1513 | BSS_CHANGED_QOS | |
1481 | BSS_CHANGED_IDLE; | 1514 | BSS_CHANGED_IDLE | |
1515 | BSS_CHANGED_TXPOWER; | ||
1482 | 1516 | ||
1483 | switch (sdata->vif.type) { | 1517 | switch (sdata->vif.type) { |
1484 | case NL80211_IFTYPE_STATION: | 1518 | case NL80211_IFTYPE_STATION: |
@@ -1495,9 +1529,13 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1495 | case NL80211_IFTYPE_AP: | 1529 | case NL80211_IFTYPE_AP: |
1496 | changed |= BSS_CHANGED_SSID; | 1530 | changed |= BSS_CHANGED_SSID; |
1497 | 1531 | ||
1498 | if (sdata->vif.type == NL80211_IFTYPE_AP) | 1532 | if (sdata->vif.type == NL80211_IFTYPE_AP) { |
1499 | changed |= BSS_CHANGED_AP_PROBE_RESP; | 1533 | changed |= BSS_CHANGED_AP_PROBE_RESP; |
1500 | 1534 | ||
1535 | if (rcu_access_pointer(sdata->u.ap.beacon)) | ||
1536 | drv_start_ap(local, sdata); | ||
1537 | } | ||
1538 | |||
1501 | /* fall through */ | 1539 | /* fall through */ |
1502 | case NL80211_IFTYPE_MESH_POINT: | 1540 | case NL80211_IFTYPE_MESH_POINT: |
1503 | changed |= BSS_CHANGED_BEACON | | 1541 | changed |= BSS_CHANGED_BEACON | |
@@ -1596,8 +1634,10 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1596 | * If this is for hw restart things are still running. | 1634 | * If this is for hw restart things are still running. |
1597 | * We may want to change that later, however. | 1635 | * We may want to change that later, however. |
1598 | */ | 1636 | */ |
1599 | if (!local->suspended) | 1637 | if (!local->suspended) { |
1638 | drv_restart_complete(local); | ||
1600 | return 0; | 1639 | return 0; |
1640 | } | ||
1601 | 1641 | ||
1602 | #ifdef CONFIG_PM | 1642 | #ifdef CONFIG_PM |
1603 | /* first set suspended false, then resuming */ | 1643 | /* first set suspended false, then resuming */ |
@@ -1833,8 +1873,7 @@ u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, | |||
1833 | } | 1873 | } |
1834 | 1874 | ||
1835 | u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, | 1875 | u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, |
1836 | struct ieee80211_channel *channel, | 1876 | const struct cfg80211_chan_def *chandef, |
1837 | enum nl80211_channel_type channel_type, | ||
1838 | u16 prot_mode) | 1877 | u16 prot_mode) |
1839 | { | 1878 | { |
1840 | struct ieee80211_ht_operation *ht_oper; | 1879 | struct ieee80211_ht_operation *ht_oper; |
@@ -1842,23 +1881,25 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, | |||
1842 | *pos++ = WLAN_EID_HT_OPERATION; | 1881 | *pos++ = WLAN_EID_HT_OPERATION; |
1843 | *pos++ = sizeof(struct ieee80211_ht_operation); | 1882 | *pos++ = sizeof(struct ieee80211_ht_operation); |
1844 | ht_oper = (struct ieee80211_ht_operation *)pos; | 1883 | ht_oper = (struct ieee80211_ht_operation *)pos; |
1845 | ht_oper->primary_chan = | 1884 | ht_oper->primary_chan = ieee80211_frequency_to_channel( |
1846 | ieee80211_frequency_to_channel(channel->center_freq); | 1885 | chandef->chan->center_freq); |
1847 | switch (channel_type) { | 1886 | switch (chandef->width) { |
1848 | case NL80211_CHAN_HT40MINUS: | 1887 | case NL80211_CHAN_WIDTH_160: |
1849 | ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_BELOW; | 1888 | case NL80211_CHAN_WIDTH_80P80: |
1850 | break; | 1889 | case NL80211_CHAN_WIDTH_80: |
1851 | case NL80211_CHAN_HT40PLUS: | 1890 | case NL80211_CHAN_WIDTH_40: |
1852 | ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; | 1891 | if (chandef->center_freq1 > chandef->chan->center_freq) |
1892 | ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; | ||
1893 | else | ||
1894 | ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_BELOW; | ||
1853 | break; | 1895 | break; |
1854 | case NL80211_CHAN_HT20: | ||
1855 | default: | 1896 | default: |
1856 | ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE; | 1897 | ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE; |
1857 | break; | 1898 | break; |
1858 | } | 1899 | } |
1859 | if (ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 && | 1900 | if (ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 && |
1860 | channel_type != NL80211_CHAN_NO_HT && | 1901 | chandef->width != NL80211_CHAN_WIDTH_20_NOHT && |
1861 | channel_type != NL80211_CHAN_HT20) | 1902 | chandef->width != NL80211_CHAN_WIDTH_20) |
1862 | ht_oper->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY; | 1903 | ht_oper->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY; |
1863 | 1904 | ||
1864 | ht_oper->operation_mode = cpu_to_le16(prot_mode); | 1905 | ht_oper->operation_mode = cpu_to_le16(prot_mode); |
@@ -1872,13 +1913,17 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, | |||
1872 | return pos + sizeof(struct ieee80211_ht_operation); | 1913 | return pos + sizeof(struct ieee80211_ht_operation); |
1873 | } | 1914 | } |
1874 | 1915 | ||
1875 | enum nl80211_channel_type | 1916 | void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan, |
1876 | ieee80211_ht_oper_to_channel_type(struct ieee80211_ht_operation *ht_oper) | 1917 | struct ieee80211_ht_operation *ht_oper, |
1918 | struct cfg80211_chan_def *chandef) | ||
1877 | { | 1919 | { |
1878 | enum nl80211_channel_type channel_type; | 1920 | enum nl80211_channel_type channel_type; |
1879 | 1921 | ||
1880 | if (!ht_oper) | 1922 | if (!ht_oper) { |
1881 | return NL80211_CHAN_NO_HT; | 1923 | cfg80211_chandef_create(chandef, control_chan, |
1924 | NL80211_CHAN_NO_HT); | ||
1925 | return; | ||
1926 | } | ||
1882 | 1927 | ||
1883 | switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { | 1928 | switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { |
1884 | case IEEE80211_HT_PARAM_CHA_SEC_NONE: | 1929 | case IEEE80211_HT_PARAM_CHA_SEC_NONE: |
@@ -1894,7 +1939,7 @@ ieee80211_ht_oper_to_channel_type(struct ieee80211_ht_operation *ht_oper) | |||
1894 | channel_type = NL80211_CHAN_NO_HT; | 1939 | channel_type = NL80211_CHAN_NO_HT; |
1895 | } | 1940 | } |
1896 | 1941 | ||
1897 | return channel_type; | 1942 | cfg80211_chandef_create(chandef, control_chan, channel_type); |
1898 | } | 1943 | } |
1899 | 1944 | ||
1900 | int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, | 1945 | int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, |
@@ -1992,3 +2037,68 @@ u8 ieee80211_mcs_to_chains(const struct ieee80211_mcs_info *mcs) | |||
1992 | return 2; | 2037 | return 2; |
1993 | return 1; | 2038 | return 1; |
1994 | } | 2039 | } |
2040 | |||
2041 | /** | ||
2042 | * ieee80211_calculate_rx_timestamp - calculate timestamp in frame | ||
2043 | * @local: mac80211 hw info struct | ||
2044 | * @status: RX status | ||
2045 | * @mpdu_len: total MPDU length (including FCS) | ||
2046 | * @mpdu_offset: offset into MPDU to calculate timestamp at | ||
2047 | * | ||
2048 | * This function calculates the RX timestamp at the given MPDU offset, taking | ||
2049 | * into account what the RX timestamp was. An offset of 0 will just normalize | ||
2050 | * the timestamp to TSF at beginning of MPDU reception. | ||
2051 | */ | ||
2052 | u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local, | ||
2053 | struct ieee80211_rx_status *status, | ||
2054 | unsigned int mpdu_len, | ||
2055 | unsigned int mpdu_offset) | ||
2056 | { | ||
2057 | u64 ts = status->mactime; | ||
2058 | struct rate_info ri; | ||
2059 | u16 rate; | ||
2060 | |||
2061 | if (WARN_ON(!ieee80211_have_rx_timestamp(status))) | ||
2062 | return 0; | ||
2063 | |||
2064 | memset(&ri, 0, sizeof(ri)); | ||
2065 | |||
2066 | /* Fill cfg80211 rate info */ | ||
2067 | if (status->flag & RX_FLAG_HT) { | ||
2068 | ri.mcs = status->rate_idx; | ||
2069 | ri.flags |= RATE_INFO_FLAGS_MCS; | ||
2070 | if (status->flag & RX_FLAG_40MHZ) | ||
2071 | ri.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | ||
2072 | if (status->flag & RX_FLAG_SHORT_GI) | ||
2073 | ri.flags |= RATE_INFO_FLAGS_SHORT_GI; | ||
2074 | } else if (status->flag & RX_FLAG_VHT) { | ||
2075 | ri.flags |= RATE_INFO_FLAGS_VHT_MCS; | ||
2076 | ri.mcs = status->rate_idx; | ||
2077 | ri.nss = status->vht_nss; | ||
2078 | if (status->flag & RX_FLAG_40MHZ) | ||
2079 | ri.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | ||
2080 | if (status->flag & RX_FLAG_80MHZ) | ||
2081 | ri.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; | ||
2082 | if (status->flag & RX_FLAG_80P80MHZ) | ||
2083 | ri.flags |= RATE_INFO_FLAGS_80P80_MHZ_WIDTH; | ||
2084 | if (status->flag & RX_FLAG_160MHZ) | ||
2085 | ri.flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH; | ||
2086 | if (status->flag & RX_FLAG_SHORT_GI) | ||
2087 | ri.flags |= RATE_INFO_FLAGS_SHORT_GI; | ||
2088 | } else { | ||
2089 | struct ieee80211_supported_band *sband; | ||
2090 | |||
2091 | sband = local->hw.wiphy->bands[status->band]; | ||
2092 | ri.legacy = sband->bitrates[status->rate_idx].bitrate; | ||
2093 | } | ||
2094 | |||
2095 | rate = cfg80211_calculate_bitrate(&ri); | ||
2096 | |||
2097 | /* rewind from end of MPDU */ | ||
2098 | if (status->flag & RX_FLAG_MACTIME_END) | ||
2099 | ts -= mpdu_len * 8 * 10 / rate; | ||
2100 | |||
2101 | ts += mpdu_offset * 8 * 10 / rate; | ||
2102 | |||
2103 | return ts; | ||
2104 | } | ||
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index cea06e9f26f..906f00cd6d2 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c | |||
@@ -160,31 +160,37 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, | |||
160 | return ieee80211_downgrade_queue(sdata, skb); | 160 | return ieee80211_downgrade_queue(sdata, skb); |
161 | } | 161 | } |
162 | 162 | ||
163 | /** | ||
164 | * ieee80211_set_qos_hdr - Fill in the QoS header if there is one. | ||
165 | * | ||
166 | * @sdata: local subif | ||
167 | * @skb: packet to be updated | ||
168 | */ | ||
163 | void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata, | 169 | void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata, |
164 | struct sk_buff *skb) | 170 | struct sk_buff *skb) |
165 | { | 171 | { |
166 | struct ieee80211_hdr *hdr = (void *)skb->data; | 172 | struct ieee80211_hdr *hdr = (void *)skb->data; |
167 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 173 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
174 | u8 *p; | ||
175 | u8 ack_policy, tid; | ||
168 | 176 | ||
169 | /* Fill in the QoS header if there is one. */ | 177 | if (!ieee80211_is_data_qos(hdr->frame_control)) |
170 | if (ieee80211_is_data_qos(hdr->frame_control)) { | 178 | return; |
171 | u8 *p = ieee80211_get_qos_ctl(hdr); | ||
172 | u8 ack_policy, tid; | ||
173 | |||
174 | tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; | ||
175 | 179 | ||
176 | /* preserve EOSP bit */ | 180 | p = ieee80211_get_qos_ctl(hdr); |
177 | ack_policy = *p & IEEE80211_QOS_CTL_EOSP; | 181 | tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; |
178 | 182 | ||
179 | if (is_multicast_ether_addr(hdr->addr1) || | 183 | /* preserve EOSP bit */ |
180 | sdata->noack_map & BIT(tid)) { | 184 | ack_policy = *p & IEEE80211_QOS_CTL_EOSP; |
181 | ack_policy |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK; | ||
182 | info->flags |= IEEE80211_TX_CTL_NO_ACK; | ||
183 | } | ||
184 | 185 | ||
185 | /* qos header is 2 bytes */ | 186 | if (is_multicast_ether_addr(hdr->addr1) || |
186 | *p++ = ack_policy | tid; | 187 | sdata->noack_map & BIT(tid)) { |
187 | *p = ieee80211_vif_is_mesh(&sdata->vif) ? | 188 | ack_policy |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK; |
188 | (IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT >> 8) : 0; | 189 | info->flags |= IEEE80211_TX_CTL_NO_ACK; |
189 | } | 190 | } |
191 | |||
192 | /* qos header is 2 bytes */ | ||
193 | *p++ = ack_policy | tid; | ||
194 | *p = ieee80211_vif_is_mesh(&sdata->vif) ? | ||
195 | (IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT >> 8) : 0; | ||
190 | } | 196 | } |
diff --git a/net/nfc/hci/command.c b/net/nfc/hci/command.c index 07659cfd6d7..7d99410e6c1 100644 --- a/net/nfc/hci/command.c +++ b/net/nfc/hci/command.c | |||
@@ -344,7 +344,7 @@ int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate, | |||
344 | return -EADDRINUSE; | 344 | return -EADDRINUSE; |
345 | 345 | ||
346 | if (pipe != NFC_HCI_INVALID_PIPE) | 346 | if (pipe != NFC_HCI_INVALID_PIPE) |
347 | goto pipe_is_open; | 347 | goto open_pipe; |
348 | 348 | ||
349 | switch (dest_gate) { | 349 | switch (dest_gate) { |
350 | case NFC_HCI_LINK_MGMT_GATE: | 350 | case NFC_HCI_LINK_MGMT_GATE: |
@@ -361,6 +361,7 @@ int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate, | |||
361 | break; | 361 | break; |
362 | } | 362 | } |
363 | 363 | ||
364 | open_pipe: | ||
364 | r = nfc_hci_open_pipe(hdev, pipe); | 365 | r = nfc_hci_open_pipe(hdev, pipe); |
365 | if (r < 0) { | 366 | if (r < 0) { |
366 | if (pipe_created) | 367 | if (pipe_created) |
@@ -371,7 +372,6 @@ int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate, | |||
371 | return r; | 372 | return r; |
372 | } | 373 | } |
373 | 374 | ||
374 | pipe_is_open: | ||
375 | hdev->gate2pipe[dest_gate] = pipe; | 375 | hdev->gate2pipe[dest_gate] = pipe; |
376 | 376 | ||
377 | return 0; | 377 | return 0; |
diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index bc571b0efb9..7bea574d593 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c | |||
@@ -33,17 +33,20 @@ | |||
33 | /* Largest headroom needed for outgoing HCI commands */ | 33 | /* Largest headroom needed for outgoing HCI commands */ |
34 | #define HCI_CMDS_HEADROOM 1 | 34 | #define HCI_CMDS_HEADROOM 1 |
35 | 35 | ||
36 | static int nfc_hci_result_to_errno(u8 result) | 36 | int nfc_hci_result_to_errno(u8 result) |
37 | { | 37 | { |
38 | switch (result) { | 38 | switch (result) { |
39 | case NFC_HCI_ANY_OK: | 39 | case NFC_HCI_ANY_OK: |
40 | return 0; | 40 | return 0; |
41 | case NFC_HCI_ANY_E_REG_PAR_UNKNOWN: | ||
42 | return -EOPNOTSUPP; | ||
41 | case NFC_HCI_ANY_E_TIMEOUT: | 43 | case NFC_HCI_ANY_E_TIMEOUT: |
42 | return -ETIME; | 44 | return -ETIME; |
43 | default: | 45 | default: |
44 | return -1; | 46 | return -1; |
45 | } | 47 | } |
46 | } | 48 | } |
49 | EXPORT_SYMBOL(nfc_hci_result_to_errno); | ||
47 | 50 | ||
48 | static void nfc_hci_msg_tx_work(struct work_struct *work) | 51 | static void nfc_hci_msg_tx_work(struct work_struct *work) |
49 | { | 52 | { |
@@ -167,7 +170,7 @@ void nfc_hci_cmd_received(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd, | |||
167 | kfree_skb(skb); | 170 | kfree_skb(skb); |
168 | } | 171 | } |
169 | 172 | ||
170 | static u32 nfc_hci_sak_to_protocol(u8 sak) | 173 | u32 nfc_hci_sak_to_protocol(u8 sak) |
171 | { | 174 | { |
172 | switch (NFC_HCI_TYPE_A_SEL_PROT(sak)) { | 175 | switch (NFC_HCI_TYPE_A_SEL_PROT(sak)) { |
173 | case NFC_HCI_TYPE_A_SEL_PROT_MIFARE: | 176 | case NFC_HCI_TYPE_A_SEL_PROT_MIFARE: |
@@ -182,6 +185,7 @@ static u32 nfc_hci_sak_to_protocol(u8 sak) | |||
182 | return 0xffffffff; | 185 | return 0xffffffff; |
183 | } | 186 | } |
184 | } | 187 | } |
188 | EXPORT_SYMBOL(nfc_hci_sak_to_protocol); | ||
185 | 189 | ||
186 | int nfc_hci_target_discovered(struct nfc_hci_dev *hdev, u8 gate) | 190 | int nfc_hci_target_discovered(struct nfc_hci_dev *hdev, u8 gate) |
187 | { | 191 | { |
@@ -284,6 +288,12 @@ void nfc_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event, | |||
284 | struct sk_buff *skb) | 288 | struct sk_buff *skb) |
285 | { | 289 | { |
286 | int r = 0; | 290 | int r = 0; |
291 | u8 gate = nfc_hci_pipe2gate(hdev, pipe); | ||
292 | |||
293 | if (gate == 0xff) { | ||
294 | pr_err("Discarded event %x to unopened pipe %x\n", event, pipe); | ||
295 | goto exit; | ||
296 | } | ||
287 | 297 | ||
288 | switch (event) { | 298 | switch (event) { |
289 | case NFC_HCI_EVT_TARGET_DISCOVERED: | 299 | case NFC_HCI_EVT_TARGET_DISCOVERED: |
@@ -307,14 +317,11 @@ void nfc_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event, | |||
307 | goto exit; | 317 | goto exit; |
308 | } | 318 | } |
309 | 319 | ||
310 | r = nfc_hci_target_discovered(hdev, | 320 | r = nfc_hci_target_discovered(hdev, gate); |
311 | nfc_hci_pipe2gate(hdev, pipe)); | ||
312 | break; | 321 | break; |
313 | default: | 322 | default: |
314 | if (hdev->ops->event_received) { | 323 | if (hdev->ops->event_received) { |
315 | hdev->ops->event_received(hdev, | 324 | hdev->ops->event_received(hdev, gate, event, skb); |
316 | nfc_hci_pipe2gate(hdev, pipe), | ||
317 | event, skb); | ||
318 | return; | 325 | return; |
319 | } | 326 | } |
320 | 327 | ||
@@ -419,6 +426,10 @@ static int hci_dev_version(struct nfc_hci_dev *hdev) | |||
419 | 426 | ||
420 | r = nfc_hci_get_param(hdev, NFC_HCI_ID_MGMT_GATE, | 427 | r = nfc_hci_get_param(hdev, NFC_HCI_ID_MGMT_GATE, |
421 | NFC_HCI_ID_MGMT_VERSION_SW, &skb); | 428 | NFC_HCI_ID_MGMT_VERSION_SW, &skb); |
429 | if (r == -EOPNOTSUPP) { | ||
430 | pr_info("Software/Hardware info not available\n"); | ||
431 | return 0; | ||
432 | } | ||
422 | if (r < 0) | 433 | if (r < 0) |
423 | return r; | 434 | return r; |
424 | 435 | ||
diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c index ed2d17312d6..df24be48d4d 100644 --- a/net/nfc/llcp/commands.c +++ b/net/nfc/llcp/commands.c | |||
@@ -528,6 +528,23 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock, | |||
528 | if (local == NULL) | 528 | if (local == NULL) |
529 | return -ENODEV; | 529 | return -ENODEV; |
530 | 530 | ||
531 | /* Remote is ready but has not acknowledged our frames */ | ||
532 | if((sock->remote_ready && | ||
533 | skb_queue_len(&sock->tx_pending_queue) >= sock->rw && | ||
534 | skb_queue_len(&sock->tx_queue) >= 2 * sock->rw)) { | ||
535 | pr_err("Pending queue is full %d frames\n", | ||
536 | skb_queue_len(&sock->tx_pending_queue)); | ||
537 | return -ENOBUFS; | ||
538 | } | ||
539 | |||
540 | /* Remote is not ready and we've been queueing enough frames */ | ||
541 | if ((!sock->remote_ready && | ||
542 | skb_queue_len(&sock->tx_queue) >= 2 * sock->rw)) { | ||
543 | pr_err("Tx queue is full %d frames\n", | ||
544 | skb_queue_len(&sock->tx_queue)); | ||
545 | return -ENOBUFS; | ||
546 | } | ||
547 | |||
531 | msg_data = kzalloc(len, GFP_KERNEL); | 548 | msg_data = kzalloc(len, GFP_KERNEL); |
532 | if (msg_data == NULL) | 549 | if (msg_data == NULL) |
533 | return -ENOMEM; | 550 | return -ENOMEM; |
@@ -579,7 +596,7 @@ int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap, | |||
579 | struct sk_buff *pdu; | 596 | struct sk_buff *pdu; |
580 | struct nfc_llcp_local *local; | 597 | struct nfc_llcp_local *local; |
581 | size_t frag_len = 0, remaining_len; | 598 | size_t frag_len = 0, remaining_len; |
582 | u8 *msg_ptr; | 599 | u8 *msg_ptr, *msg_data; |
583 | int err; | 600 | int err; |
584 | 601 | ||
585 | pr_debug("Send UI frame len %zd\n", len); | 602 | pr_debug("Send UI frame len %zd\n", len); |
@@ -588,8 +605,17 @@ int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap, | |||
588 | if (local == NULL) | 605 | if (local == NULL) |
589 | return -ENODEV; | 606 | return -ENODEV; |
590 | 607 | ||
608 | msg_data = kzalloc(len, GFP_KERNEL); | ||
609 | if (msg_data == NULL) | ||
610 | return -ENOMEM; | ||
611 | |||
612 | if (memcpy_fromiovec(msg_data, msg->msg_iov, len)) { | ||
613 | kfree(msg_data); | ||
614 | return -EFAULT; | ||
615 | } | ||
616 | |||
591 | remaining_len = len; | 617 | remaining_len = len; |
592 | msg_ptr = (u8 *) msg->msg_iov; | 618 | msg_ptr = msg_data; |
593 | 619 | ||
594 | while (remaining_len > 0) { | 620 | while (remaining_len > 0) { |
595 | 621 | ||
@@ -616,6 +642,8 @@ int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap, | |||
616 | msg_ptr += frag_len; | 642 | msg_ptr += frag_len; |
617 | } | 643 | } |
618 | 644 | ||
645 | kfree(msg_data); | ||
646 | |||
619 | return len; | 647 | return len; |
620 | } | 648 | } |
621 | 649 | ||
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c index 2e9ddf34c09..2df87056c6d 100644 --- a/net/nfc/llcp/llcp.c +++ b/net/nfc/llcp/llcp.c | |||
@@ -656,6 +656,8 @@ static void nfc_llcp_tx_work(struct work_struct *work) | |||
656 | if (llcp_sock == NULL && nfc_llcp_ptype(skb) == LLCP_PDU_I) { | 656 | if (llcp_sock == NULL && nfc_llcp_ptype(skb) == LLCP_PDU_I) { |
657 | nfc_llcp_send_symm(local->dev); | 657 | nfc_llcp_send_symm(local->dev); |
658 | } else { | 658 | } else { |
659 | struct sk_buff *copy_skb = NULL; | ||
660 | u8 ptype = nfc_llcp_ptype(skb); | ||
659 | int ret; | 661 | int ret; |
660 | 662 | ||
661 | pr_debug("Sending pending skb\n"); | 663 | pr_debug("Sending pending skb\n"); |
@@ -663,22 +665,29 @@ static void nfc_llcp_tx_work(struct work_struct *work) | |||
663 | DUMP_PREFIX_OFFSET, 16, 1, | 665 | DUMP_PREFIX_OFFSET, 16, 1, |
664 | skb->data, skb->len, true); | 666 | skb->data, skb->len, true); |
665 | 667 | ||
668 | if (ptype == LLCP_PDU_I) | ||
669 | copy_skb = skb_copy(skb, GFP_ATOMIC); | ||
670 | |||
666 | nfc_llcp_send_to_raw_sock(local, skb, | 671 | nfc_llcp_send_to_raw_sock(local, skb, |
667 | NFC_LLCP_DIRECTION_TX); | 672 | NFC_LLCP_DIRECTION_TX); |
668 | 673 | ||
669 | ret = nfc_data_exchange(local->dev, local->target_idx, | 674 | ret = nfc_data_exchange(local->dev, local->target_idx, |
670 | skb, nfc_llcp_recv, local); | 675 | skb, nfc_llcp_recv, local); |
671 | 676 | ||
672 | if (!ret && nfc_llcp_ptype(skb) == LLCP_PDU_I) { | 677 | if (ret) { |
673 | skb = skb_get(skb); | 678 | kfree_skb(copy_skb); |
674 | skb_queue_tail(&llcp_sock->tx_pending_queue, | 679 | goto out; |
675 | skb); | ||
676 | } | 680 | } |
681 | |||
682 | if (ptype == LLCP_PDU_I && copy_skb) | ||
683 | skb_queue_tail(&llcp_sock->tx_pending_queue, | ||
684 | copy_skb); | ||
677 | } | 685 | } |
678 | } else { | 686 | } else { |
679 | nfc_llcp_send_symm(local->dev); | 687 | nfc_llcp_send_symm(local->dev); |
680 | } | 688 | } |
681 | 689 | ||
690 | out: | ||
682 | mod_timer(&local->link_timer, | 691 | mod_timer(&local->link_timer, |
683 | jiffies + msecs_to_jiffies(2 * local->remote_lto)); | 692 | jiffies + msecs_to_jiffies(2 * local->remote_lto)); |
684 | } | 693 | } |
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig index fe4adb12b3e..16d08b39921 100644 --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig | |||
@@ -140,14 +140,13 @@ config CFG80211_WEXT | |||
140 | extensions with cfg80211-based drivers. | 140 | extensions with cfg80211-based drivers. |
141 | 141 | ||
142 | config LIB80211 | 142 | config LIB80211 |
143 | tristate "Common routines for IEEE802.11 drivers" | 143 | tristate |
144 | default n | 144 | default n |
145 | help | 145 | help |
146 | This options enables a library of common routines used | 146 | This options enables a library of common routines used |
147 | by IEEE802.11 wireless LAN drivers. | 147 | by IEEE802.11 wireless LAN drivers. |
148 | 148 | ||
149 | Drivers should select this themselves if needed. Say Y if | 149 | Drivers should select this themselves if needed. |
150 | you want this built into your kernel. | ||
151 | 150 | ||
152 | config LIB80211_CRYPT_WEP | 151 | config LIB80211_CRYPT_WEP |
153 | tristate | 152 | tristate |
diff --git a/net/wireless/ap.c b/net/wireless/ap.c index e143505f05b..324e8d851dc 100644 --- a/net/wireless/ap.c +++ b/net/wireless/ap.c | |||
@@ -28,6 +28,7 @@ static int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev, | |||
28 | if (!err) { | 28 | if (!err) { |
29 | wdev->beacon_interval = 0; | 29 | wdev->beacon_interval = 0; |
30 | wdev->channel = NULL; | 30 | wdev->channel = NULL; |
31 | wdev->ssid_len = 0; | ||
31 | } | 32 | } |
32 | 33 | ||
33 | return err; | 34 | return err; |
diff --git a/net/wireless/chan.c b/net/wireless/chan.c index 48febd2160b..bf2dfd54ff3 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c | |||
@@ -11,96 +11,264 @@ | |||
11 | #include "core.h" | 11 | #include "core.h" |
12 | #include "rdev-ops.h" | 12 | #include "rdev-ops.h" |
13 | 13 | ||
14 | struct ieee80211_channel * | 14 | void cfg80211_chandef_create(struct cfg80211_chan_def *chandef, |
15 | rdev_freq_to_chan(struct cfg80211_registered_device *rdev, | 15 | struct ieee80211_channel *chan, |
16 | int freq, enum nl80211_channel_type channel_type) | 16 | enum nl80211_channel_type chan_type) |
17 | { | 17 | { |
18 | struct ieee80211_channel *chan; | 18 | if (WARN_ON(!chan)) |
19 | struct ieee80211_sta_ht_cap *ht_cap; | 19 | return; |
20 | 20 | ||
21 | chan = ieee80211_get_channel(&rdev->wiphy, freq); | 21 | chandef->chan = chan; |
22 | chandef->center_freq2 = 0; | ||
22 | 23 | ||
23 | /* Primary channel not allowed */ | 24 | switch (chan_type) { |
24 | if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) | 25 | case NL80211_CHAN_NO_HT: |
25 | return NULL; | 26 | chandef->width = NL80211_CHAN_WIDTH_20_NOHT; |
27 | chandef->center_freq1 = chan->center_freq; | ||
28 | break; | ||
29 | case NL80211_CHAN_HT20: | ||
30 | chandef->width = NL80211_CHAN_WIDTH_20; | ||
31 | chandef->center_freq1 = chan->center_freq; | ||
32 | break; | ||
33 | case NL80211_CHAN_HT40PLUS: | ||
34 | chandef->width = NL80211_CHAN_WIDTH_40; | ||
35 | chandef->center_freq1 = chan->center_freq + 10; | ||
36 | break; | ||
37 | case NL80211_CHAN_HT40MINUS: | ||
38 | chandef->width = NL80211_CHAN_WIDTH_40; | ||
39 | chandef->center_freq1 = chan->center_freq - 10; | ||
40 | break; | ||
41 | default: | ||
42 | WARN_ON(1); | ||
43 | } | ||
44 | } | ||
45 | EXPORT_SYMBOL(cfg80211_chandef_create); | ||
26 | 46 | ||
27 | if (channel_type == NL80211_CHAN_HT40MINUS && | 47 | bool cfg80211_chan_def_valid(const struct cfg80211_chan_def *chandef) |
28 | chan->flags & IEEE80211_CHAN_NO_HT40MINUS) | 48 | { |
29 | return NULL; | 49 | u32 control_freq; |
30 | else if (channel_type == NL80211_CHAN_HT40PLUS && | ||
31 | chan->flags & IEEE80211_CHAN_NO_HT40PLUS) | ||
32 | return NULL; | ||
33 | 50 | ||
34 | ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap; | 51 | if (!chandef->chan) |
52 | return false; | ||
35 | 53 | ||
36 | if (channel_type != NL80211_CHAN_NO_HT) { | 54 | control_freq = chandef->chan->center_freq; |
37 | if (!ht_cap->ht_supported) | ||
38 | return NULL; | ||
39 | 55 | ||
40 | if (channel_type != NL80211_CHAN_HT20 && | 56 | switch (chandef->width) { |
41 | (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) || | 57 | case NL80211_CHAN_WIDTH_20: |
42 | ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT)) | 58 | case NL80211_CHAN_WIDTH_20_NOHT: |
43 | return NULL; | 59 | if (chandef->center_freq1 != control_freq) |
60 | return false; | ||
61 | if (chandef->center_freq2) | ||
62 | return false; | ||
63 | break; | ||
64 | case NL80211_CHAN_WIDTH_40: | ||
65 | if (chandef->center_freq1 != control_freq + 10 && | ||
66 | chandef->center_freq1 != control_freq - 10) | ||
67 | return false; | ||
68 | if (chandef->center_freq2) | ||
69 | return false; | ||
70 | break; | ||
71 | case NL80211_CHAN_WIDTH_80P80: | ||
72 | if (chandef->center_freq1 != control_freq + 30 && | ||
73 | chandef->center_freq1 != control_freq + 10 && | ||
74 | chandef->center_freq1 != control_freq - 10 && | ||
75 | chandef->center_freq1 != control_freq - 30) | ||
76 | return false; | ||
77 | if (!chandef->center_freq2) | ||
78 | return false; | ||
79 | break; | ||
80 | case NL80211_CHAN_WIDTH_80: | ||
81 | if (chandef->center_freq1 != control_freq + 30 && | ||
82 | chandef->center_freq1 != control_freq + 10 && | ||
83 | chandef->center_freq1 != control_freq - 10 && | ||
84 | chandef->center_freq1 != control_freq - 30) | ||
85 | return false; | ||
86 | if (chandef->center_freq2) | ||
87 | return false; | ||
88 | break; | ||
89 | case NL80211_CHAN_WIDTH_160: | ||
90 | if (chandef->center_freq1 != control_freq + 70 && | ||
91 | chandef->center_freq1 != control_freq + 50 && | ||
92 | chandef->center_freq1 != control_freq + 30 && | ||
93 | chandef->center_freq1 != control_freq + 10 && | ||
94 | chandef->center_freq1 != control_freq - 10 && | ||
95 | chandef->center_freq1 != control_freq - 30 && | ||
96 | chandef->center_freq1 != control_freq - 50 && | ||
97 | chandef->center_freq1 != control_freq - 70) | ||
98 | return false; | ||
99 | if (chandef->center_freq2) | ||
100 | return false; | ||
101 | break; | ||
102 | default: | ||
103 | return false; | ||
44 | } | 104 | } |
45 | 105 | ||
46 | return chan; | 106 | return true; |
47 | } | 107 | } |
48 | 108 | ||
49 | bool cfg80211_can_beacon_sec_chan(struct wiphy *wiphy, | 109 | static void chandef_primary_freqs(const struct cfg80211_chan_def *c, |
50 | struct ieee80211_channel *chan, | 110 | int *pri40, int *pri80) |
51 | enum nl80211_channel_type channel_type) | ||
52 | { | 111 | { |
53 | struct ieee80211_channel *sec_chan; | 112 | int tmp; |
54 | int diff; | ||
55 | |||
56 | trace_cfg80211_can_beacon_sec_chan(wiphy, chan, channel_type); | ||
57 | 113 | ||
58 | switch (channel_type) { | 114 | switch (c->width) { |
59 | case NL80211_CHAN_HT40PLUS: | 115 | case NL80211_CHAN_WIDTH_40: |
60 | diff = 20; | 116 | *pri40 = c->center_freq1; |
117 | *pri80 = 0; | ||
61 | break; | 118 | break; |
62 | case NL80211_CHAN_HT40MINUS: | 119 | case NL80211_CHAN_WIDTH_80: |
63 | diff = -20; | 120 | case NL80211_CHAN_WIDTH_80P80: |
121 | *pri80 = c->center_freq1; | ||
122 | /* n_P20 */ | ||
123 | tmp = (30 + c->chan->center_freq - c->center_freq1)/20; | ||
124 | /* n_P40 */ | ||
125 | tmp /= 2; | ||
126 | /* freq_P40 */ | ||
127 | *pri40 = c->center_freq1 - 20 + 40 * tmp; | ||
128 | break; | ||
129 | case NL80211_CHAN_WIDTH_160: | ||
130 | /* n_P20 */ | ||
131 | tmp = (70 + c->chan->center_freq - c->center_freq1)/20; | ||
132 | /* n_P40 */ | ||
133 | tmp /= 2; | ||
134 | /* freq_P40 */ | ||
135 | *pri40 = c->center_freq1 - 60 + 40 * tmp; | ||
136 | /* n_P80 */ | ||
137 | tmp /= 2; | ||
138 | *pri80 = c->center_freq1 - 40 + 80 * tmp; | ||
64 | break; | 139 | break; |
65 | default: | 140 | default: |
66 | trace_cfg80211_return_bool(true); | 141 | WARN_ON_ONCE(1); |
67 | return true; | ||
68 | } | 142 | } |
143 | } | ||
144 | |||
145 | const struct cfg80211_chan_def * | ||
146 | cfg80211_chandef_compatible(const struct cfg80211_chan_def *c1, | ||
147 | const struct cfg80211_chan_def *c2) | ||
148 | { | ||
149 | u32 c1_pri40, c1_pri80, c2_pri40, c2_pri80; | ||
69 | 150 | ||
70 | sec_chan = ieee80211_get_channel(wiphy, chan->center_freq + diff); | 151 | /* If they are identical, return */ |
71 | if (!sec_chan) { | 152 | if (cfg80211_chandef_identical(c1, c2)) |
153 | return c1; | ||
154 | |||
155 | /* otherwise, must have same control channel */ | ||
156 | if (c1->chan != c2->chan) | ||
157 | return NULL; | ||
158 | |||
159 | /* | ||
160 | * If they have the same width, but aren't identical, | ||
161 | * then they can't be compatible. | ||
162 | */ | ||
163 | if (c1->width == c2->width) | ||
164 | return NULL; | ||
165 | |||
166 | if (c1->width == NL80211_CHAN_WIDTH_20_NOHT || | ||
167 | c1->width == NL80211_CHAN_WIDTH_20) | ||
168 | return c2; | ||
169 | |||
170 | if (c2->width == NL80211_CHAN_WIDTH_20_NOHT || | ||
171 | c2->width == NL80211_CHAN_WIDTH_20) | ||
172 | return c1; | ||
173 | |||
174 | chandef_primary_freqs(c1, &c1_pri40, &c1_pri80); | ||
175 | chandef_primary_freqs(c2, &c2_pri40, &c2_pri80); | ||
176 | |||
177 | if (c1_pri40 != c2_pri40) | ||
178 | return NULL; | ||
179 | |||
180 | WARN_ON(!c1_pri80 && !c2_pri80); | ||
181 | if (c1_pri80 && c2_pri80 && c1_pri80 != c2_pri80) | ||
182 | return NULL; | ||
183 | |||
184 | if (c1->width > c2->width) | ||
185 | return c1; | ||
186 | return c2; | ||
187 | } | ||
188 | EXPORT_SYMBOL(cfg80211_chandef_compatible); | ||
189 | |||
190 | bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, | ||
191 | u32 center_freq, u32 bandwidth, | ||
192 | u32 prohibited_flags) | ||
193 | { | ||
194 | struct ieee80211_channel *c; | ||
195 | u32 freq; | ||
196 | |||
197 | for (freq = center_freq - bandwidth/2 + 10; | ||
198 | freq <= center_freq + bandwidth/2 - 10; | ||
199 | freq += 20) { | ||
200 | c = ieee80211_get_channel(wiphy, freq); | ||
201 | if (!c || c->flags & prohibited_flags) | ||
202 | return false; | ||
203 | } | ||
204 | |||
205 | return true; | ||
206 | } | ||
207 | |||
208 | static bool cfg80211_check_beacon_chans(struct wiphy *wiphy, | ||
209 | u32 center_freq, u32 bw) | ||
210 | { | ||
211 | return cfg80211_secondary_chans_ok(wiphy, center_freq, bw, | ||
212 | IEEE80211_CHAN_DISABLED | | ||
213 | IEEE80211_CHAN_PASSIVE_SCAN | | ||
214 | IEEE80211_CHAN_NO_IBSS | | ||
215 | IEEE80211_CHAN_RADAR); | ||
216 | } | ||
217 | |||
218 | bool cfg80211_reg_can_beacon(struct wiphy *wiphy, | ||
219 | struct cfg80211_chan_def *chandef) | ||
220 | { | ||
221 | u32 width; | ||
222 | bool res; | ||
223 | |||
224 | trace_cfg80211_reg_can_beacon(wiphy, chandef); | ||
225 | |||
226 | if (WARN_ON(!cfg80211_chan_def_valid(chandef))) { | ||
72 | trace_cfg80211_return_bool(false); | 227 | trace_cfg80211_return_bool(false); |
73 | return false; | 228 | return false; |
74 | } | 229 | } |
75 | 230 | ||
76 | /* we'll need a DFS capability later */ | 231 | switch (chandef->width) { |
77 | if (sec_chan->flags & (IEEE80211_CHAN_DISABLED | | 232 | case NL80211_CHAN_WIDTH_20_NOHT: |
78 | IEEE80211_CHAN_PASSIVE_SCAN | | 233 | case NL80211_CHAN_WIDTH_20: |
79 | IEEE80211_CHAN_NO_IBSS | | 234 | width = 20; |
80 | IEEE80211_CHAN_RADAR)) { | 235 | break; |
236 | case NL80211_CHAN_WIDTH_40: | ||
237 | width = 40; | ||
238 | break; | ||
239 | case NL80211_CHAN_WIDTH_80: | ||
240 | case NL80211_CHAN_WIDTH_80P80: | ||
241 | width = 80; | ||
242 | break; | ||
243 | case NL80211_CHAN_WIDTH_160: | ||
244 | width = 160; | ||
245 | break; | ||
246 | default: | ||
247 | WARN_ON_ONCE(1); | ||
81 | trace_cfg80211_return_bool(false); | 248 | trace_cfg80211_return_bool(false); |
82 | return false; | 249 | return false; |
83 | } | 250 | } |
84 | trace_cfg80211_return_bool(true); | 251 | |
85 | return true; | 252 | res = cfg80211_check_beacon_chans(wiphy, chandef->center_freq1, width); |
253 | |||
254 | if (res && chandef->center_freq2) | ||
255 | res = cfg80211_check_beacon_chans(wiphy, chandef->center_freq2, | ||
256 | width); | ||
257 | |||
258 | trace_cfg80211_return_bool(res); | ||
259 | return res; | ||
86 | } | 260 | } |
87 | EXPORT_SYMBOL(cfg80211_can_beacon_sec_chan); | 261 | EXPORT_SYMBOL(cfg80211_reg_can_beacon); |
88 | 262 | ||
89 | int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev, | 263 | int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev, |
90 | int freq, enum nl80211_channel_type chantype) | 264 | struct cfg80211_chan_def *chandef) |
91 | { | 265 | { |
92 | struct ieee80211_channel *chan; | ||
93 | |||
94 | if (!rdev->ops->set_monitor_channel) | 266 | if (!rdev->ops->set_monitor_channel) |
95 | return -EOPNOTSUPP; | 267 | return -EOPNOTSUPP; |
96 | if (!cfg80211_has_monitors_only(rdev)) | 268 | if (!cfg80211_has_monitors_only(rdev)) |
97 | return -EBUSY; | 269 | return -EBUSY; |
98 | 270 | ||
99 | chan = rdev_freq_to_chan(rdev, freq, chantype); | 271 | return rdev_set_monitor_channel(rdev, chandef); |
100 | if (!chan) | ||
101 | return -EINVAL; | ||
102 | |||
103 | return rdev_set_monitor_channel(rdev, chan, chantype); | ||
104 | } | 272 | } |
105 | 273 | ||
106 | void | 274 | void |
diff --git a/net/wireless/core.c b/net/wireless/core.c index 26711f46a3b..14d99040035 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -326,6 +326,8 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) | |||
326 | mutex_init(&rdev->devlist_mtx); | 326 | mutex_init(&rdev->devlist_mtx); |
327 | mutex_init(&rdev->sched_scan_mtx); | 327 | mutex_init(&rdev->sched_scan_mtx); |
328 | INIT_LIST_HEAD(&rdev->wdev_list); | 328 | INIT_LIST_HEAD(&rdev->wdev_list); |
329 | INIT_LIST_HEAD(&rdev->beacon_registrations); | ||
330 | spin_lock_init(&rdev->beacon_registrations_lock); | ||
329 | spin_lock_init(&rdev->bss_lock); | 331 | spin_lock_init(&rdev->bss_lock); |
330 | INIT_LIST_HEAD(&rdev->bss_list); | 332 | INIT_LIST_HEAD(&rdev->bss_list); |
331 | INIT_WORK(&rdev->scan_done_wk, __cfg80211_scan_done); | 333 | INIT_WORK(&rdev->scan_done_wk, __cfg80211_scan_done); |
@@ -698,10 +700,15 @@ EXPORT_SYMBOL(wiphy_unregister); | |||
698 | void cfg80211_dev_free(struct cfg80211_registered_device *rdev) | 700 | void cfg80211_dev_free(struct cfg80211_registered_device *rdev) |
699 | { | 701 | { |
700 | struct cfg80211_internal_bss *scan, *tmp; | 702 | struct cfg80211_internal_bss *scan, *tmp; |
703 | struct cfg80211_beacon_registration *reg, *treg; | ||
701 | rfkill_destroy(rdev->rfkill); | 704 | rfkill_destroy(rdev->rfkill); |
702 | mutex_destroy(&rdev->mtx); | 705 | mutex_destroy(&rdev->mtx); |
703 | mutex_destroy(&rdev->devlist_mtx); | 706 | mutex_destroy(&rdev->devlist_mtx); |
704 | mutex_destroy(&rdev->sched_scan_mtx); | 707 | mutex_destroy(&rdev->sched_scan_mtx); |
708 | list_for_each_entry_safe(reg, treg, &rdev->beacon_registrations, list) { | ||
709 | list_del(®->list); | ||
710 | kfree(reg); | ||
711 | } | ||
705 | list_for_each_entry_safe(scan, tmp, &rdev->bss_list, list) | 712 | list_for_each_entry_safe(scan, tmp, &rdev->bss_list, list) |
706 | cfg80211_put_bss(&scan->pub); | 713 | cfg80211_put_bss(&scan->pub); |
707 | kfree(rdev); | 714 | kfree(rdev); |
diff --git a/net/wireless/core.h b/net/wireless/core.h index b8eb743fe7d..a0c8decf6a4 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -55,7 +55,8 @@ struct cfg80211_registered_device { | |||
55 | int opencount; /* also protected by devlist_mtx */ | 55 | int opencount; /* also protected by devlist_mtx */ |
56 | wait_queue_head_t dev_wait; | 56 | wait_queue_head_t dev_wait; |
57 | 57 | ||
58 | u32 ap_beacons_nlportid; | 58 | struct list_head beacon_registrations; |
59 | spinlock_t beacon_registrations_lock; | ||
59 | 60 | ||
60 | /* protected by RTNL only */ | 61 | /* protected by RTNL only */ |
61 | int num_running_ifaces; | 62 | int num_running_ifaces; |
@@ -260,6 +261,10 @@ enum cfg80211_chan_mode { | |||
260 | CHAN_MODE_EXCLUSIVE, | 261 | CHAN_MODE_EXCLUSIVE, |
261 | }; | 262 | }; |
262 | 263 | ||
264 | struct cfg80211_beacon_registration { | ||
265 | struct list_head list; | ||
266 | u32 nlportid; | ||
267 | }; | ||
263 | 268 | ||
264 | /* free object */ | 269 | /* free object */ |
265 | extern void cfg80211_dev_free(struct cfg80211_registered_device *rdev); | 270 | extern void cfg80211_dev_free(struct cfg80211_registered_device *rdev); |
@@ -304,9 +309,9 @@ int cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | |||
304 | const struct mesh_config *conf); | 309 | const struct mesh_config *conf); |
305 | int cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, | 310 | int cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, |
306 | struct net_device *dev); | 311 | struct net_device *dev); |
307 | int cfg80211_set_mesh_freq(struct cfg80211_registered_device *rdev, | 312 | int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev, |
308 | struct wireless_dev *wdev, int freq, | 313 | struct wireless_dev *wdev, |
309 | enum nl80211_channel_type channel_type); | 314 | struct cfg80211_chan_def *chandef); |
310 | 315 | ||
311 | /* AP */ | 316 | /* AP */ |
312 | int cfg80211_stop_ap(struct cfg80211_registered_device *rdev, | 317 | int cfg80211_stop_ap(struct cfg80211_registered_device *rdev, |
@@ -373,10 +378,8 @@ void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev); | |||
373 | int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, | 378 | int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, |
374 | struct wireless_dev *wdev, | 379 | struct wireless_dev *wdev, |
375 | struct ieee80211_channel *chan, bool offchan, | 380 | struct ieee80211_channel *chan, bool offchan, |
376 | enum nl80211_channel_type channel_type, | 381 | unsigned int wait, const u8 *buf, size_t len, |
377 | bool channel_type_valid, unsigned int wait, | 382 | bool no_cck, bool dont_wait_for_ack, u64 *cookie); |
378 | const u8 *buf, size_t len, bool no_cck, | ||
379 | bool dont_wait_for_ack, u64 *cookie); | ||
380 | void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa, | 383 | void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa, |
381 | const struct ieee80211_ht_cap *ht_capa_mask); | 384 | const struct ieee80211_ht_cap *ht_capa_mask); |
382 | 385 | ||
@@ -467,11 +470,8 @@ cfg80211_get_chan_state(struct wireless_dev *wdev, | |||
467 | struct ieee80211_channel **chan, | 470 | struct ieee80211_channel **chan, |
468 | enum cfg80211_chan_mode *chanmode); | 471 | enum cfg80211_chan_mode *chanmode); |
469 | 472 | ||
470 | struct ieee80211_channel * | ||
471 | rdev_freq_to_chan(struct cfg80211_registered_device *rdev, | ||
472 | int freq, enum nl80211_channel_type channel_type); | ||
473 | int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev, | 473 | int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev, |
474 | int freq, enum nl80211_channel_type chantype); | 474 | struct cfg80211_chan_def *chandef); |
475 | 475 | ||
476 | int ieee80211_get_ratemask(struct ieee80211_supported_band *sband, | 476 | int ieee80211_get_ratemask(struct ieee80211_supported_band *sband, |
477 | const u8 *rates, unsigned int n_rates, | 477 | const u8 *rates, unsigned int n_rates, |
@@ -483,6 +483,12 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, | |||
483 | void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, | 483 | void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, |
484 | enum nl80211_iftype iftype, int num); | 484 | enum nl80211_iftype iftype, int num); |
485 | 485 | ||
486 | bool cfg80211_chan_def_valid(const struct cfg80211_chan_def *chandef); | ||
487 | |||
488 | bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, | ||
489 | u32 center_freq, u32 bandwidth, | ||
490 | u32 prohibited_flags); | ||
491 | |||
486 | #define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10 | 492 | #define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10 |
487 | 493 | ||
488 | #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS | 494 | #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS |
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index 27941d5db72..9b9551e4a6f 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c | |||
@@ -100,9 +100,9 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, | |||
100 | * 11a for maximum compatibility. | 100 | * 11a for maximum compatibility. |
101 | */ | 101 | */ |
102 | struct ieee80211_supported_band *sband = | 102 | struct ieee80211_supported_band *sband = |
103 | rdev->wiphy.bands[params->channel->band]; | 103 | rdev->wiphy.bands[params->chandef.chan->band]; |
104 | int j; | 104 | int j; |
105 | u32 flag = params->channel->band == IEEE80211_BAND_5GHZ ? | 105 | u32 flag = params->chandef.chan->band == IEEE80211_BAND_5GHZ ? |
106 | IEEE80211_RATE_MANDATORY_A : | 106 | IEEE80211_RATE_MANDATORY_A : |
107 | IEEE80211_RATE_MANDATORY_B; | 107 | IEEE80211_RATE_MANDATORY_B; |
108 | 108 | ||
@@ -118,11 +118,11 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, | |||
118 | 118 | ||
119 | wdev->ibss_fixed = params->channel_fixed; | 119 | wdev->ibss_fixed = params->channel_fixed; |
120 | #ifdef CONFIG_CFG80211_WEXT | 120 | #ifdef CONFIG_CFG80211_WEXT |
121 | wdev->wext.ibss.channel = params->channel; | 121 | wdev->wext.ibss.chandef = params->chandef; |
122 | #endif | 122 | #endif |
123 | wdev->sme_state = CFG80211_SME_CONNECTING; | 123 | wdev->sme_state = CFG80211_SME_CONNECTING; |
124 | 124 | ||
125 | err = cfg80211_can_use_chan(rdev, wdev, params->channel, | 125 | err = cfg80211_can_use_chan(rdev, wdev, params->chandef.chan, |
126 | params->channel_fixed | 126 | params->channel_fixed |
127 | ? CHAN_MODE_SHARED | 127 | ? CHAN_MODE_SHARED |
128 | : CHAN_MODE_EXCLUSIVE); | 128 | : CHAN_MODE_EXCLUSIVE); |
@@ -251,7 +251,9 @@ int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, | |||
251 | wdev->wext.ibss.beacon_interval = 100; | 251 | wdev->wext.ibss.beacon_interval = 100; |
252 | 252 | ||
253 | /* try to find an IBSS channel if none requested ... */ | 253 | /* try to find an IBSS channel if none requested ... */ |
254 | if (!wdev->wext.ibss.channel) { | 254 | if (!wdev->wext.ibss.chandef.chan) { |
255 | wdev->wext.ibss.chandef.width = NL80211_CHAN_WIDTH_20_NOHT; | ||
256 | |||
255 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | 257 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { |
256 | struct ieee80211_supported_band *sband; | 258 | struct ieee80211_supported_band *sband; |
257 | struct ieee80211_channel *chan; | 259 | struct ieee80211_channel *chan; |
@@ -266,15 +268,15 @@ int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, | |||
266 | continue; | 268 | continue; |
267 | if (chan->flags & IEEE80211_CHAN_DISABLED) | 269 | if (chan->flags & IEEE80211_CHAN_DISABLED) |
268 | continue; | 270 | continue; |
269 | wdev->wext.ibss.channel = chan; | 271 | wdev->wext.ibss.chandef.chan = chan; |
270 | break; | 272 | break; |
271 | } | 273 | } |
272 | 274 | ||
273 | if (wdev->wext.ibss.channel) | 275 | if (wdev->wext.ibss.chandef.chan) |
274 | break; | 276 | break; |
275 | } | 277 | } |
276 | 278 | ||
277 | if (!wdev->wext.ibss.channel) | 279 | if (!wdev->wext.ibss.chandef.chan) |
278 | return -EINVAL; | 280 | return -EINVAL; |
279 | } | 281 | } |
280 | 282 | ||
@@ -336,7 +338,7 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev, | |||
336 | return -EINVAL; | 338 | return -EINVAL; |
337 | } | 339 | } |
338 | 340 | ||
339 | if (wdev->wext.ibss.channel == chan) | 341 | if (wdev->wext.ibss.chandef.chan == chan) |
340 | return 0; | 342 | return 0; |
341 | 343 | ||
342 | wdev_lock(wdev); | 344 | wdev_lock(wdev); |
@@ -349,7 +351,8 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev, | |||
349 | return err; | 351 | return err; |
350 | 352 | ||
351 | if (chan) { | 353 | if (chan) { |
352 | wdev->wext.ibss.channel = chan; | 354 | wdev->wext.ibss.chandef.chan = chan; |
355 | wdev->wext.ibss.chandef.width = NL80211_CHAN_WIDTH_20_NOHT; | ||
353 | wdev->wext.ibss.channel_fixed = true; | 356 | wdev->wext.ibss.channel_fixed = true; |
354 | } else { | 357 | } else { |
355 | /* cfg80211_ibss_wext_join will pick one if needed */ | 358 | /* cfg80211_ibss_wext_join will pick one if needed */ |
@@ -379,8 +382,8 @@ int cfg80211_ibss_wext_giwfreq(struct net_device *dev, | |||
379 | wdev_lock(wdev); | 382 | wdev_lock(wdev); |
380 | if (wdev->current_bss) | 383 | if (wdev->current_bss) |
381 | chan = wdev->current_bss->pub.channel; | 384 | chan = wdev->current_bss->pub.channel; |
382 | else if (wdev->wext.ibss.channel) | 385 | else if (wdev->wext.ibss.chandef.chan) |
383 | chan = wdev->wext.ibss.channel; | 386 | chan = wdev->wext.ibss.chandef.chan; |
384 | wdev_unlock(wdev); | 387 | wdev_unlock(wdev); |
385 | 388 | ||
386 | if (chan) { | 389 | if (chan) { |
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index 966cfc4cd79..3ee5a728228 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c | |||
@@ -73,8 +73,6 @@ const struct mesh_config default_mesh_config = { | |||
73 | 73 | ||
74 | const struct mesh_setup default_mesh_setup = { | 74 | const struct mesh_setup default_mesh_setup = { |
75 | /* cfg80211_join_mesh() will pick a channel if needed */ | 75 | /* cfg80211_join_mesh() will pick a channel if needed */ |
76 | .channel = NULL, | ||
77 | .channel_type = NL80211_CHAN_NO_HT, | ||
78 | .sync_method = IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET, | 76 | .sync_method = IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET, |
79 | .path_sel_proto = IEEE80211_PATH_PROTOCOL_HWMP, | 77 | .path_sel_proto = IEEE80211_PATH_PROTOCOL_HWMP, |
80 | .path_metric = IEEE80211_PATH_METRIC_AIRTIME, | 78 | .path_metric = IEEE80211_PATH_METRIC_AIRTIME, |
@@ -111,13 +109,12 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | |||
111 | if (!rdev->ops->join_mesh) | 109 | if (!rdev->ops->join_mesh) |
112 | return -EOPNOTSUPP; | 110 | return -EOPNOTSUPP; |
113 | 111 | ||
114 | if (!setup->channel) { | 112 | if (!setup->chandef.chan) { |
115 | /* if no channel explicitly given, use preset channel */ | 113 | /* if no channel explicitly given, use preset channel */ |
116 | setup->channel = wdev->preset_chan; | 114 | setup->chandef = wdev->preset_chandef; |
117 | setup->channel_type = wdev->preset_chantype; | ||
118 | } | 115 | } |
119 | 116 | ||
120 | if (!setup->channel) { | 117 | if (!setup->chandef.chan) { |
121 | /* if we don't have that either, use the first usable channel */ | 118 | /* if we don't have that either, use the first usable channel */ |
122 | enum ieee80211_band band; | 119 | enum ieee80211_band band; |
123 | 120 | ||
@@ -137,26 +134,25 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | |||
137 | IEEE80211_CHAN_DISABLED | | 134 | IEEE80211_CHAN_DISABLED | |
138 | IEEE80211_CHAN_RADAR)) | 135 | IEEE80211_CHAN_RADAR)) |
139 | continue; | 136 | continue; |
140 | setup->channel = chan; | 137 | setup->chandef.chan = chan; |
141 | break; | 138 | break; |
142 | } | 139 | } |
143 | 140 | ||
144 | if (setup->channel) | 141 | if (setup->chandef.chan) |
145 | break; | 142 | break; |
146 | } | 143 | } |
147 | 144 | ||
148 | /* no usable channel ... */ | 145 | /* no usable channel ... */ |
149 | if (!setup->channel) | 146 | if (!setup->chandef.chan) |
150 | return -EINVAL; | 147 | return -EINVAL; |
151 | 148 | ||
152 | setup->channel_type = NL80211_CHAN_NO_HT; | 149 | setup->chandef.width = NL80211_CHAN_WIDTH_20_NOHT;; |
153 | } | 150 | } |
154 | 151 | ||
155 | if (!cfg80211_can_beacon_sec_chan(&rdev->wiphy, setup->channel, | 152 | if (!cfg80211_reg_can_beacon(&rdev->wiphy, &setup->chandef)) |
156 | setup->channel_type)) | ||
157 | return -EINVAL; | 153 | return -EINVAL; |
158 | 154 | ||
159 | err = cfg80211_can_use_chan(rdev, wdev, setup->channel, | 155 | err = cfg80211_can_use_chan(rdev, wdev, setup->chandef.chan, |
160 | CHAN_MODE_SHARED); | 156 | CHAN_MODE_SHARED); |
161 | if (err) | 157 | if (err) |
162 | return err; | 158 | return err; |
@@ -165,7 +161,7 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | |||
165 | if (!err) { | 161 | if (!err) { |
166 | memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len); | 162 | memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len); |
167 | wdev->mesh_id_len = setup->mesh_id_len; | 163 | wdev->mesh_id_len = setup->mesh_id_len; |
168 | wdev->channel = setup->channel; | 164 | wdev->channel = setup->chandef.chan; |
169 | } | 165 | } |
170 | 166 | ||
171 | return err; | 167 | return err; |
@@ -188,20 +184,12 @@ int cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | |||
188 | return err; | 184 | return err; |
189 | } | 185 | } |
190 | 186 | ||
191 | int cfg80211_set_mesh_freq(struct cfg80211_registered_device *rdev, | 187 | int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev, |
192 | struct wireless_dev *wdev, int freq, | 188 | struct wireless_dev *wdev, |
193 | enum nl80211_channel_type channel_type) | 189 | struct cfg80211_chan_def *chandef) |
194 | { | 190 | { |
195 | struct ieee80211_channel *channel; | ||
196 | int err; | 191 | int err; |
197 | 192 | ||
198 | channel = rdev_freq_to_chan(rdev, freq, channel_type); | ||
199 | if (!channel || !cfg80211_can_beacon_sec_chan(&rdev->wiphy, | ||
200 | channel, | ||
201 | channel_type)) { | ||
202 | return -EINVAL; | ||
203 | } | ||
204 | |||
205 | /* | 193 | /* |
206 | * Workaround for libertas (only!), it puts the interface | 194 | * Workaround for libertas (only!), it puts the interface |
207 | * into mesh mode but doesn't implement join_mesh. Instead, | 195 | * into mesh mode but doesn't implement join_mesh. Instead, |
@@ -210,21 +198,21 @@ int cfg80211_set_mesh_freq(struct cfg80211_registered_device *rdev, | |||
210 | * compatible with 802.11 mesh. | 198 | * compatible with 802.11 mesh. |
211 | */ | 199 | */ |
212 | if (rdev->ops->libertas_set_mesh_channel) { | 200 | if (rdev->ops->libertas_set_mesh_channel) { |
213 | if (channel_type != NL80211_CHAN_NO_HT) | 201 | if (chandef->width != NL80211_CHAN_WIDTH_20_NOHT) |
214 | return -EINVAL; | 202 | return -EINVAL; |
215 | 203 | ||
216 | if (!netif_running(wdev->netdev)) | 204 | if (!netif_running(wdev->netdev)) |
217 | return -ENETDOWN; | 205 | return -ENETDOWN; |
218 | 206 | ||
219 | err = cfg80211_can_use_chan(rdev, wdev, channel, | 207 | err = cfg80211_can_use_chan(rdev, wdev, chandef->chan, |
220 | CHAN_MODE_SHARED); | 208 | CHAN_MODE_SHARED); |
221 | if (err) | 209 | if (err) |
222 | return err; | 210 | return err; |
223 | 211 | ||
224 | err = rdev_libertas_set_mesh_channel(rdev, wdev->netdev, | 212 | err = rdev_libertas_set_mesh_channel(rdev, wdev->netdev, |
225 | channel); | 213 | chandef->chan); |
226 | if (!err) | 214 | if (!err) |
227 | wdev->channel = channel; | 215 | wdev->channel = chandef->chan; |
228 | 216 | ||
229 | return err; | 217 | return err; |
230 | } | 218 | } |
@@ -232,8 +220,7 @@ int cfg80211_set_mesh_freq(struct cfg80211_registered_device *rdev, | |||
232 | if (wdev->mesh_id_len) | 220 | if (wdev->mesh_id_len) |
233 | return -EBUSY; | 221 | return -EBUSY; |
234 | 222 | ||
235 | wdev->preset_chan = channel; | 223 | wdev->preset_chandef = *chandef; |
236 | wdev->preset_chantype = channel_type; | ||
237 | return 0; | 224 | return 0; |
238 | } | 225 | } |
239 | 226 | ||
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 4bfd14f7c59..5e8123ee63f 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -579,31 +579,25 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, | |||
579 | 579 | ||
580 | void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie, | 580 | void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie, |
581 | struct ieee80211_channel *chan, | 581 | struct ieee80211_channel *chan, |
582 | enum nl80211_channel_type channel_type, | ||
583 | unsigned int duration, gfp_t gfp) | 582 | unsigned int duration, gfp_t gfp) |
584 | { | 583 | { |
585 | struct wiphy *wiphy = wdev->wiphy; | 584 | struct wiphy *wiphy = wdev->wiphy; |
586 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | 585 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); |
587 | 586 | ||
588 | trace_cfg80211_ready_on_channel(wdev, cookie, chan, channel_type, | 587 | trace_cfg80211_ready_on_channel(wdev, cookie, chan, duration); |
589 | duration); | 588 | nl80211_send_remain_on_channel(rdev, wdev, cookie, chan, duration, gfp); |
590 | nl80211_send_remain_on_channel(rdev, wdev, cookie, chan, channel_type, | ||
591 | duration, gfp); | ||
592 | } | 589 | } |
593 | EXPORT_SYMBOL(cfg80211_ready_on_channel); | 590 | EXPORT_SYMBOL(cfg80211_ready_on_channel); |
594 | 591 | ||
595 | void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie, | 592 | void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie, |
596 | struct ieee80211_channel *chan, | 593 | struct ieee80211_channel *chan, |
597 | enum nl80211_channel_type channel_type, | ||
598 | gfp_t gfp) | 594 | gfp_t gfp) |
599 | { | 595 | { |
600 | struct wiphy *wiphy = wdev->wiphy; | 596 | struct wiphy *wiphy = wdev->wiphy; |
601 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | 597 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); |
602 | 598 | ||
603 | trace_cfg80211_ready_on_channel_expired(wdev, cookie, chan, | 599 | trace_cfg80211_ready_on_channel_expired(wdev, cookie, chan); |
604 | channel_type); | 600 | nl80211_send_remain_on_channel_cancel(rdev, wdev, cookie, chan, gfp); |
605 | nl80211_send_remain_on_channel_cancel(rdev, wdev, cookie, chan, | ||
606 | channel_type, gfp); | ||
607 | } | 601 | } |
608 | EXPORT_SYMBOL(cfg80211_remain_on_channel_expired); | 602 | EXPORT_SYMBOL(cfg80211_remain_on_channel_expired); |
609 | 603 | ||
@@ -758,10 +752,8 @@ void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev) | |||
758 | int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, | 752 | int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, |
759 | struct wireless_dev *wdev, | 753 | struct wireless_dev *wdev, |
760 | struct ieee80211_channel *chan, bool offchan, | 754 | struct ieee80211_channel *chan, bool offchan, |
761 | enum nl80211_channel_type channel_type, | 755 | unsigned int wait, const u8 *buf, size_t len, |
762 | bool channel_type_valid, unsigned int wait, | 756 | bool no_cck, bool dont_wait_for_ack, u64 *cookie) |
763 | const u8 *buf, size_t len, bool no_cck, | ||
764 | bool dont_wait_for_ack, u64 *cookie) | ||
765 | { | 757 | { |
766 | const struct ieee80211_mgmt *mgmt; | 758 | const struct ieee80211_mgmt *mgmt; |
767 | u16 stype; | 759 | u16 stype; |
@@ -855,7 +847,6 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, | |||
855 | 847 | ||
856 | /* Transmit the Action frame as requested by user space */ | 848 | /* Transmit the Action frame as requested by user space */ |
857 | return rdev_mgmt_tx(rdev, wdev, chan, offchan, | 849 | return rdev_mgmt_tx(rdev, wdev, chan, offchan, |
858 | channel_type, channel_type_valid, | ||
859 | wait, buf, len, no_cck, dont_wait_for_ack, | 850 | wait, buf, len, no_cck, dont_wait_for_ack, |
860 | cookie); | 851 | cookie); |
861 | } | 852 | } |
@@ -997,15 +988,14 @@ void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index, | |||
997 | } | 988 | } |
998 | EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify); | 989 | EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify); |
999 | 990 | ||
1000 | void cfg80211_ch_switch_notify(struct net_device *dev, int freq, | 991 | void cfg80211_ch_switch_notify(struct net_device *dev, |
1001 | enum nl80211_channel_type type) | 992 | struct cfg80211_chan_def *chandef) |
1002 | { | 993 | { |
1003 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 994 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
1004 | struct wiphy *wiphy = wdev->wiphy; | 995 | struct wiphy *wiphy = wdev->wiphy; |
1005 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | 996 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); |
1006 | struct ieee80211_channel *chan; | ||
1007 | 997 | ||
1008 | trace_cfg80211_ch_switch_notify(dev, freq, type); | 998 | trace_cfg80211_ch_switch_notify(dev, chandef); |
1009 | 999 | ||
1010 | wdev_lock(wdev); | 1000 | wdev_lock(wdev); |
1011 | 1001 | ||
@@ -1013,12 +1003,8 @@ void cfg80211_ch_switch_notify(struct net_device *dev, int freq, | |||
1013 | wdev->iftype != NL80211_IFTYPE_P2P_GO)) | 1003 | wdev->iftype != NL80211_IFTYPE_P2P_GO)) |
1014 | goto out; | 1004 | goto out; |
1015 | 1005 | ||
1016 | chan = rdev_freq_to_chan(rdev, freq, type); | 1006 | wdev->channel = chandef->chan; |
1017 | if (WARN_ON(!chan)) | 1007 | nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL); |
1018 | goto out; | ||
1019 | |||
1020 | wdev->channel = chan; | ||
1021 | nl80211_ch_switch_notify(rdev, dev, freq, type, GFP_KERNEL); | ||
1022 | out: | 1008 | out: |
1023 | wdev_unlock(wdev); | 1009 | wdev_unlock(wdev); |
1024 | return; | 1010 | return; |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 8c0857815a9..d038fa45ecd 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -223,8 +223,13 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
223 | [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING, | 223 | [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING, |
224 | .len = 20-1 }, | 224 | .len = 20-1 }, |
225 | [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED }, | 225 | [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED }, |
226 | |||
226 | [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 }, | 227 | [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 }, |
227 | [NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 }, | 228 | [NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 }, |
229 | [NL80211_ATTR_CHANNEL_WIDTH] = { .type = NLA_U32 }, | ||
230 | [NL80211_ATTR_CENTER_FREQ1] = { .type = NLA_U32 }, | ||
231 | [NL80211_ATTR_CENTER_FREQ2] = { .type = NLA_U32 }, | ||
232 | |||
228 | [NL80211_ATTR_WIPHY_RETRY_SHORT] = { .type = NLA_U8 }, | 233 | [NL80211_ATTR_WIPHY_RETRY_SHORT] = { .type = NLA_U8 }, |
229 | [NL80211_ATTR_WIPHY_RETRY_LONG] = { .type = NLA_U8 }, | 234 | [NL80211_ATTR_WIPHY_RETRY_LONG] = { .type = NLA_U8 }, |
230 | [NL80211_ATTR_WIPHY_FRAG_THRESHOLD] = { .type = NLA_U32 }, | 235 | [NL80211_ATTR_WIPHY_FRAG_THRESHOLD] = { .type = NLA_U32 }, |
@@ -1110,6 +1115,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flag | |||
1110 | goto nla_put_failure; | 1115 | goto nla_put_failure; |
1111 | } | 1116 | } |
1112 | CMD(start_p2p_device, START_P2P_DEVICE); | 1117 | CMD(start_p2p_device, START_P2P_DEVICE); |
1118 | CMD(set_mcast_rate, SET_MCAST_RATE); | ||
1113 | 1119 | ||
1114 | #ifdef CONFIG_NL80211_TESTMODE | 1120 | #ifdef CONFIG_NL80211_TESTMODE |
1115 | CMD(testmode_cmd, TESTMODE); | 1121 | CMD(testmode_cmd, TESTMODE); |
@@ -1359,51 +1365,139 @@ static bool nl80211_can_set_dev_channel(struct wireless_dev *wdev) | |||
1359 | wdev->iftype == NL80211_IFTYPE_P2P_GO; | 1365 | wdev->iftype == NL80211_IFTYPE_P2P_GO; |
1360 | } | 1366 | } |
1361 | 1367 | ||
1362 | static bool nl80211_valid_channel_type(struct genl_info *info, | 1368 | static int nl80211_parse_chandef(struct cfg80211_registered_device *rdev, |
1363 | enum nl80211_channel_type *channel_type) | 1369 | struct genl_info *info, |
1370 | struct cfg80211_chan_def *chandef) | ||
1364 | { | 1371 | { |
1365 | enum nl80211_channel_type tmp; | 1372 | struct ieee80211_sta_ht_cap *ht_cap; |
1373 | struct ieee80211_sta_vht_cap *vht_cap; | ||
1374 | u32 control_freq, width; | ||
1366 | 1375 | ||
1367 | if (!info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) | 1376 | if (!info->attrs[NL80211_ATTR_WIPHY_FREQ]) |
1368 | return false; | 1377 | return -EINVAL; |
1369 | 1378 | ||
1370 | tmp = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]); | 1379 | control_freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); |
1371 | if (tmp != NL80211_CHAN_NO_HT && | ||
1372 | tmp != NL80211_CHAN_HT20 && | ||
1373 | tmp != NL80211_CHAN_HT40PLUS && | ||
1374 | tmp != NL80211_CHAN_HT40MINUS) | ||
1375 | return false; | ||
1376 | 1380 | ||
1377 | if (channel_type) | 1381 | chandef->chan = ieee80211_get_channel(&rdev->wiphy, control_freq); |
1378 | *channel_type = tmp; | 1382 | chandef->width = NL80211_CHAN_WIDTH_20_NOHT; |
1383 | chandef->center_freq1 = control_freq; | ||
1384 | chandef->center_freq2 = 0; | ||
1379 | 1385 | ||
1380 | return true; | 1386 | /* Primary channel not allowed */ |
1387 | if (!chandef->chan || chandef->chan->flags & IEEE80211_CHAN_DISABLED) | ||
1388 | return -EINVAL; | ||
1389 | |||
1390 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { | ||
1391 | enum nl80211_channel_type chantype; | ||
1392 | |||
1393 | chantype = nla_get_u32( | ||
1394 | info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]); | ||
1395 | |||
1396 | switch (chantype) { | ||
1397 | case NL80211_CHAN_NO_HT: | ||
1398 | case NL80211_CHAN_HT20: | ||
1399 | case NL80211_CHAN_HT40PLUS: | ||
1400 | case NL80211_CHAN_HT40MINUS: | ||
1401 | cfg80211_chandef_create(chandef, chandef->chan, | ||
1402 | chantype); | ||
1403 | break; | ||
1404 | default: | ||
1405 | return -EINVAL; | ||
1406 | } | ||
1407 | } else if (info->attrs[NL80211_ATTR_CHANNEL_WIDTH]) { | ||
1408 | chandef->width = | ||
1409 | nla_get_u32(info->attrs[NL80211_ATTR_CHANNEL_WIDTH]); | ||
1410 | if (info->attrs[NL80211_ATTR_CENTER_FREQ1]) | ||
1411 | chandef->center_freq1 = | ||
1412 | nla_get_u32( | ||
1413 | info->attrs[NL80211_ATTR_CENTER_FREQ1]); | ||
1414 | if (info->attrs[NL80211_ATTR_CENTER_FREQ2]) | ||
1415 | chandef->center_freq2 = | ||
1416 | nla_get_u32( | ||
1417 | info->attrs[NL80211_ATTR_CENTER_FREQ2]); | ||
1418 | } | ||
1419 | |||
1420 | ht_cap = &rdev->wiphy.bands[chandef->chan->band]->ht_cap; | ||
1421 | vht_cap = &rdev->wiphy.bands[chandef->chan->band]->vht_cap; | ||
1422 | |||
1423 | if (!cfg80211_chan_def_valid(chandef)) | ||
1424 | return -EINVAL; | ||
1425 | |||
1426 | switch (chandef->width) { | ||
1427 | case NL80211_CHAN_WIDTH_20: | ||
1428 | if (!ht_cap->ht_supported) | ||
1429 | return -EINVAL; | ||
1430 | case NL80211_CHAN_WIDTH_20_NOHT: | ||
1431 | width = 20; | ||
1432 | break; | ||
1433 | case NL80211_CHAN_WIDTH_40: | ||
1434 | width = 40; | ||
1435 | /* quick early regulatory check */ | ||
1436 | if (chandef->center_freq1 < control_freq && | ||
1437 | chandef->chan->flags & IEEE80211_CHAN_NO_HT40MINUS) | ||
1438 | return -EINVAL; | ||
1439 | if (chandef->center_freq1 > control_freq && | ||
1440 | chandef->chan->flags & IEEE80211_CHAN_NO_HT40PLUS) | ||
1441 | return -EINVAL; | ||
1442 | if (!ht_cap->ht_supported) | ||
1443 | return -EINVAL; | ||
1444 | if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) || | ||
1445 | ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT) | ||
1446 | return -EINVAL; | ||
1447 | break; | ||
1448 | case NL80211_CHAN_WIDTH_80: | ||
1449 | width = 80; | ||
1450 | if (!vht_cap->vht_supported) | ||
1451 | return -EINVAL; | ||
1452 | break; | ||
1453 | case NL80211_CHAN_WIDTH_80P80: | ||
1454 | width = 80; | ||
1455 | if (!vht_cap->vht_supported) | ||
1456 | return -EINVAL; | ||
1457 | if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)) | ||
1458 | return -EINVAL; | ||
1459 | break; | ||
1460 | case NL80211_CHAN_WIDTH_160: | ||
1461 | width = 160; | ||
1462 | if (!vht_cap->vht_supported) | ||
1463 | return -EINVAL; | ||
1464 | if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ)) | ||
1465 | return -EINVAL; | ||
1466 | break; | ||
1467 | default: | ||
1468 | return -EINVAL; | ||
1469 | } | ||
1470 | |||
1471 | if (!cfg80211_secondary_chans_ok(&rdev->wiphy, chandef->center_freq1, | ||
1472 | width, IEEE80211_CHAN_DISABLED)) | ||
1473 | return -EINVAL; | ||
1474 | if (chandef->center_freq2 && | ||
1475 | !cfg80211_secondary_chans_ok(&rdev->wiphy, chandef->center_freq2, | ||
1476 | width, IEEE80211_CHAN_DISABLED)) | ||
1477 | return -EINVAL; | ||
1478 | |||
1479 | /* TODO: missing regulatory check on bandwidth */ | ||
1480 | |||
1481 | return 0; | ||
1381 | } | 1482 | } |
1382 | 1483 | ||
1383 | static int __nl80211_set_channel(struct cfg80211_registered_device *rdev, | 1484 | static int __nl80211_set_channel(struct cfg80211_registered_device *rdev, |
1384 | struct wireless_dev *wdev, | 1485 | struct wireless_dev *wdev, |
1385 | struct genl_info *info) | 1486 | struct genl_info *info) |
1386 | { | 1487 | { |
1387 | struct ieee80211_channel *channel; | 1488 | struct cfg80211_chan_def chandef; |
1388 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; | ||
1389 | u32 freq; | ||
1390 | int result; | 1489 | int result; |
1391 | enum nl80211_iftype iftype = NL80211_IFTYPE_MONITOR; | 1490 | enum nl80211_iftype iftype = NL80211_IFTYPE_MONITOR; |
1392 | 1491 | ||
1393 | if (wdev) | 1492 | if (wdev) |
1394 | iftype = wdev->iftype; | 1493 | iftype = wdev->iftype; |
1395 | 1494 | ||
1396 | if (!info->attrs[NL80211_ATTR_WIPHY_FREQ]) | ||
1397 | return -EINVAL; | ||
1398 | |||
1399 | if (!nl80211_can_set_dev_channel(wdev)) | 1495 | if (!nl80211_can_set_dev_channel(wdev)) |
1400 | return -EOPNOTSUPP; | 1496 | return -EOPNOTSUPP; |
1401 | 1497 | ||
1402 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] && | 1498 | result = nl80211_parse_chandef(rdev, info, &chandef); |
1403 | !nl80211_valid_channel_type(info, &channel_type)) | 1499 | if (result) |
1404 | return -EINVAL; | 1500 | return result; |
1405 | |||
1406 | freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); | ||
1407 | 1501 | ||
1408 | mutex_lock(&rdev->devlist_mtx); | 1502 | mutex_lock(&rdev->devlist_mtx); |
1409 | switch (iftype) { | 1503 | switch (iftype) { |
@@ -1413,22 +1507,18 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev, | |||
1413 | result = -EBUSY; | 1507 | result = -EBUSY; |
1414 | break; | 1508 | break; |
1415 | } | 1509 | } |
1416 | channel = rdev_freq_to_chan(rdev, freq, channel_type); | 1510 | if (!cfg80211_reg_can_beacon(&rdev->wiphy, &chandef)) { |
1417 | if (!channel || !cfg80211_can_beacon_sec_chan(&rdev->wiphy, | ||
1418 | channel, | ||
1419 | channel_type)) { | ||
1420 | result = -EINVAL; | 1511 | result = -EINVAL; |
1421 | break; | 1512 | break; |
1422 | } | 1513 | } |
1423 | wdev->preset_chan = channel; | 1514 | wdev->preset_chandef = chandef; |
1424 | wdev->preset_chantype = channel_type; | ||
1425 | result = 0; | 1515 | result = 0; |
1426 | break; | 1516 | break; |
1427 | case NL80211_IFTYPE_MESH_POINT: | 1517 | case NL80211_IFTYPE_MESH_POINT: |
1428 | result = cfg80211_set_mesh_freq(rdev, wdev, freq, channel_type); | 1518 | result = cfg80211_set_mesh_channel(rdev, wdev, &chandef); |
1429 | break; | 1519 | break; |
1430 | case NL80211_IFTYPE_MONITOR: | 1520 | case NL80211_IFTYPE_MONITOR: |
1431 | result = cfg80211_set_monitor_channel(rdev, freq, channel_type); | 1521 | result = cfg80211_set_monitor_channel(rdev, &chandef); |
1432 | break; | 1522 | break; |
1433 | default: | 1523 | default: |
1434 | result = -EINVAL; | 1524 | result = -EINVAL; |
@@ -1516,10 +1606,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
1516 | result = 0; | 1606 | result = 0; |
1517 | 1607 | ||
1518 | mutex_lock(&rdev->mtx); | 1608 | mutex_lock(&rdev->mtx); |
1519 | } else if (nl80211_can_set_dev_channel(netdev->ieee80211_ptr)) | 1609 | } else |
1520 | wdev = netdev->ieee80211_ptr; | 1610 | wdev = netdev->ieee80211_ptr; |
1521 | else | ||
1522 | wdev = NULL; | ||
1523 | 1611 | ||
1524 | /* | 1612 | /* |
1525 | * end workaround code, by now the rdev is available | 1613 | * end workaround code, by now the rdev is available |
@@ -1579,15 +1667,21 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
1579 | } | 1667 | } |
1580 | 1668 | ||
1581 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { | 1669 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { |
1582 | result = __nl80211_set_channel(rdev, wdev, info); | 1670 | result = __nl80211_set_channel(rdev, |
1671 | nl80211_can_set_dev_channel(wdev) ? wdev : NULL, | ||
1672 | info); | ||
1583 | if (result) | 1673 | if (result) |
1584 | goto bad_res; | 1674 | goto bad_res; |
1585 | } | 1675 | } |
1586 | 1676 | ||
1587 | if (info->attrs[NL80211_ATTR_WIPHY_TX_POWER_SETTING]) { | 1677 | if (info->attrs[NL80211_ATTR_WIPHY_TX_POWER_SETTING]) { |
1678 | struct wireless_dev *txp_wdev = wdev; | ||
1588 | enum nl80211_tx_power_setting type; | 1679 | enum nl80211_tx_power_setting type; |
1589 | int idx, mbm = 0; | 1680 | int idx, mbm = 0; |
1590 | 1681 | ||
1682 | if (!(rdev->wiphy.features & NL80211_FEATURE_VIF_TXPOWER)) | ||
1683 | txp_wdev = NULL; | ||
1684 | |||
1591 | if (!rdev->ops->set_tx_power) { | 1685 | if (!rdev->ops->set_tx_power) { |
1592 | result = -EOPNOTSUPP; | 1686 | result = -EOPNOTSUPP; |
1593 | goto bad_res; | 1687 | goto bad_res; |
@@ -1607,7 +1701,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
1607 | mbm = nla_get_u32(info->attrs[idx]); | 1701 | mbm = nla_get_u32(info->attrs[idx]); |
1608 | } | 1702 | } |
1609 | 1703 | ||
1610 | result = rdev_set_tx_power(rdev, type, mbm); | 1704 | result = rdev_set_tx_power(rdev, txp_wdev, type, mbm); |
1611 | if (result) | 1705 | if (result) |
1612 | goto bad_res; | 1706 | goto bad_res; |
1613 | } | 1707 | } |
@@ -1744,6 +1838,35 @@ static inline u64 wdev_id(struct wireless_dev *wdev) | |||
1744 | ((u64)wiphy_to_dev(wdev->wiphy)->wiphy_idx << 32); | 1838 | ((u64)wiphy_to_dev(wdev->wiphy)->wiphy_idx << 32); |
1745 | } | 1839 | } |
1746 | 1840 | ||
1841 | static int nl80211_send_chandef(struct sk_buff *msg, | ||
1842 | struct cfg80211_chan_def *chandef) | ||
1843 | { | ||
1844 | WARN_ON(!cfg80211_chan_def_valid(chandef)); | ||
1845 | |||
1846 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, | ||
1847 | chandef->chan->center_freq)) | ||
1848 | return -ENOBUFS; | ||
1849 | switch (chandef->width) { | ||
1850 | case NL80211_CHAN_WIDTH_20_NOHT: | ||
1851 | case NL80211_CHAN_WIDTH_20: | ||
1852 | case NL80211_CHAN_WIDTH_40: | ||
1853 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, | ||
1854 | cfg80211_get_chandef_type(chandef))) | ||
1855 | return -ENOBUFS; | ||
1856 | break; | ||
1857 | default: | ||
1858 | break; | ||
1859 | } | ||
1860 | if (nla_put_u32(msg, NL80211_ATTR_CHANNEL_WIDTH, chandef->width)) | ||
1861 | return -ENOBUFS; | ||
1862 | if (nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ1, chandef->center_freq1)) | ||
1863 | return -ENOBUFS; | ||
1864 | if (chandef->center_freq2 && | ||
1865 | nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ2, chandef->center_freq2)) | ||
1866 | return -ENOBUFS; | ||
1867 | return 0; | ||
1868 | } | ||
1869 | |||
1747 | static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags, | 1870 | static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags, |
1748 | struct cfg80211_registered_device *rdev, | 1871 | struct cfg80211_registered_device *rdev, |
1749 | struct wireless_dev *wdev) | 1872 | struct wireless_dev *wdev) |
@@ -1770,15 +1893,18 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flag | |||
1770 | goto nla_put_failure; | 1893 | goto nla_put_failure; |
1771 | 1894 | ||
1772 | if (rdev->ops->get_channel) { | 1895 | if (rdev->ops->get_channel) { |
1773 | struct ieee80211_channel *chan; | 1896 | int ret; |
1774 | enum nl80211_channel_type channel_type; | 1897 | struct cfg80211_chan_def chandef; |
1775 | 1898 | ||
1776 | chan = rdev_get_channel(rdev, wdev, &channel_type); | 1899 | ret = rdev_get_channel(rdev, wdev, &chandef); |
1777 | if (chan && | 1900 | if (ret == 0) { |
1778 | (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, | 1901 | if (nl80211_send_chandef(msg, &chandef)) |
1779 | chan->center_freq) || | 1902 | goto nla_put_failure; |
1780 | nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, | 1903 | } |
1781 | channel_type))) | 1904 | } |
1905 | |||
1906 | if (wdev->ssid_len) { | ||
1907 | if (nla_put(msg, NL80211_ATTR_SSID, wdev->ssid_len, wdev->ssid)) | ||
1782 | goto nla_put_failure; | 1908 | goto nla_put_failure; |
1783 | } | 1909 | } |
1784 | 1910 | ||
@@ -2482,11 +2608,10 @@ static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev, | |||
2482 | wdev->iftype != NL80211_IFTYPE_P2P_GO) | 2608 | wdev->iftype != NL80211_IFTYPE_P2P_GO) |
2483 | continue; | 2609 | continue; |
2484 | 2610 | ||
2485 | if (!wdev->preset_chan) | 2611 | if (!wdev->preset_chandef.chan) |
2486 | continue; | 2612 | continue; |
2487 | 2613 | ||
2488 | params->channel = wdev->preset_chan; | 2614 | params->chandef = wdev->preset_chandef; |
2489 | params->channel_type = wdev->preset_chantype; | ||
2490 | ret = true; | 2615 | ret = true; |
2491 | break; | 2616 | break; |
2492 | } | 2617 | } |
@@ -2608,30 +2733,19 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) | |||
2608 | } | 2733 | } |
2609 | 2734 | ||
2610 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { | 2735 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { |
2611 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; | 2736 | err = nl80211_parse_chandef(rdev, info, ¶ms.chandef); |
2612 | 2737 | if (err) | |
2613 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] && | 2738 | return err; |
2614 | !nl80211_valid_channel_type(info, &channel_type)) | 2739 | } else if (wdev->preset_chandef.chan) { |
2615 | return -EINVAL; | 2740 | params.chandef = wdev->preset_chandef; |
2616 | |||
2617 | params.channel = rdev_freq_to_chan(rdev, | ||
2618 | nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]), | ||
2619 | channel_type); | ||
2620 | if (!params.channel) | ||
2621 | return -EINVAL; | ||
2622 | params.channel_type = channel_type; | ||
2623 | } else if (wdev->preset_chan) { | ||
2624 | params.channel = wdev->preset_chan; | ||
2625 | params.channel_type = wdev->preset_chantype; | ||
2626 | } else if (!nl80211_get_ap_channel(rdev, ¶ms)) | 2741 | } else if (!nl80211_get_ap_channel(rdev, ¶ms)) |
2627 | return -EINVAL; | 2742 | return -EINVAL; |
2628 | 2743 | ||
2629 | if (!cfg80211_can_beacon_sec_chan(&rdev->wiphy, params.channel, | 2744 | if (!cfg80211_reg_can_beacon(&rdev->wiphy, ¶ms.chandef)) |
2630 | params.channel_type)) | ||
2631 | return -EINVAL; | 2745 | return -EINVAL; |
2632 | 2746 | ||
2633 | mutex_lock(&rdev->devlist_mtx); | 2747 | mutex_lock(&rdev->devlist_mtx); |
2634 | err = cfg80211_can_use_chan(rdev, wdev, params.channel, | 2748 | err = cfg80211_can_use_chan(rdev, wdev, params.chandef.chan, |
2635 | CHAN_MODE_SHARED); | 2749 | CHAN_MODE_SHARED); |
2636 | mutex_unlock(&rdev->devlist_mtx); | 2750 | mutex_unlock(&rdev->devlist_mtx); |
2637 | 2751 | ||
@@ -2640,10 +2754,11 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) | |||
2640 | 2754 | ||
2641 | err = rdev_start_ap(rdev, dev, ¶ms); | 2755 | err = rdev_start_ap(rdev, dev, ¶ms); |
2642 | if (!err) { | 2756 | if (!err) { |
2643 | wdev->preset_chan = params.channel; | 2757 | wdev->preset_chandef = params.chandef; |
2644 | wdev->preset_chantype = params.channel_type; | ||
2645 | wdev->beacon_interval = params.beacon_interval; | 2758 | wdev->beacon_interval = params.beacon_interval; |
2646 | wdev->channel = params.channel; | 2759 | wdev->channel = params.chandef.chan; |
2760 | wdev->ssid_len = params.ssid_len; | ||
2761 | memcpy(wdev->ssid, params.ssid, wdev->ssid_len); | ||
2647 | } | 2762 | } |
2648 | return err; | 2763 | return err; |
2649 | } | 2764 | } |
@@ -2775,29 +2890,52 @@ static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, | |||
2775 | 2890 | ||
2776 | rate = nla_nest_start(msg, attr); | 2891 | rate = nla_nest_start(msg, attr); |
2777 | if (!rate) | 2892 | if (!rate) |
2778 | goto nla_put_failure; | 2893 | return false; |
2779 | 2894 | ||
2780 | /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */ | 2895 | /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */ |
2781 | bitrate = cfg80211_calculate_bitrate(info); | 2896 | bitrate = cfg80211_calculate_bitrate(info); |
2782 | /* report 16-bit bitrate only if we can */ | 2897 | /* report 16-bit bitrate only if we can */ |
2783 | bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0; | 2898 | bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0; |
2784 | if ((bitrate > 0 && | 2899 | if (bitrate > 0 && |
2785 | nla_put_u32(msg, NL80211_RATE_INFO_BITRATE32, bitrate)) || | 2900 | nla_put_u32(msg, NL80211_RATE_INFO_BITRATE32, bitrate)) |
2786 | (bitrate_compat > 0 && | 2901 | return false; |
2787 | nla_put_u16(msg, NL80211_RATE_INFO_BITRATE, bitrate_compat)) || | 2902 | if (bitrate_compat > 0 && |
2788 | ((info->flags & RATE_INFO_FLAGS_MCS) && | 2903 | nla_put_u16(msg, NL80211_RATE_INFO_BITRATE, bitrate_compat)) |
2789 | nla_put_u8(msg, NL80211_RATE_INFO_MCS, info->mcs)) || | 2904 | return false; |
2790 | ((info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) && | 2905 | |
2791 | nla_put_flag(msg, NL80211_RATE_INFO_40_MHZ_WIDTH)) || | 2906 | if (info->flags & RATE_INFO_FLAGS_MCS) { |
2792 | ((info->flags & RATE_INFO_FLAGS_SHORT_GI) && | 2907 | if (nla_put_u8(msg, NL80211_RATE_INFO_MCS, info->mcs)) |
2793 | nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI))) | 2908 | return false; |
2794 | goto nla_put_failure; | 2909 | if (info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH && |
2910 | nla_put_flag(msg, NL80211_RATE_INFO_40_MHZ_WIDTH)) | ||
2911 | return false; | ||
2912 | if (info->flags & RATE_INFO_FLAGS_SHORT_GI && | ||
2913 | nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI)) | ||
2914 | return false; | ||
2915 | } else if (info->flags & RATE_INFO_FLAGS_VHT_MCS) { | ||
2916 | if (nla_put_u8(msg, NL80211_RATE_INFO_VHT_MCS, info->mcs)) | ||
2917 | return false; | ||
2918 | if (nla_put_u8(msg, NL80211_RATE_INFO_VHT_NSS, info->nss)) | ||
2919 | return false; | ||
2920 | if (info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH && | ||
2921 | nla_put_flag(msg, NL80211_RATE_INFO_40_MHZ_WIDTH)) | ||
2922 | return false; | ||
2923 | if (info->flags & RATE_INFO_FLAGS_80_MHZ_WIDTH && | ||
2924 | nla_put_flag(msg, NL80211_RATE_INFO_80_MHZ_WIDTH)) | ||
2925 | return false; | ||
2926 | if (info->flags & RATE_INFO_FLAGS_80P80_MHZ_WIDTH && | ||
2927 | nla_put_flag(msg, NL80211_RATE_INFO_80P80_MHZ_WIDTH)) | ||
2928 | return false; | ||
2929 | if (info->flags & RATE_INFO_FLAGS_160_MHZ_WIDTH && | ||
2930 | nla_put_flag(msg, NL80211_RATE_INFO_160_MHZ_WIDTH)) | ||
2931 | return false; | ||
2932 | if (info->flags & RATE_INFO_FLAGS_SHORT_GI && | ||
2933 | nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI)) | ||
2934 | return false; | ||
2935 | } | ||
2795 | 2936 | ||
2796 | nla_nest_end(msg, rate); | 2937 | nla_nest_end(msg, rate); |
2797 | return true; | 2938 | return true; |
2798 | |||
2799 | nla_put_failure: | ||
2800 | return false; | ||
2801 | } | 2939 | } |
2802 | 2940 | ||
2803 | static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq, | 2941 | static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq, |
@@ -5318,8 +5456,7 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) | |||
5318 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) | 5456 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) |
5319 | return -EINVAL; | 5457 | return -EINVAL; |
5320 | 5458 | ||
5321 | if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] || | 5459 | if (!info->attrs[NL80211_ATTR_SSID] || |
5322 | !info->attrs[NL80211_ATTR_SSID] || | ||
5323 | !nla_len(info->attrs[NL80211_ATTR_SSID])) | 5460 | !nla_len(info->attrs[NL80211_ATTR_SSID])) |
5324 | return -EINVAL; | 5461 | return -EINVAL; |
5325 | 5462 | ||
@@ -5354,35 +5491,17 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) | |||
5354 | ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); | 5491 | ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); |
5355 | } | 5492 | } |
5356 | 5493 | ||
5357 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { | 5494 | err = nl80211_parse_chandef(rdev, info, &ibss.chandef); |
5358 | enum nl80211_channel_type channel_type; | 5495 | if (err) |
5359 | 5496 | return err; | |
5360 | if (!nl80211_valid_channel_type(info, &channel_type)) | ||
5361 | return -EINVAL; | ||
5362 | |||
5363 | if (channel_type != NL80211_CHAN_NO_HT && | ||
5364 | !(wiphy->features & NL80211_FEATURE_HT_IBSS)) | ||
5365 | return -EINVAL; | ||
5366 | |||
5367 | ibss.channel_type = channel_type; | ||
5368 | } else { | ||
5369 | ibss.channel_type = NL80211_CHAN_NO_HT; | ||
5370 | } | ||
5371 | 5497 | ||
5372 | ibss.channel = rdev_freq_to_chan(rdev, | 5498 | if (!cfg80211_reg_can_beacon(&rdev->wiphy, &ibss.chandef)) |
5373 | nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]), | ||
5374 | ibss.channel_type); | ||
5375 | if (!ibss.channel || | ||
5376 | ibss.channel->flags & IEEE80211_CHAN_NO_IBSS || | ||
5377 | ibss.channel->flags & IEEE80211_CHAN_DISABLED) | ||
5378 | return -EINVAL; | 5499 | return -EINVAL; |
5379 | 5500 | ||
5380 | /* Both channels should be able to initiate communication */ | 5501 | if (ibss.chandef.width > NL80211_CHAN_WIDTH_40) |
5381 | if ((ibss.channel_type == NL80211_CHAN_HT40PLUS || | ||
5382 | ibss.channel_type == NL80211_CHAN_HT40MINUS) && | ||
5383 | !cfg80211_can_beacon_sec_chan(&rdev->wiphy, ibss.channel, | ||
5384 | ibss.channel_type)) | ||
5385 | return -EINVAL; | 5502 | return -EINVAL; |
5503 | if (ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT && | ||
5504 | !(rdev->wiphy.features & NL80211_FEATURE_HT_IBSS)) | ||
5386 | 5505 | ||
5387 | ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED]; | 5506 | ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED]; |
5388 | ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY]; | 5507 | ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY]; |
@@ -5393,7 +5512,7 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) | |||
5393 | int n_rates = | 5512 | int n_rates = |
5394 | nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); | 5513 | nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); |
5395 | struct ieee80211_supported_band *sband = | 5514 | struct ieee80211_supported_band *sband = |
5396 | wiphy->bands[ibss.channel->band]; | 5515 | wiphy->bands[ibss.chandef.chan->band]; |
5397 | 5516 | ||
5398 | err = ieee80211_get_ratemask(sband, rates, n_rates, | 5517 | err = ieee80211_get_ratemask(sband, rates, n_rates, |
5399 | &ibss.basic_rates); | 5518 | &ibss.basic_rates); |
@@ -5415,7 +5534,8 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) | |||
5415 | if (IS_ERR(connkeys)) | 5534 | if (IS_ERR(connkeys)) |
5416 | return PTR_ERR(connkeys); | 5535 | return PTR_ERR(connkeys); |
5417 | 5536 | ||
5418 | if ((ibss.channel_type != NL80211_CHAN_NO_HT) && no_ht) { | 5537 | if ((ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT) && |
5538 | no_ht) { | ||
5419 | kfree(connkeys); | 5539 | kfree(connkeys); |
5420 | return -EINVAL; | 5540 | return -EINVAL; |
5421 | } | 5541 | } |
@@ -5444,6 +5564,36 @@ static int nl80211_leave_ibss(struct sk_buff *skb, struct genl_info *info) | |||
5444 | return cfg80211_leave_ibss(rdev, dev, false); | 5564 | return cfg80211_leave_ibss(rdev, dev, false); |
5445 | } | 5565 | } |
5446 | 5566 | ||
5567 | static int nl80211_set_mcast_rate(struct sk_buff *skb, struct genl_info *info) | ||
5568 | { | ||
5569 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | ||
5570 | struct net_device *dev = info->user_ptr[1]; | ||
5571 | int mcast_rate[IEEE80211_NUM_BANDS]; | ||
5572 | u32 nla_rate; | ||
5573 | int err; | ||
5574 | |||
5575 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC && | ||
5576 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) | ||
5577 | return -EOPNOTSUPP; | ||
5578 | |||
5579 | if (!rdev->ops->set_mcast_rate) | ||
5580 | return -EOPNOTSUPP; | ||
5581 | |||
5582 | memset(mcast_rate, 0, sizeof(mcast_rate)); | ||
5583 | |||
5584 | if (!info->attrs[NL80211_ATTR_MCAST_RATE]) | ||
5585 | return -EINVAL; | ||
5586 | |||
5587 | nla_rate = nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE]); | ||
5588 | if (!nl80211_parse_mcast_rate(rdev, mcast_rate, nla_rate)) | ||
5589 | return -EINVAL; | ||
5590 | |||
5591 | err = rdev->ops->set_mcast_rate(&rdev->wiphy, dev, mcast_rate); | ||
5592 | |||
5593 | return err; | ||
5594 | } | ||
5595 | |||
5596 | |||
5447 | #ifdef CONFIG_NL80211_TESTMODE | 5597 | #ifdef CONFIG_NL80211_TESTMODE |
5448 | static struct genl_multicast_group nl80211_testmode_mcgrp = { | 5598 | static struct genl_multicast_group nl80211_testmode_mcgrp = { |
5449 | .name = "testmode", | 5599 | .name = "testmode", |
@@ -5906,12 +6056,11 @@ static int nl80211_remain_on_channel(struct sk_buff *skb, | |||
5906 | { | 6056 | { |
5907 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 6057 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
5908 | struct wireless_dev *wdev = info->user_ptr[1]; | 6058 | struct wireless_dev *wdev = info->user_ptr[1]; |
5909 | struct ieee80211_channel *chan; | 6059 | struct cfg80211_chan_def chandef; |
5910 | struct sk_buff *msg; | 6060 | struct sk_buff *msg; |
5911 | void *hdr; | 6061 | void *hdr; |
5912 | u64 cookie; | 6062 | u64 cookie; |
5913 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; | 6063 | u32 duration; |
5914 | u32 freq, duration; | ||
5915 | int err; | 6064 | int err; |
5916 | 6065 | ||
5917 | if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] || | 6066 | if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] || |
@@ -5932,14 +6081,9 @@ static int nl80211_remain_on_channel(struct sk_buff *skb, | |||
5932 | duration > rdev->wiphy.max_remain_on_channel_duration) | 6081 | duration > rdev->wiphy.max_remain_on_channel_duration) |
5933 | return -EINVAL; | 6082 | return -EINVAL; |
5934 | 6083 | ||
5935 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] && | 6084 | err = nl80211_parse_chandef(rdev, info, &chandef); |
5936 | !nl80211_valid_channel_type(info, &channel_type)) | 6085 | if (err) |
5937 | return -EINVAL; | 6086 | return err; |
5938 | |||
5939 | freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); | ||
5940 | chan = rdev_freq_to_chan(rdev, freq, channel_type); | ||
5941 | if (chan == NULL) | ||
5942 | return -EINVAL; | ||
5943 | 6087 | ||
5944 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 6088 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
5945 | if (!msg) | 6089 | if (!msg) |
@@ -5953,8 +6097,8 @@ static int nl80211_remain_on_channel(struct sk_buff *skb, | |||
5953 | goto free_msg; | 6097 | goto free_msg; |
5954 | } | 6098 | } |
5955 | 6099 | ||
5956 | err = rdev_remain_on_channel(rdev, wdev, chan, channel_type, duration, | 6100 | err = rdev_remain_on_channel(rdev, wdev, chandef.chan, |
5957 | &cookie); | 6101 | duration, &cookie); |
5958 | 6102 | ||
5959 | if (err) | 6103 | if (err) |
5960 | goto free_msg; | 6104 | goto free_msg; |
@@ -6173,10 +6317,7 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
6173 | { | 6317 | { |
6174 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 6318 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
6175 | struct wireless_dev *wdev = info->user_ptr[1]; | 6319 | struct wireless_dev *wdev = info->user_ptr[1]; |
6176 | struct ieee80211_channel *chan; | 6320 | struct cfg80211_chan_def chandef; |
6177 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; | ||
6178 | bool channel_type_valid = false; | ||
6179 | u32 freq; | ||
6180 | int err; | 6321 | int err; |
6181 | void *hdr = NULL; | 6322 | void *hdr = NULL; |
6182 | u64 cookie; | 6323 | u64 cookie; |
@@ -6186,8 +6327,7 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
6186 | 6327 | ||
6187 | dont_wait_for_ack = info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK]; | 6328 | dont_wait_for_ack = info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK]; |
6188 | 6329 | ||
6189 | if (!info->attrs[NL80211_ATTR_FRAME] || | 6330 | if (!info->attrs[NL80211_ATTR_FRAME]) |
6190 | !info->attrs[NL80211_ATTR_WIPHY_FREQ]) | ||
6191 | return -EINVAL; | 6331 | return -EINVAL; |
6192 | 6332 | ||
6193 | if (!rdev->ops->mgmt_tx) | 6333 | if (!rdev->ops->mgmt_tx) |
@@ -6222,12 +6362,6 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
6222 | 6362 | ||
6223 | } | 6363 | } |
6224 | 6364 | ||
6225 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { | ||
6226 | if (!nl80211_valid_channel_type(info, &channel_type)) | ||
6227 | return -EINVAL; | ||
6228 | channel_type_valid = true; | ||
6229 | } | ||
6230 | |||
6231 | offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK]; | 6365 | offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK]; |
6232 | 6366 | ||
6233 | if (offchan && !(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX)) | 6367 | if (offchan && !(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX)) |
@@ -6235,10 +6369,9 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
6235 | 6369 | ||
6236 | no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]); | 6370 | no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]); |
6237 | 6371 | ||
6238 | freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); | 6372 | err = nl80211_parse_chandef(rdev, info, &chandef); |
6239 | chan = rdev_freq_to_chan(rdev, freq, channel_type); | 6373 | if (err) |
6240 | if (chan == NULL) | 6374 | return err; |
6241 | return -EINVAL; | ||
6242 | 6375 | ||
6243 | if (!dont_wait_for_ack) { | 6376 | if (!dont_wait_for_ack) { |
6244 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 6377 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
@@ -6254,8 +6387,7 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
6254 | } | 6387 | } |
6255 | } | 6388 | } |
6256 | 6389 | ||
6257 | err = cfg80211_mlme_mgmt_tx(rdev, wdev, chan, offchan, channel_type, | 6390 | err = cfg80211_mlme_mgmt_tx(rdev, wdev, chandef.chan, offchan, wait, |
6258 | channel_type_valid, wait, | ||
6259 | nla_data(info->attrs[NL80211_ATTR_FRAME]), | 6391 | nla_data(info->attrs[NL80211_ATTR_FRAME]), |
6260 | nla_len(info->attrs[NL80211_ATTR_FRAME]), | 6392 | nla_len(info->attrs[NL80211_ATTR_FRAME]), |
6261 | no_cck, dont_wait_for_ack, &cookie); | 6393 | no_cck, dont_wait_for_ack, &cookie); |
@@ -6519,21 +6651,12 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info) | |||
6519 | } | 6651 | } |
6520 | 6652 | ||
6521 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { | 6653 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { |
6522 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; | 6654 | err = nl80211_parse_chandef(rdev, info, &setup.chandef); |
6523 | 6655 | if (err) | |
6524 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] && | 6656 | return err; |
6525 | !nl80211_valid_channel_type(info, &channel_type)) | ||
6526 | return -EINVAL; | ||
6527 | |||
6528 | setup.channel = rdev_freq_to_chan(rdev, | ||
6529 | nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]), | ||
6530 | channel_type); | ||
6531 | if (!setup.channel) | ||
6532 | return -EINVAL; | ||
6533 | setup.channel_type = channel_type; | ||
6534 | } else { | 6657 | } else { |
6535 | /* cfg80211_join_mesh() will sort it out */ | 6658 | /* cfg80211_join_mesh() will sort it out */ |
6536 | setup.channel = NULL; | 6659 | setup.chandef.chan = NULL; |
6537 | } | 6660 | } |
6538 | 6661 | ||
6539 | return cfg80211_join_mesh(rdev, dev, &setup, &cfg); | 6662 | return cfg80211_join_mesh(rdev, dev, &setup, &cfg); |
@@ -6899,16 +7022,35 @@ static int nl80211_probe_client(struct sk_buff *skb, | |||
6899 | static int nl80211_register_beacons(struct sk_buff *skb, struct genl_info *info) | 7022 | static int nl80211_register_beacons(struct sk_buff *skb, struct genl_info *info) |
6900 | { | 7023 | { |
6901 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 7024 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
7025 | struct cfg80211_beacon_registration *reg, *nreg; | ||
7026 | int rv; | ||
6902 | 7027 | ||
6903 | if (!(rdev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS)) | 7028 | if (!(rdev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS)) |
6904 | return -EOPNOTSUPP; | 7029 | return -EOPNOTSUPP; |
6905 | 7030 | ||
6906 | if (rdev->ap_beacons_nlportid) | 7031 | nreg = kzalloc(sizeof(*nreg), GFP_KERNEL); |
6907 | return -EBUSY; | 7032 | if (!nreg) |
7033 | return -ENOMEM; | ||
6908 | 7034 | ||
6909 | rdev->ap_beacons_nlportid = info->snd_portid; | 7035 | /* First, check if already registered. */ |
7036 | spin_lock_bh(&rdev->beacon_registrations_lock); | ||
7037 | list_for_each_entry(reg, &rdev->beacon_registrations, list) { | ||
7038 | if (reg->nlportid == info->snd_portid) { | ||
7039 | rv = -EALREADY; | ||
7040 | goto out_err; | ||
7041 | } | ||
7042 | } | ||
7043 | /* Add it to the list */ | ||
7044 | nreg->nlportid = info->snd_portid; | ||
7045 | list_add(&nreg->list, &rdev->beacon_registrations); | ||
7046 | |||
7047 | spin_unlock_bh(&rdev->beacon_registrations_lock); | ||
6910 | 7048 | ||
6911 | return 0; | 7049 | return 0; |
7050 | out_err: | ||
7051 | spin_unlock_bh(&rdev->beacon_registrations_lock); | ||
7052 | kfree(nreg); | ||
7053 | return rv; | ||
6912 | } | 7054 | } |
6913 | 7055 | ||
6914 | static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info) | 7056 | static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info) |
@@ -7625,6 +7767,14 @@ static struct genl_ops nl80211_ops[] = { | |||
7625 | .internal_flags = NL80211_FLAG_NEED_WDEV_UP | | 7767 | .internal_flags = NL80211_FLAG_NEED_WDEV_UP | |
7626 | NL80211_FLAG_NEED_RTNL, | 7768 | NL80211_FLAG_NEED_RTNL, |
7627 | }, | 7769 | }, |
7770 | { | ||
7771 | .cmd = NL80211_CMD_SET_MCAST_RATE, | ||
7772 | .doit = nl80211_set_mcast_rate, | ||
7773 | .policy = nl80211_policy, | ||
7774 | .flags = GENL_ADMIN_PERM, | ||
7775 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | ||
7776 | NL80211_FLAG_NEED_RTNL, | ||
7777 | }, | ||
7628 | }; | 7778 | }; |
7629 | 7779 | ||
7630 | static struct genl_multicast_group nl80211_mlme_mcgrp = { | 7780 | static struct genl_multicast_group nl80211_mlme_mcgrp = { |
@@ -8326,7 +8476,6 @@ static void nl80211_send_remain_on_chan_event( | |||
8326 | int cmd, struct cfg80211_registered_device *rdev, | 8476 | int cmd, struct cfg80211_registered_device *rdev, |
8327 | struct wireless_dev *wdev, u64 cookie, | 8477 | struct wireless_dev *wdev, u64 cookie, |
8328 | struct ieee80211_channel *chan, | 8478 | struct ieee80211_channel *chan, |
8329 | enum nl80211_channel_type channel_type, | ||
8330 | unsigned int duration, gfp_t gfp) | 8479 | unsigned int duration, gfp_t gfp) |
8331 | { | 8480 | { |
8332 | struct sk_buff *msg; | 8481 | struct sk_buff *msg; |
@@ -8347,7 +8496,8 @@ static void nl80211_send_remain_on_chan_event( | |||
8347 | wdev->netdev->ifindex)) || | 8496 | wdev->netdev->ifindex)) || |
8348 | nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) || | 8497 | nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) || |
8349 | nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, chan->center_freq) || | 8498 | nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, chan->center_freq) || |
8350 | nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, channel_type) || | 8499 | nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, |
8500 | NL80211_CHAN_NO_HT) || | ||
8351 | nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie)) | 8501 | nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie)) |
8352 | goto nla_put_failure; | 8502 | goto nla_put_failure; |
8353 | 8503 | ||
@@ -8369,23 +8519,20 @@ static void nl80211_send_remain_on_chan_event( | |||
8369 | void nl80211_send_remain_on_channel(struct cfg80211_registered_device *rdev, | 8519 | void nl80211_send_remain_on_channel(struct cfg80211_registered_device *rdev, |
8370 | struct wireless_dev *wdev, u64 cookie, | 8520 | struct wireless_dev *wdev, u64 cookie, |
8371 | struct ieee80211_channel *chan, | 8521 | struct ieee80211_channel *chan, |
8372 | enum nl80211_channel_type channel_type, | ||
8373 | unsigned int duration, gfp_t gfp) | 8522 | unsigned int duration, gfp_t gfp) |
8374 | { | 8523 | { |
8375 | nl80211_send_remain_on_chan_event(NL80211_CMD_REMAIN_ON_CHANNEL, | 8524 | nl80211_send_remain_on_chan_event(NL80211_CMD_REMAIN_ON_CHANNEL, |
8376 | rdev, wdev, cookie, chan, | 8525 | rdev, wdev, cookie, chan, |
8377 | channel_type, duration, gfp); | 8526 | duration, gfp); |
8378 | } | 8527 | } |
8379 | 8528 | ||
8380 | void nl80211_send_remain_on_channel_cancel( | 8529 | void nl80211_send_remain_on_channel_cancel( |
8381 | struct cfg80211_registered_device *rdev, | 8530 | struct cfg80211_registered_device *rdev, |
8382 | struct wireless_dev *wdev, | 8531 | struct wireless_dev *wdev, |
8383 | u64 cookie, struct ieee80211_channel *chan, | 8532 | u64 cookie, struct ieee80211_channel *chan, gfp_t gfp) |
8384 | enum nl80211_channel_type channel_type, gfp_t gfp) | ||
8385 | { | 8533 | { |
8386 | nl80211_send_remain_on_chan_event(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL, | 8534 | nl80211_send_remain_on_chan_event(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL, |
8387 | rdev, wdev, cookie, chan, | 8535 | rdev, wdev, cookie, chan, 0, gfp); |
8388 | channel_type, 0, gfp); | ||
8389 | } | 8536 | } |
8390 | 8537 | ||
8391 | void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, | 8538 | void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, |
@@ -8741,8 +8888,8 @@ void nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev, | |||
8741 | } | 8888 | } |
8742 | 8889 | ||
8743 | void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev, | 8890 | void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev, |
8744 | struct net_device *netdev, int freq, | 8891 | struct net_device *netdev, |
8745 | enum nl80211_channel_type type, gfp_t gfp) | 8892 | struct cfg80211_chan_def *chandef, gfp_t gfp) |
8746 | { | 8893 | { |
8747 | struct sk_buff *msg; | 8894 | struct sk_buff *msg; |
8748 | void *hdr; | 8895 | void *hdr; |
@@ -8757,9 +8904,10 @@ void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev, | |||
8757 | return; | 8904 | return; |
8758 | } | 8905 | } |
8759 | 8906 | ||
8760 | if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || | 8907 | if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex)) |
8761 | nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq) || | 8908 | goto nla_put_failure; |
8762 | nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, type)) | 8909 | |
8910 | if (nl80211_send_chandef(msg, chandef)) | ||
8763 | goto nla_put_failure; | 8911 | goto nla_put_failure; |
8764 | 8912 | ||
8765 | genlmsg_end(msg, hdr); | 8913 | genlmsg_end(msg, hdr); |
@@ -8914,46 +9062,96 @@ EXPORT_SYMBOL(cfg80211_probe_status); | |||
8914 | 9062 | ||
8915 | void cfg80211_report_obss_beacon(struct wiphy *wiphy, | 9063 | void cfg80211_report_obss_beacon(struct wiphy *wiphy, |
8916 | const u8 *frame, size_t len, | 9064 | const u8 *frame, size_t len, |
8917 | int freq, int sig_dbm, gfp_t gfp) | 9065 | int freq, int sig_dbm) |
8918 | { | 9066 | { |
8919 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | 9067 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); |
8920 | struct sk_buff *msg; | 9068 | struct sk_buff *msg; |
8921 | void *hdr; | 9069 | void *hdr; |
8922 | u32 nlportid = ACCESS_ONCE(rdev->ap_beacons_nlportid); | 9070 | struct cfg80211_beacon_registration *reg; |
8923 | 9071 | ||
8924 | trace_cfg80211_report_obss_beacon(wiphy, frame, len, freq, sig_dbm); | 9072 | trace_cfg80211_report_obss_beacon(wiphy, frame, len, freq, sig_dbm); |
8925 | 9073 | ||
8926 | if (!nlportid) | 9074 | spin_lock_bh(&rdev->beacon_registrations_lock); |
8927 | return; | 9075 | list_for_each_entry(reg, &rdev->beacon_registrations, list) { |
9076 | msg = nlmsg_new(len + 100, GFP_ATOMIC); | ||
9077 | if (!msg) { | ||
9078 | spin_unlock_bh(&rdev->beacon_registrations_lock); | ||
9079 | return; | ||
9080 | } | ||
9081 | |||
9082 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME); | ||
9083 | if (!hdr) | ||
9084 | goto nla_put_failure; | ||
9085 | |||
9086 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | ||
9087 | (freq && | ||
9088 | nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq)) || | ||
9089 | (sig_dbm && | ||
9090 | nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) || | ||
9091 | nla_put(msg, NL80211_ATTR_FRAME, len, frame)) | ||
9092 | goto nla_put_failure; | ||
9093 | |||
9094 | genlmsg_end(msg, hdr); | ||
8928 | 9095 | ||
8929 | msg = nlmsg_new(len + 100, gfp); | 9096 | genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, reg->nlportid); |
9097 | } | ||
9098 | spin_unlock_bh(&rdev->beacon_registrations_lock); | ||
9099 | return; | ||
9100 | |||
9101 | nla_put_failure: | ||
9102 | spin_unlock_bh(&rdev->beacon_registrations_lock); | ||
9103 | if (hdr) | ||
9104 | genlmsg_cancel(msg, hdr); | ||
9105 | nlmsg_free(msg); | ||
9106 | } | ||
9107 | EXPORT_SYMBOL(cfg80211_report_obss_beacon); | ||
9108 | |||
9109 | void cfg80211_tdls_oper_request(struct net_device *dev, const u8 *peer, | ||
9110 | enum nl80211_tdls_operation oper, | ||
9111 | u16 reason_code, gfp_t gfp) | ||
9112 | { | ||
9113 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
9114 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | ||
9115 | struct sk_buff *msg; | ||
9116 | void *hdr; | ||
9117 | int err; | ||
9118 | |||
9119 | trace_cfg80211_tdls_oper_request(wdev->wiphy, dev, peer, oper, | ||
9120 | reason_code); | ||
9121 | |||
9122 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); | ||
8930 | if (!msg) | 9123 | if (!msg) |
8931 | return; | 9124 | return; |
8932 | 9125 | ||
8933 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME); | 9126 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_TDLS_OPER); |
8934 | if (!hdr) { | 9127 | if (!hdr) { |
8935 | nlmsg_free(msg); | 9128 | nlmsg_free(msg); |
8936 | return; | 9129 | return; |
8937 | } | 9130 | } |
8938 | 9131 | ||
8939 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | 9132 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || |
8940 | (freq && | 9133 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || |
8941 | nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq)) || | 9134 | nla_put_u8(msg, NL80211_ATTR_TDLS_OPERATION, oper) || |
8942 | (sig_dbm && | 9135 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer) || |
8943 | nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) || | 9136 | (reason_code > 0 && |
8944 | nla_put(msg, NL80211_ATTR_FRAME, len, frame)) | 9137 | nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason_code))) |
8945 | goto nla_put_failure; | 9138 | goto nla_put_failure; |
8946 | 9139 | ||
8947 | genlmsg_end(msg, hdr); | 9140 | err = genlmsg_end(msg, hdr); |
9141 | if (err < 0) { | ||
9142 | nlmsg_free(msg); | ||
9143 | return; | ||
9144 | } | ||
8948 | 9145 | ||
8949 | genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid); | 9146 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, |
9147 | nl80211_mlme_mcgrp.id, gfp); | ||
8950 | return; | 9148 | return; |
8951 | 9149 | ||
8952 | nla_put_failure: | 9150 | nla_put_failure: |
8953 | genlmsg_cancel(msg, hdr); | 9151 | genlmsg_cancel(msg, hdr); |
8954 | nlmsg_free(msg); | 9152 | nlmsg_free(msg); |
8955 | } | 9153 | } |
8956 | EXPORT_SYMBOL(cfg80211_report_obss_beacon); | 9154 | EXPORT_SYMBOL(cfg80211_tdls_oper_request); |
8957 | 9155 | ||
8958 | static int nl80211_netlink_notify(struct notifier_block * nb, | 9156 | static int nl80211_netlink_notify(struct notifier_block * nb, |
8959 | unsigned long state, | 9157 | unsigned long state, |
@@ -8962,6 +9160,7 @@ static int nl80211_netlink_notify(struct notifier_block * nb, | |||
8962 | struct netlink_notify *notify = _notify; | 9160 | struct netlink_notify *notify = _notify; |
8963 | struct cfg80211_registered_device *rdev; | 9161 | struct cfg80211_registered_device *rdev; |
8964 | struct wireless_dev *wdev; | 9162 | struct wireless_dev *wdev; |
9163 | struct cfg80211_beacon_registration *reg, *tmp; | ||
8965 | 9164 | ||
8966 | if (state != NETLINK_URELEASE) | 9165 | if (state != NETLINK_URELEASE) |
8967 | return NOTIFY_DONE; | 9166 | return NOTIFY_DONE; |
@@ -8971,8 +9170,17 @@ static int nl80211_netlink_notify(struct notifier_block * nb, | |||
8971 | list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) { | 9170 | list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) { |
8972 | list_for_each_entry_rcu(wdev, &rdev->wdev_list, list) | 9171 | list_for_each_entry_rcu(wdev, &rdev->wdev_list, list) |
8973 | cfg80211_mlme_unregister_socket(wdev, notify->portid); | 9172 | cfg80211_mlme_unregister_socket(wdev, notify->portid); |
8974 | if (rdev->ap_beacons_nlportid == notify->portid) | 9173 | |
8975 | rdev->ap_beacons_nlportid = 0; | 9174 | spin_lock_bh(&rdev->beacon_registrations_lock); |
9175 | list_for_each_entry_safe(reg, tmp, &rdev->beacon_registrations, | ||
9176 | list) { | ||
9177 | if (reg->nlportid == notify->portid) { | ||
9178 | list_del(®->list); | ||
9179 | kfree(reg); | ||
9180 | break; | ||
9181 | } | ||
9182 | } | ||
9183 | spin_unlock_bh(&rdev->beacon_registrations_lock); | ||
8976 | } | 9184 | } |
8977 | 9185 | ||
8978 | rcu_read_unlock(); | 9186 | rcu_read_unlock(); |
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index f6153516068..2acba8477e9 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h | |||
@@ -76,13 +76,11 @@ void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev, | |||
76 | void nl80211_send_remain_on_channel(struct cfg80211_registered_device *rdev, | 76 | void nl80211_send_remain_on_channel(struct cfg80211_registered_device *rdev, |
77 | struct wireless_dev *wdev, u64 cookie, | 77 | struct wireless_dev *wdev, u64 cookie, |
78 | struct ieee80211_channel *chan, | 78 | struct ieee80211_channel *chan, |
79 | enum nl80211_channel_type channel_type, | ||
80 | unsigned int duration, gfp_t gfp); | 79 | unsigned int duration, gfp_t gfp); |
81 | void nl80211_send_remain_on_channel_cancel( | 80 | void nl80211_send_remain_on_channel_cancel( |
82 | struct cfg80211_registered_device *rdev, | 81 | struct cfg80211_registered_device *rdev, |
83 | struct wireless_dev *wdev, | 82 | struct wireless_dev *wdev, |
84 | u64 cookie, struct ieee80211_channel *chan, | 83 | u64 cookie, struct ieee80211_channel *chan, gfp_t gfp); |
85 | enum nl80211_channel_type channel_type, gfp_t gfp); | ||
86 | 84 | ||
87 | void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, | 85 | void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, |
88 | struct net_device *dev, const u8 *mac_addr, | 86 | struct net_device *dev, const u8 *mac_addr, |
@@ -129,8 +127,8 @@ void nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev, | |||
129 | const u8 *bssid, bool preauth, gfp_t gfp); | 127 | const u8 *bssid, bool preauth, gfp_t gfp); |
130 | 128 | ||
131 | void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev, | 129 | void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev, |
132 | struct net_device *dev, int freq, | 130 | struct net_device *dev, |
133 | enum nl80211_channel_type type, gfp_t gfp); | 131 | struct cfg80211_chan_def *chandef, gfp_t gfp); |
134 | 132 | ||
135 | bool nl80211_unexpected_frame(struct net_device *dev, | 133 | bool nl80211_unexpected_frame(struct net_device *dev, |
136 | const u8 *addr, gfp_t gfp); | 134 | const u8 *addr, gfp_t gfp); |
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h index eb5f8974e14..6c0c8191f83 100644 --- a/net/wireless/rdev-ops.h +++ b/net/wireless/rdev-ops.h | |||
@@ -359,12 +359,11 @@ rdev_libertas_set_mesh_channel(struct cfg80211_registered_device *rdev, | |||
359 | 359 | ||
360 | static inline int | 360 | static inline int |
361 | rdev_set_monitor_channel(struct cfg80211_registered_device *rdev, | 361 | rdev_set_monitor_channel(struct cfg80211_registered_device *rdev, |
362 | struct ieee80211_channel *chan, | 362 | struct cfg80211_chan_def *chandef) |
363 | enum nl80211_channel_type channel_type) | ||
364 | { | 363 | { |
365 | int ret; | 364 | int ret; |
366 | trace_rdev_set_monitor_channel(&rdev->wiphy, chan, channel_type); | 365 | trace_rdev_set_monitor_channel(&rdev->wiphy, chandef); |
367 | ret = rdev->ops->set_monitor_channel(&rdev->wiphy, chan, channel_type); | 366 | ret = rdev->ops->set_monitor_channel(&rdev->wiphy, chandef); |
368 | trace_rdev_return_int(&rdev->wiphy, ret); | 367 | trace_rdev_return_int(&rdev->wiphy, ret); |
369 | return ret; | 368 | return ret; |
370 | } | 369 | } |
@@ -476,21 +475,22 @@ rdev_set_wiphy_params(struct cfg80211_registered_device *rdev, u32 changed) | |||
476 | } | 475 | } |
477 | 476 | ||
478 | static inline int rdev_set_tx_power(struct cfg80211_registered_device *rdev, | 477 | static inline int rdev_set_tx_power(struct cfg80211_registered_device *rdev, |
478 | struct wireless_dev *wdev, | ||
479 | enum nl80211_tx_power_setting type, int mbm) | 479 | enum nl80211_tx_power_setting type, int mbm) |
480 | { | 480 | { |
481 | int ret; | 481 | int ret; |
482 | trace_rdev_set_tx_power(&rdev->wiphy, type, mbm); | 482 | trace_rdev_set_tx_power(&rdev->wiphy, wdev, type, mbm); |
483 | ret = rdev->ops->set_tx_power(&rdev->wiphy, type, mbm); | 483 | ret = rdev->ops->set_tx_power(&rdev->wiphy, wdev, type, mbm); |
484 | trace_rdev_return_int(&rdev->wiphy, ret); | 484 | trace_rdev_return_int(&rdev->wiphy, ret); |
485 | return ret; | 485 | return ret; |
486 | } | 486 | } |
487 | 487 | ||
488 | static inline int rdev_get_tx_power(struct cfg80211_registered_device *rdev, | 488 | static inline int rdev_get_tx_power(struct cfg80211_registered_device *rdev, |
489 | int *dbm) | 489 | struct wireless_dev *wdev, int *dbm) |
490 | { | 490 | { |
491 | int ret; | 491 | int ret; |
492 | trace_rdev_get_tx_power(&rdev->wiphy); | 492 | trace_rdev_get_tx_power(&rdev->wiphy, wdev); |
493 | ret = rdev->ops->get_tx_power(&rdev->wiphy, dbm); | 493 | ret = rdev->ops->get_tx_power(&rdev->wiphy, wdev, dbm); |
494 | trace_rdev_return_int_int(&rdev->wiphy, ret, *dbm); | 494 | trace_rdev_return_int_int(&rdev->wiphy, ret, *dbm); |
495 | return ret; | 495 | return ret; |
496 | } | 496 | } |
@@ -599,14 +599,12 @@ static inline int | |||
599 | rdev_remain_on_channel(struct cfg80211_registered_device *rdev, | 599 | rdev_remain_on_channel(struct cfg80211_registered_device *rdev, |
600 | struct wireless_dev *wdev, | 600 | struct wireless_dev *wdev, |
601 | struct ieee80211_channel *chan, | 601 | struct ieee80211_channel *chan, |
602 | enum nl80211_channel_type channel_type, | ||
603 | unsigned int duration, u64 *cookie) | 602 | unsigned int duration, u64 *cookie) |
604 | { | 603 | { |
605 | int ret; | 604 | int ret; |
606 | trace_rdev_remain_on_channel(&rdev->wiphy, wdev, chan, channel_type, | 605 | trace_rdev_remain_on_channel(&rdev->wiphy, wdev, chan, duration); |
607 | duration); | ||
608 | ret = rdev->ops->remain_on_channel(&rdev->wiphy, wdev, chan, | 606 | ret = rdev->ops->remain_on_channel(&rdev->wiphy, wdev, chan, |
609 | channel_type, duration, cookie); | 607 | duration, cookie); |
610 | trace_rdev_return_int_cookie(&rdev->wiphy, ret, *cookie); | 608 | trace_rdev_return_int_cookie(&rdev->wiphy, ret, *cookie); |
611 | return ret; | 609 | return ret; |
612 | } | 610 | } |
@@ -625,17 +623,15 @@ rdev_cancel_remain_on_channel(struct cfg80211_registered_device *rdev, | |||
625 | static inline int rdev_mgmt_tx(struct cfg80211_registered_device *rdev, | 623 | static inline int rdev_mgmt_tx(struct cfg80211_registered_device *rdev, |
626 | struct wireless_dev *wdev, | 624 | struct wireless_dev *wdev, |
627 | struct ieee80211_channel *chan, bool offchan, | 625 | struct ieee80211_channel *chan, bool offchan, |
628 | enum nl80211_channel_type channel_type, | 626 | unsigned int wait, const u8 *buf, size_t len, |
629 | bool channel_type_valid, unsigned int wait, | 627 | bool no_cck, bool dont_wait_for_ack, u64 *cookie) |
630 | const u8 *buf, size_t len, bool no_cck, | ||
631 | bool dont_wait_for_ack, u64 *cookie) | ||
632 | { | 628 | { |
633 | int ret; | 629 | int ret; |
634 | trace_rdev_mgmt_tx(&rdev->wiphy, wdev, chan, offchan, channel_type, | 630 | trace_rdev_mgmt_tx(&rdev->wiphy, wdev, chan, offchan, |
635 | channel_type_valid, wait, no_cck, dont_wait_for_ack); | 631 | wait, no_cck, dont_wait_for_ack); |
636 | ret = rdev->ops->mgmt_tx(&rdev->wiphy, wdev, chan, offchan, | 632 | ret = rdev->ops->mgmt_tx(&rdev->wiphy, wdev, chan, offchan, |
637 | channel_type, channel_type_valid, wait, buf, | 633 | wait, buf, len, no_cck, |
638 | len, no_cck, dont_wait_for_ack, cookie); | 634 | dont_wait_for_ack, cookie); |
639 | trace_rdev_return_int_cookie(&rdev->wiphy, ret, *cookie); | 635 | trace_rdev_return_int_cookie(&rdev->wiphy, ret, *cookie); |
640 | return ret; | 636 | return ret; |
641 | } | 637 | } |
@@ -847,14 +843,17 @@ static inline void rdev_get_et_strings(struct cfg80211_registered_device *rdev, | |||
847 | trace_rdev_return_void(&rdev->wiphy); | 843 | trace_rdev_return_void(&rdev->wiphy); |
848 | } | 844 | } |
849 | 845 | ||
850 | static inline struct ieee80211_channel | 846 | static inline int |
851 | *rdev_get_channel(struct cfg80211_registered_device *rdev, | 847 | rdev_get_channel(struct cfg80211_registered_device *rdev, |
852 | struct wireless_dev *wdev, enum nl80211_channel_type *type) | 848 | struct wireless_dev *wdev, |
849 | struct cfg80211_chan_def *chandef) | ||
853 | { | 850 | { |
854 | struct ieee80211_channel *ret; | 851 | int ret; |
852 | |||
855 | trace_rdev_get_channel(&rdev->wiphy, wdev); | 853 | trace_rdev_get_channel(&rdev->wiphy, wdev); |
856 | ret = rdev->ops->get_channel(&rdev->wiphy, wdev, type); | 854 | ret = rdev->ops->get_channel(&rdev->wiphy, wdev, chandef); |
857 | trace_rdev_return_channel(&rdev->wiphy, ret, *type); | 855 | trace_rdev_return_chandef(&rdev->wiphy, ret, chandef); |
856 | |||
858 | return ret; | 857 | return ret; |
859 | } | 858 | } |
860 | 859 | ||
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 7f97a087f45..9596015975d 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
@@ -771,6 +771,38 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, | |||
771 | return found; | 771 | return found; |
772 | } | 772 | } |
773 | 773 | ||
774 | static struct ieee80211_channel * | ||
775 | cfg80211_get_bss_channel(struct wiphy *wiphy, const u8 *ie, size_t ielen, | ||
776 | struct ieee80211_channel *channel) | ||
777 | { | ||
778 | const u8 *tmp; | ||
779 | u32 freq; | ||
780 | int channel_number = -1; | ||
781 | |||
782 | tmp = cfg80211_find_ie(WLAN_EID_DS_PARAMS, ie, ielen); | ||
783 | if (tmp && tmp[1] == 1) { | ||
784 | channel_number = tmp[2]; | ||
785 | } else { | ||
786 | tmp = cfg80211_find_ie(WLAN_EID_HT_OPERATION, ie, ielen); | ||
787 | if (tmp && tmp[1] >= sizeof(struct ieee80211_ht_operation)) { | ||
788 | struct ieee80211_ht_operation *htop = (void *)(tmp + 2); | ||
789 | |||
790 | channel_number = htop->primary_chan; | ||
791 | } | ||
792 | } | ||
793 | |||
794 | if (channel_number < 0) | ||
795 | return channel; | ||
796 | |||
797 | freq = ieee80211_channel_to_frequency(channel_number, channel->band); | ||
798 | channel = ieee80211_get_channel(wiphy, freq); | ||
799 | if (!channel) | ||
800 | return NULL; | ||
801 | if (channel->flags & IEEE80211_CHAN_DISABLED) | ||
802 | return NULL; | ||
803 | return channel; | ||
804 | } | ||
805 | |||
774 | struct cfg80211_bss* | 806 | struct cfg80211_bss* |
775 | cfg80211_inform_bss(struct wiphy *wiphy, | 807 | cfg80211_inform_bss(struct wiphy *wiphy, |
776 | struct ieee80211_channel *channel, | 808 | struct ieee80211_channel *channel, |
@@ -790,6 +822,10 @@ cfg80211_inform_bss(struct wiphy *wiphy, | |||
790 | (signal < 0 || signal > 100))) | 822 | (signal < 0 || signal > 100))) |
791 | return NULL; | 823 | return NULL; |
792 | 824 | ||
825 | channel = cfg80211_get_bss_channel(wiphy, ie, ielen, channel); | ||
826 | if (!channel) | ||
827 | return NULL; | ||
828 | |||
793 | res = kzalloc(sizeof(*res) + privsz + ielen, gfp); | 829 | res = kzalloc(sizeof(*res) + privsz + ielen, gfp); |
794 | if (!res) | 830 | if (!res) |
795 | return NULL; | 831 | return NULL; |
@@ -839,11 +875,13 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy, | |||
839 | s32 signal, gfp_t gfp) | 875 | s32 signal, gfp_t gfp) |
840 | { | 876 | { |
841 | struct cfg80211_internal_bss *res; | 877 | struct cfg80211_internal_bss *res; |
842 | |||
843 | size_t ielen = len - offsetof(struct ieee80211_mgmt, | 878 | size_t ielen = len - offsetof(struct ieee80211_mgmt, |
844 | u.probe_resp.variable); | 879 | u.probe_resp.variable); |
845 | size_t privsz; | 880 | size_t privsz; |
846 | 881 | ||
882 | BUILD_BUG_ON(offsetof(struct ieee80211_mgmt, u.probe_resp.variable) != | ||
883 | offsetof(struct ieee80211_mgmt, u.beacon.variable)); | ||
884 | |||
847 | trace_cfg80211_inform_bss_frame(wiphy, channel, mgmt, len, signal); | 885 | trace_cfg80211_inform_bss_frame(wiphy, channel, mgmt, len, signal); |
848 | 886 | ||
849 | if (WARN_ON(!mgmt)) | 887 | if (WARN_ON(!mgmt)) |
@@ -861,6 +899,11 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy, | |||
861 | 899 | ||
862 | privsz = wiphy->bss_priv_size; | 900 | privsz = wiphy->bss_priv_size; |
863 | 901 | ||
902 | channel = cfg80211_get_bss_channel(wiphy, mgmt->u.beacon.variable, | ||
903 | ielen, channel); | ||
904 | if (!channel) | ||
905 | return NULL; | ||
906 | |||
864 | res = kzalloc(sizeof(*res) + privsz + ielen, gfp); | 907 | res = kzalloc(sizeof(*res) + privsz + ielen, gfp); |
865 | if (!res) | 908 | if (!res) |
866 | return NULL; | 909 | return NULL; |
diff --git a/net/wireless/trace.h b/net/wireless/trace.h index 0ca71caf85f..2134576f426 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h | |||
@@ -20,29 +20,26 @@ | |||
20 | #define MAC_PR_FMT "%pM" | 20 | #define MAC_PR_FMT "%pM" |
21 | #define MAC_PR_ARG(entry_mac) (__entry->entry_mac) | 21 | #define MAC_PR_ARG(entry_mac) (__entry->entry_mac) |
22 | 22 | ||
23 | #define WIPHY_ENTRY MAC_ENTRY(wiphy_mac) | 23 | #define MAXNAME 32 |
24 | #define WIPHY_ASSIGN MAC_ASSIGN(wiphy_mac, wiphy->perm_addr) | 24 | #define WIPHY_ENTRY __array(char, wiphy_name, 32) |
25 | #define WIPHY_PR_FMT "wiphy " MAC_PR_FMT | 25 | #define WIPHY_ASSIGN strlcpy(__entry->wiphy_name, wiphy_name(wiphy), MAXNAME) |
26 | #define WIPHY_PR_ARG MAC_PR_ARG(wiphy_mac) | 26 | #define WIPHY_PR_FMT "%s" |
27 | 27 | #define WIPHY_PR_ARG __entry->wiphy_name | |
28 | #define WDEV_ENTRY __field(u32, id) | 28 | |
29 | #define WDEV_ASSIGN (__entry->id) = (wdev->identifier) | 29 | #define WDEV_ENTRY __field(u32, id) |
30 | #define WDEV_PR_FMT ", wdev id: %u" | 30 | #define WDEV_ASSIGN (__entry->id) = (wdev ? wdev->identifier : 0) |
31 | #define WDEV_PR_ARG (__entry->id) | 31 | #define WDEV_PR_FMT "wdev(%u)" |
32 | 32 | #define WDEV_PR_ARG (__entry->id) | |
33 | #define NETDEV_ENTRY __array(char, name, IFNAMSIZ) \ | 33 | |
34 | MAC_ENTRY(netdev_addr) \ | 34 | #define NETDEV_ENTRY __array(char, name, IFNAMSIZ) \ |
35 | __field(int, ifindex) | 35 | __field(int, ifindex) |
36 | #define NETDEV_ASSIGN \ | 36 | #define NETDEV_ASSIGN \ |
37 | do { \ | 37 | do { \ |
38 | memcpy(__entry->name, netdev->name, IFNAMSIZ); \ | 38 | memcpy(__entry->name, netdev->name, IFNAMSIZ); \ |
39 | MAC_ASSIGN(netdev_addr, netdev->dev_addr); \ | ||
40 | (__entry->ifindex) = (netdev->ifindex); \ | 39 | (__entry->ifindex) = (netdev->ifindex); \ |
41 | } while (0) | 40 | } while (0) |
42 | #define NETDEV_PR_FMT ", netdev - name: %s, addr: " MAC_PR_FMT \ | 41 | #define NETDEV_PR_FMT "netdev:%s(%d)" |
43 | ", intf index: %d" | 42 | #define NETDEV_PR_ARG __entry->name, __entry->ifindex |
44 | #define NETDEV_PR_ARG (__entry->name), MAC_PR_ARG(netdev_addr), \ | ||
45 | (__entry->ifindex) | ||
46 | 43 | ||
47 | #define MESH_CFG_ENTRY __field(u16, dot11MeshRetryTimeout) \ | 44 | #define MESH_CFG_ENTRY __field(u16, dot11MeshRetryTimeout) \ |
48 | __field(u16, dot11MeshConfirmTimeout) \ | 45 | __field(u16, dot11MeshConfirmTimeout) \ |
@@ -123,9 +120,37 @@ | |||
123 | __entry->center_freq = 0; \ | 120 | __entry->center_freq = 0; \ |
124 | } \ | 121 | } \ |
125 | } while (0) | 122 | } while (0) |
126 | #define CHAN_PR_FMT ", band: %d, freq: %u" | 123 | #define CHAN_PR_FMT "band: %d, freq: %u" |
127 | #define CHAN_PR_ARG __entry->band, __entry->center_freq | 124 | #define CHAN_PR_ARG __entry->band, __entry->center_freq |
128 | 125 | ||
126 | #define CHAN_DEF_ENTRY __field(enum ieee80211_band, band) \ | ||
127 | __field(u32, control_freq) \ | ||
128 | __field(u32, width) \ | ||
129 | __field(u32, center_freq1) \ | ||
130 | __field(u32, center_freq2) | ||
131 | #define CHAN_DEF_ASSIGN(chandef) \ | ||
132 | do { \ | ||
133 | if ((chandef) && (chandef)->chan) { \ | ||
134 | __entry->band = (chandef)->chan->band; \ | ||
135 | __entry->control_freq = \ | ||
136 | (chandef)->chan->center_freq; \ | ||
137 | __entry->width = (chandef)->width; \ | ||
138 | __entry->center_freq1 = (chandef)->center_freq1;\ | ||
139 | __entry->center_freq2 = (chandef)->center_freq2;\ | ||
140 | } else { \ | ||
141 | __entry->band = 0; \ | ||
142 | __entry->control_freq = 0; \ | ||
143 | __entry->width = 0; \ | ||
144 | __entry->center_freq1 = 0; \ | ||
145 | __entry->center_freq2 = 0; \ | ||
146 | } \ | ||
147 | } while (0) | ||
148 | #define CHAN_DEF_PR_FMT \ | ||
149 | "band: %d, control freq: %u, width: %d, cf1: %u, cf2: %u" | ||
150 | #define CHAN_DEF_PR_ARG __entry->band, __entry->control_freq, \ | ||
151 | __entry->width, __entry->center_freq1, \ | ||
152 | __entry->center_freq2 | ||
153 | |||
129 | #define SINFO_ENTRY __field(int, generation) \ | 154 | #define SINFO_ENTRY __field(int, generation) \ |
130 | __field(u32, connected_time) \ | 155 | __field(u32, connected_time) \ |
131 | __field(u32, inactive_time) \ | 156 | __field(u32, inactive_time) \ |
@@ -260,11 +285,6 @@ DEFINE_EVENT(wiphy_only_evt, rdev_get_antenna, | |||
260 | TP_ARGS(wiphy) | 285 | TP_ARGS(wiphy) |
261 | ); | 286 | ); |
262 | 287 | ||
263 | DEFINE_EVENT(wiphy_only_evt, rdev_get_tx_power, | ||
264 | TP_PROTO(struct wiphy *wiphy), | ||
265 | TP_ARGS(wiphy) | ||
266 | ); | ||
267 | |||
268 | DEFINE_EVENT(wiphy_only_evt, rdev_rfkill_poll, | 288 | DEFINE_EVENT(wiphy_only_evt, rdev_rfkill_poll, |
269 | TP_PROTO(struct wiphy *wiphy), | 289 | TP_PROTO(struct wiphy *wiphy), |
270 | TP_ARGS(wiphy) | 290 | TP_ARGS(wiphy) |
@@ -318,7 +338,7 @@ DECLARE_EVENT_CLASS(wiphy_wdev_evt, | |||
318 | WIPHY_ASSIGN; | 338 | WIPHY_ASSIGN; |
319 | WDEV_ASSIGN; | 339 | WDEV_ASSIGN; |
320 | ), | 340 | ), |
321 | TP_printk(WIPHY_PR_FMT WDEV_PR_FMT, WIPHY_PR_ARG, WDEV_PR_ARG) | 341 | TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT, WIPHY_PR_ARG, WDEV_PR_ARG) |
322 | ); | 342 | ); |
323 | 343 | ||
324 | DEFINE_EVENT(wiphy_wdev_evt, rdev_return_wdev, | 344 | DEFINE_EVENT(wiphy_wdev_evt, rdev_return_wdev, |
@@ -345,7 +365,7 @@ TRACE_EVENT(rdev_change_virtual_intf, | |||
345 | NETDEV_ASSIGN; | 365 | NETDEV_ASSIGN; |
346 | __entry->type = type; | 366 | __entry->type = type; |
347 | ), | 367 | ), |
348 | TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", type: %d", | 368 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", type: %d", |
349 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->type) | 369 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->type) |
350 | ); | 370 | ); |
351 | 371 | ||
@@ -367,7 +387,7 @@ DECLARE_EVENT_CLASS(key_handle, | |||
367 | __entry->key_index = key_index; | 387 | __entry->key_index = key_index; |
368 | __entry->pairwise = pairwise; | 388 | __entry->pairwise = pairwise; |
369 | ), | 389 | ), |
370 | TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", key_index: %u, pairwise: %s, mac addr: " MAC_PR_FMT, | 390 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", key_index: %u, pairwise: %s, mac addr: " MAC_PR_FMT, |
371 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->key_index, | 391 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->key_index, |
372 | BOOL_TO_STR(__entry->pairwise), MAC_PR_ARG(mac_addr)) | 392 | BOOL_TO_STR(__entry->pairwise), MAC_PR_ARG(mac_addr)) |
373 | ); | 393 | ); |
@@ -408,7 +428,7 @@ TRACE_EVENT(rdev_set_default_key, | |||
408 | __entry->unicast = unicast; | 428 | __entry->unicast = unicast; |
409 | __entry->multicast = multicast; | 429 | __entry->multicast = multicast; |
410 | ), | 430 | ), |
411 | TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", key index: %u, unicast: %s, multicast: %s", | 431 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", key index: %u, unicast: %s, multicast: %s", |
412 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->key_index, | 432 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->key_index, |
413 | BOOL_TO_STR(__entry->unicast), | 433 | BOOL_TO_STR(__entry->unicast), |
414 | BOOL_TO_STR(__entry->multicast)) | 434 | BOOL_TO_STR(__entry->multicast)) |
@@ -427,7 +447,7 @@ TRACE_EVENT(rdev_set_default_mgmt_key, | |||
427 | NETDEV_ASSIGN; | 447 | NETDEV_ASSIGN; |
428 | __entry->key_index = key_index; | 448 | __entry->key_index = key_index; |
429 | ), | 449 | ), |
430 | TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", key index: %u", | 450 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", key index: %u", |
431 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->key_index) | 451 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->key_index) |
432 | ); | 452 | ); |
433 | 453 | ||
@@ -438,7 +458,7 @@ TRACE_EVENT(rdev_start_ap, | |||
438 | TP_STRUCT__entry( | 458 | TP_STRUCT__entry( |
439 | WIPHY_ENTRY | 459 | WIPHY_ENTRY |
440 | NETDEV_ENTRY | 460 | NETDEV_ENTRY |
441 | CHAN_ENTRY | 461 | CHAN_DEF_ENTRY |
442 | __field(int, beacon_interval) | 462 | __field(int, beacon_interval) |
443 | __field(int, dtim_period) | 463 | __field(int, dtim_period) |
444 | __array(char, ssid, IEEE80211_MAX_SSID_LEN + 1) | 464 | __array(char, ssid, IEEE80211_MAX_SSID_LEN + 1) |
@@ -451,7 +471,7 @@ TRACE_EVENT(rdev_start_ap, | |||
451 | TP_fast_assign( | 471 | TP_fast_assign( |
452 | WIPHY_ASSIGN; | 472 | WIPHY_ASSIGN; |
453 | NETDEV_ASSIGN; | 473 | NETDEV_ASSIGN; |
454 | CHAN_ASSIGN(settings->channel); | 474 | CHAN_DEF_ASSIGN(&settings->chandef); |
455 | __entry->beacon_interval = settings->beacon_interval; | 475 | __entry->beacon_interval = settings->beacon_interval; |
456 | __entry->dtim_period = settings->dtim_period; | 476 | __entry->dtim_period = settings->dtim_period; |
457 | __entry->hidden_ssid = settings->hidden_ssid; | 477 | __entry->hidden_ssid = settings->hidden_ssid; |
@@ -462,11 +482,11 @@ TRACE_EVENT(rdev_start_ap, | |||
462 | memset(__entry->ssid, 0, IEEE80211_MAX_SSID_LEN + 1); | 482 | memset(__entry->ssid, 0, IEEE80211_MAX_SSID_LEN + 1); |
463 | memcpy(__entry->ssid, settings->ssid, settings->ssid_len); | 483 | memcpy(__entry->ssid, settings->ssid, settings->ssid_len); |
464 | ), | 484 | ), |
465 | TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", AP settings - ssid: %s, " | 485 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", AP settings - ssid: %s, " |
466 | CHAN_PR_FMT ", beacon interval: %d, dtim period: %d, " | 486 | CHAN_DEF_PR_FMT ", beacon interval: %d, dtim period: %d, " |
467 | "hidden ssid: %d, wpa versions: %u, privacy: %s, " | 487 | "hidden ssid: %d, wpa versions: %u, privacy: %s, " |
468 | "auth type: %d, inactivity timeout: %d", | 488 | "auth type: %d, inactivity timeout: %d", |
469 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->ssid, CHAN_PR_ARG, | 489 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->ssid, CHAN_DEF_PR_ARG, |
470 | __entry->beacon_interval, __entry->dtim_period, | 490 | __entry->beacon_interval, __entry->dtim_period, |
471 | __entry->hidden_ssid, __entry->wpa_ver, | 491 | __entry->hidden_ssid, __entry->wpa_ver, |
472 | BOOL_TO_STR(__entry->privacy), __entry->auth_type, | 492 | BOOL_TO_STR(__entry->privacy), __entry->auth_type, |
@@ -515,7 +535,7 @@ TRACE_EVENT(rdev_change_beacon, | |||
515 | info->probe_resp, info->probe_resp_len); | 535 | info->probe_resp, info->probe_resp_len); |
516 | } | 536 | } |
517 | ), | 537 | ), |
518 | TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG) | 538 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG) |
519 | ); | 539 | ); |
520 | 540 | ||
521 | DECLARE_EVENT_CLASS(wiphy_netdev_evt, | 541 | DECLARE_EVENT_CLASS(wiphy_netdev_evt, |
@@ -529,7 +549,7 @@ DECLARE_EVENT_CLASS(wiphy_netdev_evt, | |||
529 | WIPHY_ASSIGN; | 549 | WIPHY_ASSIGN; |
530 | NETDEV_ASSIGN; | 550 | NETDEV_ASSIGN; |
531 | ), | 551 | ), |
532 | TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG) | 552 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG) |
533 | ); | 553 | ); |
534 | 554 | ||
535 | DEFINE_EVENT(wiphy_netdev_evt, rdev_stop_ap, | 555 | DEFINE_EVENT(wiphy_netdev_evt, rdev_stop_ap, |
@@ -607,7 +627,7 @@ DECLARE_EVENT_CLASS(station_add_change, | |||
607 | memcpy(__entry->ht_capa, params->ht_capa, | 627 | memcpy(__entry->ht_capa, params->ht_capa, |
608 | sizeof(struct ieee80211_ht_cap)); | 628 | sizeof(struct ieee80211_ht_cap)); |
609 | ), | 629 | ), |
610 | TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", station mac: " MAC_PR_FMT | 630 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", station mac: " MAC_PR_FMT |
611 | ", station flags mask: %u, station flags set: %u, " | 631 | ", station flags mask: %u, station flags set: %u, " |
612 | "station modify mask: %u, listen interval: %d, aid: %u, " | 632 | "station modify mask: %u, listen interval: %d, aid: %u, " |
613 | "plink action: %u, plink state: %u, uapsd queues: %u", | 633 | "plink action: %u, plink state: %u, uapsd queues: %u", |
@@ -643,7 +663,7 @@ DECLARE_EVENT_CLASS(wiphy_netdev_mac_evt, | |||
643 | NETDEV_ASSIGN; | 663 | NETDEV_ASSIGN; |
644 | MAC_ASSIGN(sta_mac, mac); | 664 | MAC_ASSIGN(sta_mac, mac); |
645 | ), | 665 | ), |
646 | TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", mac: " MAC_PR_FMT, | 666 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", mac: " MAC_PR_FMT, |
647 | WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(sta_mac)) | 667 | WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(sta_mac)) |
648 | ); | 668 | ); |
649 | 669 | ||
@@ -683,7 +703,7 @@ TRACE_EVENT(rdev_dump_station, | |||
683 | MAC_ASSIGN(sta_mac, mac); | 703 | MAC_ASSIGN(sta_mac, mac); |
684 | __entry->idx = idx; | 704 | __entry->idx = idx; |
685 | ), | 705 | ), |
686 | TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", station mac: " MAC_PR_FMT ", idx: %d", | 706 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", station mac: " MAC_PR_FMT ", idx: %d", |
687 | WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(sta_mac), | 707 | WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(sta_mac), |
688 | __entry->idx) | 708 | __entry->idx) |
689 | ); | 709 | ); |
@@ -721,7 +741,7 @@ DECLARE_EVENT_CLASS(mpath_evt, | |||
721 | MAC_ASSIGN(dst, dst); | 741 | MAC_ASSIGN(dst, dst); |
722 | MAC_ASSIGN(next_hop, next_hop); | 742 | MAC_ASSIGN(next_hop, next_hop); |
723 | ), | 743 | ), |
724 | TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", destination: " MAC_PR_FMT ", next hop: " MAC_PR_FMT, | 744 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", destination: " MAC_PR_FMT ", next hop: " MAC_PR_FMT, |
725 | WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(dst), | 745 | WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(dst), |
726 | MAC_PR_ARG(next_hop)) | 746 | MAC_PR_ARG(next_hop)) |
727 | ); | 747 | ); |
@@ -762,7 +782,7 @@ TRACE_EVENT(rdev_dump_mpath, | |||
762 | MAC_ASSIGN(next_hop, next_hop); | 782 | MAC_ASSIGN(next_hop, next_hop); |
763 | __entry->idx = idx; | 783 | __entry->idx = idx; |
764 | ), | 784 | ), |
765 | TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", index: %d, destination: " | 785 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", index: %d, destination: " |
766 | MAC_PR_FMT ", next hop: " MAC_PR_FMT, | 786 | MAC_PR_FMT ", next hop: " MAC_PR_FMT, |
767 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->idx, MAC_PR_ARG(dst), | 787 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->idx, MAC_PR_ARG(dst), |
768 | MAC_PR_ARG(next_hop)) | 788 | MAC_PR_ARG(next_hop)) |
@@ -839,7 +859,7 @@ TRACE_EVENT(rdev_update_mesh_config, | |||
839 | MESH_CFG_ASSIGN; | 859 | MESH_CFG_ASSIGN; |
840 | __entry->mask = mask; | 860 | __entry->mask = mask; |
841 | ), | 861 | ), |
842 | TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", mask: %u", | 862 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", mask: %u", |
843 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->mask) | 863 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->mask) |
844 | ); | 864 | ); |
845 | 865 | ||
@@ -858,7 +878,7 @@ TRACE_EVENT(rdev_join_mesh, | |||
858 | NETDEV_ASSIGN; | 878 | NETDEV_ASSIGN; |
859 | MESH_CFG_ASSIGN; | 879 | MESH_CFG_ASSIGN; |
860 | ), | 880 | ), |
861 | TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT, | 881 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT, |
862 | WIPHY_PR_ARG, NETDEV_PR_ARG) | 882 | WIPHY_PR_ARG, NETDEV_PR_ARG) |
863 | ); | 883 | ); |
864 | 884 | ||
@@ -884,7 +904,7 @@ TRACE_EVENT(rdev_change_bss, | |||
884 | __entry->ap_isolate = params->ap_isolate; | 904 | __entry->ap_isolate = params->ap_isolate; |
885 | __entry->ht_opmode = params->ht_opmode; | 905 | __entry->ht_opmode = params->ht_opmode; |
886 | ), | 906 | ), |
887 | TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", use cts prot: %d, " | 907 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", use cts prot: %d, " |
888 | "use short preamble: %d, use short slot time: %d, " | 908 | "use short preamble: %d, use short slot time: %d, " |
889 | "ap isolate: %d, ht opmode: %d", | 909 | "ap isolate: %d, ht opmode: %d", |
890 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->use_cts_prot, | 910 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->use_cts_prot, |
@@ -914,7 +934,7 @@ TRACE_EVENT(rdev_set_txq_params, | |||
914 | __entry->cwmax = params->cwmax; | 934 | __entry->cwmax = params->cwmax; |
915 | __entry->aifs = params->aifs; | 935 | __entry->aifs = params->aifs; |
916 | ), | 936 | ), |
917 | TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", ac: %d, txop: %u, cwmin: %u, cwmax: %u, aifs: %u", | 937 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", ac: %d, txop: %u, cwmin: %u, cwmax: %u, aifs: %u", |
918 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->ac, __entry->txop, | 938 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->ac, __entry->txop, |
919 | __entry->cwmin, __entry->cwmax, __entry->aifs) | 939 | __entry->cwmin, __entry->cwmax, __entry->aifs) |
920 | ); | 940 | ); |
@@ -933,26 +953,24 @@ TRACE_EVENT(rdev_libertas_set_mesh_channel, | |||
933 | NETDEV_ASSIGN; | 953 | NETDEV_ASSIGN; |
934 | CHAN_ASSIGN(chan); | 954 | CHAN_ASSIGN(chan); |
935 | ), | 955 | ), |
936 | TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT CHAN_PR_FMT, WIPHY_PR_ARG, | 956 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " CHAN_PR_FMT, WIPHY_PR_ARG, |
937 | NETDEV_PR_ARG, CHAN_PR_ARG) | 957 | NETDEV_PR_ARG, CHAN_PR_ARG) |
938 | ); | 958 | ); |
939 | 959 | ||
940 | TRACE_EVENT(rdev_set_monitor_channel, | 960 | TRACE_EVENT(rdev_set_monitor_channel, |
941 | TP_PROTO(struct wiphy *wiphy, struct ieee80211_channel *chan, | 961 | TP_PROTO(struct wiphy *wiphy, |
942 | enum nl80211_channel_type chan_type), | 962 | struct cfg80211_chan_def *chandef), |
943 | TP_ARGS(wiphy, chan, chan_type), | 963 | TP_ARGS(wiphy, chandef), |
944 | TP_STRUCT__entry( | 964 | TP_STRUCT__entry( |
945 | WIPHY_ENTRY | 965 | WIPHY_ENTRY |
946 | CHAN_ENTRY | 966 | CHAN_DEF_ENTRY |
947 | __field(enum nl80211_channel_type, chan_type) | ||
948 | ), | 967 | ), |
949 | TP_fast_assign( | 968 | TP_fast_assign( |
950 | WIPHY_ASSIGN; | 969 | WIPHY_ASSIGN; |
951 | CHAN_ASSIGN(chan); | 970 | CHAN_DEF_ASSIGN(chandef); |
952 | __entry->chan_type = chan_type; | ||
953 | ), | 971 | ), |
954 | TP_printk(WIPHY_PR_FMT CHAN_PR_FMT ", channel type : %d", | 972 | TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT, |
955 | WIPHY_PR_ARG, CHAN_PR_ARG, __entry->chan_type) | 973 | WIPHY_PR_ARG, CHAN_DEF_PR_ARG) |
956 | ); | 974 | ); |
957 | 975 | ||
958 | TRACE_EVENT(rdev_auth, | 976 | TRACE_EVENT(rdev_auth, |
@@ -974,7 +992,7 @@ TRACE_EVENT(rdev_auth, | |||
974 | memset(__entry->bssid, 0, ETH_ALEN); | 992 | memset(__entry->bssid, 0, ETH_ALEN); |
975 | __entry->auth_type = req->auth_type; | 993 | __entry->auth_type = req->auth_type; |
976 | ), | 994 | ), |
977 | TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", auth type: %d, bssid: " MAC_PR_FMT, | 995 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", auth type: %d, bssid: " MAC_PR_FMT, |
978 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->auth_type, | 996 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->auth_type, |
979 | MAC_PR_ARG(bssid)) | 997 | MAC_PR_ARG(bssid)) |
980 | ); | 998 | ); |
@@ -1002,7 +1020,7 @@ TRACE_EVENT(rdev_assoc, | |||
1002 | __entry->use_mfp = req->use_mfp; | 1020 | __entry->use_mfp = req->use_mfp; |
1003 | __entry->flags = req->flags; | 1021 | __entry->flags = req->flags; |
1004 | ), | 1022 | ), |
1005 | TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", bssid: " MAC_PR_FMT | 1023 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: " MAC_PR_FMT |
1006 | ", previous bssid: " MAC_PR_FMT ", use mfp: %s, flags: %u", | 1024 | ", previous bssid: " MAC_PR_FMT ", use mfp: %s, flags: %u", |
1007 | WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid), | 1025 | WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid), |
1008 | MAC_PR_ARG(prev_bssid), BOOL_TO_STR(__entry->use_mfp), | 1026 | MAC_PR_ARG(prev_bssid), BOOL_TO_STR(__entry->use_mfp), |
@@ -1025,7 +1043,7 @@ TRACE_EVENT(rdev_deauth, | |||
1025 | MAC_ASSIGN(bssid, req->bssid); | 1043 | MAC_ASSIGN(bssid, req->bssid); |
1026 | __entry->reason_code = req->reason_code; | 1044 | __entry->reason_code = req->reason_code; |
1027 | ), | 1045 | ), |
1028 | TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", bssid: " MAC_PR_FMT ", reason: %u", | 1046 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: " MAC_PR_FMT ", reason: %u", |
1029 | WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid), | 1047 | WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid), |
1030 | __entry->reason_code) | 1048 | __entry->reason_code) |
1031 | ); | 1049 | ); |
@@ -1051,7 +1069,7 @@ TRACE_EVENT(rdev_disassoc, | |||
1051 | __entry->reason_code = req->reason_code; | 1069 | __entry->reason_code = req->reason_code; |
1052 | __entry->local_state_change = req->local_state_change; | 1070 | __entry->local_state_change = req->local_state_change; |
1053 | ), | 1071 | ), |
1054 | TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", bssid: " MAC_PR_FMT | 1072 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: " MAC_PR_FMT |
1055 | ", reason: %u, local state change: %s", | 1073 | ", reason: %u, local state change: %s", |
1056 | WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid), | 1074 | WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid), |
1057 | __entry->reason_code, | 1075 | __entry->reason_code, |
@@ -1072,7 +1090,7 @@ TRACE_EVENT(rdev_mgmt_tx_cancel_wait, | |||
1072 | WDEV_ASSIGN; | 1090 | WDEV_ASSIGN; |
1073 | __entry->cookie = cookie; | 1091 | __entry->cookie = cookie; |
1074 | ), | 1092 | ), |
1075 | TP_printk(WIPHY_PR_FMT WDEV_PR_FMT ", cookie: %llu ", | 1093 | TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", cookie: %llu ", |
1076 | WIPHY_PR_ARG, WDEV_PR_ARG, __entry->cookie) | 1094 | WIPHY_PR_ARG, WDEV_PR_ARG, __entry->cookie) |
1077 | ); | 1095 | ); |
1078 | 1096 | ||
@@ -1092,7 +1110,7 @@ TRACE_EVENT(rdev_set_power_mgmt, | |||
1092 | __entry->enabled = enabled; | 1110 | __entry->enabled = enabled; |
1093 | __entry->timeout = timeout; | 1111 | __entry->timeout = timeout; |
1094 | ), | 1112 | ), |
1095 | TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", %senabled, timeout: %d ", | 1113 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", %senabled, timeout: %d ", |
1096 | WIPHY_PR_ARG, NETDEV_PR_ARG, | 1114 | WIPHY_PR_ARG, NETDEV_PR_ARG, |
1097 | __entry->enabled ? "" : "not ", __entry->timeout) | 1115 | __entry->enabled ? "" : "not ", __entry->timeout) |
1098 | ); | 1116 | ); |
@@ -1122,7 +1140,7 @@ TRACE_EVENT(rdev_connect, | |||
1122 | __entry->wpa_versions = sme->crypto.wpa_versions; | 1140 | __entry->wpa_versions = sme->crypto.wpa_versions; |
1123 | __entry->flags = sme->flags; | 1141 | __entry->flags = sme->flags; |
1124 | ), | 1142 | ), |
1125 | TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", bssid: " MAC_PR_FMT | 1143 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: " MAC_PR_FMT |
1126 | ", ssid: %s, auth type: %d, privacy: %s, wpa versions: %u, " | 1144 | ", ssid: %s, auth type: %d, privacy: %s, wpa versions: %u, " |
1127 | "flags: %u", | 1145 | "flags: %u", |
1128 | WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid), __entry->ssid, | 1146 | WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid), __entry->ssid, |
@@ -1147,7 +1165,7 @@ TRACE_EVENT(rdev_set_cqm_rssi_config, | |||
1147 | __entry->rssi_thold = rssi_thold; | 1165 | __entry->rssi_thold = rssi_thold; |
1148 | __entry->rssi_hyst = rssi_hyst; | 1166 | __entry->rssi_hyst = rssi_hyst; |
1149 | ), | 1167 | ), |
1150 | TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT | 1168 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT |
1151 | ", rssi_thold: %d, rssi_hyst: %u ", | 1169 | ", rssi_thold: %d, rssi_hyst: %u ", |
1152 | WIPHY_PR_ARG, NETDEV_PR_ARG, | 1170 | WIPHY_PR_ARG, NETDEV_PR_ARG, |
1153 | __entry->rssi_thold, __entry->rssi_hyst) | 1171 | __entry->rssi_thold, __entry->rssi_hyst) |
@@ -1171,7 +1189,7 @@ TRACE_EVENT(rdev_set_cqm_txe_config, | |||
1171 | __entry->pkts = pkts; | 1189 | __entry->pkts = pkts; |
1172 | __entry->intvl = intvl; | 1190 | __entry->intvl = intvl; |
1173 | ), | 1191 | ), |
1174 | TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", rate: %u, packets: %u, interval: %u", | 1192 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", rate: %u, packets: %u, interval: %u", |
1175 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->rate, __entry->pkts, | 1193 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->rate, __entry->pkts, |
1176 | __entry->intvl) | 1194 | __entry->intvl) |
1177 | ); | 1195 | ); |
@@ -1190,7 +1208,7 @@ TRACE_EVENT(rdev_disconnect, | |||
1190 | NETDEV_ASSIGN; | 1208 | NETDEV_ASSIGN; |
1191 | __entry->reason_code = reason_code; | 1209 | __entry->reason_code = reason_code; |
1192 | ), | 1210 | ), |
1193 | TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", reason code: %u", WIPHY_PR_ARG, | 1211 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", reason code: %u", WIPHY_PR_ARG, |
1194 | NETDEV_PR_ARG, __entry->reason_code) | 1212 | NETDEV_PR_ARG, __entry->reason_code) |
1195 | ); | 1213 | ); |
1196 | 1214 | ||
@@ -1211,7 +1229,7 @@ TRACE_EVENT(rdev_join_ibss, | |||
1211 | memset(__entry->ssid, 0, IEEE80211_MAX_SSID_LEN + 1); | 1229 | memset(__entry->ssid, 0, IEEE80211_MAX_SSID_LEN + 1); |
1212 | memcpy(__entry->ssid, params->ssid, params->ssid_len); | 1230 | memcpy(__entry->ssid, params->ssid, params->ssid_len); |
1213 | ), | 1231 | ), |
1214 | TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", bssid: " MAC_PR_FMT ", ssid: %s", | 1232 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: " MAC_PR_FMT ", ssid: %s", |
1215 | WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid), __entry->ssid) | 1233 | WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid), __entry->ssid) |
1216 | ); | 1234 | ); |
1217 | 1235 | ||
@@ -1230,22 +1248,29 @@ TRACE_EVENT(rdev_set_wiphy_params, | |||
1230 | WIPHY_PR_ARG, __entry->changed) | 1248 | WIPHY_PR_ARG, __entry->changed) |
1231 | ); | 1249 | ); |
1232 | 1250 | ||
1251 | DEFINE_EVENT(wiphy_wdev_evt, rdev_get_tx_power, | ||
1252 | TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev), | ||
1253 | TP_ARGS(wiphy, wdev) | ||
1254 | ); | ||
1255 | |||
1233 | TRACE_EVENT(rdev_set_tx_power, | 1256 | TRACE_EVENT(rdev_set_tx_power, |
1234 | TP_PROTO(struct wiphy *wiphy, enum nl80211_tx_power_setting type, | 1257 | TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev, |
1235 | int mbm), | 1258 | enum nl80211_tx_power_setting type, int mbm), |
1236 | TP_ARGS(wiphy, type, mbm), | 1259 | TP_ARGS(wiphy, wdev, type, mbm), |
1237 | TP_STRUCT__entry( | 1260 | TP_STRUCT__entry( |
1238 | WIPHY_ENTRY | 1261 | WIPHY_ENTRY |
1262 | WDEV_ENTRY | ||
1239 | __field(enum nl80211_tx_power_setting, type) | 1263 | __field(enum nl80211_tx_power_setting, type) |
1240 | __field(int, mbm) | 1264 | __field(int, mbm) |
1241 | ), | 1265 | ), |
1242 | TP_fast_assign( | 1266 | TP_fast_assign( |
1243 | WIPHY_ASSIGN; | 1267 | WIPHY_ASSIGN; |
1268 | WDEV_ASSIGN; | ||
1244 | __entry->type = type; | 1269 | __entry->type = type; |
1245 | __entry->mbm = mbm; | 1270 | __entry->mbm = mbm; |
1246 | ), | 1271 | ), |
1247 | TP_printk(WIPHY_PR_FMT ", type: %d, mbm: %d", | 1272 | TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", type: %u, mbm: %d", |
1248 | WIPHY_PR_ARG, __entry->type, __entry->mbm) | 1273 | WIPHY_PR_ARG, WDEV_PR_ARG,__entry->type, __entry->mbm) |
1249 | ); | 1274 | ); |
1250 | 1275 | ||
1251 | TRACE_EVENT(rdev_return_int_int, | 1276 | TRACE_EVENT(rdev_return_int_int, |
@@ -1305,7 +1330,7 @@ TRACE_EVENT(rdev_set_bitrate_mask, | |||
1305 | NETDEV_ASSIGN; | 1330 | NETDEV_ASSIGN; |
1306 | MAC_ASSIGN(peer, peer); | 1331 | MAC_ASSIGN(peer, peer); |
1307 | ), | 1332 | ), |
1308 | TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", peer: " MAC_PR_FMT, | 1333 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", peer: " MAC_PR_FMT, |
1309 | WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer)) | 1334 | WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer)) |
1310 | ); | 1335 | ); |
1311 | 1336 | ||
@@ -1325,7 +1350,7 @@ TRACE_EVENT(rdev_mgmt_frame_register, | |||
1325 | __entry->frame_type = frame_type; | 1350 | __entry->frame_type = frame_type; |
1326 | __entry->reg = reg; | 1351 | __entry->reg = reg; |
1327 | ), | 1352 | ), |
1328 | TP_printk(WIPHY_PR_FMT WDEV_PR_FMT ", frame_type: %u, reg: %s ", | 1353 | TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", frame_type: 0x%.2x, reg: %s ", |
1329 | WIPHY_PR_ARG, WDEV_PR_ARG, __entry->frame_type, | 1354 | WIPHY_PR_ARG, WDEV_PR_ARG, __entry->frame_type, |
1330 | __entry->reg ? "true" : "false") | 1355 | __entry->reg ? "true" : "false") |
1331 | ); | 1356 | ); |
@@ -1411,7 +1436,7 @@ TRACE_EVENT(rdev_sched_scan_start, | |||
1411 | WIPHY_ASSIGN; | 1436 | WIPHY_ASSIGN; |
1412 | NETDEV_ASSIGN; | 1437 | NETDEV_ASSIGN; |
1413 | ), | 1438 | ), |
1414 | TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT, | 1439 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT, |
1415 | WIPHY_PR_ARG, NETDEV_PR_ARG) | 1440 | WIPHY_PR_ARG, NETDEV_PR_ARG) |
1416 | ); | 1441 | ); |
1417 | 1442 | ||
@@ -1439,7 +1464,7 @@ TRACE_EVENT(rdev_tdls_mgmt, | |||
1439 | __entry->status_code = status_code; | 1464 | __entry->status_code = status_code; |
1440 | memcpy(__get_dynamic_array(buf), buf, len); | 1465 | memcpy(__get_dynamic_array(buf), buf, len); |
1441 | ), | 1466 | ), |
1442 | TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT MAC_PR_FMT ", action_code: %u, " | 1467 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT ", action_code: %u, " |
1443 | "dialog_token: %u, status_code: %u, buf: %#.2x ", | 1468 | "dialog_token: %u, status_code: %u, buf: %#.2x ", |
1444 | WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer), | 1469 | WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer), |
1445 | __entry->action_code, __entry->dialog_token, | 1470 | __entry->action_code, __entry->dialog_token, |
@@ -1459,7 +1484,7 @@ TRACE_EVENT(rdev_dump_survey, | |||
1459 | NETDEV_ASSIGN; | 1484 | NETDEV_ASSIGN; |
1460 | __entry->idx = idx; | 1485 | __entry->idx = idx; |
1461 | ), | 1486 | ), |
1462 | TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", index: %d", | 1487 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", index: %d", |
1463 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->idx) | 1488 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->idx) |
1464 | ); | 1489 | ); |
1465 | 1490 | ||
@@ -1516,7 +1541,7 @@ TRACE_EVENT(rdev_tdls_oper, | |||
1516 | MAC_ASSIGN(peer, peer); | 1541 | MAC_ASSIGN(peer, peer); |
1517 | __entry->oper = oper; | 1542 | __entry->oper = oper; |
1518 | ), | 1543 | ), |
1519 | TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT MAC_PR_FMT ", oper: %d", | 1544 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT ", oper: %d", |
1520 | WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer), __entry->oper) | 1545 | WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer), __entry->oper) |
1521 | ); | 1546 | ); |
1522 | 1547 | ||
@@ -1534,7 +1559,7 @@ DECLARE_EVENT_CLASS(rdev_pmksa, | |||
1534 | NETDEV_ASSIGN; | 1559 | NETDEV_ASSIGN; |
1535 | MAC_ASSIGN(bssid, pmksa->bssid); | 1560 | MAC_ASSIGN(bssid, pmksa->bssid); |
1536 | ), | 1561 | ), |
1537 | TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", bssid: " MAC_PR_FMT, | 1562 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: " MAC_PR_FMT, |
1538 | WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid)) | 1563 | WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid)) |
1539 | ); | 1564 | ); |
1540 | 1565 | ||
@@ -1552,7 +1577,7 @@ TRACE_EVENT(rdev_probe_client, | |||
1552 | NETDEV_ASSIGN; | 1577 | NETDEV_ASSIGN; |
1553 | MAC_ASSIGN(peer, peer); | 1578 | MAC_ASSIGN(peer, peer); |
1554 | ), | 1579 | ), |
1555 | TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT MAC_PR_FMT, | 1580 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT, |
1556 | WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer)) | 1581 | WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer)) |
1557 | ); | 1582 | ); |
1558 | 1583 | ||
@@ -1571,25 +1596,22 @@ DEFINE_EVENT(rdev_pmksa, rdev_del_pmksa, | |||
1571 | TRACE_EVENT(rdev_remain_on_channel, | 1596 | TRACE_EVENT(rdev_remain_on_channel, |
1572 | TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev, | 1597 | TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev, |
1573 | struct ieee80211_channel *chan, | 1598 | struct ieee80211_channel *chan, |
1574 | enum nl80211_channel_type channel_type, unsigned int duration), | 1599 | unsigned int duration), |
1575 | TP_ARGS(wiphy, wdev, chan, channel_type, duration), | 1600 | TP_ARGS(wiphy, wdev, chan, duration), |
1576 | TP_STRUCT__entry( | 1601 | TP_STRUCT__entry( |
1577 | WIPHY_ENTRY | 1602 | WIPHY_ENTRY |
1578 | WDEV_ENTRY | 1603 | WDEV_ENTRY |
1579 | CHAN_ENTRY | 1604 | CHAN_ENTRY |
1580 | __field(enum nl80211_channel_type, channel_type) | ||
1581 | __field(unsigned int, duration) | 1605 | __field(unsigned int, duration) |
1582 | ), | 1606 | ), |
1583 | TP_fast_assign( | 1607 | TP_fast_assign( |
1584 | WIPHY_ASSIGN; | 1608 | WIPHY_ASSIGN; |
1585 | WDEV_ASSIGN; | 1609 | WDEV_ASSIGN; |
1586 | CHAN_ASSIGN(chan); | 1610 | CHAN_ASSIGN(chan); |
1587 | __entry->channel_type = channel_type; | ||
1588 | __entry->duration = duration; | 1611 | __entry->duration = duration; |
1589 | ), | 1612 | ), |
1590 | TP_printk(WIPHY_PR_FMT WDEV_PR_FMT CHAN_PR_FMT ", channel type: %d, duration: %u", | 1613 | TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", " CHAN_PR_FMT ", duration: %u", |
1591 | WIPHY_PR_ARG, WDEV_PR_ARG, CHAN_PR_ARG, __entry->channel_type, | 1614 | WIPHY_PR_ARG, WDEV_PR_ARG, CHAN_PR_ARG, __entry->duration) |
1592 | __entry->duration) | ||
1593 | ); | 1615 | ); |
1594 | 1616 | ||
1595 | TRACE_EVENT(rdev_return_int_cookie, | 1617 | TRACE_EVENT(rdev_return_int_cookie, |
@@ -1622,25 +1644,20 @@ TRACE_EVENT(rdev_cancel_remain_on_channel, | |||
1622 | WDEV_ASSIGN; | 1644 | WDEV_ASSIGN; |
1623 | __entry->cookie = cookie; | 1645 | __entry->cookie = cookie; |
1624 | ), | 1646 | ), |
1625 | TP_printk(WIPHY_PR_FMT WDEV_PR_FMT ", cookie: %llu", | 1647 | TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", cookie: %llu", |
1626 | WIPHY_PR_ARG, WDEV_PR_ARG, __entry->cookie) | 1648 | WIPHY_PR_ARG, WDEV_PR_ARG, __entry->cookie) |
1627 | ); | 1649 | ); |
1628 | 1650 | ||
1629 | TRACE_EVENT(rdev_mgmt_tx, | 1651 | TRACE_EVENT(rdev_mgmt_tx, |
1630 | TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev, | 1652 | TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev, |
1631 | struct ieee80211_channel *chan, bool offchan, | 1653 | struct ieee80211_channel *chan, bool offchan, |
1632 | enum nl80211_channel_type channel_type, | 1654 | unsigned int wait, bool no_cck, bool dont_wait_for_ack), |
1633 | bool channel_type_valid, unsigned int wait, bool no_cck, | 1655 | TP_ARGS(wiphy, wdev, chan, offchan, wait, no_cck, dont_wait_for_ack), |
1634 | bool dont_wait_for_ack), | ||
1635 | TP_ARGS(wiphy, wdev, chan, offchan, channel_type, channel_type_valid, | ||
1636 | wait, no_cck, dont_wait_for_ack), | ||
1637 | TP_STRUCT__entry( | 1656 | TP_STRUCT__entry( |
1638 | WIPHY_ENTRY | 1657 | WIPHY_ENTRY |
1639 | WDEV_ENTRY | 1658 | WDEV_ENTRY |
1640 | CHAN_ENTRY | 1659 | CHAN_ENTRY |
1641 | __field(bool, offchan) | 1660 | __field(bool, offchan) |
1642 | __field(enum nl80211_channel_type, channel_type) | ||
1643 | __field(bool, channel_type_valid) | ||
1644 | __field(unsigned int, wait) | 1661 | __field(unsigned int, wait) |
1645 | __field(bool, no_cck) | 1662 | __field(bool, no_cck) |
1646 | __field(bool, dont_wait_for_ack) | 1663 | __field(bool, dont_wait_for_ack) |
@@ -1650,18 +1667,14 @@ TRACE_EVENT(rdev_mgmt_tx, | |||
1650 | WDEV_ASSIGN; | 1667 | WDEV_ASSIGN; |
1651 | CHAN_ASSIGN(chan); | 1668 | CHAN_ASSIGN(chan); |
1652 | __entry->offchan = offchan; | 1669 | __entry->offchan = offchan; |
1653 | __entry->channel_type = channel_type; | ||
1654 | __entry->channel_type_valid = channel_type_valid; | ||
1655 | __entry->wait = wait; | 1670 | __entry->wait = wait; |
1656 | __entry->no_cck = no_cck; | 1671 | __entry->no_cck = no_cck; |
1657 | __entry->dont_wait_for_ack = dont_wait_for_ack; | 1672 | __entry->dont_wait_for_ack = dont_wait_for_ack; |
1658 | ), | 1673 | ), |
1659 | TP_printk(WIPHY_PR_FMT WDEV_PR_FMT CHAN_PR_FMT ", offchan: %s, " | 1674 | TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", " CHAN_PR_FMT ", offchan: %s," |
1660 | "channel type: %d, channel type valid: %s, wait: %u, " | 1675 | " wait: %u, no cck: %s, dont wait for ack: %s", |
1661 | "no cck: %s, dont wait for ack: %s", | ||
1662 | WIPHY_PR_ARG, WDEV_PR_ARG, CHAN_PR_ARG, | 1676 | WIPHY_PR_ARG, WDEV_PR_ARG, CHAN_PR_ARG, |
1663 | BOOL_TO_STR(__entry->offchan), __entry->channel_type, | 1677 | BOOL_TO_STR(__entry->offchan), __entry->wait, |
1664 | BOOL_TO_STR(__entry->channel_type_valid), __entry->wait, | ||
1665 | BOOL_TO_STR(__entry->no_cck), | 1678 | BOOL_TO_STR(__entry->no_cck), |
1666 | BOOL_TO_STR(__entry->dont_wait_for_ack)) | 1679 | BOOL_TO_STR(__entry->dont_wait_for_ack)) |
1667 | ); | 1680 | ); |
@@ -1680,7 +1693,7 @@ TRACE_EVENT(rdev_set_noack_map, | |||
1680 | NETDEV_ASSIGN; | 1693 | NETDEV_ASSIGN; |
1681 | __entry->noack_map = noack_map; | 1694 | __entry->noack_map = noack_map; |
1682 | ), | 1695 | ), |
1683 | TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", noack_map: %u", | 1696 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", noack_map: %u", |
1684 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->noack_map) | 1697 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->noack_map) |
1685 | ); | 1698 | ); |
1686 | 1699 | ||
@@ -1697,7 +1710,7 @@ TRACE_EVENT(rdev_get_et_sset_count, | |||
1697 | NETDEV_ASSIGN; | 1710 | NETDEV_ASSIGN; |
1698 | __entry->sset = sset; | 1711 | __entry->sset = sset; |
1699 | ), | 1712 | ), |
1700 | TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", sset: %d", | 1713 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", sset: %d", |
1701 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->sset) | 1714 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->sset) |
1702 | ); | 1715 | ); |
1703 | 1716 | ||
@@ -1714,7 +1727,7 @@ TRACE_EVENT(rdev_get_et_strings, | |||
1714 | NETDEV_ASSIGN; | 1727 | NETDEV_ASSIGN; |
1715 | __entry->sset = sset; | 1728 | __entry->sset = sset; |
1716 | ), | 1729 | ), |
1717 | TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", sset: %u", | 1730 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", sset: %u", |
1718 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->sset) | 1731 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->sset) |
1719 | ); | 1732 | ); |
1720 | 1733 | ||
@@ -1723,22 +1736,25 @@ DEFINE_EVENT(wiphy_wdev_evt, rdev_get_channel, | |||
1723 | TP_ARGS(wiphy, wdev) | 1736 | TP_ARGS(wiphy, wdev) |
1724 | ); | 1737 | ); |
1725 | 1738 | ||
1726 | TRACE_EVENT(rdev_return_channel, | 1739 | TRACE_EVENT(rdev_return_chandef, |
1727 | TP_PROTO(struct wiphy *wiphy, struct ieee80211_channel *chan, | 1740 | TP_PROTO(struct wiphy *wiphy, int ret, |
1728 | enum nl80211_channel_type type), | 1741 | struct cfg80211_chan_def *chandef), |
1729 | TP_ARGS(wiphy, chan, type), | 1742 | TP_ARGS(wiphy, ret, chandef), |
1730 | TP_STRUCT__entry( | 1743 | TP_STRUCT__entry( |
1731 | WIPHY_ENTRY | 1744 | WIPHY_ENTRY |
1732 | CHAN_ENTRY | 1745 | __field(int, ret) |
1733 | __field(enum nl80211_channel_type, type) | 1746 | CHAN_DEF_ENTRY |
1734 | ), | 1747 | ), |
1735 | TP_fast_assign( | 1748 | TP_fast_assign( |
1736 | WIPHY_ASSIGN; | 1749 | WIPHY_ASSIGN; |
1737 | CHAN_ASSIGN(chan); | 1750 | if (ret == 0) |
1738 | __entry->type = type; | 1751 | CHAN_DEF_ASSIGN(chandef); |
1752 | else | ||
1753 | CHAN_DEF_ASSIGN((struct cfg80211_chan_def *)NULL); | ||
1754 | __entry->ret = ret; | ||
1739 | ), | 1755 | ), |
1740 | TP_printk(WIPHY_PR_FMT CHAN_PR_FMT ", channel type: %d", | 1756 | TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT ", ret: %d", |
1741 | WIPHY_PR_ARG, CHAN_PR_ARG, __entry->type) | 1757 | WIPHY_PR_ARG, CHAN_DEF_PR_ARG, __entry->ret) |
1742 | ); | 1758 | ); |
1743 | 1759 | ||
1744 | DEFINE_EVENT(wiphy_wdev_evt, rdev_start_p2p_device, | 1760 | DEFINE_EVENT(wiphy_wdev_evt, rdev_start_p2p_device, |
@@ -1817,7 +1833,7 @@ TRACE_EVENT(cfg80211_send_rx_assoc, | |||
1817 | MAC_ASSIGN(bssid, bss->bssid); | 1833 | MAC_ASSIGN(bssid, bss->bssid); |
1818 | CHAN_ASSIGN(bss->channel); | 1834 | CHAN_ASSIGN(bss->channel); |
1819 | ), | 1835 | ), |
1820 | TP_printk(NETDEV_PR_FMT MAC_PR_FMT CHAN_PR_FMT, | 1836 | TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT ", " CHAN_PR_FMT, |
1821 | NETDEV_PR_ARG, MAC_PR_ARG(bssid), CHAN_PR_ARG) | 1837 | NETDEV_PR_ARG, MAC_PR_ARG(bssid), CHAN_PR_ARG) |
1822 | ); | 1838 | ); |
1823 | 1839 | ||
@@ -1884,7 +1900,7 @@ TRACE_EVENT(cfg80211_michael_mic_failure, | |||
1884 | __entry->key_id = key_id; | 1900 | __entry->key_id = key_id; |
1885 | memcpy(__entry->tsc, tsc, 6); | 1901 | memcpy(__entry->tsc, tsc, 6); |
1886 | ), | 1902 | ), |
1887 | TP_printk(NETDEV_PR_FMT MAC_PR_FMT ", key type: %d, key id: %d, tsc: %pm", | 1903 | TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT ", key type: %d, key id: %d, tsc: %pm", |
1888 | NETDEV_PR_ARG, MAC_PR_ARG(addr), __entry->key_type, | 1904 | NETDEV_PR_ARG, MAC_PR_ARG(addr), __entry->key_type, |
1889 | __entry->key_id, __entry->tsc) | 1905 | __entry->key_id, __entry->tsc) |
1890 | ); | 1906 | ); |
@@ -1892,47 +1908,41 @@ TRACE_EVENT(cfg80211_michael_mic_failure, | |||
1892 | TRACE_EVENT(cfg80211_ready_on_channel, | 1908 | TRACE_EVENT(cfg80211_ready_on_channel, |
1893 | TP_PROTO(struct wireless_dev *wdev, u64 cookie, | 1909 | TP_PROTO(struct wireless_dev *wdev, u64 cookie, |
1894 | struct ieee80211_channel *chan, | 1910 | struct ieee80211_channel *chan, |
1895 | enum nl80211_channel_type channel_type, unsigned int duration), | 1911 | unsigned int duration), |
1896 | TP_ARGS(wdev, cookie, chan, channel_type, duration), | 1912 | TP_ARGS(wdev, cookie, chan, duration), |
1897 | TP_STRUCT__entry( | 1913 | TP_STRUCT__entry( |
1898 | WDEV_ENTRY | 1914 | WDEV_ENTRY |
1899 | __field(u64, cookie) | 1915 | __field(u64, cookie) |
1900 | CHAN_ENTRY | 1916 | CHAN_ENTRY |
1901 | __field(enum nl80211_channel_type, channel_type) | ||
1902 | __field(unsigned int, duration) | 1917 | __field(unsigned int, duration) |
1903 | ), | 1918 | ), |
1904 | TP_fast_assign( | 1919 | TP_fast_assign( |
1905 | WDEV_ASSIGN; | 1920 | WDEV_ASSIGN; |
1906 | __entry->cookie = cookie; | 1921 | __entry->cookie = cookie; |
1907 | CHAN_ASSIGN(chan); | 1922 | CHAN_ASSIGN(chan); |
1908 | __entry->channel_type = channel_type; | ||
1909 | __entry->duration = duration; | 1923 | __entry->duration = duration; |
1910 | ), | 1924 | ), |
1911 | TP_printk(WDEV_PR_FMT ", cookie: %llu, " CHAN_PR_FMT ", channel type: %d, duration: %u", | 1925 | TP_printk(WDEV_PR_FMT ", cookie: %llu, " CHAN_PR_FMT ", duration: %u", |
1912 | WDEV_PR_ARG, __entry->cookie, CHAN_PR_ARG, | 1926 | WDEV_PR_ARG, __entry->cookie, CHAN_PR_ARG, |
1913 | __entry->channel_type, __entry->duration) | 1927 | __entry->duration) |
1914 | ); | 1928 | ); |
1915 | 1929 | ||
1916 | TRACE_EVENT(cfg80211_ready_on_channel_expired, | 1930 | TRACE_EVENT(cfg80211_ready_on_channel_expired, |
1917 | TP_PROTO(struct wireless_dev *wdev, u64 cookie, | 1931 | TP_PROTO(struct wireless_dev *wdev, u64 cookie, |
1918 | struct ieee80211_channel *chan, | 1932 | struct ieee80211_channel *chan), |
1919 | enum nl80211_channel_type channel_type), | 1933 | TP_ARGS(wdev, cookie, chan), |
1920 | TP_ARGS(wdev, cookie, chan, channel_type), | ||
1921 | TP_STRUCT__entry( | 1934 | TP_STRUCT__entry( |
1922 | WDEV_ENTRY | 1935 | WDEV_ENTRY |
1923 | __field(u64, cookie) | 1936 | __field(u64, cookie) |
1924 | CHAN_ENTRY | 1937 | CHAN_ENTRY |
1925 | __field(enum nl80211_channel_type, channel_type) | ||
1926 | ), | 1938 | ), |
1927 | TP_fast_assign( | 1939 | TP_fast_assign( |
1928 | WDEV_ASSIGN; | 1940 | WDEV_ASSIGN; |
1929 | __entry->cookie = cookie; | 1941 | __entry->cookie = cookie; |
1930 | CHAN_ASSIGN(chan); | 1942 | CHAN_ASSIGN(chan); |
1931 | __entry->channel_type = channel_type; | ||
1932 | ), | 1943 | ), |
1933 | TP_printk(WDEV_PR_FMT ", cookie: %llu, " CHAN_PR_FMT ", channel type: %d", | 1944 | TP_printk(WDEV_PR_FMT ", cookie: %llu, " CHAN_PR_FMT, |
1934 | WDEV_PR_ARG, __entry->cookie, CHAN_PR_ARG, | 1945 | WDEV_PR_ARG, __entry->cookie, CHAN_PR_ARG) |
1935 | __entry->channel_type) | ||
1936 | ); | 1946 | ); |
1937 | 1947 | ||
1938 | TRACE_EVENT(cfg80211_new_sta, | 1948 | TRACE_EVENT(cfg80211_new_sta, |
@@ -1949,7 +1959,7 @@ TRACE_EVENT(cfg80211_new_sta, | |||
1949 | MAC_ASSIGN(mac_addr, mac_addr); | 1959 | MAC_ASSIGN(mac_addr, mac_addr); |
1950 | SINFO_ASSIGN; | 1960 | SINFO_ASSIGN; |
1951 | ), | 1961 | ), |
1952 | TP_printk(NETDEV_PR_FMT MAC_PR_FMT, | 1962 | TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT, |
1953 | NETDEV_PR_ARG, MAC_PR_ARG(mac_addr)) | 1963 | NETDEV_PR_ARG, MAC_PR_ARG(mac_addr)) |
1954 | ); | 1964 | ); |
1955 | 1965 | ||
@@ -2008,40 +2018,35 @@ TRACE_EVENT(cfg80211_cqm_rssi_notify, | |||
2008 | NETDEV_PR_ARG, __entry->rssi_event) | 2018 | NETDEV_PR_ARG, __entry->rssi_event) |
2009 | ); | 2019 | ); |
2010 | 2020 | ||
2011 | TRACE_EVENT(cfg80211_can_beacon_sec_chan, | 2021 | TRACE_EVENT(cfg80211_reg_can_beacon, |
2012 | TP_PROTO(struct wiphy *wiphy, struct ieee80211_channel *channel, | 2022 | TP_PROTO(struct wiphy *wiphy, struct cfg80211_chan_def *chandef), |
2013 | enum nl80211_channel_type channel_type), | 2023 | TP_ARGS(wiphy, chandef), |
2014 | TP_ARGS(wiphy, channel, channel_type), | ||
2015 | TP_STRUCT__entry( | 2024 | TP_STRUCT__entry( |
2016 | WIPHY_ENTRY | 2025 | WIPHY_ENTRY |
2017 | CHAN_ENTRY | 2026 | CHAN_DEF_ENTRY |
2018 | __field(enum nl80211_channel_type, channel_type) | ||
2019 | ), | 2027 | ), |
2020 | TP_fast_assign( | 2028 | TP_fast_assign( |
2021 | WIPHY_ASSIGN; | 2029 | WIPHY_ASSIGN; |
2022 | CHAN_ASSIGN(channel); | 2030 | CHAN_DEF_ASSIGN(chandef); |
2023 | __entry->channel_type = channel_type; | ||
2024 | ), | 2031 | ), |
2025 | TP_printk(WIPHY_PR_FMT CHAN_PR_FMT ", channel_type: %d", | 2032 | TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT, |
2026 | WIPHY_PR_ARG, CHAN_PR_ARG, __entry->channel_type) | 2033 | WIPHY_PR_ARG, CHAN_DEF_PR_ARG) |
2027 | ); | 2034 | ); |
2028 | 2035 | ||
2029 | TRACE_EVENT(cfg80211_ch_switch_notify, | 2036 | TRACE_EVENT(cfg80211_ch_switch_notify, |
2030 | TP_PROTO(struct net_device *netdev, int freq, | 2037 | TP_PROTO(struct net_device *netdev, |
2031 | enum nl80211_channel_type type), | 2038 | struct cfg80211_chan_def *chandef), |
2032 | TP_ARGS(netdev, freq, type), | 2039 | TP_ARGS(netdev, chandef), |
2033 | TP_STRUCT__entry( | 2040 | TP_STRUCT__entry( |
2034 | NETDEV_ENTRY | 2041 | NETDEV_ENTRY |
2035 | __field(int, freq) | 2042 | CHAN_DEF_ENTRY |
2036 | __field(enum nl80211_channel_type, type) | ||
2037 | ), | 2043 | ), |
2038 | TP_fast_assign( | 2044 | TP_fast_assign( |
2039 | NETDEV_ASSIGN; | 2045 | NETDEV_ASSIGN; |
2040 | __entry->freq = freq; | 2046 | CHAN_DEF_ASSIGN(chandef); |
2041 | __entry->type = type; | ||
2042 | ), | 2047 | ), |
2043 | TP_printk(NETDEV_PR_FMT ", freq: %d, type: %d", NETDEV_PR_ARG, | 2048 | TP_printk(NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT, |
2044 | __entry->freq, __entry->type) | 2049 | NETDEV_PR_ARG, CHAN_DEF_PR_ARG) |
2045 | ); | 2050 | ); |
2046 | 2051 | ||
2047 | DECLARE_EVENT_CLASS(cfg80211_rx_evt, | 2052 | DECLARE_EVENT_CLASS(cfg80211_rx_evt, |
@@ -2055,7 +2060,7 @@ DECLARE_EVENT_CLASS(cfg80211_rx_evt, | |||
2055 | NETDEV_ASSIGN; | 2060 | NETDEV_ASSIGN; |
2056 | MAC_ASSIGN(addr, addr); | 2061 | MAC_ASSIGN(addr, addr); |
2057 | ), | 2062 | ), |
2058 | TP_printk(NETDEV_PR_FMT MAC_PR_FMT, NETDEV_PR_ARG, MAC_PR_ARG(addr)) | 2063 | TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT, NETDEV_PR_ARG, MAC_PR_ARG(addr)) |
2059 | ); | 2064 | ); |
2060 | 2065 | ||
2061 | DEFINE_EVENT(cfg80211_rx_evt, cfg80211_ibss_joined, | 2066 | DEFINE_EVENT(cfg80211_rx_evt, cfg80211_ibss_joined, |
@@ -2089,7 +2094,7 @@ TRACE_EVENT(cfg80211_probe_status, | |||
2089 | __entry->cookie = cookie; | 2094 | __entry->cookie = cookie; |
2090 | __entry->acked = acked; | 2095 | __entry->acked = acked; |
2091 | ), | 2096 | ), |
2092 | TP_printk(NETDEV_PR_FMT MAC_PR_FMT ", cookie: %llu, acked: %s", | 2097 | TP_printk(NETDEV_PR_FMT " addr:" MAC_PR_FMT ", cookie: %llu, acked: %s", |
2093 | NETDEV_PR_ARG, MAC_PR_ARG(addr), __entry->cookie, | 2098 | NETDEV_PR_ARG, MAC_PR_ARG(addr), __entry->cookie, |
2094 | BOOL_TO_STR(__entry->acked)) | 2099 | BOOL_TO_STR(__entry->acked)) |
2095 | ); | 2100 | ); |
@@ -2155,6 +2160,29 @@ TRACE_EVENT(cfg80211_report_obss_beacon, | |||
2155 | WIPHY_PR_ARG, __entry->freq, __entry->sig_dbm) | 2160 | WIPHY_PR_ARG, __entry->freq, __entry->sig_dbm) |
2156 | ); | 2161 | ); |
2157 | 2162 | ||
2163 | TRACE_EVENT(cfg80211_tdls_oper_request, | ||
2164 | TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, const u8 *peer, | ||
2165 | enum nl80211_tdls_operation oper, u16 reason_code), | ||
2166 | TP_ARGS(wiphy, netdev, peer, oper, reason_code), | ||
2167 | TP_STRUCT__entry( | ||
2168 | WIPHY_ENTRY | ||
2169 | NETDEV_ENTRY | ||
2170 | MAC_ENTRY(peer) | ||
2171 | __field(enum nl80211_tdls_operation, oper) | ||
2172 | __field(u16, reason_code) | ||
2173 | ), | ||
2174 | TP_fast_assign( | ||
2175 | WIPHY_ASSIGN; | ||
2176 | NETDEV_ASSIGN; | ||
2177 | MAC_ASSIGN(peer, peer); | ||
2178 | __entry->oper = oper; | ||
2179 | __entry->reason_code = reason_code; | ||
2180 | ), | ||
2181 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", peer: " MAC_PR_FMT ", oper: %d, reason_code %u", | ||
2182 | WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer), __entry->oper, | ||
2183 | __entry->reason_code) | ||
2184 | ); | ||
2185 | |||
2158 | TRACE_EVENT(cfg80211_scan_done, | 2186 | TRACE_EVENT(cfg80211_scan_done, |
2159 | TP_PROTO(struct cfg80211_scan_request *request, bool aborted), | 2187 | TP_PROTO(struct cfg80211_scan_request *request, bool aborted), |
2160 | TP_ARGS(request, aborted), | 2188 | TP_ARGS(request, aborted), |
@@ -2216,7 +2244,7 @@ TRACE_EVENT(cfg80211_get_bss, | |||
2216 | __entry->capa_mask = capa_mask; | 2244 | __entry->capa_mask = capa_mask; |
2217 | __entry->capa_val = capa_val; | 2245 | __entry->capa_val = capa_val; |
2218 | ), | 2246 | ), |
2219 | TP_printk(WIPHY_PR_FMT CHAN_PR_FMT MAC_PR_FMT ", buf: %#.2x, " | 2247 | TP_printk(WIPHY_PR_FMT ", " CHAN_PR_FMT ", " MAC_PR_FMT ", buf: %#.2x, " |
2220 | "capa_mask: %d, capa_val: %u", WIPHY_PR_ARG, CHAN_PR_ARG, | 2248 | "capa_mask: %d, capa_val: %u", WIPHY_PR_ARG, CHAN_PR_ARG, |
2221 | MAC_PR_ARG(bssid), ((u8 *)__get_dynamic_array(ssid))[0], | 2249 | MAC_PR_ARG(bssid), ((u8 *)__get_dynamic_array(ssid))[0], |
2222 | __entry->capa_mask, __entry->capa_val) | 2250 | __entry->capa_mask, __entry->capa_val) |
@@ -2240,7 +2268,7 @@ TRACE_EVENT(cfg80211_inform_bss_frame, | |||
2240 | memcpy(__get_dynamic_array(mgmt), mgmt, len); | 2268 | memcpy(__get_dynamic_array(mgmt), mgmt, len); |
2241 | __entry->signal = signal; | 2269 | __entry->signal = signal; |
2242 | ), | 2270 | ), |
2243 | TP_printk(WIPHY_PR_FMT CHAN_PR_FMT "signal: %d", | 2271 | TP_printk(WIPHY_PR_FMT ", " CHAN_PR_FMT "signal: %d", |
2244 | WIPHY_PR_ARG, CHAN_PR_ARG, __entry->signal) | 2272 | WIPHY_PR_ARG, CHAN_PR_ARG, __entry->signal) |
2245 | ); | 2273 | ); |
2246 | 2274 | ||
@@ -2255,7 +2283,7 @@ DECLARE_EVENT_CLASS(cfg80211_bss_evt, | |||
2255 | MAC_ASSIGN(bssid, pub->bssid); | 2283 | MAC_ASSIGN(bssid, pub->bssid); |
2256 | CHAN_ASSIGN(pub->channel); | 2284 | CHAN_ASSIGN(pub->channel); |
2257 | ), | 2285 | ), |
2258 | TP_printk(MAC_PR_FMT CHAN_PR_FMT, MAC_PR_ARG(bssid), CHAN_PR_ARG) | 2286 | TP_printk(MAC_PR_FMT ", " CHAN_PR_FMT, MAC_PR_ARG(bssid), CHAN_PR_ARG) |
2259 | ); | 2287 | ); |
2260 | 2288 | ||
2261 | DEFINE_EVENT(cfg80211_bss_evt, cfg80211_return_bss, | 2289 | DEFINE_EVENT(cfg80211_bss_evt, cfg80211_return_bss, |
diff --git a/net/wireless/util.c b/net/wireless/util.c index 5b6c1df72f3..3cce6e48621 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -944,14 +944,86 @@ static u32 cfg80211_calculate_bitrate_60g(struct rate_info *rate) | |||
944 | return __mcs2bitrate[rate->mcs]; | 944 | return __mcs2bitrate[rate->mcs]; |
945 | } | 945 | } |
946 | 946 | ||
947 | static u32 cfg80211_calculate_bitrate_vht(struct rate_info *rate) | ||
948 | { | ||
949 | static const u32 base[4][10] = { | ||
950 | { 6500000, | ||
951 | 13000000, | ||
952 | 19500000, | ||
953 | 26000000, | ||
954 | 39000000, | ||
955 | 52000000, | ||
956 | 58500000, | ||
957 | 65000000, | ||
958 | 78000000, | ||
959 | 0, | ||
960 | }, | ||
961 | { 13500000, | ||
962 | 27000000, | ||
963 | 40500000, | ||
964 | 54000000, | ||
965 | 81000000, | ||
966 | 108000000, | ||
967 | 121500000, | ||
968 | 135000000, | ||
969 | 162000000, | ||
970 | 180000000, | ||
971 | }, | ||
972 | { 29300000, | ||
973 | 58500000, | ||
974 | 87800000, | ||
975 | 117000000, | ||
976 | 175500000, | ||
977 | 234000000, | ||
978 | 263300000, | ||
979 | 292500000, | ||
980 | 351000000, | ||
981 | 390000000, | ||
982 | }, | ||
983 | { 58500000, | ||
984 | 117000000, | ||
985 | 175500000, | ||
986 | 234000000, | ||
987 | 351000000, | ||
988 | 468000000, | ||
989 | 526500000, | ||
990 | 585000000, | ||
991 | 702000000, | ||
992 | 780000000, | ||
993 | }, | ||
994 | }; | ||
995 | u32 bitrate; | ||
996 | int idx; | ||
997 | |||
998 | if (WARN_ON_ONCE(rate->mcs > 9)) | ||
999 | return 0; | ||
1000 | |||
1001 | idx = rate->flags & (RATE_INFO_FLAGS_160_MHZ_WIDTH | | ||
1002 | RATE_INFO_FLAGS_80P80_MHZ_WIDTH) ? 3 : | ||
1003 | rate->flags & RATE_INFO_FLAGS_80_MHZ_WIDTH ? 2 : | ||
1004 | rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH ? 1 : 0; | ||
1005 | |||
1006 | bitrate = base[idx][rate->mcs]; | ||
1007 | bitrate *= rate->nss; | ||
1008 | |||
1009 | if (rate->flags & RATE_INFO_FLAGS_SHORT_GI) | ||
1010 | bitrate = (bitrate / 9) * 10; | ||
1011 | |||
1012 | /* do NOT round down here */ | ||
1013 | return (bitrate + 50000) / 100000; | ||
1014 | } | ||
1015 | |||
947 | u32 cfg80211_calculate_bitrate(struct rate_info *rate) | 1016 | u32 cfg80211_calculate_bitrate(struct rate_info *rate) |
948 | { | 1017 | { |
949 | int modulation, streams, bitrate; | 1018 | int modulation, streams, bitrate; |
950 | 1019 | ||
951 | if (!(rate->flags & RATE_INFO_FLAGS_MCS)) | 1020 | if (!(rate->flags & RATE_INFO_FLAGS_MCS) && |
1021 | !(rate->flags & RATE_INFO_FLAGS_VHT_MCS)) | ||
952 | return rate->legacy; | 1022 | return rate->legacy; |
953 | if (rate->flags & RATE_INFO_FLAGS_60G) | 1023 | if (rate->flags & RATE_INFO_FLAGS_60G) |
954 | return cfg80211_calculate_bitrate_60g(rate); | 1024 | return cfg80211_calculate_bitrate_60g(rate); |
1025 | if (rate->flags & RATE_INFO_FLAGS_VHT_MCS) | ||
1026 | return cfg80211_calculate_bitrate_vht(rate); | ||
955 | 1027 | ||
956 | /* the formula below does only work for MCS values smaller than 32 */ | 1028 | /* the formula below does only work for MCS values smaller than 32 */ |
957 | if (WARN_ON_ONCE(rate->mcs >= 32)) | 1029 | if (WARN_ON_ONCE(rate->mcs >= 32)) |
@@ -980,6 +1052,106 @@ u32 cfg80211_calculate_bitrate(struct rate_info *rate) | |||
980 | } | 1052 | } |
981 | EXPORT_SYMBOL(cfg80211_calculate_bitrate); | 1053 | EXPORT_SYMBOL(cfg80211_calculate_bitrate); |
982 | 1054 | ||
1055 | int cfg80211_get_p2p_attr(const u8 *ies, unsigned int len, | ||
1056 | enum ieee80211_p2p_attr_id attr, | ||
1057 | u8 *buf, unsigned int bufsize) | ||
1058 | { | ||
1059 | u8 *out = buf; | ||
1060 | u16 attr_remaining = 0; | ||
1061 | bool desired_attr = false; | ||
1062 | u16 desired_len = 0; | ||
1063 | |||
1064 | while (len > 0) { | ||
1065 | unsigned int iedatalen; | ||
1066 | unsigned int copy; | ||
1067 | const u8 *iedata; | ||
1068 | |||
1069 | if (len < 2) | ||
1070 | return -EILSEQ; | ||
1071 | iedatalen = ies[1]; | ||
1072 | if (iedatalen + 2 > len) | ||
1073 | return -EILSEQ; | ||
1074 | |||
1075 | if (ies[0] != WLAN_EID_VENDOR_SPECIFIC) | ||
1076 | goto cont; | ||
1077 | |||
1078 | if (iedatalen < 4) | ||
1079 | goto cont; | ||
1080 | |||
1081 | iedata = ies + 2; | ||
1082 | |||
1083 | /* check WFA OUI, P2P subtype */ | ||
1084 | if (iedata[0] != 0x50 || iedata[1] != 0x6f || | ||
1085 | iedata[2] != 0x9a || iedata[3] != 0x09) | ||
1086 | goto cont; | ||
1087 | |||
1088 | iedatalen -= 4; | ||
1089 | iedata += 4; | ||
1090 | |||
1091 | /* check attribute continuation into this IE */ | ||
1092 | copy = min_t(unsigned int, attr_remaining, iedatalen); | ||
1093 | if (copy && desired_attr) { | ||
1094 | desired_len += copy; | ||
1095 | if (out) { | ||
1096 | memcpy(out, iedata, min(bufsize, copy)); | ||
1097 | out += min(bufsize, copy); | ||
1098 | bufsize -= min(bufsize, copy); | ||
1099 | } | ||
1100 | |||
1101 | |||
1102 | if (copy == attr_remaining) | ||
1103 | return desired_len; | ||
1104 | } | ||
1105 | |||
1106 | attr_remaining -= copy; | ||
1107 | if (attr_remaining) | ||
1108 | goto cont; | ||
1109 | |||
1110 | iedatalen -= copy; | ||
1111 | iedata += copy; | ||
1112 | |||
1113 | while (iedatalen > 0) { | ||
1114 | u16 attr_len; | ||
1115 | |||
1116 | /* P2P attribute ID & size must fit */ | ||
1117 | if (iedatalen < 3) | ||
1118 | return -EILSEQ; | ||
1119 | desired_attr = iedata[0] == attr; | ||
1120 | attr_len = get_unaligned_le16(iedata + 1); | ||
1121 | iedatalen -= 3; | ||
1122 | iedata += 3; | ||
1123 | |||
1124 | copy = min_t(unsigned int, attr_len, iedatalen); | ||
1125 | |||
1126 | if (desired_attr) { | ||
1127 | desired_len += copy; | ||
1128 | if (out) { | ||
1129 | memcpy(out, iedata, min(bufsize, copy)); | ||
1130 | out += min(bufsize, copy); | ||
1131 | bufsize -= min(bufsize, copy); | ||
1132 | } | ||
1133 | |||
1134 | if (copy == attr_len) | ||
1135 | return desired_len; | ||
1136 | } | ||
1137 | |||
1138 | iedata += copy; | ||
1139 | iedatalen -= copy; | ||
1140 | attr_remaining = attr_len - copy; | ||
1141 | } | ||
1142 | |||
1143 | cont: | ||
1144 | len -= ies[1] + 2; | ||
1145 | ies += ies[1] + 2; | ||
1146 | } | ||
1147 | |||
1148 | if (attr_remaining && desired_attr) | ||
1149 | return -EILSEQ; | ||
1150 | |||
1151 | return -ENOENT; | ||
1152 | } | ||
1153 | EXPORT_SYMBOL(cfg80211_get_p2p_attr); | ||
1154 | |||
983 | int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, | 1155 | int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, |
984 | u32 beacon_int) | 1156 | u32 beacon_int) |
985 | { | 1157 | { |
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 6488d2dbc1d..f9680c9cf9b 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c | |||
@@ -784,6 +784,9 @@ static int cfg80211_wext_siwfreq(struct net_device *dev, | |||
784 | { | 784 | { |
785 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 785 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
786 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | 786 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); |
787 | struct cfg80211_chan_def chandef = { | ||
788 | .width = NL80211_CHAN_WIDTH_20_NOHT, | ||
789 | }; | ||
787 | int freq, err; | 790 | int freq, err; |
788 | 791 | ||
789 | switch (wdev->iftype) { | 792 | switch (wdev->iftype) { |
@@ -797,8 +800,12 @@ static int cfg80211_wext_siwfreq(struct net_device *dev, | |||
797 | return freq; | 800 | return freq; |
798 | if (freq == 0) | 801 | if (freq == 0) |
799 | return -EINVAL; | 802 | return -EINVAL; |
803 | chandef.center_freq1 = freq; | ||
804 | chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq); | ||
805 | if (!chandef.chan) | ||
806 | return -EINVAL; | ||
800 | mutex_lock(&rdev->devlist_mtx); | 807 | mutex_lock(&rdev->devlist_mtx); |
801 | err = cfg80211_set_monitor_channel(rdev, freq, NL80211_CHAN_NO_HT); | 808 | err = cfg80211_set_monitor_channel(rdev, &chandef); |
802 | mutex_unlock(&rdev->devlist_mtx); | 809 | mutex_unlock(&rdev->devlist_mtx); |
803 | return err; | 810 | return err; |
804 | case NL80211_IFTYPE_MESH_POINT: | 811 | case NL80211_IFTYPE_MESH_POINT: |
@@ -807,9 +814,12 @@ static int cfg80211_wext_siwfreq(struct net_device *dev, | |||
807 | return freq; | 814 | return freq; |
808 | if (freq == 0) | 815 | if (freq == 0) |
809 | return -EINVAL; | 816 | return -EINVAL; |
817 | chandef.center_freq1 = freq; | ||
818 | chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq); | ||
819 | if (!chandef.chan) | ||
820 | return -EINVAL; | ||
810 | mutex_lock(&rdev->devlist_mtx); | 821 | mutex_lock(&rdev->devlist_mtx); |
811 | err = cfg80211_set_mesh_freq(rdev, wdev, freq, | 822 | err = cfg80211_set_mesh_channel(rdev, wdev, &chandef); |
812 | NL80211_CHAN_NO_HT); | ||
813 | mutex_unlock(&rdev->devlist_mtx); | 823 | mutex_unlock(&rdev->devlist_mtx); |
814 | return err; | 824 | return err; |
815 | default: | 825 | default: |
@@ -823,8 +833,8 @@ static int cfg80211_wext_giwfreq(struct net_device *dev, | |||
823 | { | 833 | { |
824 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 834 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
825 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | 835 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); |
826 | struct ieee80211_channel *chan; | 836 | struct cfg80211_chan_def chandef; |
827 | enum nl80211_channel_type channel_type; | 837 | int ret; |
828 | 838 | ||
829 | switch (wdev->iftype) { | 839 | switch (wdev->iftype) { |
830 | case NL80211_IFTYPE_STATION: | 840 | case NL80211_IFTYPE_STATION: |
@@ -835,10 +845,10 @@ static int cfg80211_wext_giwfreq(struct net_device *dev, | |||
835 | if (!rdev->ops->get_channel) | 845 | if (!rdev->ops->get_channel) |
836 | return -EINVAL; | 846 | return -EINVAL; |
837 | 847 | ||
838 | chan = rdev_get_channel(rdev, wdev, &channel_type); | 848 | ret = rdev_get_channel(rdev, wdev, &chandef); |
839 | if (!chan) | 849 | if (ret) |
840 | return -EINVAL; | 850 | return ret; |
841 | freq->m = chan->center_freq; | 851 | freq->m = chandef.chan->center_freq; |
842 | freq->e = 6; | 852 | freq->e = 6; |
843 | return 0; | 853 | return 0; |
844 | default: | 854 | default: |
@@ -895,7 +905,7 @@ static int cfg80211_wext_siwtxpower(struct net_device *dev, | |||
895 | return 0; | 905 | return 0; |
896 | } | 906 | } |
897 | 907 | ||
898 | return rdev_set_tx_power(rdev, type, DBM_TO_MBM(dbm)); | 908 | return rdev_set_tx_power(rdev, wdev, type, DBM_TO_MBM(dbm)); |
899 | } | 909 | } |
900 | 910 | ||
901 | static int cfg80211_wext_giwtxpower(struct net_device *dev, | 911 | static int cfg80211_wext_giwtxpower(struct net_device *dev, |
@@ -914,7 +924,7 @@ static int cfg80211_wext_giwtxpower(struct net_device *dev, | |||
914 | if (!rdev->ops->get_tx_power) | 924 | if (!rdev->ops->get_tx_power) |
915 | return -EOPNOTSUPP; | 925 | return -EOPNOTSUPP; |
916 | 926 | ||
917 | err = rdev_get_tx_power(rdev, &val); | 927 | err = rdev_get_tx_power(rdev, wdev, &val); |
918 | if (err) | 928 | if (err) |
919 | return err; | 929 | return err; |
920 | 930 | ||
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c index 1f773f668d1..873af63187c 100644 --- a/net/wireless/wext-sme.c +++ b/net/wireless/wext-sme.c | |||
@@ -119,7 +119,16 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev, | |||
119 | * channel we disconnected above and reconnect below. | 119 | * channel we disconnected above and reconnect below. |
120 | */ | 120 | */ |
121 | if (chan && !wdev->wext.connect.ssid_len) { | 121 | if (chan && !wdev->wext.connect.ssid_len) { |
122 | err = cfg80211_set_monitor_channel(rdev, freq, NL80211_CHAN_NO_HT); | 122 | struct cfg80211_chan_def chandef = { |
123 | .width = NL80211_CHAN_WIDTH_20_NOHT, | ||
124 | .center_freq1 = freq, | ||
125 | }; | ||
126 | |||
127 | chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq); | ||
128 | if (chandef.chan) | ||
129 | err = cfg80211_set_monitor_channel(rdev, &chandef); | ||
130 | else | ||
131 | err = -EINVAL; | ||
123 | goto out; | 132 | goto out; |
124 | } | 133 | } |
125 | 134 | ||