diff options
178 files changed, 6570 insertions, 2748 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 62bf15f6954f..9faf35c9f899 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -148,6 +148,13 @@ L: linux-scsi@vger.kernel.org | |||
148 | S: Maintained | 148 | S: Maintained |
149 | F: drivers/scsi/53c700* | 149 | F: drivers/scsi/53c700* |
150 | 150 | ||
151 | 6LOWPAN GENERIC (BTLE/IEEE 802.15.4) | ||
152 | M: Alexander Aring <alex.aring@gmail.com> | ||
153 | L: linux-zigbee-devel@lists.sourceforge.net (moderated for non-subscribers) | ||
154 | L: linux-bluetooth@vger.kernel.org | ||
155 | S: Maintained | ||
156 | F: net/6lowpan/ | ||
157 | |||
151 | 6PACK NETWORK DRIVER FOR AX.25 | 158 | 6PACK NETWORK DRIVER FOR AX.25 |
152 | M: Andreas Koensgen <ajk@comnets.uni-bremen.de> | 159 | M: Andreas Koensgen <ajk@comnets.uni-bremen.de> |
153 | L: linux-hams@vger.kernel.org | 160 | L: linux-hams@vger.kernel.org |
diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c index 5081a8c439cc..bb694e2e9f32 100644 --- a/drivers/bcma/driver_chipcommon_pmu.c +++ b/drivers/bcma/driver_chipcommon_pmu.c | |||
@@ -603,6 +603,7 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid) | |||
603 | tmp = BCMA_CC_PMU_CTL_PLL_UPD | BCMA_CC_PMU_CTL_NOILPONW; | 603 | tmp = BCMA_CC_PMU_CTL_PLL_UPD | BCMA_CC_PMU_CTL_NOILPONW; |
604 | break; | 604 | break; |
605 | 605 | ||
606 | case BCMA_CHIP_ID_BCM43217: | ||
606 | case BCMA_CHIP_ID_BCM43227: | 607 | case BCMA_CHIP_ID_BCM43227: |
607 | case BCMA_CHIP_ID_BCM43228: | 608 | case BCMA_CHIP_ID_BCM43228: |
608 | case BCMA_CHIP_ID_BCM43428: | 609 | case BCMA_CHIP_ID_BCM43428: |
diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c index e333305363aa..3cf725a49dc1 100644 --- a/drivers/bcma/host_pci.c +++ b/drivers/bcma/host_pci.c | |||
@@ -279,6 +279,7 @@ static const struct pci_device_id bcma_pci_bridge_tbl[] = { | |||
279 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4358) }, | 279 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4358) }, |
280 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4359) }, | 280 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4359) }, |
281 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4365) }, | 281 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4365) }, |
282 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a9) }, | ||
282 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, | 283 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, |
283 | { 0, }, | 284 | { 0, }, |
284 | }; | 285 | }; |
diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c index 72bf4540f565..97bb38e9ed65 100644 --- a/drivers/bcma/sprom.c +++ b/drivers/bcma/sprom.c | |||
@@ -201,6 +201,23 @@ static int bcma_sprom_valid(struct bcma_bus *bus, const u16 *sprom, | |||
201 | SPEX(_field[7], _offset + 14, _mask, _shift); \ | 201 | SPEX(_field[7], _offset + 14, _mask, _shift); \ |
202 | } while (0) | 202 | } while (0) |
203 | 203 | ||
204 | static s8 sprom_extract_antgain(const u16 *in, u16 offset, u16 mask, u16 shift) | ||
205 | { | ||
206 | u16 v; | ||
207 | u8 gain; | ||
208 | |||
209 | v = in[SPOFF(offset)]; | ||
210 | gain = (v & mask) >> shift; | ||
211 | if (gain == 0xFF) { | ||
212 | gain = 8; /* If unset use 2dBm */ | ||
213 | } else { | ||
214 | /* Q5.2 Fractional part is stored in 0xC0 */ | ||
215 | gain = ((gain & 0xC0) >> 6) | ((gain & 0x3F) << 2); | ||
216 | } | ||
217 | |||
218 | return (s8)gain; | ||
219 | } | ||
220 | |||
204 | static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom) | 221 | static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom) |
205 | { | 222 | { |
206 | u16 v, o; | 223 | u16 v, o; |
@@ -381,14 +398,22 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom) | |||
381 | SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, ~0, 0); | 398 | SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, ~0, 0); |
382 | 399 | ||
383 | /* Extract the antenna gain values. */ | 400 | /* Extract the antenna gain values. */ |
384 | SPEX(antenna_gain.a0, SSB_SPROM8_AGAIN01, | 401 | bus->sprom.antenna_gain.a0 = sprom_extract_antgain(sprom, |
385 | SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT); | 402 | SSB_SPROM8_AGAIN01, |
386 | SPEX(antenna_gain.a1, SSB_SPROM8_AGAIN01, | 403 | SSB_SPROM8_AGAIN0, |
387 | SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT); | 404 | SSB_SPROM8_AGAIN0_SHIFT); |
388 | SPEX(antenna_gain.a2, SSB_SPROM8_AGAIN23, | 405 | bus->sprom.antenna_gain.a1 = sprom_extract_antgain(sprom, |
389 | SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT); | 406 | SSB_SPROM8_AGAIN01, |
390 | SPEX(antenna_gain.a3, SSB_SPROM8_AGAIN23, | 407 | SSB_SPROM8_AGAIN1, |
391 | SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT); | 408 | SSB_SPROM8_AGAIN1_SHIFT); |
409 | bus->sprom.antenna_gain.a2 = sprom_extract_antgain(sprom, | ||
410 | SSB_SPROM8_AGAIN23, | ||
411 | SSB_SPROM8_AGAIN2, | ||
412 | SSB_SPROM8_AGAIN2_SHIFT); | ||
413 | bus->sprom.antenna_gain.a3 = sprom_extract_antgain(sprom, | ||
414 | SSB_SPROM8_AGAIN23, | ||
415 | SSB_SPROM8_AGAIN3, | ||
416 | SSB_SPROM8_AGAIN3_SHIFT); | ||
392 | 417 | ||
393 | SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON, | 418 | SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON, |
394 | SSB_SPROM8_LEDDC_ON_SHIFT); | 419 | SSB_SPROM8_LEDDC_ON_SHIFT); |
@@ -509,6 +534,7 @@ static bool bcma_sprom_onchip_available(struct bcma_bus *bus) | |||
509 | /* for these chips OTP is always available */ | 534 | /* for these chips OTP is always available */ |
510 | present = true; | 535 | present = true; |
511 | break; | 536 | break; |
537 | case BCMA_CHIP_ID_BCM43217: | ||
512 | case BCMA_CHIP_ID_BCM43227: | 538 | case BCMA_CHIP_ID_BCM43227: |
513 | case BCMA_CHIP_ID_BCM43228: | 539 | case BCMA_CHIP_ID_BCM43228: |
514 | case BCMA_CHIP_ID_BCM43428: | 540 | case BCMA_CHIP_ID_BCM43428: |
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/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index e00f8f5b5c8e..dc487b5d1156 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c | |||
@@ -431,6 +431,9 @@ static int hci_uart_register_dev(struct hci_uart *hu) | |||
431 | if (test_bit(HCI_UART_RAW_DEVICE, &hu->hdev_flags)) | 431 | if (test_bit(HCI_UART_RAW_DEVICE, &hu->hdev_flags)) |
432 | set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); | 432 | set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); |
433 | 433 | ||
434 | if (test_bit(HCI_UART_EXT_CONFIG, &hu->hdev_flags)) | ||
435 | set_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks); | ||
436 | |||
434 | if (!test_bit(HCI_UART_RESET_ON_INIT, &hu->hdev_flags)) | 437 | if (!test_bit(HCI_UART_RESET_ON_INIT, &hu->hdev_flags)) |
435 | set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); | 438 | set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); |
436 | 439 | ||
@@ -477,6 +480,22 @@ static int hci_uart_set_proto(struct hci_uart *hu, int id) | |||
477 | return 0; | 480 | return 0; |
478 | } | 481 | } |
479 | 482 | ||
483 | static int hci_uart_set_flags(struct hci_uart *hu, unsigned long flags) | ||
484 | { | ||
485 | unsigned long valid_flags = BIT(HCI_UART_RAW_DEVICE) | | ||
486 | BIT(HCI_UART_RESET_ON_INIT) | | ||
487 | BIT(HCI_UART_CREATE_AMP) | | ||
488 | BIT(HCI_UART_INIT_PENDING) | | ||
489 | BIT(HCI_UART_EXT_CONFIG); | ||
490 | |||
491 | if ((flags & ~valid_flags)) | ||
492 | return -EINVAL; | ||
493 | |||
494 | hu->hdev_flags = flags; | ||
495 | |||
496 | return 0; | ||
497 | } | ||
498 | |||
480 | /* hci_uart_tty_ioctl() | 499 | /* hci_uart_tty_ioctl() |
481 | * | 500 | * |
482 | * Process IOCTL system call for the tty device. | 501 | * Process IOCTL system call for the tty device. |
@@ -520,14 +539,16 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file, | |||
520 | return -EUNATCH; | 539 | return -EUNATCH; |
521 | 540 | ||
522 | case HCIUARTGETDEVICE: | 541 | case HCIUARTGETDEVICE: |
523 | if (test_bit(HCI_UART_PROTO_SET, &hu->flags)) | 542 | if (test_bit(HCI_UART_REGISTERED, &hu->flags)) |
524 | return hu->hdev->id; | 543 | return hu->hdev->id; |
525 | return -EUNATCH; | 544 | return -EUNATCH; |
526 | 545 | ||
527 | case HCIUARTSETFLAGS: | 546 | case HCIUARTSETFLAGS: |
528 | if (test_bit(HCI_UART_PROTO_SET, &hu->flags)) | 547 | if (test_bit(HCI_UART_PROTO_SET, &hu->flags)) |
529 | return -EBUSY; | 548 | return -EBUSY; |
530 | hu->hdev_flags = arg; | 549 | err = hci_uart_set_flags(hu, arg); |
550 | if (err) | ||
551 | return err; | ||
531 | break; | 552 | break; |
532 | 553 | ||
533 | case HCIUARTGETFLAGS: | 554 | case HCIUARTGETFLAGS: |
diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h index 12df101ca942..247488edcbf9 100644 --- a/drivers/bluetooth/hci_uart.h +++ b/drivers/bluetooth/hci_uart.h | |||
@@ -48,6 +48,7 @@ | |||
48 | #define HCI_UART_RESET_ON_INIT 1 | 48 | #define HCI_UART_RESET_ON_INIT 1 |
49 | #define HCI_UART_CREATE_AMP 2 | 49 | #define HCI_UART_CREATE_AMP 2 |
50 | #define HCI_UART_INIT_PENDING 3 | 50 | #define HCI_UART_INIT_PENDING 3 |
51 | #define HCI_UART_EXT_CONFIG 4 | ||
51 | 52 | ||
52 | struct hci_uart; | 53 | struct hci_uart; |
53 | 54 | ||
diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index d185dc0cd12b..4333107ecf37 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c | |||
@@ -603,16 +603,19 @@ static int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, | |||
603 | if (ret) | 603 | if (ret) |
604 | return ret; | 604 | return ret; |
605 | 605 | ||
606 | src_ring->hw_index = | 606 | read_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr); |
607 | ath10k_ce_src_ring_read_index_get(ar, ctrl_addr); | 607 | if (read_index == 0xffffffff) |
608 | src_ring->hw_index &= nentries_mask; | 608 | return -ENODEV; |
609 | |||
610 | read_index &= nentries_mask; | ||
611 | src_ring->hw_index = read_index; | ||
609 | 612 | ||
610 | ath10k_pci_sleep(ar); | 613 | ath10k_pci_sleep(ar); |
611 | } | 614 | } |
612 | 615 | ||
613 | read_index = src_ring->hw_index; | 616 | read_index = src_ring->hw_index; |
614 | 617 | ||
615 | if ((read_index == sw_index) || (read_index == 0xffffffff)) | 618 | if (read_index == sw_index) |
616 | return -EIO; | 619 | return -EIO; |
617 | 620 | ||
618 | sbase = src_ring->shadow_base; | 621 | sbase = src_ring->shadow_base; |
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index e6c56c5bb0f6..93adb8c58969 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c | |||
@@ -802,7 +802,7 @@ int ath10k_core_start(struct ath10k *ar) | |||
802 | 802 | ||
803 | INIT_LIST_HEAD(&ar->arvifs); | 803 | INIT_LIST_HEAD(&ar->arvifs); |
804 | 804 | ||
805 | if (!test_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags)) | 805 | if (!test_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags)) { |
806 | ath10k_info("%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d\n", | 806 | ath10k_info("%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d\n", |
807 | ar->hw_params.name, | 807 | ar->hw_params.name, |
808 | ar->target_version, | 808 | ar->target_version, |
@@ -811,6 +811,12 @@ int ath10k_core_start(struct ath10k *ar) | |||
811 | ar->fw_api, | 811 | ar->fw_api, |
812 | ar->htt.target_version_major, | 812 | ar->htt.target_version_major, |
813 | ar->htt.target_version_minor); | 813 | ar->htt.target_version_minor); |
814 | ath10k_info("debug %d debugfs %d tracing %d dfs %d\n", | ||
815 | config_enabled(CONFIG_ATH10K_DEBUG), | ||
816 | config_enabled(CONFIG_ATH10K_DEBUGFS), | ||
817 | config_enabled(CONFIG_ATH10K_TRACING), | ||
818 | config_enabled(CONFIG_ATH10K_DFS_CERTIFIED)); | ||
819 | } | ||
814 | 820 | ||
815 | __set_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags); | 821 | __set_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags); |
816 | 822 | ||
@@ -988,7 +994,9 @@ err_unregister_mac: | |||
988 | err_release_fw: | 994 | err_release_fw: |
989 | ath10k_core_free_firmware_files(ar); | 995 | ath10k_core_free_firmware_files(ar); |
990 | err: | 996 | err: |
991 | device_release_driver(ar->dev); | 997 | /* TODO: It's probably a good idea to release device from the driver |
998 | * but calling device_release_driver() here will cause a deadlock. | ||
999 | */ | ||
992 | return; | 1000 | return; |
993 | } | 1001 | } |
994 | 1002 | ||
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 68ceef61933d..83a5fa91531d 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h | |||
@@ -290,6 +290,9 @@ struct ath10k_debug { | |||
290 | struct ath_dfs_pool_stats dfs_pool_stats; | 290 | struct ath_dfs_pool_stats dfs_pool_stats; |
291 | 291 | ||
292 | u32 fw_dbglog_mask; | 292 | u32 fw_dbglog_mask; |
293 | |||
294 | u8 htt_max_amsdu; | ||
295 | u8 htt_max_ampdu; | ||
293 | }; | 296 | }; |
294 | 297 | ||
295 | enum ath10k_state { | 298 | enum ath10k_state { |
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 1b7ff4ba122c..3030158c478e 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c | |||
@@ -671,6 +671,72 @@ static const struct file_operations fops_htt_stats_mask = { | |||
671 | .llseek = default_llseek, | 671 | .llseek = default_llseek, |
672 | }; | 672 | }; |
673 | 673 | ||
674 | static ssize_t ath10k_read_htt_max_amsdu_ampdu(struct file *file, | ||
675 | char __user *user_buf, | ||
676 | size_t count, loff_t *ppos) | ||
677 | { | ||
678 | struct ath10k *ar = file->private_data; | ||
679 | char buf[64]; | ||
680 | u8 amsdu = 3, ampdu = 64; | ||
681 | unsigned int len; | ||
682 | |||
683 | mutex_lock(&ar->conf_mutex); | ||
684 | |||
685 | if (ar->debug.htt_max_amsdu) | ||
686 | amsdu = ar->debug.htt_max_amsdu; | ||
687 | |||
688 | if (ar->debug.htt_max_ampdu) | ||
689 | ampdu = ar->debug.htt_max_ampdu; | ||
690 | |||
691 | mutex_unlock(&ar->conf_mutex); | ||
692 | |||
693 | len = scnprintf(buf, sizeof(buf), "%u %u\n", amsdu, ampdu); | ||
694 | |||
695 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
696 | } | ||
697 | |||
698 | static ssize_t ath10k_write_htt_max_amsdu_ampdu(struct file *file, | ||
699 | const char __user *user_buf, | ||
700 | size_t count, loff_t *ppos) | ||
701 | { | ||
702 | struct ath10k *ar = file->private_data; | ||
703 | int res; | ||
704 | char buf[64]; | ||
705 | unsigned int amsdu, ampdu; | ||
706 | |||
707 | simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count); | ||
708 | |||
709 | /* make sure that buf is null terminated */ | ||
710 | buf[sizeof(buf) - 1] = 0; | ||
711 | |||
712 | res = sscanf(buf, "%u %u", &amsdu, &du); | ||
713 | |||
714 | if (res != 2) | ||
715 | return -EINVAL; | ||
716 | |||
717 | mutex_lock(&ar->conf_mutex); | ||
718 | |||
719 | res = ath10k_htt_h2t_aggr_cfg_msg(&ar->htt, ampdu, amsdu); | ||
720 | if (res) | ||
721 | goto out; | ||
722 | |||
723 | res = count; | ||
724 | ar->debug.htt_max_amsdu = amsdu; | ||
725 | ar->debug.htt_max_ampdu = ampdu; | ||
726 | |||
727 | out: | ||
728 | mutex_unlock(&ar->conf_mutex); | ||
729 | return res; | ||
730 | } | ||
731 | |||
732 | static const struct file_operations fops_htt_max_amsdu_ampdu = { | ||
733 | .read = ath10k_read_htt_max_amsdu_ampdu, | ||
734 | .write = ath10k_write_htt_max_amsdu_ampdu, | ||
735 | .open = simple_open, | ||
736 | .owner = THIS_MODULE, | ||
737 | .llseek = default_llseek, | ||
738 | }; | ||
739 | |||
674 | static ssize_t ath10k_read_fw_dbglog(struct file *file, | 740 | static ssize_t ath10k_read_fw_dbglog(struct file *file, |
675 | char __user *user_buf, | 741 | char __user *user_buf, |
676 | size_t count, loff_t *ppos) | 742 | size_t count, loff_t *ppos) |
@@ -757,6 +823,9 @@ void ath10k_debug_stop(struct ath10k *ar) | |||
757 | * warning from del_timer(). */ | 823 | * warning from del_timer(). */ |
758 | if (ar->debug.htt_stats_mask != 0) | 824 | if (ar->debug.htt_stats_mask != 0) |
759 | cancel_delayed_work(&ar->debug.htt_stats_dwork); | 825 | cancel_delayed_work(&ar->debug.htt_stats_dwork); |
826 | |||
827 | ar->debug.htt_max_amsdu = 0; | ||
828 | ar->debug.htt_max_ampdu = 0; | ||
760 | } | 829 | } |
761 | 830 | ||
762 | static ssize_t ath10k_write_simulate_radar(struct file *file, | 831 | static ssize_t ath10k_write_simulate_radar(struct file *file, |
@@ -867,6 +936,10 @@ int ath10k_debug_create(struct ath10k *ar) | |||
867 | debugfs_create_file("htt_stats_mask", S_IRUSR, ar->debug.debugfs_phy, | 936 | debugfs_create_file("htt_stats_mask", S_IRUSR, ar->debug.debugfs_phy, |
868 | ar, &fops_htt_stats_mask); | 937 | ar, &fops_htt_stats_mask); |
869 | 938 | ||
939 | debugfs_create_file("htt_max_amsdu_ampdu", S_IRUSR | S_IWUSR, | ||
940 | ar->debug.debugfs_phy, ar, | ||
941 | &fops_htt_max_amsdu_ampdu); | ||
942 | |||
870 | debugfs_create_file("fw_dbglog", S_IRUSR, ar->debug.debugfs_phy, | 943 | debugfs_create_file("fw_dbglog", S_IRUSR, ar->debug.debugfs_phy, |
871 | ar, &fops_fw_dbglog); | 944 | ar, &fops_fw_dbglog); |
872 | 945 | ||
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index 9a263462c793..6c93f3885ee5 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h | |||
@@ -240,16 +240,10 @@ struct htt_oob_sync_req { | |||
240 | __le16 rsvd0; | 240 | __le16 rsvd0; |
241 | } __packed; | 241 | } __packed; |
242 | 242 | ||
243 | #define HTT_AGGR_CONF_MAX_NUM_AMSDU_SUBFRAMES_MASK 0x1F | ||
244 | #define HTT_AGGR_CONF_MAX_NUM_AMSDU_SUBFRAMES_LSB 0 | ||
245 | |||
246 | struct htt_aggr_conf { | 243 | struct htt_aggr_conf { |
247 | u8 max_num_ampdu_subframes; | 244 | u8 max_num_ampdu_subframes; |
248 | union { | 245 | /* amsdu_subframes is limited by 0x1F mask */ |
249 | /* dont use bitfields; undefined behaviour */ | 246 | u8 max_num_amsdu_subframes; |
250 | u8 flags; /* see %HTT_AGGR_CONF_MAX_NUM_AMSDU_SUBFRAMES_ */ | ||
251 | u8 max_num_amsdu_subframes:5; | ||
252 | } __packed; | ||
253 | } __packed; | 247 | } __packed; |
254 | 248 | ||
255 | #define HTT_MGMT_FRM_HDR_DOWNLOAD_LEN 32 | 249 | #define HTT_MGMT_FRM_HDR_DOWNLOAD_LEN 32 |
@@ -1343,6 +1337,9 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb); | |||
1343 | int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt); | 1337 | int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt); |
1344 | int ath10k_htt_h2t_stats_req(struct ath10k_htt *htt, u8 mask, u64 cookie); | 1338 | int ath10k_htt_h2t_stats_req(struct ath10k_htt *htt, u8 mask, u64 cookie); |
1345 | int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt); | 1339 | int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt); |
1340 | int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt, | ||
1341 | u8 max_subfrms_ampdu, | ||
1342 | u8 max_subfrms_amsdu); | ||
1346 | 1343 | ||
1347 | void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt); | 1344 | void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt); |
1348 | int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt); | 1345 | int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt); |
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index 7064354d1f4f..accb6b4f6faf 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c | |||
@@ -307,6 +307,52 @@ int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt) | |||
307 | return 0; | 307 | return 0; |
308 | } | 308 | } |
309 | 309 | ||
310 | int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt, | ||
311 | u8 max_subfrms_ampdu, | ||
312 | u8 max_subfrms_amsdu) | ||
313 | { | ||
314 | struct htt_aggr_conf *aggr_conf; | ||
315 | struct sk_buff *skb; | ||
316 | struct htt_cmd *cmd; | ||
317 | int len; | ||
318 | int ret; | ||
319 | |||
320 | /* Firmware defaults are: amsdu = 3 and ampdu = 64 */ | ||
321 | |||
322 | if (max_subfrms_ampdu == 0 || max_subfrms_ampdu > 64) | ||
323 | return -EINVAL; | ||
324 | |||
325 | if (max_subfrms_amsdu == 0 || max_subfrms_amsdu > 31) | ||
326 | return -EINVAL; | ||
327 | |||
328 | len = sizeof(cmd->hdr); | ||
329 | len += sizeof(cmd->aggr_conf); | ||
330 | |||
331 | skb = ath10k_htc_alloc_skb(len); | ||
332 | if (!skb) | ||
333 | return -ENOMEM; | ||
334 | |||
335 | skb_put(skb, len); | ||
336 | cmd = (struct htt_cmd *)skb->data; | ||
337 | cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_AGGR_CFG; | ||
338 | |||
339 | aggr_conf = &cmd->aggr_conf; | ||
340 | aggr_conf->max_num_ampdu_subframes = max_subfrms_ampdu; | ||
341 | aggr_conf->max_num_amsdu_subframes = max_subfrms_amsdu; | ||
342 | |||
343 | ath10k_dbg(ATH10K_DBG_HTT, "htt h2t aggr cfg msg amsdu %d ampdu %d", | ||
344 | aggr_conf->max_num_amsdu_subframes, | ||
345 | aggr_conf->max_num_ampdu_subframes); | ||
346 | |||
347 | ret = ath10k_htc_send(&htt->ar->htc, htt->eid, skb); | ||
348 | if (ret) { | ||
349 | dev_kfree_skb_any(skb); | ||
350 | return ret; | ||
351 | } | ||
352 | |||
353 | return 0; | ||
354 | } | ||
355 | |||
310 | int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) | 356 | int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) |
311 | { | 357 | { |
312 | struct device *dev = htt->ar->dev; | 358 | struct device *dev = htt->ar->dev; |
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index d0004d59c97e..06840d101c45 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c | |||
@@ -1362,8 +1362,6 @@ static int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar, | |||
1362 | ath10k_ce_recv_buf_enqueue(ce_rx, &xfer, resp_paddr); | 1362 | ath10k_ce_recv_buf_enqueue(ce_rx, &xfer, resp_paddr); |
1363 | } | 1363 | } |
1364 | 1364 | ||
1365 | init_completion(&xfer.done); | ||
1366 | |||
1367 | ret = ath10k_ce_send(ce_tx, &xfer, req_paddr, req_len, -1, 0); | 1365 | ret = ath10k_ce_send(ce_tx, &xfer, req_paddr, req_len, -1, 0); |
1368 | if (ret) | 1366 | if (ret) |
1369 | goto err_resp; | 1367 | goto err_resp; |
@@ -1414,10 +1412,7 @@ static void ath10k_pci_bmi_send_done(struct ath10k_ce_pipe *ce_state) | |||
1414 | &nbytes, &transfer_id)) | 1412 | &nbytes, &transfer_id)) |
1415 | return; | 1413 | return; |
1416 | 1414 | ||
1417 | if (xfer->wait_for_resp) | 1415 | xfer->tx_done = true; |
1418 | return; | ||
1419 | |||
1420 | complete(&xfer->done); | ||
1421 | } | 1416 | } |
1422 | 1417 | ||
1423 | static void ath10k_pci_bmi_recv_data(struct ath10k_ce_pipe *ce_state) | 1418 | static void ath10k_pci_bmi_recv_data(struct ath10k_ce_pipe *ce_state) |
@@ -1438,7 +1433,7 @@ static void ath10k_pci_bmi_recv_data(struct ath10k_ce_pipe *ce_state) | |||
1438 | } | 1433 | } |
1439 | 1434 | ||
1440 | xfer->resp_len = nbytes; | 1435 | xfer->resp_len = nbytes; |
1441 | complete(&xfer->done); | 1436 | xfer->rx_done = true; |
1442 | } | 1437 | } |
1443 | 1438 | ||
1444 | static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe, | 1439 | static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe, |
@@ -1451,7 +1446,7 @@ static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe, | |||
1451 | ath10k_pci_bmi_send_done(tx_pipe); | 1446 | ath10k_pci_bmi_send_done(tx_pipe); |
1452 | ath10k_pci_bmi_recv_data(rx_pipe); | 1447 | ath10k_pci_bmi_recv_data(rx_pipe); |
1453 | 1448 | ||
1454 | if (completion_done(&xfer->done)) | 1449 | if (xfer->tx_done && (xfer->rx_done == xfer->wait_for_resp)) |
1455 | return 0; | 1450 | return 0; |
1456 | 1451 | ||
1457 | schedule(); | 1452 | schedule(); |
diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index dfdebb4157aa..940129209990 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h | |||
@@ -38,7 +38,8 @@ | |||
38 | #define DIAG_TRANSFER_LIMIT 2048 | 38 | #define DIAG_TRANSFER_LIMIT 2048 |
39 | 39 | ||
40 | struct bmi_xfer { | 40 | struct bmi_xfer { |
41 | struct completion done; | 41 | bool tx_done; |
42 | bool rx_done; | ||
42 | bool wait_for_resp; | 43 | bool wait_for_resp; |
43 | u32 resp_len; | 44 | u32 resp_len; |
44 | }; | 45 | }; |
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 4b7782a529ac..6f83cae57655 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c | |||
@@ -2106,7 +2106,6 @@ static void ath10k_wmi_main_process_rx(struct ath10k *ar, struct sk_buff *skb) | |||
2106 | { | 2106 | { |
2107 | struct wmi_cmd_hdr *cmd_hdr; | 2107 | struct wmi_cmd_hdr *cmd_hdr; |
2108 | enum wmi_event_id id; | 2108 | enum wmi_event_id id; |
2109 | u16 len; | ||
2110 | 2109 | ||
2111 | cmd_hdr = (struct wmi_cmd_hdr *)skb->data; | 2110 | cmd_hdr = (struct wmi_cmd_hdr *)skb->data; |
2112 | id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); | 2111 | id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); |
@@ -2114,8 +2113,6 @@ static void ath10k_wmi_main_process_rx(struct ath10k *ar, struct sk_buff *skb) | |||
2114 | if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL) | 2113 | if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL) |
2115 | return; | 2114 | return; |
2116 | 2115 | ||
2117 | len = skb->len; | ||
2118 | |||
2119 | trace_ath10k_wmi_event(id, skb->data, skb->len); | 2116 | trace_ath10k_wmi_event(id, skb->data, skb->len); |
2120 | 2117 | ||
2121 | switch (id) { | 2118 | switch (id) { |
@@ -2225,7 +2222,6 @@ static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb) | |||
2225 | { | 2222 | { |
2226 | struct wmi_cmd_hdr *cmd_hdr; | 2223 | struct wmi_cmd_hdr *cmd_hdr; |
2227 | enum wmi_10x_event_id id; | 2224 | enum wmi_10x_event_id id; |
2228 | u16 len; | ||
2229 | 2225 | ||
2230 | cmd_hdr = (struct wmi_cmd_hdr *)skb->data; | 2226 | cmd_hdr = (struct wmi_cmd_hdr *)skb->data; |
2231 | id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); | 2227 | id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); |
@@ -2233,8 +2229,6 @@ static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb) | |||
2233 | if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL) | 2229 | if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL) |
2234 | return; | 2230 | return; |
2235 | 2231 | ||
2236 | len = skb->len; | ||
2237 | |||
2238 | trace_ath10k_wmi_event(id, skb->data, skb->len); | 2232 | trace_ath10k_wmi_event(id, skb->data, skb->len); |
2239 | 2233 | ||
2240 | switch (id) { | 2234 | switch (id) { |
diff --git a/drivers/net/wireless/ath/ath6kl/bmi.h b/drivers/net/wireless/ath/ath6kl/bmi.h index 18fdd69e1f71..397a52f2628b 100644 --- a/drivers/net/wireless/ath/ath6kl/bmi.h +++ b/drivers/net/wireless/ath/ath6kl/bmi.h | |||
@@ -242,7 +242,8 @@ struct ath6kl_bmi_target_info { | |||
242 | (void) (check_type == val); \ | 242 | (void) (check_type == val); \ |
243 | addr = ath6kl_get_hi_item_addr(ar, HI_ITEM(item)); \ | 243 | addr = ath6kl_get_hi_item_addr(ar, HI_ITEM(item)); \ |
244 | ret = ath6kl_bmi_read(ar, addr, (u8 *) &tmp, 4); \ | 244 | ret = ath6kl_bmi_read(ar, addr, (u8 *) &tmp, 4); \ |
245 | *val = le32_to_cpu(tmp); \ | 245 | if (!ret) \ |
246 | *val = le32_to_cpu(tmp); \ | ||
246 | ret; \ | 247 | ret; \ |
247 | }) | 248 | }) |
248 | 249 | ||
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 1c4ce8e3eebe..e535807c3d89 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c | |||
@@ -2899,7 +2899,8 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
2899 | if (info->inactivity_timeout) { | 2899 | if (info->inactivity_timeout) { |
2900 | inactivity_timeout = info->inactivity_timeout; | 2900 | inactivity_timeout = info->inactivity_timeout; |
2901 | 2901 | ||
2902 | if (ar->hw.flags & ATH6KL_HW_AP_INACTIVITY_MINS) | 2902 | if (test_bit(ATH6KL_FW_CAPABILITY_AP_INACTIVITY_MINS, |
2903 | ar->fw_capabilities)) | ||
2903 | inactivity_timeout = DIV_ROUND_UP(inactivity_timeout, | 2904 | inactivity_timeout = DIV_ROUND_UP(inactivity_timeout, |
2904 | 60); | 2905 | 60); |
2905 | 2906 | ||
@@ -3782,7 +3783,8 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) | |||
3782 | ath6kl_band_5ghz.ht_cap.ht_supported = false; | 3783 | ath6kl_band_5ghz.ht_cap.ht_supported = false; |
3783 | } | 3784 | } |
3784 | 3785 | ||
3785 | if (ar->hw.flags & ATH6KL_HW_64BIT_RATES) { | 3786 | if (test_bit(ATH6KL_FW_CAPABILITY_64BIT_RATES, |
3787 | ar->fw_capabilities)) { | ||
3786 | ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff; | 3788 | ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff; |
3787 | ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff; | 3789 | ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff; |
3788 | ath6kl_band_2ghz.ht_cap.mcs.rx_mask[1] = 0xff; | 3790 | ath6kl_band_2ghz.ht_cap.mcs.rx_mask[1] = 0xff; |
diff --git a/drivers/net/wireless/ath/ath6kl/core.c b/drivers/net/wireless/ath/ath6kl/core.c index b0b652042760..0df74b245af4 100644 --- a/drivers/net/wireless/ath/ath6kl/core.c +++ b/drivers/net/wireless/ath/ath6kl/core.c | |||
@@ -123,6 +123,22 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type) | |||
123 | 123 | ||
124 | /* FIXME: we should free all firmwares in the error cases below */ | 124 | /* FIXME: we should free all firmwares in the error cases below */ |
125 | 125 | ||
126 | /* | ||
127 | * Backwards compatibility support for older ar6004 firmware images | ||
128 | * which do not set these feature flags. | ||
129 | */ | ||
130 | if (ar->target_type == TARGET_TYPE_AR6004 && | ||
131 | ar->fw_api <= 4) { | ||
132 | __set_bit(ATH6KL_FW_CAPABILITY_64BIT_RATES, | ||
133 | ar->fw_capabilities); | ||
134 | __set_bit(ATH6KL_FW_CAPABILITY_AP_INACTIVITY_MINS, | ||
135 | ar->fw_capabilities); | ||
136 | |||
137 | if (ar->hw.id == AR6004_HW_1_3_VERSION) | ||
138 | __set_bit(ATH6KL_FW_CAPABILITY_MAP_LP_ENDPOINT, | ||
139 | ar->fw_capabilities); | ||
140 | } | ||
141 | |||
126 | /* Indicate that WMI is enabled (although not ready yet) */ | 142 | /* Indicate that WMI is enabled (although not ready yet) */ |
127 | set_bit(WMI_ENABLED, &ar->flag); | 143 | set_bit(WMI_ENABLED, &ar->flag); |
128 | ar->wmi = ath6kl_wmi_init(ar); | 144 | ar->wmi = ath6kl_wmi_init(ar); |
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index 26b0f92424e1..2b78c863d030 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h | |||
@@ -136,6 +136,21 @@ enum ath6kl_fw_capability { | |||
136 | */ | 136 | */ |
137 | ATH6KL_FW_CAPABILITY_HEART_BEAT_POLL, | 137 | ATH6KL_FW_CAPABILITY_HEART_BEAT_POLL, |
138 | 138 | ||
139 | /* WMI_SET_TX_SELECT_RATES_CMDID uses 64 bit size rate table */ | ||
140 | ATH6KL_FW_CAPABILITY_64BIT_RATES, | ||
141 | |||
142 | /* WMI_AP_CONN_INACT_CMDID uses minutes as units */ | ||
143 | ATH6KL_FW_CAPABILITY_AP_INACTIVITY_MINS, | ||
144 | |||
145 | /* use low priority endpoint for all data */ | ||
146 | ATH6KL_FW_CAPABILITY_MAP_LP_ENDPOINT, | ||
147 | |||
148 | /* ratetable is the 2 stream version (max MCS15) */ | ||
149 | ATH6KL_FW_CAPABILITY_RATETABLE_MCS15, | ||
150 | |||
151 | /* firmare doesn't support IP checksumming */ | ||
152 | ATH6KL_FW_CAPABILITY_NO_IP_CHECKSUM, | ||
153 | |||
139 | /* this needs to be last */ | 154 | /* this needs to be last */ |
140 | ATH6KL_FW_CAPABILITY_MAX, | 155 | ATH6KL_FW_CAPABILITY_MAX, |
141 | }; | 156 | }; |
@@ -149,15 +164,13 @@ struct ath6kl_fw_ie { | |||
149 | }; | 164 | }; |
150 | 165 | ||
151 | enum ath6kl_hw_flags { | 166 | enum ath6kl_hw_flags { |
152 | ATH6KL_HW_64BIT_RATES = BIT(0), | ||
153 | ATH6KL_HW_AP_INACTIVITY_MINS = BIT(1), | ||
154 | ATH6KL_HW_MAP_LP_ENDPOINT = BIT(2), | ||
155 | ATH6KL_HW_SDIO_CRC_ERROR_WAR = BIT(3), | 167 | ATH6KL_HW_SDIO_CRC_ERROR_WAR = BIT(3), |
156 | }; | 168 | }; |
157 | 169 | ||
158 | #define ATH6KL_FW_API2_FILE "fw-2.bin" | 170 | #define ATH6KL_FW_API2_FILE "fw-2.bin" |
159 | #define ATH6KL_FW_API3_FILE "fw-3.bin" | 171 | #define ATH6KL_FW_API3_FILE "fw-3.bin" |
160 | #define ATH6KL_FW_API4_FILE "fw-4.bin" | 172 | #define ATH6KL_FW_API4_FILE "fw-4.bin" |
173 | #define ATH6KL_FW_API5_FILE "fw-5.bin" | ||
161 | 174 | ||
162 | /* AR6003 1.0 definitions */ | 175 | /* AR6003 1.0 definitions */ |
163 | #define AR6003_HW_1_0_VERSION 0x300002ba | 176 | #define AR6003_HW_1_0_VERSION 0x300002ba |
@@ -215,8 +228,21 @@ enum ath6kl_hw_flags { | |||
215 | #define AR6004_HW_1_3_VERSION 0x31c8088a | 228 | #define AR6004_HW_1_3_VERSION 0x31c8088a |
216 | #define AR6004_HW_1_3_FW_DIR "ath6k/AR6004/hw1.3" | 229 | #define AR6004_HW_1_3_FW_DIR "ath6k/AR6004/hw1.3" |
217 | #define AR6004_HW_1_3_FIRMWARE_FILE "fw.ram.bin" | 230 | #define AR6004_HW_1_3_FIRMWARE_FILE "fw.ram.bin" |
218 | #define AR6004_HW_1_3_BOARD_DATA_FILE "ath6k/AR6004/hw1.3/bdata.bin" | 231 | #define AR6004_HW_1_3_TCMD_FIRMWARE_FILE "utf.bin" |
219 | #define AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE "ath6k/AR6004/hw1.3/bdata.bin" | 232 | #define AR6004_HW_1_3_UTF_FIRMWARE_FILE "utf.bin" |
233 | #define AR6004_HW_1_3_TESTSCRIPT_FILE "nullTestFlow.bin" | ||
234 | #define AR6004_HW_1_3_BOARD_DATA_FILE AR6004_HW_1_3_FW_DIR "/bdata.bin" | ||
235 | #define AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE AR6004_HW_1_3_FW_DIR "/bdata.bin" | ||
236 | |||
237 | /* AR6004 3.0 definitions */ | ||
238 | #define AR6004_HW_3_0_VERSION 0x31C809F8 | ||
239 | #define AR6004_HW_3_0_FW_DIR "ath6k/AR6004/hw3.0" | ||
240 | #define AR6004_HW_3_0_FIRMWARE_FILE "fw.ram.bin" | ||
241 | #define AR6004_HW_3_0_TCMD_FIRMWARE_FILE "utf.bin" | ||
242 | #define AR6004_HW_3_0_UTF_FIRMWARE_FILE "utf.bin" | ||
243 | #define AR6004_HW_3_0_TESTSCRIPT_FILE "nullTestFlow.bin" | ||
244 | #define AR6004_HW_3_0_BOARD_DATA_FILE AR6004_HW_3_0_FW_DIR "/bdata.bin" | ||
245 | #define AR6004_HW_3_0_DEFAULT_BOARD_DATA_FILE AR6004_HW_3_0_FW_DIR "/bdata.bin" | ||
220 | 246 | ||
221 | /* Per STA data, used in AP mode */ | 247 | /* Per STA data, used in AP mode */ |
222 | #define STA_PS_AWAKE BIT(0) | 248 | #define STA_PS_AWAKE BIT(0) |
diff --git a/drivers/net/wireless/ath/ath6kl/htc_pipe.c b/drivers/net/wireless/ath/ath6kl/htc_pipe.c index 756fe52a12c8..ca1a18c86c0d 100644 --- a/drivers/net/wireless/ath/ath6kl/htc_pipe.c +++ b/drivers/net/wireless/ath/ath6kl/htc_pipe.c | |||
@@ -1170,8 +1170,12 @@ static int htc_wait_recv_ctrl_message(struct htc_target *target) | |||
1170 | static void htc_rxctrl_complete(struct htc_target *context, | 1170 | static void htc_rxctrl_complete(struct htc_target *context, |
1171 | struct htc_packet *packet) | 1171 | struct htc_packet *packet) |
1172 | { | 1172 | { |
1173 | /* TODO, can't really receive HTC control messages yet.... */ | 1173 | struct sk_buff *skb = packet->skb; |
1174 | ath6kl_dbg(ATH6KL_DBG_HTC, "%s: invalid call function\n", __func__); | 1174 | |
1175 | if (packet->endpoint == ENDPOINT_0 && | ||
1176 | packet->status == -ECANCELED && | ||
1177 | skb != NULL) | ||
1178 | dev_kfree_skb(skb); | ||
1175 | } | 1179 | } |
1176 | 1180 | ||
1177 | /* htc pipe initialization */ | 1181 | /* htc pipe initialization */ |
@@ -1678,7 +1682,29 @@ static void ath6kl_htc_pipe_activity_changed(struct htc_target *target, | |||
1678 | 1682 | ||
1679 | static void ath6kl_htc_pipe_flush_rx_buf(struct htc_target *target) | 1683 | static void ath6kl_htc_pipe_flush_rx_buf(struct htc_target *target) |
1680 | { | 1684 | { |
1681 | /* TODO */ | 1685 | struct htc_endpoint *endpoint; |
1686 | struct htc_packet *packet, *tmp_pkt; | ||
1687 | int i; | ||
1688 | |||
1689 | for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) { | ||
1690 | endpoint = &target->endpoint[i]; | ||
1691 | |||
1692 | spin_lock_bh(&target->rx_lock); | ||
1693 | |||
1694 | list_for_each_entry_safe(packet, tmp_pkt, | ||
1695 | &endpoint->rx_bufq, list) { | ||
1696 | list_del(&packet->list); | ||
1697 | spin_unlock_bh(&target->rx_lock); | ||
1698 | ath6kl_dbg(ATH6KL_DBG_HTC, | ||
1699 | "htc rx flush pkt 0x%p len %d ep %d\n", | ||
1700 | packet, packet->buf_len, | ||
1701 | packet->endpoint); | ||
1702 | dev_kfree_skb(packet->pkt_cntxt); | ||
1703 | spin_lock_bh(&target->rx_lock); | ||
1704 | } | ||
1705 | |||
1706 | spin_unlock_bh(&target->rx_lock); | ||
1707 | } | ||
1682 | } | 1708 | } |
1683 | 1709 | ||
1684 | static int ath6kl_htc_pipe_credit_setup(struct htc_target *target, | 1710 | static int ath6kl_htc_pipe_credit_setup(struct htc_target *target, |
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 8ee7097f0b25..fffd52355123 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c | |||
@@ -93,8 +93,7 @@ static const struct ath6kl_hw hw_list[] = { | |||
93 | .board_addr = 0x433900, | 93 | .board_addr = 0x433900, |
94 | .refclk_hz = 26000000, | 94 | .refclk_hz = 26000000, |
95 | .uarttx_pin = 11, | 95 | .uarttx_pin = 11, |
96 | .flags = ATH6KL_HW_64BIT_RATES | | 96 | .flags = 0, |
97 | ATH6KL_HW_AP_INACTIVITY_MINS, | ||
98 | 97 | ||
99 | .fw = { | 98 | .fw = { |
100 | .dir = AR6004_HW_1_0_FW_DIR, | 99 | .dir = AR6004_HW_1_0_FW_DIR, |
@@ -114,8 +113,7 @@ static const struct ath6kl_hw hw_list[] = { | |||
114 | .board_addr = 0x43d400, | 113 | .board_addr = 0x43d400, |
115 | .refclk_hz = 40000000, | 114 | .refclk_hz = 40000000, |
116 | .uarttx_pin = 11, | 115 | .uarttx_pin = 11, |
117 | .flags = ATH6KL_HW_64BIT_RATES | | 116 | .flags = 0, |
118 | ATH6KL_HW_AP_INACTIVITY_MINS, | ||
119 | .fw = { | 117 | .fw = { |
120 | .dir = AR6004_HW_1_1_FW_DIR, | 118 | .dir = AR6004_HW_1_1_FW_DIR, |
121 | .fw = AR6004_HW_1_1_FIRMWARE_FILE, | 119 | .fw = AR6004_HW_1_1_FIRMWARE_FILE, |
@@ -134,8 +132,7 @@ static const struct ath6kl_hw hw_list[] = { | |||
134 | .board_addr = 0x435c00, | 132 | .board_addr = 0x435c00, |
135 | .refclk_hz = 40000000, | 133 | .refclk_hz = 40000000, |
136 | .uarttx_pin = 11, | 134 | .uarttx_pin = 11, |
137 | .flags = ATH6KL_HW_64BIT_RATES | | 135 | .flags = 0, |
138 | ATH6KL_HW_AP_INACTIVITY_MINS, | ||
139 | 136 | ||
140 | .fw = { | 137 | .fw = { |
141 | .dir = AR6004_HW_1_2_FW_DIR, | 138 | .dir = AR6004_HW_1_2_FW_DIR, |
@@ -152,20 +149,43 @@ static const struct ath6kl_hw hw_list[] = { | |||
152 | .board_ext_data_addr = 0x437000, | 149 | .board_ext_data_addr = 0x437000, |
153 | .reserved_ram_size = 7168, | 150 | .reserved_ram_size = 7168, |
154 | .board_addr = 0x436400, | 151 | .board_addr = 0x436400, |
155 | .refclk_hz = 40000000, | 152 | .refclk_hz = 0, |
156 | .uarttx_pin = 11, | 153 | .uarttx_pin = 11, |
157 | .flags = ATH6KL_HW_64BIT_RATES | | 154 | .flags = 0, |
158 | ATH6KL_HW_AP_INACTIVITY_MINS | | ||
159 | ATH6KL_HW_MAP_LP_ENDPOINT, | ||
160 | 155 | ||
161 | .fw = { | 156 | .fw = { |
162 | .dir = AR6004_HW_1_3_FW_DIR, | 157 | .dir = AR6004_HW_1_3_FW_DIR, |
163 | .fw = AR6004_HW_1_3_FIRMWARE_FILE, | 158 | .fw = AR6004_HW_1_3_FIRMWARE_FILE, |
159 | .tcmd = AR6004_HW_1_3_TCMD_FIRMWARE_FILE, | ||
160 | .utf = AR6004_HW_1_3_UTF_FIRMWARE_FILE, | ||
161 | .testscript = AR6004_HW_1_3_TESTSCRIPT_FILE, | ||
164 | }, | 162 | }, |
165 | 163 | ||
166 | .fw_board = AR6004_HW_1_3_BOARD_DATA_FILE, | 164 | .fw_board = AR6004_HW_1_3_BOARD_DATA_FILE, |
167 | .fw_default_board = AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE, | 165 | .fw_default_board = AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE, |
168 | }, | 166 | }, |
167 | { | ||
168 | .id = AR6004_HW_3_0_VERSION, | ||
169 | .name = "ar6004 hw 3.0", | ||
170 | .dataset_patch_addr = 0, | ||
171 | .app_load_addr = 0x1234, | ||
172 | .board_ext_data_addr = 0, | ||
173 | .reserved_ram_size = 7168, | ||
174 | .board_addr = 0x436400, | ||
175 | .testscript_addr = 0, | ||
176 | .flags = 0, | ||
177 | |||
178 | .fw = { | ||
179 | .dir = AR6004_HW_3_0_FW_DIR, | ||
180 | .fw = AR6004_HW_3_0_FIRMWARE_FILE, | ||
181 | .tcmd = AR6004_HW_3_0_TCMD_FIRMWARE_FILE, | ||
182 | .utf = AR6004_HW_3_0_UTF_FIRMWARE_FILE, | ||
183 | .testscript = AR6004_HW_3_0_TESTSCRIPT_FILE, | ||
184 | }, | ||
185 | |||
186 | .fw_board = AR6004_HW_3_0_BOARD_DATA_FILE, | ||
187 | .fw_default_board = AR6004_HW_3_0_DEFAULT_BOARD_DATA_FILE, | ||
188 | }, | ||
169 | }; | 189 | }; |
170 | 190 | ||
171 | /* | 191 | /* |
@@ -601,7 +621,9 @@ int ath6kl_configure_target(struct ath6kl *ar) | |||
601 | * but possible in theory. | 621 | * but possible in theory. |
602 | */ | 622 | */ |
603 | 623 | ||
604 | if (ar->target_type == TARGET_TYPE_AR6003) { | 624 | if ((ar->target_type == TARGET_TYPE_AR6003) || |
625 | (ar->version.target_ver == AR6004_HW_1_3_VERSION) || | ||
626 | (ar->version.target_ver == AR6004_HW_3_0_VERSION)) { | ||
605 | param = ar->hw.board_ext_data_addr; | 627 | param = ar->hw.board_ext_data_addr; |
606 | ram_reserved_size = ar->hw.reserved_ram_size; | 628 | ram_reserved_size = ar->hw.reserved_ram_size; |
607 | 629 | ||
@@ -629,9 +651,12 @@ int ath6kl_configure_target(struct ath6kl *ar) | |||
629 | return status; | 651 | return status; |
630 | 652 | ||
631 | /* Configure target refclk_hz */ | 653 | /* Configure target refclk_hz */ |
632 | status = ath6kl_bmi_write_hi32(ar, hi_refclk_hz, ar->hw.refclk_hz); | 654 | if (ar->hw.refclk_hz != 0) { |
633 | if (status) | 655 | status = ath6kl_bmi_write_hi32(ar, hi_refclk_hz, |
634 | return status; | 656 | ar->hw.refclk_hz); |
657 | if (status) | ||
658 | return status; | ||
659 | } | ||
635 | 660 | ||
636 | return 0; | 661 | return 0; |
637 | } | 662 | } |
@@ -1112,6 +1137,12 @@ int ath6kl_init_fetch_firmwares(struct ath6kl *ar) | |||
1112 | if (ret) | 1137 | if (ret) |
1113 | return ret; | 1138 | return ret; |
1114 | 1139 | ||
1140 | ret = ath6kl_fetch_fw_apin(ar, ATH6KL_FW_API5_FILE); | ||
1141 | if (ret == 0) { | ||
1142 | ar->fw_api = 5; | ||
1143 | goto out; | ||
1144 | } | ||
1145 | |||
1115 | ret = ath6kl_fetch_fw_apin(ar, ATH6KL_FW_API4_FILE); | 1146 | ret = ath6kl_fetch_fw_apin(ar, ATH6KL_FW_API4_FILE); |
1116 | if (ret == 0) { | 1147 | if (ret == 0) { |
1117 | ar->fw_api = 4; | 1148 | ar->fw_api = 4; |
@@ -1161,11 +1192,19 @@ static int ath6kl_upload_board_file(struct ath6kl *ar) | |||
1161 | ath6kl_bmi_write_hi32(ar, hi_board_data, | 1192 | ath6kl_bmi_write_hi32(ar, hi_board_data, |
1162 | board_address); | 1193 | board_address); |
1163 | } else { | 1194 | } else { |
1164 | ath6kl_bmi_read_hi32(ar, hi_board_data, &board_address); | 1195 | ret = ath6kl_bmi_read_hi32(ar, hi_board_data, &board_address); |
1196 | if (ret) { | ||
1197 | ath6kl_err("Failed to get board file target address.\n"); | ||
1198 | return ret; | ||
1199 | } | ||
1165 | } | 1200 | } |
1166 | 1201 | ||
1167 | /* determine where in target ram to write extended board data */ | 1202 | /* determine where in target ram to write extended board data */ |
1168 | ath6kl_bmi_read_hi32(ar, hi_board_ext_data, &board_ext_address); | 1203 | ret = ath6kl_bmi_read_hi32(ar, hi_board_ext_data, &board_ext_address); |
1204 | if (ret) { | ||
1205 | ath6kl_err("Failed to get extended board file target address.\n"); | ||
1206 | return ret; | ||
1207 | } | ||
1169 | 1208 | ||
1170 | if (ar->target_type == TARGET_TYPE_AR6003 && | 1209 | if (ar->target_type == TARGET_TYPE_AR6003 && |
1171 | board_ext_address == 0) { | 1210 | board_ext_address == 0) { |
@@ -1229,7 +1268,13 @@ static int ath6kl_upload_board_file(struct ath6kl *ar) | |||
1229 | } | 1268 | } |
1230 | 1269 | ||
1231 | /* record the fact that Board Data IS initialized */ | 1270 | /* record the fact that Board Data IS initialized */ |
1232 | ath6kl_bmi_write_hi32(ar, hi_board_data_initialized, 1); | 1271 | if ((ar->version.target_ver == AR6004_HW_1_3_VERSION) || |
1272 | (ar->version.target_ver == AR6004_HW_3_0_VERSION)) | ||
1273 | param = board_data_size; | ||
1274 | else | ||
1275 | param = 1; | ||
1276 | |||
1277 | ath6kl_bmi_write_hi32(ar, hi_board_data_initialized, param); | ||
1233 | 1278 | ||
1234 | return ret; | 1279 | return ret; |
1235 | } | 1280 | } |
@@ -1360,7 +1405,11 @@ static int ath6kl_upload_testscript(struct ath6kl *ar) | |||
1360 | } | 1405 | } |
1361 | 1406 | ||
1362 | ath6kl_bmi_write_hi32(ar, hi_ota_testscript, address); | 1407 | ath6kl_bmi_write_hi32(ar, hi_ota_testscript, address); |
1363 | ath6kl_bmi_write_hi32(ar, hi_end_ram_reserve_sz, 4096); | 1408 | |
1409 | if ((ar->version.target_ver != AR6004_HW_1_3_VERSION) && | ||
1410 | (ar->version.target_ver != AR6004_HW_3_0_VERSION)) | ||
1411 | ath6kl_bmi_write_hi32(ar, hi_end_ram_reserve_sz, 4096); | ||
1412 | |||
1364 | ath6kl_bmi_write_hi32(ar, hi_test_apps_related, 1); | 1413 | ath6kl_bmi_write_hi32(ar, hi_test_apps_related, 1); |
1365 | 1414 | ||
1366 | return 0; | 1415 | return 0; |
@@ -1566,6 +1615,11 @@ static const struct fw_capa_str_map { | |||
1566 | { ATH6KL_FW_CAPABILITY_REGDOMAIN, "regdomain" }, | 1615 | { ATH6KL_FW_CAPABILITY_REGDOMAIN, "regdomain" }, |
1567 | { ATH6KL_FW_CAPABILITY_SCHED_SCAN_V2, "sched-scan-v2" }, | 1616 | { ATH6KL_FW_CAPABILITY_SCHED_SCAN_V2, "sched-scan-v2" }, |
1568 | { ATH6KL_FW_CAPABILITY_HEART_BEAT_POLL, "hb-poll" }, | 1617 | { ATH6KL_FW_CAPABILITY_HEART_BEAT_POLL, "hb-poll" }, |
1618 | { ATH6KL_FW_CAPABILITY_64BIT_RATES, "64bit-rates" }, | ||
1619 | { ATH6KL_FW_CAPABILITY_AP_INACTIVITY_MINS, "ap-inactivity-mins" }, | ||
1620 | { ATH6KL_FW_CAPABILITY_MAP_LP_ENDPOINT, "map-lp-endpoint" }, | ||
1621 | { ATH6KL_FW_CAPABILITY_RATETABLE_MCS15, "ratetable-mcs15" }, | ||
1622 | { ATH6KL_FW_CAPABILITY_NO_IP_CHECKSUM, "no-ip-checksum" }, | ||
1569 | }; | 1623 | }; |
1570 | 1624 | ||
1571 | static const char *ath6kl_init_get_fw_capa_name(unsigned int id) | 1625 | static const char *ath6kl_init_get_fw_capa_name(unsigned int id) |
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index d56554674da4..21516bc65785 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c | |||
@@ -702,6 +702,7 @@ static void ath6kl_update_target_stats(struct ath6kl_vif *vif, u8 *ptr, u32 len) | |||
702 | struct ath6kl *ar = vif->ar; | 702 | struct ath6kl *ar = vif->ar; |
703 | struct target_stats *stats = &vif->target_stats; | 703 | struct target_stats *stats = &vif->target_stats; |
704 | struct tkip_ccmp_stats *ccmp_stats; | 704 | struct tkip_ccmp_stats *ccmp_stats; |
705 | s32 rate; | ||
705 | u8 ac; | 706 | u8 ac; |
706 | 707 | ||
707 | if (len < sizeof(*tgt_stats)) | 708 | if (len < sizeof(*tgt_stats)) |
@@ -731,8 +732,9 @@ static void ath6kl_update_target_stats(struct ath6kl_vif *vif, u8 *ptr, u32 len) | |||
731 | le32_to_cpu(tgt_stats->stats.tx.mult_retry_cnt); | 732 | le32_to_cpu(tgt_stats->stats.tx.mult_retry_cnt); |
732 | stats->tx_rts_fail_cnt += | 733 | stats->tx_rts_fail_cnt += |
733 | le32_to_cpu(tgt_stats->stats.tx.rts_fail_cnt); | 734 | le32_to_cpu(tgt_stats->stats.tx.rts_fail_cnt); |
734 | stats->tx_ucast_rate = | 735 | |
735 | ath6kl_wmi_get_rate(a_sle32_to_cpu(tgt_stats->stats.tx.ucast_rate)); | 736 | rate = a_sle32_to_cpu(tgt_stats->stats.tx.ucast_rate); |
737 | stats->tx_ucast_rate = ath6kl_wmi_get_rate(ar->wmi, rate); | ||
736 | 738 | ||
737 | stats->rx_pkt += le32_to_cpu(tgt_stats->stats.rx.pkt); | 739 | stats->rx_pkt += le32_to_cpu(tgt_stats->stats.rx.pkt); |
738 | stats->rx_byte += le32_to_cpu(tgt_stats->stats.rx.byte); | 740 | stats->rx_byte += le32_to_cpu(tgt_stats->stats.rx.byte); |
@@ -749,8 +751,9 @@ static void ath6kl_update_target_stats(struct ath6kl_vif *vif, u8 *ptr, u32 len) | |||
749 | le32_to_cpu(tgt_stats->stats.rx.key_cache_miss); | 751 | le32_to_cpu(tgt_stats->stats.rx.key_cache_miss); |
750 | stats->rx_decrypt_err += le32_to_cpu(tgt_stats->stats.rx.decrypt_err); | 752 | stats->rx_decrypt_err += le32_to_cpu(tgt_stats->stats.rx.decrypt_err); |
751 | stats->rx_dupl_frame += le32_to_cpu(tgt_stats->stats.rx.dupl_frame); | 753 | stats->rx_dupl_frame += le32_to_cpu(tgt_stats->stats.rx.dupl_frame); |
752 | stats->rx_ucast_rate = | 754 | |
753 | ath6kl_wmi_get_rate(a_sle32_to_cpu(tgt_stats->stats.rx.ucast_rate)); | 755 | rate = a_sle32_to_cpu(tgt_stats->stats.rx.ucast_rate); |
756 | stats->rx_ucast_rate = ath6kl_wmi_get_rate(ar->wmi, rate); | ||
754 | 757 | ||
755 | ccmp_stats = &tgt_stats->stats.tkip_ccmp_stats; | 758 | ccmp_stats = &tgt_stats->stats.tkip_ccmp_stats; |
756 | 759 | ||
@@ -1290,6 +1293,8 @@ static const struct net_device_ops ath6kl_netdev_ops = { | |||
1290 | 1293 | ||
1291 | void init_netdev(struct net_device *dev) | 1294 | void init_netdev(struct net_device *dev) |
1292 | { | 1295 | { |
1296 | struct ath6kl *ar = ath6kl_priv(dev); | ||
1297 | |||
1293 | dev->netdev_ops = &ath6kl_netdev_ops; | 1298 | dev->netdev_ops = &ath6kl_netdev_ops; |
1294 | dev->destructor = free_netdev; | 1299 | dev->destructor = free_netdev; |
1295 | dev->watchdog_timeo = ATH6KL_TX_TIMEOUT; | 1300 | dev->watchdog_timeo = ATH6KL_TX_TIMEOUT; |
@@ -1301,7 +1306,9 @@ void init_netdev(struct net_device *dev) | |||
1301 | WMI_MAX_TX_META_SZ + | 1306 | WMI_MAX_TX_META_SZ + |
1302 | ATH6KL_HTC_ALIGN_BYTES, 4); | 1307 | ATH6KL_HTC_ALIGN_BYTES, 4); |
1303 | 1308 | ||
1304 | dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM; | 1309 | if (!test_bit(ATH6KL_FW_CAPABILITY_NO_IP_CHECKSUM, |
1310 | ar->fw_capabilities)) | ||
1311 | dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM; | ||
1305 | 1312 | ||
1306 | return; | 1313 | return; |
1307 | } | 1314 | } |
diff --git a/drivers/net/wireless/ath/ath6kl/usb.c b/drivers/net/wireless/ath/ath6kl/usb.c index 3afc5a463d06..c44325856b81 100644 --- a/drivers/net/wireless/ath/ath6kl/usb.c +++ b/drivers/net/wireless/ath/ath6kl/usb.c | |||
@@ -802,7 +802,8 @@ static int ath6kl_usb_map_service_pipe(struct ath6kl *ar, u16 svc_id, | |||
802 | break; | 802 | break; |
803 | case WMI_DATA_VI_SVC: | 803 | case WMI_DATA_VI_SVC: |
804 | 804 | ||
805 | if (ar->hw.flags & ATH6KL_HW_MAP_LP_ENDPOINT) | 805 | if (test_bit(ATH6KL_FW_CAPABILITY_MAP_LP_ENDPOINT, |
806 | ar->fw_capabilities)) | ||
806 | *ul_pipe = ATH6KL_USB_PIPE_TX_DATA_LP; | 807 | *ul_pipe = ATH6KL_USB_PIPE_TX_DATA_LP; |
807 | else | 808 | else |
808 | *ul_pipe = ATH6KL_USB_PIPE_TX_DATA_MP; | 809 | *ul_pipe = ATH6KL_USB_PIPE_TX_DATA_MP; |
@@ -814,7 +815,8 @@ static int ath6kl_usb_map_service_pipe(struct ath6kl *ar, u16 svc_id, | |||
814 | break; | 815 | break; |
815 | case WMI_DATA_VO_SVC: | 816 | case WMI_DATA_VO_SVC: |
816 | 817 | ||
817 | if (ar->hw.flags & ATH6KL_HW_MAP_LP_ENDPOINT) | 818 | if (test_bit(ATH6KL_FW_CAPABILITY_MAP_LP_ENDPOINT, |
819 | ar->fw_capabilities)) | ||
818 | *ul_pipe = ATH6KL_USB_PIPE_TX_DATA_LP; | 820 | *ul_pipe = ATH6KL_USB_PIPE_TX_DATA_LP; |
819 | else | 821 | else |
820 | *ul_pipe = ATH6KL_USB_PIPE_TX_DATA_MP; | 822 | *ul_pipe = ATH6KL_USB_PIPE_TX_DATA_MP; |
@@ -1208,6 +1210,7 @@ static int ath6kl_usb_pm_reset_resume(struct usb_interface *intf) | |||
1208 | 1210 | ||
1209 | /* table of devices that work with this driver */ | 1211 | /* table of devices that work with this driver */ |
1210 | static struct usb_device_id ath6kl_usb_ids[] = { | 1212 | static struct usb_device_id ath6kl_usb_ids[] = { |
1213 | {USB_DEVICE(0x0cf3, 0x9375)}, | ||
1211 | {USB_DEVICE(0x0cf3, 0x9374)}, | 1214 | {USB_DEVICE(0x0cf3, 0x9374)}, |
1212 | { /* Terminating entry */ }, | 1215 | { /* Terminating entry */ }, |
1213 | }; | 1216 | }; |
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index 4d7f9e4712e9..94df345d08c2 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c | |||
@@ -59,6 +59,55 @@ static const s32 wmi_rate_tbl[][2] = { | |||
59 | {0, 0} | 59 | {0, 0} |
60 | }; | 60 | }; |
61 | 61 | ||
62 | static const s32 wmi_rate_tbl_mcs15[][2] = { | ||
63 | /* {W/O SGI, with SGI} */ | ||
64 | {1000, 1000}, | ||
65 | {2000, 2000}, | ||
66 | {5500, 5500}, | ||
67 | {11000, 11000}, | ||
68 | {6000, 6000}, | ||
69 | {9000, 9000}, | ||
70 | {12000, 12000}, | ||
71 | {18000, 18000}, | ||
72 | {24000, 24000}, | ||
73 | {36000, 36000}, | ||
74 | {48000, 48000}, | ||
75 | {54000, 54000}, | ||
76 | {6500, 7200}, /* HT 20, MCS 0 */ | ||
77 | {13000, 14400}, | ||
78 | {19500, 21700}, | ||
79 | {26000, 28900}, | ||
80 | {39000, 43300}, | ||
81 | {52000, 57800}, | ||
82 | {58500, 65000}, | ||
83 | {65000, 72200}, | ||
84 | {13000, 14400}, /* HT 20, MCS 8 */ | ||
85 | {26000, 28900}, | ||
86 | {39000, 43300}, | ||
87 | {52000, 57800}, | ||
88 | {78000, 86700}, | ||
89 | {104000, 115600}, | ||
90 | {117000, 130000}, | ||
91 | {130000, 144400}, /* HT 20, MCS 15 */ | ||
92 | {13500, 15000}, /*HT 40, MCS 0 */ | ||
93 | {27000, 30000}, | ||
94 | {40500, 45000}, | ||
95 | {54000, 60000}, | ||
96 | {81000, 90000}, | ||
97 | {108000, 120000}, | ||
98 | {121500, 135000}, | ||
99 | {135000, 150000}, | ||
100 | {27000, 30000}, /*HT 40, MCS 8 */ | ||
101 | {54000, 60000}, | ||
102 | {81000, 90000}, | ||
103 | {108000, 120000}, | ||
104 | {162000, 180000}, | ||
105 | {216000, 240000}, | ||
106 | {243000, 270000}, | ||
107 | {270000, 300000}, /*HT 40, MCS 15 */ | ||
108 | {0, 0} | ||
109 | }; | ||
110 | |||
62 | /* 802.1d to AC mapping. Refer pg 57 of WMM-test-plan-v1.2 */ | 111 | /* 802.1d to AC mapping. Refer pg 57 of WMM-test-plan-v1.2 */ |
63 | static const u8 up_to_ac[] = { | 112 | static const u8 up_to_ac[] = { |
64 | WMM_AC_BE, | 113 | WMM_AC_BE, |
@@ -2838,7 +2887,8 @@ int ath6kl_wmi_set_bitrate_mask(struct wmi *wmi, u8 if_idx, | |||
2838 | { | 2887 | { |
2839 | struct ath6kl *ar = wmi->parent_dev; | 2888 | struct ath6kl *ar = wmi->parent_dev; |
2840 | 2889 | ||
2841 | if (ar->hw.flags & ATH6KL_HW_64BIT_RATES) | 2890 | if (test_bit(ATH6KL_FW_CAPABILITY_64BIT_RATES, |
2891 | ar->fw_capabilities)) | ||
2842 | return ath6kl_set_bitrate_mask64(wmi, if_idx, mask); | 2892 | return ath6kl_set_bitrate_mask64(wmi, if_idx, mask); |
2843 | else | 2893 | else |
2844 | return ath6kl_set_bitrate_mask32(wmi, if_idx, mask); | 2894 | return ath6kl_set_bitrate_mask32(wmi, if_idx, mask); |
@@ -3279,9 +3329,11 @@ int ath6kl_wmi_set_regdomain_cmd(struct wmi *wmi, const char *alpha2) | |||
3279 | NO_SYNC_WMIFLAG); | 3329 | NO_SYNC_WMIFLAG); |
3280 | } | 3330 | } |
3281 | 3331 | ||
3282 | s32 ath6kl_wmi_get_rate(s8 rate_index) | 3332 | s32 ath6kl_wmi_get_rate(struct wmi *wmi, s8 rate_index) |
3283 | { | 3333 | { |
3334 | struct ath6kl *ar = wmi->parent_dev; | ||
3284 | u8 sgi = 0; | 3335 | u8 sgi = 0; |
3336 | s32 ret; | ||
3285 | 3337 | ||
3286 | if (rate_index == RATE_AUTO) | 3338 | if (rate_index == RATE_AUTO) |
3287 | return 0; | 3339 | return 0; |
@@ -3292,10 +3344,20 @@ s32 ath6kl_wmi_get_rate(s8 rate_index) | |||
3292 | sgi = 1; | 3344 | sgi = 1; |
3293 | } | 3345 | } |
3294 | 3346 | ||
3295 | if (WARN_ON(rate_index > RATE_MCS_7_40)) | 3347 | if (test_bit(ATH6KL_FW_CAPABILITY_RATETABLE_MCS15, |
3296 | rate_index = RATE_MCS_7_40; | 3348 | ar->fw_capabilities)) { |
3349 | if (WARN_ON(rate_index >= ARRAY_SIZE(wmi_rate_tbl_mcs15))) | ||
3350 | return 0; | ||
3351 | |||
3352 | ret = wmi_rate_tbl_mcs15[(u32) rate_index][sgi]; | ||
3353 | } else { | ||
3354 | if (WARN_ON(rate_index >= ARRAY_SIZE(wmi_rate_tbl))) | ||
3355 | return 0; | ||
3297 | 3356 | ||
3298 | return wmi_rate_tbl[(u32) rate_index][sgi]; | 3357 | ret = wmi_rate_tbl[(u32) rate_index][sgi]; |
3358 | } | ||
3359 | |||
3360 | return ret; | ||
3299 | } | 3361 | } |
3300 | 3362 | ||
3301 | static int ath6kl_wmi_get_pmkid_list_event_rx(struct wmi *wmi, u8 *datap, | 3363 | static int ath6kl_wmi_get_pmkid_list_event_rx(struct wmi *wmi, u8 *datap, |
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h index bb23fc00111d..19f88b4a24fb 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.h +++ b/drivers/net/wireless/ath/ath6kl/wmi.h | |||
@@ -2632,7 +2632,7 @@ int ath6kl_wmi_set_htcap_cmd(struct wmi *wmi, u8 if_idx, | |||
2632 | struct ath6kl_htcap *htcap); | 2632 | struct ath6kl_htcap *htcap); |
2633 | int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len); | 2633 | int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len); |
2634 | 2634 | ||
2635 | s32 ath6kl_wmi_get_rate(s8 rate_index); | 2635 | s32 ath6kl_wmi_get_rate(struct wmi *wmi, s8 rate_index); |
2636 | 2636 | ||
2637 | int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, u8 if_idx, | 2637 | int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, u8 if_idx, |
2638 | __be32 ips0, __be32 ips1); | 2638 | __be32 ips0, __be32 ips1); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c index 741b38ddcb37..59af9f9712da 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c | |||
@@ -281,7 +281,7 @@ ar9002_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) | |||
281 | 281 | ||
282 | ACCESS_ONCE(ads->ds_ctl0) = (i->pkt_len & AR_FrameLen) | 282 | ACCESS_ONCE(ads->ds_ctl0) = (i->pkt_len & AR_FrameLen) |
283 | | (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) | 283 | | (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) |
284 | | SM(i->txpower, AR_XmitPower) | 284 | | SM(i->txpower, AR_XmitPower0) |
285 | | (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) | 285 | | (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) |
286 | | (i->flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0) | 286 | | (i->flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0) |
287 | | (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0) | 287 | | (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0) |
@@ -306,6 +306,10 @@ ar9002_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) | |||
306 | | set11nRateFlags(i->rates, 2) | 306 | | set11nRateFlags(i->rates, 2) |
307 | | set11nRateFlags(i->rates, 3) | 307 | | set11nRateFlags(i->rates, 3) |
308 | | SM(i->rtscts_rate, AR_RTSCTSRate); | 308 | | SM(i->rtscts_rate, AR_RTSCTSRate); |
309 | |||
310 | ACCESS_ONCE(ads->ds_ctl9) = SM(i->txpower, AR_XmitPower1); | ||
311 | ACCESS_ONCE(ads->ds_ctl10) = SM(i->txpower, AR_XmitPower2); | ||
312 | ACCESS_ONCE(ads->ds_ctl11) = SM(i->txpower, AR_XmitPower3); | ||
309 | } | 313 | } |
310 | 314 | ||
311 | static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds, | 315 | static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds, |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index 729ffbf07343..71e38e85aa99 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c | |||
@@ -101,7 +101,7 @@ ar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) | |||
101 | 101 | ||
102 | ACCESS_ONCE(ads->ctl11) = (i->pkt_len & AR_FrameLen) | 102 | ACCESS_ONCE(ads->ctl11) = (i->pkt_len & AR_FrameLen) |
103 | | (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) | 103 | | (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) |
104 | | SM(i->txpower, AR_XmitPower) | 104 | | SM(i->txpower, AR_XmitPower0) |
105 | | (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) | 105 | | (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) |
106 | | (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0) | 106 | | (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0) |
107 | | (i->flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0) | 107 | | (i->flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0) |
@@ -151,6 +151,10 @@ ar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) | |||
151 | | SM(i->rtscts_rate, AR_RTSCTSRate); | 151 | | SM(i->rtscts_rate, AR_RTSCTSRate); |
152 | 152 | ||
153 | ACCESS_ONCE(ads->ctl19) = AR_Not_Sounding; | 153 | ACCESS_ONCE(ads->ctl19) = AR_Not_Sounding; |
154 | |||
155 | ACCESS_ONCE(ads->ctl20) = SM(i->txpower, AR_XmitPower1); | ||
156 | ACCESS_ONCE(ads->ctl21) = SM(i->txpower, AR_XmitPower2); | ||
157 | ACCESS_ONCE(ads->ctl22) = SM(i->txpower, AR_XmitPower3); | ||
154 | } | 158 | } |
155 | 159 | ||
156 | static u16 ar9003_calc_ptr_chksum(struct ar9003_txc *ads) | 160 | static u16 ar9003_calc_ptr_chksum(struct ar9003_txc *ads) |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 11b5e4dd6294..7fc13a8da675 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -182,7 +182,8 @@ struct ath_atx_ac { | |||
182 | 182 | ||
183 | struct ath_frame_info { | 183 | struct ath_frame_info { |
184 | struct ath_buf *bf; | 184 | struct ath_buf *bf; |
185 | int framelen; | 185 | u16 framelen; |
186 | s8 txq; | ||
186 | enum ath9k_key_type keytype; | 187 | enum ath9k_key_type keytype; |
187 | u8 keyix; | 188 | u8 keyix; |
188 | u8 rtscts_rate; | 189 | u8 rtscts_rate; |
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index ce073e995dfe..d2279365be6f 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -202,7 +202,7 @@ static ssize_t write_file_ani(struct file *file, | |||
202 | if (kstrtoul(buf, 0, &ani)) | 202 | if (kstrtoul(buf, 0, &ani)) |
203 | return -EINVAL; | 203 | return -EINVAL; |
204 | 204 | ||
205 | if (ani < 0 || ani > 1) | 205 | if (ani > 1) |
206 | return -EINVAL; | 206 | return -EINVAL; |
207 | 207 | ||
208 | common->disable_ani = !ani; | 208 | common->disable_ani = !ani; |
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index da7686757535..6c56cafa5ca4 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h | |||
@@ -346,8 +346,14 @@ struct ar5416_desc { | |||
346 | #define AR_FrameLen 0x00000fff | 346 | #define AR_FrameLen 0x00000fff |
347 | #define AR_VirtMoreFrag 0x00001000 | 347 | #define AR_VirtMoreFrag 0x00001000 |
348 | #define AR_TxCtlRsvd00 0x0000e000 | 348 | #define AR_TxCtlRsvd00 0x0000e000 |
349 | #define AR_XmitPower 0x003f0000 | 349 | #define AR_XmitPower0 0x003f0000 |
350 | #define AR_XmitPower_S 16 | 350 | #define AR_XmitPower0_S 16 |
351 | #define AR_XmitPower1 0x3f000000 | ||
352 | #define AR_XmitPower1_S 24 | ||
353 | #define AR_XmitPower2 0x3f000000 | ||
354 | #define AR_XmitPower2_S 24 | ||
355 | #define AR_XmitPower3 0x3f000000 | ||
356 | #define AR_XmitPower3_S 24 | ||
351 | #define AR_RTSEnable 0x00400000 | 357 | #define AR_RTSEnable 0x00400000 |
352 | #define AR_VEOL 0x00800000 | 358 | #define AR_VEOL 0x00800000 |
353 | #define AR_ClrDestMask 0x01000000 | 359 | #define AR_ClrDestMask 0x01000000 |
diff --git a/drivers/net/wireless/ath/ath9k/spectral.c b/drivers/net/wireless/ath/ath9k/spectral.c index 99f4de95c264..5fe29b9f8fa2 100644 --- a/drivers/net/wireless/ath/ath9k/spectral.c +++ b/drivers/net/wireless/ath/ath9k/spectral.c | |||
@@ -313,7 +313,7 @@ static ssize_t write_file_spectral_short_repeat(struct file *file, | |||
313 | if (kstrtoul(buf, 0, &val)) | 313 | if (kstrtoul(buf, 0, &val)) |
314 | return -EINVAL; | 314 | return -EINVAL; |
315 | 315 | ||
316 | if (val < 0 || val > 1) | 316 | if (val > 1) |
317 | return -EINVAL; | 317 | return -EINVAL; |
318 | 318 | ||
319 | sc->spec_config.short_repeat = val; | 319 | sc->spec_config.short_repeat = val; |
@@ -361,7 +361,7 @@ static ssize_t write_file_spectral_count(struct file *file, | |||
361 | if (kstrtoul(buf, 0, &val)) | 361 | if (kstrtoul(buf, 0, &val)) |
362 | return -EINVAL; | 362 | return -EINVAL; |
363 | 363 | ||
364 | if (val < 0 || val > 255) | 364 | if (val > 255) |
365 | return -EINVAL; | 365 | return -EINVAL; |
366 | 366 | ||
367 | sc->spec_config.count = val; | 367 | sc->spec_config.count = val; |
@@ -409,7 +409,7 @@ static ssize_t write_file_spectral_period(struct file *file, | |||
409 | if (kstrtoul(buf, 0, &val)) | 409 | if (kstrtoul(buf, 0, &val)) |
410 | return -EINVAL; | 410 | return -EINVAL; |
411 | 411 | ||
412 | if (val < 0 || val > 255) | 412 | if (val > 255) |
413 | return -EINVAL; | 413 | return -EINVAL; |
414 | 414 | ||
415 | sc->spec_config.period = val; | 415 | sc->spec_config.period = val; |
@@ -457,7 +457,7 @@ static ssize_t write_file_spectral_fft_period(struct file *file, | |||
457 | if (kstrtoul(buf, 0, &val)) | 457 | if (kstrtoul(buf, 0, &val)) |
458 | return -EINVAL; | 458 | return -EINVAL; |
459 | 459 | ||
460 | if (val < 0 || val > 15) | 460 | if (val > 15) |
461 | return -EINVAL; | 461 | return -EINVAL; |
462 | 462 | ||
463 | sc->spec_config.fft_period = val; | 463 | sc->spec_config.fft_period = val; |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index d4927c9a6bae..704fcbcbe20b 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -157,15 +157,14 @@ static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq, | |||
157 | struct sk_buff *skb) | 157 | struct sk_buff *skb) |
158 | { | 158 | { |
159 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 159 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
160 | int q, hw_queue; | 160 | struct ath_frame_info *fi = get_frame_info(skb); |
161 | 161 | int hw_queue; | |
162 | q = skb_get_queue_mapping(skb); | 162 | int q = fi->txq; |
163 | if (txq == sc->tx.uapsdq) | ||
164 | txq = sc->tx.txq_map[q]; | ||
165 | 163 | ||
166 | if (txq != sc->tx.txq_map[q]) | 164 | if (q < 0) |
167 | return; | 165 | return; |
168 | 166 | ||
167 | txq = sc->tx.txq_map[q]; | ||
169 | if (WARN_ON(--txq->pending_frames < 0)) | 168 | if (WARN_ON(--txq->pending_frames < 0)) |
170 | txq->pending_frames = 0; | 169 | txq->pending_frames = 0; |
171 | 170 | ||
@@ -898,6 +897,15 @@ ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq, | |||
898 | 897 | ||
899 | tx_info = IEEE80211_SKB_CB(skb); | 898 | tx_info = IEEE80211_SKB_CB(skb); |
900 | tx_info->flags &= ~IEEE80211_TX_CTL_CLEAR_PS_FILT; | 899 | tx_info->flags &= ~IEEE80211_TX_CTL_CLEAR_PS_FILT; |
900 | |||
901 | /* | ||
902 | * No aggregation session is running, but there may be frames | ||
903 | * from a previous session or a failed attempt in the queue. | ||
904 | * Send them out as normal data frames | ||
905 | */ | ||
906 | if (!tid->active) | ||
907 | tx_info->flags &= ~IEEE80211_TX_CTL_AMPDU; | ||
908 | |||
901 | if (!(tx_info->flags & IEEE80211_TX_CTL_AMPDU)) { | 909 | if (!(tx_info->flags & IEEE80211_TX_CTL_AMPDU)) { |
902 | bf->bf_state.bf_type = 0; | 910 | bf->bf_state.bf_type = 0; |
903 | return bf; | 911 | return bf; |
@@ -2036,6 +2044,7 @@ static void setup_frame_info(struct ieee80211_hw *hw, | |||
2036 | an = (struct ath_node *) sta->drv_priv; | 2044 | an = (struct ath_node *) sta->drv_priv; |
2037 | 2045 | ||
2038 | memset(fi, 0, sizeof(*fi)); | 2046 | memset(fi, 0, sizeof(*fi)); |
2047 | fi->txq = -1; | ||
2039 | if (hw_key) | 2048 | if (hw_key) |
2040 | fi->keyix = hw_key->hw_key_idx; | 2049 | fi->keyix = hw_key->hw_key_idx; |
2041 | else if (an && ieee80211_is_data(hdr->frame_control) && an->ps_key > 0) | 2050 | else if (an && ieee80211_is_data(hdr->frame_control) && an->ps_key > 0) |
@@ -2187,6 +2196,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2187 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 2196 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
2188 | struct ieee80211_sta *sta = txctl->sta; | 2197 | struct ieee80211_sta *sta = txctl->sta; |
2189 | struct ieee80211_vif *vif = info->control.vif; | 2198 | struct ieee80211_vif *vif = info->control.vif; |
2199 | struct ath_frame_info *fi = get_frame_info(skb); | ||
2190 | struct ath_vif *avp = NULL; | 2200 | struct ath_vif *avp = NULL; |
2191 | struct ath_softc *sc = hw->priv; | 2201 | struct ath_softc *sc = hw->priv; |
2192 | struct ath_txq *txq = txctl->txq; | 2202 | struct ath_txq *txq = txctl->txq; |
@@ -2216,11 +2226,13 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2216 | hw_queue = (info->hw_queue >= sc->hw->queues - 2) ? q : info->hw_queue; | 2226 | hw_queue = (info->hw_queue >= sc->hw->queues - 2) ? q : info->hw_queue; |
2217 | 2227 | ||
2218 | ath_txq_lock(sc, txq); | 2228 | ath_txq_lock(sc, txq); |
2219 | if (txq == sc->tx.txq_map[q] && | 2229 | if (txq == sc->tx.txq_map[q]) { |
2220 | ++txq->pending_frames > sc->tx.txq_max_pending[q] && | 2230 | fi->txq = q; |
2221 | !txq->stopped) { | 2231 | if (++txq->pending_frames > sc->tx.txq_max_pending[q] && |
2222 | ieee80211_stop_queue(sc->hw, hw_queue); | 2232 | !txq->stopped) { |
2223 | txq->stopped = true; | 2233 | ieee80211_stop_queue(sc->hw, hw_queue); |
2234 | txq->stopped = true; | ||
2235 | } | ||
2224 | } | 2236 | } |
2225 | 2237 | ||
2226 | queue = ieee80211_is_data_present(hdr->frame_control); | 2238 | queue = ieee80211_is_data_present(hdr->frame_control); |
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index a868c5eebe37..8f66186adb8c 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c | |||
@@ -448,8 +448,10 @@ static ssize_t wil_write_file_rxon(struct file *file, const char __user *buf, | |||
448 | char *kbuf = kmalloc(len + 1, GFP_KERNEL); | 448 | char *kbuf = kmalloc(len + 1, GFP_KERNEL); |
449 | if (!kbuf) | 449 | if (!kbuf) |
450 | return -ENOMEM; | 450 | return -ENOMEM; |
451 | if (copy_from_user(kbuf, buf, len)) | 451 | if (copy_from_user(kbuf, buf, len)) { |
452 | kfree(kbuf); | ||
452 | return -EIO; | 453 | return -EIO; |
454 | } | ||
453 | 455 | ||
454 | kbuf[len] = '\0'; | 456 | kbuf[len] = '\0'; |
455 | rc = kstrtol(kbuf, 0, &channel); | 457 | rc = kstrtol(kbuf, 0, &channel); |
@@ -963,6 +965,26 @@ static const struct file_operations fops_sta = { | |||
963 | }; | 965 | }; |
964 | 966 | ||
965 | /*----------------*/ | 967 | /*----------------*/ |
968 | static void wil6210_debugfs_init_blobs(struct wil6210_priv *wil, | ||
969 | struct dentry *dbg) | ||
970 | { | ||
971 | int i; | ||
972 | char name[32]; | ||
973 | |||
974 | for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) { | ||
975 | struct debugfs_blob_wrapper *blob = &wil->blobs[i]; | ||
976 | const struct fw_map *map = &fw_mapping[i]; | ||
977 | |||
978 | if (!map->name) | ||
979 | continue; | ||
980 | |||
981 | blob->data = (void * __force)wil->csr + HOSTADDR(map->host); | ||
982 | blob->size = map->to - map->from; | ||
983 | snprintf(name, sizeof(name), "blob_%s", map->name); | ||
984 | wil_debugfs_create_ioblob(name, S_IRUGO, dbg, blob); | ||
985 | } | ||
986 | } | ||
987 | |||
966 | int wil6210_debugfs_init(struct wil6210_priv *wil) | 988 | int wil6210_debugfs_init(struct wil6210_priv *wil) |
967 | { | 989 | { |
968 | struct dentry *dbg = wil->debug = debugfs_create_dir(WIL_NAME, | 990 | struct dentry *dbg = wil->debug = debugfs_create_dir(WIL_NAME, |
@@ -986,6 +1008,8 @@ int wil6210_debugfs_init(struct wil6210_priv *wil) | |||
986 | &wil->secure_pcp); | 1008 | &wil->secure_pcp); |
987 | wil_debugfs_create_ulong("status", S_IRUGO | S_IWUSR, dbg, | 1009 | wil_debugfs_create_ulong("status", S_IRUGO | S_IWUSR, dbg, |
988 | &wil->status); | 1010 | &wil->status); |
1011 | debugfs_create_u32("fw_version", S_IRUGO, dbg, &wil->fw_version); | ||
1012 | debugfs_create_x32("hw_version", S_IRUGO, dbg, &wil->hw_version); | ||
989 | 1013 | ||
990 | wil6210_debugfs_create_ISR(wil, "USER_ICR", dbg, | 1014 | wil6210_debugfs_create_ISR(wil, "USER_ICR", dbg, |
991 | HOSTADDR(RGF_USER_USER_ICR)); | 1015 | HOSTADDR(RGF_USER_USER_ICR)); |
@@ -998,6 +1022,9 @@ int wil6210_debugfs_init(struct wil6210_priv *wil) | |||
998 | wil6210_debugfs_create_pseudo_ISR(wil, dbg); | 1022 | wil6210_debugfs_create_pseudo_ISR(wil, dbg); |
999 | wil6210_debugfs_create_ITR_CNT(wil, dbg); | 1023 | wil6210_debugfs_create_ITR_CNT(wil, dbg); |
1000 | 1024 | ||
1025 | wil_debugfs_create_iomem_x32("RGF_USER_USAGE_1", S_IRUGO, dbg, | ||
1026 | wil->csr + | ||
1027 | HOSTADDR(RGF_USER_USAGE_1)); | ||
1001 | debugfs_create_u32("mem_addr", S_IRUGO | S_IWUSR, dbg, &mem_addr); | 1028 | debugfs_create_u32("mem_addr", S_IRUGO | S_IWUSR, dbg, &mem_addr); |
1002 | debugfs_create_file("mem_val", S_IRUGO, dbg, wil, &fops_memread); | 1029 | debugfs_create_file("mem_val", S_IRUGO, dbg, wil, &fops_memread); |
1003 | 1030 | ||
@@ -1010,34 +1037,7 @@ int wil6210_debugfs_init(struct wil6210_priv *wil) | |||
1010 | debugfs_create_file("link", S_IRUGO, dbg, wil, &fops_link); | 1037 | debugfs_create_file("link", S_IRUGO, dbg, wil, &fops_link); |
1011 | debugfs_create_file("info", S_IRUGO, dbg, wil, &fops_info); | 1038 | debugfs_create_file("info", S_IRUGO, dbg, wil, &fops_info); |
1012 | 1039 | ||
1013 | wil->rgf_blob.data = (void * __force)wil->csr + 0; | 1040 | wil6210_debugfs_init_blobs(wil, dbg); |
1014 | wil->rgf_blob.size = 0xa000; | ||
1015 | wil_debugfs_create_ioblob("blob_rgf", S_IRUGO, dbg, &wil->rgf_blob); | ||
1016 | |||
1017 | wil->fw_code_blob.data = (void * __force)wil->csr + 0x40000; | ||
1018 | wil->fw_code_blob.size = 0x40000; | ||
1019 | wil_debugfs_create_ioblob("blob_fw_code", S_IRUGO, dbg, | ||
1020 | &wil->fw_code_blob); | ||
1021 | |||
1022 | wil->fw_data_blob.data = (void * __force)wil->csr + 0x80000; | ||
1023 | wil->fw_data_blob.size = 0x8000; | ||
1024 | wil_debugfs_create_ioblob("blob_fw_data", S_IRUGO, dbg, | ||
1025 | &wil->fw_data_blob); | ||
1026 | |||
1027 | wil->fw_peri_blob.data = (void * __force)wil->csr + 0x88000; | ||
1028 | wil->fw_peri_blob.size = 0x18000; | ||
1029 | wil_debugfs_create_ioblob("blob_fw_peri", S_IRUGO, dbg, | ||
1030 | &wil->fw_peri_blob); | ||
1031 | |||
1032 | wil->uc_code_blob.data = (void * __force)wil->csr + 0xa0000; | ||
1033 | wil->uc_code_blob.size = 0x10000; | ||
1034 | wil_debugfs_create_ioblob("blob_uc_code", S_IRUGO, dbg, | ||
1035 | &wil->uc_code_blob); | ||
1036 | |||
1037 | wil->uc_data_blob.data = (void * __force)wil->csr + 0xb0000; | ||
1038 | wil->uc_data_blob.size = 0x4000; | ||
1039 | wil_debugfs_create_ioblob("blob_uc_data", S_IRUGO, dbg, | ||
1040 | &wil->uc_data_blob); | ||
1041 | 1041 | ||
1042 | return 0; | 1042 | return 0; |
1043 | } | 1043 | } |
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 53a689ed7c7d..3704d2a434f3 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c | |||
@@ -314,8 +314,9 @@ static void wil_target_reset(struct wil6210_priv *wil) | |||
314 | int delay = 0; | 314 | int delay = 0; |
315 | u32 hw_state; | 315 | u32 hw_state; |
316 | u32 rev_id; | 316 | u32 rev_id; |
317 | bool is_sparrow = (wil->board->board == WIL_BOARD_SPARROW); | ||
317 | 318 | ||
318 | wil_dbg_misc(wil, "Resetting...\n"); | 319 | wil_dbg_misc(wil, "Resetting \"%s\"...\n", wil->board->name); |
319 | 320 | ||
320 | /* register read */ | 321 | /* register read */ |
321 | #define R(a) ioread32(wil->csr + HOSTADDR(a)) | 322 | #define R(a) ioread32(wil->csr + HOSTADDR(a)) |
@@ -328,35 +329,59 @@ static void wil_target_reset(struct wil6210_priv *wil) | |||
328 | 329 | ||
329 | wil->hw_version = R(RGF_USER_FW_REV_ID); | 330 | wil->hw_version = R(RGF_USER_FW_REV_ID); |
330 | rev_id = wil->hw_version & 0xff; | 331 | rev_id = wil->hw_version & 0xff; |
332 | |||
333 | /* Clear MAC link up */ | ||
334 | S(RGF_HP_CTRL, BIT(15)); | ||
331 | /* hpal_perst_from_pad_src_n_mask */ | 335 | /* hpal_perst_from_pad_src_n_mask */ |
332 | S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT(6)); | 336 | S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT(6)); |
333 | /* car_perst_rst_src_n_mask */ | 337 | /* car_perst_rst_src_n_mask */ |
334 | S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT(7)); | 338 | S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT(7)); |
335 | wmb(); /* order is important here */ | 339 | wmb(); /* order is important here */ |
336 | 340 | ||
341 | if (is_sparrow) { | ||
342 | W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0, 0x3ff81f); | ||
343 | wmb(); /* order is important here */ | ||
344 | } | ||
345 | |||
337 | W(RGF_USER_MAC_CPU_0, BIT(1)); /* mac_cpu_man_rst */ | 346 | W(RGF_USER_MAC_CPU_0, BIT(1)); /* mac_cpu_man_rst */ |
338 | W(RGF_USER_USER_CPU_0, BIT(1)); /* user_cpu_man_rst */ | 347 | W(RGF_USER_USER_CPU_0, BIT(1)); /* user_cpu_man_rst */ |
339 | wmb(); /* order is important here */ | 348 | wmb(); /* order is important here */ |
340 | 349 | ||
341 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0xFE000000); | 350 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0xFE000000); |
342 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0x0000003F); | 351 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0x0000003F); |
343 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000170); | 352 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, is_sparrow ? 0x000000B0 : 0x00000170); |
344 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xFFE7FC00); | 353 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xFFE7FC00); |
345 | wmb(); /* order is important here */ | 354 | wmb(); /* order is important here */ |
346 | 355 | ||
356 | if (is_sparrow) { | ||
357 | W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0, 0x0); | ||
358 | wmb(); /* order is important here */ | ||
359 | } | ||
360 | |||
347 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0); | 361 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0); |
348 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0); | 362 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0); |
349 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0); | 363 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0); |
350 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0); | 364 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0); |
351 | wmb(); /* order is important here */ | 365 | wmb(); /* order is important here */ |
352 | 366 | ||
353 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000001); | 367 | if (is_sparrow) { |
354 | if (rev_id == 1) { | 368 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000003); |
355 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00000080); | 369 | /* reset A2 PCIE AHB */ |
356 | } else { | ||
357 | W(RGF_PCIE_LOS_COUNTER_CTL, BIT(6) | BIT(8)); | ||
358 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00008000); | 370 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00008000); |
371 | |||
372 | } else { | ||
373 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000001); | ||
374 | if (rev_id == 1) { | ||
375 | /* reset A1 BOTH PCIE AHB & PCIE RGF */ | ||
376 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00000080); | ||
377 | } else { | ||
378 | W(RGF_PCIE_LOS_COUNTER_CTL, BIT(6) | BIT(8)); | ||
379 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00008000); | ||
380 | } | ||
381 | |||
359 | } | 382 | } |
383 | |||
384 | /* TODO: check order here!!! Erez code is different */ | ||
360 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0); | 385 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0); |
361 | wmb(); /* order is important here */ | 386 | wmb(); /* order is important here */ |
362 | 387 | ||
@@ -371,7 +396,8 @@ static void wil_target_reset(struct wil6210_priv *wil) | |||
371 | } | 396 | } |
372 | } while (hw_state != HW_MACHINE_BOOT_DONE); | 397 | } while (hw_state != HW_MACHINE_BOOT_DONE); |
373 | 398 | ||
374 | if (rev_id == 2) | 399 | /* TODO: Erez check rev_id != 1 */ |
400 | if (!is_sparrow && (rev_id != 1)) | ||
375 | W(RGF_PCIE_LOS_COUNTER_CTL, BIT(8)); | 401 | W(RGF_PCIE_LOS_COUNTER_CTL, BIT(8)); |
376 | 402 | ||
377 | C(RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_RST_PWGD); | 403 | C(RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_RST_PWGD); |
diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c index 77b6272d93fb..d3fbfa28db62 100644 --- a/drivers/net/wireless/ath/wil6210/pcie_bus.c +++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c | |||
@@ -122,10 +122,12 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
122 | struct wil6210_priv *wil; | 122 | struct wil6210_priv *wil; |
123 | struct device *dev = &pdev->dev; | 123 | struct device *dev = &pdev->dev; |
124 | void __iomem *csr; | 124 | void __iomem *csr; |
125 | struct wil_board *board = (struct wil_board *)id->driver_data; | ||
125 | int rc; | 126 | int rc; |
126 | 127 | ||
127 | /* check HW */ | 128 | /* check HW */ |
128 | dev_info(&pdev->dev, WIL_NAME " device found [%04x:%04x] (rev %x)\n", | 129 | dev_info(&pdev->dev, WIL_NAME |
130 | " \"%s\" device found [%04x:%04x] (rev %x)\n", board->name, | ||
129 | (int)pdev->vendor, (int)pdev->device, (int)pdev->revision); | 131 | (int)pdev->vendor, (int)pdev->device, (int)pdev->revision); |
130 | 132 | ||
131 | if (pci_resource_len(pdev, 0) != WIL6210_MEM_SIZE) { | 133 | if (pci_resource_len(pdev, 0) != WIL6210_MEM_SIZE) { |
@@ -175,6 +177,7 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
175 | 177 | ||
176 | pci_set_drvdata(pdev, wil); | 178 | pci_set_drvdata(pdev, wil); |
177 | wil->pdev = pdev; | 179 | wil->pdev = pdev; |
180 | wil->board = board; | ||
178 | 181 | ||
179 | wil6210_clear_irq(wil); | 182 | wil6210_clear_irq(wil); |
180 | /* FW should raise IRQ when ready */ | 183 | /* FW should raise IRQ when ready */ |
@@ -225,8 +228,21 @@ static void wil_pcie_remove(struct pci_dev *pdev) | |||
225 | pci_disable_device(pdev); | 228 | pci_disable_device(pdev); |
226 | } | 229 | } |
227 | 230 | ||
228 | static DEFINE_PCI_DEVICE_TABLE(wil6210_pcie_ids) = { | 231 | static const struct wil_board wil_board_marlon = { |
229 | { PCI_DEVICE(0x1ae9, 0x0301) }, | 232 | .board = WIL_BOARD_MARLON, |
233 | .name = "marlon", | ||
234 | }; | ||
235 | |||
236 | static const struct wil_board wil_board_sparrow = { | ||
237 | .board = WIL_BOARD_SPARROW, | ||
238 | .name = "sparrow", | ||
239 | }; | ||
240 | |||
241 | static const struct pci_device_id wil6210_pcie_ids[] = { | ||
242 | { PCI_DEVICE(0x1ae9, 0x0301), | ||
243 | .driver_data = (kernel_ulong_t)&wil_board_marlon }, | ||
244 | { PCI_DEVICE(0x1ae9, 0x0310), | ||
245 | .driver_data = (kernel_ulong_t)&wil_board_sparrow }, | ||
230 | { /* end: all zeroes */ }, | 246 | { /* end: all zeroes */ }, |
231 | }; | 247 | }; |
232 | MODULE_DEVICE_TABLE(pci, wil6210_pcie_ids); | 248 | MODULE_DEVICE_TABLE(pci, wil6210_pcie_ids); |
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index af4b93e4beb5..d3467943d39d 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c | |||
@@ -1108,8 +1108,10 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid) | |||
1108 | while (vring->swtail != new_swtail) { | 1108 | while (vring->swtail != new_swtail) { |
1109 | struct vring_tx_desc dd, *d = ⅆ | 1109 | struct vring_tx_desc dd, *d = ⅆ |
1110 | u16 dmalen; | 1110 | u16 dmalen; |
1111 | struct wil_ctx *ctx = &vring->ctx[vring->swtail]; | 1111 | struct sk_buff *skb; |
1112 | struct sk_buff *skb = ctx->skb; | 1112 | |
1113 | ctx = &vring->ctx[vring->swtail]; | ||
1114 | skb = ctx->skb; | ||
1113 | _d = &vring->va[vring->swtail].tx; | 1115 | _d = &vring->va[vring->swtail].tx; |
1114 | 1116 | ||
1115 | *d = *_d; | 1117 | *d = *_d; |
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 424906635f05..67e9624f7111 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h | |||
@@ -24,6 +24,13 @@ | |||
24 | 24 | ||
25 | #define WIL_NAME "wil6210" | 25 | #define WIL_NAME "wil6210" |
26 | 26 | ||
27 | struct wil_board { | ||
28 | int board; | ||
29 | #define WIL_BOARD_MARLON (1) | ||
30 | #define WIL_BOARD_SPARROW (2) | ||
31 | const char * const name; | ||
32 | }; | ||
33 | |||
27 | /** | 34 | /** |
28 | * extract bits [@b0:@b1] (inclusive) from the value @x | 35 | * extract bits [@b0:@b1] (inclusive) from the value @x |
29 | * it should be @b0 <= @b1, or result is incorrect | 36 | * it should be @b0 <= @b1, or result is incorrect |
@@ -78,6 +85,7 @@ struct RGF_ICR { | |||
78 | } __packed; | 85 | } __packed; |
79 | 86 | ||
80 | /* registers - FW addresses */ | 87 | /* registers - FW addresses */ |
88 | #define RGF_USER_USAGE_1 (0x880004) | ||
81 | #define RGF_USER_HW_MACHINE_STATE (0x8801dc) | 89 | #define RGF_USER_HW_MACHINE_STATE (0x8801dc) |
82 | #define HW_MACHINE_BOOT_DONE (0x3fffffd) | 90 | #define HW_MACHINE_BOOT_DONE (0x3fffffd) |
83 | #define RGF_USER_USER_CPU_0 (0x8801e0) | 91 | #define RGF_USER_USER_CPU_0 (0x8801e0) |
@@ -93,6 +101,7 @@ struct RGF_ICR { | |||
93 | #define RGF_USER_CLKS_CTL_SW_RST_MASK_0 (0x880b14) | 101 | #define RGF_USER_CLKS_CTL_SW_RST_MASK_0 (0x880b14) |
94 | #define RGF_USER_USER_ICR (0x880b4c) /* struct RGF_ICR */ | 102 | #define RGF_USER_USER_ICR (0x880b4c) /* struct RGF_ICR */ |
95 | #define BIT_USER_USER_ICR_SW_INT_2 BIT(18) | 103 | #define BIT_USER_USER_ICR_SW_INT_2 BIT(18) |
104 | #define RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0 (0x880c18) | ||
96 | 105 | ||
97 | #define RGF_DMA_EP_TX_ICR (0x881bb4) /* struct RGF_ICR */ | 106 | #define RGF_DMA_EP_TX_ICR (0x881bb4) /* struct RGF_ICR */ |
98 | #define BIT_DMA_EP_TX_ICR_TX_DONE BIT(0) | 107 | #define BIT_DMA_EP_TX_ICR_TX_DONE BIT(0) |
@@ -121,6 +130,7 @@ struct RGF_ICR { | |||
121 | #define BIT_DMA_PSEUDO_CAUSE_TX BIT(1) | 130 | #define BIT_DMA_PSEUDO_CAUSE_TX BIT(1) |
122 | #define BIT_DMA_PSEUDO_CAUSE_MISC BIT(2) | 131 | #define BIT_DMA_PSEUDO_CAUSE_MISC BIT(2) |
123 | 132 | ||
133 | #define RGF_HP_CTRL (0x88265c) | ||
124 | #define RGF_PCIE_LOS_COUNTER_CTL (0x882dc4) | 134 | #define RGF_PCIE_LOS_COUNTER_CTL (0x882dc4) |
125 | 135 | ||
126 | /* popular locations */ | 136 | /* popular locations */ |
@@ -135,6 +145,14 @@ struct RGF_ICR { | |||
135 | #define ISR_MISC_FW_ERROR BIT_DMA_EP_MISC_ICR_FW_INT(3) | 145 | #define ISR_MISC_FW_ERROR BIT_DMA_EP_MISC_ICR_FW_INT(3) |
136 | 146 | ||
137 | /* Hardware definitions end */ | 147 | /* Hardware definitions end */ |
148 | struct fw_map { | ||
149 | u32 from; /* linker address - from, inclusive */ | ||
150 | u32 to; /* linker address - to, exclusive */ | ||
151 | u32 host; /* PCI/Host address - BAR0 + 0x880000 */ | ||
152 | const char *name; /* for debugfs */ | ||
153 | }; | ||
154 | /* array size should be in sync with actual definition in the wmi.c */ | ||
155 | extern const struct fw_map fw_mapping[7]; | ||
138 | 156 | ||
139 | /** | 157 | /** |
140 | * mk_cidxtid - construct @cidxtid field | 158 | * mk_cidxtid - construct @cidxtid field |
@@ -365,6 +383,7 @@ struct wil6210_priv { | |||
365 | ulong status; | 383 | ulong status; |
366 | u32 fw_version; | 384 | u32 fw_version; |
367 | u32 hw_version; | 385 | u32 hw_version; |
386 | struct wil_board *board; | ||
368 | u8 n_mids; /* number of additional MIDs as reported by FW */ | 387 | u8 n_mids; /* number of additional MIDs as reported by FW */ |
369 | int recovery_count; /* num of FW recovery attempts in a short time */ | 388 | int recovery_count; /* num of FW recovery attempts in a short time */ |
370 | unsigned long last_fw_recovery; /* jiffies of last fw recovery */ | 389 | unsigned long last_fw_recovery; /* jiffies of last fw recovery */ |
@@ -415,12 +434,7 @@ struct wil6210_priv { | |||
415 | atomic_t isr_count_rx, isr_count_tx; | 434 | atomic_t isr_count_rx, isr_count_tx; |
416 | /* debugfs */ | 435 | /* debugfs */ |
417 | struct dentry *debug; | 436 | struct dentry *debug; |
418 | struct debugfs_blob_wrapper fw_code_blob; | 437 | struct debugfs_blob_wrapper blobs[ARRAY_SIZE(fw_mapping)]; |
419 | struct debugfs_blob_wrapper fw_data_blob; | ||
420 | struct debugfs_blob_wrapper fw_peri_blob; | ||
421 | struct debugfs_blob_wrapper uc_code_blob; | ||
422 | struct debugfs_blob_wrapper uc_data_blob; | ||
423 | struct debugfs_blob_wrapper rgf_blob; | ||
424 | }; | 438 | }; |
425 | 439 | ||
426 | #define wil_to_wiphy(i) (i->wdev->wiphy) | 440 | #define wil_to_wiphy(i) (i->wdev->wiphy) |
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index a136dab560e2..1d1d0afdd2e1 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c | |||
@@ -65,18 +65,17 @@ | |||
65 | 65 | ||
66 | /** | 66 | /** |
67 | * @fw_mapping provides memory remapping table | 67 | * @fw_mapping provides memory remapping table |
68 | * | ||
69 | * array size should be in sync with the declaration in the wil6210.h | ||
68 | */ | 70 | */ |
69 | static const struct { | 71 | const struct fw_map fw_mapping[] = { |
70 | u32 from; /* linker address - from, inclusive */ | 72 | {0x000000, 0x040000, 0x8c0000, "fw_code"}, /* FW code RAM 256k */ |
71 | u32 to; /* linker address - to, exclusive */ | 73 | {0x800000, 0x808000, 0x900000, "fw_data"}, /* FW data RAM 32k */ |
72 | u32 host; /* PCI/Host address - BAR0 + 0x880000 */ | 74 | {0x840000, 0x860000, 0x908000, "fw_peri"}, /* periph. data RAM 128k */ |
73 | } fw_mapping[] = { | 75 | {0x880000, 0x88a000, 0x880000, "rgf"}, /* various RGF 40k */ |
74 | {0x000000, 0x040000, 0x8c0000}, /* FW code RAM 256k */ | 76 | {0x88a000, 0x88b000, 0x88a000, "AGC_tbl"}, /* AGC table 4k */ |
75 | {0x800000, 0x808000, 0x900000}, /* FW data RAM 32k */ | 77 | {0x88b000, 0x88c000, 0x88b000, "rgf_ext"}, /* Pcie_ext_rgf 4k */ |
76 | {0x840000, 0x860000, 0x908000}, /* peripheral data RAM 128k/96k used */ | 78 | {0x8c0000, 0x949000, 0x8c0000, "upper"}, /* upper area 548k */ |
77 | {0x880000, 0x88a000, 0x880000}, /* various RGF */ | ||
78 | {0x88b000, 0x88c000, 0x88b000}, /* Pcie_ext_rgf */ | ||
79 | {0x8c0000, 0x949000, 0x8c0000}, /* trivial mapping for upper area */ | ||
80 | /* | 79 | /* |
81 | * 920000..930000 ucode code RAM | 80 | * 920000..930000 ucode code RAM |
82 | * 930000..932000 ucode data RAM | 81 | * 930000..932000 ucode data RAM |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 15aaeb132a32..d7055febe119 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -210,6 +210,9 @@ static struct ieee80211_channel b43_2ghz_chantable[] = { | |||
210 | CHAN2G(13, 2472, 0), | 210 | CHAN2G(13, 2472, 0), |
211 | CHAN2G(14, 2484, 0), | 211 | CHAN2G(14, 2484, 0), |
212 | }; | 212 | }; |
213 | |||
214 | /* No support for the last 3 channels (12, 13, 14) */ | ||
215 | #define b43_2ghz_chantable_limited_size 11 | ||
213 | #undef CHAN2G | 216 | #undef CHAN2G |
214 | 217 | ||
215 | #define CHAN4G(_channel, _flags) { \ | 218 | #define CHAN4G(_channel, _flags) { \ |
@@ -287,6 +290,14 @@ static struct ieee80211_channel b43_5ghz_nphy_chantable[] = { | |||
287 | CHAN5G(182, 0), | 290 | CHAN5G(182, 0), |
288 | }; | 291 | }; |
289 | 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 | |||
290 | static struct ieee80211_channel b43_5ghz_aphy_chantable[] = { | 301 | static struct ieee80211_channel b43_5ghz_aphy_chantable[] = { |
291 | CHAN5G(34, 0), CHAN5G(36, 0), | 302 | CHAN5G(34, 0), CHAN5G(36, 0), |
292 | CHAN5G(38, 0), CHAN5G(40, 0), | 303 | CHAN5G(38, 0), CHAN5G(40, 0), |
@@ -319,6 +330,14 @@ static struct ieee80211_supported_band b43_band_5GHz_nphy = { | |||
319 | .n_bitrates = b43_a_ratetable_size, | 330 | .n_bitrates = b43_a_ratetable_size, |
320 | }; | 331 | }; |
321 | 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 | |||
322 | static struct ieee80211_supported_band b43_band_5GHz_aphy = { | 341 | static struct ieee80211_supported_band b43_band_5GHz_aphy = { |
323 | .band = IEEE80211_BAND_5GHZ, | 342 | .band = IEEE80211_BAND_5GHZ, |
324 | .channels = b43_5ghz_aphy_chantable, | 343 | .channels = b43_5ghz_aphy_chantable, |
@@ -335,6 +354,14 @@ static struct ieee80211_supported_band b43_band_2GHz = { | |||
335 | .n_bitrates = b43_g_ratetable_size, | 354 | .n_bitrates = b43_g_ratetable_size, |
336 | }; | 355 | }; |
337 | 356 | ||
357 | static struct ieee80211_supported_band b43_band_2ghz_limited = { | ||
358 | .band = IEEE80211_BAND_2GHZ, | ||
359 | .channels = b43_2ghz_chantable, | ||
360 | .n_channels = b43_2ghz_chantable_limited_size, | ||
361 | .bitrates = b43_g_ratetable, | ||
362 | .n_bitrates = b43_g_ratetable_size, | ||
363 | }; | ||
364 | |||
338 | static void b43_wireless_core_exit(struct b43_wldev *dev); | 365 | static void b43_wireless_core_exit(struct b43_wldev *dev); |
339 | static int b43_wireless_core_init(struct b43_wldev *dev); | 366 | static int b43_wireless_core_init(struct b43_wldev *dev); |
340 | static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev); | 367 | static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev); |
@@ -2953,6 +2980,45 @@ void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on) | |||
2953 | } | 2980 | } |
2954 | } | 2981 | } |
2955 | 2982 | ||
2983 | /* brcms_b_switch_macfreq */ | ||
2984 | void b43_mac_switch_freq(struct b43_wldev *dev, u8 spurmode) | ||
2985 | { | ||
2986 | u16 chip_id = dev->dev->chip_id; | ||
2987 | |||
2988 | if (chip_id == BCMA_CHIP_ID_BCM43217 || | ||
2989 | chip_id == BCMA_CHIP_ID_BCM43222 || | ||
2990 | chip_id == BCMA_CHIP_ID_BCM43224 || | ||
2991 | chip_id == BCMA_CHIP_ID_BCM43225 || | ||
2992 | chip_id == BCMA_CHIP_ID_BCM43227 || | ||
2993 | chip_id == BCMA_CHIP_ID_BCM43228) { | ||
2994 | switch (spurmode) { | ||
2995 | case 2: /* 126 Mhz */ | ||
2996 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x2082); | ||
2997 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8); | ||
2998 | break; | ||
2999 | case 1: /* 123 Mhz */ | ||
3000 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x5341); | ||
3001 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8); | ||
3002 | break; | ||
3003 | default: /* 120 Mhz */ | ||
3004 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x8889); | ||
3005 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8); | ||
3006 | break; | ||
3007 | } | ||
3008 | } else if (dev->phy.type == B43_PHYTYPE_LCN) { | ||
3009 | switch (spurmode) { | ||
3010 | case 1: /* 82 Mhz */ | ||
3011 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x7CE0); | ||
3012 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0xC); | ||
3013 | break; | ||
3014 | default: /* 80 Mhz */ | ||
3015 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0xCCCD); | ||
3016 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0xC); | ||
3017 | break; | ||
3018 | } | ||
3019 | } | ||
3020 | } | ||
3021 | |||
2956 | static void b43_adjust_opmode(struct b43_wldev *dev) | 3022 | static void b43_adjust_opmode(struct b43_wldev *dev) |
2957 | { | 3023 | { |
2958 | struct b43_wl *wl = dev->wl; | 3024 | struct b43_wl *wl = dev->wl; |
@@ -4335,8 +4401,9 @@ static int b43_phy_versioning(struct b43_wldev *dev) | |||
4335 | u8 phy_type; | 4401 | u8 phy_type; |
4336 | u8 phy_rev; | 4402 | u8 phy_rev; |
4337 | u16 radio_manuf; | 4403 | u16 radio_manuf; |
4338 | u16 radio_ver; | 4404 | u16 radio_id; |
4339 | u16 radio_rev; | 4405 | u16 radio_rev; |
4406 | u8 radio_ver; | ||
4340 | int unsupported = 0; | 4407 | int unsupported = 0; |
4341 | 4408 | ||
4342 | /* Get PHY versioning */ | 4409 | /* Get PHY versioning */ |
@@ -4360,7 +4427,7 @@ static int b43_phy_versioning(struct b43_wldev *dev) | |||
4360 | #endif | 4427 | #endif |
4361 | #ifdef CONFIG_B43_PHY_N | 4428 | #ifdef CONFIG_B43_PHY_N |
4362 | case B43_PHYTYPE_N: | 4429 | case B43_PHYTYPE_N: |
4363 | if (phy_rev > 9) | 4430 | if (phy_rev >= 19) |
4364 | unsupported = 1; | 4431 | unsupported = 1; |
4365 | break; | 4432 | break; |
4366 | #endif | 4433 | #endif |
@@ -4402,7 +4469,9 @@ static int b43_phy_versioning(struct b43_wldev *dev) | |||
4402 | radio_rev = b43_read16(dev, B43_MMIO_RADIO24_DATA); | 4469 | radio_rev = b43_read16(dev, B43_MMIO_RADIO24_DATA); |
4403 | 4470 | ||
4404 | b43_write16(dev, B43_MMIO_RADIO24_CONTROL, 1); | 4471 | b43_write16(dev, B43_MMIO_RADIO24_CONTROL, 1); |
4405 | 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? */ | ||
4406 | } else if (core_rev >= 24) { | 4475 | } else if (core_rev >= 24) { |
4407 | u16 radio24[3]; | 4476 | u16 radio24[3]; |
4408 | 4477 | ||
@@ -4411,12 +4480,10 @@ static int b43_phy_versioning(struct b43_wldev *dev) | |||
4411 | radio24[tmp] = b43_read16(dev, B43_MMIO_RADIO24_DATA); | 4480 | radio24[tmp] = b43_read16(dev, B43_MMIO_RADIO24_DATA); |
4412 | } | 4481 | } |
4413 | 4482 | ||
4414 | /* Broadcom uses "id" for our "ver" and has separated "ver" */ | ||
4415 | /* radio_ver = (radio24[0] & 0xF0) >> 4; */ | ||
4416 | |||
4417 | radio_manuf = 0x17F; | 4483 | radio_manuf = 0x17F; |
4418 | radio_ver = (radio24[2] << 8) | radio24[1]; | 4484 | radio_id = (radio24[2] << 8) | radio24[1]; |
4419 | radio_rev = (radio24[0] & 0xF); | 4485 | radio_rev = (radio24[0] & 0xF); |
4486 | radio_ver = (radio24[0] & 0xF0) >> 4; | ||
4420 | } else { | 4487 | } else { |
4421 | if (dev->dev->chip_id == 0x4317) { | 4488 | if (dev->dev->chip_id == 0x4317) { |
4422 | if (dev->dev->chip_rev == 0) | 4489 | if (dev->dev->chip_rev == 0) |
@@ -4435,15 +4502,16 @@ static int b43_phy_versioning(struct b43_wldev *dev) | |||
4435 | << 16; | 4502 | << 16; |
4436 | } | 4503 | } |
4437 | radio_manuf = (tmp & 0x00000FFF); | 4504 | radio_manuf = (tmp & 0x00000FFF); |
4438 | radio_ver = (tmp & 0x0FFFF000) >> 12; | 4505 | radio_id = (tmp & 0x0FFFF000) >> 12; |
4439 | radio_rev = (tmp & 0xF0000000) >> 28; | 4506 | radio_rev = (tmp & 0xF0000000) >> 28; |
4507 | radio_ver = 0; /* Probably not available on old hw */ | ||
4440 | } | 4508 | } |
4441 | 4509 | ||
4442 | if (radio_manuf != 0x17F /* Broadcom */) | 4510 | if (radio_manuf != 0x17F /* Broadcom */) |
4443 | unsupported = 1; | 4511 | unsupported = 1; |
4444 | switch (phy_type) { | 4512 | switch (phy_type) { |
4445 | case B43_PHYTYPE_A: | 4513 | case B43_PHYTYPE_A: |
4446 | if (radio_ver != 0x2060) | 4514 | if (radio_id != 0x2060) |
4447 | unsupported = 1; | 4515 | unsupported = 1; |
4448 | if (radio_rev != 1) | 4516 | if (radio_rev != 1) |
4449 | unsupported = 1; | 4517 | unsupported = 1; |
@@ -4451,43 +4519,49 @@ static int b43_phy_versioning(struct b43_wldev *dev) | |||
4451 | unsupported = 1; | 4519 | unsupported = 1; |
4452 | break; | 4520 | break; |
4453 | case B43_PHYTYPE_B: | 4521 | case B43_PHYTYPE_B: |
4454 | if ((radio_ver & 0xFFF0) != 0x2050) | 4522 | if ((radio_id & 0xFFF0) != 0x2050) |
4455 | unsupported = 1; | 4523 | unsupported = 1; |
4456 | break; | 4524 | break; |
4457 | case B43_PHYTYPE_G: | 4525 | case B43_PHYTYPE_G: |
4458 | if (radio_ver != 0x2050) | 4526 | if (radio_id != 0x2050) |
4459 | unsupported = 1; | 4527 | unsupported = 1; |
4460 | break; | 4528 | break; |
4461 | case B43_PHYTYPE_N: | 4529 | case B43_PHYTYPE_N: |
4462 | if (radio_ver != 0x2055 && radio_ver != 0x2056) | 4530 | if (radio_id != 0x2055 && radio_id != 0x2056 && |
4531 | radio_id != 0x2057) | ||
4532 | unsupported = 1; | ||
4533 | if (radio_id == 0x2057 && | ||
4534 | !(radio_rev == 9 || radio_rev == 14)) | ||
4463 | unsupported = 1; | 4535 | unsupported = 1; |
4464 | break; | 4536 | break; |
4465 | case B43_PHYTYPE_LP: | 4537 | case B43_PHYTYPE_LP: |
4466 | if (radio_ver != 0x2062 && radio_ver != 0x2063) | 4538 | if (radio_id != 0x2062 && radio_id != 0x2063) |
4467 | unsupported = 1; | 4539 | unsupported = 1; |
4468 | break; | 4540 | break; |
4469 | case B43_PHYTYPE_HT: | 4541 | case B43_PHYTYPE_HT: |
4470 | if (radio_ver != 0x2059) | 4542 | if (radio_id != 0x2059) |
4471 | unsupported = 1; | 4543 | unsupported = 1; |
4472 | break; | 4544 | break; |
4473 | case B43_PHYTYPE_LCN: | 4545 | case B43_PHYTYPE_LCN: |
4474 | if (radio_ver != 0x2064) | 4546 | if (radio_id != 0x2064) |
4475 | unsupported = 1; | 4547 | unsupported = 1; |
4476 | break; | 4548 | break; |
4477 | default: | 4549 | default: |
4478 | B43_WARN_ON(1); | 4550 | B43_WARN_ON(1); |
4479 | } | 4551 | } |
4480 | if (unsupported) { | 4552 | if (unsupported) { |
4481 | b43err(dev->wl, "FOUND UNSUPPORTED RADIO " | 4553 | b43err(dev->wl, |
4482 | "(Manuf 0x%X, Version 0x%X, Revision %u)\n", | 4554 | "FOUND UNSUPPORTED RADIO (Manuf 0x%X, ID 0x%X, Revision %u, Version %u)\n", |
4483 | radio_manuf, radio_ver, radio_rev); | 4555 | radio_manuf, radio_id, radio_rev, radio_ver); |
4484 | return -EOPNOTSUPP; | 4556 | return -EOPNOTSUPP; |
4485 | } | 4557 | } |
4486 | b43dbg(dev->wl, "Found Radio: Manuf 0x%X, Version 0x%X, Revision %u\n", | 4558 | b43info(dev->wl, |
4487 | 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); | ||
4488 | 4561 | ||
4562 | /* FIXME: b43 treats "id" as "ver" and ignores the real "ver" */ | ||
4489 | phy->radio_manuf = radio_manuf; | 4563 | phy->radio_manuf = radio_manuf; |
4490 | phy->radio_ver = radio_ver; | 4564 | phy->radio_ver = radio_id; |
4491 | phy->radio_rev = radio_rev; | 4565 | phy->radio_rev = radio_rev; |
4492 | 4566 | ||
4493 | phy->analog = analog_type; | 4567 | phy->analog = analog_type; |
@@ -5095,12 +5169,24 @@ static int b43_setup_bands(struct b43_wldev *dev, | |||
5095 | bool have_2ghz_phy, bool have_5ghz_phy) | 5169 | bool have_2ghz_phy, bool have_5ghz_phy) |
5096 | { | 5170 | { |
5097 | struct ieee80211_hw *hw = dev->wl->hw; | 5171 | struct ieee80211_hw *hw = dev->wl->hw; |
5172 | struct b43_phy *phy = &dev->phy; | ||
5173 | bool limited_2g; | ||
5174 | bool limited_5g; | ||
5175 | |||
5176 | /* We don't support all 2 GHz channels on some devices */ | ||
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; | ||
5098 | 5181 | ||
5099 | if (have_2ghz_phy) | 5182 | if (have_2ghz_phy) |
5100 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &b43_band_2GHz; | 5183 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = limited_2g ? |
5184 | &b43_band_2ghz_limited : &b43_band_2GHz; | ||
5101 | if (dev->phy.type == B43_PHYTYPE_N) { | 5185 | if (dev->phy.type == B43_PHYTYPE_N) { |
5102 | if (have_5ghz_phy) | 5186 | if (have_5ghz_phy) |
5103 | 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; | ||
5104 | } else { | 5190 | } else { |
5105 | if (have_5ghz_phy) | 5191 | if (have_5ghz_phy) |
5106 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &b43_band_5GHz_aphy; | 5192 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &b43_band_5GHz_aphy; |
@@ -5248,14 +5334,15 @@ static int b43_wireless_core_attach(struct b43_wldev *dev) | |||
5248 | b43_supported_bands(dev, &have_2ghz_phy, &have_5ghz_phy); | 5334 | b43_supported_bands(dev, &have_2ghz_phy, &have_5ghz_phy); |
5249 | 5335 | ||
5250 | /* We don't support 5 GHz on some PHYs yet */ | 5336 | /* We don't support 5 GHz on some PHYs yet */ |
5251 | switch (dev->phy.type) { | 5337 | if (have_5ghz_phy) { |
5252 | case B43_PHYTYPE_A: | 5338 | switch (dev->phy.type) { |
5253 | case B43_PHYTYPE_G: | 5339 | case B43_PHYTYPE_A: |
5254 | case B43_PHYTYPE_N: | 5340 | case B43_PHYTYPE_G: |
5255 | case B43_PHYTYPE_LP: | 5341 | case B43_PHYTYPE_LP: |
5256 | case B43_PHYTYPE_HT: | 5342 | case B43_PHYTYPE_HT: |
5257 | b43warn(wl, "5 GHz band is unsupported on this PHY\n"); | 5343 | b43warn(wl, "5 GHz band is unsupported on this PHY\n"); |
5258 | have_5ghz_phy = false; | 5344 | have_5ghz_phy = false; |
5345 | } | ||
5259 | } | 5346 | } |
5260 | 5347 | ||
5261 | if (!have_2ghz_phy && !have_5ghz_phy) { | 5348 | if (!have_2ghz_phy && !have_5ghz_phy) { |
diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h index f476fc337d64..9f22e4b4c132 100644 --- a/drivers/net/wireless/b43/main.h +++ b/drivers/net/wireless/b43/main.h | |||
@@ -99,6 +99,7 @@ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags); | |||
99 | void b43_mac_suspend(struct b43_wldev *dev); | 99 | void b43_mac_suspend(struct b43_wldev *dev); |
100 | void b43_mac_enable(struct b43_wldev *dev); | 100 | void b43_mac_enable(struct b43_wldev *dev); |
101 | void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on); | 101 | void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on); |
102 | void b43_mac_switch_freq(struct b43_wldev *dev, u8 spurmode); | ||
102 | 103 | ||
103 | 104 | ||
104 | struct b43_request_fw_context; | 105 | struct b43_request_fw_context; |
diff --git a/drivers/net/wireless/b43/phy_lcn.c b/drivers/net/wireless/b43/phy_lcn.c index 0bafa3b17035..e76bbdf3247e 100644 --- a/drivers/net/wireless/b43/phy_lcn.c +++ b/drivers/net/wireless/b43/phy_lcn.c | |||
@@ -54,39 +54,6 @@ enum lcn_sense_type { | |||
54 | B43_SENSE_VBAT, | 54 | B43_SENSE_VBAT, |
55 | }; | 55 | }; |
56 | 56 | ||
57 | /* In theory it's PHY common function, move if needed */ | ||
58 | /* brcms_b_switch_macfreq */ | ||
59 | static void b43_phy_switch_macfreq(struct b43_wldev *dev, u8 spurmode) | ||
60 | { | ||
61 | if (dev->dev->chip_id == 43224 || dev->dev->chip_id == 43225) { | ||
62 | switch (spurmode) { | ||
63 | case 2: /* 126 Mhz */ | ||
64 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x2082); | ||
65 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8); | ||
66 | break; | ||
67 | case 1: /* 123 Mhz */ | ||
68 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x5341); | ||
69 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8); | ||
70 | break; | ||
71 | default: /* 120 Mhz */ | ||
72 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x8889); | ||
73 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8); | ||
74 | break; | ||
75 | } | ||
76 | } else if (dev->phy.type == B43_PHYTYPE_LCN) { | ||
77 | switch (spurmode) { | ||
78 | case 1: /* 82 Mhz */ | ||
79 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x7CE0); | ||
80 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0xC); | ||
81 | break; | ||
82 | default: /* 80 Mhz */ | ||
83 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0xCCCD); | ||
84 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0xC); | ||
85 | break; | ||
86 | } | ||
87 | } | ||
88 | } | ||
89 | |||
90 | /************************************************** | 57 | /************************************************** |
91 | * Radio 2064. | 58 | * Radio 2064. |
92 | **************************************************/ | 59 | **************************************************/ |
@@ -609,7 +576,7 @@ static void b43_phy_lcn_txrx_spur_avoidance_mode(struct b43_wldev *dev, | |||
609 | b43_phy_write(dev, 0x93b, ((0 << 13) + 23)); | 576 | b43_phy_write(dev, 0x93b, ((0 << 13) + 23)); |
610 | b43_phy_write(dev, 0x93c, ((0 << 13) + 1989)); | 577 | b43_phy_write(dev, 0x93c, ((0 << 13) + 1989)); |
611 | } | 578 | } |
612 | b43_phy_switch_macfreq(dev, enable); | 579 | b43_mac_switch_freq(dev, enable); |
613 | } | 580 | } |
614 | 581 | ||
615 | /************************************************** | 582 | /************************************************** |
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 50ca6f87d5e8..d269fbb27b9e 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include "main.h" | 36 | #include "main.h" |
37 | 37 | ||
38 | struct nphy_txgains { | 38 | struct nphy_txgains { |
39 | u16 tx_lpf[2]; | ||
39 | u16 txgm[2]; | 40 | u16 txgm[2]; |
40 | u16 pga[2]; | 41 | u16 pga[2]; |
41 | u16 pad[2]; | 42 | u16 pad[2]; |
@@ -43,6 +44,7 @@ struct nphy_txgains { | |||
43 | }; | 44 | }; |
44 | 45 | ||
45 | struct nphy_iqcal_params { | 46 | struct nphy_iqcal_params { |
47 | u16 tx_lpf; | ||
46 | u16 txgm; | 48 | u16 txgm; |
47 | u16 pga; | 49 | u16 pga; |
48 | u16 pad; | 50 | u16 pad; |
@@ -69,6 +71,14 @@ enum b43_nphy_rf_sequence { | |||
69 | B43_RFSEQ_UPDATE_GAINU, | 71 | B43_RFSEQ_UPDATE_GAINU, |
70 | }; | 72 | }; |
71 | 73 | ||
74 | enum n_rf_ctl_over_cmd { | ||
75 | N_RF_CTL_OVER_CMD_RXRF_PU = 0, | ||
76 | N_RF_CTL_OVER_CMD_RX_PU = 1, | ||
77 | N_RF_CTL_OVER_CMD_TX_PU = 2, | ||
78 | N_RF_CTL_OVER_CMD_RX_GAIN = 3, | ||
79 | N_RF_CTL_OVER_CMD_TX_GAIN = 4, | ||
80 | }; | ||
81 | |||
72 | enum n_intc_override { | 82 | enum n_intc_override { |
73 | N_INTC_OVERRIDE_OFF = 0, | 83 | N_INTC_OVERRIDE_OFF = 0, |
74 | N_INTC_OVERRIDE_TRSW = 1, | 84 | N_INTC_OVERRIDE_TRSW = 1, |
@@ -140,11 +150,19 @@ ok: | |||
140 | b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode); | 150 | b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode); |
141 | } | 151 | } |
142 | 152 | ||
153 | static void b43_nphy_rf_ctl_override_rev19(struct b43_wldev *dev, u16 field, | ||
154 | u16 value, u8 core, bool off, | ||
155 | u8 override_id) | ||
156 | { | ||
157 | /* TODO */ | ||
158 | } | ||
159 | |||
143 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverrideRev7 */ | 160 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverrideRev7 */ |
144 | static void b43_nphy_rf_ctl_override_rev7(struct b43_wldev *dev, u16 field, | 161 | static void b43_nphy_rf_ctl_override_rev7(struct b43_wldev *dev, u16 field, |
145 | u16 value, u8 core, bool off, | 162 | u16 value, u8 core, bool off, |
146 | u8 override) | 163 | u8 override) |
147 | { | 164 | { |
165 | struct b43_phy *phy = &dev->phy; | ||
148 | const struct nphy_rf_control_override_rev7 *e; | 166 | const struct nphy_rf_control_override_rev7 *e; |
149 | u16 en_addrs[3][2] = { | 167 | u16 en_addrs[3][2] = { |
150 | { 0x0E7, 0x0EC }, { 0x342, 0x343 }, { 0x346, 0x347 } | 168 | { 0x0E7, 0x0EC }, { 0x342, 0x343 }, { 0x346, 0x347 } |
@@ -154,6 +172,11 @@ static void b43_nphy_rf_ctl_override_rev7(struct b43_wldev *dev, u16 field, | |||
154 | u16 val_addr; | 172 | u16 val_addr; |
155 | u8 i; | 173 | u8 i; |
156 | 174 | ||
175 | if (phy->rev >= 19 || phy->rev < 3) { | ||
176 | B43_WARN_ON(1); | ||
177 | return; | ||
178 | } | ||
179 | |||
157 | /* Remember: we can get NULL! */ | 180 | /* Remember: we can get NULL! */ |
158 | e = b43_nphy_get_rf_ctl_over_rev7(dev, field, override); | 181 | e = b43_nphy_get_rf_ctl_over_rev7(dev, field, override); |
159 | 182 | ||
@@ -181,6 +204,50 @@ static void b43_nphy_rf_ctl_override_rev7(struct b43_wldev *dev, u16 field, | |||
181 | } | 204 | } |
182 | } | 205 | } |
183 | 206 | ||
207 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverideOneToMany */ | ||
208 | static void b43_nphy_rf_ctl_override_one_to_many(struct b43_wldev *dev, | ||
209 | enum n_rf_ctl_over_cmd cmd, | ||
210 | u16 value, u8 core, bool off) | ||
211 | { | ||
212 | struct b43_phy *phy = &dev->phy; | ||
213 | u16 tmp; | ||
214 | |||
215 | B43_WARN_ON(phy->rev < 7); | ||
216 | |||
217 | switch (cmd) { | ||
218 | case N_RF_CTL_OVER_CMD_RXRF_PU: | ||
219 | b43_nphy_rf_ctl_override_rev7(dev, 0x20, value, core, off, 1); | ||
220 | b43_nphy_rf_ctl_override_rev7(dev, 0x10, value, core, off, 1); | ||
221 | b43_nphy_rf_ctl_override_rev7(dev, 0x08, value, core, off, 1); | ||
222 | break; | ||
223 | case N_RF_CTL_OVER_CMD_RX_PU: | ||
224 | b43_nphy_rf_ctl_override_rev7(dev, 0x4, 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); | ||
227 | b43_nphy_rf_ctl_override_rev7(dev, 0x2, value, core, off, 2); | ||
228 | b43_nphy_rf_ctl_override_rev7(dev, 0x0800, 0, core, off, 1); | ||
229 | break; | ||
230 | case N_RF_CTL_OVER_CMD_TX_PU: | ||
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); | ||
233 | b43_nphy_rf_ctl_override_rev7(dev, 0x1, value, core, off, 2); | ||
234 | b43_nphy_rf_ctl_override_rev7(dev, 0x0800, 1, core, off, 1); | ||
235 | break; | ||
236 | case N_RF_CTL_OVER_CMD_RX_GAIN: | ||
237 | tmp = value & 0xFF; | ||
238 | b43_nphy_rf_ctl_override_rev7(dev, 0x0800, tmp, core, off, 0); | ||
239 | tmp = value >> 8; | ||
240 | b43_nphy_rf_ctl_override_rev7(dev, 0x6000, tmp, core, off, 0); | ||
241 | break; | ||
242 | case N_RF_CTL_OVER_CMD_TX_GAIN: | ||
243 | tmp = value & 0x7FFF; | ||
244 | b43_nphy_rf_ctl_override_rev7(dev, 0x1000, tmp, core, off, 0); | ||
245 | tmp = value >> 14; | ||
246 | b43_nphy_rf_ctl_override_rev7(dev, 0x4000, tmp, core, off, 0); | ||
247 | break; | ||
248 | } | ||
249 | } | ||
250 | |||
184 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverride */ | 251 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverride */ |
185 | static void b43_nphy_rf_ctl_override(struct b43_wldev *dev, u16 field, | 252 | static void b43_nphy_rf_ctl_override(struct b43_wldev *dev, u16 field, |
186 | u16 value, u8 core, bool off) | 253 | u16 value, u8 core, bool off) |
@@ -264,6 +331,8 @@ static void b43_nphy_rf_ctl_intc_override_rev7(struct b43_wldev *dev, | |||
264 | u16 reg, tmp, tmp2, val; | 331 | u16 reg, tmp, tmp2, val; |
265 | int core; | 332 | int core; |
266 | 333 | ||
334 | /* TODO: What about rev19+? Revs 3+ and 7+ are a bit similar */ | ||
335 | |||
267 | for (core = 0; core < 2; core++) { | 336 | for (core = 0; core < 2; core++) { |
268 | if ((core_sel == 1 && core != 0) || | 337 | if ((core_sel == 1 && core != 0) || |
269 | (core_sel == 2 && core != 1)) | 338 | (core_sel == 2 && core != 1)) |
@@ -274,6 +343,7 @@ static void b43_nphy_rf_ctl_intc_override_rev7(struct b43_wldev *dev, | |||
274 | switch (intc_override) { | 343 | switch (intc_override) { |
275 | case N_INTC_OVERRIDE_OFF: | 344 | case N_INTC_OVERRIDE_OFF: |
276 | b43_phy_write(dev, reg, 0); | 345 | b43_phy_write(dev, reg, 0); |
346 | b43_phy_mask(dev, 0x2ff, ~0x2000); | ||
277 | b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); | 347 | b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); |
278 | break; | 348 | break; |
279 | case N_INTC_OVERRIDE_TRSW: | 349 | case N_INTC_OVERRIDE_TRSW: |
@@ -505,6 +575,14 @@ static void b43_nphy_stay_in_carrier_search(struct b43_wldev *dev, bool enable) | |||
505 | } | 575 | } |
506 | } | 576 | } |
507 | 577 | ||
578 | /* http://bcm-v4.sipsolutions.net/PHY/N/Read_Lpf_Bw_Ctl */ | ||
579 | static u16 b43_nphy_read_lpf_ctl(struct b43_wldev *dev, u16 offset) | ||
580 | { | ||
581 | if (!offset) | ||
582 | offset = b43_is_40mhz(dev) ? 0x159 : 0x154; | ||
583 | return b43_ntab_read(dev, B43_NTAB16(7, offset)) & 0x7; | ||
584 | } | ||
585 | |||
508 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/AdjustLnaGainTbl */ | 586 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/AdjustLnaGainTbl */ |
509 | static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev) | 587 | static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev) |
510 | { | 588 | { |
@@ -669,10 +747,63 @@ static void b43_radio_2057_setup(struct b43_wldev *dev, | |||
669 | b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, 0x8); | 747 | b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, 0x8); |
670 | } | 748 | } |
671 | break; | 749 | break; |
672 | /* TODO */ | 750 | case 9: /* e.g. PHY rev 16 */ |
751 | b43_radio_write(dev, R2057_LOGEN_PTAT_RESETS, 0x20); | ||
752 | b43_radio_write(dev, R2057_VCOBUF_IDACS, 0x18); | ||
753 | if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { | ||
754 | b43_radio_write(dev, R2057_LOGEN_PTAT_RESETS, 0x38); | ||
755 | b43_radio_write(dev, R2057_VCOBUF_IDACS, 0x0f); | ||
756 | |||
757 | if (b43_is_40mhz(dev)) { | ||
758 | /* TODO */ | ||
759 | } else { | ||
760 | b43_radio_write(dev, | ||
761 | R2057_PAD_BIAS_FILTER_BWS_CORE0, | ||
762 | 0x3c); | ||
763 | b43_radio_write(dev, | ||
764 | R2057_PAD_BIAS_FILTER_BWS_CORE1, | ||
765 | 0x3c); | ||
766 | } | ||
767 | } | ||
768 | break; | ||
769 | case 14: /* 2 GHz only */ | ||
770 | b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_R1, 0x1b); | ||
771 | b43_radio_write(dev, R2057_CP_KPD_IDAC, 0x3f); | ||
772 | b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C1, 0x1f); | ||
773 | b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, 0x1f); | ||
774 | break; | ||
673 | } | 775 | } |
674 | 776 | ||
675 | /* TODO */ | 777 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { |
778 | u16 txmix2g_tune_boost_pu = 0; | ||
779 | u16 pad2g_tune_pus = 0; | ||
780 | |||
781 | if (b43_nphy_ipa(dev)) { | ||
782 | switch (phy->radio_rev) { | ||
783 | case 9: | ||
784 | txmix2g_tune_boost_pu = 0x0041; | ||
785 | /* TODO */ | ||
786 | break; | ||
787 | case 14: | ||
788 | txmix2g_tune_boost_pu = 0x21; | ||
789 | pad2g_tune_pus = 0x23; | ||
790 | break; | ||
791 | } | ||
792 | } | ||
793 | |||
794 | if (txmix2g_tune_boost_pu) | ||
795 | b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE0, | ||
796 | txmix2g_tune_boost_pu); | ||
797 | if (pad2g_tune_pus) | ||
798 | b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE0, | ||
799 | pad2g_tune_pus); | ||
800 | if (txmix2g_tune_boost_pu) | ||
801 | b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE1, | ||
802 | txmix2g_tune_boost_pu); | ||
803 | if (pad2g_tune_pus) | ||
804 | b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE1, | ||
805 | pad2g_tune_pus); | ||
806 | } | ||
676 | 807 | ||
677 | usleep_range(50, 100); | 808 | usleep_range(50, 100); |
678 | 809 | ||
@@ -690,13 +821,62 @@ static void b43_radio_2057_setup(struct b43_wldev *dev, | |||
690 | static u8 b43_radio_2057_rcal(struct b43_wldev *dev) | 821 | static u8 b43_radio_2057_rcal(struct b43_wldev *dev) |
691 | { | 822 | { |
692 | struct b43_phy *phy = &dev->phy; | 823 | struct b43_phy *phy = &dev->phy; |
824 | u16 saved_regs_phy[12]; | ||
825 | u16 saved_regs_phy_rf[6]; | ||
826 | u16 saved_regs_radio[2] = { }; | ||
827 | static const u16 phy_to_store[] = { | ||
828 | B43_NPHY_RFCTL_RSSIO1, B43_NPHY_RFCTL_RSSIO2, | ||
829 | B43_NPHY_RFCTL_LUT_TRSW_LO1, B43_NPHY_RFCTL_LUT_TRSW_LO2, | ||
830 | B43_NPHY_RFCTL_RXG1, B43_NPHY_RFCTL_RXG2, | ||
831 | B43_NPHY_RFCTL_TXG1, B43_NPHY_RFCTL_TXG2, | ||
832 | B43_NPHY_REV7_RF_CTL_MISC_REG3, B43_NPHY_REV7_RF_CTL_MISC_REG4, | ||
833 | B43_NPHY_REV7_RF_CTL_MISC_REG5, B43_NPHY_REV7_RF_CTL_MISC_REG6, | ||
834 | }; | ||
835 | static const u16 phy_to_store_rf[] = { | ||
836 | B43_NPHY_REV3_RFCTL_OVER0, B43_NPHY_REV3_RFCTL_OVER1, | ||
837 | B43_NPHY_REV7_RF_CTL_OVER3, B43_NPHY_REV7_RF_CTL_OVER4, | ||
838 | B43_NPHY_REV7_RF_CTL_OVER5, B43_NPHY_REV7_RF_CTL_OVER6, | ||
839 | }; | ||
693 | u16 tmp; | 840 | u16 tmp; |
841 | int i; | ||
694 | 842 | ||
695 | if (phy->radio_rev == 5) { | 843 | /* Save */ |
696 | b43_phy_mask(dev, 0x342, ~0x2); | 844 | for (i = 0; i < ARRAY_SIZE(phy_to_store); i++) |
845 | saved_regs_phy[i] = b43_phy_read(dev, phy_to_store[i]); | ||
846 | for (i = 0; i < ARRAY_SIZE(phy_to_store_rf); i++) | ||
847 | saved_regs_phy_rf[i] = b43_phy_read(dev, phy_to_store_rf[i]); | ||
848 | |||
849 | /* Set */ | ||
850 | for (i = 0; i < ARRAY_SIZE(phy_to_store); i++) | ||
851 | b43_phy_write(dev, phy_to_store[i], 0); | ||
852 | b43_phy_write(dev, B43_NPHY_REV3_RFCTL_OVER0, 0x07ff); | ||
853 | b43_phy_write(dev, B43_NPHY_REV3_RFCTL_OVER1, 0x07ff); | ||
854 | b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER3, 0x07ff); | ||
855 | b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER4, 0x07ff); | ||
856 | b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER5, 0x007f); | ||
857 | b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER6, 0x007f); | ||
858 | |||
859 | switch (phy->radio_rev) { | ||
860 | case 5: | ||
861 | b43_phy_mask(dev, B43_NPHY_REV7_RF_CTL_OVER3, ~0x2); | ||
697 | udelay(10); | 862 | udelay(10); |
698 | b43_radio_set(dev, R2057_IQTEST_SEL_PU, 0x1); | 863 | b43_radio_set(dev, R2057_IQTEST_SEL_PU, 0x1); |
699 | b43_radio_maskset(dev, 0x1ca, ~0x2, 0x1); | 864 | b43_radio_maskset(dev, R2057v7_IQTEST_SEL_PU2, ~0x2, 0x1); |
865 | break; | ||
866 | case 9: | ||
867 | b43_phy_set(dev, B43_NPHY_REV7_RF_CTL_OVER3, 0x2); | ||
868 | b43_phy_set(dev, B43_NPHY_REV7_RF_CTL_MISC_REG3, 0x2); | ||
869 | saved_regs_radio[0] = b43_radio_read(dev, R2057_IQTEST_SEL_PU); | ||
870 | b43_radio_write(dev, R2057_IQTEST_SEL_PU, 0x11); | ||
871 | break; | ||
872 | case 14: | ||
873 | saved_regs_radio[0] = b43_radio_read(dev, R2057_IQTEST_SEL_PU); | ||
874 | saved_regs_radio[1] = b43_radio_read(dev, R2057v7_IQTEST_SEL_PU2); | ||
875 | b43_phy_set(dev, B43_NPHY_REV7_RF_CTL_MISC_REG3, 0x2); | ||
876 | b43_phy_set(dev, B43_NPHY_REV7_RF_CTL_OVER3, 0x2); | ||
877 | b43_radio_write(dev, R2057v7_IQTEST_SEL_PU2, 0x2); | ||
878 | b43_radio_write(dev, R2057_IQTEST_SEL_PU, 0x1); | ||
879 | break; | ||
700 | } | 880 | } |
701 | 881 | ||
702 | /* Enable */ | 882 | /* Enable */ |
@@ -720,14 +900,30 @@ static u8 b43_radio_2057_rcal(struct b43_wldev *dev) | |||
720 | /* Disable */ | 900 | /* Disable */ |
721 | b43_radio_mask(dev, R2057_RCAL_CONFIG, ~0x1); | 901 | b43_radio_mask(dev, R2057_RCAL_CONFIG, ~0x1); |
722 | 902 | ||
723 | if (phy->radio_rev == 5) { | 903 | /* Restore */ |
724 | b43_radio_mask(dev, R2057_IPA2G_CASCONV_CORE0, ~0x1); | 904 | for (i = 0; i < ARRAY_SIZE(phy_to_store_rf); i++) |
725 | b43_radio_mask(dev, 0x1ca, ~0x2); | 905 | b43_phy_write(dev, phy_to_store_rf[i], saved_regs_phy_rf[i]); |
726 | } | 906 | for (i = 0; i < ARRAY_SIZE(phy_to_store); i++) |
727 | if (phy->radio_rev <= 4 || phy->radio_rev == 6) { | 907 | b43_phy_write(dev, phy_to_store[i], saved_regs_phy[i]); |
908 | |||
909 | switch (phy->radio_rev) { | ||
910 | case 0 ... 4: | ||
911 | case 6: | ||
728 | b43_radio_maskset(dev, R2057_TEMPSENSE_CONFIG, ~0x3C, tmp); | 912 | b43_radio_maskset(dev, R2057_TEMPSENSE_CONFIG, ~0x3C, tmp); |
729 | b43_radio_maskset(dev, R2057_BANDGAP_RCAL_TRIM, ~0xF0, | 913 | b43_radio_maskset(dev, R2057_BANDGAP_RCAL_TRIM, ~0xF0, |
730 | tmp << 2); | 914 | tmp << 2); |
915 | break; | ||
916 | case 5: | ||
917 | b43_radio_mask(dev, R2057_IPA2G_CASCONV_CORE0, ~0x1); | ||
918 | b43_radio_mask(dev, R2057v7_IQTEST_SEL_PU2, ~0x2); | ||
919 | break; | ||
920 | case 9: | ||
921 | b43_radio_write(dev, R2057_IQTEST_SEL_PU, saved_regs_radio[0]); | ||
922 | break; | ||
923 | case 14: | ||
924 | b43_radio_write(dev, R2057_IQTEST_SEL_PU, saved_regs_radio[0]); | ||
925 | b43_radio_write(dev, R2057v7_IQTEST_SEL_PU2, saved_regs_radio[1]); | ||
926 | break; | ||
731 | } | 927 | } |
732 | 928 | ||
733 | return tmp & 0x3e; | 929 | return tmp & 0x3e; |
@@ -749,7 +945,7 @@ static u16 b43_radio_2057_rccal(struct b43_wldev *dev) | |||
749 | b43_radio_write(dev, R2057_RCCAL_TRC0, 0xC0); | 945 | b43_radio_write(dev, R2057_RCCAL_TRC0, 0xC0); |
750 | } else { | 946 | } else { |
751 | b43_radio_write(dev, R2057v7_RCCAL_MASTER, 0x61); | 947 | b43_radio_write(dev, R2057v7_RCCAL_MASTER, 0x61); |
752 | b43_radio_write(dev, R2057_RCCAL_TRC0, 0xE1); | 948 | b43_radio_write(dev, R2057_RCCAL_TRC0, 0xE9); |
753 | } | 949 | } |
754 | b43_radio_write(dev, R2057_RCCAL_X1, 0x6E); | 950 | b43_radio_write(dev, R2057_RCCAL_X1, 0x6E); |
755 | 951 | ||
@@ -829,6 +1025,9 @@ static void b43_radio_2057_init_post(struct b43_wldev *dev) | |||
829 | { | 1025 | { |
830 | b43_radio_set(dev, R2057_XTALPUOVR_PINCTRL, 0x1); | 1026 | b43_radio_set(dev, R2057_XTALPUOVR_PINCTRL, 0x1); |
831 | 1027 | ||
1028 | if (0) /* FIXME: Is this BCM43217 specific? */ | ||
1029 | b43_radio_set(dev, R2057_XTALPUOVR_PINCTRL, 0x2); | ||
1030 | |||
832 | b43_radio_set(dev, R2057_RFPLL_MISC_CAL_RESETN, 0x78); | 1031 | b43_radio_set(dev, R2057_RFPLL_MISC_CAL_RESETN, 0x78); |
833 | b43_radio_set(dev, R2057_XTAL_CONFIG2, 0x80); | 1032 | b43_radio_set(dev, R2057_XTAL_CONFIG2, 0x80); |
834 | mdelay(2); | 1033 | mdelay(2); |
@@ -1386,6 +1585,7 @@ static void b43_nphy_run_samples(struct b43_wldev *dev, u16 samps, u16 loops, | |||
1386 | u16 wait, bool iqmode, bool dac_test, | 1585 | u16 wait, bool iqmode, bool dac_test, |
1387 | bool modify_bbmult) | 1586 | bool modify_bbmult) |
1388 | { | 1587 | { |
1588 | struct b43_phy *phy = &dev->phy; | ||
1389 | struct b43_phy_n *nphy = dev->phy.n; | 1589 | struct b43_phy_n *nphy = dev->phy.n; |
1390 | int i; | 1590 | int i; |
1391 | u16 seq_mode; | 1591 | u16 seq_mode; |
@@ -1393,6 +1593,26 @@ static void b43_nphy_run_samples(struct b43_wldev *dev, u16 samps, u16 loops, | |||
1393 | 1593 | ||
1394 | b43_nphy_stay_in_carrier_search(dev, true); | 1594 | b43_nphy_stay_in_carrier_search(dev, true); |
1395 | 1595 | ||
1596 | if (phy->rev >= 7) { | ||
1597 | bool lpf_bw3, lpf_bw4; | ||
1598 | |||
1599 | lpf_bw3 = 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; | ||
1601 | |||
1602 | if (lpf_bw3 || lpf_bw4) { | ||
1603 | /* TODO */ | ||
1604 | } else { | ||
1605 | u16 value = b43_nphy_read_lpf_ctl(dev, 0); | ||
1606 | if (phy->rev >= 19) | ||
1607 | b43_nphy_rf_ctl_override_rev19(dev, 0x80, value, | ||
1608 | 0, false, 1); | ||
1609 | else | ||
1610 | b43_nphy_rf_ctl_override_rev7(dev, 0x80, value, | ||
1611 | 0, false, 1); | ||
1612 | nphy->lpf_bw_overrode_for_sample_play = true; | ||
1613 | } | ||
1614 | } | ||
1615 | |||
1396 | if ((nphy->bb_mult_save & 0x80000000) == 0) { | 1616 | if ((nphy->bb_mult_save & 0x80000000) == 0) { |
1397 | tmp = b43_ntab_read(dev, B43_NTAB16(15, 87)); | 1617 | tmp = b43_ntab_read(dev, B43_NTAB16(15, 87)); |
1398 | nphy->bb_mult_save = (tmp & 0xFFFF) | 0x80000000; | 1618 | nphy->bb_mult_save = (tmp & 0xFFFF) | 0x80000000; |
@@ -1520,6 +1740,12 @@ static void b43_nphy_scale_offset_rssi(struct b43_wldev *dev, u16 scale, | |||
1520 | } | 1740 | } |
1521 | } | 1741 | } |
1522 | 1742 | ||
1743 | static void b43_nphy_rssi_select_rev19(struct b43_wldev *dev, u8 code, | ||
1744 | enum n_rssi_type rssi_type) | ||
1745 | { | ||
1746 | /* TODO */ | ||
1747 | } | ||
1748 | |||
1523 | static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, | 1749 | static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, |
1524 | enum n_rssi_type rssi_type) | 1750 | enum n_rssi_type rssi_type) |
1525 | { | 1751 | { |
@@ -1589,13 +1815,15 @@ static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, | |||
1589 | enum ieee80211_band band = | 1815 | enum ieee80211_band band = |
1590 | b43_current_band(dev->wl); | 1816 | b43_current_band(dev->wl); |
1591 | 1817 | ||
1592 | if (b43_nphy_ipa(dev)) | 1818 | if (dev->phy.rev < 7) { |
1593 | val = (band == IEEE80211_BAND_5GHZ) ? 0xC : 0xE; | 1819 | if (b43_nphy_ipa(dev)) |
1594 | else | 1820 | val = (band == IEEE80211_BAND_5GHZ) ? 0xC : 0xE; |
1595 | val = 0x11; | 1821 | else |
1596 | reg = (i == 0) ? 0x2000 : 0x3000; | 1822 | val = 0x11; |
1597 | reg |= B2055_PADDRV; | 1823 | reg = (i == 0) ? B2056_TX0 : B2056_TX1; |
1598 | b43_radio_write(dev, reg, val); | 1824 | reg |= B2056_TX_TX_SSI_MUX; |
1825 | b43_radio_write(dev, reg, val); | ||
1826 | } | ||
1599 | 1827 | ||
1600 | reg = (i == 0) ? | 1828 | reg = (i == 0) ? |
1601 | B43_NPHY_AFECTL_OVER1 : | 1829 | B43_NPHY_AFECTL_OVER1 : |
@@ -1682,7 +1910,9 @@ static void b43_nphy_rev2_rssi_select(struct b43_wldev *dev, u8 code, | |||
1682 | static void b43_nphy_rssi_select(struct b43_wldev *dev, u8 code, | 1910 | static void b43_nphy_rssi_select(struct b43_wldev *dev, u8 code, |
1683 | enum n_rssi_type type) | 1911 | enum n_rssi_type type) |
1684 | { | 1912 | { |
1685 | if (dev->phy.rev >= 3) | 1913 | if (dev->phy.rev >= 19) |
1914 | b43_nphy_rssi_select_rev19(dev, code, type); | ||
1915 | else if (dev->phy.rev >= 3) | ||
1686 | b43_nphy_rev3_rssi_select(dev, code, type); | 1916 | b43_nphy_rev3_rssi_select(dev, code, type); |
1687 | else | 1917 | else |
1688 | b43_nphy_rev2_rssi_select(dev, code, type); | 1918 | b43_nphy_rev2_rssi_select(dev, code, type); |
@@ -1726,6 +1956,8 @@ static int b43_nphy_poll_rssi(struct b43_wldev *dev, enum n_rssi_type rssi_type, | |||
1726 | u16 save_regs_phy[9]; | 1956 | u16 save_regs_phy[9]; |
1727 | u16 s[2]; | 1957 | u16 s[2]; |
1728 | 1958 | ||
1959 | /* TODO: rev7+ is treated like rev3+, what about rev19+? */ | ||
1960 | |||
1729 | if (dev->phy.rev >= 3) { | 1961 | if (dev->phy.rev >= 3) { |
1730 | save_regs_phy[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1); | 1962 | save_regs_phy[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1); |
1731 | save_regs_phy[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2); | 1963 | save_regs_phy[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2); |
@@ -1825,12 +2057,14 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev) | |||
1825 | B43_NPHY_AFECTL_OVER1, B43_NPHY_AFECTL_OVER, | 2057 | B43_NPHY_AFECTL_OVER1, B43_NPHY_AFECTL_OVER, |
1826 | B43_NPHY_AFECTL_C1, B43_NPHY_AFECTL_C2, | 2058 | B43_NPHY_AFECTL_C1, B43_NPHY_AFECTL_C2, |
1827 | B43_NPHY_TXF_40CO_B1S1, B43_NPHY_RFCTL_OVER, | 2059 | B43_NPHY_TXF_40CO_B1S1, B43_NPHY_RFCTL_OVER, |
1828 | 0x342, 0x343, 0x346, 0x347, | 2060 | B43_NPHY_REV7_RF_CTL_OVER3, B43_NPHY_REV7_RF_CTL_OVER4, |
2061 | B43_NPHY_REV7_RF_CTL_OVER5, B43_NPHY_REV7_RF_CTL_OVER6, | ||
1829 | 0x2ff, | 2062 | 0x2ff, |
1830 | B43_NPHY_TXF_40CO_B1S0, B43_NPHY_TXF_40CO_B32S1, | 2063 | B43_NPHY_TXF_40CO_B1S0, B43_NPHY_TXF_40CO_B32S1, |
1831 | B43_NPHY_RFCTL_CMD, | 2064 | B43_NPHY_RFCTL_CMD, |
1832 | B43_NPHY_RFCTL_LUT_TRSW_UP1, B43_NPHY_RFCTL_LUT_TRSW_UP2, | 2065 | B43_NPHY_RFCTL_LUT_TRSW_UP1, B43_NPHY_RFCTL_LUT_TRSW_UP2, |
1833 | 0x340, 0x341, 0x344, 0x345, | 2066 | B43_NPHY_REV7_RF_CTL_MISC_REG3, B43_NPHY_REV7_RF_CTL_MISC_REG4, |
2067 | B43_NPHY_REV7_RF_CTL_MISC_REG5, B43_NPHY_REV7_RF_CTL_MISC_REG6, | ||
1834 | B43_NPHY_RFCTL_RSSIO1, B43_NPHY_RFCTL_RSSIO2 | 2068 | B43_NPHY_RFCTL_RSSIO1, B43_NPHY_RFCTL_RSSIO2 |
1835 | }; | 2069 | }; |
1836 | u16 *regs_to_store; | 2070 | u16 *regs_to_store; |
@@ -1877,9 +2111,24 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev) | |||
1877 | b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, 1, 7); | 2111 | b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, 1, 7); |
1878 | 2112 | ||
1879 | if (dev->phy.rev >= 7) { | 2113 | if (dev->phy.rev >= 7) { |
1880 | /* TODO */ | 2114 | b43_nphy_rf_ctl_override_one_to_many(dev, |
2115 | N_RF_CTL_OVER_CMD_RXRF_PU, | ||
2116 | 0, 0, false); | ||
2117 | b43_nphy_rf_ctl_override_one_to_many(dev, | ||
2118 | N_RF_CTL_OVER_CMD_RX_PU, | ||
2119 | 1, 0, false); | ||
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); | ||
1881 | if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { | 2122 | if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { |
2123 | b43_nphy_rf_ctl_override_rev7(dev, 0x20, 0, 0, false, | ||
2124 | 0); | ||
2125 | b43_nphy_rf_ctl_override_rev7(dev, 0x10, 1, 0, false, | ||
2126 | 0); | ||
1882 | } else { | 2127 | } else { |
2128 | b43_nphy_rf_ctl_override_rev7(dev, 0x10, 0, 0, false, | ||
2129 | 0); | ||
2130 | b43_nphy_rf_ctl_override_rev7(dev, 0x20, 1, 0, false, | ||
2131 | 0); | ||
1883 | } | 2132 | } |
1884 | } else { | 2133 | } else { |
1885 | b43_nphy_rf_ctl_override(dev, 0x1, 0, 0, false); | 2134 | b43_nphy_rf_ctl_override(dev, 0x1, 0, 0, false); |
@@ -1908,7 +2157,10 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev) | |||
1908 | /* Grab RSSI results for every possible VCM */ | 2157 | /* Grab RSSI results for every possible VCM */ |
1909 | for (vcm = 0; vcm < 8; vcm++) { | 2158 | for (vcm = 0; vcm < 8; vcm++) { |
1910 | if (dev->phy.rev >= 7) | 2159 | if (dev->phy.rev >= 7) |
1911 | ; | 2160 | b43_radio_maskset(dev, |
2161 | core ? R2057_NB_MASTER_CORE1 : | ||
2162 | R2057_NB_MASTER_CORE0, | ||
2163 | ~R2057_VCM_MASK, vcm); | ||
1912 | else | 2164 | else |
1913 | b43_radio_maskset(dev, r | B2056_RX_RSSI_MISC, | 2165 | b43_radio_maskset(dev, r | B2056_RX_RSSI_MISC, |
1914 | 0xE3, vcm << 2); | 2166 | 0xE3, vcm << 2); |
@@ -1939,7 +2191,10 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev) | |||
1939 | 2191 | ||
1940 | /* Select the best VCM */ | 2192 | /* Select the best VCM */ |
1941 | if (dev->phy.rev >= 7) | 2193 | if (dev->phy.rev >= 7) |
1942 | ; | 2194 | b43_radio_maskset(dev, |
2195 | core ? R2057_NB_MASTER_CORE1 : | ||
2196 | R2057_NB_MASTER_CORE0, | ||
2197 | ~R2057_VCM_MASK, vcm); | ||
1943 | else | 2198 | else |
1944 | b43_radio_maskset(dev, r | B2056_RX_RSSI_MISC, | 2199 | b43_radio_maskset(dev, r | B2056_RX_RSSI_MISC, |
1945 | 0xE3, vcm_final << 2); | 2200 | 0xE3, vcm_final << 2); |
@@ -2009,6 +2264,10 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev) | |||
2009 | rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G; | 2264 | rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G; |
2010 | } | 2265 | } |
2011 | if (dev->phy.rev >= 7) { | 2266 | if (dev->phy.rev >= 7) { |
2267 | rssical_radio_regs[0] = b43_radio_read(dev, | ||
2268 | R2057_NB_MASTER_CORE0); | ||
2269 | rssical_radio_regs[1] = b43_radio_read(dev, | ||
2270 | R2057_NB_MASTER_CORE1); | ||
2012 | } else { | 2271 | } else { |
2013 | rssical_radio_regs[0] = b43_radio_read(dev, B2056_RX0 | | 2272 | rssical_radio_regs[0] = b43_radio_read(dev, B2056_RX0 | |
2014 | B2056_RX_RSSI_MISC); | 2273 | B2056_RX_RSSI_MISC); |
@@ -2209,7 +2468,9 @@ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, enum n_rssi_type type) | |||
2209 | */ | 2468 | */ |
2210 | static void b43_nphy_rssi_cal(struct b43_wldev *dev) | 2469 | static void b43_nphy_rssi_cal(struct b43_wldev *dev) |
2211 | { | 2470 | { |
2212 | if (dev->phy.rev >= 3) { | 2471 | if (dev->phy.rev >= 19) { |
2472 | /* TODO */ | ||
2473 | } else if (dev->phy.rev >= 3) { | ||
2213 | b43_nphy_rev3_rssi_cal(dev); | 2474 | b43_nphy_rev3_rssi_cal(dev); |
2214 | } else { | 2475 | } else { |
2215 | b43_nphy_rev2_rssi_cal(dev, N_RSSI_NB); | 2476 | b43_nphy_rev2_rssi_cal(dev, N_RSSI_NB); |
@@ -2222,7 +2483,21 @@ static void b43_nphy_rssi_cal(struct b43_wldev *dev) | |||
2222 | * Workarounds | 2483 | * Workarounds |
2223 | **************************************************/ | 2484 | **************************************************/ |
2224 | 2485 | ||
2225 | static void b43_nphy_gain_ctl_workarounds_rev3plus(struct b43_wldev *dev) | 2486 | static void b43_nphy_gain_ctl_workarounds_rev19(struct b43_wldev *dev) |
2487 | { | ||
2488 | /* TODO */ | ||
2489 | } | ||
2490 | |||
2491 | static void b43_nphy_gain_ctl_workarounds_rev7(struct b43_wldev *dev) | ||
2492 | { | ||
2493 | struct b43_phy *phy = &dev->phy; | ||
2494 | |||
2495 | switch (phy->rev) { | ||
2496 | /* TODO */ | ||
2497 | } | ||
2498 | } | ||
2499 | |||
2500 | static void b43_nphy_gain_ctl_workarounds_rev3(struct b43_wldev *dev) | ||
2226 | { | 2501 | { |
2227 | struct ssb_sprom *sprom = dev->dev->bus_sprom; | 2502 | struct ssb_sprom *sprom = dev->dev->bus_sprom; |
2228 | 2503 | ||
@@ -2419,46 +2694,54 @@ static void b43_nphy_gain_ctl_workarounds_rev1_2(struct b43_wldev *dev) | |||
2419 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */ | 2694 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */ |
2420 | static void b43_nphy_gain_ctl_workarounds(struct b43_wldev *dev) | 2695 | static void b43_nphy_gain_ctl_workarounds(struct b43_wldev *dev) |
2421 | { | 2696 | { |
2422 | if (dev->phy.rev >= 7) | 2697 | if (dev->phy.rev >= 19) |
2423 | ; /* TODO */ | 2698 | b43_nphy_gain_ctl_workarounds_rev19(dev); |
2699 | else if (dev->phy.rev >= 7) | ||
2700 | b43_nphy_gain_ctl_workarounds_rev7(dev); | ||
2424 | else if (dev->phy.rev >= 3) | 2701 | else if (dev->phy.rev >= 3) |
2425 | b43_nphy_gain_ctl_workarounds_rev3plus(dev); | 2702 | b43_nphy_gain_ctl_workarounds_rev3(dev); |
2426 | else | 2703 | else |
2427 | b43_nphy_gain_ctl_workarounds_rev1_2(dev); | 2704 | b43_nphy_gain_ctl_workarounds_rev1_2(dev); |
2428 | } | 2705 | } |
2429 | 2706 | ||
2430 | /* http://bcm-v4.sipsolutions.net/PHY/N/Read_Lpf_Bw_Ctl */ | ||
2431 | static u16 b43_nphy_read_lpf_ctl(struct b43_wldev *dev, u16 offset) | ||
2432 | { | ||
2433 | if (!offset) | ||
2434 | offset = b43_is_40mhz(dev) ? 0x159 : 0x154; | ||
2435 | return b43_ntab_read(dev, B43_NTAB16(7, offset)) & 0x7; | ||
2436 | } | ||
2437 | |||
2438 | static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) | 2707 | static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) |
2439 | { | 2708 | { |
2440 | struct ssb_sprom *sprom = dev->dev->bus_sprom; | 2709 | struct ssb_sprom *sprom = dev->dev->bus_sprom; |
2441 | struct b43_phy *phy = &dev->phy; | 2710 | struct b43_phy *phy = &dev->phy; |
2442 | 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 */ | ||
2443 | 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, |
2444 | 0x1F }; | 2717 | 0x1F }; |
2445 | 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 }; |
2446 | 2719 | ||
2447 | u16 ntab7_15e_16e[] = { 0x10f, 0x10f }; | 2720 | static const u16 ntab7_15e_16e[] = { 0, 0x10f, 0x10f }; |
2448 | u8 ntab7_138_146[] = { 0x11, 0x11 }; | 2721 | u8 ntab7_138_146[] = { 0x11, 0x11 }; |
2449 | u8 ntab7_133[] = { 0x77, 0x11, 0x11 }; | 2722 | u8 ntab7_133[] = { 0x77, 0x11, 0x11 }; |
2450 | 2723 | ||
2451 | u16 lpf_20, lpf_40, lpf_11b; | 2724 | u16 lpf_ofdm_20mhz[2], lpf_ofdm_40mhz[2], lpf_11b[2]; |
2452 | u16 bcap_val, bcap_val_11b, bcap_val_11n_20, bcap_val_11n_40; | 2725 | u16 bcap_val; |
2453 | 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]; | ||
2454 | bool rccal_ovrd = false; | 2729 | bool rccal_ovrd = false; |
2455 | 2730 | ||
2456 | u16 rx2tx_lut_20_11b, rx2tx_lut_20_11n, rx2tx_lut_40_11n; | ||
2457 | u16 bias, conv, filt; | 2731 | u16 bias, conv, filt; |
2458 | 2732 | ||
2733 | u32 noise_tbl[2]; | ||
2734 | |||
2459 | u32 tmp32; | 2735 | u32 tmp32; |
2460 | u8 core; | 2736 | u8 core; |
2461 | 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 | |||
2462 | if (phy->rev == 7) { | 2745 | if (phy->rev == 7) { |
2463 | b43_phy_set(dev, B43_NPHY_FINERX2_CGC, 0x10); | 2746 | b43_phy_set(dev, B43_NPHY_FINERX2_CGC, 0x10); |
2464 | b43_phy_maskset(dev, B43_NPHY_FREQGAIN0, 0xFF80, 0x0020); | 2747 | b43_phy_maskset(dev, B43_NPHY_FREQGAIN0, 0xFF80, 0x0020); |
@@ -2478,11 +2761,18 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) | |||
2478 | b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0xFF80, 0x0040); | 2761 | b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0xFF80, 0x0040); |
2479 | b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0x80FF, 0x4000); | 2762 | b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0x80FF, 0x4000); |
2480 | } | 2763 | } |
2481 | 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) { | ||
2482 | b43_phy_write(dev, B43_NPHY_FORCEFRONT0, 0x1B0); | 2769 | b43_phy_write(dev, B43_NPHY_FORCEFRONT0, 0x1B0); |
2483 | b43_phy_write(dev, B43_NPHY_FORCEFRONT1, 0x1B0); | 2770 | b43_phy_write(dev, B43_NPHY_FORCEFRONT1, 0x1B0); |
2484 | } | 2771 | } |
2485 | 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) | ||
2486 | b43_phy_maskset(dev, B43_NPHY_TXTAILCNT, ~0xFF, 0x72); | 2776 | b43_phy_maskset(dev, B43_NPHY_TXTAILCNT, ~0xFF, 0x72); |
2487 | 2777 | ||
2488 | b43_ntab_write(dev, B43_NTAB16(8, 0x00), 2); | 2778 | b43_ntab_write(dev, B43_NTAB16(8, 0x00), 2); |
@@ -2490,9 +2780,11 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) | |||
2490 | tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0)); | 2780 | tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0)); |
2491 | tmp32 &= 0xffffff; | 2781 | tmp32 &= 0xffffff; |
2492 | b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32); | 2782 | b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32); |
2493 | 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); |
2494 | 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); |
2495 | 2785 | ||
2786 | b43_nphy_set_rf_sequence(dev, 1, tx2rx_events, tx2rx_delays, | ||
2787 | ARRAY_SIZE(tx2rx_events)); | ||
2496 | if (b43_nphy_ipa(dev)) | 2788 | if (b43_nphy_ipa(dev)) |
2497 | b43_nphy_set_rf_sequence(dev, 0, rx2tx_events_ipa, | 2789 | b43_nphy_set_rf_sequence(dev, 0, rx2tx_events_ipa, |
2498 | rx2tx_delays_ipa, ARRAY_SIZE(rx2tx_events_ipa)); | 2790 | rx2tx_delays_ipa, ARRAY_SIZE(rx2tx_events_ipa)); |
@@ -2500,84 +2792,176 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) | |||
2500 | b43_phy_maskset(dev, B43_NPHY_EPS_OVERRIDEI_0, 0x3FFF, 0x4000); | 2792 | b43_phy_maskset(dev, B43_NPHY_EPS_OVERRIDEI_0, 0x3FFF, 0x4000); |
2501 | b43_phy_maskset(dev, B43_NPHY_EPS_OVERRIDEI_1, 0x3FFF, 0x4000); | 2793 | b43_phy_maskset(dev, B43_NPHY_EPS_OVERRIDEI_1, 0x3FFF, 0x4000); |
2502 | 2794 | ||
2503 | lpf_20 = b43_nphy_read_lpf_ctl(dev, 0x154); | 2795 | for (core = 0; core < 2; core++) { |
2504 | lpf_40 = b43_nphy_read_lpf_ctl(dev, 0x159); | 2796 | lpf_ofdm_20mhz[core] = b43_nphy_read_lpf_ctl(dev, 0x154 + core * 0x10); |
2505 | 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 | |||
2506 | if (b43_nphy_ipa(dev)) { | 2804 | if (b43_nphy_ipa(dev)) { |
2507 | if ((phy->radio_rev == 5 && b43_is_40mhz(dev)) || | 2805 | bool ghz2 = b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ; |
2508 | phy->radio_rev == 7 || phy->radio_rev == 8) { | 2806 | |
2509 | bcap_val = b43_radio_read(dev, 0x16b); | 2807 | switch (phy->radio_rev) { |
2510 | scap_val = b43_radio_read(dev, 0x16a); | 2808 | case 5: |
2511 | scap_val_11b = scap_val; | 2809 | /* Check radio version (to be 0) by PHY rev for now */ |
2512 | bcap_val_11b = bcap_val; | 2810 | if (phy->rev == 8 && b43_is_40mhz(dev)) { |
2513 | if (phy->radio_rev == 5 && b43_is_40mhz(dev)) { | 2811 | for (core = 0; core < 2; core++) { |
2514 | scap_val_11n_20 = scap_val; | 2812 | scap_val_11b[core] = scap_val; |
2515 | bcap_val_11n_20 = bcap_val; | 2813 | bcap_val_11b[core] = bcap_val; |
2516 | 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 | |||
2517 | rccal_ovrd = true; | 2820 | rccal_ovrd = true; |
2518 | } else { /* Rev 7/8 */ | 2821 | } |
2519 | lpf_20 = 4; | 2822 | if (phy->rev == 9) { |
2520 | 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; | ||
2521 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { | 2833 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { |
2522 | scap_val_11n_20 = 0xc; | 2834 | scap_val_11n_20[core] = 0xc; |
2523 | bcap_val_11n_20 = 0xc; | 2835 | bcap_val_11n_20[core] = 0xc; |
2524 | scap_val_11n_40 = 0xa; | 2836 | scap_val_11n_40[core] = 0xa; |
2525 | bcap_val_11n_40 = 0xa; | 2837 | bcap_val_11n_40[core] = 0xa; |
2526 | } else { | 2838 | } else { |
2527 | scap_val_11n_20 = 0x14; | 2839 | scap_val_11n_20[core] = 0x14; |
2528 | bcap_val_11n_20 = 0x14; | 2840 | bcap_val_11n_20[core] = 0x14; |
2529 | scap_val_11n_40 = 0xf; | 2841 | scap_val_11n_40[core] = 0xf; |
2530 | bcap_val_11n_40 = 0xf; | 2842 | bcap_val_11n_40[core] = 0xf; |
2531 | } | 2843 | } |
2532 | rccal_ovrd = true; | ||
2533 | } | 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; | ||
2534 | } | 2900 | } |
2535 | } else { | 2901 | } else { |
2536 | if (phy->radio_rev == 5) { | 2902 | if (phy->radio_rev == 5) { |
2537 | lpf_20 = 1; | 2903 | for (core = 0; core < 2; core++) { |
2538 | lpf_40 = 3; | 2904 | lpf_ofdm_20mhz[core] = 1; |
2539 | bcap_val = b43_radio_read(dev, 0x16b); | 2905 | lpf_ofdm_40mhz[core] = 3; |
2540 | scap_val = b43_radio_read(dev, 0x16a); | 2906 | scap_val_11b[core] = scap_val; |
2541 | scap_val_11b = scap_val; | 2907 | bcap_val_11b[core] = bcap_val; |
2542 | bcap_val_11b = bcap_val; | 2908 | scap_val_11n_20[core] = 0x11; |
2543 | scap_val_11n_20 = 0x11; | 2909 | scap_val_11n_40[core] = 0x11; |
2544 | scap_val_11n_40 = 0x11; | 2910 | bcap_val_11n_20[core] = 0x13; |
2545 | bcap_val_11n_20 = 0x13; | 2911 | bcap_val_11n_40[core] = 0x13; |
2546 | bcap_val_11n_40 = 0x13; | 2912 | } |
2913 | |||
2547 | rccal_ovrd = true; | 2914 | rccal_ovrd = true; |
2548 | } | 2915 | } |
2549 | } | 2916 | } |
2550 | if (rccal_ovrd) { | 2917 | if (rccal_ovrd) { |
2551 | 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]; |
2552 | (scap_val_11b << 3) | | 2919 | u8 rx2tx_lut_extra = 1; |
2553 | lpf_11b; | 2920 | |
2554 | rx2tx_lut_20_11n = (bcap_val_11n_20 << 8) | | 2921 | for (core = 0; core < 2; core++) { |
2555 | (scap_val_11n_20 << 3) | | 2922 | bcap_val_11b[core] = clamp_val(bcap_val_11b[core], 0, 0x1f); |
2556 | lpf_20; | 2923 | scap_val_11b[core] = clamp_val(scap_val_11b[core], 0, 0x1f); |
2557 | rx2tx_lut_40_11n = (bcap_val_11n_40 << 8) | | 2924 | bcap_val_11n_20[core] = clamp_val(bcap_val_11n_20[core], 0, 0x1f); |
2558 | (scap_val_11n_40 << 3) | | 2925 | scap_val_11n_20[core] = clamp_val(scap_val_11n_20[core], 0, 0x1f); |
2559 | 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 | |||
2560 | for (core = 0; core < 2; core++) { | 2943 | for (core = 0; core < 2; core++) { |
2561 | b43_ntab_write(dev, B43_NTAB16(7, 0x152 + core * 16), | 2944 | b43_ntab_write(dev, B43_NTAB16(7, 0x152 + core * 16), |
2562 | rx2tx_lut_20_11b); | 2945 | rx2tx_lut_20_11b[core]); |
2563 | b43_ntab_write(dev, B43_NTAB16(7, 0x153 + core * 16), | 2946 | b43_ntab_write(dev, B43_NTAB16(7, 0x153 + core * 16), |
2564 | rx2tx_lut_20_11n); | 2947 | rx2tx_lut_20_11n[core]); |
2565 | b43_ntab_write(dev, B43_NTAB16(7, 0x154 + core * 16), | 2948 | b43_ntab_write(dev, B43_NTAB16(7, 0x154 + core * 16), |
2566 | rx2tx_lut_20_11n); | 2949 | rx2tx_lut_20_11n[core]); |
2567 | b43_ntab_write(dev, B43_NTAB16(7, 0x155 + core * 16), | 2950 | b43_ntab_write(dev, B43_NTAB16(7, 0x155 + core * 16), |
2568 | rx2tx_lut_40_11n); | 2951 | rx2tx_lut_40_11n[core]); |
2569 | b43_ntab_write(dev, B43_NTAB16(7, 0x156 + core * 16), | 2952 | b43_ntab_write(dev, B43_NTAB16(7, 0x156 + core * 16), |
2570 | rx2tx_lut_40_11n); | 2953 | rx2tx_lut_40_11n[core]); |
2571 | b43_ntab_write(dev, B43_NTAB16(7, 0x157 + core * 16), | 2954 | b43_ntab_write(dev, B43_NTAB16(7, 0x157 + core * 16), |
2572 | rx2tx_lut_40_11n); | 2955 | rx2tx_lut_40_11n[core]); |
2573 | b43_ntab_write(dev, B43_NTAB16(7, 0x158 + core * 16), | 2956 | b43_ntab_write(dev, B43_NTAB16(7, 0x158 + core * 16), |
2574 | rx2tx_lut_40_11n); | 2957 | rx2tx_lut_40_11n[core]); |
2575 | b43_ntab_write(dev, B43_NTAB16(7, 0x159 + core * 16), | 2958 | b43_ntab_write(dev, B43_NTAB16(7, 0x159 + core * 16), |
2576 | rx2tx_lut_40_11n); | 2959 | rx2tx_lut_40_11n[core]); |
2577 | } | 2960 | } |
2578 | b43_nphy_rf_ctl_override_rev7(dev, 16, 1, 3, false, 2); | ||
2579 | } | 2961 | } |
2962 | |||
2580 | b43_phy_write(dev, 0x32F, 0x3); | 2963 | b43_phy_write(dev, 0x32F, 0x3); |
2964 | |||
2581 | if (phy->radio_rev == 4 || phy->radio_rev == 6) | 2965 | if (phy->radio_rev == 4 || phy->radio_rev == 6) |
2582 | 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); |
2583 | 2967 | ||
@@ -2625,7 +3009,8 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) | |||
2625 | 0x7f); | 3009 | 0x7f); |
2626 | } | 3010 | } |
2627 | } | 3011 | } |
2628 | if (phy->radio_rev == 3) { | 3012 | switch (phy->radio_rev) { |
3013 | case 3: | ||
2629 | for (core = 0; core < 2; core++) { | 3014 | for (core = 0; core < 2; core++) { |
2630 | if (core == 0) { | 3015 | if (core == 0) { |
2631 | b43_radio_write(dev, 0x64, | 3016 | b43_radio_write(dev, 0x64, |
@@ -2651,7 +3036,9 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) | |||
2651 | 0x3E); | 3036 | 0x3E); |
2652 | } | 3037 | } |
2653 | } | 3038 | } |
2654 | } else if (phy->radio_rev == 7 || phy->radio_rev == 8) { | 3039 | break; |
3040 | case 7: | ||
3041 | case 8: | ||
2655 | if (!b43_is_40mhz(dev)) { | 3042 | if (!b43_is_40mhz(dev)) { |
2656 | b43_radio_write(dev, 0x5F, 0x14); | 3043 | b43_radio_write(dev, 0x5F, 0x14); |
2657 | b43_radio_write(dev, 0xE8, 0x12); | 3044 | b43_radio_write(dev, 0xE8, 0x12); |
@@ -2659,6 +3046,21 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) | |||
2659 | b43_radio_write(dev, 0x5F, 0x16); | 3046 | b43_radio_write(dev, 0x5F, 0x16); |
2660 | b43_radio_write(dev, 0xE8, 0x16); | 3047 | b43_radio_write(dev, 0xE8, 0x16); |
2661 | } | 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; | ||
2662 | } | 3064 | } |
2663 | } else { | 3065 | } else { |
2664 | u16 freq = phy->chandef->chan->center_freq; | 3066 | u16 freq = phy->chandef->chan->center_freq; |
@@ -2706,8 +3108,8 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) | |||
2706 | b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x1); | 3108 | b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x1); |
2707 | b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x1); | 3109 | b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x1); |
2708 | b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x1); | 3110 | b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x1); |
2709 | b43_ntab_write(dev, B43_NTAB16(8, 0x05), 0x20); | 3111 | b43_ntab_write(dev, B43_NTAB16(8, 0x05), 0); |
2710 | b43_ntab_write(dev, B43_NTAB16(8, 0x15), 0x20); | 3112 | b43_ntab_write(dev, B43_NTAB16(8, 0x15), 0); |
2711 | 3113 | ||
2712 | b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x4); | 3114 | b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x4); |
2713 | b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x4); | 3115 | b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x4); |
@@ -2718,20 +3120,20 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) | |||
2718 | b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, 0x2); | 3120 | b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, 0x2); |
2719 | 3121 | ||
2720 | b43_ntab_write(dev, B43_NTAB32(16, 0x100), 20); | 3122 | b43_ntab_write(dev, B43_NTAB32(16, 0x100), 20); |
2721 | 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); |
2722 | b43_ntab_write(dev, B43_NTAB16(7, 0x141), 0x77); | 3124 | b43_ntab_write(dev, B43_NTAB16(7, 0x141), 0x77); |
2723 | 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); |
2724 | 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); |
2725 | b43_ntab_write(dev, B43_NTAB16(7, 0x123), 0x77); | 3127 | b43_ntab_write(dev, B43_NTAB16(7, 0x123), 0x77); |
2726 | b43_ntab_write(dev, B43_NTAB16(7, 0x12A), 0x77); | 3128 | b43_ntab_write(dev, B43_NTAB16(7, 0x12A), 0x77); |
2727 | 3129 | ||
2728 | if (!b43_is_40mhz(dev)) { | 3130 | b43_ntab_read_bulk(dev, B43_NTAB32(16, 0x02), 1, noise_tbl); |
2729 | b43_ntab_write(dev, B43_NTAB32(16, 0x03), 0x18D); | 3131 | noise_tbl[1] = b43_is_40mhz(dev) ? 0x14D : 0x18D; |
2730 | b43_ntab_write(dev, B43_NTAB32(16, 0x7F), 0x18D); | 3132 | b43_ntab_write_bulk(dev, B43_NTAB32(16, 0x02), 2, noise_tbl); |
2731 | } else { | 3133 | |
2732 | b43_ntab_write(dev, B43_NTAB32(16, 0x03), 0x14D); | 3134 | b43_ntab_read_bulk(dev, B43_NTAB32(16, 0x7E), 1, noise_tbl); |
2733 | b43_ntab_write(dev, B43_NTAB32(16, 0x7F), 0x14D); | 3135 | noise_tbl[1] = b43_is_40mhz(dev) ? 0x14D : 0x18D; |
2734 | } | 3136 | b43_ntab_write_bulk(dev, B43_NTAB32(16, 0x7E), 2, noise_tbl); |
2735 | 3137 | ||
2736 | b43_nphy_gain_ctl_workarounds(dev); | 3138 | b43_nphy_gain_ctl_workarounds(dev); |
2737 | 3139 | ||
@@ -3059,6 +3461,7 @@ static void b43_nphy_workarounds(struct b43_wldev *dev) | |||
3059 | b43_phy_set(dev, B43_NPHY_IQFLIP, | 3461 | b43_phy_set(dev, B43_NPHY_IQFLIP, |
3060 | B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2); | 3462 | B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2); |
3061 | 3463 | ||
3464 | /* TODO: rev19+ */ | ||
3062 | if (dev->phy.rev >= 7) | 3465 | if (dev->phy.rev >= 7) |
3063 | b43_nphy_workarounds_rev7plus(dev); | 3466 | b43_nphy_workarounds_rev7plus(dev); |
3064 | else if (dev->phy.rev >= 3) | 3467 | else if (dev->phy.rev >= 3) |
@@ -3120,6 +3523,7 @@ static void b43_nphy_update_txrx_chain(struct b43_wldev *dev) | |||
3120 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/stop-playback */ | 3523 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/stop-playback */ |
3121 | static void b43_nphy_stop_playback(struct b43_wldev *dev) | 3524 | static void b43_nphy_stop_playback(struct b43_wldev *dev) |
3122 | { | 3525 | { |
3526 | struct b43_phy *phy = &dev->phy; | ||
3123 | struct b43_phy_n *nphy = dev->phy.n; | 3527 | struct b43_phy_n *nphy = dev->phy.n; |
3124 | u16 tmp; | 3528 | u16 tmp; |
3125 | 3529 | ||
@@ -3140,6 +3544,15 @@ static void b43_nphy_stop_playback(struct b43_wldev *dev) | |||
3140 | nphy->bb_mult_save = 0; | 3544 | nphy->bb_mult_save = 0; |
3141 | } | 3545 | } |
3142 | 3546 | ||
3547 | if (phy->rev >= 7 && nphy->lpf_bw_overrode_for_sample_play) { | ||
3548 | if (phy->rev >= 19) | ||
3549 | b43_nphy_rf_ctl_override_rev19(dev, 0x80, 0, 0, true, | ||
3550 | 1); | ||
3551 | else | ||
3552 | b43_nphy_rf_ctl_override_rev7(dev, 0x80, 0, 0, true, 1); | ||
3553 | nphy->lpf_bw_overrode_for_sample_play = false; | ||
3554 | } | ||
3555 | |||
3143 | if (nphy->hang_avoid) | 3556 | if (nphy->hang_avoid) |
3144 | b43_nphy_stay_in_carrier_search(dev, 0); | 3557 | b43_nphy_stay_in_carrier_search(dev, 0); |
3145 | } | 3558 | } |
@@ -3149,16 +3562,23 @@ static void b43_nphy_iq_cal_gain_params(struct b43_wldev *dev, u16 core, | |||
3149 | struct nphy_txgains target, | 3562 | struct nphy_txgains target, |
3150 | struct nphy_iqcal_params *params) | 3563 | struct nphy_iqcal_params *params) |
3151 | { | 3564 | { |
3565 | struct b43_phy *phy = &dev->phy; | ||
3152 | int i, j, indx; | 3566 | int i, j, indx; |
3153 | u16 gain; | 3567 | u16 gain; |
3154 | 3568 | ||
3155 | if (dev->phy.rev >= 3) { | 3569 | if (dev->phy.rev >= 3) { |
3570 | params->tx_lpf = target.tx_lpf[core]; /* Rev 7+ */ | ||
3156 | params->txgm = target.txgm[core]; | 3571 | params->txgm = target.txgm[core]; |
3157 | params->pga = target.pga[core]; | 3572 | params->pga = target.pga[core]; |
3158 | params->pad = target.pad[core]; | 3573 | params->pad = target.pad[core]; |
3159 | params->ipa = target.ipa[core]; | 3574 | params->ipa = target.ipa[core]; |
3160 | params->cal_gain = (params->txgm << 12) | (params->pga << 8) | | 3575 | if (phy->rev >= 19) { |
3161 | (params->pad << 4) | (params->ipa); | 3576 | /* TODO */ |
3577 | } else if (phy->rev >= 7) { | ||
3578 | params->cal_gain = (params->txgm << 12) | (params->pga << 8) | (params->pad << 3) | (params->ipa) | (params->tx_lpf << 15); | ||
3579 | } else { | ||
3580 | params->cal_gain = (params->txgm << 12) | (params->pga << 8) | (params->pad << 4) | (params->ipa); | ||
3581 | } | ||
3162 | for (j = 0; j < 5; j++) | 3582 | for (j = 0; j < 5; j++) |
3163 | params->ncorr[j] = 0x79; | 3583 | params->ncorr[j] = 0x79; |
3164 | } else { | 3584 | } else { |
@@ -3199,6 +3619,7 @@ static enum b43_txpwr_result b43_nphy_op_recalc_txpower(struct b43_wldev *dev, | |||
3199 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlEnable */ | 3619 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlEnable */ |
3200 | static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable) | 3620 | static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable) |
3201 | { | 3621 | { |
3622 | struct b43_phy *phy = &dev->phy; | ||
3202 | struct b43_phy_n *nphy = dev->phy.n; | 3623 | struct b43_phy_n *nphy = dev->phy.n; |
3203 | u8 i; | 3624 | u8 i; |
3204 | u16 bmask, val, tmp; | 3625 | u16 bmask, val, tmp; |
@@ -3268,12 +3689,25 @@ static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable) | |||
3268 | b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, ~(bmask), val); | 3689 | b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, ~(bmask), val); |
3269 | 3690 | ||
3270 | if (band == IEEE80211_BAND_5GHZ) { | 3691 | if (band == IEEE80211_BAND_5GHZ) { |
3271 | b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, | 3692 | if (phy->rev >= 19) { |
3272 | ~B43_NPHY_TXPCTL_CMD_INIT, 0x64); | 3693 | /* TODO */ |
3273 | if (dev->phy.rev > 1) | 3694 | } else if (phy->rev >= 7) { |
3695 | b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, | ||
3696 | ~B43_NPHY_TXPCTL_CMD_INIT, | ||
3697 | 0x32); | ||
3274 | b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT, | 3698 | b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT, |
3275 | ~B43_NPHY_TXPCTL_INIT_PIDXI1, | 3699 | ~B43_NPHY_TXPCTL_INIT_PIDXI1, |
3700 | 0x32); | ||
3701 | } else { | ||
3702 | b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, | ||
3703 | ~B43_NPHY_TXPCTL_CMD_INIT, | ||
3276 | 0x64); | 3704 | 0x64); |
3705 | if (phy->rev > 1) | ||
3706 | b43_phy_maskset(dev, | ||
3707 | B43_NPHY_TXPCTL_INIT, | ||
3708 | ~B43_NPHY_TXPCTL_INIT_PIDXI1, | ||
3709 | 0x64); | ||
3710 | } | ||
3277 | } | 3711 | } |
3278 | 3712 | ||
3279 | if (dev->phy.rev >= 3) { | 3713 | if (dev->phy.rev >= 3) { |
@@ -3290,6 +3724,10 @@ static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable) | |||
3290 | } | 3724 | } |
3291 | } | 3725 | } |
3292 | 3726 | ||
3727 | if (phy->rev >= 7) { | ||
3728 | /* TODO */ | ||
3729 | } | ||
3730 | |||
3293 | if (dev->phy.rev >= 3) { | 3731 | if (dev->phy.rev >= 3) { |
3294 | b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x100); | 3732 | b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x100); |
3295 | b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x100); | 3733 | b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x100); |
@@ -3331,6 +3769,7 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev) | |||
3331 | if (nphy->hang_avoid) | 3769 | if (nphy->hang_avoid) |
3332 | b43_nphy_stay_in_carrier_search(dev, 1); | 3770 | b43_nphy_stay_in_carrier_search(dev, 1); |
3333 | 3771 | ||
3772 | /* TODO: rev19+ */ | ||
3334 | if (dev->phy.rev >= 7) { | 3773 | if (dev->phy.rev >= 7) { |
3335 | txpi[0] = txpi[1] = 30; | 3774 | txpi[0] = txpi[1] = 30; |
3336 | } else if (dev->phy.rev >= 3) { | 3775 | } else if (dev->phy.rev >= 3) { |
@@ -3433,7 +3872,9 @@ static void b43_nphy_ipa_internal_tssi_setup(struct b43_wldev *dev) | |||
3433 | u8 core; | 3872 | u8 core; |
3434 | u16 r; /* routing */ | 3873 | u16 r; /* routing */ |
3435 | 3874 | ||
3436 | if (phy->rev >= 7) { | 3875 | if (phy->rev >= 19) { |
3876 | /* TODO */ | ||
3877 | } else if (phy->rev >= 7) { | ||
3437 | for (core = 0; core < 2; core++) { | 3878 | for (core = 0; core < 2; core++) { |
3438 | r = core ? 0x190 : 0x170; | 3879 | r = core ? 0x190 : 0x170; |
3439 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { | 3880 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { |
@@ -3516,13 +3957,16 @@ static void b43_nphy_tx_power_ctl_idle_tssi(struct b43_wldev *dev) | |||
3516 | u32 tmp; | 3957 | u32 tmp; |
3517 | s32 rssi[4] = { }; | 3958 | s32 rssi[4] = { }; |
3518 | 3959 | ||
3519 | /* TODO: check if we can transmit */ | 3960 | if (phy->chandef->chan->flags & IEEE80211_CHAN_NO_IR) |
3961 | return; | ||
3520 | 3962 | ||
3521 | if (b43_nphy_ipa(dev)) | 3963 | if (b43_nphy_ipa(dev)) |
3522 | b43_nphy_ipa_internal_tssi_setup(dev); | 3964 | b43_nphy_ipa_internal_tssi_setup(dev); |
3523 | 3965 | ||
3524 | if (phy->rev >= 7) | 3966 | if (phy->rev >= 19) |
3525 | b43_nphy_rf_ctl_override_rev7(dev, 0x2000, 0, 3, false, 0); | 3967 | b43_nphy_rf_ctl_override_rev19(dev, 0x1000, 0, 3, false, 0); |
3968 | else if (phy->rev >= 7) | ||
3969 | b43_nphy_rf_ctl_override_rev7(dev, 0x1000, 0, 3, false, 0); | ||
3526 | else if (phy->rev >= 3) | 3970 | else if (phy->rev >= 3) |
3527 | b43_nphy_rf_ctl_override(dev, 0x2000, 0, 3, false); | 3971 | b43_nphy_rf_ctl_override(dev, 0x2000, 0, 3, false); |
3528 | 3972 | ||
@@ -3531,14 +3975,20 @@ static void b43_nphy_tx_power_ctl_idle_tssi(struct b43_wldev *dev) | |||
3531 | udelay(20); | 3975 | udelay(20); |
3532 | tmp = b43_nphy_poll_rssi(dev, N_RSSI_TSSI_2G, rssi, 1); | 3976 | tmp = b43_nphy_poll_rssi(dev, N_RSSI_TSSI_2G, rssi, 1); |
3533 | b43_nphy_stop_playback(dev); | 3977 | b43_nphy_stop_playback(dev); |
3978 | |||
3534 | b43_nphy_rssi_select(dev, 0, N_RSSI_W1); | 3979 | b43_nphy_rssi_select(dev, 0, N_RSSI_W1); |
3535 | 3980 | ||
3536 | if (phy->rev >= 7) | 3981 | if (phy->rev >= 19) |
3537 | b43_nphy_rf_ctl_override_rev7(dev, 0x2000, 0, 3, true, 0); | 3982 | b43_nphy_rf_ctl_override_rev19(dev, 0x1000, 0, 3, true, 0); |
3983 | else if (phy->rev >= 7) | ||
3984 | b43_nphy_rf_ctl_override_rev7(dev, 0x1000, 0, 3, true, 0); | ||
3538 | else if (phy->rev >= 3) | 3985 | else if (phy->rev >= 3) |
3539 | b43_nphy_rf_ctl_override(dev, 0x2000, 0, 3, true); | 3986 | b43_nphy_rf_ctl_override(dev, 0x2000, 0, 3, true); |
3540 | 3987 | ||
3541 | if (phy->rev >= 3) { | 3988 | if (phy->rev >= 19) { |
3989 | /* TODO */ | ||
3990 | return; | ||
3991 | } else if (phy->rev >= 3) { | ||
3542 | nphy->pwr_ctl_info[0].idle_tssi_5g = (tmp >> 24) & 0xFF; | 3992 | nphy->pwr_ctl_info[0].idle_tssi_5g = (tmp >> 24) & 0xFF; |
3543 | nphy->pwr_ctl_info[1].idle_tssi_5g = (tmp >> 8) & 0xFF; | 3993 | nphy->pwr_ctl_info[1].idle_tssi_5g = (tmp >> 8) & 0xFF; |
3544 | } else { | 3994 | } else { |
@@ -3730,7 +4180,9 @@ static void b43_nphy_tx_power_ctl_setup(struct b43_wldev *dev) | |||
3730 | udelay(1); | 4180 | udelay(1); |
3731 | } | 4181 | } |
3732 | 4182 | ||
3733 | if (dev->phy.rev >= 7) { | 4183 | if (phy->rev >= 19) { |
4184 | /* TODO */ | ||
4185 | } else if (phy->rev >= 7) { | ||
3734 | b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, | 4186 | b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, |
3735 | ~B43_NPHY_TXPCTL_CMD_INIT, 0x19); | 4187 | ~B43_NPHY_TXPCTL_CMD_INIT, 0x19); |
3736 | b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT, | 4188 | b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT, |
@@ -3793,24 +4245,30 @@ static void b43_nphy_tx_gain_table_upload(struct b43_wldev *dev) | |||
3793 | b43_ntab_write_bulk(dev, B43_NTAB32(26, 192), 128, table); | 4245 | b43_ntab_write_bulk(dev, B43_NTAB32(26, 192), 128, table); |
3794 | b43_ntab_write_bulk(dev, B43_NTAB32(27, 192), 128, table); | 4246 | b43_ntab_write_bulk(dev, B43_NTAB32(27, 192), 128, table); |
3795 | 4247 | ||
3796 | if (phy->rev >= 3) { | 4248 | if (phy->rev < 3) |
4249 | return; | ||
4250 | |||
3797 | #if 0 | 4251 | #if 0 |
3798 | nphy->gmval = (table[0] >> 16) & 0x7000; | 4252 | nphy->gmval = (table[0] >> 16) & 0x7000; |
3799 | #endif | 4253 | #endif |
3800 | 4254 | ||
3801 | for (i = 0; i < 128; i++) { | 4255 | for (i = 0; i < 128; i++) { |
4256 | if (phy->rev >= 19) { | ||
4257 | /* TODO */ | ||
4258 | return; | ||
4259 | } else if (phy->rev >= 7) { | ||
4260 | /* TODO */ | ||
4261 | return; | ||
4262 | } else { | ||
3802 | pga_gain = (table[i] >> 24) & 0xF; | 4263 | pga_gain = (table[i] >> 24) & 0xF; |
3803 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) | 4264 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) |
3804 | rfpwr_offset = | 4265 | rfpwr_offset = b43_ntab_papd_pga_gain_delta_ipa_2g[pga_gain]; |
3805 | b43_ntab_papd_pga_gain_delta_ipa_2g[pga_gain]; | ||
3806 | else | 4266 | else |
3807 | rfpwr_offset = | 4267 | rfpwr_offset = 0; /* FIXME */ |
3808 | 0; /* FIXME */ | ||
3809 | b43_ntab_write(dev, B43_NTAB32(26, 576 + i), | ||
3810 | rfpwr_offset); | ||
3811 | b43_ntab_write(dev, B43_NTAB32(27, 576 + i), | ||
3812 | rfpwr_offset); | ||
3813 | } | 4268 | } |
4269 | |||
4270 | b43_ntab_write(dev, B43_NTAB32(26, 576 + i), rfpwr_offset); | ||
4271 | b43_ntab_write(dev, B43_NTAB32(27, 576 + i), rfpwr_offset); | ||
3814 | } | 4272 | } |
3815 | } | 4273 | } |
3816 | 4274 | ||
@@ -3827,7 +4285,9 @@ static void b43_nphy_pa_override(struct b43_wldev *dev, bool enable) | |||
3827 | nphy->rfctrl_intc2_save = b43_phy_read(dev, | 4285 | nphy->rfctrl_intc2_save = b43_phy_read(dev, |
3828 | B43_NPHY_RFCTL_INTC2); | 4286 | B43_NPHY_RFCTL_INTC2); |
3829 | band = b43_current_band(dev->wl); | 4287 | band = b43_current_band(dev->wl); |
3830 | if (dev->phy.rev >= 3) { | 4288 | if (dev->phy.rev >= 7) { |
4289 | tmp = 0x1480; | ||
4290 | } else if (dev->phy.rev >= 3) { | ||
3831 | if (band == IEEE80211_BAND_5GHZ) | 4291 | if (band == IEEE80211_BAND_5GHZ) |
3832 | tmp = 0x600; | 4292 | tmp = 0x600; |
3833 | else | 4293 | else |
@@ -4274,7 +4734,13 @@ static void b43_nphy_restore_rssi_cal(struct b43_wldev *dev) | |||
4274 | rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G; | 4734 | rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G; |
4275 | } | 4735 | } |
4276 | 4736 | ||
4277 | if (dev->phy.rev >= 7) { | 4737 | if (dev->phy.rev >= 19) { |
4738 | /* TODO */ | ||
4739 | } else if (dev->phy.rev >= 7) { | ||
4740 | b43_radio_maskset(dev, R2057_NB_MASTER_CORE0, ~R2057_VCM_MASK, | ||
4741 | rssical_radio_regs[0]); | ||
4742 | b43_radio_maskset(dev, R2057_NB_MASTER_CORE1, ~R2057_VCM_MASK, | ||
4743 | rssical_radio_regs[1]); | ||
4278 | } else { | 4744 | } else { |
4279 | b43_radio_maskset(dev, B2056_RX0 | B2056_RX_RSSI_MISC, 0xE3, | 4745 | b43_radio_maskset(dev, B2056_RX0 | B2056_RX_RSSI_MISC, 0xE3, |
4280 | rssical_radio_regs[0]); | 4746 | rssical_radio_regs[0]); |
@@ -4298,15 +4764,78 @@ static void b43_nphy_restore_rssi_cal(struct b43_wldev *dev) | |||
4298 | b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, rssical_phy_regs[11]); | 4764 | b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, rssical_phy_regs[11]); |
4299 | } | 4765 | } |
4300 | 4766 | ||
4767 | static void b43_nphy_tx_cal_radio_setup_rev19(struct b43_wldev *dev) | ||
4768 | { | ||
4769 | /* TODO */ | ||
4770 | } | ||
4771 | |||
4772 | static void b43_nphy_tx_cal_radio_setup_rev7(struct b43_wldev *dev) | ||
4773 | { | ||
4774 | struct b43_phy *phy = &dev->phy; | ||
4775 | struct b43_phy_n *nphy = dev->phy.n; | ||
4776 | u16 *save = nphy->tx_rx_cal_radio_saveregs; | ||
4777 | int core, off; | ||
4778 | u16 r, tmp; | ||
4779 | |||
4780 | for (core = 0; core < 2; core++) { | ||
4781 | r = core ? 0x20 : 0; | ||
4782 | off = core * 11; | ||
4783 | |||
4784 | save[off + 0] = b43_radio_read(dev, r + R2057_TX0_TX_SSI_MASTER); | ||
4785 | save[off + 1] = b43_radio_read(dev, r + R2057_TX0_IQCAL_VCM_HG); | ||
4786 | save[off + 2] = b43_radio_read(dev, r + R2057_TX0_IQCAL_IDAC); | ||
4787 | save[off + 3] = b43_radio_read(dev, r + R2057_TX0_TSSI_VCM); | ||
4788 | save[off + 4] = 0; | ||
4789 | save[off + 5] = b43_radio_read(dev, r + R2057_TX0_TX_SSI_MUX); | ||
4790 | if (phy->radio_rev != 5) | ||
4791 | save[off + 6] = b43_radio_read(dev, r + R2057_TX0_TSSIA); | ||
4792 | save[off + 7] = b43_radio_read(dev, r + R2057_TX0_TSSIG); | ||
4793 | save[off + 8] = b43_radio_read(dev, r + R2057_TX0_TSSI_MISC1); | ||
4794 | |||
4795 | if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { | ||
4796 | b43_radio_write(dev, r + R2057_TX0_TX_SSI_MASTER, 0xA); | ||
4797 | b43_radio_write(dev, r + R2057_TX0_IQCAL_VCM_HG, 0x43); | ||
4798 | b43_radio_write(dev, r + R2057_TX0_IQCAL_IDAC, 0x55); | ||
4799 | b43_radio_write(dev, r + R2057_TX0_TSSI_VCM, 0); | ||
4800 | b43_radio_write(dev, r + R2057_TX0_TSSIG, 0); | ||
4801 | if (nphy->use_int_tx_iq_lo_cal) { | ||
4802 | b43_radio_write(dev, r + R2057_TX0_TX_SSI_MUX, 0x4); | ||
4803 | tmp = true ? 0x31 : 0x21; /* TODO */ | ||
4804 | b43_radio_write(dev, r + R2057_TX0_TSSIA, tmp); | ||
4805 | } | ||
4806 | b43_radio_write(dev, r + R2057_TX0_TSSI_MISC1, 0x00); | ||
4807 | } else { | ||
4808 | b43_radio_write(dev, r + R2057_TX0_TX_SSI_MASTER, 0x6); | ||
4809 | b43_radio_write(dev, r + R2057_TX0_IQCAL_VCM_HG, 0x43); | ||
4810 | b43_radio_write(dev, r + R2057_TX0_IQCAL_IDAC, 0x55); | ||
4811 | b43_radio_write(dev, r + R2057_TX0_TSSI_VCM, 0); | ||
4812 | |||
4813 | if (phy->radio_rev != 5) | ||
4814 | b43_radio_write(dev, r + R2057_TX0_TSSIA, 0); | ||
4815 | if (nphy->use_int_tx_iq_lo_cal) { | ||
4816 | b43_radio_write(dev, r + R2057_TX0_TX_SSI_MUX, 0x6); | ||
4817 | tmp = true ? 0x31 : 0x21; /* TODO */ | ||
4818 | b43_radio_write(dev, r + R2057_TX0_TSSIG, tmp); | ||
4819 | } | ||
4820 | b43_radio_write(dev, r + R2057_TX0_TSSI_MISC1, 0); | ||
4821 | } | ||
4822 | } | ||
4823 | } | ||
4824 | |||
4301 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalRadioSetup */ | 4825 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalRadioSetup */ |
4302 | static void b43_nphy_tx_cal_radio_setup(struct b43_wldev *dev) | 4826 | static void b43_nphy_tx_cal_radio_setup(struct b43_wldev *dev) |
4303 | { | 4827 | { |
4828 | struct b43_phy *phy = &dev->phy; | ||
4304 | struct b43_phy_n *nphy = dev->phy.n; | 4829 | struct b43_phy_n *nphy = dev->phy.n; |
4305 | u16 *save = nphy->tx_rx_cal_radio_saveregs; | 4830 | u16 *save = nphy->tx_rx_cal_radio_saveregs; |
4306 | u16 tmp; | 4831 | u16 tmp; |
4307 | u8 offset, i; | 4832 | u8 offset, i; |
4308 | 4833 | ||
4309 | if (dev->phy.rev >= 3) { | 4834 | if (phy->rev >= 19) { |
4835 | b43_nphy_tx_cal_radio_setup_rev19(dev); | ||
4836 | } else if (phy->rev >= 7) { | ||
4837 | b43_nphy_tx_cal_radio_setup_rev7(dev); | ||
4838 | } else if (phy->rev >= 3) { | ||
4310 | for (i = 0; i < 2; i++) { | 4839 | for (i = 0; i < 2; i++) { |
4311 | tmp = (i == 0) ? 0x2000 : 0x3000; | 4840 | tmp = (i == 0) ? 0x2000 : 0x3000; |
4312 | offset = i * 11; | 4841 | offset = i * 11; |
@@ -4415,41 +4944,61 @@ static void b43_nphy_update_tx_cal_ladder(struct b43_wldev *dev, u16 core) | |||
4415 | } | 4944 | } |
4416 | } | 4945 | } |
4417 | 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 | |||
4418 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ExtPaSetTxDigiFilts */ | 4958 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ExtPaSetTxDigiFilts */ |
4419 | 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) |
4420 | { | 4960 | { |
4421 | int i; | 4961 | b43_nphy_pa_set_tx_dig_filter(dev, 0x2C5, |
4422 | for (i = 0; i < 15; i++) | 4962 | tbl_tx_filter_coef_rev4[2]); |
4423 | b43_phy_write(dev, B43_PHY_N(0x2C5 + i), | ||
4424 | tbl_tx_filter_coef_rev4[2][i]); | ||
4425 | } | 4963 | } |
4426 | 4964 | ||
4427 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IpaSetTxDigiFilts */ | 4965 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IpaSetTxDigiFilts */ |
4428 | 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) |
4429 | { | 4967 | { |
4430 | int i, j; | ||
4431 | /* B43_NPHY_TXF_20CO_S0A1, B43_NPHY_TXF_40CO_S0A1, unknown */ | 4968 | /* B43_NPHY_TXF_20CO_S0A1, B43_NPHY_TXF_40CO_S0A1, unknown */ |
4432 | 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; | ||
4433 | 4976 | ||
4434 | for (i = 0; i < 3; i++) | 4977 | for (i = 0; i < 3; i++) |
4435 | for (j = 0; j < 15; j++) | 4978 | b43_nphy_pa_set_tx_dig_filter(dev, offset[i], |
4436 | b43_phy_write(dev, B43_PHY_N(offset[i] + j), | 4979 | tbl_tx_filter_coef_rev4[i]); |
4437 | 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 | } | ||
4438 | 4990 | ||
4439 | if (b43_is_40mhz(dev)) { | 4991 | if (b43_is_40mhz(dev)) { |
4440 | for (j = 0; j < 15; j++) | 4992 | b43_nphy_pa_set_tx_dig_filter(dev, 0x186, |
4441 | b43_phy_write(dev, B43_PHY_N(offset[0] + j), | 4993 | tbl_tx_filter_coef_rev4[3]); |
4442 | tbl_tx_filter_coef_rev4[3][j]); | 4994 | } else { |
4443 | } else if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { | 4995 | if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) |
4444 | for (j = 0; j < 15; j++) | 4996 | b43_nphy_pa_set_tx_dig_filter(dev, 0x186, |
4445 | b43_phy_write(dev, B43_PHY_N(offset[0] + j), | 4997 | tbl_tx_filter_coef_rev4[5]); |
4446 | tbl_tx_filter_coef_rev4[5][j]); | 4998 | if (dev->phy.channel == 14) |
4447 | } | 4999 | b43_nphy_pa_set_tx_dig_filter(dev, 0x186, |
4448 | 5000 | tbl_tx_filter_coef_rev4[6]); | |
4449 | if (dev->phy.channel == 14) | 5001 | } |
4450 | for (j = 0; j < 15; j++) | ||
4451 | b43_phy_write(dev, B43_PHY_N(offset[0] + j), | ||
4452 | tbl_tx_filter_coef_rev4[6][j]); | ||
4453 | } | 5002 | } |
4454 | 5003 | ||
4455 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetTxGain */ | 5004 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetTxGain */ |
@@ -4471,7 +5020,13 @@ static struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev) | |||
4471 | b43_nphy_stay_in_carrier_search(dev, false); | 5020 | b43_nphy_stay_in_carrier_search(dev, false); |
4472 | 5021 | ||
4473 | for (i = 0; i < 2; ++i) { | 5022 | for (i = 0; i < 2; ++i) { |
4474 | if (dev->phy.rev >= 3) { | 5023 | if (dev->phy.rev >= 7) { |
5024 | target.ipa[i] = curr_gain[i] & 0x0007; | ||
5025 | target.pad[i] = (curr_gain[i] & 0x00F8) >> 3; | ||
5026 | target.pga[i] = (curr_gain[i] & 0x0F00) >> 8; | ||
5027 | target.txgm[i] = (curr_gain[i] & 0x7000) >> 12; | ||
5028 | target.tx_lpf[i] = (curr_gain[i] & 0x8000) >> 15; | ||
5029 | } else if (dev->phy.rev >= 3) { | ||
4475 | target.ipa[i] = curr_gain[i] & 0x000F; | 5030 | target.ipa[i] = curr_gain[i] & 0x000F; |
4476 | target.pad[i] = (curr_gain[i] & 0x00F0) >> 4; | 5031 | target.pad[i] = (curr_gain[i] & 0x00F0) >> 4; |
4477 | target.pga[i] = (curr_gain[i] & 0x0F00) >> 8; | 5032 | target.pga[i] = (curr_gain[i] & 0x0F00) >> 8; |
@@ -4498,7 +5053,13 @@ static struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev) | |||
4498 | if (!table) | 5053 | if (!table) |
4499 | break; | 5054 | break; |
4500 | 5055 | ||
4501 | if (dev->phy.rev >= 3) { | 5056 | if (dev->phy.rev >= 7) { |
5057 | target.ipa[i] = (table[index[i]] >> 16) & 0x7; | ||
5058 | target.pad[i] = (table[index[i]] >> 19) & 0x1F; | ||
5059 | target.pga[i] = (table[index[i]] >> 24) & 0xF; | ||
5060 | target.txgm[i] = (table[index[i]] >> 28) & 0x7; | ||
5061 | target.tx_lpf[i] = (table[index[i]] >> 31) & 0x1; | ||
5062 | } else if (dev->phy.rev >= 3) { | ||
4502 | target.ipa[i] = (table[index[i]] >> 16) & 0xF; | 5063 | target.ipa[i] = (table[index[i]] >> 16) & 0xF; |
4503 | target.pad[i] = (table[index[i]] >> 20) & 0xF; | 5064 | target.pad[i] = (table[index[i]] >> 20) & 0xF; |
4504 | target.pga[i] = (table[index[i]] >> 24) & 0xF; | 5065 | target.pga[i] = (table[index[i]] >> 24) & 0xF; |
@@ -4547,6 +5108,8 @@ static void b43_nphy_tx_cal_phy_cleanup(struct b43_wldev *dev) | |||
4547 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhySetup */ | 5108 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhySetup */ |
4548 | static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev) | 5109 | static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev) |
4549 | { | 5110 | { |
5111 | struct b43_phy *phy = &dev->phy; | ||
5112 | struct b43_phy_n *nphy = dev->phy.n; | ||
4550 | u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs; | 5113 | u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs; |
4551 | u16 tmp; | 5114 | u16 tmp; |
4552 | 5115 | ||
@@ -4578,7 +5141,12 @@ static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev) | |||
4578 | regs[7] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1); | 5141 | regs[7] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1); |
4579 | regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2); | 5142 | regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2); |
4580 | 5143 | ||
4581 | b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_PA, 1, 3); | 5144 | if (!nphy->use_int_tx_iq_lo_cal) |
5145 | b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_PA, | ||
5146 | 1, 3); | ||
5147 | else | ||
5148 | b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_PA, | ||
5149 | 0, 3); | ||
4582 | b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, 2, 1); | 5150 | b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, 2, 1); |
4583 | b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, 8, 2); | 5151 | b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, 8, 2); |
4584 | 5152 | ||
@@ -4586,6 +5154,33 @@ static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev) | |||
4586 | regs[10] = b43_phy_read(dev, B43_NPHY_PAPD_EN1); | 5154 | regs[10] = b43_phy_read(dev, B43_NPHY_PAPD_EN1); |
4587 | b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x0001); | 5155 | b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x0001); |
4588 | b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x0001); | 5156 | b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x0001); |
5157 | |||
5158 | tmp = b43_nphy_read_lpf_ctl(dev, 0); | ||
5159 | if (phy->rev >= 19) | ||
5160 | b43_nphy_rf_ctl_override_rev19(dev, 0x80, tmp, 0, false, | ||
5161 | 1); | ||
5162 | else if (phy->rev >= 7) | ||
5163 | b43_nphy_rf_ctl_override_rev7(dev, 0x80, tmp, 0, false, | ||
5164 | 1); | ||
5165 | |||
5166 | if (nphy->use_int_tx_iq_lo_cal && true /* FIXME */) { | ||
5167 | if (phy->rev >= 19) { | ||
5168 | b43_nphy_rf_ctl_override_rev19(dev, 0x8, 0, 0x3, | ||
5169 | false, 0); | ||
5170 | } else if (phy->rev >= 8) { | ||
5171 | b43_nphy_rf_ctl_override_rev7(dev, 0x8, 0, 0x3, | ||
5172 | false, 0); | ||
5173 | } else if (phy->rev == 7) { | ||
5174 | b43_radio_maskset(dev, R2057_OVR_REG0, 1 << 4, 1 << 4); | ||
5175 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { | ||
5176 | b43_radio_maskset(dev, R2057_PAD2G_TUNE_PUS_CORE0, ~1, 0); | ||
5177 | b43_radio_maskset(dev, R2057_PAD2G_TUNE_PUS_CORE1, ~1, 0); | ||
5178 | } else { | ||
5179 | b43_radio_maskset(dev, R2057_IPA5G_CASCOFFV_PU_CORE0, ~1, 0); | ||
5180 | b43_radio_maskset(dev, R2057_IPA5G_CASCOFFV_PU_CORE1, ~1, 0); | ||
5181 | } | ||
5182 | } | ||
5183 | } | ||
4589 | } else { | 5184 | } else { |
4590 | b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, 0xA000); | 5185 | b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, 0xA000); |
4591 | b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, 0xA000); | 5186 | b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, 0xA000); |
@@ -4614,6 +5209,7 @@ static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev) | |||
4614 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SaveCal */ | 5209 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SaveCal */ |
4615 | static void b43_nphy_save_cal(struct b43_wldev *dev) | 5210 | static void b43_nphy_save_cal(struct b43_wldev *dev) |
4616 | { | 5211 | { |
5212 | struct b43_phy *phy = &dev->phy; | ||
4617 | struct b43_phy_n *nphy = dev->phy.n; | 5213 | struct b43_phy_n *nphy = dev->phy.n; |
4618 | 5214 | ||
4619 | struct b43_phy_n_iq_comp *rxcal_coeffs = NULL; | 5215 | struct b43_phy_n_iq_comp *rxcal_coeffs = NULL; |
@@ -4638,7 +5234,26 @@ static void b43_nphy_save_cal(struct b43_wldev *dev) | |||
4638 | 5234 | ||
4639 | b43_nphy_rx_iq_coeffs(dev, false, rxcal_coeffs); | 5235 | b43_nphy_rx_iq_coeffs(dev, false, rxcal_coeffs); |
4640 | /* TODO use some definitions */ | 5236 | /* TODO use some definitions */ |
4641 | if (dev->phy.rev >= 3) { | 5237 | if (phy->rev >= 19) { |
5238 | /* TODO */ | ||
5239 | } else if (phy->rev >= 7) { | ||
5240 | txcal_radio_regs[0] = b43_radio_read(dev, | ||
5241 | R2057_TX0_LOFT_FINE_I); | ||
5242 | txcal_radio_regs[1] = b43_radio_read(dev, | ||
5243 | R2057_TX0_LOFT_FINE_Q); | ||
5244 | txcal_radio_regs[4] = b43_radio_read(dev, | ||
5245 | R2057_TX0_LOFT_COARSE_I); | ||
5246 | txcal_radio_regs[5] = b43_radio_read(dev, | ||
5247 | R2057_TX0_LOFT_COARSE_Q); | ||
5248 | txcal_radio_regs[2] = b43_radio_read(dev, | ||
5249 | R2057_TX1_LOFT_FINE_I); | ||
5250 | txcal_radio_regs[3] = b43_radio_read(dev, | ||
5251 | R2057_TX1_LOFT_FINE_Q); | ||
5252 | txcal_radio_regs[6] = b43_radio_read(dev, | ||
5253 | R2057_TX1_LOFT_COARSE_I); | ||
5254 | txcal_radio_regs[7] = b43_radio_read(dev, | ||
5255 | R2057_TX1_LOFT_COARSE_Q); | ||
5256 | } else if (phy->rev >= 3) { | ||
4642 | txcal_radio_regs[0] = b43_radio_read(dev, 0x2021); | 5257 | txcal_radio_regs[0] = b43_radio_read(dev, 0x2021); |
4643 | txcal_radio_regs[1] = b43_radio_read(dev, 0x2022); | 5258 | txcal_radio_regs[1] = b43_radio_read(dev, 0x2022); |
4644 | txcal_radio_regs[2] = b43_radio_read(dev, 0x3021); | 5259 | txcal_radio_regs[2] = b43_radio_read(dev, 0x3021); |
@@ -4665,6 +5280,7 @@ static void b43_nphy_save_cal(struct b43_wldev *dev) | |||
4665 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreCal */ | 5280 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreCal */ |
4666 | static void b43_nphy_restore_cal(struct b43_wldev *dev) | 5281 | static void b43_nphy_restore_cal(struct b43_wldev *dev) |
4667 | { | 5282 | { |
5283 | struct b43_phy *phy = &dev->phy; | ||
4668 | struct b43_phy_n *nphy = dev->phy.n; | 5284 | struct b43_phy_n *nphy = dev->phy.n; |
4669 | 5285 | ||
4670 | u16 coef[4]; | 5286 | u16 coef[4]; |
@@ -4712,7 +5328,26 @@ static void b43_nphy_restore_cal(struct b43_wldev *dev) | |||
4712 | } | 5328 | } |
4713 | 5329 | ||
4714 | /* TODO use some definitions */ | 5330 | /* TODO use some definitions */ |
4715 | if (dev->phy.rev >= 3) { | 5331 | if (phy->rev >= 19) { |
5332 | /* TODO */ | ||
5333 | } else if (phy->rev >= 7) { | ||
5334 | b43_radio_write(dev, R2057_TX0_LOFT_FINE_I, | ||
5335 | txcal_radio_regs[0]); | ||
5336 | b43_radio_write(dev, R2057_TX0_LOFT_FINE_Q, | ||
5337 | txcal_radio_regs[1]); | ||
5338 | b43_radio_write(dev, R2057_TX0_LOFT_COARSE_I, | ||
5339 | txcal_radio_regs[4]); | ||
5340 | b43_radio_write(dev, R2057_TX0_LOFT_COARSE_Q, | ||
5341 | txcal_radio_regs[5]); | ||
5342 | b43_radio_write(dev, R2057_TX1_LOFT_FINE_I, | ||
5343 | txcal_radio_regs[2]); | ||
5344 | b43_radio_write(dev, R2057_TX1_LOFT_FINE_Q, | ||
5345 | txcal_radio_regs[3]); | ||
5346 | b43_radio_write(dev, R2057_TX1_LOFT_COARSE_I, | ||
5347 | txcal_radio_regs[6]); | ||
5348 | b43_radio_write(dev, R2057_TX1_LOFT_COARSE_Q, | ||
5349 | txcal_radio_regs[7]); | ||
5350 | } else if (phy->rev >= 3) { | ||
4716 | b43_radio_write(dev, 0x2021, txcal_radio_regs[0]); | 5351 | b43_radio_write(dev, 0x2021, txcal_radio_regs[0]); |
4717 | b43_radio_write(dev, 0x2022, txcal_radio_regs[1]); | 5352 | b43_radio_write(dev, 0x2022, txcal_radio_regs[1]); |
4718 | b43_radio_write(dev, 0x3021, txcal_radio_regs[2]); | 5353 | b43_radio_write(dev, 0x3021, txcal_radio_regs[2]); |
@@ -4789,7 +5424,13 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev, | |||
4789 | } | 5424 | } |
4790 | } | 5425 | } |
4791 | 5426 | ||
4792 | b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8AA9); | 5427 | if (phy->rev >= 19) { |
5428 | /* TODO */ | ||
5429 | } else if (phy->rev >= 7) { | ||
5430 | b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8AD9); | ||
5431 | } else { | ||
5432 | b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8AA9); | ||
5433 | } | ||
4793 | 5434 | ||
4794 | if (!b43_is_40mhz(dev)) | 5435 | if (!b43_is_40mhz(dev)) |
4795 | freq = 2500; | 5436 | freq = 2500; |
@@ -5183,6 +5824,9 @@ static int b43_nphy_rev3_cal_rx_iq(struct b43_wldev *dev, | |||
5183 | static int b43_nphy_cal_rx_iq(struct b43_wldev *dev, | 5824 | static int b43_nphy_cal_rx_iq(struct b43_wldev *dev, |
5184 | struct nphy_txgains target, u8 type, bool debug) | 5825 | struct nphy_txgains target, u8 type, bool debug) |
5185 | { | 5826 | { |
5827 | if (dev->phy.rev >= 7) | ||
5828 | type = 0; | ||
5829 | |||
5186 | if (dev->phy.rev >= 3) | 5830 | if (dev->phy.rev >= 3) |
5187 | return b43_nphy_rev3_cal_rx_iq(dev, target, type, debug); | 5831 | return b43_nphy_rev3_cal_rx_iq(dev, target, type, debug); |
5188 | else | 5832 | else |
@@ -5269,6 +5913,9 @@ static void b43_nphy_bphy_init(struct b43_wldev *dev) | |||
5269 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SuperSwitchInit */ | 5913 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SuperSwitchInit */ |
5270 | static void b43_nphy_superswitch_init(struct b43_wldev *dev, bool init) | 5914 | static void b43_nphy_superswitch_init(struct b43_wldev *dev, bool init) |
5271 | { | 5915 | { |
5916 | if (dev->phy.rev >= 7) | ||
5917 | return; | ||
5918 | |||
5272 | if (dev->phy.rev >= 3) { | 5919 | if (dev->phy.rev >= 3) { |
5273 | if (!init) | 5920 | if (!init) |
5274 | return; | 5921 | return; |
@@ -5344,6 +5991,10 @@ static int b43_phy_initn(struct b43_wldev *dev) | |||
5344 | #endif | 5991 | #endif |
5345 | } | 5992 | } |
5346 | } | 5993 | } |
5994 | nphy->use_int_tx_iq_lo_cal = b43_nphy_ipa(dev) || | ||
5995 | phy->rev >= 7 || | ||
5996 | (phy->rev >= 5 && | ||
5997 | sprom->boardflags2_hi & B43_BFH2_INTERNDET_TXIQCAL); | ||
5347 | nphy->deaf_count = 0; | 5998 | nphy->deaf_count = 0; |
5348 | b43_nphy_tables_init(dev); | 5999 | b43_nphy_tables_init(dev); |
5349 | nphy->crsminpwr_adjusted = false; | 6000 | nphy->crsminpwr_adjusted = false; |
@@ -5353,6 +6004,16 @@ static int b43_phy_initn(struct b43_wldev *dev) | |||
5353 | if (dev->phy.rev >= 3) { | 6004 | if (dev->phy.rev >= 3) { |
5354 | b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S1, 0); | 6005 | b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S1, 0); |
5355 | b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0); | 6006 | b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0); |
6007 | if (phy->rev >= 7) { | ||
6008 | b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER3, 0); | ||
6009 | b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER4, 0); | ||
6010 | b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER5, 0); | ||
6011 | b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER6, 0); | ||
6012 | } | ||
6013 | if (phy->rev >= 19) { | ||
6014 | /* TODO */ | ||
6015 | } | ||
6016 | |||
5356 | b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, 0); | 6017 | b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, 0); |
5357 | b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, 0); | 6018 | b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, 0); |
5358 | } else { | 6019 | } else { |
@@ -5390,7 +6051,9 @@ static int b43_phy_initn(struct b43_wldev *dev) | |||
5390 | b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x50); | 6051 | b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x50); |
5391 | b43_phy_write(dev, B43_NPHY_TXRIFS_FRDEL, 0x30); | 6052 | b43_phy_write(dev, B43_NPHY_TXRIFS_FRDEL, 0x30); |
5392 | 6053 | ||
5393 | b43_nphy_update_mimo_config(dev, nphy->preamble_override); | 6054 | if (phy->rev < 8) |
6055 | b43_nphy_update_mimo_config(dev, nphy->preamble_override); | ||
6056 | |||
5394 | b43_nphy_update_txrx_chain(dev); | 6057 | b43_nphy_update_txrx_chain(dev); |
5395 | 6058 | ||
5396 | if (phy->rev < 2) { | 6059 | if (phy->rev < 2) { |
@@ -5422,10 +6085,12 @@ static int b43_phy_initn(struct b43_wldev *dev) | |||
5422 | 6085 | ||
5423 | b43_mac_phy_clock_set(dev, true); | 6086 | b43_mac_phy_clock_set(dev, true); |
5424 | 6087 | ||
5425 | b43_nphy_pa_override(dev, false); | 6088 | if (phy->rev < 7) { |
5426 | b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX); | 6089 | b43_nphy_pa_override(dev, false); |
5427 | b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); | 6090 | b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX); |
5428 | b43_nphy_pa_override(dev, true); | 6091 | b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); |
6092 | b43_nphy_pa_override(dev, true); | ||
6093 | } | ||
5429 | 6094 | ||
5430 | b43_nphy_classifier(dev, 0, 0); | 6095 | b43_nphy_classifier(dev, 0, 0); |
5431 | b43_nphy_read_clip_detection(dev, clip); | 6096 | b43_nphy_read_clip_detection(dev, clip); |
@@ -5548,23 +6213,23 @@ static void b43_nphy_channel_setup(struct b43_wldev *dev, | |||
5548 | struct b43_phy *phy = &dev->phy; | 6213 | struct b43_phy *phy = &dev->phy; |
5549 | struct b43_phy_n *nphy = dev->phy.n; | 6214 | struct b43_phy_n *nphy = dev->phy.n; |
5550 | int ch = new_channel->hw_value; | 6215 | int ch = new_channel->hw_value; |
5551 | |||
5552 | u16 old_band_5ghz; | ||
5553 | u16 tmp16; | 6216 | u16 tmp16; |
5554 | 6217 | ||
5555 | old_band_5ghz = | 6218 | if (new_channel->band == IEEE80211_BAND_5GHZ) { |
5556 | b43_phy_read(dev, B43_NPHY_BANDCTL) & B43_NPHY_BANDCTL_5GHZ; | ||
5557 | if (new_channel->band == IEEE80211_BAND_5GHZ && !old_band_5ghz) { | ||
5558 | tmp16 = b43_read16(dev, B43_MMIO_PSM_PHY_HDR); | 6219 | tmp16 = b43_read16(dev, B43_MMIO_PSM_PHY_HDR); |
5559 | b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16 | 4); | 6220 | b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16 | 4); |
5560 | b43_phy_set(dev, B43_PHY_B_BBCFG, 0xC000); | 6221 | /* Put BPHY in the reset */ |
6222 | b43_phy_set(dev, B43_PHY_B_BBCFG, | ||
6223 | B43_PHY_B_BBCFG_RSTCCA | B43_PHY_B_BBCFG_RSTRX); | ||
5561 | b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16); | 6224 | b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16); |
5562 | b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ); | 6225 | b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ); |
5563 | } else if (new_channel->band == IEEE80211_BAND_2GHZ && old_band_5ghz) { | 6226 | } else if (new_channel->band == IEEE80211_BAND_2GHZ) { |
5564 | b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ); | 6227 | b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ); |
5565 | tmp16 = b43_read16(dev, B43_MMIO_PSM_PHY_HDR); | 6228 | tmp16 = b43_read16(dev, B43_MMIO_PSM_PHY_HDR); |
5566 | b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16 | 4); | 6229 | b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16 | 4); |
5567 | b43_phy_mask(dev, B43_PHY_B_BBCFG, 0x3FFF); | 6230 | /* Take BPHY out of the reset */ |
6231 | b43_phy_mask(dev, B43_PHY_B_BBCFG, | ||
6232 | (u16)~(B43_PHY_B_BBCFG_RSTCCA | B43_PHY_B_BBCFG_RSTRX)); | ||
5568 | b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16); | 6233 | b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16); |
5569 | } | 6234 | } |
5570 | 6235 | ||
@@ -5589,31 +6254,45 @@ static void b43_nphy_channel_setup(struct b43_wldev *dev, | |||
5589 | 6254 | ||
5590 | if (dev->phy.rev >= 3 && | 6255 | if (dev->phy.rev >= 3 && |
5591 | dev->phy.n->spur_avoid != B43_SPUR_AVOID_DISABLE) { | 6256 | dev->phy.n->spur_avoid != B43_SPUR_AVOID_DISABLE) { |
5592 | bool avoid = false; | 6257 | u8 spuravoid = 0; |
6258 | |||
5593 | if (dev->phy.n->spur_avoid == B43_SPUR_AVOID_FORCE) { | 6259 | if (dev->phy.n->spur_avoid == B43_SPUR_AVOID_FORCE) { |
5594 | avoid = true; | 6260 | spuravoid = 1; |
5595 | } else if (!b43_is_40mhz(dev)) { | 6261 | } else if (phy->rev >= 19) { |
5596 | if ((ch >= 5 && ch <= 8) || ch == 13 || ch == 14) | 6262 | /* TODO */ |
5597 | avoid = true; | 6263 | } else if (phy->rev >= 18) { |
5598 | } else { /* 40MHz */ | 6264 | /* TODO */ |
5599 | if (nphy->aband_spurwar_en && | 6265 | } else if (phy->rev >= 17) { |
5600 | (ch == 38 || ch == 102 || ch == 118)) | 6266 | /* TODO: Off for channels 1-11, but check 12-14! */ |
5601 | avoid = dev->dev->chip_id == 0x4716; | 6267 | } else if (phy->rev >= 16) { |
6268 | /* TODO: Off for 2 GHz, but check 5 GHz! */ | ||
6269 | } else if (phy->rev >= 7) { | ||
6270 | if (!b43_is_40mhz(dev)) { /* 20MHz */ | ||
6271 | if (ch == 13 || ch == 14 || ch == 153) | ||
6272 | spuravoid = 1; | ||
6273 | } else { /* 40 MHz */ | ||
6274 | if (ch == 54) | ||
6275 | spuravoid = 1; | ||
6276 | } | ||
6277 | } else { | ||
6278 | if (!b43_is_40mhz(dev)) { /* 20MHz */ | ||
6279 | if ((ch >= 5 && ch <= 8) || ch == 13 || ch == 14) | ||
6280 | spuravoid = 1; | ||
6281 | } else { /* 40MHz */ | ||
6282 | if (nphy->aband_spurwar_en && | ||
6283 | (ch == 38 || ch == 102 || ch == 118)) | ||
6284 | spuravoid = dev->dev->chip_id == 0x4716; | ||
6285 | } | ||
5602 | } | 6286 | } |
5603 | 6287 | ||
5604 | b43_nphy_pmu_spur_avoid(dev, avoid); | 6288 | b43_nphy_pmu_spur_avoid(dev, spuravoid); |
5605 | 6289 | ||
5606 | if (dev->dev->chip_id == 43222 || dev->dev->chip_id == 43224 || | 6290 | b43_mac_switch_freq(dev, spuravoid); |
5607 | dev->dev->chip_id == 43225) { | ||
5608 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, | ||
5609 | avoid ? 0x5341 : 0x8889); | ||
5610 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8); | ||
5611 | } | ||
5612 | 6291 | ||
5613 | if (dev->phy.rev == 3 || dev->phy.rev == 4) | 6292 | if (dev->phy.rev == 3 || dev->phy.rev == 4) |
5614 | ; /* TODO: reset PLL */ | 6293 | ; /* TODO: reset PLL */ |
5615 | 6294 | ||
5616 | if (avoid) | 6295 | if (spuravoid) |
5617 | b43_phy_set(dev, B43_NPHY_BBCFG, B43_NPHY_BBCFG_RSTRX); | 6296 | b43_phy_set(dev, B43_NPHY_BBCFG, B43_NPHY_BBCFG_RSTRX); |
5618 | else | 6297 | else |
5619 | b43_phy_mask(dev, B43_NPHY_BBCFG, | 6298 | b43_phy_mask(dev, B43_NPHY_BBCFG, |
@@ -5644,7 +6323,10 @@ static int b43_nphy_set_channel(struct b43_wldev *dev, | |||
5644 | 6323 | ||
5645 | u8 tmp; | 6324 | u8 tmp; |
5646 | 6325 | ||
5647 | if (phy->rev >= 7) { | 6326 | if (phy->rev >= 19) { |
6327 | return -ESRCH; | ||
6328 | /* TODO */ | ||
6329 | } else if (phy->rev >= 7) { | ||
5648 | r2057_get_chantabent_rev7(dev, channel->center_freq, | 6330 | r2057_get_chantabent_rev7(dev, channel->center_freq, |
5649 | &tabent_r7, &tabent_r7_2g); | 6331 | &tabent_r7, &tabent_r7_2g); |
5650 | if (!tabent_r7 && !tabent_r7_2g) | 6332 | if (!tabent_r7 && !tabent_r7_2g) |
@@ -5681,7 +6363,9 @@ static int b43_nphy_set_channel(struct b43_wldev *dev, | |||
5681 | b43_phy_mask(dev, 0x310, (u16)~0x8000); | 6363 | b43_phy_mask(dev, 0x310, (u16)~0x8000); |
5682 | } | 6364 | } |
5683 | 6365 | ||
5684 | if (phy->rev >= 7) { | 6366 | if (phy->rev >= 19) { |
6367 | /* TODO */ | ||
6368 | } else if (phy->rev >= 7) { | ||
5685 | const struct b43_phy_n_sfo_cfg *phy_regs = tabent_r7 ? | 6369 | const struct b43_phy_n_sfo_cfg *phy_regs = tabent_r7 ? |
5686 | &(tabent_r7->phy_regs) : &(tabent_r7_2g->phy_regs); | 6370 | &(tabent_r7->phy_regs) : &(tabent_r7_2g->phy_regs); |
5687 | 6371 | ||
@@ -5834,7 +6518,7 @@ static void b43_nphy_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask, | |||
5834 | static u16 b43_nphy_op_radio_read(struct b43_wldev *dev, u16 reg) | 6518 | static u16 b43_nphy_op_radio_read(struct b43_wldev *dev, u16 reg) |
5835 | { | 6519 | { |
5836 | /* Register 1 is a 32-bit register. */ | 6520 | /* Register 1 is a 32-bit register. */ |
5837 | B43_WARN_ON(reg == 1); | 6521 | B43_WARN_ON(dev->phy.rev < 7 && reg == 1); |
5838 | 6522 | ||
5839 | if (dev->phy.rev >= 7) | 6523 | if (dev->phy.rev >= 7) |
5840 | reg |= 0x200; /* Radio 0x2057 */ | 6524 | reg |= 0x200; /* Radio 0x2057 */ |
@@ -5848,7 +6532,7 @@ static u16 b43_nphy_op_radio_read(struct b43_wldev *dev, u16 reg) | |||
5848 | static void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value) | 6532 | static void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value) |
5849 | { | 6533 | { |
5850 | /* Register 1 is a 32-bit register. */ | 6534 | /* Register 1 is a 32-bit register. */ |
5851 | B43_WARN_ON(reg == 1); | 6535 | B43_WARN_ON(dev->phy.rev < 7 && reg == 1); |
5852 | 6536 | ||
5853 | b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg); | 6537 | b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg); |
5854 | b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value); | 6538 | b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value); |
@@ -5858,15 +6542,23 @@ static void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value) | |||
5858 | static void b43_nphy_op_software_rfkill(struct b43_wldev *dev, | 6542 | static void b43_nphy_op_software_rfkill(struct b43_wldev *dev, |
5859 | bool blocked) | 6543 | bool blocked) |
5860 | { | 6544 | { |
6545 | struct b43_phy *phy = &dev->phy; | ||
6546 | |||
5861 | if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED) | 6547 | if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED) |
5862 | b43err(dev->wl, "MAC not suspended\n"); | 6548 | b43err(dev->wl, "MAC not suspended\n"); |
5863 | 6549 | ||
5864 | if (blocked) { | 6550 | if (blocked) { |
5865 | b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, | 6551 | if (phy->rev >= 19) { |
5866 | ~B43_NPHY_RFCTL_CMD_CHIP0PU); | ||
5867 | if (dev->phy.rev >= 7) { | ||
5868 | /* TODO */ | 6552 | /* TODO */ |
5869 | } else if (dev->phy.rev >= 3) { | 6553 | } else if (phy->rev >= 8) { |
6554 | b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, | ||
6555 | ~B43_NPHY_RFCTL_CMD_CHIP0PU); | ||
6556 | } else if (phy->rev >= 7) { | ||
6557 | /* Nothing needed */ | ||
6558 | } else if (phy->rev >= 3) { | ||
6559 | b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, | ||
6560 | ~B43_NPHY_RFCTL_CMD_CHIP0PU); | ||
6561 | |||
5870 | b43_radio_mask(dev, 0x09, ~0x2); | 6562 | b43_radio_mask(dev, 0x09, ~0x2); |
5871 | 6563 | ||
5872 | b43_radio_write(dev, 0x204D, 0); | 6564 | b43_radio_write(dev, 0x204D, 0); |
@@ -5884,11 +6576,13 @@ static void b43_nphy_op_software_rfkill(struct b43_wldev *dev, | |||
5884 | b43_radio_write(dev, 0x3064, 0); | 6576 | b43_radio_write(dev, 0x3064, 0); |
5885 | } | 6577 | } |
5886 | } else { | 6578 | } else { |
5887 | if (dev->phy.rev >= 7) { | 6579 | if (phy->rev >= 19) { |
6580 | /* TODO */ | ||
6581 | } else if (phy->rev >= 7) { | ||
5888 | if (!dev->phy.radio_on) | 6582 | if (!dev->phy.radio_on) |
5889 | b43_radio_2057_init(dev); | 6583 | b43_radio_2057_init(dev); |
5890 | b43_switch_channel(dev, dev->phy.channel); | 6584 | b43_switch_channel(dev, dev->phy.channel); |
5891 | } else if (dev->phy.rev >= 3) { | 6585 | } else if (phy->rev >= 3) { |
5892 | if (!dev->phy.radio_on) | 6586 | if (!dev->phy.radio_on) |
5893 | b43_radio_init2056(dev); | 6587 | b43_radio_init2056(dev); |
5894 | b43_switch_channel(dev, dev->phy.channel); | 6588 | b43_switch_channel(dev, dev->phy.channel); |
@@ -5901,10 +6595,13 @@ static void b43_nphy_op_software_rfkill(struct b43_wldev *dev, | |||
5901 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/Anacore */ | 6595 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/Anacore */ |
5902 | static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on) | 6596 | static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on) |
5903 | { | 6597 | { |
6598 | struct b43_phy *phy = &dev->phy; | ||
5904 | u16 override = on ? 0x0 : 0x7FFF; | 6599 | u16 override = on ? 0x0 : 0x7FFF; |
5905 | u16 core = on ? 0xD : 0x00FD; | 6600 | u16 core = on ? 0xD : 0x00FD; |
5906 | 6601 | ||
5907 | if (dev->phy.rev >= 3) { | 6602 | if (phy->rev >= 19) { |
6603 | /* TODO */ | ||
6604 | } else if (phy->rev >= 3) { | ||
5908 | if (on) { | 6605 | if (on) { |
5909 | b43_phy_write(dev, B43_NPHY_AFECTL_C1, core); | 6606 | b43_phy_write(dev, B43_NPHY_AFECTL_C1, core); |
5910 | b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, override); | 6607 | b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, override); |
diff --git a/drivers/net/wireless/b43/phy_n.h b/drivers/net/wireless/b43/phy_n.h index ecfbf66dbc3b..30bec815b969 100644 --- a/drivers/net/wireless/b43/phy_n.h +++ b/drivers/net/wireless/b43/phy_n.h | |||
@@ -366,11 +366,13 @@ | |||
366 | #define B43_NPHY_TXF_40CO_B1S0 B43_PHY_N(0x0E5) /* TX filter 40 coeff B1 stage 0 */ | 366 | #define B43_NPHY_TXF_40CO_B1S0 B43_PHY_N(0x0E5) /* TX filter 40 coeff B1 stage 0 */ |
367 | #define B43_NPHY_TXF_40CO_B32S1 B43_PHY_N(0x0E6) /* TX filter 40 coeff B32 stage 1 */ | 367 | #define B43_NPHY_TXF_40CO_B32S1 B43_PHY_N(0x0E6) /* TX filter 40 coeff B32 stage 1 */ |
368 | #define B43_NPHY_TXF_40CO_B1S1 B43_PHY_N(0x0E7) /* TX filter 40 coeff B1 stage 1 */ | 368 | #define B43_NPHY_TXF_40CO_B1S1 B43_PHY_N(0x0E7) /* TX filter 40 coeff B1 stage 1 */ |
369 | #define B43_NPHY_REV3_RFCTL_OVER0 B43_PHY_N(0x0E7) | ||
369 | #define B43_NPHY_TXF_40CO_B32S2 B43_PHY_N(0x0E8) /* TX filter 40 coeff B32 stage 2 */ | 370 | #define B43_NPHY_TXF_40CO_B32S2 B43_PHY_N(0x0E8) /* TX filter 40 coeff B32 stage 2 */ |
370 | #define B43_NPHY_TXF_40CO_B1S2 B43_PHY_N(0x0E9) /* TX filter 40 coeff B1 stage 2 */ | 371 | #define B43_NPHY_TXF_40CO_B1S2 B43_PHY_N(0x0E9) /* TX filter 40 coeff B1 stage 2 */ |
371 | #define B43_NPHY_BIST_STAT2 B43_PHY_N(0x0EA) /* BIST status 2 */ | 372 | #define B43_NPHY_BIST_STAT2 B43_PHY_N(0x0EA) /* BIST status 2 */ |
372 | #define B43_NPHY_BIST_STAT3 B43_PHY_N(0x0EB) /* BIST status 3 */ | 373 | #define B43_NPHY_BIST_STAT3 B43_PHY_N(0x0EB) /* BIST status 3 */ |
373 | #define B43_NPHY_RFCTL_OVER B43_PHY_N(0x0EC) /* RF control override */ | 374 | #define B43_NPHY_RFCTL_OVER B43_PHY_N(0x0EC) /* RF control override */ |
375 | #define B43_NPHY_REV3_RFCTL_OVER1 B43_PHY_N(0x0EC) | ||
374 | #define B43_NPHY_MIMOCFG B43_PHY_N(0x0ED) /* MIMO config */ | 376 | #define B43_NPHY_MIMOCFG B43_PHY_N(0x0ED) /* MIMO config */ |
375 | #define B43_NPHY_MIMOCFG_GFMIX 0x0004 /* Greenfield or mixed mode */ | 377 | #define B43_NPHY_MIMOCFG_GFMIX 0x0004 /* Greenfield or mixed mode */ |
376 | #define B43_NPHY_MIMOCFG_AUTO 0x0100 /* Greenfield/mixed mode auto */ | 378 | #define B43_NPHY_MIMOCFG_AUTO 0x0100 /* Greenfield/mixed mode auto */ |
@@ -857,7 +859,18 @@ | |||
857 | #define B43_NPHY_REV3_C2_CLIP2_GAIN_A B43_PHY_N(0x2AF) | 859 | #define B43_NPHY_REV3_C2_CLIP2_GAIN_A B43_PHY_N(0x2AF) |
858 | #define B43_NPHY_REV3_C2_CLIP2_GAIN_B B43_PHY_N(0x2B0) | 860 | #define B43_NPHY_REV3_C2_CLIP2_GAIN_B B43_PHY_N(0x2B0) |
859 | 861 | ||
862 | #define B43_NPHY_REV7_RF_CTL_MISC_REG3 B43_PHY_N(0x340) | ||
863 | #define B43_NPHY_REV7_RF_CTL_MISC_REG4 B43_PHY_N(0x341) | ||
864 | #define B43_NPHY_REV7_RF_CTL_OVER3 B43_PHY_N(0x342) | ||
865 | #define B43_NPHY_REV7_RF_CTL_OVER4 B43_PHY_N(0x343) | ||
866 | #define B43_NPHY_REV7_RF_CTL_MISC_REG5 B43_PHY_N(0x344) | ||
867 | #define B43_NPHY_REV7_RF_CTL_MISC_REG6 B43_PHY_N(0x345) | ||
868 | #define B43_NPHY_REV7_RF_CTL_OVER5 B43_PHY_N(0x346) | ||
869 | #define B43_NPHY_REV7_RF_CTL_OVER6 B43_PHY_N(0x347) | ||
870 | |||
860 | #define B43_PHY_B_BBCFG B43_PHY_N_BMODE(0x001) /* BB config */ | 871 | #define B43_PHY_B_BBCFG B43_PHY_N_BMODE(0x001) /* BB config */ |
872 | #define B43_PHY_B_BBCFG_RSTCCA 0x4000 /* Reset CCA */ | ||
873 | #define B43_PHY_B_BBCFG_RSTRX 0x8000 /* Reset RX */ | ||
861 | #define B43_PHY_B_TEST B43_PHY_N_BMODE(0x00A) | 874 | #define B43_PHY_B_TEST B43_PHY_N_BMODE(0x00A) |
862 | 875 | ||
863 | struct b43_wldev; | 876 | struct b43_wldev; |
@@ -935,6 +948,8 @@ struct b43_phy_n { | |||
935 | bool gain_boost; | 948 | bool gain_boost; |
936 | bool elna_gain_config; | 949 | bool elna_gain_config; |
937 | bool band5g_pwrgain; | 950 | bool band5g_pwrgain; |
951 | bool use_int_tx_iq_lo_cal; | ||
952 | bool lpf_bw_overrode_for_sample_play; | ||
938 | 953 | ||
939 | u8 mphase_cal_phase_id; | 954 | u8 mphase_cal_phase_id; |
940 | u16 mphase_txcal_cmdidx; | 955 | u16 mphase_txcal_cmdidx; |
diff --git a/drivers/net/wireless/b43/radio_2057.c b/drivers/net/wireless/b43/radio_2057.c index df3574545819..ff1e026a61a1 100644 --- a/drivers/net/wireless/b43/radio_2057.c +++ b/drivers/net/wireless/b43/radio_2057.c | |||
@@ -105,6 +105,27 @@ static u16 r2057_rev8_init[][2] = { | |||
105 | }; | 105 | }; |
106 | */ | 106 | */ |
107 | 107 | ||
108 | /* Extracted from MMIO dump of 6.30.223.141 */ | ||
109 | static u16 r2057_rev9_init[][2] = { | ||
110 | { 0x27, 0x1f }, { 0x28, 0x0a }, { 0x29, 0x2f }, { 0x42, 0x1f }, | ||
111 | { 0x48, 0x3f }, { 0x5c, 0x41 }, { 0x63, 0x14 }, { 0x64, 0x12 }, | ||
112 | { 0x66, 0xff }, { 0x74, 0xa3 }, { 0x7b, 0x14 }, { 0x7c, 0x14 }, | ||
113 | { 0x7d, 0xee }, { 0x86, 0xc0 }, { 0xc4, 0x10 }, { 0xc9, 0x01 }, | ||
114 | { 0xe1, 0x41 }, { 0xe8, 0x14 }, { 0xe9, 0x12 }, { 0xeb, 0xff }, | ||
115 | { 0xf5, 0x0a }, { 0xf8, 0x09 }, { 0xf9, 0xa3 }, { 0x100, 0x14 }, | ||
116 | { 0x101, 0x10 }, { 0x102, 0xee }, { 0x10b, 0xc0 }, { 0x149, 0x10 }, | ||
117 | { 0x14e, 0x01 }, { 0x1b7, 0x05 }, { 0x1c2, 0xa0 }, | ||
118 | }; | ||
119 | |||
120 | /* Extracted from MMIO dump of 6.30.223.248 */ | ||
121 | static u16 r2057_rev14_init[][2] = { | ||
122 | { 0x011, 0xfc }, { 0x030, 0x24 }, { 0x040, 0x1c }, { 0x082, 0x08 }, | ||
123 | { 0x0b4, 0x44 }, { 0x0c8, 0x01 }, { 0x0c9, 0x01 }, { 0x107, 0x08 }, | ||
124 | { 0x14d, 0x01 }, { 0x14e, 0x01 }, { 0x1af, 0x40 }, { 0x1b0, 0x40 }, | ||
125 | { 0x1cc, 0x01 }, { 0x1cf, 0x10 }, { 0x1d0, 0x0f }, { 0x1d3, 0x10 }, | ||
126 | { 0x1d4, 0x0f }, | ||
127 | }; | ||
128 | |||
108 | #define RADIOREGS7(r00, r01, r02, r03, r04, r05, r06, r07, r08, r09, \ | 129 | #define RADIOREGS7(r00, r01, r02, r03, r04, r05, r06, r07, r08, r09, \ |
109 | r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, \ | 130 | r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, \ |
110 | r20, r21, r22, r23, r24, r25, r26, r27) \ | 131 | r20, r21, r22, r23, r24, r25, r26, r27) \ |
@@ -137,6 +158,27 @@ static u16 r2057_rev8_init[][2] = { | |||
137 | .radio_lna2g_tune_core1 = r26, \ | 158 | .radio_lna2g_tune_core1 = r26, \ |
138 | .radio_lna5g_tune_core1 = r27 | 159 | .radio_lna5g_tune_core1 = r27 |
139 | 160 | ||
161 | #define RADIOREGS7_2G(r00, r01, r02, r03, r04, r05, r06, r07, r08, r09, \ | ||
162 | r10, r11, r12, r13, r14, r15, r16, r17) \ | ||
163 | .radio_vcocal_countval0 = r00, \ | ||
164 | .radio_vcocal_countval1 = r01, \ | ||
165 | .radio_rfpll_refmaster_sparextalsize = r02, \ | ||
166 | .radio_rfpll_loopfilter_r1 = r03, \ | ||
167 | .radio_rfpll_loopfilter_c2 = r04, \ | ||
168 | .radio_rfpll_loopfilter_c1 = r05, \ | ||
169 | .radio_cp_kpd_idac = r06, \ | ||
170 | .radio_rfpll_mmd0 = r07, \ | ||
171 | .radio_rfpll_mmd1 = r08, \ | ||
172 | .radio_vcobuf_tune = r09, \ | ||
173 | .radio_logen_mx2g_tune = r10, \ | ||
174 | .radio_logen_indbuf2g_tune = r11, \ | ||
175 | .radio_txmix2g_tune_boost_pu_core0 = r12, \ | ||
176 | .radio_pad2g_tune_pus_core0 = r13, \ | ||
177 | .radio_lna2g_tune_core0 = r14, \ | ||
178 | .radio_txmix2g_tune_boost_pu_core1 = r15, \ | ||
179 | .radio_pad2g_tune_pus_core1 = r16, \ | ||
180 | .radio_lna2g_tune_core1 = r17 | ||
181 | |||
140 | #define PHYREGS(r0, r1, r2, r3, r4, r5) \ | 182 | #define PHYREGS(r0, r1, r2, r3, r4, r5) \ |
141 | .phy_regs.phy_bw1a = r0, \ | 183 | .phy_regs.phy_bw1a = r0, \ |
142 | .phy_regs.phy_bw2 = r1, \ | 184 | .phy_regs.phy_bw2 = r1, \ |
@@ -145,6 +187,353 @@ static u16 r2057_rev8_init[][2] = { | |||
145 | .phy_regs.phy_bw5 = r4, \ | 187 | .phy_regs.phy_bw5 = r4, \ |
146 | .phy_regs.phy_bw6 = r5 | 188 | .phy_regs.phy_bw6 = r5 |
147 | 189 | ||
190 | /* Copied from brcmsmac (5.75.11): chan_info_nphyrev8_2057_rev5 */ | ||
191 | static const struct b43_nphy_chantabent_rev7_2g b43_nphy_chantab_phy_rev8_radio_rev5[] = { | ||
192 | { | ||
193 | .freq = 2412, | ||
194 | RADIOREGS7_2G(0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, | ||
195 | 0x09, 0x0d, 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, | ||
196 | 0x03, 0xff), | ||
197 | PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443), | ||
198 | }, | ||
199 | { | ||
200 | .freq = 2417, | ||
201 | RADIOREGS7_2G(0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, | ||
202 | 0x09, 0x0d, 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, | ||
203 | 0x03, 0xff), | ||
204 | PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441), | ||
205 | }, | ||
206 | { | ||
207 | .freq = 2422, | ||
208 | RADIOREGS7_2G(0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, | ||
209 | 0x09, 0x0d, 0x08, 0x0e, 0x61, 0x03, 0xef, 0x61, | ||
210 | 0x03, 0xef), | ||
211 | PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f), | ||
212 | }, | ||
213 | { | ||
214 | .freq = 2427, | ||
215 | RADIOREGS7_2G(0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, | ||
216 | 0x09, 0x0c, 0x08, 0x0e, 0x61, 0x03, 0xdf, 0x61, | ||
217 | 0x03, 0xdf), | ||
218 | PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d), | ||
219 | }, | ||
220 | { | ||
221 | .freq = 2432, | ||
222 | RADIOREGS7_2G(0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, | ||
223 | 0x09, 0x0c, 0x07, 0x0d, 0x61, 0x03, 0xcf, 0x61, | ||
224 | 0x03, 0xcf), | ||
225 | PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a), | ||
226 | }, | ||
227 | { | ||
228 | .freq = 2437, | ||
229 | RADIOREGS7_2G(0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, | ||
230 | 0x09, 0x0c, 0x07, 0x0d, 0x61, 0x03, 0xbf, 0x61, | ||
231 | 0x03, 0xbf), | ||
232 | PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438), | ||
233 | }, | ||
234 | { | ||
235 | .freq = 2442, | ||
236 | RADIOREGS7_2G(0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, | ||
237 | 0x09, 0x0b, 0x07, 0x0d, 0x61, 0x03, 0xaf, 0x61, | ||
238 | 0x03, 0xaf), | ||
239 | PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436), | ||
240 | }, | ||
241 | { | ||
242 | .freq = 2447, | ||
243 | RADIOREGS7_2G(0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, | ||
244 | 0x09, 0x0b, 0x07, 0x0d, 0x61, 0x03, 0x9f, 0x61, | ||
245 | 0x03, 0x9f), | ||
246 | PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434), | ||
247 | }, | ||
248 | { | ||
249 | .freq = 2452, | ||
250 | RADIOREGS7_2G(0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, | ||
251 | 0x09, 0x0b, 0x07, 0x0d, 0x61, 0x03, 0x8f, 0x61, | ||
252 | 0x03, 0x8f), | ||
253 | PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431), | ||
254 | }, | ||
255 | { | ||
256 | .freq = 2457, | ||
257 | RADIOREGS7_2G(0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, | ||
258 | 0x09, 0x0b, 0x07, 0x0c, 0x61, 0x03, 0x7f, 0x61, | ||
259 | 0x03, 0x7f), | ||
260 | PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f), | ||
261 | }, | ||
262 | { | ||
263 | .freq = 2462, | ||
264 | RADIOREGS7_2G(0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, | ||
265 | 0x09, 0x0b, 0x07, 0x0c, 0x61, 0x03, 0x6f, 0x61, | ||
266 | 0x03, 0x6f), | ||
267 | PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d), | ||
268 | }, | ||
269 | { | ||
270 | .freq = 2467, | ||
271 | RADIOREGS7_2G(0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, | ||
272 | 0x09, 0x0b, 0x06, 0x0c, 0x61, 0x03, 0x5f, 0x61, | ||
273 | 0x03, 0x5f), | ||
274 | PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b), | ||
275 | }, | ||
276 | { | ||
277 | .freq = 2472, | ||
278 | RADIOREGS7_2G(0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, | ||
279 | 0x09, 0x0a, 0x06, 0x0b, 0x61, 0x03, 0x4f, 0x61, | ||
280 | 0x03, 0x4f), | ||
281 | PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429), | ||
282 | }, | ||
283 | { | ||
284 | .freq = 2484, | ||
285 | RADIOREGS7_2G(0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, | ||
286 | 0x09, 0x0a, 0x06, 0x0b, 0x61, 0x03, 0x3f, 0x61, | ||
287 | 0x03, 0x3f), | ||
288 | PHYREGS(0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424), | ||
289 | } | ||
290 | }; | ||
291 | |||
292 | /* Extracted from MMIO dump of 6.30.223.248 */ | ||
293 | static const struct b43_nphy_chantabent_rev7_2g b43_nphy_chantab_phy_rev17_radio_rev14[] = { | ||
294 | { | ||
295 | .freq = 2412, | ||
296 | RADIOREGS7_2G(0x48, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x6c, | ||
297 | 0x09, 0x0d, 0x09, 0x03, 0x21, 0x53, 0xff, 0x21, | ||
298 | 0x53, 0xff), | ||
299 | PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443), | ||
300 | }, | ||
301 | { | ||
302 | .freq = 2417, | ||
303 | RADIOREGS7_2G(0x4b, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x71, | ||
304 | 0x09, 0x0d, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21, | ||
305 | 0x53, 0xff), | ||
306 | PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441), | ||
307 | }, | ||
308 | { | ||
309 | .freq = 2422, | ||
310 | RADIOREGS7_2G(0x4e, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x76, | ||
311 | 0x09, 0x0d, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21, | ||
312 | 0x53, 0xff), | ||
313 | PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f), | ||
314 | }, | ||
315 | { | ||
316 | .freq = 2427, | ||
317 | RADIOREGS7_2G(0x52, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x7b, | ||
318 | 0x09, 0x0c, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21, | ||
319 | 0x53, 0xff), | ||
320 | PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d), | ||
321 | }, | ||
322 | { | ||
323 | .freq = 2432, | ||
324 | RADIOREGS7_2G(0x55, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x80, | ||
325 | 0x09, 0x0c, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21, | ||
326 | 0x53, 0xff), | ||
327 | PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a), | ||
328 | }, | ||
329 | { | ||
330 | .freq = 2437, | ||
331 | RADIOREGS7_2G(0x58, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x85, | ||
332 | 0x09, 0x0c, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21, | ||
333 | 0x53, 0xff), | ||
334 | PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438), | ||
335 | }, | ||
336 | { | ||
337 | .freq = 2442, | ||
338 | RADIOREGS7_2G(0x5c, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x8a, | ||
339 | 0x09, 0x0c, 0x08, 0x03, 0x21, 0x43, 0xff, 0x21, | ||
340 | 0x43, 0xff), | ||
341 | PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436), | ||
342 | }, | ||
343 | { | ||
344 | .freq = 2447, | ||
345 | RADIOREGS7_2G(0x5f, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x8f, | ||
346 | 0x09, 0x0c, 0x08, 0x03, 0x21, 0x43, 0xff, 0x21, | ||
347 | 0x43, 0xff), | ||
348 | PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434), | ||
349 | }, | ||
350 | { | ||
351 | .freq = 2452, | ||
352 | RADIOREGS7_2G(0x62, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x94, | ||
353 | 0x09, 0x0c, 0x08, 0x03, 0x21, 0x43, 0xff, 0x21, | ||
354 | 0x43, 0xff), | ||
355 | PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431), | ||
356 | }, | ||
357 | { | ||
358 | .freq = 2457, | ||
359 | RADIOREGS7_2G(0x66, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x99, | ||
360 | 0x09, 0x0b, 0x07, 0x03, 0x21, 0x43, 0xff, 0x21, | ||
361 | 0x43, 0xff), | ||
362 | PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f), | ||
363 | }, | ||
364 | { | ||
365 | .freq = 2462, | ||
366 | RADIOREGS7_2G(0x69, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x9e, | ||
367 | 0x09, 0x0b, 0x07, 0x03, 0x01, 0x43, 0xff, 0x01, | ||
368 | 0x43, 0xff), | ||
369 | PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d), | ||
370 | }, | ||
371 | }; | ||
372 | |||
373 | /* Extracted from MMIO dump of 6.30.223.141 */ | ||
374 | static const struct b43_nphy_chantabent_rev7 b43_nphy_chantab_phy_rev16_radio_rev9[] = { | ||
375 | { | ||
376 | .freq = 2412, | ||
377 | RADIOREGS7(0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, | ||
378 | 0x09, 0x0f, 0x0a, 0x00, 0x0a, 0x00, 0x41, 0x63, | ||
379 | 0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00, | ||
380 | 0x00, 0x00, 0xf0, 0x00), | ||
381 | PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443), | ||
382 | }, | ||
383 | { | ||
384 | .freq = 2417, | ||
385 | RADIOREGS7(0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, | ||
386 | 0x09, 0x0f, 0x0a, 0x00, 0x0a, 0x00, 0x41, 0x63, | ||
387 | 0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00, | ||
388 | 0x00, 0x00, 0xf0, 0x00), | ||
389 | PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441), | ||
390 | }, | ||
391 | { | ||
392 | .freq = 2422, | ||
393 | RADIOREGS7(0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, | ||
394 | 0x09, 0x0f, 0x09, 0x00, 0x09, 0x00, 0x41, 0x63, | ||
395 | 0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00, | ||
396 | 0x00, 0x00, 0xf0, 0x00), | ||
397 | PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f), | ||
398 | }, | ||
399 | { | ||
400 | .freq = 2427, | ||
401 | RADIOREGS7(0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, | ||
402 | 0x09, 0x0f, 0x09, 0x00, 0x09, 0x00, 0x41, 0x63, | ||
403 | 0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00, | ||
404 | 0x00, 0x00, 0xf0, 0x00), | ||
405 | PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d), | ||
406 | }, | ||
407 | { | ||
408 | .freq = 2432, | ||
409 | RADIOREGS7(0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, | ||
410 | 0x09, 0x0f, 0x08, 0x00, 0x08, 0x00, 0x41, 0x63, | ||
411 | 0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00, | ||
412 | 0x00, 0x00, 0xf0, 0x00), | ||
413 | PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a), | ||
414 | }, | ||
415 | { | ||
416 | .freq = 2437, | ||
417 | RADIOREGS7(0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, | ||
418 | 0x09, 0x0f, 0x08, 0x00, 0x08, 0x00, 0x41, 0x63, | ||
419 | 0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00, | ||
420 | 0x00, 0x00, 0xf0, 0x00), | ||
421 | PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438), | ||
422 | }, | ||
423 | { | ||
424 | .freq = 2442, | ||
425 | RADIOREGS7(0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, | ||
426 | 0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x41, 0x63, | ||
427 | 0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00, | ||
428 | 0x00, 0x00, 0xf0, 0x00), | ||
429 | PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436), | ||
430 | }, | ||
431 | { | ||
432 | .freq = 2447, | ||
433 | RADIOREGS7(0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, | ||
434 | 0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x41, 0x63, | ||
435 | 0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00, | ||
436 | 0x00, 0x00, 0xf0, 0x00), | ||
437 | PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434), | ||
438 | }, | ||
439 | { | ||
440 | .freq = 2452, | ||
441 | RADIOREGS7(0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, | ||
442 | 0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x41, 0x63, | ||
443 | 0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00, | ||
444 | 0x00, 0x00, 0xf0, 0x00), | ||
445 | PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431), | ||
446 | }, | ||
447 | { | ||
448 | .freq = 2457, | ||
449 | RADIOREGS7(0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, | ||
450 | 0x09, 0x0f, 0x06, 0x00, 0x06, 0x00, 0x41, 0x63, | ||
451 | 0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00, | ||
452 | 0x00, 0x00, 0xf0, 0x00), | ||
453 | PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f), | ||
454 | }, | ||
455 | { | ||
456 | .freq = 2462, | ||
457 | RADIOREGS7(0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, | ||
458 | 0x09, 0x0f, 0x06, 0x00, 0x06, 0x00, 0x41, 0x63, | ||
459 | 0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00, | ||
460 | 0x00, 0x00, 0xf0, 0x00), | ||
461 | PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d), | ||
462 | }, | ||
463 | { | ||
464 | .freq = 5180, | ||
465 | RADIOREGS7(0xbe, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x06, | ||
466 | 0x02, 0x0e, 0x00, 0x0e, 0x00, 0x9e, 0x00, 0x00, | ||
467 | 0x9f, 0x2f, 0xa3, 0x00, 0xfc, 0x00, 0x00, 0x4f, | ||
468 | 0x3a, 0x83, 0x00, 0xfc), | ||
469 | PHYREGS(0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb), | ||
470 | }, | ||
471 | { | ||
472 | .freq = 5200, | ||
473 | RADIOREGS7(0xc5, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x08, | ||
474 | 0x02, 0x0e, 0x00, 0x0e, 0x00, 0x9e, 0x00, 0x00, | ||
475 | 0x7f, 0x2f, 0x83, 0x00, 0xf8, 0x00, 0x00, 0x4c, | ||
476 | 0x4a, 0x83, 0x00, 0xf8), | ||
477 | PHYREGS(0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9), | ||
478 | }, | ||
479 | { | ||
480 | .freq = 5220, | ||
481 | RADIOREGS7(0xcc, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x0a, | ||
482 | 0x02, 0x0e, 0x00, 0x0e, 0x00, 0x9e, 0x00, 0x00, | ||
483 | 0x6d, 0x3d, 0x83, 0x00, 0xf8, 0x00, 0x00, 0x2d, | ||
484 | 0x2a, 0x73, 0x00, 0xf8), | ||
485 | PHYREGS(0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7), | ||
486 | }, | ||
487 | { | ||
488 | .freq = 5240, | ||
489 | RADIOREGS7(0xd2, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x0c, | ||
490 | 0x02, 0x0d, 0x00, 0x0d, 0x00, 0x8d, 0x00, 0x00, | ||
491 | 0x4d, 0x1c, 0x73, 0x00, 0xf8, 0x00, 0x00, 0x4d, | ||
492 | 0x2b, 0x73, 0x00, 0xf8), | ||
493 | PHYREGS(0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5), | ||
494 | }, | ||
495 | { | ||
496 | .freq = 5745, | ||
497 | RADIOREGS7(0x7b, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x7d, | ||
498 | 0x04, 0x08, 0x00, 0x06, 0x00, 0x15, 0x00, 0x00, | ||
499 | 0x08, 0x03, 0x03, 0x00, 0x30, 0x00, 0x00, 0x06, | ||
500 | 0x02, 0x03, 0x00, 0x30), | ||
501 | PHYREGS(0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9), | ||
502 | }, | ||
503 | { | ||
504 | .freq = 5765, | ||
505 | RADIOREGS7(0x81, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x81, | ||
506 | 0x04, 0x08, 0x00, 0x06, 0x00, 0x15, 0x00, 0x00, | ||
507 | 0x06, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x05, | ||
508 | 0x02, 0x03, 0x00, 0x00), | ||
509 | PHYREGS(0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8), | ||
510 | }, | ||
511 | { | ||
512 | .freq = 5785, | ||
513 | RADIOREGS7(0x88, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x85, | ||
514 | 0x04, 0x08, 0x00, 0x06, 0x00, 0x15, 0x00, 0x00, | ||
515 | 0x08, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x05, | ||
516 | 0x21, 0x03, 0x00, 0x00), | ||
517 | PHYREGS(0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6), | ||
518 | }, | ||
519 | { | ||
520 | .freq = 5805, | ||
521 | RADIOREGS7(0x8f, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x89, | ||
522 | 0x04, 0x07, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00, | ||
523 | 0x06, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, | ||
524 | 0x00, 0x03, 0x00, 0x00), | ||
525 | PHYREGS(0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4), | ||
526 | }, | ||
527 | { | ||
528 | .freq = 5825, | ||
529 | RADIOREGS7(0x95, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x8d, | ||
530 | 0x04, 0x07, 0x00, 0x05, 0x00, 0x03, 0x00, 0x00, | ||
531 | 0x05, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, | ||
532 | 0x00, 0x03, 0x00, 0x00), | ||
533 | PHYREGS(0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3), | ||
534 | }, | ||
535 | }; | ||
536 | |||
148 | void r2057_upload_inittabs(struct b43_wldev *dev) | 537 | void r2057_upload_inittabs(struct b43_wldev *dev) |
149 | { | 538 | { |
150 | struct b43_phy *phy = &dev->phy; | 539 | struct b43_phy *phy = &dev->phy; |
@@ -171,6 +560,18 @@ void r2057_upload_inittabs(struct b43_wldev *dev) | |||
171 | size = ARRAY_SIZE(r2057_rev5a_init); | 560 | size = ARRAY_SIZE(r2057_rev5a_init); |
172 | } | 561 | } |
173 | break; | 562 | break; |
563 | case 16: | ||
564 | if (phy->radio_rev == 9) { | ||
565 | table = r2057_rev9_init[0]; | ||
566 | size = ARRAY_SIZE(r2057_rev9_init); | ||
567 | } | ||
568 | break; | ||
569 | case 17: | ||
570 | if (phy->radio_rev == 14) { | ||
571 | table = r2057_rev14_init[0]; | ||
572 | size = ARRAY_SIZE(r2057_rev14_init); | ||
573 | } | ||
574 | break; | ||
174 | } | 575 | } |
175 | 576 | ||
176 | B43_WARN_ON(!table); | 577 | B43_WARN_ON(!table); |
@@ -193,8 +594,25 @@ void r2057_get_chantabent_rev7(struct b43_wldev *dev, u16 freq, | |||
193 | *tabent_r7 = NULL; | 594 | *tabent_r7 = NULL; |
194 | *tabent_r7_2g = NULL; | 595 | *tabent_r7_2g = NULL; |
195 | 596 | ||
196 | /* TODO */ | ||
197 | switch (phy->rev) { | 597 | switch (phy->rev) { |
598 | case 8: | ||
599 | if (phy->radio_rev == 5) { | ||
600 | e_r7_2g = b43_nphy_chantab_phy_rev8_radio_rev5; | ||
601 | len = ARRAY_SIZE(b43_nphy_chantab_phy_rev8_radio_rev5); | ||
602 | } | ||
603 | break; | ||
604 | case 16: | ||
605 | if (phy->radio_rev == 9) { | ||
606 | e_r7 = b43_nphy_chantab_phy_rev16_radio_rev9; | ||
607 | len = ARRAY_SIZE(b43_nphy_chantab_phy_rev16_radio_rev9); | ||
608 | } | ||
609 | break; | ||
610 | case 17: | ||
611 | if (phy->radio_rev == 14) { | ||
612 | e_r7_2g = b43_nphy_chantab_phy_rev17_radio_rev14; | ||
613 | len = ARRAY_SIZE(b43_nphy_chantab_phy_rev17_radio_rev14); | ||
614 | } | ||
615 | break; | ||
198 | default: | 616 | default: |
199 | break; | 617 | break; |
200 | } | 618 | } |
diff --git a/drivers/net/wireless/b43/radio_2057.h b/drivers/net/wireless/b43/radio_2057.h index 675d1bb64429..220d080238ff 100644 --- a/drivers/net/wireless/b43/radio_2057.h +++ b/drivers/net/wireless/b43/radio_2057.h | |||
@@ -84,6 +84,8 @@ | |||
84 | #define R2057_CMOSBUF_RX_RCCR 0x04c | 84 | #define R2057_CMOSBUF_RX_RCCR 0x04c |
85 | #define R2057_LOGEN_SEL_PKDET 0x04d | 85 | #define R2057_LOGEN_SEL_PKDET 0x04d |
86 | #define R2057_CMOSBUF_SHAREIQ_PTAT 0x04e | 86 | #define R2057_CMOSBUF_SHAREIQ_PTAT 0x04e |
87 | |||
88 | /* MISC core 0 */ | ||
87 | #define R2057_RXTXBIAS_CONFIG_CORE0 0x04f | 89 | #define R2057_RXTXBIAS_CONFIG_CORE0 0x04f |
88 | #define R2057_TXGM_TXRF_PUS_CORE0 0x050 | 90 | #define R2057_TXGM_TXRF_PUS_CORE0 0x050 |
89 | #define R2057_TXGM_IDAC_BLEED_CORE0 0x051 | 91 | #define R2057_TXGM_IDAC_BLEED_CORE0 0x051 |
@@ -204,6 +206,8 @@ | |||
204 | #define R2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE0 0x0d1 | 206 | #define R2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE0 0x0d1 |
205 | #define R2057_LPF_GAIN_CORE0 0x0d2 | 207 | #define R2057_LPF_GAIN_CORE0 0x0d2 |
206 | #define R2057_DACBUF_IDACS_BW_CORE0 0x0d3 | 208 | #define R2057_DACBUF_IDACS_BW_CORE0 0x0d3 |
209 | |||
210 | /* MISC core 1 */ | ||
207 | #define R2057_RXTXBIAS_CONFIG_CORE1 0x0d4 | 211 | #define R2057_RXTXBIAS_CONFIG_CORE1 0x0d4 |
208 | #define R2057_TXGM_TXRF_PUS_CORE1 0x0d5 | 212 | #define R2057_TXGM_TXRF_PUS_CORE1 0x0d5 |
209 | #define R2057_TXGM_IDAC_BLEED_CORE1 0x0d6 | 213 | #define R2057_TXGM_IDAC_BLEED_CORE1 0x0d6 |
@@ -324,6 +328,7 @@ | |||
324 | #define R2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE1 0x156 | 328 | #define R2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE1 0x156 |
325 | #define R2057_LPF_GAIN_CORE1 0x157 | 329 | #define R2057_LPF_GAIN_CORE1 0x157 |
326 | #define R2057_DACBUF_IDACS_BW_CORE1 0x158 | 330 | #define R2057_DACBUF_IDACS_BW_CORE1 0x158 |
331 | |||
327 | #define R2057_DACBUF_VINCM_CORE1 0x159 | 332 | #define R2057_DACBUF_VINCM_CORE1 0x159 |
328 | #define R2057_RCCAL_START_R1_Q1_P1 0x15a | 333 | #define R2057_RCCAL_START_R1_Q1_P1 0x15a |
329 | #define R2057_RCCAL_X1 0x15b | 334 | #define R2057_RCCAL_X1 0x15b |
@@ -345,6 +350,8 @@ | |||
345 | #define R2057_RCCAL_BCAP_VAL 0x16b | 350 | #define R2057_RCCAL_BCAP_VAL 0x16b |
346 | #define R2057_RCCAL_HPC_VAL 0x16c | 351 | #define R2057_RCCAL_HPC_VAL 0x16c |
347 | #define R2057_RCCAL_OVERRIDES 0x16d | 352 | #define R2057_RCCAL_OVERRIDES 0x16d |
353 | |||
354 | /* TX core 0 */ | ||
348 | #define R2057_TX0_IQCAL_GAIN_BW 0x170 | 355 | #define R2057_TX0_IQCAL_GAIN_BW 0x170 |
349 | #define R2057_TX0_LOFT_FINE_I 0x171 | 356 | #define R2057_TX0_LOFT_FINE_I 0x171 |
350 | #define R2057_TX0_LOFT_FINE_Q 0x172 | 357 | #define R2057_TX0_LOFT_FINE_Q 0x172 |
@@ -362,6 +369,8 @@ | |||
362 | #define R2057_TX0_TXRXCOUPLE_2G_PWRUP 0x17e | 369 | #define R2057_TX0_TXRXCOUPLE_2G_PWRUP 0x17e |
363 | #define R2057_TX0_TXRXCOUPLE_5G_ATTEN 0x17f | 370 | #define R2057_TX0_TXRXCOUPLE_5G_ATTEN 0x17f |
364 | #define R2057_TX0_TXRXCOUPLE_5G_PWRUP 0x180 | 371 | #define R2057_TX0_TXRXCOUPLE_5G_PWRUP 0x180 |
372 | |||
373 | /* TX core 1 */ | ||
365 | #define R2057_TX1_IQCAL_GAIN_BW 0x190 | 374 | #define R2057_TX1_IQCAL_GAIN_BW 0x190 |
366 | #define R2057_TX1_LOFT_FINE_I 0x191 | 375 | #define R2057_TX1_LOFT_FINE_I 0x191 |
367 | #define R2057_TX1_LOFT_FINE_Q 0x192 | 376 | #define R2057_TX1_LOFT_FINE_Q 0x192 |
@@ -379,6 +388,7 @@ | |||
379 | #define R2057_TX1_TXRXCOUPLE_2G_PWRUP 0x19e | 388 | #define R2057_TX1_TXRXCOUPLE_2G_PWRUP 0x19e |
380 | #define R2057_TX1_TXRXCOUPLE_5G_ATTEN 0x19f | 389 | #define R2057_TX1_TXRXCOUPLE_5G_ATTEN 0x19f |
381 | #define R2057_TX1_TXRXCOUPLE_5G_PWRUP 0x1a0 | 390 | #define R2057_TX1_TXRXCOUPLE_5G_PWRUP 0x1a0 |
391 | |||
382 | #define R2057_AFE_VCM_CAL_MASTER_CORE0 0x1a1 | 392 | #define R2057_AFE_VCM_CAL_MASTER_CORE0 0x1a1 |
383 | #define R2057_AFE_SET_VCM_I_CORE0 0x1a2 | 393 | #define R2057_AFE_SET_VCM_I_CORE0 0x1a2 |
384 | #define R2057_AFE_SET_VCM_Q_CORE0 0x1a3 | 394 | #define R2057_AFE_SET_VCM_Q_CORE0 0x1a3 |
diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c index b28dce950e1f..4b5885077b01 100644 --- a/drivers/net/wireless/b43/tables_nphy.c +++ b/drivers/net/wireless/b43/tables_nphy.c | |||
@@ -2408,6 +2408,41 @@ static const u32 b43_ntab_tx_gain_epa_rev3_2g[] = { | |||
2408 | 0x1041003c, 0x1041003b, 0x10410039, 0x10410037, | 2408 | 0x1041003c, 0x1041003b, 0x10410039, 0x10410037, |
2409 | }; | 2409 | }; |
2410 | 2410 | ||
2411 | static const u32 b43_ntab_tx_gain_epa_rev3_hi_pwr_2g[] = { | ||
2412 | 0x0f410044, 0x0f410042, 0x0f410040, 0x0f41003e, | ||
2413 | 0x0f41003c, 0x0f41003b, 0x0f410039, 0x0f410037, | ||
2414 | 0x0e410044, 0x0e410042, 0x0e410040, 0x0e41003e, | ||
2415 | 0x0e41003c, 0x0e41003b, 0x0e410039, 0x0e410037, | ||
2416 | 0x0d410044, 0x0d410042, 0x0d410040, 0x0d41003e, | ||
2417 | 0x0d41003c, 0x0d41003b, 0x0d410039, 0x0d410037, | ||
2418 | 0x0c410044, 0x0c410042, 0x0c410040, 0x0c41003e, | ||
2419 | 0x0c41003c, 0x0c41003b, 0x0c410039, 0x0c410037, | ||
2420 | 0x0b410044, 0x0b410042, 0x0b410040, 0x0b41003e, | ||
2421 | 0x0b41003c, 0x0b41003b, 0x0b410039, 0x0b410037, | ||
2422 | 0x0a410044, 0x0a410042, 0x0a410040, 0x0a41003e, | ||
2423 | 0x0a41003c, 0x0a41003b, 0x0a410039, 0x0a410037, | ||
2424 | 0x09410044, 0x09410042, 0x09410040, 0x0941003e, | ||
2425 | 0x0941003c, 0x0941003b, 0x09410039, 0x09410037, | ||
2426 | 0x08410044, 0x08410042, 0x08410040, 0x0841003e, | ||
2427 | 0x0841003c, 0x0841003b, 0x08410039, 0x08410037, | ||
2428 | 0x07410044, 0x07410042, 0x07410040, 0x0741003e, | ||
2429 | 0x0741003c, 0x0741003b, 0x07410039, 0x07410037, | ||
2430 | 0x06410044, 0x06410042, 0x06410040, 0x0641003e, | ||
2431 | 0x0641003c, 0x0641003b, 0x06410039, 0x06410037, | ||
2432 | 0x05410044, 0x05410042, 0x05410040, 0x0541003e, | ||
2433 | 0x0541003c, 0x0541003b, 0x05410039, 0x05410037, | ||
2434 | 0x04410044, 0x04410042, 0x04410040, 0x0441003e, | ||
2435 | 0x0441003c, 0x0441003b, 0x04410039, 0x04410037, | ||
2436 | 0x03410044, 0x03410042, 0x03410040, 0x0341003e, | ||
2437 | 0x0341003c, 0x0341003b, 0x03410039, 0x03410037, | ||
2438 | 0x02410044, 0x02410042, 0x02410040, 0x0241003e, | ||
2439 | 0x0241003c, 0x0241003b, 0x02410039, 0x02410037, | ||
2440 | 0x01410044, 0x01410042, 0x01410040, 0x0141003e, | ||
2441 | 0x0141003c, 0x0141003b, 0x01410039, 0x01410037, | ||
2442 | 0x00410044, 0x00410042, 0x00410040, 0x0041003e, | ||
2443 | 0x0041003c, 0x0041003b, 0x00410039, 0x00410037 | ||
2444 | }; | ||
2445 | |||
2411 | /* EPA 5 GHz */ | 2446 | /* EPA 5 GHz */ |
2412 | 2447 | ||
2413 | static const u32 b43_ntab_tx_gain_epa_rev3_5g[] = { | 2448 | static const u32 b43_ntab_tx_gain_epa_rev3_5g[] = { |
@@ -2480,6 +2515,41 @@ static const u32 b43_ntab_tx_gain_epa_rev4_5g[] = { | |||
2480 | 0x20d2003a, 0x20d20038, 0x20d20036, 0x20d20034, | 2515 | 0x20d2003a, 0x20d20038, 0x20d20036, 0x20d20034, |
2481 | }; | 2516 | }; |
2482 | 2517 | ||
2518 | static const u32 b43_ntab_tx_gain_epa_rev4_hi_pwr_5g[] = { | ||
2519 | 0x2ff10044, 0x2ff10042, 0x2ff10040, 0x2ff1003e, | ||
2520 | 0x2ff1003c, 0x2ff1003b, 0x2ff10039, 0x2ff10037, | ||
2521 | 0x2ef10044, 0x2ef10042, 0x2ef10040, 0x2ef1003e, | ||
2522 | 0x2ef1003c, 0x2ef1003b, 0x2ef10039, 0x2ef10037, | ||
2523 | 0x2df10044, 0x2df10042, 0x2df10040, 0x2df1003e, | ||
2524 | 0x2df1003c, 0x2df1003b, 0x2df10039, 0x2df10037, | ||
2525 | 0x2cf10044, 0x2cf10042, 0x2cf10040, 0x2cf1003e, | ||
2526 | 0x2cf1003c, 0x2cf1003b, 0x2cf10039, 0x2cf10037, | ||
2527 | 0x2bf10044, 0x2bf10042, 0x2bf10040, 0x2bf1003e, | ||
2528 | 0x2bf1003c, 0x2bf1003b, 0x2bf10039, 0x2bf10037, | ||
2529 | 0x2af10044, 0x2af10042, 0x2af10040, 0x2af1003e, | ||
2530 | 0x2af1003c, 0x2af1003b, 0x2af10039, 0x2af10037, | ||
2531 | 0x29f10044, 0x29f10042, 0x29f10040, 0x29f1003e, | ||
2532 | 0x29f1003c, 0x29f1003b, 0x29f10039, 0x29f10037, | ||
2533 | 0x28f10044, 0x28f10042, 0x28f10040, 0x28f1003e, | ||
2534 | 0x28f1003c, 0x28f1003b, 0x28f10039, 0x28f10037, | ||
2535 | 0x27f10044, 0x27f10042, 0x27f10040, 0x27f1003e, | ||
2536 | 0x27f1003c, 0x27f1003b, 0x27f10039, 0x27f10037, | ||
2537 | 0x26f10044, 0x26f10042, 0x26f10040, 0x26f1003e, | ||
2538 | 0x26f1003c, 0x26f1003b, 0x26f10039, 0x26f10037, | ||
2539 | 0x25f10044, 0x25f10042, 0x25f10040, 0x25f1003e, | ||
2540 | 0x25f1003c, 0x25f1003b, 0x25f10039, 0x25f10037, | ||
2541 | 0x24f10044, 0x24f10042, 0x24f10040, 0x24f1003e, | ||
2542 | 0x24f1003c, 0x24f1003b, 0x24f10039, 0x24f10038, | ||
2543 | 0x23f10041, 0x23f10040, 0x23f1003f, 0x23f1003e, | ||
2544 | 0x23f1003c, 0x23f1003b, 0x23f10039, 0x23f10037, | ||
2545 | 0x22f10044, 0x22f10042, 0x22f10040, 0x22f1003e, | ||
2546 | 0x22f1003c, 0x22f1003b, 0x22f10039, 0x22f10037, | ||
2547 | 0x21f10044, 0x21f10042, 0x21f10040, 0x21f1003e, | ||
2548 | 0x21f1003c, 0x21f1003b, 0x21f10039, 0x21f10037, | ||
2549 | 0x20d10043, 0x20d10041, 0x20d1003e, 0x20d1003c, | ||
2550 | 0x20d1003a, 0x20d10038, 0x20d10036, 0x20d10034 | ||
2551 | }; | ||
2552 | |||
2483 | static const u32 b43_ntab_tx_gain_epa_rev5_5g[] = { | 2553 | static const u32 b43_ntab_tx_gain_epa_rev5_5g[] = { |
2484 | 0x0f62004a, 0x0f620048, 0x0f620046, 0x0f620044, | 2554 | 0x0f62004a, 0x0f620048, 0x0f620046, 0x0f620044, |
2485 | 0x0f620042, 0x0f620040, 0x0f62003e, 0x0f62003c, | 2555 | 0x0f620042, 0x0f620040, 0x0f62003e, 0x0f62003c, |
@@ -2622,6 +2692,42 @@ static const u32 b43_ntab_tx_gain_ipa_rev6_2g[] = { | |||
2622 | 0x00f70028, 0x00f70027, 0x00f70026, 0x00f70025, | 2692 | 0x00f70028, 0x00f70027, 0x00f70026, 0x00f70025, |
2623 | }; | 2693 | }; |
2624 | 2694 | ||
2695 | /* Copied from brcmsmac (5.75.11): nphy_tpc_txgain_ipa_2g_2057rev5 */ | ||
2696 | static const u32 b43_ntab_tx_gain_ipa_2057_rev5_2g[] = { | ||
2697 | 0x30ff0031, 0x30e70031, 0x30e7002e, 0x30cf002e, | ||
2698 | 0x30bf002e, 0x30af002e, 0x309f002f, 0x307f0033, | ||
2699 | 0x307f0031, 0x307f002e, 0x3077002e, 0x306f002e, | ||
2700 | 0x3067002e, 0x305f002f, 0x30570030, 0x3057002d, | ||
2701 | 0x304f002e, 0x30470031, 0x3047002e, 0x3047002c, | ||
2702 | 0x30470029, 0x303f002c, 0x303f0029, 0x3037002d, | ||
2703 | 0x3037002a, 0x30370028, 0x302f002c, 0x302f002a, | ||
2704 | 0x302f0028, 0x302f0026, 0x3027002c, 0x30270029, | ||
2705 | 0x30270027, 0x30270025, 0x30270023, 0x301f002c, | ||
2706 | 0x301f002a, 0x301f0028, 0x301f0025, 0x301f0024, | ||
2707 | 0x301f0022, 0x301f001f, 0x3017002d, 0x3017002b, | ||
2708 | 0x30170028, 0x30170026, 0x30170024, 0x30170022, | ||
2709 | 0x30170020, 0x3017001e, 0x3017001d, 0x3017001b, | ||
2710 | 0x3017001a, 0x30170018, 0x30170017, 0x30170015, | ||
2711 | 0x300f002c, 0x300f0029, 0x300f0027, 0x300f0024, | ||
2712 | 0x300f0022, 0x300f0021, 0x300f001f, 0x300f001d, | ||
2713 | 0x300f001b, 0x300f001a, 0x300f0018, 0x300f0017, | ||
2714 | 0x300f0016, 0x300f0015, 0x300f0115, 0x300f0215, | ||
2715 | 0x300f0315, 0x300f0415, 0x300f0515, 0x300f0615, | ||
2716 | 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, | ||
2717 | 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, | ||
2718 | 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, | ||
2719 | 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, | ||
2720 | 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, | ||
2721 | 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, | ||
2722 | 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, | ||
2723 | 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, | ||
2724 | 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, | ||
2725 | 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, | ||
2726 | 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, | ||
2727 | 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, | ||
2728 | 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, | ||
2729 | }; | ||
2730 | |||
2625 | /* Extracted from MMIO dump of 6.30.223.141 */ | 2731 | /* Extracted from MMIO dump of 6.30.223.141 */ |
2626 | static const u32 b43_ntab_tx_gain_ipa_2057_rev9_2g[] = { | 2732 | static const u32 b43_ntab_tx_gain_ipa_2057_rev9_2g[] = { |
2627 | 0x60ff0031, 0x60e7002c, 0x60cf002a, 0x60c70029, | 2733 | 0x60ff0031, 0x60e7002c, 0x60cf002a, 0x60c70029, |
@@ -2658,6 +2764,42 @@ static const u32 b43_ntab_tx_gain_ipa_2057_rev9_2g[] = { | |||
2658 | 0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715, | 2764 | 0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715, |
2659 | }; | 2765 | }; |
2660 | 2766 | ||
2767 | /* Extracted from MMIO dump of 6.30.223.248 */ | ||
2768 | static const u32 b43_ntab_tx_gain_ipa_2057_rev14_2g[] = { | ||
2769 | 0x50df002e, 0x50cf002d, 0x50bf002c, 0x50b7002b, | ||
2770 | 0x50af002a, 0x50a70029, 0x509f0029, 0x50970028, | ||
2771 | 0x508f0027, 0x50870027, 0x507f0027, 0x50770027, | ||
2772 | 0x506f0027, 0x50670027, 0x505f0028, 0x50570029, | ||
2773 | 0x504f002b, 0x5047002e, 0x5047002b, 0x50470029, | ||
2774 | 0x503f002c, 0x503f0029, 0x5037002c, 0x5037002a, | ||
2775 | 0x50370028, 0x502f002d, 0x502f002b, 0x502f0028, | ||
2776 | 0x502f0026, 0x5027002d, 0x5027002a, 0x50270028, | ||
2777 | 0x50270026, 0x50270024, 0x501f002e, 0x501f002b, | ||
2778 | 0x501f0029, 0x501f0027, 0x501f0024, 0x501f0022, | ||
2779 | 0x501f0020, 0x501f001f, 0x5017002c, 0x50170029, | ||
2780 | 0x50170027, 0x50170024, 0x50170022, 0x50170021, | ||
2781 | 0x5017001f, 0x5017001d, 0x5017001b, 0x5017001a, | ||
2782 | 0x50170018, 0x50170017, 0x50170015, 0x500f002c, | ||
2783 | 0x500f002a, 0x500f0027, 0x500f0025, 0x500f0023, | ||
2784 | 0x500f0022, 0x500f001f, 0x500f001e, 0x500f001c, | ||
2785 | 0x500f001a, 0x500f0019, 0x500f0018, 0x500f0016, | ||
2786 | 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015, | ||
2787 | 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015, | ||
2788 | 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015, | ||
2789 | 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015, | ||
2790 | 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015, | ||
2791 | 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015, | ||
2792 | 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015, | ||
2793 | 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015, | ||
2794 | 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015, | ||
2795 | 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015, | ||
2796 | 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015, | ||
2797 | 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015, | ||
2798 | 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015, | ||
2799 | 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015, | ||
2800 | 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015, | ||
2801 | }; | ||
2802 | |||
2661 | /* IPA 2 5Hz */ | 2803 | /* IPA 2 5Hz */ |
2662 | 2804 | ||
2663 | static const u32 b43_ntab_tx_gain_ipa_rev3_5g[] = { | 2805 | static const u32 b43_ntab_tx_gain_ipa_rev3_5g[] = { |
@@ -2967,11 +3109,11 @@ static const struct nphy_rf_control_override_rev7 | |||
2967 | { 0x0010, 0x07A, 0x07D, 0x0010, 4 }, | 3109 | { 0x0010, 0x07A, 0x07D, 0x0010, 4 }, |
2968 | { 0x0020, 0x07A, 0x07D, 0x0020, 5 }, | 3110 | { 0x0020, 0x07A, 0x07D, 0x0020, 5 }, |
2969 | { 0x0040, 0x07A, 0x07D, 0x0040, 6 }, | 3111 | { 0x0040, 0x07A, 0x07D, 0x0040, 6 }, |
2970 | { 0x0080, 0x0F8, 0x0FA, 0x0080, 7 }, | 3112 | { 0x0080, 0x07A, 0x07D, 0x0080, 7 }, |
2971 | { 0x0400, 0x0F8, 0x0FA, 0x0070, 4 }, | 3113 | { 0x0400, 0x0F8, 0x0FA, 0x0070, 4 }, |
2972 | { 0x0800, 0x07B, 0x07E, 0xFFFF, 0 }, | 3114 | { 0x0800, 0x07B, 0x07E, 0xFFFF, 0 }, |
2973 | { 0x1000, 0x07C, 0x07F, 0xFFFF, 0 }, | 3115 | { 0x1000, 0x07C, 0x07F, 0xFFFF, 0 }, |
2974 | { 0x6000, 0x348, 0x349, 0xFFFF, 0 }, | 3116 | { 0x6000, 0x348, 0x349, 0x00FF, 0 }, |
2975 | { 0x2000, 0x348, 0x349, 0x000F, 0 }, | 3117 | { 0x2000, 0x348, 0x349, 0x000F, 0 }, |
2976 | }; | 3118 | }; |
2977 | 3119 | ||
@@ -3477,9 +3619,18 @@ static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev) | |||
3477 | 3619 | ||
3478 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { | 3620 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { |
3479 | switch (phy->rev) { | 3621 | switch (phy->rev) { |
3622 | case 17: | ||
3623 | if (phy->radio_rev == 14) | ||
3624 | return b43_ntab_tx_gain_ipa_2057_rev14_2g; | ||
3625 | break; | ||
3480 | case 16: | 3626 | case 16: |
3481 | if (phy->radio_rev == 9) | 3627 | if (phy->radio_rev == 9) |
3482 | return b43_ntab_tx_gain_ipa_2057_rev9_2g; | 3628 | return b43_ntab_tx_gain_ipa_2057_rev9_2g; |
3629 | break; | ||
3630 | case 8: | ||
3631 | if (phy->radio_rev == 5) | ||
3632 | return b43_ntab_tx_gain_ipa_2057_rev5_2g; | ||
3633 | break; | ||
3483 | case 6: | 3634 | case 6: |
3484 | if (dev->dev->chip_id == BCMA_CHIP_ID_BCM47162) | 3635 | if (dev->dev->chip_id == BCMA_CHIP_ID_BCM47162) |
3485 | return b43_ntab_tx_gain_ipa_rev5_2g; | 3636 | return b43_ntab_tx_gain_ipa_rev5_2g; |
@@ -3489,23 +3640,24 @@ static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev) | |||
3489 | case 4: | 3640 | case 4: |
3490 | case 3: | 3641 | case 3: |
3491 | return b43_ntab_tx_gain_ipa_rev3_2g; | 3642 | return b43_ntab_tx_gain_ipa_rev3_2g; |
3492 | default: | ||
3493 | b43err(dev->wl, | ||
3494 | "No 2GHz IPA gain table available for this device\n"); | ||
3495 | return NULL; | ||
3496 | } | 3643 | } |
3644 | |||
3645 | b43err(dev->wl, | ||
3646 | "No 2GHz IPA gain table available for this device\n"); | ||
3647 | return NULL; | ||
3497 | } else { | 3648 | } else { |
3498 | switch (phy->rev) { | 3649 | switch (phy->rev) { |
3499 | case 16: | 3650 | case 16: |
3500 | if (phy->radio_rev == 9) | 3651 | if (phy->radio_rev == 9) |
3501 | return b43_ntab_tx_gain_ipa_2057_rev9_5g; | 3652 | return b43_ntab_tx_gain_ipa_2057_rev9_5g; |
3653 | break; | ||
3502 | case 3 ... 6: | 3654 | case 3 ... 6: |
3503 | return b43_ntab_tx_gain_ipa_rev3_5g; | 3655 | return b43_ntab_tx_gain_ipa_rev3_5g; |
3504 | default: | ||
3505 | b43err(dev->wl, | ||
3506 | "No 5GHz IPA gain table available for this device\n"); | ||
3507 | return NULL; | ||
3508 | } | 3656 | } |
3657 | |||
3658 | b43err(dev->wl, | ||
3659 | "No 5GHz IPA gain table available for this device\n"); | ||
3660 | return NULL; | ||
3509 | } | 3661 | } |
3510 | } | 3662 | } |
3511 | 3663 | ||
@@ -3530,7 +3682,7 @@ const u32 *b43_nphy_get_tx_gain_table(struct b43_wldev *dev) | |||
3530 | case 4: | 3682 | case 4: |
3531 | return sprom->fem.ghz5.extpa_gain == 3 ? | 3683 | return sprom->fem.ghz5.extpa_gain == 3 ? |
3532 | b43_ntab_tx_gain_epa_rev4_5g : | 3684 | b43_ntab_tx_gain_epa_rev4_5g : |
3533 | b43_ntab_tx_gain_epa_rev4_5g; /* FIXME */ | 3685 | b43_ntab_tx_gain_epa_rev4_hi_pwr_5g; |
3534 | case 3: | 3686 | case 3: |
3535 | return b43_ntab_tx_gain_epa_rev3_5g; | 3687 | return b43_ntab_tx_gain_epa_rev3_5g; |
3536 | default: | 3688 | default: |
@@ -3543,7 +3695,7 @@ const u32 *b43_nphy_get_tx_gain_table(struct b43_wldev *dev) | |||
3543 | case 6: | 3695 | case 6: |
3544 | case 5: | 3696 | case 5: |
3545 | if (sprom->fem.ghz5.extpa_gain == 3) | 3697 | if (sprom->fem.ghz5.extpa_gain == 3) |
3546 | return b43_ntab_tx_gain_epa_rev3_2g; /* FIXME */ | 3698 | return b43_ntab_tx_gain_epa_rev3_hi_pwr_2g; |
3547 | /* fall through */ | 3699 | /* fall through */ |
3548 | case 4: | 3700 | case 4: |
3549 | case 3: | 3701 | case 3: |
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/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/brcm80211/brcmfmac/Makefile index 4cffb2ee3673..de0cff3df389 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/Makefile +++ b/drivers/net/wireless/brcm80211/brcmfmac/Makefile | |||
@@ -34,6 +34,7 @@ brcmfmac-objs += \ | |||
34 | dhd_common.o \ | 34 | dhd_common.o \ |
35 | dhd_linux.o \ | 35 | dhd_linux.o \ |
36 | firmware.o \ | 36 | firmware.o \ |
37 | feature.o \ | ||
37 | btcoex.o \ | 38 | btcoex.o \ |
38 | vendor.o | 39 | vendor.o |
39 | brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \ | 40 | brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index a16e644e7c08..f467cafe3e8f 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <linux/mmc/sdio.h> | 25 | #include <linux/mmc/sdio.h> |
26 | #include <linux/mmc/core.h> | 26 | #include <linux/mmc/core.h> |
27 | #include <linux/mmc/sdio_func.h> | 27 | #include <linux/mmc/sdio_func.h> |
28 | #include <linux/mmc/sdio_ids.h> | ||
29 | #include <linux/mmc/card.h> | 28 | #include <linux/mmc/card.h> |
30 | #include <linux/mmc/host.h> | 29 | #include <linux/mmc/host.h> |
31 | #include <linux/platform_device.h> | 30 | #include <linux/platform_device.h> |
@@ -979,18 +978,20 @@ out: | |||
979 | return ret; | 978 | return ret; |
980 | } | 979 | } |
981 | 980 | ||
981 | #define BRCMF_SDIO_DEVICE(dev_id) \ | ||
982 | {SDIO_DEVICE(BRCM_SDIO_VENDOR_ID_BROADCOM, dev_id)} | ||
983 | |||
982 | /* devices we support, null terminated */ | 984 | /* devices we support, null terminated */ |
983 | static const struct sdio_device_id brcmf_sdmmc_ids[] = { | 985 | static const struct sdio_device_id brcmf_sdmmc_ids[] = { |
984 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43143)}, | 986 | BRCMF_SDIO_DEVICE(BRCM_SDIO_43143_DEVICE_ID), |
985 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43241)}, | 987 | BRCMF_SDIO_DEVICE(BRCM_SDIO_43241_DEVICE_ID), |
986 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)}, | 988 | BRCMF_SDIO_DEVICE(BRCM_SDIO_4329_DEVICE_ID), |
987 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330)}, | 989 | BRCMF_SDIO_DEVICE(BRCM_SDIO_4330_DEVICE_ID), |
988 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4334)}, | 990 | BRCMF_SDIO_DEVICE(BRCM_SDIO_4334_DEVICE_ID), |
989 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43362)}, | 991 | BRCMF_SDIO_DEVICE(BRCM_SDIO_43362_DEVICE_ID), |
990 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, | 992 | BRCMF_SDIO_DEVICE(BRCM_SDIO_4335_4339_DEVICE_ID), |
991 | SDIO_DEVICE_ID_BROADCOM_4335_4339)}, | 993 | BRCMF_SDIO_DEVICE(BRCM_SDIO_4354_DEVICE_ID), |
992 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4354)}, | 994 | { /* end: all zeroes */ } |
993 | { /* end: all zeroes */ }, | ||
994 | }; | 995 | }; |
995 | MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); | 996 | MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); |
996 | 997 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/brcm80211/brcmfmac/chip.c index c7c9f15c0fe0..96800db0536b 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c | |||
@@ -482,30 +482,30 @@ static inline int brcmf_chip_cores_check(struct brcmf_chip_priv *ci) | |||
482 | static void brcmf_chip_get_raminfo(struct brcmf_chip_priv *ci) | 482 | static void brcmf_chip_get_raminfo(struct brcmf_chip_priv *ci) |
483 | { | 483 | { |
484 | switch (ci->pub.chip) { | 484 | switch (ci->pub.chip) { |
485 | case BCM4329_CHIP_ID: | 485 | case BRCM_CC_4329_CHIP_ID: |
486 | ci->pub.ramsize = BCM4329_RAMSIZE; | 486 | ci->pub.ramsize = BCM4329_RAMSIZE; |
487 | break; | 487 | break; |
488 | case BCM43143_CHIP_ID: | 488 | case BRCM_CC_43143_CHIP_ID: |
489 | ci->pub.ramsize = BCM43143_RAMSIZE; | 489 | ci->pub.ramsize = BCM43143_RAMSIZE; |
490 | break; | 490 | break; |
491 | case BCM43241_CHIP_ID: | 491 | case BRCM_CC_43241_CHIP_ID: |
492 | ci->pub.ramsize = 0x90000; | 492 | ci->pub.ramsize = 0x90000; |
493 | break; | 493 | break; |
494 | case BCM4330_CHIP_ID: | 494 | case BRCM_CC_4330_CHIP_ID: |
495 | ci->pub.ramsize = 0x48000; | 495 | ci->pub.ramsize = 0x48000; |
496 | break; | 496 | break; |
497 | case BCM4334_CHIP_ID: | 497 | case BRCM_CC_4334_CHIP_ID: |
498 | ci->pub.ramsize = 0x80000; | 498 | ci->pub.ramsize = 0x80000; |
499 | break; | 499 | break; |
500 | case BCM4335_CHIP_ID: | 500 | case BRCM_CC_4335_CHIP_ID: |
501 | ci->pub.ramsize = 0xc0000; | 501 | ci->pub.ramsize = 0xc0000; |
502 | ci->pub.rambase = 0x180000; | 502 | ci->pub.rambase = 0x180000; |
503 | break; | 503 | break; |
504 | case BCM43362_CHIP_ID: | 504 | case BRCM_CC_43362_CHIP_ID: |
505 | ci->pub.ramsize = 0x3c000; | 505 | ci->pub.ramsize = 0x3c000; |
506 | break; | 506 | break; |
507 | case BCM4339_CHIP_ID: | 507 | case BRCM_CC_4339_CHIP_ID: |
508 | case BCM4354_CHIP_ID: | 508 | case BRCM_CC_4354_CHIP_ID: |
509 | ci->pub.ramsize = 0xc0000; | 509 | ci->pub.ramsize = 0xc0000; |
510 | ci->pub.rambase = 0x180000; | 510 | ci->pub.rambase = 0x180000; |
511 | break; | 511 | break; |
@@ -682,7 +682,7 @@ static int brcmf_chip_recognition(struct brcmf_chip_priv *ci) | |||
682 | ci->pub.chiprev); | 682 | ci->pub.chiprev); |
683 | 683 | ||
684 | if (socitype == SOCI_SB) { | 684 | if (socitype == SOCI_SB) { |
685 | if (ci->pub.chip != BCM4329_CHIP_ID) { | 685 | if (ci->pub.chip != BRCM_CC_4329_CHIP_ID) { |
686 | brcmf_err("SB chip is not supported\n"); | 686 | brcmf_err("SB chip is not supported\n"); |
687 | return -ENODEV; | 687 | return -ENODEV; |
688 | } | 688 | } |
@@ -1008,13 +1008,13 @@ bool brcmf_chip_sr_capable(struct brcmf_chip *pub) | |||
1008 | chip = container_of(pub, struct brcmf_chip_priv, pub); | 1008 | chip = container_of(pub, struct brcmf_chip_priv, pub); |
1009 | 1009 | ||
1010 | switch (pub->chip) { | 1010 | switch (pub->chip) { |
1011 | case BCM4354_CHIP_ID: | 1011 | case BRCM_CC_4354_CHIP_ID: |
1012 | /* explicitly check SR engine enable bit */ | 1012 | /* explicitly check SR engine enable bit */ |
1013 | pmu_cc3_mask = BIT(2); | 1013 | pmu_cc3_mask = BIT(2); |
1014 | /* fall-through */ | 1014 | /* fall-through */ |
1015 | case BCM43241_CHIP_ID: | 1015 | case BRCM_CC_43241_CHIP_ID: |
1016 | case BCM4335_CHIP_ID: | 1016 | case BRCM_CC_4335_CHIP_ID: |
1017 | case BCM4339_CHIP_ID: | 1017 | case BRCM_CC_4339_CHIP_ID: |
1018 | /* read PMU chipcontrol register 3 */ | 1018 | /* read PMU chipcontrol register 3 */ |
1019 | addr = CORE_CC_REG(base, chipcontrol_addr); | 1019 | addr = CORE_CC_REG(base, chipcontrol_addr); |
1020 | chip->ops->write32(chip->ctx, addr, 3); | 1020 | chip->ops->write32(chip->ctx, addr, 3); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h index a8998eb60d22..7da6441bcfa8 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h | |||
@@ -103,6 +103,10 @@ struct brcmf_pub { | |||
103 | 103 | ||
104 | struct brcmf_ampdu_rx_reorder | 104 | struct brcmf_ampdu_rx_reorder |
105 | *reorder_flows[BRCMF_AMPDU_RX_REORDER_MAXFLOWS]; | 105 | *reorder_flows[BRCMF_AMPDU_RX_REORDER_MAXFLOWS]; |
106 | |||
107 | u32 feat_flags; | ||
108 | u32 chip_quirks; | ||
109 | |||
106 | #ifdef DEBUG | 110 | #ifdef DEBUG |
107 | struct dentry *dbgfs_dir; | 111 | struct dentry *dbgfs_dir; |
108 | #endif | 112 | #endif |
@@ -175,7 +179,6 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx, | |||
175 | void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx); | 179 | void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx); |
176 | void brcmf_txflowblock_if(struct brcmf_if *ifp, | 180 | void brcmf_txflowblock_if(struct brcmf_if *ifp, |
177 | enum brcmf_netif_stop_reason reason, bool state); | 181 | enum brcmf_netif_stop_reason reason, bool state); |
178 | u32 brcmf_get_chip_info(struct brcmf_if *ifp); | ||
179 | void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx, | 182 | void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx, |
180 | bool success); | 183 | bool success); |
181 | 184 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c index 03fe8aca4d32..be9f4f829192 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c | |||
@@ -41,37 +41,12 @@ void brcmf_debugfs_exit(void) | |||
41 | root_folder = NULL; | 41 | root_folder = NULL; |
42 | } | 42 | } |
43 | 43 | ||
44 | static | 44 | static int brcmf_debugfs_chipinfo_read(struct seq_file *seq, void *data) |
45 | ssize_t brcmf_debugfs_chipinfo_read(struct file *f, char __user *data, | ||
46 | size_t count, loff_t *ppos) | ||
47 | { | 45 | { |
48 | struct brcmf_pub *drvr = f->private_data; | 46 | struct brcmf_bus *bus = dev_get_drvdata(seq->private); |
49 | struct brcmf_bus *bus = drvr->bus_if; | ||
50 | char buf[40]; | ||
51 | int res; | ||
52 | |||
53 | /* only allow read from start */ | ||
54 | if (*ppos > 0) | ||
55 | return 0; | ||
56 | |||
57 | res = scnprintf(buf, sizeof(buf), "chip: %x(%u) rev %u\n", | ||
58 | bus->chip, bus->chip, bus->chiprev); | ||
59 | return simple_read_from_buffer(data, count, ppos, buf, res); | ||
60 | } | ||
61 | |||
62 | static const struct file_operations brcmf_debugfs_chipinfo_ops = { | ||
63 | .owner = THIS_MODULE, | ||
64 | .open = simple_open, | ||
65 | .read = brcmf_debugfs_chipinfo_read | ||
66 | }; | ||
67 | |||
68 | static int brcmf_debugfs_create_chipinfo(struct brcmf_pub *drvr) | ||
69 | { | ||
70 | struct dentry *dentry = drvr->dbgfs_dir; | ||
71 | 47 | ||
72 | if (!IS_ERR_OR_NULL(dentry)) | 48 | seq_printf(seq, "chip: %x(%u) rev %u\n", |
73 | debugfs_create_file("chipinfo", S_IRUGO, dentry, drvr, | 49 | bus->chip, bus->chip, bus->chiprev); |
74 | &brcmf_debugfs_chipinfo_ops); | ||
75 | return 0; | 50 | return 0; |
76 | } | 51 | } |
77 | 52 | ||
@@ -83,7 +58,8 @@ int brcmf_debugfs_attach(struct brcmf_pub *drvr) | |||
83 | return -ENODEV; | 58 | return -ENODEV; |
84 | 59 | ||
85 | drvr->dbgfs_dir = debugfs_create_dir(dev_name(dev), root_folder); | 60 | drvr->dbgfs_dir = debugfs_create_dir(dev_name(dev), root_folder); |
86 | brcmf_debugfs_create_chipinfo(drvr); | 61 | brcmf_debugfs_add_entry(drvr, "chipinfo", brcmf_debugfs_chipinfo_read); |
62 | |||
87 | return PTR_ERR_OR_ZERO(drvr->dbgfs_dir); | 63 | return PTR_ERR_OR_ZERO(drvr->dbgfs_dir); |
88 | } | 64 | } |
89 | 65 | ||
@@ -98,148 +74,44 @@ struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr) | |||
98 | return drvr->dbgfs_dir; | 74 | return drvr->dbgfs_dir; |
99 | } | 75 | } |
100 | 76 | ||
101 | static | 77 | struct brcmf_debugfs_entry { |
102 | ssize_t brcmf_debugfs_sdio_counter_read(struct file *f, char __user *data, | 78 | int (*read)(struct seq_file *seq, void *data); |
103 | size_t count, loff_t *ppos) | 79 | struct brcmf_pub *drvr; |
104 | { | ||
105 | struct brcmf_sdio_count *sdcnt = f->private_data; | ||
106 | char buf[750]; | ||
107 | int res; | ||
108 | |||
109 | /* only allow read from start */ | ||
110 | if (*ppos > 0) | ||
111 | return 0; | ||
112 | |||
113 | res = scnprintf(buf, sizeof(buf), | ||
114 | "intrcount: %u\nlastintrs: %u\n" | ||
115 | "pollcnt: %u\nregfails: %u\n" | ||
116 | "tx_sderrs: %u\nfcqueued: %u\n" | ||
117 | "rxrtx: %u\nrx_toolong: %u\n" | ||
118 | "rxc_errors: %u\nrx_hdrfail: %u\n" | ||
119 | "rx_badhdr: %u\nrx_badseq: %u\n" | ||
120 | "fc_rcvd: %u\nfc_xoff: %u\n" | ||
121 | "fc_xon: %u\nrxglomfail: %u\n" | ||
122 | "rxglomframes: %u\nrxglompkts: %u\n" | ||
123 | "f2rxhdrs: %u\nf2rxdata: %u\n" | ||
124 | "f2txdata: %u\nf1regdata: %u\n" | ||
125 | "tickcnt: %u\ntx_ctlerrs: %lu\n" | ||
126 | "tx_ctlpkts: %lu\nrx_ctlerrs: %lu\n" | ||
127 | "rx_ctlpkts: %lu\nrx_readahead: %lu\n", | ||
128 | sdcnt->intrcount, sdcnt->lastintrs, | ||
129 | sdcnt->pollcnt, sdcnt->regfails, | ||
130 | sdcnt->tx_sderrs, sdcnt->fcqueued, | ||
131 | sdcnt->rxrtx, sdcnt->rx_toolong, | ||
132 | sdcnt->rxc_errors, sdcnt->rx_hdrfail, | ||
133 | sdcnt->rx_badhdr, sdcnt->rx_badseq, | ||
134 | sdcnt->fc_rcvd, sdcnt->fc_xoff, | ||
135 | sdcnt->fc_xon, sdcnt->rxglomfail, | ||
136 | sdcnt->rxglomframes, sdcnt->rxglompkts, | ||
137 | sdcnt->f2rxhdrs, sdcnt->f2rxdata, | ||
138 | sdcnt->f2txdata, sdcnt->f1regdata, | ||
139 | sdcnt->tickcnt, sdcnt->tx_ctlerrs, | ||
140 | sdcnt->tx_ctlpkts, sdcnt->rx_ctlerrs, | ||
141 | sdcnt->rx_ctlpkts, sdcnt->rx_readahead_cnt); | ||
142 | |||
143 | return simple_read_from_buffer(data, count, ppos, buf, res); | ||
144 | } | ||
145 | |||
146 | static const struct file_operations brcmf_debugfs_sdio_counter_ops = { | ||
147 | .owner = THIS_MODULE, | ||
148 | .open = simple_open, | ||
149 | .read = brcmf_debugfs_sdio_counter_read | ||
150 | }; | 80 | }; |
151 | 81 | ||
152 | void brcmf_debugfs_create_sdio_count(struct brcmf_pub *drvr, | 82 | static int brcmf_debugfs_entry_open(struct inode *inode, struct file *f) |
153 | struct brcmf_sdio_count *sdcnt) | ||
154 | { | 83 | { |
155 | struct dentry *dentry = drvr->dbgfs_dir; | 84 | struct brcmf_debugfs_entry *entry = inode->i_private; |
156 | 85 | ||
157 | if (!IS_ERR_OR_NULL(dentry)) | 86 | return single_open(f, entry->read, entry->drvr->bus_if->dev); |
158 | debugfs_create_file("counters", S_IRUGO, dentry, | ||
159 | sdcnt, &brcmf_debugfs_sdio_counter_ops); | ||
160 | } | ||
161 | |||
162 | static | ||
163 | ssize_t brcmf_debugfs_fws_stats_read(struct file *f, char __user *data, | ||
164 | size_t count, loff_t *ppos) | ||
165 | { | ||
166 | struct brcmf_fws_stats *fwstats = f->private_data; | ||
167 | char buf[650]; | ||
168 | int res; | ||
169 | |||
170 | /* only allow read from start */ | ||
171 | if (*ppos > 0) | ||
172 | return 0; | ||
173 | |||
174 | res = scnprintf(buf, sizeof(buf), | ||
175 | "header_pulls: %u\n" | ||
176 | "header_only_pkt: %u\n" | ||
177 | "tlv_parse_failed: %u\n" | ||
178 | "tlv_invalid_type: %u\n" | ||
179 | "mac_update_fails: %u\n" | ||
180 | "ps_update_fails: %u\n" | ||
181 | "if_update_fails: %u\n" | ||
182 | "pkt2bus: %u\n" | ||
183 | "generic_error: %u\n" | ||
184 | "rollback_success: %u\n" | ||
185 | "rollback_failed: %u\n" | ||
186 | "delayq_full: %u\n" | ||
187 | "supprq_full: %u\n" | ||
188 | "txs_indicate: %u\n" | ||
189 | "txs_discard: %u\n" | ||
190 | "txs_suppr_core: %u\n" | ||
191 | "txs_suppr_ps: %u\n" | ||
192 | "txs_tossed: %u\n" | ||
193 | "txs_host_tossed: %u\n" | ||
194 | "bus_flow_block: %u\n" | ||
195 | "fws_flow_block: %u\n" | ||
196 | "send_pkts: BK:%u BE:%u VO:%u VI:%u BCMC:%u\n" | ||
197 | "requested_sent: BK:%u BE:%u VO:%u VI:%u BCMC:%u\n", | ||
198 | fwstats->header_pulls, | ||
199 | fwstats->header_only_pkt, | ||
200 | fwstats->tlv_parse_failed, | ||
201 | fwstats->tlv_invalid_type, | ||
202 | fwstats->mac_update_failed, | ||
203 | fwstats->mac_ps_update_failed, | ||
204 | fwstats->if_update_failed, | ||
205 | fwstats->pkt2bus, | ||
206 | fwstats->generic_error, | ||
207 | fwstats->rollback_success, | ||
208 | fwstats->rollback_failed, | ||
209 | fwstats->delayq_full_error, | ||
210 | fwstats->supprq_full_error, | ||
211 | fwstats->txs_indicate, | ||
212 | fwstats->txs_discard, | ||
213 | fwstats->txs_supp_core, | ||
214 | fwstats->txs_supp_ps, | ||
215 | fwstats->txs_tossed, | ||
216 | fwstats->txs_host_tossed, | ||
217 | fwstats->bus_flow_block, | ||
218 | fwstats->fws_flow_block, | ||
219 | fwstats->send_pkts[0], fwstats->send_pkts[1], | ||
220 | fwstats->send_pkts[2], fwstats->send_pkts[3], | ||
221 | fwstats->send_pkts[4], | ||
222 | fwstats->requested_sent[0], | ||
223 | fwstats->requested_sent[1], | ||
224 | fwstats->requested_sent[2], | ||
225 | fwstats->requested_sent[3], | ||
226 | fwstats->requested_sent[4]); | ||
227 | |||
228 | return simple_read_from_buffer(data, count, ppos, buf, res); | ||
229 | } | 87 | } |
230 | 88 | ||
231 | static const struct file_operations brcmf_debugfs_fws_stats_ops = { | 89 | static const struct file_operations brcmf_debugfs_def_ops = { |
232 | .owner = THIS_MODULE, | 90 | .owner = THIS_MODULE, |
233 | .open = simple_open, | 91 | .open = brcmf_debugfs_entry_open, |
234 | .read = brcmf_debugfs_fws_stats_read | 92 | .release = single_release, |
93 | .read = seq_read, | ||
94 | .llseek = seq_lseek | ||
235 | }; | 95 | }; |
236 | 96 | ||
237 | void brcmf_debugfs_create_fws_stats(struct brcmf_pub *drvr, | 97 | int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn, |
238 | struct brcmf_fws_stats *stats) | 98 | int (*read_fn)(struct seq_file *seq, void *data)) |
239 | { | 99 | { |
240 | struct dentry *dentry = drvr->dbgfs_dir; | 100 | struct dentry *dentry = drvr->dbgfs_dir; |
101 | struct brcmf_debugfs_entry *entry; | ||
102 | |||
103 | if (IS_ERR_OR_NULL(dentry)) | ||
104 | return -ENOENT; | ||
105 | |||
106 | entry = devm_kzalloc(drvr->bus_if->dev, sizeof(*entry), GFP_KERNEL); | ||
107 | if (!entry) | ||
108 | return -ENOMEM; | ||
109 | |||
110 | entry->read = read_fn; | ||
111 | entry->drvr = drvr; | ||
112 | |||
113 | dentry = debugfs_create_file(fn, S_IRUGO, dentry, entry, | ||
114 | &brcmf_debugfs_def_ops); | ||
241 | 115 | ||
242 | if (!IS_ERR_OR_NULL(dentry)) | 116 | return PTR_ERR_OR_ZERO(dentry); |
243 | debugfs_create_file("fws_stats", S_IRUGO, dentry, | ||
244 | stats, &brcmf_debugfs_fws_stats_ops); | ||
245 | } | 117 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h index ef52ed7abc69..6eade7c60c63 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h | |||
@@ -100,68 +100,6 @@ do { \ | |||
100 | 100 | ||
101 | extern int brcmf_msg_level; | 101 | extern int brcmf_msg_level; |
102 | 102 | ||
103 | /* | ||
104 | * hold counter variables used in brcmfmac sdio driver. | ||
105 | */ | ||
106 | struct brcmf_sdio_count { | ||
107 | uint intrcount; /* Count of device interrupt callbacks */ | ||
108 | uint lastintrs; /* Count as of last watchdog timer */ | ||
109 | uint pollcnt; /* Count of active polls */ | ||
110 | uint regfails; /* Count of R_REG failures */ | ||
111 | uint tx_sderrs; /* Count of tx attempts with sd errors */ | ||
112 | uint fcqueued; /* Tx packets that got queued */ | ||
113 | uint rxrtx; /* Count of rtx requests (NAK to dongle) */ | ||
114 | uint rx_toolong; /* Receive frames too long to receive */ | ||
115 | uint rxc_errors; /* SDIO errors when reading control frames */ | ||
116 | uint rx_hdrfail; /* SDIO errors on header reads */ | ||
117 | uint rx_badhdr; /* Bad received headers (roosync?) */ | ||
118 | uint rx_badseq; /* Mismatched rx sequence number */ | ||
119 | uint fc_rcvd; /* Number of flow-control events received */ | ||
120 | uint fc_xoff; /* Number which turned on flow-control */ | ||
121 | uint fc_xon; /* Number which turned off flow-control */ | ||
122 | uint rxglomfail; /* Failed deglom attempts */ | ||
123 | uint rxglomframes; /* Number of glom frames (superframes) */ | ||
124 | uint rxglompkts; /* Number of packets from glom frames */ | ||
125 | uint f2rxhdrs; /* Number of header reads */ | ||
126 | uint f2rxdata; /* Number of frame data reads */ | ||
127 | uint f2txdata; /* Number of f2 frame writes */ | ||
128 | uint f1regdata; /* Number of f1 register accesses */ | ||
129 | uint tickcnt; /* Number of watchdog been schedule */ | ||
130 | ulong tx_ctlerrs; /* Err of sending ctrl frames */ | ||
131 | ulong tx_ctlpkts; /* Ctrl frames sent to dongle */ | ||
132 | ulong rx_ctlerrs; /* Err of processing rx ctrl frames */ | ||
133 | ulong rx_ctlpkts; /* Ctrl frames processed from dongle */ | ||
134 | ulong rx_readahead_cnt; /* packets where header read-ahead was used */ | ||
135 | }; | ||
136 | |||
137 | struct brcmf_fws_stats { | ||
138 | u32 tlv_parse_failed; | ||
139 | u32 tlv_invalid_type; | ||
140 | u32 header_only_pkt; | ||
141 | u32 header_pulls; | ||
142 | u32 pkt2bus; | ||
143 | u32 send_pkts[5]; | ||
144 | u32 requested_sent[5]; | ||
145 | u32 generic_error; | ||
146 | u32 mac_update_failed; | ||
147 | u32 mac_ps_update_failed; | ||
148 | u32 if_update_failed; | ||
149 | u32 packet_request_failed; | ||
150 | u32 credit_request_failed; | ||
151 | u32 rollback_success; | ||
152 | u32 rollback_failed; | ||
153 | u32 delayq_full_error; | ||
154 | u32 supprq_full_error; | ||
155 | u32 txs_indicate; | ||
156 | u32 txs_discard; | ||
157 | u32 txs_supp_core; | ||
158 | u32 txs_supp_ps; | ||
159 | u32 txs_tossed; | ||
160 | u32 txs_host_tossed; | ||
161 | u32 bus_flow_block; | ||
162 | u32 fws_flow_block; | ||
163 | }; | ||
164 | |||
165 | struct brcmf_pub; | 103 | struct brcmf_pub; |
166 | #ifdef DEBUG | 104 | #ifdef DEBUG |
167 | void brcmf_debugfs_init(void); | 105 | void brcmf_debugfs_init(void); |
@@ -169,10 +107,8 @@ void brcmf_debugfs_exit(void); | |||
169 | int brcmf_debugfs_attach(struct brcmf_pub *drvr); | 107 | int brcmf_debugfs_attach(struct brcmf_pub *drvr); |
170 | void brcmf_debugfs_detach(struct brcmf_pub *drvr); | 108 | void brcmf_debugfs_detach(struct brcmf_pub *drvr); |
171 | struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr); | 109 | struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr); |
172 | void brcmf_debugfs_create_sdio_count(struct brcmf_pub *drvr, | 110 | int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn, |
173 | struct brcmf_sdio_count *sdcnt); | 111 | int (*read_fn)(struct seq_file *seq, void *data)); |
174 | void brcmf_debugfs_create_fws_stats(struct brcmf_pub *drvr, | ||
175 | struct brcmf_fws_stats *stats); | ||
176 | #else | 112 | #else |
177 | static inline void brcmf_debugfs_init(void) | 113 | static inline void brcmf_debugfs_init(void) |
178 | { | 114 | { |
@@ -187,9 +123,11 @@ static inline int brcmf_debugfs_attach(struct brcmf_pub *drvr) | |||
187 | static inline void brcmf_debugfs_detach(struct brcmf_pub *drvr) | 123 | static inline void brcmf_debugfs_detach(struct brcmf_pub *drvr) |
188 | { | 124 | { |
189 | } | 125 | } |
190 | static inline void brcmf_debugfs_create_fws_stats(struct brcmf_pub *drvr, | 126 | static inline |
191 | struct brcmf_fws_stats *stats) | 127 | int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn, |
128 | int (*read_fn)(struct seq_file *seq, void *data)) | ||
192 | { | 129 | { |
130 | return 0; | ||
193 | } | 131 | } |
194 | #endif | 132 | #endif |
195 | 133 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index 2699441d4f41..347b4260f45b 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include "wl_cfg80211.h" | 30 | #include "wl_cfg80211.h" |
31 | #include "fwil.h" | 31 | #include "fwil.h" |
32 | #include "fwsignal.h" | 32 | #include "fwsignal.h" |
33 | #include "feature.h" | ||
33 | #include "proto.h" | 34 | #include "proto.h" |
34 | 35 | ||
35 | MODULE_AUTHOR("Broadcom Corporation"); | 36 | MODULE_AUTHOR("Broadcom Corporation"); |
@@ -937,6 +938,8 @@ int brcmf_bus_start(struct device *dev) | |||
937 | if (ret < 0) | 938 | if (ret < 0) |
938 | goto fail; | 939 | goto fail; |
939 | 940 | ||
941 | brcmf_feat_attach(drvr); | ||
942 | |||
940 | ret = brcmf_fws_init(drvr); | 943 | ret = brcmf_fws_init(drvr); |
941 | if (ret < 0) | 944 | if (ret < 0) |
942 | goto fail; | 945 | goto fail; |
@@ -1074,16 +1077,6 @@ int brcmf_netdev_wait_pend8021x(struct net_device *ndev) | |||
1074 | return !err; | 1077 | return !err; |
1075 | } | 1078 | } |
1076 | 1079 | ||
1077 | /* | ||
1078 | * return chip id and rev of the device encoded in u32. | ||
1079 | */ | ||
1080 | u32 brcmf_get_chip_info(struct brcmf_if *ifp) | ||
1081 | { | ||
1082 | struct brcmf_bus *bus = ifp->drvr->bus_if; | ||
1083 | |||
1084 | return bus->chip << 4 | bus->chiprev; | ||
1085 | } | ||
1086 | |||
1087 | static void brcmf_driver_register(struct work_struct *work) | 1080 | static void brcmf_driver_register(struct work_struct *work) |
1088 | { | 1081 | { |
1089 | #ifdef CONFIG_BRCMFMAC_SDIO | 1082 | #ifdef CONFIG_BRCMFMAC_SDIO |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index 8fa0dbbbda72..67d91d5cc13d 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | |||
@@ -391,6 +391,40 @@ struct brcmf_sdio_hdrinfo { | |||
391 | u16 tail_pad; | 391 | u16 tail_pad; |
392 | }; | 392 | }; |
393 | 393 | ||
394 | /* | ||
395 | * hold counter variables | ||
396 | */ | ||
397 | struct brcmf_sdio_count { | ||
398 | uint intrcount; /* Count of device interrupt callbacks */ | ||
399 | uint lastintrs; /* Count as of last watchdog timer */ | ||
400 | uint pollcnt; /* Count of active polls */ | ||
401 | uint regfails; /* Count of R_REG failures */ | ||
402 | uint tx_sderrs; /* Count of tx attempts with sd errors */ | ||
403 | uint fcqueued; /* Tx packets that got queued */ | ||
404 | uint rxrtx; /* Count of rtx requests (NAK to dongle) */ | ||
405 | uint rx_toolong; /* Receive frames too long to receive */ | ||
406 | uint rxc_errors; /* SDIO errors when reading control frames */ | ||
407 | uint rx_hdrfail; /* SDIO errors on header reads */ | ||
408 | uint rx_badhdr; /* Bad received headers (roosync?) */ | ||
409 | uint rx_badseq; /* Mismatched rx sequence number */ | ||
410 | uint fc_rcvd; /* Number of flow-control events received */ | ||
411 | uint fc_xoff; /* Number which turned on flow-control */ | ||
412 | uint fc_xon; /* Number which turned off flow-control */ | ||
413 | uint rxglomfail; /* Failed deglom attempts */ | ||
414 | uint rxglomframes; /* Number of glom frames (superframes) */ | ||
415 | uint rxglompkts; /* Number of packets from glom frames */ | ||
416 | uint f2rxhdrs; /* Number of header reads */ | ||
417 | uint f2rxdata; /* Number of frame data reads */ | ||
418 | uint f2txdata; /* Number of f2 frame writes */ | ||
419 | uint f1regdata; /* Number of f1 register accesses */ | ||
420 | uint tickcnt; /* Number of watchdog been schedule */ | ||
421 | ulong tx_ctlerrs; /* Err of sending ctrl frames */ | ||
422 | ulong tx_ctlpkts; /* Ctrl frames sent to dongle */ | ||
423 | ulong rx_ctlerrs; /* Err of processing rx ctrl frames */ | ||
424 | ulong rx_ctlpkts; /* Ctrl frames processed from dongle */ | ||
425 | ulong rx_readahead_cnt; /* packets where header read-ahead was used */ | ||
426 | }; | ||
427 | |||
394 | /* misc chip info needed by some of the routines */ | 428 | /* misc chip info needed by some of the routines */ |
395 | /* Private data for SDIO bus interaction */ | 429 | /* Private data for SDIO bus interaction */ |
396 | struct brcmf_sdio { | 430 | struct brcmf_sdio { |
@@ -620,40 +654,46 @@ enum brcmf_firmware_type { | |||
620 | name ## _FIRMWARE_NAME, name ## _NVRAM_NAME | 654 | name ## _FIRMWARE_NAME, name ## _NVRAM_NAME |
621 | 655 | ||
622 | static const struct brcmf_firmware_names brcmf_fwname_data[] = { | 656 | static const struct brcmf_firmware_names brcmf_fwname_data[] = { |
623 | { BCM43143_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM43143) }, | 657 | { BRCM_CC_43143_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM43143) }, |
624 | { BCM43241_CHIP_ID, 0x0000001F, BRCMF_FIRMWARE_NVRAM(BCM43241B0) }, | 658 | { BRCM_CC_43241_CHIP_ID, 0x0000001F, BRCMF_FIRMWARE_NVRAM(BCM43241B0) }, |
625 | { BCM43241_CHIP_ID, 0xFFFFFFE0, BRCMF_FIRMWARE_NVRAM(BCM43241B4) }, | 659 | { BRCM_CC_43241_CHIP_ID, 0xFFFFFFE0, BRCMF_FIRMWARE_NVRAM(BCM43241B4) }, |
626 | { BCM4329_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4329) }, | 660 | { BRCM_CC_4329_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4329) }, |
627 | { BCM4330_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4330) }, | 661 | { BRCM_CC_4330_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4330) }, |
628 | { BCM4334_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4334) }, | 662 | { BRCM_CC_4334_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4334) }, |
629 | { BCM4335_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4335) }, | 663 | { BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4335) }, |
630 | { BCM43362_CHIP_ID, 0xFFFFFFFE, BRCMF_FIRMWARE_NVRAM(BCM43362) }, | 664 | { BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, BRCMF_FIRMWARE_NVRAM(BCM43362) }, |
631 | { BCM4339_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4339) }, | 665 | { BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4339) }, |
632 | { BCM4354_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4354) } | 666 | { BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4354) } |
633 | }; | 667 | }; |
634 | 668 | ||
635 | static const char *brcmf_sdio_get_fwname(struct brcmf_chip *ci, | 669 | static int brcmf_sdio_get_fwnames(struct brcmf_chip *ci, |
636 | enum brcmf_firmware_type type) | 670 | struct brcmf_sdio_dev *sdiodev) |
637 | { | 671 | { |
638 | int i; | 672 | int i; |
639 | 673 | ||
640 | for (i = 0; i < ARRAY_SIZE(brcmf_fwname_data); i++) { | 674 | for (i = 0; i < ARRAY_SIZE(brcmf_fwname_data); i++) { |
641 | if (brcmf_fwname_data[i].chipid == ci->chip && | 675 | if (brcmf_fwname_data[i].chipid == ci->chip && |
642 | brcmf_fwname_data[i].revmsk & BIT(ci->chiprev)) { | 676 | brcmf_fwname_data[i].revmsk & BIT(ci->chiprev)) |
643 | switch (type) { | 677 | break; |
644 | case BRCMF_FIRMWARE_BIN: | ||
645 | return brcmf_fwname_data[i].bin; | ||
646 | case BRCMF_FIRMWARE_NVRAM: | ||
647 | return brcmf_fwname_data[i].nv; | ||
648 | default: | ||
649 | brcmf_err("invalid firmware type (%d)\n", type); | ||
650 | return NULL; | ||
651 | } | ||
652 | } | ||
653 | } | 678 | } |
654 | brcmf_err("Unknown chipid %d [%d]\n", | 679 | |
655 | ci->chip, ci->chiprev); | 680 | if (i == ARRAY_SIZE(brcmf_fwname_data)) { |
656 | return NULL; | 681 | brcmf_err("Unknown chipid %d [%d]\n", ci->chip, ci->chiprev); |
682 | return -ENODEV; | ||
683 | } | ||
684 | |||
685 | /* check if firmware path is provided by module parameter */ | ||
686 | if (brcmf_firmware_path[0] != '\0') { | ||
687 | if (brcmf_firmware_path[strlen(brcmf_firmware_path) - 1] != '/') | ||
688 | strcat(brcmf_firmware_path, "/"); | ||
689 | |||
690 | strcpy(sdiodev->fw_name, brcmf_firmware_path); | ||
691 | strcpy(sdiodev->nvram_name, brcmf_firmware_path); | ||
692 | } | ||
693 | strcat(sdiodev->fw_name, brcmf_fwname_data[i].bin); | ||
694 | strcat(sdiodev->nvram_name, brcmf_fwname_data[i].nv); | ||
695 | |||
696 | return 0; | ||
657 | } | 697 | } |
658 | 698 | ||
659 | static void pkt_align(struct sk_buff *p, int len, int align) | 699 | static void pkt_align(struct sk_buff *p, int len, int align) |
@@ -2898,16 +2938,13 @@ brcmf_sdio_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) | |||
2898 | } | 2938 | } |
2899 | 2939 | ||
2900 | #ifdef DEBUG | 2940 | #ifdef DEBUG |
2901 | static int brcmf_sdio_dump_console(struct brcmf_sdio *bus, | 2941 | static int brcmf_sdio_dump_console(struct seq_file *seq, struct brcmf_sdio *bus, |
2902 | struct sdpcm_shared *sh, char __user *data, | 2942 | struct sdpcm_shared *sh) |
2903 | size_t count) | ||
2904 | { | 2943 | { |
2905 | u32 addr, console_ptr, console_size, console_index; | 2944 | u32 addr, console_ptr, console_size, console_index; |
2906 | char *conbuf = NULL; | 2945 | char *conbuf = NULL; |
2907 | __le32 sh_val; | 2946 | __le32 sh_val; |
2908 | int rv; | 2947 | int rv; |
2909 | loff_t pos = 0; | ||
2910 | int nbytes = 0; | ||
2911 | 2948 | ||
2912 | /* obtain console information from device memory */ | 2949 | /* obtain console information from device memory */ |
2913 | addr = sh->console_addr + offsetof(struct rte_console, log_le); | 2950 | addr = sh->console_addr + offsetof(struct rte_console, log_le); |
@@ -2945,33 +2982,24 @@ static int brcmf_sdio_dump_console(struct brcmf_sdio *bus, | |||
2945 | if (rv < 0) | 2982 | if (rv < 0) |
2946 | goto done; | 2983 | goto done; |
2947 | 2984 | ||
2948 | rv = simple_read_from_buffer(data, count, &pos, | 2985 | rv = seq_write(seq, conbuf + console_index, |
2949 | conbuf + console_index, | 2986 | console_size - console_index); |
2950 | console_size - console_index); | ||
2951 | if (rv < 0) | 2987 | if (rv < 0) |
2952 | goto done; | 2988 | goto done; |
2953 | 2989 | ||
2954 | nbytes = rv; | 2990 | if (console_index > 0) |
2955 | if (console_index > 0) { | 2991 | rv = seq_write(seq, conbuf, console_index - 1); |
2956 | pos = 0; | 2992 | |
2957 | rv = simple_read_from_buffer(data+nbytes, count, &pos, | ||
2958 | conbuf, console_index - 1); | ||
2959 | if (rv < 0) | ||
2960 | goto done; | ||
2961 | rv += nbytes; | ||
2962 | } | ||
2963 | done: | 2993 | done: |
2964 | vfree(conbuf); | 2994 | vfree(conbuf); |
2965 | return rv; | 2995 | return rv; |
2966 | } | 2996 | } |
2967 | 2997 | ||
2968 | static int brcmf_sdio_trap_info(struct brcmf_sdio *bus, struct sdpcm_shared *sh, | 2998 | static int brcmf_sdio_trap_info(struct seq_file *seq, struct brcmf_sdio *bus, |
2969 | char __user *data, size_t count) | 2999 | struct sdpcm_shared *sh) |
2970 | { | 3000 | { |
2971 | int error, res; | 3001 | int error; |
2972 | char buf[350]; | ||
2973 | struct brcmf_trap_info tr; | 3002 | struct brcmf_trap_info tr; |
2974 | loff_t pos = 0; | ||
2975 | 3003 | ||
2976 | if ((sh->flags & SDPCM_SHARED_TRAP) == 0) { | 3004 | if ((sh->flags & SDPCM_SHARED_TRAP) == 0) { |
2977 | brcmf_dbg(INFO, "no trap in firmware\n"); | 3005 | brcmf_dbg(INFO, "no trap in firmware\n"); |
@@ -2983,34 +3011,30 @@ static int brcmf_sdio_trap_info(struct brcmf_sdio *bus, struct sdpcm_shared *sh, | |||
2983 | if (error < 0) | 3011 | if (error < 0) |
2984 | return error; | 3012 | return error; |
2985 | 3013 | ||
2986 | res = scnprintf(buf, sizeof(buf), | 3014 | seq_printf(seq, |
2987 | "dongle trap info: type 0x%x @ epc 0x%08x\n" | 3015 | "dongle trap info: type 0x%x @ epc 0x%08x\n" |
2988 | " cpsr 0x%08x spsr 0x%08x sp 0x%08x\n" | 3016 | " cpsr 0x%08x spsr 0x%08x sp 0x%08x\n" |
2989 | " lr 0x%08x pc 0x%08x offset 0x%x\n" | 3017 | " lr 0x%08x pc 0x%08x offset 0x%x\n" |
2990 | " r0 0x%08x r1 0x%08x r2 0x%08x r3 0x%08x\n" | 3018 | " r0 0x%08x r1 0x%08x r2 0x%08x r3 0x%08x\n" |
2991 | " r4 0x%08x r5 0x%08x r6 0x%08x r7 0x%08x\n", | 3019 | " r4 0x%08x r5 0x%08x r6 0x%08x r7 0x%08x\n", |
2992 | le32_to_cpu(tr.type), le32_to_cpu(tr.epc), | 3020 | le32_to_cpu(tr.type), le32_to_cpu(tr.epc), |
2993 | le32_to_cpu(tr.cpsr), le32_to_cpu(tr.spsr), | 3021 | le32_to_cpu(tr.cpsr), le32_to_cpu(tr.spsr), |
2994 | le32_to_cpu(tr.r13), le32_to_cpu(tr.r14), | 3022 | le32_to_cpu(tr.r13), le32_to_cpu(tr.r14), |
2995 | le32_to_cpu(tr.pc), sh->trap_addr, | 3023 | le32_to_cpu(tr.pc), sh->trap_addr, |
2996 | le32_to_cpu(tr.r0), le32_to_cpu(tr.r1), | 3024 | le32_to_cpu(tr.r0), le32_to_cpu(tr.r1), |
2997 | le32_to_cpu(tr.r2), le32_to_cpu(tr.r3), | 3025 | le32_to_cpu(tr.r2), le32_to_cpu(tr.r3), |
2998 | le32_to_cpu(tr.r4), le32_to_cpu(tr.r5), | 3026 | le32_to_cpu(tr.r4), le32_to_cpu(tr.r5), |
2999 | le32_to_cpu(tr.r6), le32_to_cpu(tr.r7)); | 3027 | le32_to_cpu(tr.r6), le32_to_cpu(tr.r7)); |
3000 | 3028 | ||
3001 | return simple_read_from_buffer(data, count, &pos, buf, res); | 3029 | return 0; |
3002 | } | 3030 | } |
3003 | 3031 | ||
3004 | static int brcmf_sdio_assert_info(struct brcmf_sdio *bus, | 3032 | static int brcmf_sdio_assert_info(struct seq_file *seq, struct brcmf_sdio *bus, |
3005 | struct sdpcm_shared *sh, char __user *data, | 3033 | struct sdpcm_shared *sh) |
3006 | size_t count) | ||
3007 | { | 3034 | { |
3008 | int error = 0; | 3035 | int error = 0; |
3009 | char buf[200]; | ||
3010 | char file[80] = "?"; | 3036 | char file[80] = "?"; |
3011 | char expr[80] = "<???>"; | 3037 | char expr[80] = "<???>"; |
3012 | int res; | ||
3013 | loff_t pos = 0; | ||
3014 | 3038 | ||
3015 | if ((sh->flags & SDPCM_SHARED_ASSERT_BUILT) == 0) { | 3039 | if ((sh->flags & SDPCM_SHARED_ASSERT_BUILT) == 0) { |
3016 | brcmf_dbg(INFO, "firmware not built with -assert\n"); | 3040 | brcmf_dbg(INFO, "firmware not built with -assert\n"); |
@@ -3035,10 +3059,9 @@ static int brcmf_sdio_assert_info(struct brcmf_sdio *bus, | |||
3035 | } | 3059 | } |
3036 | sdio_release_host(bus->sdiodev->func[1]); | 3060 | sdio_release_host(bus->sdiodev->func[1]); |
3037 | 3061 | ||
3038 | res = scnprintf(buf, sizeof(buf), | 3062 | seq_printf(seq, "dongle assert: %s:%d: assert(%s)\n", |
3039 | "dongle assert: %s:%d: assert(%s)\n", | 3063 | file, sh->assert_line, expr); |
3040 | file, sh->assert_line, expr); | 3064 | return 0; |
3041 | return simple_read_from_buffer(data, count, &pos, buf, res); | ||
3042 | } | 3065 | } |
3043 | 3066 | ||
3044 | static int brcmf_sdio_checkdied(struct brcmf_sdio *bus) | 3067 | static int brcmf_sdio_checkdied(struct brcmf_sdio *bus) |
@@ -3062,59 +3085,75 @@ static int brcmf_sdio_checkdied(struct brcmf_sdio *bus) | |||
3062 | return 0; | 3085 | return 0; |
3063 | } | 3086 | } |
3064 | 3087 | ||
3065 | static int brcmf_sdio_died_dump(struct brcmf_sdio *bus, char __user *data, | 3088 | static int brcmf_sdio_died_dump(struct seq_file *seq, struct brcmf_sdio *bus) |
3066 | size_t count, loff_t *ppos) | ||
3067 | { | 3089 | { |
3068 | int error = 0; | 3090 | int error = 0; |
3069 | struct sdpcm_shared sh; | 3091 | struct sdpcm_shared sh; |
3070 | int nbytes = 0; | ||
3071 | loff_t pos = *ppos; | ||
3072 | |||
3073 | if (pos != 0) | ||
3074 | return 0; | ||
3075 | 3092 | ||
3076 | error = brcmf_sdio_readshared(bus, &sh); | 3093 | error = brcmf_sdio_readshared(bus, &sh); |
3077 | if (error < 0) | 3094 | if (error < 0) |
3078 | goto done; | 3095 | goto done; |
3079 | 3096 | ||
3080 | error = brcmf_sdio_assert_info(bus, &sh, data, count); | 3097 | error = brcmf_sdio_assert_info(seq, bus, &sh); |
3081 | if (error < 0) | 3098 | if (error < 0) |
3082 | goto done; | 3099 | goto done; |
3083 | nbytes = error; | ||
3084 | 3100 | ||
3085 | error = brcmf_sdio_trap_info(bus, &sh, data+nbytes, count); | 3101 | error = brcmf_sdio_trap_info(seq, bus, &sh); |
3086 | if (error < 0) | 3102 | if (error < 0) |
3087 | goto done; | 3103 | goto done; |
3088 | nbytes += error; | ||
3089 | 3104 | ||
3090 | error = brcmf_sdio_dump_console(bus, &sh, data+nbytes, count); | 3105 | error = brcmf_sdio_dump_console(seq, bus, &sh); |
3091 | if (error < 0) | ||
3092 | goto done; | ||
3093 | nbytes += error; | ||
3094 | 3106 | ||
3095 | error = nbytes; | ||
3096 | *ppos += nbytes; | ||
3097 | done: | 3107 | done: |
3098 | return error; | 3108 | return error; |
3099 | } | 3109 | } |
3100 | 3110 | ||
3101 | static ssize_t brcmf_sdio_forensic_read(struct file *f, char __user *data, | 3111 | static int brcmf_sdio_forensic_read(struct seq_file *seq, void *data) |
3102 | size_t count, loff_t *ppos) | ||
3103 | { | 3112 | { |
3104 | struct brcmf_sdio *bus = f->private_data; | 3113 | struct brcmf_bus *bus_if = dev_get_drvdata(seq->private); |
3105 | int res; | 3114 | struct brcmf_sdio *bus = bus_if->bus_priv.sdio->bus; |
3106 | 3115 | ||
3107 | res = brcmf_sdio_died_dump(bus, data, count, ppos); | 3116 | return brcmf_sdio_died_dump(seq, bus); |
3108 | if (res > 0) | ||
3109 | *ppos += res; | ||
3110 | return (ssize_t)res; | ||
3111 | } | 3117 | } |
3112 | 3118 | ||
3113 | static const struct file_operations brcmf_sdio_forensic_ops = { | 3119 | static int brcmf_debugfs_sdio_count_read(struct seq_file *seq, void *data) |
3114 | .owner = THIS_MODULE, | 3120 | { |
3115 | .open = simple_open, | 3121 | struct brcmf_bus *bus_if = dev_get_drvdata(seq->private); |
3116 | .read = brcmf_sdio_forensic_read | 3122 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; |
3117 | }; | 3123 | struct brcmf_sdio_count *sdcnt = &sdiodev->bus->sdcnt; |
3124 | |||
3125 | seq_printf(seq, | ||
3126 | "intrcount: %u\nlastintrs: %u\n" | ||
3127 | "pollcnt: %u\nregfails: %u\n" | ||
3128 | "tx_sderrs: %u\nfcqueued: %u\n" | ||
3129 | "rxrtx: %u\nrx_toolong: %u\n" | ||
3130 | "rxc_errors: %u\nrx_hdrfail: %u\n" | ||
3131 | "rx_badhdr: %u\nrx_badseq: %u\n" | ||
3132 | "fc_rcvd: %u\nfc_xoff: %u\n" | ||
3133 | "fc_xon: %u\nrxglomfail: %u\n" | ||
3134 | "rxglomframes: %u\nrxglompkts: %u\n" | ||
3135 | "f2rxhdrs: %u\nf2rxdata: %u\n" | ||
3136 | "f2txdata: %u\nf1regdata: %u\n" | ||
3137 | "tickcnt: %u\ntx_ctlerrs: %lu\n" | ||
3138 | "tx_ctlpkts: %lu\nrx_ctlerrs: %lu\n" | ||
3139 | "rx_ctlpkts: %lu\nrx_readahead: %lu\n", | ||
3140 | sdcnt->intrcount, sdcnt->lastintrs, | ||
3141 | sdcnt->pollcnt, sdcnt->regfails, | ||
3142 | sdcnt->tx_sderrs, sdcnt->fcqueued, | ||
3143 | sdcnt->rxrtx, sdcnt->rx_toolong, | ||
3144 | sdcnt->rxc_errors, sdcnt->rx_hdrfail, | ||
3145 | sdcnt->rx_badhdr, sdcnt->rx_badseq, | ||
3146 | sdcnt->fc_rcvd, sdcnt->fc_xoff, | ||
3147 | sdcnt->fc_xon, sdcnt->rxglomfail, | ||
3148 | sdcnt->rxglomframes, sdcnt->rxglompkts, | ||
3149 | sdcnt->f2rxhdrs, sdcnt->f2rxdata, | ||
3150 | sdcnt->f2txdata, sdcnt->f1regdata, | ||
3151 | sdcnt->tickcnt, sdcnt->tx_ctlerrs, | ||
3152 | sdcnt->tx_ctlpkts, sdcnt->rx_ctlerrs, | ||
3153 | sdcnt->rx_ctlpkts, sdcnt->rx_readahead_cnt); | ||
3154 | |||
3155 | return 0; | ||
3156 | } | ||
3118 | 3157 | ||
3119 | static void brcmf_sdio_debugfs_create(struct brcmf_sdio *bus) | 3158 | static void brcmf_sdio_debugfs_create(struct brcmf_sdio *bus) |
3120 | { | 3159 | { |
@@ -3124,9 +3163,9 @@ static void brcmf_sdio_debugfs_create(struct brcmf_sdio *bus) | |||
3124 | if (IS_ERR_OR_NULL(dentry)) | 3163 | if (IS_ERR_OR_NULL(dentry)) |
3125 | return; | 3164 | return; |
3126 | 3165 | ||
3127 | debugfs_create_file("forensics", S_IRUGO, dentry, bus, | 3166 | brcmf_debugfs_add_entry(drvr, "forensics", brcmf_sdio_forensic_read); |
3128 | &brcmf_sdio_forensic_ops); | 3167 | brcmf_debugfs_add_entry(drvr, "counters", |
3129 | brcmf_debugfs_create_sdio_count(drvr, &bus->sdcnt); | 3168 | brcmf_debugfs_sdio_count_read); |
3130 | debugfs_create_u32("console_interval", 0644, dentry, | 3169 | debugfs_create_u32("console_interval", 0644, dentry, |
3131 | &bus->console_interval); | 3170 | &bus->console_interval); |
3132 | } | 3171 | } |
@@ -3598,17 +3637,17 @@ brcmf_sdio_drivestrengthinit(struct brcmf_sdio_dev *sdiodev, | |||
3598 | return; | 3637 | return; |
3599 | 3638 | ||
3600 | switch (SDIOD_DRVSTR_KEY(ci->chip, ci->pmurev)) { | 3639 | switch (SDIOD_DRVSTR_KEY(ci->chip, ci->pmurev)) { |
3601 | case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID, 12): | 3640 | case SDIOD_DRVSTR_KEY(BRCM_CC_4330_CHIP_ID, 12): |
3602 | str_tab = sdiod_drvstr_tab1_1v8; | 3641 | str_tab = sdiod_drvstr_tab1_1v8; |
3603 | str_mask = 0x00003800; | 3642 | str_mask = 0x00003800; |
3604 | str_shift = 11; | 3643 | str_shift = 11; |
3605 | break; | 3644 | break; |
3606 | case SDIOD_DRVSTR_KEY(BCM4334_CHIP_ID, 17): | 3645 | case SDIOD_DRVSTR_KEY(BRCM_CC_4334_CHIP_ID, 17): |
3607 | str_tab = sdiod_drvstr_tab6_1v8; | 3646 | str_tab = sdiod_drvstr_tab6_1v8; |
3608 | str_mask = 0x00001800; | 3647 | str_mask = 0x00001800; |
3609 | str_shift = 11; | 3648 | str_shift = 11; |
3610 | break; | 3649 | break; |
3611 | case SDIOD_DRVSTR_KEY(BCM43143_CHIP_ID, 17): | 3650 | case SDIOD_DRVSTR_KEY(BRCM_CC_43143_CHIP_ID, 17): |
3612 | /* note: 43143 does not support tristate */ | 3651 | /* note: 43143 does not support tristate */ |
3613 | i = ARRAY_SIZE(sdiod_drvstr_tab2_3v3) - 1; | 3652 | i = ARRAY_SIZE(sdiod_drvstr_tab2_3v3) - 1; |
3614 | if (drivestrength >= sdiod_drvstr_tab2_3v3[i].strength) { | 3653 | if (drivestrength >= sdiod_drvstr_tab2_3v3[i].strength) { |
@@ -3619,7 +3658,7 @@ brcmf_sdio_drivestrengthinit(struct brcmf_sdio_dev *sdiodev, | |||
3619 | brcmf_err("Invalid SDIO Drive strength for chip %s, strength=%d\n", | 3658 | brcmf_err("Invalid SDIO Drive strength for chip %s, strength=%d\n", |
3620 | ci->name, drivestrength); | 3659 | ci->name, drivestrength); |
3621 | break; | 3660 | break; |
3622 | case SDIOD_DRVSTR_KEY(BCM43362_CHIP_ID, 13): | 3661 | case SDIOD_DRVSTR_KEY(BRCM_CC_43362_CHIP_ID, 13): |
3623 | str_tab = sdiod_drive_strength_tab5_1v8; | 3662 | str_tab = sdiod_drive_strength_tab5_1v8; |
3624 | str_mask = 0x00003800; | 3663 | str_mask = 0x00003800; |
3625 | str_shift = 11; | 3664 | str_shift = 11; |
@@ -3720,12 +3759,12 @@ static u32 brcmf_sdio_buscore_read32(void *ctx, u32 addr) | |||
3720 | u32 val, rev; | 3759 | u32 val, rev; |
3721 | 3760 | ||
3722 | val = brcmf_sdiod_regrl(sdiodev, addr, NULL); | 3761 | val = brcmf_sdiod_regrl(sdiodev, addr, NULL); |
3723 | if (sdiodev->func[0]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339 && | 3762 | if (sdiodev->func[0]->device == BRCM_SDIO_4335_4339_DEVICE_ID && |
3724 | addr == CORE_CC_REG(SI_ENUM_BASE, chipid)) { | 3763 | addr == CORE_CC_REG(SI_ENUM_BASE, chipid)) { |
3725 | rev = (val & CID_REV_MASK) >> CID_REV_SHIFT; | 3764 | rev = (val & CID_REV_MASK) >> CID_REV_SHIFT; |
3726 | if (rev >= 2) { | 3765 | if (rev >= 2) { |
3727 | val &= ~CID_ID_MASK; | 3766 | val &= ~CID_ID_MASK; |
3728 | val |= BCM4339_CHIP_ID; | 3767 | val |= BRCM_CC_4339_CHIP_ID; |
3729 | } | 3768 | } |
3730 | } | 3769 | } |
3731 | return val; | 3770 | return val; |
@@ -4127,11 +4166,12 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) | |||
4127 | brcmf_sdio_debugfs_create(bus); | 4166 | brcmf_sdio_debugfs_create(bus); |
4128 | brcmf_dbg(INFO, "completed!!\n"); | 4167 | brcmf_dbg(INFO, "completed!!\n"); |
4129 | 4168 | ||
4169 | ret = brcmf_sdio_get_fwnames(bus->ci, sdiodev); | ||
4170 | if (ret) | ||
4171 | goto fail; | ||
4172 | |||
4130 | ret = brcmf_fw_get_firmwares(sdiodev->dev, BRCMF_FW_REQUEST_NVRAM, | 4173 | ret = brcmf_fw_get_firmwares(sdiodev->dev, BRCMF_FW_REQUEST_NVRAM, |
4131 | brcmf_sdio_get_fwname(bus->ci, | 4174 | sdiodev->fw_name, sdiodev->nvram_name, |
4132 | BRCMF_FIRMWARE_BIN), | ||
4133 | brcmf_sdio_get_fwname(bus->ci, | ||
4134 | BRCMF_FIRMWARE_NVRAM), | ||
4135 | brcmf_sdio_firmware_callback); | 4175 | brcmf_sdio_firmware_callback); |
4136 | if (ret != 0) { | 4176 | if (ret != 0) { |
4137 | brcmf_err("async firmware request failed: %d\n", ret); | 4177 | brcmf_err("async firmware request failed: %d\n", ret); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/feature.c b/drivers/net/wireless/brcm80211/brcmfmac/feature.c new file mode 100644 index 000000000000..50877e3c5d2f --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.c | |||
@@ -0,0 +1,136 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2014 Broadcom Corporation | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include <linux/netdevice.h> | ||
18 | |||
19 | #include <brcm_hw_ids.h> | ||
20 | #include "dhd.h" | ||
21 | #include "dhd_bus.h" | ||
22 | #include "dhd_dbg.h" | ||
23 | #include "fwil.h" | ||
24 | #include "feature.h" | ||
25 | |||
26 | /* | ||
27 | * firmware error code received if iovar is unsupported. | ||
28 | */ | ||
29 | #define EBRCMF_FEAT_UNSUPPORTED 23 | ||
30 | |||
31 | /* | ||
32 | * expand feature list to array of feature strings. | ||
33 | */ | ||
34 | #define BRCMF_FEAT_DEF(_f) \ | ||
35 | #_f, | ||
36 | static const char *brcmf_feat_names[] = { | ||
37 | BRCMF_FEAT_LIST | ||
38 | }; | ||
39 | #undef BRCMF_FEAT_DEF | ||
40 | |||
41 | #ifdef DEBUG | ||
42 | /* | ||
43 | * expand quirk list to array of quirk strings. | ||
44 | */ | ||
45 | #define BRCMF_QUIRK_DEF(_q) \ | ||
46 | #_q, | ||
47 | static const char * const brcmf_quirk_names[] = { | ||
48 | BRCMF_QUIRK_LIST | ||
49 | }; | ||
50 | #undef BRCMF_QUIRK_DEF | ||
51 | |||
52 | /** | ||
53 | * brcmf_feat_debugfs_read() - expose feature info to debugfs. | ||
54 | * | ||
55 | * @seq: sequence for debugfs entry. | ||
56 | * @data: raw data pointer. | ||
57 | */ | ||
58 | static int brcmf_feat_debugfs_read(struct seq_file *seq, void *data) | ||
59 | { | ||
60 | struct brcmf_bus *bus_if = dev_get_drvdata(seq->private); | ||
61 | u32 feats = bus_if->drvr->feat_flags; | ||
62 | u32 quirks = bus_if->drvr->chip_quirks; | ||
63 | int id; | ||
64 | |||
65 | seq_printf(seq, "Features: %08x\n", feats); | ||
66 | for (id = 0; id < BRCMF_FEAT_LAST; id++) | ||
67 | if (feats & BIT(id)) | ||
68 | seq_printf(seq, "\t%s\n", brcmf_feat_names[id]); | ||
69 | seq_printf(seq, "\nQuirks: %08x\n", quirks); | ||
70 | for (id = 0; id < BRCMF_FEAT_QUIRK_LAST; id++) | ||
71 | if (quirks & BIT(id)) | ||
72 | seq_printf(seq, "\t%s\n", brcmf_quirk_names[id]); | ||
73 | return 0; | ||
74 | } | ||
75 | #else | ||
76 | static int brcmf_feat_debugfs_read(struct seq_file *seq, void *data) | ||
77 | { | ||
78 | return 0; | ||
79 | } | ||
80 | #endif /* DEBUG */ | ||
81 | |||
82 | /** | ||
83 | * brcmf_feat_iovar_int_get() - determine feature through iovar query. | ||
84 | * | ||
85 | * @ifp: interface to query. | ||
86 | * @id: feature id. | ||
87 | * @name: iovar name. | ||
88 | */ | ||
89 | static void brcmf_feat_iovar_int_get(struct brcmf_if *ifp, | ||
90 | enum brcmf_feat_id id, char *name) | ||
91 | { | ||
92 | u32 data; | ||
93 | int err; | ||
94 | |||
95 | err = brcmf_fil_iovar_int_get(ifp, name, &data); | ||
96 | if (err == 0) { | ||
97 | brcmf_dbg(INFO, "enabling feature: %s\n", brcmf_feat_names[id]); | ||
98 | ifp->drvr->feat_flags |= BIT(id); | ||
99 | } else { | ||
100 | brcmf_dbg(TRACE, "%s feature check failed: %d\n", | ||
101 | brcmf_feat_names[id], err); | ||
102 | } | ||
103 | } | ||
104 | |||
105 | void brcmf_feat_attach(struct brcmf_pub *drvr) | ||
106 | { | ||
107 | struct brcmf_if *ifp = drvr->iflist[0]; | ||
108 | |||
109 | brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_MCHAN, "mchan"); | ||
110 | |||
111 | /* set chip related quirks */ | ||
112 | switch (drvr->bus_if->chip) { | ||
113 | case BRCM_CC_43236_CHIP_ID: | ||
114 | drvr->chip_quirks |= BIT(BRCMF_FEAT_QUIRK_AUTO_AUTH); | ||
115 | break; | ||
116 | case BRCM_CC_4329_CHIP_ID: | ||
117 | drvr->chip_quirks |= BIT(BRCMF_FEAT_QUIRK_NEED_MPC); | ||
118 | break; | ||
119 | default: | ||
120 | /* no quirks */ | ||
121 | break; | ||
122 | } | ||
123 | |||
124 | brcmf_debugfs_add_entry(drvr, "features", brcmf_feat_debugfs_read); | ||
125 | } | ||
126 | |||
127 | bool brcmf_feat_is_enabled(struct brcmf_if *ifp, enum brcmf_feat_id id) | ||
128 | { | ||
129 | return (ifp->drvr->feat_flags & BIT(id)); | ||
130 | } | ||
131 | |||
132 | bool brcmf_feat_is_quirk_enabled(struct brcmf_if *ifp, | ||
133 | enum brcmf_feat_quirk quirk) | ||
134 | { | ||
135 | return (ifp->drvr->chip_quirks & BIT(quirk)); | ||
136 | } | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/feature.h b/drivers/net/wireless/brcm80211/brcmfmac/feature.h new file mode 100644 index 000000000000..961d175f8afb --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.h | |||
@@ -0,0 +1,86 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2014 Broadcom Corporation | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | #ifndef _BRCMF_FEATURE_H | ||
17 | #define _BRCMF_FEATURE_H | ||
18 | |||
19 | /* | ||
20 | * Features: | ||
21 | * | ||
22 | * MCHAN: multi-channel for concurrent P2P. | ||
23 | */ | ||
24 | #define BRCMF_FEAT_LIST \ | ||
25 | BRCMF_FEAT_DEF(MCHAN) | ||
26 | /* | ||
27 | * Quirks: | ||
28 | * | ||
29 | * AUTO_AUTH: workaround needed for automatic authentication type. | ||
30 | * NEED_MPC: driver needs to disable MPC during scanning operation. | ||
31 | */ | ||
32 | #define BRCMF_QUIRK_LIST \ | ||
33 | BRCMF_QUIRK_DEF(AUTO_AUTH) \ | ||
34 | BRCMF_QUIRK_DEF(NEED_MPC) | ||
35 | |||
36 | #define BRCMF_FEAT_DEF(_f) \ | ||
37 | BRCMF_FEAT_ ## _f, | ||
38 | /* | ||
39 | * expand feature list to enumeration. | ||
40 | */ | ||
41 | enum brcmf_feat_id { | ||
42 | BRCMF_FEAT_LIST | ||
43 | BRCMF_FEAT_LAST | ||
44 | }; | ||
45 | #undef BRCMF_FEAT_DEF | ||
46 | |||
47 | #define BRCMF_QUIRK_DEF(_q) \ | ||
48 | BRCMF_FEAT_QUIRK_ ## _q, | ||
49 | /* | ||
50 | * expand quirk list to enumeration. | ||
51 | */ | ||
52 | enum brcmf_feat_quirk { | ||
53 | BRCMF_QUIRK_LIST | ||
54 | BRCMF_FEAT_QUIRK_LAST | ||
55 | }; | ||
56 | #undef BRCMF_QUIRK_DEF | ||
57 | |||
58 | /** | ||
59 | * brcmf_feat_attach() - determine features and quirks. | ||
60 | * | ||
61 | * @drvr: driver instance. | ||
62 | */ | ||
63 | void brcmf_feat_attach(struct brcmf_pub *drvr); | ||
64 | |||
65 | /** | ||
66 | * brcmf_feat_is_enabled() - query feature. | ||
67 | * | ||
68 | * @ifp: interface instance. | ||
69 | * @id: feature id to check. | ||
70 | * | ||
71 | * Return: true is feature is enabled; otherwise false. | ||
72 | */ | ||
73 | bool brcmf_feat_is_enabled(struct brcmf_if *ifp, enum brcmf_feat_id id); | ||
74 | |||
75 | /** | ||
76 | * brcmf_feat_is_quirk_enabled() - query chip quirk. | ||
77 | * | ||
78 | * @ifp: interface instance. | ||
79 | * @quirk: quirk id to check. | ||
80 | * | ||
81 | * Return: true is quirk is enabled; otherwise false. | ||
82 | */ | ||
83 | bool brcmf_feat_is_quirk_enabled(struct brcmf_if *ifp, | ||
84 | enum brcmf_feat_quirk quirk); | ||
85 | |||
86 | #endif /* _BRCMF_FEATURE_H */ | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c index 7b7d237c1ddb..8ea9f283d2b8 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c | |||
@@ -18,10 +18,15 @@ | |||
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/device.h> | 19 | #include <linux/device.h> |
20 | #include <linux/firmware.h> | 20 | #include <linux/firmware.h> |
21 | #include <linux/module.h> | ||
21 | 22 | ||
22 | #include "dhd_dbg.h" | 23 | #include "dhd_dbg.h" |
23 | #include "firmware.h" | 24 | #include "firmware.h" |
24 | 25 | ||
26 | char brcmf_firmware_path[BRCMF_FW_PATH_LEN]; | ||
27 | module_param_string(firmware_path, brcmf_firmware_path, | ||
28 | BRCMF_FW_PATH_LEN, 0440); | ||
29 | |||
25 | enum nvram_parser_state { | 30 | enum nvram_parser_state { |
26 | IDLE, | 31 | IDLE, |
27 | KEY, | 32 | KEY, |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/firmware.h b/drivers/net/wireless/brcm80211/brcmfmac/firmware.h index 6431bfd7afff..4d3482356b77 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.h | |||
@@ -21,6 +21,11 @@ | |||
21 | #define BRCMF_FW_REQ_FLAGS 0x00F0 | 21 | #define BRCMF_FW_REQ_FLAGS 0x00F0 |
22 | #define BRCMF_FW_REQ_NV_OPTIONAL 0x0010 | 22 | #define BRCMF_FW_REQ_NV_OPTIONAL 0x0010 |
23 | 23 | ||
24 | #define BRCMF_FW_PATH_LEN 256 | ||
25 | #define BRCMF_FW_NAME_LEN 32 | ||
26 | |||
27 | extern char brcmf_firmware_path[]; | ||
28 | |||
24 | void brcmf_fw_nvram_free(void *nvram); | 29 | void brcmf_fw_nvram_free(void *nvram); |
25 | /* | 30 | /* |
26 | * Request firmware(s) asynchronously. When the asynchronous request | 31 | * Request firmware(s) asynchronously. When the asynchronous request |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index 699908de314a..d42f7d04b65f 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | |||
@@ -454,6 +454,34 @@ struct brcmf_fws_macdesc_table { | |||
454 | struct brcmf_fws_mac_descriptor other; | 454 | struct brcmf_fws_mac_descriptor other; |
455 | }; | 455 | }; |
456 | 456 | ||
457 | struct brcmf_fws_stats { | ||
458 | u32 tlv_parse_failed; | ||
459 | u32 tlv_invalid_type; | ||
460 | u32 header_only_pkt; | ||
461 | u32 header_pulls; | ||
462 | u32 pkt2bus; | ||
463 | u32 send_pkts[5]; | ||
464 | u32 requested_sent[5]; | ||
465 | u32 generic_error; | ||
466 | u32 mac_update_failed; | ||
467 | u32 mac_ps_update_failed; | ||
468 | u32 if_update_failed; | ||
469 | u32 packet_request_failed; | ||
470 | u32 credit_request_failed; | ||
471 | u32 rollback_success; | ||
472 | u32 rollback_failed; | ||
473 | u32 delayq_full_error; | ||
474 | u32 supprq_full_error; | ||
475 | u32 txs_indicate; | ||
476 | u32 txs_discard; | ||
477 | u32 txs_supp_core; | ||
478 | u32 txs_supp_ps; | ||
479 | u32 txs_tossed; | ||
480 | u32 txs_host_tossed; | ||
481 | u32 bus_flow_block; | ||
482 | u32 fws_flow_block; | ||
483 | }; | ||
484 | |||
457 | struct brcmf_fws_info { | 485 | struct brcmf_fws_info { |
458 | struct brcmf_pub *drvr; | 486 | struct brcmf_pub *drvr; |
459 | spinlock_t spinlock; | 487 | spinlock_t spinlock; |
@@ -2017,6 +2045,75 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker) | |||
2017 | brcmf_fws_unlock(fws); | 2045 | brcmf_fws_unlock(fws); |
2018 | } | 2046 | } |
2019 | 2047 | ||
2048 | #ifdef DEBUG | ||
2049 | static int brcmf_debugfs_fws_stats_read(struct seq_file *seq, void *data) | ||
2050 | { | ||
2051 | struct brcmf_bus *bus_if = dev_get_drvdata(seq->private); | ||
2052 | struct brcmf_fws_stats *fwstats = &bus_if->drvr->fws->stats; | ||
2053 | |||
2054 | seq_printf(seq, | ||
2055 | "header_pulls: %u\n" | ||
2056 | "header_only_pkt: %u\n" | ||
2057 | "tlv_parse_failed: %u\n" | ||
2058 | "tlv_invalid_type: %u\n" | ||
2059 | "mac_update_fails: %u\n" | ||
2060 | "ps_update_fails: %u\n" | ||
2061 | "if_update_fails: %u\n" | ||
2062 | "pkt2bus: %u\n" | ||
2063 | "generic_error: %u\n" | ||
2064 | "rollback_success: %u\n" | ||
2065 | "rollback_failed: %u\n" | ||
2066 | "delayq_full: %u\n" | ||
2067 | "supprq_full: %u\n" | ||
2068 | "txs_indicate: %u\n" | ||
2069 | "txs_discard: %u\n" | ||
2070 | "txs_suppr_core: %u\n" | ||
2071 | "txs_suppr_ps: %u\n" | ||
2072 | "txs_tossed: %u\n" | ||
2073 | "txs_host_tossed: %u\n" | ||
2074 | "bus_flow_block: %u\n" | ||
2075 | "fws_flow_block: %u\n" | ||
2076 | "send_pkts: BK:%u BE:%u VO:%u VI:%u BCMC:%u\n" | ||
2077 | "requested_sent: BK:%u BE:%u VO:%u VI:%u BCMC:%u\n", | ||
2078 | fwstats->header_pulls, | ||
2079 | fwstats->header_only_pkt, | ||
2080 | fwstats->tlv_parse_failed, | ||
2081 | fwstats->tlv_invalid_type, | ||
2082 | fwstats->mac_update_failed, | ||
2083 | fwstats->mac_ps_update_failed, | ||
2084 | fwstats->if_update_failed, | ||
2085 | fwstats->pkt2bus, | ||
2086 | fwstats->generic_error, | ||
2087 | fwstats->rollback_success, | ||
2088 | fwstats->rollback_failed, | ||
2089 | fwstats->delayq_full_error, | ||
2090 | fwstats->supprq_full_error, | ||
2091 | fwstats->txs_indicate, | ||
2092 | fwstats->txs_discard, | ||
2093 | fwstats->txs_supp_core, | ||
2094 | fwstats->txs_supp_ps, | ||
2095 | fwstats->txs_tossed, | ||
2096 | fwstats->txs_host_tossed, | ||
2097 | fwstats->bus_flow_block, | ||
2098 | fwstats->fws_flow_block, | ||
2099 | fwstats->send_pkts[0], fwstats->send_pkts[1], | ||
2100 | fwstats->send_pkts[2], fwstats->send_pkts[3], | ||
2101 | fwstats->send_pkts[4], | ||
2102 | fwstats->requested_sent[0], | ||
2103 | fwstats->requested_sent[1], | ||
2104 | fwstats->requested_sent[2], | ||
2105 | fwstats->requested_sent[3], | ||
2106 | fwstats->requested_sent[4]); | ||
2107 | |||
2108 | return 0; | ||
2109 | } | ||
2110 | #else | ||
2111 | static int brcmf_debugfs_fws_stats_read(struct seq_file *seq, void *data) | ||
2112 | { | ||
2113 | return 0; | ||
2114 | } | ||
2115 | #endif | ||
2116 | |||
2020 | int brcmf_fws_init(struct brcmf_pub *drvr) | 2117 | int brcmf_fws_init(struct brcmf_pub *drvr) |
2021 | { | 2118 | { |
2022 | struct brcmf_fws_info *fws; | 2119 | struct brcmf_fws_info *fws; |
@@ -2107,7 +2204,8 @@ int brcmf_fws_init(struct brcmf_pub *drvr) | |||
2107 | BRCMF_FWS_PSQ_LEN); | 2204 | BRCMF_FWS_PSQ_LEN); |
2108 | 2205 | ||
2109 | /* create debugfs file for statistics */ | 2206 | /* create debugfs file for statistics */ |
2110 | brcmf_debugfs_create_fws_stats(drvr, &fws->stats); | 2207 | brcmf_debugfs_add_entry(drvr, "fws_stats", |
2208 | brcmf_debugfs_fws_stats_read); | ||
2111 | 2209 | ||
2112 | brcmf_dbg(INFO, "%s bdcv2 tlv signaling [%x]\n", | 2210 | brcmf_dbg(INFO, "%s bdcv2 tlv signaling [%x]\n", |
2113 | fws->fw_signals ? "enabled" : "disabled", tlv); | 2211 | fws->fw_signals ? "enabled" : "disabled", tlv); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h index 3deab7959a0d..6c5e585ccda9 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h | |||
@@ -18,6 +18,8 @@ | |||
18 | #define _BRCM_SDH_H_ | 18 | #define _BRCM_SDH_H_ |
19 | 19 | ||
20 | #include <linux/skbuff.h> | 20 | #include <linux/skbuff.h> |
21 | #include <linux/firmware.h> | ||
22 | #include "firmware.h" | ||
21 | 23 | ||
22 | #define SDIO_FUNC_0 0 | 24 | #define SDIO_FUNC_0 0 |
23 | #define SDIO_FUNC_1 1 | 25 | #define SDIO_FUNC_1 1 |
@@ -182,6 +184,8 @@ struct brcmf_sdio_dev { | |||
182 | uint max_segment_size; | 184 | uint max_segment_size; |
183 | uint txglomsz; | 185 | uint txglomsz; |
184 | struct sg_table sgtable; | 186 | struct sg_table sgtable; |
187 | char fw_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN]; | ||
188 | char nvram_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN]; | ||
185 | }; | 189 | }; |
186 | 190 | ||
187 | /* sdio core registers */ | 191 | /* sdio core registers */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index b732a99e402c..dc135915470d 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/vmalloc.h> | 21 | #include <linux/vmalloc.h> |
22 | 22 | ||
23 | #include <brcmu_utils.h> | 23 | #include <brcmu_utils.h> |
24 | #include <brcm_hw_ids.h> | ||
24 | #include <brcmu_wifi.h> | 25 | #include <brcmu_wifi.h> |
25 | #include <dhd_bus.h> | 26 | #include <dhd_bus.h> |
26 | #include <dhd_dbg.h> | 27 | #include <dhd_dbg.h> |
@@ -913,16 +914,16 @@ static int brcmf_usb_dlrun(struct brcmf_usbdev_info *devinfo) | |||
913 | static bool brcmf_usb_chip_support(int chipid, int chiprev) | 914 | static bool brcmf_usb_chip_support(int chipid, int chiprev) |
914 | { | 915 | { |
915 | switch(chipid) { | 916 | switch(chipid) { |
916 | case 43143: | 917 | case BRCM_CC_43143_CHIP_ID: |
917 | return true; | 918 | return true; |
918 | case 43235: | 919 | case BRCM_CC_43235_CHIP_ID: |
919 | case 43236: | 920 | case BRCM_CC_43236_CHIP_ID: |
920 | case 43238: | 921 | case BRCM_CC_43238_CHIP_ID: |
921 | return (chiprev == 3); | 922 | return (chiprev == 3); |
922 | case 43242: | 923 | case BRCM_CC_43242_CHIP_ID: |
923 | return true; | 924 | return true; |
924 | case 43566: | 925 | case BRCM_CC_43566_CHIP_ID: |
925 | case 43569: | 926 | case BRCM_CC_43569_CHIP_ID: |
926 | return true; | 927 | return true; |
927 | default: | 928 | default: |
928 | break; | 929 | break; |
@@ -1016,16 +1017,16 @@ static int check_file(const u8 *headers) | |||
1016 | static const char *brcmf_usb_get_fwname(struct brcmf_usbdev_info *devinfo) | 1017 | static const char *brcmf_usb_get_fwname(struct brcmf_usbdev_info *devinfo) |
1017 | { | 1018 | { |
1018 | switch (devinfo->bus_pub.devid) { | 1019 | switch (devinfo->bus_pub.devid) { |
1019 | case 43143: | 1020 | case BRCM_CC_43143_CHIP_ID: |
1020 | return BRCMF_USB_43143_FW_NAME; | 1021 | return BRCMF_USB_43143_FW_NAME; |
1021 | case 43235: | 1022 | case BRCM_CC_43235_CHIP_ID: |
1022 | case 43236: | 1023 | case BRCM_CC_43236_CHIP_ID: |
1023 | case 43238: | 1024 | case BRCM_CC_43238_CHIP_ID: |
1024 | return BRCMF_USB_43236_FW_NAME; | 1025 | return BRCMF_USB_43236_FW_NAME; |
1025 | case 43242: | 1026 | case BRCM_CC_43242_CHIP_ID: |
1026 | return BRCMF_USB_43242_FW_NAME; | 1027 | return BRCMF_USB_43242_FW_NAME; |
1027 | case 43566: | 1028 | case BRCM_CC_43566_CHIP_ID: |
1028 | case 43569: | 1029 | case BRCM_CC_43569_CHIP_ID: |
1029 | return BRCMF_USB_43569_FW_NAME; | 1030 | return BRCMF_USB_43569_FW_NAME; |
1030 | default: | 1031 | default: |
1031 | return NULL; | 1032 | return NULL; |
@@ -1366,21 +1367,17 @@ static int brcmf_usb_reset_resume(struct usb_interface *intf) | |||
1366 | brcmf_usb_probe_phase2); | 1367 | brcmf_usb_probe_phase2); |
1367 | } | 1368 | } |
1368 | 1369 | ||
1369 | #define BRCMF_USB_VENDOR_ID_BROADCOM 0x0a5c | 1370 | #define BRCMF_USB_DEVICE(dev_id) \ |
1370 | #define BRCMF_USB_DEVICE_ID_43143 0xbd1e | 1371 | { USB_DEVICE(BRCM_USB_VENDOR_ID_BROADCOM, dev_id) } |
1371 | #define BRCMF_USB_DEVICE_ID_43236 0xbd17 | ||
1372 | #define BRCMF_USB_DEVICE_ID_43242 0xbd1f | ||
1373 | #define BRCMF_USB_DEVICE_ID_43569 0xbd27 | ||
1374 | #define BRCMF_USB_DEVICE_ID_BCMFW 0x0bdc | ||
1375 | 1372 | ||
1376 | static struct usb_device_id brcmf_usb_devid_table[] = { | 1373 | static struct usb_device_id brcmf_usb_devid_table[] = { |
1377 | { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_43143) }, | 1374 | BRCMF_USB_DEVICE(BRCM_USB_43143_DEVICE_ID), |
1378 | { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_43236) }, | 1375 | BRCMF_USB_DEVICE(BRCM_USB_43236_DEVICE_ID), |
1379 | { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_43242) }, | 1376 | BRCMF_USB_DEVICE(BRCM_USB_43242_DEVICE_ID), |
1380 | { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_43569) }, | 1377 | BRCMF_USB_DEVICE(BRCM_USB_43569_DEVICE_ID), |
1381 | /* special entry for device with firmware loaded and running */ | 1378 | /* special entry for device with firmware loaded and running */ |
1382 | { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_BCMFW) }, | 1379 | BRCMF_USB_DEVICE(BRCM_USB_BCMFW_DEVICE_ID), |
1383 | { } | 1380 | { /* end: all zeroes */ } |
1384 | }; | 1381 | }; |
1385 | 1382 | ||
1386 | MODULE_DEVICE_TABLE(usb, brcmf_usb_devid_table); | 1383 | MODULE_DEVICE_TABLE(usb, brcmf_usb_devid_table); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 9682cf213ec4..48078a321716 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include "p2p.h" | 33 | #include "p2p.h" |
34 | #include "btcoex.h" | 34 | #include "btcoex.h" |
35 | #include "wl_cfg80211.h" | 35 | #include "wl_cfg80211.h" |
36 | #include "feature.h" | ||
36 | #include "fwil.h" | 37 | #include "fwil.h" |
37 | #include "vendor.h" | 38 | #include "vendor.h" |
38 | 39 | ||
@@ -102,24 +103,6 @@ static bool check_vif_up(struct brcmf_cfg80211_vif *vif) | |||
102 | return true; | 103 | return true; |
103 | } | 104 | } |
104 | 105 | ||
105 | #define CHAN2G(_channel, _freq, _flags) { \ | ||
106 | .band = IEEE80211_BAND_2GHZ, \ | ||
107 | .center_freq = (_freq), \ | ||
108 | .hw_value = (_channel), \ | ||
109 | .flags = (_flags), \ | ||
110 | .max_antenna_gain = 0, \ | ||
111 | .max_power = 30, \ | ||
112 | } | ||
113 | |||
114 | #define CHAN5G(_channel, _flags) { \ | ||
115 | .band = IEEE80211_BAND_5GHZ, \ | ||
116 | .center_freq = 5000 + (5 * (_channel)), \ | ||
117 | .hw_value = (_channel), \ | ||
118 | .flags = (_flags), \ | ||
119 | .max_antenna_gain = 0, \ | ||
120 | .max_power = 30, \ | ||
121 | } | ||
122 | |||
123 | #define RATE_TO_BASE100KBPS(rate) (((rate) * 10) / 2) | 106 | #define RATE_TO_BASE100KBPS(rate) (((rate) * 10) / 2) |
124 | #define RATETAB_ENT(_rateid, _flags) \ | 107 | #define RATETAB_ENT(_rateid, _flags) \ |
125 | { \ | 108 | { \ |
@@ -148,58 +131,17 @@ static struct ieee80211_rate __wl_rates[] = { | |||
148 | #define wl_g_rates (__wl_rates + 0) | 131 | #define wl_g_rates (__wl_rates + 0) |
149 | #define wl_g_rates_size 12 | 132 | #define wl_g_rates_size 12 |
150 | 133 | ||
151 | static struct ieee80211_channel __wl_2ghz_channels[] = { | 134 | /* Band templates duplicated per wiphy. The channel info |
152 | CHAN2G(1, 2412, 0), | 135 | * is filled in after querying the device. |
153 | CHAN2G(2, 2417, 0), | 136 | */ |
154 | CHAN2G(3, 2422, 0), | 137 | static const struct ieee80211_supported_band __wl_band_2ghz = { |
155 | CHAN2G(4, 2427, 0), | ||
156 | CHAN2G(5, 2432, 0), | ||
157 | CHAN2G(6, 2437, 0), | ||
158 | CHAN2G(7, 2442, 0), | ||
159 | CHAN2G(8, 2447, 0), | ||
160 | CHAN2G(9, 2452, 0), | ||
161 | CHAN2G(10, 2457, 0), | ||
162 | CHAN2G(11, 2462, 0), | ||
163 | CHAN2G(12, 2467, 0), | ||
164 | CHAN2G(13, 2472, 0), | ||
165 | CHAN2G(14, 2484, 0), | ||
166 | }; | ||
167 | |||
168 | static struct ieee80211_channel __wl_5ghz_a_channels[] = { | ||
169 | CHAN5G(34, 0), CHAN5G(36, 0), | ||
170 | CHAN5G(38, 0), CHAN5G(40, 0), | ||
171 | CHAN5G(42, 0), CHAN5G(44, 0), | ||
172 | CHAN5G(46, 0), CHAN5G(48, 0), | ||
173 | CHAN5G(52, 0), CHAN5G(56, 0), | ||
174 | CHAN5G(60, 0), CHAN5G(64, 0), | ||
175 | CHAN5G(100, 0), CHAN5G(104, 0), | ||
176 | CHAN5G(108, 0), CHAN5G(112, 0), | ||
177 | CHAN5G(116, 0), CHAN5G(120, 0), | ||
178 | CHAN5G(124, 0), CHAN5G(128, 0), | ||
179 | CHAN5G(132, 0), CHAN5G(136, 0), | ||
180 | CHAN5G(140, 0), CHAN5G(149, 0), | ||
181 | CHAN5G(153, 0), CHAN5G(157, 0), | ||
182 | CHAN5G(161, 0), CHAN5G(165, 0), | ||
183 | CHAN5G(184, 0), CHAN5G(188, 0), | ||
184 | CHAN5G(192, 0), CHAN5G(196, 0), | ||
185 | CHAN5G(200, 0), CHAN5G(204, 0), | ||
186 | CHAN5G(208, 0), CHAN5G(212, 0), | ||
187 | CHAN5G(216, 0), | ||
188 | }; | ||
189 | |||
190 | static struct ieee80211_supported_band __wl_band_2ghz = { | ||
191 | .band = IEEE80211_BAND_2GHZ, | 138 | .band = IEEE80211_BAND_2GHZ, |
192 | .channels = __wl_2ghz_channels, | ||
193 | .n_channels = ARRAY_SIZE(__wl_2ghz_channels), | ||
194 | .bitrates = wl_g_rates, | 139 | .bitrates = wl_g_rates, |
195 | .n_bitrates = wl_g_rates_size, | 140 | .n_bitrates = wl_g_rates_size, |
196 | .ht_cap = {IEEE80211_HT_CAP_SUP_WIDTH_20_40, true}, | ||
197 | }; | 141 | }; |
198 | 142 | ||
199 | static struct ieee80211_supported_band __wl_band_5ghz_a = { | 143 | static const struct ieee80211_supported_band __wl_band_5ghz_a = { |
200 | .band = IEEE80211_BAND_5GHZ, | 144 | .band = IEEE80211_BAND_5GHZ, |
201 | .channels = __wl_5ghz_a_channels, | ||
202 | .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels), | ||
203 | .bitrates = wl_a_rates, | 145 | .bitrates = wl_a_rates, |
204 | .n_bitrates = wl_a_rates_size, | 146 | .n_bitrates = wl_a_rates_size, |
205 | }; | 147 | }; |
@@ -592,7 +534,7 @@ static struct wireless_dev *brcmf_cfg80211_add_iface(struct wiphy *wiphy, | |||
592 | 534 | ||
593 | static void brcmf_scan_config_mpc(struct brcmf_if *ifp, int mpc) | 535 | static void brcmf_scan_config_mpc(struct brcmf_if *ifp, int mpc) |
594 | { | 536 | { |
595 | if ((brcmf_get_chip_info(ifp) >> 4) == 0x4329) | 537 | if (brcmf_feat_is_quirk_enabled(ifp, BRCMF_FEAT_QUIRK_NEED_MPC)) |
596 | brcmf_set_mpc(ifp, mpc); | 538 | brcmf_set_mpc(ifp, mpc); |
597 | } | 539 | } |
598 | 540 | ||
@@ -1619,17 +1561,10 @@ static | |||
1619 | enum nl80211_auth_type brcmf_war_auth_type(struct brcmf_if *ifp, | 1561 | enum nl80211_auth_type brcmf_war_auth_type(struct brcmf_if *ifp, |
1620 | enum nl80211_auth_type type) | 1562 | enum nl80211_auth_type type) |
1621 | { | 1563 | { |
1622 | u32 ci; | 1564 | if (type == NL80211_AUTHTYPE_AUTOMATIC && |
1623 | if (type == NL80211_AUTHTYPE_AUTOMATIC) { | 1565 | brcmf_feat_is_quirk_enabled(ifp, BRCMF_FEAT_QUIRK_AUTO_AUTH)) { |
1624 | /* shift to ignore chip revision */ | 1566 | brcmf_dbg(CONN, "WAR: use OPEN instead of AUTO\n"); |
1625 | ci = brcmf_get_chip_info(ifp) >> 4; | 1567 | type = NL80211_AUTHTYPE_OPEN_SYSTEM; |
1626 | switch (ci) { | ||
1627 | case 43236: | ||
1628 | brcmf_dbg(CONN, "43236 WAR: use OPEN instead of AUTO\n"); | ||
1629 | return NL80211_AUTHTYPE_OPEN_SYSTEM; | ||
1630 | default: | ||
1631 | break; | ||
1632 | } | ||
1633 | } | 1568 | } |
1634 | return type; | 1569 | return type; |
1635 | } | 1570 | } |
@@ -4284,122 +4219,6 @@ static struct cfg80211_ops wl_cfg80211_ops = { | |||
4284 | .tdls_oper = brcmf_cfg80211_tdls_oper, | 4219 | .tdls_oper = brcmf_cfg80211_tdls_oper, |
4285 | }; | 4220 | }; |
4286 | 4221 | ||
4287 | static void brcmf_wiphy_pno_params(struct wiphy *wiphy) | ||
4288 | { | ||
4289 | /* scheduled scan settings */ | ||
4290 | wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT; | ||
4291 | wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT; | ||
4292 | wiphy->max_sched_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX; | ||
4293 | wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; | ||
4294 | } | ||
4295 | |||
4296 | static const struct ieee80211_iface_limit brcmf_iface_limits[] = { | ||
4297 | { | ||
4298 | .max = 2, | ||
4299 | .types = BIT(NL80211_IFTYPE_STATION) | | ||
4300 | BIT(NL80211_IFTYPE_ADHOC) | | ||
4301 | BIT(NL80211_IFTYPE_AP) | ||
4302 | }, | ||
4303 | { | ||
4304 | .max = 1, | ||
4305 | .types = BIT(NL80211_IFTYPE_P2P_CLIENT) | | ||
4306 | BIT(NL80211_IFTYPE_P2P_GO) | ||
4307 | }, | ||
4308 | { | ||
4309 | .max = 1, | ||
4310 | .types = BIT(NL80211_IFTYPE_P2P_DEVICE) | ||
4311 | } | ||
4312 | }; | ||
4313 | static const struct ieee80211_iface_combination brcmf_iface_combos[] = { | ||
4314 | { | ||
4315 | .max_interfaces = BRCMF_IFACE_MAX_CNT, | ||
4316 | .num_different_channels = 2, | ||
4317 | .n_limits = ARRAY_SIZE(brcmf_iface_limits), | ||
4318 | .limits = brcmf_iface_limits | ||
4319 | } | ||
4320 | }; | ||
4321 | |||
4322 | static const struct ieee80211_txrx_stypes | ||
4323 | brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = { | ||
4324 | [NL80211_IFTYPE_STATION] = { | ||
4325 | .tx = 0xffff, | ||
4326 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
4327 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | ||
4328 | }, | ||
4329 | [NL80211_IFTYPE_P2P_CLIENT] = { | ||
4330 | .tx = 0xffff, | ||
4331 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
4332 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | ||
4333 | }, | ||
4334 | [NL80211_IFTYPE_P2P_GO] = { | ||
4335 | .tx = 0xffff, | ||
4336 | .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | | ||
4337 | BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | | ||
4338 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | | ||
4339 | BIT(IEEE80211_STYPE_DISASSOC >> 4) | | ||
4340 | BIT(IEEE80211_STYPE_AUTH >> 4) | | ||
4341 | BIT(IEEE80211_STYPE_DEAUTH >> 4) | | ||
4342 | BIT(IEEE80211_STYPE_ACTION >> 4) | ||
4343 | }, | ||
4344 | [NL80211_IFTYPE_P2P_DEVICE] = { | ||
4345 | .tx = 0xffff, | ||
4346 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
4347 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | ||
4348 | } | ||
4349 | }; | ||
4350 | |||
4351 | static struct wiphy *brcmf_setup_wiphy(struct device *phydev) | ||
4352 | { | ||
4353 | struct wiphy *wiphy; | ||
4354 | s32 err = 0; | ||
4355 | |||
4356 | wiphy = wiphy_new(&wl_cfg80211_ops, sizeof(struct brcmf_cfg80211_info)); | ||
4357 | if (!wiphy) { | ||
4358 | brcmf_err("Could not allocate wiphy device\n"); | ||
4359 | return ERR_PTR(-ENOMEM); | ||
4360 | } | ||
4361 | set_wiphy_dev(wiphy, phydev); | ||
4362 | wiphy->max_scan_ssids = WL_NUM_SCAN_MAX; | ||
4363 | wiphy->max_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX; | ||
4364 | wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX; | ||
4365 | wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | ||
4366 | BIT(NL80211_IFTYPE_ADHOC) | | ||
4367 | BIT(NL80211_IFTYPE_AP) | | ||
4368 | BIT(NL80211_IFTYPE_P2P_CLIENT) | | ||
4369 | BIT(NL80211_IFTYPE_P2P_GO) | | ||
4370 | BIT(NL80211_IFTYPE_P2P_DEVICE); | ||
4371 | wiphy->iface_combinations = brcmf_iface_combos; | ||
4372 | wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos); | ||
4373 | wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; | ||
4374 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | ||
4375 | wiphy->cipher_suites = __wl_cipher_suites; | ||
4376 | wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites); | ||
4377 | wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT | | ||
4378 | WIPHY_FLAG_OFFCHAN_TX | | ||
4379 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | | ||
4380 | WIPHY_FLAG_SUPPORTS_TDLS; | ||
4381 | if (!brcmf_roamoff) | ||
4382 | wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM; | ||
4383 | wiphy->mgmt_stypes = brcmf_txrx_stypes; | ||
4384 | wiphy->max_remain_on_channel_duration = 5000; | ||
4385 | brcmf_wiphy_pno_params(wiphy); | ||
4386 | brcmf_dbg(INFO, "Registering custom regulatory\n"); | ||
4387 | wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; | ||
4388 | wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom); | ||
4389 | |||
4390 | /* vendor commands/events support */ | ||
4391 | wiphy->vendor_commands = brcmf_vendor_cmds; | ||
4392 | wiphy->n_vendor_commands = BRCMF_VNDR_CMDS_LAST - 1; | ||
4393 | |||
4394 | err = wiphy_register(wiphy); | ||
4395 | if (err < 0) { | ||
4396 | brcmf_err("Could not register wiphy device (%d)\n", err); | ||
4397 | wiphy_free(wiphy); | ||
4398 | return ERR_PTR(err); | ||
4399 | } | ||
4400 | return wiphy; | ||
4401 | } | ||
4402 | |||
4403 | struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg, | 4222 | struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg, |
4404 | enum nl80211_iftype type, | 4223 | enum nl80211_iftype type, |
4405 | bool pm_block) | 4224 | bool pm_block) |
@@ -4943,138 +4762,6 @@ static void init_vif_event(struct brcmf_cfg80211_vif_event *event) | |||
4943 | mutex_init(&event->vif_event_lock); | 4762 | mutex_init(&event->vif_event_lock); |
4944 | } | 4763 | } |
4945 | 4764 | ||
4946 | static int brcmf_enable_bw40_2g(struct brcmf_if *ifp) | ||
4947 | { | ||
4948 | struct brcmf_fil_bwcap_le band_bwcap; | ||
4949 | u32 val; | ||
4950 | int err; | ||
4951 | |||
4952 | /* verify support for bw_cap command */ | ||
4953 | val = WLC_BAND_5G; | ||
4954 | err = brcmf_fil_iovar_int_get(ifp, "bw_cap", &val); | ||
4955 | |||
4956 | if (!err) { | ||
4957 | /* only set 2G bandwidth using bw_cap command */ | ||
4958 | band_bwcap.band = cpu_to_le32(WLC_BAND_2G); | ||
4959 | band_bwcap.bw_cap = cpu_to_le32(WLC_BW_CAP_40MHZ); | ||
4960 | err = brcmf_fil_iovar_data_set(ifp, "bw_cap", &band_bwcap, | ||
4961 | sizeof(band_bwcap)); | ||
4962 | } else { | ||
4963 | brcmf_dbg(INFO, "fallback to mimo_bw_cap\n"); | ||
4964 | val = WLC_N_BW_40ALL; | ||
4965 | err = brcmf_fil_iovar_int_set(ifp, "mimo_bw_cap", val); | ||
4966 | } | ||
4967 | return err; | ||
4968 | } | ||
4969 | |||
4970 | struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, | ||
4971 | struct device *busdev) | ||
4972 | { | ||
4973 | struct net_device *ndev = drvr->iflist[0]->ndev; | ||
4974 | struct brcmf_cfg80211_info *cfg; | ||
4975 | struct wiphy *wiphy; | ||
4976 | struct brcmf_cfg80211_vif *vif; | ||
4977 | struct brcmf_if *ifp; | ||
4978 | s32 err = 0; | ||
4979 | s32 io_type; | ||
4980 | |||
4981 | if (!ndev) { | ||
4982 | brcmf_err("ndev is invalid\n"); | ||
4983 | return NULL; | ||
4984 | } | ||
4985 | |||
4986 | ifp = netdev_priv(ndev); | ||
4987 | wiphy = brcmf_setup_wiphy(busdev); | ||
4988 | if (IS_ERR(wiphy)) | ||
4989 | return NULL; | ||
4990 | |||
4991 | cfg = wiphy_priv(wiphy); | ||
4992 | cfg->wiphy = wiphy; | ||
4993 | cfg->pub = drvr; | ||
4994 | init_vif_event(&cfg->vif_event); | ||
4995 | INIT_LIST_HEAD(&cfg->vif_list); | ||
4996 | |||
4997 | vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_STATION, false); | ||
4998 | if (IS_ERR(vif)) { | ||
4999 | wiphy_free(wiphy); | ||
5000 | return NULL; | ||
5001 | } | ||
5002 | |||
5003 | vif->ifp = ifp; | ||
5004 | vif->wdev.netdev = ndev; | ||
5005 | ndev->ieee80211_ptr = &vif->wdev; | ||
5006 | SET_NETDEV_DEV(ndev, wiphy_dev(cfg->wiphy)); | ||
5007 | |||
5008 | err = wl_init_priv(cfg); | ||
5009 | if (err) { | ||
5010 | brcmf_err("Failed to init iwm_priv (%d)\n", err); | ||
5011 | goto cfg80211_attach_out; | ||
5012 | } | ||
5013 | ifp->vif = vif; | ||
5014 | |||
5015 | err = brcmf_p2p_attach(cfg); | ||
5016 | if (err) { | ||
5017 | brcmf_err("P2P initilisation failed (%d)\n", err); | ||
5018 | goto cfg80211_p2p_attach_out; | ||
5019 | } | ||
5020 | err = brcmf_btcoex_attach(cfg); | ||
5021 | if (err) { | ||
5022 | brcmf_err("BT-coex initialisation failed (%d)\n", err); | ||
5023 | brcmf_p2p_detach(&cfg->p2p); | ||
5024 | goto cfg80211_p2p_attach_out; | ||
5025 | } | ||
5026 | |||
5027 | /* If cfg80211 didn't disable 40MHz HT CAP in wiphy_register(), | ||
5028 | * setup 40MHz in 2GHz band and enable OBSS scanning. | ||
5029 | */ | ||
5030 | if (wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap.cap & | ||
5031 | IEEE80211_HT_CAP_SUP_WIDTH_20_40) { | ||
5032 | err = brcmf_enable_bw40_2g(ifp); | ||
5033 | if (!err) | ||
5034 | err = brcmf_fil_iovar_int_set(ifp, "obss_coex", | ||
5035 | BRCMF_OBSS_COEX_AUTO); | ||
5036 | } | ||
5037 | /* clear for now and rely on update later */ | ||
5038 | wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap.ht_supported = false; | ||
5039 | wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap.cap = 0; | ||
5040 | |||
5041 | err = brcmf_fil_iovar_int_set(ifp, "tdls_enable", 1); | ||
5042 | if (err) { | ||
5043 | brcmf_dbg(INFO, "TDLS not enabled (%d)\n", err); | ||
5044 | wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_TDLS; | ||
5045 | } | ||
5046 | |||
5047 | err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_VERSION, | ||
5048 | &io_type); | ||
5049 | if (err) { | ||
5050 | brcmf_err("Failed to get D11 version (%d)\n", err); | ||
5051 | goto cfg80211_p2p_attach_out; | ||
5052 | } | ||
5053 | cfg->d11inf.io_type = (u8)io_type; | ||
5054 | brcmu_d11_attach(&cfg->d11inf); | ||
5055 | |||
5056 | return cfg; | ||
5057 | |||
5058 | cfg80211_p2p_attach_out: | ||
5059 | wl_deinit_priv(cfg); | ||
5060 | |||
5061 | cfg80211_attach_out: | ||
5062 | brcmf_free_vif(vif); | ||
5063 | return NULL; | ||
5064 | } | ||
5065 | |||
5066 | void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg) | ||
5067 | { | ||
5068 | if (!cfg) | ||
5069 | return; | ||
5070 | |||
5071 | WARN_ON(!list_empty(&cfg->vif_list)); | ||
5072 | wiphy_unregister(cfg->wiphy); | ||
5073 | brcmf_btcoex_detach(cfg); | ||
5074 | wl_deinit_priv(cfg); | ||
5075 | wiphy_free(cfg->wiphy); | ||
5076 | } | ||
5077 | |||
5078 | static s32 | 4765 | static s32 |
5079 | brcmf_dongle_roam(struct brcmf_if *ifp, u32 bcn_timeout) | 4766 | brcmf_dongle_roam(struct brcmf_if *ifp, u32 bcn_timeout) |
5080 | { | 4767 | { |
@@ -5167,25 +4854,77 @@ dongle_scantime_out: | |||
5167 | return err; | 4854 | return err; |
5168 | } | 4855 | } |
5169 | 4856 | ||
4857 | /* Filter the list of channels received from firmware counting only | ||
4858 | * the 20MHz channels. The wiphy band data only needs those which get | ||
4859 | * flagged to indicate if they can take part in higher bandwidth. | ||
4860 | */ | ||
4861 | static void brcmf_count_20mhz_channels(struct brcmf_cfg80211_info *cfg, | ||
4862 | struct brcmf_chanspec_list *chlist, | ||
4863 | u32 chcnt[]) | ||
4864 | { | ||
4865 | u32 total = le32_to_cpu(chlist->count); | ||
4866 | struct brcmu_chan ch; | ||
4867 | int i; | ||
4868 | |||
4869 | for (i = 0; i <= total; i++) { | ||
4870 | ch.chspec = (u16)le32_to_cpu(chlist->element[i]); | ||
4871 | cfg->d11inf.decchspec(&ch); | ||
4872 | |||
4873 | /* Firmware gives a ordered list. We skip non-20MHz | ||
4874 | * channels is 2G. For 5G we can abort upon reaching | ||
4875 | * a non-20MHz channel in the list. | ||
4876 | */ | ||
4877 | if (ch.bw != BRCMU_CHAN_BW_20) { | ||
4878 | if (ch.band == BRCMU_CHAN_BAND_5G) | ||
4879 | break; | ||
4880 | else | ||
4881 | continue; | ||
4882 | } | ||
4883 | |||
4884 | if (ch.band == BRCMU_CHAN_BAND_2G) | ||
4885 | chcnt[0] += 1; | ||
4886 | else if (ch.band == BRCMU_CHAN_BAND_5G) | ||
4887 | chcnt[1] += 1; | ||
4888 | } | ||
4889 | } | ||
4890 | |||
4891 | static void brcmf_update_bw40_channel_flag(struct ieee80211_channel *channel, | ||
4892 | struct brcmu_chan *ch) | ||
4893 | { | ||
4894 | u32 ht40_flag; | ||
5170 | 4895 | ||
5171 | static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, | 4896 | ht40_flag = channel->flags & IEEE80211_CHAN_NO_HT40; |
5172 | u32 bw_cap[]) | 4897 | if (ch->sb == BRCMU_CHAN_SB_U) { |
4898 | if (ht40_flag == IEEE80211_CHAN_NO_HT40) | ||
4899 | channel->flags &= ~IEEE80211_CHAN_NO_HT40; | ||
4900 | channel->flags |= IEEE80211_CHAN_NO_HT40PLUS; | ||
4901 | } else { | ||
4902 | /* It should be one of | ||
4903 | * IEEE80211_CHAN_NO_HT40 or | ||
4904 | * IEEE80211_CHAN_NO_HT40PLUS | ||
4905 | */ | ||
4906 | channel->flags &= ~IEEE80211_CHAN_NO_HT40; | ||
4907 | if (ht40_flag == IEEE80211_CHAN_NO_HT40) | ||
4908 | channel->flags |= IEEE80211_CHAN_NO_HT40MINUS; | ||
4909 | } | ||
4910 | } | ||
4911 | |||
4912 | static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg, | ||
4913 | u32 bw_cap[]) | ||
5173 | { | 4914 | { |
5174 | struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); | 4915 | struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); |
5175 | struct ieee80211_channel *band_chan_arr; | 4916 | struct ieee80211_supported_band *band; |
4917 | struct ieee80211_channel *channel; | ||
4918 | struct wiphy *wiphy; | ||
5176 | struct brcmf_chanspec_list *list; | 4919 | struct brcmf_chanspec_list *list; |
5177 | struct brcmu_chan ch; | 4920 | struct brcmu_chan ch; |
5178 | s32 err; | 4921 | int err; |
5179 | u8 *pbuf; | 4922 | u8 *pbuf; |
5180 | u32 i, j; | 4923 | u32 i, j; |
5181 | u32 total; | 4924 | u32 total; |
5182 | enum ieee80211_band band; | 4925 | u32 chaninfo; |
5183 | u32 channel; | 4926 | u32 chcnt[2] = { 0, 0 }; |
5184 | u32 *n_cnt; | ||
5185 | u32 index; | 4927 | u32 index; |
5186 | u32 ht40_flag; | ||
5187 | bool update; | ||
5188 | u32 array_size; | ||
5189 | 4928 | ||
5190 | pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL); | 4929 | pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL); |
5191 | 4930 | ||
@@ -5198,11 +4937,45 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, | |||
5198 | BRCMF_DCMD_MEDLEN); | 4937 | BRCMF_DCMD_MEDLEN); |
5199 | if (err) { | 4938 | if (err) { |
5200 | brcmf_err("get chanspecs error (%d)\n", err); | 4939 | brcmf_err("get chanspecs error (%d)\n", err); |
5201 | goto exit; | 4940 | goto fail_pbuf; |
5202 | } | 4941 | } |
5203 | 4942 | ||
5204 | __wl_band_2ghz.n_channels = 0; | 4943 | brcmf_count_20mhz_channels(cfg, list, chcnt); |
5205 | __wl_band_5ghz_a.n_channels = 0; | 4944 | wiphy = cfg_to_wiphy(cfg); |
4945 | if (chcnt[0]) { | ||
4946 | band = kmemdup(&__wl_band_2ghz, sizeof(__wl_band_2ghz), | ||
4947 | GFP_KERNEL); | ||
4948 | if (band == NULL) { | ||
4949 | err = -ENOMEM; | ||
4950 | goto fail_pbuf; | ||
4951 | } | ||
4952 | band->channels = kcalloc(chcnt[0], sizeof(*channel), | ||
4953 | GFP_KERNEL); | ||
4954 | if (band->channels == NULL) { | ||
4955 | kfree(band); | ||
4956 | err = -ENOMEM; | ||
4957 | goto fail_pbuf; | ||
4958 | } | ||
4959 | band->n_channels = 0; | ||
4960 | wiphy->bands[IEEE80211_BAND_2GHZ] = band; | ||
4961 | } | ||
4962 | if (chcnt[1]) { | ||
4963 | band = kmemdup(&__wl_band_5ghz_a, sizeof(__wl_band_5ghz_a), | ||
4964 | GFP_KERNEL); | ||
4965 | if (band == NULL) { | ||
4966 | err = -ENOMEM; | ||
4967 | goto fail_band2g; | ||
4968 | } | ||
4969 | band->channels = kcalloc(chcnt[1], sizeof(*channel), | ||
4970 | GFP_KERNEL); | ||
4971 | if (band->channels == NULL) { | ||
4972 | kfree(band); | ||
4973 | err = -ENOMEM; | ||
4974 | goto fail_band2g; | ||
4975 | } | ||
4976 | band->n_channels = 0; | ||
4977 | wiphy->bands[IEEE80211_BAND_5GHZ] = band; | ||
4978 | } | ||
5206 | 4979 | ||
5207 | total = le32_to_cpu(list->count); | 4980 | total = le32_to_cpu(list->count); |
5208 | for (i = 0; i < total; i++) { | 4981 | for (i = 0; i < total; i++) { |
@@ -5210,100 +4983,151 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, | |||
5210 | cfg->d11inf.decchspec(&ch); | 4983 | cfg->d11inf.decchspec(&ch); |
5211 | 4984 | ||
5212 | if (ch.band == BRCMU_CHAN_BAND_2G) { | 4985 | if (ch.band == BRCMU_CHAN_BAND_2G) { |
5213 | band_chan_arr = __wl_2ghz_channels; | 4986 | band = wiphy->bands[IEEE80211_BAND_2GHZ]; |
5214 | array_size = ARRAY_SIZE(__wl_2ghz_channels); | ||
5215 | n_cnt = &__wl_band_2ghz.n_channels; | ||
5216 | band = IEEE80211_BAND_2GHZ; | ||
5217 | } else if (ch.band == BRCMU_CHAN_BAND_5G) { | 4987 | } else if (ch.band == BRCMU_CHAN_BAND_5G) { |
5218 | band_chan_arr = __wl_5ghz_a_channels; | 4988 | band = wiphy->bands[IEEE80211_BAND_5GHZ]; |
5219 | array_size = ARRAY_SIZE(__wl_5ghz_a_channels); | ||
5220 | n_cnt = &__wl_band_5ghz_a.n_channels; | ||
5221 | band = IEEE80211_BAND_5GHZ; | ||
5222 | } else { | 4989 | } else { |
5223 | brcmf_err("Invalid channel Spec. 0x%x.\n", ch.chspec); | 4990 | brcmf_err("Invalid channel Spec. 0x%x.\n", ch.chspec); |
5224 | continue; | 4991 | continue; |
5225 | } | 4992 | } |
5226 | if (!(bw_cap[band] & WLC_BW_40MHZ_BIT) && | 4993 | if (!(bw_cap[band->band] & WLC_BW_40MHZ_BIT) && |
5227 | ch.bw == BRCMU_CHAN_BW_40) | 4994 | ch.bw == BRCMU_CHAN_BW_40) |
5228 | continue; | 4995 | continue; |
5229 | if (!(bw_cap[band] & WLC_BW_80MHZ_BIT) && | 4996 | if (!(bw_cap[band->band] & WLC_BW_80MHZ_BIT) && |
5230 | ch.bw == BRCMU_CHAN_BW_80) | 4997 | ch.bw == BRCMU_CHAN_BW_80) |
5231 | continue; | 4998 | continue; |
5232 | update = false; | 4999 | |
5233 | for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) { | 5000 | channel = band->channels; |
5234 | if (band_chan_arr[j].hw_value == ch.chnum) { | 5001 | index = band->n_channels; |
5235 | update = true; | 5002 | for (j = 0; j < band->n_channels; j++) { |
5003 | if (channel[j].hw_value == ch.chnum) { | ||
5004 | index = j; | ||
5236 | break; | 5005 | break; |
5237 | } | 5006 | } |
5238 | } | 5007 | } |
5239 | if (update) | 5008 | channel[index].center_freq = |
5240 | index = j; | 5009 | ieee80211_channel_to_frequency(ch.chnum, band->band); |
5241 | else | 5010 | channel[index].hw_value = ch.chnum; |
5242 | index = *n_cnt; | 5011 | |
5243 | if (index < array_size) { | 5012 | /* assuming the chanspecs order is HT20, |
5244 | band_chan_arr[index].center_freq = | 5013 | * HT40 upper, HT40 lower, and VHT80. |
5245 | ieee80211_channel_to_frequency(ch.chnum, band); | 5014 | */ |
5246 | band_chan_arr[index].hw_value = ch.chnum; | 5015 | if (ch.bw == BRCMU_CHAN_BW_80) { |
5247 | 5016 | channel[index].flags &= ~IEEE80211_CHAN_NO_80MHZ; | |
5248 | /* assuming the chanspecs order is HT20, | 5017 | } else if (ch.bw == BRCMU_CHAN_BW_40) { |
5249 | * HT40 upper, HT40 lower, and VHT80. | 5018 | brcmf_update_bw40_channel_flag(&channel[index], &ch); |
5019 | } else { | ||
5020 | /* disable other bandwidths for now as mentioned | ||
5021 | * order assure they are enabled for subsequent | ||
5022 | * chanspecs. | ||
5250 | */ | 5023 | */ |
5251 | if (ch.bw == BRCMU_CHAN_BW_80) { | 5024 | channel[index].flags = IEEE80211_CHAN_NO_HT40 | |
5252 | band_chan_arr[index].flags &= | 5025 | IEEE80211_CHAN_NO_80MHZ; |
5253 | ~IEEE80211_CHAN_NO_80MHZ; | 5026 | ch.bw = BRCMU_CHAN_BW_20; |
5254 | } else if (ch.bw == BRCMU_CHAN_BW_40) { | 5027 | cfg->d11inf.encchspec(&ch); |
5255 | ht40_flag = band_chan_arr[index].flags & | 5028 | chaninfo = ch.chspec; |
5256 | IEEE80211_CHAN_NO_HT40; | 5029 | err = brcmf_fil_bsscfg_int_get(ifp, "per_chan_info", |
5257 | if (ch.sb == BRCMU_CHAN_SB_U) { | 5030 | &chaninfo); |
5258 | if (ht40_flag == IEEE80211_CHAN_NO_HT40) | 5031 | if (!err) { |
5259 | band_chan_arr[index].flags &= | 5032 | if (chaninfo & WL_CHAN_RADAR) |
5260 | ~IEEE80211_CHAN_NO_HT40; | 5033 | channel[index].flags |= |
5261 | band_chan_arr[index].flags |= | 5034 | (IEEE80211_CHAN_RADAR | |
5262 | IEEE80211_CHAN_NO_HT40PLUS; | 5035 | IEEE80211_CHAN_NO_IR); |
5263 | } else { | 5036 | if (chaninfo & WL_CHAN_PASSIVE) |
5264 | /* It should be one of | 5037 | channel[index].flags |= |
5265 | * IEEE80211_CHAN_NO_HT40 or | 5038 | IEEE80211_CHAN_NO_IR; |
5266 | * IEEE80211_CHAN_NO_HT40PLUS | ||
5267 | */ | ||
5268 | band_chan_arr[index].flags &= | ||
5269 | ~IEEE80211_CHAN_NO_HT40; | ||
5270 | if (ht40_flag == IEEE80211_CHAN_NO_HT40) | ||
5271 | band_chan_arr[index].flags |= | ||
5272 | IEEE80211_CHAN_NO_HT40MINUS; | ||
5273 | } | ||
5274 | } else { | ||
5275 | /* disable other bandwidths for now as mentioned | ||
5276 | * order assure they are enabled for subsequent | ||
5277 | * chanspecs. | ||
5278 | */ | ||
5279 | band_chan_arr[index].flags = | ||
5280 | IEEE80211_CHAN_NO_HT40 | | ||
5281 | IEEE80211_CHAN_NO_80MHZ; | ||
5282 | ch.bw = BRCMU_CHAN_BW_20; | ||
5283 | cfg->d11inf.encchspec(&ch); | ||
5284 | channel = ch.chspec; | ||
5285 | err = brcmf_fil_bsscfg_int_get(ifp, | ||
5286 | "per_chan_info", | ||
5287 | &channel); | ||
5288 | if (!err) { | ||
5289 | if (channel & WL_CHAN_RADAR) | ||
5290 | band_chan_arr[index].flags |= | ||
5291 | (IEEE80211_CHAN_RADAR | | ||
5292 | IEEE80211_CHAN_NO_IR); | ||
5293 | if (channel & WL_CHAN_PASSIVE) | ||
5294 | band_chan_arr[index].flags |= | ||
5295 | IEEE80211_CHAN_NO_IR; | ||
5296 | } | ||
5297 | } | 5039 | } |
5298 | if (!update) | ||
5299 | (*n_cnt)++; | ||
5300 | } | 5040 | } |
5041 | if (index == band->n_channels) | ||
5042 | band->n_channels++; | ||
5301 | } | 5043 | } |
5302 | exit: | 5044 | kfree(pbuf); |
5045 | return 0; | ||
5046 | |||
5047 | fail_band2g: | ||
5048 | kfree(wiphy->bands[IEEE80211_BAND_2GHZ]->channels); | ||
5049 | kfree(wiphy->bands[IEEE80211_BAND_2GHZ]); | ||
5050 | wiphy->bands[IEEE80211_BAND_2GHZ] = NULL; | ||
5051 | fail_pbuf: | ||
5303 | kfree(pbuf); | 5052 | kfree(pbuf); |
5304 | return err; | 5053 | return err; |
5305 | } | 5054 | } |
5306 | 5055 | ||
5056 | static int brcmf_enable_bw40_2g(struct brcmf_cfg80211_info *cfg) | ||
5057 | { | ||
5058 | struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); | ||
5059 | struct ieee80211_supported_band *band; | ||
5060 | struct brcmf_fil_bwcap_le band_bwcap; | ||
5061 | struct brcmf_chanspec_list *list; | ||
5062 | u8 *pbuf; | ||
5063 | u32 val; | ||
5064 | int err; | ||
5065 | struct brcmu_chan ch; | ||
5066 | u32 num_chan; | ||
5067 | int i, j; | ||
5068 | |||
5069 | /* verify support for bw_cap command */ | ||
5070 | val = WLC_BAND_5G; | ||
5071 | err = brcmf_fil_iovar_int_get(ifp, "bw_cap", &val); | ||
5072 | |||
5073 | if (!err) { | ||
5074 | /* only set 2G bandwidth using bw_cap command */ | ||
5075 | band_bwcap.band = cpu_to_le32(WLC_BAND_2G); | ||
5076 | band_bwcap.bw_cap = cpu_to_le32(WLC_BW_CAP_40MHZ); | ||
5077 | err = brcmf_fil_iovar_data_set(ifp, "bw_cap", &band_bwcap, | ||
5078 | sizeof(band_bwcap)); | ||
5079 | } else { | ||
5080 | brcmf_dbg(INFO, "fallback to mimo_bw_cap\n"); | ||
5081 | val = WLC_N_BW_40ALL; | ||
5082 | err = brcmf_fil_iovar_int_set(ifp, "mimo_bw_cap", val); | ||
5083 | } | ||
5084 | |||
5085 | if (!err) { | ||
5086 | /* update channel info in 2G band */ | ||
5087 | pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL); | ||
5088 | |||
5089 | if (pbuf == NULL) | ||
5090 | return -ENOMEM; | ||
5091 | |||
5092 | ch.band = BRCMU_CHAN_BAND_2G; | ||
5093 | ch.bw = BRCMU_CHAN_BW_40; | ||
5094 | ch.chnum = 0; | ||
5095 | cfg->d11inf.encchspec(&ch); | ||
5096 | |||
5097 | /* pass encoded chanspec in query */ | ||
5098 | *(__le16 *)pbuf = cpu_to_le16(ch.chspec); | ||
5099 | |||
5100 | err = brcmf_fil_iovar_data_get(ifp, "chanspecs", pbuf, | ||
5101 | BRCMF_DCMD_MEDLEN); | ||
5102 | if (err) { | ||
5103 | brcmf_err("get chanspecs error (%d)\n", err); | ||
5104 | kfree(pbuf); | ||
5105 | return err; | ||
5106 | } | ||
5107 | |||
5108 | band = cfg_to_wiphy(cfg)->bands[IEEE80211_BAND_2GHZ]; | ||
5109 | list = (struct brcmf_chanspec_list *)pbuf; | ||
5110 | num_chan = le32_to_cpu(list->count); | ||
5111 | for (i = 0; i < num_chan; i++) { | ||
5112 | ch.chspec = (u16)le32_to_cpu(list->element[i]); | ||
5113 | cfg->d11inf.decchspec(&ch); | ||
5114 | if (WARN_ON(ch.band != BRCMU_CHAN_BAND_2G)) | ||
5115 | continue; | ||
5116 | if (WARN_ON(ch.bw != BRCMU_CHAN_BW_40)) | ||
5117 | continue; | ||
5118 | for (j = 0; j < band->n_channels; j++) { | ||
5119 | if (band->channels[j].hw_value == ch.chnum) | ||
5120 | break; | ||
5121 | } | ||
5122 | if (WARN_ON(j == band->n_channels)) | ||
5123 | continue; | ||
5124 | |||
5125 | brcmf_update_bw40_channel_flag(&band->channels[j], &ch); | ||
5126 | } | ||
5127 | } | ||
5128 | return err; | ||
5129 | } | ||
5130 | |||
5307 | static void brcmf_get_bwcap(struct brcmf_if *ifp, u32 bw_cap[]) | 5131 | static void brcmf_get_bwcap(struct brcmf_if *ifp, u32 bw_cap[]) |
5308 | { | 5132 | { |
5309 | u32 band, mimo_bwcap; | 5133 | u32 band, mimo_bwcap; |
@@ -5394,44 +5218,19 @@ static void brcmf_update_vht_cap(struct ieee80211_supported_band *band, | |||
5394 | band->vht_cap.vht_mcs.tx_mcs_map = mcs_map; | 5218 | band->vht_cap.vht_mcs.tx_mcs_map = mcs_map; |
5395 | } | 5219 | } |
5396 | 5220 | ||
5397 | static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg) | 5221 | static int brcmf_setup_wiphybands(struct wiphy *wiphy) |
5398 | { | 5222 | { |
5223 | struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy); | ||
5399 | struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); | 5224 | struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); |
5400 | struct wiphy *wiphy; | ||
5401 | s32 phy_list; | ||
5402 | u32 band_list[3]; | ||
5403 | u32 nmode = 0; | 5225 | u32 nmode = 0; |
5404 | u32 vhtmode = 0; | 5226 | u32 vhtmode = 0; |
5405 | u32 bw_cap[2] = { 0, 0 }; | 5227 | u32 bw_cap[2] = { WLC_BW_20MHZ_BIT, WLC_BW_20MHZ_BIT }; |
5406 | u32 rxchain; | 5228 | u32 rxchain; |
5407 | u32 nchain; | 5229 | u32 nchain; |
5408 | s8 phy; | 5230 | int err; |
5409 | s32 err; | ||
5410 | u32 nband; | ||
5411 | s32 i; | 5231 | s32 i; |
5412 | struct ieee80211_supported_band *bands[2] = { NULL, NULL }; | ||
5413 | struct ieee80211_supported_band *band; | 5232 | struct ieee80211_supported_band *band; |
5414 | 5233 | ||
5415 | err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_PHYLIST, | ||
5416 | &phy_list, sizeof(phy_list)); | ||
5417 | if (err) { | ||
5418 | brcmf_err("BRCMF_C_GET_PHYLIST error (%d)\n", err); | ||
5419 | return err; | ||
5420 | } | ||
5421 | |||
5422 | phy = ((char *)&phy_list)[0]; | ||
5423 | brcmf_dbg(INFO, "BRCMF_C_GET_PHYLIST reported: %c phy\n", phy); | ||
5424 | |||
5425 | |||
5426 | err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BANDLIST, | ||
5427 | &band_list, sizeof(band_list)); | ||
5428 | if (err) { | ||
5429 | brcmf_err("BRCMF_C_GET_BANDLIST error (%d)\n", err); | ||
5430 | return err; | ||
5431 | } | ||
5432 | brcmf_dbg(INFO, "BRCMF_C_GET_BANDLIST reported: 0x%08x 0x%08x 0x%08x phy\n", | ||
5433 | band_list[0], band_list[1], band_list[2]); | ||
5434 | |||
5435 | (void)brcmf_fil_iovar_int_get(ifp, "vhtmode", &vhtmode); | 5234 | (void)brcmf_fil_iovar_int_get(ifp, "vhtmode", &vhtmode); |
5436 | err = brcmf_fil_iovar_int_get(ifp, "nmode", &nmode); | 5235 | err = brcmf_fil_iovar_int_get(ifp, "nmode", &nmode); |
5437 | if (err) { | 5236 | if (err) { |
@@ -5453,44 +5252,129 @@ static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg) | |||
5453 | } | 5252 | } |
5454 | brcmf_dbg(INFO, "nchain=%d\n", nchain); | 5253 | brcmf_dbg(INFO, "nchain=%d\n", nchain); |
5455 | 5254 | ||
5456 | err = brcmf_construct_reginfo(cfg, bw_cap); | 5255 | err = brcmf_construct_chaninfo(cfg, bw_cap); |
5457 | if (err) { | 5256 | if (err) { |
5458 | brcmf_err("brcmf_construct_reginfo failed (%d)\n", err); | 5257 | brcmf_err("brcmf_construct_chaninfo failed (%d)\n", err); |
5459 | return err; | 5258 | return err; |
5460 | } | 5259 | } |
5461 | 5260 | ||
5462 | nband = band_list[0]; | 5261 | wiphy = cfg_to_wiphy(cfg); |
5463 | 5262 | for (i = 0; i < ARRAY_SIZE(wiphy->bands); i++) { | |
5464 | for (i = 1; i <= nband && i < ARRAY_SIZE(band_list); i++) { | 5263 | band = wiphy->bands[i]; |
5465 | band = NULL; | 5264 | if (band == NULL) |
5466 | if ((band_list[i] == WLC_BAND_5G) && | ||
5467 | (__wl_band_5ghz_a.n_channels > 0)) | ||
5468 | band = &__wl_band_5ghz_a; | ||
5469 | else if ((band_list[i] == WLC_BAND_2G) && | ||
5470 | (__wl_band_2ghz.n_channels > 0)) | ||
5471 | band = &__wl_band_2ghz; | ||
5472 | else | ||
5473 | continue; | 5265 | continue; |
5474 | 5266 | ||
5475 | if (nmode) | 5267 | if (nmode) |
5476 | brcmf_update_ht_cap(band, bw_cap, nchain); | 5268 | brcmf_update_ht_cap(band, bw_cap, nchain); |
5477 | if (vhtmode) | 5269 | if (vhtmode) |
5478 | brcmf_update_vht_cap(band, bw_cap, nchain); | 5270 | brcmf_update_vht_cap(band, bw_cap, nchain); |
5479 | bands[band->band] = band; | ||
5480 | } | 5271 | } |
5481 | 5272 | ||
5482 | wiphy = cfg_to_wiphy(cfg); | 5273 | return 0; |
5483 | wiphy->bands[IEEE80211_BAND_2GHZ] = bands[IEEE80211_BAND_2GHZ]; | ||
5484 | wiphy->bands[IEEE80211_BAND_5GHZ] = bands[IEEE80211_BAND_5GHZ]; | ||
5485 | wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom); | ||
5486 | |||
5487 | return err; | ||
5488 | } | 5274 | } |
5489 | 5275 | ||
5276 | static const struct ieee80211_iface_limit brcmf_iface_limits[] = { | ||
5277 | { | ||
5278 | .max = 2, | ||
5279 | .types = BIT(NL80211_IFTYPE_STATION) | | ||
5280 | BIT(NL80211_IFTYPE_ADHOC) | | ||
5281 | BIT(NL80211_IFTYPE_AP) | ||
5282 | }, | ||
5283 | { | ||
5284 | .max = 1, | ||
5285 | .types = BIT(NL80211_IFTYPE_P2P_CLIENT) | | ||
5286 | BIT(NL80211_IFTYPE_P2P_GO) | ||
5287 | }, | ||
5288 | { | ||
5289 | .max = 1, | ||
5290 | .types = BIT(NL80211_IFTYPE_P2P_DEVICE) | ||
5291 | } | ||
5292 | }; | ||
5293 | static struct ieee80211_iface_combination brcmf_iface_combos[] = { | ||
5294 | { | ||
5295 | .max_interfaces = BRCMF_IFACE_MAX_CNT, | ||
5296 | .num_different_channels = 1, | ||
5297 | .n_limits = ARRAY_SIZE(brcmf_iface_limits), | ||
5298 | .limits = brcmf_iface_limits | ||
5299 | } | ||
5300 | }; | ||
5301 | |||
5302 | static const struct ieee80211_txrx_stypes | ||
5303 | brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = { | ||
5304 | [NL80211_IFTYPE_STATION] = { | ||
5305 | .tx = 0xffff, | ||
5306 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
5307 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | ||
5308 | }, | ||
5309 | [NL80211_IFTYPE_P2P_CLIENT] = { | ||
5310 | .tx = 0xffff, | ||
5311 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
5312 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | ||
5313 | }, | ||
5314 | [NL80211_IFTYPE_P2P_GO] = { | ||
5315 | .tx = 0xffff, | ||
5316 | .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | | ||
5317 | BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | | ||
5318 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | | ||
5319 | BIT(IEEE80211_STYPE_DISASSOC >> 4) | | ||
5320 | BIT(IEEE80211_STYPE_AUTH >> 4) | | ||
5321 | BIT(IEEE80211_STYPE_DEAUTH >> 4) | | ||
5322 | BIT(IEEE80211_STYPE_ACTION >> 4) | ||
5323 | }, | ||
5324 | [NL80211_IFTYPE_P2P_DEVICE] = { | ||
5325 | .tx = 0xffff, | ||
5326 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
5327 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | ||
5328 | } | ||
5329 | }; | ||
5490 | 5330 | ||
5491 | static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_info *cfg) | 5331 | static void brcmf_wiphy_pno_params(struct wiphy *wiphy) |
5492 | { | 5332 | { |
5493 | return brcmf_update_wiphybands(cfg); | 5333 | /* scheduled scan settings */ |
5334 | wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT; | ||
5335 | wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT; | ||
5336 | wiphy->max_sched_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX; | ||
5337 | wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; | ||
5338 | } | ||
5339 | |||
5340 | static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp) | ||
5341 | { | ||
5342 | struct ieee80211_iface_combination ifc_combo; | ||
5343 | wiphy->max_scan_ssids = WL_NUM_SCAN_MAX; | ||
5344 | wiphy->max_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX; | ||
5345 | wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX; | ||
5346 | wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | ||
5347 | BIT(NL80211_IFTYPE_ADHOC) | | ||
5348 | BIT(NL80211_IFTYPE_AP) | | ||
5349 | BIT(NL80211_IFTYPE_P2P_CLIENT) | | ||
5350 | BIT(NL80211_IFTYPE_P2P_GO) | | ||
5351 | BIT(NL80211_IFTYPE_P2P_DEVICE); | ||
5352 | /* need VSDB firmware feature for concurrent channels */ | ||
5353 | ifc_combo = brcmf_iface_combos[0]; | ||
5354 | if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN)) | ||
5355 | ifc_combo.num_different_channels = 2; | ||
5356 | wiphy->iface_combinations = kmemdup(&ifc_combo, | ||
5357 | sizeof(ifc_combo), | ||
5358 | GFP_KERNEL); | ||
5359 | wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos); | ||
5360 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | ||
5361 | wiphy->cipher_suites = __wl_cipher_suites; | ||
5362 | wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites); | ||
5363 | wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT | | ||
5364 | WIPHY_FLAG_OFFCHAN_TX | | ||
5365 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | | ||
5366 | WIPHY_FLAG_SUPPORTS_TDLS; | ||
5367 | if (!brcmf_roamoff) | ||
5368 | wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM; | ||
5369 | wiphy->mgmt_stypes = brcmf_txrx_stypes; | ||
5370 | wiphy->max_remain_on_channel_duration = 5000; | ||
5371 | brcmf_wiphy_pno_params(wiphy); | ||
5372 | |||
5373 | /* vendor commands/events support */ | ||
5374 | wiphy->vendor_commands = brcmf_vendor_cmds; | ||
5375 | wiphy->n_vendor_commands = BRCMF_VNDR_CMDS_LAST - 1; | ||
5376 | |||
5377 | return brcmf_setup_wiphybands(wiphy); | ||
5494 | } | 5378 | } |
5495 | 5379 | ||
5496 | static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) | 5380 | static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) |
@@ -5528,9 +5412,6 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) | |||
5528 | NULL, NULL); | 5412 | NULL, NULL); |
5529 | if (err) | 5413 | if (err) |
5530 | goto default_conf_out; | 5414 | goto default_conf_out; |
5531 | err = brcmf_dongle_probecap(cfg); | ||
5532 | if (err) | ||
5533 | goto default_conf_out; | ||
5534 | 5415 | ||
5535 | brcmf_configure_arp_offload(ifp, true); | 5416 | brcmf_configure_arp_offload(ifp, true); |
5536 | 5417 | ||
@@ -5658,3 +5539,150 @@ int brcmf_cfg80211_wait_vif_event_timeout(struct brcmf_cfg80211_info *cfg, | |||
5658 | vif_event_equals(event, action), timeout); | 5539 | vif_event_equals(event, action), timeout); |
5659 | } | 5540 | } |
5660 | 5541 | ||
5542 | static void brcmf_free_wiphy(struct wiphy *wiphy) | ||
5543 | { | ||
5544 | kfree(wiphy->iface_combinations); | ||
5545 | if (wiphy->bands[IEEE80211_BAND_2GHZ]) { | ||
5546 | kfree(wiphy->bands[IEEE80211_BAND_2GHZ]->channels); | ||
5547 | kfree(wiphy->bands[IEEE80211_BAND_2GHZ]); | ||
5548 | } | ||
5549 | if (wiphy->bands[IEEE80211_BAND_5GHZ]) { | ||
5550 | kfree(wiphy->bands[IEEE80211_BAND_5GHZ]->channels); | ||
5551 | kfree(wiphy->bands[IEEE80211_BAND_5GHZ]); | ||
5552 | } | ||
5553 | wiphy_free(wiphy); | ||
5554 | } | ||
5555 | |||
5556 | struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, | ||
5557 | struct device *busdev) | ||
5558 | { | ||
5559 | struct net_device *ndev = drvr->iflist[0]->ndev; | ||
5560 | struct brcmf_cfg80211_info *cfg; | ||
5561 | struct wiphy *wiphy; | ||
5562 | struct brcmf_cfg80211_vif *vif; | ||
5563 | struct brcmf_if *ifp; | ||
5564 | s32 err = 0; | ||
5565 | s32 io_type; | ||
5566 | u16 *cap = NULL; | ||
5567 | |||
5568 | if (!ndev) { | ||
5569 | brcmf_err("ndev is invalid\n"); | ||
5570 | return NULL; | ||
5571 | } | ||
5572 | |||
5573 | ifp = netdev_priv(ndev); | ||
5574 | wiphy = wiphy_new(&wl_cfg80211_ops, sizeof(struct brcmf_cfg80211_info)); | ||
5575 | if (!wiphy) { | ||
5576 | brcmf_err("Could not allocate wiphy device\n"); | ||
5577 | return NULL; | ||
5578 | } | ||
5579 | set_wiphy_dev(wiphy, busdev); | ||
5580 | |||
5581 | cfg = wiphy_priv(wiphy); | ||
5582 | cfg->wiphy = wiphy; | ||
5583 | cfg->pub = drvr; | ||
5584 | init_vif_event(&cfg->vif_event); | ||
5585 | INIT_LIST_HEAD(&cfg->vif_list); | ||
5586 | |||
5587 | vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_STATION, false); | ||
5588 | if (IS_ERR(vif)) | ||
5589 | goto wiphy_out; | ||
5590 | |||
5591 | vif->ifp = ifp; | ||
5592 | vif->wdev.netdev = ndev; | ||
5593 | ndev->ieee80211_ptr = &vif->wdev; | ||
5594 | SET_NETDEV_DEV(ndev, wiphy_dev(cfg->wiphy)); | ||
5595 | |||
5596 | err = wl_init_priv(cfg); | ||
5597 | if (err) { | ||
5598 | brcmf_err("Failed to init iwm_priv (%d)\n", err); | ||
5599 | brcmf_free_vif(vif); | ||
5600 | goto wiphy_out; | ||
5601 | } | ||
5602 | ifp->vif = vif; | ||
5603 | |||
5604 | /* determine d11 io type before wiphy setup */ | ||
5605 | err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_VERSION, &io_type); | ||
5606 | if (err) { | ||
5607 | brcmf_err("Failed to get D11 version (%d)\n", err); | ||
5608 | goto priv_out; | ||
5609 | } | ||
5610 | cfg->d11inf.io_type = (u8)io_type; | ||
5611 | brcmu_d11_attach(&cfg->d11inf); | ||
5612 | |||
5613 | err = brcmf_setup_wiphy(wiphy, ifp); | ||
5614 | if (err < 0) | ||
5615 | goto priv_out; | ||
5616 | |||
5617 | brcmf_dbg(INFO, "Registering custom regulatory\n"); | ||
5618 | wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; | ||
5619 | wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom); | ||
5620 | |||
5621 | /* firmware defaults to 40MHz disabled in 2G band. We signal | ||
5622 | * cfg80211 here that we do and have it decide we can enable | ||
5623 | * it. But first check if device does support 2G operation. | ||
5624 | */ | ||
5625 | if (wiphy->bands[IEEE80211_BAND_2GHZ]) { | ||
5626 | cap = &wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap.cap; | ||
5627 | *cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
5628 | } | ||
5629 | err = wiphy_register(wiphy); | ||
5630 | if (err < 0) { | ||
5631 | brcmf_err("Could not register wiphy device (%d)\n", err); | ||
5632 | goto priv_out; | ||
5633 | } | ||
5634 | |||
5635 | /* If cfg80211 didn't disable 40MHz HT CAP in wiphy_register(), | ||
5636 | * setup 40MHz in 2GHz band and enable OBSS scanning. | ||
5637 | */ | ||
5638 | if (cap && (*cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) { | ||
5639 | err = brcmf_enable_bw40_2g(cfg); | ||
5640 | if (!err) | ||
5641 | err = brcmf_fil_iovar_int_set(ifp, "obss_coex", | ||
5642 | BRCMF_OBSS_COEX_AUTO); | ||
5643 | else | ||
5644 | *cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
5645 | } | ||
5646 | |||
5647 | err = brcmf_p2p_attach(cfg); | ||
5648 | if (err) { | ||
5649 | brcmf_err("P2P initilisation failed (%d)\n", err); | ||
5650 | goto wiphy_unreg_out; | ||
5651 | } | ||
5652 | err = brcmf_btcoex_attach(cfg); | ||
5653 | if (err) { | ||
5654 | brcmf_err("BT-coex initialisation failed (%d)\n", err); | ||
5655 | brcmf_p2p_detach(&cfg->p2p); | ||
5656 | goto wiphy_unreg_out; | ||
5657 | } | ||
5658 | |||
5659 | err = brcmf_fil_iovar_int_set(ifp, "tdls_enable", 1); | ||
5660 | if (err) { | ||
5661 | brcmf_dbg(INFO, "TDLS not enabled (%d)\n", err); | ||
5662 | wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_TDLS; | ||
5663 | } | ||
5664 | |||
5665 | return cfg; | ||
5666 | |||
5667 | wiphy_unreg_out: | ||
5668 | wiphy_unregister(cfg->wiphy); | ||
5669 | priv_out: | ||
5670 | wl_deinit_priv(cfg); | ||
5671 | brcmf_free_vif(vif); | ||
5672 | wiphy_out: | ||
5673 | brcmf_free_wiphy(wiphy); | ||
5674 | return NULL; | ||
5675 | } | ||
5676 | |||
5677 | void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg) | ||
5678 | { | ||
5679 | if (!cfg) | ||
5680 | return; | ||
5681 | |||
5682 | WARN_ON(!list_empty(&cfg->vif_list)); | ||
5683 | wiphy_unregister(cfg->wiphy); | ||
5684 | brcmf_btcoex_detach(cfg); | ||
5685 | brcmf_p2p_detach(&cfg->p2p); | ||
5686 | wl_deinit_priv(cfg); | ||
5687 | brcmf_free_wiphy(cfg->wiphy); | ||
5688 | } | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c index af8ba64ace39..1b474828d5b8 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c | |||
@@ -4707,41 +4707,6 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core, | |||
4707 | return err; | 4707 | return err; |
4708 | } | 4708 | } |
4709 | 4709 | ||
4710 | static void brcms_c_attach_antgain_init(struct brcms_c_info *wlc) | ||
4711 | { | ||
4712 | uint unit; | ||
4713 | unit = wlc->pub->unit; | ||
4714 | |||
4715 | if ((wlc->band->antgain == -1) && (wlc->pub->sromrev == 1)) { | ||
4716 | /* default antenna gain for srom rev 1 is 2 dBm (8 qdbm) */ | ||
4717 | wlc->band->antgain = 8; | ||
4718 | } else if (wlc->band->antgain == -1) { | ||
4719 | wiphy_err(wlc->wiphy, "wl%d: %s: Invalid antennas available in" | ||
4720 | " srom, using 2dB\n", unit, __func__); | ||
4721 | wlc->band->antgain = 8; | ||
4722 | } else { | ||
4723 | s8 gain, fract; | ||
4724 | /* Older sroms specified gain in whole dbm only. In order | ||
4725 | * be able to specify qdbm granularity and remain backward | ||
4726 | * compatible the whole dbms are now encoded in only | ||
4727 | * low 6 bits and remaining qdbms are encoded in the hi 2 bits. | ||
4728 | * 6 bit signed number ranges from -32 - 31. | ||
4729 | * | ||
4730 | * Examples: | ||
4731 | * 0x1 = 1 db, | ||
4732 | * 0xc1 = 1.75 db (1 + 3 quarters), | ||
4733 | * 0x3f = -1 (-1 + 0 quarters), | ||
4734 | * 0x7f = -.75 (-1 + 1 quarters) = -3 qdbm. | ||
4735 | * 0xbf = -.50 (-1 + 2 quarters) = -2 qdbm. | ||
4736 | */ | ||
4737 | gain = wlc->band->antgain & 0x3f; | ||
4738 | gain <<= 2; /* Sign extend */ | ||
4739 | gain >>= 2; | ||
4740 | fract = (wlc->band->antgain & 0xc0) >> 6; | ||
4741 | wlc->band->antgain = 4 * gain + fract; | ||
4742 | } | ||
4743 | } | ||
4744 | |||
4745 | static bool brcms_c_attach_stf_ant_init(struct brcms_c_info *wlc) | 4710 | static bool brcms_c_attach_stf_ant_init(struct brcms_c_info *wlc) |
4746 | { | 4711 | { |
4747 | int aa; | 4712 | int aa; |
@@ -4780,8 +4745,6 @@ static bool brcms_c_attach_stf_ant_init(struct brcms_c_info *wlc) | |||
4780 | else | 4745 | else |
4781 | wlc->band->antgain = sprom->antenna_gain.a0; | 4746 | wlc->band->antgain = sprom->antenna_gain.a0; |
4782 | 4747 | ||
4783 | brcms_c_attach_antgain_init(wlc); | ||
4784 | |||
4785 | return true; | 4748 | return true; |
4786 | } | 4749 | } |
4787 | 4750 | ||
diff --git a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h index d816270db3be..64d1a7ba040c 100644 --- a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h +++ b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h | |||
@@ -17,32 +17,56 @@ | |||
17 | #ifndef _BRCM_HW_IDS_H_ | 17 | #ifndef _BRCM_HW_IDS_H_ |
18 | #define _BRCM_HW_IDS_H_ | 18 | #define _BRCM_HW_IDS_H_ |
19 | 19 | ||
20 | #define BCM4313_D11N2G_ID 0x4727 /* 4313 802.11n 2.4G device */ | 20 | #include <linux/pci_ids.h> |
21 | #include <linux/mmc/sdio_ids.h> | ||
22 | |||
23 | #define BRCM_USB_VENDOR_ID_BROADCOM 0x0a5c | ||
24 | #define BRCM_PCIE_VENDOR_ID_BROADCOM PCI_VENDOR_ID_BROADCOM | ||
25 | #define BRCM_SDIO_VENDOR_ID_BROADCOM SDIO_VENDOR_ID_BROADCOM | ||
26 | |||
27 | /* Chipcommon Core Chip IDs */ | ||
28 | #define BRCM_CC_43143_CHIP_ID 43143 | ||
29 | #define BRCM_CC_43235_CHIP_ID 43235 | ||
30 | #define BRCM_CC_43236_CHIP_ID 43236 | ||
31 | #define BRCM_CC_43238_CHIP_ID 43238 | ||
32 | #define BRCM_CC_43241_CHIP_ID 0x4324 | ||
33 | #define BRCM_CC_43242_CHIP_ID 43242 | ||
34 | #define BRCM_CC_4329_CHIP_ID 0x4329 | ||
35 | #define BRCM_CC_4330_CHIP_ID 0x4330 | ||
36 | #define BRCM_CC_4334_CHIP_ID 0x4334 | ||
37 | #define BRCM_CC_43362_CHIP_ID 43362 | ||
38 | #define BRCM_CC_4335_CHIP_ID 0x4335 | ||
39 | #define BRCM_CC_4339_CHIP_ID 0x4339 | ||
40 | #define BRCM_CC_4354_CHIP_ID 0x4354 | ||
41 | #define BRCM_CC_43566_CHIP_ID 43566 | ||
42 | #define BRCM_CC_43569_CHIP_ID 43569 | ||
43 | |||
44 | /* SDIO Device IDs */ | ||
45 | #define BRCM_SDIO_43143_DEVICE_ID BRCM_CC_43143_CHIP_ID | ||
46 | #define BRCM_SDIO_43241_DEVICE_ID BRCM_CC_43241_CHIP_ID | ||
47 | #define BRCM_SDIO_4329_DEVICE_ID BRCM_CC_4329_CHIP_ID | ||
48 | #define BRCM_SDIO_4330_DEVICE_ID BRCM_CC_4330_CHIP_ID | ||
49 | #define BRCM_SDIO_4334_DEVICE_ID BRCM_CC_4334_CHIP_ID | ||
50 | #define BRCM_SDIO_43362_DEVICE_ID BRCM_CC_43362_CHIP_ID | ||
51 | #define BRCM_SDIO_4335_4339_DEVICE_ID BRCM_CC_4335_CHIP_ID | ||
52 | #define BRCM_SDIO_4354_DEVICE_ID BRCM_CC_4354_CHIP_ID | ||
21 | 53 | ||
54 | /* USB Device IDs */ | ||
55 | #define BRCM_USB_43143_DEVICE_ID 0xbd1e | ||
56 | #define BRCM_USB_43236_DEVICE_ID 0xbd17 | ||
57 | #define BRCM_USB_43242_DEVICE_ID 0xbd1f | ||
58 | #define BRCM_USB_43569_DEVICE_ID 0xbd27 | ||
59 | #define BRCM_USB_BCMFW_DEVICE_ID 0x0bdc | ||
60 | |||
61 | /* brcmsmac IDs */ | ||
62 | #define BCM4313_D11N2G_ID 0x4727 /* 4313 802.11n 2.4G device */ | ||
22 | #define BCM43224_D11N_ID 0x4353 /* 43224 802.11n dualband device */ | 63 | #define BCM43224_D11N_ID 0x4353 /* 43224 802.11n dualband device */ |
23 | #define BCM43224_D11N_ID_VEN1 0x0576 /* Vendor specific 43224 802.11n db */ | 64 | #define BCM43224_D11N_ID_VEN1 0x0576 /* Vendor specific 43224 802.11n db */ |
24 | |||
25 | #define BCM43225_D11N2G_ID 0x4357 /* 43225 802.11n 2.4GHz device */ | 65 | #define BCM43225_D11N2G_ID 0x4357 /* 43225 802.11n 2.4GHz device */ |
26 | |||
27 | #define BCM43236_D11N_ID 0x4346 /* 43236 802.11n dualband device */ | 66 | #define BCM43236_D11N_ID 0x4346 /* 43236 802.11n dualband device */ |
28 | #define BCM43236_D11N2G_ID 0x4347 /* 43236 802.11n 2.4GHz device */ | 67 | #define BCM43236_D11N2G_ID 0x4347 /* 43236 802.11n 2.4GHz device */ |
29 | 68 | ||
30 | /* Chipcommon Core Chip IDs */ | ||
31 | #define BCM4313_CHIP_ID 0x4313 | 69 | #define BCM4313_CHIP_ID 0x4313 |
32 | #define BCM43143_CHIP_ID 43143 | ||
33 | #define BCM43224_CHIP_ID 43224 | 70 | #define BCM43224_CHIP_ID 43224 |
34 | #define BCM43225_CHIP_ID 43225 | ||
35 | #define BCM43235_CHIP_ID 43235 | ||
36 | #define BCM43236_CHIP_ID 43236 | ||
37 | #define BCM43238_CHIP_ID 43238 | ||
38 | #define BCM43241_CHIP_ID 0x4324 | ||
39 | #define BCM4329_CHIP_ID 0x4329 | ||
40 | #define BCM4330_CHIP_ID 0x4330 | ||
41 | #define BCM4331_CHIP_ID 0x4331 | ||
42 | #define BCM4334_CHIP_ID 0x4334 | ||
43 | #define BCM4335_CHIP_ID 0x4335 | ||
44 | #define BCM43362_CHIP_ID 43362 | ||
45 | #define BCM4339_CHIP_ID 0x4339 | ||
46 | #define BCM4354_CHIP_ID 0x4354 | ||
47 | 71 | ||
48 | #endif /* _BRCM_HW_IDS_H_ */ | 72 | #endif /* _BRCM_HW_IDS_H_ */ |
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 5ea65fce0b83..1326f6121835 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/11n.c b/drivers/net/wireless/mwifiex/11n.c index 9d6d8d9f01e3..62f5dbe602d3 100644 --- a/drivers/net/wireless/mwifiex/11n.c +++ b/drivers/net/wireless/mwifiex/11n.c | |||
@@ -541,7 +541,6 @@ void mwifiex_create_ba_tbl(struct mwifiex_private *priv, u8 *ra, int tid, | |||
541 | int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac) | 541 | int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac) |
542 | { | 542 | { |
543 | struct host_cmd_ds_11n_addba_req add_ba_req; | 543 | struct host_cmd_ds_11n_addba_req add_ba_req; |
544 | struct mwifiex_sta_node *sta_ptr; | ||
545 | u32 tx_win_size = priv->add_ba_param.tx_win_size; | 544 | u32 tx_win_size = priv->add_ba_param.tx_win_size; |
546 | static u8 dialog_tok; | 545 | static u8 dialog_tok; |
547 | int ret; | 546 | int ret; |
@@ -553,6 +552,8 @@ int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac) | |||
553 | ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) && | 552 | ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) && |
554 | priv->adapter->is_hw_11ac_capable && | 553 | priv->adapter->is_hw_11ac_capable && |
555 | memcmp(priv->cfg_bssid, peer_mac, ETH_ALEN)) { | 554 | memcmp(priv->cfg_bssid, peer_mac, ETH_ALEN)) { |
555 | struct mwifiex_sta_node *sta_ptr; | ||
556 | |||
556 | sta_ptr = mwifiex_get_sta_entry(priv, peer_mac); | 557 | sta_ptr = mwifiex_get_sta_entry(priv, peer_mac); |
557 | if (!sta_ptr) { | 558 | if (!sta_ptr) { |
558 | dev_warn(priv->adapter->dev, | 559 | dev_warn(priv->adapter->dev, |
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c index b22bae3d1205..06a2c215ef5e 100644 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.c +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c | |||
@@ -249,13 +249,22 @@ void mwifiex_11n_del_rx_reorder_tbl_by_ta(struct mwifiex_private *priv, u8 *ta) | |||
249 | * buffered in Rx reordering table. | 249 | * buffered in Rx reordering table. |
250 | */ | 250 | */ |
251 | static int | 251 | static int |
252 | mwifiex_11n_find_last_seq_num(struct mwifiex_rx_reorder_tbl *rx_reorder_tbl_ptr) | 252 | mwifiex_11n_find_last_seq_num(struct reorder_tmr_cnxt *ctx) |
253 | { | 253 | { |
254 | struct mwifiex_rx_reorder_tbl *rx_reorder_tbl_ptr = ctx->ptr; | ||
255 | struct mwifiex_private *priv = ctx->priv; | ||
256 | unsigned long flags; | ||
254 | int i; | 257 | int i; |
255 | 258 | ||
256 | for (i = (rx_reorder_tbl_ptr->win_size - 1); i >= 0; --i) | 259 | spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags); |
257 | if (rx_reorder_tbl_ptr->rx_reorder_ptr[i]) | 260 | for (i = rx_reorder_tbl_ptr->win_size - 1; i >= 0; --i) { |
261 | if (rx_reorder_tbl_ptr->rx_reorder_ptr[i]) { | ||
262 | spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, | ||
263 | flags); | ||
258 | return i; | 264 | return i; |
265 | } | ||
266 | } | ||
267 | spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags); | ||
259 | 268 | ||
260 | return -1; | 269 | return -1; |
261 | } | 270 | } |
@@ -274,7 +283,7 @@ mwifiex_flush_data(unsigned long context) | |||
274 | (struct reorder_tmr_cnxt *) context; | 283 | (struct reorder_tmr_cnxt *) context; |
275 | int start_win, seq_num; | 284 | int start_win, seq_num; |
276 | 285 | ||
277 | seq_num = mwifiex_11n_find_last_seq_num(ctx->ptr); | 286 | seq_num = mwifiex_11n_find_last_seq_num(ctx); |
278 | 287 | ||
279 | if (seq_num < 0) | 288 | if (seq_num < 0) |
280 | return; | 289 | return; |
@@ -729,9 +738,9 @@ void mwifiex_11n_cleanup_reorder_tbl(struct mwifiex_private *priv) | |||
729 | mwifiex_del_rx_reorder_entry(priv, del_tbl_ptr); | 738 | mwifiex_del_rx_reorder_entry(priv, del_tbl_ptr); |
730 | spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags); | 739 | spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags); |
731 | } | 740 | } |
741 | INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr); | ||
732 | spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags); | 742 | spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags); |
733 | 743 | ||
734 | INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr); | ||
735 | mwifiex_reset_11n_rx_seq_num(priv); | 744 | mwifiex_reset_11n_rx_seq_num(priv); |
736 | } | 745 | } |
737 | 746 | ||
@@ -749,10 +758,14 @@ void mwifiex_update_rxreor_flags(struct mwifiex_adapter *adapter, u8 flags) | |||
749 | priv = adapter->priv[i]; | 758 | priv = adapter->priv[i]; |
750 | if (!priv) | 759 | if (!priv) |
751 | continue; | 760 | continue; |
752 | if (list_empty(&priv->rx_reorder_tbl_ptr)) | ||
753 | continue; | ||
754 | 761 | ||
755 | spin_lock_irqsave(&priv->rx_reorder_tbl_lock, lock_flags); | 762 | spin_lock_irqsave(&priv->rx_reorder_tbl_lock, lock_flags); |
763 | if (list_empty(&priv->rx_reorder_tbl_ptr)) { | ||
764 | spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, | ||
765 | lock_flags); | ||
766 | continue; | ||
767 | } | ||
768 | |||
756 | list_for_each_entry(tbl, &priv->rx_reorder_tbl_ptr, list) | 769 | list_for_each_entry(tbl, &priv->rx_reorder_tbl_ptr, list) |
757 | tbl->flags = flags; | 770 | tbl->flags = flags; |
758 | spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, lock_flags); | 771 | spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, lock_flags); |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index ca87f923c61e..e2e6bf13c2d8 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -1604,9 +1604,6 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, | |||
1604 | return -EINVAL; | 1604 | return -EINVAL; |
1605 | } | 1605 | } |
1606 | 1606 | ||
1607 | /* disconnect before try to associate */ | ||
1608 | mwifiex_deauthenticate(priv, NULL); | ||
1609 | |||
1610 | /* As this is new association, clear locally stored | 1607 | /* As this is new association, clear locally stored |
1611 | * keys and security related flags */ | 1608 | * keys and security related flags */ |
1612 | priv->sec_info.wpa_enabled = false; | 1609 | priv->sec_info.wpa_enabled = false; |
@@ -1744,6 +1741,11 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, | |||
1744 | return -EINVAL; | 1741 | return -EINVAL; |
1745 | } | 1742 | } |
1746 | 1743 | ||
1744 | if (priv->wdev && priv->wdev->current_bss) { | ||
1745 | wiphy_warn(wiphy, "%s: already connected\n", dev->name); | ||
1746 | return -EALREADY; | ||
1747 | } | ||
1748 | |||
1747 | wiphy_dbg(wiphy, "info: Trying to associate to %s and bssid %pM\n", | 1749 | wiphy_dbg(wiphy, "info: Trying to associate to %s and bssid %pM\n", |
1748 | (char *) sme->ssid, sme->bssid); | 1750 | (char *) sme->ssid, sme->bssid); |
1749 | 1751 | ||
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index 5899eee87fb1..baf0aab63c04 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c | |||
@@ -137,7 +137,6 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv, | |||
137 | struct host_cmd_ds_command *host_cmd; | 137 | struct host_cmd_ds_command *host_cmd; |
138 | uint16_t cmd_code; | 138 | uint16_t cmd_code; |
139 | uint16_t cmd_size; | 139 | uint16_t cmd_size; |
140 | struct timeval tstamp; | ||
141 | unsigned long flags; | 140 | unsigned long flags; |
142 | __le32 tmp; | 141 | __le32 tmp; |
143 | 142 | ||
@@ -198,10 +197,8 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv, | |||
198 | */ | 197 | */ |
199 | skb_put(cmd_node->cmd_skb, cmd_size - cmd_node->cmd_skb->len); | 198 | skb_put(cmd_node->cmd_skb, cmd_size - cmd_node->cmd_skb->len); |
200 | 199 | ||
201 | do_gettimeofday(&tstamp); | 200 | dev_dbg(adapter->dev, |
202 | dev_dbg(adapter->dev, "cmd: DNLD_CMD: (%lu.%lu): %#x, act %#x, len %d," | 201 | "cmd: DNLD_CMD: %#x, act %#x, len %d, seqno %#x\n", cmd_code, |
203 | " seqno %#x\n", | ||
204 | tstamp.tv_sec, tstamp.tv_usec, cmd_code, | ||
205 | le16_to_cpu(*(__le16 *) ((u8 *) host_cmd + S_DS_GEN)), cmd_size, | 202 | le16_to_cpu(*(__le16 *) ((u8 *) host_cmd + S_DS_GEN)), cmd_size, |
206 | le16_to_cpu(host_cmd->seq_num)); | 203 | le16_to_cpu(host_cmd->seq_num)); |
207 | 204 | ||
@@ -273,7 +270,6 @@ static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter) | |||
273 | (struct mwifiex_opt_sleep_confirm *) | 270 | (struct mwifiex_opt_sleep_confirm *) |
274 | adapter->sleep_cfm->data; | 271 | adapter->sleep_cfm->data; |
275 | struct sk_buff *sleep_cfm_tmp; | 272 | struct sk_buff *sleep_cfm_tmp; |
276 | struct timeval ts; | ||
277 | __le32 tmp; | 273 | __le32 tmp; |
278 | 274 | ||
279 | priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); | 275 | priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); |
@@ -284,10 +280,9 @@ static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter) | |||
284 | (adapter->seq_num, priv->bss_num, | 280 | (adapter->seq_num, priv->bss_num, |
285 | priv->bss_type))); | 281 | priv->bss_type))); |
286 | 282 | ||
287 | do_gettimeofday(&ts); | ||
288 | dev_dbg(adapter->dev, | 283 | dev_dbg(adapter->dev, |
289 | "cmd: DNLD_CMD: (%lu.%lu): %#x, act %#x, len %d, seqno %#x\n", | 284 | "cmd: DNLD_CMD: %#x, act %#x, len %d, seqno %#x\n", |
290 | ts.tv_sec, ts.tv_usec, le16_to_cpu(sleep_cfm_buf->command), | 285 | le16_to_cpu(sleep_cfm_buf->command), |
291 | le16_to_cpu(sleep_cfm_buf->action), | 286 | le16_to_cpu(sleep_cfm_buf->action), |
292 | le16_to_cpu(sleep_cfm_buf->size), | 287 | le16_to_cpu(sleep_cfm_buf->size), |
293 | le16_to_cpu(sleep_cfm_buf->seq_num)); | 288 | le16_to_cpu(sleep_cfm_buf->seq_num)); |
@@ -442,7 +437,6 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter) | |||
442 | mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); | 437 | mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); |
443 | struct sk_buff *skb = adapter->event_skb; | 438 | struct sk_buff *skb = adapter->event_skb; |
444 | u32 eventcause = adapter->event_cause; | 439 | u32 eventcause = adapter->event_cause; |
445 | struct timeval tstamp; | ||
446 | struct mwifiex_rxinfo *rx_info; | 440 | struct mwifiex_rxinfo *rx_info; |
447 | 441 | ||
448 | /* Save the last event to debug log */ | 442 | /* Save the last event to debug log */ |
@@ -467,9 +461,7 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter) | |||
467 | rx_info->bss_type = priv->bss_type; | 461 | rx_info->bss_type = priv->bss_type; |
468 | } | 462 | } |
469 | 463 | ||
470 | do_gettimeofday(&tstamp); | 464 | dev_dbg(adapter->dev, "EVENT: cause: %#x\n", eventcause); |
471 | dev_dbg(adapter->dev, "EVENT: %lu.%lu: cause: %#x\n", | ||
472 | tstamp.tv_sec, tstamp.tv_usec, eventcause); | ||
473 | if (eventcause == EVENT_PS_SLEEP || eventcause == EVENT_PS_AWAKE) { | 465 | if (eventcause == EVENT_PS_SLEEP || eventcause == EVENT_PS_AWAKE) { |
474 | /* Handle PS_SLEEP/AWAKE events on STA */ | 466 | /* Handle PS_SLEEP/AWAKE events on STA */ |
475 | priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA); | 467 | priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA); |
@@ -781,7 +773,6 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter) | |||
781 | uint16_t orig_cmdresp_no; | 773 | uint16_t orig_cmdresp_no; |
782 | uint16_t cmdresp_no; | 774 | uint16_t cmdresp_no; |
783 | uint16_t cmdresp_result; | 775 | uint16_t cmdresp_result; |
784 | struct timeval tstamp; | ||
785 | unsigned long flags; | 776 | unsigned long flags; |
786 | 777 | ||
787 | /* Now we got response from FW, cancel the command timer */ | 778 | /* Now we got response from FW, cancel the command timer */ |
@@ -839,11 +830,10 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter) | |||
839 | adapter->dbg.last_cmd_resp_id[adapter->dbg.last_cmd_resp_index] = | 830 | adapter->dbg.last_cmd_resp_id[adapter->dbg.last_cmd_resp_index] = |
840 | orig_cmdresp_no; | 831 | orig_cmdresp_no; |
841 | 832 | ||
842 | do_gettimeofday(&tstamp); | 833 | dev_dbg(adapter->dev, |
843 | dev_dbg(adapter->dev, "cmd: CMD_RESP: (%lu.%lu): 0x%x, result %d," | 834 | "cmd: CMD_RESP: 0x%x, result %d, len %d, seqno 0x%x\n", |
844 | " len %d, seqno 0x%x\n", | 835 | orig_cmdresp_no, cmdresp_result, |
845 | tstamp.tv_sec, tstamp.tv_usec, orig_cmdresp_no, cmdresp_result, | 836 | le16_to_cpu(resp->size), le16_to_cpu(resp->seq_num)); |
846 | le16_to_cpu(resp->size), le16_to_cpu(resp->seq_num)); | ||
847 | 837 | ||
848 | if (!(orig_cmdresp_no & HostCmd_RET_BIT)) { | 838 | if (!(orig_cmdresp_no & HostCmd_RET_BIT)) { |
849 | dev_err(adapter->dev, "CMD_RESP: invalid cmd resp\n"); | 839 | dev_err(adapter->dev, "CMD_RESP: invalid cmd resp\n"); |
@@ -903,7 +893,6 @@ mwifiex_cmd_timeout_func(unsigned long function_context) | |||
903 | struct mwifiex_adapter *adapter = | 893 | struct mwifiex_adapter *adapter = |
904 | (struct mwifiex_adapter *) function_context; | 894 | (struct mwifiex_adapter *) function_context; |
905 | struct cmd_ctrl_node *cmd_node; | 895 | struct cmd_ctrl_node *cmd_node; |
906 | struct timeval tstamp; | ||
907 | 896 | ||
908 | adapter->is_cmd_timedout = 1; | 897 | adapter->is_cmd_timedout = 1; |
909 | if (!adapter->curr_cmd) { | 898 | if (!adapter->curr_cmd) { |
@@ -916,10 +905,8 @@ mwifiex_cmd_timeout_func(unsigned long function_context) | |||
916 | adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index]; | 905 | adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index]; |
917 | adapter->dbg.timeout_cmd_act = | 906 | adapter->dbg.timeout_cmd_act = |
918 | adapter->dbg.last_cmd_act[adapter->dbg.last_cmd_index]; | 907 | adapter->dbg.last_cmd_act[adapter->dbg.last_cmd_index]; |
919 | do_gettimeofday(&tstamp); | ||
920 | dev_err(adapter->dev, | 908 | dev_err(adapter->dev, |
921 | "%s: Timeout cmd id (%lu.%lu) = %#x, act = %#x\n", | 909 | "%s: Timeout cmd id = %#x, act = %#x\n", __func__, |
922 | __func__, tstamp.tv_sec, tstamp.tv_usec, | ||
923 | adapter->dbg.timeout_cmd_id, | 910 | adapter->dbg.timeout_cmd_id, |
924 | adapter->dbg.timeout_cmd_act); | 911 | adapter->dbg.timeout_cmd_act); |
925 | 912 | ||
@@ -1237,18 +1224,15 @@ mwifiex_process_sleep_confirm_resp(struct mwifiex_adapter *adapter, | |||
1237 | uint16_t result = le16_to_cpu(cmd->result); | 1224 | uint16_t result = le16_to_cpu(cmd->result); |
1238 | uint16_t command = le16_to_cpu(cmd->command); | 1225 | uint16_t command = le16_to_cpu(cmd->command); |
1239 | uint16_t seq_num = le16_to_cpu(cmd->seq_num); | 1226 | uint16_t seq_num = le16_to_cpu(cmd->seq_num); |
1240 | struct timeval ts; | ||
1241 | 1227 | ||
1242 | if (!upld_len) { | 1228 | if (!upld_len) { |
1243 | dev_err(adapter->dev, "%s: cmd size is 0\n", __func__); | 1229 | dev_err(adapter->dev, "%s: cmd size is 0\n", __func__); |
1244 | return; | 1230 | return; |
1245 | } | 1231 | } |
1246 | 1232 | ||
1247 | do_gettimeofday(&ts); | ||
1248 | dev_dbg(adapter->dev, | 1233 | dev_dbg(adapter->dev, |
1249 | "cmd: CMD_RESP: (%lu.%lu): 0x%x, result %d, len %d, seqno 0x%x\n", | 1234 | "cmd: CMD_RESP: 0x%x, result %d, len %d, seqno 0x%x\n", |
1250 | ts.tv_sec, ts.tv_usec, command, result, le16_to_cpu(cmd->size), | 1235 | command, result, le16_to_cpu(cmd->size), seq_num); |
1251 | seq_num); | ||
1252 | 1236 | ||
1253 | /* Get BSS number and corresponding priv */ | 1237 | /* Get BSS number and corresponding priv */ |
1254 | priv = mwifiex_get_priv_by_id(adapter, HostCmd_GET_BSS_NO(seq_num), | 1238 | priv = mwifiex_get_priv_by_id(adapter, HostCmd_GET_BSS_NO(seq_num), |
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 5561573452bb..49da2d53d294 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h | |||
@@ -713,7 +713,7 @@ struct mwifiex_ie_types_vendor_param_set { | |||
713 | u8 ie[MWIFIEX_MAX_VSIE_LEN]; | 713 | u8 ie[MWIFIEX_MAX_VSIE_LEN]; |
714 | }; | 714 | }; |
715 | 715 | ||
716 | #define MWIFIEX_TDLS_IDLE_TIMEOUT 60 | 716 | #define MWIFIEX_TDLS_IDLE_TIMEOUT_IN_SEC 60 |
717 | 717 | ||
718 | struct mwifiex_ie_types_tdls_idle_timeout { | 718 | struct mwifiex_ie_types_tdls_idle_timeout { |
719 | struct mwifiex_ie_types_header header; | 719 | struct mwifiex_ie_types_header header; |
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index fc135649b85f..8d6c25908b6d 100644 --- a/drivers/net/wireless/mwifiex/join.c +++ b/drivers/net/wireless/mwifiex/join.c | |||
@@ -949,7 +949,7 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv, | |||
949 | chan_tlv->chan_scan_param[0].radio_type |= | 949 | chan_tlv->chan_scan_param[0].radio_type |= |
950 | (IEEE80211_HT_PARAM_CHA_SEC_ABOVE << 4); | 950 | (IEEE80211_HT_PARAM_CHA_SEC_ABOVE << 4); |
951 | else if (adapter->sec_chan_offset == | 951 | else if (adapter->sec_chan_offset == |
952 | IEEE80211_HT_PARAM_CHA_SEC_ABOVE) | 952 | IEEE80211_HT_PARAM_CHA_SEC_BELOW) |
953 | chan_tlv->chan_scan_param[0].radio_type |= | 953 | chan_tlv->chan_scan_param[0].radio_type |= |
954 | (IEEE80211_HT_PARAM_CHA_SEC_BELOW << 4); | 954 | (IEEE80211_HT_PARAM_CHA_SEC_BELOW << 4); |
955 | } | 955 | } |
@@ -1288,8 +1288,6 @@ done: | |||
1288 | int mwifiex_associate(struct mwifiex_private *priv, | 1288 | int mwifiex_associate(struct mwifiex_private *priv, |
1289 | struct mwifiex_bssdescriptor *bss_desc) | 1289 | struct mwifiex_bssdescriptor *bss_desc) |
1290 | { | 1290 | { |
1291 | u8 current_bssid[ETH_ALEN]; | ||
1292 | |||
1293 | /* Return error if the adapter is not STA role or table entry | 1291 | /* Return error if the adapter is not STA role or table entry |
1294 | * is not marked as infra. | 1292 | * is not marked as infra. |
1295 | */ | 1293 | */ |
@@ -1304,10 +1302,6 @@ int mwifiex_associate(struct mwifiex_private *priv, | |||
1304 | else | 1302 | else |
1305 | mwifiex_set_ba_params(priv); | 1303 | mwifiex_set_ba_params(priv); |
1306 | 1304 | ||
1307 | memcpy(¤t_bssid, | ||
1308 | &priv->curr_bss_params.bss_descriptor.mac_address, | ||
1309 | sizeof(current_bssid)); | ||
1310 | |||
1311 | /* Clear any past association response stored for application | 1305 | /* Clear any past association response stored for application |
1312 | retrieval */ | 1306 | retrieval */ |
1313 | priv->assoc_rsp_size = 0; | 1307 | priv->assoc_rsp_size = 0; |
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 3e5194fb0b0f..dfa37eadc4db 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c | |||
@@ -33,6 +33,7 @@ static void scan_delay_timer_fn(unsigned long data) | |||
33 | struct mwifiex_private *priv = (struct mwifiex_private *)data; | 33 | struct mwifiex_private *priv = (struct mwifiex_private *)data; |
34 | struct mwifiex_adapter *adapter = priv->adapter; | 34 | struct mwifiex_adapter *adapter = priv->adapter; |
35 | struct cmd_ctrl_node *cmd_node, *tmp_node; | 35 | struct cmd_ctrl_node *cmd_node, *tmp_node; |
36 | spinlock_t *scan_q_lock = &adapter->scan_pending_q_lock; | ||
36 | unsigned long flags; | 37 | unsigned long flags; |
37 | 38 | ||
38 | if (adapter->surprise_removed) | 39 | if (adapter->surprise_removed) |
@@ -44,13 +45,13 @@ static void scan_delay_timer_fn(unsigned long data) | |||
44 | * Abort scan operation by cancelling all pending scan | 45 | * Abort scan operation by cancelling all pending scan |
45 | * commands | 46 | * commands |
46 | */ | 47 | */ |
47 | spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); | 48 | spin_lock_irqsave(scan_q_lock, flags); |
48 | list_for_each_entry_safe(cmd_node, tmp_node, | 49 | list_for_each_entry_safe(cmd_node, tmp_node, |
49 | &adapter->scan_pending_q, list) { | 50 | &adapter->scan_pending_q, list) { |
50 | list_del(&cmd_node->list); | 51 | list_del(&cmd_node->list); |
51 | mwifiex_insert_cmd_to_free_q(adapter, cmd_node); | 52 | mwifiex_insert_cmd_to_free_q(adapter, cmd_node); |
52 | } | 53 | } |
53 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); | 54 | spin_unlock_irqrestore(scan_q_lock, flags); |
54 | 55 | ||
55 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); | 56 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); |
56 | adapter->scan_processing = false; | 57 | adapter->scan_processing = false; |
@@ -79,12 +80,17 @@ static void scan_delay_timer_fn(unsigned long data) | |||
79 | */ | 80 | */ |
80 | adapter->scan_delay_cnt = 0; | 81 | adapter->scan_delay_cnt = 0; |
81 | adapter->empty_tx_q_cnt = 0; | 82 | adapter->empty_tx_q_cnt = 0; |
82 | spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); | 83 | spin_lock_irqsave(scan_q_lock, flags); |
84 | |||
85 | if (list_empty(&adapter->scan_pending_q)) { | ||
86 | spin_unlock_irqrestore(scan_q_lock, flags); | ||
87 | goto done; | ||
88 | } | ||
89 | |||
83 | cmd_node = list_first_entry(&adapter->scan_pending_q, | 90 | cmd_node = list_first_entry(&adapter->scan_pending_q, |
84 | struct cmd_ctrl_node, list); | 91 | struct cmd_ctrl_node, list); |
85 | list_del(&cmd_node->list); | 92 | list_del(&cmd_node->list); |
86 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, | 93 | spin_unlock_irqrestore(scan_q_lock, flags); |
87 | flags); | ||
88 | 94 | ||
89 | mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, | 95 | mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, |
90 | true); | 96 | true); |
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c index 5f7afffdd34e..c16dd2cc8198 100644 --- a/drivers/net/wireless/mwifiex/pcie.c +++ b/drivers/net/wireless/mwifiex/pcie.c | |||
@@ -2238,7 +2238,6 @@ static void mwifiex_pcie_fw_dump_work(struct mwifiex_adapter *adapter) | |||
2238 | struct pcie_service_card *card = adapter->card; | 2238 | struct pcie_service_card *card = adapter->card; |
2239 | const struct mwifiex_pcie_card_reg *creg = card->pcie.reg; | 2239 | const struct mwifiex_pcie_card_reg *creg = card->pcie.reg; |
2240 | unsigned int reg, reg_start, reg_end; | 2240 | unsigned int reg, reg_start, reg_end; |
2241 | struct timeval t; | ||
2242 | u8 *dbg_ptr, *end_ptr, dump_num, idx, i, read_reg, doneflag = 0; | 2241 | u8 *dbg_ptr, *end_ptr, dump_num, idx, i, read_reg, doneflag = 0; |
2243 | enum rdwr_status stat; | 2242 | enum rdwr_status stat; |
2244 | u32 memory_size; | 2243 | u32 memory_size; |
@@ -2257,9 +2256,7 @@ static void mwifiex_pcie_fw_dump_work(struct mwifiex_adapter *adapter) | |||
2257 | entry->mem_size = 0; | 2256 | entry->mem_size = 0; |
2258 | } | 2257 | } |
2259 | 2258 | ||
2260 | do_gettimeofday(&t); | 2259 | dev_info(adapter->dev, "== mwifiex firmware dump start ==\n"); |
2261 | dev_info(adapter->dev, "== mwifiex firmware dump start: %u.%06u ==\n", | ||
2262 | (u32)t.tv_sec, (u32)t.tv_usec); | ||
2263 | 2260 | ||
2264 | /* Read the number of the memories which will dump */ | 2261 | /* Read the number of the memories which will dump */ |
2265 | stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag); | 2262 | stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag); |
@@ -2303,9 +2300,8 @@ static void mwifiex_pcie_fw_dump_work(struct mwifiex_adapter *adapter) | |||
2303 | end_ptr = dbg_ptr + memory_size; | 2300 | end_ptr = dbg_ptr + memory_size; |
2304 | 2301 | ||
2305 | doneflag = entry->done_flag; | 2302 | doneflag = entry->done_flag; |
2306 | do_gettimeofday(&t); | 2303 | dev_info(adapter->dev, "Start %s output, please wait...\n", |
2307 | dev_info(adapter->dev, "Start %s output %u.%06u, please wait...\n", | 2304 | entry->mem_name); |
2308 | entry->mem_name, (u32)t.tv_sec, (u32)t.tv_usec); | ||
2309 | 2305 | ||
2310 | do { | 2306 | do { |
2311 | stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag); | 2307 | stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag); |
@@ -2331,9 +2327,7 @@ static void mwifiex_pcie_fw_dump_work(struct mwifiex_adapter *adapter) | |||
2331 | break; | 2327 | break; |
2332 | } while (true); | 2328 | } while (true); |
2333 | } | 2329 | } |
2334 | do_gettimeofday(&t); | 2330 | dev_info(adapter->dev, "== mwifiex firmware dump end ==\n"); |
2335 | dev_info(adapter->dev, "== mwifiex firmware dump end: %u.%06u ==\n", | ||
2336 | (u32)t.tv_sec, (u32)t.tv_usec); | ||
2337 | 2331 | ||
2338 | kobject_uevent_env(&adapter->wiphy->dev.kobj, KOBJ_CHANGE, env); | 2332 | kobject_uevent_env(&adapter->wiphy->dev.kobj, KOBJ_CHANGE, env); |
2339 | 2333 | ||
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index 1da04a086bd9..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 | ||
@@ -2012,7 +2013,6 @@ static void mwifiex_sdio_fw_dump_work(struct work_struct *work) | |||
2012 | int ret = 0; | 2013 | int ret = 0; |
2013 | unsigned int reg, reg_start, reg_end; | 2014 | unsigned int reg, reg_start, reg_end; |
2014 | u8 *dbg_ptr, *end_ptr, dump_num, idx, i, read_reg, doneflag = 0; | 2015 | u8 *dbg_ptr, *end_ptr, dump_num, idx, i, read_reg, doneflag = 0; |
2015 | struct timeval t; | ||
2016 | enum rdwr_status stat; | 2016 | enum rdwr_status stat; |
2017 | u32 memory_size; | 2017 | u32 memory_size; |
2018 | static char *env[] = { "DRIVER=mwifiex_sdio", "EVENT=fw_dump", NULL }; | 2018 | static char *env[] = { "DRIVER=mwifiex_sdio", "EVENT=fw_dump", NULL }; |
@@ -2033,9 +2033,7 @@ static void mwifiex_sdio_fw_dump_work(struct work_struct *work) | |||
2033 | mwifiex_pm_wakeup_card(adapter); | 2033 | mwifiex_pm_wakeup_card(adapter); |
2034 | sdio_claim_host(card->func); | 2034 | sdio_claim_host(card->func); |
2035 | 2035 | ||
2036 | do_gettimeofday(&t); | 2036 | dev_info(adapter->dev, "== mwifiex firmware dump start ==\n"); |
2037 | dev_info(adapter->dev, "== mwifiex firmware dump start: %u.%06u ==\n", | ||
2038 | (u32)t.tv_sec, (u32)t.tv_usec); | ||
2039 | 2037 | ||
2040 | stat = mwifiex_sdio_rdwr_firmware(adapter, doneflag); | 2038 | stat = mwifiex_sdio_rdwr_firmware(adapter, doneflag); |
2041 | if (stat == RDWR_STATUS_FAILURE) | 2039 | if (stat == RDWR_STATUS_FAILURE) |
@@ -2087,9 +2085,8 @@ static void mwifiex_sdio_fw_dump_work(struct work_struct *work) | |||
2087 | end_ptr = dbg_ptr + memory_size; | 2085 | end_ptr = dbg_ptr + memory_size; |
2088 | 2086 | ||
2089 | doneflag = entry->done_flag; | 2087 | doneflag = entry->done_flag; |
2090 | do_gettimeofday(&t); | 2088 | dev_info(adapter->dev, "Start %s output, please wait...\n", |
2091 | dev_info(adapter->dev, "Start %s output %u.%06u, please wait...\n", | 2089 | entry->mem_name); |
2092 | entry->mem_name, (u32)t.tv_sec, (u32)t.tv_usec); | ||
2093 | 2090 | ||
2094 | do { | 2091 | do { |
2095 | stat = mwifiex_sdio_rdwr_firmware(adapter, doneflag); | 2092 | stat = mwifiex_sdio_rdwr_firmware(adapter, doneflag); |
@@ -2120,9 +2117,7 @@ static void mwifiex_sdio_fw_dump_work(struct work_struct *work) | |||
2120 | break; | 2117 | break; |
2121 | } while (1); | 2118 | } while (1); |
2122 | } | 2119 | } |
2123 | do_gettimeofday(&t); | 2120 | dev_info(adapter->dev, "== mwifiex firmware dump end ==\n"); |
2124 | dev_info(adapter->dev, "== mwifiex firmware dump end: %u.%06u ==\n", | ||
2125 | (u32)t.tv_sec, (u32)t.tv_usec); | ||
2126 | 2121 | ||
2127 | kobject_uevent_env(&adapter->wiphy->dev.kobj, KOBJ_CHANGE, env); | 2122 | kobject_uevent_env(&adapter->wiphy->dev.kobj, KOBJ_CHANGE, env); |
2128 | 2123 | ||
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index 0f077aaadab6..733de92a4c61 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c | |||
@@ -1647,7 +1647,7 @@ mwifiex_cmd_tdls_oper(struct mwifiex_private *priv, | |||
1647 | timeout = (void *)(pos + config_len); | 1647 | timeout = (void *)(pos + config_len); |
1648 | timeout->header.type = cpu_to_le16(TLV_TYPE_TDLS_IDLE_TIMEOUT); | 1648 | timeout->header.type = cpu_to_le16(TLV_TYPE_TDLS_IDLE_TIMEOUT); |
1649 | timeout->header.len = cpu_to_le16(sizeof(timeout->value)); | 1649 | timeout->header.len = cpu_to_le16(sizeof(timeout->value)); |
1650 | timeout->value = cpu_to_le16(MWIFIEX_TDLS_IDLE_TIMEOUT); | 1650 | timeout->value = cpu_to_le16(MWIFIEX_TDLS_IDLE_TIMEOUT_IN_SEC); |
1651 | config_len += sizeof(struct mwifiex_ie_types_tdls_idle_timeout); | 1651 | config_len += sizeof(struct mwifiex_ie_types_tdls_idle_timeout); |
1652 | 1652 | ||
1653 | break; | 1653 | break; |
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index 822357b7b0bb..08b78baeb846 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c | |||
@@ -908,7 +908,7 @@ static int mwifiex_ret_tdls_oper(struct mwifiex_private *priv, | |||
908 | break; | 908 | break; |
909 | default: | 909 | default: |
910 | dev_err(priv->adapter->dev, | 910 | dev_err(priv->adapter->dev, |
911 | "Unknown TDLS command action respnse %d", action); | 911 | "Unknown TDLS command action response %d", action); |
912 | return -1; | 912 | return -1; |
913 | } | 913 | } |
914 | 914 | ||
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 1a03d4d8b418..caae9738100a 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c | |||
@@ -283,10 +283,6 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, | |||
283 | priv->bss_mode == NL80211_IFTYPE_P2P_CLIENT) { | 283 | priv->bss_mode == NL80211_IFTYPE_P2P_CLIENT) { |
284 | u8 config_bands; | 284 | u8 config_bands; |
285 | 285 | ||
286 | ret = mwifiex_deauthenticate(priv, NULL); | ||
287 | if (ret) | ||
288 | goto done; | ||
289 | |||
290 | if (!bss_desc) | 286 | if (!bss_desc) |
291 | return -1; | 287 | return -1; |
292 | 288 | ||
@@ -345,12 +341,6 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, | |||
345 | goto done; | 341 | goto done; |
346 | } | 342 | } |
347 | 343 | ||
348 | /* Exit Adhoc mode first */ | ||
349 | dev_dbg(adapter->dev, "info: Sending Adhoc Stop\n"); | ||
350 | ret = mwifiex_deauthenticate(priv, NULL); | ||
351 | if (ret) | ||
352 | goto done; | ||
353 | |||
354 | priv->adhoc_is_link_sensed = false; | 344 | priv->adhoc_is_link_sensed = false; |
355 | 345 | ||
356 | ret = mwifiex_check_network_compatibility(priv, bss_desc); | 346 | ret = mwifiex_check_network_compatibility(priv, bss_desc); |
diff --git a/drivers/net/wireless/mwifiex/tdls.c b/drivers/net/wireless/mwifiex/tdls.c index a414161c6064..4c5fd953893d 100644 --- a/drivers/net/wireless/mwifiex/tdls.c +++ b/drivers/net/wireless/mwifiex/tdls.c | |||
@@ -781,6 +781,7 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv, | |||
781 | struct mwifiex_sta_node *sta_ptr; | 781 | struct mwifiex_sta_node *sta_ptr; |
782 | u8 *peer, *pos, *end; | 782 | u8 *peer, *pos, *end; |
783 | u8 i, action, basic; | 783 | u8 i, action, basic; |
784 | __le16 cap = 0; | ||
784 | int ie_len = 0; | 785 | int ie_len = 0; |
785 | 786 | ||
786 | if (len < (sizeof(struct ethhdr) + 3)) | 787 | if (len < (sizeof(struct ethhdr) + 3)) |
@@ -792,18 +793,9 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv, | |||
792 | 793 | ||
793 | peer = buf + ETH_ALEN; | 794 | peer = buf + ETH_ALEN; |
794 | action = *(buf + sizeof(struct ethhdr) + 2); | 795 | action = *(buf + sizeof(struct ethhdr) + 2); |
795 | |||
796 | /* just handle TDLS setup request/response/confirm */ | ||
797 | if (action > WLAN_TDLS_SETUP_CONFIRM) | ||
798 | return; | ||
799 | |||
800 | dev_dbg(priv->adapter->dev, | 796 | dev_dbg(priv->adapter->dev, |
801 | "rx:tdls action: peer=%pM, action=%d\n", peer, action); | 797 | "rx:tdls action: peer=%pM, action=%d\n", peer, action); |
802 | 798 | ||
803 | sta_ptr = mwifiex_add_sta_entry(priv, peer); | ||
804 | if (!sta_ptr) | ||
805 | return; | ||
806 | |||
807 | switch (action) { | 799 | switch (action) { |
808 | case WLAN_TDLS_SETUP_REQUEST: | 800 | case WLAN_TDLS_SETUP_REQUEST: |
809 | if (len < (sizeof(struct ethhdr) + TDLS_REQ_FIX_LEN)) | 801 | if (len < (sizeof(struct ethhdr) + TDLS_REQ_FIX_LEN)) |
@@ -811,7 +803,7 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv, | |||
811 | 803 | ||
812 | pos = buf + sizeof(struct ethhdr) + 4; | 804 | pos = buf + sizeof(struct ethhdr) + 4; |
813 | /* payload 1+ category 1 + action 1 + dialog 1 */ | 805 | /* payload 1+ category 1 + action 1 + dialog 1 */ |
814 | sta_ptr->tdls_cap.capab = cpu_to_le16(*(u16 *)pos); | 806 | cap = cpu_to_le16(*(u16 *)pos); |
815 | ie_len = len - sizeof(struct ethhdr) - TDLS_REQ_FIX_LEN; | 807 | ie_len = len - sizeof(struct ethhdr) - TDLS_REQ_FIX_LEN; |
816 | pos += 2; | 808 | pos += 2; |
817 | break; | 809 | break; |
@@ -821,7 +813,7 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv, | |||
821 | return; | 813 | return; |
822 | /* payload 1+ category 1 + action 1 + dialog 1 + status code 2*/ | 814 | /* payload 1+ category 1 + action 1 + dialog 1 + status code 2*/ |
823 | pos = buf + sizeof(struct ethhdr) + 6; | 815 | pos = buf + sizeof(struct ethhdr) + 6; |
824 | sta_ptr->tdls_cap.capab = cpu_to_le16(*(u16 *)pos); | 816 | cap = cpu_to_le16(*(u16 *)pos); |
825 | ie_len = len - sizeof(struct ethhdr) - TDLS_RESP_FIX_LEN; | 817 | ie_len = len - sizeof(struct ethhdr) - TDLS_RESP_FIX_LEN; |
826 | pos += 2; | 818 | pos += 2; |
827 | break; | 819 | break; |
@@ -833,10 +825,16 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv, | |||
833 | ie_len = len - sizeof(struct ethhdr) - TDLS_CONFIRM_FIX_LEN; | 825 | ie_len = len - sizeof(struct ethhdr) - TDLS_CONFIRM_FIX_LEN; |
834 | break; | 826 | break; |
835 | default: | 827 | default: |
836 | dev_warn(priv->adapter->dev, "Unknown TDLS frame type.\n"); | 828 | dev_dbg(priv->adapter->dev, "Unknown TDLS frame type.\n"); |
837 | return; | 829 | return; |
838 | } | 830 | } |
839 | 831 | ||
832 | sta_ptr = mwifiex_add_sta_entry(priv, peer); | ||
833 | if (!sta_ptr) | ||
834 | return; | ||
835 | |||
836 | sta_ptr->tdls_cap.capab = cap; | ||
837 | |||
840 | for (end = pos + ie_len; pos + 1 < end; pos += 2 + pos[1]) { | 838 | for (end = pos + ie_len; pos + 1 < end; pos += 2 + pos[1]) { |
841 | if (pos + 2 + pos[1] > end) | 839 | if (pos + 2 + pos[1] > end) |
842 | break; | 840 | break; |
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 832006b5aab1..573897b8e878 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c | |||
@@ -1284,6 +1284,8 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
1284 | /* Arcadyan */ | 1284 | /* Arcadyan */ |
1285 | { USB_DEVICE(0x043e, 0x7a12) }, | 1285 | { USB_DEVICE(0x043e, 0x7a12) }, |
1286 | { USB_DEVICE(0x043e, 0x7a32) }, | 1286 | { USB_DEVICE(0x043e, 0x7a32) }, |
1287 | /* ASUS */ | ||
1288 | { USB_DEVICE(0x0b05, 0x17e8) }, | ||
1287 | /* Azurewave */ | 1289 | /* Azurewave */ |
1288 | { USB_DEVICE(0x13d3, 0x3329) }, | 1290 | { USB_DEVICE(0x13d3, 0x3329) }, |
1289 | { USB_DEVICE(0x13d3, 0x3365) }, | 1291 | { USB_DEVICE(0x13d3, 0x3365) }, |
@@ -1320,6 +1322,7 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
1320 | { USB_DEVICE(0x057c, 0x8501) }, | 1322 | { USB_DEVICE(0x057c, 0x8501) }, |
1321 | /* Buffalo */ | 1323 | /* Buffalo */ |
1322 | { USB_DEVICE(0x0411, 0x0241) }, | 1324 | { USB_DEVICE(0x0411, 0x0241) }, |
1325 | { USB_DEVICE(0x0411, 0x0253) }, | ||
1323 | /* D-Link */ | 1326 | /* D-Link */ |
1324 | { USB_DEVICE(0x2001, 0x3c1a) }, | 1327 | { USB_DEVICE(0x2001, 0x3c1a) }, |
1325 | { USB_DEVICE(0x2001, 0x3c21) }, | 1328 | { USB_DEVICE(0x2001, 0x3c21) }, |
@@ -1410,6 +1413,7 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
1410 | { USB_DEVICE(0x0df6, 0x0053) }, | 1413 | { USB_DEVICE(0x0df6, 0x0053) }, |
1411 | { USB_DEVICE(0x0df6, 0x0069) }, | 1414 | { USB_DEVICE(0x0df6, 0x0069) }, |
1412 | { USB_DEVICE(0x0df6, 0x006f) }, | 1415 | { USB_DEVICE(0x0df6, 0x006f) }, |
1416 | { USB_DEVICE(0x0df6, 0x0078) }, | ||
1413 | /* SMC */ | 1417 | /* SMC */ |
1414 | { USB_DEVICE(0x083a, 0xa512) }, | 1418 | { USB_DEVICE(0x083a, 0xa512) }, |
1415 | { USB_DEVICE(0x083a, 0xc522) }, | 1419 | { USB_DEVICE(0x083a, 0xc522) }, |
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c index d50dfac91631..0bccf123831e 100644 --- a/drivers/net/wireless/ti/wl12xx/main.c +++ b/drivers/net/wireless/ti/wl12xx/main.c | |||
@@ -1668,7 +1668,7 @@ static bool wl12xx_lnk_high_prio(struct wl1271 *wl, u8 hlid, | |||
1668 | { | 1668 | { |
1669 | u8 thold; | 1669 | u8 thold; |
1670 | 1670 | ||
1671 | if (test_bit(hlid, (unsigned long *)&wl->fw_fast_lnk_map)) | 1671 | if (test_bit(hlid, &wl->fw_fast_lnk_map)) |
1672 | thold = wl->conf.tx.fast_link_thold; | 1672 | thold = wl->conf.tx.fast_link_thold; |
1673 | else | 1673 | else |
1674 | thold = wl->conf.tx.slow_link_thold; | 1674 | thold = wl->conf.tx.slow_link_thold; |
diff --git a/drivers/net/wireless/ti/wl18xx/cmd.c b/drivers/net/wireless/ti/wl18xx/cmd.c index 7649c75cd68d..44f0b205b065 100644 --- a/drivers/net/wireless/ti/wl18xx/cmd.c +++ b/drivers/net/wireless/ti/wl18xx/cmd.c | |||
@@ -78,3 +78,92 @@ out_free: | |||
78 | out: | 78 | out: |
79 | return ret; | 79 | return ret; |
80 | } | 80 | } |
81 | |||
82 | int wl18xx_cmd_smart_config_start(struct wl1271 *wl, u32 group_bitmap) | ||
83 | { | ||
84 | struct wl18xx_cmd_smart_config_start *cmd; | ||
85 | int ret = 0; | ||
86 | |||
87 | wl1271_debug(DEBUG_CMD, "cmd smart config start group_bitmap=0x%x", | ||
88 | group_bitmap); | ||
89 | |||
90 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
91 | if (!cmd) { | ||
92 | ret = -ENOMEM; | ||
93 | goto out; | ||
94 | } | ||
95 | |||
96 | cmd->group_id_bitmask = cpu_to_le32(group_bitmap); | ||
97 | |||
98 | ret = wl1271_cmd_send(wl, CMD_SMART_CONFIG_START, cmd, sizeof(*cmd), 0); | ||
99 | if (ret < 0) { | ||
100 | wl1271_error("failed to send smart config start command"); | ||
101 | goto out_free; | ||
102 | } | ||
103 | |||
104 | out_free: | ||
105 | kfree(cmd); | ||
106 | out: | ||
107 | return ret; | ||
108 | } | ||
109 | |||
110 | int wl18xx_cmd_smart_config_stop(struct wl1271 *wl) | ||
111 | { | ||
112 | struct wl1271_cmd_header *cmd; | ||
113 | int ret = 0; | ||
114 | |||
115 | wl1271_debug(DEBUG_CMD, "cmd smart config stop"); | ||
116 | |||
117 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
118 | if (!cmd) { | ||
119 | ret = -ENOMEM; | ||
120 | goto out; | ||
121 | } | ||
122 | |||
123 | ret = wl1271_cmd_send(wl, CMD_SMART_CONFIG_STOP, cmd, sizeof(*cmd), 0); | ||
124 | if (ret < 0) { | ||
125 | wl1271_error("failed to send smart config stop command"); | ||
126 | goto out_free; | ||
127 | } | ||
128 | |||
129 | out_free: | ||
130 | kfree(cmd); | ||
131 | out: | ||
132 | return ret; | ||
133 | } | ||
134 | |||
135 | int wl18xx_cmd_smart_config_set_group_key(struct wl1271 *wl, u16 group_id, | ||
136 | u8 key_len, u8 *key) | ||
137 | { | ||
138 | struct wl18xx_cmd_smart_config_set_group_key *cmd; | ||
139 | int ret = 0; | ||
140 | |||
141 | wl1271_debug(DEBUG_CMD, "cmd smart config set group key id=0x%x", | ||
142 | group_id); | ||
143 | |||
144 | if (key_len != sizeof(cmd->key)) { | ||
145 | wl1271_error("invalid group key size: %d", key_len); | ||
146 | return -E2BIG; | ||
147 | } | ||
148 | |||
149 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
150 | if (!cmd) { | ||
151 | ret = -ENOMEM; | ||
152 | goto out; | ||
153 | } | ||
154 | |||
155 | cmd->group_id = cpu_to_le32(group_id); | ||
156 | memcpy(cmd->key, key, key_len); | ||
157 | |||
158 | ret = wl1271_cmd_send(wl, CMD_SMART_CONFIG_SET_GROUP_KEY, cmd, | ||
159 | sizeof(*cmd), 0); | ||
160 | if (ret < 0) { | ||
161 | wl1271_error("failed to send smart config set group key cmd"); | ||
162 | goto out_free; | ||
163 | } | ||
164 | |||
165 | out_free: | ||
166 | kfree(cmd); | ||
167 | out: | ||
168 | return ret; | ||
169 | } | ||
diff --git a/drivers/net/wireless/ti/wl18xx/cmd.h b/drivers/net/wireless/ti/wl18xx/cmd.h index 6687d10899ac..92499e2dfa83 100644 --- a/drivers/net/wireless/ti/wl18xx/cmd.h +++ b/drivers/net/wireless/ti/wl18xx/cmd.h | |||
@@ -45,8 +45,25 @@ struct wl18xx_cmd_channel_switch { | |||
45 | u8 padding[2]; | 45 | u8 padding[2]; |
46 | } __packed; | 46 | } __packed; |
47 | 47 | ||
48 | struct wl18xx_cmd_smart_config_start { | ||
49 | struct wl1271_cmd_header header; | ||
50 | |||
51 | __le32 group_id_bitmask; | ||
52 | } __packed; | ||
53 | |||
54 | struct wl18xx_cmd_smart_config_set_group_key { | ||
55 | struct wl1271_cmd_header header; | ||
56 | |||
57 | __le32 group_id; | ||
58 | |||
59 | u8 key[16]; | ||
60 | } __packed; | ||
61 | |||
48 | int wl18xx_cmd_channel_switch(struct wl1271 *wl, | 62 | int wl18xx_cmd_channel_switch(struct wl1271 *wl, |
49 | struct wl12xx_vif *wlvif, | 63 | struct wl12xx_vif *wlvif, |
50 | struct ieee80211_channel_switch *ch_switch); | 64 | struct ieee80211_channel_switch *ch_switch); |
51 | 65 | int wl18xx_cmd_smart_config_start(struct wl1271 *wl, u32 group_bitmap); | |
66 | int wl18xx_cmd_smart_config_stop(struct wl1271 *wl); | ||
67 | int wl18xx_cmd_smart_config_set_group_key(struct wl1271 *wl, u16 group_id, | ||
68 | u8 key_len, u8 *key); | ||
52 | #endif | 69 | #endif |
diff --git a/drivers/net/wireless/ti/wl18xx/event.c b/drivers/net/wireless/ti/wl18xx/event.c index c9199d7804c6..eb1848e08424 100644 --- a/drivers/net/wireless/ti/wl18xx/event.c +++ b/drivers/net/wireless/ti/wl18xx/event.c | |||
@@ -19,10 +19,12 @@ | |||
19 | * | 19 | * |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <net/genetlink.h> | ||
22 | #include "event.h" | 23 | #include "event.h" |
23 | #include "scan.h" | 24 | #include "scan.h" |
24 | #include "../wlcore/cmd.h" | 25 | #include "../wlcore/cmd.h" |
25 | #include "../wlcore/debug.h" | 26 | #include "../wlcore/debug.h" |
27 | #include "../wlcore/vendor_cmd.h" | ||
26 | 28 | ||
27 | int wl18xx_wait_for_event(struct wl1271 *wl, enum wlcore_wait_event event, | 29 | int wl18xx_wait_for_event(struct wl1271 *wl, enum wlcore_wait_event event, |
28 | bool *timeout) | 30 | bool *timeout) |
@@ -45,6 +47,58 @@ int wl18xx_wait_for_event(struct wl1271 *wl, enum wlcore_wait_event event, | |||
45 | return wlcore_cmd_wait_for_event_or_timeout(wl, local_event, timeout); | 47 | return wlcore_cmd_wait_for_event_or_timeout(wl, local_event, timeout); |
46 | } | 48 | } |
47 | 49 | ||
50 | static int wlcore_smart_config_sync_event(struct wl1271 *wl, u8 sync_channel, | ||
51 | u8 sync_band) | ||
52 | { | ||
53 | struct sk_buff *skb; | ||
54 | enum ieee80211_band band; | ||
55 | int freq; | ||
56 | |||
57 | if (sync_band == WLCORE_BAND_5GHZ) | ||
58 | band = IEEE80211_BAND_5GHZ; | ||
59 | else | ||
60 | band = IEEE80211_BAND_2GHZ; | ||
61 | |||
62 | freq = ieee80211_channel_to_frequency(sync_channel, band); | ||
63 | |||
64 | wl1271_debug(DEBUG_EVENT, | ||
65 | "SMART_CONFIG_SYNC_EVENT_ID, freq: %d (chan: %d band %d)", | ||
66 | freq, sync_channel, sync_band); | ||
67 | skb = cfg80211_vendor_event_alloc(wl->hw->wiphy, 20, | ||
68 | WLCORE_VENDOR_EVENT_SC_SYNC, | ||
69 | GFP_KERNEL); | ||
70 | |||
71 | if (nla_put_u32(skb, WLCORE_VENDOR_ATTR_FREQ, freq)) { | ||
72 | kfree_skb(skb); | ||
73 | return -EMSGSIZE; | ||
74 | } | ||
75 | cfg80211_vendor_event(skb, GFP_KERNEL); | ||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | static int wlcore_smart_config_decode_event(struct wl1271 *wl, | ||
80 | u8 ssid_len, u8 *ssid, | ||
81 | u8 pwd_len, u8 *pwd) | ||
82 | { | ||
83 | struct sk_buff *skb; | ||
84 | |||
85 | wl1271_debug(DEBUG_EVENT, "SMART_CONFIG_DECODE_EVENT_ID"); | ||
86 | wl1271_dump_ascii(DEBUG_EVENT, "SSID:", ssid, ssid_len); | ||
87 | |||
88 | skb = cfg80211_vendor_event_alloc(wl->hw->wiphy, | ||
89 | ssid_len + pwd_len + 20, | ||
90 | WLCORE_VENDOR_EVENT_SC_DECODE, | ||
91 | GFP_KERNEL); | ||
92 | |||
93 | if (nla_put(skb, WLCORE_VENDOR_ATTR_SSID, ssid_len, ssid) || | ||
94 | nla_put(skb, WLCORE_VENDOR_ATTR_PSK, pwd_len, pwd)) { | ||
95 | kfree_skb(skb); | ||
96 | return -EMSGSIZE; | ||
97 | } | ||
98 | cfg80211_vendor_event(skb, GFP_KERNEL); | ||
99 | return 0; | ||
100 | } | ||
101 | |||
48 | int wl18xx_process_mailbox_events(struct wl1271 *wl) | 102 | int wl18xx_process_mailbox_events(struct wl1271 *wl) |
49 | { | 103 | { |
50 | struct wl18xx_event_mailbox *mbox = wl->mbox; | 104 | struct wl18xx_event_mailbox *mbox = wl->mbox; |
@@ -107,5 +161,16 @@ int wl18xx_process_mailbox_events(struct wl1271 *wl) | |||
107 | if (vector & REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID) | 161 | if (vector & REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID) |
108 | wlcore_event_roc_complete(wl); | 162 | wlcore_event_roc_complete(wl); |
109 | 163 | ||
164 | if (vector & SMART_CONFIG_SYNC_EVENT_ID) | ||
165 | wlcore_smart_config_sync_event(wl, mbox->sc_sync_channel, | ||
166 | mbox->sc_sync_band); | ||
167 | |||
168 | if (vector & SMART_CONFIG_DECODE_EVENT_ID) | ||
169 | wlcore_smart_config_decode_event(wl, | ||
170 | mbox->sc_ssid_len, | ||
171 | mbox->sc_ssid, | ||
172 | mbox->sc_pwd_len, | ||
173 | mbox->sc_pwd); | ||
174 | |||
110 | return 0; | 175 | return 0; |
111 | } | 176 | } |
diff --git a/drivers/net/wireless/ti/wl18xx/event.h b/drivers/net/wireless/ti/wl18xx/event.h index a76e98eb8372..0680312d4943 100644 --- a/drivers/net/wireless/ti/wl18xx/event.h +++ b/drivers/net/wireless/ti/wl18xx/event.h | |||
@@ -38,6 +38,8 @@ enum { | |||
38 | REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID = BIT(18), | 38 | REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID = BIT(18), |
39 | DFS_CHANNELS_CONFIG_COMPLETE_EVENT = BIT(19), | 39 | DFS_CHANNELS_CONFIG_COMPLETE_EVENT = BIT(19), |
40 | PERIODIC_SCAN_REPORT_EVENT_ID = BIT(20), | 40 | PERIODIC_SCAN_REPORT_EVENT_ID = BIT(20), |
41 | SMART_CONFIG_SYNC_EVENT_ID = BIT(22), | ||
42 | SMART_CONFIG_DECODE_EVENT_ID = BIT(23), | ||
41 | }; | 43 | }; |
42 | 44 | ||
43 | struct wl18xx_event_mailbox { | 45 | struct wl18xx_event_mailbox { |
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c index de5b4fa5d166..7af1936719eb 100644 --- a/drivers/net/wireless/ti/wl18xx/main.c +++ b/drivers/net/wireless/ti/wl18xx/main.c | |||
@@ -992,7 +992,10 @@ static int wl18xx_boot(struct wl1271 *wl) | |||
992 | REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID | | 992 | REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID | |
993 | INACTIVE_STA_EVENT_ID | | 993 | INACTIVE_STA_EVENT_ID | |
994 | CHANNEL_SWITCH_COMPLETE_EVENT_ID | | 994 | CHANNEL_SWITCH_COMPLETE_EVENT_ID | |
995 | DFS_CHANNELS_CONFIG_COMPLETE_EVENT; | 995 | DFS_CHANNELS_CONFIG_COMPLETE_EVENT | |
996 | SMART_CONFIG_SYNC_EVENT_ID | | ||
997 | SMART_CONFIG_DECODE_EVENT_ID; | ||
998 | ; | ||
996 | 999 | ||
997 | wl->ap_event_mask = MAX_TX_FAILURE_EVENT_ID; | 1000 | wl->ap_event_mask = MAX_TX_FAILURE_EVENT_ID; |
998 | 1001 | ||
@@ -1606,15 +1609,20 @@ static bool wl18xx_lnk_high_prio(struct wl1271 *wl, u8 hlid, | |||
1606 | u8 thold; | 1609 | u8 thold; |
1607 | struct wl18xx_fw_status_priv *status_priv = | 1610 | struct wl18xx_fw_status_priv *status_priv = |
1608 | (struct wl18xx_fw_status_priv *)wl->fw_status->priv; | 1611 | (struct wl18xx_fw_status_priv *)wl->fw_status->priv; |
1609 | u32 suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap); | 1612 | unsigned long suspend_bitmap; |
1613 | |||
1614 | /* if we don't have the link map yet, assume they all low prio */ | ||
1615 | if (!status_priv) | ||
1616 | return false; | ||
1610 | 1617 | ||
1611 | /* suspended links are never high priority */ | 1618 | /* suspended links are never high priority */ |
1612 | if (test_bit(hlid, (unsigned long *)&suspend_bitmap)) | 1619 | suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap); |
1620 | if (test_bit(hlid, &suspend_bitmap)) | ||
1613 | return false; | 1621 | return false; |
1614 | 1622 | ||
1615 | /* the priority thresholds are taken from FW */ | 1623 | /* the priority thresholds are taken from FW */ |
1616 | if (test_bit(hlid, (unsigned long *)&wl->fw_fast_lnk_map) && | 1624 | if (test_bit(hlid, &wl->fw_fast_lnk_map) && |
1617 | !test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map)) | 1625 | !test_bit(hlid, &wl->ap_fw_ps_map)) |
1618 | thold = status_priv->tx_fast_link_prio_threshold; | 1626 | thold = status_priv->tx_fast_link_prio_threshold; |
1619 | else | 1627 | else |
1620 | thold = status_priv->tx_slow_link_prio_threshold; | 1628 | thold = status_priv->tx_slow_link_prio_threshold; |
@@ -1628,12 +1636,17 @@ static bool wl18xx_lnk_low_prio(struct wl1271 *wl, u8 hlid, | |||
1628 | u8 thold; | 1636 | u8 thold; |
1629 | struct wl18xx_fw_status_priv *status_priv = | 1637 | struct wl18xx_fw_status_priv *status_priv = |
1630 | (struct wl18xx_fw_status_priv *)wl->fw_status->priv; | 1638 | (struct wl18xx_fw_status_priv *)wl->fw_status->priv; |
1631 | u32 suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap); | 1639 | unsigned long suspend_bitmap; |
1640 | |||
1641 | /* if we don't have the link map yet, assume they all low prio */ | ||
1642 | if (!status_priv) | ||
1643 | return true; | ||
1632 | 1644 | ||
1633 | if (test_bit(hlid, (unsigned long *)&suspend_bitmap)) | 1645 | suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap); |
1646 | if (test_bit(hlid, &suspend_bitmap)) | ||
1634 | thold = status_priv->tx_suspend_threshold; | 1647 | thold = status_priv->tx_suspend_threshold; |
1635 | else if (test_bit(hlid, (unsigned long *)&wl->fw_fast_lnk_map) && | 1648 | else if (test_bit(hlid, &wl->fw_fast_lnk_map) && |
1636 | !test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map)) | 1649 | !test_bit(hlid, &wl->ap_fw_ps_map)) |
1637 | thold = status_priv->tx_fast_stop_threshold; | 1650 | thold = status_priv->tx_fast_stop_threshold; |
1638 | else | 1651 | else |
1639 | thold = status_priv->tx_slow_stop_threshold; | 1652 | thold = status_priv->tx_slow_stop_threshold; |
@@ -1687,6 +1700,9 @@ static struct wlcore_ops wl18xx_ops = { | |||
1687 | .convert_hwaddr = wl18xx_convert_hwaddr, | 1700 | .convert_hwaddr = wl18xx_convert_hwaddr, |
1688 | .lnk_high_prio = wl18xx_lnk_high_prio, | 1701 | .lnk_high_prio = wl18xx_lnk_high_prio, |
1689 | .lnk_low_prio = wl18xx_lnk_low_prio, | 1702 | .lnk_low_prio = wl18xx_lnk_low_prio, |
1703 | .smart_config_start = wl18xx_cmd_smart_config_start, | ||
1704 | .smart_config_stop = wl18xx_cmd_smart_config_stop, | ||
1705 | .smart_config_set_group_key = wl18xx_cmd_smart_config_set_group_key, | ||
1690 | }; | 1706 | }; |
1691 | 1707 | ||
1692 | /* HT cap appropriate for wide channels in 2Ghz */ | 1708 | /* HT cap appropriate for wide channels in 2Ghz */ |
diff --git a/drivers/net/wireless/ti/wl18xx/tx.c b/drivers/net/wireless/ti/wl18xx/tx.c index be1ebd55ac88..3406ffb53325 100644 --- a/drivers/net/wireless/ti/wl18xx/tx.c +++ b/drivers/net/wireless/ti/wl18xx/tx.c | |||
@@ -30,7 +30,7 @@ | |||
30 | 30 | ||
31 | static | 31 | static |
32 | void wl18xx_get_last_tx_rate(struct wl1271 *wl, struct ieee80211_vif *vif, | 32 | void wl18xx_get_last_tx_rate(struct wl1271 *wl, struct ieee80211_vif *vif, |
33 | struct ieee80211_tx_rate *rate) | 33 | u8 band, struct ieee80211_tx_rate *rate) |
34 | { | 34 | { |
35 | u8 fw_rate = wl->fw_status->counters.tx_last_rate; | 35 | u8 fw_rate = wl->fw_status->counters.tx_last_rate; |
36 | 36 | ||
@@ -43,6 +43,8 @@ void wl18xx_get_last_tx_rate(struct wl1271 *wl, struct ieee80211_vif *vif, | |||
43 | 43 | ||
44 | if (fw_rate <= CONF_HW_RATE_INDEX_54MBPS) { | 44 | if (fw_rate <= CONF_HW_RATE_INDEX_54MBPS) { |
45 | rate->idx = fw_rate; | 45 | rate->idx = fw_rate; |
46 | if (band == IEEE80211_BAND_5GHZ) | ||
47 | rate->idx -= CONF_HW_RATE_INDEX_6MBPS; | ||
46 | rate->flags = 0; | 48 | rate->flags = 0; |
47 | } else { | 49 | } else { |
48 | rate->flags = IEEE80211_TX_RC_MCS; | 50 | rate->flags = IEEE80211_TX_RC_MCS; |
@@ -102,7 +104,8 @@ static void wl18xx_tx_complete_packet(struct wl1271 *wl, u8 tx_stat_byte) | |||
102 | * first pass info->control.vif while it's valid, and then fill out | 104 | * first pass info->control.vif while it's valid, and then fill out |
103 | * the info->status structures | 105 | * the info->status structures |
104 | */ | 106 | */ |
105 | wl18xx_get_last_tx_rate(wl, info->control.vif, &info->status.rates[0]); | 107 | wl18xx_get_last_tx_rate(wl, info->control.vif, |
108 | info->band, &info->status.rates[0]); | ||
106 | 109 | ||
107 | info->status.rates[0].count = 1; /* no data about retries */ | 110 | info->status.rates[0].count = 1; /* no data about retries */ |
108 | info->status.ack_signal = -1; | 111 | info->status.ack_signal = -1; |
diff --git a/drivers/net/wireless/ti/wl18xx/wl18xx.h b/drivers/net/wireless/ti/wl18xx/wl18xx.h index eb7cfe817010..6a2b88030c1d 100644 --- a/drivers/net/wireless/ti/wl18xx/wl18xx.h +++ b/drivers/net/wireless/ti/wl18xx/wl18xx.h | |||
@@ -38,7 +38,7 @@ | |||
38 | #define WL18XX_NUM_TX_DESCRIPTORS 32 | 38 | #define WL18XX_NUM_TX_DESCRIPTORS 32 |
39 | #define WL18XX_NUM_RX_DESCRIPTORS 32 | 39 | #define WL18XX_NUM_RX_DESCRIPTORS 32 |
40 | 40 | ||
41 | #define WL18XX_NUM_MAC_ADDRESSES 3 | 41 | #define WL18XX_NUM_MAC_ADDRESSES 2 |
42 | 42 | ||
43 | #define WL18XX_RX_BA_MAX_SESSIONS 13 | 43 | #define WL18XX_RX_BA_MAX_SESSIONS 13 |
44 | 44 | ||
diff --git a/drivers/net/wireless/ti/wlcore/Makefile b/drivers/net/wireless/ti/wlcore/Makefile index 4f23931d7bd5..0a69c1373643 100644 --- a/drivers/net/wireless/ti/wlcore/Makefile +++ b/drivers/net/wireless/ti/wlcore/Makefile | |||
@@ -1,5 +1,5 @@ | |||
1 | wlcore-objs = main.o cmd.o io.o event.o tx.o rx.o ps.o acx.o \ | 1 | wlcore-objs = main.o cmd.o io.o event.o tx.o rx.o ps.o acx.o \ |
2 | boot.o init.o debugfs.o scan.o sysfs.o | 2 | boot.o init.o debugfs.o scan.o sysfs.o vendor_cmd.o |
3 | 3 | ||
4 | wlcore_spi-objs = spi.o | 4 | wlcore_spi-objs = spi.o |
5 | wlcore_sdio-objs = sdio.o | 5 | wlcore_sdio-objs = sdio.o |
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c index e269c0a57017..05604ee31224 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.c +++ b/drivers/net/wireless/ti/wlcore/cmd.c | |||
@@ -372,9 +372,9 @@ void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid) | |||
372 | wl1271_tx_reset_link_queues(wl, *hlid); | 372 | wl1271_tx_reset_link_queues(wl, *hlid); |
373 | wl->links[*hlid].wlvif = NULL; | 373 | wl->links[*hlid].wlvif = NULL; |
374 | 374 | ||
375 | if (wlvif->bss_type == BSS_TYPE_STA_BSS || | 375 | if (wlvif->bss_type == BSS_TYPE_AP_BSS && |
376 | (wlvif->bss_type == BSS_TYPE_AP_BSS && | 376 | *hlid == wlvif->ap.bcast_hlid) { |
377 | *hlid == wlvif->ap.bcast_hlid)) { | 377 | u32 sqn_padding = WL1271_TX_SQN_POST_RECOVERY_PADDING; |
378 | /* | 378 | /* |
379 | * save the total freed packets in the wlvif, in case this is | 379 | * save the total freed packets in the wlvif, in case this is |
380 | * recovery or suspend | 380 | * recovery or suspend |
@@ -385,9 +385,11 @@ void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid) | |||
385 | * increment the initial seq number on recovery to account for | 385 | * increment the initial seq number on recovery to account for |
386 | * transmitted packets that we haven't yet got in the FW status | 386 | * transmitted packets that we haven't yet got in the FW status |
387 | */ | 387 | */ |
388 | if (wlvif->encryption_type == KEY_GEM) | ||
389 | sqn_padding = WL1271_TX_SQN_POST_RECOVERY_PADDING_GEM; | ||
390 | |||
388 | if (test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) | 391 | if (test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) |
389 | wlvif->total_freed_pkts += | 392 | wlvif->total_freed_pkts += sqn_padding; |
390 | WL1271_TX_SQN_POST_RECOVERY_PADDING; | ||
391 | } | 393 | } |
392 | 394 | ||
393 | wl->links[*hlid].total_freed_pkts = 0; | 395 | wl->links[*hlid].total_freed_pkts = 0; |
diff --git a/drivers/net/wireless/ti/wlcore/cmd.h b/drivers/net/wireless/ti/wlcore/cmd.h index 6788d7356ca5..ca6a28b03f8f 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.h +++ b/drivers/net/wireless/ti/wlcore/cmd.h | |||
@@ -170,6 +170,9 @@ enum wl1271_commands { | |||
170 | 170 | ||
171 | /* start of 18xx specific commands */ | 171 | /* start of 18xx specific commands */ |
172 | CMD_DFS_CHANNEL_CONFIG = 60, | 172 | CMD_DFS_CHANNEL_CONFIG = 60, |
173 | CMD_SMART_CONFIG_START = 61, | ||
174 | CMD_SMART_CONFIG_STOP = 62, | ||
175 | CMD_SMART_CONFIG_SET_GROUP_KEY = 63, | ||
173 | 176 | ||
174 | MAX_COMMAND_ID = 0xFFFF, | 177 | MAX_COMMAND_ID = 0xFFFF, |
175 | }; | 178 | }; |
diff --git a/drivers/net/wireless/ti/wlcore/debugfs.c b/drivers/net/wireless/ti/wlcore/debugfs.c index 89893c717025..0be21f62fcb0 100644 --- a/drivers/net/wireless/ti/wlcore/debugfs.c +++ b/drivers/net/wireless/ti/wlcore/debugfs.c | |||
@@ -496,7 +496,7 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, | |||
496 | DRIVER_STATE_PRINT_INT(sg_enabled); | 496 | DRIVER_STATE_PRINT_INT(sg_enabled); |
497 | DRIVER_STATE_PRINT_INT(enable_11a); | 497 | DRIVER_STATE_PRINT_INT(enable_11a); |
498 | DRIVER_STATE_PRINT_INT(noise); | 498 | DRIVER_STATE_PRINT_INT(noise); |
499 | DRIVER_STATE_PRINT_HEX(ap_fw_ps_map); | 499 | DRIVER_STATE_PRINT_LHEX(ap_fw_ps_map); |
500 | DRIVER_STATE_PRINT_LHEX(ap_ps_map); | 500 | DRIVER_STATE_PRINT_LHEX(ap_ps_map); |
501 | DRIVER_STATE_PRINT_HEX(quirks); | 501 | DRIVER_STATE_PRINT_HEX(quirks); |
502 | DRIVER_STATE_PRINT_HEX(irq); | 502 | DRIVER_STATE_PRINT_HEX(irq); |
diff --git a/drivers/net/wireless/ti/wlcore/hw_ops.h b/drivers/net/wireless/ti/wlcore/hw_ops.h index 1555ff970050..aa9f82c72296 100644 --- a/drivers/net/wireless/ti/wlcore/hw_ops.h +++ b/drivers/net/wireless/ti/wlcore/hw_ops.h | |||
@@ -260,4 +260,31 @@ wlcore_hw_lnk_low_prio(struct wl1271 *wl, u8 hlid, | |||
260 | return wl->ops->lnk_low_prio(wl, hlid, lnk); | 260 | return wl->ops->lnk_low_prio(wl, hlid, lnk); |
261 | } | 261 | } |
262 | 262 | ||
263 | static inline int | ||
264 | wlcore_smart_config_start(struct wl1271 *wl, u32 group_bitmap) | ||
265 | { | ||
266 | if (!wl->ops->smart_config_start) | ||
267 | return -EINVAL; | ||
268 | |||
269 | return wl->ops->smart_config_start(wl, group_bitmap); | ||
270 | } | ||
271 | |||
272 | static inline int | ||
273 | wlcore_smart_config_stop(struct wl1271 *wl) | ||
274 | { | ||
275 | if (!wl->ops->smart_config_stop) | ||
276 | return -EINVAL; | ||
277 | |||
278 | return wl->ops->smart_config_stop(wl); | ||
279 | } | ||
280 | |||
281 | static inline int | ||
282 | wlcore_smart_config_set_group_key(struct wl1271 *wl, u16 group_id, | ||
283 | u8 key_len, u8 *key) | ||
284 | { | ||
285 | if (!wl->ops->smart_config_set_group_key) | ||
286 | return -EINVAL; | ||
287 | |||
288 | return wl->ops->smart_config_set_group_key(wl, group_id, key_len, key); | ||
289 | } | ||
263 | #endif | 290 | #endif |
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 48f83868f9cb..575c8f6d4009 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include "init.h" | 37 | #include "init.h" |
38 | #include "debugfs.h" | 38 | #include "debugfs.h" |
39 | #include "testmode.h" | 39 | #include "testmode.h" |
40 | #include "vendor_cmd.h" | ||
40 | #include "scan.h" | 41 | #include "scan.h" |
41 | #include "hw_ops.h" | 42 | #include "hw_ops.h" |
42 | #include "sysfs.h" | 43 | #include "sysfs.h" |
@@ -332,7 +333,7 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, | |||
332 | { | 333 | { |
333 | bool fw_ps; | 334 | bool fw_ps; |
334 | 335 | ||
335 | fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); | 336 | fw_ps = test_bit(hlid, &wl->ap_fw_ps_map); |
336 | 337 | ||
337 | /* | 338 | /* |
338 | * Wake up from high level PS if the STA is asleep with too little | 339 | * Wake up from high level PS if the STA is asleep with too little |
@@ -359,13 +360,13 @@ static void wl12xx_irq_update_links_status(struct wl1271 *wl, | |||
359 | struct wl12xx_vif *wlvif, | 360 | struct wl12xx_vif *wlvif, |
360 | struct wl_fw_status *status) | 361 | struct wl_fw_status *status) |
361 | { | 362 | { |
362 | u32 cur_fw_ps_map; | 363 | unsigned long cur_fw_ps_map; |
363 | u8 hlid; | 364 | u8 hlid; |
364 | 365 | ||
365 | cur_fw_ps_map = status->link_ps_bitmap; | 366 | cur_fw_ps_map = status->link_ps_bitmap; |
366 | if (wl->ap_fw_ps_map != cur_fw_ps_map) { | 367 | if (wl->ap_fw_ps_map != cur_fw_ps_map) { |
367 | wl1271_debug(DEBUG_PSM, | 368 | wl1271_debug(DEBUG_PSM, |
368 | "link ps prev 0x%x cur 0x%x changed 0x%x", | 369 | "link ps prev 0x%lx cur 0x%lx changed 0x%lx", |
369 | wl->ap_fw_ps_map, cur_fw_ps_map, | 370 | wl->ap_fw_ps_map, cur_fw_ps_map, |
370 | wl->ap_fw_ps_map ^ cur_fw_ps_map); | 371 | wl->ap_fw_ps_map ^ cur_fw_ps_map); |
371 | 372 | ||
@@ -898,6 +899,44 @@ out: | |||
898 | wlcore_set_partition(wl, &old_part); | 899 | wlcore_set_partition(wl, &old_part); |
899 | } | 900 | } |
900 | 901 | ||
902 | static void wlcore_save_freed_pkts(struct wl1271 *wl, struct wl12xx_vif *wlvif, | ||
903 | u8 hlid, struct ieee80211_sta *sta) | ||
904 | { | ||
905 | struct wl1271_station *wl_sta; | ||
906 | u32 sqn_recovery_padding = WL1271_TX_SQN_POST_RECOVERY_PADDING; | ||
907 | |||
908 | wl_sta = (void *)sta->drv_priv; | ||
909 | wl_sta->total_freed_pkts = wl->links[hlid].total_freed_pkts; | ||
910 | |||
911 | /* | ||
912 | * increment the initial seq number on recovery to account for | ||
913 | * transmitted packets that we haven't yet got in the FW status | ||
914 | */ | ||
915 | if (wlvif->encryption_type == KEY_GEM) | ||
916 | sqn_recovery_padding = WL1271_TX_SQN_POST_RECOVERY_PADDING_GEM; | ||
917 | |||
918 | if (test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) | ||
919 | wl_sta->total_freed_pkts += sqn_recovery_padding; | ||
920 | } | ||
921 | |||
922 | static void wlcore_save_freed_pkts_addr(struct wl1271 *wl, | ||
923 | struct wl12xx_vif *wlvif, | ||
924 | u8 hlid, const u8 *addr) | ||
925 | { | ||
926 | struct ieee80211_sta *sta; | ||
927 | struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); | ||
928 | |||
929 | if (WARN_ON(hlid == WL12XX_INVALID_LINK_ID || | ||
930 | is_zero_ether_addr(addr))) | ||
931 | return; | ||
932 | |||
933 | rcu_read_lock(); | ||
934 | sta = ieee80211_find_sta(vif, addr); | ||
935 | if (sta) | ||
936 | wlcore_save_freed_pkts(wl, wlvif, hlid, sta); | ||
937 | rcu_read_unlock(); | ||
938 | } | ||
939 | |||
901 | static void wlcore_print_recovery(struct wl1271 *wl) | 940 | static void wlcore_print_recovery(struct wl1271 *wl) |
902 | { | 941 | { |
903 | u32 pc = 0; | 942 | u32 pc = 0; |
@@ -961,6 +1000,13 @@ static void wl1271_recovery_work(struct work_struct *work) | |||
961 | wlvif = list_first_entry(&wl->wlvif_list, | 1000 | wlvif = list_first_entry(&wl->wlvif_list, |
962 | struct wl12xx_vif, list); | 1001 | struct wl12xx_vif, list); |
963 | vif = wl12xx_wlvif_to_vif(wlvif); | 1002 | vif = wl12xx_wlvif_to_vif(wlvif); |
1003 | |||
1004 | if (wlvif->bss_type == BSS_TYPE_STA_BSS && | ||
1005 | test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) { | ||
1006 | wlcore_save_freed_pkts_addr(wl, wlvif, wlvif->sta.hlid, | ||
1007 | vif->bss_conf.bssid); | ||
1008 | } | ||
1009 | |||
964 | __wl1271_op_remove_interface(wl, vif, false); | 1010 | __wl1271_op_remove_interface(wl, vif, false); |
965 | } | 1011 | } |
966 | 1012 | ||
@@ -4703,36 +4749,18 @@ static int wl1271_allocate_sta(struct wl1271 *wl, | |||
4703 | 4749 | ||
4704 | void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid) | 4750 | void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid) |
4705 | { | 4751 | { |
4706 | struct wl1271_station *wl_sta; | ||
4707 | struct ieee80211_sta *sta; | ||
4708 | struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); | ||
4709 | |||
4710 | if (!test_bit(hlid, wlvif->ap.sta_hlid_map)) | 4752 | if (!test_bit(hlid, wlvif->ap.sta_hlid_map)) |
4711 | return; | 4753 | return; |
4712 | 4754 | ||
4713 | clear_bit(hlid, wlvif->ap.sta_hlid_map); | 4755 | clear_bit(hlid, wlvif->ap.sta_hlid_map); |
4714 | __clear_bit(hlid, &wl->ap_ps_map); | 4756 | __clear_bit(hlid, &wl->ap_ps_map); |
4715 | __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); | 4757 | __clear_bit(hlid, &wl->ap_fw_ps_map); |
4716 | 4758 | ||
4717 | /* | 4759 | /* |
4718 | * save the last used PN in the private part of iee80211_sta, | 4760 | * save the last used PN in the private part of iee80211_sta, |
4719 | * in case of recovery/suspend | 4761 | * in case of recovery/suspend |
4720 | */ | 4762 | */ |
4721 | rcu_read_lock(); | 4763 | wlcore_save_freed_pkts_addr(wl, wlvif, hlid, wl->links[hlid].addr); |
4722 | sta = ieee80211_find_sta(vif, wl->links[hlid].addr); | ||
4723 | if (sta) { | ||
4724 | wl_sta = (void *)sta->drv_priv; | ||
4725 | wl_sta->total_freed_pkts = wl->links[hlid].total_freed_pkts; | ||
4726 | |||
4727 | /* | ||
4728 | * increment the initial seq number on recovery to account for | ||
4729 | * transmitted packets that we haven't yet got in the FW status | ||
4730 | */ | ||
4731 | if (test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) | ||
4732 | wl_sta->total_freed_pkts += | ||
4733 | WL1271_TX_SQN_POST_RECOVERY_PADDING; | ||
4734 | } | ||
4735 | rcu_read_unlock(); | ||
4736 | 4764 | ||
4737 | wl12xx_free_link(wl, wlvif, &hlid); | 4765 | wl12xx_free_link(wl, wlvif, &hlid); |
4738 | wl->active_sta_count--; | 4766 | wl->active_sta_count--; |
@@ -4915,6 +4943,21 @@ static int wl12xx_update_sta_state(struct wl1271 *wl, | |||
4915 | clear_bit(WLVIF_FLAG_STA_STATE_SENT, &wlvif->flags); | 4943 | clear_bit(WLVIF_FLAG_STA_STATE_SENT, &wlvif->flags); |
4916 | } | 4944 | } |
4917 | 4945 | ||
4946 | /* save seq number on disassoc (suspend) */ | ||
4947 | if (is_sta && | ||
4948 | old_state == IEEE80211_STA_ASSOC && | ||
4949 | new_state == IEEE80211_STA_AUTH) { | ||
4950 | wlcore_save_freed_pkts(wl, wlvif, wlvif->sta.hlid, sta); | ||
4951 | wlvif->total_freed_pkts = 0; | ||
4952 | } | ||
4953 | |||
4954 | /* restore seq number on assoc (resume) */ | ||
4955 | if (is_sta && | ||
4956 | old_state == IEEE80211_STA_AUTH && | ||
4957 | new_state == IEEE80211_STA_ASSOC) { | ||
4958 | wlvif->total_freed_pkts = wl_sta->total_freed_pkts; | ||
4959 | } | ||
4960 | |||
4918 | /* clear ROCs on failure or authorization */ | 4961 | /* clear ROCs on failure or authorization */ |
4919 | if (is_sta && | 4962 | if (is_sta && |
4920 | (new_state == IEEE80211_STA_AUTHORIZED || | 4963 | (new_state == IEEE80211_STA_AUTHORIZED || |
@@ -5149,6 +5192,10 @@ static void wl12xx_op_channel_switch(struct ieee80211_hw *hw, | |||
5149 | if (unlikely(wl->state == WLCORE_STATE_OFF)) { | 5192 | if (unlikely(wl->state == WLCORE_STATE_OFF)) { |
5150 | wl12xx_for_each_wlvif_sta(wl, wlvif) { | 5193 | wl12xx_for_each_wlvif_sta(wl, wlvif) { |
5151 | struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); | 5194 | struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); |
5195 | |||
5196 | if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) | ||
5197 | continue; | ||
5198 | |||
5152 | ieee80211_chswitch_done(vif, false); | 5199 | ieee80211_chswitch_done(vif, false); |
5153 | } | 5200 | } |
5154 | goto out; | 5201 | goto out; |
@@ -5164,6 +5211,9 @@ static void wl12xx_op_channel_switch(struct ieee80211_hw *hw, | |||
5164 | wl12xx_for_each_wlvif_sta(wl, wlvif) { | 5211 | wl12xx_for_each_wlvif_sta(wl, wlvif) { |
5165 | unsigned long delay_usec; | 5212 | unsigned long delay_usec; |
5166 | 5213 | ||
5214 | if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) | ||
5215 | continue; | ||
5216 | |||
5167 | ret = wl->ops->channel_switch(wl, wlvif, ch_switch); | 5217 | ret = wl->ops->channel_switch(wl, wlvif, ch_switch); |
5168 | if (ret) | 5218 | if (ret) |
5169 | goto out_sleep; | 5219 | goto out_sleep; |
@@ -5619,7 +5669,7 @@ static void wl12xx_derive_mac_addresses(struct wl1271 *wl, u32 oui, u32 nic) | |||
5619 | memcpy(&wl->addresses[idx], &wl->addresses[0], | 5669 | memcpy(&wl->addresses[idx], &wl->addresses[0], |
5620 | sizeof(wl->addresses[0])); | 5670 | sizeof(wl->addresses[0])); |
5621 | /* LAA bit */ | 5671 | /* LAA bit */ |
5622 | wl->addresses[idx].addr[2] |= BIT(1); | 5672 | wl->addresses[idx].addr[0] |= BIT(1); |
5623 | } | 5673 | } |
5624 | 5674 | ||
5625 | wl->hw->wiphy->n_addresses = WLCORE_NUM_MAC_ADDRESSES; | 5675 | wl->hw->wiphy->n_addresses = WLCORE_NUM_MAC_ADDRESSES; |
@@ -5764,7 +5814,7 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) | |||
5764 | wl->hw->wiphy->max_sched_scan_ie_len = WL1271_CMD_TEMPL_MAX_SIZE - | 5814 | wl->hw->wiphy->max_sched_scan_ie_len = WL1271_CMD_TEMPL_MAX_SIZE - |
5765 | sizeof(struct ieee80211_header); | 5815 | sizeof(struct ieee80211_header); |
5766 | 5816 | ||
5767 | wl->hw->wiphy->max_remain_on_channel_duration = 5000; | 5817 | wl->hw->wiphy->max_remain_on_channel_duration = 30000; |
5768 | 5818 | ||
5769 | wl->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD | | 5819 | wl->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD | |
5770 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | | 5820 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | |
@@ -5833,6 +5883,9 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) | |||
5833 | wl->hw->wiphy->iface_combinations = wl->iface_combinations; | 5883 | wl->hw->wiphy->iface_combinations = wl->iface_combinations; |
5834 | wl->hw->wiphy->n_iface_combinations = wl->n_iface_combinations; | 5884 | wl->hw->wiphy->n_iface_combinations = wl->n_iface_combinations; |
5835 | 5885 | ||
5886 | /* register vendor commands */ | ||
5887 | wlcore_set_vendor_commands(wl->hw->wiphy); | ||
5888 | |||
5836 | SET_IEEE80211_DEV(wl->hw, wl->dev); | 5889 | SET_IEEE80211_DEV(wl->hw, wl->dev); |
5837 | 5890 | ||
5838 | wl->hw->sta_data_size = sizeof(struct wl1271_station); | 5891 | wl->hw->sta_data_size = sizeof(struct wl1271_station); |
diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c index 40b43115f835..f0ac36139bcc 100644 --- a/drivers/net/wireless/ti/wlcore/tx.c +++ b/drivers/net/wireless/ti/wlcore/tx.c | |||
@@ -126,7 +126,7 @@ static void wl1271_tx_regulate_link(struct wl1271 *wl, | |||
126 | if (WARN_ON(!test_bit(hlid, wlvif->links_map))) | 126 | if (WARN_ON(!test_bit(hlid, wlvif->links_map))) |
127 | return; | 127 | return; |
128 | 128 | ||
129 | fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); | 129 | fw_ps = test_bit(hlid, &wl->ap_fw_ps_map); |
130 | tx_pkts = wl->links[hlid].allocated_pkts; | 130 | tx_pkts = wl->links[hlid].allocated_pkts; |
131 | 131 | ||
132 | /* | 132 | /* |
diff --git a/drivers/net/wireless/ti/wlcore/vendor_cmd.c b/drivers/net/wireless/ti/wlcore/vendor_cmd.c new file mode 100644 index 000000000000..ad86a48dcfcb --- /dev/null +++ b/drivers/net/wireless/ti/wlcore/vendor_cmd.c | |||
@@ -0,0 +1,197 @@ | |||
1 | /* | ||
2 | * This file is part of wlcore | ||
3 | * | ||
4 | * Copyright (C) 2014 Texas Instruments. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <net/mac80211.h> | ||
12 | #include <net/netlink.h> | ||
13 | |||
14 | #include "wlcore.h" | ||
15 | #include "debug.h" | ||
16 | #include "ps.h" | ||
17 | #include "hw_ops.h" | ||
18 | #include "vendor_cmd.h" | ||
19 | |||
20 | static const | ||
21 | struct nla_policy wlcore_vendor_attr_policy[NUM_WLCORE_VENDOR_ATTR] = { | ||
22 | [WLCORE_VENDOR_ATTR_FREQ] = { .type = NLA_U32 }, | ||
23 | [WLCORE_VENDOR_ATTR_GROUP_ID] = { .type = NLA_U32 }, | ||
24 | [WLCORE_VENDOR_ATTR_GROUP_KEY] = { .type = NLA_U32, | ||
25 | .len = WLAN_MAX_KEY_LEN }, | ||
26 | }; | ||
27 | |||
28 | static int | ||
29 | wlcore_vendor_cmd_smart_config_start(struct wiphy *wiphy, | ||
30 | struct wireless_dev *wdev, | ||
31 | const void *data, int data_len) | ||
32 | { | ||
33 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); | ||
34 | struct wl1271 *wl = hw->priv; | ||
35 | struct nlattr *tb[NUM_WLCORE_VENDOR_ATTR]; | ||
36 | int ret; | ||
37 | |||
38 | wl1271_debug(DEBUG_CMD, "vendor cmd smart config start"); | ||
39 | |||
40 | if (!data) | ||
41 | return -EINVAL; | ||
42 | |||
43 | ret = nla_parse(tb, MAX_WLCORE_VENDOR_ATTR, data, data_len, | ||
44 | wlcore_vendor_attr_policy); | ||
45 | if (ret) | ||
46 | return ret; | ||
47 | |||
48 | if (!tb[WLCORE_VENDOR_ATTR_GROUP_ID]) | ||
49 | return -EINVAL; | ||
50 | |||
51 | mutex_lock(&wl->mutex); | ||
52 | |||
53 | if (unlikely(wl->state != WLCORE_STATE_ON)) { | ||
54 | ret = -EINVAL; | ||
55 | goto out; | ||
56 | } | ||
57 | |||
58 | ret = wl1271_ps_elp_wakeup(wl); | ||
59 | if (ret < 0) | ||
60 | goto out; | ||
61 | |||
62 | ret = wlcore_smart_config_start(wl, | ||
63 | nla_get_u32(tb[WLCORE_VENDOR_ATTR_GROUP_ID])); | ||
64 | |||
65 | wl1271_ps_elp_sleep(wl); | ||
66 | out: | ||
67 | mutex_unlock(&wl->mutex); | ||
68 | |||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | static int | ||
73 | wlcore_vendor_cmd_smart_config_stop(struct wiphy *wiphy, | ||
74 | struct wireless_dev *wdev, | ||
75 | const void *data, int data_len) | ||
76 | { | ||
77 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); | ||
78 | struct wl1271 *wl = hw->priv; | ||
79 | int ret; | ||
80 | |||
81 | wl1271_debug(DEBUG_CMD, "testmode cmd smart config stop"); | ||
82 | |||
83 | mutex_lock(&wl->mutex); | ||
84 | |||
85 | if (unlikely(wl->state != WLCORE_STATE_ON)) { | ||
86 | ret = -EINVAL; | ||
87 | goto out; | ||
88 | } | ||
89 | |||
90 | ret = wl1271_ps_elp_wakeup(wl); | ||
91 | if (ret < 0) | ||
92 | goto out; | ||
93 | |||
94 | ret = wlcore_smart_config_stop(wl); | ||
95 | |||
96 | wl1271_ps_elp_sleep(wl); | ||
97 | out: | ||
98 | mutex_unlock(&wl->mutex); | ||
99 | |||
100 | return ret; | ||
101 | } | ||
102 | |||
103 | static int | ||
104 | wlcore_vendor_cmd_smart_config_set_group_key(struct wiphy *wiphy, | ||
105 | struct wireless_dev *wdev, | ||
106 | const void *data, int data_len) | ||
107 | { | ||
108 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); | ||
109 | struct wl1271 *wl = hw->priv; | ||
110 | struct nlattr *tb[NUM_WLCORE_VENDOR_ATTR]; | ||
111 | int ret; | ||
112 | |||
113 | wl1271_debug(DEBUG_CMD, "testmode cmd smart config set group key"); | ||
114 | |||
115 | if (!data) | ||
116 | return -EINVAL; | ||
117 | |||
118 | ret = nla_parse(tb, MAX_WLCORE_VENDOR_ATTR, data, data_len, | ||
119 | wlcore_vendor_attr_policy); | ||
120 | if (ret) | ||
121 | return ret; | ||
122 | |||
123 | if (!tb[WLCORE_VENDOR_ATTR_GROUP_ID] || | ||
124 | !tb[WLCORE_VENDOR_ATTR_GROUP_KEY]) | ||
125 | return -EINVAL; | ||
126 | |||
127 | mutex_lock(&wl->mutex); | ||
128 | |||
129 | if (unlikely(wl->state != WLCORE_STATE_ON)) { | ||
130 | ret = -EINVAL; | ||
131 | goto out; | ||
132 | } | ||
133 | |||
134 | ret = wl1271_ps_elp_wakeup(wl); | ||
135 | if (ret < 0) | ||
136 | goto out; | ||
137 | |||
138 | ret = wlcore_smart_config_set_group_key(wl, | ||
139 | nla_get_u32(tb[WLCORE_VENDOR_ATTR_GROUP_ID]), | ||
140 | nla_len(tb[WLCORE_VENDOR_ATTR_GROUP_KEY]), | ||
141 | nla_data(tb[WLCORE_VENDOR_ATTR_GROUP_KEY])); | ||
142 | |||
143 | wl1271_ps_elp_sleep(wl); | ||
144 | out: | ||
145 | mutex_unlock(&wl->mutex); | ||
146 | |||
147 | return ret; | ||
148 | } | ||
149 | |||
150 | static const struct wiphy_vendor_command wlcore_vendor_commands[] = { | ||
151 | { | ||
152 | .info = { | ||
153 | .vendor_id = TI_OUI, | ||
154 | .subcmd = WLCORE_VENDOR_CMD_SMART_CONFIG_START, | ||
155 | }, | ||
156 | .flags = WIPHY_VENDOR_CMD_NEED_NETDEV | | ||
157 | WIPHY_VENDOR_CMD_NEED_RUNNING, | ||
158 | .doit = wlcore_vendor_cmd_smart_config_start, | ||
159 | }, | ||
160 | { | ||
161 | .info = { | ||
162 | .vendor_id = TI_OUI, | ||
163 | .subcmd = WLCORE_VENDOR_CMD_SMART_CONFIG_STOP, | ||
164 | }, | ||
165 | .flags = WIPHY_VENDOR_CMD_NEED_NETDEV | | ||
166 | WIPHY_VENDOR_CMD_NEED_RUNNING, | ||
167 | .doit = wlcore_vendor_cmd_smart_config_stop, | ||
168 | }, | ||
169 | { | ||
170 | .info = { | ||
171 | .vendor_id = TI_OUI, | ||
172 | .subcmd = WLCORE_VENDOR_CMD_SMART_CONFIG_SET_GROUP_KEY, | ||
173 | }, | ||
174 | .flags = WIPHY_VENDOR_CMD_NEED_NETDEV | | ||
175 | WIPHY_VENDOR_CMD_NEED_RUNNING, | ||
176 | .doit = wlcore_vendor_cmd_smart_config_set_group_key, | ||
177 | }, | ||
178 | }; | ||
179 | |||
180 | static const struct nl80211_vendor_cmd_info wlcore_vendor_events[] = { | ||
181 | { | ||
182 | .vendor_id = TI_OUI, | ||
183 | .subcmd = WLCORE_VENDOR_EVENT_SC_SYNC, | ||
184 | }, | ||
185 | { | ||
186 | .vendor_id = TI_OUI, | ||
187 | .subcmd = WLCORE_VENDOR_EVENT_SC_DECODE, | ||
188 | }, | ||
189 | }; | ||
190 | |||
191 | void wlcore_set_vendor_commands(struct wiphy *wiphy) | ||
192 | { | ||
193 | wiphy->vendor_commands = wlcore_vendor_commands; | ||
194 | wiphy->n_vendor_commands = ARRAY_SIZE(wlcore_vendor_commands); | ||
195 | wiphy->vendor_events = wlcore_vendor_events; | ||
196 | wiphy->n_vendor_events = ARRAY_SIZE(wlcore_vendor_events); | ||
197 | } | ||
diff --git a/drivers/net/wireless/ti/wlcore/vendor_cmd.h b/drivers/net/wireless/ti/wlcore/vendor_cmd.h new file mode 100644 index 000000000000..6e0c15e30f03 --- /dev/null +++ b/drivers/net/wireless/ti/wlcore/vendor_cmd.h | |||
@@ -0,0 +1,45 @@ | |||
1 | /* | ||
2 | * This file is part of wlcore | ||
3 | * | ||
4 | * Copyright (C) 2014 Texas Instruments. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #ifndef __WLCORE_VENDOR_H__ | ||
12 | #define __WLCORE_VENDOR_H__ | ||
13 | |||
14 | #ifdef __KERNEL__ | ||
15 | void wlcore_set_vendor_commands(struct wiphy *wiphy); | ||
16 | #endif | ||
17 | |||
18 | #define TI_OUI 0x080028 | ||
19 | |||
20 | enum wlcore_vendor_commands { | ||
21 | WLCORE_VENDOR_CMD_SMART_CONFIG_START, | ||
22 | WLCORE_VENDOR_CMD_SMART_CONFIG_STOP, | ||
23 | WLCORE_VENDOR_CMD_SMART_CONFIG_SET_GROUP_KEY, | ||
24 | |||
25 | NUM_WLCORE_VENDOR_CMD, | ||
26 | MAX_WLCORE_VENDOR_CMD = NUM_WLCORE_VENDOR_CMD - 1 | ||
27 | }; | ||
28 | |||
29 | enum wlcore_vendor_attributes { | ||
30 | WLCORE_VENDOR_ATTR_FREQ, | ||
31 | WLCORE_VENDOR_ATTR_PSK, | ||
32 | WLCORE_VENDOR_ATTR_SSID, | ||
33 | WLCORE_VENDOR_ATTR_GROUP_ID, | ||
34 | WLCORE_VENDOR_ATTR_GROUP_KEY, | ||
35 | |||
36 | NUM_WLCORE_VENDOR_ATTR, | ||
37 | MAX_WLCORE_VENDOR_ATTR = NUM_WLCORE_VENDOR_ATTR - 1 | ||
38 | }; | ||
39 | |||
40 | enum wlcore_vendor_events { | ||
41 | WLCORE_VENDOR_EVENT_SC_SYNC, | ||
42 | WLCORE_VENDOR_EVENT_SC_DECODE, | ||
43 | }; | ||
44 | |||
45 | #endif /* __WLCORE_VENDOR_H__ */ | ||
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h index 71320509b56d..df78cf12ef15 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/drivers/net/wireless/ti/wlcore/wlcore.h | |||
@@ -117,6 +117,10 @@ struct wlcore_ops { | |||
117 | struct wl1271_link *lnk); | 117 | struct wl1271_link *lnk); |
118 | bool (*lnk_low_prio)(struct wl1271 *wl, u8 hlid, | 118 | bool (*lnk_low_prio)(struct wl1271 *wl, u8 hlid, |
119 | struct wl1271_link *lnk); | 119 | struct wl1271_link *lnk); |
120 | int (*smart_config_start)(struct wl1271 *wl, u32 group_bitmap); | ||
121 | int (*smart_config_stop)(struct wl1271 *wl); | ||
122 | int (*smart_config_set_group_key)(struct wl1271 *wl, u16 group_id, | ||
123 | u8 key_len, u8 *key); | ||
120 | }; | 124 | }; |
121 | 125 | ||
122 | enum wlcore_partitions { | 126 | enum wlcore_partitions { |
@@ -384,10 +388,10 @@ struct wl1271 { | |||
384 | int active_link_count; | 388 | int active_link_count; |
385 | 389 | ||
386 | /* Fast/slow links bitmap according to FW */ | 390 | /* Fast/slow links bitmap according to FW */ |
387 | u32 fw_fast_lnk_map; | 391 | unsigned long fw_fast_lnk_map; |
388 | 392 | ||
389 | /* AP-mode - a bitmap of links currently in PS mode according to FW */ | 393 | /* AP-mode - a bitmap of links currently in PS mode according to FW */ |
390 | u32 ap_fw_ps_map; | 394 | unsigned long ap_fw_ps_map; |
391 | 395 | ||
392 | /* AP-mode - a bitmap of links currently in PS mode in mac80211 */ | 396 | /* AP-mode - a bitmap of links currently in PS mode in mac80211 */ |
393 | unsigned long ap_ps_map; | 397 | unsigned long ap_ps_map; |
diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h index c2c34a84ff3d..0e52556044d9 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore_i.h +++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h | |||
@@ -45,6 +45,9 @@ | |||
45 | #define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff)) | 45 | #define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff)) |
46 | #define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff)) | 46 | #define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff)) |
47 | #define WL1271_TX_SQN_POST_RECOVERY_PADDING 0xff | 47 | #define WL1271_TX_SQN_POST_RECOVERY_PADDING 0xff |
48 | /* Use smaller padding for GEM, as some APs have issues when it's too big */ | ||
49 | #define WL1271_TX_SQN_POST_RECOVERY_PADDING_GEM 0x20 | ||
50 | |||
48 | 51 | ||
49 | #define WL1271_CIPHER_SUITE_GEM 0x00147201 | 52 | #define WL1271_CIPHER_SUITE_GEM 0x00147201 |
50 | 53 | ||
@@ -324,6 +327,7 @@ struct wl1271_station { | |||
324 | * total freed FW packets on the link to the STA - used for tracking the | 327 | * total freed FW packets on the link to the STA - used for tracking the |
325 | * AES/TKIP PN across recoveries. Re-initialized each time from the | 328 | * AES/TKIP PN across recoveries. Re-initialized each time from the |
326 | * wl1271_station structure. | 329 | * wl1271_station structure. |
330 | * Used in both AP and STA mode. | ||
327 | */ | 331 | */ |
328 | u64 total_freed_pkts; | 332 | u64 total_freed_pkts; |
329 | }; | 333 | }; |
@@ -460,21 +464,19 @@ struct wl12xx_vif { | |||
460 | struct delayed_work pending_auth_complete_work; | 464 | struct delayed_work pending_auth_complete_work; |
461 | 465 | ||
462 | /* | 466 | /* |
467 | * total freed FW packets on the link. | ||
468 | * For STA this holds the PN of the link to the AP. | ||
469 | * For AP this holds the PN of the broadcast link. | ||
470 | */ | ||
471 | u64 total_freed_pkts; | ||
472 | |||
473 | /* | ||
463 | * This struct must be last! | 474 | * This struct must be last! |
464 | * data that has to be saved acrossed reconfigs (e.g. recovery) | 475 | * data that has to be saved acrossed reconfigs (e.g. recovery) |
465 | * should be declared in this struct. | 476 | * should be declared in this struct. |
466 | */ | 477 | */ |
467 | struct { | 478 | struct { |
468 | u8 persistent[0]; | 479 | u8 persistent[0]; |
469 | |||
470 | /* | ||
471 | * total freed FW packets on the link - used for | ||
472 | * storing the AES/TKIP PN during recovery, as this | ||
473 | * structure is not zeroed out. | ||
474 | * For STA this holds the PN of the link to the AP. | ||
475 | * For AP this holds the PN of the broadcast link. | ||
476 | */ | ||
477 | u64 total_freed_pkts; | ||
478 | }; | 480 | }; |
479 | }; | 481 | }; |
480 | 482 | ||
diff --git a/drivers/net/wireless/zd1211rw/Kconfig b/drivers/net/wireless/zd1211rw/Kconfig index 96c8e1de0879..95920581860a 100644 --- a/drivers/net/wireless/zd1211rw/Kconfig +++ b/drivers/net/wireless/zd1211rw/Kconfig | |||
@@ -3,11 +3,11 @@ config ZD1211RW | |||
3 | depends on USB && MAC80211 | 3 | depends on USB && MAC80211 |
4 | select FW_LOADER | 4 | select FW_LOADER |
5 | ---help--- | 5 | ---help--- |
6 | This is an experimental driver for the ZyDAS ZD1211/ZD1211B wireless | 6 | This is a driver for the ZyDAS ZD1211/ZD1211B wireless |
7 | chip, present in many USB-wireless adapters. | 7 | chip, present in many USB-wireless adapters. |
8 | 8 | ||
9 | Device firmware is required alongside this driver. You can download | 9 | Device firmware is required alongside this driver. You can download |
10 | the firmware distribution from http://zd1211.ath.cx/get-firmware | 10 | the firmware distribution from http://sf.net/projects/zd1211/files/ |
11 | 11 | ||
12 | config ZD1211RW_DEBUG | 12 | config ZD1211RW_DEBUG |
13 | bool "ZyDAS ZD1211 debugging" | 13 | bool "ZyDAS ZD1211 debugging" |
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c index a8dc95ebf2d6..0f28c08fcb3c 100644 --- a/drivers/ssb/pci.c +++ b/drivers/ssb/pci.c | |||
@@ -326,13 +326,13 @@ err_ctlreg: | |||
326 | return err; | 326 | return err; |
327 | } | 327 | } |
328 | 328 | ||
329 | static s8 r123_extract_antgain(u8 sprom_revision, const u16 *in, | 329 | static s8 sprom_extract_antgain(u8 sprom_revision, const u16 *in, u16 offset, |
330 | u16 mask, u16 shift) | 330 | u16 mask, u16 shift) |
331 | { | 331 | { |
332 | u16 v; | 332 | u16 v; |
333 | u8 gain; | 333 | u8 gain; |
334 | 334 | ||
335 | v = in[SPOFF(SSB_SPROM1_AGAIN)]; | 335 | v = in[SPOFF(offset)]; |
336 | gain = (v & mask) >> shift; | 336 | gain = (v & mask) >> shift; |
337 | if (gain == 0xFF) | 337 | if (gain == 0xFF) |
338 | gain = 2; /* If unset use 2dBm */ | 338 | gain = 2; /* If unset use 2dBm */ |
@@ -416,12 +416,14 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) | |||
416 | SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0); | 416 | SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0); |
417 | 417 | ||
418 | /* Extract the antenna gain values. */ | 418 | /* Extract the antenna gain values. */ |
419 | out->antenna_gain.a0 = r123_extract_antgain(out->revision, in, | 419 | out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in, |
420 | SSB_SPROM1_AGAIN_BG, | 420 | SSB_SPROM1_AGAIN, |
421 | SSB_SPROM1_AGAIN_BG_SHIFT); | 421 | SSB_SPROM1_AGAIN_BG, |
422 | out->antenna_gain.a1 = r123_extract_antgain(out->revision, in, | 422 | SSB_SPROM1_AGAIN_BG_SHIFT); |
423 | SSB_SPROM1_AGAIN_A, | 423 | out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in, |
424 | SSB_SPROM1_AGAIN_A_SHIFT); | 424 | SSB_SPROM1_AGAIN, |
425 | SSB_SPROM1_AGAIN_A, | ||
426 | SSB_SPROM1_AGAIN_A_SHIFT); | ||
425 | if (out->revision >= 2) | 427 | if (out->revision >= 2) |
426 | sprom_extract_r23(out, in); | 428 | sprom_extract_r23(out, in); |
427 | } | 429 | } |
@@ -468,7 +470,15 @@ static void sprom_extract_r458(struct ssb_sprom *out, const u16 *in) | |||
468 | 470 | ||
469 | static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in) | 471 | static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in) |
470 | { | 472 | { |
473 | static const u16 pwr_info_offset[] = { | ||
474 | SSB_SPROM4_PWR_INFO_CORE0, SSB_SPROM4_PWR_INFO_CORE1, | ||
475 | SSB_SPROM4_PWR_INFO_CORE2, SSB_SPROM4_PWR_INFO_CORE3 | ||
476 | }; | ||
471 | u16 il0mac_offset; | 477 | u16 il0mac_offset; |
478 | int i; | ||
479 | |||
480 | BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) != | ||
481 | ARRAY_SIZE(out->core_pwr_info)); | ||
472 | 482 | ||
473 | if (out->revision == 4) | 483 | if (out->revision == 4) |
474 | il0mac_offset = SSB_SPROM4_IL0MAC; | 484 | il0mac_offset = SSB_SPROM4_IL0MAC; |
@@ -524,14 +534,59 @@ static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in) | |||
524 | } | 534 | } |
525 | 535 | ||
526 | /* Extract the antenna gain values. */ | 536 | /* Extract the antenna gain values. */ |
527 | SPEX(antenna_gain.a0, SSB_SPROM4_AGAIN01, | 537 | out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in, |
528 | SSB_SPROM4_AGAIN0, SSB_SPROM4_AGAIN0_SHIFT); | 538 | SSB_SPROM4_AGAIN01, |
529 | SPEX(antenna_gain.a1, SSB_SPROM4_AGAIN01, | 539 | SSB_SPROM4_AGAIN0, |
530 | SSB_SPROM4_AGAIN1, SSB_SPROM4_AGAIN1_SHIFT); | 540 | SSB_SPROM4_AGAIN0_SHIFT); |
531 | SPEX(antenna_gain.a2, SSB_SPROM4_AGAIN23, | 541 | out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in, |
532 | SSB_SPROM4_AGAIN2, SSB_SPROM4_AGAIN2_SHIFT); | 542 | SSB_SPROM4_AGAIN01, |
533 | SPEX(antenna_gain.a3, SSB_SPROM4_AGAIN23, | 543 | SSB_SPROM4_AGAIN1, |
534 | SSB_SPROM4_AGAIN3, SSB_SPROM4_AGAIN3_SHIFT); | 544 | SSB_SPROM4_AGAIN1_SHIFT); |
545 | out->antenna_gain.a2 = sprom_extract_antgain(out->revision, in, | ||
546 | SSB_SPROM4_AGAIN23, | ||
547 | SSB_SPROM4_AGAIN2, | ||
548 | SSB_SPROM4_AGAIN2_SHIFT); | ||
549 | out->antenna_gain.a3 = sprom_extract_antgain(out->revision, in, | ||
550 | SSB_SPROM4_AGAIN23, | ||
551 | SSB_SPROM4_AGAIN3, | ||
552 | SSB_SPROM4_AGAIN3_SHIFT); | ||
553 | |||
554 | /* Extract cores power info info */ | ||
555 | for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) { | ||
556 | u16 o = pwr_info_offset[i]; | ||
557 | |||
558 | SPEX(core_pwr_info[i].itssi_2g, o + SSB_SPROM4_2G_MAXP_ITSSI, | ||
559 | SSB_SPROM4_2G_ITSSI, SSB_SPROM4_2G_ITSSI_SHIFT); | ||
560 | SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SPROM4_2G_MAXP_ITSSI, | ||
561 | SSB_SPROM4_2G_MAXP, 0); | ||
562 | |||
563 | SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SPROM4_2G_PA_0, ~0, 0); | ||
564 | SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SPROM4_2G_PA_1, ~0, 0); | ||
565 | SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SPROM4_2G_PA_2, ~0, 0); | ||
566 | SPEX(core_pwr_info[i].pa_2g[3], o + SSB_SPROM4_2G_PA_3, ~0, 0); | ||
567 | |||
568 | SPEX(core_pwr_info[i].itssi_5g, o + SSB_SPROM4_5G_MAXP_ITSSI, | ||
569 | SSB_SPROM4_5G_ITSSI, SSB_SPROM4_5G_ITSSI_SHIFT); | ||
570 | SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SPROM4_5G_MAXP_ITSSI, | ||
571 | SSB_SPROM4_5G_MAXP, 0); | ||
572 | SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM4_5GHL_MAXP, | ||
573 | SSB_SPROM4_5GH_MAXP, 0); | ||
574 | SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM4_5GHL_MAXP, | ||
575 | SSB_SPROM4_5GL_MAXP, SSB_SPROM4_5GL_MAXP_SHIFT); | ||
576 | |||
577 | SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SPROM4_5GL_PA_0, ~0, 0); | ||
578 | SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SPROM4_5GL_PA_1, ~0, 0); | ||
579 | SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SPROM4_5GL_PA_2, ~0, 0); | ||
580 | SPEX(core_pwr_info[i].pa_5gl[3], o + SSB_SPROM4_5GL_PA_3, ~0, 0); | ||
581 | SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SPROM4_5G_PA_0, ~0, 0); | ||
582 | SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SPROM4_5G_PA_1, ~0, 0); | ||
583 | SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SPROM4_5G_PA_2, ~0, 0); | ||
584 | SPEX(core_pwr_info[i].pa_5g[3], o + SSB_SPROM4_5G_PA_3, ~0, 0); | ||
585 | SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SPROM4_5GH_PA_0, ~0, 0); | ||
586 | SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SPROM4_5GH_PA_1, ~0, 0); | ||
587 | SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SPROM4_5GH_PA_2, ~0, 0); | ||
588 | SPEX(core_pwr_info[i].pa_5gh[3], o + SSB_SPROM4_5GH_PA_3, ~0, 0); | ||
589 | } | ||
535 | 590 | ||
536 | sprom_extract_r458(out, in); | 591 | sprom_extract_r458(out, in); |
537 | 592 | ||
@@ -621,14 +676,22 @@ static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in) | |||
621 | SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0); | 676 | SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0); |
622 | 677 | ||
623 | /* Extract the antenna gain values. */ | 678 | /* Extract the antenna gain values. */ |
624 | SPEX(antenna_gain.a0, SSB_SPROM8_AGAIN01, | 679 | out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in, |
625 | SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT); | 680 | SSB_SPROM8_AGAIN01, |
626 | SPEX(antenna_gain.a1, SSB_SPROM8_AGAIN01, | 681 | SSB_SPROM8_AGAIN0, |
627 | SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT); | 682 | SSB_SPROM8_AGAIN0_SHIFT); |
628 | SPEX(antenna_gain.a2, SSB_SPROM8_AGAIN23, | 683 | out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in, |
629 | SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT); | 684 | SSB_SPROM8_AGAIN01, |
630 | SPEX(antenna_gain.a3, SSB_SPROM8_AGAIN23, | 685 | SSB_SPROM8_AGAIN1, |
631 | SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT); | 686 | SSB_SPROM8_AGAIN1_SHIFT); |
687 | out->antenna_gain.a2 = sprom_extract_antgain(out->revision, in, | ||
688 | SSB_SPROM8_AGAIN23, | ||
689 | SSB_SPROM8_AGAIN2, | ||
690 | SSB_SPROM8_AGAIN2_SHIFT); | ||
691 | out->antenna_gain.a3 = sprom_extract_antgain(out->revision, in, | ||
692 | SSB_SPROM8_AGAIN23, | ||
693 | SSB_SPROM8_AGAIN3, | ||
694 | SSB_SPROM8_AGAIN3_SHIFT); | ||
632 | 695 | ||
633 | /* Extract cores power info info */ | 696 | /* Extract cores power info info */ |
634 | for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) { | 697 | for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) { |
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index e82289047272..afec6450450f 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c | |||
@@ -59,7 +59,7 @@ | |||
59 | #include <linux/gfp.h> | 59 | #include <linux/gfp.h> |
60 | 60 | ||
61 | #include <net/bluetooth/bluetooth.h> | 61 | #include <net/bluetooth/bluetooth.h> |
62 | #include <net/bluetooth/hci.h> | 62 | #include <net/bluetooth/hci_sock.h> |
63 | #include <net/bluetooth/rfcomm.h> | 63 | #include <net/bluetooth/rfcomm.h> |
64 | 64 | ||
65 | #include <linux/capi.h> | 65 | #include <linux/capi.h> |
diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h index 452286a38b2b..969af0f2bdf9 100644 --- a/include/linux/bcma/bcma.h +++ b/include/linux/bcma/bcma.h | |||
@@ -158,6 +158,8 @@ struct bcma_host_ops { | |||
158 | /* Chip IDs of PCIe devices */ | 158 | /* Chip IDs of PCIe devices */ |
159 | #define BCMA_CHIP_ID_BCM4313 0x4313 | 159 | #define BCMA_CHIP_ID_BCM4313 0x4313 |
160 | #define BCMA_CHIP_ID_BCM43142 43142 | 160 | #define BCMA_CHIP_ID_BCM43142 43142 |
161 | #define BCMA_CHIP_ID_BCM43217 43217 | ||
162 | #define BCMA_CHIP_ID_BCM43222 43222 | ||
161 | #define BCMA_CHIP_ID_BCM43224 43224 | 163 | #define BCMA_CHIP_ID_BCM43224 43224 |
162 | #define BCMA_PKG_ID_BCM43224_FAB_CSM 0x8 | 164 | #define BCMA_PKG_ID_BCM43224_FAB_CSM 0x8 |
163 | #define BCMA_PKG_ID_BCM43224_FAB_SMIC 0xa | 165 | #define BCMA_PKG_ID_BCM43224_FAB_SMIC 0xa |
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/linux/ssb/ssb_regs.h b/include/linux/ssb/ssb_regs.h index f9f931c89e3e..f7b9100686c3 100644 --- a/include/linux/ssb/ssb_regs.h +++ b/include/linux/ssb/ssb_regs.h | |||
@@ -345,6 +345,43 @@ | |||
345 | #define SSB_SPROM4_TXPID5GH2_SHIFT 0 | 345 | #define SSB_SPROM4_TXPID5GH2_SHIFT 0 |
346 | #define SSB_SPROM4_TXPID5GH3 0xFF00 | 346 | #define SSB_SPROM4_TXPID5GH3 0xFF00 |
347 | #define SSB_SPROM4_TXPID5GH3_SHIFT 8 | 347 | #define SSB_SPROM4_TXPID5GH3_SHIFT 8 |
348 | |||
349 | /* There are 4 blocks with power info sharing the same layout */ | ||
350 | #define SSB_SPROM4_PWR_INFO_CORE0 0x0080 | ||
351 | #define SSB_SPROM4_PWR_INFO_CORE1 0x00AE | ||
352 | #define SSB_SPROM4_PWR_INFO_CORE2 0x00DC | ||
353 | #define SSB_SPROM4_PWR_INFO_CORE3 0x010A | ||
354 | |||
355 | #define SSB_SPROM4_2G_MAXP_ITSSI 0x00 /* 2 GHz ITSSI and 2 GHz Max Power */ | ||
356 | #define SSB_SPROM4_2G_MAXP 0x00FF | ||
357 | #define SSB_SPROM4_2G_ITSSI 0xFF00 | ||
358 | #define SSB_SPROM4_2G_ITSSI_SHIFT 8 | ||
359 | #define SSB_SPROM4_2G_PA_0 0x02 /* 2 GHz power amp */ | ||
360 | #define SSB_SPROM4_2G_PA_1 0x04 | ||
361 | #define SSB_SPROM4_2G_PA_2 0x06 | ||
362 | #define SSB_SPROM4_2G_PA_3 0x08 | ||
363 | #define SSB_SPROM4_5G_MAXP_ITSSI 0x0A /* 5 GHz ITSSI and 5.3 GHz Max Power */ | ||
364 | #define SSB_SPROM4_5G_MAXP 0x00FF | ||
365 | #define SSB_SPROM4_5G_ITSSI 0xFF00 | ||
366 | #define SSB_SPROM4_5G_ITSSI_SHIFT 8 | ||
367 | #define SSB_SPROM4_5GHL_MAXP 0x0C /* 5.2 GHz and 5.8 GHz Max Power */ | ||
368 | #define SSB_SPROM4_5GH_MAXP 0x00FF | ||
369 | #define SSB_SPROM4_5GL_MAXP 0xFF00 | ||
370 | #define SSB_SPROM4_5GL_MAXP_SHIFT 8 | ||
371 | #define SSB_SPROM4_5G_PA_0 0x0E /* 5.3 GHz power amp */ | ||
372 | #define SSB_SPROM4_5G_PA_1 0x10 | ||
373 | #define SSB_SPROM4_5G_PA_2 0x12 | ||
374 | #define SSB_SPROM4_5G_PA_3 0x14 | ||
375 | #define SSB_SPROM4_5GL_PA_0 0x16 /* 5.2 GHz power amp */ | ||
376 | #define SSB_SPROM4_5GL_PA_1 0x18 | ||
377 | #define SSB_SPROM4_5GL_PA_2 0x1A | ||
378 | #define SSB_SPROM4_5GL_PA_3 0x1C | ||
379 | #define SSB_SPROM4_5GH_PA_0 0x1E /* 5.8 GHz power amp */ | ||
380 | #define SSB_SPROM4_5GH_PA_1 0x20 | ||
381 | #define SSB_SPROM4_5GH_PA_2 0x22 | ||
382 | #define SSB_SPROM4_5GH_PA_3 0x24 | ||
383 | |||
384 | /* TODO: Make it deprecated */ | ||
348 | #define SSB_SPROM4_MAXP_BG 0x0080 /* Max Power BG in path 1 */ | 385 | #define SSB_SPROM4_MAXP_BG 0x0080 /* Max Power BG in path 1 */ |
349 | #define SSB_SPROM4_MAXP_BG_MASK 0x00FF /* Mask for Max Power BG */ | 386 | #define SSB_SPROM4_MAXP_BG_MASK 0x00FF /* Mask for Max Power BG */ |
350 | #define SSB_SPROM4_ITSSI_BG 0xFF00 /* Mask for path 1 itssi_bg */ | 387 | #define SSB_SPROM4_ITSSI_BG 0xFF00 /* Mask for path 1 itssi_bg */ |
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index a01236e2df13..f0a3d8890760 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h | |||
@@ -202,33 +202,6 @@ enum { | |||
202 | #define HCI_PERSISTENT_MASK (BIT(HCI_LE_SCAN) | BIT(HCI_PERIODIC_INQ) | \ | 202 | #define HCI_PERSISTENT_MASK (BIT(HCI_LE_SCAN) | BIT(HCI_PERIODIC_INQ) | \ |
203 | BIT(HCI_FAST_CONNECTABLE) | BIT(HCI_LE_ADV)) | 203 | BIT(HCI_FAST_CONNECTABLE) | BIT(HCI_LE_ADV)) |
204 | 204 | ||
205 | /* HCI ioctl defines */ | ||
206 | #define HCIDEVUP _IOW('H', 201, int) | ||
207 | #define HCIDEVDOWN _IOW('H', 202, int) | ||
208 | #define HCIDEVRESET _IOW('H', 203, int) | ||
209 | #define HCIDEVRESTAT _IOW('H', 204, int) | ||
210 | |||
211 | #define HCIGETDEVLIST _IOR('H', 210, int) | ||
212 | #define HCIGETDEVINFO _IOR('H', 211, int) | ||
213 | #define HCIGETCONNLIST _IOR('H', 212, int) | ||
214 | #define HCIGETCONNINFO _IOR('H', 213, int) | ||
215 | #define HCIGETAUTHINFO _IOR('H', 215, int) | ||
216 | |||
217 | #define HCISETRAW _IOW('H', 220, int) | ||
218 | #define HCISETSCAN _IOW('H', 221, int) | ||
219 | #define HCISETAUTH _IOW('H', 222, int) | ||
220 | #define HCISETENCRYPT _IOW('H', 223, int) | ||
221 | #define HCISETPTYPE _IOW('H', 224, int) | ||
222 | #define HCISETLINKPOL _IOW('H', 225, int) | ||
223 | #define HCISETLINKMODE _IOW('H', 226, int) | ||
224 | #define HCISETACLMTU _IOW('H', 227, int) | ||
225 | #define HCISETSCOMTU _IOW('H', 228, int) | ||
226 | |||
227 | #define HCIBLOCKADDR _IOW('H', 230, int) | ||
228 | #define HCIUNBLOCKADDR _IOW('H', 231, int) | ||
229 | |||
230 | #define HCIINQUIRY _IOR('H', 240, int) | ||
231 | |||
232 | /* HCI timeouts */ | 205 | /* HCI timeouts */ |
233 | #define HCI_DISCONN_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */ | 206 | #define HCI_DISCONN_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */ |
234 | #define HCI_PAIRING_TIMEOUT msecs_to_jiffies(60000) /* 60 seconds */ | 207 | #define HCI_PAIRING_TIMEOUT msecs_to_jiffies(60000) /* 60 seconds */ |
@@ -356,6 +329,7 @@ enum { | |||
356 | #define LMP_HOST_SC 0x08 | 329 | #define LMP_HOST_SC 0x08 |
357 | 330 | ||
358 | /* LE features */ | 331 | /* LE features */ |
332 | #define HCI_LE_ENCRYPTION 0x01 | ||
359 | #define HCI_LE_CONN_PARAM_REQ_PROC 0x02 | 333 | #define HCI_LE_CONN_PARAM_REQ_PROC 0x02 |
360 | #define HCI_LE_PING 0x10 | 334 | #define HCI_LE_PING 0x10 |
361 | 335 | ||
@@ -427,6 +401,9 @@ enum { | |||
427 | /* The core spec defines 127 as the "not available" value */ | 401 | /* The core spec defines 127 as the "not available" value */ |
428 | #define HCI_TX_POWER_INVALID 127 | 402 | #define HCI_TX_POWER_INVALID 127 |
429 | 403 | ||
404 | #define HCI_ROLE_MASTER 0x00 | ||
405 | #define HCI_ROLE_SLAVE 0x01 | ||
406 | |||
430 | /* Extended Inquiry Response field types */ | 407 | /* Extended Inquiry Response field types */ |
431 | #define EIR_FLAGS 0x01 /* flags */ | 408 | #define EIR_FLAGS 0x01 /* flags */ |
432 | #define EIR_UUID16_SOME 0x02 /* 16-bit UUID, more available */ | 409 | #define EIR_UUID16_SOME 0x02 /* 16-bit UUID, more available */ |
@@ -1739,9 +1716,6 @@ struct hci_ev_sync_train_complete { | |||
1739 | 1716 | ||
1740 | #define HCI_EV_SLAVE_PAGE_RESP_TIMEOUT 0x54 | 1717 | #define HCI_EV_SLAVE_PAGE_RESP_TIMEOUT 0x54 |
1741 | 1718 | ||
1742 | /* Low energy meta events */ | ||
1743 | #define LE_CONN_ROLE_MASTER 0x00 | ||
1744 | |||
1745 | #define HCI_EV_LE_CONN_COMPLETE 0x01 | 1719 | #define HCI_EV_LE_CONN_COMPLETE 0x01 |
1746 | struct hci_ev_le_conn_complete { | 1720 | struct hci_ev_le_conn_complete { |
1747 | __u8 status; | 1721 | __u8 status; |
@@ -1871,126 +1845,4 @@ static inline struct hci_sco_hdr *hci_sco_hdr(const struct sk_buff *skb) | |||
1871 | #define hci_handle(h) (h & 0x0fff) | 1845 | #define hci_handle(h) (h & 0x0fff) |
1872 | #define hci_flags(h) (h >> 12) | 1846 | #define hci_flags(h) (h >> 12) |
1873 | 1847 | ||
1874 | /* ---- HCI Sockets ---- */ | ||
1875 | |||
1876 | /* Socket options */ | ||
1877 | #define HCI_DATA_DIR 1 | ||
1878 | #define HCI_FILTER 2 | ||
1879 | #define HCI_TIME_STAMP 3 | ||
1880 | |||
1881 | /* CMSG flags */ | ||
1882 | #define HCI_CMSG_DIR 0x0001 | ||
1883 | #define HCI_CMSG_TSTAMP 0x0002 | ||
1884 | |||
1885 | struct sockaddr_hci { | ||
1886 | sa_family_t hci_family; | ||
1887 | unsigned short hci_dev; | ||
1888 | unsigned short hci_channel; | ||
1889 | }; | ||
1890 | #define HCI_DEV_NONE 0xffff | ||
1891 | |||
1892 | #define HCI_CHANNEL_RAW 0 | ||
1893 | #define HCI_CHANNEL_USER 1 | ||
1894 | #define HCI_CHANNEL_MONITOR 2 | ||
1895 | #define HCI_CHANNEL_CONTROL 3 | ||
1896 | |||
1897 | struct hci_filter { | ||
1898 | unsigned long type_mask; | ||
1899 | unsigned long event_mask[2]; | ||
1900 | __le16 opcode; | ||
1901 | }; | ||
1902 | |||
1903 | struct hci_ufilter { | ||
1904 | __u32 type_mask; | ||
1905 | __u32 event_mask[2]; | ||
1906 | __le16 opcode; | ||
1907 | }; | ||
1908 | |||
1909 | #define HCI_FLT_TYPE_BITS 31 | ||
1910 | #define HCI_FLT_EVENT_BITS 63 | ||
1911 | #define HCI_FLT_OGF_BITS 63 | ||
1912 | #define HCI_FLT_OCF_BITS 127 | ||
1913 | |||
1914 | /* ---- HCI Ioctl requests structures ---- */ | ||
1915 | struct hci_dev_stats { | ||
1916 | __u32 err_rx; | ||
1917 | __u32 err_tx; | ||
1918 | __u32 cmd_tx; | ||
1919 | __u32 evt_rx; | ||
1920 | __u32 acl_tx; | ||
1921 | __u32 acl_rx; | ||
1922 | __u32 sco_tx; | ||
1923 | __u32 sco_rx; | ||
1924 | __u32 byte_rx; | ||
1925 | __u32 byte_tx; | ||
1926 | }; | ||
1927 | |||
1928 | struct hci_dev_info { | ||
1929 | __u16 dev_id; | ||
1930 | char name[8]; | ||
1931 | |||
1932 | bdaddr_t bdaddr; | ||
1933 | |||
1934 | __u32 flags; | ||
1935 | __u8 type; | ||
1936 | |||
1937 | __u8 features[8]; | ||
1938 | |||
1939 | __u32 pkt_type; | ||
1940 | __u32 link_policy; | ||
1941 | __u32 link_mode; | ||
1942 | |||
1943 | __u16 acl_mtu; | ||
1944 | __u16 acl_pkts; | ||
1945 | __u16 sco_mtu; | ||
1946 | __u16 sco_pkts; | ||
1947 | |||
1948 | struct hci_dev_stats stat; | ||
1949 | }; | ||
1950 | |||
1951 | struct hci_conn_info { | ||
1952 | __u16 handle; | ||
1953 | bdaddr_t bdaddr; | ||
1954 | __u8 type; | ||
1955 | __u8 out; | ||
1956 | __u16 state; | ||
1957 | __u32 link_mode; | ||
1958 | }; | ||
1959 | |||
1960 | struct hci_dev_req { | ||
1961 | __u16 dev_id; | ||
1962 | __u32 dev_opt; | ||
1963 | }; | ||
1964 | |||
1965 | struct hci_dev_list_req { | ||
1966 | __u16 dev_num; | ||
1967 | struct hci_dev_req dev_req[0]; /* hci_dev_req structures */ | ||
1968 | }; | ||
1969 | |||
1970 | struct hci_conn_list_req { | ||
1971 | __u16 dev_id; | ||
1972 | __u16 conn_num; | ||
1973 | struct hci_conn_info conn_info[0]; | ||
1974 | }; | ||
1975 | |||
1976 | struct hci_conn_info_req { | ||
1977 | bdaddr_t bdaddr; | ||
1978 | __u8 type; | ||
1979 | struct hci_conn_info conn_info[0]; | ||
1980 | }; | ||
1981 | |||
1982 | struct hci_auth_info_req { | ||
1983 | bdaddr_t bdaddr; | ||
1984 | __u8 type; | ||
1985 | }; | ||
1986 | |||
1987 | struct hci_inquiry_req { | ||
1988 | __u16 dev_id; | ||
1989 | __u16 flags; | ||
1990 | __u8 lap[3]; | ||
1991 | __u8 length; | ||
1992 | __u8 num_rsp; | ||
1993 | }; | ||
1994 | #define IREQ_CACHE_FLUSH 0x0001 | ||
1995 | |||
1996 | #endif /* __HCI_H */ | 1848 | #endif /* __HCI_H */ |
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index e69c2b08c0c6..996ed065b6c2 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
@@ -26,6 +26,7 @@ | |||
26 | #define __HCI_CORE_H | 26 | #define __HCI_CORE_H |
27 | 27 | ||
28 | #include <net/bluetooth/hci.h> | 28 | #include <net/bluetooth/hci.h> |
29 | #include <net/bluetooth/hci_sock.h> | ||
29 | 30 | ||
30 | /* HCI priority */ | 31 | /* HCI priority */ |
31 | #define HCI_PRIO_MAX 7 | 32 | #define HCI_PRIO_MAX 7 |
@@ -82,6 +83,7 @@ struct hci_conn_hash { | |||
82 | unsigned int amp_num; | 83 | unsigned int amp_num; |
83 | unsigned int sco_num; | 84 | unsigned int sco_num; |
84 | unsigned int le_num; | 85 | unsigned int le_num; |
86 | unsigned int le_num_slave; | ||
85 | }; | 87 | }; |
86 | 88 | ||
87 | struct bdaddr_list { | 89 | struct bdaddr_list { |
@@ -370,6 +372,7 @@ struct hci_conn { | |||
370 | __u16 state; | 372 | __u16 state; |
371 | __u8 mode; | 373 | __u8 mode; |
372 | __u8 type; | 374 | __u8 type; |
375 | __u8 role; | ||
373 | bool out; | 376 | bool out; |
374 | __u8 attempt; | 377 | __u8 attempt; |
375 | __u8 dev_class[3]; | 378 | __u8 dev_class[3]; |
@@ -539,12 +542,12 @@ enum { | |||
539 | HCI_CONN_POWER_SAVE, | 542 | HCI_CONN_POWER_SAVE, |
540 | HCI_CONN_REMOTE_OOB, | 543 | HCI_CONN_REMOTE_OOB, |
541 | HCI_CONN_FLUSH_KEY, | 544 | HCI_CONN_FLUSH_KEY, |
542 | HCI_CONN_MASTER, | ||
543 | HCI_CONN_ENCRYPT, | 545 | HCI_CONN_ENCRYPT, |
544 | HCI_CONN_AUTH, | 546 | HCI_CONN_AUTH, |
545 | HCI_CONN_SECURE, | 547 | HCI_CONN_SECURE, |
546 | HCI_CONN_FIPS, | 548 | HCI_CONN_FIPS, |
547 | HCI_CONN_STK_ENCRYPT, | 549 | HCI_CONN_STK_ENCRYPT, |
550 | HCI_CONN_AUTH_INITIATOR, | ||
548 | }; | 551 | }; |
549 | 552 | ||
550 | static inline bool hci_conn_ssp_enabled(struct hci_conn *conn) | 553 | static inline bool hci_conn_ssp_enabled(struct hci_conn *conn) |
@@ -574,6 +577,8 @@ static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c) | |||
574 | break; | 577 | break; |
575 | case LE_LINK: | 578 | case LE_LINK: |
576 | h->le_num++; | 579 | h->le_num++; |
580 | if (c->role == HCI_ROLE_SLAVE) | ||
581 | h->le_num_slave++; | ||
577 | break; | 582 | break; |
578 | case SCO_LINK: | 583 | case SCO_LINK: |
579 | case ESCO_LINK: | 584 | case ESCO_LINK: |
@@ -598,6 +603,8 @@ static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c) | |||
598 | break; | 603 | break; |
599 | case LE_LINK: | 604 | case LE_LINK: |
600 | h->le_num--; | 605 | h->le_num--; |
606 | if (c->role == HCI_ROLE_SLAVE) | ||
607 | h->le_num_slave--; | ||
601 | break; | 608 | break; |
602 | case SCO_LINK: | 609 | case SCO_LINK: |
603 | case ESCO_LINK: | 610 | case ESCO_LINK: |
@@ -694,7 +701,8 @@ void hci_disconnect(struct hci_conn *conn, __u8 reason); | |||
694 | bool hci_setup_sync(struct hci_conn *conn, __u16 handle); | 701 | bool hci_setup_sync(struct hci_conn *conn, __u16 handle); |
695 | void hci_sco_setup(struct hci_conn *conn, __u8 status); | 702 | void hci_sco_setup(struct hci_conn *conn, __u8 status); |
696 | 703 | ||
697 | 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); | ||
698 | int hci_conn_del(struct hci_conn *conn); | 706 | int hci_conn_del(struct hci_conn *conn); |
699 | void hci_conn_hash_flush(struct hci_dev *hdev); | 707 | void hci_conn_hash_flush(struct hci_dev *hdev); |
700 | void hci_conn_check_pending(struct hci_dev *hdev); | 708 | void hci_conn_check_pending(struct hci_dev *hdev); |
@@ -706,14 +714,15 @@ struct hci_chan *hci_chan_lookup_handle(struct hci_dev *hdev, __u16 handle); | |||
706 | 714 | ||
707 | 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, |
708 | u8 dst_type, u8 sec_level, u16 conn_timeout, | 716 | u8 dst_type, u8 sec_level, u16 conn_timeout, |
709 | bool master); | 717 | u8 role); |
710 | 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, |
711 | u8 sec_level, u8 auth_type); | 719 | u8 sec_level, u8 auth_type); |
712 | 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, |
713 | __u16 setting); | 721 | __u16 setting); |
714 | int hci_conn_check_link_mode(struct hci_conn *conn); | 722 | int hci_conn_check_link_mode(struct hci_conn *conn); |
715 | 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); |
716 | 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); | ||
717 | int hci_conn_change_link_key(struct hci_conn *conn); | 726 | int hci_conn_change_link_key(struct hci_conn *conn); |
718 | int hci_conn_switch_role(struct hci_conn *conn, __u8 role); | 727 | int hci_conn_switch_role(struct hci_conn *conn, __u8 role); |
719 | 728 | ||
@@ -880,12 +889,12 @@ struct link_key *hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, | |||
880 | bdaddr_t *bdaddr, u8 *val, u8 type, | 889 | bdaddr_t *bdaddr, u8 *val, u8 type, |
881 | u8 pin_len, bool *persistent); | 890 | u8 pin_len, bool *persistent); |
882 | 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, |
883 | bool master); | 892 | u8 role); |
884 | 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, |
885 | u8 addr_type, u8 type, u8 authenticated, | 894 | u8 addr_type, u8 type, u8 authenticated, |
886 | u8 tk[16], u8 enc_size, __le16 ediv, __le64 rand); | 895 | u8 tk[16], u8 enc_size, __le16 ediv, __le64 rand); |
887 | 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, |
888 | u8 addr_type, bool master); | 897 | u8 addr_type, u8 role); |
889 | 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); |
890 | void hci_smp_ltks_clear(struct hci_dev *hdev); | 899 | void hci_smp_ltks_clear(struct hci_dev *hdev); |
891 | 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); |
@@ -1239,6 +1248,7 @@ void hci_req_add(struct hci_request *req, u16 opcode, u32 plen, | |||
1239 | void hci_req_add_ev(struct hci_request *req, u16 opcode, u32 plen, | 1248 | void hci_req_add_ev(struct hci_request *req, u16 opcode, u32 plen, |
1240 | const void *param, u8 event); | 1249 | const void *param, u8 event); |
1241 | void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status); | 1250 | void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status); |
1251 | bool hci_req_pending(struct hci_dev *hdev); | ||
1242 | 1252 | ||
1243 | void hci_req_add_le_scan_disable(struct hci_request *req); | 1253 | void hci_req_add_le_scan_disable(struct hci_request *req); |
1244 | void hci_req_add_le_passive_scan(struct hci_request *req); | 1254 | void hci_req_add_le_passive_scan(struct hci_request *req); |
@@ -1286,10 +1296,8 @@ void mgmt_index_added(struct hci_dev *hdev); | |||
1286 | void mgmt_index_removed(struct hci_dev *hdev); | 1296 | void mgmt_index_removed(struct hci_dev *hdev); |
1287 | void mgmt_set_powered_failed(struct hci_dev *hdev, int err); | 1297 | void mgmt_set_powered_failed(struct hci_dev *hdev, int err); |
1288 | int mgmt_powered(struct hci_dev *hdev, u8 powered); | 1298 | int mgmt_powered(struct hci_dev *hdev, u8 powered); |
1299 | int mgmt_update_adv_data(struct hci_dev *hdev); | ||
1289 | void mgmt_discoverable_timeout(struct hci_dev *hdev); | 1300 | void mgmt_discoverable_timeout(struct hci_dev *hdev); |
1290 | void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable); | ||
1291 | void mgmt_connectable(struct hci_dev *hdev, u8 connectable); | ||
1292 | void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status); | ||
1293 | void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, | 1301 | void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, |
1294 | bool persistent); | 1302 | bool persistent); |
1295 | void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | 1303 | void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, |
@@ -1350,34 +1358,6 @@ void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr, | |||
1350 | void mgmt_reenable_advertising(struct hci_dev *hdev); | 1358 | void mgmt_reenable_advertising(struct hci_dev *hdev); |
1351 | void mgmt_smp_complete(struct hci_conn *conn, bool complete); | 1359 | void mgmt_smp_complete(struct hci_conn *conn, bool complete); |
1352 | 1360 | ||
1353 | /* HCI info for socket */ | ||
1354 | #define hci_pi(sk) ((struct hci_pinfo *) sk) | ||
1355 | |||
1356 | struct hci_pinfo { | ||
1357 | struct bt_sock bt; | ||
1358 | struct hci_dev *hdev; | ||
1359 | struct hci_filter filter; | ||
1360 | __u32 cmsg_mask; | ||
1361 | unsigned short channel; | ||
1362 | }; | ||
1363 | |||
1364 | /* HCI security filter */ | ||
1365 | #define HCI_SFLT_MAX_OGF 5 | ||
1366 | |||
1367 | struct hci_sec_filter { | ||
1368 | __u32 type_mask; | ||
1369 | __u32 event_mask[2]; | ||
1370 | __u32 ocf_mask[HCI_SFLT_MAX_OGF + 1][4]; | ||
1371 | }; | ||
1372 | |||
1373 | /* ----- HCI requests ----- */ | ||
1374 | #define HCI_REQ_DONE 0 | ||
1375 | #define HCI_REQ_PEND 1 | ||
1376 | #define HCI_REQ_CANCELED 2 | ||
1377 | |||
1378 | #define hci_req_lock(d) mutex_lock(&d->req_lock) | ||
1379 | #define hci_req_unlock(d) mutex_unlock(&d->req_lock) | ||
1380 | |||
1381 | u8 hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, u16 latency, | 1361 | u8 hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, u16 latency, |
1382 | u16 to_multiplier); | 1362 | u16 to_multiplier); |
1383 | void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __le64 rand, | 1363 | void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __le64 rand, |
diff --git a/include/net/bluetooth/hci_sock.h b/include/net/bluetooth/hci_sock.h new file mode 100644 index 000000000000..9a46d665c1b5 --- /dev/null +++ b/include/net/bluetooth/hci_sock.h | |||
@@ -0,0 +1,175 @@ | |||
1 | /* | ||
2 | BlueZ - Bluetooth protocol stack for Linux | ||
3 | Copyright (C) 2000-2001 Qualcomm Incorporated | ||
4 | |||
5 | Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com> | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License version 2 as | ||
9 | published by the Free Software Foundation; | ||
10 | |||
11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||
12 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
13 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. | ||
14 | IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY | ||
15 | CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES | ||
16 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
17 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
18 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
19 | |||
20 | ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, | ||
21 | COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS | ||
22 | SOFTWARE IS DISCLAIMED. | ||
23 | */ | ||
24 | |||
25 | #ifndef __HCI_SOCK_H | ||
26 | #define __HCI_SOCK_H | ||
27 | |||
28 | /* Socket options */ | ||
29 | #define HCI_DATA_DIR 1 | ||
30 | #define HCI_FILTER 2 | ||
31 | #define HCI_TIME_STAMP 3 | ||
32 | |||
33 | /* CMSG flags */ | ||
34 | #define HCI_CMSG_DIR 0x0001 | ||
35 | #define HCI_CMSG_TSTAMP 0x0002 | ||
36 | |||
37 | struct sockaddr_hci { | ||
38 | sa_family_t hci_family; | ||
39 | unsigned short hci_dev; | ||
40 | unsigned short hci_channel; | ||
41 | }; | ||
42 | #define HCI_DEV_NONE 0xffff | ||
43 | |||
44 | #define HCI_CHANNEL_RAW 0 | ||
45 | #define HCI_CHANNEL_USER 1 | ||
46 | #define HCI_CHANNEL_MONITOR 2 | ||
47 | #define HCI_CHANNEL_CONTROL 3 | ||
48 | |||
49 | struct hci_filter { | ||
50 | unsigned long type_mask; | ||
51 | unsigned long event_mask[2]; | ||
52 | __le16 opcode; | ||
53 | }; | ||
54 | |||
55 | struct hci_ufilter { | ||
56 | __u32 type_mask; | ||
57 | __u32 event_mask[2]; | ||
58 | __le16 opcode; | ||
59 | }; | ||
60 | |||
61 | #define HCI_FLT_TYPE_BITS 31 | ||
62 | #define HCI_FLT_EVENT_BITS 63 | ||
63 | #define HCI_FLT_OGF_BITS 63 | ||
64 | #define HCI_FLT_OCF_BITS 127 | ||
65 | |||
66 | /* Ioctl defines */ | ||
67 | #define HCIDEVUP _IOW('H', 201, int) | ||
68 | #define HCIDEVDOWN _IOW('H', 202, int) | ||
69 | #define HCIDEVRESET _IOW('H', 203, int) | ||
70 | #define HCIDEVRESTAT _IOW('H', 204, int) | ||
71 | |||
72 | #define HCIGETDEVLIST _IOR('H', 210, int) | ||
73 | #define HCIGETDEVINFO _IOR('H', 211, int) | ||
74 | #define HCIGETCONNLIST _IOR('H', 212, int) | ||
75 | #define HCIGETCONNINFO _IOR('H', 213, int) | ||
76 | #define HCIGETAUTHINFO _IOR('H', 215, int) | ||
77 | |||
78 | #define HCISETRAW _IOW('H', 220, int) | ||
79 | #define HCISETSCAN _IOW('H', 221, int) | ||
80 | #define HCISETAUTH _IOW('H', 222, int) | ||
81 | #define HCISETENCRYPT _IOW('H', 223, int) | ||
82 | #define HCISETPTYPE _IOW('H', 224, int) | ||
83 | #define HCISETLINKPOL _IOW('H', 225, int) | ||
84 | #define HCISETLINKMODE _IOW('H', 226, int) | ||
85 | #define HCISETACLMTU _IOW('H', 227, int) | ||
86 | #define HCISETSCOMTU _IOW('H', 228, int) | ||
87 | |||
88 | #define HCIBLOCKADDR _IOW('H', 230, int) | ||
89 | #define HCIUNBLOCKADDR _IOW('H', 231, int) | ||
90 | |||
91 | #define HCIINQUIRY _IOR('H', 240, int) | ||
92 | |||
93 | /* Ioctl requests structures */ | ||
94 | struct hci_dev_stats { | ||
95 | __u32 err_rx; | ||
96 | __u32 err_tx; | ||
97 | __u32 cmd_tx; | ||
98 | __u32 evt_rx; | ||
99 | __u32 acl_tx; | ||
100 | __u32 acl_rx; | ||
101 | __u32 sco_tx; | ||
102 | __u32 sco_rx; | ||
103 | __u32 byte_rx; | ||
104 | __u32 byte_tx; | ||
105 | }; | ||
106 | |||
107 | struct hci_dev_info { | ||
108 | __u16 dev_id; | ||
109 | char name[8]; | ||
110 | |||
111 | bdaddr_t bdaddr; | ||
112 | |||
113 | __u32 flags; | ||
114 | __u8 type; | ||
115 | |||
116 | __u8 features[8]; | ||
117 | |||
118 | __u32 pkt_type; | ||
119 | __u32 link_policy; | ||
120 | __u32 link_mode; | ||
121 | |||
122 | __u16 acl_mtu; | ||
123 | __u16 acl_pkts; | ||
124 | __u16 sco_mtu; | ||
125 | __u16 sco_pkts; | ||
126 | |||
127 | struct hci_dev_stats stat; | ||
128 | }; | ||
129 | |||
130 | struct hci_conn_info { | ||
131 | __u16 handle; | ||
132 | bdaddr_t bdaddr; | ||
133 | __u8 type; | ||
134 | __u8 out; | ||
135 | __u16 state; | ||
136 | __u32 link_mode; | ||
137 | }; | ||
138 | |||
139 | struct hci_dev_req { | ||
140 | __u16 dev_id; | ||
141 | __u32 dev_opt; | ||
142 | }; | ||
143 | |||
144 | struct hci_dev_list_req { | ||
145 | __u16 dev_num; | ||
146 | struct hci_dev_req dev_req[0]; /* hci_dev_req structures */ | ||
147 | }; | ||
148 | |||
149 | struct hci_conn_list_req { | ||
150 | __u16 dev_id; | ||
151 | __u16 conn_num; | ||
152 | struct hci_conn_info conn_info[0]; | ||
153 | }; | ||
154 | |||
155 | struct hci_conn_info_req { | ||
156 | bdaddr_t bdaddr; | ||
157 | __u8 type; | ||
158 | struct hci_conn_info conn_info[0]; | ||
159 | }; | ||
160 | |||
161 | struct hci_auth_info_req { | ||
162 | bdaddr_t bdaddr; | ||
163 | __u8 type; | ||
164 | }; | ||
165 | |||
166 | struct hci_inquiry_req { | ||
167 | __u16 dev_id; | ||
168 | __u16 flags; | ||
169 | __u8 lap[3]; | ||
170 | __u8 length; | ||
171 | __u8 num_rsp; | ||
172 | }; | ||
173 | #define IREQ_CACHE_FLUSH 0x0001 | ||
174 | |||
175 | #endif /* __HCI_SOCK_H */ | ||
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index e0c6a9abdb62..8df15ad0d43f 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h | |||
@@ -134,9 +134,12 @@ struct l2cap_conninfo { | |||
134 | #define L2CAP_FCS_CRC16 0x01 | 134 | #define L2CAP_FCS_CRC16 0x01 |
135 | 135 | ||
136 | /* L2CAP fixed channels */ | 136 | /* L2CAP fixed channels */ |
137 | #define L2CAP_FC_L2CAP 0x02 | 137 | #define L2CAP_FC_SIG_BREDR 0x02 |
138 | #define L2CAP_FC_CONNLESS 0x04 | 138 | #define L2CAP_FC_CONNLESS 0x04 |
139 | #define L2CAP_FC_A2MP 0x08 | 139 | #define L2CAP_FC_A2MP 0x08 |
140 | #define L2CAP_FC_ATT 0x10 | ||
141 | #define L2CAP_FC_SIG_LE 0x20 | ||
142 | #define L2CAP_FC_SMP_LE 0x40 | ||
140 | 143 | ||
141 | /* L2CAP Control Field bit masks */ | 144 | /* L2CAP Control Field bit masks */ |
142 | #define L2CAP_CTRL_SAR 0xC000 | 145 | #define L2CAP_CTRL_SAR 0xC000 |
@@ -622,11 +625,10 @@ struct l2cap_conn { | |||
622 | 625 | ||
623 | struct delayed_work info_timer; | 626 | struct delayed_work info_timer; |
624 | 627 | ||
625 | spinlock_t lock; | ||
626 | |||
627 | struct sk_buff *rx_skb; | 628 | struct sk_buff *rx_skb; |
628 | __u32 rx_len; | 629 | __u32 rx_len; |
629 | __u8 tx_ident; | 630 | __u8 tx_ident; |
631 | struct mutex ident_lock; | ||
630 | 632 | ||
631 | struct sk_buff_head pending_rx; | 633 | struct sk_buff_head pending_rx; |
632 | struct work_struct pending_rx_work; | 634 | struct work_struct pending_rx_work; |
@@ -903,7 +905,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, | |||
903 | bdaddr_t *dst, u8 dst_type); | 905 | bdaddr_t *dst, u8 dst_type); |
904 | 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); |
905 | void l2cap_chan_busy(struct l2cap_chan *chan, int busy); | 907 | void l2cap_chan_busy(struct l2cap_chan *chan, int busy); |
906 | int l2cap_chan_check_security(struct l2cap_chan *chan); | 908 | int l2cap_chan_check_security(struct l2cap_chan *chan, bool initiator); |
907 | void l2cap_chan_set_defaults(struct l2cap_chan *chan); | 909 | void l2cap_chan_set_defaults(struct l2cap_chan *chan); |
908 | int l2cap_ertm_init(struct l2cap_chan *chan); | 910 | int l2cap_ertm_init(struct l2cap_chan *chan); |
909 | 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/bluetooth/sco.h b/include/net/bluetooth/sco.h index 2019d1a0996a..f40ddb4264fc 100644 --- a/include/net/bluetooth/sco.h +++ b/include/net/bluetooth/sco.h | |||
@@ -27,11 +27,6 @@ | |||
27 | 27 | ||
28 | /* SCO defaults */ | 28 | /* SCO defaults */ |
29 | #define SCO_DEFAULT_MTU 500 | 29 | #define SCO_DEFAULT_MTU 500 |
30 | #define SCO_DEFAULT_FLUSH_TO 0xFFFF | ||
31 | |||
32 | #define SCO_CONN_TIMEOUT (HZ * 40) | ||
33 | #define SCO_DISCONN_TIMEOUT (HZ * 2) | ||
34 | #define SCO_CONN_IDLE_TIMEOUT (HZ * 60) | ||
35 | 30 | ||
36 | /* SCO socket address */ | 31 | /* SCO socket address */ |
37 | struct sockaddr_sco { | 32 | struct sockaddr_sco { |
@@ -51,29 +46,4 @@ struct sco_conninfo { | |||
51 | __u8 dev_class[3]; | 46 | __u8 dev_class[3]; |
52 | }; | 47 | }; |
53 | 48 | ||
54 | /* ---- SCO connections ---- */ | ||
55 | struct sco_conn { | ||
56 | struct hci_conn *hcon; | ||
57 | |||
58 | spinlock_t lock; | ||
59 | struct sock *sk; | ||
60 | |||
61 | unsigned int mtu; | ||
62 | }; | ||
63 | |||
64 | #define sco_conn_lock(c) spin_lock(&c->lock); | ||
65 | #define sco_conn_unlock(c) spin_unlock(&c->lock); | ||
66 | |||
67 | /* ----- SCO socket info ----- */ | ||
68 | #define sco_pi(sk) ((struct sco_pinfo *) sk) | ||
69 | |||
70 | struct sco_pinfo { | ||
71 | struct bt_sock bt; | ||
72 | bdaddr_t src; | ||
73 | bdaddr_t dst; | ||
74 | __u32 flags; | ||
75 | __u16 setting; | ||
76 | struct sco_conn *conn; | ||
77 | }; | ||
78 | |||
79 | #endif /* __SCO_H */ | 49 | #endif /* __SCO_H */ |
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/6lowpan/Kconfig b/net/6lowpan/Kconfig new file mode 100644 index 000000000000..028a5c6d1f61 --- /dev/null +++ b/net/6lowpan/Kconfig | |||
@@ -0,0 +1,6 @@ | |||
1 | config 6LOWPAN | ||
2 | bool "6LoWPAN Support" | ||
3 | depends on IPV6 | ||
4 | ---help--- | ||
5 | This enables IPv6 over Low power Wireless Personal Area Network - | ||
6 | "6LoWPAN" which is supported by IEEE 802.15.4 or Bluetooth stacks. | ||
diff --git a/net/6lowpan/Makefile b/net/6lowpan/Makefile new file mode 100644 index 000000000000..415886bb456a --- /dev/null +++ b/net/6lowpan/Makefile | |||
@@ -0,0 +1,3 @@ | |||
1 | obj-$(CONFIG_6LOWPAN) := 6lowpan.o | ||
2 | |||
3 | 6lowpan-y := iphc.o | ||
diff --git a/net/ieee802154/6lowpan_iphc.c b/net/6lowpan/iphc.c index a1b7117a9600..a1b7117a9600 100644 --- a/net/ieee802154/6lowpan_iphc.c +++ b/net/6lowpan/iphc.c | |||
diff --git a/net/Kconfig b/net/Kconfig index d92afe4204d9..4051fdfa4367 100644 --- a/net/Kconfig +++ b/net/Kconfig | |||
@@ -214,6 +214,7 @@ source "drivers/net/appletalk/Kconfig" | |||
214 | source "net/x25/Kconfig" | 214 | source "net/x25/Kconfig" |
215 | source "net/lapb/Kconfig" | 215 | source "net/lapb/Kconfig" |
216 | source "net/phonet/Kconfig" | 216 | source "net/phonet/Kconfig" |
217 | source "net/6lowpan/Kconfig" | ||
217 | source "net/ieee802154/Kconfig" | 218 | source "net/ieee802154/Kconfig" |
218 | source "net/mac802154/Kconfig" | 219 | source "net/mac802154/Kconfig" |
219 | source "net/sched/Kconfig" | 220 | source "net/sched/Kconfig" |
diff --git a/net/Makefile b/net/Makefile index cbbbe6d657ca..7ed1970074b0 100644 --- a/net/Makefile +++ b/net/Makefile | |||
@@ -57,7 +57,8 @@ obj-$(CONFIG_CAIF) += caif/ | |||
57 | ifneq ($(CONFIG_DCB),) | 57 | ifneq ($(CONFIG_DCB),) |
58 | obj-y += dcb/ | 58 | obj-y += dcb/ |
59 | endif | 59 | endif |
60 | obj-y += ieee802154/ | 60 | obj-$(CONFIG_6LOWPAN) += 6lowpan/ |
61 | obj-$(CONFIG_IEEE802154) += ieee802154/ | ||
61 | obj-$(CONFIG_MAC802154) += mac802154/ | 62 | obj-$(CONFIG_MAC802154) += mac802154/ |
62 | 63 | ||
63 | ifeq ($(CONFIG_NET),y) | 64 | ifeq ($(CONFIG_NET),y) |
diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig index f5afaa22f6ec..600fb29288f4 100644 --- a/net/bluetooth/Kconfig +++ b/net/bluetooth/Kconfig | |||
@@ -41,8 +41,7 @@ menuconfig BT | |||
41 | 41 | ||
42 | config BT_6LOWPAN | 42 | config BT_6LOWPAN |
43 | tristate "Bluetooth 6LoWPAN support" | 43 | tristate "Bluetooth 6LoWPAN support" |
44 | depends on BT && IPV6 | 44 | depends on BT && 6LOWPAN |
45 | select 6LOWPAN_IPHC if BT_6LOWPAN | ||
46 | help | 45 | help |
47 | IPv6 compression over Bluetooth Low Energy. | 46 | IPv6 compression over Bluetooth Low Energy. |
48 | 47 | ||
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/cmtp/capi.c b/net/bluetooth/cmtp/capi.c index cd75e4d64b90..1ca8a87a0787 100644 --- a/net/bluetooth/cmtp/capi.c +++ b/net/bluetooth/cmtp/capi.c | |||
@@ -362,12 +362,6 @@ void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb) | |||
362 | CAPIMSG_SETCONTROL(skb->data, contr); | 362 | CAPIMSG_SETCONTROL(skb->data, contr); |
363 | } | 363 | } |
364 | 364 | ||
365 | if (!ctrl) { | ||
366 | BT_ERR("Can't find controller %d for message", session->num); | ||
367 | kfree_skb(skb); | ||
368 | return; | ||
369 | } | ||
370 | |||
371 | capi_ctr_handle_message(ctrl, appl, skb); | 365 | capi_ctr_handle_message(ctrl, appl, skb); |
372 | } | 366 | } |
373 | 367 | ||
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 84431b86af96..cfcb6055ced8 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -54,6 +54,15 @@ DEFINE_RWLOCK(hci_cb_list_lock); | |||
54 | /* HCI ID Numbering */ | 54 | /* HCI ID Numbering */ |
55 | static DEFINE_IDA(hci_index_ida); | 55 | static DEFINE_IDA(hci_index_ida); |
56 | 56 | ||
57 | /* ----- HCI requests ----- */ | ||
58 | |||
59 | #define HCI_REQ_DONE 0 | ||
60 | #define HCI_REQ_PEND 1 | ||
61 | #define HCI_REQ_CANCELED 2 | ||
62 | |||
63 | #define hci_req_lock(d) mutex_lock(&d->req_lock) | ||
64 | #define hci_req_unlock(d) mutex_unlock(&d->req_lock) | ||
65 | |||
57 | /* ---- HCI notifications ---- */ | 66 | /* ---- HCI notifications ---- */ |
58 | 67 | ||
59 | static void hci_notify(struct hci_dev *hdev, int event) | 68 | static void hci_notify(struct hci_dev *hdev, int event) |
@@ -1339,9 +1348,6 @@ static void le_setup(struct hci_request *req) | |||
1339 | /* Read LE Supported States */ | 1348 | /* Read LE Supported States */ |
1340 | hci_req_add(req, HCI_OP_LE_READ_SUPPORTED_STATES, 0, NULL); | 1349 | hci_req_add(req, HCI_OP_LE_READ_SUPPORTED_STATES, 0, NULL); |
1341 | 1350 | ||
1342 | /* Read LE Advertising Channel TX Power */ | ||
1343 | hci_req_add(req, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL); | ||
1344 | |||
1345 | /* Read LE White List Size */ | 1351 | /* Read LE White List Size */ |
1346 | hci_req_add(req, HCI_OP_LE_READ_WHITE_LIST_SIZE, 0, NULL); | 1352 | hci_req_add(req, HCI_OP_LE_READ_WHITE_LIST_SIZE, 0, NULL); |
1347 | 1353 | ||
@@ -1416,14 +1422,17 @@ static void hci_setup_event_mask(struct hci_request *req) | |||
1416 | /* Use a different default for LE-only devices */ | 1422 | /* Use a different default for LE-only devices */ |
1417 | memset(events, 0, sizeof(events)); | 1423 | memset(events, 0, sizeof(events)); |
1418 | events[0] |= 0x10; /* Disconnection Complete */ | 1424 | events[0] |= 0x10; /* Disconnection Complete */ |
1419 | events[0] |= 0x80; /* Encryption Change */ | ||
1420 | events[1] |= 0x08; /* Read Remote Version Information Complete */ | 1425 | events[1] |= 0x08; /* Read Remote Version Information Complete */ |
1421 | events[1] |= 0x20; /* Command Complete */ | 1426 | events[1] |= 0x20; /* Command Complete */ |
1422 | events[1] |= 0x40; /* Command Status */ | 1427 | events[1] |= 0x40; /* Command Status */ |
1423 | events[1] |= 0x80; /* Hardware Error */ | 1428 | events[1] |= 0x80; /* Hardware Error */ |
1424 | events[2] |= 0x04; /* Number of Completed Packets */ | 1429 | events[2] |= 0x04; /* Number of Completed Packets */ |
1425 | events[3] |= 0x02; /* Data Buffer Overflow */ | 1430 | events[3] |= 0x02; /* Data Buffer Overflow */ |
1426 | events[5] |= 0x80; /* Encryption Key Refresh Complete */ | 1431 | |
1432 | if (hdev->le_features[0] & HCI_LE_ENCRYPTION) { | ||
1433 | events[0] |= 0x80; /* Encryption Change */ | ||
1434 | events[5] |= 0x80; /* Encryption Key Refresh Complete */ | ||
1435 | } | ||
1427 | } | 1436 | } |
1428 | 1437 | ||
1429 | if (lmp_inq_rssi_capable(hdev)) | 1438 | if (lmp_inq_rssi_capable(hdev)) |
@@ -1476,8 +1485,6 @@ static void hci_init2_req(struct hci_request *req, unsigned long opt) | |||
1476 | if (lmp_le_capable(hdev)) | 1485 | if (lmp_le_capable(hdev)) |
1477 | le_setup(req); | 1486 | le_setup(req); |
1478 | 1487 | ||
1479 | hci_setup_event_mask(req); | ||
1480 | |||
1481 | /* AVM Berlin (31), aka "BlueFRITZ!", doesn't support the read | 1488 | /* AVM Berlin (31), aka "BlueFRITZ!", doesn't support the read |
1482 | * local supported commands HCI command. | 1489 | * local supported commands HCI command. |
1483 | */ | 1490 | */ |
@@ -1605,6 +1612,8 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt) | |||
1605 | struct hci_dev *hdev = req->hdev; | 1612 | struct hci_dev *hdev = req->hdev; |
1606 | u8 p; | 1613 | u8 p; |
1607 | 1614 | ||
1615 | hci_setup_event_mask(req); | ||
1616 | |||
1608 | /* Some Broadcom based Bluetooth controllers do not support the | 1617 | /* Some Broadcom based Bluetooth controllers do not support the |
1609 | * Delete Stored Link Key command. They are clearly indicating its | 1618 | * Delete Stored Link Key command. They are clearly indicating its |
1610 | * absence in the bit mask of supported commands. | 1619 | * absence in the bit mask of supported commands. |
@@ -1635,7 +1644,10 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt) | |||
1635 | u8 events[8]; | 1644 | u8 events[8]; |
1636 | 1645 | ||
1637 | memset(events, 0, sizeof(events)); | 1646 | memset(events, 0, sizeof(events)); |
1638 | events[0] = 0x1f; | 1647 | events[0] = 0x0f; |
1648 | |||
1649 | if (hdev->le_features[0] & HCI_LE_ENCRYPTION) | ||
1650 | events[0] |= 0x10; /* LE Long Term Key Request */ | ||
1639 | 1651 | ||
1640 | /* If controller supports the Connection Parameters Request | 1652 | /* If controller supports the Connection Parameters Request |
1641 | * Link Layer Procedure, enable the corresponding event. | 1653 | * Link Layer Procedure, enable the corresponding event. |
@@ -1648,6 +1660,11 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt) | |||
1648 | hci_req_add(req, HCI_OP_LE_SET_EVENT_MASK, sizeof(events), | 1660 | hci_req_add(req, HCI_OP_LE_SET_EVENT_MASK, sizeof(events), |
1649 | events); | 1661 | events); |
1650 | 1662 | ||
1663 | if (hdev->commands[25] & 0x40) { | ||
1664 | /* Read LE Advertising Channel TX Power */ | ||
1665 | hci_req_add(req, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL); | ||
1666 | } | ||
1667 | |||
1651 | hci_set_le_support(req); | 1668 | hci_set_le_support(req); |
1652 | } | 1669 | } |
1653 | 1670 | ||
@@ -2071,7 +2088,7 @@ u32 hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data, | |||
2071 | } | 2088 | } |
2072 | 2089 | ||
2073 | /* Entry not in the cache. Add new one. */ | 2090 | /* Entry not in the cache. Add new one. */ |
2074 | ie = kzalloc(sizeof(struct inquiry_entry), GFP_ATOMIC); | 2091 | ie = kzalloc(sizeof(*ie), GFP_KERNEL); |
2075 | if (!ie) { | 2092 | if (!ie) { |
2076 | flags |= MGMT_DEV_FOUND_CONFIRM_NAME; | 2093 | flags |= MGMT_DEV_FOUND_CONFIRM_NAME; |
2077 | goto done; | 2094 | goto done; |
@@ -2435,6 +2452,16 @@ int hci_dev_open(__u16 dev) | |||
2435 | */ | 2452 | */ |
2436 | flush_workqueue(hdev->req_workqueue); | 2453 | flush_workqueue(hdev->req_workqueue); |
2437 | 2454 | ||
2455 | /* For controllers not using the management interface and that | ||
2456 | * are brought up using legacy ioctl, set the HCI_PAIRABLE bit | ||
2457 | * so that pairing works for them. Once the management interface | ||
2458 | * is in use this bit will be cleared again and userspace has | ||
2459 | * to explicitly enable it. | ||
2460 | */ | ||
2461 | if (!test_bit(HCI_USER_CHANNEL, &hdev->dev_flags) && | ||
2462 | !test_bit(HCI_MGMT, &hdev->dev_flags)) | ||
2463 | set_bit(HCI_PAIRABLE, &hdev->dev_flags); | ||
2464 | |||
2438 | err = hci_dev_do_open(hdev); | 2465 | err = hci_dev_do_open(hdev); |
2439 | 2466 | ||
2440 | done: | 2467 | done: |
@@ -2655,6 +2682,42 @@ done: | |||
2655 | return ret; | 2682 | return ret; |
2656 | } | 2683 | } |
2657 | 2684 | ||
2685 | static void hci_update_scan_state(struct hci_dev *hdev, u8 scan) | ||
2686 | { | ||
2687 | bool conn_changed, discov_changed; | ||
2688 | |||
2689 | BT_DBG("%s scan 0x%02x", hdev->name, scan); | ||
2690 | |||
2691 | if ((scan & SCAN_PAGE)) | ||
2692 | conn_changed = !test_and_set_bit(HCI_CONNECTABLE, | ||
2693 | &hdev->dev_flags); | ||
2694 | else | ||
2695 | conn_changed = test_and_clear_bit(HCI_CONNECTABLE, | ||
2696 | &hdev->dev_flags); | ||
2697 | |||
2698 | if ((scan & SCAN_INQUIRY)) { | ||
2699 | discov_changed = !test_and_set_bit(HCI_DISCOVERABLE, | ||
2700 | &hdev->dev_flags); | ||
2701 | } else { | ||
2702 | clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags); | ||
2703 | discov_changed = test_and_clear_bit(HCI_DISCOVERABLE, | ||
2704 | &hdev->dev_flags); | ||
2705 | } | ||
2706 | |||
2707 | if (!test_bit(HCI_MGMT, &hdev->dev_flags)) | ||
2708 | return; | ||
2709 | |||
2710 | if (conn_changed || discov_changed) { | ||
2711 | /* In case this was disabled through mgmt */ | ||
2712 | set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags); | ||
2713 | |||
2714 | if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) | ||
2715 | mgmt_update_adv_data(hdev); | ||
2716 | |||
2717 | mgmt_new_settings(hdev); | ||
2718 | } | ||
2719 | } | ||
2720 | |||
2658 | int hci_dev_cmd(unsigned int cmd, void __user *arg) | 2721 | int hci_dev_cmd(unsigned int cmd, void __user *arg) |
2659 | { | 2722 | { |
2660 | struct hci_dev *hdev; | 2723 | struct hci_dev *hdev; |
@@ -2716,22 +2779,11 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg) | |||
2716 | err = hci_req_sync(hdev, hci_scan_req, dr.dev_opt, | 2779 | err = hci_req_sync(hdev, hci_scan_req, dr.dev_opt, |
2717 | HCI_INIT_TIMEOUT); | 2780 | HCI_INIT_TIMEOUT); |
2718 | 2781 | ||
2719 | /* Ensure that the connectable state gets correctly | 2782 | /* Ensure that the connectable and discoverable states |
2720 | * notified if the whitelist is in use. | 2783 | * get correctly modified as this was a non-mgmt change. |
2721 | */ | 2784 | */ |
2722 | if (!err && !list_empty(&hdev->whitelist)) { | 2785 | if (!err) |
2723 | bool changed; | 2786 | hci_update_scan_state(hdev, dr.dev_opt); |
2724 | |||
2725 | if ((dr.dev_opt & SCAN_PAGE)) | ||
2726 | changed = !test_and_set_bit(HCI_CONNECTABLE, | ||
2727 | &hdev->dev_flags); | ||
2728 | else | ||
2729 | changed = test_and_set_bit(HCI_CONNECTABLE, | ||
2730 | &hdev->dev_flags); | ||
2731 | |||
2732 | if (changed) | ||
2733 | mgmt_new_settings(hdev); | ||
2734 | } | ||
2735 | break; | 2787 | break; |
2736 | 2788 | ||
2737 | case HCISETLINKPOL: | 2789 | case HCISETLINKPOL: |
@@ -2792,14 +2844,17 @@ int hci_get_dev_list(void __user *arg) | |||
2792 | 2844 | ||
2793 | read_lock(&hci_dev_list_lock); | 2845 | read_lock(&hci_dev_list_lock); |
2794 | list_for_each_entry(hdev, &hci_dev_list, list) { | 2846 | list_for_each_entry(hdev, &hci_dev_list, list) { |
2795 | if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) | 2847 | unsigned long flags = hdev->flags; |
2796 | cancel_delayed_work(&hdev->power_off); | ||
2797 | 2848 | ||
2798 | if (!test_bit(HCI_MGMT, &hdev->dev_flags)) | 2849 | /* When the auto-off is configured it means the transport |
2799 | set_bit(HCI_PAIRABLE, &hdev->dev_flags); | 2850 | * is running, but in that case still indicate that the |
2851 | * device is actually down. | ||
2852 | */ | ||
2853 | if (test_bit(HCI_AUTO_OFF, &hdev->dev_flags)) | ||
2854 | flags &= ~BIT(HCI_UP); | ||
2800 | 2855 | ||
2801 | (dr + n)->dev_id = hdev->id; | 2856 | (dr + n)->dev_id = hdev->id; |
2802 | (dr + n)->dev_opt = hdev->flags; | 2857 | (dr + n)->dev_opt = flags; |
2803 | 2858 | ||
2804 | if (++n >= dev_num) | 2859 | if (++n >= dev_num) |
2805 | break; | 2860 | break; |
@@ -2819,6 +2874,7 @@ int hci_get_dev_info(void __user *arg) | |||
2819 | { | 2874 | { |
2820 | struct hci_dev *hdev; | 2875 | struct hci_dev *hdev; |
2821 | struct hci_dev_info di; | 2876 | struct hci_dev_info di; |
2877 | unsigned long flags; | ||
2822 | int err = 0; | 2878 | int err = 0; |
2823 | 2879 | ||
2824 | if (copy_from_user(&di, arg, sizeof(di))) | 2880 | if (copy_from_user(&di, arg, sizeof(di))) |
@@ -2828,16 +2884,19 @@ int hci_get_dev_info(void __user *arg) | |||
2828 | if (!hdev) | 2884 | if (!hdev) |
2829 | return -ENODEV; | 2885 | return -ENODEV; |
2830 | 2886 | ||
2831 | if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) | 2887 | /* When the auto-off is configured it means the transport |
2832 | cancel_delayed_work_sync(&hdev->power_off); | 2888 | * is running, but in that case still indicate that the |
2833 | 2889 | * device is actually down. | |
2834 | if (!test_bit(HCI_MGMT, &hdev->dev_flags)) | 2890 | */ |
2835 | set_bit(HCI_PAIRABLE, &hdev->dev_flags); | 2891 | if (test_bit(HCI_AUTO_OFF, &hdev->dev_flags)) |
2892 | flags = hdev->flags & ~BIT(HCI_UP); | ||
2893 | else | ||
2894 | flags = hdev->flags; | ||
2836 | 2895 | ||
2837 | strcpy(di.name, hdev->name); | 2896 | strcpy(di.name, hdev->name); |
2838 | di.bdaddr = hdev->bdaddr; | 2897 | di.bdaddr = hdev->bdaddr; |
2839 | di.type = (hdev->bus & 0x0f) | ((hdev->dev_type & 0x03) << 4); | 2898 | di.type = (hdev->bus & 0x0f) | ((hdev->dev_type & 0x03) << 4); |
2840 | di.flags = hdev->flags; | 2899 | di.flags = flags; |
2841 | di.pkt_type = hdev->pkt_type; | 2900 | di.pkt_type = hdev->pkt_type; |
2842 | if (lmp_bredr_capable(hdev)) { | 2901 | if (lmp_bredr_capable(hdev)) { |
2843 | di.acl_mtu = hdev->acl_mtu; | 2902 | di.acl_mtu = hdev->acl_mtu; |
@@ -3062,13 +3121,16 @@ static bool hci_persistent_key(struct hci_dev *hdev, struct hci_conn *conn, | |||
3062 | return false; | 3121 | return false; |
3063 | } | 3122 | } |
3064 | 3123 | ||
3065 | static bool ltk_type_master(u8 type) | 3124 | static u8 ltk_role(u8 type) |
3066 | { | 3125 | { |
3067 | return (type == SMP_LTK); | 3126 | if (type == SMP_LTK) |
3127 | return HCI_ROLE_MASTER; | ||
3128 | |||
3129 | return HCI_ROLE_SLAVE; | ||
3068 | } | 3130 | } |
3069 | 3131 | ||
3070 | 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, |
3071 | bool master) | 3133 | u8 role) |
3072 | { | 3134 | { |
3073 | struct smp_ltk *k; | 3135 | struct smp_ltk *k; |
3074 | 3136 | ||
@@ -3076,7 +3138,7 @@ struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, __le64 rand, | |||
3076 | if (k->ediv != ediv || k->rand != rand) | 3138 | if (k->ediv != ediv || k->rand != rand) |
3077 | continue; | 3139 | continue; |
3078 | 3140 | ||
3079 | if (ltk_type_master(k->type) != master) | 3141 | if (ltk_role(k->type) != role) |
3080 | continue; | 3142 | continue; |
3081 | 3143 | ||
3082 | return k; | 3144 | return k; |
@@ -3086,14 +3148,14 @@ struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, __le64 rand, | |||
3086 | } | 3148 | } |
3087 | 3149 | ||
3088 | 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, |
3089 | u8 addr_type, bool master) | 3151 | u8 addr_type, u8 role) |
3090 | { | 3152 | { |
3091 | struct smp_ltk *k; | 3153 | struct smp_ltk *k; |
3092 | 3154 | ||
3093 | list_for_each_entry(k, &hdev->long_term_keys, list) | 3155 | list_for_each_entry(k, &hdev->long_term_keys, list) |
3094 | if (addr_type == k->bdaddr_type && | 3156 | if (addr_type == k->bdaddr_type && |
3095 | bacmp(bdaddr, &k->bdaddr) == 0 && | 3157 | bacmp(bdaddr, &k->bdaddr) == 0 && |
3096 | ltk_type_master(k->type) == master) | 3158 | ltk_role(k->type) == role) |
3097 | return k; | 3159 | return k; |
3098 | 3160 | ||
3099 | return NULL; | 3161 | return NULL; |
@@ -3188,9 +3250,9 @@ struct smp_ltk *hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, | |||
3188 | u8 tk[16], u8 enc_size, __le16 ediv, __le64 rand) | 3250 | u8 tk[16], u8 enc_size, __le16 ediv, __le64 rand) |
3189 | { | 3251 | { |
3190 | struct smp_ltk *key, *old_key; | 3252 | struct smp_ltk *key, *old_key; |
3191 | bool master = ltk_type_master(type); | 3253 | u8 role = ltk_role(type); |
3192 | 3254 | ||
3193 | 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); |
3194 | if (old_key) | 3256 | if (old_key) |
3195 | key = old_key; | 3257 | key = old_key; |
3196 | else { | 3258 | else { |
@@ -3430,7 +3492,7 @@ int hci_bdaddr_list_add(struct list_head *list, bdaddr_t *bdaddr, u8 type) | |||
3430 | if (hci_bdaddr_list_lookup(list, bdaddr, type)) | 3492 | if (hci_bdaddr_list_lookup(list, bdaddr, type)) |
3431 | return -EEXIST; | 3493 | return -EEXIST; |
3432 | 3494 | ||
3433 | entry = kzalloc(sizeof(struct bdaddr_list), GFP_KERNEL); | 3495 | entry = kzalloc(sizeof(*entry), GFP_KERNEL); |
3434 | if (!entry) | 3496 | if (!entry) |
3435 | return -ENOMEM; | 3497 | return -ENOMEM; |
3436 | 3498 | ||
@@ -3835,7 +3897,7 @@ struct hci_dev *hci_alloc_dev(void) | |||
3835 | { | 3897 | { |
3836 | struct hci_dev *hdev; | 3898 | struct hci_dev *hdev; |
3837 | 3899 | ||
3838 | hdev = kzalloc(sizeof(struct hci_dev), GFP_KERNEL); | 3900 | hdev = kzalloc(sizeof(*hdev), GFP_KERNEL); |
3839 | if (!hdev) | 3901 | if (!hdev) |
3840 | return NULL; | 3902 | return NULL; |
3841 | 3903 | ||
@@ -4390,6 +4452,11 @@ int hci_req_run(struct hci_request *req, hci_req_complete_t complete) | |||
4390 | return 0; | 4452 | return 0; |
4391 | } | 4453 | } |
4392 | 4454 | ||
4455 | bool hci_req_pending(struct hci_dev *hdev) | ||
4456 | { | ||
4457 | return (hdev->req_status == HCI_REQ_PEND); | ||
4458 | } | ||
4459 | |||
4393 | static struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode, | 4460 | static struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode, |
4394 | u32 plen, const void *param) | 4461 | u32 plen, const void *param) |
4395 | { | 4462 | { |
@@ -5398,8 +5465,7 @@ void hci_update_background_scan(struct hci_dev *hdev) | |||
5398 | 5465 | ||
5399 | hci_req_init(&req, hdev); | 5466 | hci_req_init(&req, hdev); |
5400 | 5467 | ||
5401 | if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags) && | 5468 | if (list_empty(&hdev->pend_le_conns) && |
5402 | list_empty(&hdev->pend_le_conns) && | ||
5403 | list_empty(&hdev->pend_le_reports)) { | 5469 | list_empty(&hdev->pend_le_reports)) { |
5404 | /* If there is no pending LE connections or devices | 5470 | /* If there is no pending LE connections or devices |
5405 | * 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 c8ae9ee3cb12..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 | } |
@@ -296,7 +292,6 @@ static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) | |||
296 | { | 292 | { |
297 | __u8 status = *((__u8 *) skb->data); | 293 | __u8 status = *((__u8 *) skb->data); |
298 | __u8 param; | 294 | __u8 param; |
299 | int old_pscan, old_iscan; | ||
300 | void *sent; | 295 | void *sent; |
301 | 296 | ||
302 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | 297 | BT_DBG("%s status 0x%2.2x", hdev->name, status); |
@@ -310,32 +305,19 @@ static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) | |||
310 | hci_dev_lock(hdev); | 305 | hci_dev_lock(hdev); |
311 | 306 | ||
312 | if (status) { | 307 | if (status) { |
313 | mgmt_write_scan_failed(hdev, param, status); | ||
314 | hdev->discov_timeout = 0; | 308 | hdev->discov_timeout = 0; |
315 | goto done; | 309 | goto done; |
316 | } | 310 | } |
317 | 311 | ||
318 | /* We need to ensure that we set this back on if someone changed | 312 | if (param & SCAN_INQUIRY) |
319 | * the scan mode through a raw HCI socket. | ||
320 | */ | ||
321 | set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags); | ||
322 | |||
323 | old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags); | ||
324 | old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags); | ||
325 | |||
326 | if (param & SCAN_INQUIRY) { | ||
327 | set_bit(HCI_ISCAN, &hdev->flags); | 313 | set_bit(HCI_ISCAN, &hdev->flags); |
328 | if (!old_iscan) | 314 | else |
329 | mgmt_discoverable(hdev, 1); | 315 | clear_bit(HCI_ISCAN, &hdev->flags); |
330 | } else if (old_iscan) | ||
331 | mgmt_discoverable(hdev, 0); | ||
332 | 316 | ||
333 | if (param & SCAN_PAGE) { | 317 | if (param & SCAN_PAGE) |
334 | set_bit(HCI_PSCAN, &hdev->flags); | 318 | set_bit(HCI_PSCAN, &hdev->flags); |
335 | if (!old_pscan) | 319 | else |
336 | mgmt_connectable(hdev, 1); | 320 | clear_bit(HCI_ISCAN, &hdev->flags); |
337 | } else if (old_pscan) | ||
338 | mgmt_connectable(hdev, 0); | ||
339 | 321 | ||
340 | done: | 322 | done: |
341 | hci_dev_unlock(hdev); | 323 | hci_dev_unlock(hdev); |
@@ -1432,11 +1414,9 @@ static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) | |||
1432 | } | 1414 | } |
1433 | } else { | 1415 | } else { |
1434 | if (!conn) { | 1416 | if (!conn) { |
1435 | conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr); | 1417 | conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr, |
1436 | if (conn) { | 1418 | HCI_ROLE_MASTER); |
1437 | conn->out = true; | 1419 | if (!conn) |
1438 | set_bit(HCI_CONN_MASTER, &conn->flags); | ||
1439 | } else | ||
1440 | BT_ERR("No memory for new connection"); | 1420 | BT_ERR("No memory for new connection"); |
1441 | } | 1421 | } |
1442 | } | 1422 | } |
@@ -1665,6 +1645,8 @@ static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) | |||
1665 | if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { | 1645 | if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { |
1666 | struct hci_cp_auth_requested auth_cp; | 1646 | struct hci_cp_auth_requested auth_cp; |
1667 | 1647 | ||
1648 | set_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags); | ||
1649 | |||
1668 | auth_cp.handle = __cpu_to_le16(conn->handle); | 1650 | auth_cp.handle = __cpu_to_le16(conn->handle); |
1669 | hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, | 1651 | hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, |
1670 | sizeof(auth_cp), &auth_cp); | 1652 | sizeof(auth_cp), &auth_cp); |
@@ -2149,18 +2131,17 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2149 | return; | 2131 | return; |
2150 | } | 2132 | } |
2151 | 2133 | ||
2152 | if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) { | 2134 | if (hci_bdaddr_list_lookup(&hdev->blacklist, &ev->bdaddr, |
2153 | if (hci_bdaddr_list_lookup(&hdev->blacklist, &ev->bdaddr, | 2135 | BDADDR_BREDR)) { |
2154 | BDADDR_BREDR)) { | 2136 | hci_reject_conn(hdev, &ev->bdaddr); |
2155 | hci_reject_conn(hdev, &ev->bdaddr); | 2137 | return; |
2156 | return; | 2138 | } |
2157 | } | 2139 | |
2158 | } else { | 2140 | if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags) && |
2159 | if (!hci_bdaddr_list_lookup(&hdev->whitelist, &ev->bdaddr, | 2141 | !hci_bdaddr_list_lookup(&hdev->whitelist, &ev->bdaddr, |
2160 | BDADDR_BREDR)) { | 2142 | BDADDR_BREDR)) { |
2161 | hci_reject_conn(hdev, &ev->bdaddr); | 2143 | hci_reject_conn(hdev, &ev->bdaddr); |
2162 | return; | 2144 | return; |
2163 | } | ||
2164 | } | 2145 | } |
2165 | 2146 | ||
2166 | /* Connection accepted */ | 2147 | /* Connection accepted */ |
@@ -2174,7 +2155,8 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2174 | conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, | 2155 | conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, |
2175 | &ev->bdaddr); | 2156 | &ev->bdaddr); |
2176 | if (!conn) { | 2157 | if (!conn) { |
2177 | 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); | ||
2178 | if (!conn) { | 2160 | if (!conn) { |
2179 | BT_ERR("No memory for new connection"); | 2161 | BT_ERR("No memory for new connection"); |
2180 | hci_dev_unlock(hdev); | 2162 | hci_dev_unlock(hdev); |
@@ -2407,6 +2389,9 @@ check_auth: | |||
2407 | 2389 | ||
2408 | if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { | 2390 | if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { |
2409 | struct hci_cp_auth_requested cp; | 2391 | struct hci_cp_auth_requested cp; |
2392 | |||
2393 | set_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags); | ||
2394 | |||
2410 | cp.handle = __cpu_to_le16(conn->handle); | 2395 | cp.handle = __cpu_to_le16(conn->handle); |
2411 | hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); | 2396 | hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); |
2412 | } | 2397 | } |
@@ -2938,12 +2923,8 @@ static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2938 | 2923 | ||
2939 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); | 2924 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); |
2940 | if (conn) { | 2925 | if (conn) { |
2941 | if (!ev->status) { | 2926 | if (!ev->status) |
2942 | if (ev->role) | 2927 | conn->role = ev->role; |
2943 | clear_bit(HCI_CONN_MASTER, &conn->flags); | ||
2944 | else | ||
2945 | set_bit(HCI_CONN_MASTER, &conn->flags); | ||
2946 | } | ||
2947 | 2928 | ||
2948 | clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags); | 2929 | clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags); |
2949 | 2930 | ||
@@ -3137,10 +3118,11 @@ static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
3137 | hci_conn_drop(conn); | 3118 | hci_conn_drop(conn); |
3138 | } | 3119 | } |
3139 | 3120 | ||
3140 | 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)) { | ||
3141 | hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, | 3123 | hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, |
3142 | sizeof(ev->bdaddr), &ev->bdaddr); | 3124 | sizeof(ev->bdaddr), &ev->bdaddr); |
3143 | else if (test_bit(HCI_MGMT, &hdev->dev_flags)) { | 3125 | } else if (test_bit(HCI_MGMT, &hdev->dev_flags)) { |
3144 | u8 secure; | 3126 | u8 secure; |
3145 | 3127 | ||
3146 | if (conn->pending_sec_level == BT_SECURITY_HIGH) | 3128 | if (conn->pending_sec_level == BT_SECURITY_HIGH) |
@@ -3666,7 +3648,11 @@ static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
3666 | if (!test_bit(HCI_MGMT, &hdev->dev_flags)) | 3648 | if (!test_bit(HCI_MGMT, &hdev->dev_flags)) |
3667 | goto unlock; | 3649 | goto unlock; |
3668 | 3650 | ||
3651 | /* Allow pairing if we're pairable, the initiators of the | ||
3652 | * pairing or if the remote is not requesting bonding. | ||
3653 | */ | ||
3669 | 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) || | ||
3670 | (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { | 3656 | (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { |
3671 | struct hci_cp_io_capability_reply cp; | 3657 | struct hci_cp_io_capability_reply cp; |
3672 | 3658 | ||
@@ -3678,18 +3664,14 @@ static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
3678 | 3664 | ||
3679 | /* If we are initiators, there is no remote information yet */ | 3665 | /* If we are initiators, there is no remote information yet */ |
3680 | if (conn->remote_auth == 0xff) { | 3666 | if (conn->remote_auth == 0xff) { |
3681 | cp.authentication = conn->auth_type; | ||
3682 | |||
3683 | /* Request MITM protection if our IO caps allow it | 3667 | /* Request MITM protection if our IO caps allow it |
3684 | * except for the no-bonding case. | 3668 | * except for the no-bonding case. |
3685 | * conn->auth_type is not updated here since | ||
3686 | * that might cause the user confirmation to be | ||
3687 | * rejected in case the remote doesn't have the | ||
3688 | * IO capabilities for MITM. | ||
3689 | */ | 3669 | */ |
3690 | if (conn->io_capability != HCI_IO_NO_INPUT_OUTPUT && | 3670 | if (conn->io_capability != HCI_IO_NO_INPUT_OUTPUT && |
3691 | cp.authentication != HCI_AT_NO_BONDING) | 3671 | conn->auth_type != HCI_AT_NO_BONDING) |
3692 | cp.authentication |= 0x01; | 3672 | conn->auth_type |= 0x01; |
3673 | |||
3674 | cp.authentication = conn->auth_type; | ||
3693 | } else { | 3675 | } else { |
3694 | conn->auth_type = hci_get_auth_req(conn); | 3676 | conn->auth_type = hci_get_auth_req(conn); |
3695 | cp.authentication = conn->auth_type; | 3677 | cp.authentication = conn->auth_type; |
@@ -3761,9 +3743,12 @@ static void hci_user_confirm_request_evt(struct hci_dev *hdev, | |||
3761 | rem_mitm = (conn->remote_auth & 0x01); | 3743 | rem_mitm = (conn->remote_auth & 0x01); |
3762 | 3744 | ||
3763 | /* If we require MITM but the remote device can't provide that | 3745 | /* If we require MITM but the remote device can't provide that |
3764 | * (it has NoInputNoOutput) then reject the confirmation request | 3746 | * (it has NoInputNoOutput) then reject the confirmation |
3747 | * request. We check the security level here since it doesn't | ||
3748 | * necessarily match conn->auth_type. | ||
3765 | */ | 3749 | */ |
3766 | if (loc_mitm && conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) { | 3750 | if (conn->pending_sec_level > BT_SECURITY_MEDIUM && |
3751 | conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) { | ||
3767 | BT_DBG("Rejecting request: remote device can't provide MITM"); | 3752 | BT_DBG("Rejecting request: remote device can't provide MITM"); |
3768 | hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY, | 3753 | hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY, |
3769 | sizeof(ev->bdaddr), &ev->bdaddr); | 3754 | sizeof(ev->bdaddr), &ev->bdaddr); |
@@ -3777,9 +3762,11 @@ static void hci_user_confirm_request_evt(struct hci_dev *hdev, | |||
3777 | /* If we're not the initiators request authorization to | 3762 | /* If we're not the initiators request authorization to |
3778 | * proceed from user space (mgmt_user_confirm with | 3763 | * proceed from user space (mgmt_user_confirm with |
3779 | * confirm_hint set to 1). The exception is if neither | 3764 | * confirm_hint set to 1). The exception is if neither |
3780 | * 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 | ||
3781 | */ | 3767 | */ |
3782 | 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 && | ||
3783 | (loc_mitm || rem_mitm)) { | 3770 | (loc_mitm || rem_mitm)) { |
3784 | BT_DBG("Confirming auto-accept as acceptor"); | 3771 | BT_DBG("Confirming auto-accept as acceptor"); |
3785 | confirm_hint = 1; | 3772 | confirm_hint = 1; |
@@ -3893,6 +3880,9 @@ static void hci_simple_pair_complete_evt(struct hci_dev *hdev, | |||
3893 | if (!conn) | 3880 | if (!conn) |
3894 | goto unlock; | 3881 | goto unlock; |
3895 | 3882 | ||
3883 | /* Reset the authentication requirement to unknown */ | ||
3884 | conn->remote_auth = 0xff; | ||
3885 | |||
3896 | /* To avoid duplicate auth_failed events to user space we check | 3886 | /* To avoid duplicate auth_failed events to user space we check |
3897 | * 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 |
3898 | * initiated the authentication. A traditional auth_complete | 3888 | * initiated the authentication. A traditional auth_complete |
@@ -4123,7 +4113,7 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
4123 | 4113 | ||
4124 | conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); | 4114 | conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); |
4125 | if (!conn) { | 4115 | if (!conn) { |
4126 | conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); | 4116 | conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr, ev->role); |
4127 | if (!conn) { | 4117 | if (!conn) { |
4128 | BT_ERR("No memory for new connection"); | 4118 | BT_ERR("No memory for new connection"); |
4129 | goto unlock; | 4119 | goto unlock; |
@@ -4131,11 +4121,6 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
4131 | 4121 | ||
4132 | conn->dst_type = ev->bdaddr_type; | 4122 | conn->dst_type = ev->bdaddr_type; |
4133 | 4123 | ||
4134 | if (ev->role == LE_CONN_ROLE_MASTER) { | ||
4135 | conn->out = true; | ||
4136 | set_bit(HCI_CONN_MASTER, &conn->flags); | ||
4137 | } | ||
4138 | |||
4139 | /* If we didn't have a hci_conn object previously | 4124 | /* If we didn't have a hci_conn object previously |
4140 | * but we're in master role this must be something | 4125 | * but we're in master role this must be something |
4141 | * initiated using a white list. Since white list based | 4126 | * initiated using a white list. Since white list based |
@@ -4202,14 +4187,14 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
4202 | else | 4187 | else |
4203 | addr_type = BDADDR_LE_RANDOM; | 4188 | addr_type = BDADDR_LE_RANDOM; |
4204 | 4189 | ||
4205 | /* Drop the connection if he device is blocked */ | 4190 | if (ev->status) { |
4206 | if (hci_bdaddr_list_lookup(&hdev->blacklist, &conn->dst, addr_type)) { | 4191 | hci_le_conn_failed(conn, ev->status); |
4207 | hci_conn_drop(conn); | ||
4208 | goto unlock; | 4192 | goto unlock; |
4209 | } | 4193 | } |
4210 | 4194 | ||
4211 | if (ev->status) { | 4195 | /* Drop the connection if the device is blocked */ |
4212 | hci_le_conn_failed(conn, ev->status); | 4196 | if (hci_bdaddr_list_lookup(&hdev->blacklist, &conn->dst, addr_type)) { |
4197 | hci_conn_drop(conn); | ||
4213 | goto unlock; | 4198 | goto unlock; |
4214 | } | 4199 | } |
4215 | 4200 | ||
@@ -4275,6 +4260,12 @@ static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr, | |||
4275 | if (hci_bdaddr_list_lookup(&hdev->blacklist, addr, addr_type)) | 4260 | if (hci_bdaddr_list_lookup(&hdev->blacklist, addr, addr_type)) |
4276 | return; | 4261 | return; |
4277 | 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 | |||
4278 | /* If we're connectable, always connect any ADV_DIRECT_IND event */ | 4269 | /* If we're connectable, always connect any ADV_DIRECT_IND event */ |
4279 | if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags) && | 4270 | if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags) && |
4280 | adv_type == LE_ADV_DIRECT_IND) | 4271 | adv_type == LE_ADV_DIRECT_IND) |
@@ -4287,9 +4278,8 @@ static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr, | |||
4287 | return; | 4278 | return; |
4288 | 4279 | ||
4289 | connect: | 4280 | connect: |
4290 | /* Request connection in master = true role */ | ||
4291 | conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW, | 4281 | conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW, |
4292 | HCI_LE_AUTOCONN_TIMEOUT, true); | 4282 | HCI_LE_AUTOCONN_TIMEOUT, HCI_ROLE_MASTER); |
4293 | if (!IS_ERR(conn)) | 4283 | if (!IS_ERR(conn)) |
4294 | return; | 4284 | return; |
4295 | 4285 | ||
@@ -4329,14 +4319,11 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr, | |||
4329 | * device found events. | 4319 | * device found events. |
4330 | */ | 4320 | */ |
4331 | if (hdev->le_scan_type == LE_SCAN_PASSIVE) { | 4321 | if (hdev->le_scan_type == LE_SCAN_PASSIVE) { |
4332 | struct hci_conn_params *param; | ||
4333 | |||
4334 | if (type == LE_ADV_DIRECT_IND) | 4322 | if (type == LE_ADV_DIRECT_IND) |
4335 | return; | 4323 | return; |
4336 | 4324 | ||
4337 | param = hci_pend_le_action_lookup(&hdev->pend_le_reports, | 4325 | if (!hci_pend_le_action_lookup(&hdev->pend_le_reports, |
4338 | bdaddr, bdaddr_type); | 4326 | bdaddr, bdaddr_type)) |
4339 | if (!param) | ||
4340 | return; | 4327 | return; |
4341 | 4328 | ||
4342 | if (type == LE_ADV_NONCONN_IND || type == LE_ADV_SCAN_IND) | 4329 | if (type == LE_ADV_NONCONN_IND || type == LE_ADV_SCAN_IND) |
@@ -4470,7 +4457,7 @@ static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
4470 | if (conn == NULL) | 4457 | if (conn == NULL) |
4471 | goto not_found; | 4458 | goto not_found; |
4472 | 4459 | ||
4473 | ltk = hci_find_ltk(hdev, ev->ediv, ev->rand, conn->out); | 4460 | ltk = hci_find_ltk(hdev, ev->ediv, ev->rand, conn->role); |
4474 | if (ltk == NULL) | 4461 | if (ltk == NULL) |
4475 | goto not_found; | 4462 | goto not_found; |
4476 | 4463 | ||
@@ -4545,7 +4532,7 @@ static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev, | |||
4545 | return send_conn_param_neg_reply(hdev, handle, | 4532 | return send_conn_param_neg_reply(hdev, handle, |
4546 | HCI_ERROR_INVALID_LL_PARAMS); | 4533 | HCI_ERROR_INVALID_LL_PARAMS); |
4547 | 4534 | ||
4548 | if (test_bit(HCI_CONN_MASTER, &hcon->flags)) { | 4535 | if (hcon->role == HCI_ROLE_MASTER) { |
4549 | struct hci_conn_params *params; | 4536 | struct hci_conn_params *params; |
4550 | u8 store_hint; | 4537 | u8 store_hint; |
4551 | 4538 | ||
@@ -4638,7 +4625,7 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) | |||
4638 | /* Received events are (currently) only needed when a request is | 4625 | /* Received events are (currently) only needed when a request is |
4639 | * ongoing so avoid unnecessary memory allocation. | 4626 | * ongoing so avoid unnecessary memory allocation. |
4640 | */ | 4627 | */ |
4641 | if (hdev->req_status == HCI_REQ_PEND) { | 4628 | if (hci_req_pending(hdev)) { |
4642 | kfree_skb(hdev->recv_evt); | 4629 | kfree_skb(hdev->recv_evt); |
4643 | hdev->recv_evt = skb_clone(skb, GFP_KERNEL); | 4630 | hdev->recv_evt = skb_clone(skb, GFP_KERNEL); |
4644 | } | 4631 | } |
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index c64728d571ae..115f149362ba 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c | |||
@@ -35,13 +35,32 @@ static atomic_t monitor_promisc = ATOMIC_INIT(0); | |||
35 | 35 | ||
36 | /* ----- HCI socket interface ----- */ | 36 | /* ----- HCI socket interface ----- */ |
37 | 37 | ||
38 | /* Socket info */ | ||
39 | #define hci_pi(sk) ((struct hci_pinfo *) sk) | ||
40 | |||
41 | struct hci_pinfo { | ||
42 | struct bt_sock bt; | ||
43 | struct hci_dev *hdev; | ||
44 | struct hci_filter filter; | ||
45 | __u32 cmsg_mask; | ||
46 | unsigned short channel; | ||
47 | }; | ||
48 | |||
38 | static inline int hci_test_bit(int nr, void *addr) | 49 | static inline int hci_test_bit(int nr, void *addr) |
39 | { | 50 | { |
40 | return *((__u32 *) addr + (nr >> 5)) & ((__u32) 1 << (nr & 31)); | 51 | return *((__u32 *) addr + (nr >> 5)) & ((__u32) 1 << (nr & 31)); |
41 | } | 52 | } |
42 | 53 | ||
43 | /* Security filter */ | 54 | /* Security filter */ |
44 | static struct hci_sec_filter hci_sec_filter = { | 55 | #define HCI_SFLT_MAX_OGF 5 |
56 | |||
57 | struct hci_sec_filter { | ||
58 | __u32 type_mask; | ||
59 | __u32 event_mask[2]; | ||
60 | __u32 ocf_mask[HCI_SFLT_MAX_OGF + 1][4]; | ||
61 | }; | ||
62 | |||
63 | static const struct hci_sec_filter hci_sec_filter = { | ||
45 | /* Packet types */ | 64 | /* Packet types */ |
46 | 0x10, | 65 | 0x10, |
47 | /* Events */ | 66 | /* Events */ |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 8680aae678ce..46547b920f88 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -46,7 +46,7 @@ | |||
46 | bool disable_ertm; | 46 | bool disable_ertm; |
47 | 47 | ||
48 | static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN | L2CAP_FEAT_UCD; | 48 | static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN | L2CAP_FEAT_UCD; |
49 | static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP | L2CAP_FC_CONNLESS, }; | 49 | static u8 l2cap_fixed_chan[8] = { L2CAP_FC_SIG_BREDR | L2CAP_FC_CONNLESS, }; |
50 | 50 | ||
51 | static LIST_HEAD(chan_list); | 51 | static LIST_HEAD(chan_list); |
52 | static DEFINE_RWLOCK(chan_list_lock); | 52 | static DEFINE_RWLOCK(chan_list_lock); |
@@ -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) |
@@ -798,14 +799,14 @@ static u8 l2cap_get_ident(struct l2cap_conn *conn) | |||
798 | * 200 - 254 are used by utilities like l2ping, etc. | 799 | * 200 - 254 are used by utilities like l2ping, etc. |
799 | */ | 800 | */ |
800 | 801 | ||
801 | spin_lock(&conn->lock); | 802 | mutex_lock(&conn->ident_lock); |
802 | 803 | ||
803 | if (++conn->tx_ident > 128) | 804 | if (++conn->tx_ident > 128) |
804 | conn->tx_ident = 1; | 805 | conn->tx_ident = 1; |
805 | 806 | ||
806 | id = conn->tx_ident; | 807 | id = conn->tx_ident; |
807 | 808 | ||
808 | spin_unlock(&conn->lock); | 809 | mutex_unlock(&conn->ident_lock); |
809 | 810 | ||
810 | return id; | 811 | return id; |
811 | } | 812 | } |
@@ -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; |
@@ -7016,7 +7017,7 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon) | |||
7016 | conn->hs_enabled = test_bit(HCI_HS_ENABLED, | 7017 | conn->hs_enabled = test_bit(HCI_HS_ENABLED, |
7017 | &hcon->hdev->dev_flags); | 7018 | &hcon->hdev->dev_flags); |
7018 | 7019 | ||
7019 | spin_lock_init(&conn->lock); | 7020 | mutex_init(&conn->ident_lock); |
7020 | mutex_init(&conn->chan_lock); | 7021 | mutex_init(&conn->chan_lock); |
7021 | 7022 | ||
7022 | INIT_LIST_HEAD(&conn->chan_l); | 7023 | INIT_LIST_HEAD(&conn->chan_l); |
@@ -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 91b1f92c681e..190668367e42 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -906,6 +906,16 @@ static void update_adv_data(struct hci_request *req) | |||
906 | hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp); | 906 | hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp); |
907 | } | 907 | } |
908 | 908 | ||
909 | int mgmt_update_adv_data(struct hci_dev *hdev) | ||
910 | { | ||
911 | struct hci_request req; | ||
912 | |||
913 | hci_req_init(&req, hdev); | ||
914 | update_adv_data(&req); | ||
915 | |||
916 | return hci_req_run(&req, NULL); | ||
917 | } | ||
918 | |||
909 | static void create_eir(struct hci_dev *hdev, u8 *data) | 919 | static void create_eir(struct hci_dev *hdev, u8 *data) |
910 | { | 920 | { |
911 | u8 *ptr = data; | 921 | u8 *ptr = data; |
@@ -1743,7 +1753,7 @@ static void set_connectable_complete(struct hci_dev *hdev, u8 status) | |||
1743 | { | 1753 | { |
1744 | struct pending_cmd *cmd; | 1754 | struct pending_cmd *cmd; |
1745 | struct mgmt_mode *cp; | 1755 | struct mgmt_mode *cp; |
1746 | bool changed; | 1756 | bool conn_changed, discov_changed; |
1747 | 1757 | ||
1748 | BT_DBG("status 0x%02x", status); | 1758 | BT_DBG("status 0x%02x", status); |
1749 | 1759 | ||
@@ -1760,15 +1770,23 @@ static void set_connectable_complete(struct hci_dev *hdev, u8 status) | |||
1760 | } | 1770 | } |
1761 | 1771 | ||
1762 | cp = cmd->param; | 1772 | cp = cmd->param; |
1763 | if (cp->val) | 1773 | if (cp->val) { |
1764 | changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags); | 1774 | conn_changed = !test_and_set_bit(HCI_CONNECTABLE, |
1765 | else | 1775 | &hdev->dev_flags); |
1766 | changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags); | 1776 | discov_changed = false; |
1777 | } else { | ||
1778 | conn_changed = test_and_clear_bit(HCI_CONNECTABLE, | ||
1779 | &hdev->dev_flags); | ||
1780 | discov_changed = test_and_clear_bit(HCI_DISCOVERABLE, | ||
1781 | &hdev->dev_flags); | ||
1782 | } | ||
1767 | 1783 | ||
1768 | send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev); | 1784 | send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev); |
1769 | 1785 | ||
1770 | if (changed) { | 1786 | if (conn_changed || discov_changed) { |
1771 | new_settings(hdev, cmd->sk); | 1787 | new_settings(hdev, cmd->sk); |
1788 | if (discov_changed) | ||
1789 | mgmt_update_adv_data(hdev); | ||
1772 | hci_update_background_scan(hdev); | 1790 | hci_update_background_scan(hdev); |
1773 | } | 1791 | } |
1774 | 1792 | ||
@@ -1882,8 +1900,8 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1882 | if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) | 1900 | if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) |
1883 | write_fast_connectable(&req, false); | 1901 | write_fast_connectable(&req, false); |
1884 | 1902 | ||
1885 | if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) && | 1903 | /* Update the advertising parameters if necessary */ |
1886 | !test_bit(HCI_LE_ADV, &hdev->dev_flags)) | 1904 | if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) |
1887 | enable_advertising(&req); | 1905 | enable_advertising(&req); |
1888 | 1906 | ||
1889 | err = hci_req_run(&req, set_connectable_complete); | 1907 | err = hci_req_run(&req, set_connectable_complete); |
@@ -3136,9 +3154,9 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data, | |||
3136 | */ | 3154 | */ |
3137 | hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type); | 3155 | hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type); |
3138 | 3156 | ||
3139 | /* Request a connection with master = true role */ | ||
3140 | conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type, | 3157 | conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type, |
3141 | sec_level, HCI_LE_CONN_TIMEOUT, true); | 3158 | sec_level, HCI_LE_CONN_TIMEOUT, |
3159 | HCI_ROLE_MASTER); | ||
3142 | } | 3160 | } |
3143 | 3161 | ||
3144 | if (IS_ERR(conn)) { | 3162 | if (IS_ERR(conn)) { |
@@ -3184,7 +3202,7 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data, | |||
3184 | cmd->user_data = conn; | 3202 | cmd->user_data = conn; |
3185 | 3203 | ||
3186 | if (conn->state == BT_CONNECTED && | 3204 | if (conn->state == BT_CONNECTED && |
3187 | hci_conn_security(conn, sec_level, auth_type)) | 3205 | hci_conn_security(conn, sec_level, auth_type, true)) |
3188 | pairing_complete(cmd, 0); | 3206 | pairing_complete(cmd, 0); |
3189 | 3207 | ||
3190 | err = 0; | 3208 | err = 0; |
@@ -6031,88 +6049,6 @@ void mgmt_discoverable_timeout(struct hci_dev *hdev) | |||
6031 | hci_dev_unlock(hdev); | 6049 | hci_dev_unlock(hdev); |
6032 | } | 6050 | } |
6033 | 6051 | ||
6034 | void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable) | ||
6035 | { | ||
6036 | bool changed; | ||
6037 | |||
6038 | /* Nothing needed here if there's a pending command since that | ||
6039 | * commands request completion callback takes care of everything | ||
6040 | * necessary. | ||
6041 | */ | ||
6042 | if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev)) | ||
6043 | return; | ||
6044 | |||
6045 | /* Powering off may clear the scan mode - don't let that interfere */ | ||
6046 | if (!discoverable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) | ||
6047 | return; | ||
6048 | |||
6049 | if (discoverable) { | ||
6050 | changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags); | ||
6051 | } else { | ||
6052 | clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags); | ||
6053 | changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags); | ||
6054 | } | ||
6055 | |||
6056 | if (changed) { | ||
6057 | struct hci_request req; | ||
6058 | |||
6059 | /* In case this change in discoverable was triggered by | ||
6060 | * a disabling of connectable there could be a need to | ||
6061 | * update the advertising flags. | ||
6062 | */ | ||
6063 | hci_req_init(&req, hdev); | ||
6064 | update_adv_data(&req); | ||
6065 | hci_req_run(&req, NULL); | ||
6066 | |||
6067 | new_settings(hdev, NULL); | ||
6068 | } | ||
6069 | } | ||
6070 | |||
6071 | void mgmt_connectable(struct hci_dev *hdev, u8 connectable) | ||
6072 | { | ||
6073 | bool changed; | ||
6074 | |||
6075 | /* Nothing needed here if there's a pending command since that | ||
6076 | * commands request completion callback takes care of everything | ||
6077 | * necessary. | ||
6078 | */ | ||
6079 | if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) | ||
6080 | return; | ||
6081 | |||
6082 | /* Powering off may clear the scan mode - don't let that interfere */ | ||
6083 | if (!connectable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) | ||
6084 | return; | ||
6085 | |||
6086 | /* If something else than mgmt changed the page scan state we | ||
6087 | * can't differentiate this from a change triggered by adding | ||
6088 | * the first element to the whitelist. Therefore, avoid | ||
6089 | * incorrectly setting HCI_CONNECTABLE. | ||
6090 | */ | ||
6091 | if (connectable && !list_empty(&hdev->whitelist)) | ||
6092 | return; | ||
6093 | |||
6094 | if (connectable) | ||
6095 | changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags); | ||
6096 | else | ||
6097 | changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags); | ||
6098 | |||
6099 | if (changed) | ||
6100 | new_settings(hdev, NULL); | ||
6101 | } | ||
6102 | |||
6103 | void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status) | ||
6104 | { | ||
6105 | u8 mgmt_err = mgmt_status(status); | ||
6106 | |||
6107 | if (scan & SCAN_PAGE) | ||
6108 | mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev, | ||
6109 | cmd_status_rsp, &mgmt_err); | ||
6110 | |||
6111 | if (scan & SCAN_INQUIRY) | ||
6112 | mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev, | ||
6113 | cmd_status_rsp, &mgmt_err); | ||
6114 | } | ||
6115 | |||
6116 | void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, | 6052 | void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, |
6117 | bool persistent) | 6053 | bool persistent) |
6118 | { | 6054 | { |
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 c06dbd3938e8..7ee9e4ab00f8 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c | |||
@@ -40,13 +40,38 @@ static struct bt_sock_list sco_sk_list = { | |||
40 | .lock = __RW_LOCK_UNLOCKED(sco_sk_list.lock) | 40 | .lock = __RW_LOCK_UNLOCKED(sco_sk_list.lock) |
41 | }; | 41 | }; |
42 | 42 | ||
43 | static void __sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent); | 43 | /* ---- SCO connections ---- */ |
44 | static void sco_chan_del(struct sock *sk, int err); | 44 | struct sco_conn { |
45 | struct hci_conn *hcon; | ||
46 | |||
47 | spinlock_t lock; | ||
48 | struct sock *sk; | ||
49 | |||
50 | unsigned int mtu; | ||
51 | }; | ||
52 | |||
53 | #define sco_conn_lock(c) spin_lock(&c->lock); | ||
54 | #define sco_conn_unlock(c) spin_unlock(&c->lock); | ||
45 | 55 | ||
46 | static void sco_sock_close(struct sock *sk); | 56 | static void sco_sock_close(struct sock *sk); |
47 | static void sco_sock_kill(struct sock *sk); | 57 | static void sco_sock_kill(struct sock *sk); |
48 | 58 | ||
59 | /* ----- SCO socket info ----- */ | ||
60 | #define sco_pi(sk) ((struct sco_pinfo *) sk) | ||
61 | |||
62 | struct sco_pinfo { | ||
63 | struct bt_sock bt; | ||
64 | bdaddr_t src; | ||
65 | bdaddr_t dst; | ||
66 | __u32 flags; | ||
67 | __u16 setting; | ||
68 | struct sco_conn *conn; | ||
69 | }; | ||
70 | |||
49 | /* ---- SCO timers ---- */ | 71 | /* ---- SCO timers ---- */ |
72 | #define SCO_CONN_TIMEOUT (HZ * 40) | ||
73 | #define SCO_DISCONN_TIMEOUT (HZ * 2) | ||
74 | |||
50 | static void sco_sock_timeout(unsigned long arg) | 75 | static void sco_sock_timeout(unsigned long arg) |
51 | { | 76 | { |
52 | struct sock *sk = (struct sock *) arg; | 77 | struct sock *sk = (struct sock *) arg; |
@@ -102,13 +127,31 @@ static struct sco_conn *sco_conn_add(struct hci_conn *hcon) | |||
102 | return conn; | 127 | return conn; |
103 | } | 128 | } |
104 | 129 | ||
105 | static struct sock *sco_chan_get(struct sco_conn *conn) | 130 | /* Delete channel. |
131 | * Must be called on the locked socket. */ | ||
132 | static void sco_chan_del(struct sock *sk, int err) | ||
106 | { | 133 | { |
107 | struct sock *sk = NULL; | 134 | struct sco_conn *conn; |
108 | sco_conn_lock(conn); | 135 | |
109 | sk = conn->sk; | 136 | conn = sco_pi(sk)->conn; |
110 | sco_conn_unlock(conn); | 137 | |
111 | return sk; | 138 | BT_DBG("sk %p, conn %p, err %d", sk, conn, err); |
139 | |||
140 | if (conn) { | ||
141 | sco_conn_lock(conn); | ||
142 | conn->sk = NULL; | ||
143 | sco_pi(sk)->conn = NULL; | ||
144 | sco_conn_unlock(conn); | ||
145 | |||
146 | if (conn->hcon) | ||
147 | hci_conn_drop(conn->hcon); | ||
148 | } | ||
149 | |||
150 | sk->sk_state = BT_CLOSED; | ||
151 | sk->sk_err = err; | ||
152 | sk->sk_state_change(sk); | ||
153 | |||
154 | sock_set_flag(sk, SOCK_ZAPPED); | ||
112 | } | 155 | } |
113 | 156 | ||
114 | static int sco_conn_del(struct hci_conn *hcon, int err) | 157 | static int sco_conn_del(struct hci_conn *hcon, int err) |
@@ -122,7 +165,10 @@ static int sco_conn_del(struct hci_conn *hcon, int err) | |||
122 | BT_DBG("hcon %p conn %p, err %d", hcon, conn, err); | 165 | BT_DBG("hcon %p conn %p, err %d", hcon, conn, err); |
123 | 166 | ||
124 | /* Kill socket */ | 167 | /* Kill socket */ |
125 | sk = sco_chan_get(conn); | 168 | sco_conn_lock(conn); |
169 | sk = conn->sk; | ||
170 | sco_conn_unlock(conn); | ||
171 | |||
126 | if (sk) { | 172 | if (sk) { |
127 | bh_lock_sock(sk); | 173 | bh_lock_sock(sk); |
128 | sco_sock_clear_timer(sk); | 174 | sco_sock_clear_timer(sk); |
@@ -136,6 +182,17 @@ static int sco_conn_del(struct hci_conn *hcon, int err) | |||
136 | return 0; | 182 | return 0; |
137 | } | 183 | } |
138 | 184 | ||
185 | static void __sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent) | ||
186 | { | ||
187 | BT_DBG("conn %p", conn); | ||
188 | |||
189 | sco_pi(sk)->conn = conn; | ||
190 | conn->sk = sk; | ||
191 | |||
192 | if (parent) | ||
193 | bt_accept_enqueue(parent, sk); | ||
194 | } | ||
195 | |||
139 | static int sco_chan_add(struct sco_conn *conn, struct sock *sk, | 196 | static int sco_chan_add(struct sco_conn *conn, struct sock *sk, |
140 | struct sock *parent) | 197 | struct sock *parent) |
141 | { | 198 | { |
@@ -240,7 +297,11 @@ static int sco_send_frame(struct sock *sk, struct msghdr *msg, int len) | |||
240 | 297 | ||
241 | static void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb) | 298 | static void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb) |
242 | { | 299 | { |
243 | struct sock *sk = sco_chan_get(conn); | 300 | struct sock *sk; |
301 | |||
302 | sco_conn_lock(conn); | ||
303 | sk = conn->sk; | ||
304 | sco_conn_unlock(conn); | ||
244 | 305 | ||
245 | if (!sk) | 306 | if (!sk) |
246 | goto drop; | 307 | goto drop; |
@@ -909,7 +970,8 @@ static int sco_sock_shutdown(struct socket *sock, int how) | |||
909 | sco_sock_clear_timer(sk); | 970 | sco_sock_clear_timer(sk); |
910 | __sco_sock_close(sk); | 971 | __sco_sock_close(sk); |
911 | 972 | ||
912 | if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) | 973 | if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime && |
974 | !(current->flags & PF_EXITING)) | ||
913 | err = bt_sock_wait_state(sk, BT_CLOSED, | 975 | err = bt_sock_wait_state(sk, BT_CLOSED, |
914 | sk->sk_lingertime); | 976 | sk->sk_lingertime); |
915 | } | 977 | } |
@@ -929,7 +991,8 @@ static int sco_sock_release(struct socket *sock) | |||
929 | 991 | ||
930 | sco_sock_close(sk); | 992 | sco_sock_close(sk); |
931 | 993 | ||
932 | if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) { | 994 | if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime && |
995 | !(current->flags & PF_EXITING)) { | ||
933 | lock_sock(sk); | 996 | lock_sock(sk); |
934 | err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime); | 997 | err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime); |
935 | release_sock(sk); | 998 | release_sock(sk); |
@@ -940,44 +1003,6 @@ static int sco_sock_release(struct socket *sock) | |||
940 | return err; | 1003 | return err; |
941 | } | 1004 | } |
942 | 1005 | ||
943 | static void __sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent) | ||
944 | { | ||
945 | BT_DBG("conn %p", conn); | ||
946 | |||
947 | sco_pi(sk)->conn = conn; | ||
948 | conn->sk = sk; | ||
949 | |||
950 | if (parent) | ||
951 | bt_accept_enqueue(parent, sk); | ||
952 | } | ||
953 | |||
954 | /* Delete channel. | ||
955 | * Must be called on the locked socket. */ | ||
956 | static void sco_chan_del(struct sock *sk, int err) | ||
957 | { | ||
958 | struct sco_conn *conn; | ||
959 | |||
960 | conn = sco_pi(sk)->conn; | ||
961 | |||
962 | BT_DBG("sk %p, conn %p, err %d", sk, conn, err); | ||
963 | |||
964 | if (conn) { | ||
965 | sco_conn_lock(conn); | ||
966 | conn->sk = NULL; | ||
967 | sco_pi(sk)->conn = NULL; | ||
968 | sco_conn_unlock(conn); | ||
969 | |||
970 | if (conn->hcon) | ||
971 | hci_conn_drop(conn->hcon); | ||
972 | } | ||
973 | |||
974 | sk->sk_state = BT_CLOSED; | ||
975 | sk->sk_err = err; | ||
976 | sk->sk_state_change(sk); | ||
977 | |||
978 | sock_set_flag(sk, SOCK_ZAPPED); | ||
979 | } | ||
980 | |||
981 | static void sco_conn_ready(struct sco_conn *conn) | 1006 | static void sco_conn_ready(struct sco_conn *conn) |
982 | { | 1007 | { |
983 | struct sock *parent; | 1008 | struct sock *parent; |
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 55c41de2f5a0..e49c83d8b957 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c | |||
@@ -391,10 +391,12 @@ static const u8 gen_method[5][5] = { | |||
391 | 391 | ||
392 | static u8 get_auth_method(struct smp_chan *smp, u8 local_io, u8 remote_io) | 392 | static u8 get_auth_method(struct smp_chan *smp, u8 local_io, u8 remote_io) |
393 | { | 393 | { |
394 | /* If either side has unknown io_caps, use JUST WORKS */ | 394 | /* If either side has unknown io_caps, use JUST_CFM (which gets |
395 | * converted later to JUST_WORKS if we're initiators. | ||
396 | */ | ||
395 | if (local_io > SMP_IO_KEYBOARD_DISPLAY || | 397 | if (local_io > SMP_IO_KEYBOARD_DISPLAY || |
396 | remote_io > SMP_IO_KEYBOARD_DISPLAY) | 398 | remote_io > SMP_IO_KEYBOARD_DISPLAY) |
397 | return JUST_WORKS; | 399 | return JUST_CFM; |
398 | 400 | ||
399 | return gen_method[remote_io][local_io]; | 401 | return gen_method[remote_io][local_io]; |
400 | } | 402 | } |
@@ -414,21 +416,25 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth, | |||
414 | 416 | ||
415 | BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io); | 417 | BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io); |
416 | 418 | ||
417 | /* If neither side wants MITM, use JUST WORKS */ | 419 | /* If neither side wants MITM, either "just" confirm an incoming |
418 | /* Otherwise, look up method from the table */ | 420 | * request or use just-works for outgoing ones. The JUST_CFM |
421 | * will be converted to JUST_WORKS if necessary later in this | ||
422 | * function. If either side has MITM look up the method from the | ||
423 | * table. | ||
424 | */ | ||
419 | if (!(auth & SMP_AUTH_MITM)) | 425 | if (!(auth & SMP_AUTH_MITM)) |
420 | method = JUST_WORKS; | 426 | method = JUST_CFM; |
421 | else | 427 | else |
422 | method = get_auth_method(smp, local_io, remote_io); | 428 | method = get_auth_method(smp, local_io, remote_io); |
423 | 429 | ||
424 | /* If not bonding, don't ask user to confirm a Zero TK */ | ||
425 | if (!(auth & SMP_AUTH_BONDING) && method == JUST_CFM) | ||
426 | method = JUST_WORKS; | ||
427 | |||
428 | /* Don't confirm locally initiated pairing attempts */ | 430 | /* Don't confirm locally initiated pairing attempts */ |
429 | if (method == JUST_CFM && test_bit(SMP_FLAG_INITIATOR, &smp->flags)) | 431 | if (method == JUST_CFM && test_bit(SMP_FLAG_INITIATOR, &smp->flags)) |
430 | method = JUST_WORKS; | 432 | method = JUST_WORKS; |
431 | 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 | |||
432 | /* If Just Works, Continue with Zero TK */ | 438 | /* If Just Works, Continue with Zero TK */ |
433 | if (method == JUST_WORKS) { | 439 | if (method == JUST_WORKS) { |
434 | set_bit(SMP_FLAG_TK_VALID, &smp->flags); | 440 | set_bit(SMP_FLAG_TK_VALID, &smp->flags); |
@@ -443,7 +449,7 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth, | |||
443 | * Confirms and the slave Enters the passkey. | 449 | * Confirms and the slave Enters the passkey. |
444 | */ | 450 | */ |
445 | if (method == OVERLAP) { | 451 | if (method == OVERLAP) { |
446 | if (test_bit(HCI_CONN_MASTER, &hcon->flags)) | 452 | if (hcon->role == HCI_ROLE_MASTER) |
447 | method = CFM_PASSKEY; | 453 | method = CFM_PASSKEY; |
448 | else | 454 | else |
449 | method = REQ_PASSKEY; | 455 | method = REQ_PASSKEY; |
@@ -674,6 +680,7 @@ int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey) | |||
674 | static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) | 680 | static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) |
675 | { | 681 | { |
676 | struct smp_cmd_pairing rsp, *req = (void *) skb->data; | 682 | struct smp_cmd_pairing rsp, *req = (void *) skb->data; |
683 | struct hci_dev *hdev = conn->hcon->hdev; | ||
677 | struct smp_chan *smp; | 684 | struct smp_chan *smp; |
678 | u8 key_size, auth, sec_level; | 685 | u8 key_size, auth, sec_level; |
679 | int ret; | 686 | int ret; |
@@ -683,7 +690,7 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
683 | if (skb->len < sizeof(*req)) | 690 | if (skb->len < sizeof(*req)) |
684 | return SMP_INVALID_PARAMS; | 691 | return SMP_INVALID_PARAMS; |
685 | 692 | ||
686 | if (test_bit(HCI_CONN_MASTER, &conn->hcon->flags)) | 693 | if (conn->hcon->role != HCI_ROLE_SLAVE) |
687 | return SMP_CMD_NOTSUPP; | 694 | return SMP_CMD_NOTSUPP; |
688 | 695 | ||
689 | 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)) |
@@ -694,6 +701,10 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
694 | if (!smp) | 701 | if (!smp) |
695 | return SMP_UNSPECIFIED; | 702 | return SMP_UNSPECIFIED; |
696 | 703 | ||
704 | if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags) && | ||
705 | (req->auth_req & SMP_AUTH_BONDING)) | ||
706 | return SMP_PAIRING_NOTSUPP; | ||
707 | |||
697 | smp->preq[0] = SMP_CMD_PAIRING_REQ; | 708 | smp->preq[0] = SMP_CMD_PAIRING_REQ; |
698 | memcpy(&smp->preq[1], req, sizeof(*req)); | 709 | memcpy(&smp->preq[1], req, sizeof(*req)); |
699 | skb_pull(skb, sizeof(*req)); | 710 | skb_pull(skb, sizeof(*req)); |
@@ -733,8 +744,6 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
733 | if (ret) | 744 | if (ret) |
734 | return SMP_UNSPECIFIED; | 745 | return SMP_UNSPECIFIED; |
735 | 746 | ||
736 | clear_bit(SMP_FLAG_INITIATOR, &smp->flags); | ||
737 | |||
738 | return 0; | 747 | return 0; |
739 | } | 748 | } |
740 | 749 | ||
@@ -750,7 +759,7 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb) | |||
750 | if (skb->len < sizeof(*rsp)) | 759 | if (skb->len < sizeof(*rsp)) |
751 | return SMP_INVALID_PARAMS; | 760 | return SMP_INVALID_PARAMS; |
752 | 761 | ||
753 | if (!test_bit(HCI_CONN_MASTER, &conn->hcon->flags)) | 762 | if (conn->hcon->role != HCI_ROLE_MASTER) |
754 | return SMP_CMD_NOTSUPP; | 763 | return SMP_CMD_NOTSUPP; |
755 | 764 | ||
756 | skb_pull(skb, sizeof(*rsp)); | 765 | skb_pull(skb, sizeof(*rsp)); |
@@ -844,7 +853,7 @@ static bool smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level) | |||
844 | struct hci_conn *hcon = conn->hcon; | 853 | struct hci_conn *hcon = conn->hcon; |
845 | 854 | ||
846 | 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, |
847 | hcon->out); | 856 | hcon->role); |
848 | if (!key) | 857 | if (!key) |
849 | return false; | 858 | return false; |
850 | 859 | ||
@@ -871,9 +880,12 @@ bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level) | |||
871 | /* If we're encrypted with an STK always claim insufficient | 880 | /* If we're encrypted with an STK always claim insufficient |
872 | * security. This way we allow the connection to be re-encrypted | 881 | * security. This way we allow the connection to be re-encrypted |
873 | * with an LTK, even if the LTK provides the same level of | 882 | * with an LTK, even if the LTK provides the same level of |
874 | * security. | 883 | * security. Only exception is if we don't have an LTK (e.g. |
884 | * because of key distribution bits). | ||
875 | */ | 885 | */ |
876 | if (test_bit(HCI_CONN_STK_ENCRYPT, &hcon->flags)) | 886 | if (test_bit(HCI_CONN_STK_ENCRYPT, &hcon->flags) && |
887 | hci_find_ltk_by_addr(hcon->hdev, &hcon->dst, hcon->dst_type, | ||
888 | hcon->role)) | ||
877 | return false; | 889 | return false; |
878 | 890 | ||
879 | if (hcon->sec_level >= sec_level) | 891 | if (hcon->sec_level >= sec_level) |
@@ -895,7 +907,7 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
895 | if (skb->len < sizeof(*rp)) | 907 | if (skb->len < sizeof(*rp)) |
896 | return SMP_INVALID_PARAMS; | 908 | return SMP_INVALID_PARAMS; |
897 | 909 | ||
898 | if (!test_bit(HCI_CONN_MASTER, &conn->hcon->flags)) | 910 | if (hcon->role != HCI_ROLE_MASTER) |
899 | return SMP_CMD_NOTSUPP; | 911 | return SMP_CMD_NOTSUPP; |
900 | 912 | ||
901 | sec_level = authreq_to_seclevel(rp->auth_req); | 913 | sec_level = authreq_to_seclevel(rp->auth_req); |
@@ -911,6 +923,10 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
911 | if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) | 923 | if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) |
912 | return 0; | 924 | return 0; |
913 | 925 | ||
926 | if (!test_bit(HCI_PAIRABLE, &hcon->hdev->dev_flags) && | ||
927 | (rp->auth_req & SMP_AUTH_BONDING)) | ||
928 | return SMP_PAIRING_NOTSUPP; | ||
929 | |||
914 | smp = smp_chan_create(conn); | 930 | smp = smp_chan_create(conn); |
915 | if (!smp) | 931 | if (!smp) |
916 | return SMP_UNSPECIFIED; | 932 | return SMP_UNSPECIFIED; |
@@ -925,8 +941,6 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
925 | 941 | ||
926 | smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp); | 942 | smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp); |
927 | 943 | ||
928 | clear_bit(SMP_FLAG_INITIATOR, &smp->flags); | ||
929 | |||
930 | return 0; | 944 | return 0; |
931 | } | 945 | } |
932 | 946 | ||
@@ -951,7 +965,7 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) | |||
951 | if (sec_level > hcon->pending_sec_level) | 965 | if (sec_level > hcon->pending_sec_level) |
952 | hcon->pending_sec_level = sec_level; | 966 | hcon->pending_sec_level = sec_level; |
953 | 967 | ||
954 | if (test_bit(HCI_CONN_MASTER, &hcon->flags)) | 968 | if (hcon->role == HCI_ROLE_MASTER) |
955 | if (smp_ltk_encrypt(conn, hcon->pending_sec_level)) | 969 | if (smp_ltk_encrypt(conn, hcon->pending_sec_level)) |
956 | return 0; | 970 | return 0; |
957 | 971 | ||
@@ -971,7 +985,7 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) | |||
971 | hcon->pending_sec_level > BT_SECURITY_MEDIUM) | 985 | hcon->pending_sec_level > BT_SECURITY_MEDIUM) |
972 | authreq |= SMP_AUTH_MITM; | 986 | authreq |= SMP_AUTH_MITM; |
973 | 987 | ||
974 | if (test_bit(HCI_CONN_MASTER, &hcon->flags)) { | 988 | if (hcon->role == HCI_ROLE_MASTER) { |
975 | struct smp_cmd_pairing cp; | 989 | struct smp_cmd_pairing cp; |
976 | 990 | ||
977 | build_pairing_cmd(conn, &cp, NULL, authreq); | 991 | build_pairing_cmd(conn, &cp, NULL, authreq); |
@@ -1175,7 +1189,7 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) | |||
1175 | } | 1189 | } |
1176 | 1190 | ||
1177 | if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags)) { | 1191 | if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags)) { |
1178 | err = -ENOTSUPP; | 1192 | err = -EOPNOTSUPP; |
1179 | reason = SMP_PAIRING_NOTSUPP; | 1193 | reason = SMP_PAIRING_NOTSUPP; |
1180 | goto done; | 1194 | goto done; |
1181 | } | 1195 | } |
@@ -1193,7 +1207,7 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) | |||
1193 | !conn->smp_chan) { | 1207 | !conn->smp_chan) { |
1194 | BT_ERR("Unexpected SMP command 0x%02x. Disconnecting.", code); | 1208 | BT_ERR("Unexpected SMP command 0x%02x. Disconnecting.", code); |
1195 | kfree_skb(skb); | 1209 | kfree_skb(skb); |
1196 | return -ENOTSUPP; | 1210 | return -EOPNOTSUPP; |
1197 | } | 1211 | } |
1198 | 1212 | ||
1199 | switch (code) { | 1213 | switch (code) { |
diff --git a/net/ieee802154/Kconfig b/net/ieee802154/Kconfig index 8af1330b3137..c0d4154d144f 100644 --- a/net/ieee802154/Kconfig +++ b/net/ieee802154/Kconfig | |||
@@ -12,13 +12,6 @@ config IEEE802154 | |||
12 | 12 | ||
13 | config IEEE802154_6LOWPAN | 13 | config IEEE802154_6LOWPAN |
14 | tristate "6lowpan support over IEEE 802.15.4" | 14 | tristate "6lowpan support over IEEE 802.15.4" |
15 | depends on IEEE802154 && IPV6 | 15 | depends on IEEE802154 && 6LOWPAN |
16 | select 6LOWPAN_IPHC | ||
17 | ---help--- | 16 | ---help--- |
18 | IPv6 compression over IEEE 802.15.4. | 17 | IPv6 compression over IEEE 802.15.4. |
19 | |||
20 | config 6LOWPAN_IPHC | ||
21 | tristate | ||
22 | ---help--- | ||
23 | 6lowpan compression code which is shared between IEEE 802.15.4 and Bluetooth | ||
24 | stacks. | ||
diff --git a/net/ieee802154/Makefile b/net/ieee802154/Makefile index bf1b51497a41..3914b1ed4274 100644 --- a/net/ieee802154/Makefile +++ b/net/ieee802154/Makefile | |||
@@ -1,8 +1,7 @@ | |||
1 | obj-$(CONFIG_IEEE802154) += ieee802154.o af_802154.o | 1 | obj-$(CONFIG_IEEE802154) += ieee802154.o af_802154.o |
2 | obj-$(CONFIG_IEEE802154_6LOWPAN) += 6lowpan.o | 2 | obj-$(CONFIG_IEEE802154_6LOWPAN) += ieee802154_6lowpan.o |
3 | obj-$(CONFIG_6LOWPAN_IPHC) += 6lowpan_iphc.o | ||
4 | 3 | ||
5 | 6lowpan-y := 6lowpan_rtnl.o reassembly.o | 4 | ieee802154_6lowpan-y := 6lowpan_rtnl.o reassembly.o |
6 | ieee802154-y := netlink.o nl-mac.o nl-phy.o nl_policy.o wpan-class.o \ | 5 | ieee802154-y := netlink.o nl-mac.o nl-phy.o nl_policy.o wpan-class.o \ |
7 | header_ops.o | 6 | header_ops.o |
8 | af_802154-y := af_ieee802154.o raw.o dgram.o | 7 | af_802154-y := af_ieee802154.o raw.o dgram.o |
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 4edfc7c1524f..01eede7406a5 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.c b/net/mac80211/sta_info.c index f41177f58b30..c6ee2139fbc5 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -1724,12 +1724,15 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
1724 | { | 1724 | { |
1725 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 1725 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
1726 | struct ieee80211_local *local = sdata->local; | 1726 | struct ieee80211_local *local = sdata->local; |
1727 | struct rate_control_ref *ref = local->rate_ctrl; | 1727 | struct rate_control_ref *ref = NULL; |
1728 | struct timespec uptime; | 1728 | struct timespec uptime; |
1729 | u64 packets = 0; | 1729 | u64 packets = 0; |
1730 | u32 thr = 0; | 1730 | u32 thr = 0; |
1731 | int i, ac; | 1731 | int i, ac; |
1732 | 1732 | ||
1733 | if (test_sta_flag(sta, WLAN_STA_RATE_CONTROL)) | ||
1734 | ref = local->rate_ctrl; | ||
1735 | |||
1733 | sinfo->generation = sdata->local->sta_generation; | 1736 | sinfo->generation = sdata->local->sta_generation; |
1734 | 1737 | ||
1735 | sinfo->filled = STATION_INFO_INACTIVE_TIME | | 1738 | sinfo->filled = STATION_INFO_INACTIVE_TIME | |
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/tx.c b/net/mac80211/tx.c index 865bdaf06ff1..464106c023d8 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -415,6 +415,9 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx) | |||
415 | if (ieee80211_has_order(hdr->frame_control)) | 415 | if (ieee80211_has_order(hdr->frame_control)) |
416 | return TX_CONTINUE; | 416 | return TX_CONTINUE; |
417 | 417 | ||
418 | if (ieee80211_is_probe_req(hdr->frame_control)) | ||
419 | return TX_CONTINUE; | ||
420 | |||
418 | if (tx->local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) | 421 | if (tx->local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) |
419 | info->hw_queue = tx->sdata->vif.cab_queue; | 422 | info->hw_queue = tx->sdata->vif.cab_queue; |
420 | 423 | ||
@@ -464,6 +467,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
464 | { | 467 | { |
465 | struct sta_info *sta = tx->sta; | 468 | struct sta_info *sta = tx->sta; |
466 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | 469 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); |
470 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; | ||
467 | struct ieee80211_local *local = tx->local; | 471 | struct ieee80211_local *local = tx->local; |
468 | 472 | ||
469 | if (unlikely(!sta)) | 473 | if (unlikely(!sta)) |
@@ -475,6 +479,12 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
475 | !(info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER))) { | 479 | !(info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER))) { |
476 | int ac = skb_get_queue_mapping(tx->skb); | 480 | int ac = skb_get_queue_mapping(tx->skb); |
477 | 481 | ||
482 | if (ieee80211_is_mgmt(hdr->frame_control) && | ||
483 | !ieee80211_is_bufferable_mmpdu(hdr->frame_control)) { | ||
484 | info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER; | ||
485 | return TX_CONTINUE; | ||
486 | } | ||
487 | |||
478 | ps_dbg(sta->sdata, "STA %pM aid %d: PS buffer for AC %d\n", | 488 | ps_dbg(sta->sdata, "STA %pM aid %d: PS buffer for AC %d\n", |
479 | sta->sta.addr, sta->sta.aid, ac); | 489 | sta->sta.addr, sta->sta.aid, ac); |
480 | if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) | 490 | if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) |
@@ -534,19 +544,9 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
534 | static ieee80211_tx_result debug_noinline | 544 | static ieee80211_tx_result debug_noinline |
535 | ieee80211_tx_h_ps_buf(struct ieee80211_tx_data *tx) | 545 | ieee80211_tx_h_ps_buf(struct ieee80211_tx_data *tx) |
536 | { | 546 | { |
537 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | ||
538 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; | ||
539 | |||
540 | if (unlikely(tx->flags & IEEE80211_TX_PS_BUFFERED)) | 547 | if (unlikely(tx->flags & IEEE80211_TX_PS_BUFFERED)) |
541 | return TX_CONTINUE; | 548 | return TX_CONTINUE; |
542 | 549 | ||
543 | if (ieee80211_is_mgmt(hdr->frame_control) && | ||
544 | !ieee80211_is_bufferable_mmpdu(hdr->frame_control)) { | ||
545 | if (tx->flags & IEEE80211_TX_UNICAST) | ||
546 | info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER; | ||
547 | return TX_CONTINUE; | ||
548 | } | ||
549 | |||
550 | if (tx->flags & IEEE80211_TX_UNICAST) | 550 | if (tx->flags & IEEE80211_TX_UNICAST) |
551 | return ieee80211_tx_h_unicast_ps_buf(tx); | 551 | return ieee80211_tx_h_unicast_ps_buf(tx); |
552 | else | 552 | else |
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 */ |
diff --git a/net/wireless/trace.h b/net/wireless/trace.h index 85474ee501eb..0c524cd76c83 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h | |||
@@ -2049,7 +2049,8 @@ TRACE_EVENT(cfg80211_michael_mic_failure, | |||
2049 | MAC_ASSIGN(addr, addr); | 2049 | MAC_ASSIGN(addr, addr); |
2050 | __entry->key_type = key_type; | 2050 | __entry->key_type = key_type; |
2051 | __entry->key_id = key_id; | 2051 | __entry->key_id = key_id; |
2052 | memcpy(__entry->tsc, tsc, 6); | 2052 | if (tsc) |
2053 | memcpy(__entry->tsc, tsc, 6); | ||
2053 | ), | 2054 | ), |
2054 | TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT ", key type: %d, key id: %d, tsc: %pm", | 2055 | TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT ", key type: %d, key id: %d, tsc: %pm", |
2055 | NETDEV_PR_ARG, MAC_PR_ARG(addr), __entry->key_type, | 2056 | NETDEV_PR_ARG, MAC_PR_ARG(addr), __entry->key_type, |