diff options
65 files changed, 2245 insertions, 856 deletions
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 230c552daf91..a0d7355ef127 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/device.h> | 27 | #include <linux/device.h> |
28 | #include <linux/firmware.h> | 28 | #include <linux/firmware.h> |
29 | #include <linux/usb.h> | 29 | #include <linux/usb.h> |
30 | #include <asm/unaligned.h> | ||
30 | #include <net/bluetooth/bluetooth.h> | 31 | #include <net/bluetooth/bluetooth.h> |
31 | 32 | ||
32 | #define VERSION "1.0" | 33 | #define VERSION "1.0" |
@@ -50,12 +51,12 @@ | |||
50 | #define ATH3K_NAME_LEN 0xFF | 51 | #define ATH3K_NAME_LEN 0xFF |
51 | 52 | ||
52 | struct ath3k_version { | 53 | struct ath3k_version { |
53 | unsigned int rom_version; | 54 | __le32 rom_version; |
54 | unsigned int build_version; | 55 | __le32 build_version; |
55 | unsigned int ram_version; | 56 | __le32 ram_version; |
56 | unsigned char ref_clock; | 57 | __u8 ref_clock; |
57 | unsigned char reserved[0x07]; | 58 | __u8 reserved[7]; |
58 | }; | 59 | } __packed; |
59 | 60 | ||
60 | static const struct usb_device_id ath3k_table[] = { | 61 | static const struct usb_device_id ath3k_table[] = { |
61 | /* Atheros AR3011 */ | 62 | /* Atheros AR3011 */ |
@@ -349,7 +350,8 @@ static int ath3k_load_patch(struct usb_device *udev) | |||
349 | unsigned char fw_state; | 350 | unsigned char fw_state; |
350 | char filename[ATH3K_NAME_LEN] = {0}; | 351 | char filename[ATH3K_NAME_LEN] = {0}; |
351 | const struct firmware *firmware; | 352 | const struct firmware *firmware; |
352 | struct ath3k_version fw_version, pt_version; | 353 | struct ath3k_version fw_version; |
354 | __u32 pt_rom_version, pt_build_version; | ||
353 | int ret; | 355 | int ret; |
354 | 356 | ||
355 | ret = ath3k_get_state(udev, &fw_state); | 357 | ret = ath3k_get_state(udev, &fw_state); |
@@ -370,7 +372,7 @@ static int ath3k_load_patch(struct usb_device *udev) | |||
370 | } | 372 | } |
371 | 373 | ||
372 | snprintf(filename, ATH3K_NAME_LEN, "ar3k/AthrBT_0x%08x.dfu", | 374 | snprintf(filename, ATH3K_NAME_LEN, "ar3k/AthrBT_0x%08x.dfu", |
373 | le32_to_cpu(fw_version.rom_version)); | 375 | le32_to_cpu(fw_version.rom_version)); |
374 | 376 | ||
375 | ret = request_firmware(&firmware, filename, &udev->dev); | 377 | ret = request_firmware(&firmware, filename, &udev->dev); |
376 | if (ret < 0) { | 378 | if (ret < 0) { |
@@ -378,12 +380,13 @@ static int ath3k_load_patch(struct usb_device *udev) | |||
378 | return ret; | 380 | return ret; |
379 | } | 381 | } |
380 | 382 | ||
381 | pt_version.rom_version = *(int *)(firmware->data + firmware->size - 8); | 383 | pt_rom_version = get_unaligned_le32(firmware->data + |
382 | pt_version.build_version = *(int *) | 384 | firmware->size - 8); |
383 | (firmware->data + firmware->size - 4); | 385 | pt_build_version = get_unaligned_le32(firmware->data + |
386 | firmware->size - 4); | ||
384 | 387 | ||
385 | if ((pt_version.rom_version != fw_version.rom_version) || | 388 | if (pt_rom_version != le32_to_cpu(fw_version.rom_version) || |
386 | (pt_version.build_version <= fw_version.build_version)) { | 389 | pt_build_version <= le32_to_cpu(fw_version.build_version)) { |
387 | BT_ERR("Patch file version did not match with firmware"); | 390 | BT_ERR("Patch file version did not match with firmware"); |
388 | release_firmware(firmware); | 391 | release_firmware(firmware); |
389 | return -EINVAL; | 392 | return -EINVAL; |
diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h index caf684119a4e..38ad66289ad6 100644 --- a/drivers/bluetooth/btmrvl_drv.h +++ b/drivers/bluetooth/btmrvl_drv.h | |||
@@ -91,6 +91,7 @@ struct btmrvl_private { | |||
91 | 91 | ||
92 | /* Vendor specific Bluetooth commands */ | 92 | /* Vendor specific Bluetooth commands */ |
93 | #define BT_CMD_PSCAN_WIN_REPORT_ENABLE 0xFC03 | 93 | #define BT_CMD_PSCAN_WIN_REPORT_ENABLE 0xFC03 |
94 | #define BT_CMD_SET_BDADDR 0xFC22 | ||
94 | #define BT_CMD_AUTO_SLEEP_MODE 0xFC23 | 95 | #define BT_CMD_AUTO_SLEEP_MODE 0xFC23 |
95 | #define BT_CMD_HOST_SLEEP_CONFIG 0xFC59 | 96 | #define BT_CMD_HOST_SLEEP_CONFIG 0xFC59 |
96 | #define BT_CMD_HOST_SLEEP_ENABLE 0xFC5A | 97 | #define BT_CMD_HOST_SLEEP_ENABLE 0xFC5A |
diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c index cc65fd2fe856..bae8e6a0ecf6 100644 --- a/drivers/bluetooth/btmrvl_main.c +++ b/drivers/bluetooth/btmrvl_main.c | |||
@@ -539,6 +539,29 @@ static int btmrvl_setup(struct hci_dev *hdev) | |||
539 | return 0; | 539 | return 0; |
540 | } | 540 | } |
541 | 541 | ||
542 | static int btmrvl_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr) | ||
543 | { | ||
544 | struct sk_buff *skb; | ||
545 | long ret; | ||
546 | u8 buf[8]; | ||
547 | |||
548 | buf[0] = MRVL_VENDOR_PKT; | ||
549 | buf[1] = sizeof(bdaddr_t); | ||
550 | memcpy(buf + 2, bdaddr, sizeof(bdaddr_t)); | ||
551 | |||
552 | skb = __hci_cmd_sync(hdev, BT_CMD_SET_BDADDR, sizeof(buf), buf, | ||
553 | HCI_INIT_TIMEOUT); | ||
554 | if (IS_ERR(skb)) { | ||
555 | ret = PTR_ERR(skb); | ||
556 | BT_ERR("%s: changing btmrvl device address failed (%ld)", | ||
557 | hdev->name, ret); | ||
558 | return ret; | ||
559 | } | ||
560 | kfree_skb(skb); | ||
561 | |||
562 | return 0; | ||
563 | } | ||
564 | |||
542 | /* | 565 | /* |
543 | * This function handles the event generated by firmware, rx data | 566 | * This function handles the event generated by firmware, rx data |
544 | * received from firmware, and tx data sent from kernel. | 567 | * received from firmware, and tx data sent from kernel. |
@@ -632,6 +655,7 @@ int btmrvl_register_hdev(struct btmrvl_private *priv) | |||
632 | hdev->flush = btmrvl_flush; | 655 | hdev->flush = btmrvl_flush; |
633 | hdev->send = btmrvl_send_frame; | 656 | hdev->send = btmrvl_send_frame; |
634 | hdev->setup = btmrvl_setup; | 657 | hdev->setup = btmrvl_setup; |
658 | hdev->set_bdaddr = btmrvl_set_bdaddr; | ||
635 | 659 | ||
636 | hdev->dev_type = priv->btmrvl_dev.dev_type; | 660 | hdev->dev_type = priv->btmrvl_dev.dev_type; |
637 | 661 | ||
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index efff06438b02..3e683b153259 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c | |||
@@ -1169,6 +1169,10 @@ static int btmrvl_sdio_suspend(struct device *dev) | |||
1169 | } | 1169 | } |
1170 | 1170 | ||
1171 | priv = card->priv; | 1171 | priv = card->priv; |
1172 | hcidev = priv->btmrvl_dev.hcidev; | ||
1173 | BT_DBG("%s: SDIO suspend", hcidev->name); | ||
1174 | hci_suspend_dev(hcidev); | ||
1175 | skb_queue_purge(&priv->adapter->tx_queue); | ||
1172 | 1176 | ||
1173 | if (priv->adapter->hs_state != HS_ACTIVATED) { | 1177 | if (priv->adapter->hs_state != HS_ACTIVATED) { |
1174 | if (btmrvl_enable_hs(priv)) { | 1178 | if (btmrvl_enable_hs(priv)) { |
@@ -1176,10 +1180,6 @@ static int btmrvl_sdio_suspend(struct device *dev) | |||
1176 | return -EBUSY; | 1180 | return -EBUSY; |
1177 | } | 1181 | } |
1178 | } | 1182 | } |
1179 | hcidev = priv->btmrvl_dev.hcidev; | ||
1180 | BT_DBG("%s: SDIO suspend", hcidev->name); | ||
1181 | hci_suspend_dev(hcidev); | ||
1182 | skb_queue_purge(&priv->adapter->tx_queue); | ||
1183 | 1183 | ||
1184 | priv->adapter->is_suspended = true; | 1184 | priv->adapter->is_suspended = true; |
1185 | 1185 | ||
@@ -1221,13 +1221,13 @@ static int btmrvl_sdio_resume(struct device *dev) | |||
1221 | return 0; | 1221 | return 0; |
1222 | } | 1222 | } |
1223 | 1223 | ||
1224 | priv->adapter->is_suspended = false; | ||
1225 | hcidev = priv->btmrvl_dev.hcidev; | ||
1226 | BT_DBG("%s: SDIO resume", hcidev->name); | ||
1227 | hci_resume_dev(hcidev); | ||
1228 | priv->hw_wakeup_firmware(priv); | 1224 | priv->hw_wakeup_firmware(priv); |
1229 | priv->adapter->hs_state = HS_DEACTIVATED; | 1225 | priv->adapter->hs_state = HS_DEACTIVATED; |
1226 | hcidev = priv->btmrvl_dev.hcidev; | ||
1230 | BT_DBG("%s: HS DEACTIVATED in resume!", hcidev->name); | 1227 | BT_DBG("%s: HS DEACTIVATED in resume!", hcidev->name); |
1228 | priv->adapter->is_suspended = false; | ||
1229 | BT_DBG("%s: SDIO resume", hcidev->name); | ||
1230 | hci_resume_dev(hcidev); | ||
1231 | 1231 | ||
1232 | return 0; | 1232 | return 0; |
1233 | } | 1233 | } |
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index ed7b33b06b43..292c38e8aa17 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c | |||
@@ -48,6 +48,7 @@ static struct usb_driver btusb_driver; | |||
48 | #define BTUSB_INTEL 0x100 | 48 | #define BTUSB_INTEL 0x100 |
49 | #define BTUSB_INTEL_BOOT 0x200 | 49 | #define BTUSB_INTEL_BOOT 0x200 |
50 | #define BTUSB_BCM_PATCHRAM 0x400 | 50 | #define BTUSB_BCM_PATCHRAM 0x400 |
51 | #define BTUSB_MARVELL 0x800 | ||
51 | 52 | ||
52 | static const struct usb_device_id btusb_table[] = { | 53 | static const struct usb_device_id btusb_table[] = { |
53 | /* Generic Bluetooth USB device */ | 54 | /* Generic Bluetooth USB device */ |
@@ -113,6 +114,9 @@ static const struct usb_device_id btusb_table[] = { | |||
113 | { USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01), | 114 | { USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01), |
114 | .driver_info = BTUSB_BCM_PATCHRAM }, | 115 | .driver_info = BTUSB_BCM_PATCHRAM }, |
115 | 116 | ||
117 | /* ASUSTek Computer - Broadcom based */ | ||
118 | { USB_VENDOR_AND_INTERFACE_INFO(0x0b05, 0xff, 0x01, 0x01) }, | ||
119 | |||
116 | /* Belkin F8065bf - Broadcom based */ | 120 | /* Belkin F8065bf - Broadcom based */ |
117 | { USB_VENDOR_AND_INTERFACE_INFO(0x050d, 0xff, 0x01, 0x01) }, | 121 | { USB_VENDOR_AND_INTERFACE_INFO(0x050d, 0xff, 0x01, 0x01) }, |
118 | 122 | ||
@@ -242,6 +246,10 @@ static const struct usb_device_id blacklist_table[] = { | |||
242 | { USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL }, | 246 | { USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL }, |
243 | { USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL }, | 247 | { USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL }, |
244 | 248 | ||
249 | /* Marvell device */ | ||
250 | { USB_DEVICE(0x1286, 0x2044), .driver_info = BTUSB_MARVELL }, | ||
251 | { USB_DEVICE(0x1286, 0x2046), .driver_info = BTUSB_MARVELL }, | ||
252 | |||
245 | { } /* Terminating entry */ | 253 | { } /* Terminating entry */ |
246 | }; | 254 | }; |
247 | 255 | ||
@@ -1455,6 +1463,29 @@ static int btusb_set_bdaddr_intel(struct hci_dev *hdev, const bdaddr_t *bdaddr) | |||
1455 | return 0; | 1463 | return 0; |
1456 | } | 1464 | } |
1457 | 1465 | ||
1466 | static int btusb_set_bdaddr_marvell(struct hci_dev *hdev, | ||
1467 | const bdaddr_t *bdaddr) | ||
1468 | { | ||
1469 | struct sk_buff *skb; | ||
1470 | u8 buf[8]; | ||
1471 | long ret; | ||
1472 | |||
1473 | buf[0] = 0xfe; | ||
1474 | buf[1] = sizeof(bdaddr_t); | ||
1475 | memcpy(buf + 2, bdaddr, sizeof(bdaddr_t)); | ||
1476 | |||
1477 | skb = __hci_cmd_sync(hdev, 0xfc22, sizeof(buf), buf, HCI_INIT_TIMEOUT); | ||
1478 | if (IS_ERR(skb)) { | ||
1479 | ret = PTR_ERR(skb); | ||
1480 | BT_ERR("%s: changing Marvell device address failed (%ld)", | ||
1481 | hdev->name, ret); | ||
1482 | return ret; | ||
1483 | } | ||
1484 | kfree_skb(skb); | ||
1485 | |||
1486 | return 0; | ||
1487 | } | ||
1488 | |||
1458 | #define BDADDR_BCM20702A0 (&(bdaddr_t) {{0x00, 0xa0, 0x02, 0x70, 0x20, 0x00}}) | 1489 | #define BDADDR_BCM20702A0 (&(bdaddr_t) {{0x00, 0xa0, 0x02, 0x70, 0x20, 0x00}}) |
1459 | 1490 | ||
1460 | static int btusb_setup_bcm_patchram(struct hci_dev *hdev) | 1491 | static int btusb_setup_bcm_patchram(struct hci_dev *hdev) |
@@ -1766,6 +1797,9 @@ static int btusb_probe(struct usb_interface *intf, | |||
1766 | hdev->set_bdaddr = btusb_set_bdaddr_intel; | 1797 | hdev->set_bdaddr = btusb_set_bdaddr_intel; |
1767 | } | 1798 | } |
1768 | 1799 | ||
1800 | if (id->driver_info & BTUSB_MARVELL) | ||
1801 | hdev->set_bdaddr = btusb_set_bdaddr_marvell; | ||
1802 | |||
1769 | if (id->driver_info & BTUSB_INTEL_BOOT) | 1803 | if (id->driver_info & BTUSB_INTEL_BOOT) |
1770 | set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); | 1804 | set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); |
1771 | 1805 | ||
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 3e127be06bfb..d7055febe119 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -290,6 +290,14 @@ static struct ieee80211_channel b43_5ghz_nphy_chantable[] = { | |||
290 | CHAN5G(182, 0), | 290 | CHAN5G(182, 0), |
291 | }; | 291 | }; |
292 | 292 | ||
293 | static struct ieee80211_channel b43_5ghz_nphy_chantable_limited[] = { | ||
294 | CHAN5G(36, 0), CHAN5G(40, 0), | ||
295 | CHAN5G(44, 0), CHAN5G(48, 0), | ||
296 | CHAN5G(149, 0), CHAN5G(153, 0), | ||
297 | CHAN5G(157, 0), CHAN5G(161, 0), | ||
298 | CHAN5G(165, 0), | ||
299 | }; | ||
300 | |||
293 | static struct ieee80211_channel b43_5ghz_aphy_chantable[] = { | 301 | static struct ieee80211_channel b43_5ghz_aphy_chantable[] = { |
294 | CHAN5G(34, 0), CHAN5G(36, 0), | 302 | CHAN5G(34, 0), CHAN5G(36, 0), |
295 | CHAN5G(38, 0), CHAN5G(40, 0), | 303 | CHAN5G(38, 0), CHAN5G(40, 0), |
@@ -322,6 +330,14 @@ static struct ieee80211_supported_band b43_band_5GHz_nphy = { | |||
322 | .n_bitrates = b43_a_ratetable_size, | 330 | .n_bitrates = b43_a_ratetable_size, |
323 | }; | 331 | }; |
324 | 332 | ||
333 | static struct ieee80211_supported_band b43_band_5GHz_nphy_limited = { | ||
334 | .band = IEEE80211_BAND_5GHZ, | ||
335 | .channels = b43_5ghz_nphy_chantable_limited, | ||
336 | .n_channels = ARRAY_SIZE(b43_5ghz_nphy_chantable_limited), | ||
337 | .bitrates = b43_a_ratetable, | ||
338 | .n_bitrates = b43_a_ratetable_size, | ||
339 | }; | ||
340 | |||
325 | static struct ieee80211_supported_band b43_band_5GHz_aphy = { | 341 | static struct ieee80211_supported_band b43_band_5GHz_aphy = { |
326 | .band = IEEE80211_BAND_5GHZ, | 342 | .band = IEEE80211_BAND_5GHZ, |
327 | .channels = b43_5ghz_aphy_chantable, | 343 | .channels = b43_5ghz_aphy_chantable, |
@@ -4385,8 +4401,9 @@ static int b43_phy_versioning(struct b43_wldev *dev) | |||
4385 | u8 phy_type; | 4401 | u8 phy_type; |
4386 | u8 phy_rev; | 4402 | u8 phy_rev; |
4387 | u16 radio_manuf; | 4403 | u16 radio_manuf; |
4388 | u16 radio_ver; | 4404 | u16 radio_id; |
4389 | u16 radio_rev; | 4405 | u16 radio_rev; |
4406 | u8 radio_ver; | ||
4390 | int unsupported = 0; | 4407 | int unsupported = 0; |
4391 | 4408 | ||
4392 | /* Get PHY versioning */ | 4409 | /* Get PHY versioning */ |
@@ -4452,7 +4469,9 @@ static int b43_phy_versioning(struct b43_wldev *dev) | |||
4452 | radio_rev = b43_read16(dev, B43_MMIO_RADIO24_DATA); | 4469 | radio_rev = b43_read16(dev, B43_MMIO_RADIO24_DATA); |
4453 | 4470 | ||
4454 | b43_write16(dev, B43_MMIO_RADIO24_CONTROL, 1); | 4471 | b43_write16(dev, B43_MMIO_RADIO24_CONTROL, 1); |
4455 | radio_ver = b43_read16(dev, B43_MMIO_RADIO24_DATA); | 4472 | radio_id = b43_read16(dev, B43_MMIO_RADIO24_DATA); |
4473 | |||
4474 | radio_ver = 0; /* Is there version somewhere? */ | ||
4456 | } else if (core_rev >= 24) { | 4475 | } else if (core_rev >= 24) { |
4457 | u16 radio24[3]; | 4476 | u16 radio24[3]; |
4458 | 4477 | ||
@@ -4461,12 +4480,10 @@ static int b43_phy_versioning(struct b43_wldev *dev) | |||
4461 | radio24[tmp] = b43_read16(dev, B43_MMIO_RADIO24_DATA); | 4480 | radio24[tmp] = b43_read16(dev, B43_MMIO_RADIO24_DATA); |
4462 | } | 4481 | } |
4463 | 4482 | ||
4464 | /* Broadcom uses "id" for our "ver" and has separated "ver" */ | ||
4465 | /* radio_ver = (radio24[0] & 0xF0) >> 4; */ | ||
4466 | |||
4467 | radio_manuf = 0x17F; | 4483 | radio_manuf = 0x17F; |
4468 | radio_ver = (radio24[2] << 8) | radio24[1]; | 4484 | radio_id = (radio24[2] << 8) | radio24[1]; |
4469 | radio_rev = (radio24[0] & 0xF); | 4485 | radio_rev = (radio24[0] & 0xF); |
4486 | radio_ver = (radio24[0] & 0xF0) >> 4; | ||
4470 | } else { | 4487 | } else { |
4471 | if (dev->dev->chip_id == 0x4317) { | 4488 | if (dev->dev->chip_id == 0x4317) { |
4472 | if (dev->dev->chip_rev == 0) | 4489 | if (dev->dev->chip_rev == 0) |
@@ -4485,15 +4502,16 @@ static int b43_phy_versioning(struct b43_wldev *dev) | |||
4485 | << 16; | 4502 | << 16; |
4486 | } | 4503 | } |
4487 | radio_manuf = (tmp & 0x00000FFF); | 4504 | radio_manuf = (tmp & 0x00000FFF); |
4488 | radio_ver = (tmp & 0x0FFFF000) >> 12; | 4505 | radio_id = (tmp & 0x0FFFF000) >> 12; |
4489 | radio_rev = (tmp & 0xF0000000) >> 28; | 4506 | radio_rev = (tmp & 0xF0000000) >> 28; |
4507 | radio_ver = 0; /* Probably not available on old hw */ | ||
4490 | } | 4508 | } |
4491 | 4509 | ||
4492 | if (radio_manuf != 0x17F /* Broadcom */) | 4510 | if (radio_manuf != 0x17F /* Broadcom */) |
4493 | unsupported = 1; | 4511 | unsupported = 1; |
4494 | switch (phy_type) { | 4512 | switch (phy_type) { |
4495 | case B43_PHYTYPE_A: | 4513 | case B43_PHYTYPE_A: |
4496 | if (radio_ver != 0x2060) | 4514 | if (radio_id != 0x2060) |
4497 | unsupported = 1; | 4515 | unsupported = 1; |
4498 | if (radio_rev != 1) | 4516 | if (radio_rev != 1) |
4499 | unsupported = 1; | 4517 | unsupported = 1; |
@@ -4501,30 +4519,31 @@ static int b43_phy_versioning(struct b43_wldev *dev) | |||
4501 | unsupported = 1; | 4519 | unsupported = 1; |
4502 | break; | 4520 | break; |
4503 | case B43_PHYTYPE_B: | 4521 | case B43_PHYTYPE_B: |
4504 | if ((radio_ver & 0xFFF0) != 0x2050) | 4522 | if ((radio_id & 0xFFF0) != 0x2050) |
4505 | unsupported = 1; | 4523 | unsupported = 1; |
4506 | break; | 4524 | break; |
4507 | case B43_PHYTYPE_G: | 4525 | case B43_PHYTYPE_G: |
4508 | if (radio_ver != 0x2050) | 4526 | if (radio_id != 0x2050) |
4509 | unsupported = 1; | 4527 | unsupported = 1; |
4510 | break; | 4528 | break; |
4511 | case B43_PHYTYPE_N: | 4529 | case B43_PHYTYPE_N: |
4512 | if (radio_ver != 0x2055 && radio_ver != 0x2056 && | 4530 | if (radio_id != 0x2055 && radio_id != 0x2056 && |
4513 | radio_ver != 0x2057) | 4531 | radio_id != 0x2057) |
4514 | unsupported = 1; | 4532 | unsupported = 1; |
4515 | if (radio_ver == 0x2057 && !(radio_rev == 9)) | 4533 | if (radio_id == 0x2057 && |
4534 | !(radio_rev == 9 || radio_rev == 14)) | ||
4516 | unsupported = 1; | 4535 | unsupported = 1; |
4517 | break; | 4536 | break; |
4518 | case B43_PHYTYPE_LP: | 4537 | case B43_PHYTYPE_LP: |
4519 | if (radio_ver != 0x2062 && radio_ver != 0x2063) | 4538 | if (radio_id != 0x2062 && radio_id != 0x2063) |
4520 | unsupported = 1; | 4539 | unsupported = 1; |
4521 | break; | 4540 | break; |
4522 | case B43_PHYTYPE_HT: | 4541 | case B43_PHYTYPE_HT: |
4523 | if (radio_ver != 0x2059) | 4542 | if (radio_id != 0x2059) |
4524 | unsupported = 1; | 4543 | unsupported = 1; |
4525 | break; | 4544 | break; |
4526 | case B43_PHYTYPE_LCN: | 4545 | case B43_PHYTYPE_LCN: |
4527 | if (radio_ver != 0x2064) | 4546 | if (radio_id != 0x2064) |
4528 | unsupported = 1; | 4547 | unsupported = 1; |
4529 | break; | 4548 | break; |
4530 | default: | 4549 | default: |
@@ -4532,15 +4551,17 @@ static int b43_phy_versioning(struct b43_wldev *dev) | |||
4532 | } | 4551 | } |
4533 | if (unsupported) { | 4552 | if (unsupported) { |
4534 | b43err(dev->wl, | 4553 | b43err(dev->wl, |
4535 | "FOUND UNSUPPORTED RADIO (Manuf 0x%X, ID 0x%X, Revision %u)\n", | 4554 | "FOUND UNSUPPORTED RADIO (Manuf 0x%X, ID 0x%X, Revision %u, Version %u)\n", |
4536 | radio_manuf, radio_ver, radio_rev); | 4555 | radio_manuf, radio_id, radio_rev, radio_ver); |
4537 | return -EOPNOTSUPP; | 4556 | return -EOPNOTSUPP; |
4538 | } | 4557 | } |
4539 | b43info(dev->wl, "Found Radio: Manuf 0x%X, ID 0x%X, Revision %u\n", | 4558 | b43info(dev->wl, |
4540 | radio_manuf, radio_ver, radio_rev); | 4559 | "Found Radio: Manuf 0x%X, ID 0x%X, Revision %u, Version %u\n", |
4560 | radio_manuf, radio_id, radio_rev, radio_ver); | ||
4541 | 4561 | ||
4562 | /* FIXME: b43 treats "id" as "ver" and ignores the real "ver" */ | ||
4542 | phy->radio_manuf = radio_manuf; | 4563 | phy->radio_manuf = radio_manuf; |
4543 | phy->radio_ver = radio_ver; | 4564 | phy->radio_ver = radio_id; |
4544 | phy->radio_rev = radio_rev; | 4565 | phy->radio_rev = radio_rev; |
4545 | 4566 | ||
4546 | phy->analog = analog_type; | 4567 | phy->analog = analog_type; |
@@ -5150,16 +5171,22 @@ static int b43_setup_bands(struct b43_wldev *dev, | |||
5150 | struct ieee80211_hw *hw = dev->wl->hw; | 5171 | struct ieee80211_hw *hw = dev->wl->hw; |
5151 | struct b43_phy *phy = &dev->phy; | 5172 | struct b43_phy *phy = &dev->phy; |
5152 | bool limited_2g; | 5173 | bool limited_2g; |
5174 | bool limited_5g; | ||
5153 | 5175 | ||
5154 | /* We don't support all 2 GHz channels on some devices */ | 5176 | /* We don't support all 2 GHz channels on some devices */ |
5155 | limited_2g = phy->radio_ver == 0x2057 && phy->radio_rev == 9; | 5177 | limited_2g = phy->radio_ver == 0x2057 && |
5178 | (phy->radio_rev == 9 || phy->radio_rev == 14); | ||
5179 | limited_5g = phy->radio_ver == 0x2057 && | ||
5180 | phy->radio_rev == 9; | ||
5156 | 5181 | ||
5157 | if (have_2ghz_phy) | 5182 | if (have_2ghz_phy) |
5158 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = limited_2g ? | 5183 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = limited_2g ? |
5159 | &b43_band_2ghz_limited : &b43_band_2GHz; | 5184 | &b43_band_2ghz_limited : &b43_band_2GHz; |
5160 | if (dev->phy.type == B43_PHYTYPE_N) { | 5185 | if (dev->phy.type == B43_PHYTYPE_N) { |
5161 | if (have_5ghz_phy) | 5186 | if (have_5ghz_phy) |
5162 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &b43_band_5GHz_nphy; | 5187 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = limited_5g ? |
5188 | &b43_band_5GHz_nphy_limited : | ||
5189 | &b43_band_5GHz_nphy; | ||
5163 | } else { | 5190 | } else { |
5164 | if (have_5ghz_phy) | 5191 | if (have_5ghz_phy) |
5165 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &b43_band_5GHz_aphy; | 5192 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &b43_band_5GHz_aphy; |
@@ -5311,7 +5338,6 @@ static int b43_wireless_core_attach(struct b43_wldev *dev) | |||
5311 | switch (dev->phy.type) { | 5338 | switch (dev->phy.type) { |
5312 | case B43_PHYTYPE_A: | 5339 | case B43_PHYTYPE_A: |
5313 | case B43_PHYTYPE_G: | 5340 | case B43_PHYTYPE_G: |
5314 | case B43_PHYTYPE_N: | ||
5315 | case B43_PHYTYPE_LP: | 5341 | case B43_PHYTYPE_LP: |
5316 | case B43_PHYTYPE_HT: | 5342 | case B43_PHYTYPE_HT: |
5317 | b43warn(wl, "5 GHz band is unsupported on this PHY\n"); | 5343 | b43warn(wl, "5 GHz band is unsupported on this PHY\n"); |
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 92bfe352ba08..d269fbb27b9e 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c | |||
@@ -225,13 +225,13 @@ static void b43_nphy_rf_ctl_override_one_to_many(struct b43_wldev *dev, | |||
225 | b43_nphy_rf_ctl_override_rev7(dev, 0x2, value, core, off, 1); | 225 | b43_nphy_rf_ctl_override_rev7(dev, 0x2, value, core, off, 1); |
226 | b43_nphy_rf_ctl_override_rev7(dev, 0x1, value, core, off, 1); | 226 | b43_nphy_rf_ctl_override_rev7(dev, 0x1, value, core, off, 1); |
227 | b43_nphy_rf_ctl_override_rev7(dev, 0x2, value, core, off, 2); | 227 | b43_nphy_rf_ctl_override_rev7(dev, 0x2, value, core, off, 2); |
228 | b43_nphy_rf_ctl_override_rev7(dev, 0x0800, value, core, off, 1); | 228 | b43_nphy_rf_ctl_override_rev7(dev, 0x0800, 0, core, off, 1); |
229 | break; | 229 | break; |
230 | case N_RF_CTL_OVER_CMD_TX_PU: | 230 | case N_RF_CTL_OVER_CMD_TX_PU: |
231 | b43_nphy_rf_ctl_override_rev7(dev, 0x4, value, core, off, 0); | 231 | b43_nphy_rf_ctl_override_rev7(dev, 0x4, value, core, off, 0); |
232 | b43_nphy_rf_ctl_override_rev7(dev, 0x2, value, core, off, 1); | 232 | b43_nphy_rf_ctl_override_rev7(dev, 0x2, value, core, off, 1); |
233 | b43_nphy_rf_ctl_override_rev7(dev, 0x1, value, core, off, 2); | 233 | b43_nphy_rf_ctl_override_rev7(dev, 0x1, value, core, off, 2); |
234 | b43_nphy_rf_ctl_override_rev7(dev, 0x0800, value, core, off, 1); | 234 | b43_nphy_rf_ctl_override_rev7(dev, 0x0800, 1, core, off, 1); |
235 | break; | 235 | break; |
236 | case N_RF_CTL_OVER_CMD_RX_GAIN: | 236 | case N_RF_CTL_OVER_CMD_RX_GAIN: |
237 | tmp = value & 0xFF; | 237 | tmp = value & 0xFF; |
@@ -343,6 +343,7 @@ static void b43_nphy_rf_ctl_intc_override_rev7(struct b43_wldev *dev, | |||
343 | switch (intc_override) { | 343 | switch (intc_override) { |
344 | case N_INTC_OVERRIDE_OFF: | 344 | case N_INTC_OVERRIDE_OFF: |
345 | b43_phy_write(dev, reg, 0); | 345 | b43_phy_write(dev, reg, 0); |
346 | b43_phy_mask(dev, 0x2ff, ~0x2000); | ||
346 | b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); | 347 | b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); |
347 | break; | 348 | break; |
348 | case N_INTC_OVERRIDE_TRSW: | 349 | case N_INTC_OVERRIDE_TRSW: |
@@ -1596,7 +1597,7 @@ static void b43_nphy_run_samples(struct b43_wldev *dev, u16 samps, u16 loops, | |||
1596 | bool lpf_bw3, lpf_bw4; | 1597 | bool lpf_bw3, lpf_bw4; |
1597 | 1598 | ||
1598 | lpf_bw3 = b43_phy_read(dev, B43_NPHY_REV7_RF_CTL_OVER3) & 0x80; | 1599 | lpf_bw3 = b43_phy_read(dev, B43_NPHY_REV7_RF_CTL_OVER3) & 0x80; |
1599 | lpf_bw4 = b43_phy_read(dev, B43_NPHY_REV7_RF_CTL_OVER3) & 0x80; | 1600 | lpf_bw4 = b43_phy_read(dev, B43_NPHY_REV7_RF_CTL_OVER4) & 0x80; |
1600 | 1601 | ||
1601 | if (lpf_bw3 || lpf_bw4) { | 1602 | if (lpf_bw3 || lpf_bw4) { |
1602 | /* TODO */ | 1603 | /* TODO */ |
@@ -2117,7 +2118,7 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev) | |||
2117 | N_RF_CTL_OVER_CMD_RX_PU, | 2118 | N_RF_CTL_OVER_CMD_RX_PU, |
2118 | 1, 0, false); | 2119 | 1, 0, false); |
2119 | b43_nphy_rf_ctl_override_rev7(dev, 0x80, 1, 0, false, 0); | 2120 | b43_nphy_rf_ctl_override_rev7(dev, 0x80, 1, 0, false, 0); |
2120 | b43_nphy_rf_ctl_override_rev7(dev, 0x80, 1, 0, false, 0); | 2121 | b43_nphy_rf_ctl_override_rev7(dev, 0x40, 1, 0, false, 0); |
2121 | if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { | 2122 | if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { |
2122 | b43_nphy_rf_ctl_override_rev7(dev, 0x20, 0, 0, false, | 2123 | b43_nphy_rf_ctl_override_rev7(dev, 0x20, 0, 0, false, |
2123 | 0); | 2124 | 0); |
@@ -2708,25 +2709,39 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) | |||
2708 | struct ssb_sprom *sprom = dev->dev->bus_sprom; | 2709 | struct ssb_sprom *sprom = dev->dev->bus_sprom; |
2709 | struct b43_phy *phy = &dev->phy; | 2710 | struct b43_phy *phy = &dev->phy; |
2710 | 2711 | ||
2712 | /* TX to RX */ | ||
2713 | u8 tx2rx_events[7] = { 4, 3, 5, 2, 1, 8, 31, }; | ||
2714 | u8 tx2rx_delays[7] = { 8, 4, 4, 4, 4, 6, 1, }; | ||
2715 | /* RX to TX */ | ||
2711 | u8 rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3, | 2716 | u8 rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3, |
2712 | 0x1F }; | 2717 | 0x1F }; |
2713 | u8 rx2tx_delays_ipa[9] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 }; | 2718 | u8 rx2tx_delays_ipa[9] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 }; |
2714 | 2719 | ||
2715 | u16 ntab7_15e_16e[] = { 0x10f, 0x10f }; | 2720 | static const u16 ntab7_15e_16e[] = { 0, 0x10f, 0x10f }; |
2716 | u8 ntab7_138_146[] = { 0x11, 0x11 }; | 2721 | u8 ntab7_138_146[] = { 0x11, 0x11 }; |
2717 | u8 ntab7_133[] = { 0x77, 0x11, 0x11 }; | 2722 | u8 ntab7_133[] = { 0x77, 0x11, 0x11 }; |
2718 | 2723 | ||
2719 | u16 lpf_20, lpf_40, lpf_11b; | 2724 | u16 lpf_ofdm_20mhz[2], lpf_ofdm_40mhz[2], lpf_11b[2]; |
2720 | u16 bcap_val, bcap_val_11b, bcap_val_11n_20, bcap_val_11n_40; | 2725 | u16 bcap_val; |
2721 | u16 scap_val, scap_val_11b, scap_val_11n_20, scap_val_11n_40; | 2726 | s16 bcap_val_11b[2], bcap_val_11n_20[2], bcap_val_11n_40[2]; |
2727 | u16 scap_val; | ||
2728 | s16 scap_val_11b[2], scap_val_11n_20[2], scap_val_11n_40[2]; | ||
2722 | bool rccal_ovrd = false; | 2729 | bool rccal_ovrd = false; |
2723 | 2730 | ||
2724 | u16 rx2tx_lut_20_11b, rx2tx_lut_20_11n, rx2tx_lut_40_11n; | ||
2725 | u16 bias, conv, filt; | 2731 | u16 bias, conv, filt; |
2726 | 2732 | ||
2733 | u32 noise_tbl[2]; | ||
2734 | |||
2727 | u32 tmp32; | 2735 | u32 tmp32; |
2728 | u8 core; | 2736 | u8 core; |
2729 | 2737 | ||
2738 | b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x0125); | ||
2739 | b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x01b3); | ||
2740 | b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x0105); | ||
2741 | b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x016e); | ||
2742 | b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0x00cd); | ||
2743 | b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x0020); | ||
2744 | |||
2730 | if (phy->rev == 7) { | 2745 | if (phy->rev == 7) { |
2731 | b43_phy_set(dev, B43_NPHY_FINERX2_CGC, 0x10); | 2746 | b43_phy_set(dev, B43_NPHY_FINERX2_CGC, 0x10); |
2732 | b43_phy_maskset(dev, B43_NPHY_FREQGAIN0, 0xFF80, 0x0020); | 2747 | b43_phy_maskset(dev, B43_NPHY_FREQGAIN0, 0xFF80, 0x0020); |
@@ -2746,11 +2761,18 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) | |||
2746 | b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0xFF80, 0x0040); | 2761 | b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0xFF80, 0x0040); |
2747 | b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0x80FF, 0x4000); | 2762 | b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0x80FF, 0x4000); |
2748 | } | 2763 | } |
2749 | if (phy->rev <= 8) { | 2764 | |
2765 | if (phy->rev >= 16) { | ||
2766 | b43_phy_write(dev, B43_NPHY_FORCEFRONT0, 0x7ff); | ||
2767 | b43_phy_write(dev, B43_NPHY_FORCEFRONT1, 0x7ff); | ||
2768 | } else if (phy->rev <= 8) { | ||
2750 | b43_phy_write(dev, B43_NPHY_FORCEFRONT0, 0x1B0); | 2769 | b43_phy_write(dev, B43_NPHY_FORCEFRONT0, 0x1B0); |
2751 | b43_phy_write(dev, B43_NPHY_FORCEFRONT1, 0x1B0); | 2770 | b43_phy_write(dev, B43_NPHY_FORCEFRONT1, 0x1B0); |
2752 | } | 2771 | } |
2753 | if (phy->rev >= 8) | 2772 | |
2773 | if (phy->rev >= 16) | ||
2774 | b43_phy_maskset(dev, B43_NPHY_TXTAILCNT, ~0xFF, 0xa0); | ||
2775 | else if (phy->rev >= 8) | ||
2754 | b43_phy_maskset(dev, B43_NPHY_TXTAILCNT, ~0xFF, 0x72); | 2776 | b43_phy_maskset(dev, B43_NPHY_TXTAILCNT, ~0xFF, 0x72); |
2755 | 2777 | ||
2756 | b43_ntab_write(dev, B43_NTAB16(8, 0x00), 2); | 2778 | b43_ntab_write(dev, B43_NTAB16(8, 0x00), 2); |
@@ -2758,9 +2780,11 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) | |||
2758 | tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0)); | 2780 | tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0)); |
2759 | tmp32 &= 0xffffff; | 2781 | tmp32 &= 0xffffff; |
2760 | b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32); | 2782 | b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32); |
2761 | b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x15e), 2, ntab7_15e_16e); | 2783 | b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x15d), 3, ntab7_15e_16e); |
2762 | b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x16e), 2, ntab7_15e_16e); | 2784 | b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x16d), 3, ntab7_15e_16e); |
2763 | 2785 | ||
2786 | b43_nphy_set_rf_sequence(dev, 1, tx2rx_events, tx2rx_delays, | ||
2787 | ARRAY_SIZE(tx2rx_events)); | ||
2764 | if (b43_nphy_ipa(dev)) | 2788 | if (b43_nphy_ipa(dev)) |
2765 | b43_nphy_set_rf_sequence(dev, 0, rx2tx_events_ipa, | 2789 | b43_nphy_set_rf_sequence(dev, 0, rx2tx_events_ipa, |
2766 | rx2tx_delays_ipa, ARRAY_SIZE(rx2tx_events_ipa)); | 2790 | rx2tx_delays_ipa, ARRAY_SIZE(rx2tx_events_ipa)); |
@@ -2768,84 +2792,176 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) | |||
2768 | b43_phy_maskset(dev, B43_NPHY_EPS_OVERRIDEI_0, 0x3FFF, 0x4000); | 2792 | b43_phy_maskset(dev, B43_NPHY_EPS_OVERRIDEI_0, 0x3FFF, 0x4000); |
2769 | b43_phy_maskset(dev, B43_NPHY_EPS_OVERRIDEI_1, 0x3FFF, 0x4000); | 2793 | b43_phy_maskset(dev, B43_NPHY_EPS_OVERRIDEI_1, 0x3FFF, 0x4000); |
2770 | 2794 | ||
2771 | lpf_20 = b43_nphy_read_lpf_ctl(dev, 0x154); | 2795 | for (core = 0; core < 2; core++) { |
2772 | lpf_40 = b43_nphy_read_lpf_ctl(dev, 0x159); | 2796 | lpf_ofdm_20mhz[core] = b43_nphy_read_lpf_ctl(dev, 0x154 + core * 0x10); |
2773 | lpf_11b = b43_nphy_read_lpf_ctl(dev, 0x152); | 2797 | lpf_ofdm_40mhz[core] = b43_nphy_read_lpf_ctl(dev, 0x159 + core * 0x10); |
2798 | lpf_11b[core] = b43_nphy_read_lpf_ctl(dev, 0x152 + core * 0x10); | ||
2799 | } | ||
2800 | |||
2801 | bcap_val = b43_radio_read(dev, R2057_RCCAL_BCAP_VAL); | ||
2802 | scap_val = b43_radio_read(dev, R2057_RCCAL_SCAP_VAL); | ||
2803 | |||
2774 | if (b43_nphy_ipa(dev)) { | 2804 | if (b43_nphy_ipa(dev)) { |
2775 | if ((phy->radio_rev == 5 && b43_is_40mhz(dev)) || | 2805 | bool ghz2 = b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ; |
2776 | phy->radio_rev == 7 || phy->radio_rev == 8) { | 2806 | |
2777 | bcap_val = b43_radio_read(dev, 0x16b); | 2807 | switch (phy->radio_rev) { |
2778 | scap_val = b43_radio_read(dev, 0x16a); | 2808 | case 5: |
2779 | scap_val_11b = scap_val; | 2809 | /* Check radio version (to be 0) by PHY rev for now */ |
2780 | bcap_val_11b = bcap_val; | 2810 | if (phy->rev == 8 && b43_is_40mhz(dev)) { |
2781 | if (phy->radio_rev == 5 && b43_is_40mhz(dev)) { | 2811 | for (core = 0; core < 2; core++) { |
2782 | scap_val_11n_20 = scap_val; | 2812 | scap_val_11b[core] = scap_val; |
2783 | bcap_val_11n_20 = bcap_val; | 2813 | bcap_val_11b[core] = bcap_val; |
2784 | scap_val_11n_40 = bcap_val_11n_40 = 0xc; | 2814 | scap_val_11n_20[core] = scap_val; |
2815 | bcap_val_11n_20[core] = bcap_val; | ||
2816 | scap_val_11n_40[core] = 0xc; | ||
2817 | bcap_val_11n_40[core] = 0xc; | ||
2818 | } | ||
2819 | |||
2785 | rccal_ovrd = true; | 2820 | rccal_ovrd = true; |
2786 | } else { /* Rev 7/8 */ | 2821 | } |
2787 | lpf_20 = 4; | 2822 | if (phy->rev == 9) { |
2788 | lpf_11b = 1; | 2823 | /* TODO: Radio version 1 (e.g. BCM5357B0) */ |
2824 | } | ||
2825 | break; | ||
2826 | case 7: | ||
2827 | case 8: | ||
2828 | for (core = 0; core < 2; core++) { | ||
2829 | scap_val_11b[core] = scap_val; | ||
2830 | bcap_val_11b[core] = bcap_val; | ||
2831 | lpf_ofdm_20mhz[core] = 4; | ||
2832 | lpf_11b[core] = 1; | ||
2789 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { | 2833 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { |
2790 | scap_val_11n_20 = 0xc; | 2834 | scap_val_11n_20[core] = 0xc; |
2791 | bcap_val_11n_20 = 0xc; | 2835 | bcap_val_11n_20[core] = 0xc; |
2792 | scap_val_11n_40 = 0xa; | 2836 | scap_val_11n_40[core] = 0xa; |
2793 | bcap_val_11n_40 = 0xa; | 2837 | bcap_val_11n_40[core] = 0xa; |
2794 | } else { | 2838 | } else { |
2795 | scap_val_11n_20 = 0x14; | 2839 | scap_val_11n_20[core] = 0x14; |
2796 | bcap_val_11n_20 = 0x14; | 2840 | bcap_val_11n_20[core] = 0x14; |
2797 | scap_val_11n_40 = 0xf; | 2841 | scap_val_11n_40[core] = 0xf; |
2798 | bcap_val_11n_40 = 0xf; | 2842 | bcap_val_11n_40[core] = 0xf; |
2799 | } | 2843 | } |
2800 | rccal_ovrd = true; | ||
2801 | } | 2844 | } |
2845 | |||
2846 | rccal_ovrd = true; | ||
2847 | break; | ||
2848 | case 9: | ||
2849 | for (core = 0; core < 2; core++) { | ||
2850 | bcap_val_11b[core] = bcap_val; | ||
2851 | scap_val_11b[core] = scap_val; | ||
2852 | lpf_11b[core] = 1; | ||
2853 | |||
2854 | if (ghz2) { | ||
2855 | bcap_val_11n_20[core] = bcap_val + 13; | ||
2856 | scap_val_11n_20[core] = scap_val + 15; | ||
2857 | } else { | ||
2858 | bcap_val_11n_20[core] = bcap_val + 14; | ||
2859 | scap_val_11n_20[core] = scap_val + 15; | ||
2860 | } | ||
2861 | lpf_ofdm_20mhz[core] = 4; | ||
2862 | |||
2863 | if (ghz2) { | ||
2864 | bcap_val_11n_40[core] = bcap_val - 7; | ||
2865 | scap_val_11n_40[core] = scap_val - 5; | ||
2866 | } else { | ||
2867 | bcap_val_11n_40[core] = bcap_val + 2; | ||
2868 | scap_val_11n_40[core] = scap_val + 4; | ||
2869 | } | ||
2870 | lpf_ofdm_40mhz[core] = 4; | ||
2871 | } | ||
2872 | |||
2873 | rccal_ovrd = true; | ||
2874 | break; | ||
2875 | case 14: | ||
2876 | for (core = 0; core < 2; core++) { | ||
2877 | bcap_val_11b[core] = bcap_val; | ||
2878 | scap_val_11b[core] = scap_val; | ||
2879 | lpf_11b[core] = 1; | ||
2880 | } | ||
2881 | |||
2882 | bcap_val_11n_20[0] = bcap_val + 20; | ||
2883 | scap_val_11n_20[0] = scap_val + 20; | ||
2884 | lpf_ofdm_20mhz[0] = 3; | ||
2885 | |||
2886 | bcap_val_11n_20[1] = bcap_val + 16; | ||
2887 | scap_val_11n_20[1] = scap_val + 16; | ||
2888 | lpf_ofdm_20mhz[1] = 3; | ||
2889 | |||
2890 | bcap_val_11n_40[0] = bcap_val + 20; | ||
2891 | scap_val_11n_40[0] = scap_val + 20; | ||
2892 | lpf_ofdm_40mhz[0] = 4; | ||
2893 | |||
2894 | bcap_val_11n_40[1] = bcap_val + 10; | ||
2895 | scap_val_11n_40[1] = scap_val + 10; | ||
2896 | lpf_ofdm_40mhz[1] = 4; | ||
2897 | |||
2898 | rccal_ovrd = true; | ||
2899 | break; | ||
2802 | } | 2900 | } |
2803 | } else { | 2901 | } else { |
2804 | if (phy->radio_rev == 5) { | 2902 | if (phy->radio_rev == 5) { |
2805 | lpf_20 = 1; | 2903 | for (core = 0; core < 2; core++) { |
2806 | lpf_40 = 3; | 2904 | lpf_ofdm_20mhz[core] = 1; |
2807 | bcap_val = b43_radio_read(dev, 0x16b); | 2905 | lpf_ofdm_40mhz[core] = 3; |
2808 | scap_val = b43_radio_read(dev, 0x16a); | 2906 | scap_val_11b[core] = scap_val; |
2809 | scap_val_11b = scap_val; | 2907 | bcap_val_11b[core] = bcap_val; |
2810 | bcap_val_11b = bcap_val; | 2908 | scap_val_11n_20[core] = 0x11; |
2811 | scap_val_11n_20 = 0x11; | 2909 | scap_val_11n_40[core] = 0x11; |
2812 | scap_val_11n_40 = 0x11; | 2910 | bcap_val_11n_20[core] = 0x13; |
2813 | bcap_val_11n_20 = 0x13; | 2911 | bcap_val_11n_40[core] = 0x13; |
2814 | bcap_val_11n_40 = 0x13; | 2912 | } |
2913 | |||
2815 | rccal_ovrd = true; | 2914 | rccal_ovrd = true; |
2816 | } | 2915 | } |
2817 | } | 2916 | } |
2818 | if (rccal_ovrd) { | 2917 | if (rccal_ovrd) { |
2819 | rx2tx_lut_20_11b = (bcap_val_11b << 8) | | 2918 | u16 rx2tx_lut_20_11b[2], rx2tx_lut_20_11n[2], rx2tx_lut_40_11n[2]; |
2820 | (scap_val_11b << 3) | | 2919 | u8 rx2tx_lut_extra = 1; |
2821 | lpf_11b; | 2920 | |
2822 | rx2tx_lut_20_11n = (bcap_val_11n_20 << 8) | | 2921 | for (core = 0; core < 2; core++) { |
2823 | (scap_val_11n_20 << 3) | | 2922 | bcap_val_11b[core] = clamp_val(bcap_val_11b[core], 0, 0x1f); |
2824 | lpf_20; | 2923 | scap_val_11b[core] = clamp_val(scap_val_11b[core], 0, 0x1f); |
2825 | rx2tx_lut_40_11n = (bcap_val_11n_40 << 8) | | 2924 | bcap_val_11n_20[core] = clamp_val(bcap_val_11n_20[core], 0, 0x1f); |
2826 | (scap_val_11n_40 << 3) | | 2925 | scap_val_11n_20[core] = clamp_val(scap_val_11n_20[core], 0, 0x1f); |
2827 | lpf_40; | 2926 | bcap_val_11n_40[core] = clamp_val(bcap_val_11n_40[core], 0, 0x1f); |
2927 | scap_val_11n_40[core] = clamp_val(scap_val_11n_40[core], 0, 0x1f); | ||
2928 | |||
2929 | rx2tx_lut_20_11b[core] = (rx2tx_lut_extra << 13) | | ||
2930 | (bcap_val_11b[core] << 8) | | ||
2931 | (scap_val_11b[core] << 3) | | ||
2932 | lpf_11b[core]; | ||
2933 | rx2tx_lut_20_11n[core] = (rx2tx_lut_extra << 13) | | ||
2934 | (bcap_val_11n_20[core] << 8) | | ||
2935 | (scap_val_11n_20[core] << 3) | | ||
2936 | lpf_ofdm_20mhz[core]; | ||
2937 | rx2tx_lut_40_11n[core] = (rx2tx_lut_extra << 13) | | ||
2938 | (bcap_val_11n_40[core] << 8) | | ||
2939 | (scap_val_11n_40[core] << 3) | | ||
2940 | lpf_ofdm_40mhz[core]; | ||
2941 | } | ||
2942 | |||
2828 | for (core = 0; core < 2; core++) { | 2943 | for (core = 0; core < 2; core++) { |
2829 | b43_ntab_write(dev, B43_NTAB16(7, 0x152 + core * 16), | 2944 | b43_ntab_write(dev, B43_NTAB16(7, 0x152 + core * 16), |
2830 | rx2tx_lut_20_11b); | 2945 | rx2tx_lut_20_11b[core]); |
2831 | b43_ntab_write(dev, B43_NTAB16(7, 0x153 + core * 16), | 2946 | b43_ntab_write(dev, B43_NTAB16(7, 0x153 + core * 16), |
2832 | rx2tx_lut_20_11n); | 2947 | rx2tx_lut_20_11n[core]); |
2833 | b43_ntab_write(dev, B43_NTAB16(7, 0x154 + core * 16), | 2948 | b43_ntab_write(dev, B43_NTAB16(7, 0x154 + core * 16), |
2834 | rx2tx_lut_20_11n); | 2949 | rx2tx_lut_20_11n[core]); |
2835 | b43_ntab_write(dev, B43_NTAB16(7, 0x155 + core * 16), | 2950 | b43_ntab_write(dev, B43_NTAB16(7, 0x155 + core * 16), |
2836 | rx2tx_lut_40_11n); | 2951 | rx2tx_lut_40_11n[core]); |
2837 | b43_ntab_write(dev, B43_NTAB16(7, 0x156 + core * 16), | 2952 | b43_ntab_write(dev, B43_NTAB16(7, 0x156 + core * 16), |
2838 | rx2tx_lut_40_11n); | 2953 | rx2tx_lut_40_11n[core]); |
2839 | b43_ntab_write(dev, B43_NTAB16(7, 0x157 + core * 16), | 2954 | b43_ntab_write(dev, B43_NTAB16(7, 0x157 + core * 16), |
2840 | rx2tx_lut_40_11n); | 2955 | rx2tx_lut_40_11n[core]); |
2841 | b43_ntab_write(dev, B43_NTAB16(7, 0x158 + core * 16), | 2956 | b43_ntab_write(dev, B43_NTAB16(7, 0x158 + core * 16), |
2842 | rx2tx_lut_40_11n); | 2957 | rx2tx_lut_40_11n[core]); |
2843 | b43_ntab_write(dev, B43_NTAB16(7, 0x159 + core * 16), | 2958 | b43_ntab_write(dev, B43_NTAB16(7, 0x159 + core * 16), |
2844 | rx2tx_lut_40_11n); | 2959 | rx2tx_lut_40_11n[core]); |
2845 | } | 2960 | } |
2846 | b43_nphy_rf_ctl_override_rev7(dev, 16, 1, 3, false, 2); | ||
2847 | } | 2961 | } |
2962 | |||
2848 | b43_phy_write(dev, 0x32F, 0x3); | 2963 | b43_phy_write(dev, 0x32F, 0x3); |
2964 | |||
2849 | if (phy->radio_rev == 4 || phy->radio_rev == 6) | 2965 | if (phy->radio_rev == 4 || phy->radio_rev == 6) |
2850 | b43_nphy_rf_ctl_override_rev7(dev, 4, 1, 3, false, 0); | 2966 | b43_nphy_rf_ctl_override_rev7(dev, 4, 1, 3, false, 0); |
2851 | 2967 | ||
@@ -2893,7 +3009,8 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) | |||
2893 | 0x7f); | 3009 | 0x7f); |
2894 | } | 3010 | } |
2895 | } | 3011 | } |
2896 | if (phy->radio_rev == 3) { | 3012 | switch (phy->radio_rev) { |
3013 | case 3: | ||
2897 | for (core = 0; core < 2; core++) { | 3014 | for (core = 0; core < 2; core++) { |
2898 | if (core == 0) { | 3015 | if (core == 0) { |
2899 | b43_radio_write(dev, 0x64, | 3016 | b43_radio_write(dev, 0x64, |
@@ -2919,7 +3036,9 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) | |||
2919 | 0x3E); | 3036 | 0x3E); |
2920 | } | 3037 | } |
2921 | } | 3038 | } |
2922 | } else if (phy->radio_rev == 7 || phy->radio_rev == 8) { | 3039 | break; |
3040 | case 7: | ||
3041 | case 8: | ||
2923 | if (!b43_is_40mhz(dev)) { | 3042 | if (!b43_is_40mhz(dev)) { |
2924 | b43_radio_write(dev, 0x5F, 0x14); | 3043 | b43_radio_write(dev, 0x5F, 0x14); |
2925 | b43_radio_write(dev, 0xE8, 0x12); | 3044 | b43_radio_write(dev, 0xE8, 0x12); |
@@ -2927,6 +3046,21 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) | |||
2927 | b43_radio_write(dev, 0x5F, 0x16); | 3046 | b43_radio_write(dev, 0x5F, 0x16); |
2928 | b43_radio_write(dev, 0xE8, 0x16); | 3047 | b43_radio_write(dev, 0xE8, 0x16); |
2929 | } | 3048 | } |
3049 | break; | ||
3050 | case 14: | ||
3051 | for (core = 0; core < 2; core++) { | ||
3052 | int o = core ? 0x85 : 0; | ||
3053 | |||
3054 | b43_radio_write(dev, o + R2057_IPA2G_CASCONV_CORE0, 0x13); | ||
3055 | b43_radio_write(dev, o + R2057_TXMIX2G_TUNE_BOOST_PU_CORE0, 0x21); | ||
3056 | b43_radio_write(dev, o + R2057_IPA2G_BIAS_FILTER_CORE0, 0xff); | ||
3057 | b43_radio_write(dev, o + R2057_PAD2G_IDACS_CORE0, 0x88); | ||
3058 | b43_radio_write(dev, o + R2057_PAD2G_TUNE_PUS_CORE0, 0x23); | ||
3059 | b43_radio_write(dev, o + R2057_IPA2G_IMAIN_CORE0, 0x16); | ||
3060 | b43_radio_write(dev, o + R2057_PAD_BIAS_FILTER_BWS_CORE0, 0x3e); | ||
3061 | b43_radio_write(dev, o + R2057_BACKUP1_CORE0, 0x10); | ||
3062 | } | ||
3063 | break; | ||
2930 | } | 3064 | } |
2931 | } else { | 3065 | } else { |
2932 | u16 freq = phy->chandef->chan->center_freq; | 3066 | u16 freq = phy->chandef->chan->center_freq; |
@@ -2974,8 +3108,8 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) | |||
2974 | b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x1); | 3108 | b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x1); |
2975 | b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x1); | 3109 | b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x1); |
2976 | b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x1); | 3110 | b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x1); |
2977 | b43_ntab_write(dev, B43_NTAB16(8, 0x05), 0x20); | 3111 | b43_ntab_write(dev, B43_NTAB16(8, 0x05), 0); |
2978 | b43_ntab_write(dev, B43_NTAB16(8, 0x15), 0x20); | 3112 | b43_ntab_write(dev, B43_NTAB16(8, 0x15), 0); |
2979 | 3113 | ||
2980 | b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x4); | 3114 | b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x4); |
2981 | b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x4); | 3115 | b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x4); |
@@ -2986,20 +3120,20 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) | |||
2986 | b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, 0x2); | 3120 | b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, 0x2); |
2987 | 3121 | ||
2988 | b43_ntab_write(dev, B43_NTAB32(16, 0x100), 20); | 3122 | b43_ntab_write(dev, B43_NTAB32(16, 0x100), 20); |
2989 | b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x138), 2, ntab7_138_146); | 3123 | b43_ntab_write_bulk(dev, B43_NTAB8(7, 0x138), 2, ntab7_138_146); |
2990 | b43_ntab_write(dev, B43_NTAB16(7, 0x141), 0x77); | 3124 | b43_ntab_write(dev, B43_NTAB16(7, 0x141), 0x77); |
2991 | b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x133), 3, ntab7_133); | 3125 | b43_ntab_write_bulk(dev, B43_NTAB8(7, 0x133), 3, ntab7_133); |
2992 | b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x146), 2, ntab7_138_146); | 3126 | b43_ntab_write_bulk(dev, B43_NTAB8(7, 0x146), 2, ntab7_138_146); |
2993 | b43_ntab_write(dev, B43_NTAB16(7, 0x123), 0x77); | 3127 | b43_ntab_write(dev, B43_NTAB16(7, 0x123), 0x77); |
2994 | b43_ntab_write(dev, B43_NTAB16(7, 0x12A), 0x77); | 3128 | b43_ntab_write(dev, B43_NTAB16(7, 0x12A), 0x77); |
2995 | 3129 | ||
2996 | if (!b43_is_40mhz(dev)) { | 3130 | b43_ntab_read_bulk(dev, B43_NTAB32(16, 0x02), 1, noise_tbl); |
2997 | b43_ntab_write(dev, B43_NTAB32(16, 0x03), 0x18D); | 3131 | noise_tbl[1] = b43_is_40mhz(dev) ? 0x14D : 0x18D; |
2998 | b43_ntab_write(dev, B43_NTAB32(16, 0x7F), 0x18D); | 3132 | b43_ntab_write_bulk(dev, B43_NTAB32(16, 0x02), 2, noise_tbl); |
2999 | } else { | 3133 | |
3000 | b43_ntab_write(dev, B43_NTAB32(16, 0x03), 0x14D); | 3134 | b43_ntab_read_bulk(dev, B43_NTAB32(16, 0x7E), 1, noise_tbl); |
3001 | b43_ntab_write(dev, B43_NTAB32(16, 0x7F), 0x14D); | 3135 | noise_tbl[1] = b43_is_40mhz(dev) ? 0x14D : 0x18D; |
3002 | } | 3136 | b43_ntab_write_bulk(dev, B43_NTAB32(16, 0x7E), 2, noise_tbl); |
3003 | 3137 | ||
3004 | b43_nphy_gain_ctl_workarounds(dev); | 3138 | b43_nphy_gain_ctl_workarounds(dev); |
3005 | 3139 | ||
@@ -3410,7 +3544,7 @@ static void b43_nphy_stop_playback(struct b43_wldev *dev) | |||
3410 | nphy->bb_mult_save = 0; | 3544 | nphy->bb_mult_save = 0; |
3411 | } | 3545 | } |
3412 | 3546 | ||
3413 | if (phy->rev >= 7) { | 3547 | if (phy->rev >= 7 && nphy->lpf_bw_overrode_for_sample_play) { |
3414 | if (phy->rev >= 19) | 3548 | if (phy->rev >= 19) |
3415 | b43_nphy_rf_ctl_override_rev19(dev, 0x80, 0, 0, true, | 3549 | b43_nphy_rf_ctl_override_rev19(dev, 0x80, 0, 0, true, |
3416 | 1); | 3550 | 1); |
@@ -3823,15 +3957,16 @@ static void b43_nphy_tx_power_ctl_idle_tssi(struct b43_wldev *dev) | |||
3823 | u32 tmp; | 3957 | u32 tmp; |
3824 | s32 rssi[4] = { }; | 3958 | s32 rssi[4] = { }; |
3825 | 3959 | ||
3826 | /* TODO: check if we can transmit */ | 3960 | if (phy->chandef->chan->flags & IEEE80211_CHAN_NO_IR) |
3961 | return; | ||
3827 | 3962 | ||
3828 | if (b43_nphy_ipa(dev)) | 3963 | if (b43_nphy_ipa(dev)) |
3829 | b43_nphy_ipa_internal_tssi_setup(dev); | 3964 | b43_nphy_ipa_internal_tssi_setup(dev); |
3830 | 3965 | ||
3831 | if (phy->rev >= 19) | 3966 | if (phy->rev >= 19) |
3832 | b43_nphy_rf_ctl_override_rev19(dev, 0x2000, 0, 3, false, 0); | 3967 | b43_nphy_rf_ctl_override_rev19(dev, 0x1000, 0, 3, false, 0); |
3833 | else if (phy->rev >= 7) | 3968 | else if (phy->rev >= 7) |
3834 | b43_nphy_rf_ctl_override_rev7(dev, 0x2000, 0, 3, false, 0); | 3969 | b43_nphy_rf_ctl_override_rev7(dev, 0x1000, 0, 3, false, 0); |
3835 | else if (phy->rev >= 3) | 3970 | else if (phy->rev >= 3) |
3836 | b43_nphy_rf_ctl_override(dev, 0x2000, 0, 3, false); | 3971 | b43_nphy_rf_ctl_override(dev, 0x2000, 0, 3, false); |
3837 | 3972 | ||
@@ -3844,9 +3979,9 @@ static void b43_nphy_tx_power_ctl_idle_tssi(struct b43_wldev *dev) | |||
3844 | b43_nphy_rssi_select(dev, 0, N_RSSI_W1); | 3979 | b43_nphy_rssi_select(dev, 0, N_RSSI_W1); |
3845 | 3980 | ||
3846 | if (phy->rev >= 19) | 3981 | if (phy->rev >= 19) |
3847 | b43_nphy_rf_ctl_override_rev19(dev, 0x2000, 0, 3, true, 0); | 3982 | b43_nphy_rf_ctl_override_rev19(dev, 0x1000, 0, 3, true, 0); |
3848 | else if (phy->rev >= 7) | 3983 | else if (phy->rev >= 7) |
3849 | b43_nphy_rf_ctl_override_rev7(dev, 0x2000, 0, 3, true, 0); | 3984 | b43_nphy_rf_ctl_override_rev7(dev, 0x1000, 0, 3, true, 0); |
3850 | else if (phy->rev >= 3) | 3985 | else if (phy->rev >= 3) |
3851 | b43_nphy_rf_ctl_override(dev, 0x2000, 0, 3, true); | 3986 | b43_nphy_rf_ctl_override(dev, 0x2000, 0, 3, true); |
3852 | 3987 | ||
@@ -4809,41 +4944,61 @@ static void b43_nphy_update_tx_cal_ladder(struct b43_wldev *dev, u16 core) | |||
4809 | } | 4944 | } |
4810 | } | 4945 | } |
4811 | 4946 | ||
4947 | static void b43_nphy_pa_set_tx_dig_filter(struct b43_wldev *dev, u16 offset, | ||
4948 | const s16 *filter) | ||
4949 | { | ||
4950 | int i; | ||
4951 | |||
4952 | offset = B43_PHY_N(offset); | ||
4953 | |||
4954 | for (i = 0; i < 15; i++, offset++) | ||
4955 | b43_phy_write(dev, offset, filter[i]); | ||
4956 | } | ||
4957 | |||
4812 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ExtPaSetTxDigiFilts */ | 4958 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ExtPaSetTxDigiFilts */ |
4813 | static void b43_nphy_ext_pa_set_tx_dig_filters(struct b43_wldev *dev) | 4959 | static void b43_nphy_ext_pa_set_tx_dig_filters(struct b43_wldev *dev) |
4814 | { | 4960 | { |
4815 | int i; | 4961 | b43_nphy_pa_set_tx_dig_filter(dev, 0x2C5, |
4816 | for (i = 0; i < 15; i++) | 4962 | tbl_tx_filter_coef_rev4[2]); |
4817 | b43_phy_write(dev, B43_PHY_N(0x2C5 + i), | ||
4818 | tbl_tx_filter_coef_rev4[2][i]); | ||
4819 | } | 4963 | } |
4820 | 4964 | ||
4821 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IpaSetTxDigiFilts */ | 4965 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IpaSetTxDigiFilts */ |
4822 | static void b43_nphy_int_pa_set_tx_dig_filters(struct b43_wldev *dev) | 4966 | static void b43_nphy_int_pa_set_tx_dig_filters(struct b43_wldev *dev) |
4823 | { | 4967 | { |
4824 | int i, j; | ||
4825 | /* B43_NPHY_TXF_20CO_S0A1, B43_NPHY_TXF_40CO_S0A1, unknown */ | 4968 | /* B43_NPHY_TXF_20CO_S0A1, B43_NPHY_TXF_40CO_S0A1, unknown */ |
4826 | static const u16 offset[] = { 0x186, 0x195, 0x2C5 }; | 4969 | static const u16 offset[] = { 0x186, 0x195, 0x2C5 }; |
4970 | static const s16 dig_filter_phy_rev16[] = { | ||
4971 | -375, 136, -407, 208, -1527, | ||
4972 | 956, 93, 186, 93, 230, | ||
4973 | -44, 230, 201, -191, 201, | ||
4974 | }; | ||
4975 | int i; | ||
4827 | 4976 | ||
4828 | for (i = 0; i < 3; i++) | 4977 | for (i = 0; i < 3; i++) |
4829 | for (j = 0; j < 15; j++) | 4978 | b43_nphy_pa_set_tx_dig_filter(dev, offset[i], |
4830 | b43_phy_write(dev, B43_PHY_N(offset[i] + j), | 4979 | tbl_tx_filter_coef_rev4[i]); |
4831 | tbl_tx_filter_coef_rev4[i][j]); | 4980 | |
4981 | /* Verified with BCM43227 and BCM43228 */ | ||
4982 | if (dev->phy.rev == 16) | ||
4983 | b43_nphy_pa_set_tx_dig_filter(dev, 0x186, dig_filter_phy_rev16); | ||
4984 | |||
4985 | if (dev->dev->chip_id == BCMA_CHIP_ID_BCM43217) { | ||
4986 | b43_nphy_pa_set_tx_dig_filter(dev, 0x186, dig_filter_phy_rev16); | ||
4987 | b43_nphy_pa_set_tx_dig_filter(dev, 0x195, | ||
4988 | tbl_tx_filter_coef_rev4[1]); | ||
4989 | } | ||
4832 | 4990 | ||
4833 | if (b43_is_40mhz(dev)) { | 4991 | if (b43_is_40mhz(dev)) { |
4834 | for (j = 0; j < 15; j++) | 4992 | b43_nphy_pa_set_tx_dig_filter(dev, 0x186, |
4835 | b43_phy_write(dev, B43_PHY_N(offset[0] + j), | 4993 | tbl_tx_filter_coef_rev4[3]); |
4836 | tbl_tx_filter_coef_rev4[3][j]); | 4994 | } else { |
4837 | } else if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { | 4995 | if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) |
4838 | for (j = 0; j < 15; j++) | 4996 | b43_nphy_pa_set_tx_dig_filter(dev, 0x186, |
4839 | b43_phy_write(dev, B43_PHY_N(offset[0] + j), | 4997 | tbl_tx_filter_coef_rev4[5]); |
4840 | tbl_tx_filter_coef_rev4[5][j]); | 4998 | if (dev->phy.channel == 14) |
4841 | } | 4999 | b43_nphy_pa_set_tx_dig_filter(dev, 0x186, |
4842 | 5000 | tbl_tx_filter_coef_rev4[6]); | |
4843 | if (dev->phy.channel == 14) | 5001 | } |
4844 | for (j = 0; j < 15; j++) | ||
4845 | b43_phy_write(dev, B43_PHY_N(offset[0] + j), | ||
4846 | tbl_tx_filter_coef_rev4[6][j]); | ||
4847 | } | 5002 | } |
4848 | 5003 | ||
4849 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetTxGain */ | 5004 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetTxGain */ |
diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c index ab27c2de2f43..4b5885077b01 100644 --- a/drivers/net/wireless/b43/tables_nphy.c +++ b/drivers/net/wireless/b43/tables_nphy.c | |||
@@ -3109,11 +3109,11 @@ static const struct nphy_rf_control_override_rev7 | |||
3109 | { 0x0010, 0x07A, 0x07D, 0x0010, 4 }, | 3109 | { 0x0010, 0x07A, 0x07D, 0x0010, 4 }, |
3110 | { 0x0020, 0x07A, 0x07D, 0x0020, 5 }, | 3110 | { 0x0020, 0x07A, 0x07D, 0x0020, 5 }, |
3111 | { 0x0040, 0x07A, 0x07D, 0x0040, 6 }, | 3111 | { 0x0040, 0x07A, 0x07D, 0x0040, 6 }, |
3112 | { 0x0080, 0x0F8, 0x0FA, 0x0080, 7 }, | 3112 | { 0x0080, 0x07A, 0x07D, 0x0080, 7 }, |
3113 | { 0x0400, 0x0F8, 0x0FA, 0x0070, 4 }, | 3113 | { 0x0400, 0x0F8, 0x0FA, 0x0070, 4 }, |
3114 | { 0x0800, 0x07B, 0x07E, 0xFFFF, 0 }, | 3114 | { 0x0800, 0x07B, 0x07E, 0xFFFF, 0 }, |
3115 | { 0x1000, 0x07C, 0x07F, 0xFFFF, 0 }, | 3115 | { 0x1000, 0x07C, 0x07F, 0xFFFF, 0 }, |
3116 | { 0x6000, 0x348, 0x349, 0xFFFF, 0 }, | 3116 | { 0x6000, 0x348, 0x349, 0x00FF, 0 }, |
3117 | { 0x2000, 0x348, 0x349, 0x000F, 0 }, | 3117 | { 0x2000, 0x348, 0x349, 0x000F, 0 }, |
3118 | }; | 3118 | }; |
3119 | 3119 | ||
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index 6e6ef3fc2247..426dc13c44cd 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c | |||
@@ -80,9 +80,10 @@ static int b43_plcp_get_bitrate_idx_cck(struct b43_plcp_hdr6 *plcp) | |||
80 | } | 80 | } |
81 | 81 | ||
82 | /* Extract the bitrate index out of an OFDM PLCP header. */ | 82 | /* Extract the bitrate index out of an OFDM PLCP header. */ |
83 | static int b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool aphy) | 83 | static int b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool ghz5) |
84 | { | 84 | { |
85 | int base = aphy ? 0 : 4; | 85 | /* For 2 GHz band first OFDM rate is at index 4, see main.c */ |
86 | int base = ghz5 ? 0 : 4; | ||
86 | 87 | ||
87 | switch (plcp->raw[0] & 0xF) { | 88 | switch (plcp->raw[0] & 0xF) { |
88 | case 0xB: | 89 | case 0xB: |
@@ -767,7 +768,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) | |||
767 | 768 | ||
768 | if (phystat0 & B43_RX_PHYST0_OFDM) | 769 | if (phystat0 & B43_RX_PHYST0_OFDM) |
769 | rate_idx = b43_plcp_get_bitrate_idx_ofdm(plcp, | 770 | rate_idx = b43_plcp_get_bitrate_idx_ofdm(plcp, |
770 | phytype == B43_PHYTYPE_A); | 771 | !!(chanstat & B43_RX_CHAN_5GHZ)); |
771 | else | 772 | else |
772 | rate_idx = b43_plcp_get_bitrate_idx_cck(plcp); | 773 | rate_idx = b43_plcp_get_bitrate_idx_cck(plcp); |
773 | if (unlikely(rate_idx == -1)) { | 774 | if (unlikely(rate_idx == -1)) { |
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index 7fd50428b934..6451d2b6abcf 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig | |||
@@ -20,16 +20,17 @@ config IWLWIFI | |||
20 | Intel 2000 Series Wi-Fi Adapters | 20 | Intel 2000 Series Wi-Fi Adapters |
21 | Intel 7260 Wi-Fi Adapter | 21 | Intel 7260 Wi-Fi Adapter |
22 | Intel 3160 Wi-Fi Adapter | 22 | Intel 3160 Wi-Fi Adapter |
23 | Intel 7265 Wi-Fi Adapter | ||
23 | 24 | ||
24 | 25 | ||
25 | This driver uses the kernel's mac80211 subsystem. | 26 | This driver uses the kernel's mac80211 subsystem. |
26 | 27 | ||
27 | In order to use this driver, you will need a microcode (uCode) | 28 | In order to use this driver, you will need a firmware |
28 | image for it. You can obtain the microcode from: | 29 | image for it. You can obtain the microcode from: |
29 | 30 | ||
30 | <http://intellinuxwireless.org/>. | 31 | <http://wireless.kernel.org/en/users/Drivers/iwlwifi>. |
31 | 32 | ||
32 | The microcode is typically installed in /lib/firmware. You can | 33 | The firmware is typically installed in /lib/firmware. You can |
33 | look in the hotplug script /etc/hotplug/firmware.agent to | 34 | look in the hotplug script /etc/hotplug/firmware.agent to |
34 | determine which directory FIRMWARE_DIR is set to when the script | 35 | determine which directory FIRMWARE_DIR is set to when the script |
35 | runs. | 36 | runs. |
@@ -39,9 +40,10 @@ config IWLWIFI | |||
39 | say M here and read <file:Documentation/kbuild/modules.txt>. The | 40 | say M here and read <file:Documentation/kbuild/modules.txt>. The |
40 | module will be called iwlwifi. | 41 | module will be called iwlwifi. |
41 | 42 | ||
43 | if IWLWIFI | ||
44 | |||
42 | config IWLWIFI_LEDS | 45 | config IWLWIFI_LEDS |
43 | bool | 46 | bool |
44 | depends on IWLWIFI | ||
45 | depends on LEDS_CLASS=y || LEDS_CLASS=IWLWIFI | 47 | depends on LEDS_CLASS=y || LEDS_CLASS=IWLWIFI |
46 | select LEDS_TRIGGERS | 48 | select LEDS_TRIGGERS |
47 | select MAC80211_LEDS | 49 | select MAC80211_LEDS |
@@ -49,7 +51,7 @@ config IWLWIFI_LEDS | |||
49 | 51 | ||
50 | config IWLDVM | 52 | config IWLDVM |
51 | tristate "Intel Wireless WiFi DVM Firmware support" | 53 | tristate "Intel Wireless WiFi DVM Firmware support" |
52 | depends on IWLWIFI | 54 | depends on m |
53 | default IWLWIFI | 55 | default IWLWIFI |
54 | help | 56 | help |
55 | This is the driver that supports the DVM firmware which is | 57 | This is the driver that supports the DVM firmware which is |
@@ -58,7 +60,7 @@ config IWLDVM | |||
58 | 60 | ||
59 | config IWLMVM | 61 | config IWLMVM |
60 | tristate "Intel Wireless WiFi MVM Firmware support" | 62 | tristate "Intel Wireless WiFi MVM Firmware support" |
61 | depends on IWLWIFI | 63 | depends on m |
62 | help | 64 | help |
63 | This is the driver that supports the MVM firmware which is | 65 | This is the driver that supports the MVM firmware which is |
64 | currently only available for 7260 and 3160 devices. | 66 | currently only available for 7260 and 3160 devices. |
@@ -70,7 +72,7 @@ config IWLWIFI_OPMODE_MODULAR | |||
70 | default y if IWLMVM=m | 72 | default y if IWLMVM=m |
71 | 73 | ||
72 | comment "WARNING: iwlwifi is useless without IWLDVM or IWLMVM" | 74 | comment "WARNING: iwlwifi is useless without IWLDVM or IWLMVM" |
73 | depends on IWLWIFI && IWLDVM=n && IWLMVM=n | 75 | depends on IWLDVM=n && IWLMVM=n |
74 | 76 | ||
75 | config IWLWIFI_BCAST_FILTERING | 77 | config IWLWIFI_BCAST_FILTERING |
76 | bool "Enable broadcast filtering" | 78 | bool "Enable broadcast filtering" |
@@ -86,11 +88,9 @@ config IWLWIFI_BCAST_FILTERING | |||
86 | expect incoming broadcasts for their normal operations. | 88 | expect incoming broadcasts for their normal operations. |
87 | 89 | ||
88 | menu "Debugging Options" | 90 | menu "Debugging Options" |
89 | depends on IWLWIFI | ||
90 | 91 | ||
91 | config IWLWIFI_DEBUG | 92 | config IWLWIFI_DEBUG |
92 | bool "Enable full debugging output in the iwlwifi driver" | 93 | bool "Enable full debugging output in the iwlwifi driver" |
93 | depends on IWLWIFI | ||
94 | ---help--- | 94 | ---help--- |
95 | This option will enable debug tracing output for the iwlwifi drivers | 95 | This option will enable debug tracing output for the iwlwifi drivers |
96 | 96 | ||
@@ -115,7 +115,7 @@ config IWLWIFI_DEBUG | |||
115 | 115 | ||
116 | config IWLWIFI_DEBUGFS | 116 | config IWLWIFI_DEBUGFS |
117 | bool "iwlwifi debugfs support" | 117 | bool "iwlwifi debugfs support" |
118 | depends on IWLWIFI && MAC80211_DEBUGFS | 118 | depends on MAC80211_DEBUGFS |
119 | ---help--- | 119 | ---help--- |
120 | Enable creation of debugfs files for the iwlwifi drivers. This | 120 | Enable creation of debugfs files for the iwlwifi drivers. This |
121 | is a low-impact option that allows getting insight into the | 121 | is a low-impact option that allows getting insight into the |
@@ -123,13 +123,12 @@ config IWLWIFI_DEBUGFS | |||
123 | 123 | ||
124 | config IWLWIFI_DEBUG_EXPERIMENTAL_UCODE | 124 | config IWLWIFI_DEBUG_EXPERIMENTAL_UCODE |
125 | bool "Experimental uCode support" | 125 | bool "Experimental uCode support" |
126 | depends on IWLWIFI && IWLWIFI_DEBUG | 126 | depends on IWLWIFI_DEBUG |
127 | ---help--- | 127 | ---help--- |
128 | Enable use of experimental ucode for testing and debugging. | 128 | Enable use of experimental ucode for testing and debugging. |
129 | 129 | ||
130 | config IWLWIFI_DEVICE_TRACING | 130 | config IWLWIFI_DEVICE_TRACING |
131 | bool "iwlwifi device access tracing" | 131 | bool "iwlwifi device access tracing" |
132 | depends on IWLWIFI | ||
133 | depends on EVENT_TRACING | 132 | depends on EVENT_TRACING |
134 | help | 133 | help |
135 | Say Y here to trace all commands, including TX frames and IO | 134 | Say Y here to trace all commands, including TX frames and IO |
@@ -145,3 +144,5 @@ config IWLWIFI_DEVICE_TRACING | |||
145 | If unsure, say Y so we can help you better when problems | 144 | If unsure, say Y so we can help you better when problems |
146 | occur. | 145 | occur. |
147 | endmenu | 146 | endmenu |
147 | |||
148 | endif | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-8000.c b/drivers/net/wireless/iwlwifi/iwl-8000.c index 51486cc9d943..44b19e015102 100644 --- a/drivers/net/wireless/iwlwifi/iwl-8000.c +++ b/drivers/net/wireless/iwlwifi/iwl-8000.c | |||
@@ -85,6 +85,9 @@ | |||
85 | #define NVM_HW_SECTION_NUM_FAMILY_8000 10 | 85 | #define NVM_HW_SECTION_NUM_FAMILY_8000 10 |
86 | #define DEFAULT_NVM_FILE_FAMILY_8000 "iwl_nvm_8000.bin" | 86 | #define DEFAULT_NVM_FILE_FAMILY_8000 "iwl_nvm_8000.bin" |
87 | 87 | ||
88 | /* Max SDIO RX aggregation size of the ADDBA request/response */ | ||
89 | #define MAX_RX_AGG_SIZE_8260_SDIO 28 | ||
90 | |||
88 | static const struct iwl_base_params iwl8000_base_params = { | 91 | static const struct iwl_base_params iwl8000_base_params = { |
89 | .eeprom_size = OTP_LOW_IMAGE_SIZE_FAMILY_8000, | 92 | .eeprom_size = OTP_LOW_IMAGE_SIZE_FAMILY_8000, |
90 | .num_of_queues = IWLAGN_NUM_QUEUES, | 93 | .num_of_queues = IWLAGN_NUM_QUEUES, |
@@ -129,6 +132,7 @@ const struct iwl_cfg iwl8260_2ac_sdio_cfg = { | |||
129 | .nvm_ver = IWL8000_NVM_VERSION, | 132 | .nvm_ver = IWL8000_NVM_VERSION, |
130 | .nvm_calib_ver = IWL8000_TX_POWER_VERSION, | 133 | .nvm_calib_ver = IWL8000_TX_POWER_VERSION, |
131 | .default_nvm_file = DEFAULT_NVM_FILE_FAMILY_8000, | 134 | .default_nvm_file = DEFAULT_NVM_FILE_FAMILY_8000, |
135 | .max_rx_agg_size = MAX_RX_AGG_SIZE_8260_SDIO, | ||
132 | }; | 136 | }; |
133 | 137 | ||
134 | MODULE_FIRMWARE(IWL8000_MODULE_FIRMWARE(IWL8000_UCODE_API_OK)); | 138 | MODULE_FIRMWARE(IWL8000_MODULE_FIRMWARE(IWL8000_UCODE_API_OK)); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h index 034c2fc4b69f..8da596db9abe 100644 --- a/drivers/net/wireless/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/iwlwifi/iwl-config.h | |||
@@ -240,6 +240,7 @@ struct iwl_pwr_tx_backoff { | |||
240 | * @d0i3: device uses d0i3 instead of d3 | 240 | * @d0i3: device uses d0i3 instead of d3 |
241 | * @nvm_hw_section_num: the ID of the HW NVM section | 241 | * @nvm_hw_section_num: the ID of the HW NVM section |
242 | * @pwr_tx_backoffs: translation table between power limits and backoffs | 242 | * @pwr_tx_backoffs: translation table between power limits and backoffs |
243 | * @max_rx_agg_size: max RX aggregation size of the ADDBA request/response | ||
243 | * | 244 | * |
244 | * We enable the driver to be backward compatible wrt. hardware features. | 245 | * We enable the driver to be backward compatible wrt. hardware features. |
245 | * API differences in uCode shouldn't be handled here but through TLVs | 246 | * API differences in uCode shouldn't be handled here but through TLVs |
@@ -276,6 +277,7 @@ struct iwl_cfg { | |||
276 | const struct iwl_pwr_tx_backoff *pwr_tx_backoffs; | 277 | const struct iwl_pwr_tx_backoff *pwr_tx_backoffs; |
277 | bool no_power_up_nic_in_init; | 278 | bool no_power_up_nic_in_init; |
278 | const char *default_nvm_file; | 279 | const char *default_nvm_file; |
280 | unsigned int max_rx_agg_size; | ||
279 | }; | 281 | }; |
280 | 282 | ||
281 | /* | 283 | /* |
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h b/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h index c39a0b899e83..de5994a776c7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h | |||
@@ -70,21 +70,24 @@ | |||
70 | /** | 70 | /** |
71 | * enum iwl_fw_error_dump_type - types of data in the dump file | 71 | * enum iwl_fw_error_dump_type - types of data in the dump file |
72 | * @IWL_FW_ERROR_DUMP_SRAM: | 72 | * @IWL_FW_ERROR_DUMP_SRAM: |
73 | * @IWL_FW_ERROR_DUMP_REG: | 73 | * @IWL_FW_ERROR_DUMP_CSR: Control Status Registers - from offset 0 |
74 | * @IWL_FW_ERROR_DUMP_RXF: | 74 | * @IWL_FW_ERROR_DUMP_RXF: |
75 | * @IWL_FW_ERROR_DUMP_TXCMD: last TX command data, structured as | 75 | * @IWL_FW_ERROR_DUMP_TXCMD: last TX command data, structured as |
76 | * &struct iwl_fw_error_dump_txcmd packets | 76 | * &struct iwl_fw_error_dump_txcmd packets |
77 | * @IWL_FW_ERROR_DUMP_DEV_FW_INFO: struct %iwl_fw_error_dump_info | 77 | * @IWL_FW_ERROR_DUMP_DEV_FW_INFO: struct %iwl_fw_error_dump_info |
78 | * info on the device / firmware. | 78 | * info on the device / firmware. |
79 | * @IWL_FW_ERROR_DUMP_FW_MONITOR: firmware monitor | 79 | * @IWL_FW_ERROR_DUMP_FW_MONITOR: firmware monitor |
80 | * @IWL_FW_ERROR_DUMP_PRPH: range of periphery registers - there can be several | ||
81 | * sections like this in a single file. | ||
80 | */ | 82 | */ |
81 | enum iwl_fw_error_dump_type { | 83 | enum iwl_fw_error_dump_type { |
82 | IWL_FW_ERROR_DUMP_SRAM = 0, | 84 | IWL_FW_ERROR_DUMP_SRAM = 0, |
83 | IWL_FW_ERROR_DUMP_REG = 1, | 85 | IWL_FW_ERROR_DUMP_CSR = 1, |
84 | IWL_FW_ERROR_DUMP_RXF = 2, | 86 | IWL_FW_ERROR_DUMP_RXF = 2, |
85 | IWL_FW_ERROR_DUMP_TXCMD = 3, | 87 | IWL_FW_ERROR_DUMP_TXCMD = 3, |
86 | IWL_FW_ERROR_DUMP_DEV_FW_INFO = 4, | 88 | IWL_FW_ERROR_DUMP_DEV_FW_INFO = 4, |
87 | IWL_FW_ERROR_DUMP_FW_MONITOR = 5, | 89 | IWL_FW_ERROR_DUMP_FW_MONITOR = 5, |
90 | IWL_FW_ERROR_DUMP_PRPH = 6, | ||
88 | 91 | ||
89 | IWL_FW_ERROR_DUMP_MAX, | 92 | IWL_FW_ERROR_DUMP_MAX, |
90 | }; | 93 | }; |
@@ -163,6 +166,16 @@ struct iwl_fw_error_dump_fw_mon { | |||
163 | } __packed; | 166 | } __packed; |
164 | 167 | ||
165 | /** | 168 | /** |
169 | * struct iwl_fw_error_dump_prph - periphery registers data | ||
170 | * @prph_start: address of the first register in this chunk | ||
171 | * @data: the content of the registers | ||
172 | */ | ||
173 | struct iwl_fw_error_dump_prph { | ||
174 | __le32 prph_start; | ||
175 | __le32 data[]; | ||
176 | }; | ||
177 | |||
178 | /** | ||
166 | * iwl_fw_error_next_data - advance fw error dump data pointer | 179 | * iwl_fw_error_next_data - advance fw error dump data pointer |
167 | * @data: previous data block | 180 | * @data: previous data block |
168 | * Returns: next data block | 181 | * Returns: next data block |
diff --git a/drivers/net/wireless/iwlwifi/iwl-modparams.h b/drivers/net/wireless/iwlwifi/iwl-modparams.h index f2d39cb011fc..71507cf490e6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-modparams.h +++ b/drivers/net/wireless/iwlwifi/iwl-modparams.h | |||
@@ -99,7 +99,7 @@ enum iwl_disable_11n { | |||
99 | * @wd_disable: disable stuck queue check, default = 1 | 99 | * @wd_disable: disable stuck queue check, default = 1 |
100 | * @bt_coex_active: enable bt coex, default = true | 100 | * @bt_coex_active: enable bt coex, default = true |
101 | * @led_mode: system default, default = 0 | 101 | * @led_mode: system default, default = 0 |
102 | * @power_save: disable power save, default = false | 102 | * @power_save: enable power save, default = false |
103 | * @power_level: power level, default = 1 | 103 | * @power_level: power level, default = 1 |
104 | * @debug_level: levels are IWL_DL_* | 104 | * @debug_level: levels are IWL_DL_* |
105 | * @ant_coupling: antenna coupling in dB, default = 0 | 105 | * @ant_coupling: antenna coupling in dB, default = 0 |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 34d49e171fb4..656371a668da 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
@@ -394,6 +394,11 @@ struct iwl_trans_config { | |||
394 | const char *const *command_names; | 394 | const char *const *command_names; |
395 | }; | 395 | }; |
396 | 396 | ||
397 | struct iwl_trans_dump_data { | ||
398 | u32 len; | ||
399 | u8 data[]; | ||
400 | }; | ||
401 | |||
397 | struct iwl_trans; | 402 | struct iwl_trans; |
398 | 403 | ||
399 | /** | 404 | /** |
@@ -461,10 +466,8 @@ struct iwl_trans; | |||
461 | * @unref: release a reference previously taken with @ref. Note that | 466 | * @unref: release a reference previously taken with @ref. Note that |
462 | * initially the reference count is 1, making an initial @unref | 467 | * initially the reference count is 1, making an initial @unref |
463 | * necessary to allow low power states. | 468 | * necessary to allow low power states. |
464 | * @dump_data: fill a data dump with debug data, maybe containing last | 469 | * @dump_data: return a vmalloc'ed buffer with debug data, maybe containing last |
465 | * TX'ed commands and similar. When called with a NULL buffer and | 470 | * TX'ed commands and similar. The buffer will be vfree'd by the caller. |
466 | * zero buffer length, provide only the (estimated) required buffer | ||
467 | * length. Return the used buffer length. | ||
468 | * Note that the transport must fill in the proper file headers. | 471 | * Note that the transport must fill in the proper file headers. |
469 | */ | 472 | */ |
470 | struct iwl_trans_ops { | 473 | struct iwl_trans_ops { |
@@ -518,7 +521,7 @@ struct iwl_trans_ops { | |||
518 | void (*unref)(struct iwl_trans *trans); | 521 | void (*unref)(struct iwl_trans *trans); |
519 | 522 | ||
520 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 523 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
521 | u32 (*dump_data)(struct iwl_trans *trans, void *buf, u32 buflen); | 524 | struct iwl_trans_dump_data *(*dump_data)(struct iwl_trans *trans); |
522 | #endif | 525 | #endif |
523 | }; | 526 | }; |
524 | 527 | ||
@@ -685,12 +688,12 @@ static inline void iwl_trans_unref(struct iwl_trans *trans) | |||
685 | } | 688 | } |
686 | 689 | ||
687 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 690 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
688 | static inline u32 iwl_trans_dump_data(struct iwl_trans *trans, | 691 | static inline struct iwl_trans_dump_data * |
689 | void *buf, u32 buflen) | 692 | iwl_trans_dump_data(struct iwl_trans *trans) |
690 | { | 693 | { |
691 | if (!trans->ops->dump_data) | 694 | if (!trans->ops->dump_data) |
692 | return 0; | 695 | return NULL; |
693 | return trans->ops->dump_data(trans, buf, buflen); | 696 | return trans->ops->dump_data(trans); |
694 | } | 697 | } |
695 | #endif | 698 | #endif |
696 | 699 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/coex.c b/drivers/net/wireless/iwlwifi/mvm/coex.c index 8110fe00bf55..2291bbcaaeab 100644 --- a/drivers/net/wireless/iwlwifi/mvm/coex.c +++ b/drivers/net/wireless/iwlwifi/mvm/coex.c | |||
@@ -72,16 +72,56 @@ | |||
72 | 72 | ||
73 | #define BT_ANTENNA_COUPLING_THRESHOLD (30) | 73 | #define BT_ANTENNA_COUPLING_THRESHOLD (30) |
74 | 74 | ||
75 | const u32 iwl_bt_ack_kill_msk[BT_KILL_MSK_MAX] = { | 75 | const u32 iwl_bt_ctl_kill_msk[BT_KILL_MSK_MAX] = { |
76 | [BT_KILL_MSK_DEFAULT] = 0xffff0000, | 76 | [BT_KILL_MSK_DEFAULT] = 0xfffffc00, |
77 | [BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff, | 77 | [BT_KILL_MSK_NEVER] = 0xffffffff, |
78 | [BT_KILL_MSK_REDUCED_TXPOW] = 0, | 78 | [BT_KILL_MSK_ALWAYS] = 0, |
79 | }; | 79 | }; |
80 | 80 | ||
81 | const u32 iwl_bt_cts_kill_msk[BT_KILL_MSK_MAX] = { | 81 | const u8 iwl_bt_cts_kill_msk[BT_MAX_AG][BT_COEX_MAX_LUT] = { |
82 | [BT_KILL_MSK_DEFAULT] = 0xffff0000, | 82 | { |
83 | [BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff, | 83 | BT_KILL_MSK_ALWAYS, |
84 | [BT_KILL_MSK_REDUCED_TXPOW] = 0, | 84 | BT_KILL_MSK_ALWAYS, |
85 | BT_KILL_MSK_ALWAYS, | ||
86 | }, | ||
87 | { | ||
88 | BT_KILL_MSK_NEVER, | ||
89 | BT_KILL_MSK_NEVER, | ||
90 | BT_KILL_MSK_NEVER, | ||
91 | }, | ||
92 | { | ||
93 | BT_KILL_MSK_NEVER, | ||
94 | BT_KILL_MSK_NEVER, | ||
95 | BT_KILL_MSK_NEVER, | ||
96 | }, | ||
97 | { | ||
98 | BT_KILL_MSK_DEFAULT, | ||
99 | BT_KILL_MSK_NEVER, | ||
100 | BT_KILL_MSK_DEFAULT, | ||
101 | }, | ||
102 | }; | ||
103 | |||
104 | const u8 iwl_bt_ack_kill_msk[BT_MAX_AG][BT_COEX_MAX_LUT] = { | ||
105 | { | ||
106 | BT_KILL_MSK_ALWAYS, | ||
107 | BT_KILL_MSK_ALWAYS, | ||
108 | BT_KILL_MSK_ALWAYS, | ||
109 | }, | ||
110 | { | ||
111 | BT_KILL_MSK_ALWAYS, | ||
112 | BT_KILL_MSK_ALWAYS, | ||
113 | BT_KILL_MSK_ALWAYS, | ||
114 | }, | ||
115 | { | ||
116 | BT_KILL_MSK_ALWAYS, | ||
117 | BT_KILL_MSK_ALWAYS, | ||
118 | BT_KILL_MSK_ALWAYS, | ||
119 | }, | ||
120 | { | ||
121 | BT_KILL_MSK_DEFAULT, | ||
122 | BT_KILL_MSK_ALWAYS, | ||
123 | BT_KILL_MSK_DEFAULT, | ||
124 | }, | ||
85 | }; | 125 | }; |
86 | 126 | ||
87 | static const __le32 iwl_bt_prio_boost[BT_COEX_BOOST_SIZE] = { | 127 | static const __le32 iwl_bt_prio_boost[BT_COEX_BOOST_SIZE] = { |
@@ -611,54 +651,43 @@ send_cmd: | |||
611 | return ret; | 651 | return ret; |
612 | } | 652 | } |
613 | 653 | ||
614 | static int iwl_mvm_bt_udpate_sw_boost(struct iwl_mvm *mvm, | 654 | static int iwl_mvm_bt_udpate_sw_boost(struct iwl_mvm *mvm) |
615 | bool reduced_tx_power) | ||
616 | { | 655 | { |
617 | enum iwl_bt_kill_msk bt_kill_msk; | ||
618 | struct iwl_bt_coex_sw_boost_update_cmd cmd = {}; | ||
619 | struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif; | 656 | struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif; |
657 | u32 primary_lut = le32_to_cpu(notif->primary_ch_lut); | ||
658 | u32 secondary_lut = le32_to_cpu(notif->secondary_ch_lut); | ||
659 | u32 ag = le32_to_cpu(notif->bt_activity_grading); | ||
660 | struct iwl_bt_coex_sw_boost_update_cmd cmd = {}; | ||
661 | u8 ack_kill_msk[NUM_PHY_CTX] = {}; | ||
662 | u8 cts_kill_msk[NUM_PHY_CTX] = {}; | ||
663 | int i; | ||
620 | 664 | ||
621 | lockdep_assert_held(&mvm->mutex); | 665 | lockdep_assert_held(&mvm->mutex); |
622 | 666 | ||
623 | if (reduced_tx_power) { | 667 | ack_kill_msk[0] = iwl_bt_ack_kill_msk[ag][primary_lut]; |
624 | /* Reduced Tx power has precedence on the type of the profile */ | 668 | cts_kill_msk[0] = iwl_bt_cts_kill_msk[ag][primary_lut]; |
625 | bt_kill_msk = BT_KILL_MSK_REDUCED_TXPOW; | ||
626 | } else { | ||
627 | /* Low latency BT profile is active: give higher prio to BT */ | ||
628 | if (BT_MBOX_MSG(notif, 3, SCO_STATE) || | ||
629 | BT_MBOX_MSG(notif, 3, A2DP_STATE) || | ||
630 | BT_MBOX_MSG(notif, 3, SNIFF_STATE)) | ||
631 | bt_kill_msk = BT_KILL_MSK_SCO_HID_A2DP; | ||
632 | else | ||
633 | bt_kill_msk = BT_KILL_MSK_DEFAULT; | ||
634 | } | ||
635 | 669 | ||
636 | IWL_DEBUG_COEX(mvm, | 670 | ack_kill_msk[1] = iwl_bt_ack_kill_msk[ag][secondary_lut]; |
637 | "Update kill_msk: %d - SCO %sactive A2DP %sactive SNIFF %sactive\n", | 671 | cts_kill_msk[1] = iwl_bt_cts_kill_msk[ag][secondary_lut]; |
638 | bt_kill_msk, | ||
639 | BT_MBOX_MSG(notif, 3, SCO_STATE) ? "" : "in", | ||
640 | BT_MBOX_MSG(notif, 3, A2DP_STATE) ? "" : "in", | ||
641 | BT_MBOX_MSG(notif, 3, SNIFF_STATE) ? "" : "in"); | ||
642 | 672 | ||
643 | /* Don't send HCMD if there is no update */ | 673 | /* Don't send HCMD if there is no update */ |
644 | if (bt_kill_msk == mvm->bt_kill_msk) | 674 | if (!memcmp(ack_kill_msk, mvm->bt_ack_kill_msk, sizeof(ack_kill_msk)) || |
675 | !memcmp(cts_kill_msk, mvm->bt_cts_kill_msk, sizeof(cts_kill_msk))) | ||
645 | return 0; | 676 | return 0; |
646 | 677 | ||
647 | mvm->bt_kill_msk = bt_kill_msk; | 678 | memcpy(mvm->bt_ack_kill_msk, ack_kill_msk, |
679 | sizeof(mvm->bt_ack_kill_msk)); | ||
680 | memcpy(mvm->bt_cts_kill_msk, cts_kill_msk, | ||
681 | sizeof(mvm->bt_cts_kill_msk)); | ||
648 | 682 | ||
649 | cmd.boost_values[0].kill_ack_msk = | 683 | BUILD_BUG_ON(ARRAY_SIZE(ack_kill_msk) < ARRAY_SIZE(cmd.boost_values)); |
650 | cpu_to_le32(iwl_bt_ack_kill_msk[bt_kill_msk]); | ||
651 | cmd.boost_values[0].kill_cts_msk = | ||
652 | cpu_to_le32(iwl_bt_cts_kill_msk[bt_kill_msk]); | ||
653 | 684 | ||
654 | cmd.boost_values[1].kill_ack_msk = cmd.boost_values[0].kill_ack_msk; | 685 | for (i = 0; i < ARRAY_SIZE(cmd.boost_values); i++) { |
655 | cmd.boost_values[2].kill_cts_msk = cmd.boost_values[0].kill_cts_msk; | 686 | cmd.boost_values[i].kill_ack_msk = |
656 | cmd.boost_values[1].kill_ack_msk = cmd.boost_values[0].kill_ack_msk; | 687 | cpu_to_le32(iwl_bt_ctl_kill_msk[ack_kill_msk[i]]); |
657 | cmd.boost_values[2].kill_cts_msk = cmd.boost_values[0].kill_cts_msk; | 688 | cmd.boost_values[i].kill_cts_msk = |
658 | 689 | cpu_to_le32(iwl_bt_ctl_kill_msk[cts_kill_msk[i]]); | |
659 | IWL_DEBUG_COEX(mvm, "ACK Kill msk = 0x%08x, CTS Kill msk = 0x%08x\n", | 690 | } |
660 | iwl_bt_ack_kill_msk[bt_kill_msk], | ||
661 | iwl_bt_cts_kill_msk[bt_kill_msk]); | ||
662 | 691 | ||
663 | return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_UPDATE_SW_BOOST, 0, | 692 | return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_UPDATE_SW_BOOST, 0, |
664 | sizeof(cmd), &cmd); | 693 | sizeof(cmd), &cmd); |
@@ -700,8 +729,6 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, | |||
700 | struct iwl_bt_iterator_data { | 729 | struct iwl_bt_iterator_data { |
701 | struct iwl_bt_coex_profile_notif *notif; | 730 | struct iwl_bt_coex_profile_notif *notif; |
702 | struct iwl_mvm *mvm; | 731 | struct iwl_mvm *mvm; |
703 | u32 num_bss_ifaces; | ||
704 | bool reduced_tx_power; | ||
705 | struct ieee80211_chanctx_conf *primary; | 732 | struct ieee80211_chanctx_conf *primary; |
706 | struct ieee80211_chanctx_conf *secondary; | 733 | struct ieee80211_chanctx_conf *secondary; |
707 | bool primary_ll; | 734 | bool primary_ll; |
@@ -737,22 +764,12 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, | |||
737 | 764 | ||
738 | switch (vif->type) { | 765 | switch (vif->type) { |
739 | case NL80211_IFTYPE_STATION: | 766 | case NL80211_IFTYPE_STATION: |
740 | /* Count BSSes vifs */ | ||
741 | data->num_bss_ifaces++; | ||
742 | /* default smps_mode for BSS / P2P client is AUTOMATIC */ | 767 | /* default smps_mode for BSS / P2P client is AUTOMATIC */ |
743 | smps_mode = IEEE80211_SMPS_AUTOMATIC; | 768 | smps_mode = IEEE80211_SMPS_AUTOMATIC; |
744 | break; | 769 | break; |
745 | case NL80211_IFTYPE_AP: | 770 | case NL80211_IFTYPE_AP: |
746 | /* default smps_mode for AP / GO is OFF */ | 771 | if (!mvmvif->ap_ibss_active) |
747 | smps_mode = IEEE80211_SMPS_OFF; | ||
748 | if (!mvmvif->ap_ibss_active) { | ||
749 | iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, | ||
750 | smps_mode); | ||
751 | return; | 772 | return; |
752 | } | ||
753 | |||
754 | /* the Ack / Cts kill mask must be default if AP / GO */ | ||
755 | data->reduced_tx_power = false; | ||
756 | break; | 773 | break; |
757 | default: | 774 | default: |
758 | return; | 775 | return; |
@@ -763,11 +780,10 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, | |||
763 | /* If channel context is invalid or not on 2.4GHz .. */ | 780 | /* If channel context is invalid or not on 2.4GHz .. */ |
764 | if ((!chanctx_conf || | 781 | if ((!chanctx_conf || |
765 | chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ)) { | 782 | chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ)) { |
766 | /* ... relax constraints and disable rssi events */ | ||
767 | iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, | ||
768 | smps_mode); | ||
769 | data->reduced_tx_power = false; | ||
770 | if (vif->type == NL80211_IFTYPE_STATION) { | 783 | if (vif->type == NL80211_IFTYPE_STATION) { |
784 | /* ... relax constraints and disable rssi events */ | ||
785 | iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, | ||
786 | smps_mode); | ||
771 | iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, | 787 | iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, |
772 | false); | 788 | false); |
773 | iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0); | 789 | iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0); |
@@ -779,9 +795,7 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, | |||
779 | if (bt_activity_grading >= BT_HIGH_TRAFFIC) | 795 | if (bt_activity_grading >= BT_HIGH_TRAFFIC) |
780 | smps_mode = IEEE80211_SMPS_STATIC; | 796 | smps_mode = IEEE80211_SMPS_STATIC; |
781 | else if (bt_activity_grading >= BT_LOW_TRAFFIC) | 797 | else if (bt_activity_grading >= BT_LOW_TRAFFIC) |
782 | smps_mode = vif->type == NL80211_IFTYPE_AP ? | 798 | smps_mode = IEEE80211_SMPS_DYNAMIC; |
783 | IEEE80211_SMPS_OFF : | ||
784 | IEEE80211_SMPS_DYNAMIC; | ||
785 | 799 | ||
786 | /* relax SMPS contraints for next association */ | 800 | /* relax SMPS contraints for next association */ |
787 | if (!vif->bss_conf.assoc) | 801 | if (!vif->bss_conf.assoc) |
@@ -795,7 +809,9 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, | |||
795 | "mac %d: bt_activity_grading %d smps_req %d\n", | 809 | "mac %d: bt_activity_grading %d smps_req %d\n", |
796 | mvmvif->id, bt_activity_grading, smps_mode); | 810 | mvmvif->id, bt_activity_grading, smps_mode); |
797 | 811 | ||
798 | iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, smps_mode); | 812 | if (vif->type == NL80211_IFTYPE_STATION) |
813 | iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, | ||
814 | smps_mode); | ||
799 | 815 | ||
800 | /* low latency is always primary */ | 816 | /* low latency is always primary */ |
801 | if (iwl_mvm_vif_low_latency(mvmvif)) { | 817 | if (iwl_mvm_vif_low_latency(mvmvif)) { |
@@ -846,7 +862,6 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, | |||
846 | if (iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT || | 862 | if (iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT || |
847 | mvm->cfg->bt_shared_single_ant || !vif->bss_conf.assoc || | 863 | mvm->cfg->bt_shared_single_ant || !vif->bss_conf.assoc || |
848 | le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) == BT_OFF) { | 864 | le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) == BT_OFF) { |
849 | data->reduced_tx_power = false; | ||
850 | iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false); | 865 | iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false); |
851 | iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0); | 866 | iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0); |
852 | return; | 867 | return; |
@@ -861,23 +876,9 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, | |||
861 | if (ave_rssi > -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH) { | 876 | if (ave_rssi > -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH) { |
862 | if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true)) | 877 | if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true)) |
863 | IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n"); | 878 | IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n"); |
864 | |||
865 | /* | ||
866 | * bt_kill_msk can be BT_KILL_MSK_REDUCED_TXPOW only if all the | ||
867 | * BSS / P2P clients have rssi above threshold. | ||
868 | * We set the bt_kill_msk to BT_KILL_MSK_REDUCED_TXPOW before | ||
869 | * the iteration, if one interface's rssi isn't good enough, | ||
870 | * bt_kill_msk will be set to default values. | ||
871 | */ | ||
872 | } else if (ave_rssi < -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH) { | 879 | } else if (ave_rssi < -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH) { |
873 | if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false)) | 880 | if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false)) |
874 | IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n"); | 881 | IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n"); |
875 | |||
876 | /* | ||
877 | * One interface hasn't rssi above threshold, bt_kill_msk must | ||
878 | * be set to default values. | ||
879 | */ | ||
880 | data->reduced_tx_power = false; | ||
881 | } | 882 | } |
882 | 883 | ||
883 | /* Begin to monitor the RSSI: it may influence the reduced Tx power */ | 884 | /* Begin to monitor the RSSI: it may influence the reduced Tx power */ |
@@ -889,7 +890,6 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm) | |||
889 | struct iwl_bt_iterator_data data = { | 890 | struct iwl_bt_iterator_data data = { |
890 | .mvm = mvm, | 891 | .mvm = mvm, |
891 | .notif = &mvm->last_bt_notif, | 892 | .notif = &mvm->last_bt_notif, |
892 | .reduced_tx_power = true, | ||
893 | }; | 893 | }; |
894 | struct iwl_bt_coex_ci_cmd cmd = {}; | 894 | struct iwl_bt_coex_ci_cmd cmd = {}; |
895 | u8 ci_bw_idx; | 895 | u8 ci_bw_idx; |
@@ -959,14 +959,7 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm) | |||
959 | memcpy(&mvm->last_bt_ci_cmd, &cmd, sizeof(cmd)); | 959 | memcpy(&mvm->last_bt_ci_cmd, &cmd, sizeof(cmd)); |
960 | } | 960 | } |
961 | 961 | ||
962 | /* | 962 | if (iwl_mvm_bt_udpate_sw_boost(mvm)) |
963 | * If there are no BSS / P2P client interfaces, reduced Tx Power is | ||
964 | * irrelevant since it is based on the RSSI coming from the beacon. | ||
965 | * Use BT_KILL_MSK_DEFAULT in that case. | ||
966 | */ | ||
967 | data.reduced_tx_power = data.reduced_tx_power && data.num_bss_ifaces; | ||
968 | |||
969 | if (iwl_mvm_bt_udpate_sw_boost(mvm, data.reduced_tx_power)) | ||
970 | IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n"); | 963 | IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n"); |
971 | } | 964 | } |
972 | 965 | ||
@@ -1035,16 +1028,6 @@ static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac, | |||
1035 | return; | 1028 | return; |
1036 | 1029 | ||
1037 | mvmsta = iwl_mvm_sta_from_mac80211(sta); | 1030 | mvmsta = iwl_mvm_sta_from_mac80211(sta); |
1038 | |||
1039 | data->num_bss_ifaces++; | ||
1040 | |||
1041 | /* | ||
1042 | * This interface doesn't support reduced Tx power (because of low | ||
1043 | * RSSI probably), then set bt_kill_msk to default values. | ||
1044 | */ | ||
1045 | if (!mvmsta->bt_reduced_txpower) | ||
1046 | data->reduced_tx_power = false; | ||
1047 | /* else - possibly leave it to BT_KILL_MSK_REDUCED_TXPOW */ | ||
1048 | } | 1031 | } |
1049 | 1032 | ||
1050 | void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 1033 | void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
@@ -1053,7 +1036,6 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
1053 | struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv; | 1036 | struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv; |
1054 | struct iwl_bt_iterator_data data = { | 1037 | struct iwl_bt_iterator_data data = { |
1055 | .mvm = mvm, | 1038 | .mvm = mvm, |
1056 | .reduced_tx_power = true, | ||
1057 | }; | 1039 | }; |
1058 | int ret; | 1040 | int ret; |
1059 | 1041 | ||
@@ -1100,14 +1082,7 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
1100 | mvm->hw, IEEE80211_IFACE_ITER_NORMAL, | 1082 | mvm->hw, IEEE80211_IFACE_ITER_NORMAL, |
1101 | iwl_mvm_bt_rssi_iterator, &data); | 1083 | iwl_mvm_bt_rssi_iterator, &data); |
1102 | 1084 | ||
1103 | /* | 1085 | if (iwl_mvm_bt_udpate_sw_boost(mvm)) |
1104 | * If there are no BSS / P2P client interfaces, reduced Tx Power is | ||
1105 | * irrelevant since it is based on the RSSI coming from the beacon. | ||
1106 | * Use BT_KILL_MSK_DEFAULT in that case. | ||
1107 | */ | ||
1108 | data.reduced_tx_power = data.reduced_tx_power && data.num_bss_ifaces; | ||
1109 | |||
1110 | if (iwl_mvm_bt_udpate_sw_boost(mvm, data.reduced_tx_power)) | ||
1111 | IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n"); | 1086 | IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n"); |
1112 | } | 1087 | } |
1113 | 1088 | ||
@@ -1150,7 +1125,7 @@ bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm, | |||
1150 | enum iwl_bt_coex_lut_type lut_type; | 1125 | enum iwl_bt_coex_lut_type lut_type; |
1151 | 1126 | ||
1152 | if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT)) | 1127 | if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT)) |
1153 | return iwl_mvm_coex_agg_time_limit_old(mvm, sta); | 1128 | return iwl_mvm_bt_coex_is_mimo_allowed_old(mvm, sta); |
1154 | 1129 | ||
1155 | if (IWL_COEX_IS_TTC_ON(mvm->last_bt_notif.ttc_rrc_status, phy_ctxt->id)) | 1130 | if (IWL_COEX_IS_TTC_ON(mvm->last_bt_notif.ttc_rrc_status, phy_ctxt->id)) |
1156 | return true; | 1131 | return true; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c b/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c index ce50363d314b..a3be33359927 100644 --- a/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c +++ b/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c | |||
@@ -649,10 +649,6 @@ int iwl_send_bt_init_conf_old(struct iwl_mvm *mvm) | |||
649 | sizeof(iwl_bt_prio_boost)); | 649 | sizeof(iwl_bt_prio_boost)); |
650 | memcpy(&bt_cmd->bt4_multiprio_lut, iwl_bt_mprio_lut, | 650 | memcpy(&bt_cmd->bt4_multiprio_lut, iwl_bt_mprio_lut, |
651 | sizeof(iwl_bt_mprio_lut)); | 651 | sizeof(iwl_bt_mprio_lut)); |
652 | bt_cmd->kill_ack_msk = | ||
653 | cpu_to_le32(iwl_bt_ack_kill_msk[BT_KILL_MSK_DEFAULT]); | ||
654 | bt_cmd->kill_cts_msk = | ||
655 | cpu_to_le32(iwl_bt_cts_kill_msk[BT_KILL_MSK_DEFAULT]); | ||
656 | 652 | ||
657 | send_cmd: | 653 | send_cmd: |
658 | memset(&mvm->last_bt_notif_old, 0, sizeof(mvm->last_bt_notif_old)); | 654 | memset(&mvm->last_bt_notif_old, 0, sizeof(mvm->last_bt_notif_old)); |
@@ -664,12 +660,13 @@ send_cmd: | |||
664 | return ret; | 660 | return ret; |
665 | } | 661 | } |
666 | 662 | ||
667 | static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm, | 663 | static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm) |
668 | bool reduced_tx_power) | ||
669 | { | 664 | { |
670 | enum iwl_bt_kill_msk bt_kill_msk; | ||
671 | struct iwl_bt_coex_cmd_old *bt_cmd; | ||
672 | struct iwl_bt_coex_profile_notif_old *notif = &mvm->last_bt_notif_old; | 665 | struct iwl_bt_coex_profile_notif_old *notif = &mvm->last_bt_notif_old; |
666 | u32 primary_lut = le32_to_cpu(notif->primary_ch_lut); | ||
667 | u32 ag = le32_to_cpu(notif->bt_activity_grading); | ||
668 | struct iwl_bt_coex_cmd_old *bt_cmd; | ||
669 | u8 ack_kill_msk, cts_kill_msk; | ||
673 | struct iwl_host_cmd cmd = { | 670 | struct iwl_host_cmd cmd = { |
674 | .id = BT_CONFIG, | 671 | .id = BT_CONFIG, |
675 | .data[0] = &bt_cmd, | 672 | .data[0] = &bt_cmd, |
@@ -680,31 +677,15 @@ static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm, | |||
680 | 677 | ||
681 | lockdep_assert_held(&mvm->mutex); | 678 | lockdep_assert_held(&mvm->mutex); |
682 | 679 | ||
683 | if (reduced_tx_power) { | 680 | ack_kill_msk = iwl_bt_ack_kill_msk[ag][primary_lut]; |
684 | /* Reduced Tx power has precedence on the type of the profile */ | 681 | cts_kill_msk = iwl_bt_cts_kill_msk[ag][primary_lut]; |
685 | bt_kill_msk = BT_KILL_MSK_REDUCED_TXPOW; | ||
686 | } else { | ||
687 | /* Low latency BT profile is active: give higher prio to BT */ | ||
688 | if (BT_MBOX_MSG(notif, 3, SCO_STATE) || | ||
689 | BT_MBOX_MSG(notif, 3, A2DP_STATE) || | ||
690 | BT_MBOX_MSG(notif, 3, SNIFF_STATE)) | ||
691 | bt_kill_msk = BT_KILL_MSK_SCO_HID_A2DP; | ||
692 | else | ||
693 | bt_kill_msk = BT_KILL_MSK_DEFAULT; | ||
694 | } | ||
695 | |||
696 | IWL_DEBUG_COEX(mvm, | ||
697 | "Update kill_msk: %d - SCO %sactive A2DP %sactive SNIFF %sactive\n", | ||
698 | bt_kill_msk, | ||
699 | BT_MBOX_MSG(notif, 3, SCO_STATE) ? "" : "in", | ||
700 | BT_MBOX_MSG(notif, 3, A2DP_STATE) ? "" : "in", | ||
701 | BT_MBOX_MSG(notif, 3, SNIFF_STATE) ? "" : "in"); | ||
702 | 682 | ||
703 | /* Don't send HCMD if there is no update */ | 683 | if (mvm->bt_ack_kill_msk[0] == ack_kill_msk && |
704 | if (bt_kill_msk == mvm->bt_kill_msk) | 684 | mvm->bt_cts_kill_msk[0] == cts_kill_msk) |
705 | return 0; | 685 | return 0; |
706 | 686 | ||
707 | mvm->bt_kill_msk = bt_kill_msk; | 687 | mvm->bt_ack_kill_msk[0] = ack_kill_msk; |
688 | mvm->bt_cts_kill_msk[0] = cts_kill_msk; | ||
708 | 689 | ||
709 | bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL); | 690 | bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL); |
710 | if (!bt_cmd) | 691 | if (!bt_cmd) |
@@ -712,16 +693,12 @@ static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm, | |||
712 | cmd.data[0] = bt_cmd; | 693 | cmd.data[0] = bt_cmd; |
713 | bt_cmd->flags = cpu_to_le32(BT_COEX_NW_OLD); | 694 | bt_cmd->flags = cpu_to_le32(BT_COEX_NW_OLD); |
714 | 695 | ||
715 | bt_cmd->kill_ack_msk = cpu_to_le32(iwl_bt_ack_kill_msk[bt_kill_msk]); | 696 | bt_cmd->kill_ack_msk = cpu_to_le32(iwl_bt_ctl_kill_msk[ack_kill_msk]); |
716 | bt_cmd->kill_cts_msk = cpu_to_le32(iwl_bt_cts_kill_msk[bt_kill_msk]); | 697 | bt_cmd->kill_cts_msk = cpu_to_le32(iwl_bt_ctl_kill_msk[cts_kill_msk]); |
717 | bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_ENABLE | | 698 | bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_ENABLE | |
718 | BT_VALID_KILL_ACK | | 699 | BT_VALID_KILL_ACK | |
719 | BT_VALID_KILL_CTS); | 700 | BT_VALID_KILL_CTS); |
720 | 701 | ||
721 | IWL_DEBUG_COEX(mvm, "ACK Kill msk = 0x%08x, CTS Kill msk = 0x%08x\n", | ||
722 | iwl_bt_ack_kill_msk[bt_kill_msk], | ||
723 | iwl_bt_cts_kill_msk[bt_kill_msk]); | ||
724 | |||
725 | ret = iwl_mvm_send_cmd(mvm, &cmd); | 702 | ret = iwl_mvm_send_cmd(mvm, &cmd); |
726 | 703 | ||
727 | kfree(bt_cmd); | 704 | kfree(bt_cmd); |
@@ -777,8 +754,6 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, | |||
777 | struct iwl_bt_iterator_data { | 754 | struct iwl_bt_iterator_data { |
778 | struct iwl_bt_coex_profile_notif_old *notif; | 755 | struct iwl_bt_coex_profile_notif_old *notif; |
779 | struct iwl_mvm *mvm; | 756 | struct iwl_mvm *mvm; |
780 | u32 num_bss_ifaces; | ||
781 | bool reduced_tx_power; | ||
782 | struct ieee80211_chanctx_conf *primary; | 757 | struct ieee80211_chanctx_conf *primary; |
783 | struct ieee80211_chanctx_conf *secondary; | 758 | struct ieee80211_chanctx_conf *secondary; |
784 | bool primary_ll; | 759 | bool primary_ll; |
@@ -814,22 +789,12 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, | |||
814 | 789 | ||
815 | switch (vif->type) { | 790 | switch (vif->type) { |
816 | case NL80211_IFTYPE_STATION: | 791 | case NL80211_IFTYPE_STATION: |
817 | /* Count BSSes vifs */ | ||
818 | data->num_bss_ifaces++; | ||
819 | /* default smps_mode for BSS / P2P client is AUTOMATIC */ | 792 | /* default smps_mode for BSS / P2P client is AUTOMATIC */ |
820 | smps_mode = IEEE80211_SMPS_AUTOMATIC; | 793 | smps_mode = IEEE80211_SMPS_AUTOMATIC; |
821 | break; | 794 | break; |
822 | case NL80211_IFTYPE_AP: | 795 | case NL80211_IFTYPE_AP: |
823 | /* default smps_mode for AP / GO is OFF */ | 796 | if (!mvmvif->ap_ibss_active) |
824 | smps_mode = IEEE80211_SMPS_OFF; | ||
825 | if (!mvmvif->ap_ibss_active) { | ||
826 | iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, | ||
827 | smps_mode); | ||
828 | return; | 797 | return; |
829 | } | ||
830 | |||
831 | /* the Ack / Cts kill mask must be default if AP / GO */ | ||
832 | data->reduced_tx_power = false; | ||
833 | break; | 798 | break; |
834 | default: | 799 | default: |
835 | return; | 800 | return; |
@@ -840,11 +805,10 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, | |||
840 | /* If channel context is invalid or not on 2.4GHz .. */ | 805 | /* If channel context is invalid or not on 2.4GHz .. */ |
841 | if ((!chanctx_conf || | 806 | if ((!chanctx_conf || |
842 | chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ)) { | 807 | chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ)) { |
843 | /* ... relax constraints and disable rssi events */ | ||
844 | iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, | ||
845 | smps_mode); | ||
846 | data->reduced_tx_power = false; | ||
847 | if (vif->type == NL80211_IFTYPE_STATION) { | 808 | if (vif->type == NL80211_IFTYPE_STATION) { |
809 | /* ... relax constraints and disable rssi events */ | ||
810 | iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, | ||
811 | smps_mode); | ||
848 | iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, | 812 | iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, |
849 | false); | 813 | false); |
850 | iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0); | 814 | iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0); |
@@ -869,7 +833,9 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, | |||
869 | mvmvif->id, data->notif->bt_status, bt_activity_grading, | 833 | mvmvif->id, data->notif->bt_status, bt_activity_grading, |
870 | smps_mode); | 834 | smps_mode); |
871 | 835 | ||
872 | iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, smps_mode); | 836 | if (vif->type == NL80211_IFTYPE_STATION) |
837 | iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, | ||
838 | smps_mode); | ||
873 | 839 | ||
874 | /* low latency is always primary */ | 840 | /* low latency is always primary */ |
875 | if (iwl_mvm_vif_low_latency(mvmvif)) { | 841 | if (iwl_mvm_vif_low_latency(mvmvif)) { |
@@ -920,7 +886,6 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, | |||
920 | if (iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT || | 886 | if (iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT || |
921 | mvm->cfg->bt_shared_single_ant || !vif->bss_conf.assoc || | 887 | mvm->cfg->bt_shared_single_ant || !vif->bss_conf.assoc || |
922 | !data->notif->bt_status) { | 888 | !data->notif->bt_status) { |
923 | data->reduced_tx_power = false; | ||
924 | iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false); | 889 | iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false); |
925 | iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0); | 890 | iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0); |
926 | return; | 891 | return; |
@@ -935,23 +900,9 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, | |||
935 | if (ave_rssi > -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH) { | 900 | if (ave_rssi > -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH) { |
936 | if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true)) | 901 | if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true)) |
937 | IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n"); | 902 | IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n"); |
938 | |||
939 | /* | ||
940 | * bt_kill_msk can be BT_KILL_MSK_REDUCED_TXPOW only if all the | ||
941 | * BSS / P2P clients have rssi above threshold. | ||
942 | * We set the bt_kill_msk to BT_KILL_MSK_REDUCED_TXPOW before | ||
943 | * the iteration, if one interface's rssi isn't good enough, | ||
944 | * bt_kill_msk will be set to default values. | ||
945 | */ | ||
946 | } else if (ave_rssi < -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH) { | 903 | } else if (ave_rssi < -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH) { |
947 | if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false)) | 904 | if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false)) |
948 | IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n"); | 905 | IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n"); |
949 | |||
950 | /* | ||
951 | * One interface hasn't rssi above threshold, bt_kill_msk must | ||
952 | * be set to default values. | ||
953 | */ | ||
954 | data->reduced_tx_power = false; | ||
955 | } | 906 | } |
956 | 907 | ||
957 | /* Begin to monitor the RSSI: it may influence the reduced Tx power */ | 908 | /* Begin to monitor the RSSI: it may influence the reduced Tx power */ |
@@ -963,7 +914,6 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm) | |||
963 | struct iwl_bt_iterator_data data = { | 914 | struct iwl_bt_iterator_data data = { |
964 | .mvm = mvm, | 915 | .mvm = mvm, |
965 | .notif = &mvm->last_bt_notif_old, | 916 | .notif = &mvm->last_bt_notif_old, |
966 | .reduced_tx_power = true, | ||
967 | }; | 917 | }; |
968 | struct iwl_bt_coex_ci_cmd_old cmd = {}; | 918 | struct iwl_bt_coex_ci_cmd_old cmd = {}; |
969 | u8 ci_bw_idx; | 919 | u8 ci_bw_idx; |
@@ -1037,14 +987,7 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm) | |||
1037 | memcpy(&mvm->last_bt_ci_cmd_old, &cmd, sizeof(cmd)); | 987 | memcpy(&mvm->last_bt_ci_cmd_old, &cmd, sizeof(cmd)); |
1038 | } | 988 | } |
1039 | 989 | ||
1040 | /* | 990 | if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm)) |
1041 | * If there are no BSS / P2P client interfaces, reduced Tx Power is | ||
1042 | * irrelevant since it is based on the RSSI coming from the beacon. | ||
1043 | * Use BT_KILL_MSK_DEFAULT in that case. | ||
1044 | */ | ||
1045 | data.reduced_tx_power = data.reduced_tx_power && data.num_bss_ifaces; | ||
1046 | |||
1047 | if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm, data.reduced_tx_power)) | ||
1048 | IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n"); | 991 | IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n"); |
1049 | } | 992 | } |
1050 | 993 | ||
@@ -1115,16 +1058,6 @@ static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac, | |||
1115 | return; | 1058 | return; |
1116 | 1059 | ||
1117 | mvmsta = iwl_mvm_sta_from_mac80211(sta); | 1060 | mvmsta = iwl_mvm_sta_from_mac80211(sta); |
1118 | |||
1119 | data->num_bss_ifaces++; | ||
1120 | |||
1121 | /* | ||
1122 | * This interface doesn't support reduced Tx power (because of low | ||
1123 | * RSSI probably), then set bt_kill_msk to default values. | ||
1124 | */ | ||
1125 | if (!mvmsta->bt_reduced_txpower) | ||
1126 | data->reduced_tx_power = false; | ||
1127 | /* else - possibly leave it to BT_KILL_MSK_REDUCED_TXPOW */ | ||
1128 | } | 1061 | } |
1129 | 1062 | ||
1130 | void iwl_mvm_bt_rssi_event_old(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 1063 | void iwl_mvm_bt_rssi_event_old(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
@@ -1133,7 +1066,6 @@ void iwl_mvm_bt_rssi_event_old(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
1133 | struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv; | 1066 | struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv; |
1134 | struct iwl_bt_iterator_data data = { | 1067 | struct iwl_bt_iterator_data data = { |
1135 | .mvm = mvm, | 1068 | .mvm = mvm, |
1136 | .reduced_tx_power = true, | ||
1137 | }; | 1069 | }; |
1138 | int ret; | 1070 | int ret; |
1139 | 1071 | ||
@@ -1175,14 +1107,7 @@ void iwl_mvm_bt_rssi_event_old(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
1175 | mvm->hw, IEEE80211_IFACE_ITER_NORMAL, | 1107 | mvm->hw, IEEE80211_IFACE_ITER_NORMAL, |
1176 | iwl_mvm_bt_rssi_iterator, &data); | 1108 | iwl_mvm_bt_rssi_iterator, &data); |
1177 | 1109 | ||
1178 | /* | 1110 | if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm)) |
1179 | * If there are no BSS / P2P client interfaces, reduced Tx Power is | ||
1180 | * irrelevant since it is based on the RSSI coming from the beacon. | ||
1181 | * Use BT_KILL_MSK_DEFAULT in that case. | ||
1182 | */ | ||
1183 | data.reduced_tx_power = data.reduced_tx_power && data.num_bss_ifaces; | ||
1184 | |||
1185 | if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm, data.reduced_tx_power)) | ||
1186 | IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n"); | 1111 | IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n"); |
1187 | } | 1112 | } |
1188 | 1113 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index f131ef0ec5b3..7d18f466fbb3 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c | |||
@@ -146,17 +146,47 @@ static ssize_t iwl_dbgfs_fw_error_dump_read(struct file *file, | |||
146 | char __user *user_buf, | 146 | char __user *user_buf, |
147 | size_t count, loff_t *ppos) | 147 | size_t count, loff_t *ppos) |
148 | { | 148 | { |
149 | struct iwl_fw_error_dump_file *dump_file = file->private_data; | 149 | struct iwl_mvm_dump_ptrs *dump_ptrs = (void *)file->private_data; |
150 | ssize_t bytes_read = 0; | ||
151 | ssize_t bytes_read_trans = 0; | ||
152 | |||
153 | if (*ppos < dump_ptrs->op_mode_len) | ||
154 | bytes_read += | ||
155 | simple_read_from_buffer(user_buf, count, ppos, | ||
156 | dump_ptrs->op_mode_ptr, | ||
157 | dump_ptrs->op_mode_len); | ||
158 | |||
159 | if (bytes_read < 0 || *ppos < dump_ptrs->op_mode_len) | ||
160 | return bytes_read; | ||
161 | |||
162 | if (dump_ptrs->trans_ptr) { | ||
163 | *ppos -= dump_ptrs->op_mode_len; | ||
164 | bytes_read_trans = | ||
165 | simple_read_from_buffer(user_buf + bytes_read, | ||
166 | count - bytes_read, ppos, | ||
167 | dump_ptrs->trans_ptr->data, | ||
168 | dump_ptrs->trans_ptr->len); | ||
169 | *ppos += dump_ptrs->op_mode_len; | ||
170 | |||
171 | if (bytes_read_trans >= 0) | ||
172 | bytes_read += bytes_read_trans; | ||
173 | else if (!bytes_read) | ||
174 | /* propagate the failure */ | ||
175 | return bytes_read_trans; | ||
176 | } | ||
177 | |||
178 | return bytes_read; | ||
150 | 179 | ||
151 | return simple_read_from_buffer(user_buf, count, ppos, | ||
152 | dump_file, | ||
153 | le32_to_cpu(dump_file->file_len)); | ||
154 | } | 180 | } |
155 | 181 | ||
156 | static int iwl_dbgfs_fw_error_dump_release(struct inode *inode, | 182 | static int iwl_dbgfs_fw_error_dump_release(struct inode *inode, |
157 | struct file *file) | 183 | struct file *file) |
158 | { | 184 | { |
159 | vfree(file->private_data); | 185 | struct iwl_mvm_dump_ptrs *dump_ptrs = (void *)file->private_data; |
186 | |||
187 | vfree(dump_ptrs->op_mode_ptr); | ||
188 | vfree(dump_ptrs->trans_ptr); | ||
189 | kfree(dump_ptrs); | ||
160 | 190 | ||
161 | return 0; | 191 | return 0; |
162 | } | 192 | } |
@@ -514,9 +544,9 @@ static ssize_t iwl_dbgfs_bt_cmd_read(struct file *file, char __user *user_buf, | |||
514 | 544 | ||
515 | pos += scnprintf(buf+pos, bufsz-pos, "BT Configuration CMD\n"); | 545 | pos += scnprintf(buf+pos, bufsz-pos, "BT Configuration CMD\n"); |
516 | pos += scnprintf(buf+pos, bufsz-pos, "\tACK Kill Mask 0x%08x\n", | 546 | pos += scnprintf(buf+pos, bufsz-pos, "\tACK Kill Mask 0x%08x\n", |
517 | iwl_bt_ack_kill_msk[mvm->bt_kill_msk]); | 547 | iwl_bt_ctl_kill_msk[mvm->bt_ack_kill_msk[0]]); |
518 | pos += scnprintf(buf+pos, bufsz-pos, "\tCTS Kill Mask 0x%08x\n", | 548 | pos += scnprintf(buf+pos, bufsz-pos, "\tCTS Kill Mask 0x%08x\n", |
519 | iwl_bt_cts_kill_msk[mvm->bt_kill_msk]); | 549 | iwl_bt_ctl_kill_msk[mvm->bt_cts_kill_msk[0]]); |
520 | 550 | ||
521 | } else { | 551 | } else { |
522 | struct iwl_bt_coex_ci_cmd *cmd = &mvm->last_bt_ci_cmd; | 552 | struct iwl_bt_coex_ci_cmd *cmd = &mvm->last_bt_ci_cmd; |
@@ -531,10 +561,19 @@ static ssize_t iwl_dbgfs_bt_cmd_read(struct file *file, char __user *user_buf, | |||
531 | le64_to_cpu(cmd->bt_secondary_ci)); | 561 | le64_to_cpu(cmd->bt_secondary_ci)); |
532 | 562 | ||
533 | pos += scnprintf(buf+pos, bufsz-pos, "BT Configuration CMD\n"); | 563 | pos += scnprintf(buf+pos, bufsz-pos, "BT Configuration CMD\n"); |
534 | pos += scnprintf(buf+pos, bufsz-pos, "\tACK Kill Mask 0x%08x\n", | 564 | pos += scnprintf(buf+pos, bufsz-pos, |
535 | iwl_bt_ack_kill_msk[mvm->bt_kill_msk]); | 565 | "\tPrimary: ACK Kill Mask 0x%08x\n", |
536 | pos += scnprintf(buf+pos, bufsz-pos, "\tCTS Kill Mask 0x%08x\n", | 566 | iwl_bt_ctl_kill_msk[mvm->bt_ack_kill_msk[0]]); |
537 | iwl_bt_cts_kill_msk[mvm->bt_kill_msk]); | 567 | pos += scnprintf(buf+pos, bufsz-pos, |
568 | "\tPrimary: CTS Kill Mask 0x%08x\n", | ||
569 | iwl_bt_ctl_kill_msk[mvm->bt_cts_kill_msk[0]]); | ||
570 | pos += scnprintf(buf+pos, bufsz-pos, | ||
571 | "\tSecondary: ACK Kill Mask 0x%08x\n", | ||
572 | iwl_bt_ctl_kill_msk[mvm->bt_ack_kill_msk[1]]); | ||
573 | pos += scnprintf(buf+pos, bufsz-pos, | ||
574 | "\tSecondary: CTS Kill Mask 0x%08x\n", | ||
575 | iwl_bt_ctl_kill_msk[mvm->bt_cts_kill_msk[1]]); | ||
576 | |||
538 | } | 577 | } |
539 | 578 | ||
540 | mutex_unlock(&mvm->mutex); | 579 | mutex_unlock(&mvm->mutex); |
@@ -830,8 +869,14 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf, | |||
830 | static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mvm *mvm, char *buf, | 869 | static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mvm *mvm, char *buf, |
831 | size_t count, loff_t *ppos) | 870 | size_t count, loff_t *ppos) |
832 | { | 871 | { |
872 | int ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_NMI); | ||
873 | if (ret) | ||
874 | return ret; | ||
875 | |||
833 | iwl_force_nmi(mvm->trans); | 876 | iwl_force_nmi(mvm->trans); |
834 | 877 | ||
878 | iwl_mvm_unref(mvm, IWL_MVM_REF_NMI); | ||
879 | |||
835 | return count; | 880 | return count; |
836 | } | 881 | } |
837 | 882 | ||
@@ -1115,11 +1160,11 @@ static ssize_t iwl_dbgfs_d3_sram_read(struct file *file, char __user *user_buf, | |||
1115 | } | 1160 | } |
1116 | #endif | 1161 | #endif |
1117 | 1162 | ||
1118 | #define PRINT_MVM_REF(ref) do { \ | 1163 | #define PRINT_MVM_REF(ref) do { \ |
1119 | if (test_bit(ref, mvm->ref_bitmap)) \ | 1164 | if (mvm->refs[ref]) \ |
1120 | pos += scnprintf(buf + pos, bufsz - pos, \ | 1165 | pos += scnprintf(buf + pos, bufsz - pos, \ |
1121 | "\t(0x%lx) %s\n", \ | 1166 | "\t(0x%lx): %d %s\n", \ |
1122 | BIT(ref), #ref); \ | 1167 | BIT(ref), mvm->refs[ref], #ref); \ |
1123 | } while (0) | 1168 | } while (0) |
1124 | 1169 | ||
1125 | static ssize_t iwl_dbgfs_d0i3_refs_read(struct file *file, | 1170 | static ssize_t iwl_dbgfs_d0i3_refs_read(struct file *file, |
@@ -1127,12 +1172,17 @@ static ssize_t iwl_dbgfs_d0i3_refs_read(struct file *file, | |||
1127 | size_t count, loff_t *ppos) | 1172 | size_t count, loff_t *ppos) |
1128 | { | 1173 | { |
1129 | struct iwl_mvm *mvm = file->private_data; | 1174 | struct iwl_mvm *mvm = file->private_data; |
1130 | int pos = 0; | 1175 | int i, pos = 0; |
1131 | char buf[256]; | 1176 | char buf[256]; |
1132 | const size_t bufsz = sizeof(buf); | 1177 | const size_t bufsz = sizeof(buf); |
1178 | u32 refs = 0; | ||
1133 | 1179 | ||
1134 | pos += scnprintf(buf + pos, bufsz - pos, "taken mvm refs: 0x%lx\n", | 1180 | for (i = 0; i < IWL_MVM_REF_COUNT; i++) |
1135 | mvm->ref_bitmap[0]); | 1181 | if (mvm->refs[i]) |
1182 | refs |= BIT(i); | ||
1183 | |||
1184 | pos += scnprintf(buf + pos, bufsz - pos, "taken mvm refs: 0x%x\n", | ||
1185 | refs); | ||
1136 | 1186 | ||
1137 | PRINT_MVM_REF(IWL_MVM_REF_UCODE_DOWN); | 1187 | PRINT_MVM_REF(IWL_MVM_REF_UCODE_DOWN); |
1138 | PRINT_MVM_REF(IWL_MVM_REF_SCAN); | 1188 | PRINT_MVM_REF(IWL_MVM_REF_SCAN); |
@@ -1158,7 +1208,7 @@ static ssize_t iwl_dbgfs_d0i3_refs_write(struct iwl_mvm *mvm, char *buf, | |||
1158 | 1208 | ||
1159 | mutex_lock(&mvm->mutex); | 1209 | mutex_lock(&mvm->mutex); |
1160 | 1210 | ||
1161 | taken = test_bit(IWL_MVM_REF_USER, mvm->ref_bitmap); | 1211 | taken = mvm->refs[IWL_MVM_REF_USER]; |
1162 | if (value == 1 && !taken) | 1212 | if (value == 1 && !taken) |
1163 | iwl_mvm_ref(mvm, IWL_MVM_REF_USER); | 1213 | iwl_mvm_ref(mvm, IWL_MVM_REF_USER); |
1164 | else if (value == 0 && taken) | 1214 | else if (value == 0 && taken) |
@@ -1194,14 +1244,21 @@ iwl_dbgfs_prph_reg_read(struct file *file, | |||
1194 | int pos = 0; | 1244 | int pos = 0; |
1195 | char buf[32]; | 1245 | char buf[32]; |
1196 | const size_t bufsz = sizeof(buf); | 1246 | const size_t bufsz = sizeof(buf); |
1247 | int ret; | ||
1197 | 1248 | ||
1198 | if (!mvm->dbgfs_prph_reg_addr) | 1249 | if (!mvm->dbgfs_prph_reg_addr) |
1199 | return -EINVAL; | 1250 | return -EINVAL; |
1200 | 1251 | ||
1252 | ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PRPH_READ); | ||
1253 | if (ret) | ||
1254 | return ret; | ||
1255 | |||
1201 | pos += scnprintf(buf + pos, bufsz - pos, "Reg 0x%x: (0x%x)\n", | 1256 | pos += scnprintf(buf + pos, bufsz - pos, "Reg 0x%x: (0x%x)\n", |
1202 | mvm->dbgfs_prph_reg_addr, | 1257 | mvm->dbgfs_prph_reg_addr, |
1203 | iwl_read_prph(mvm->trans, mvm->dbgfs_prph_reg_addr)); | 1258 | iwl_read_prph(mvm->trans, mvm->dbgfs_prph_reg_addr)); |
1204 | 1259 | ||
1260 | iwl_mvm_unref(mvm, IWL_MVM_REF_PRPH_READ); | ||
1261 | |||
1205 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 1262 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
1206 | } | 1263 | } |
1207 | 1264 | ||
@@ -1211,6 +1268,7 @@ iwl_dbgfs_prph_reg_write(struct iwl_mvm *mvm, char *buf, | |||
1211 | { | 1268 | { |
1212 | u8 args; | 1269 | u8 args; |
1213 | u32 value; | 1270 | u32 value; |
1271 | int ret; | ||
1214 | 1272 | ||
1215 | args = sscanf(buf, "%i %i", &mvm->dbgfs_prph_reg_addr, &value); | 1273 | args = sscanf(buf, "%i %i", &mvm->dbgfs_prph_reg_addr, &value); |
1216 | /* if we only want to set the reg address - nothing more to do */ | 1274 | /* if we only want to set the reg address - nothing more to do */ |
@@ -1221,7 +1279,13 @@ iwl_dbgfs_prph_reg_write(struct iwl_mvm *mvm, char *buf, | |||
1221 | if (args != 2) | 1279 | if (args != 2) |
1222 | return -EINVAL; | 1280 | return -EINVAL; |
1223 | 1281 | ||
1282 | ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PRPH_WRITE); | ||
1283 | if (ret) | ||
1284 | return ret; | ||
1285 | |||
1224 | iwl_write_prph(mvm->trans, mvm->dbgfs_prph_reg_addr, value); | 1286 | iwl_write_prph(mvm->trans, mvm->dbgfs_prph_reg_addr, value); |
1287 | |||
1288 | iwl_mvm_unref(mvm, IWL_MVM_REF_PRPH_WRITE); | ||
1225 | out: | 1289 | out: |
1226 | return count; | 1290 | return count; |
1227 | } | 1291 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h index ab12aaa43034..69875716dcdb 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h | |||
@@ -385,6 +385,8 @@ enum iwl_bt_activity_grading { | |||
385 | BT_ON_NO_CONNECTION = 1, | 385 | BT_ON_NO_CONNECTION = 1, |
386 | BT_LOW_TRAFFIC = 2, | 386 | BT_LOW_TRAFFIC = 2, |
387 | BT_HIGH_TRAFFIC = 3, | 387 | BT_HIGH_TRAFFIC = 3, |
388 | |||
389 | BT_MAX_AG, | ||
388 | }; /* BT_COEX_BT_ACTIVITY_GRADING_API_E_VER_1 */ | 390 | }; /* BT_COEX_BT_ACTIVITY_GRADING_API_E_VER_1 */ |
389 | 391 | ||
390 | enum iwl_bt_ci_compliance { | 392 | enum iwl_bt_ci_compliance { |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h index b8e4e78d601b..95f5b3274efb 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h | |||
@@ -133,6 +133,7 @@ enum { | |||
133 | /* Scan offload */ | 133 | /* Scan offload */ |
134 | SCAN_OFFLOAD_REQUEST_CMD = 0x51, | 134 | SCAN_OFFLOAD_REQUEST_CMD = 0x51, |
135 | SCAN_OFFLOAD_ABORT_CMD = 0x52, | 135 | SCAN_OFFLOAD_ABORT_CMD = 0x52, |
136 | HOT_SPOT_CMD = 0x53, | ||
136 | SCAN_OFFLOAD_COMPLETE = 0x6D, | 137 | SCAN_OFFLOAD_COMPLETE = 0x6D, |
137 | SCAN_OFFLOAD_UPDATE_PROFILES_CMD = 0x6E, | 138 | SCAN_OFFLOAD_UPDATE_PROFILES_CMD = 0x6E, |
138 | SCAN_OFFLOAD_CONFIG_CMD = 0x6f, | 139 | SCAN_OFFLOAD_CONFIG_CMD = 0x6f, |
@@ -910,6 +911,72 @@ struct iwl_phy_context_cmd { | |||
910 | __le32 dsp_cfg_flags; | 911 | __le32 dsp_cfg_flags; |
911 | } __packed; /* PHY_CONTEXT_CMD_API_VER_1 */ | 912 | } __packed; /* PHY_CONTEXT_CMD_API_VER_1 */ |
912 | 913 | ||
914 | /* | ||
915 | * Aux ROC command | ||
916 | * | ||
917 | * Command requests the firmware to create a time event for a certain duration | ||
918 | * and remain on the given channel. This is done by using the Aux framework in | ||
919 | * the FW. | ||
920 | * The command was first used for Hot Spot issues - but can be used regardless | ||
921 | * to Hot Spot. | ||
922 | * | ||
923 | * ( HOT_SPOT_CMD 0x53 ) | ||
924 | * | ||
925 | * @id_and_color: ID and color of the MAC | ||
926 | * @action: action to perform, one of FW_CTXT_ACTION_* | ||
927 | * @event_unique_id: If the action FW_CTXT_ACTION_REMOVE then the | ||
928 | * event_unique_id should be the id of the time event assigned by ucode. | ||
929 | * Otherwise ignore the event_unique_id. | ||
930 | * @sta_id_and_color: station id and color, resumed during "Remain On Channel" | ||
931 | * activity. | ||
932 | * @channel_info: channel info | ||
933 | * @node_addr: Our MAC Address | ||
934 | * @reserved: reserved for alignment | ||
935 | * @apply_time: GP2 value to start (should always be the current GP2 value) | ||
936 | * @apply_time_max_delay: Maximum apply time delay value in TU. Defines max | ||
937 | * time by which start of the event is allowed to be postponed. | ||
938 | * @duration: event duration in TU To calculate event duration: | ||
939 | * timeEventDuration = min(duration, remainingQuota) | ||
940 | */ | ||
941 | struct iwl_hs20_roc_req { | ||
942 | /* COMMON_INDEX_HDR_API_S_VER_1 hdr */ | ||
943 | __le32 id_and_color; | ||
944 | __le32 action; | ||
945 | __le32 event_unique_id; | ||
946 | __le32 sta_id_and_color; | ||
947 | struct iwl_fw_channel_info channel_info; | ||
948 | u8 node_addr[ETH_ALEN]; | ||
949 | __le16 reserved; | ||
950 | __le32 apply_time; | ||
951 | __le32 apply_time_max_delay; | ||
952 | __le32 duration; | ||
953 | } __packed; /* HOT_SPOT_CMD_API_S_VER_1 */ | ||
954 | |||
955 | /* | ||
956 | * values for AUX ROC result values | ||
957 | */ | ||
958 | enum iwl_mvm_hot_spot { | ||
959 | HOT_SPOT_RSP_STATUS_OK, | ||
960 | HOT_SPOT_RSP_STATUS_TOO_MANY_EVENTS, | ||
961 | HOT_SPOT_MAX_NUM_OF_SESSIONS, | ||
962 | }; | ||
963 | |||
964 | /* | ||
965 | * Aux ROC command response | ||
966 | * | ||
967 | * In response to iwl_hs20_roc_req the FW sends this command to notify the | ||
968 | * driver the uid of the timevent. | ||
969 | * | ||
970 | * ( HOT_SPOT_CMD 0x53 ) | ||
971 | * | ||
972 | * @event_unique_id: Unique ID of time event assigned by ucode | ||
973 | * @status: Return status 0 is success, all the rest used for specific errors | ||
974 | */ | ||
975 | struct iwl_hs20_roc_res { | ||
976 | __le32 event_unique_id; | ||
977 | __le32 status; | ||
978 | } __packed; /* HOT_SPOT_RSP_API_S_VER_1 */ | ||
979 | |||
913 | #define IWL_RX_INFO_PHY_CNT 8 | 980 | #define IWL_RX_INFO_PHY_CNT 8 |
914 | #define IWL_RX_INFO_ENERGY_ANT_ABC_IDX 1 | 981 | #define IWL_RX_INFO_ENERGY_ANT_ABC_IDX 1 |
915 | #define IWL_RX_INFO_ENERGY_ANT_A_MSK 0x000000ff | 982 | #define IWL_RX_INFO_ENERGY_ANT_A_MSK 0x000000ff |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c index 96b9cf8137e7..0e523e28cabf 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | |||
@@ -1074,8 +1074,12 @@ static int iwl_mvm_mac_ctxt_cmd_ap(struct iwl_mvm *mvm, | |||
1074 | /* Fill the common data for all mac context types */ | 1074 | /* Fill the common data for all mac context types */ |
1075 | iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); | 1075 | iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); |
1076 | 1076 | ||
1077 | /* Also enable probe requests to pass */ | 1077 | /* |
1078 | cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST); | 1078 | * pass probe requests and beacons from other APs (needed |
1079 | * for ht protection) | ||
1080 | */ | ||
1081 | cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST | | ||
1082 | MAC_FILTER_IN_BEACON); | ||
1079 | 1083 | ||
1080 | /* Fill the data specific for ap mode */ | 1084 | /* Fill the data specific for ap mode */ |
1081 | iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.ap, | 1085 | iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.ap, |
@@ -1096,6 +1100,13 @@ static int iwl_mvm_mac_ctxt_cmd_go(struct iwl_mvm *mvm, | |||
1096 | /* Fill the common data for all mac context types */ | 1100 | /* Fill the common data for all mac context types */ |
1097 | iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); | 1101 | iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); |
1098 | 1102 | ||
1103 | /* | ||
1104 | * pass probe requests and beacons from other APs (needed | ||
1105 | * for ht protection) | ||
1106 | */ | ||
1107 | cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST | | ||
1108 | MAC_FILTER_IN_BEACON); | ||
1109 | |||
1099 | /* Fill the data specific for GO mode */ | 1110 | /* Fill the data specific for GO mode */ |
1100 | iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.go.ap, | 1111 | iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.go.ap, |
1101 | action == FW_CTXT_ACTION_ADD); | 1112 | action == FW_CTXT_ACTION_ADD); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 2eb6ebee4467..0d6a8b768a68 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
@@ -211,7 +211,9 @@ void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type) | |||
211 | return; | 211 | return; |
212 | 212 | ||
213 | IWL_DEBUG_RPM(mvm, "Take mvm reference - type %d\n", ref_type); | 213 | IWL_DEBUG_RPM(mvm, "Take mvm reference - type %d\n", ref_type); |
214 | WARN_ON(test_and_set_bit(ref_type, mvm->ref_bitmap)); | 214 | spin_lock_bh(&mvm->refs_lock); |
215 | mvm->refs[ref_type]++; | ||
216 | spin_unlock_bh(&mvm->refs_lock); | ||
215 | iwl_trans_ref(mvm->trans); | 217 | iwl_trans_ref(mvm->trans); |
216 | } | 218 | } |
217 | 219 | ||
@@ -221,29 +223,35 @@ void iwl_mvm_unref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type) | |||
221 | return; | 223 | return; |
222 | 224 | ||
223 | IWL_DEBUG_RPM(mvm, "Leave mvm reference - type %d\n", ref_type); | 225 | IWL_DEBUG_RPM(mvm, "Leave mvm reference - type %d\n", ref_type); |
224 | WARN_ON(!test_and_clear_bit(ref_type, mvm->ref_bitmap)); | 226 | spin_lock_bh(&mvm->refs_lock); |
227 | WARN_ON(!mvm->refs[ref_type]--); | ||
228 | spin_unlock_bh(&mvm->refs_lock); | ||
225 | iwl_trans_unref(mvm->trans); | 229 | iwl_trans_unref(mvm->trans); |
226 | } | 230 | } |
227 | 231 | ||
228 | static void | 232 | static void iwl_mvm_unref_all_except(struct iwl_mvm *mvm, |
229 | iwl_mvm_unref_all_except(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref) | 233 | enum iwl_mvm_ref_type except_ref) |
230 | { | 234 | { |
231 | int i; | 235 | int i, j; |
232 | 236 | ||
233 | if (!iwl_mvm_is_d0i3_supported(mvm)) | 237 | if (!iwl_mvm_is_d0i3_supported(mvm)) |
234 | return; | 238 | return; |
235 | 239 | ||
236 | for_each_set_bit(i, mvm->ref_bitmap, IWL_MVM_REF_COUNT) { | 240 | spin_lock_bh(&mvm->refs_lock); |
237 | if (ref == i) | 241 | for (i = 0; i < IWL_MVM_REF_COUNT; i++) { |
242 | if (except_ref == i || !mvm->refs[i]) | ||
238 | continue; | 243 | continue; |
239 | 244 | ||
240 | IWL_DEBUG_RPM(mvm, "Cleanup: remove mvm ref type %d\n", i); | 245 | IWL_DEBUG_RPM(mvm, "Cleanup: remove mvm ref type %d (%d)\n", |
241 | clear_bit(i, mvm->ref_bitmap); | 246 | i, mvm->refs[i]); |
242 | iwl_trans_unref(mvm->trans); | 247 | for (j = 0; j < mvm->refs[i]; j++) |
248 | iwl_trans_unref(mvm->trans); | ||
249 | mvm->refs[i] = 0; | ||
243 | } | 250 | } |
251 | spin_unlock_bh(&mvm->refs_lock); | ||
244 | } | 252 | } |
245 | 253 | ||
246 | static int iwl_mvm_ref_sync(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type) | 254 | int iwl_mvm_ref_sync(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type) |
247 | { | 255 | { |
248 | iwl_mvm_ref(mvm, ref_type); | 256 | iwl_mvm_ref(mvm, ref_type); |
249 | 257 | ||
@@ -321,13 +329,6 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
321 | hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP; | 329 | hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP; |
322 | } | 330 | } |
323 | 331 | ||
324 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT && | ||
325 | !iwlwifi_mod_params.uapsd_disable) { | ||
326 | hw->flags |= IEEE80211_HW_SUPPORTS_UAPSD; | ||
327 | hw->uapsd_queues = IWL_UAPSD_AC_INFO; | ||
328 | hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP; | ||
329 | } | ||
330 | |||
331 | if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN) | 332 | if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN) |
332 | hw->flags |= IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS; | 333 | hw->flags |= IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS; |
333 | 334 | ||
@@ -660,6 +661,7 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac, | |||
660 | spin_unlock_bh(&mvm->time_event_lock); | 661 | spin_unlock_bh(&mvm->time_event_lock); |
661 | 662 | ||
662 | mvmvif->phy_ctxt = NULL; | 663 | mvmvif->phy_ctxt = NULL; |
664 | memset(&mvmvif->bf_data, 0, sizeof(mvmvif->bf_data)); | ||
663 | } | 665 | } |
664 | 666 | ||
665 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 667 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
@@ -668,11 +670,11 @@ static void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) | |||
668 | struct iwl_fw_error_dump_file *dump_file; | 670 | struct iwl_fw_error_dump_file *dump_file; |
669 | struct iwl_fw_error_dump_data *dump_data; | 671 | struct iwl_fw_error_dump_data *dump_data; |
670 | struct iwl_fw_error_dump_info *dump_info; | 672 | struct iwl_fw_error_dump_info *dump_info; |
673 | struct iwl_mvm_dump_ptrs *fw_error_dump; | ||
671 | const struct fw_img *img; | 674 | const struct fw_img *img; |
672 | u32 sram_len, sram_ofs; | 675 | u32 sram_len, sram_ofs; |
673 | u32 file_len, rxf_len; | 676 | u32 file_len, rxf_len; |
674 | unsigned long flags; | 677 | unsigned long flags; |
675 | u32 trans_len; | ||
676 | int reg_val; | 678 | int reg_val; |
677 | 679 | ||
678 | lockdep_assert_held(&mvm->mutex); | 680 | lockdep_assert_held(&mvm->mutex); |
@@ -680,6 +682,10 @@ static void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) | |||
680 | if (mvm->fw_error_dump) | 682 | if (mvm->fw_error_dump) |
681 | return; | 683 | return; |
682 | 684 | ||
685 | fw_error_dump = kzalloc(sizeof(*mvm->fw_error_dump), GFP_KERNEL); | ||
686 | if (!fw_error_dump) | ||
687 | return; | ||
688 | |||
683 | img = &mvm->fw->img[mvm->cur_ucode]; | 689 | img = &mvm->fw->img[mvm->cur_ucode]; |
684 | sram_ofs = img->sec[IWL_UCODE_SECTION_DATA].offset; | 690 | sram_ofs = img->sec[IWL_UCODE_SECTION_DATA].offset; |
685 | sram_len = img->sec[IWL_UCODE_SECTION_DATA].len; | 691 | sram_len = img->sec[IWL_UCODE_SECTION_DATA].len; |
@@ -697,18 +703,15 @@ static void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) | |||
697 | rxf_len + | 703 | rxf_len + |
698 | sizeof(*dump_info); | 704 | sizeof(*dump_info); |
699 | 705 | ||
700 | trans_len = iwl_trans_dump_data(mvm->trans, NULL, 0); | ||
701 | if (trans_len) | ||
702 | file_len += trans_len; | ||
703 | |||
704 | dump_file = vzalloc(file_len); | 706 | dump_file = vzalloc(file_len); |
705 | if (!dump_file) | 707 | if (!dump_file) { |
708 | kfree(fw_error_dump); | ||
706 | return; | 709 | return; |
710 | } | ||
707 | 711 | ||
708 | mvm->fw_error_dump = dump_file; | 712 | fw_error_dump->op_mode_ptr = dump_file; |
709 | 713 | ||
710 | dump_file->barker = cpu_to_le32(IWL_FW_ERROR_DUMP_BARKER); | 714 | dump_file->barker = cpu_to_le32(IWL_FW_ERROR_DUMP_BARKER); |
711 | dump_file->file_len = cpu_to_le32(file_len); | ||
712 | dump_data = (void *)dump_file->data; | 715 | dump_data = (void *)dump_file->data; |
713 | 716 | ||
714 | dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_DEV_FW_INFO); | 717 | dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_DEV_FW_INFO); |
@@ -749,14 +752,12 @@ static void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) | |||
749 | iwl_trans_read_mem_bytes(mvm->trans, sram_ofs, dump_data->data, | 752 | iwl_trans_read_mem_bytes(mvm->trans, sram_ofs, dump_data->data, |
750 | sram_len); | 753 | sram_len); |
751 | 754 | ||
752 | if (trans_len) { | 755 | fw_error_dump->trans_ptr = iwl_trans_dump_data(mvm->trans); |
753 | void *buf = iwl_fw_error_next_data(dump_data); | 756 | fw_error_dump->op_mode_len = file_len; |
754 | u32 real_trans_len = iwl_trans_dump_data(mvm->trans, buf, | 757 | if (fw_error_dump->trans_ptr) |
755 | trans_len); | 758 | file_len += fw_error_dump->trans_ptr->len; |
756 | dump_data = (void *)((u8 *)buf + real_trans_len); | 759 | dump_file->file_len = cpu_to_le32(file_len); |
757 | dump_file->file_len = | 760 | mvm->fw_error_dump = fw_error_dump; |
758 | cpu_to_le32(file_len - trans_len + real_trans_len); | ||
759 | } | ||
760 | } | 761 | } |
761 | #endif | 762 | #endif |
762 | 763 | ||
@@ -788,6 +789,12 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm) | |||
788 | iwl_mvm_reset_phy_ctxts(mvm); | 789 | iwl_mvm_reset_phy_ctxts(mvm); |
789 | memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table)); | 790 | memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table)); |
790 | memset(mvm->sta_drained, 0, sizeof(mvm->sta_drained)); | 791 | memset(mvm->sta_drained, 0, sizeof(mvm->sta_drained)); |
792 | memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif)); | ||
793 | memset(&mvm->last_bt_notif_old, 0, sizeof(mvm->last_bt_notif_old)); | ||
794 | memset(&mvm->last_bt_ci_cmd, 0, sizeof(mvm->last_bt_ci_cmd)); | ||
795 | memset(&mvm->last_bt_ci_cmd_old, 0, sizeof(mvm->last_bt_ci_cmd_old)); | ||
796 | memset(&mvm->bt_ack_kill_msk, 0, sizeof(mvm->bt_ack_kill_msk)); | ||
797 | memset(&mvm->bt_cts_kill_msk, 0, sizeof(mvm->bt_cts_kill_msk)); | ||
791 | 798 | ||
792 | ieee80211_wake_queues(mvm->hw); | 799 | ieee80211_wake_queues(mvm->hw); |
793 | 800 | ||
@@ -1399,6 +1406,28 @@ static inline int iwl_mvm_configure_bcast_filter(struct iwl_mvm *mvm, | |||
1399 | } | 1406 | } |
1400 | #endif | 1407 | #endif |
1401 | 1408 | ||
1409 | static void iwl_mvm_teardown_tdls_peers(struct iwl_mvm *mvm) | ||
1410 | { | ||
1411 | struct ieee80211_sta *sta; | ||
1412 | struct iwl_mvm_sta *mvmsta; | ||
1413 | int i; | ||
1414 | |||
1415 | lockdep_assert_held(&mvm->mutex); | ||
1416 | |||
1417 | for (i = 0; i < IWL_MVM_STATION_COUNT; i++) { | ||
1418 | sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i], | ||
1419 | lockdep_is_held(&mvm->mutex)); | ||
1420 | if (!sta || IS_ERR(sta) || !sta->tdls) | ||
1421 | continue; | ||
1422 | |||
1423 | mvmsta = iwl_mvm_sta_from_mac80211(sta); | ||
1424 | ieee80211_tdls_oper_request(mvmsta->vif, sta->addr, | ||
1425 | NL80211_TDLS_TEARDOWN, | ||
1426 | WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED, | ||
1427 | GFP_KERNEL); | ||
1428 | } | ||
1429 | } | ||
1430 | |||
1402 | static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | 1431 | static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, |
1403 | struct ieee80211_vif *vif, | 1432 | struct ieee80211_vif *vif, |
1404 | struct ieee80211_bss_conf *bss_conf, | 1433 | struct ieee80211_bss_conf *bss_conf, |
@@ -1494,14 +1523,18 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | |||
1494 | */ | 1523 | */ |
1495 | iwl_mvm_remove_time_event(mvm, mvmvif, | 1524 | iwl_mvm_remove_time_event(mvm, mvmvif, |
1496 | &mvmvif->time_event_data); | 1525 | &mvmvif->time_event_data); |
1497 | iwl_mvm_sf_update(mvm, vif, false); | ||
1498 | WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0)); | ||
1499 | } else if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS | | 1526 | } else if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS | |
1500 | BSS_CHANGED_QOS)) { | 1527 | BSS_CHANGED_QOS)) { |
1501 | ret = iwl_mvm_power_update_mac(mvm); | 1528 | ret = iwl_mvm_power_update_mac(mvm); |
1502 | if (ret) | 1529 | if (ret) |
1503 | IWL_ERR(mvm, "failed to update power mode\n"); | 1530 | IWL_ERR(mvm, "failed to update power mode\n"); |
1504 | } | 1531 | } |
1532 | |||
1533 | if (changes & BSS_CHANGED_BEACON_INFO) { | ||
1534 | iwl_mvm_sf_update(mvm, vif, false); | ||
1535 | WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0)); | ||
1536 | } | ||
1537 | |||
1505 | if (changes & BSS_CHANGED_TXPOWER) { | 1538 | if (changes & BSS_CHANGED_TXPOWER) { |
1506 | IWL_DEBUG_CALIB(mvm, "Changing TX Power to %d\n", | 1539 | IWL_DEBUG_CALIB(mvm, "Changing TX Power to %d\n", |
1507 | bss_conf->txpower); | 1540 | bss_conf->txpower); |
@@ -1533,6 +1566,14 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw, | |||
1533 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 1566 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
1534 | int ret; | 1567 | int ret; |
1535 | 1568 | ||
1569 | /* | ||
1570 | * iwl_mvm_mac_ctxt_add() might read directly from the device | ||
1571 | * (the system time), so make sure it is available. | ||
1572 | */ | ||
1573 | ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_START_AP); | ||
1574 | if (ret) | ||
1575 | return ret; | ||
1576 | |||
1536 | mutex_lock(&mvm->mutex); | 1577 | mutex_lock(&mvm->mutex); |
1537 | 1578 | ||
1538 | /* Send the beacon template */ | 1579 | /* Send the beacon template */ |
@@ -1581,6 +1622,10 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw, | |||
1581 | 1622 | ||
1582 | iwl_mvm_bt_coex_vif_change(mvm); | 1623 | iwl_mvm_bt_coex_vif_change(mvm); |
1583 | 1624 | ||
1625 | /* we don't support TDLS during DCM */ | ||
1626 | if (iwl_mvm_phy_ctx_count(mvm) > 1) | ||
1627 | iwl_mvm_teardown_tdls_peers(mvm); | ||
1628 | |||
1584 | mutex_unlock(&mvm->mutex); | 1629 | mutex_unlock(&mvm->mutex); |
1585 | return 0; | 1630 | return 0; |
1586 | 1631 | ||
@@ -1594,6 +1639,7 @@ out_remove: | |||
1594 | iwl_mvm_mac_ctxt_remove(mvm, vif); | 1639 | iwl_mvm_mac_ctxt_remove(mvm, vif); |
1595 | out_unlock: | 1640 | out_unlock: |
1596 | mutex_unlock(&mvm->mutex); | 1641 | mutex_unlock(&mvm->mutex); |
1642 | iwl_mvm_unref(mvm, IWL_MVM_REF_START_AP); | ||
1597 | return ret; | 1643 | return ret; |
1598 | } | 1644 | } |
1599 | 1645 | ||
@@ -1671,6 +1717,14 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw, | |||
1671 | { | 1717 | { |
1672 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 1718 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
1673 | 1719 | ||
1720 | /* | ||
1721 | * iwl_mvm_bss_info_changed_station() might call | ||
1722 | * iwl_mvm_protect_session(), which reads directly from | ||
1723 | * the device (the system time), so make sure it is available. | ||
1724 | */ | ||
1725 | if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_BSS_CHANGED)) | ||
1726 | return; | ||
1727 | |||
1674 | mutex_lock(&mvm->mutex); | 1728 | mutex_lock(&mvm->mutex); |
1675 | 1729 | ||
1676 | if (changes & BSS_CHANGED_IDLE && !bss_conf->idle) | 1730 | if (changes & BSS_CHANGED_IDLE && !bss_conf->idle) |
@@ -1690,8 +1744,50 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw, | |||
1690 | } | 1744 | } |
1691 | 1745 | ||
1692 | mutex_unlock(&mvm->mutex); | 1746 | mutex_unlock(&mvm->mutex); |
1747 | iwl_mvm_unref(mvm, IWL_MVM_REF_BSS_CHANGED); | ||
1693 | } | 1748 | } |
1694 | 1749 | ||
1750 | static int iwl_mvm_cancel_scan_wait_notif(struct iwl_mvm *mvm, | ||
1751 | enum iwl_scan_status scan_type) | ||
1752 | { | ||
1753 | int ret; | ||
1754 | bool wait_for_handlers = false; | ||
1755 | |||
1756 | mutex_lock(&mvm->mutex); | ||
1757 | |||
1758 | if (mvm->scan_status != scan_type) { | ||
1759 | ret = 0; | ||
1760 | /* make sure there are no pending notifications */ | ||
1761 | wait_for_handlers = true; | ||
1762 | goto out; | ||
1763 | } | ||
1764 | |||
1765 | switch (scan_type) { | ||
1766 | case IWL_MVM_SCAN_SCHED: | ||
1767 | ret = iwl_mvm_scan_offload_stop(mvm, true); | ||
1768 | break; | ||
1769 | case IWL_MVM_SCAN_OS: | ||
1770 | ret = iwl_mvm_cancel_scan(mvm); | ||
1771 | break; | ||
1772 | case IWL_MVM_SCAN_NONE: | ||
1773 | default: | ||
1774 | WARN_ON_ONCE(1); | ||
1775 | ret = -EINVAL; | ||
1776 | break; | ||
1777 | } | ||
1778 | if (ret) | ||
1779 | goto out; | ||
1780 | |||
1781 | wait_for_handlers = true; | ||
1782 | out: | ||
1783 | mutex_unlock(&mvm->mutex); | ||
1784 | |||
1785 | /* make sure we consume the completion notification */ | ||
1786 | if (wait_for_handlers) | ||
1787 | iwl_mvm_wait_for_async_handlers(mvm); | ||
1788 | |||
1789 | return ret; | ||
1790 | } | ||
1695 | static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw, | 1791 | static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw, |
1696 | struct ieee80211_vif *vif, | 1792 | struct ieee80211_vif *vif, |
1697 | struct ieee80211_scan_request *hw_req) | 1793 | struct ieee80211_scan_request *hw_req) |
@@ -1704,19 +1800,13 @@ static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw, | |||
1704 | req->n_channels > mvm->fw->ucode_capa.n_scan_channels) | 1800 | req->n_channels > mvm->fw->ucode_capa.n_scan_channels) |
1705 | return -EINVAL; | 1801 | return -EINVAL; |
1706 | 1802 | ||
1803 | ret = iwl_mvm_cancel_scan_wait_notif(mvm, IWL_MVM_SCAN_SCHED); | ||
1804 | if (ret) | ||
1805 | return ret; | ||
1806 | |||
1707 | mutex_lock(&mvm->mutex); | 1807 | mutex_lock(&mvm->mutex); |
1708 | 1808 | ||
1709 | switch (mvm->scan_status) { | 1809 | if (mvm->scan_status != IWL_MVM_SCAN_NONE) { |
1710 | case IWL_MVM_SCAN_SCHED: | ||
1711 | ret = iwl_mvm_scan_offload_stop(mvm, true); | ||
1712 | if (ret) { | ||
1713 | ret = -EBUSY; | ||
1714 | goto out; | ||
1715 | } | ||
1716 | break; | ||
1717 | case IWL_MVM_SCAN_NONE: | ||
1718 | break; | ||
1719 | default: | ||
1720 | ret = -EBUSY; | 1810 | ret = -EBUSY; |
1721 | goto out; | 1811 | goto out; |
1722 | } | 1812 | } |
@@ -1732,8 +1822,6 @@ static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw, | |||
1732 | iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); | 1822 | iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); |
1733 | out: | 1823 | out: |
1734 | mutex_unlock(&mvm->mutex); | 1824 | mutex_unlock(&mvm->mutex); |
1735 | /* make sure to flush the Rx handler before the next scan arrives */ | ||
1736 | iwl_mvm_wait_for_async_handlers(mvm); | ||
1737 | return ret; | 1825 | return ret; |
1738 | } | 1826 | } |
1739 | 1827 | ||
@@ -1885,28 +1973,6 @@ static void iwl_mvm_recalc_tdls_state(struct iwl_mvm *mvm, | |||
1885 | iwl_mvm_power_update_mac(mvm); | 1973 | iwl_mvm_power_update_mac(mvm); |
1886 | } | 1974 | } |
1887 | 1975 | ||
1888 | static void iwl_mvm_teardown_tdls_peers(struct iwl_mvm *mvm) | ||
1889 | { | ||
1890 | struct ieee80211_sta *sta; | ||
1891 | struct iwl_mvm_sta *mvmsta; | ||
1892 | int i; | ||
1893 | |||
1894 | lockdep_assert_held(&mvm->mutex); | ||
1895 | |||
1896 | for (i = 0; i < IWL_MVM_STATION_COUNT; i++) { | ||
1897 | sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i], | ||
1898 | lockdep_is_held(&mvm->mutex)); | ||
1899 | if (!sta || IS_ERR(sta) || !sta->tdls) | ||
1900 | continue; | ||
1901 | |||
1902 | mvmsta = iwl_mvm_sta_from_mac80211(sta); | ||
1903 | ieee80211_tdls_oper_request(mvmsta->vif, sta->addr, | ||
1904 | NL80211_TDLS_TEARDOWN, | ||
1905 | WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED, | ||
1906 | GFP_KERNEL); | ||
1907 | } | ||
1908 | } | ||
1909 | |||
1910 | static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, | 1976 | static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, |
1911 | struct ieee80211_vif *vif, | 1977 | struct ieee80211_vif *vif, |
1912 | struct ieee80211_sta *sta, | 1978 | struct ieee80211_sta *sta, |
@@ -2065,10 +2131,19 @@ static void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw, | |||
2065 | if (WARN_ON_ONCE(vif->bss_conf.assoc)) | 2131 | if (WARN_ON_ONCE(vif->bss_conf.assoc)) |
2066 | return; | 2132 | return; |
2067 | 2133 | ||
2134 | /* | ||
2135 | * iwl_mvm_protect_session() reads directly from the device | ||
2136 | * (the system time), so make sure it is available. | ||
2137 | */ | ||
2138 | if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PREPARE_TX)) | ||
2139 | return; | ||
2140 | |||
2068 | mutex_lock(&mvm->mutex); | 2141 | mutex_lock(&mvm->mutex); |
2069 | /* Try really hard to protect the session and hear a beacon */ | 2142 | /* Try really hard to protect the session and hear a beacon */ |
2070 | iwl_mvm_protect_session(mvm, vif, duration, min_duration, 500); | 2143 | iwl_mvm_protect_session(mvm, vif, duration, min_duration, 500); |
2071 | mutex_unlock(&mvm->mutex); | 2144 | mutex_unlock(&mvm->mutex); |
2145 | |||
2146 | iwl_mvm_unref(mvm, IWL_MVM_REF_PREPARE_TX); | ||
2072 | } | 2147 | } |
2073 | 2148 | ||
2074 | static void iwl_mvm_mac_mgd_protect_tdls_discover(struct ieee80211_hw *hw, | 2149 | static void iwl_mvm_mac_mgd_protect_tdls_discover(struct ieee80211_hw *hw, |
@@ -2077,10 +2152,19 @@ static void iwl_mvm_mac_mgd_protect_tdls_discover(struct ieee80211_hw *hw, | |||
2077 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 2152 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
2078 | u32 duration = 2 * vif->bss_conf.dtim_period * vif->bss_conf.beacon_int; | 2153 | u32 duration = 2 * vif->bss_conf.dtim_period * vif->bss_conf.beacon_int; |
2079 | 2154 | ||
2155 | /* | ||
2156 | * iwl_mvm_protect_session() reads directly from the device | ||
2157 | * (the system time), so make sure it is available. | ||
2158 | */ | ||
2159 | if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PROTECT_TDLS)) | ||
2160 | return; | ||
2161 | |||
2080 | mutex_lock(&mvm->mutex); | 2162 | mutex_lock(&mvm->mutex); |
2081 | /* Protect the session to hear the TDLS setup response on the channel */ | 2163 | /* Protect the session to hear the TDLS setup response on the channel */ |
2082 | iwl_mvm_protect_session(mvm, vif, duration, duration, 100); | 2164 | iwl_mvm_protect_session(mvm, vif, duration, duration, 100); |
2083 | mutex_unlock(&mvm->mutex); | 2165 | mutex_unlock(&mvm->mutex); |
2166 | |||
2167 | iwl_mvm_unref(mvm, IWL_MVM_REF_PROTECT_TDLS); | ||
2084 | } | 2168 | } |
2085 | 2169 | ||
2086 | static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw, | 2170 | static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw, |
@@ -2091,6 +2175,10 @@ static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw, | |||
2091 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 2175 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
2092 | int ret; | 2176 | int ret; |
2093 | 2177 | ||
2178 | ret = iwl_mvm_cancel_scan_wait_notif(mvm, IWL_MVM_SCAN_OS); | ||
2179 | if (ret) | ||
2180 | return ret; | ||
2181 | |||
2094 | mutex_lock(&mvm->mutex); | 2182 | mutex_lock(&mvm->mutex); |
2095 | 2183 | ||
2096 | if (!iwl_mvm_is_idle(mvm)) { | 2184 | if (!iwl_mvm_is_idle(mvm)) { |
@@ -2098,26 +2186,7 @@ static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw, | |||
2098 | goto out; | 2186 | goto out; |
2099 | } | 2187 | } |
2100 | 2188 | ||
2101 | switch (mvm->scan_status) { | 2189 | if (mvm->scan_status != IWL_MVM_SCAN_NONE) { |
2102 | case IWL_MVM_SCAN_OS: | ||
2103 | IWL_DEBUG_SCAN(mvm, "Stopping previous scan for sched_scan\n"); | ||
2104 | ret = iwl_mvm_cancel_scan(mvm); | ||
2105 | if (ret) { | ||
2106 | ret = -EBUSY; | ||
2107 | goto out; | ||
2108 | } | ||
2109 | |||
2110 | /* | ||
2111 | * iwl_mvm_rx_scan_complete() will be called soon but will | ||
2112 | * not reset the scan status as it won't be IWL_MVM_SCAN_OS | ||
2113 | * any more since we queue the next scan immediately (below). | ||
2114 | * We make sure it is called before the next scan starts by | ||
2115 | * flushing the async-handlers work. | ||
2116 | */ | ||
2117 | break; | ||
2118 | case IWL_MVM_SCAN_NONE: | ||
2119 | break; | ||
2120 | default: | ||
2121 | ret = -EBUSY; | 2190 | ret = -EBUSY; |
2122 | goto out; | 2191 | goto out; |
2123 | } | 2192 | } |
@@ -2145,8 +2214,6 @@ err: | |||
2145 | mvm->scan_status = IWL_MVM_SCAN_NONE; | 2214 | mvm->scan_status = IWL_MVM_SCAN_NONE; |
2146 | out: | 2215 | out: |
2147 | mutex_unlock(&mvm->mutex); | 2216 | mutex_unlock(&mvm->mutex); |
2148 | /* make sure to flush the Rx handler before the next scan arrives */ | ||
2149 | iwl_mvm_wait_for_async_handlers(mvm); | ||
2150 | return ret; | 2217 | return ret; |
2151 | } | 2218 | } |
2152 | 2219 | ||
@@ -2266,6 +2333,119 @@ static void iwl_mvm_mac_update_tkip_key(struct ieee80211_hw *hw, | |||
2266 | } | 2333 | } |
2267 | 2334 | ||
2268 | 2335 | ||
2336 | static bool iwl_mvm_rx_aux_roc(struct iwl_notif_wait_data *notif_wait, | ||
2337 | struct iwl_rx_packet *pkt, void *data) | ||
2338 | { | ||
2339 | struct iwl_mvm *mvm = | ||
2340 | container_of(notif_wait, struct iwl_mvm, notif_wait); | ||
2341 | struct iwl_hs20_roc_res *resp; | ||
2342 | int resp_len = iwl_rx_packet_payload_len(pkt); | ||
2343 | struct iwl_mvm_time_event_data *te_data = data; | ||
2344 | |||
2345 | if (WARN_ON(pkt->hdr.cmd != HOT_SPOT_CMD)) | ||
2346 | return true; | ||
2347 | |||
2348 | if (WARN_ON_ONCE(resp_len != sizeof(*resp))) { | ||
2349 | IWL_ERR(mvm, "Invalid HOT_SPOT_CMD response\n"); | ||
2350 | return true; | ||
2351 | } | ||
2352 | |||
2353 | resp = (void *)pkt->data; | ||
2354 | |||
2355 | IWL_DEBUG_TE(mvm, | ||
2356 | "Aux ROC: Recieved response from ucode: status=%d uid=%d\n", | ||
2357 | resp->status, resp->event_unique_id); | ||
2358 | |||
2359 | te_data->uid = le32_to_cpu(resp->event_unique_id); | ||
2360 | IWL_DEBUG_TE(mvm, "TIME_EVENT_CMD response - UID = 0x%x\n", | ||
2361 | te_data->uid); | ||
2362 | |||
2363 | spin_lock_bh(&mvm->time_event_lock); | ||
2364 | list_add_tail(&te_data->list, &mvm->aux_roc_te_list); | ||
2365 | spin_unlock_bh(&mvm->time_event_lock); | ||
2366 | |||
2367 | return true; | ||
2368 | } | ||
2369 | |||
2370 | #define AUX_ROC_MAX_DELAY_ON_CHANNEL 5000 | ||
2371 | static int iwl_mvm_send_aux_roc_cmd(struct iwl_mvm *mvm, | ||
2372 | struct ieee80211_channel *channel, | ||
2373 | struct ieee80211_vif *vif, | ||
2374 | int duration) | ||
2375 | { | ||
2376 | int res, time_reg = DEVICE_SYSTEM_TIME_REG; | ||
2377 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
2378 | struct iwl_mvm_time_event_data *te_data = &mvmvif->hs_time_event_data; | ||
2379 | static const u8 time_event_response[] = { HOT_SPOT_CMD }; | ||
2380 | struct iwl_notification_wait wait_time_event; | ||
2381 | struct iwl_hs20_roc_req aux_roc_req = { | ||
2382 | .action = cpu_to_le32(FW_CTXT_ACTION_ADD), | ||
2383 | .id_and_color = | ||
2384 | cpu_to_le32(FW_CMD_ID_AND_COLOR(MAC_INDEX_AUX, 0)), | ||
2385 | .sta_id_and_color = cpu_to_le32(mvm->aux_sta.sta_id), | ||
2386 | /* Set the channel info data */ | ||
2387 | .channel_info.band = (channel->band == IEEE80211_BAND_2GHZ) ? | ||
2388 | PHY_BAND_24 : PHY_BAND_5, | ||
2389 | .channel_info.channel = channel->hw_value, | ||
2390 | .channel_info.width = PHY_VHT_CHANNEL_MODE20, | ||
2391 | /* Set the time and duration */ | ||
2392 | .apply_time = cpu_to_le32(iwl_read_prph(mvm->trans, time_reg)), | ||
2393 | .apply_time_max_delay = | ||
2394 | cpu_to_le32(MSEC_TO_TU(AUX_ROC_MAX_DELAY_ON_CHANNEL)), | ||
2395 | .duration = cpu_to_le32(MSEC_TO_TU(duration)), | ||
2396 | }; | ||
2397 | |||
2398 | /* Set the node address */ | ||
2399 | memcpy(aux_roc_req.node_addr, vif->addr, ETH_ALEN); | ||
2400 | |||
2401 | te_data->vif = vif; | ||
2402 | te_data->duration = duration; | ||
2403 | te_data->id = HOT_SPOT_CMD; | ||
2404 | |||
2405 | lockdep_assert_held(&mvm->mutex); | ||
2406 | |||
2407 | spin_lock_bh(&mvm->time_event_lock); | ||
2408 | list_add_tail(&te_data->list, &mvm->time_event_list); | ||
2409 | spin_unlock_bh(&mvm->time_event_lock); | ||
2410 | |||
2411 | /* | ||
2412 | * Use a notification wait, which really just processes the | ||
2413 | * command response and doesn't wait for anything, in order | ||
2414 | * to be able to process the response and get the UID inside | ||
2415 | * the RX path. Using CMD_WANT_SKB doesn't work because it | ||
2416 | * stores the buffer and then wakes up this thread, by which | ||
2417 | * time another notification (that the time event started) | ||
2418 | * might already be processed unsuccessfully. | ||
2419 | */ | ||
2420 | iwl_init_notification_wait(&mvm->notif_wait, &wait_time_event, | ||
2421 | time_event_response, | ||
2422 | ARRAY_SIZE(time_event_response), | ||
2423 | iwl_mvm_rx_aux_roc, te_data); | ||
2424 | |||
2425 | res = iwl_mvm_send_cmd_pdu(mvm, HOT_SPOT_CMD, 0, sizeof(aux_roc_req), | ||
2426 | &aux_roc_req); | ||
2427 | |||
2428 | if (res) { | ||
2429 | IWL_ERR(mvm, "Couldn't send HOT_SPOT_CMD: %d\n", res); | ||
2430 | iwl_remove_notification(&mvm->notif_wait, &wait_time_event); | ||
2431 | goto out_clear_te; | ||
2432 | } | ||
2433 | |||
2434 | /* No need to wait for anything, so just pass 1 (0 isn't valid) */ | ||
2435 | res = iwl_wait_notification(&mvm->notif_wait, &wait_time_event, 1); | ||
2436 | /* should never fail */ | ||
2437 | WARN_ON_ONCE(res); | ||
2438 | |||
2439 | if (res) { | ||
2440 | out_clear_te: | ||
2441 | spin_lock_bh(&mvm->time_event_lock); | ||
2442 | iwl_mvm_te_clear_data(mvm, te_data); | ||
2443 | spin_unlock_bh(&mvm->time_event_lock); | ||
2444 | } | ||
2445 | |||
2446 | return res; | ||
2447 | } | ||
2448 | |||
2269 | static int iwl_mvm_roc(struct ieee80211_hw *hw, | 2449 | static int iwl_mvm_roc(struct ieee80211_hw *hw, |
2270 | struct ieee80211_vif *vif, | 2450 | struct ieee80211_vif *vif, |
2271 | struct ieee80211_channel *channel, | 2451 | struct ieee80211_channel *channel, |
@@ -2281,8 +2461,17 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw, | |||
2281 | IWL_DEBUG_MAC80211(mvm, "enter (%d, %d, %d)\n", channel->hw_value, | 2461 | IWL_DEBUG_MAC80211(mvm, "enter (%d, %d, %d)\n", channel->hw_value, |
2282 | duration, type); | 2462 | duration, type); |
2283 | 2463 | ||
2284 | if (vif->type != NL80211_IFTYPE_P2P_DEVICE) { | 2464 | switch (vif->type) { |
2285 | IWL_ERR(mvm, "vif isn't a P2P_DEVICE: %d\n", vif->type); | 2465 | case NL80211_IFTYPE_STATION: |
2466 | /* Use aux roc framework (HS20) */ | ||
2467 | ret = iwl_mvm_send_aux_roc_cmd(mvm, channel, | ||
2468 | vif, duration); | ||
2469 | return ret; | ||
2470 | case NL80211_IFTYPE_P2P_DEVICE: | ||
2471 | /* handle below */ | ||
2472 | break; | ||
2473 | default: | ||
2474 | IWL_ERR(mvm, "vif isn't P2P_DEVICE: %d\n", vif->type); | ||
2286 | return -EINVAL; | 2475 | return -EINVAL; |
2287 | } | 2476 | } |
2288 | 2477 | ||
@@ -2661,6 +2850,10 @@ static int iwl_mvm_switch_vif_chanctx(struct ieee80211_hw *hw, | |||
2661 | goto out_remove; | 2850 | goto out_remove; |
2662 | } | 2851 | } |
2663 | 2852 | ||
2853 | /* we don't support TDLS during DCM - can be caused by channel switch */ | ||
2854 | if (iwl_mvm_phy_ctx_count(mvm) > 1) | ||
2855 | iwl_mvm_teardown_tdls_peers(mvm); | ||
2856 | |||
2664 | goto out; | 2857 | goto out; |
2665 | 2858 | ||
2666 | out_remove: | 2859 | out_remove: |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 785e5232c757..2e73d3bd7757 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h | |||
@@ -82,6 +82,8 @@ | |||
82 | /* RSSI offset for WkP */ | 82 | /* RSSI offset for WkP */ |
83 | #define IWL_RSSI_OFFSET 50 | 83 | #define IWL_RSSI_OFFSET 50 |
84 | #define IWL_MVM_MISSED_BEACONS_THRESHOLD 8 | 84 | #define IWL_MVM_MISSED_BEACONS_THRESHOLD 8 |
85 | /* A TimeUnit is 1024 microsecond */ | ||
86 | #define MSEC_TO_TU(_msec) (_msec*1000/1024) | ||
85 | 87 | ||
86 | /* | 88 | /* |
87 | * The CSA NoA is scheduled IWL_MVM_CHANNEL_SWITCH_TIME TUs before "beacon 0" | 89 | * The CSA NoA is scheduled IWL_MVM_CHANNEL_SWITCH_TIME TUs before "beacon 0" |
@@ -126,6 +128,21 @@ struct iwl_mvm_mod_params { | |||
126 | }; | 128 | }; |
127 | extern struct iwl_mvm_mod_params iwlmvm_mod_params; | 129 | extern struct iwl_mvm_mod_params iwlmvm_mod_params; |
128 | 130 | ||
131 | /** | ||
132 | * struct iwl_mvm_dump_ptrs - set of pointers needed for the fw-error-dump | ||
133 | * | ||
134 | * @op_mode_ptr: pointer to the buffer coming from the mvm op_mode | ||
135 | * @trans_ptr: pointer to struct %iwl_trans_dump_data which contains the | ||
136 | * transport's data. | ||
137 | * @trans_len: length of the valid data in trans_ptr | ||
138 | * @op_mode_len: length of the valid data in op_mode_ptr | ||
139 | */ | ||
140 | struct iwl_mvm_dump_ptrs { | ||
141 | struct iwl_trans_dump_data *trans_ptr; | ||
142 | void *op_mode_ptr; | ||
143 | u32 op_mode_len; | ||
144 | }; | ||
145 | |||
129 | struct iwl_mvm_phy_ctxt { | 146 | struct iwl_mvm_phy_ctxt { |
130 | u16 id; | 147 | u16 id; |
131 | u16 color; | 148 | u16 color; |
@@ -249,6 +266,15 @@ enum iwl_mvm_ref_type { | |||
249 | IWL_MVM_REF_TX, | 266 | IWL_MVM_REF_TX, |
250 | IWL_MVM_REF_TX_AGG, | 267 | IWL_MVM_REF_TX_AGG, |
251 | IWL_MVM_REF_ADD_IF, | 268 | IWL_MVM_REF_ADD_IF, |
269 | IWL_MVM_REF_START_AP, | ||
270 | IWL_MVM_REF_BSS_CHANGED, | ||
271 | IWL_MVM_REF_PREPARE_TX, | ||
272 | IWL_MVM_REF_PROTECT_TDLS, | ||
273 | IWL_MVM_REF_CHECK_CTKILL, | ||
274 | IWL_MVM_REF_PRPH_READ, | ||
275 | IWL_MVM_REF_PRPH_WRITE, | ||
276 | IWL_MVM_REF_NMI, | ||
277 | IWL_MVM_REF_TM_CMD, | ||
252 | IWL_MVM_REF_EXIT_WORK, | 278 | IWL_MVM_REF_EXIT_WORK, |
253 | 279 | ||
254 | IWL_MVM_REF_COUNT, | 280 | IWL_MVM_REF_COUNT, |
@@ -327,6 +353,7 @@ struct iwl_mvm_vif { | |||
327 | */ | 353 | */ |
328 | struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS]; | 354 | struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS]; |
329 | struct iwl_mvm_time_event_data time_event_data; | 355 | struct iwl_mvm_time_event_data time_event_data; |
356 | struct iwl_mvm_time_event_data hs_time_event_data; | ||
330 | 357 | ||
331 | struct iwl_mvm_int_sta bcast_sta; | 358 | struct iwl_mvm_int_sta bcast_sta; |
332 | 359 | ||
@@ -606,14 +633,15 @@ struct iwl_mvm { | |||
606 | */ | 633 | */ |
607 | unsigned long fw_key_table[BITS_TO_LONGS(STA_KEY_MAX_NUM)]; | 634 | unsigned long fw_key_table[BITS_TO_LONGS(STA_KEY_MAX_NUM)]; |
608 | 635 | ||
609 | /* A bitmap of reference types taken by the driver. */ | 636 | /* references taken by the driver and spinlock protecting them */ |
610 | unsigned long ref_bitmap[BITS_TO_LONGS(IWL_MVM_REF_COUNT)]; | 637 | spinlock_t refs_lock; |
638 | u8 refs[IWL_MVM_REF_COUNT]; | ||
611 | 639 | ||
612 | u8 vif_count; | 640 | u8 vif_count; |
613 | 641 | ||
614 | /* -1 for always, 0 for never, >0 for that many times */ | 642 | /* -1 for always, 0 for never, >0 for that many times */ |
615 | s8 restart_fw; | 643 | s8 restart_fw; |
616 | void *fw_error_dump; | 644 | struct iwl_mvm_dump_ptrs *fw_error_dump; |
617 | 645 | ||
618 | #ifdef CONFIG_IWLWIFI_LEDS | 646 | #ifdef CONFIG_IWLWIFI_LEDS |
619 | struct led_classdev led; | 647 | struct led_classdev led; |
@@ -647,7 +675,8 @@ struct iwl_mvm { | |||
647 | wait_queue_head_t d0i3_exit_waitq; | 675 | wait_queue_head_t d0i3_exit_waitq; |
648 | 676 | ||
649 | /* BT-Coex */ | 677 | /* BT-Coex */ |
650 | u8 bt_kill_msk; | 678 | u8 bt_ack_kill_msk[NUM_PHY_CTX]; |
679 | u8 bt_cts_kill_msk[NUM_PHY_CTX]; | ||
651 | 680 | ||
652 | struct iwl_bt_coex_profile_notif_old last_bt_notif_old; | 681 | struct iwl_bt_coex_profile_notif_old last_bt_notif_old; |
653 | struct iwl_bt_coex_ci_cmd_old last_bt_ci_cmd_old; | 682 | struct iwl_bt_coex_ci_cmd_old last_bt_ci_cmd_old; |
@@ -659,6 +688,9 @@ struct iwl_mvm { | |||
659 | u8 bt_tx_prio; | 688 | u8 bt_tx_prio; |
660 | enum iwl_bt_force_ant_mode bt_force_ant_mode; | 689 | enum iwl_bt_force_ant_mode bt_force_ant_mode; |
661 | 690 | ||
691 | /* Aux ROC */ | ||
692 | struct list_head aux_roc_te_list; | ||
693 | |||
662 | /* Thermal Throttling and CTkill */ | 694 | /* Thermal Throttling and CTkill */ |
663 | struct iwl_mvm_tt_mgmt thermal_throttle; | 695 | struct iwl_mvm_tt_mgmt thermal_throttle; |
664 | s32 temperature; /* Celsius */ | 696 | s32 temperature; /* Celsius */ |
@@ -697,6 +729,7 @@ enum iwl_mvm_status { | |||
697 | IWL_MVM_STATUS_ROC_RUNNING, | 729 | IWL_MVM_STATUS_ROC_RUNNING, |
698 | IWL_MVM_STATUS_IN_HW_RESTART, | 730 | IWL_MVM_STATUS_IN_HW_RESTART, |
699 | IWL_MVM_STATUS_IN_D0I3, | 731 | IWL_MVM_STATUS_IN_D0I3, |
732 | IWL_MVM_STATUS_ROC_AUX_RUNNING, | ||
700 | }; | 733 | }; |
701 | 734 | ||
702 | static inline bool iwl_mvm_is_radio_killed(struct iwl_mvm *mvm) | 735 | static inline bool iwl_mvm_is_radio_killed(struct iwl_mvm *mvm) |
@@ -988,6 +1021,7 @@ int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm, | |||
988 | /* D0i3 */ | 1021 | /* D0i3 */ |
989 | void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type); | 1022 | void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type); |
990 | void iwl_mvm_unref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type); | 1023 | void iwl_mvm_unref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type); |
1024 | int iwl_mvm_ref_sync(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type); | ||
991 | void iwl_mvm_d0i3_enable_tx(struct iwl_mvm *mvm, __le16 *qos_seq); | 1025 | void iwl_mvm_d0i3_enable_tx(struct iwl_mvm *mvm, __le16 *qos_seq); |
992 | int _iwl_mvm_exit_d0i3(struct iwl_mvm *mvm); | 1026 | int _iwl_mvm_exit_d0i3(struct iwl_mvm *mvm); |
993 | 1027 | ||
@@ -1029,12 +1063,14 @@ int iwl_mvm_rx_ant_coupling_notif_old(struct iwl_mvm *mvm, | |||
1029 | 1063 | ||
1030 | enum iwl_bt_kill_msk { | 1064 | enum iwl_bt_kill_msk { |
1031 | BT_KILL_MSK_DEFAULT, | 1065 | BT_KILL_MSK_DEFAULT, |
1032 | BT_KILL_MSK_SCO_HID_A2DP, | 1066 | BT_KILL_MSK_NEVER, |
1033 | BT_KILL_MSK_REDUCED_TXPOW, | 1067 | BT_KILL_MSK_ALWAYS, |
1034 | BT_KILL_MSK_MAX, | 1068 | BT_KILL_MSK_MAX, |
1035 | }; | 1069 | }; |
1036 | extern const u32 iwl_bt_ack_kill_msk[BT_KILL_MSK_MAX]; | 1070 | |
1037 | extern const u32 iwl_bt_cts_kill_msk[BT_KILL_MSK_MAX]; | 1071 | extern const u8 iwl_bt_ack_kill_msk[BT_MAX_AG][BT_COEX_MAX_LUT]; |
1072 | extern const u8 iwl_bt_cts_kill_msk[BT_MAX_AG][BT_COEX_MAX_LUT]; | ||
1073 | extern const u32 iwl_bt_ctl_kill_msk[BT_KILL_MSK_MAX]; | ||
1038 | 1074 | ||
1039 | /* beacon filtering */ | 1075 | /* beacon filtering */ |
1040 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 1076 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c index b04805ccb443..cfdd314fdd5d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c | |||
@@ -265,7 +265,7 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm) | |||
265 | if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) { | 265 | if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) { |
266 | if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data || | 266 | if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data || |
267 | !mvm->nvm_sections[mvm->cfg->nvm_hw_section_num].data) { | 267 | !mvm->nvm_sections[mvm->cfg->nvm_hw_section_num].data) { |
268 | IWL_ERR(mvm, "Can't parse empty NVM sections\n"); | 268 | IWL_ERR(mvm, "Can't parse empty OTP/NVM sections\n"); |
269 | return NULL; | 269 | return NULL; |
270 | } | 270 | } |
271 | } else { | 271 | } else { |
@@ -273,7 +273,7 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm) | |||
273 | if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data || | 273 | if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data || |
274 | !mvm->nvm_sections[NVM_SECTION_TYPE_REGULATORY].data) { | 274 | !mvm->nvm_sections[NVM_SECTION_TYPE_REGULATORY].data) { |
275 | IWL_ERR(mvm, | 275 | IWL_ERR(mvm, |
276 | "Can't parse empty family 8000 NVM sections\n"); | 276 | "Can't parse empty family 8000 OTP/NVM sections\n"); |
277 | return NULL; | 277 | return NULL; |
278 | } | 278 | } |
279 | /* MAC_OVERRIDE or at least HW section must exist */ | 279 | /* MAC_OVERRIDE or at least HW section must exist */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index 7d7b2fbe7cd1..610dbcb0dc27 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c | |||
@@ -289,6 +289,7 @@ static const char *const iwl_mvm_cmd_strings[REPLY_MAX] = { | |||
289 | CMD(MATCH_FOUND_NOTIFICATION), | 289 | CMD(MATCH_FOUND_NOTIFICATION), |
290 | CMD(SCAN_OFFLOAD_REQUEST_CMD), | 290 | CMD(SCAN_OFFLOAD_REQUEST_CMD), |
291 | CMD(SCAN_OFFLOAD_ABORT_CMD), | 291 | CMD(SCAN_OFFLOAD_ABORT_CMD), |
292 | CMD(HOT_SPOT_CMD), | ||
292 | CMD(SCAN_OFFLOAD_COMPLETE), | 293 | CMD(SCAN_OFFLOAD_COMPLETE), |
293 | CMD(SCAN_OFFLOAD_UPDATE_PROFILES_CMD), | 294 | CMD(SCAN_OFFLOAD_UPDATE_PROFILES_CMD), |
294 | CMD(SCAN_ITERATION_COMPLETE), | 295 | CMD(SCAN_ITERATION_COMPLETE), |
@@ -391,6 +392,9 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
391 | if (!hw) | 392 | if (!hw) |
392 | return NULL; | 393 | return NULL; |
393 | 394 | ||
395 | if (cfg->max_rx_agg_size) | ||
396 | hw->max_rx_aggregation_subframes = cfg->max_rx_agg_size; | ||
397 | |||
394 | op_mode = hw->priv; | 398 | op_mode = hw->priv; |
395 | op_mode->ops = &iwl_mvm_ops; | 399 | op_mode->ops = &iwl_mvm_ops; |
396 | 400 | ||
@@ -416,6 +420,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
416 | mutex_init(&mvm->d0i3_suspend_mutex); | 420 | mutex_init(&mvm->d0i3_suspend_mutex); |
417 | spin_lock_init(&mvm->async_handlers_lock); | 421 | spin_lock_init(&mvm->async_handlers_lock); |
418 | INIT_LIST_HEAD(&mvm->time_event_list); | 422 | INIT_LIST_HEAD(&mvm->time_event_list); |
423 | INIT_LIST_HEAD(&mvm->aux_roc_te_list); | ||
419 | INIT_LIST_HEAD(&mvm->async_handlers_list); | 424 | INIT_LIST_HEAD(&mvm->async_handlers_list); |
420 | spin_lock_init(&mvm->time_event_lock); | 425 | spin_lock_init(&mvm->time_event_lock); |
421 | 426 | ||
@@ -425,6 +430,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
425 | INIT_WORK(&mvm->d0i3_exit_work, iwl_mvm_d0i3_exit_work); | 430 | INIT_WORK(&mvm->d0i3_exit_work, iwl_mvm_d0i3_exit_work); |
426 | 431 | ||
427 | spin_lock_init(&mvm->d0i3_tx_lock); | 432 | spin_lock_init(&mvm->d0i3_tx_lock); |
433 | spin_lock_init(&mvm->refs_lock); | ||
428 | skb_queue_head_init(&mvm->d0i3_tx); | 434 | skb_queue_head_init(&mvm->d0i3_tx); |
429 | init_waitqueue_head(&mvm->d0i3_exit_waitq); | 435 | init_waitqueue_head(&mvm->d0i3_exit_waitq); |
430 | 436 | ||
@@ -539,7 +545,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
539 | memset(&mvm->rx_stats, 0, sizeof(struct mvm_statistics_rx)); | 545 | memset(&mvm->rx_stats, 0, sizeof(struct mvm_statistics_rx)); |
540 | 546 | ||
541 | /* rpm starts with a taken ref. only set the appropriate bit here. */ | 547 | /* rpm starts with a taken ref. only set the appropriate bit here. */ |
542 | set_bit(IWL_MVM_REF_UCODE_DOWN, mvm->ref_bitmap); | 548 | mvm->refs[IWL_MVM_REF_UCODE_DOWN] = 1; |
543 | 549 | ||
544 | return op_mode; | 550 | return op_mode; |
545 | 551 | ||
@@ -567,7 +573,11 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode) | |||
567 | ieee80211_unregister_hw(mvm->hw); | 573 | ieee80211_unregister_hw(mvm->hw); |
568 | 574 | ||
569 | kfree(mvm->scan_cmd); | 575 | kfree(mvm->scan_cmd); |
570 | vfree(mvm->fw_error_dump); | 576 | if (mvm->fw_error_dump) { |
577 | vfree(mvm->fw_error_dump->op_mode_ptr); | ||
578 | vfree(mvm->fw_error_dump->trans_ptr); | ||
579 | kfree(mvm->fw_error_dump); | ||
580 | } | ||
571 | kfree(mvm->mcast_filter_cmd); | 581 | kfree(mvm->mcast_filter_cmd); |
572 | mvm->mcast_filter_cmd = NULL; | 582 | mvm->mcast_filter_cmd = NULL; |
573 | 583 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index 812813964847..763548880399 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c | |||
@@ -98,23 +98,21 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
98 | bool update) | 98 | bool update) |
99 | { | 99 | { |
100 | struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; | 100 | struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; |
101 | struct iwl_mvm_add_sta_cmd add_sta_cmd; | 101 | struct iwl_mvm_add_sta_cmd add_sta_cmd = { |
102 | .sta_id = mvm_sta->sta_id, | ||
103 | .mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color), | ||
104 | .add_modify = update ? 1 : 0, | ||
105 | .station_flags_msk = cpu_to_le32(STA_FLG_FAT_EN_MSK | | ||
106 | STA_FLG_MIMO_EN_MSK), | ||
107 | }; | ||
102 | int ret; | 108 | int ret; |
103 | u32 status; | 109 | u32 status; |
104 | u32 agg_size = 0, mpdu_dens = 0; | 110 | u32 agg_size = 0, mpdu_dens = 0; |
105 | 111 | ||
106 | memset(&add_sta_cmd, 0, sizeof(add_sta_cmd)); | ||
107 | |||
108 | add_sta_cmd.sta_id = mvm_sta->sta_id; | ||
109 | add_sta_cmd.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color); | ||
110 | if (!update) { | 112 | if (!update) { |
111 | add_sta_cmd.tfd_queue_msk = cpu_to_le32(mvm_sta->tfd_queue_msk); | 113 | add_sta_cmd.tfd_queue_msk = cpu_to_le32(mvm_sta->tfd_queue_msk); |
112 | memcpy(&add_sta_cmd.addr, sta->addr, ETH_ALEN); | 114 | memcpy(&add_sta_cmd.addr, sta->addr, ETH_ALEN); |
113 | } | 115 | } |
114 | add_sta_cmd.add_modify = update ? 1 : 0; | ||
115 | |||
116 | add_sta_cmd.station_flags_msk |= cpu_to_le32(STA_FLG_FAT_EN_MSK | | ||
117 | STA_FLG_MIMO_EN_MSK); | ||
118 | 116 | ||
119 | switch (sta->bandwidth) { | 117 | switch (sta->bandwidth) { |
120 | case IEEE80211_STA_RX_BW_160: | 118 | case IEEE80211_STA_RX_BW_160: |
@@ -528,8 +526,12 @@ int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm) | |||
528 | 526 | ||
529 | lockdep_assert_held(&mvm->mutex); | 527 | lockdep_assert_held(&mvm->mutex); |
530 | 528 | ||
531 | /* Add the aux station, but without any queues */ | 529 | /* Map Aux queue to fifo - needs to happen before adding Aux station */ |
532 | ret = iwl_mvm_allocate_int_sta(mvm, &mvm->aux_sta, 0, | 530 | iwl_trans_ac_txq_enable(mvm->trans, mvm->aux_queue, |
531 | IWL_MVM_TX_FIFO_MCAST); | ||
532 | |||
533 | /* Allocate aux station and assign to it the aux queue */ | ||
534 | ret = iwl_mvm_allocate_int_sta(mvm, &mvm->aux_sta, BIT(mvm->aux_queue), | ||
533 | NL80211_IFTYPE_UNSPECIFIED); | 535 | NL80211_IFTYPE_UNSPECIFIED); |
534 | if (ret) | 536 | if (ret) |
535 | return ret; | 537 | return ret; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c index ae52613b97f2..33e5041f1efc 100644 --- a/drivers/net/wireless/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c | |||
@@ -72,9 +72,6 @@ | |||
72 | #include "iwl-io.h" | 72 | #include "iwl-io.h" |
73 | #include "iwl-prph.h" | 73 | #include "iwl-prph.h" |
74 | 74 | ||
75 | /* A TimeUnit is 1024 microsecond */ | ||
76 | #define MSEC_TO_TU(_msec) (_msec*1000/1024) | ||
77 | |||
78 | /* | 75 | /* |
79 | * For the high priority TE use a time event type that has similar priority to | 76 | * For the high priority TE use a time event type that has similar priority to |
80 | * the FW's action scan priority. | 77 | * the FW's action scan priority. |
@@ -100,6 +97,21 @@ void iwl_mvm_te_clear_data(struct iwl_mvm *mvm, | |||
100 | void iwl_mvm_roc_done_wk(struct work_struct *wk) | 97 | void iwl_mvm_roc_done_wk(struct work_struct *wk) |
101 | { | 98 | { |
102 | struct iwl_mvm *mvm = container_of(wk, struct iwl_mvm, roc_done_wk); | 99 | struct iwl_mvm *mvm = container_of(wk, struct iwl_mvm, roc_done_wk); |
100 | u32 queues = 0; | ||
101 | |||
102 | /* | ||
103 | * Clear the ROC_RUNNING /ROC_AUX_RUNNING status bit. | ||
104 | * This will cause the TX path to drop offchannel transmissions. | ||
105 | * That would also be done by mac80211, but it is racy, in particular | ||
106 | * in the case that the time event actually completed in the firmware | ||
107 | * (which is handled in iwl_mvm_te_handle_notif). | ||
108 | */ | ||
109 | if (test_and_clear_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status)) | ||
110 | queues |= BIT(IWL_MVM_OFFCHANNEL_QUEUE); | ||
111 | if (test_and_clear_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status)) | ||
112 | queues |= BIT(mvm->aux_queue); | ||
113 | |||
114 | iwl_mvm_unref(mvm, IWL_MVM_REF_ROC); | ||
103 | 115 | ||
104 | synchronize_net(); | 116 | synchronize_net(); |
105 | 117 | ||
@@ -113,22 +125,12 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk) | |||
113 | * issue as it will have to complete before the next command is | 125 | * issue as it will have to complete before the next command is |
114 | * executed, and a new time event means a new command. | 126 | * executed, and a new time event means a new command. |
115 | */ | 127 | */ |
116 | iwl_mvm_flush_tx_path(mvm, BIT(IWL_MVM_OFFCHANNEL_QUEUE), false); | 128 | iwl_mvm_flush_tx_path(mvm, queues, false); |
117 | } | 129 | } |
118 | 130 | ||
119 | static void iwl_mvm_roc_finished(struct iwl_mvm *mvm) | 131 | static void iwl_mvm_roc_finished(struct iwl_mvm *mvm) |
120 | { | 132 | { |
121 | /* | 133 | /* |
122 | * First, clear the ROC_RUNNING status bit. This will cause the TX | ||
123 | * path to drop offchannel transmissions. That would also be done | ||
124 | * by mac80211, but it is racy, in particular in the case that the | ||
125 | * time event actually completed in the firmware (which is handled | ||
126 | * in iwl_mvm_te_handle_notif). | ||
127 | */ | ||
128 | clear_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status); | ||
129 | iwl_mvm_unref(mvm, IWL_MVM_REF_ROC); | ||
130 | |||
131 | /* | ||
132 | * Of course, our status bit is just as racy as mac80211, so in | 134 | * Of course, our status bit is just as racy as mac80211, so in |
133 | * addition, fire off the work struct which will drop all frames | 135 | * addition, fire off the work struct which will drop all frames |
134 | * from the hardware queues that made it through the race. First | 136 | * from the hardware queues that made it through the race. First |
@@ -263,6 +265,60 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm, | |||
263 | } | 265 | } |
264 | 266 | ||
265 | /* | 267 | /* |
268 | * Handle A Aux ROC time event | ||
269 | */ | ||
270 | static int iwl_mvm_aux_roc_te_handle_notif(struct iwl_mvm *mvm, | ||
271 | struct iwl_time_event_notif *notif) | ||
272 | { | ||
273 | struct iwl_mvm_time_event_data *te_data, *tmp; | ||
274 | bool aux_roc_te = false; | ||
275 | |||
276 | list_for_each_entry_safe(te_data, tmp, &mvm->aux_roc_te_list, list) { | ||
277 | if (le32_to_cpu(notif->unique_id) == te_data->uid) { | ||
278 | aux_roc_te = true; | ||
279 | break; | ||
280 | } | ||
281 | } | ||
282 | if (!aux_roc_te) /* Not a Aux ROC time event */ | ||
283 | return -EINVAL; | ||
284 | |||
285 | if (!le32_to_cpu(notif->status)) { | ||
286 | IWL_DEBUG_TE(mvm, | ||
287 | "ERROR: Aux ROC Time Event %s notification failure\n", | ||
288 | (le32_to_cpu(notif->action) & | ||
289 | TE_V2_NOTIF_HOST_EVENT_START) ? "start" : "end"); | ||
290 | return -EINVAL; | ||
291 | } | ||
292 | |||
293 | IWL_DEBUG_TE(mvm, | ||
294 | "Aux ROC time event notification - UID = 0x%x action %d\n", | ||
295 | le32_to_cpu(notif->unique_id), | ||
296 | le32_to_cpu(notif->action)); | ||
297 | |||
298 | if (le32_to_cpu(notif->action) == TE_V2_NOTIF_HOST_EVENT_END) { | ||
299 | /* End TE, notify mac80211 */ | ||
300 | ieee80211_remain_on_channel_expired(mvm->hw); | ||
301 | iwl_mvm_roc_finished(mvm); /* flush aux queue */ | ||
302 | list_del(&te_data->list); /* remove from list */ | ||
303 | te_data->running = false; | ||
304 | te_data->vif = NULL; | ||
305 | te_data->uid = 0; | ||
306 | } else if (le32_to_cpu(notif->action) == TE_V2_NOTIF_HOST_EVENT_START) { | ||
307 | set_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status); | ||
308 | set_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status); | ||
309 | te_data->running = true; | ||
310 | ieee80211_ready_on_channel(mvm->hw); /* Start TE */ | ||
311 | } else { | ||
312 | IWL_DEBUG_TE(mvm, | ||
313 | "ERROR: Unknown Aux ROC Time Event (action = %d)\n", | ||
314 | le32_to_cpu(notif->action)); | ||
315 | return -EINVAL; | ||
316 | } | ||
317 | |||
318 | return 0; | ||
319 | } | ||
320 | |||
321 | /* | ||
266 | * The Rx handler for time event notifications | 322 | * The Rx handler for time event notifications |
267 | */ | 323 | */ |
268 | int iwl_mvm_rx_time_event_notif(struct iwl_mvm *mvm, | 324 | int iwl_mvm_rx_time_event_notif(struct iwl_mvm *mvm, |
@@ -278,10 +334,15 @@ int iwl_mvm_rx_time_event_notif(struct iwl_mvm *mvm, | |||
278 | le32_to_cpu(notif->action)); | 334 | le32_to_cpu(notif->action)); |
279 | 335 | ||
280 | spin_lock_bh(&mvm->time_event_lock); | 336 | spin_lock_bh(&mvm->time_event_lock); |
337 | /* This time event is triggered for Aux ROC request */ | ||
338 | if (!iwl_mvm_aux_roc_te_handle_notif(mvm, notif)) | ||
339 | goto unlock; | ||
340 | |||
281 | list_for_each_entry_safe(te_data, tmp, &mvm->time_event_list, list) { | 341 | list_for_each_entry_safe(te_data, tmp, &mvm->time_event_list, list) { |
282 | if (le32_to_cpu(notif->unique_id) == te_data->uid) | 342 | if (le32_to_cpu(notif->unique_id) == te_data->uid) |
283 | iwl_mvm_te_handle_notif(mvm, te_data, notif); | 343 | iwl_mvm_te_handle_notif(mvm, te_data, notif); |
284 | } | 344 | } |
345 | unlock: | ||
285 | spin_unlock_bh(&mvm->time_event_lock); | 346 | spin_unlock_bh(&mvm->time_event_lock); |
286 | 347 | ||
287 | return 0; | 348 | return 0; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/tt.c b/drivers/net/wireless/iwlwifi/mvm/tt.c index 868561512783..0464599c111e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tt.c +++ b/drivers/net/wireless/iwlwifi/mvm/tt.c | |||
@@ -140,9 +140,9 @@ static u16 iwl_mvm_dts_get_ptat_deviation_offset(struct iwl_mvm *mvm) | |||
140 | 140 | ||
141 | /* TODO: move parsing to NVM code */ | 141 | /* TODO: move parsing to NVM code */ |
142 | calib = mvm->nvm_sections[NVM_SECTION_TYPE_CALIBRATION].data; | 142 | calib = mvm->nvm_sections[NVM_SECTION_TYPE_CALIBRATION].data; |
143 | ptat = calib[OTP_DTS_DIODE_DEVIATION]; | 143 | ptat = calib[OTP_DTS_DIODE_DEVIATION * 2]; |
144 | pa1 = calib[OTP_DTS_DIODE_DEVIATION + 1]; | 144 | pa1 = calib[OTP_DTS_DIODE_DEVIATION * 2 + 1]; |
145 | pa2 = calib[OTP_DTS_DIODE_DEVIATION + 2]; | 145 | pa2 = calib[OTP_DTS_DIODE_DEVIATION * 2 + 2]; |
146 | 146 | ||
147 | /* get the median: */ | 147 | /* get the median: */ |
148 | if (ptat > pa1) { | 148 | if (ptat > pa1) { |
@@ -338,10 +338,16 @@ static void check_exit_ctkill(struct work_struct *work) | |||
338 | 338 | ||
339 | duration = tt->params->ct_kill_duration; | 339 | duration = tt->params->ct_kill_duration; |
340 | 340 | ||
341 | /* make sure the device is available for direct read/writes */ | ||
342 | if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_CHECK_CTKILL)) | ||
343 | goto reschedule; | ||
344 | |||
341 | iwl_trans_start_hw(mvm->trans); | 345 | iwl_trans_start_hw(mvm->trans); |
342 | temp = check_nic_temperature(mvm); | 346 | temp = check_nic_temperature(mvm); |
343 | iwl_trans_stop_device(mvm->trans); | 347 | iwl_trans_stop_device(mvm->trans); |
344 | 348 | ||
349 | iwl_mvm_unref(mvm, IWL_MVM_REF_CHECK_CTKILL); | ||
350 | |||
345 | if (temp < MIN_TEMPERATURE || temp > MAX_TEMPERATURE) { | 351 | if (temp < MIN_TEMPERATURE || temp > MAX_TEMPERATURE) { |
346 | IWL_DEBUG_TEMP(mvm, "Failed to measure NIC temperature\n"); | 352 | IWL_DEBUG_TEMP(mvm, "Failed to measure NIC temperature\n"); |
347 | goto reschedule; | 353 | goto reschedule; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index e9ff38635c21..dbc870713882 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c | |||
@@ -311,6 +311,16 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) | |||
311 | return -1; | 311 | return -1; |
312 | 312 | ||
313 | /* | 313 | /* |
314 | * IWL_MVM_OFFCHANNEL_QUEUE is used for ROC packets that can be used | ||
315 | * in 2 different types of vifs, P2P & STATION. P2P uses the offchannel | ||
316 | * queue. STATION (HS2.0) uses the auxiliary context of the FW, | ||
317 | * and hence needs to be sent on the aux queue | ||
318 | */ | ||
319 | if (IEEE80211_SKB_CB(skb)->hw_queue == IWL_MVM_OFFCHANNEL_QUEUE && | ||
320 | info->control.vif->type == NL80211_IFTYPE_STATION) | ||
321 | IEEE80211_SKB_CB(skb)->hw_queue = mvm->aux_queue; | ||
322 | |||
323 | /* | ||
314 | * If the interface on which frame is sent is the P2P_DEVICE | 324 | * If the interface on which frame is sent is the P2P_DEVICE |
315 | * or an AP/GO interface use the broadcast station associated | 325 | * or an AP/GO interface use the broadcast station associated |
316 | * with it; otherwise use the AUX station. | 326 | * with it; otherwise use the AUX station. |
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index 5b5b0d8c6f60..06e04aaf61ee 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c | |||
@@ -67,6 +67,7 @@ | |||
67 | #include <linux/sched.h> | 67 | #include <linux/sched.h> |
68 | #include <linux/bitops.h> | 68 | #include <linux/bitops.h> |
69 | #include <linux/gfp.h> | 69 | #include <linux/gfp.h> |
70 | #include <linux/vmalloc.h> | ||
70 | 71 | ||
71 | #include "iwl-drv.h" | 72 | #include "iwl-drv.h" |
72 | #include "iwl-trans.h" | 73 | #include "iwl-trans.h" |
@@ -1773,28 +1774,207 @@ static u32 iwl_trans_pcie_get_cmdlen(struct iwl_tfd *tfd) | |||
1773 | return cmdlen; | 1774 | return cmdlen; |
1774 | } | 1775 | } |
1775 | 1776 | ||
1776 | static u32 iwl_trans_pcie_dump_data(struct iwl_trans *trans, | 1777 | static const struct { |
1777 | void *buf, u32 buflen) | 1778 | u32 start, end; |
1779 | } iwl_prph_dump_addr[] = { | ||
1780 | { .start = 0x00a00000, .end = 0x00a00000 }, | ||
1781 | { .start = 0x00a0000c, .end = 0x00a00024 }, | ||
1782 | { .start = 0x00a0002c, .end = 0x00a0003c }, | ||
1783 | { .start = 0x00a00410, .end = 0x00a00418 }, | ||
1784 | { .start = 0x00a00420, .end = 0x00a00420 }, | ||
1785 | { .start = 0x00a00428, .end = 0x00a00428 }, | ||
1786 | { .start = 0x00a00430, .end = 0x00a0043c }, | ||
1787 | { .start = 0x00a00444, .end = 0x00a00444 }, | ||
1788 | { .start = 0x00a004c0, .end = 0x00a004cc }, | ||
1789 | { .start = 0x00a004d8, .end = 0x00a004d8 }, | ||
1790 | { .start = 0x00a004e0, .end = 0x00a004f0 }, | ||
1791 | { .start = 0x00a00840, .end = 0x00a00840 }, | ||
1792 | { .start = 0x00a00850, .end = 0x00a00858 }, | ||
1793 | { .start = 0x00a01004, .end = 0x00a01008 }, | ||
1794 | { .start = 0x00a01010, .end = 0x00a01010 }, | ||
1795 | { .start = 0x00a01018, .end = 0x00a01018 }, | ||
1796 | { .start = 0x00a01024, .end = 0x00a01024 }, | ||
1797 | { .start = 0x00a0102c, .end = 0x00a01034 }, | ||
1798 | { .start = 0x00a0103c, .end = 0x00a01040 }, | ||
1799 | { .start = 0x00a01048, .end = 0x00a01094 }, | ||
1800 | { .start = 0x00a01c00, .end = 0x00a01c20 }, | ||
1801 | { .start = 0x00a01c58, .end = 0x00a01c58 }, | ||
1802 | { .start = 0x00a01c7c, .end = 0x00a01c7c }, | ||
1803 | { .start = 0x00a01c28, .end = 0x00a01c54 }, | ||
1804 | { .start = 0x00a01c5c, .end = 0x00a01c5c }, | ||
1805 | { .start = 0x00a01c84, .end = 0x00a01c84 }, | ||
1806 | { .start = 0x00a01ce0, .end = 0x00a01d0c }, | ||
1807 | { .start = 0x00a01d18, .end = 0x00a01d20 }, | ||
1808 | { .start = 0x00a01d2c, .end = 0x00a01d30 }, | ||
1809 | { .start = 0x00a01d40, .end = 0x00a01d5c }, | ||
1810 | { .start = 0x00a01d80, .end = 0x00a01d80 }, | ||
1811 | { .start = 0x00a01d98, .end = 0x00a01d98 }, | ||
1812 | { .start = 0x00a01dc0, .end = 0x00a01dfc }, | ||
1813 | { .start = 0x00a01e00, .end = 0x00a01e2c }, | ||
1814 | { .start = 0x00a01e40, .end = 0x00a01e60 }, | ||
1815 | { .start = 0x00a01e84, .end = 0x00a01e90 }, | ||
1816 | { .start = 0x00a01e9c, .end = 0x00a01ec4 }, | ||
1817 | { .start = 0x00a01ed0, .end = 0x00a01ed0 }, | ||
1818 | { .start = 0x00a01f00, .end = 0x00a01f14 }, | ||
1819 | { .start = 0x00a01f44, .end = 0x00a01f58 }, | ||
1820 | { .start = 0x00a01f80, .end = 0x00a01fa8 }, | ||
1821 | { .start = 0x00a01fb0, .end = 0x00a01fbc }, | ||
1822 | { .start = 0x00a01ff8, .end = 0x00a01ffc }, | ||
1823 | { .start = 0x00a02000, .end = 0x00a02048 }, | ||
1824 | { .start = 0x00a02068, .end = 0x00a020f0 }, | ||
1825 | { .start = 0x00a02100, .end = 0x00a02118 }, | ||
1826 | { .start = 0x00a02140, .end = 0x00a0214c }, | ||
1827 | { .start = 0x00a02168, .end = 0x00a0218c }, | ||
1828 | { .start = 0x00a021c0, .end = 0x00a021c0 }, | ||
1829 | { .start = 0x00a02400, .end = 0x00a02410 }, | ||
1830 | { .start = 0x00a02418, .end = 0x00a02420 }, | ||
1831 | { .start = 0x00a02428, .end = 0x00a0242c }, | ||
1832 | { .start = 0x00a02434, .end = 0x00a02434 }, | ||
1833 | { .start = 0x00a02440, .end = 0x00a02460 }, | ||
1834 | { .start = 0x00a02468, .end = 0x00a024b0 }, | ||
1835 | { .start = 0x00a024c8, .end = 0x00a024cc }, | ||
1836 | { .start = 0x00a02500, .end = 0x00a02504 }, | ||
1837 | { .start = 0x00a0250c, .end = 0x00a02510 }, | ||
1838 | { .start = 0x00a02540, .end = 0x00a02554 }, | ||
1839 | { .start = 0x00a02580, .end = 0x00a025f4 }, | ||
1840 | { .start = 0x00a02600, .end = 0x00a0260c }, | ||
1841 | { .start = 0x00a02648, .end = 0x00a02650 }, | ||
1842 | { .start = 0x00a02680, .end = 0x00a02680 }, | ||
1843 | { .start = 0x00a026c0, .end = 0x00a026d0 }, | ||
1844 | { .start = 0x00a02700, .end = 0x00a0270c }, | ||
1845 | { .start = 0x00a02804, .end = 0x00a02804 }, | ||
1846 | { .start = 0x00a02818, .end = 0x00a0281c }, | ||
1847 | { .start = 0x00a02c00, .end = 0x00a02db4 }, | ||
1848 | { .start = 0x00a02df4, .end = 0x00a02fb0 }, | ||
1849 | { .start = 0x00a03000, .end = 0x00a03014 }, | ||
1850 | { .start = 0x00a0301c, .end = 0x00a0302c }, | ||
1851 | { .start = 0x00a03034, .end = 0x00a03038 }, | ||
1852 | { .start = 0x00a03040, .end = 0x00a03048 }, | ||
1853 | { .start = 0x00a03060, .end = 0x00a03068 }, | ||
1854 | { .start = 0x00a03070, .end = 0x00a03074 }, | ||
1855 | { .start = 0x00a0307c, .end = 0x00a0307c }, | ||
1856 | { .start = 0x00a03080, .end = 0x00a03084 }, | ||
1857 | { .start = 0x00a0308c, .end = 0x00a03090 }, | ||
1858 | { .start = 0x00a03098, .end = 0x00a03098 }, | ||
1859 | { .start = 0x00a030a0, .end = 0x00a030a0 }, | ||
1860 | { .start = 0x00a030a8, .end = 0x00a030b4 }, | ||
1861 | { .start = 0x00a030bc, .end = 0x00a030bc }, | ||
1862 | { .start = 0x00a030c0, .end = 0x00a0312c }, | ||
1863 | { .start = 0x00a03c00, .end = 0x00a03c5c }, | ||
1864 | { .start = 0x00a04400, .end = 0x00a04454 }, | ||
1865 | { .start = 0x00a04460, .end = 0x00a04474 }, | ||
1866 | { .start = 0x00a044c0, .end = 0x00a044ec }, | ||
1867 | { .start = 0x00a04500, .end = 0x00a04504 }, | ||
1868 | { .start = 0x00a04510, .end = 0x00a04538 }, | ||
1869 | { .start = 0x00a04540, .end = 0x00a04548 }, | ||
1870 | { .start = 0x00a04560, .end = 0x00a0457c }, | ||
1871 | { .start = 0x00a04590, .end = 0x00a04598 }, | ||
1872 | { .start = 0x00a045c0, .end = 0x00a045f4 }, | ||
1873 | }; | ||
1874 | |||
1875 | static u32 iwl_trans_pcie_dump_prph(struct iwl_trans *trans, | ||
1876 | struct iwl_fw_error_dump_data **data) | ||
1877 | { | ||
1878 | struct iwl_fw_error_dump_prph *prph; | ||
1879 | unsigned long flags; | ||
1880 | u32 prph_len = 0, i; | ||
1881 | |||
1882 | if (!iwl_trans_grab_nic_access(trans, false, &flags)) | ||
1883 | return 0; | ||
1884 | |||
1885 | for (i = 0; i < ARRAY_SIZE(iwl_prph_dump_addr); i++) { | ||
1886 | /* The range includes both boundaries */ | ||
1887 | int num_bytes_in_chunk = iwl_prph_dump_addr[i].end - | ||
1888 | iwl_prph_dump_addr[i].start + 4; | ||
1889 | int reg; | ||
1890 | __le32 *val; | ||
1891 | |||
1892 | prph_len += sizeof(*data) + sizeof(*prph) + | ||
1893 | num_bytes_in_chunk; | ||
1894 | |||
1895 | (*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PRPH); | ||
1896 | (*data)->len = cpu_to_le32(sizeof(*prph) + | ||
1897 | num_bytes_in_chunk); | ||
1898 | prph = (void *)(*data)->data; | ||
1899 | prph->prph_start = cpu_to_le32(iwl_prph_dump_addr[i].start); | ||
1900 | val = (void *)prph->data; | ||
1901 | |||
1902 | for (reg = iwl_prph_dump_addr[i].start; | ||
1903 | reg <= iwl_prph_dump_addr[i].end; | ||
1904 | reg += 4) | ||
1905 | *val++ = cpu_to_le32(iwl_trans_pcie_read_prph(trans, | ||
1906 | reg)); | ||
1907 | *data = iwl_fw_error_next_data(*data); | ||
1908 | } | ||
1909 | |||
1910 | iwl_trans_release_nic_access(trans, &flags); | ||
1911 | |||
1912 | return prph_len; | ||
1913 | } | ||
1914 | |||
1915 | #define IWL_CSR_TO_DUMP (0x250) | ||
1916 | |||
1917 | static u32 iwl_trans_pcie_dump_csr(struct iwl_trans *trans, | ||
1918 | struct iwl_fw_error_dump_data **data) | ||
1919 | { | ||
1920 | u32 csr_len = sizeof(**data) + IWL_CSR_TO_DUMP; | ||
1921 | __le32 *val; | ||
1922 | int i; | ||
1923 | |||
1924 | (*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_CSR); | ||
1925 | (*data)->len = cpu_to_le32(IWL_CSR_TO_DUMP); | ||
1926 | val = (void *)(*data)->data; | ||
1927 | |||
1928 | for (i = 0; i < IWL_CSR_TO_DUMP; i += 4) | ||
1929 | *val++ = cpu_to_le32(iwl_trans_pcie_read32(trans, i)); | ||
1930 | |||
1931 | *data = iwl_fw_error_next_data(*data); | ||
1932 | |||
1933 | return csr_len; | ||
1934 | } | ||
1935 | |||
1936 | static | ||
1937 | struct iwl_trans_dump_data *iwl_trans_pcie_dump_data(struct iwl_trans *trans) | ||
1778 | { | 1938 | { |
1779 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 1939 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
1780 | struct iwl_fw_error_dump_data *data; | 1940 | struct iwl_fw_error_dump_data *data; |
1781 | struct iwl_txq *cmdq = &trans_pcie->txq[trans_pcie->cmd_queue]; | 1941 | struct iwl_txq *cmdq = &trans_pcie->txq[trans_pcie->cmd_queue]; |
1782 | struct iwl_fw_error_dump_txcmd *txcmd; | 1942 | struct iwl_fw_error_dump_txcmd *txcmd; |
1943 | struct iwl_trans_dump_data *dump_data; | ||
1783 | u32 len; | 1944 | u32 len; |
1784 | int i, ptr; | 1945 | int i, ptr; |
1785 | 1946 | ||
1786 | len = sizeof(*data) + | 1947 | /* transport dump header */ |
1948 | len = sizeof(*dump_data); | ||
1949 | |||
1950 | /* host commands */ | ||
1951 | len += sizeof(*data) + | ||
1787 | cmdq->q.n_window * (sizeof(*txcmd) + TFD_MAX_PAYLOAD_SIZE); | 1952 | cmdq->q.n_window * (sizeof(*txcmd) + TFD_MAX_PAYLOAD_SIZE); |
1788 | 1953 | ||
1954 | /* CSR registers */ | ||
1955 | len += sizeof(*data) + IWL_CSR_TO_DUMP; | ||
1956 | |||
1957 | /* PRPH registers */ | ||
1958 | for (i = 0; i < ARRAY_SIZE(iwl_prph_dump_addr); i++) { | ||
1959 | /* The range includes both boundaries */ | ||
1960 | int num_bytes_in_chunk = iwl_prph_dump_addr[i].end - | ||
1961 | iwl_prph_dump_addr[i].start + 4; | ||
1962 | |||
1963 | len += sizeof(*data) + sizeof(struct iwl_fw_error_dump_prph) + | ||
1964 | num_bytes_in_chunk; | ||
1965 | } | ||
1966 | |||
1967 | /* FW monitor */ | ||
1789 | if (trans_pcie->fw_mon_page) | 1968 | if (trans_pcie->fw_mon_page) |
1790 | len += sizeof(*data) + sizeof(struct iwl_fw_error_dump_fw_mon) + | 1969 | len += sizeof(*data) + sizeof(struct iwl_fw_error_dump_fw_mon) + |
1791 | trans_pcie->fw_mon_size; | 1970 | trans_pcie->fw_mon_size; |
1792 | 1971 | ||
1793 | if (!buf) | 1972 | dump_data = vzalloc(len); |
1794 | return len; | 1973 | if (!dump_data) |
1974 | return NULL; | ||
1795 | 1975 | ||
1796 | len = 0; | 1976 | len = 0; |
1797 | data = buf; | 1977 | data = (void *)dump_data->data; |
1798 | data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_TXCMD); | 1978 | data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_TXCMD); |
1799 | txcmd = (void *)data->data; | 1979 | txcmd = (void *)data->data; |
1800 | spin_lock_bh(&cmdq->lock); | 1980 | spin_lock_bh(&cmdq->lock); |
@@ -1820,11 +2000,15 @@ static u32 iwl_trans_pcie_dump_data(struct iwl_trans *trans, | |||
1820 | 2000 | ||
1821 | data->len = cpu_to_le32(len); | 2001 | data->len = cpu_to_le32(len); |
1822 | len += sizeof(*data); | 2002 | len += sizeof(*data); |
2003 | data = iwl_fw_error_next_data(data); | ||
2004 | |||
2005 | len += iwl_trans_pcie_dump_prph(trans, &data); | ||
2006 | len += iwl_trans_pcie_dump_csr(trans, &data); | ||
2007 | /* data is already pointing to the next section */ | ||
1823 | 2008 | ||
1824 | if (trans_pcie->fw_mon_page) { | 2009 | if (trans_pcie->fw_mon_page) { |
1825 | struct iwl_fw_error_dump_fw_mon *fw_mon_data; | 2010 | struct iwl_fw_error_dump_fw_mon *fw_mon_data; |
1826 | 2011 | ||
1827 | data = iwl_fw_error_next_data(data); | ||
1828 | data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_FW_MONITOR); | 2012 | data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_FW_MONITOR); |
1829 | data->len = cpu_to_le32(trans_pcie->fw_mon_size + | 2013 | data->len = cpu_to_le32(trans_pcie->fw_mon_size + |
1830 | sizeof(*fw_mon_data)); | 2014 | sizeof(*fw_mon_data)); |
@@ -1852,7 +2036,9 @@ static u32 iwl_trans_pcie_dump_data(struct iwl_trans *trans, | |||
1852 | trans_pcie->fw_mon_size; | 2036 | trans_pcie->fw_mon_size; |
1853 | } | 2037 | } |
1854 | 2038 | ||
1855 | return len; | 2039 | dump_data->len = len; |
2040 | |||
2041 | return dump_data; | ||
1856 | } | 2042 | } |
1857 | #else | 2043 | #else |
1858 | static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, | 2044 | static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index eba51460a5de..f39f504cc3a0 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -685,11 +685,16 @@ static void mac80211_hwsim_set_tsf(struct ieee80211_hw *hw, | |||
685 | struct mac80211_hwsim_data *data = hw->priv; | 685 | struct mac80211_hwsim_data *data = hw->priv; |
686 | u64 now = mac80211_hwsim_get_tsf(hw, vif); | 686 | u64 now = mac80211_hwsim_get_tsf(hw, vif); |
687 | u32 bcn_int = data->beacon_int; | 687 | u32 bcn_int = data->beacon_int; |
688 | s64 delta = tsf - now; | 688 | u64 delta = abs64(tsf - now); |
689 | 689 | ||
690 | data->tsf_offset += delta; | ||
691 | /* adjust after beaconing with new timestamp at old TBTT */ | 690 | /* adjust after beaconing with new timestamp at old TBTT */ |
692 | data->bcn_delta = do_div(delta, bcn_int); | 691 | if (tsf > now) { |
692 | data->tsf_offset += delta; | ||
693 | data->bcn_delta = do_div(delta, bcn_int); | ||
694 | } else { | ||
695 | data->tsf_offset -= delta; | ||
696 | data->bcn_delta = -do_div(delta, bcn_int); | ||
697 | } | ||
693 | } | 698 | } |
694 | 699 | ||
695 | static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw, | 700 | static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw, |
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index 3e48ef5ca53c..1770fa3fc1e6 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c | |||
@@ -1954,6 +1954,7 @@ static void mwifiex_sdio_card_reset_work(struct mwifiex_adapter *adapter) | |||
1954 | mmc_remove_host(target); | 1954 | mmc_remove_host(target); |
1955 | /* 20ms delay is based on experiment with sdhci controller */ | 1955 | /* 20ms delay is based on experiment with sdhci controller */ |
1956 | mdelay(20); | 1956 | mdelay(20); |
1957 | target->rescan_entered = 0; /* rescan non-removable cards */ | ||
1957 | mmc_add_host(target); | 1958 | mmc_add_host(target); |
1958 | } | 1959 | } |
1959 | 1960 | ||
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 75d17e15da33..63ab3873c5ed 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h | |||
@@ -1001,6 +1001,26 @@ struct ieee80211_vendor_ie { | |||
1001 | u8 oui_type; | 1001 | u8 oui_type; |
1002 | } __packed; | 1002 | } __packed; |
1003 | 1003 | ||
1004 | struct ieee80211_wmm_ac_param { | ||
1005 | u8 aci_aifsn; /* AIFSN, ACM, ACI */ | ||
1006 | u8 cw; /* ECWmin, ECWmax (CW = 2^ECW - 1) */ | ||
1007 | __le16 txop_limit; | ||
1008 | } __packed; | ||
1009 | |||
1010 | struct ieee80211_wmm_param_ie { | ||
1011 | u8 element_id; /* Element ID: 221 (0xdd); */ | ||
1012 | u8 len; /* Length: 24 */ | ||
1013 | /* required fields for WMM version 1 */ | ||
1014 | u8 oui[3]; /* 00:50:f2 */ | ||
1015 | u8 oui_type; /* 2 */ | ||
1016 | u8 oui_subtype; /* 1 */ | ||
1017 | u8 version; /* 1 for WMM version 1.0 */ | ||
1018 | u8 qos_info; /* AP/STA specific QoS info */ | ||
1019 | u8 reserved; /* 0 */ | ||
1020 | /* AC_BE, AC_BK, AC_VI, AC_VO */ | ||
1021 | struct ieee80211_wmm_ac_param ac[4]; | ||
1022 | } __packed; | ||
1023 | |||
1004 | /* Control frames */ | 1024 | /* Control frames */ |
1005 | struct ieee80211_rts { | 1025 | struct ieee80211_rts { |
1006 | __le16 frame_control; | 1026 | __le16 frame_control; |
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 2fee852816ee..f0a3d8890760 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h | |||
@@ -401,6 +401,9 @@ enum { | |||
401 | /* The core spec defines 127 as the "not available" value */ | 401 | /* The core spec defines 127 as the "not available" value */ |
402 | #define HCI_TX_POWER_INVALID 127 | 402 | #define HCI_TX_POWER_INVALID 127 |
403 | 403 | ||
404 | #define HCI_ROLE_MASTER 0x00 | ||
405 | #define HCI_ROLE_SLAVE 0x01 | ||
406 | |||
404 | /* Extended Inquiry Response field types */ | 407 | /* Extended Inquiry Response field types */ |
405 | #define EIR_FLAGS 0x01 /* flags */ | 408 | #define EIR_FLAGS 0x01 /* flags */ |
406 | #define EIR_UUID16_SOME 0x02 /* 16-bit UUID, more available */ | 409 | #define EIR_UUID16_SOME 0x02 /* 16-bit UUID, more available */ |
@@ -1713,9 +1716,6 @@ struct hci_ev_sync_train_complete { | |||
1713 | 1716 | ||
1714 | #define HCI_EV_SLAVE_PAGE_RESP_TIMEOUT 0x54 | 1717 | #define HCI_EV_SLAVE_PAGE_RESP_TIMEOUT 0x54 |
1715 | 1718 | ||
1716 | /* Low energy meta events */ | ||
1717 | #define LE_CONN_ROLE_MASTER 0x00 | ||
1718 | |||
1719 | #define HCI_EV_LE_CONN_COMPLETE 0x01 | 1719 | #define HCI_EV_LE_CONN_COMPLETE 0x01 |
1720 | struct hci_ev_le_conn_complete { | 1720 | struct hci_ev_le_conn_complete { |
1721 | __u8 status; | 1721 | __u8 status; |
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index b52c2ef3f56d..996ed065b6c2 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
@@ -83,6 +83,7 @@ struct hci_conn_hash { | |||
83 | unsigned int amp_num; | 83 | unsigned int amp_num; |
84 | unsigned int sco_num; | 84 | unsigned int sco_num; |
85 | unsigned int le_num; | 85 | unsigned int le_num; |
86 | unsigned int le_num_slave; | ||
86 | }; | 87 | }; |
87 | 88 | ||
88 | struct bdaddr_list { | 89 | struct bdaddr_list { |
@@ -371,6 +372,7 @@ struct hci_conn { | |||
371 | __u16 state; | 372 | __u16 state; |
372 | __u8 mode; | 373 | __u8 mode; |
373 | __u8 type; | 374 | __u8 type; |
375 | __u8 role; | ||
374 | bool out; | 376 | bool out; |
375 | __u8 attempt; | 377 | __u8 attempt; |
376 | __u8 dev_class[3]; | 378 | __u8 dev_class[3]; |
@@ -540,12 +542,12 @@ enum { | |||
540 | HCI_CONN_POWER_SAVE, | 542 | HCI_CONN_POWER_SAVE, |
541 | HCI_CONN_REMOTE_OOB, | 543 | HCI_CONN_REMOTE_OOB, |
542 | HCI_CONN_FLUSH_KEY, | 544 | HCI_CONN_FLUSH_KEY, |
543 | HCI_CONN_MASTER, | ||
544 | HCI_CONN_ENCRYPT, | 545 | HCI_CONN_ENCRYPT, |
545 | HCI_CONN_AUTH, | 546 | HCI_CONN_AUTH, |
546 | HCI_CONN_SECURE, | 547 | HCI_CONN_SECURE, |
547 | HCI_CONN_FIPS, | 548 | HCI_CONN_FIPS, |
548 | HCI_CONN_STK_ENCRYPT, | 549 | HCI_CONN_STK_ENCRYPT, |
550 | HCI_CONN_AUTH_INITIATOR, | ||
549 | }; | 551 | }; |
550 | 552 | ||
551 | static inline bool hci_conn_ssp_enabled(struct hci_conn *conn) | 553 | static inline bool hci_conn_ssp_enabled(struct hci_conn *conn) |
@@ -575,6 +577,8 @@ static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c) | |||
575 | break; | 577 | break; |
576 | case LE_LINK: | 578 | case LE_LINK: |
577 | h->le_num++; | 579 | h->le_num++; |
580 | if (c->role == HCI_ROLE_SLAVE) | ||
581 | h->le_num_slave++; | ||
578 | break; | 582 | break; |
579 | case SCO_LINK: | 583 | case SCO_LINK: |
580 | case ESCO_LINK: | 584 | case ESCO_LINK: |
@@ -599,6 +603,8 @@ static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c) | |||
599 | break; | 603 | break; |
600 | case LE_LINK: | 604 | case LE_LINK: |
601 | h->le_num--; | 605 | h->le_num--; |
606 | if (c->role == HCI_ROLE_SLAVE) | ||
607 | h->le_num_slave--; | ||
602 | break; | 608 | break; |
603 | case SCO_LINK: | 609 | case SCO_LINK: |
604 | case ESCO_LINK: | 610 | case ESCO_LINK: |
@@ -695,7 +701,8 @@ void hci_disconnect(struct hci_conn *conn, __u8 reason); | |||
695 | bool hci_setup_sync(struct hci_conn *conn, __u16 handle); | 701 | bool hci_setup_sync(struct hci_conn *conn, __u16 handle); |
696 | void hci_sco_setup(struct hci_conn *conn, __u8 status); | 702 | void hci_sco_setup(struct hci_conn *conn, __u8 status); |
697 | 703 | ||
698 | struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst); | 704 | struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst, |
705 | u8 role); | ||
699 | int hci_conn_del(struct hci_conn *conn); | 706 | int hci_conn_del(struct hci_conn *conn); |
700 | void hci_conn_hash_flush(struct hci_dev *hdev); | 707 | void hci_conn_hash_flush(struct hci_dev *hdev); |
701 | void hci_conn_check_pending(struct hci_dev *hdev); | 708 | void hci_conn_check_pending(struct hci_dev *hdev); |
@@ -707,14 +714,15 @@ struct hci_chan *hci_chan_lookup_handle(struct hci_dev *hdev, __u16 handle); | |||
707 | 714 | ||
708 | struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, | 715 | struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, |
709 | u8 dst_type, u8 sec_level, u16 conn_timeout, | 716 | u8 dst_type, u8 sec_level, u16 conn_timeout, |
710 | bool master); | 717 | u8 role); |
711 | struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, | 718 | struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, |
712 | u8 sec_level, u8 auth_type); | 719 | u8 sec_level, u8 auth_type); |
713 | struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst, | 720 | struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst, |
714 | __u16 setting); | 721 | __u16 setting); |
715 | int hci_conn_check_link_mode(struct hci_conn *conn); | 722 | int hci_conn_check_link_mode(struct hci_conn *conn); |
716 | int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level); | 723 | int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level); |
717 | int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type); | 724 | int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type, |
725 | bool initiator); | ||
718 | int hci_conn_change_link_key(struct hci_conn *conn); | 726 | int hci_conn_change_link_key(struct hci_conn *conn); |
719 | int hci_conn_switch_role(struct hci_conn *conn, __u8 role); | 727 | int hci_conn_switch_role(struct hci_conn *conn, __u8 role); |
720 | 728 | ||
@@ -881,12 +889,12 @@ struct link_key *hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, | |||
881 | bdaddr_t *bdaddr, u8 *val, u8 type, | 889 | bdaddr_t *bdaddr, u8 *val, u8 type, |
882 | u8 pin_len, bool *persistent); | 890 | u8 pin_len, bool *persistent); |
883 | struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, __le64 rand, | 891 | struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, __le64 rand, |
884 | bool master); | 892 | u8 role); |
885 | struct smp_ltk *hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, | 893 | struct smp_ltk *hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, |
886 | u8 addr_type, u8 type, u8 authenticated, | 894 | u8 addr_type, u8 type, u8 authenticated, |
887 | u8 tk[16], u8 enc_size, __le16 ediv, __le64 rand); | 895 | u8 tk[16], u8 enc_size, __le16 ediv, __le64 rand); |
888 | struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr, | 896 | struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr, |
889 | u8 addr_type, bool master); | 897 | u8 addr_type, u8 role); |
890 | int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 bdaddr_type); | 898 | int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 bdaddr_type); |
891 | void hci_smp_ltks_clear(struct hci_dev *hdev); | 899 | void hci_smp_ltks_clear(struct hci_dev *hdev); |
892 | int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr); | 900 | int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr); |
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 1fffd92808b0..8df15ad0d43f 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h | |||
@@ -905,7 +905,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, | |||
905 | bdaddr_t *dst, u8 dst_type); | 905 | bdaddr_t *dst, u8 dst_type); |
906 | int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len); | 906 | int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len); |
907 | void l2cap_chan_busy(struct l2cap_chan *chan, int busy); | 907 | void l2cap_chan_busy(struct l2cap_chan *chan, int busy); |
908 | int l2cap_chan_check_security(struct l2cap_chan *chan); | 908 | int l2cap_chan_check_security(struct l2cap_chan *chan, bool initiator); |
909 | void l2cap_chan_set_defaults(struct l2cap_chan *chan); | 909 | void l2cap_chan_set_defaults(struct l2cap_chan *chan); |
910 | int l2cap_ertm_init(struct l2cap_chan *chan); | 910 | int l2cap_ertm_init(struct l2cap_chan *chan); |
911 | void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan); | 911 | void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan); |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 9ce5cb17ed82..dae2e24616e1 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -4552,6 +4552,40 @@ void ieee80211_stop_rx_ba_session(struct ieee80211_vif *vif, u16 ba_rx_bitmap, | |||
4552 | */ | 4552 | */ |
4553 | void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn); | 4553 | void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn); |
4554 | 4554 | ||
4555 | /** | ||
4556 | * ieee80211_start_rx_ba_session_offl - start a Rx BA session | ||
4557 | * | ||
4558 | * Some device drivers may offload part of the Rx aggregation flow including | ||
4559 | * AddBa/DelBa negotiation but may otherwise be incapable of full Rx | ||
4560 | * reordering. | ||
4561 | * | ||
4562 | * Create structures responsible for reordering so device drivers may call here | ||
4563 | * when they complete AddBa negotiation. | ||
4564 | * | ||
4565 | * @vif: &struct ieee80211_vif pointer from the add_interface callback | ||
4566 | * @addr: station mac address | ||
4567 | * @tid: the rx tid | ||
4568 | */ | ||
4569 | void ieee80211_start_rx_ba_session_offl(struct ieee80211_vif *vif, | ||
4570 | const u8 *addr, u16 tid); | ||
4571 | |||
4572 | /** | ||
4573 | * ieee80211_stop_rx_ba_session_offl - stop a Rx BA session | ||
4574 | * | ||
4575 | * Some device drivers may offload part of the Rx aggregation flow including | ||
4576 | * AddBa/DelBa negotiation but may otherwise be incapable of full Rx | ||
4577 | * reordering. | ||
4578 | * | ||
4579 | * Destroy structures responsible for reordering so device drivers may call here | ||
4580 | * when they complete DelBa negotiation. | ||
4581 | * | ||
4582 | * @vif: &struct ieee80211_vif pointer from the add_interface callback | ||
4583 | * @addr: station mac address | ||
4584 | * @tid: the rx tid | ||
4585 | */ | ||
4586 | void ieee80211_stop_rx_ba_session_offl(struct ieee80211_vif *vif, | ||
4587 | const u8 *addr, u16 tid); | ||
4588 | |||
4555 | /* Rate control API */ | 4589 | /* Rate control API */ |
4556 | 4590 | ||
4557 | /** | 4591 | /** |
diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c index bb39509b3f06..016cdb66df6c 100644 --- a/net/bluetooth/amp.c +++ b/net/bluetooth/amp.c | |||
@@ -113,8 +113,9 @@ struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr, | |||
113 | { | 113 | { |
114 | bdaddr_t *dst = &mgr->l2cap_conn->hcon->dst; | 114 | bdaddr_t *dst = &mgr->l2cap_conn->hcon->dst; |
115 | struct hci_conn *hcon; | 115 | struct hci_conn *hcon; |
116 | u8 role = out ? HCI_ROLE_MASTER : HCI_ROLE_SLAVE; | ||
116 | 117 | ||
117 | hcon = hci_conn_add(hdev, AMP_LINK, dst); | 118 | hcon = hci_conn_add(hdev, AMP_LINK, dst, role); |
118 | if (!hcon) | 119 | if (!hcon) |
119 | return NULL; | 120 | return NULL; |
120 | 121 | ||
@@ -125,7 +126,6 @@ struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr, | |||
125 | hcon->handle = __next_handle(mgr); | 126 | hcon->handle = __next_handle(mgr); |
126 | hcon->remote_id = remote_id; | 127 | hcon->remote_id = remote_id; |
127 | hcon->amp_mgr = amp_mgr_get(mgr); | 128 | hcon->amp_mgr = amp_mgr_get(mgr); |
128 | hcon->out = out; | ||
129 | 129 | ||
130 | return hcon; | 130 | return hcon; |
131 | } | 131 | } |
@@ -133,8 +133,8 @@ struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr, | |||
133 | /* AMP crypto key generation interface */ | 133 | /* AMP crypto key generation interface */ |
134 | static int hmac_sha256(u8 *key, u8 ksize, char *plaintext, u8 psize, u8 *output) | 134 | static int hmac_sha256(u8 *key, u8 ksize, char *plaintext, u8 psize, u8 *output) |
135 | { | 135 | { |
136 | int ret = 0; | ||
137 | struct crypto_shash *tfm; | 136 | struct crypto_shash *tfm; |
137 | int ret; | ||
138 | 138 | ||
139 | if (!ksize) | 139 | if (!ksize) |
140 | return -EINVAL; | 140 | return -EINVAL; |
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 490ee8846d9e..b50dabb3f86a 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -66,8 +66,7 @@ static void hci_acl_create_connection(struct hci_conn *conn) | |||
66 | 66 | ||
67 | conn->state = BT_CONNECT; | 67 | conn->state = BT_CONNECT; |
68 | conn->out = true; | 68 | conn->out = true; |
69 | 69 | conn->role = HCI_ROLE_MASTER; | |
70 | set_bit(HCI_CONN_MASTER, &conn->flags); | ||
71 | 70 | ||
72 | conn->attempt++; | 71 | conn->attempt++; |
73 | 72 | ||
@@ -335,7 +334,7 @@ static void hci_conn_timeout(struct work_struct *work) | |||
335 | * event handling and hci_clock_offset_evt function. | 334 | * event handling and hci_clock_offset_evt function. |
336 | */ | 335 | */ |
337 | if (conn->type == ACL_LINK && | 336 | if (conn->type == ACL_LINK && |
338 | test_bit(HCI_CONN_MASTER, &conn->flags)) { | 337 | conn->role == HCI_ROLE_MASTER) { |
339 | struct hci_dev *hdev = conn->hdev; | 338 | struct hci_dev *hdev = conn->hdev; |
340 | struct hci_cp_read_clock_offset cp; | 339 | struct hci_cp_read_clock_offset cp; |
341 | 340 | ||
@@ -422,13 +421,14 @@ static void le_conn_timeout(struct work_struct *work) | |||
422 | hci_le_create_connection_cancel(conn); | 421 | hci_le_create_connection_cancel(conn); |
423 | } | 422 | } |
424 | 423 | ||
425 | struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) | 424 | struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst, |
425 | u8 role) | ||
426 | { | 426 | { |
427 | struct hci_conn *conn; | 427 | struct hci_conn *conn; |
428 | 428 | ||
429 | BT_DBG("%s dst %pMR", hdev->name, dst); | 429 | BT_DBG("%s dst %pMR", hdev->name, dst); |
430 | 430 | ||
431 | conn = kzalloc(sizeof(struct hci_conn), GFP_KERNEL); | 431 | conn = kzalloc(sizeof(*conn), GFP_KERNEL); |
432 | if (!conn) | 432 | if (!conn) |
433 | return NULL; | 433 | return NULL; |
434 | 434 | ||
@@ -436,6 +436,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) | |||
436 | bacpy(&conn->src, &hdev->bdaddr); | 436 | bacpy(&conn->src, &hdev->bdaddr); |
437 | conn->hdev = hdev; | 437 | conn->hdev = hdev; |
438 | conn->type = type; | 438 | conn->type = type; |
439 | conn->role = role; | ||
439 | conn->mode = HCI_CM_ACTIVE; | 440 | conn->mode = HCI_CM_ACTIVE; |
440 | conn->state = BT_OPEN; | 441 | conn->state = BT_OPEN; |
441 | conn->auth_type = HCI_AT_GENERAL_BONDING; | 442 | conn->auth_type = HCI_AT_GENERAL_BONDING; |
@@ -448,6 +449,9 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) | |||
448 | set_bit(HCI_CONN_POWER_SAVE, &conn->flags); | 449 | set_bit(HCI_CONN_POWER_SAVE, &conn->flags); |
449 | conn->disc_timeout = HCI_DISCONN_TIMEOUT; | 450 | conn->disc_timeout = HCI_DISCONN_TIMEOUT; |
450 | 451 | ||
452 | if (conn->role == HCI_ROLE_MASTER) | ||
453 | conn->out = true; | ||
454 | |||
451 | switch (type) { | 455 | switch (type) { |
452 | case ACL_LINK: | 456 | case ACL_LINK: |
453 | conn->pkt_type = hdev->pkt_type & ACL_PTYPE_MASK; | 457 | conn->pkt_type = hdev->pkt_type & ACL_PTYPE_MASK; |
@@ -698,7 +702,7 @@ static void hci_req_directed_advertising(struct hci_request *req, | |||
698 | 702 | ||
699 | struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, | 703 | struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, |
700 | u8 dst_type, u8 sec_level, u16 conn_timeout, | 704 | u8 dst_type, u8 sec_level, u16 conn_timeout, |
701 | bool master) | 705 | u8 role) |
702 | { | 706 | { |
703 | struct hci_conn_params *params; | 707 | struct hci_conn_params *params; |
704 | struct hci_conn *conn; | 708 | struct hci_conn *conn; |
@@ -747,7 +751,7 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, | |||
747 | dst_type = ADDR_LE_DEV_RANDOM; | 751 | dst_type = ADDR_LE_DEV_RANDOM; |
748 | } | 752 | } |
749 | 753 | ||
750 | conn = hci_conn_add(hdev, LE_LINK, dst); | 754 | conn = hci_conn_add(hdev, LE_LINK, dst, role); |
751 | if (!conn) | 755 | if (!conn) |
752 | return ERR_PTR(-ENOMEM); | 756 | return ERR_PTR(-ENOMEM); |
753 | 757 | ||
@@ -771,7 +775,7 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, | |||
771 | } | 775 | } |
772 | 776 | ||
773 | /* If requested to connect as slave use directed advertising */ | 777 | /* If requested to connect as slave use directed advertising */ |
774 | if (!master) { | 778 | if (conn->role == HCI_ROLE_SLAVE) { |
775 | /* If we're active scanning most controllers are unable | 779 | /* If we're active scanning most controllers are unable |
776 | * to initiate advertising. Simply reject the attempt. | 780 | * to initiate advertising. Simply reject the attempt. |
777 | */ | 781 | */ |
@@ -786,9 +790,6 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, | |||
786 | goto create_conn; | 790 | goto create_conn; |
787 | } | 791 | } |
788 | 792 | ||
789 | conn->out = true; | ||
790 | set_bit(HCI_CONN_MASTER, &conn->flags); | ||
791 | |||
792 | params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type); | 793 | params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type); |
793 | if (params) { | 794 | if (params) { |
794 | conn->le_conn_min_interval = params->conn_min_interval; | 795 | conn->le_conn_min_interval = params->conn_min_interval; |
@@ -833,11 +834,11 @@ struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, | |||
833 | struct hci_conn *acl; | 834 | struct hci_conn *acl; |
834 | 835 | ||
835 | if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) | 836 | if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) |
836 | return ERR_PTR(-ENOTSUPP); | 837 | return ERR_PTR(-EOPNOTSUPP); |
837 | 838 | ||
838 | acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst); | 839 | acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst); |
839 | if (!acl) { | 840 | if (!acl) { |
840 | acl = hci_conn_add(hdev, ACL_LINK, dst); | 841 | acl = hci_conn_add(hdev, ACL_LINK, dst, HCI_ROLE_MASTER); |
841 | if (!acl) | 842 | if (!acl) |
842 | return ERR_PTR(-ENOMEM); | 843 | return ERR_PTR(-ENOMEM); |
843 | } | 844 | } |
@@ -866,7 +867,7 @@ struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst, | |||
866 | 867 | ||
867 | sco = hci_conn_hash_lookup_ba(hdev, type, dst); | 868 | sco = hci_conn_hash_lookup_ba(hdev, type, dst); |
868 | if (!sco) { | 869 | if (!sco) { |
869 | sco = hci_conn_add(hdev, type, dst); | 870 | sco = hci_conn_add(hdev, type, dst, HCI_ROLE_MASTER); |
870 | if (!sco) { | 871 | if (!sco) { |
871 | hci_conn_drop(acl); | 872 | hci_conn_drop(acl); |
872 | return ERR_PTR(-ENOMEM); | 873 | return ERR_PTR(-ENOMEM); |
@@ -972,7 +973,8 @@ static void hci_conn_encrypt(struct hci_conn *conn) | |||
972 | } | 973 | } |
973 | 974 | ||
974 | /* Enable security */ | 975 | /* Enable security */ |
975 | int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) | 976 | int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type, |
977 | bool initiator) | ||
976 | { | 978 | { |
977 | BT_DBG("hcon %p", conn); | 979 | BT_DBG("hcon %p", conn); |
978 | 980 | ||
@@ -1025,6 +1027,9 @@ auth: | |||
1025 | if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) | 1027 | if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) |
1026 | return 0; | 1028 | return 0; |
1027 | 1029 | ||
1030 | if (initiator) | ||
1031 | set_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags); | ||
1032 | |||
1028 | if (!hci_conn_auth(conn, sec_level, auth_type)) | 1033 | if (!hci_conn_auth(conn, sec_level, auth_type)) |
1029 | return 0; | 1034 | return 0; |
1030 | 1035 | ||
@@ -1076,7 +1081,7 @@ int hci_conn_switch_role(struct hci_conn *conn, __u8 role) | |||
1076 | { | 1081 | { |
1077 | BT_DBG("hcon %p", conn); | 1082 | BT_DBG("hcon %p", conn); |
1078 | 1083 | ||
1079 | if (!role && test_bit(HCI_CONN_MASTER, &conn->flags)) | 1084 | if (role == conn->role) |
1080 | return 1; | 1085 | return 1; |
1081 | 1086 | ||
1082 | if (!test_and_set_bit(HCI_CONN_RSWITCH_PEND, &conn->flags)) { | 1087 | if (!test_and_set_bit(HCI_CONN_RSWITCH_PEND, &conn->flags)) { |
@@ -1151,7 +1156,7 @@ static u32 get_link_mode(struct hci_conn *conn) | |||
1151 | { | 1156 | { |
1152 | u32 link_mode = 0; | 1157 | u32 link_mode = 0; |
1153 | 1158 | ||
1154 | if (test_bit(HCI_CONN_MASTER, &conn->flags)) | 1159 | if (conn->role == HCI_ROLE_MASTER) |
1155 | link_mode |= HCI_LM_MASTER; | 1160 | link_mode |= HCI_LM_MASTER; |
1156 | 1161 | ||
1157 | if (test_bit(HCI_CONN_ENCRYPT, &conn->flags)) | 1162 | if (test_bit(HCI_CONN_ENCRYPT, &conn->flags)) |
@@ -1277,7 +1282,7 @@ struct hci_chan *hci_chan_create(struct hci_conn *conn) | |||
1277 | 1282 | ||
1278 | BT_DBG("%s hcon %p", hdev->name, conn); | 1283 | BT_DBG("%s hcon %p", hdev->name, conn); |
1279 | 1284 | ||
1280 | chan = kzalloc(sizeof(struct hci_chan), GFP_KERNEL); | 1285 | chan = kzalloc(sizeof(*chan), GFP_KERNEL); |
1281 | if (!chan) | 1286 | if (!chan) |
1282 | return NULL; | 1287 | return NULL; |
1283 | 1288 | ||
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 172041e2b15a..cfcb6055ced8 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -2088,7 +2088,7 @@ u32 hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data, | |||
2088 | } | 2088 | } |
2089 | 2089 | ||
2090 | /* Entry not in the cache. Add new one. */ | 2090 | /* Entry not in the cache. Add new one. */ |
2091 | ie = kzalloc(sizeof(struct inquiry_entry), GFP_KERNEL); | 2091 | ie = kzalloc(sizeof(*ie), GFP_KERNEL); |
2092 | if (!ie) { | 2092 | if (!ie) { |
2093 | flags |= MGMT_DEV_FOUND_CONFIRM_NAME; | 2093 | flags |= MGMT_DEV_FOUND_CONFIRM_NAME; |
2094 | goto done; | 2094 | goto done; |
@@ -3121,13 +3121,16 @@ static bool hci_persistent_key(struct hci_dev *hdev, struct hci_conn *conn, | |||
3121 | return false; | 3121 | return false; |
3122 | } | 3122 | } |
3123 | 3123 | ||
3124 | static bool ltk_type_master(u8 type) | 3124 | static u8 ltk_role(u8 type) |
3125 | { | 3125 | { |
3126 | return (type == SMP_LTK); | 3126 | if (type == SMP_LTK) |
3127 | return HCI_ROLE_MASTER; | ||
3128 | |||
3129 | return HCI_ROLE_SLAVE; | ||
3127 | } | 3130 | } |
3128 | 3131 | ||
3129 | struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, __le64 rand, | 3132 | struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, __le64 rand, |
3130 | bool master) | 3133 | u8 role) |
3131 | { | 3134 | { |
3132 | struct smp_ltk *k; | 3135 | struct smp_ltk *k; |
3133 | 3136 | ||
@@ -3135,7 +3138,7 @@ struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, __le64 rand, | |||
3135 | if (k->ediv != ediv || k->rand != rand) | 3138 | if (k->ediv != ediv || k->rand != rand) |
3136 | continue; | 3139 | continue; |
3137 | 3140 | ||
3138 | if (ltk_type_master(k->type) != master) | 3141 | if (ltk_role(k->type) != role) |
3139 | continue; | 3142 | continue; |
3140 | 3143 | ||
3141 | return k; | 3144 | return k; |
@@ -3145,14 +3148,14 @@ struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, __le64 rand, | |||
3145 | } | 3148 | } |
3146 | 3149 | ||
3147 | struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr, | 3150 | struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr, |
3148 | u8 addr_type, bool master) | 3151 | u8 addr_type, u8 role) |
3149 | { | 3152 | { |
3150 | struct smp_ltk *k; | 3153 | struct smp_ltk *k; |
3151 | 3154 | ||
3152 | list_for_each_entry(k, &hdev->long_term_keys, list) | 3155 | list_for_each_entry(k, &hdev->long_term_keys, list) |
3153 | if (addr_type == k->bdaddr_type && | 3156 | if (addr_type == k->bdaddr_type && |
3154 | bacmp(bdaddr, &k->bdaddr) == 0 && | 3157 | bacmp(bdaddr, &k->bdaddr) == 0 && |
3155 | ltk_type_master(k->type) == master) | 3158 | ltk_role(k->type) == role) |
3156 | return k; | 3159 | return k; |
3157 | 3160 | ||
3158 | return NULL; | 3161 | return NULL; |
@@ -3247,9 +3250,9 @@ struct smp_ltk *hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, | |||
3247 | u8 tk[16], u8 enc_size, __le16 ediv, __le64 rand) | 3250 | u8 tk[16], u8 enc_size, __le16 ediv, __le64 rand) |
3248 | { | 3251 | { |
3249 | struct smp_ltk *key, *old_key; | 3252 | struct smp_ltk *key, *old_key; |
3250 | bool master = ltk_type_master(type); | 3253 | u8 role = ltk_role(type); |
3251 | 3254 | ||
3252 | old_key = hci_find_ltk_by_addr(hdev, bdaddr, addr_type, master); | 3255 | old_key = hci_find_ltk_by_addr(hdev, bdaddr, addr_type, role); |
3253 | if (old_key) | 3256 | if (old_key) |
3254 | key = old_key; | 3257 | key = old_key; |
3255 | else { | 3258 | else { |
@@ -3489,7 +3492,7 @@ int hci_bdaddr_list_add(struct list_head *list, bdaddr_t *bdaddr, u8 type) | |||
3489 | if (hci_bdaddr_list_lookup(list, bdaddr, type)) | 3492 | if (hci_bdaddr_list_lookup(list, bdaddr, type)) |
3490 | return -EEXIST; | 3493 | return -EEXIST; |
3491 | 3494 | ||
3492 | entry = kzalloc(sizeof(struct bdaddr_list), GFP_KERNEL); | 3495 | entry = kzalloc(sizeof(*entry), GFP_KERNEL); |
3493 | if (!entry) | 3496 | if (!entry) |
3494 | return -ENOMEM; | 3497 | return -ENOMEM; |
3495 | 3498 | ||
@@ -3894,7 +3897,7 @@ struct hci_dev *hci_alloc_dev(void) | |||
3894 | { | 3897 | { |
3895 | struct hci_dev *hdev; | 3898 | struct hci_dev *hdev; |
3896 | 3899 | ||
3897 | hdev = kzalloc(sizeof(struct hci_dev), GFP_KERNEL); | 3900 | hdev = kzalloc(sizeof(*hdev), GFP_KERNEL); |
3898 | if (!hdev) | 3901 | if (!hdev) |
3899 | return NULL; | 3902 | return NULL; |
3900 | 3903 | ||
@@ -5462,8 +5465,7 @@ void hci_update_background_scan(struct hci_dev *hdev) | |||
5462 | 5465 | ||
5463 | hci_req_init(&req, hdev); | 5466 | hci_req_init(&req, hdev); |
5464 | 5467 | ||
5465 | if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags) && | 5468 | if (list_empty(&hdev->pend_le_conns) && |
5466 | list_empty(&hdev->pend_le_conns) && | ||
5467 | list_empty(&hdev->pend_le_reports)) { | 5469 | list_empty(&hdev->pend_le_reports)) { |
5468 | /* If there is no pending LE connections or devices | 5470 | /* If there is no pending LE connections or devices |
5469 | * to be scanned for, we should stop the background | 5471 | * to be scanned for, we should stop the background |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 8980bd24b8c0..4c41774aa556 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -101,12 +101,8 @@ static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb) | |||
101 | hci_dev_lock(hdev); | 101 | hci_dev_lock(hdev); |
102 | 102 | ||
103 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); | 103 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); |
104 | if (conn) { | 104 | if (conn) |
105 | if (rp->role) | 105 | conn->role = rp->role; |
106 | clear_bit(HCI_CONN_MASTER, &conn->flags); | ||
107 | else | ||
108 | set_bit(HCI_CONN_MASTER, &conn->flags); | ||
109 | } | ||
110 | 106 | ||
111 | hci_dev_unlock(hdev); | 107 | hci_dev_unlock(hdev); |
112 | } | 108 | } |
@@ -1418,11 +1414,9 @@ static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) | |||
1418 | } | 1414 | } |
1419 | } else { | 1415 | } else { |
1420 | if (!conn) { | 1416 | if (!conn) { |
1421 | conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr); | 1417 | conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr, |
1422 | if (conn) { | 1418 | HCI_ROLE_MASTER); |
1423 | conn->out = true; | 1419 | if (!conn) |
1424 | set_bit(HCI_CONN_MASTER, &conn->flags); | ||
1425 | } else | ||
1426 | BT_ERR("No memory for new connection"); | 1420 | BT_ERR("No memory for new connection"); |
1427 | } | 1421 | } |
1428 | } | 1422 | } |
@@ -1651,6 +1645,8 @@ static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) | |||
1651 | if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { | 1645 | if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { |
1652 | struct hci_cp_auth_requested auth_cp; | 1646 | struct hci_cp_auth_requested auth_cp; |
1653 | 1647 | ||
1648 | set_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags); | ||
1649 | |||
1654 | auth_cp.handle = __cpu_to_le16(conn->handle); | 1650 | auth_cp.handle = __cpu_to_le16(conn->handle); |
1655 | hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, | 1651 | hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, |
1656 | sizeof(auth_cp), &auth_cp); | 1652 | sizeof(auth_cp), &auth_cp); |
@@ -2135,18 +2131,17 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2135 | return; | 2131 | return; |
2136 | } | 2132 | } |
2137 | 2133 | ||
2138 | if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) { | 2134 | if (hci_bdaddr_list_lookup(&hdev->blacklist, &ev->bdaddr, |
2139 | if (hci_bdaddr_list_lookup(&hdev->blacklist, &ev->bdaddr, | 2135 | BDADDR_BREDR)) { |
2140 | BDADDR_BREDR)) { | 2136 | hci_reject_conn(hdev, &ev->bdaddr); |
2141 | hci_reject_conn(hdev, &ev->bdaddr); | 2137 | return; |
2142 | return; | 2138 | } |
2143 | } | 2139 | |
2144 | } else { | 2140 | if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags) && |
2145 | if (!hci_bdaddr_list_lookup(&hdev->whitelist, &ev->bdaddr, | 2141 | !hci_bdaddr_list_lookup(&hdev->whitelist, &ev->bdaddr, |
2146 | BDADDR_BREDR)) { | 2142 | BDADDR_BREDR)) { |
2147 | hci_reject_conn(hdev, &ev->bdaddr); | 2143 | hci_reject_conn(hdev, &ev->bdaddr); |
2148 | return; | 2144 | return; |
2149 | } | ||
2150 | } | 2145 | } |
2151 | 2146 | ||
2152 | /* Connection accepted */ | 2147 | /* Connection accepted */ |
@@ -2160,7 +2155,8 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2160 | conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, | 2155 | conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, |
2161 | &ev->bdaddr); | 2156 | &ev->bdaddr); |
2162 | if (!conn) { | 2157 | if (!conn) { |
2163 | conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr); | 2158 | conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr, |
2159 | HCI_ROLE_SLAVE); | ||
2164 | if (!conn) { | 2160 | if (!conn) { |
2165 | BT_ERR("No memory for new connection"); | 2161 | BT_ERR("No memory for new connection"); |
2166 | hci_dev_unlock(hdev); | 2162 | hci_dev_unlock(hdev); |
@@ -2393,6 +2389,9 @@ check_auth: | |||
2393 | 2389 | ||
2394 | if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { | 2390 | if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { |
2395 | struct hci_cp_auth_requested cp; | 2391 | struct hci_cp_auth_requested cp; |
2392 | |||
2393 | set_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags); | ||
2394 | |||
2396 | cp.handle = __cpu_to_le16(conn->handle); | 2395 | cp.handle = __cpu_to_le16(conn->handle); |
2397 | hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); | 2396 | hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); |
2398 | } | 2397 | } |
@@ -2924,12 +2923,8 @@ static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2924 | 2923 | ||
2925 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); | 2924 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); |
2926 | if (conn) { | 2925 | if (conn) { |
2927 | if (!ev->status) { | 2926 | if (!ev->status) |
2928 | if (ev->role) | 2927 | conn->role = ev->role; |
2929 | clear_bit(HCI_CONN_MASTER, &conn->flags); | ||
2930 | else | ||
2931 | set_bit(HCI_CONN_MASTER, &conn->flags); | ||
2932 | } | ||
2933 | 2928 | ||
2934 | clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags); | 2929 | clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags); |
2935 | 2930 | ||
@@ -3123,10 +3118,11 @@ static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
3123 | hci_conn_drop(conn); | 3118 | hci_conn_drop(conn); |
3124 | } | 3119 | } |
3125 | 3120 | ||
3126 | if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags)) | 3121 | if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags) && |
3122 | !test_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags)) { | ||
3127 | hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, | 3123 | hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, |
3128 | sizeof(ev->bdaddr), &ev->bdaddr); | 3124 | sizeof(ev->bdaddr), &ev->bdaddr); |
3129 | else if (test_bit(HCI_MGMT, &hdev->dev_flags)) { | 3125 | } else if (test_bit(HCI_MGMT, &hdev->dev_flags)) { |
3130 | u8 secure; | 3126 | u8 secure; |
3131 | 3127 | ||
3132 | if (conn->pending_sec_level == BT_SECURITY_HIGH) | 3128 | if (conn->pending_sec_level == BT_SECURITY_HIGH) |
@@ -3652,7 +3648,11 @@ static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
3652 | if (!test_bit(HCI_MGMT, &hdev->dev_flags)) | 3648 | if (!test_bit(HCI_MGMT, &hdev->dev_flags)) |
3653 | goto unlock; | 3649 | goto unlock; |
3654 | 3650 | ||
3651 | /* Allow pairing if we're pairable, the initiators of the | ||
3652 | * pairing or if the remote is not requesting bonding. | ||
3653 | */ | ||
3655 | if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) || | 3654 | if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) || |
3655 | test_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags) || | ||
3656 | (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { | 3656 | (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { |
3657 | struct hci_cp_io_capability_reply cp; | 3657 | struct hci_cp_io_capability_reply cp; |
3658 | 3658 | ||
@@ -3668,7 +3668,7 @@ static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
3668 | * except for the no-bonding case. | 3668 | * except for the no-bonding case. |
3669 | */ | 3669 | */ |
3670 | if (conn->io_capability != HCI_IO_NO_INPUT_OUTPUT && | 3670 | if (conn->io_capability != HCI_IO_NO_INPUT_OUTPUT && |
3671 | cp.authentication != HCI_AT_NO_BONDING) | 3671 | conn->auth_type != HCI_AT_NO_BONDING) |
3672 | conn->auth_type |= 0x01; | 3672 | conn->auth_type |= 0x01; |
3673 | 3673 | ||
3674 | cp.authentication = conn->auth_type; | 3674 | cp.authentication = conn->auth_type; |
@@ -3762,9 +3762,11 @@ static void hci_user_confirm_request_evt(struct hci_dev *hdev, | |||
3762 | /* If we're not the initiators request authorization to | 3762 | /* If we're not the initiators request authorization to |
3763 | * proceed from user space (mgmt_user_confirm with | 3763 | * proceed from user space (mgmt_user_confirm with |
3764 | * confirm_hint set to 1). The exception is if neither | 3764 | * confirm_hint set to 1). The exception is if neither |
3765 | * side had MITM in which case we do auto-accept. | 3765 | * side had MITM or if the local IO capability is |
3766 | * NoInputNoOutput, in which case we do auto-accept | ||
3766 | */ | 3767 | */ |
3767 | if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && | 3768 | if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && |
3769 | conn->io_capability != HCI_IO_NO_INPUT_OUTPUT && | ||
3768 | (loc_mitm || rem_mitm)) { | 3770 | (loc_mitm || rem_mitm)) { |
3769 | BT_DBG("Confirming auto-accept as acceptor"); | 3771 | BT_DBG("Confirming auto-accept as acceptor"); |
3770 | confirm_hint = 1; | 3772 | confirm_hint = 1; |
@@ -3878,6 +3880,9 @@ static void hci_simple_pair_complete_evt(struct hci_dev *hdev, | |||
3878 | if (!conn) | 3880 | if (!conn) |
3879 | goto unlock; | 3881 | goto unlock; |
3880 | 3882 | ||
3883 | /* Reset the authentication requirement to unknown */ | ||
3884 | conn->remote_auth = 0xff; | ||
3885 | |||
3881 | /* To avoid duplicate auth_failed events to user space we check | 3886 | /* To avoid duplicate auth_failed events to user space we check |
3882 | * the HCI_CONN_AUTH_PEND flag which will be set if we | 3887 | * the HCI_CONN_AUTH_PEND flag which will be set if we |
3883 | * initiated the authentication. A traditional auth_complete | 3888 | * initiated the authentication. A traditional auth_complete |
@@ -4108,7 +4113,7 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
4108 | 4113 | ||
4109 | conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); | 4114 | conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); |
4110 | if (!conn) { | 4115 | if (!conn) { |
4111 | conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); | 4116 | conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr, ev->role); |
4112 | if (!conn) { | 4117 | if (!conn) { |
4113 | BT_ERR("No memory for new connection"); | 4118 | BT_ERR("No memory for new connection"); |
4114 | goto unlock; | 4119 | goto unlock; |
@@ -4116,11 +4121,6 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
4116 | 4121 | ||
4117 | conn->dst_type = ev->bdaddr_type; | 4122 | conn->dst_type = ev->bdaddr_type; |
4118 | 4123 | ||
4119 | if (ev->role == LE_CONN_ROLE_MASTER) { | ||
4120 | conn->out = true; | ||
4121 | set_bit(HCI_CONN_MASTER, &conn->flags); | ||
4122 | } | ||
4123 | |||
4124 | /* If we didn't have a hci_conn object previously | 4124 | /* If we didn't have a hci_conn object previously |
4125 | * but we're in master role this must be something | 4125 | * but we're in master role this must be something |
4126 | * initiated using a white list. Since white list based | 4126 | * initiated using a white list. Since white list based |
@@ -4187,14 +4187,14 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
4187 | else | 4187 | else |
4188 | addr_type = BDADDR_LE_RANDOM; | 4188 | addr_type = BDADDR_LE_RANDOM; |
4189 | 4189 | ||
4190 | /* Drop the connection if he device is blocked */ | 4190 | if (ev->status) { |
4191 | if (hci_bdaddr_list_lookup(&hdev->blacklist, &conn->dst, addr_type)) { | 4191 | hci_le_conn_failed(conn, ev->status); |
4192 | hci_conn_drop(conn); | ||
4193 | goto unlock; | 4192 | goto unlock; |
4194 | } | 4193 | } |
4195 | 4194 | ||
4196 | if (ev->status) { | 4195 | /* Drop the connection if the device is blocked */ |
4197 | hci_le_conn_failed(conn, ev->status); | 4196 | if (hci_bdaddr_list_lookup(&hdev->blacklist, &conn->dst, addr_type)) { |
4197 | hci_conn_drop(conn); | ||
4198 | goto unlock; | 4198 | goto unlock; |
4199 | } | 4199 | } |
4200 | 4200 | ||
@@ -4260,6 +4260,12 @@ static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr, | |||
4260 | if (hci_bdaddr_list_lookup(&hdev->blacklist, addr, addr_type)) | 4260 | if (hci_bdaddr_list_lookup(&hdev->blacklist, addr, addr_type)) |
4261 | return; | 4261 | return; |
4262 | 4262 | ||
4263 | /* Most controller will fail if we try to create new connections | ||
4264 | * while we have an existing one in slave role. | ||
4265 | */ | ||
4266 | if (hdev->conn_hash.le_num_slave > 0) | ||
4267 | return; | ||
4268 | |||
4263 | /* If we're connectable, always connect any ADV_DIRECT_IND event */ | 4269 | /* If we're connectable, always connect any ADV_DIRECT_IND event */ |
4264 | if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags) && | 4270 | if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags) && |
4265 | adv_type == LE_ADV_DIRECT_IND) | 4271 | adv_type == LE_ADV_DIRECT_IND) |
@@ -4272,9 +4278,8 @@ static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr, | |||
4272 | return; | 4278 | return; |
4273 | 4279 | ||
4274 | connect: | 4280 | connect: |
4275 | /* Request connection in master = true role */ | ||
4276 | conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW, | 4281 | conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW, |
4277 | HCI_LE_AUTOCONN_TIMEOUT, true); | 4282 | HCI_LE_AUTOCONN_TIMEOUT, HCI_ROLE_MASTER); |
4278 | if (!IS_ERR(conn)) | 4283 | if (!IS_ERR(conn)) |
4279 | return; | 4284 | return; |
4280 | 4285 | ||
@@ -4314,14 +4319,11 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr, | |||
4314 | * device found events. | 4319 | * device found events. |
4315 | */ | 4320 | */ |
4316 | if (hdev->le_scan_type == LE_SCAN_PASSIVE) { | 4321 | if (hdev->le_scan_type == LE_SCAN_PASSIVE) { |
4317 | struct hci_conn_params *param; | ||
4318 | |||
4319 | if (type == LE_ADV_DIRECT_IND) | 4322 | if (type == LE_ADV_DIRECT_IND) |
4320 | return; | 4323 | return; |
4321 | 4324 | ||
4322 | param = hci_pend_le_action_lookup(&hdev->pend_le_reports, | 4325 | if (!hci_pend_le_action_lookup(&hdev->pend_le_reports, |
4323 | bdaddr, bdaddr_type); | 4326 | bdaddr, bdaddr_type)) |
4324 | if (!param) | ||
4325 | return; | 4327 | return; |
4326 | 4328 | ||
4327 | if (type == LE_ADV_NONCONN_IND || type == LE_ADV_SCAN_IND) | 4329 | if (type == LE_ADV_NONCONN_IND || type == LE_ADV_SCAN_IND) |
@@ -4455,7 +4457,7 @@ static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
4455 | if (conn == NULL) | 4457 | if (conn == NULL) |
4456 | goto not_found; | 4458 | goto not_found; |
4457 | 4459 | ||
4458 | ltk = hci_find_ltk(hdev, ev->ediv, ev->rand, conn->out); | 4460 | ltk = hci_find_ltk(hdev, ev->ediv, ev->rand, conn->role); |
4459 | if (ltk == NULL) | 4461 | if (ltk == NULL) |
4460 | goto not_found; | 4462 | goto not_found; |
4461 | 4463 | ||
@@ -4530,7 +4532,7 @@ static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev, | |||
4530 | return send_conn_param_neg_reply(hdev, handle, | 4532 | return send_conn_param_neg_reply(hdev, handle, |
4531 | HCI_ERROR_INVALID_LL_PARAMS); | 4533 | HCI_ERROR_INVALID_LL_PARAMS); |
4532 | 4534 | ||
4533 | if (test_bit(HCI_CONN_MASTER, &hcon->flags)) { | 4535 | if (hcon->role == HCI_ROLE_MASTER) { |
4534 | struct hci_conn_params *params; | 4536 | struct hci_conn_params *params; |
4535 | u8 store_hint; | 4537 | u8 store_hint; |
4536 | 4538 | ||
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 8538cb07b0c0..46547b920f88 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -775,7 +775,7 @@ static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) | |||
775 | } | 775 | } |
776 | 776 | ||
777 | /* Service level security */ | 777 | /* Service level security */ |
778 | int l2cap_chan_check_security(struct l2cap_chan *chan) | 778 | int l2cap_chan_check_security(struct l2cap_chan *chan, bool initiator) |
779 | { | 779 | { |
780 | struct l2cap_conn *conn = chan->conn; | 780 | struct l2cap_conn *conn = chan->conn; |
781 | __u8 auth_type; | 781 | __u8 auth_type; |
@@ -785,7 +785,8 @@ int l2cap_chan_check_security(struct l2cap_chan *chan) | |||
785 | 785 | ||
786 | auth_type = l2cap_get_auth_type(chan); | 786 | auth_type = l2cap_get_auth_type(chan); |
787 | 787 | ||
788 | return hci_conn_security(conn->hcon, chan->sec_level, auth_type); | 788 | return hci_conn_security(conn->hcon, chan->sec_level, auth_type, |
789 | initiator); | ||
789 | } | 790 | } |
790 | 791 | ||
791 | static u8 l2cap_get_ident(struct l2cap_conn *conn) | 792 | static u8 l2cap_get_ident(struct l2cap_conn *conn) |
@@ -1278,7 +1279,7 @@ static void l2cap_do_start(struct l2cap_chan *chan) | |||
1278 | if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)) | 1279 | if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)) |
1279 | return; | 1280 | return; |
1280 | 1281 | ||
1281 | if (l2cap_chan_check_security(chan) && | 1282 | if (l2cap_chan_check_security(chan, true) && |
1282 | __l2cap_no_conn_pending(chan)) { | 1283 | __l2cap_no_conn_pending(chan)) { |
1283 | l2cap_start_connection(chan); | 1284 | l2cap_start_connection(chan); |
1284 | } | 1285 | } |
@@ -1357,7 +1358,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn) | |||
1357 | } | 1358 | } |
1358 | 1359 | ||
1359 | if (chan->state == BT_CONNECT) { | 1360 | if (chan->state == BT_CONNECT) { |
1360 | if (!l2cap_chan_check_security(chan) || | 1361 | if (!l2cap_chan_check_security(chan, true) || |
1361 | !__l2cap_no_conn_pending(chan)) { | 1362 | !__l2cap_no_conn_pending(chan)) { |
1362 | l2cap_chan_unlock(chan); | 1363 | l2cap_chan_unlock(chan); |
1363 | continue; | 1364 | continue; |
@@ -1379,7 +1380,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn) | |||
1379 | rsp.scid = cpu_to_le16(chan->dcid); | 1380 | rsp.scid = cpu_to_le16(chan->dcid); |
1380 | rsp.dcid = cpu_to_le16(chan->scid); | 1381 | rsp.dcid = cpu_to_le16(chan->scid); |
1381 | 1382 | ||
1382 | if (l2cap_chan_check_security(chan)) { | 1383 | if (l2cap_chan_check_security(chan, false)) { |
1383 | if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { | 1384 | if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { |
1384 | rsp.result = cpu_to_le16(L2CAP_CR_PEND); | 1385 | rsp.result = cpu_to_le16(L2CAP_CR_PEND); |
1385 | rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND); | 1386 | rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND); |
@@ -1487,7 +1488,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) | |||
1487 | * been configured for this connection. If not, then trigger | 1488 | * been configured for this connection. If not, then trigger |
1488 | * the connection update procedure. | 1489 | * the connection update procedure. |
1489 | */ | 1490 | */ |
1490 | if (!test_bit(HCI_CONN_MASTER, &hcon->flags) && | 1491 | if (hcon->role == HCI_ROLE_SLAVE && |
1491 | (hcon->le_conn_interval < hcon->le_conn_min_interval || | 1492 | (hcon->le_conn_interval < hcon->le_conn_min_interval || |
1492 | hcon->le_conn_interval > hcon->le_conn_max_interval)) { | 1493 | hcon->le_conn_interval > hcon->le_conn_max_interval)) { |
1493 | struct l2cap_conn_param_update_req req; | 1494 | struct l2cap_conn_param_update_req req; |
@@ -3849,7 +3850,7 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, | |||
3849 | chan->ident = cmd->ident; | 3850 | chan->ident = cmd->ident; |
3850 | 3851 | ||
3851 | if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) { | 3852 | if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) { |
3852 | if (l2cap_chan_check_security(chan)) { | 3853 | if (l2cap_chan_check_security(chan, false)) { |
3853 | if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { | 3854 | if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { |
3854 | l2cap_state_change(chan, BT_CONNECT2); | 3855 | l2cap_state_change(chan, BT_CONNECT2); |
3855 | result = L2CAP_CR_PEND; | 3856 | result = L2CAP_CR_PEND; |
@@ -5227,7 +5228,7 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, | |||
5227 | u16 min, max, latency, to_multiplier; | 5228 | u16 min, max, latency, to_multiplier; |
5228 | int err; | 5229 | int err; |
5229 | 5230 | ||
5230 | if (!test_bit(HCI_CONN_MASTER, &hcon->flags)) | 5231 | if (hcon->role != HCI_ROLE_MASTER) |
5231 | return -EINVAL; | 5232 | return -EINVAL; |
5232 | 5233 | ||
5233 | if (cmd_len != sizeof(struct l2cap_conn_param_update_req)) | 5234 | if (cmd_len != sizeof(struct l2cap_conn_param_update_req)) |
@@ -6984,7 +6985,7 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon) | |||
6984 | if (!hchan) | 6985 | if (!hchan) |
6985 | return NULL; | 6986 | return NULL; |
6986 | 6987 | ||
6987 | conn = kzalloc(sizeof(struct l2cap_conn), GFP_KERNEL); | 6988 | conn = kzalloc(sizeof(*conn), GFP_KERNEL); |
6988 | if (!conn) { | 6989 | if (!conn) { |
6989 | hci_chan_del(hchan); | 6990 | hci_chan_del(hchan); |
6990 | return NULL; | 6991 | return NULL; |
@@ -7093,7 +7094,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, | |||
7093 | break; | 7094 | break; |
7094 | /* fall through */ | 7095 | /* fall through */ |
7095 | default: | 7096 | default: |
7096 | err = -ENOTSUPP; | 7097 | err = -EOPNOTSUPP; |
7097 | goto done; | 7098 | goto done; |
7098 | } | 7099 | } |
7099 | 7100 | ||
@@ -7128,7 +7129,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, | |||
7128 | chan->dcid = cid; | 7129 | chan->dcid = cid; |
7129 | 7130 | ||
7130 | if (bdaddr_type_is_le(dst_type)) { | 7131 | if (bdaddr_type_is_le(dst_type)) { |
7131 | bool master; | 7132 | u8 role; |
7132 | 7133 | ||
7133 | /* Convert from L2CAP channel address type to HCI address type | 7134 | /* Convert from L2CAP channel address type to HCI address type |
7134 | */ | 7135 | */ |
@@ -7137,10 +7138,13 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, | |||
7137 | else | 7138 | else |
7138 | dst_type = ADDR_LE_DEV_RANDOM; | 7139 | dst_type = ADDR_LE_DEV_RANDOM; |
7139 | 7140 | ||
7140 | master = !test_bit(HCI_ADVERTISING, &hdev->dev_flags); | 7141 | if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) |
7142 | role = HCI_ROLE_SLAVE; | ||
7143 | else | ||
7144 | role = HCI_ROLE_MASTER; | ||
7141 | 7145 | ||
7142 | hcon = hci_connect_le(hdev, dst, dst_type, chan->sec_level, | 7146 | hcon = hci_connect_le(hdev, dst, dst_type, chan->sec_level, |
7143 | HCI_LE_CONN_TIMEOUT, master); | 7147 | HCI_LE_CONN_TIMEOUT, role); |
7144 | } else { | 7148 | } else { |
7145 | u8 auth_type = l2cap_get_auth_type(chan); | 7149 | u8 auth_type = l2cap_get_auth_type(chan); |
7146 | hcon = hci_connect_acl(hdev, dst, chan->sec_level, auth_type); | 7150 | hcon = hci_connect_acl(hdev, dst, chan->sec_level, auth_type); |
@@ -7188,7 +7192,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, | |||
7188 | if (hcon->state == BT_CONNECTED) { | 7192 | if (hcon->state == BT_CONNECTED) { |
7189 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { | 7193 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { |
7190 | __clear_chan_timer(chan); | 7194 | __clear_chan_timer(chan); |
7191 | if (l2cap_chan_check_security(chan)) | 7195 | if (l2cap_chan_check_security(chan, true)) |
7192 | l2cap_state_change(chan, BT_CONNECTED); | 7196 | l2cap_state_change(chan, BT_CONNECTED); |
7193 | } else | 7197 | } else |
7194 | l2cap_do_start(chan); | 7198 | l2cap_do_start(chan); |
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 9bb4d1b3a483..1884f72083c2 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -279,7 +279,7 @@ static int l2cap_sock_listen(struct socket *sock, int backlog) | |||
279 | break; | 279 | break; |
280 | /* fall through */ | 280 | /* fall through */ |
281 | default: | 281 | default: |
282 | err = -ENOTSUPP; | 282 | err = -EOPNOTSUPP; |
283 | goto done; | 283 | goto done; |
284 | } | 284 | } |
285 | 285 | ||
@@ -797,7 +797,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, | |||
797 | } else if ((sk->sk_state == BT_CONNECT2 && | 797 | } else if ((sk->sk_state == BT_CONNECT2 && |
798 | test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) || | 798 | test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) || |
799 | sk->sk_state == BT_CONNECTED) { | 799 | sk->sk_state == BT_CONNECTED) { |
800 | if (!l2cap_chan_check_security(chan)) | 800 | if (!l2cap_chan_check_security(chan, true)) |
801 | set_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags); | 801 | set_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags); |
802 | else | 802 | else |
803 | sk->sk_state_change(sk); | 803 | sk->sk_state_change(sk); |
@@ -1112,7 +1112,8 @@ static int l2cap_sock_shutdown(struct socket *sock, int how) | |||
1112 | l2cap_chan_close(chan, 0); | 1112 | l2cap_chan_close(chan, 0); |
1113 | lock_sock(sk); | 1113 | lock_sock(sk); |
1114 | 1114 | ||
1115 | if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) | 1115 | if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime && |
1116 | !(current->flags & PF_EXITING)) | ||
1116 | err = bt_sock_wait_state(sk, BT_CLOSED, | 1117 | err = bt_sock_wait_state(sk, BT_CLOSED, |
1117 | sk->sk_lingertime); | 1118 | sk->sk_lingertime); |
1118 | } | 1119 | } |
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 7703b72653ff..190668367e42 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -3154,9 +3154,9 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data, | |||
3154 | */ | 3154 | */ |
3155 | hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type); | 3155 | hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type); |
3156 | 3156 | ||
3157 | /* Request a connection with master = true role */ | ||
3158 | conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type, | 3157 | conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type, |
3159 | sec_level, HCI_LE_CONN_TIMEOUT, true); | 3158 | sec_level, HCI_LE_CONN_TIMEOUT, |
3159 | HCI_ROLE_MASTER); | ||
3160 | } | 3160 | } |
3161 | 3161 | ||
3162 | if (IS_ERR(conn)) { | 3162 | if (IS_ERR(conn)) { |
@@ -3202,7 +3202,7 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data, | |||
3202 | cmd->user_data = conn; | 3202 | cmd->user_data = conn; |
3203 | 3203 | ||
3204 | if (conn->state == BT_CONNECTED && | 3204 | if (conn->state == BT_CONNECTED && |
3205 | hci_conn_security(conn, sec_level, auth_type)) | 3205 | hci_conn_security(conn, sec_level, auth_type, true)) |
3206 | pairing_complete(cmd, 0); | 3206 | pairing_complete(cmd, 0); |
3207 | 3207 | ||
3208 | err = 0; | 3208 | err = 0; |
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 754b6fe4f742..a0690a84f3e9 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c | |||
@@ -227,7 +227,8 @@ static int rfcomm_check_security(struct rfcomm_dlc *d) | |||
227 | break; | 227 | break; |
228 | } | 228 | } |
229 | 229 | ||
230 | return hci_conn_security(conn->hcon, d->sec_level, auth_type); | 230 | return hci_conn_security(conn->hcon, d->sec_level, auth_type, |
231 | d->out); | ||
231 | } | 232 | } |
232 | 233 | ||
233 | static void rfcomm_session_timeout(unsigned long arg) | 234 | static void rfcomm_session_timeout(unsigned long arg) |
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index c603a5eb4720..8bbbb5ec468c 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c | |||
@@ -918,7 +918,8 @@ static int rfcomm_sock_shutdown(struct socket *sock, int how) | |||
918 | sk->sk_shutdown = SHUTDOWN_MASK; | 918 | sk->sk_shutdown = SHUTDOWN_MASK; |
919 | __rfcomm_sock_close(sk); | 919 | __rfcomm_sock_close(sk); |
920 | 920 | ||
921 | if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) | 921 | if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime && |
922 | !(current->flags & PF_EXITING)) | ||
922 | err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime); | 923 | err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime); |
923 | } | 924 | } |
924 | release_sock(sk); | 925 | release_sock(sk); |
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index ebf7ee6a446c..7ee9e4ab00f8 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c | |||
@@ -970,7 +970,8 @@ static int sco_sock_shutdown(struct socket *sock, int how) | |||
970 | sco_sock_clear_timer(sk); | 970 | sco_sock_clear_timer(sk); |
971 | __sco_sock_close(sk); | 971 | __sco_sock_close(sk); |
972 | 972 | ||
973 | if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) | 973 | if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime && |
974 | !(current->flags & PF_EXITING)) | ||
974 | err = bt_sock_wait_state(sk, BT_CLOSED, | 975 | err = bt_sock_wait_state(sk, BT_CLOSED, |
975 | sk->sk_lingertime); | 976 | sk->sk_lingertime); |
976 | } | 977 | } |
@@ -990,7 +991,8 @@ static int sco_sock_release(struct socket *sock) | |||
990 | 991 | ||
991 | sco_sock_close(sk); | 992 | sco_sock_close(sk); |
992 | 993 | ||
993 | if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) { | 994 | if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime && |
995 | !(current->flags & PF_EXITING)) { | ||
994 | lock_sock(sk); | 996 | lock_sock(sk); |
995 | err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime); | 997 | err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime); |
996 | release_sock(sk); | 998 | release_sock(sk); |
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 8339d6b0f2b8..e49c83d8b957 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c | |||
@@ -431,6 +431,10 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth, | |||
431 | if (method == JUST_CFM && test_bit(SMP_FLAG_INITIATOR, &smp->flags)) | 431 | if (method == JUST_CFM && test_bit(SMP_FLAG_INITIATOR, &smp->flags)) |
432 | method = JUST_WORKS; | 432 | method = JUST_WORKS; |
433 | 433 | ||
434 | /* Don't bother user space with no IO capabilities */ | ||
435 | if (method == JUST_CFM && hcon->io_capability == HCI_IO_NO_INPUT_OUTPUT) | ||
436 | method = JUST_WORKS; | ||
437 | |||
434 | /* If Just Works, Continue with Zero TK */ | 438 | /* If Just Works, Continue with Zero TK */ |
435 | if (method == JUST_WORKS) { | 439 | if (method == JUST_WORKS) { |
436 | set_bit(SMP_FLAG_TK_VALID, &smp->flags); | 440 | set_bit(SMP_FLAG_TK_VALID, &smp->flags); |
@@ -445,7 +449,7 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth, | |||
445 | * Confirms and the slave Enters the passkey. | 449 | * Confirms and the slave Enters the passkey. |
446 | */ | 450 | */ |
447 | if (method == OVERLAP) { | 451 | if (method == OVERLAP) { |
448 | if (test_bit(HCI_CONN_MASTER, &hcon->flags)) | 452 | if (hcon->role == HCI_ROLE_MASTER) |
449 | method = CFM_PASSKEY; | 453 | method = CFM_PASSKEY; |
450 | else | 454 | else |
451 | method = REQ_PASSKEY; | 455 | method = REQ_PASSKEY; |
@@ -686,7 +690,7 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
686 | if (skb->len < sizeof(*req)) | 690 | if (skb->len < sizeof(*req)) |
687 | return SMP_INVALID_PARAMS; | 691 | return SMP_INVALID_PARAMS; |
688 | 692 | ||
689 | if (test_bit(HCI_CONN_MASTER, &conn->hcon->flags)) | 693 | if (conn->hcon->role != HCI_ROLE_SLAVE) |
690 | return SMP_CMD_NOTSUPP; | 694 | return SMP_CMD_NOTSUPP; |
691 | 695 | ||
692 | if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) | 696 | if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) |
@@ -755,7 +759,7 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb) | |||
755 | if (skb->len < sizeof(*rsp)) | 759 | if (skb->len < sizeof(*rsp)) |
756 | return SMP_INVALID_PARAMS; | 760 | return SMP_INVALID_PARAMS; |
757 | 761 | ||
758 | if (!test_bit(HCI_CONN_MASTER, &conn->hcon->flags)) | 762 | if (conn->hcon->role != HCI_ROLE_MASTER) |
759 | return SMP_CMD_NOTSUPP; | 763 | return SMP_CMD_NOTSUPP; |
760 | 764 | ||
761 | skb_pull(skb, sizeof(*rsp)); | 765 | skb_pull(skb, sizeof(*rsp)); |
@@ -849,7 +853,7 @@ static bool smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level) | |||
849 | struct hci_conn *hcon = conn->hcon; | 853 | struct hci_conn *hcon = conn->hcon; |
850 | 854 | ||
851 | key = hci_find_ltk_by_addr(hcon->hdev, &hcon->dst, hcon->dst_type, | 855 | key = hci_find_ltk_by_addr(hcon->hdev, &hcon->dst, hcon->dst_type, |
852 | hcon->out); | 856 | hcon->role); |
853 | if (!key) | 857 | if (!key) |
854 | return false; | 858 | return false; |
855 | 859 | ||
@@ -881,7 +885,7 @@ bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level) | |||
881 | */ | 885 | */ |
882 | if (test_bit(HCI_CONN_STK_ENCRYPT, &hcon->flags) && | 886 | if (test_bit(HCI_CONN_STK_ENCRYPT, &hcon->flags) && |
883 | hci_find_ltk_by_addr(hcon->hdev, &hcon->dst, hcon->dst_type, | 887 | hci_find_ltk_by_addr(hcon->hdev, &hcon->dst, hcon->dst_type, |
884 | hcon->out)) | 888 | hcon->role)) |
885 | return false; | 889 | return false; |
886 | 890 | ||
887 | if (hcon->sec_level >= sec_level) | 891 | if (hcon->sec_level >= sec_level) |
@@ -903,7 +907,7 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
903 | if (skb->len < sizeof(*rp)) | 907 | if (skb->len < sizeof(*rp)) |
904 | return SMP_INVALID_PARAMS; | 908 | return SMP_INVALID_PARAMS; |
905 | 909 | ||
906 | if (!test_bit(HCI_CONN_MASTER, &conn->hcon->flags)) | 910 | if (hcon->role != HCI_ROLE_MASTER) |
907 | return SMP_CMD_NOTSUPP; | 911 | return SMP_CMD_NOTSUPP; |
908 | 912 | ||
909 | sec_level = authreq_to_seclevel(rp->auth_req); | 913 | sec_level = authreq_to_seclevel(rp->auth_req); |
@@ -961,7 +965,7 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) | |||
961 | if (sec_level > hcon->pending_sec_level) | 965 | if (sec_level > hcon->pending_sec_level) |
962 | hcon->pending_sec_level = sec_level; | 966 | hcon->pending_sec_level = sec_level; |
963 | 967 | ||
964 | if (test_bit(HCI_CONN_MASTER, &hcon->flags)) | 968 | if (hcon->role == HCI_ROLE_MASTER) |
965 | if (smp_ltk_encrypt(conn, hcon->pending_sec_level)) | 969 | if (smp_ltk_encrypt(conn, hcon->pending_sec_level)) |
966 | return 0; | 970 | return 0; |
967 | 971 | ||
@@ -981,7 +985,7 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) | |||
981 | hcon->pending_sec_level > BT_SECURITY_MEDIUM) | 985 | hcon->pending_sec_level > BT_SECURITY_MEDIUM) |
982 | authreq |= SMP_AUTH_MITM; | 986 | authreq |= SMP_AUTH_MITM; |
983 | 987 | ||
984 | if (test_bit(HCI_CONN_MASTER, &hcon->flags)) { | 988 | if (hcon->role == HCI_ROLE_MASTER) { |
985 | struct smp_cmd_pairing cp; | 989 | struct smp_cmd_pairing cp; |
986 | 990 | ||
987 | build_pairing_cmd(conn, &cp, NULL, authreq); | 991 | build_pairing_cmd(conn, &cp, NULL, authreq); |
@@ -1185,7 +1189,7 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) | |||
1185 | } | 1189 | } |
1186 | 1190 | ||
1187 | if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags)) { | 1191 | if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags)) { |
1188 | err = -ENOTSUPP; | 1192 | err = -EOPNOTSUPP; |
1189 | reason = SMP_PAIRING_NOTSUPP; | 1193 | reason = SMP_PAIRING_NOTSUPP; |
1190 | goto done; | 1194 | goto done; |
1191 | } | 1195 | } |
@@ -1203,7 +1207,7 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) | |||
1203 | !conn->smp_chan) { | 1207 | !conn->smp_chan) { |
1204 | BT_ERR("Unexpected SMP command 0x%02x. Disconnecting.", code); | 1208 | BT_ERR("Unexpected SMP command 0x%02x. Disconnecting.", code); |
1205 | kfree_skb(skb); | 1209 | kfree_skb(skb); |
1206 | return -ENOTSUPP; | 1210 | return -EOPNOTSUPP; |
1207 | } | 1211 | } |
1208 | 1212 | ||
1209 | switch (code) { | 1213 | switch (code) { |
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 31bf2586fb84..f0e84bc48038 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c | |||
@@ -52,7 +52,7 @@ static void ieee80211_free_tid_rx(struct rcu_head *h) | |||
52 | del_timer_sync(&tid_rx->reorder_timer); | 52 | del_timer_sync(&tid_rx->reorder_timer); |
53 | 53 | ||
54 | for (i = 0; i < tid_rx->buf_size; i++) | 54 | for (i = 0; i < tid_rx->buf_size; i++) |
55 | dev_kfree_skb(tid_rx->reorder_buf[i]); | 55 | __skb_queue_purge(&tid_rx->reorder_buf[i]); |
56 | kfree(tid_rx->reorder_buf); | 56 | kfree(tid_rx->reorder_buf); |
57 | kfree(tid_rx->reorder_time); | 57 | kfree(tid_rx->reorder_time); |
58 | kfree(tid_rx); | 58 | kfree(tid_rx); |
@@ -224,28 +224,15 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d | |||
224 | ieee80211_tx_skb(sdata, skb); | 224 | ieee80211_tx_skb(sdata, skb); |
225 | } | 225 | } |
226 | 226 | ||
227 | void ieee80211_process_addba_request(struct ieee80211_local *local, | 227 | void __ieee80211_start_rx_ba_session(struct sta_info *sta, |
228 | struct sta_info *sta, | 228 | u8 dialog_token, u16 timeout, |
229 | struct ieee80211_mgmt *mgmt, | 229 | u16 start_seq_num, u16 ba_policy, u16 tid, |
230 | size_t len) | 230 | u16 buf_size, bool tx) |
231 | { | 231 | { |
232 | struct ieee80211_local *local = sta->sdata->local; | ||
232 | struct tid_ampdu_rx *tid_agg_rx; | 233 | struct tid_ampdu_rx *tid_agg_rx; |
233 | u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num, status; | 234 | int i, ret = -EOPNOTSUPP; |
234 | u8 dialog_token; | 235 | u16 status = WLAN_STATUS_REQUEST_DECLINED; |
235 | int ret = -EOPNOTSUPP; | ||
236 | |||
237 | /* extract session parameters from addba request frame */ | ||
238 | dialog_token = mgmt->u.action.u.addba_req.dialog_token; | ||
239 | timeout = le16_to_cpu(mgmt->u.action.u.addba_req.timeout); | ||
240 | start_seq_num = | ||
241 | le16_to_cpu(mgmt->u.action.u.addba_req.start_seq_num) >> 4; | ||
242 | |||
243 | capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab); | ||
244 | ba_policy = (capab & IEEE80211_ADDBA_PARAM_POLICY_MASK) >> 1; | ||
245 | tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; | ||
246 | buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6; | ||
247 | |||
248 | status = WLAN_STATUS_REQUEST_DECLINED; | ||
249 | 236 | ||
250 | if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) { | 237 | if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) { |
251 | ht_dbg(sta->sdata, | 238 | ht_dbg(sta->sdata, |
@@ -264,7 +251,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
264 | status = WLAN_STATUS_INVALID_QOS_PARAM; | 251 | status = WLAN_STATUS_INVALID_QOS_PARAM; |
265 | ht_dbg_ratelimited(sta->sdata, | 252 | ht_dbg_ratelimited(sta->sdata, |
266 | "AddBA Req with bad params from %pM on tid %u. policy %d, buffer size %d\n", | 253 | "AddBA Req with bad params from %pM on tid %u. policy %d, buffer size %d\n", |
267 | mgmt->sa, tid, ba_policy, buf_size); | 254 | sta->sta.addr, tid, ba_policy, buf_size); |
268 | goto end_no_lock; | 255 | goto end_no_lock; |
269 | } | 256 | } |
270 | /* determine default buffer size */ | 257 | /* determine default buffer size */ |
@@ -281,7 +268,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
281 | if (sta->ampdu_mlme.tid_rx[tid]) { | 268 | if (sta->ampdu_mlme.tid_rx[tid]) { |
282 | ht_dbg_ratelimited(sta->sdata, | 269 | ht_dbg_ratelimited(sta->sdata, |
283 | "unexpected AddBA Req from %pM on tid %u\n", | 270 | "unexpected AddBA Req from %pM on tid %u\n", |
284 | mgmt->sa, tid); | 271 | sta->sta.addr, tid); |
285 | 272 | ||
286 | /* delete existing Rx BA session on the same tid */ | 273 | /* delete existing Rx BA session on the same tid */ |
287 | ___ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT, | 274 | ___ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT, |
@@ -308,7 +295,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
308 | 295 | ||
309 | /* prepare reordering buffer */ | 296 | /* prepare reordering buffer */ |
310 | tid_agg_rx->reorder_buf = | 297 | tid_agg_rx->reorder_buf = |
311 | kcalloc(buf_size, sizeof(struct sk_buff *), GFP_KERNEL); | 298 | kcalloc(buf_size, sizeof(struct sk_buff_head), GFP_KERNEL); |
312 | tid_agg_rx->reorder_time = | 299 | tid_agg_rx->reorder_time = |
313 | kcalloc(buf_size, sizeof(unsigned long), GFP_KERNEL); | 300 | kcalloc(buf_size, sizeof(unsigned long), GFP_KERNEL); |
314 | if (!tid_agg_rx->reorder_buf || !tid_agg_rx->reorder_time) { | 301 | if (!tid_agg_rx->reorder_buf || !tid_agg_rx->reorder_time) { |
@@ -318,6 +305,9 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
318 | goto end; | 305 | goto end; |
319 | } | 306 | } |
320 | 307 | ||
308 | for (i = 0; i < buf_size; i++) | ||
309 | __skb_queue_head_init(&tid_agg_rx->reorder_buf[i]); | ||
310 | |||
321 | ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START, | 311 | ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START, |
322 | &sta->sta, tid, &start_seq_num, 0); | 312 | &sta->sta, tid, &start_seq_num, 0); |
323 | ht_dbg(sta->sdata, "Rx A-MPDU request on %pM tid %d result %d\n", | 313 | ht_dbg(sta->sdata, "Rx A-MPDU request on %pM tid %d result %d\n", |
@@ -350,6 +340,74 @@ end: | |||
350 | mutex_unlock(&sta->ampdu_mlme.mtx); | 340 | mutex_unlock(&sta->ampdu_mlme.mtx); |
351 | 341 | ||
352 | end_no_lock: | 342 | end_no_lock: |
353 | ieee80211_send_addba_resp(sta->sdata, sta->sta.addr, tid, | 343 | if (tx) |
354 | dialog_token, status, 1, buf_size, timeout); | 344 | ieee80211_send_addba_resp(sta->sdata, sta->sta.addr, tid, |
345 | dialog_token, status, 1, buf_size, | ||
346 | timeout); | ||
347 | } | ||
348 | |||
349 | void ieee80211_process_addba_request(struct ieee80211_local *local, | ||
350 | struct sta_info *sta, | ||
351 | struct ieee80211_mgmt *mgmt, | ||
352 | size_t len) | ||
353 | { | ||
354 | u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num; | ||
355 | u8 dialog_token; | ||
356 | |||
357 | /* extract session parameters from addba request frame */ | ||
358 | dialog_token = mgmt->u.action.u.addba_req.dialog_token; | ||
359 | timeout = le16_to_cpu(mgmt->u.action.u.addba_req.timeout); | ||
360 | start_seq_num = | ||
361 | le16_to_cpu(mgmt->u.action.u.addba_req.start_seq_num) >> 4; | ||
362 | |||
363 | capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab); | ||
364 | ba_policy = (capab & IEEE80211_ADDBA_PARAM_POLICY_MASK) >> 1; | ||
365 | tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; | ||
366 | buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6; | ||
367 | |||
368 | __ieee80211_start_rx_ba_session(sta, dialog_token, timeout, | ||
369 | start_seq_num, ba_policy, tid, | ||
370 | buf_size, true); | ||
371 | } | ||
372 | |||
373 | void ieee80211_start_rx_ba_session_offl(struct ieee80211_vif *vif, | ||
374 | const u8 *addr, u16 tid) | ||
375 | { | ||
376 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
377 | struct ieee80211_local *local = sdata->local; | ||
378 | struct ieee80211_rx_agg *rx_agg; | ||
379 | struct sk_buff *skb = dev_alloc_skb(0); | ||
380 | |||
381 | if (unlikely(!skb)) | ||
382 | return; | ||
383 | |||
384 | rx_agg = (struct ieee80211_rx_agg *) &skb->cb; | ||
385 | memcpy(&rx_agg->addr, addr, ETH_ALEN); | ||
386 | rx_agg->tid = tid; | ||
387 | |||
388 | skb->pkt_type = IEEE80211_SDATA_QUEUE_RX_AGG_START; | ||
389 | skb_queue_tail(&sdata->skb_queue, skb); | ||
390 | ieee80211_queue_work(&local->hw, &sdata->work); | ||
391 | } | ||
392 | EXPORT_SYMBOL(ieee80211_start_rx_ba_session_offl); | ||
393 | |||
394 | void ieee80211_stop_rx_ba_session_offl(struct ieee80211_vif *vif, | ||
395 | const u8 *addr, u16 tid) | ||
396 | { | ||
397 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
398 | struct ieee80211_local *local = sdata->local; | ||
399 | struct ieee80211_rx_agg *rx_agg; | ||
400 | struct sk_buff *skb = dev_alloc_skb(0); | ||
401 | |||
402 | if (unlikely(!skb)) | ||
403 | return; | ||
404 | |||
405 | rx_agg = (struct ieee80211_rx_agg *) &skb->cb; | ||
406 | memcpy(&rx_agg->addr, addr, ETH_ALEN); | ||
407 | rx_agg->tid = tid; | ||
408 | |||
409 | skb->pkt_type = IEEE80211_SDATA_QUEUE_RX_AGG_STOP; | ||
410 | skb_queue_tail(&sdata->skb_queue, skb); | ||
411 | ieee80211_queue_work(&local->hw, &sdata->work); | ||
355 | } | 412 | } |
413 | EXPORT_SYMBOL(ieee80211_stop_rx_ba_session_offl); | ||
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index c3fd4d275bf4..6d537f03c0ba 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c | |||
@@ -66,7 +66,7 @@ static bool ieee80211_can_create_new_chanctx(struct ieee80211_local *local) | |||
66 | static struct ieee80211_chanctx * | 66 | static struct ieee80211_chanctx * |
67 | ieee80211_vif_get_chanctx(struct ieee80211_sub_if_data *sdata) | 67 | ieee80211_vif_get_chanctx(struct ieee80211_sub_if_data *sdata) |
68 | { | 68 | { |
69 | struct ieee80211_local *local = sdata->local; | 69 | struct ieee80211_local *local __maybe_unused = sdata->local; |
70 | struct ieee80211_chanctx_conf *conf; | 70 | struct ieee80211_chanctx_conf *conf; |
71 | 71 | ||
72 | conf = rcu_dereference_protected(sdata->vif.chanctx_conf, | 72 | conf = rcu_dereference_protected(sdata->vif.chanctx_conf, |
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 15702ff64a4c..ff630be2ca75 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -150,13 +150,12 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata, | |||
150 | 150 | ||
151 | /* | 151 | /* |
152 | * If user has specified capability over-rides, take care | 152 | * If user has specified capability over-rides, take care |
153 | * of that if the station we're setting up is the AP that | 153 | * of that if the station we're setting up is the AP or TDLS peer that |
154 | * we advertised a restricted capability set to. Override | 154 | * we advertised a restricted capability set to. Override |
155 | * our own capabilities and then use those below. | 155 | * our own capabilities and then use those below. |
156 | */ | 156 | */ |
157 | if ((sdata->vif.type == NL80211_IFTYPE_STATION || | 157 | if (sdata->vif.type == NL80211_IFTYPE_STATION || |
158 | sdata->vif.type == NL80211_IFTYPE_ADHOC) && | 158 | sdata->vif.type == NL80211_IFTYPE_ADHOC) |
159 | !test_sta_flag(sta, WLAN_STA_TDLS_PEER)) | ||
160 | ieee80211_apply_htcap_overrides(sdata, &own_cap); | 159 | ieee80211_apply_htcap_overrides(sdata, &own_cap); |
161 | 160 | ||
162 | /* | 161 | /* |
@@ -228,6 +227,9 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata, | |||
228 | if (own_cap.mcs.rx_mask[32/8] & ht_cap_ie->mcs.rx_mask[32/8] & 1) | 227 | if (own_cap.mcs.rx_mask[32/8] & ht_cap_ie->mcs.rx_mask[32/8] & 1) |
229 | ht_cap.mcs.rx_mask[32/8] |= 1; | 228 | ht_cap.mcs.rx_mask[32/8] |= 1; |
230 | 229 | ||
230 | /* set Rx highest rate */ | ||
231 | ht_cap.mcs.rx_highest = ht_cap_ie->mcs.rx_highest; | ||
232 | |||
231 | apply: | 233 | apply: |
232 | changed = memcmp(&sta->sta.ht_cap, &ht_cap, sizeof(ht_cap)); | 234 | changed = memcmp(&sta->sta.ht_cap, &ht_cap, sizeof(ht_cap)); |
233 | 235 | ||
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 713485f9effc..9713dc54ea4b 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -189,17 +189,8 @@ ieee80211_ibss_build_presp(struct ieee80211_sub_if_data *sdata, | |||
189 | chandef, 0); | 189 | chandef, 0); |
190 | } | 190 | } |
191 | 191 | ||
192 | if (local->hw.queues >= IEEE80211_NUM_ACS) { | 192 | if (local->hw.queues >= IEEE80211_NUM_ACS) |
193 | *pos++ = WLAN_EID_VENDOR_SPECIFIC; | 193 | pos = ieee80211_add_wmm_info_ie(pos, 0); /* U-APSD not in use */ |
194 | *pos++ = 7; /* len */ | ||
195 | *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */ | ||
196 | *pos++ = 0x50; | ||
197 | *pos++ = 0xf2; | ||
198 | *pos++ = 2; /* WME */ | ||
199 | *pos++ = 0; /* WME info */ | ||
200 | *pos++ = 1; /* WME ver */ | ||
201 | *pos++ = 0; /* U-APSD no in use */ | ||
202 | } | ||
203 | 194 | ||
204 | presp->head_len = pos - presp->head; | 195 | presp->head_len = pos - presp->head; |
205 | if (WARN_ON(presp->head_len > frame_len)) | 196 | if (WARN_ON(presp->head_len > frame_len)) |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 9e025e1184cc..ef7a089ac546 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -345,7 +345,6 @@ enum ieee80211_sta_flags { | |||
345 | IEEE80211_STA_CONNECTION_POLL = BIT(1), | 345 | IEEE80211_STA_CONNECTION_POLL = BIT(1), |
346 | IEEE80211_STA_CONTROL_PORT = BIT(2), | 346 | IEEE80211_STA_CONTROL_PORT = BIT(2), |
347 | IEEE80211_STA_DISABLE_HT = BIT(4), | 347 | IEEE80211_STA_DISABLE_HT = BIT(4), |
348 | IEEE80211_STA_CSA_RECEIVED = BIT(5), | ||
349 | IEEE80211_STA_MFP_ENABLED = BIT(6), | 348 | IEEE80211_STA_MFP_ENABLED = BIT(6), |
350 | IEEE80211_STA_UAPSD_ENABLED = BIT(7), | 349 | IEEE80211_STA_UAPSD_ENABLED = BIT(7), |
351 | IEEE80211_STA_NULLFUNC_ACKED = BIT(8), | 350 | IEEE80211_STA_NULLFUNC_ACKED = BIT(8), |
@@ -503,6 +502,9 @@ struct ieee80211_if_managed { | |||
503 | struct ieee80211_ht_cap ht_capa_mask; /* Valid parts of ht_capa */ | 502 | struct ieee80211_ht_cap ht_capa_mask; /* Valid parts of ht_capa */ |
504 | struct ieee80211_vht_cap vht_capa; /* configured VHT overrides */ | 503 | struct ieee80211_vht_cap vht_capa; /* configured VHT overrides */ |
505 | struct ieee80211_vht_cap vht_capa_mask; /* Valid parts of vht_capa */ | 504 | struct ieee80211_vht_cap vht_capa_mask; /* Valid parts of vht_capa */ |
505 | |||
506 | u8 tdls_peer[ETH_ALEN] __aligned(2); | ||
507 | struct delayed_work tdls_peer_del_work; | ||
506 | }; | 508 | }; |
507 | 509 | ||
508 | struct ieee80211_if_ibss { | 510 | struct ieee80211_if_ibss { |
@@ -815,9 +817,6 @@ struct ieee80211_sub_if_data { | |||
815 | bool radar_required; | 817 | bool radar_required; |
816 | struct delayed_work dfs_cac_timer_work; | 818 | struct delayed_work dfs_cac_timer_work; |
817 | 819 | ||
818 | u8 tdls_peer[ETH_ALEN] __aligned(2); | ||
819 | struct delayed_work tdls_peer_del_work; | ||
820 | |||
821 | /* | 820 | /* |
822 | * AP this belongs to: self in AP mode and | 821 | * AP this belongs to: self in AP mode and |
823 | * corresponding AP in VLAN mode, NULL for | 822 | * corresponding AP in VLAN mode, NULL for |
@@ -926,10 +925,17 @@ ieee80211_vif_get_shift(struct ieee80211_vif *vif) | |||
926 | return shift; | 925 | return shift; |
927 | } | 926 | } |
928 | 927 | ||
928 | struct ieee80211_rx_agg { | ||
929 | u8 addr[ETH_ALEN]; | ||
930 | u16 tid; | ||
931 | }; | ||
932 | |||
929 | enum sdata_queue_type { | 933 | enum sdata_queue_type { |
930 | IEEE80211_SDATA_QUEUE_TYPE_FRAME = 0, | 934 | IEEE80211_SDATA_QUEUE_TYPE_FRAME = 0, |
931 | IEEE80211_SDATA_QUEUE_AGG_START = 1, | 935 | IEEE80211_SDATA_QUEUE_AGG_START = 1, |
932 | IEEE80211_SDATA_QUEUE_AGG_STOP = 2, | 936 | IEEE80211_SDATA_QUEUE_AGG_STOP = 2, |
937 | IEEE80211_SDATA_QUEUE_RX_AGG_START = 3, | ||
938 | IEEE80211_SDATA_QUEUE_RX_AGG_STOP = 4, | ||
933 | }; | 939 | }; |
934 | 940 | ||
935 | enum { | 941 | enum { |
@@ -1578,6 +1584,10 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | |||
1578 | u16 initiator, u16 reason, bool stop); | 1584 | u16 initiator, u16 reason, bool stop); |
1579 | void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | 1585 | void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, |
1580 | u16 initiator, u16 reason, bool stop); | 1586 | u16 initiator, u16 reason, bool stop); |
1587 | void __ieee80211_start_rx_ba_session(struct sta_info *sta, | ||
1588 | u8 dialog_token, u16 timeout, | ||
1589 | u16 start_seq_num, u16 ba_policy, u16 tid, | ||
1590 | u16 buf_size, bool tx); | ||
1581 | void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, | 1591 | void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, |
1582 | enum ieee80211_agg_stop_reason reason); | 1592 | enum ieee80211_agg_stop_reason reason); |
1583 | void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, | 1593 | void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, |
@@ -1730,6 +1740,21 @@ static inline void ieee802_11_parse_elems(const u8 *start, size_t len, | |||
1730 | ieee802_11_parse_elems_crc(start, len, action, elems, 0, 0); | 1740 | ieee802_11_parse_elems_crc(start, len, action, elems, 0, 0); |
1731 | } | 1741 | } |
1732 | 1742 | ||
1743 | static inline bool ieee80211_rx_reorder_ready(struct sk_buff_head *frames) | ||
1744 | { | ||
1745 | struct sk_buff *tail = skb_peek_tail(frames); | ||
1746 | struct ieee80211_rx_status *status; | ||
1747 | |||
1748 | if (!tail) | ||
1749 | return false; | ||
1750 | |||
1751 | status = IEEE80211_SKB_RXCB(tail); | ||
1752 | if (status->flag & RX_FLAG_AMSDU_MORE) | ||
1753 | return false; | ||
1754 | |||
1755 | return true; | ||
1756 | } | ||
1757 | |||
1733 | void ieee80211_dynamic_ps_enable_work(struct work_struct *work); | 1758 | void ieee80211_dynamic_ps_enable_work(struct work_struct *work); |
1734 | void ieee80211_dynamic_ps_disable_work(struct work_struct *work); | 1759 | void ieee80211_dynamic_ps_disable_work(struct work_struct *work); |
1735 | void ieee80211_dynamic_ps_timer(unsigned long data); | 1760 | void ieee80211_dynamic_ps_timer(unsigned long data); |
@@ -1824,6 +1849,7 @@ int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, | |||
1824 | int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata, | 1849 | int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata, |
1825 | struct sk_buff *skb, bool need_basic, | 1850 | struct sk_buff *skb, bool need_basic, |
1826 | enum ieee80211_band band); | 1851 | enum ieee80211_band band); |
1852 | u8 *ieee80211_add_wmm_info_ie(u8 *buf, u8 qosinfo); | ||
1827 | 1853 | ||
1828 | /* channel management */ | 1854 | /* channel management */ |
1829 | void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan, | 1855 | void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index bbf51b2f0651..29be8854a027 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -1140,6 +1140,7 @@ static void ieee80211_iface_work(struct work_struct *work) | |||
1140 | struct sk_buff *skb; | 1140 | struct sk_buff *skb; |
1141 | struct sta_info *sta; | 1141 | struct sta_info *sta; |
1142 | struct ieee80211_ra_tid *ra_tid; | 1142 | struct ieee80211_ra_tid *ra_tid; |
1143 | struct ieee80211_rx_agg *rx_agg; | ||
1143 | 1144 | ||
1144 | if (!ieee80211_sdata_running(sdata)) | 1145 | if (!ieee80211_sdata_running(sdata)) |
1145 | return; | 1146 | return; |
@@ -1167,6 +1168,34 @@ static void ieee80211_iface_work(struct work_struct *work) | |||
1167 | ra_tid = (void *)&skb->cb; | 1168 | ra_tid = (void *)&skb->cb; |
1168 | ieee80211_stop_tx_ba_cb(&sdata->vif, ra_tid->ra, | 1169 | ieee80211_stop_tx_ba_cb(&sdata->vif, ra_tid->ra, |
1169 | ra_tid->tid); | 1170 | ra_tid->tid); |
1171 | } else if (skb->pkt_type == IEEE80211_SDATA_QUEUE_RX_AGG_START) { | ||
1172 | rx_agg = (void *)&skb->cb; | ||
1173 | mutex_lock(&local->sta_mtx); | ||
1174 | sta = sta_info_get_bss(sdata, rx_agg->addr); | ||
1175 | if (sta) { | ||
1176 | u16 last_seq; | ||
1177 | |||
1178 | last_seq = le16_to_cpu( | ||
1179 | sta->last_seq_ctrl[rx_agg->tid]); | ||
1180 | |||
1181 | __ieee80211_start_rx_ba_session(sta, | ||
1182 | 0, 0, | ||
1183 | ieee80211_sn_inc(last_seq), | ||
1184 | 1, rx_agg->tid, | ||
1185 | IEEE80211_MAX_AMPDU_BUF, | ||
1186 | false); | ||
1187 | } | ||
1188 | mutex_unlock(&local->sta_mtx); | ||
1189 | } else if (skb->pkt_type == IEEE80211_SDATA_QUEUE_RX_AGG_STOP) { | ||
1190 | rx_agg = (void *)&skb->cb; | ||
1191 | mutex_lock(&local->sta_mtx); | ||
1192 | sta = sta_info_get_bss(sdata, rx_agg->addr); | ||
1193 | if (sta) | ||
1194 | __ieee80211_stop_rx_ba_session(sta, | ||
1195 | rx_agg->tid, | ||
1196 | WLAN_BACK_RECIPIENT, 0, | ||
1197 | false); | ||
1198 | mutex_unlock(&local->sta_mtx); | ||
1170 | } else if (ieee80211_is_action(mgmt->frame_control) && | 1199 | } else if (ieee80211_is_action(mgmt->frame_control) && |
1171 | mgmt->u.action.category == WLAN_CATEGORY_BACK) { | 1200 | mgmt->u.action.category == WLAN_CATEGORY_BACK) { |
1172 | int len = skb->len; | 1201 | int len = skb->len; |
@@ -1672,8 +1701,6 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1672 | ieee80211_dfs_cac_timer_work); | 1701 | ieee80211_dfs_cac_timer_work); |
1673 | INIT_DELAYED_WORK(&sdata->dec_tailroom_needed_wk, | 1702 | INIT_DELAYED_WORK(&sdata->dec_tailroom_needed_wk, |
1674 | ieee80211_delayed_tailroom_dec); | 1703 | ieee80211_delayed_tailroom_dec); |
1675 | INIT_DELAYED_WORK(&sdata->tdls_peer_del_work, | ||
1676 | ieee80211_tdls_peer_del_work); | ||
1677 | 1704 | ||
1678 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { | 1705 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { |
1679 | struct ieee80211_supported_band *sband; | 1706 | struct ieee80211_supported_band *sband; |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 16d97f044a20..d808cff80153 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -482,9 +482,6 @@ int ieee80211_key_link(struct ieee80211_key *key, | |||
482 | int idx, ret; | 482 | int idx, ret; |
483 | bool pairwise; | 483 | bool pairwise; |
484 | 484 | ||
485 | if (WARN_ON(!sdata || !key)) | ||
486 | return -EINVAL; | ||
487 | |||
488 | pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE; | 485 | pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE; |
489 | idx = key->conf.keyidx; | 486 | idx = key->conf.keyidx; |
490 | key->local = sdata->local; | 487 | key->local = sdata->local; |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 931330bbe00c..31a8afaf7332 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -830,16 +830,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
830 | qos_info = 0; | 830 | qos_info = 0; |
831 | } | 831 | } |
832 | 832 | ||
833 | pos = skb_put(skb, 9); | 833 | pos = ieee80211_add_wmm_info_ie(skb_put(skb, 9), qos_info); |
834 | *pos++ = WLAN_EID_VENDOR_SPECIFIC; | ||
835 | *pos++ = 7; /* len */ | ||
836 | *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */ | ||
837 | *pos++ = 0x50; | ||
838 | *pos++ = 0xf2; | ||
839 | *pos++ = 2; /* WME */ | ||
840 | *pos++ = 0; /* WME info */ | ||
841 | *pos++ = 1; /* WME ver */ | ||
842 | *pos++ = qos_info; | ||
843 | } | 834 | } |
844 | 835 | ||
845 | /* add any remaining custom (i.e. vendor specific here) IEs */ | 836 | /* add any remaining custom (i.e. vendor specific here) IEs */ |
@@ -1005,8 +996,6 @@ static void ieee80211_chswitch_work(struct work_struct *work) | |||
1005 | sdata->csa_block_tx = false; | 996 | sdata->csa_block_tx = false; |
1006 | } | 997 | } |
1007 | 998 | ||
1008 | ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED; | ||
1009 | |||
1010 | ieee80211_sta_reset_beacon_monitor(sdata); | 999 | ieee80211_sta_reset_beacon_monitor(sdata); |
1011 | ieee80211_sta_reset_conn_monitor(sdata); | 1000 | ieee80211_sta_reset_conn_monitor(sdata); |
1012 | 1001 | ||
@@ -1064,7 +1053,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
1064 | return; | 1053 | return; |
1065 | 1054 | ||
1066 | /* disregard subsequent announcements if we are already processing */ | 1055 | /* disregard subsequent announcements if we are already processing */ |
1067 | if (ifmgd->flags & IEEE80211_STA_CSA_RECEIVED) | 1056 | if (sdata->vif.csa_active) |
1068 | return; | 1057 | return; |
1069 | 1058 | ||
1070 | current_band = cbss->channel->band; | 1059 | current_band = cbss->channel->band; |
@@ -1091,8 +1080,6 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
1091 | return; | 1080 | return; |
1092 | } | 1081 | } |
1093 | 1082 | ||
1094 | ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED; | ||
1095 | |||
1096 | mutex_lock(&local->mtx); | 1083 | mutex_lock(&local->mtx); |
1097 | mutex_lock(&local->chanctx_mtx); | 1084 | mutex_lock(&local->chanctx_mtx); |
1098 | conf = rcu_dereference_protected(sdata->vif.chanctx_conf, | 1085 | conf = rcu_dereference_protected(sdata->vif.chanctx_conf, |
@@ -2108,8 +2095,6 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata) | |||
2108 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, | 2095 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, |
2109 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, | 2096 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, |
2110 | true, frame_buf); | 2097 | true, frame_buf); |
2111 | ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED; | ||
2112 | |||
2113 | mutex_lock(&local->mtx); | 2098 | mutex_lock(&local->mtx); |
2114 | sdata->vif.csa_active = false; | 2099 | sdata->vif.csa_active = false; |
2115 | if (sdata->csa_block_tx) { | 2100 | if (sdata->csa_block_tx) { |
@@ -3722,6 +3707,8 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) | |||
3722 | INIT_WORK(&ifmgd->csa_connection_drop_work, | 3707 | INIT_WORK(&ifmgd->csa_connection_drop_work, |
3723 | ieee80211_csa_connection_drop_work); | 3708 | ieee80211_csa_connection_drop_work); |
3724 | INIT_WORK(&ifmgd->request_smps_work, ieee80211_request_smps_mgd_work); | 3709 | INIT_WORK(&ifmgd->request_smps_work, ieee80211_request_smps_mgd_work); |
3710 | INIT_DELAYED_WORK(&ifmgd->tdls_peer_del_work, | ||
3711 | ieee80211_tdls_peer_del_work); | ||
3725 | setup_timer(&ifmgd->timer, ieee80211_sta_timer, | 3712 | setup_timer(&ifmgd->timer, ieee80211_sta_timer, |
3726 | (unsigned long) sdata); | 3713 | (unsigned long) sdata); |
3727 | setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer, | 3714 | setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer, |
@@ -4585,6 +4572,7 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata) | |||
4585 | cancel_work_sync(&ifmgd->request_smps_work); | 4572 | cancel_work_sync(&ifmgd->request_smps_work); |
4586 | cancel_work_sync(&ifmgd->csa_connection_drop_work); | 4573 | cancel_work_sync(&ifmgd->csa_connection_drop_work); |
4587 | cancel_work_sync(&ifmgd->chswitch_work); | 4574 | cancel_work_sync(&ifmgd->chswitch_work); |
4575 | cancel_delayed_work_sync(&ifmgd->tdls_peer_del_work); | ||
4588 | 4576 | ||
4589 | sdata_lock(sdata); | 4577 | sdata_lock(sdata); |
4590 | if (ifmgd->assoc_data) { | 4578 | if (ifmgd->assoc_data) { |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 5f572bed1761..bd2c9b22c945 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -688,20 +688,27 @@ static void ieee80211_release_reorder_frame(struct ieee80211_sub_if_data *sdata, | |||
688 | int index, | 688 | int index, |
689 | struct sk_buff_head *frames) | 689 | struct sk_buff_head *frames) |
690 | { | 690 | { |
691 | struct sk_buff *skb = tid_agg_rx->reorder_buf[index]; | 691 | struct sk_buff_head *skb_list = &tid_agg_rx->reorder_buf[index]; |
692 | struct sk_buff *skb; | ||
692 | struct ieee80211_rx_status *status; | 693 | struct ieee80211_rx_status *status; |
693 | 694 | ||
694 | lockdep_assert_held(&tid_agg_rx->reorder_lock); | 695 | lockdep_assert_held(&tid_agg_rx->reorder_lock); |
695 | 696 | ||
696 | if (!skb) | 697 | if (skb_queue_empty(skb_list)) |
698 | goto no_frame; | ||
699 | |||
700 | if (!ieee80211_rx_reorder_ready(skb_list)) { | ||
701 | __skb_queue_purge(skb_list); | ||
697 | goto no_frame; | 702 | goto no_frame; |
703 | } | ||
698 | 704 | ||
699 | /* release the frame from the reorder ring buffer */ | 705 | /* release frames from the reorder ring buffer */ |
700 | tid_agg_rx->stored_mpdu_num--; | 706 | tid_agg_rx->stored_mpdu_num--; |
701 | tid_agg_rx->reorder_buf[index] = NULL; | 707 | while ((skb = __skb_dequeue(skb_list))) { |
702 | status = IEEE80211_SKB_RXCB(skb); | 708 | status = IEEE80211_SKB_RXCB(skb); |
703 | status->rx_flags |= IEEE80211_RX_DEFERRED_RELEASE; | 709 | status->rx_flags |= IEEE80211_RX_DEFERRED_RELEASE; |
704 | __skb_queue_tail(frames, skb); | 710 | __skb_queue_tail(frames, skb); |
711 | } | ||
705 | 712 | ||
706 | no_frame: | 713 | no_frame: |
707 | tid_agg_rx->head_seq_num = ieee80211_sn_inc(tid_agg_rx->head_seq_num); | 714 | tid_agg_rx->head_seq_num = ieee80211_sn_inc(tid_agg_rx->head_seq_num); |
@@ -738,13 +745,13 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata, | |||
738 | struct tid_ampdu_rx *tid_agg_rx, | 745 | struct tid_ampdu_rx *tid_agg_rx, |
739 | struct sk_buff_head *frames) | 746 | struct sk_buff_head *frames) |
740 | { | 747 | { |
741 | int index, j; | 748 | int index, i, j; |
742 | 749 | ||
743 | lockdep_assert_held(&tid_agg_rx->reorder_lock); | 750 | lockdep_assert_held(&tid_agg_rx->reorder_lock); |
744 | 751 | ||
745 | /* release the buffer until next missing frame */ | 752 | /* release the buffer until next missing frame */ |
746 | index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size; | 753 | index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size; |
747 | if (!tid_agg_rx->reorder_buf[index] && | 754 | if (!ieee80211_rx_reorder_ready(&tid_agg_rx->reorder_buf[index]) && |
748 | tid_agg_rx->stored_mpdu_num) { | 755 | tid_agg_rx->stored_mpdu_num) { |
749 | /* | 756 | /* |
750 | * No buffers ready to be released, but check whether any | 757 | * No buffers ready to be released, but check whether any |
@@ -753,7 +760,8 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata, | |||
753 | int skipped = 1; | 760 | int skipped = 1; |
754 | for (j = (index + 1) % tid_agg_rx->buf_size; j != index; | 761 | for (j = (index + 1) % tid_agg_rx->buf_size; j != index; |
755 | j = (j + 1) % tid_agg_rx->buf_size) { | 762 | j = (j + 1) % tid_agg_rx->buf_size) { |
756 | if (!tid_agg_rx->reorder_buf[j]) { | 763 | if (!ieee80211_rx_reorder_ready( |
764 | &tid_agg_rx->reorder_buf[j])) { | ||
757 | skipped++; | 765 | skipped++; |
758 | continue; | 766 | continue; |
759 | } | 767 | } |
@@ -762,6 +770,11 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata, | |||
762 | HT_RX_REORDER_BUF_TIMEOUT)) | 770 | HT_RX_REORDER_BUF_TIMEOUT)) |
763 | goto set_release_timer; | 771 | goto set_release_timer; |
764 | 772 | ||
773 | /* don't leave incomplete A-MSDUs around */ | ||
774 | for (i = (index + 1) % tid_agg_rx->buf_size; i != j; | ||
775 | i = (i + 1) % tid_agg_rx->buf_size) | ||
776 | __skb_queue_purge(&tid_agg_rx->reorder_buf[i]); | ||
777 | |||
765 | ht_dbg_ratelimited(sdata, | 778 | ht_dbg_ratelimited(sdata, |
766 | "release an RX reorder frame due to timeout on earlier frames\n"); | 779 | "release an RX reorder frame due to timeout on earlier frames\n"); |
767 | ieee80211_release_reorder_frame(sdata, tid_agg_rx, j, | 780 | ieee80211_release_reorder_frame(sdata, tid_agg_rx, j, |
@@ -775,7 +788,8 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata, | |||
775 | skipped) & IEEE80211_SN_MASK; | 788 | skipped) & IEEE80211_SN_MASK; |
776 | skipped = 0; | 789 | skipped = 0; |
777 | } | 790 | } |
778 | } else while (tid_agg_rx->reorder_buf[index]) { | 791 | } else while (ieee80211_rx_reorder_ready( |
792 | &tid_agg_rx->reorder_buf[index])) { | ||
779 | ieee80211_release_reorder_frame(sdata, tid_agg_rx, index, | 793 | ieee80211_release_reorder_frame(sdata, tid_agg_rx, index, |
780 | frames); | 794 | frames); |
781 | index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size; | 795 | index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size; |
@@ -786,7 +800,8 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata, | |||
786 | 800 | ||
787 | for (; j != (index - 1) % tid_agg_rx->buf_size; | 801 | for (; j != (index - 1) % tid_agg_rx->buf_size; |
788 | j = (j + 1) % tid_agg_rx->buf_size) { | 802 | j = (j + 1) % tid_agg_rx->buf_size) { |
789 | if (tid_agg_rx->reorder_buf[j]) | 803 | if (ieee80211_rx_reorder_ready( |
804 | &tid_agg_rx->reorder_buf[j])) | ||
790 | break; | 805 | break; |
791 | } | 806 | } |
792 | 807 | ||
@@ -811,6 +826,7 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata | |||
811 | struct sk_buff_head *frames) | 826 | struct sk_buff_head *frames) |
812 | { | 827 | { |
813 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 828 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
829 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | ||
814 | u16 sc = le16_to_cpu(hdr->seq_ctrl); | 830 | u16 sc = le16_to_cpu(hdr->seq_ctrl); |
815 | u16 mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4; | 831 | u16 mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4; |
816 | u16 head_seq_num, buf_size; | 832 | u16 head_seq_num, buf_size; |
@@ -845,7 +861,7 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata | |||
845 | index = mpdu_seq_num % tid_agg_rx->buf_size; | 861 | index = mpdu_seq_num % tid_agg_rx->buf_size; |
846 | 862 | ||
847 | /* check if we already stored this frame */ | 863 | /* check if we already stored this frame */ |
848 | if (tid_agg_rx->reorder_buf[index]) { | 864 | if (ieee80211_rx_reorder_ready(&tid_agg_rx->reorder_buf[index])) { |
849 | dev_kfree_skb(skb); | 865 | dev_kfree_skb(skb); |
850 | goto out; | 866 | goto out; |
851 | } | 867 | } |
@@ -858,17 +874,20 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata | |||
858 | */ | 874 | */ |
859 | if (mpdu_seq_num == tid_agg_rx->head_seq_num && | 875 | if (mpdu_seq_num == tid_agg_rx->head_seq_num && |
860 | tid_agg_rx->stored_mpdu_num == 0) { | 876 | tid_agg_rx->stored_mpdu_num == 0) { |
861 | tid_agg_rx->head_seq_num = | 877 | if (!(status->flag & RX_FLAG_AMSDU_MORE)) |
862 | ieee80211_sn_inc(tid_agg_rx->head_seq_num); | 878 | tid_agg_rx->head_seq_num = |
879 | ieee80211_sn_inc(tid_agg_rx->head_seq_num); | ||
863 | ret = false; | 880 | ret = false; |
864 | goto out; | 881 | goto out; |
865 | } | 882 | } |
866 | 883 | ||
867 | /* put the frame in the reordering buffer */ | 884 | /* put the frame in the reordering buffer */ |
868 | tid_agg_rx->reorder_buf[index] = skb; | 885 | __skb_queue_tail(&tid_agg_rx->reorder_buf[index], skb); |
869 | tid_agg_rx->reorder_time[index] = jiffies; | 886 | if (!(status->flag & RX_FLAG_AMSDU_MORE)) { |
870 | tid_agg_rx->stored_mpdu_num++; | 887 | tid_agg_rx->reorder_time[index] = jiffies; |
871 | ieee80211_sta_reorder_release(sdata, tid_agg_rx, frames); | 888 | tid_agg_rx->stored_mpdu_num++; |
889 | ieee80211_sta_reorder_release(sdata, tid_agg_rx, frames); | ||
890 | } | ||
872 | 891 | ||
873 | out: | 892 | out: |
874 | spin_unlock(&tid_agg_rx->reorder_lock); | 893 | spin_unlock(&tid_agg_rx->reorder_lock); |
@@ -3129,6 +3148,14 @@ static bool prepare_for_handlers(struct ieee80211_rx_data *rx, | |||
3129 | if (!ieee80211_is_beacon(hdr->frame_control)) | 3148 | if (!ieee80211_is_beacon(hdr->frame_control)) |
3130 | return false; | 3149 | return false; |
3131 | status->rx_flags &= ~IEEE80211_RX_RA_MATCH; | 3150 | status->rx_flags &= ~IEEE80211_RX_RA_MATCH; |
3151 | } else if (!ieee80211_has_tods(hdr->frame_control)) { | ||
3152 | /* ignore data frames to TDLS-peers */ | ||
3153 | if (ieee80211_is_data(hdr->frame_control)) | ||
3154 | return false; | ||
3155 | /* ignore action frames to TDLS-peers */ | ||
3156 | if (ieee80211_is_action(hdr->frame_control) && | ||
3157 | !ether_addr_equal(bssid, hdr->addr1)) | ||
3158 | return false; | ||
3132 | } | 3159 | } |
3133 | break; | 3160 | break; |
3134 | case NL80211_IFTYPE_WDS: | 3161 | case NL80211_IFTYPE_WDS: |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 2a04361b2162..d411bcc8ef08 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -47,6 +47,8 @@ | |||
47 | * @WLAN_STA_TDLS_PEER: Station is a TDLS peer. | 47 | * @WLAN_STA_TDLS_PEER: Station is a TDLS peer. |
48 | * @WLAN_STA_TDLS_PEER_AUTH: This TDLS peer is authorized to send direct | 48 | * @WLAN_STA_TDLS_PEER_AUTH: This TDLS peer is authorized to send direct |
49 | * packets. This means the link is enabled. | 49 | * packets. This means the link is enabled. |
50 | * @WLAN_STA_TDLS_INITIATOR: We are the initiator of the TDLS link with this | ||
51 | * station. | ||
50 | * @WLAN_STA_UAPSD: Station requested unscheduled SP while driver was | 52 | * @WLAN_STA_UAPSD: Station requested unscheduled SP while driver was |
51 | * keeping station in power-save mode, reply when the driver | 53 | * keeping station in power-save mode, reply when the driver |
52 | * unblocks the station. | 54 | * unblocks the station. |
@@ -76,6 +78,7 @@ enum ieee80211_sta_info_flags { | |||
76 | WLAN_STA_PSPOLL, | 78 | WLAN_STA_PSPOLL, |
77 | WLAN_STA_TDLS_PEER, | 79 | WLAN_STA_TDLS_PEER, |
78 | WLAN_STA_TDLS_PEER_AUTH, | 80 | WLAN_STA_TDLS_PEER_AUTH, |
81 | WLAN_STA_TDLS_INITIATOR, | ||
79 | WLAN_STA_UAPSD, | 82 | WLAN_STA_UAPSD, |
80 | WLAN_STA_SP, | 83 | WLAN_STA_SP, |
81 | WLAN_STA_4ADDR_EVENT, | 84 | WLAN_STA_4ADDR_EVENT, |
@@ -152,7 +155,8 @@ struct tid_ampdu_tx { | |||
152 | /** | 155 | /** |
153 | * struct tid_ampdu_rx - TID aggregation information (Rx). | 156 | * struct tid_ampdu_rx - TID aggregation information (Rx). |
154 | * | 157 | * |
155 | * @reorder_buf: buffer to reorder incoming aggregated MPDUs | 158 | * @reorder_buf: buffer to reorder incoming aggregated MPDUs. An MPDU may be an |
159 | * A-MSDU with individually reported subframes. | ||
156 | * @reorder_time: jiffies when skb was added | 160 | * @reorder_time: jiffies when skb was added |
157 | * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value) | 161 | * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value) |
158 | * @reorder_timer: releases expired frames from the reorder buffer. | 162 | * @reorder_timer: releases expired frames from the reorder buffer. |
@@ -177,7 +181,7 @@ struct tid_ampdu_tx { | |||
177 | struct tid_ampdu_rx { | 181 | struct tid_ampdu_rx { |
178 | struct rcu_head rcu_head; | 182 | struct rcu_head rcu_head; |
179 | spinlock_t reorder_lock; | 183 | spinlock_t reorder_lock; |
180 | struct sk_buff **reorder_buf; | 184 | struct sk_buff_head *reorder_buf; |
181 | unsigned long *reorder_time; | 185 | unsigned long *reorder_time; |
182 | struct timer_list session_timer; | 186 | struct timer_list session_timer; |
183 | struct timer_list reorder_timer; | 187 | struct timer_list reorder_timer; |
diff --git a/net/mac80211/tdls.c b/net/mac80211/tdls.c index f7185338a0fa..1b21050be174 100644 --- a/net/mac80211/tdls.c +++ b/net/mac80211/tdls.c | |||
@@ -8,6 +8,7 @@ | |||
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/ieee80211.h> | 10 | #include <linux/ieee80211.h> |
11 | #include <linux/log2.h> | ||
11 | #include <net/cfg80211.h> | 12 | #include <net/cfg80211.h> |
12 | #include "ieee80211_i.h" | 13 | #include "ieee80211_i.h" |
13 | #include "driver-ops.h" | 14 | #include "driver-ops.h" |
@@ -21,14 +22,14 @@ void ieee80211_tdls_peer_del_work(struct work_struct *wk) | |||
21 | struct ieee80211_local *local; | 22 | struct ieee80211_local *local; |
22 | 23 | ||
23 | sdata = container_of(wk, struct ieee80211_sub_if_data, | 24 | sdata = container_of(wk, struct ieee80211_sub_if_data, |
24 | tdls_peer_del_work.work); | 25 | u.mgd.tdls_peer_del_work.work); |
25 | local = sdata->local; | 26 | local = sdata->local; |
26 | 27 | ||
27 | mutex_lock(&local->mtx); | 28 | mutex_lock(&local->mtx); |
28 | if (!is_zero_ether_addr(sdata->tdls_peer)) { | 29 | if (!is_zero_ether_addr(sdata->u.mgd.tdls_peer)) { |
29 | tdls_dbg(sdata, "TDLS del peer %pM\n", sdata->tdls_peer); | 30 | tdls_dbg(sdata, "TDLS del peer %pM\n", sdata->u.mgd.tdls_peer); |
30 | sta_info_destroy_addr(sdata, sdata->tdls_peer); | 31 | sta_info_destroy_addr(sdata, sdata->u.mgd.tdls_peer); |
31 | eth_zero_addr(sdata->tdls_peer); | 32 | eth_zero_addr(sdata->u.mgd.tdls_peer); |
32 | } | 33 | } |
33 | mutex_unlock(&local->mtx); | 34 | mutex_unlock(&local->mtx); |
34 | } | 35 | } |
@@ -46,11 +47,16 @@ static void ieee80211_tdls_add_ext_capab(struct sk_buff *skb) | |||
46 | *pos++ = WLAN_EXT_CAPA5_TDLS_ENABLED; | 47 | *pos++ = WLAN_EXT_CAPA5_TDLS_ENABLED; |
47 | } | 48 | } |
48 | 49 | ||
49 | static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata) | 50 | static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata, |
51 | u16 status_code) | ||
50 | { | 52 | { |
51 | struct ieee80211_local *local = sdata->local; | 53 | struct ieee80211_local *local = sdata->local; |
52 | u16 capab; | 54 | u16 capab; |
53 | 55 | ||
56 | /* The capability will be 0 when sending a failure code */ | ||
57 | if (status_code != 0) | ||
58 | return 0; | ||
59 | |||
54 | capab = 0; | 60 | capab = 0; |
55 | if (ieee80211_get_sdata_band(sdata) != IEEE80211_BAND_2GHZ) | 61 | if (ieee80211_get_sdata_band(sdata) != IEEE80211_BAND_2GHZ) |
56 | return capab; | 62 | return capab; |
@@ -63,19 +69,332 @@ static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata) | |||
63 | return capab; | 69 | return capab; |
64 | } | 70 | } |
65 | 71 | ||
66 | static void ieee80211_tdls_add_link_ie(struct sk_buff *skb, const u8 *src_addr, | 72 | static void ieee80211_tdls_add_link_ie(struct ieee80211_sub_if_data *sdata, |
67 | const u8 *peer, const u8 *bssid) | 73 | struct sk_buff *skb, const u8 *peer, |
74 | bool initiator) | ||
68 | { | 75 | { |
69 | struct ieee80211_tdls_lnkie *lnkid; | 76 | struct ieee80211_tdls_lnkie *lnkid; |
77 | const u8 *init_addr, *rsp_addr; | ||
78 | |||
79 | if (initiator) { | ||
80 | init_addr = sdata->vif.addr; | ||
81 | rsp_addr = peer; | ||
82 | } else { | ||
83 | init_addr = peer; | ||
84 | rsp_addr = sdata->vif.addr; | ||
85 | } | ||
70 | 86 | ||
71 | lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie)); | 87 | lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie)); |
72 | 88 | ||
73 | lnkid->ie_type = WLAN_EID_LINK_ID; | 89 | lnkid->ie_type = WLAN_EID_LINK_ID; |
74 | lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) - 2; | 90 | lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) - 2; |
75 | 91 | ||
76 | memcpy(lnkid->bssid, bssid, ETH_ALEN); | 92 | memcpy(lnkid->bssid, sdata->u.mgd.bssid, ETH_ALEN); |
77 | memcpy(lnkid->init_sta, src_addr, ETH_ALEN); | 93 | memcpy(lnkid->init_sta, init_addr, ETH_ALEN); |
78 | memcpy(lnkid->resp_sta, peer, ETH_ALEN); | 94 | memcpy(lnkid->resp_sta, rsp_addr, ETH_ALEN); |
95 | } | ||
96 | |||
97 | /* translate numbering in the WMM parameter IE to the mac80211 notation */ | ||
98 | static enum ieee80211_ac_numbers ieee80211_ac_from_wmm(int ac) | ||
99 | { | ||
100 | switch (ac) { | ||
101 | default: | ||
102 | WARN_ON_ONCE(1); | ||
103 | case 0: | ||
104 | return IEEE80211_AC_BE; | ||
105 | case 1: | ||
106 | return IEEE80211_AC_BK; | ||
107 | case 2: | ||
108 | return IEEE80211_AC_VI; | ||
109 | case 3: | ||
110 | return IEEE80211_AC_VO; | ||
111 | } | ||
112 | } | ||
113 | |||
114 | static u8 ieee80211_wmm_aci_aifsn(int aifsn, bool acm, int aci) | ||
115 | { | ||
116 | u8 ret; | ||
117 | |||
118 | ret = aifsn & 0x0f; | ||
119 | if (acm) | ||
120 | ret |= 0x10; | ||
121 | ret |= (aci << 5) & 0x60; | ||
122 | return ret; | ||
123 | } | ||
124 | |||
125 | static u8 ieee80211_wmm_ecw(u16 cw_min, u16 cw_max) | ||
126 | { | ||
127 | return ((ilog2(cw_min + 1) << 0x0) & 0x0f) | | ||
128 | ((ilog2(cw_max + 1) << 0x4) & 0xf0); | ||
129 | } | ||
130 | |||
131 | static void ieee80211_tdls_add_wmm_param_ie(struct ieee80211_sub_if_data *sdata, | ||
132 | struct sk_buff *skb) | ||
133 | { | ||
134 | struct ieee80211_wmm_param_ie *wmm; | ||
135 | struct ieee80211_tx_queue_params *txq; | ||
136 | int i; | ||
137 | |||
138 | wmm = (void *)skb_put(skb, sizeof(*wmm)); | ||
139 | memset(wmm, 0, sizeof(*wmm)); | ||
140 | |||
141 | wmm->element_id = WLAN_EID_VENDOR_SPECIFIC; | ||
142 | wmm->len = sizeof(*wmm) - 2; | ||
143 | |||
144 | wmm->oui[0] = 0x00; /* Microsoft OUI 00:50:F2 */ | ||
145 | wmm->oui[1] = 0x50; | ||
146 | wmm->oui[2] = 0xf2; | ||
147 | wmm->oui_type = 2; /* WME */ | ||
148 | wmm->oui_subtype = 1; /* WME param */ | ||
149 | wmm->version = 1; /* WME ver */ | ||
150 | wmm->qos_info = 0; /* U-APSD not in use */ | ||
151 | |||
152 | /* | ||
153 | * Use the EDCA parameters defined for the BSS, or default if the AP | ||
154 | * doesn't support it, as mandated by 802.11-2012 section 10.22.4 | ||
155 | */ | ||
156 | for (i = 0; i < IEEE80211_NUM_ACS; i++) { | ||
157 | txq = &sdata->tx_conf[ieee80211_ac_from_wmm(i)]; | ||
158 | wmm->ac[i].aci_aifsn = ieee80211_wmm_aci_aifsn(txq->aifs, | ||
159 | txq->acm, i); | ||
160 | wmm->ac[i].cw = ieee80211_wmm_ecw(txq->cw_min, txq->cw_max); | ||
161 | wmm->ac[i].txop_limit = cpu_to_le16(txq->txop); | ||
162 | } | ||
163 | } | ||
164 | |||
165 | static void | ||
166 | ieee80211_tdls_add_setup_start_ies(struct ieee80211_sub_if_data *sdata, | ||
167 | struct sk_buff *skb, const u8 *peer, | ||
168 | u8 action_code, bool initiator, | ||
169 | const u8 *extra_ies, size_t extra_ies_len) | ||
170 | { | ||
171 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); | ||
172 | struct ieee80211_local *local = sdata->local; | ||
173 | struct ieee80211_supported_band *sband; | ||
174 | struct ieee80211_sta_ht_cap ht_cap; | ||
175 | struct sta_info *sta = NULL; | ||
176 | size_t offset = 0, noffset; | ||
177 | u8 *pos; | ||
178 | |||
179 | rcu_read_lock(); | ||
180 | |||
181 | /* we should have the peer STA if we're already responding */ | ||
182 | if (action_code == WLAN_TDLS_SETUP_RESPONSE) { | ||
183 | sta = sta_info_get(sdata, peer); | ||
184 | if (WARN_ON_ONCE(!sta)) { | ||
185 | rcu_read_unlock(); | ||
186 | return; | ||
187 | } | ||
188 | } | ||
189 | |||
190 | ieee80211_add_srates_ie(sdata, skb, false, band); | ||
191 | ieee80211_add_ext_srates_ie(sdata, skb, false, band); | ||
192 | |||
193 | /* add any custom IEs that go before Extended Capabilities */ | ||
194 | if (extra_ies_len) { | ||
195 | static const u8 before_ext_cap[] = { | ||
196 | WLAN_EID_SUPP_RATES, | ||
197 | WLAN_EID_COUNTRY, | ||
198 | WLAN_EID_EXT_SUPP_RATES, | ||
199 | WLAN_EID_SUPPORTED_CHANNELS, | ||
200 | WLAN_EID_RSN, | ||
201 | }; | ||
202 | noffset = ieee80211_ie_split(extra_ies, extra_ies_len, | ||
203 | before_ext_cap, | ||
204 | ARRAY_SIZE(before_ext_cap), | ||
205 | offset); | ||
206 | pos = skb_put(skb, noffset - offset); | ||
207 | memcpy(pos, extra_ies + offset, noffset - offset); | ||
208 | offset = noffset; | ||
209 | } | ||
210 | |||
211 | ieee80211_tdls_add_ext_capab(skb); | ||
212 | |||
213 | /* add the QoS element if we support it */ | ||
214 | if (local->hw.queues >= IEEE80211_NUM_ACS && | ||
215 | action_code != WLAN_PUB_ACTION_TDLS_DISCOVER_RES) | ||
216 | ieee80211_add_wmm_info_ie(skb_put(skb, 9), 0); /* no U-APSD */ | ||
217 | |||
218 | /* add any custom IEs that go before HT capabilities */ | ||
219 | if (extra_ies_len) { | ||
220 | static const u8 before_ht_cap[] = { | ||
221 | WLAN_EID_SUPP_RATES, | ||
222 | WLAN_EID_COUNTRY, | ||
223 | WLAN_EID_EXT_SUPP_RATES, | ||
224 | WLAN_EID_SUPPORTED_CHANNELS, | ||
225 | WLAN_EID_RSN, | ||
226 | WLAN_EID_EXT_CAPABILITY, | ||
227 | WLAN_EID_QOS_CAPA, | ||
228 | WLAN_EID_FAST_BSS_TRANSITION, | ||
229 | WLAN_EID_TIMEOUT_INTERVAL, | ||
230 | WLAN_EID_SUPPORTED_REGULATORY_CLASSES, | ||
231 | }; | ||
232 | noffset = ieee80211_ie_split(extra_ies, extra_ies_len, | ||
233 | before_ht_cap, | ||
234 | ARRAY_SIZE(before_ht_cap), | ||
235 | offset); | ||
236 | pos = skb_put(skb, noffset - offset); | ||
237 | memcpy(pos, extra_ies + offset, noffset - offset); | ||
238 | offset = noffset; | ||
239 | } | ||
240 | |||
241 | /* | ||
242 | * with TDLS we can switch channels, and HT-caps are not necessarily | ||
243 | * the same on all bands. The specification limits the setup to a | ||
244 | * single HT-cap, so use the current band for now. | ||
245 | */ | ||
246 | sband = local->hw.wiphy->bands[band]; | ||
247 | memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap)); | ||
248 | if ((action_code == WLAN_TDLS_SETUP_REQUEST || | ||
249 | action_code == WLAN_TDLS_SETUP_RESPONSE) && | ||
250 | ht_cap.ht_supported && (!sta || sta->sta.ht_cap.ht_supported)) { | ||
251 | if (action_code == WLAN_TDLS_SETUP_REQUEST) { | ||
252 | ieee80211_apply_htcap_overrides(sdata, &ht_cap); | ||
253 | |||
254 | /* disable SMPS in TDLS initiator */ | ||
255 | ht_cap.cap |= (WLAN_HT_CAP_SM_PS_DISABLED | ||
256 | << IEEE80211_HT_CAP_SM_PS_SHIFT); | ||
257 | } else { | ||
258 | /* disable SMPS in TDLS responder */ | ||
259 | sta->sta.ht_cap.cap |= | ||
260 | (WLAN_HT_CAP_SM_PS_DISABLED | ||
261 | << IEEE80211_HT_CAP_SM_PS_SHIFT); | ||
262 | |||
263 | /* the peer caps are already intersected with our own */ | ||
264 | memcpy(&ht_cap, &sta->sta.ht_cap, sizeof(ht_cap)); | ||
265 | } | ||
266 | |||
267 | pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2); | ||
268 | ieee80211_ie_build_ht_cap(pos, &ht_cap, ht_cap.cap); | ||
269 | } | ||
270 | |||
271 | rcu_read_unlock(); | ||
272 | |||
273 | /* add any remaining IEs */ | ||
274 | if (extra_ies_len) { | ||
275 | noffset = extra_ies_len; | ||
276 | pos = skb_put(skb, noffset - offset); | ||
277 | memcpy(pos, extra_ies + offset, noffset - offset); | ||
278 | } | ||
279 | |||
280 | ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator); | ||
281 | } | ||
282 | |||
283 | static void | ||
284 | ieee80211_tdls_add_setup_cfm_ies(struct ieee80211_sub_if_data *sdata, | ||
285 | struct sk_buff *skb, const u8 *peer, | ||
286 | bool initiator, const u8 *extra_ies, | ||
287 | size_t extra_ies_len) | ||
288 | { | ||
289 | struct ieee80211_local *local = sdata->local; | ||
290 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
291 | size_t offset = 0, noffset; | ||
292 | struct sta_info *sta, *ap_sta; | ||
293 | u8 *pos; | ||
294 | |||
295 | rcu_read_lock(); | ||
296 | |||
297 | sta = sta_info_get(sdata, peer); | ||
298 | ap_sta = sta_info_get(sdata, ifmgd->bssid); | ||
299 | if (WARN_ON_ONCE(!sta || !ap_sta)) { | ||
300 | rcu_read_unlock(); | ||
301 | return; | ||
302 | } | ||
303 | |||
304 | /* add any custom IEs that go before the QoS IE */ | ||
305 | if (extra_ies_len) { | ||
306 | static const u8 before_qos[] = { | ||
307 | WLAN_EID_RSN, | ||
308 | }; | ||
309 | noffset = ieee80211_ie_split(extra_ies, extra_ies_len, | ||
310 | before_qos, | ||
311 | ARRAY_SIZE(before_qos), | ||
312 | offset); | ||
313 | pos = skb_put(skb, noffset - offset); | ||
314 | memcpy(pos, extra_ies + offset, noffset - offset); | ||
315 | offset = noffset; | ||
316 | } | ||
317 | |||
318 | /* add the QoS param IE if both the peer and we support it */ | ||
319 | if (local->hw.queues >= IEEE80211_NUM_ACS && | ||
320 | test_sta_flag(sta, WLAN_STA_WME)) | ||
321 | ieee80211_tdls_add_wmm_param_ie(sdata, skb); | ||
322 | |||
323 | /* add any custom IEs that go before HT operation */ | ||
324 | if (extra_ies_len) { | ||
325 | static const u8 before_ht_op[] = { | ||
326 | WLAN_EID_RSN, | ||
327 | WLAN_EID_QOS_CAPA, | ||
328 | WLAN_EID_FAST_BSS_TRANSITION, | ||
329 | WLAN_EID_TIMEOUT_INTERVAL, | ||
330 | }; | ||
331 | noffset = ieee80211_ie_split(extra_ies, extra_ies_len, | ||
332 | before_ht_op, | ||
333 | ARRAY_SIZE(before_ht_op), | ||
334 | offset); | ||
335 | pos = skb_put(skb, noffset - offset); | ||
336 | memcpy(pos, extra_ies + offset, noffset - offset); | ||
337 | offset = noffset; | ||
338 | } | ||
339 | |||
340 | /* if HT support is only added in TDLS, we need an HT-operation IE */ | ||
341 | if (!ap_sta->sta.ht_cap.ht_supported && sta->sta.ht_cap.ht_supported) { | ||
342 | struct ieee80211_chanctx_conf *chanctx_conf = | ||
343 | rcu_dereference(sdata->vif.chanctx_conf); | ||
344 | if (!WARN_ON(!chanctx_conf)) { | ||
345 | pos = skb_put(skb, 2 + | ||
346 | sizeof(struct ieee80211_ht_operation)); | ||
347 | /* send an empty HT operation IE */ | ||
348 | ieee80211_ie_build_ht_oper(pos, &sta->sta.ht_cap, | ||
349 | &chanctx_conf->def, 0); | ||
350 | } | ||
351 | } | ||
352 | |||
353 | rcu_read_unlock(); | ||
354 | |||
355 | /* add any remaining IEs */ | ||
356 | if (extra_ies_len) { | ||
357 | noffset = extra_ies_len; | ||
358 | pos = skb_put(skb, noffset - offset); | ||
359 | memcpy(pos, extra_ies + offset, noffset - offset); | ||
360 | } | ||
361 | |||
362 | ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator); | ||
363 | } | ||
364 | |||
365 | static void ieee80211_tdls_add_ies(struct ieee80211_sub_if_data *sdata, | ||
366 | struct sk_buff *skb, const u8 *peer, | ||
367 | u8 action_code, u16 status_code, | ||
368 | bool initiator, const u8 *extra_ies, | ||
369 | size_t extra_ies_len) | ||
370 | { | ||
371 | switch (action_code) { | ||
372 | case WLAN_TDLS_SETUP_REQUEST: | ||
373 | case WLAN_TDLS_SETUP_RESPONSE: | ||
374 | case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: | ||
375 | if (status_code == 0) | ||
376 | ieee80211_tdls_add_setup_start_ies(sdata, skb, peer, | ||
377 | action_code, | ||
378 | initiator, | ||
379 | extra_ies, | ||
380 | extra_ies_len); | ||
381 | break; | ||
382 | case WLAN_TDLS_SETUP_CONFIRM: | ||
383 | if (status_code == 0) | ||
384 | ieee80211_tdls_add_setup_cfm_ies(sdata, skb, peer, | ||
385 | initiator, extra_ies, | ||
386 | extra_ies_len); | ||
387 | break; | ||
388 | case WLAN_TDLS_TEARDOWN: | ||
389 | case WLAN_TDLS_DISCOVERY_REQUEST: | ||
390 | if (extra_ies_len) | ||
391 | memcpy(skb_put(skb, extra_ies_len), extra_ies, | ||
392 | extra_ies_len); | ||
393 | if (status_code == 0 || action_code == WLAN_TDLS_TEARDOWN) | ||
394 | ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator); | ||
395 | break; | ||
396 | } | ||
397 | |||
79 | } | 398 | } |
80 | 399 | ||
81 | static int | 400 | static int |
@@ -84,7 +403,6 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, | |||
84 | u16 status_code, struct sk_buff *skb) | 403 | u16 status_code, struct sk_buff *skb) |
85 | { | 404 | { |
86 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 405 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
87 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); | ||
88 | struct ieee80211_tdls_data *tf; | 406 | struct ieee80211_tdls_data *tf; |
89 | 407 | ||
90 | tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u)); | 408 | tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u)); |
@@ -102,11 +420,8 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, | |||
102 | skb_put(skb, sizeof(tf->u.setup_req)); | 420 | skb_put(skb, sizeof(tf->u.setup_req)); |
103 | tf->u.setup_req.dialog_token = dialog_token; | 421 | tf->u.setup_req.dialog_token = dialog_token; |
104 | tf->u.setup_req.capability = | 422 | tf->u.setup_req.capability = |
105 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); | 423 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata, |
106 | 424 | status_code)); | |
107 | ieee80211_add_srates_ie(sdata, skb, false, band); | ||
108 | ieee80211_add_ext_srates_ie(sdata, skb, false, band); | ||
109 | ieee80211_tdls_add_ext_capab(skb); | ||
110 | break; | 425 | break; |
111 | case WLAN_TDLS_SETUP_RESPONSE: | 426 | case WLAN_TDLS_SETUP_RESPONSE: |
112 | tf->category = WLAN_CATEGORY_TDLS; | 427 | tf->category = WLAN_CATEGORY_TDLS; |
@@ -116,11 +431,8 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, | |||
116 | tf->u.setup_resp.status_code = cpu_to_le16(status_code); | 431 | tf->u.setup_resp.status_code = cpu_to_le16(status_code); |
117 | tf->u.setup_resp.dialog_token = dialog_token; | 432 | tf->u.setup_resp.dialog_token = dialog_token; |
118 | tf->u.setup_resp.capability = | 433 | tf->u.setup_resp.capability = |
119 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); | 434 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata, |
120 | 435 | status_code)); | |
121 | ieee80211_add_srates_ie(sdata, skb, false, band); | ||
122 | ieee80211_add_ext_srates_ie(sdata, skb, false, band); | ||
123 | ieee80211_tdls_add_ext_capab(skb); | ||
124 | break; | 436 | break; |
125 | case WLAN_TDLS_SETUP_CONFIRM: | 437 | case WLAN_TDLS_SETUP_CONFIRM: |
126 | tf->category = WLAN_CATEGORY_TDLS; | 438 | tf->category = WLAN_CATEGORY_TDLS; |
@@ -157,7 +469,6 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev, | |||
157 | u16 status_code, struct sk_buff *skb) | 469 | u16 status_code, struct sk_buff *skb) |
158 | { | 470 | { |
159 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 471 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
160 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); | ||
161 | struct ieee80211_mgmt *mgmt; | 472 | struct ieee80211_mgmt *mgmt; |
162 | 473 | ||
163 | mgmt = (void *)skb_put(skb, 24); | 474 | mgmt = (void *)skb_put(skb, 24); |
@@ -178,11 +489,8 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev, | |||
178 | mgmt->u.action.u.tdls_discover_resp.dialog_token = | 489 | mgmt->u.action.u.tdls_discover_resp.dialog_token = |
179 | dialog_token; | 490 | dialog_token; |
180 | mgmt->u.action.u.tdls_discover_resp.capability = | 491 | mgmt->u.action.u.tdls_discover_resp.capability = |
181 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); | 492 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata, |
182 | 493 | status_code)); | |
183 | ieee80211_add_srates_ie(sdata, skb, false, band); | ||
184 | ieee80211_add_ext_srates_ie(sdata, skb, false, band); | ||
185 | ieee80211_tdls_add_ext_capab(skb); | ||
186 | break; | 494 | break; |
187 | default: | 495 | default: |
188 | return -EINVAL; | 496 | return -EINVAL; |
@@ -202,7 +510,7 @@ ieee80211_tdls_prep_mgmt_packet(struct wiphy *wiphy, struct net_device *dev, | |||
202 | struct ieee80211_local *local = sdata->local; | 510 | struct ieee80211_local *local = sdata->local; |
203 | struct sk_buff *skb = NULL; | 511 | struct sk_buff *skb = NULL; |
204 | bool send_direct; | 512 | bool send_direct; |
205 | const u8 *init_addr, *rsp_addr; | 513 | struct sta_info *sta; |
206 | int ret; | 514 | int ret; |
207 | 515 | ||
208 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + | 516 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + |
@@ -210,6 +518,9 @@ ieee80211_tdls_prep_mgmt_packet(struct wiphy *wiphy, struct net_device *dev, | |||
210 | sizeof(struct ieee80211_tdls_data)) + | 518 | sizeof(struct ieee80211_tdls_data)) + |
211 | 50 + /* supported rates */ | 519 | 50 + /* supported rates */ |
212 | 7 + /* ext capab */ | 520 | 7 + /* ext capab */ |
521 | 26 + /* max(WMM-info, WMM-param) */ | ||
522 | 2 + max(sizeof(struct ieee80211_ht_cap), | ||
523 | sizeof(struct ieee80211_ht_operation)) + | ||
213 | extra_ies_len + | 524 | extra_ies_len + |
214 | sizeof(struct ieee80211_tdls_lnkie)); | 525 | sizeof(struct ieee80211_tdls_lnkie)); |
215 | if (!skb) | 526 | if (!skb) |
@@ -242,45 +553,48 @@ ieee80211_tdls_prep_mgmt_packet(struct wiphy *wiphy, struct net_device *dev, | |||
242 | if (ret < 0) | 553 | if (ret < 0) |
243 | goto fail; | 554 | goto fail; |
244 | 555 | ||
245 | if (extra_ies_len) | 556 | rcu_read_lock(); |
246 | memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len); | 557 | sta = sta_info_get(sdata, peer); |
247 | 558 | ||
248 | /* sanity check for initiator */ | 559 | /* infer the initiator if we can, to support old userspace */ |
249 | switch (action_code) { | 560 | switch (action_code) { |
250 | case WLAN_TDLS_SETUP_REQUEST: | 561 | case WLAN_TDLS_SETUP_REQUEST: |
562 | if (sta) | ||
563 | set_sta_flag(sta, WLAN_STA_TDLS_INITIATOR); | ||
564 | /* fall-through */ | ||
251 | case WLAN_TDLS_SETUP_CONFIRM: | 565 | case WLAN_TDLS_SETUP_CONFIRM: |
252 | case WLAN_TDLS_DISCOVERY_REQUEST: | 566 | case WLAN_TDLS_DISCOVERY_REQUEST: |
253 | if (!initiator) { | 567 | initiator = true; |
254 | ret = -EINVAL; | ||
255 | goto fail; | ||
256 | } | ||
257 | break; | 568 | break; |
258 | case WLAN_TDLS_SETUP_RESPONSE: | 569 | case WLAN_TDLS_SETUP_RESPONSE: |
570 | /* | ||
571 | * In some testing scenarios, we send a request and response. | ||
572 | * Make the last packet sent take effect for the initiator | ||
573 | * value. | ||
574 | */ | ||
575 | if (sta) | ||
576 | clear_sta_flag(sta, WLAN_STA_TDLS_INITIATOR); | ||
577 | /* fall-through */ | ||
259 | case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: | 578 | case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: |
260 | if (initiator) { | 579 | initiator = false; |
261 | ret = -EINVAL; | ||
262 | goto fail; | ||
263 | } | ||
264 | break; | 580 | break; |
265 | case WLAN_TDLS_TEARDOWN: | 581 | case WLAN_TDLS_TEARDOWN: |
266 | /* any value is ok */ | 582 | /* any value is ok */ |
267 | break; | 583 | break; |
268 | default: | 584 | default: |
269 | ret = -ENOTSUPP; | 585 | ret = -ENOTSUPP; |
270 | goto fail; | 586 | break; |
271 | } | 587 | } |
272 | 588 | ||
273 | if (initiator) { | 589 | if (sta && test_sta_flag(sta, WLAN_STA_TDLS_INITIATOR)) |
274 | init_addr = sdata->vif.addr; | 590 | initiator = true; |
275 | rsp_addr = peer; | ||
276 | } else { | ||
277 | init_addr = peer; | ||
278 | rsp_addr = sdata->vif.addr; | ||
279 | } | ||
280 | 591 | ||
281 | ieee80211_tdls_add_link_ie(skb, init_addr, rsp_addr, | 592 | rcu_read_unlock(); |
282 | sdata->u.mgd.bssid); | 593 | if (ret < 0) |
594 | goto fail; | ||
283 | 595 | ||
596 | ieee80211_tdls_add_ies(sdata, skb, peer, action_code, status_code, | ||
597 | initiator, extra_ies, extra_ies_len); | ||
284 | if (send_direct) { | 598 | if (send_direct) { |
285 | ieee80211_tx_skb(sdata, skb); | 599 | ieee80211_tx_skb(sdata, skb); |
286 | return 0; | 600 | return 0; |
@@ -327,8 +641,8 @@ ieee80211_tdls_mgmt_setup(struct wiphy *wiphy, struct net_device *dev, | |||
327 | mutex_lock(&local->mtx); | 641 | mutex_lock(&local->mtx); |
328 | 642 | ||
329 | /* we don't support concurrent TDLS peer setups */ | 643 | /* we don't support concurrent TDLS peer setups */ |
330 | if (!is_zero_ether_addr(sdata->tdls_peer) && | 644 | if (!is_zero_ether_addr(sdata->u.mgd.tdls_peer) && |
331 | !ether_addr_equal(sdata->tdls_peer, peer)) { | 645 | !ether_addr_equal(sdata->u.mgd.tdls_peer, peer)) { |
332 | ret = -EBUSY; | 646 | ret = -EBUSY; |
333 | goto exit; | 647 | goto exit; |
334 | } | 648 | } |
@@ -336,15 +650,19 @@ ieee80211_tdls_mgmt_setup(struct wiphy *wiphy, struct net_device *dev, | |||
336 | /* | 650 | /* |
337 | * make sure we have a STA representing the peer so we drop or buffer | 651 | * make sure we have a STA representing the peer so we drop or buffer |
338 | * non-TDLS-setup frames to the peer. We can't send other packets | 652 | * non-TDLS-setup frames to the peer. We can't send other packets |
339 | * during setup through the AP path | 653 | * during setup through the AP path. |
654 | * Allow error packets to be sent - sometimes we don't even add a STA | ||
655 | * before failing the setup. | ||
340 | */ | 656 | */ |
341 | rcu_read_lock(); | 657 | if (status_code == 0) { |
342 | if (!sta_info_get(sdata, peer)) { | 658 | rcu_read_lock(); |
659 | if (!sta_info_get(sdata, peer)) { | ||
660 | rcu_read_unlock(); | ||
661 | ret = -ENOLINK; | ||
662 | goto exit; | ||
663 | } | ||
343 | rcu_read_unlock(); | 664 | rcu_read_unlock(); |
344 | ret = -ENOLINK; | ||
345 | goto exit; | ||
346 | } | 665 | } |
347 | rcu_read_unlock(); | ||
348 | 666 | ||
349 | ieee80211_flush_queues(local, sdata); | 667 | ieee80211_flush_queues(local, sdata); |
350 | 668 | ||
@@ -355,9 +673,9 @@ ieee80211_tdls_mgmt_setup(struct wiphy *wiphy, struct net_device *dev, | |||
355 | if (ret < 0) | 673 | if (ret < 0) |
356 | goto exit; | 674 | goto exit; |
357 | 675 | ||
358 | memcpy(sdata->tdls_peer, peer, ETH_ALEN); | 676 | memcpy(sdata->u.mgd.tdls_peer, peer, ETH_ALEN); |
359 | ieee80211_queue_delayed_work(&sdata->local->hw, | 677 | ieee80211_queue_delayed_work(&sdata->local->hw, |
360 | &sdata->tdls_peer_del_work, | 678 | &sdata->u.mgd.tdls_peer_del_work, |
361 | TDLS_PEER_SETUP_TIMEOUT); | 679 | TDLS_PEER_SETUP_TIMEOUT); |
362 | 680 | ||
363 | exit: | 681 | exit: |
@@ -513,11 +831,22 @@ int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, | |||
513 | set_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH); | 831 | set_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH); |
514 | rcu_read_unlock(); | 832 | rcu_read_unlock(); |
515 | 833 | ||
516 | WARN_ON_ONCE(is_zero_ether_addr(sdata->tdls_peer) || | 834 | WARN_ON_ONCE(is_zero_ether_addr(sdata->u.mgd.tdls_peer) || |
517 | !ether_addr_equal(sdata->tdls_peer, peer)); | 835 | !ether_addr_equal(sdata->u.mgd.tdls_peer, peer)); |
518 | ret = 0; | 836 | ret = 0; |
519 | break; | 837 | break; |
520 | case NL80211_TDLS_DISABLE_LINK: | 838 | case NL80211_TDLS_DISABLE_LINK: |
839 | /* | ||
840 | * The teardown message in ieee80211_tdls_mgmt_teardown() was | ||
841 | * created while the queues were stopped, so it might still be | ||
842 | * pending. Before flushing the queues we need to be sure the | ||
843 | * message is handled by the tasklet handling pending messages, | ||
844 | * otherwise we might start destroying the station before | ||
845 | * sending the teardown packet. | ||
846 | * Note that this only forces the tasklet to flush pendings - | ||
847 | * not to stop the tasklet from rescheduling itself. | ||
848 | */ | ||
849 | tasklet_kill(&local->tx_pending_tasklet); | ||
521 | /* flush a potentially queued teardown packet */ | 850 | /* flush a potentially queued teardown packet */ |
522 | ieee80211_flush_queues(local, sdata); | 851 | ieee80211_flush_queues(local, sdata); |
523 | 852 | ||
@@ -528,9 +857,9 @@ int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, | |||
528 | break; | 857 | break; |
529 | } | 858 | } |
530 | 859 | ||
531 | if (ret == 0 && ether_addr_equal(sdata->tdls_peer, peer)) { | 860 | if (ret == 0 && ether_addr_equal(sdata->u.mgd.tdls_peer, peer)) { |
532 | cancel_delayed_work(&sdata->tdls_peer_del_work); | 861 | cancel_delayed_work(&sdata->u.mgd.tdls_peer_del_work); |
533 | eth_zero_addr(sdata->tdls_peer); | 862 | eth_zero_addr(sdata->u.mgd.tdls_peer); |
534 | } | 863 | } |
535 | 864 | ||
536 | mutex_unlock(&local->mtx); | 865 | mutex_unlock(&local->mtx); |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index df1bb7e16cfe..725af7a468d2 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -3083,3 +3083,18 @@ int ieee80211_max_num_channels(struct ieee80211_local *local) | |||
3083 | 3083 | ||
3084 | return max_num_different_channels; | 3084 | return max_num_different_channels; |
3085 | } | 3085 | } |
3086 | |||
3087 | u8 *ieee80211_add_wmm_info_ie(u8 *buf, u8 qosinfo) | ||
3088 | { | ||
3089 | *buf++ = WLAN_EID_VENDOR_SPECIFIC; | ||
3090 | *buf++ = 7; /* len */ | ||
3091 | *buf++ = 0x00; /* Microsoft OUI 00:50:F2 */ | ||
3092 | *buf++ = 0x50; | ||
3093 | *buf++ = 0xf2; | ||
3094 | *buf++ = 2; /* WME */ | ||
3095 | *buf++ = 0; /* WME info */ | ||
3096 | *buf++ = 1; /* WME ver */ | ||
3097 | *buf++ = qosinfo; /* U-APSD no in use */ | ||
3098 | |||
3099 | return buf; | ||
3100 | } | ||
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c index 9265adfdabfc..671ce0d27a80 100644 --- a/net/mac80211/vht.c +++ b/net/mac80211/vht.c | |||
@@ -129,6 +129,10 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, | |||
129 | if (!vht_cap_ie || !sband->vht_cap.vht_supported) | 129 | if (!vht_cap_ie || !sband->vht_cap.vht_supported) |
130 | return; | 130 | return; |
131 | 131 | ||
132 | /* don't support VHT for TDLS peers for now */ | ||
133 | if (test_sta_flag(sta, WLAN_STA_TDLS_PEER)) | ||
134 | return; | ||
135 | |||
132 | /* | 136 | /* |
133 | * A VHT STA must support 40 MHz, but if we verify that here | 137 | * A VHT STA must support 40 MHz, but if we verify that here |
134 | * then we break a few things - some APs (e.g. Netgear R6300v2 | 138 | * then we break a few things - some APs (e.g. Netgear R6300v2 |
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 9b3dcc201145..f7d4ca4c46e0 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -811,7 +811,7 @@ ieee80211_crypto_hw_encrypt(struct ieee80211_tx_data *tx) | |||
811 | ieee80211_rx_result | 811 | ieee80211_rx_result |
812 | ieee80211_crypto_hw_decrypt(struct ieee80211_rx_data *rx) | 812 | ieee80211_crypto_hw_decrypt(struct ieee80211_rx_data *rx) |
813 | { | 813 | { |
814 | if (rx->sta->cipher_scheme) | 814 | if (rx->sta && rx->sta->cipher_scheme) |
815 | return ieee80211_crypto_cs_decrypt(rx); | 815 | return ieee80211_crypto_cs_decrypt(rx); |
816 | 816 | ||
817 | return RX_DROP_UNUSABLE; | 817 | return RX_DROP_UNUSABLE; |
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig index 405f3c4cf70c..29c8675f9a11 100644 --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig | |||
@@ -162,6 +162,12 @@ config CFG80211_INTERNAL_REGDB | |||
162 | and includes code to query that database. This is an alternative | 162 | and includes code to query that database. This is an alternative |
163 | to using CRDA for defining regulatory rules for the kernel. | 163 | to using CRDA for defining regulatory rules for the kernel. |
164 | 164 | ||
165 | Using this option requires some parsing of the db.txt at build time, | ||
166 | the parser will be upkept with the latest wireless-regdb updates but | ||
167 | older wireless-regdb formats will be ignored. The parser may later | ||
168 | be replaced to avoid issues with conflicts on versions of | ||
169 | wireless-regdb. | ||
170 | |||
165 | For details see: | 171 | For details see: |
166 | 172 | ||
167 | http://wireless.kernel.org/en/developers/Regulatory | 173 | http://wireless.kernel.org/en/developers/Regulatory |
diff --git a/net/wireless/genregdb.awk b/net/wireless/genregdb.awk index 40c37fc5b67c..baf2426b555a 100644 --- a/net/wireless/genregdb.awk +++ b/net/wireless/genregdb.awk | |||
@@ -51,32 +51,41 @@ function parse_country_head() { | |||
51 | 51 | ||
52 | function parse_reg_rule() | 52 | function parse_reg_rule() |
53 | { | 53 | { |
54 | flag_starts_at = 7 | ||
55 | |||
54 | start = $1 | 56 | start = $1 |
55 | sub(/\(/, "", start) | 57 | sub(/\(/, "", start) |
56 | end = $3 | 58 | end = $3 |
57 | bw = $5 | 59 | bw = $5 |
58 | sub(/\),/, "", bw) | 60 | sub(/\),/, "", bw) |
59 | gain = $6 | 61 | gain = 0 |
60 | sub(/\(/, "", gain) | 62 | power = $6 |
61 | sub(/,/, "", gain) | ||
62 | power = $7 | ||
63 | sub(/\)/, "", power) | ||
64 | sub(/,/, "", power) | ||
65 | # power might be in mW... | 63 | # power might be in mW... |
66 | units = $8 | 64 | units = $7 |
65 | dfs_cac = 0 | ||
66 | |||
67 | sub(/\(/, "", power) | ||
68 | sub(/\),/, "", power) | ||
69 | sub(/\),/, "", units) | ||
67 | sub(/\)/, "", units) | 70 | sub(/\)/, "", units) |
68 | sub(/,/, "", units) | 71 | |
69 | dfs_cac = $9 | ||
70 | if (units == "mW") { | 72 | if (units == "mW") { |
73 | flag_starts_at = 8 | ||
71 | power = 10 * log(power)/log(10) | 74 | power = 10 * log(power)/log(10) |
75 | if ($8 ~ /[[:digit:]]/) { | ||
76 | flag_starts_at = 9 | ||
77 | dfs_cac = $8 | ||
78 | } | ||
72 | } else { | 79 | } else { |
73 | dfs_cac = $8 | 80 | if ($7 ~ /[[:digit:]]/) { |
81 | flag_starts_at = 8 | ||
82 | dfs_cac = $7 | ||
83 | } | ||
74 | } | 84 | } |
75 | sub(/,/, "", dfs_cac) | ||
76 | sub(/\(/, "", dfs_cac) | 85 | sub(/\(/, "", dfs_cac) |
77 | sub(/\)/, "", dfs_cac) | 86 | sub(/\),/, "", dfs_cac) |
78 | flagstr = "" | 87 | flagstr = "" |
79 | for (i=8; i<=NF; i++) | 88 | for (i=flag_starts_at; i<=NF; i++) |
80 | flagstr = flagstr $i | 89 | flagstr = flagstr $i |
81 | split(flagstr, flagarray, ",") | 90 | split(flagstr, flagarray, ",") |
82 | flags = "" | 91 | flags = "" |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 082f5c62b8cf..df7b1332a1ec 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -3814,7 +3814,8 @@ int cfg80211_check_station_change(struct wiphy *wiphy, | |||
3814 | { | 3814 | { |
3815 | if (params->listen_interval != -1) | 3815 | if (params->listen_interval != -1) |
3816 | return -EINVAL; | 3816 | return -EINVAL; |
3817 | if (params->aid) | 3817 | if (params->aid && |
3818 | !(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) | ||
3818 | return -EINVAL; | 3819 | return -EINVAL; |
3819 | 3820 | ||
3820 | /* When you run into this, adjust the code below for the new flag */ | 3821 | /* When you run into this, adjust the code below for the new flag */ |