diff options
author | Johannes Berg <johannes.berg@intel.com> | 2012-06-28 07:45:58 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2012-06-28 07:45:58 -0400 |
commit | b1fbd46976d047a6d6767872a9112afaa914fd82 (patch) | |
tree | 59b471d8b38ca2a271fcde02f8f049e390ef485b | |
parent | bf0c111ec80355ee9fe2e2bdb609a536b54768d8 (diff) | |
parent | bf52592fe4901f486a5266fd73e4ee80205b18b4 (diff) |
Merge remote-tracking branch 'wireless-next/master' into mac80211-next
237 files changed, 12779 insertions, 9277 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index c5fd905206e..fe6dd3d7d2c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -1595,6 +1595,7 @@ M: Arend van Spriel <arend@broadcom.com> | |||
1595 | M: Franky (Zhenhui) Lin <frankyl@broadcom.com> | 1595 | M: Franky (Zhenhui) Lin <frankyl@broadcom.com> |
1596 | M: Kan Yan <kanyan@broadcom.com> | 1596 | M: Kan Yan <kanyan@broadcom.com> |
1597 | L: linux-wireless@vger.kernel.org | 1597 | L: linux-wireless@vger.kernel.org |
1598 | L: brcm80211-dev-list@broadcom.com | ||
1598 | S: Supported | 1599 | S: Supported |
1599 | F: drivers/net/wireless/brcm80211/ | 1600 | F: drivers/net/wireless/brcm80211/ |
1600 | 1601 | ||
@@ -1800,6 +1801,9 @@ F: include/linux/cfag12864b.h | |||
1800 | CFG80211 and NL80211 | 1801 | CFG80211 and NL80211 |
1801 | M: Johannes Berg <johannes@sipsolutions.net> | 1802 | M: Johannes Berg <johannes@sipsolutions.net> |
1802 | L: linux-wireless@vger.kernel.org | 1803 | L: linux-wireless@vger.kernel.org |
1804 | W: http://wireless.kernel.org/ | ||
1805 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git | ||
1806 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git | ||
1803 | S: Maintained | 1807 | S: Maintained |
1804 | F: include/linux/nl80211.h | 1808 | F: include/linux/nl80211.h |
1805 | F: include/net/cfg80211.h | 1809 | F: include/net/cfg80211.h |
@@ -4340,7 +4344,8 @@ MAC80211 | |||
4340 | M: Johannes Berg <johannes@sipsolutions.net> | 4344 | M: Johannes Berg <johannes@sipsolutions.net> |
4341 | L: linux-wireless@vger.kernel.org | 4345 | L: linux-wireless@vger.kernel.org |
4342 | W: http://wireless.kernel.org/ | 4346 | W: http://wireless.kernel.org/ |
4343 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless.git | 4347 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git |
4348 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git | ||
4344 | S: Maintained | 4349 | S: Maintained |
4345 | F: Documentation/networking/mac80211-injection.txt | 4350 | F: Documentation/networking/mac80211-injection.txt |
4346 | F: include/net/mac80211.h | 4351 | F: include/net/mac80211.h |
@@ -4351,7 +4356,8 @@ M: Stefano Brivio <stefano.brivio@polimi.it> | |||
4351 | M: Mattias Nissler <mattias.nissler@gmx.de> | 4356 | M: Mattias Nissler <mattias.nissler@gmx.de> |
4352 | L: linux-wireless@vger.kernel.org | 4357 | L: linux-wireless@vger.kernel.org |
4353 | W: http://wireless.kernel.org/en/developers/Documentation/mac80211/RateControl/PID | 4358 | W: http://wireless.kernel.org/en/developers/Documentation/mac80211/RateControl/PID |
4354 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless.git | 4359 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git |
4360 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git | ||
4355 | S: Maintained | 4361 | S: Maintained |
4356 | F: net/mac80211/rc80211_pid* | 4362 | F: net/mac80211/rc80211_pid* |
4357 | 4363 | ||
@@ -5695,6 +5701,9 @@ F: include/linux/remoteproc.h | |||
5695 | RFKILL | 5701 | RFKILL |
5696 | M: Johannes Berg <johannes@sipsolutions.net> | 5702 | M: Johannes Berg <johannes@sipsolutions.net> |
5697 | L: linux-wireless@vger.kernel.org | 5703 | L: linux-wireless@vger.kernel.org |
5704 | W: http://wireless.kernel.org/ | ||
5705 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git | ||
5706 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git | ||
5698 | S: Maintained | 5707 | S: Maintained |
5699 | F: Documentation/rfkill.txt | 5708 | F: Documentation/rfkill.txt |
5700 | F: net/rfkill/ | 5709 | F: net/rfkill/ |
diff --git a/drivers/bcma/driver_pci.c b/drivers/bcma/driver_pci.c index 9a96f14c8f4..c32ebd537ab 100644 --- a/drivers/bcma/driver_pci.c +++ b/drivers/bcma/driver_pci.c | |||
@@ -232,17 +232,19 @@ void __devinit bcma_core_pci_init(struct bcma_drv_pci *pc) | |||
232 | int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core, | 232 | int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core, |
233 | bool enable) | 233 | bool enable) |
234 | { | 234 | { |
235 | struct pci_dev *pdev = pc->core->bus->host_pci; | 235 | struct pci_dev *pdev; |
236 | u32 coremask, tmp; | 236 | u32 coremask, tmp; |
237 | int err = 0; | 237 | int err = 0; |
238 | 238 | ||
239 | if (core->bus->hosttype != BCMA_HOSTTYPE_PCI) { | 239 | if (!pc || core->bus->hosttype != BCMA_HOSTTYPE_PCI) { |
240 | /* This bcma device is not on a PCI host-bus. So the IRQs are | 240 | /* This bcma device is not on a PCI host-bus. So the IRQs are |
241 | * not routed through the PCI core. | 241 | * not routed through the PCI core. |
242 | * So we must not enable routing through the PCI core. */ | 242 | * So we must not enable routing through the PCI core. */ |
243 | goto out; | 243 | goto out; |
244 | } | 244 | } |
245 | 245 | ||
246 | pdev = pc->core->bus->host_pci; | ||
247 | |||
246 | err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp); | 248 | err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp); |
247 | if (err) | 249 | if (err) |
248 | goto out; | 250 | goto out; |
diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c index 5ed0718fc66..a3420585d94 100644 --- a/drivers/bcma/scan.c +++ b/drivers/bcma/scan.c | |||
@@ -28,6 +28,12 @@ static const struct bcma_device_id_name bcma_arm_device_names[] = { | |||
28 | 28 | ||
29 | static const struct bcma_device_id_name bcma_bcm_device_names[] = { | 29 | static const struct bcma_device_id_name bcma_bcm_device_names[] = { |
30 | { BCMA_CORE_OOB_ROUTER, "OOB Router" }, | 30 | { BCMA_CORE_OOB_ROUTER, "OOB Router" }, |
31 | { BCMA_CORE_4706_CHIPCOMMON, "BCM4706 ChipCommon" }, | ||
32 | { BCMA_CORE_4706_SOC_RAM, "BCM4706 SOC RAM" }, | ||
33 | { BCMA_CORE_4706_MAC_GBIT, "BCM4706 GBit MAC" }, | ||
34 | { BCMA_CORE_AMEMC, "AMEMC (DDR)" }, | ||
35 | { BCMA_CORE_ALTA, "ALTA (I2S)" }, | ||
36 | { BCMA_CORE_4706_MAC_GBIT_COMMON, "BCM4706 GBit MAC Common" }, | ||
31 | { BCMA_CORE_INVALID, "Invalid" }, | 37 | { BCMA_CORE_INVALID, "Invalid" }, |
32 | { BCMA_CORE_CHIPCOMMON, "ChipCommon" }, | 38 | { BCMA_CORE_CHIPCOMMON, "ChipCommon" }, |
33 | { BCMA_CORE_ILINE20, "ILine 20" }, | 39 | { BCMA_CORE_ILINE20, "ILine 20" }, |
diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index 1fcd9238035..585c88e0189 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c | |||
@@ -231,12 +231,12 @@ static void bluecard_write_wakeup(bluecard_info_t *info) | |||
231 | } | 231 | } |
232 | 232 | ||
233 | do { | 233 | do { |
234 | register unsigned int iobase = info->p_dev->resource[0]->start; | 234 | unsigned int iobase = info->p_dev->resource[0]->start; |
235 | register unsigned int offset; | 235 | unsigned int offset; |
236 | register unsigned char command; | 236 | unsigned char command; |
237 | register unsigned long ready_bit; | 237 | unsigned long ready_bit; |
238 | register struct sk_buff *skb; | 238 | register struct sk_buff *skb; |
239 | register int len; | 239 | int len; |
240 | 240 | ||
241 | clear_bit(XMIT_WAKEUP, &(info->tx_state)); | 241 | clear_bit(XMIT_WAKEUP, &(info->tx_state)); |
242 | 242 | ||
diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c index 609861a53c2..29caaed2d71 100644 --- a/drivers/bluetooth/bpa10x.c +++ b/drivers/bluetooth/bpa10x.c | |||
@@ -470,7 +470,7 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id * | |||
470 | hdev->flush = bpa10x_flush; | 470 | hdev->flush = bpa10x_flush; |
471 | hdev->send = bpa10x_send_frame; | 471 | hdev->send = bpa10x_send_frame; |
472 | 472 | ||
473 | set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks); | 473 | set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); |
474 | 474 | ||
475 | err = hci_register_dev(hdev); | 475 | err = hci_register_dev(hdev); |
476 | if (err < 0) { | 476 | if (err < 0) { |
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index 308c8599ab5..b2b0fbbb43b 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c | |||
@@ -186,9 +186,9 @@ static void bt3c_write_wakeup(bt3c_info_t *info) | |||
186 | return; | 186 | return; |
187 | 187 | ||
188 | do { | 188 | do { |
189 | register unsigned int iobase = info->p_dev->resource[0]->start; | 189 | unsigned int iobase = info->p_dev->resource[0]->start; |
190 | register struct sk_buff *skb; | 190 | register struct sk_buff *skb; |
191 | register int len; | 191 | int len; |
192 | 192 | ||
193 | if (!pcmcia_dev_present(info->p_dev)) | 193 | if (!pcmcia_dev_present(info->p_dev)) |
194 | break; | 194 | break; |
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index a853244e7fd..2867499f725 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c | |||
@@ -110,6 +110,9 @@ static const struct sdio_device_id btmrvl_sdio_ids[] = { | |||
110 | /* Marvell SD8787 Bluetooth device */ | 110 | /* Marvell SD8787 Bluetooth device */ |
111 | { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911A), | 111 | { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911A), |
112 | .driver_data = (unsigned long) &btmrvl_sdio_sd8787 }, | 112 | .driver_data = (unsigned long) &btmrvl_sdio_sd8787 }, |
113 | /* Marvell SD8787 Bluetooth AMP device */ | ||
114 | { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911B), | ||
115 | .driver_data = (unsigned long) &btmrvl_sdio_sd8787 }, | ||
113 | /* Marvell SD8797 Bluetooth device */ | 116 | /* Marvell SD8797 Bluetooth device */ |
114 | { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912A), | 117 | { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912A), |
115 | .driver_data = (unsigned long) &btmrvl_sdio_sd8797 }, | 118 | .driver_data = (unsigned long) &btmrvl_sdio_sd8797 }, |
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c index c4fc2f3fc32..65b8d996840 100644 --- a/drivers/bluetooth/btuart_cs.c +++ b/drivers/bluetooth/btuart_cs.c | |||
@@ -140,9 +140,9 @@ static void btuart_write_wakeup(btuart_info_t *info) | |||
140 | } | 140 | } |
141 | 141 | ||
142 | do { | 142 | do { |
143 | register unsigned int iobase = info->p_dev->resource[0]->start; | 143 | unsigned int iobase = info->p_dev->resource[0]->start; |
144 | register struct sk_buff *skb; | 144 | register struct sk_buff *skb; |
145 | register int len; | 145 | int len; |
146 | 146 | ||
147 | clear_bit(XMIT_WAKEUP, &(info->tx_state)); | 147 | clear_bit(XMIT_WAKEUP, &(info->tx_state)); |
148 | 148 | ||
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index c9463af8e56..a45e717f5f8 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c | |||
@@ -21,15 +21,7 @@ | |||
21 | * | 21 | * |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/module.h> | 24 | #include <linux/module.h> |
26 | #include <linux/init.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <linux/types.h> | ||
29 | #include <linux/sched.h> | ||
30 | #include <linux/errno.h> | ||
31 | #include <linux/skbuff.h> | ||
32 | |||
33 | #include <linux/usb.h> | 25 | #include <linux/usb.h> |
34 | 26 | ||
35 | #include <net/bluetooth/bluetooth.h> | 27 | #include <net/bluetooth/bluetooth.h> |
@@ -1026,7 +1018,7 @@ static int btusb_probe(struct usb_interface *intf, | |||
1026 | data->isoc = usb_ifnum_to_if(data->udev, 1); | 1018 | data->isoc = usb_ifnum_to_if(data->udev, 1); |
1027 | 1019 | ||
1028 | if (!reset) | 1020 | if (!reset) |
1029 | set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks); | 1021 | set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); |
1030 | 1022 | ||
1031 | if (force_scofix || id->driver_info & BTUSB_WRONG_SCO_MTU) { | 1023 | if (force_scofix || id->driver_info & BTUSB_WRONG_SCO_MTU) { |
1032 | if (!disable_scofix) | 1024 | if (!disable_scofix) |
@@ -1038,7 +1030,7 @@ static int btusb_probe(struct usb_interface *intf, | |||
1038 | 1030 | ||
1039 | if (id->driver_info & BTUSB_DIGIANSWER) { | 1031 | if (id->driver_info & BTUSB_DIGIANSWER) { |
1040 | data->cmdreq_type = USB_TYPE_VENDOR; | 1032 | data->cmdreq_type = USB_TYPE_VENDOR; |
1041 | set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks); | 1033 | set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); |
1042 | } | 1034 | } |
1043 | 1035 | ||
1044 | if (id->driver_info & BTUSB_CSR) { | 1036 | if (id->driver_info & BTUSB_CSR) { |
@@ -1046,7 +1038,7 @@ static int btusb_probe(struct usb_interface *intf, | |||
1046 | 1038 | ||
1047 | /* Old firmware would otherwise execute USB reset */ | 1039 | /* Old firmware would otherwise execute USB reset */ |
1048 | if (le16_to_cpu(udev->descriptor.bcdDevice) < 0x117) | 1040 | if (le16_to_cpu(udev->descriptor.bcdDevice) < 0x117) |
1049 | set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks); | 1041 | set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); |
1050 | } | 1042 | } |
1051 | 1043 | ||
1052 | if (id->driver_info & BTUSB_SNIFFER) { | 1044 | if (id->driver_info & BTUSB_SNIFFER) { |
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index 6e8d9618968..b1b37ccd3cd 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c | |||
@@ -144,9 +144,9 @@ static void dtl1_write_wakeup(dtl1_info_t *info) | |||
144 | } | 144 | } |
145 | 145 | ||
146 | do { | 146 | do { |
147 | register unsigned int iobase = info->p_dev->resource[0]->start; | 147 | unsigned int iobase = info->p_dev->resource[0]->start; |
148 | register struct sk_buff *skb; | 148 | register struct sk_buff *skb; |
149 | register int len; | 149 | int len; |
150 | 150 | ||
151 | clear_bit(XMIT_WAKEUP, &(info->tx_state)); | 151 | clear_bit(XMIT_WAKEUP, &(info->tx_state)); |
152 | 152 | ||
diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c index 661a8dc4d2f..57e502e0608 100644 --- a/drivers/bluetooth/hci_bcsp.c +++ b/drivers/bluetooth/hci_bcsp.c | |||
@@ -552,7 +552,7 @@ static u16 bscp_get_crc(struct bcsp_struct *bcsp) | |||
552 | static int bcsp_recv(struct hci_uart *hu, void *data, int count) | 552 | static int bcsp_recv(struct hci_uart *hu, void *data, int count) |
553 | { | 553 | { |
554 | struct bcsp_struct *bcsp = hu->priv; | 554 | struct bcsp_struct *bcsp = hu->priv; |
555 | register unsigned char *ptr; | 555 | unsigned char *ptr; |
556 | 556 | ||
557 | BT_DBG("hu %p count %d rx_state %d rx_count %ld", | 557 | BT_DBG("hu %p count %d rx_state %d rx_count %ld", |
558 | hu, count, bcsp->rx_state, bcsp->rx_count); | 558 | hu, count, bcsp->rx_state, bcsp->rx_count); |
diff --git a/drivers/bluetooth/hci_h4.c b/drivers/bluetooth/hci_h4.c index 748329468d2..c60623f206d 100644 --- a/drivers/bluetooth/hci_h4.c +++ b/drivers/bluetooth/hci_h4.c | |||
@@ -126,7 +126,7 @@ static int h4_enqueue(struct hci_uart *hu, struct sk_buff *skb) | |||
126 | 126 | ||
127 | static inline int h4_check_data_len(struct h4_struct *h4, int len) | 127 | static inline int h4_check_data_len(struct h4_struct *h4, int len) |
128 | { | 128 | { |
129 | register int room = skb_tailroom(h4->rx_skb); | 129 | int room = skb_tailroom(h4->rx_skb); |
130 | 130 | ||
131 | BT_DBG("len %d room %d", len, room); | 131 | BT_DBG("len %d room %d", len, room); |
132 | 132 | ||
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index e564579a611..2f9b796e106 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c | |||
@@ -394,7 +394,7 @@ static int hci_uart_register_dev(struct hci_uart *hu) | |||
394 | set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); | 394 | set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); |
395 | 395 | ||
396 | if (!test_bit(HCI_UART_RESET_ON_INIT, &hu->hdev_flags)) | 396 | if (!test_bit(HCI_UART_RESET_ON_INIT, &hu->hdev_flags)) |
397 | set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks); | 397 | set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); |
398 | 398 | ||
399 | if (test_bit(HCI_UART_CREATE_AMP, &hu->hdev_flags)) | 399 | if (test_bit(HCI_UART_CREATE_AMP, &hu->hdev_flags)) |
400 | hdev->dev_type = HCI_AMP; | 400 | hdev->dev_type = HCI_AMP; |
diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c index b874c0efde2..ff6d589c34a 100644 --- a/drivers/bluetooth/hci_ll.c +++ b/drivers/bluetooth/hci_ll.c | |||
@@ -348,7 +348,7 @@ static int ll_enqueue(struct hci_uart *hu, struct sk_buff *skb) | |||
348 | 348 | ||
349 | static inline int ll_check_data_len(struct ll_struct *ll, int len) | 349 | static inline int ll_check_data_len(struct ll_struct *ll, int len) |
350 | { | 350 | { |
351 | register int room = skb_tailroom(ll->rx_skb); | 351 | int room = skb_tailroom(ll->rx_skb); |
352 | 352 | ||
353 | BT_DBG("len %d room %d", len, room); | 353 | BT_DBG("len %d room %d", len, room); |
354 | 354 | ||
@@ -374,11 +374,11 @@ static inline int ll_check_data_len(struct ll_struct *ll, int len) | |||
374 | static int ll_recv(struct hci_uart *hu, void *data, int count) | 374 | static int ll_recv(struct hci_uart *hu, void *data, int count) |
375 | { | 375 | { |
376 | struct ll_struct *ll = hu->priv; | 376 | struct ll_struct *ll = hu->priv; |
377 | register char *ptr; | 377 | char *ptr; |
378 | struct hci_event_hdr *eh; | 378 | struct hci_event_hdr *eh; |
379 | struct hci_acl_hdr *ah; | 379 | struct hci_acl_hdr *ah; |
380 | struct hci_sco_hdr *sh; | 380 | struct hci_sco_hdr *sh; |
381 | register int len, type, dlen; | 381 | int len, type, dlen; |
382 | 382 | ||
383 | BT_DBG("hu %p count %d rx_state %ld rx_count %ld", hu, count, ll->rx_state, ll->rx_count); | 383 | BT_DBG("hu %p count %d rx_state %ld rx_count %ld", hu, count, ll->rx_state, ll->rx_count); |
384 | 384 | ||
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index b8fce0d4d72..aca1d2689e9 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c | |||
@@ -53,6 +53,11 @@ | |||
53 | 53 | ||
54 | #define DEFAULT_BG_SCAN_PERIOD 60 | 54 | #define DEFAULT_BG_SCAN_PERIOD 60 |
55 | 55 | ||
56 | struct ath6kl_cfg80211_match_probe_ssid { | ||
57 | struct cfg80211_ssid ssid; | ||
58 | u8 flag; | ||
59 | }; | ||
60 | |||
56 | static struct ieee80211_rate ath6kl_rates[] = { | 61 | static struct ieee80211_rate ath6kl_rates[] = { |
57 | RATETAB_ENT(10, 0x1, 0), | 62 | RATETAB_ENT(10, 0x1, 0), |
58 | RATETAB_ENT(20, 0x2, 0), | 63 | RATETAB_ENT(20, 0x2, 0), |
@@ -576,6 +581,9 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, | |||
576 | 581 | ||
577 | vif->nw_type = vif->next_mode; | 582 | vif->nw_type = vif->next_mode; |
578 | 583 | ||
584 | /* enable enhanced bmiss detection if applicable */ | ||
585 | ath6kl_cfg80211_sta_bmiss_enhance(vif, true); | ||
586 | |||
579 | if (vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) | 587 | if (vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) |
580 | nw_subtype = SUBTYPE_P2PCLIENT; | 588 | nw_subtype = SUBTYPE_P2PCLIENT; |
581 | 589 | ||
@@ -852,20 +860,6 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason, | |||
852 | } | 860 | } |
853 | } | 861 | } |
854 | 862 | ||
855 | /* | ||
856 | * Send a disconnect command to target when a disconnect event is | ||
857 | * received with reason code other than 3 (DISCONNECT_CMD - disconnect | ||
858 | * request from host) to make the firmware stop trying to connect even | ||
859 | * after giving disconnect event. There will be one more disconnect | ||
860 | * event for this disconnect command with reason code DISCONNECT_CMD | ||
861 | * which will be notified to cfg80211. | ||
862 | */ | ||
863 | |||
864 | if (reason != DISCONNECT_CMD) { | ||
865 | ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx); | ||
866 | return; | ||
867 | } | ||
868 | |||
869 | clear_bit(CONNECT_PEND, &vif->flags); | 863 | clear_bit(CONNECT_PEND, &vif->flags); |
870 | 864 | ||
871 | if (vif->sme_state == SME_CONNECTING) { | 865 | if (vif->sme_state == SME_CONNECTING) { |
@@ -875,32 +869,96 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason, | |||
875 | WLAN_STATUS_UNSPECIFIED_FAILURE, | 869 | WLAN_STATUS_UNSPECIFIED_FAILURE, |
876 | GFP_KERNEL); | 870 | GFP_KERNEL); |
877 | } else if (vif->sme_state == SME_CONNECTED) { | 871 | } else if (vif->sme_state == SME_CONNECTED) { |
878 | cfg80211_disconnected(vif->ndev, reason, | 872 | cfg80211_disconnected(vif->ndev, proto_reason, |
879 | NULL, 0, GFP_KERNEL); | 873 | NULL, 0, GFP_KERNEL); |
880 | } | 874 | } |
881 | 875 | ||
882 | vif->sme_state = SME_DISCONNECTED; | 876 | vif->sme_state = SME_DISCONNECTED; |
877 | |||
878 | /* | ||
879 | * Send a disconnect command to target when a disconnect event is | ||
880 | * received with reason code other than 3 (DISCONNECT_CMD - disconnect | ||
881 | * request from host) to make the firmware stop trying to connect even | ||
882 | * after giving disconnect event. There will be one more disconnect | ||
883 | * event for this disconnect command with reason code DISCONNECT_CMD | ||
884 | * which won't be notified to cfg80211. | ||
885 | */ | ||
886 | if (reason != DISCONNECT_CMD) | ||
887 | ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx); | ||
883 | } | 888 | } |
884 | 889 | ||
885 | static int ath6kl_set_probed_ssids(struct ath6kl *ar, | 890 | static int ath6kl_set_probed_ssids(struct ath6kl *ar, |
886 | struct ath6kl_vif *vif, | 891 | struct ath6kl_vif *vif, |
887 | struct cfg80211_ssid *ssids, int n_ssids) | 892 | struct cfg80211_ssid *ssids, int n_ssids, |
893 | struct cfg80211_match_set *match_set, | ||
894 | int n_match_ssid) | ||
888 | { | 895 | { |
889 | u8 i; | 896 | u8 i, j, index_to_add, ssid_found = false; |
897 | struct ath6kl_cfg80211_match_probe_ssid ssid_list[MAX_PROBED_SSIDS]; | ||
898 | |||
899 | memset(ssid_list, 0, sizeof(ssid_list)); | ||
890 | 900 | ||
891 | if (n_ssids > MAX_PROBED_SSID_INDEX) | 901 | if (n_ssids > MAX_PROBED_SSIDS || |
902 | n_match_ssid > MAX_PROBED_SSIDS) | ||
892 | return -EINVAL; | 903 | return -EINVAL; |
893 | 904 | ||
894 | for (i = 0; i < n_ssids; i++) { | 905 | for (i = 0; i < n_ssids; i++) { |
906 | memcpy(ssid_list[i].ssid.ssid, | ||
907 | ssids[i].ssid, | ||
908 | ssids[i].ssid_len); | ||
909 | ssid_list[i].ssid.ssid_len = ssids[i].ssid_len; | ||
910 | |||
911 | if (ssids[i].ssid_len) | ||
912 | ssid_list[i].flag = SPECIFIC_SSID_FLAG; | ||
913 | else | ||
914 | ssid_list[i].flag = ANY_SSID_FLAG; | ||
915 | |||
916 | if (n_match_ssid == 0) | ||
917 | ssid_list[i].flag |= MATCH_SSID_FLAG; | ||
918 | } | ||
919 | |||
920 | index_to_add = i; | ||
921 | |||
922 | for (i = 0; i < n_match_ssid; i++) { | ||
923 | ssid_found = false; | ||
924 | |||
925 | for (j = 0; j < n_ssids; j++) { | ||
926 | if ((match_set[i].ssid.ssid_len == | ||
927 | ssid_list[j].ssid.ssid_len) && | ||
928 | (!memcmp(ssid_list[j].ssid.ssid, | ||
929 | match_set[i].ssid.ssid, | ||
930 | match_set[i].ssid.ssid_len))) { | ||
931 | ssid_list[j].flag |= MATCH_SSID_FLAG; | ||
932 | ssid_found = true; | ||
933 | break; | ||
934 | } | ||
935 | } | ||
936 | |||
937 | if (ssid_found) | ||
938 | continue; | ||
939 | |||
940 | if (index_to_add >= MAX_PROBED_SSIDS) | ||
941 | continue; | ||
942 | |||
943 | ssid_list[index_to_add].ssid.ssid_len = | ||
944 | match_set[i].ssid.ssid_len; | ||
945 | memcpy(ssid_list[index_to_add].ssid.ssid, | ||
946 | match_set[i].ssid.ssid, | ||
947 | match_set[i].ssid.ssid_len); | ||
948 | ssid_list[index_to_add].flag |= MATCH_SSID_FLAG; | ||
949 | index_to_add++; | ||
950 | } | ||
951 | |||
952 | for (i = 0; i < index_to_add; i++) { | ||
895 | ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, i, | 953 | ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, i, |
896 | ssids[i].ssid_len ? | 954 | ssid_list[i].flag, |
897 | SPECIFIC_SSID_FLAG : ANY_SSID_FLAG, | 955 | ssid_list[i].ssid.ssid_len, |
898 | ssids[i].ssid_len, | 956 | ssid_list[i].ssid.ssid); |
899 | ssids[i].ssid); | 957 | |
900 | } | 958 | } |
901 | 959 | ||
902 | /* Make sure no old entries are left behind */ | 960 | /* Make sure no old entries are left behind */ |
903 | for (i = n_ssids; i < MAX_PROBED_SSID_INDEX; i++) { | 961 | for (i = index_to_add; i < MAX_PROBED_SSIDS; i++) { |
904 | ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, i, | 962 | ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, i, |
905 | DISABLE_SSID_FLAG, 0, NULL); | 963 | DISABLE_SSID_FLAG, 0, NULL); |
906 | } | 964 | } |
@@ -934,7 +992,7 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, | |||
934 | } | 992 | } |
935 | 993 | ||
936 | ret = ath6kl_set_probed_ssids(ar, vif, request->ssids, | 994 | ret = ath6kl_set_probed_ssids(ar, vif, request->ssids, |
937 | request->n_ssids); | 995 | request->n_ssids, NULL, 0); |
938 | if (ret < 0) | 996 | if (ret < 0) |
939 | return ret; | 997 | return ret; |
940 | 998 | ||
@@ -943,7 +1001,7 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, | |||
943 | WMI_FRAME_PROBE_REQ, | 1001 | WMI_FRAME_PROBE_REQ, |
944 | request->ie, request->ie_len); | 1002 | request->ie, request->ie_len); |
945 | if (ret) { | 1003 | if (ret) { |
946 | ath6kl_err("failed to set Probe Request appie for scan"); | 1004 | ath6kl_err("failed to set Probe Request appie for scan\n"); |
947 | return ret; | 1005 | return ret; |
948 | } | 1006 | } |
949 | 1007 | ||
@@ -1512,6 +1570,9 @@ static int ath6kl_cfg80211_change_iface(struct wiphy *wiphy, | |||
1512 | } | 1570 | } |
1513 | } | 1571 | } |
1514 | 1572 | ||
1573 | /* need to clean up enhanced bmiss detection fw state */ | ||
1574 | ath6kl_cfg80211_sta_bmiss_enhance(vif, false); | ||
1575 | |||
1515 | set_iface_type: | 1576 | set_iface_type: |
1516 | switch (type) { | 1577 | switch (type) { |
1517 | case NL80211_IFTYPE_STATION: | 1578 | case NL80211_IFTYPE_STATION: |
@@ -2074,7 +2135,9 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) | |||
2074 | if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST)) | 2135 | if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST)) |
2075 | return -EINVAL; | 2136 | return -EINVAL; |
2076 | 2137 | ||
2077 | if (!test_bit(NETDEV_MCAST_ALL_ON, &vif->flags)) { | 2138 | if (!test_bit(NETDEV_MCAST_ALL_ON, &vif->flags) && |
2139 | test_bit(ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER, | ||
2140 | ar->fw_capabilities)) { | ||
2078 | ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, | 2141 | ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, |
2079 | vif->fw_vif_idx, false); | 2142 | vif->fw_vif_idx, false); |
2080 | if (ret) | 2143 | if (ret) |
@@ -2209,7 +2272,9 @@ static int ath6kl_wow_resume(struct ath6kl *ar) | |||
2209 | 2272 | ||
2210 | ar->state = ATH6KL_STATE_ON; | 2273 | ar->state = ATH6KL_STATE_ON; |
2211 | 2274 | ||
2212 | if (!test_bit(NETDEV_MCAST_ALL_OFF, &vif->flags)) { | 2275 | if (!test_bit(NETDEV_MCAST_ALL_OFF, &vif->flags) && |
2276 | test_bit(ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER, | ||
2277 | ar->fw_capabilities)) { | ||
2213 | ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, | 2278 | ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, |
2214 | vif->fw_vif_idx, true); | 2279 | vif->fw_vif_idx, true); |
2215 | if (ret) | 2280 | if (ret) |
@@ -2475,7 +2540,7 @@ void ath6kl_check_wow_status(struct ath6kl *ar) | |||
2475 | static int ath6kl_set_htcap(struct ath6kl_vif *vif, enum ieee80211_band band, | 2540 | static int ath6kl_set_htcap(struct ath6kl_vif *vif, enum ieee80211_band band, |
2476 | bool ht_enable) | 2541 | bool ht_enable) |
2477 | { | 2542 | { |
2478 | struct ath6kl_htcap *htcap = &vif->htcap; | 2543 | struct ath6kl_htcap *htcap = &vif->htcap[band]; |
2479 | 2544 | ||
2480 | if (htcap->ht_enable == ht_enable) | 2545 | if (htcap->ht_enable == ht_enable) |
2481 | return 0; | 2546 | return 0; |
@@ -2585,6 +2650,30 @@ static int ath6kl_set_ies(struct ath6kl_vif *vif, | |||
2585 | return 0; | 2650 | return 0; |
2586 | } | 2651 | } |
2587 | 2652 | ||
2653 | void ath6kl_cfg80211_sta_bmiss_enhance(struct ath6kl_vif *vif, bool enable) | ||
2654 | { | ||
2655 | int err; | ||
2656 | |||
2657 | if (WARN_ON(!test_bit(WMI_READY, &vif->ar->flag))) | ||
2658 | return; | ||
2659 | |||
2660 | if (vif->nw_type != INFRA_NETWORK) | ||
2661 | return; | ||
2662 | |||
2663 | if (!test_bit(ATH6KL_FW_CAPABILITY_BMISS_ENHANCE, | ||
2664 | vif->ar->fw_capabilities)) | ||
2665 | return; | ||
2666 | |||
2667 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s fw bmiss enhance\n", | ||
2668 | enable ? "enable" : "disable"); | ||
2669 | |||
2670 | err = ath6kl_wmi_sta_bmiss_enhance_cmd(vif->ar->wmi, | ||
2671 | vif->fw_vif_idx, enable); | ||
2672 | if (err) | ||
2673 | ath6kl_err("failed to %s enhanced bmiss detection: %d\n", | ||
2674 | enable ? "enable" : "disable", err); | ||
2675 | } | ||
2676 | |||
2588 | static int ath6kl_get_rsn_capab(struct cfg80211_beacon_data *beacon, | 2677 | static int ath6kl_get_rsn_capab(struct cfg80211_beacon_data *beacon, |
2589 | u8 *rsn_capab) | 2678 | u8 *rsn_capab) |
2590 | { | 2679 | { |
@@ -2665,9 +2754,15 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
2665 | 2754 | ||
2666 | /* TODO: | 2755 | /* TODO: |
2667 | * info->interval | 2756 | * info->interval |
2668 | * info->dtim_period | ||
2669 | */ | 2757 | */ |
2670 | 2758 | ||
2759 | ret = ath6kl_wmi_ap_set_dtim_cmd(ar->wmi, vif->fw_vif_idx, | ||
2760 | info->dtim_period); | ||
2761 | |||
2762 | /* ignore error, just print a warning and continue normally */ | ||
2763 | if (ret) | ||
2764 | ath6kl_warn("Failed to set dtim_period in beacon: %d\n", ret); | ||
2765 | |||
2671 | if (info->beacon.head == NULL) | 2766 | if (info->beacon.head == NULL) |
2672 | return -EINVAL; | 2767 | return -EINVAL; |
2673 | mgmt = (struct ieee80211_mgmt *) info->beacon.head; | 2768 | mgmt = (struct ieee80211_mgmt *) info->beacon.head; |
@@ -3131,10 +3226,24 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy, | |||
3131 | ath6kl_cfg80211_scan_complete_event(vif, true); | 3226 | ath6kl_cfg80211_scan_complete_event(vif, true); |
3132 | 3227 | ||
3133 | ret = ath6kl_set_probed_ssids(ar, vif, request->ssids, | 3228 | ret = ath6kl_set_probed_ssids(ar, vif, request->ssids, |
3134 | request->n_ssids); | 3229 | request->n_ssids, |
3230 | request->match_sets, | ||
3231 | request->n_match_sets); | ||
3135 | if (ret < 0) | 3232 | if (ret < 0) |
3136 | return ret; | 3233 | return ret; |
3137 | 3234 | ||
3235 | if (!request->n_match_sets) { | ||
3236 | ret = ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx, | ||
3237 | ALL_BSS_FILTER, 0); | ||
3238 | if (ret < 0) | ||
3239 | return ret; | ||
3240 | } else { | ||
3241 | ret = ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx, | ||
3242 | MATCHED_SSID_FILTER, 0); | ||
3243 | if (ret < 0) | ||
3244 | return ret; | ||
3245 | } | ||
3246 | |||
3138 | /* fw uses seconds, also make sure that it's >0 */ | 3247 | /* fw uses seconds, also make sure that it's >0 */ |
3139 | interval = max_t(u16, 1, request->interval / 1000); | 3248 | interval = max_t(u16, 1, request->interval / 1000); |
3140 | 3249 | ||
@@ -3156,7 +3265,7 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy, | |||
3156 | WMI_FRAME_PROBE_REQ, | 3265 | WMI_FRAME_PROBE_REQ, |
3157 | request->ie, request->ie_len); | 3266 | request->ie, request->ie_len); |
3158 | if (ret) { | 3267 | if (ret) { |
3159 | ath6kl_warn("Failed to set probe request IE for scheduled scan: %d", | 3268 | ath6kl_warn("Failed to set probe request IE for scheduled scan: %d\n", |
3160 | ret); | 3269 | ret); |
3161 | return ret; | 3270 | return ret; |
3162 | } | 3271 | } |
@@ -3188,6 +3297,18 @@ static int ath6kl_cfg80211_sscan_stop(struct wiphy *wiphy, | |||
3188 | return 0; | 3297 | return 0; |
3189 | } | 3298 | } |
3190 | 3299 | ||
3300 | static int ath6kl_cfg80211_set_bitrate(struct wiphy *wiphy, | ||
3301 | struct net_device *dev, | ||
3302 | const u8 *addr, | ||
3303 | const struct cfg80211_bitrate_mask *mask) | ||
3304 | { | ||
3305 | struct ath6kl *ar = ath6kl_priv(dev); | ||
3306 | struct ath6kl_vif *vif = netdev_priv(dev); | ||
3307 | |||
3308 | return ath6kl_wmi_set_bitrate_mask(ar->wmi, vif->fw_vif_idx, | ||
3309 | mask); | ||
3310 | } | ||
3311 | |||
3191 | static const struct ieee80211_txrx_stypes | 3312 | static const struct ieee80211_txrx_stypes |
3192 | ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = { | 3313 | ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = { |
3193 | [NL80211_IFTYPE_STATION] = { | 3314 | [NL80211_IFTYPE_STATION] = { |
@@ -3253,6 +3374,7 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = { | |||
3253 | .mgmt_frame_register = ath6kl_mgmt_frame_register, | 3374 | .mgmt_frame_register = ath6kl_mgmt_frame_register, |
3254 | .sched_scan_start = ath6kl_cfg80211_sscan_start, | 3375 | .sched_scan_start = ath6kl_cfg80211_sscan_start, |
3255 | .sched_scan_stop = ath6kl_cfg80211_sscan_stop, | 3376 | .sched_scan_stop = ath6kl_cfg80211_sscan_stop, |
3377 | .set_bitrate_mask = ath6kl_cfg80211_set_bitrate, | ||
3256 | }; | 3378 | }; |
3257 | 3379 | ||
3258 | void ath6kl_cfg80211_stop(struct ath6kl_vif *vif) | 3380 | void ath6kl_cfg80211_stop(struct ath6kl_vif *vif) |
@@ -3380,7 +3502,8 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name, | |||
3380 | vif->listen_intvl_t = ATH6KL_DEFAULT_LISTEN_INTVAL; | 3502 | vif->listen_intvl_t = ATH6KL_DEFAULT_LISTEN_INTVAL; |
3381 | vif->bmiss_time_t = ATH6KL_DEFAULT_BMISS_TIME; | 3503 | vif->bmiss_time_t = ATH6KL_DEFAULT_BMISS_TIME; |
3382 | vif->bg_scan_period = 0; | 3504 | vif->bg_scan_period = 0; |
3383 | vif->htcap.ht_enable = true; | 3505 | vif->htcap[IEEE80211_BAND_2GHZ].ht_enable = true; |
3506 | vif->htcap[IEEE80211_BAND_5GHZ].ht_enable = true; | ||
3384 | 3507 | ||
3385 | memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN); | 3508 | memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN); |
3386 | if (fw_vif_idx != 0) | 3509 | if (fw_vif_idx != 0) |
@@ -3440,7 +3563,13 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) | |||
3440 | } | 3563 | } |
3441 | 3564 | ||
3442 | /* max num of ssids that can be probed during scanning */ | 3565 | /* max num of ssids that can be probed during scanning */ |
3443 | wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX; | 3566 | wiphy->max_scan_ssids = MAX_PROBED_SSIDS; |
3567 | |||
3568 | /* max num of ssids that can be matched after scan */ | ||
3569 | if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN_MATCH_LIST, | ||
3570 | ar->fw_capabilities)) | ||
3571 | wiphy->max_match_sets = MAX_PROBED_SSIDS; | ||
3572 | |||
3444 | wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */ | 3573 | wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */ |
3445 | switch (ar->hw.cap) { | 3574 | switch (ar->hw.cap) { |
3446 | case WMI_11AN_CAP: | 3575 | case WMI_11AN_CAP: |
@@ -3477,6 +3606,17 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) | |||
3477 | ath6kl_band_5ghz.ht_cap.cap = 0; | 3606 | ath6kl_band_5ghz.ht_cap.cap = 0; |
3478 | ath6kl_band_5ghz.ht_cap.ht_supported = false; | 3607 | ath6kl_band_5ghz.ht_cap.ht_supported = false; |
3479 | } | 3608 | } |
3609 | |||
3610 | if (ar->hw.flags & ATH6KL_HW_FLAG_64BIT_RATES) { | ||
3611 | ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff; | ||
3612 | ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff; | ||
3613 | ath6kl_band_2ghz.ht_cap.mcs.rx_mask[1] = 0xff; | ||
3614 | ath6kl_band_5ghz.ht_cap.mcs.rx_mask[1] = 0xff; | ||
3615 | } else { | ||
3616 | ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff; | ||
3617 | ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff; | ||
3618 | } | ||
3619 | |||
3480 | if (band_2gig) | 3620 | if (band_2gig) |
3481 | wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz; | 3621 | wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz; |
3482 | if (band_5gig) | 3622 | if (band_5gig) |
@@ -3499,7 +3639,7 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) | |||
3499 | wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE; | 3639 | wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE; |
3500 | #endif | 3640 | #endif |
3501 | 3641 | ||
3502 | wiphy->max_sched_scan_ssids = MAX_PROBED_SSID_INDEX; | 3642 | wiphy->max_sched_scan_ssids = MAX_PROBED_SSIDS; |
3503 | 3643 | ||
3504 | ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM | | 3644 | ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM | |
3505 | WIPHY_FLAG_HAVE_AP_SME | | 3645 | WIPHY_FLAG_HAVE_AP_SME | |
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.h b/drivers/net/wireless/ath/ath6kl/cfg80211.h index 5ea8cbb79f4..b992046a1b0 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.h +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.h | |||
@@ -62,5 +62,7 @@ void ath6kl_cfg80211_cleanup(struct ath6kl *ar); | |||
62 | 62 | ||
63 | struct ath6kl *ath6kl_cfg80211_create(void); | 63 | struct ath6kl *ath6kl_cfg80211_create(void); |
64 | void ath6kl_cfg80211_destroy(struct ath6kl *ar); | 64 | void ath6kl_cfg80211_destroy(struct ath6kl *ar); |
65 | /* TODO: remove this once ath6kl_vif_cleanup() is moved to cfg80211.c */ | ||
66 | void ath6kl_cfg80211_sta_bmiss_enhance(struct ath6kl_vif *vif, bool enable); | ||
65 | 67 | ||
66 | #endif /* ATH6KL_CFG80211_H */ | 68 | #endif /* ATH6KL_CFG80211_H */ |
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index 8443b2a4133..d38a31de344 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h | |||
@@ -100,6 +100,21 @@ enum ath6kl_fw_capability { | |||
100 | /* Firmware has support to override rsn cap of rsn ie */ | 100 | /* Firmware has support to override rsn cap of rsn ie */ |
101 | ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE, | 101 | ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE, |
102 | 102 | ||
103 | /* | ||
104 | * Multicast support in WOW and host awake mode. | ||
105 | * Allow all multicast in host awake mode. | ||
106 | * Apply multicast filter in WOW mode. | ||
107 | */ | ||
108 | ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER, | ||
109 | |||
110 | /* Firmware supports enhanced bmiss detection */ | ||
111 | ATH6KL_FW_CAPABILITY_BMISS_ENHANCE, | ||
112 | |||
113 | /* | ||
114 | * FW supports matching of ssid in schedule scan | ||
115 | */ | ||
116 | ATH6KL_FW_CAPABILITY_SCHED_SCAN_MATCH_LIST, | ||
117 | |||
103 | /* this needs to be last */ | 118 | /* this needs to be last */ |
104 | ATH6KL_FW_CAPABILITY_MAX, | 119 | ATH6KL_FW_CAPABILITY_MAX, |
105 | }; | 120 | }; |
@@ -112,6 +127,10 @@ struct ath6kl_fw_ie { | |||
112 | u8 data[0]; | 127 | u8 data[0]; |
113 | }; | 128 | }; |
114 | 129 | ||
130 | enum ath6kl_hw_flags { | ||
131 | ATH6KL_HW_FLAG_64BIT_RATES = BIT(0), | ||
132 | }; | ||
133 | |||
115 | #define ATH6KL_FW_API2_FILE "fw-2.bin" | 134 | #define ATH6KL_FW_API2_FILE "fw-2.bin" |
116 | #define ATH6KL_FW_API3_FILE "fw-3.bin" | 135 | #define ATH6KL_FW_API3_FILE "fw-3.bin" |
117 | 136 | ||
@@ -196,7 +215,7 @@ struct ath6kl_fw_ie { | |||
196 | 215 | ||
197 | #define AGGR_NUM_OF_FREE_NETBUFS 16 | 216 | #define AGGR_NUM_OF_FREE_NETBUFS 16 |
198 | 217 | ||
199 | #define AGGR_RX_TIMEOUT 400 /* in ms */ | 218 | #define AGGR_RX_TIMEOUT 100 /* in ms */ |
200 | 219 | ||
201 | #define WMI_TIMEOUT (2 * HZ) | 220 | #define WMI_TIMEOUT (2 * HZ) |
202 | 221 | ||
@@ -245,7 +264,6 @@ struct skb_hold_q { | |||
245 | 264 | ||
246 | struct rxtid { | 265 | struct rxtid { |
247 | bool aggr; | 266 | bool aggr; |
248 | bool progress; | ||
249 | bool timer_mon; | 267 | bool timer_mon; |
250 | u16 win_sz; | 268 | u16 win_sz; |
251 | u16 seq_next; | 269 | u16 seq_next; |
@@ -254,9 +272,15 @@ struct rxtid { | |||
254 | struct sk_buff_head q; | 272 | struct sk_buff_head q; |
255 | 273 | ||
256 | /* | 274 | /* |
257 | * FIXME: No clue what this should protect. Apparently it should | 275 | * lock mainly protects seq_next and hold_q. Movement of seq_next |
258 | * protect some of the fields above but they are also accessed | 276 | * needs to be protected between aggr_timeout() and |
259 | * without taking the lock. | 277 | * aggr_process_recv_frm(). hold_q will be holding the pending |
278 | * reorder frames and it's access should also be protected. | ||
279 | * Some of the other fields like hold_q_sz, win_sz and aggr are | ||
280 | * initialized/reset when receiving addba/delba req, also while | ||
281 | * deleting aggr state all the pending buffers are flushed before | ||
282 | * resetting these fields, so there should not be any race in accessing | ||
283 | * these fields. | ||
260 | */ | 284 | */ |
261 | spinlock_t lock; | 285 | spinlock_t lock; |
262 | }; | 286 | }; |
@@ -541,7 +565,7 @@ struct ath6kl_vif { | |||
541 | struct ath6kl_wep_key wep_key_list[WMI_MAX_KEY_INDEX + 1]; | 565 | struct ath6kl_wep_key wep_key_list[WMI_MAX_KEY_INDEX + 1]; |
542 | struct ath6kl_key keys[WMI_MAX_KEY_INDEX + 1]; | 566 | struct ath6kl_key keys[WMI_MAX_KEY_INDEX + 1]; |
543 | struct aggr_info *aggr_cntxt; | 567 | struct aggr_info *aggr_cntxt; |
544 | struct ath6kl_htcap htcap; | 568 | struct ath6kl_htcap htcap[IEEE80211_NUM_BANDS]; |
545 | 569 | ||
546 | struct timer_list disconnect_timer; | 570 | struct timer_list disconnect_timer; |
547 | struct timer_list sched_scan_timer; | 571 | struct timer_list sched_scan_timer; |
@@ -684,6 +708,8 @@ struct ath6kl { | |||
684 | u32 testscript_addr; | 708 | u32 testscript_addr; |
685 | enum wmi_phy_cap cap; | 709 | enum wmi_phy_cap cap; |
686 | 710 | ||
711 | u32 flags; | ||
712 | |||
687 | struct ath6kl_hw_fw { | 713 | struct ath6kl_hw_fw { |
688 | const char *dir; | 714 | const char *dir; |
689 | const char *otp; | 715 | const char *otp; |
diff --git a/drivers/net/wireless/ath/ath6kl/htc_mbox.c b/drivers/net/wireless/ath/ath6kl/htc_mbox.c index 2798624d3a9..cd0e1ba410d 100644 --- a/drivers/net/wireless/ath/ath6kl/htc_mbox.c +++ b/drivers/net/wireless/ath/ath6kl/htc_mbox.c | |||
@@ -1309,7 +1309,7 @@ static int ath6kl_htc_rx_packet(struct htc_target *target, | |||
1309 | } | 1309 | } |
1310 | 1310 | ||
1311 | ath6kl_dbg(ATH6KL_DBG_HTC, | 1311 | ath6kl_dbg(ATH6KL_DBG_HTC, |
1312 | "htc rx 0x%p hdr x%x len %d mbox 0x%x\n", | 1312 | "htc rx 0x%p hdr 0x%x len %d mbox 0x%x\n", |
1313 | packet, packet->info.rx.exp_hdr, | 1313 | packet, packet->info.rx.exp_hdr, |
1314 | padded_len, dev->ar->mbox_info.htc_addr); | 1314 | padded_len, dev->ar->mbox_info.htc_addr); |
1315 | 1315 | ||
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 7eb0515f458..f90b5db741c 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c | |||
@@ -42,6 +42,7 @@ static const struct ath6kl_hw hw_list[] = { | |||
42 | .reserved_ram_size = 6912, | 42 | .reserved_ram_size = 6912, |
43 | .refclk_hz = 26000000, | 43 | .refclk_hz = 26000000, |
44 | .uarttx_pin = 8, | 44 | .uarttx_pin = 8, |
45 | .flags = 0, | ||
45 | 46 | ||
46 | /* hw2.0 needs override address hardcoded */ | 47 | /* hw2.0 needs override address hardcoded */ |
47 | .app_start_override_addr = 0x944C00, | 48 | .app_start_override_addr = 0x944C00, |
@@ -67,6 +68,7 @@ static const struct ath6kl_hw hw_list[] = { | |||
67 | .refclk_hz = 26000000, | 68 | .refclk_hz = 26000000, |
68 | .uarttx_pin = 8, | 69 | .uarttx_pin = 8, |
69 | .testscript_addr = 0x57ef74, | 70 | .testscript_addr = 0x57ef74, |
71 | .flags = 0, | ||
70 | 72 | ||
71 | .fw = { | 73 | .fw = { |
72 | .dir = AR6003_HW_2_1_1_FW_DIR, | 74 | .dir = AR6003_HW_2_1_1_FW_DIR, |
@@ -91,6 +93,7 @@ static const struct ath6kl_hw hw_list[] = { | |||
91 | .board_addr = 0x433900, | 93 | .board_addr = 0x433900, |
92 | .refclk_hz = 26000000, | 94 | .refclk_hz = 26000000, |
93 | .uarttx_pin = 11, | 95 | .uarttx_pin = 11, |
96 | .flags = ATH6KL_HW_FLAG_64BIT_RATES, | ||
94 | 97 | ||
95 | .fw = { | 98 | .fw = { |
96 | .dir = AR6004_HW_1_0_FW_DIR, | 99 | .dir = AR6004_HW_1_0_FW_DIR, |
@@ -110,6 +113,7 @@ static const struct ath6kl_hw hw_list[] = { | |||
110 | .board_addr = 0x43d400, | 113 | .board_addr = 0x43d400, |
111 | .refclk_hz = 40000000, | 114 | .refclk_hz = 40000000, |
112 | .uarttx_pin = 11, | 115 | .uarttx_pin = 11, |
116 | .flags = ATH6KL_HW_FLAG_64BIT_RATES, | ||
113 | 117 | ||
114 | .fw = { | 118 | .fw = { |
115 | .dir = AR6004_HW_1_1_FW_DIR, | 119 | .dir = AR6004_HW_1_1_FW_DIR, |
@@ -129,6 +133,7 @@ static const struct ath6kl_hw hw_list[] = { | |||
129 | .board_addr = 0x435c00, | 133 | .board_addr = 0x435c00, |
130 | .refclk_hz = 40000000, | 134 | .refclk_hz = 40000000, |
131 | .uarttx_pin = 11, | 135 | .uarttx_pin = 11, |
136 | .flags = ATH6KL_HW_FLAG_64BIT_RATES, | ||
132 | 137 | ||
133 | .fw = { | 138 | .fw = { |
134 | .dir = AR6004_HW_1_2_FW_DIR, | 139 | .dir = AR6004_HW_1_2_FW_DIR, |
@@ -938,6 +943,14 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name) | |||
938 | } | 943 | } |
939 | 944 | ||
940 | switch (ie_id) { | 945 | switch (ie_id) { |
946 | case ATH6KL_FW_IE_FW_VERSION: | ||
947 | strlcpy(ar->wiphy->fw_version, data, | ||
948 | sizeof(ar->wiphy->fw_version)); | ||
949 | |||
950 | ath6kl_dbg(ATH6KL_DBG_BOOT, | ||
951 | "found fw version %s\n", | ||
952 | ar->wiphy->fw_version); | ||
953 | break; | ||
941 | case ATH6KL_FW_IE_OTP_IMAGE: | 954 | case ATH6KL_FW_IE_OTP_IMAGE: |
942 | ath6kl_dbg(ATH6KL_DBG_BOOT, "found otp image ie (%zd B)\n", | 955 | ath6kl_dbg(ATH6KL_DBG_BOOT, "found otp image ie (%zd B)\n", |
943 | ie_len); | 956 | ie_len); |
@@ -991,9 +1004,6 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name) | |||
991 | ar->hw.reserved_ram_size); | 1004 | ar->hw.reserved_ram_size); |
992 | break; | 1005 | break; |
993 | case ATH6KL_FW_IE_CAPABILITIES: | 1006 | case ATH6KL_FW_IE_CAPABILITIES: |
994 | if (ie_len < DIV_ROUND_UP(ATH6KL_FW_CAPABILITY_MAX, 8)) | ||
995 | break; | ||
996 | |||
997 | ath6kl_dbg(ATH6KL_DBG_BOOT, | 1007 | ath6kl_dbg(ATH6KL_DBG_BOOT, |
998 | "found firmware capabilities ie (%zd B)\n", | 1008 | "found firmware capabilities ie (%zd B)\n", |
999 | ie_len); | 1009 | ie_len); |
@@ -1002,6 +1012,9 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name) | |||
1002 | index = i / 8; | 1012 | index = i / 8; |
1003 | bit = i % 8; | 1013 | bit = i % 8; |
1004 | 1014 | ||
1015 | if (index == ie_len) | ||
1016 | break; | ||
1017 | |||
1005 | if (data[index] & (1 << bit)) | 1018 | if (data[index] & (1 << bit)) |
1006 | __set_bit(i, ar->fw_capabilities); | 1019 | __set_bit(i, ar->fw_capabilities); |
1007 | } | 1020 | } |
@@ -1392,6 +1405,12 @@ static int ath6kl_init_upload(struct ath6kl *ar) | |||
1392 | ar->version.target_ver == AR6003_HW_2_1_1_VERSION) { | 1405 | ar->version.target_ver == AR6003_HW_2_1_1_VERSION) { |
1393 | ath6kl_err("temporary war to avoid sdio crc error\n"); | 1406 | ath6kl_err("temporary war to avoid sdio crc error\n"); |
1394 | 1407 | ||
1408 | param = 0x28; | ||
1409 | address = GPIO_BASE_ADDRESS + GPIO_PIN9_ADDRESS; | ||
1410 | status = ath6kl_bmi_reg_write(ar, address, param); | ||
1411 | if (status) | ||
1412 | return status; | ||
1413 | |||
1395 | param = 0x20; | 1414 | param = 0x20; |
1396 | 1415 | ||
1397 | address = GPIO_BASE_ADDRESS + GPIO_PIN10_ADDRESS; | 1416 | address = GPIO_BASE_ADDRESS + GPIO_PIN10_ADDRESS; |
@@ -1659,6 +1678,9 @@ void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready) | |||
1659 | cfg80211_scan_done(vif->scan_req, true); | 1678 | cfg80211_scan_done(vif->scan_req, true); |
1660 | vif->scan_req = NULL; | 1679 | vif->scan_req = NULL; |
1661 | } | 1680 | } |
1681 | |||
1682 | /* need to clean up enhanced bmiss detection fw state */ | ||
1683 | ath6kl_cfg80211_sta_bmiss_enhance(vif, false); | ||
1662 | } | 1684 | } |
1663 | 1685 | ||
1664 | void ath6kl_stop_txrx(struct ath6kl *ar) | 1686 | void ath6kl_stop_txrx(struct ath6kl *ar) |
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index b836f279511..c189e28e86a 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c | |||
@@ -554,20 +554,24 @@ void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver, | |||
554 | struct ath6kl *ar = devt; | 554 | struct ath6kl *ar = devt; |
555 | 555 | ||
556 | memcpy(ar->mac_addr, datap, ETH_ALEN); | 556 | memcpy(ar->mac_addr, datap, ETH_ALEN); |
557 | ath6kl_dbg(ATH6KL_DBG_TRC, "%s: mac addr = %pM\n", | 557 | |
558 | __func__, ar->mac_addr); | 558 | ath6kl_dbg(ATH6KL_DBG_BOOT, |
559 | "ready event mac addr %pM sw_ver 0x%x abi_ver 0x%x cap 0x%x\n", | ||
560 | ar->mac_addr, sw_ver, abi_ver, cap); | ||
559 | 561 | ||
560 | ar->version.wlan_ver = sw_ver; | 562 | ar->version.wlan_ver = sw_ver; |
561 | ar->version.abi_ver = abi_ver; | 563 | ar->version.abi_ver = abi_ver; |
562 | ar->hw.cap = cap; | 564 | ar->hw.cap = cap; |
563 | 565 | ||
564 | snprintf(ar->wiphy->fw_version, | 566 | if (strlen(ar->wiphy->fw_version) == 0) { |
565 | sizeof(ar->wiphy->fw_version), | 567 | snprintf(ar->wiphy->fw_version, |
566 | "%u.%u.%u.%u", | 568 | sizeof(ar->wiphy->fw_version), |
567 | (ar->version.wlan_ver & 0xf0000000) >> 28, | 569 | "%u.%u.%u.%u", |
568 | (ar->version.wlan_ver & 0x0f000000) >> 24, | 570 | (ar->version.wlan_ver & 0xf0000000) >> 28, |
569 | (ar->version.wlan_ver & 0x00ff0000) >> 16, | 571 | (ar->version.wlan_ver & 0x0f000000) >> 24, |
570 | (ar->version.wlan_ver & 0x0000ffff)); | 572 | (ar->version.wlan_ver & 0x00ff0000) >> 16, |
573 | (ar->version.wlan_ver & 0x0000ffff)); | ||
574 | } | ||
571 | 575 | ||
572 | /* indicate to the waiting thread that the ready event was received */ | 576 | /* indicate to the waiting thread that the ready event was received */ |
573 | set_bit(WMI_READY, &ar->flag); | 577 | set_bit(WMI_READY, &ar->flag); |
@@ -1166,7 +1170,10 @@ static void ath6kl_set_multicast_list(struct net_device *ndev) | |||
1166 | else | 1170 | else |
1167 | clear_bit(NETDEV_MCAST_ALL_ON, &vif->flags); | 1171 | clear_bit(NETDEV_MCAST_ALL_ON, &vif->flags); |
1168 | 1172 | ||
1169 | mc_all_on = mc_all_on || (vif->ar->state == ATH6KL_STATE_ON); | 1173 | if (test_bit(ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER, |
1174 | vif->ar->fw_capabilities)) { | ||
1175 | mc_all_on = mc_all_on || (vif->ar->state == ATH6KL_STATE_ON); | ||
1176 | } | ||
1170 | 1177 | ||
1171 | if (!(ndev->flags & IFF_MULTICAST)) { | 1178 | if (!(ndev->flags & IFF_MULTICAST)) { |
1172 | mc_all_on = false; | 1179 | mc_all_on = false; |
diff --git a/drivers/net/wireless/ath/ath6kl/target.h b/drivers/net/wireless/ath/ath6kl/target.h index 78e0ef4567a..a98c12ba70c 100644 --- a/drivers/net/wireless/ath/ath6kl/target.h +++ b/drivers/net/wireless/ath/ath6kl/target.h | |||
@@ -45,6 +45,7 @@ | |||
45 | #define LPO_CAL_ENABLE_S 20 | 45 | #define LPO_CAL_ENABLE_S 20 |
46 | #define LPO_CAL_ENABLE 0x00100000 | 46 | #define LPO_CAL_ENABLE 0x00100000 |
47 | 47 | ||
48 | #define GPIO_PIN9_ADDRESS 0x0000004c | ||
48 | #define GPIO_PIN10_ADDRESS 0x00000050 | 49 | #define GPIO_PIN10_ADDRESS 0x00000050 |
49 | #define GPIO_PIN11_ADDRESS 0x00000054 | 50 | #define GPIO_PIN11_ADDRESS 0x00000054 |
50 | #define GPIO_PIN12_ADDRESS 0x00000058 | 51 | #define GPIO_PIN12_ADDRESS 0x00000058 |
diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c index 67206aedea6..7dfa0fd86d7 100644 --- a/drivers/net/wireless/ath/ath6kl/txrx.c +++ b/drivers/net/wireless/ath/ath6kl/txrx.c | |||
@@ -1036,6 +1036,7 @@ static void aggr_deque_frms(struct aggr_info_conn *agg_conn, u8 tid, | |||
1036 | rxtid = &agg_conn->rx_tid[tid]; | 1036 | rxtid = &agg_conn->rx_tid[tid]; |
1037 | stats = &agg_conn->stat[tid]; | 1037 | stats = &agg_conn->stat[tid]; |
1038 | 1038 | ||
1039 | spin_lock_bh(&rxtid->lock); | ||
1039 | idx = AGGR_WIN_IDX(rxtid->seq_next, rxtid->hold_q_sz); | 1040 | idx = AGGR_WIN_IDX(rxtid->seq_next, rxtid->hold_q_sz); |
1040 | 1041 | ||
1041 | /* | 1042 | /* |
@@ -1054,8 +1055,6 @@ static void aggr_deque_frms(struct aggr_info_conn *agg_conn, u8 tid, | |||
1054 | seq_end = seq_no ? seq_no : rxtid->seq_next; | 1055 | seq_end = seq_no ? seq_no : rxtid->seq_next; |
1055 | idx_end = AGGR_WIN_IDX(seq_end, rxtid->hold_q_sz); | 1056 | idx_end = AGGR_WIN_IDX(seq_end, rxtid->hold_q_sz); |
1056 | 1057 | ||
1057 | spin_lock_bh(&rxtid->lock); | ||
1058 | |||
1059 | do { | 1058 | do { |
1060 | node = &rxtid->hold_q[idx]; | 1059 | node = &rxtid->hold_q[idx]; |
1061 | if ((order == 1) && (!node->skb)) | 1060 | if ((order == 1) && (!node->skb)) |
@@ -1127,11 +1126,13 @@ static bool aggr_process_recv_frm(struct aggr_info_conn *agg_conn, u8 tid, | |||
1127 | ((end > extended_end) && (cur > extended_end) && | 1126 | ((end > extended_end) && (cur > extended_end) && |
1128 | (cur < end))) { | 1127 | (cur < end))) { |
1129 | aggr_deque_frms(agg_conn, tid, 0, 0); | 1128 | aggr_deque_frms(agg_conn, tid, 0, 0); |
1129 | spin_lock_bh(&rxtid->lock); | ||
1130 | if (cur >= rxtid->hold_q_sz - 1) | 1130 | if (cur >= rxtid->hold_q_sz - 1) |
1131 | rxtid->seq_next = cur - (rxtid->hold_q_sz - 1); | 1131 | rxtid->seq_next = cur - (rxtid->hold_q_sz - 1); |
1132 | else | 1132 | else |
1133 | rxtid->seq_next = ATH6KL_MAX_SEQ_NO - | 1133 | rxtid->seq_next = ATH6KL_MAX_SEQ_NO - |
1134 | (rxtid->hold_q_sz - 2 - cur); | 1134 | (rxtid->hold_q_sz - 2 - cur); |
1135 | spin_unlock_bh(&rxtid->lock); | ||
1135 | } else { | 1136 | } else { |
1136 | /* | 1137 | /* |
1137 | * Dequeue only those frames that are outside the | 1138 | * Dequeue only those frames that are outside the |
@@ -1185,25 +1186,25 @@ static bool aggr_process_recv_frm(struct aggr_info_conn *agg_conn, u8 tid, | |||
1185 | aggr_deque_frms(agg_conn, tid, 0, 1); | 1186 | aggr_deque_frms(agg_conn, tid, 0, 1); |
1186 | 1187 | ||
1187 | if (agg_conn->timer_scheduled) | 1188 | if (agg_conn->timer_scheduled) |
1188 | rxtid->progress = true; | 1189 | return is_queued; |
1189 | else | 1190 | |
1190 | for (idx = 0 ; idx < rxtid->hold_q_sz; idx++) { | 1191 | spin_lock_bh(&rxtid->lock); |
1191 | if (rxtid->hold_q[idx].skb) { | 1192 | for (idx = 0 ; idx < rxtid->hold_q_sz; idx++) { |
1192 | /* | 1193 | if (rxtid->hold_q[idx].skb) { |
1193 | * There is a frame in the queue and no | 1194 | /* |
1194 | * timer so start a timer to ensure that | 1195 | * There is a frame in the queue and no |
1195 | * the frame doesn't remain stuck | 1196 | * timer so start a timer to ensure that |
1196 | * forever. | 1197 | * the frame doesn't remain stuck |
1197 | */ | 1198 | * forever. |
1198 | agg_conn->timer_scheduled = true; | 1199 | */ |
1199 | mod_timer(&agg_conn->timer, | 1200 | agg_conn->timer_scheduled = true; |
1200 | (jiffies + | 1201 | mod_timer(&agg_conn->timer, |
1201 | HZ * (AGGR_RX_TIMEOUT) / 1000)); | 1202 | (jiffies + (HZ * AGGR_RX_TIMEOUT) / 1000)); |
1202 | rxtid->progress = false; | 1203 | rxtid->timer_mon = true; |
1203 | rxtid->timer_mon = true; | 1204 | break; |
1204 | break; | ||
1205 | } | ||
1206 | } | 1205 | } |
1206 | } | ||
1207 | spin_unlock_bh(&rxtid->lock); | ||
1207 | 1208 | ||
1208 | return is_queued; | 1209 | return is_queued; |
1209 | } | 1210 | } |
@@ -1608,7 +1609,7 @@ static void aggr_timeout(unsigned long arg) | |||
1608 | rxtid = &aggr_conn->rx_tid[i]; | 1609 | rxtid = &aggr_conn->rx_tid[i]; |
1609 | stats = &aggr_conn->stat[i]; | 1610 | stats = &aggr_conn->stat[i]; |
1610 | 1611 | ||
1611 | if (!rxtid->aggr || !rxtid->timer_mon || rxtid->progress) | 1612 | if (!rxtid->aggr || !rxtid->timer_mon) |
1612 | continue; | 1613 | continue; |
1613 | 1614 | ||
1614 | stats->num_timeouts++; | 1615 | stats->num_timeouts++; |
@@ -1626,14 +1627,15 @@ static void aggr_timeout(unsigned long arg) | |||
1626 | rxtid = &aggr_conn->rx_tid[i]; | 1627 | rxtid = &aggr_conn->rx_tid[i]; |
1627 | 1628 | ||
1628 | if (rxtid->aggr && rxtid->hold_q) { | 1629 | if (rxtid->aggr && rxtid->hold_q) { |
1630 | spin_lock_bh(&rxtid->lock); | ||
1629 | for (j = 0; j < rxtid->hold_q_sz; j++) { | 1631 | for (j = 0; j < rxtid->hold_q_sz; j++) { |
1630 | if (rxtid->hold_q[j].skb) { | 1632 | if (rxtid->hold_q[j].skb) { |
1631 | aggr_conn->timer_scheduled = true; | 1633 | aggr_conn->timer_scheduled = true; |
1632 | rxtid->timer_mon = true; | 1634 | rxtid->timer_mon = true; |
1633 | rxtid->progress = false; | ||
1634 | break; | 1635 | break; |
1635 | } | 1636 | } |
1636 | } | 1637 | } |
1638 | spin_unlock_bh(&rxtid->lock); | ||
1637 | 1639 | ||
1638 | if (j >= rxtid->hold_q_sz) | 1640 | if (j >= rxtid->hold_q_sz) |
1639 | rxtid->timer_mon = false; | 1641 | rxtid->timer_mon = false; |
@@ -1660,7 +1662,6 @@ static void aggr_delete_tid_state(struct aggr_info_conn *aggr_conn, u8 tid) | |||
1660 | aggr_deque_frms(aggr_conn, tid, 0, 0); | 1662 | aggr_deque_frms(aggr_conn, tid, 0, 0); |
1661 | 1663 | ||
1662 | rxtid->aggr = false; | 1664 | rxtid->aggr = false; |
1663 | rxtid->progress = false; | ||
1664 | rxtid->timer_mon = false; | 1665 | rxtid->timer_mon = false; |
1665 | rxtid->win_sz = 0; | 1666 | rxtid->win_sz = 0; |
1666 | rxtid->seq_next = 0; | 1667 | rxtid->seq_next = 0; |
@@ -1739,7 +1740,6 @@ void aggr_conn_init(struct ath6kl_vif *vif, struct aggr_info *aggr_info, | |||
1739 | for (i = 0; i < NUM_OF_TIDS; i++) { | 1740 | for (i = 0; i < NUM_OF_TIDS; i++) { |
1740 | rxtid = &aggr_conn->rx_tid[i]; | 1741 | rxtid = &aggr_conn->rx_tid[i]; |
1741 | rxtid->aggr = false; | 1742 | rxtid->aggr = false; |
1742 | rxtid->progress = false; | ||
1743 | rxtid->timer_mon = false; | 1743 | rxtid->timer_mon = false; |
1744 | skb_queue_head_init(&rxtid->q); | 1744 | skb_queue_head_init(&rxtid->q); |
1745 | spin_lock_init(&rxtid->lock); | 1745 | spin_lock_init(&rxtid->lock); |
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index ee8ec2394c2..a6caa673e8a 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c | |||
@@ -743,7 +743,6 @@ int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid) | |||
743 | return -ENOMEM; | 743 | return -ENOMEM; |
744 | 744 | ||
745 | cmd = (struct roam_ctrl_cmd *) skb->data; | 745 | cmd = (struct roam_ctrl_cmd *) skb->data; |
746 | memset(cmd, 0, sizeof(*cmd)); | ||
747 | 746 | ||
748 | memcpy(cmd->info.bssid, bssid, ETH_ALEN); | 747 | memcpy(cmd->info.bssid, bssid, ETH_ALEN); |
749 | cmd->roam_ctrl = WMI_FORCE_ROAM; | 748 | cmd->roam_ctrl = WMI_FORCE_ROAM; |
@@ -753,6 +752,22 @@ int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid) | |||
753 | NO_SYNC_WMIFLAG); | 752 | NO_SYNC_WMIFLAG); |
754 | } | 753 | } |
755 | 754 | ||
755 | int ath6kl_wmi_ap_set_dtim_cmd(struct wmi *wmi, u8 if_idx, u32 dtim_period) | ||
756 | { | ||
757 | struct sk_buff *skb; | ||
758 | struct set_dtim_cmd *cmd; | ||
759 | |||
760 | skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); | ||
761 | if (!skb) | ||
762 | return -ENOMEM; | ||
763 | |||
764 | cmd = (struct set_dtim_cmd *) skb->data; | ||
765 | |||
766 | cmd->dtim_period = cpu_to_le32(dtim_period); | ||
767 | return ath6kl_wmi_cmd_send(wmi, if_idx, skb, | ||
768 | WMI_AP_SET_DTIM_CMDID, NO_SYNC_WMIFLAG); | ||
769 | } | ||
770 | |||
756 | int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode) | 771 | int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode) |
757 | { | 772 | { |
758 | struct sk_buff *skb; | 773 | struct sk_buff *skb; |
@@ -763,7 +778,6 @@ int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode) | |||
763 | return -ENOMEM; | 778 | return -ENOMEM; |
764 | 779 | ||
765 | cmd = (struct roam_ctrl_cmd *) skb->data; | 780 | cmd = (struct roam_ctrl_cmd *) skb->data; |
766 | memset(cmd, 0, sizeof(*cmd)); | ||
767 | 781 | ||
768 | cmd->info.roam_mode = mode; | 782 | cmd->info.roam_mode = mode; |
769 | cmd->roam_ctrl = WMI_SET_ROAM_MODE; | 783 | cmd->roam_ctrl = WMI_SET_ROAM_MODE; |
@@ -1995,7 +2009,7 @@ int ath6kl_wmi_probedssid_cmd(struct wmi *wmi, u8 if_idx, u8 index, u8 flag, | |||
1995 | struct wmi_probed_ssid_cmd *cmd; | 2009 | struct wmi_probed_ssid_cmd *cmd; |
1996 | int ret; | 2010 | int ret; |
1997 | 2011 | ||
1998 | if (index > MAX_PROBED_SSID_INDEX) | 2012 | if (index >= MAX_PROBED_SSIDS) |
1999 | return -EINVAL; | 2013 | return -EINVAL; |
2000 | 2014 | ||
2001 | if (ssid_len > sizeof(cmd->ssid)) | 2015 | if (ssid_len > sizeof(cmd->ssid)) |
@@ -2599,6 +2613,115 @@ static void ath6kl_wmi_relinquish_implicit_pstream_credits(struct wmi *wmi) | |||
2599 | spin_unlock_bh(&wmi->lock); | 2613 | spin_unlock_bh(&wmi->lock); |
2600 | } | 2614 | } |
2601 | 2615 | ||
2616 | static int ath6kl_set_bitrate_mask64(struct wmi *wmi, u8 if_idx, | ||
2617 | const struct cfg80211_bitrate_mask *mask) | ||
2618 | { | ||
2619 | struct sk_buff *skb; | ||
2620 | int ret, mode, band; | ||
2621 | u64 mcsrate, ratemask[IEEE80211_NUM_BANDS]; | ||
2622 | struct wmi_set_tx_select_rates64_cmd *cmd; | ||
2623 | |||
2624 | memset(&ratemask, 0, sizeof(ratemask)); | ||
2625 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | ||
2626 | /* copy legacy rate mask */ | ||
2627 | ratemask[band] = mask->control[band].legacy; | ||
2628 | if (band == IEEE80211_BAND_5GHZ) | ||
2629 | ratemask[band] = | ||
2630 | mask->control[band].legacy << 4; | ||
2631 | |||
2632 | /* copy mcs rate mask */ | ||
2633 | mcsrate = mask->control[band].mcs[1]; | ||
2634 | mcsrate <<= 8; | ||
2635 | mcsrate |= mask->control[band].mcs[0]; | ||
2636 | ratemask[band] |= mcsrate << 12; | ||
2637 | ratemask[band] |= mcsrate << 28; | ||
2638 | } | ||
2639 | |||
2640 | ath6kl_dbg(ATH6KL_DBG_WMI, | ||
2641 | "Ratemask 64 bit: 2.4:%llx 5:%llx\n", | ||
2642 | ratemask[0], ratemask[1]); | ||
2643 | |||
2644 | skb = ath6kl_wmi_get_new_buf(sizeof(*cmd) * WMI_RATES_MODE_MAX); | ||
2645 | if (!skb) | ||
2646 | return -ENOMEM; | ||
2647 | |||
2648 | cmd = (struct wmi_set_tx_select_rates64_cmd *) skb->data; | ||
2649 | for (mode = 0; mode < WMI_RATES_MODE_MAX; mode++) { | ||
2650 | /* A mode operate in 5GHZ band */ | ||
2651 | if (mode == WMI_RATES_MODE_11A || | ||
2652 | mode == WMI_RATES_MODE_11A_HT20 || | ||
2653 | mode == WMI_RATES_MODE_11A_HT40) | ||
2654 | band = IEEE80211_BAND_5GHZ; | ||
2655 | else | ||
2656 | band = IEEE80211_BAND_2GHZ; | ||
2657 | cmd->ratemask[mode] = cpu_to_le64(ratemask[band]); | ||
2658 | } | ||
2659 | |||
2660 | ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, | ||
2661 | WMI_SET_TX_SELECT_RATES_CMDID, | ||
2662 | NO_SYNC_WMIFLAG); | ||
2663 | return ret; | ||
2664 | } | ||
2665 | |||
2666 | static int ath6kl_set_bitrate_mask32(struct wmi *wmi, u8 if_idx, | ||
2667 | const struct cfg80211_bitrate_mask *mask) | ||
2668 | { | ||
2669 | struct sk_buff *skb; | ||
2670 | int ret, mode, band; | ||
2671 | u32 mcsrate, ratemask[IEEE80211_NUM_BANDS]; | ||
2672 | struct wmi_set_tx_select_rates32_cmd *cmd; | ||
2673 | |||
2674 | memset(&ratemask, 0, sizeof(ratemask)); | ||
2675 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | ||
2676 | /* copy legacy rate mask */ | ||
2677 | ratemask[band] = mask->control[band].legacy; | ||
2678 | if (band == IEEE80211_BAND_5GHZ) | ||
2679 | ratemask[band] = | ||
2680 | mask->control[band].legacy << 4; | ||
2681 | |||
2682 | /* copy mcs rate mask */ | ||
2683 | mcsrate = mask->control[band].mcs[0]; | ||
2684 | ratemask[band] |= mcsrate << 12; | ||
2685 | ratemask[band] |= mcsrate << 20; | ||
2686 | } | ||
2687 | |||
2688 | ath6kl_dbg(ATH6KL_DBG_WMI, | ||
2689 | "Ratemask 32 bit: 2.4:%x 5:%x\n", | ||
2690 | ratemask[0], ratemask[1]); | ||
2691 | |||
2692 | skb = ath6kl_wmi_get_new_buf(sizeof(*cmd) * WMI_RATES_MODE_MAX); | ||
2693 | if (!skb) | ||
2694 | return -ENOMEM; | ||
2695 | |||
2696 | cmd = (struct wmi_set_tx_select_rates32_cmd *) skb->data; | ||
2697 | for (mode = 0; mode < WMI_RATES_MODE_MAX; mode++) { | ||
2698 | /* A mode operate in 5GHZ band */ | ||
2699 | if (mode == WMI_RATES_MODE_11A || | ||
2700 | mode == WMI_RATES_MODE_11A_HT20 || | ||
2701 | mode == WMI_RATES_MODE_11A_HT40) | ||
2702 | band = IEEE80211_BAND_5GHZ; | ||
2703 | else | ||
2704 | band = IEEE80211_BAND_2GHZ; | ||
2705 | cmd->ratemask[mode] = cpu_to_le32(ratemask[band]); | ||
2706 | } | ||
2707 | |||
2708 | ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, | ||
2709 | WMI_SET_TX_SELECT_RATES_CMDID, | ||
2710 | NO_SYNC_WMIFLAG); | ||
2711 | return ret; | ||
2712 | } | ||
2713 | |||
2714 | int ath6kl_wmi_set_bitrate_mask(struct wmi *wmi, u8 if_idx, | ||
2715 | const struct cfg80211_bitrate_mask *mask) | ||
2716 | { | ||
2717 | struct ath6kl *ar = wmi->parent_dev; | ||
2718 | |||
2719 | if (ar->hw.flags & ATH6KL_HW_FLAG_64BIT_RATES) | ||
2720 | return ath6kl_set_bitrate_mask64(wmi, if_idx, mask); | ||
2721 | else | ||
2722 | return ath6kl_set_bitrate_mask32(wmi, if_idx, mask); | ||
2723 | } | ||
2724 | |||
2602 | int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx, | 2725 | int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx, |
2603 | enum ath6kl_host_mode host_mode) | 2726 | enum ath6kl_host_mode host_mode) |
2604 | { | 2727 | { |
@@ -2997,6 +3120,25 @@ int ath6kl_wmi_add_del_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, | |||
2997 | return ret; | 3120 | return ret; |
2998 | } | 3121 | } |
2999 | 3122 | ||
3123 | int ath6kl_wmi_sta_bmiss_enhance_cmd(struct wmi *wmi, u8 if_idx, bool enhance) | ||
3124 | { | ||
3125 | struct sk_buff *skb; | ||
3126 | struct wmi_sta_bmiss_enhance_cmd *cmd; | ||
3127 | int ret; | ||
3128 | |||
3129 | skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); | ||
3130 | if (!skb) | ||
3131 | return -ENOMEM; | ||
3132 | |||
3133 | cmd = (struct wmi_sta_bmiss_enhance_cmd *) skb->data; | ||
3134 | cmd->enable = enhance ? 1 : 0; | ||
3135 | |||
3136 | ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, | ||
3137 | WMI_STA_BMISS_ENHANCE_CMDID, | ||
3138 | NO_SYNC_WMIFLAG); | ||
3139 | return ret; | ||
3140 | } | ||
3141 | |||
3000 | s32 ath6kl_wmi_get_rate(s8 rate_index) | 3142 | s32 ath6kl_wmi_get_rate(s8 rate_index) |
3001 | { | 3143 | { |
3002 | if (rate_index == RATE_AUTO) | 3144 | if (rate_index == RATE_AUTO) |
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h index 9076bec3a2b..43339aca585 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.h +++ b/drivers/net/wireless/ath/ath6kl/wmi.h | |||
@@ -624,6 +624,10 @@ enum wmi_cmd_id { | |||
624 | WMI_SEND_MGMT_CMDID, | 624 | WMI_SEND_MGMT_CMDID, |
625 | WMI_BEGIN_SCAN_CMDID, | 625 | WMI_BEGIN_SCAN_CMDID, |
626 | 626 | ||
627 | WMI_SET_BLACK_LIST, | ||
628 | WMI_SET_MCASTRATE, | ||
629 | |||
630 | WMI_STA_BMISS_ENHANCE_CMDID, | ||
627 | }; | 631 | }; |
628 | 632 | ||
629 | enum wmi_mgmt_frame_type { | 633 | enum wmi_mgmt_frame_type { |
@@ -960,6 +964,9 @@ enum wmi_bss_filter { | |||
960 | /* beacons matching probed ssid */ | 964 | /* beacons matching probed ssid */ |
961 | PROBED_SSID_FILTER, | 965 | PROBED_SSID_FILTER, |
962 | 966 | ||
967 | /* beacons matching matched ssid */ | ||
968 | MATCHED_SSID_FILTER, | ||
969 | |||
963 | /* marker only */ | 970 | /* marker only */ |
964 | LAST_BSS_FILTER, | 971 | LAST_BSS_FILTER, |
965 | }; | 972 | }; |
@@ -978,7 +985,7 @@ struct wmi_bss_filter_cmd { | |||
978 | } __packed; | 985 | } __packed; |
979 | 986 | ||
980 | /* WMI_SET_PROBED_SSID_CMDID */ | 987 | /* WMI_SET_PROBED_SSID_CMDID */ |
981 | #define MAX_PROBED_SSID_INDEX 9 | 988 | #define MAX_PROBED_SSIDS 16 |
982 | 989 | ||
983 | enum wmi_ssid_flag { | 990 | enum wmi_ssid_flag { |
984 | /* disables entry */ | 991 | /* disables entry */ |
@@ -989,10 +996,13 @@ enum wmi_ssid_flag { | |||
989 | 996 | ||
990 | /* probes for any ssid */ | 997 | /* probes for any ssid */ |
991 | ANY_SSID_FLAG = 0x02, | 998 | ANY_SSID_FLAG = 0x02, |
999 | |||
1000 | /* match for ssid */ | ||
1001 | MATCH_SSID_FLAG = 0x08, | ||
992 | }; | 1002 | }; |
993 | 1003 | ||
994 | struct wmi_probed_ssid_cmd { | 1004 | struct wmi_probed_ssid_cmd { |
995 | /* 0 to MAX_PROBED_SSID_INDEX */ | 1005 | /* 0 to MAX_PROBED_SSIDS - 1 */ |
996 | u8 entry_index; | 1006 | u8 entry_index; |
997 | 1007 | ||
998 | /* see, enum wmi_ssid_flg */ | 1008 | /* see, enum wmi_ssid_flg */ |
@@ -1017,6 +1027,11 @@ struct wmi_bmiss_time_cmd { | |||
1017 | __le16 num_beacons; | 1027 | __le16 num_beacons; |
1018 | }; | 1028 | }; |
1019 | 1029 | ||
1030 | /* WMI_STA_ENHANCE_BMISS_CMDID */ | ||
1031 | struct wmi_sta_bmiss_enhance_cmd { | ||
1032 | u8 enable; | ||
1033 | } __packed; | ||
1034 | |||
1020 | /* WMI_SET_POWER_MODE_CMDID */ | 1035 | /* WMI_SET_POWER_MODE_CMDID */ |
1021 | enum wmi_power_mode { | 1036 | enum wmi_power_mode { |
1022 | REC_POWER = 0x01, | 1037 | REC_POWER = 0x01, |
@@ -1048,6 +1063,36 @@ struct wmi_power_params_cmd { | |||
1048 | __le16 ps_fail_event_policy; | 1063 | __le16 ps_fail_event_policy; |
1049 | } __packed; | 1064 | } __packed; |
1050 | 1065 | ||
1066 | /* | ||
1067 | * Ratemask for below modes should be passed | ||
1068 | * to WMI_SET_TX_SELECT_RATES_CMDID. | ||
1069 | * AR6003 has 32 bit mask for each modes. | ||
1070 | * First 12 bits for legacy rates, 13 to 20 | ||
1071 | * bits for HT 20 rates and 21 to 28 bits for | ||
1072 | * HT 40 rates | ||
1073 | */ | ||
1074 | enum wmi_mode_phy { | ||
1075 | WMI_RATES_MODE_11A = 0, | ||
1076 | WMI_RATES_MODE_11G, | ||
1077 | WMI_RATES_MODE_11B, | ||
1078 | WMI_RATES_MODE_11GONLY, | ||
1079 | WMI_RATES_MODE_11A_HT20, | ||
1080 | WMI_RATES_MODE_11G_HT20, | ||
1081 | WMI_RATES_MODE_11A_HT40, | ||
1082 | WMI_RATES_MODE_11G_HT40, | ||
1083 | WMI_RATES_MODE_MAX | ||
1084 | }; | ||
1085 | |||
1086 | /* WMI_SET_TX_SELECT_RATES_CMDID */ | ||
1087 | struct wmi_set_tx_select_rates32_cmd { | ||
1088 | __le32 ratemask[WMI_RATES_MODE_MAX]; | ||
1089 | } __packed; | ||
1090 | |||
1091 | /* WMI_SET_TX_SELECT_RATES_CMDID */ | ||
1092 | struct wmi_set_tx_select_rates64_cmd { | ||
1093 | __le64 ratemask[WMI_RATES_MODE_MAX]; | ||
1094 | } __packed; | ||
1095 | |||
1051 | /* WMI_SET_DISC_TIMEOUT_CMDID */ | 1096 | /* WMI_SET_DISC_TIMEOUT_CMDID */ |
1052 | struct wmi_disc_timeout_cmd { | 1097 | struct wmi_disc_timeout_cmd { |
1053 | /* seconds */ | 1098 | /* seconds */ |
@@ -1572,6 +1617,10 @@ struct roam_ctrl_cmd { | |||
1572 | u8 roam_ctrl; | 1617 | u8 roam_ctrl; |
1573 | } __packed; | 1618 | } __packed; |
1574 | 1619 | ||
1620 | struct set_dtim_cmd { | ||
1621 | __le32 dtim_period; | ||
1622 | } __packed; | ||
1623 | |||
1575 | /* BSS INFO HDR version 2.0 */ | 1624 | /* BSS INFO HDR version 2.0 */ |
1576 | struct wmi_bss_info_hdr2 { | 1625 | struct wmi_bss_info_hdr2 { |
1577 | __le16 ch; /* frequency in MHz */ | 1626 | __le16 ch; /* frequency in MHz */ |
@@ -2532,6 +2581,8 @@ int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, u8 if_idx, | |||
2532 | __be32 ips0, __be32 ips1); | 2581 | __be32 ips0, __be32 ips1); |
2533 | int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx, | 2582 | int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx, |
2534 | enum ath6kl_host_mode host_mode); | 2583 | enum ath6kl_host_mode host_mode); |
2584 | int ath6kl_wmi_set_bitrate_mask(struct wmi *wmi, u8 if_idx, | ||
2585 | const struct cfg80211_bitrate_mask *mask); | ||
2535 | int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx, | 2586 | int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx, |
2536 | enum ath6kl_wow_mode wow_mode, | 2587 | enum ath6kl_wow_mode wow_mode, |
2537 | u32 filter, u16 host_req_delay); | 2588 | u32 filter, u16 host_req_delay); |
@@ -2542,11 +2593,14 @@ int ath6kl_wmi_add_wow_pattern_cmd(struct wmi *wmi, u8 if_idx, | |||
2542 | int ath6kl_wmi_del_wow_pattern_cmd(struct wmi *wmi, u8 if_idx, | 2593 | int ath6kl_wmi_del_wow_pattern_cmd(struct wmi *wmi, u8 if_idx, |
2543 | u16 list_id, u16 filter_id); | 2594 | u16 list_id, u16 filter_id); |
2544 | int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi); | 2595 | int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi); |
2596 | int ath6kl_wmi_ap_set_dtim_cmd(struct wmi *wmi, u8 if_idx, u32 dtim_period); | ||
2545 | int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid); | 2597 | int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid); |
2546 | int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode); | 2598 | int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode); |
2547 | int ath6kl_wmi_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, bool mc_all_on); | 2599 | int ath6kl_wmi_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, bool mc_all_on); |
2548 | int ath6kl_wmi_add_del_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, | 2600 | int ath6kl_wmi_add_del_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, |
2549 | u8 *filter, bool add_filter); | 2601 | u8 *filter, bool add_filter); |
2602 | int ath6kl_wmi_sta_bmiss_enhance_cmd(struct wmi *wmi, u8 if_idx, bool enable); | ||
2603 | |||
2550 | /* AP mode uAPSD */ | 2604 | /* AP mode uAPSD */ |
2551 | int ath6kl_wmi_ap_set_apsd(struct wmi *wmi, u8 if_idx, u8 enable); | 2605 | int ath6kl_wmi_ap_set_apsd(struct wmi *wmi, u8 if_idx, u8 enable); |
2552 | 2606 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index b4c77f9d747..7ebc3465f22 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c | |||
@@ -104,11 +104,6 @@ static const struct ani_cck_level_entry cck_level_table[] = { | |||
104 | #define ATH9K_ANI_CCK_DEF_LEVEL \ | 104 | #define ATH9K_ANI_CCK_DEF_LEVEL \ |
105 | 2 /* default level - matches the INI settings */ | 105 | 2 /* default level - matches the INI settings */ |
106 | 106 | ||
107 | static bool use_new_ani(struct ath_hw *ah) | ||
108 | { | ||
109 | return AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani; | ||
110 | } | ||
111 | |||
112 | static void ath9k_hw_update_mibstats(struct ath_hw *ah, | 107 | static void ath9k_hw_update_mibstats(struct ath_hw *ah, |
113 | struct ath9k_mib_stats *stats) | 108 | struct ath9k_mib_stats *stats) |
114 | { | 109 | { |
@@ -122,8 +117,6 @@ static void ath9k_hw_update_mibstats(struct ath_hw *ah, | |||
122 | static void ath9k_ani_restart(struct ath_hw *ah) | 117 | static void ath9k_ani_restart(struct ath_hw *ah) |
123 | { | 118 | { |
124 | struct ar5416AniState *aniState; | 119 | struct ar5416AniState *aniState; |
125 | struct ath_common *common = ath9k_hw_common(ah); | ||
126 | u32 ofdm_base = 0, cck_base = 0; | ||
127 | 120 | ||
128 | if (!DO_ANI(ah)) | 121 | if (!DO_ANI(ah)) |
129 | return; | 122 | return; |
@@ -131,18 +124,10 @@ static void ath9k_ani_restart(struct ath_hw *ah) | |||
131 | aniState = &ah->curchan->ani; | 124 | aniState = &ah->curchan->ani; |
132 | aniState->listenTime = 0; | 125 | aniState->listenTime = 0; |
133 | 126 | ||
134 | if (!use_new_ani(ah)) { | ||
135 | ofdm_base = AR_PHY_COUNTMAX - ah->config.ofdm_trig_high; | ||
136 | cck_base = AR_PHY_COUNTMAX - ah->config.cck_trig_high; | ||
137 | } | ||
138 | |||
139 | ath_dbg(common, ANI, "Writing ofdmbase=%u cckbase=%u\n", | ||
140 | ofdm_base, cck_base); | ||
141 | |||
142 | ENABLE_REGWRITE_BUFFER(ah); | 127 | ENABLE_REGWRITE_BUFFER(ah); |
143 | 128 | ||
144 | REG_WRITE(ah, AR_PHY_ERR_1, ofdm_base); | 129 | REG_WRITE(ah, AR_PHY_ERR_1, 0); |
145 | REG_WRITE(ah, AR_PHY_ERR_2, cck_base); | 130 | REG_WRITE(ah, AR_PHY_ERR_2, 0); |
146 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); | 131 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); |
147 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); | 132 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); |
148 | 133 | ||
@@ -154,110 +139,6 @@ static void ath9k_ani_restart(struct ath_hw *ah) | |||
154 | aniState->cckPhyErrCount = 0; | 139 | aniState->cckPhyErrCount = 0; |
155 | } | 140 | } |
156 | 141 | ||
157 | static void ath9k_hw_ani_ofdm_err_trigger_old(struct ath_hw *ah) | ||
158 | { | ||
159 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; | ||
160 | struct ar5416AniState *aniState; | ||
161 | int32_t rssi; | ||
162 | |||
163 | aniState = &ah->curchan->ani; | ||
164 | |||
165 | if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) { | ||
166 | if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, | ||
167 | aniState->noiseImmunityLevel + 1)) { | ||
168 | return; | ||
169 | } | ||
170 | } | ||
171 | |||
172 | if (aniState->spurImmunityLevel < HAL_SPUR_IMMUNE_MAX) { | ||
173 | if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, | ||
174 | aniState->spurImmunityLevel + 1)) { | ||
175 | return; | ||
176 | } | ||
177 | } | ||
178 | |||
179 | if (ah->opmode == NL80211_IFTYPE_AP) { | ||
180 | if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) { | ||
181 | ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, | ||
182 | aniState->firstepLevel + 1); | ||
183 | } | ||
184 | return; | ||
185 | } | ||
186 | rssi = BEACON_RSSI(ah); | ||
187 | if (rssi > aniState->rssiThrHigh) { | ||
188 | if (!aniState->ofdmWeakSigDetectOff) { | ||
189 | if (ath9k_hw_ani_control(ah, | ||
190 | ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, | ||
191 | false)) { | ||
192 | ath9k_hw_ani_control(ah, | ||
193 | ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0); | ||
194 | return; | ||
195 | } | ||
196 | } | ||
197 | if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) { | ||
198 | ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, | ||
199 | aniState->firstepLevel + 1); | ||
200 | return; | ||
201 | } | ||
202 | } else if (rssi > aniState->rssiThrLow) { | ||
203 | if (aniState->ofdmWeakSigDetectOff) | ||
204 | ath9k_hw_ani_control(ah, | ||
205 | ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, | ||
206 | true); | ||
207 | if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) | ||
208 | ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, | ||
209 | aniState->firstepLevel + 1); | ||
210 | return; | ||
211 | } else { | ||
212 | if ((conf->channel->band == IEEE80211_BAND_2GHZ) && | ||
213 | !conf_is_ht(conf)) { | ||
214 | if (!aniState->ofdmWeakSigDetectOff) | ||
215 | ath9k_hw_ani_control(ah, | ||
216 | ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, | ||
217 | false); | ||
218 | if (aniState->firstepLevel > 0) | ||
219 | ath9k_hw_ani_control(ah, | ||
220 | ATH9K_ANI_FIRSTEP_LEVEL, 0); | ||
221 | return; | ||
222 | } | ||
223 | } | ||
224 | } | ||
225 | |||
226 | static void ath9k_hw_ani_cck_err_trigger_old(struct ath_hw *ah) | ||
227 | { | ||
228 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; | ||
229 | struct ar5416AniState *aniState; | ||
230 | int32_t rssi; | ||
231 | |||
232 | aniState = &ah->curchan->ani; | ||
233 | if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) { | ||
234 | if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, | ||
235 | aniState->noiseImmunityLevel + 1)) { | ||
236 | return; | ||
237 | } | ||
238 | } | ||
239 | if (ah->opmode == NL80211_IFTYPE_AP) { | ||
240 | if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) { | ||
241 | ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, | ||
242 | aniState->firstepLevel + 1); | ||
243 | } | ||
244 | return; | ||
245 | } | ||
246 | rssi = BEACON_RSSI(ah); | ||
247 | if (rssi > aniState->rssiThrLow) { | ||
248 | if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) | ||
249 | ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, | ||
250 | aniState->firstepLevel + 1); | ||
251 | } else { | ||
252 | if ((conf->channel->band == IEEE80211_BAND_2GHZ) && | ||
253 | !conf_is_ht(conf)) { | ||
254 | if (aniState->firstepLevel > 0) | ||
255 | ath9k_hw_ani_control(ah, | ||
256 | ATH9K_ANI_FIRSTEP_LEVEL, 0); | ||
257 | } | ||
258 | } | ||
259 | } | ||
260 | |||
261 | /* Adjust the OFDM Noise Immunity Level */ | 142 | /* Adjust the OFDM Noise Immunity Level */ |
262 | static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel) | 143 | static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel) |
263 | { | 144 | { |
@@ -265,18 +146,15 @@ static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel) | |||
265 | struct ath_common *common = ath9k_hw_common(ah); | 146 | struct ath_common *common = ath9k_hw_common(ah); |
266 | const struct ani_ofdm_level_entry *entry_ofdm; | 147 | const struct ani_ofdm_level_entry *entry_ofdm; |
267 | const struct ani_cck_level_entry *entry_cck; | 148 | const struct ani_cck_level_entry *entry_cck; |
268 | 149 | bool weak_sig; | |
269 | aniState->noiseFloor = BEACON_RSSI(ah); | ||
270 | 150 | ||
271 | ath_dbg(common, ANI, "**** ofdmlevel %d=>%d, rssi=%d[lo=%d hi=%d]\n", | 151 | ath_dbg(common, ANI, "**** ofdmlevel %d=>%d, rssi=%d[lo=%d hi=%d]\n", |
272 | aniState->ofdmNoiseImmunityLevel, | 152 | aniState->ofdmNoiseImmunityLevel, |
273 | immunityLevel, aniState->noiseFloor, | 153 | immunityLevel, BEACON_RSSI(ah), |
274 | aniState->rssiThrLow, aniState->rssiThrHigh); | 154 | aniState->rssiThrLow, aniState->rssiThrHigh); |
275 | 155 | ||
276 | if (aniState->update_ani) | 156 | if (aniState->update_ani) |
277 | aniState->ofdmNoiseImmunityLevel = | 157 | aniState->ofdmNoiseImmunityLevel = immunityLevel; |
278 | (immunityLevel > ATH9K_ANI_OFDM_DEF_LEVEL) ? | ||
279 | immunityLevel : ATH9K_ANI_OFDM_DEF_LEVEL; | ||
280 | 158 | ||
281 | entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel]; | 159 | entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel]; |
282 | entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel]; | 160 | entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel]; |
@@ -292,12 +170,22 @@ static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel) | |||
292 | ATH9K_ANI_FIRSTEP_LEVEL, | 170 | ATH9K_ANI_FIRSTEP_LEVEL, |
293 | entry_ofdm->fir_step_level); | 171 | entry_ofdm->fir_step_level); |
294 | 172 | ||
295 | if ((aniState->noiseFloor >= aniState->rssiThrHigh) && | 173 | weak_sig = entry_ofdm->ofdm_weak_signal_on; |
296 | (!aniState->ofdmWeakSigDetectOff != | 174 | if (ah->opmode == NL80211_IFTYPE_STATION && |
297 | entry_ofdm->ofdm_weak_signal_on)) { | 175 | BEACON_RSSI(ah) <= aniState->rssiThrHigh) |
176 | weak_sig = true; | ||
177 | |||
178 | if (aniState->ofdmWeakSigDetect != weak_sig) | ||
298 | ath9k_hw_ani_control(ah, | 179 | ath9k_hw_ani_control(ah, |
299 | ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, | 180 | ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, |
300 | entry_ofdm->ofdm_weak_signal_on); | 181 | entry_ofdm->ofdm_weak_signal_on); |
182 | |||
183 | if (aniState->ofdmNoiseImmunityLevel >= ATH9K_ANI_OFDM_DEF_LEVEL) { | ||
184 | ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH; | ||
185 | ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_ABOVE_INI; | ||
186 | } else { | ||
187 | ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_BELOW_INI; | ||
188 | ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW; | ||
301 | } | 189 | } |
302 | } | 190 | } |
303 | 191 | ||
@@ -308,11 +196,6 @@ static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah) | |||
308 | if (!DO_ANI(ah)) | 196 | if (!DO_ANI(ah)) |
309 | return; | 197 | return; |
310 | 198 | ||
311 | if (!use_new_ani(ah)) { | ||
312 | ath9k_hw_ani_ofdm_err_trigger_old(ah); | ||
313 | return; | ||
314 | } | ||
315 | |||
316 | aniState = &ah->curchan->ani; | 199 | aniState = &ah->curchan->ani; |
317 | 200 | ||
318 | if (aniState->ofdmNoiseImmunityLevel < ATH9K_ANI_OFDM_MAX_LEVEL) | 201 | if (aniState->ofdmNoiseImmunityLevel < ATH9K_ANI_OFDM_MAX_LEVEL) |
@@ -329,22 +212,18 @@ static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel) | |||
329 | const struct ani_ofdm_level_entry *entry_ofdm; | 212 | const struct ani_ofdm_level_entry *entry_ofdm; |
330 | const struct ani_cck_level_entry *entry_cck; | 213 | const struct ani_cck_level_entry *entry_cck; |
331 | 214 | ||
332 | aniState->noiseFloor = BEACON_RSSI(ah); | ||
333 | ath_dbg(common, ANI, "**** ccklevel %d=>%d, rssi=%d[lo=%d hi=%d]\n", | 215 | ath_dbg(common, ANI, "**** ccklevel %d=>%d, rssi=%d[lo=%d hi=%d]\n", |
334 | aniState->cckNoiseImmunityLevel, immunityLevel, | 216 | aniState->cckNoiseImmunityLevel, immunityLevel, |
335 | aniState->noiseFloor, aniState->rssiThrLow, | 217 | BEACON_RSSI(ah), aniState->rssiThrLow, |
336 | aniState->rssiThrHigh); | 218 | aniState->rssiThrHigh); |
337 | 219 | ||
338 | if ((ah->opmode == NL80211_IFTYPE_STATION || | 220 | if (ah->opmode == NL80211_IFTYPE_STATION && |
339 | ah->opmode == NL80211_IFTYPE_ADHOC) && | 221 | BEACON_RSSI(ah) <= aniState->rssiThrLow && |
340 | aniState->noiseFloor <= aniState->rssiThrLow && | ||
341 | immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI) | 222 | immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI) |
342 | immunityLevel = ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI; | 223 | immunityLevel = ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI; |
343 | 224 | ||
344 | if (aniState->update_ani) | 225 | if (aniState->update_ani) |
345 | aniState->cckNoiseImmunityLevel = | 226 | aniState->cckNoiseImmunityLevel = immunityLevel; |
346 | (immunityLevel > ATH9K_ANI_CCK_DEF_LEVEL) ? | ||
347 | immunityLevel : ATH9K_ANI_CCK_DEF_LEVEL; | ||
348 | 227 | ||
349 | entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel]; | 228 | entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel]; |
350 | entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel]; | 229 | entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel]; |
@@ -359,7 +238,7 @@ static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel) | |||
359 | if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9485(ah)) | 238 | if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9485(ah)) |
360 | return; | 239 | return; |
361 | 240 | ||
362 | if (aniState->mrcCCKOff == entry_cck->mrc_cck_on) | 241 | if (aniState->mrcCCK != entry_cck->mrc_cck_on) |
363 | ath9k_hw_ani_control(ah, | 242 | ath9k_hw_ani_control(ah, |
364 | ATH9K_ANI_MRC_CCK, | 243 | ATH9K_ANI_MRC_CCK, |
365 | entry_cck->mrc_cck_on); | 244 | entry_cck->mrc_cck_on); |
@@ -372,70 +251,12 @@ static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah) | |||
372 | if (!DO_ANI(ah)) | 251 | if (!DO_ANI(ah)) |
373 | return; | 252 | return; |
374 | 253 | ||
375 | if (!use_new_ani(ah)) { | ||
376 | ath9k_hw_ani_cck_err_trigger_old(ah); | ||
377 | return; | ||
378 | } | ||
379 | |||
380 | aniState = &ah->curchan->ani; | 254 | aniState = &ah->curchan->ani; |
381 | 255 | ||
382 | if (aniState->cckNoiseImmunityLevel < ATH9K_ANI_CCK_MAX_LEVEL) | 256 | if (aniState->cckNoiseImmunityLevel < ATH9K_ANI_CCK_MAX_LEVEL) |
383 | ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel + 1); | 257 | ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel + 1); |
384 | } | 258 | } |
385 | 259 | ||
386 | static void ath9k_hw_ani_lower_immunity_old(struct ath_hw *ah) | ||
387 | { | ||
388 | struct ar5416AniState *aniState; | ||
389 | int32_t rssi; | ||
390 | |||
391 | aniState = &ah->curchan->ani; | ||
392 | |||
393 | if (ah->opmode == NL80211_IFTYPE_AP) { | ||
394 | if (aniState->firstepLevel > 0) { | ||
395 | if (ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, | ||
396 | aniState->firstepLevel - 1)) | ||
397 | return; | ||
398 | } | ||
399 | } else { | ||
400 | rssi = BEACON_RSSI(ah); | ||
401 | if (rssi > aniState->rssiThrHigh) { | ||
402 | /* XXX: Handle me */ | ||
403 | } else if (rssi > aniState->rssiThrLow) { | ||
404 | if (aniState->ofdmWeakSigDetectOff) { | ||
405 | if (ath9k_hw_ani_control(ah, | ||
406 | ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, | ||
407 | true)) | ||
408 | return; | ||
409 | } | ||
410 | if (aniState->firstepLevel > 0) { | ||
411 | if (ath9k_hw_ani_control(ah, | ||
412 | ATH9K_ANI_FIRSTEP_LEVEL, | ||
413 | aniState->firstepLevel - 1)) | ||
414 | return; | ||
415 | } | ||
416 | } else { | ||
417 | if (aniState->firstepLevel > 0) { | ||
418 | if (ath9k_hw_ani_control(ah, | ||
419 | ATH9K_ANI_FIRSTEP_LEVEL, | ||
420 | aniState->firstepLevel - 1)) | ||
421 | return; | ||
422 | } | ||
423 | } | ||
424 | } | ||
425 | |||
426 | if (aniState->spurImmunityLevel > 0) { | ||
427 | if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, | ||
428 | aniState->spurImmunityLevel - 1)) | ||
429 | return; | ||
430 | } | ||
431 | |||
432 | if (aniState->noiseImmunityLevel > 0) { | ||
433 | ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, | ||
434 | aniState->noiseImmunityLevel - 1); | ||
435 | return; | ||
436 | } | ||
437 | } | ||
438 | |||
439 | /* | 260 | /* |
440 | * only lower either OFDM or CCK errors per turn | 261 | * only lower either OFDM or CCK errors per turn |
441 | * we lower the other one next time | 262 | * we lower the other one next time |
@@ -446,11 +267,6 @@ static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah) | |||
446 | 267 | ||
447 | aniState = &ah->curchan->ani; | 268 | aniState = &ah->curchan->ani; |
448 | 269 | ||
449 | if (!use_new_ani(ah)) { | ||
450 | ath9k_hw_ani_lower_immunity_old(ah); | ||
451 | return; | ||
452 | } | ||
453 | |||
454 | /* lower OFDM noise immunity */ | 270 | /* lower OFDM noise immunity */ |
455 | if (aniState->ofdmNoiseImmunityLevel > 0 && | 271 | if (aniState->ofdmNoiseImmunityLevel > 0 && |
456 | (aniState->ofdmsTurn || aniState->cckNoiseImmunityLevel == 0)) { | 272 | (aniState->ofdmsTurn || aniState->cckNoiseImmunityLevel == 0)) { |
@@ -463,72 +279,6 @@ static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah) | |||
463 | ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel - 1); | 279 | ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel - 1); |
464 | } | 280 | } |
465 | 281 | ||
466 | static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning) | ||
467 | { | ||
468 | struct ar5416AniState *aniState; | ||
469 | struct ath9k_channel *chan = ah->curchan; | ||
470 | struct ath_common *common = ath9k_hw_common(ah); | ||
471 | |||
472 | if (!DO_ANI(ah)) | ||
473 | return; | ||
474 | |||
475 | aniState = &ah->curchan->ani; | ||
476 | |||
477 | if (ah->opmode != NL80211_IFTYPE_STATION | ||
478 | && ah->opmode != NL80211_IFTYPE_ADHOC) { | ||
479 | ath_dbg(common, ANI, "Reset ANI state opmode %u\n", ah->opmode); | ||
480 | ah->stats.ast_ani_reset++; | ||
481 | |||
482 | if (ah->opmode == NL80211_IFTYPE_AP) { | ||
483 | /* | ||
484 | * ath9k_hw_ani_control() will only process items set on | ||
485 | * ah->ani_function | ||
486 | */ | ||
487 | if (IS_CHAN_2GHZ(chan)) | ||
488 | ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL | | ||
489 | ATH9K_ANI_FIRSTEP_LEVEL); | ||
490 | else | ||
491 | ah->ani_function = 0; | ||
492 | } | ||
493 | |||
494 | ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, 0); | ||
495 | ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0); | ||
496 | ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 0); | ||
497 | ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, | ||
498 | !ATH9K_ANI_USE_OFDM_WEAK_SIG); | ||
499 | ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR, | ||
500 | ATH9K_ANI_CCK_WEAK_SIG_THR); | ||
501 | |||
502 | ath9k_ani_restart(ah); | ||
503 | return; | ||
504 | } | ||
505 | |||
506 | if (aniState->noiseImmunityLevel != 0) | ||
507 | ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, | ||
508 | aniState->noiseImmunityLevel); | ||
509 | if (aniState->spurImmunityLevel != 0) | ||
510 | ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, | ||
511 | aniState->spurImmunityLevel); | ||
512 | if (aniState->ofdmWeakSigDetectOff) | ||
513 | ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, | ||
514 | !aniState->ofdmWeakSigDetectOff); | ||
515 | if (aniState->cckWeakSigThreshold) | ||
516 | ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR, | ||
517 | aniState->cckWeakSigThreshold); | ||
518 | if (aniState->firstepLevel != 0) | ||
519 | ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, | ||
520 | aniState->firstepLevel); | ||
521 | |||
522 | ath9k_ani_restart(ah); | ||
523 | |||
524 | ENABLE_REGWRITE_BUFFER(ah); | ||
525 | |||
526 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); | ||
527 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); | ||
528 | |||
529 | REGWRITE_BUFFER_FLUSH(ah); | ||
530 | } | ||
531 | |||
532 | /* | 282 | /* |
533 | * Restore the ANI parameters in the HAL and reset the statistics. | 283 | * Restore the ANI parameters in the HAL and reset the statistics. |
534 | * This routine should be called for every hardware reset and for | 284 | * This routine should be called for every hardware reset and for |
@@ -539,13 +289,11 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning) | |||
539 | struct ar5416AniState *aniState = &ah->curchan->ani; | 289 | struct ar5416AniState *aniState = &ah->curchan->ani; |
540 | struct ath9k_channel *chan = ah->curchan; | 290 | struct ath9k_channel *chan = ah->curchan; |
541 | struct ath_common *common = ath9k_hw_common(ah); | 291 | struct ath_common *common = ath9k_hw_common(ah); |
292 | int ofdm_nil, cck_nil; | ||
542 | 293 | ||
543 | if (!DO_ANI(ah)) | 294 | if (!DO_ANI(ah)) |
544 | return; | 295 | return; |
545 | 296 | ||
546 | if (!use_new_ani(ah)) | ||
547 | return ath9k_ani_reset_old(ah, is_scanning); | ||
548 | |||
549 | BUG_ON(aniState == NULL); | 297 | BUG_ON(aniState == NULL); |
550 | ah->stats.ast_ani_reset++; | 298 | ah->stats.ast_ani_reset++; |
551 | 299 | ||
@@ -563,6 +311,11 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning) | |||
563 | /* always allow mode (on/off) to be controlled */ | 311 | /* always allow mode (on/off) to be controlled */ |
564 | ah->ani_function |= ATH9K_ANI_MODE; | 312 | ah->ani_function |= ATH9K_ANI_MODE; |
565 | 313 | ||
314 | ofdm_nil = max_t(int, ATH9K_ANI_OFDM_DEF_LEVEL, | ||
315 | aniState->ofdmNoiseImmunityLevel); | ||
316 | cck_nil = max_t(int, ATH9K_ANI_CCK_DEF_LEVEL, | ||
317 | aniState->cckNoiseImmunityLevel); | ||
318 | |||
566 | if (is_scanning || | 319 | if (is_scanning || |
567 | (ah->opmode != NL80211_IFTYPE_STATION && | 320 | (ah->opmode != NL80211_IFTYPE_STATION && |
568 | ah->opmode != NL80211_IFTYPE_ADHOC)) { | 321 | ah->opmode != NL80211_IFTYPE_ADHOC)) { |
@@ -586,8 +339,8 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning) | |||
586 | aniState->cckNoiseImmunityLevel); | 339 | aniState->cckNoiseImmunityLevel); |
587 | 340 | ||
588 | aniState->update_ani = false; | 341 | aniState->update_ani = false; |
589 | ath9k_hw_set_ofdm_nil(ah, ATH9K_ANI_OFDM_DEF_LEVEL); | 342 | ofdm_nil = ATH9K_ANI_OFDM_DEF_LEVEL; |
590 | ath9k_hw_set_cck_nil(ah, ATH9K_ANI_CCK_DEF_LEVEL); | 343 | cck_nil = ATH9K_ANI_CCK_DEF_LEVEL; |
591 | } | 344 | } |
592 | } else { | 345 | } else { |
593 | /* | 346 | /* |
@@ -603,11 +356,9 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning) | |||
603 | aniState->cckNoiseImmunityLevel); | 356 | aniState->cckNoiseImmunityLevel); |
604 | 357 | ||
605 | aniState->update_ani = true; | 358 | aniState->update_ani = true; |
606 | ath9k_hw_set_ofdm_nil(ah, | ||
607 | aniState->ofdmNoiseImmunityLevel); | ||
608 | ath9k_hw_set_cck_nil(ah, | ||
609 | aniState->cckNoiseImmunityLevel); | ||
610 | } | 359 | } |
360 | ath9k_hw_set_ofdm_nil(ah, ofdm_nil); | ||
361 | ath9k_hw_set_cck_nil(ah, cck_nil); | ||
611 | 362 | ||
612 | /* | 363 | /* |
613 | * enable phy counters if hw supports or if not, enable phy | 364 | * enable phy counters if hw supports or if not, enable phy |
@@ -627,9 +378,6 @@ static bool ath9k_hw_ani_read_counters(struct ath_hw *ah) | |||
627 | { | 378 | { |
628 | struct ath_common *common = ath9k_hw_common(ah); | 379 | struct ath_common *common = ath9k_hw_common(ah); |
629 | struct ar5416AniState *aniState = &ah->curchan->ani; | 380 | struct ar5416AniState *aniState = &ah->curchan->ani; |
630 | u32 ofdm_base = 0; | ||
631 | u32 cck_base = 0; | ||
632 | u32 ofdmPhyErrCnt, cckPhyErrCnt; | ||
633 | u32 phyCnt1, phyCnt2; | 381 | u32 phyCnt1, phyCnt2; |
634 | int32_t listenTime; | 382 | int32_t listenTime; |
635 | 383 | ||
@@ -642,11 +390,6 @@ static bool ath9k_hw_ani_read_counters(struct ath_hw *ah) | |||
642 | return false; | 390 | return false; |
643 | } | 391 | } |
644 | 392 | ||
645 | if (!use_new_ani(ah)) { | ||
646 | ofdm_base = AR_PHY_COUNTMAX - ah->config.ofdm_trig_high; | ||
647 | cck_base = AR_PHY_COUNTMAX - ah->config.cck_trig_high; | ||
648 | } | ||
649 | |||
650 | aniState->listenTime += listenTime; | 393 | aniState->listenTime += listenTime; |
651 | 394 | ||
652 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); | 395 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); |
@@ -654,35 +397,12 @@ static bool ath9k_hw_ani_read_counters(struct ath_hw *ah) | |||
654 | phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); | 397 | phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); |
655 | phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); | 398 | phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); |
656 | 399 | ||
657 | if (!use_new_ani(ah) && (phyCnt1 < ofdm_base || phyCnt2 < cck_base)) { | 400 | ah->stats.ast_ani_ofdmerrs += phyCnt1 - aniState->ofdmPhyErrCount; |
658 | if (phyCnt1 < ofdm_base) { | 401 | aniState->ofdmPhyErrCount = phyCnt1; |
659 | ath_dbg(common, ANI, | ||
660 | "phyCnt1 0x%x, resetting counter value to 0x%x\n", | ||
661 | phyCnt1, ofdm_base); | ||
662 | REG_WRITE(ah, AR_PHY_ERR_1, ofdm_base); | ||
663 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, | ||
664 | AR_PHY_ERR_OFDM_TIMING); | ||
665 | } | ||
666 | if (phyCnt2 < cck_base) { | ||
667 | ath_dbg(common, ANI, | ||
668 | "phyCnt2 0x%x, resetting counter value to 0x%x\n", | ||
669 | phyCnt2, cck_base); | ||
670 | REG_WRITE(ah, AR_PHY_ERR_2, cck_base); | ||
671 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, | ||
672 | AR_PHY_ERR_CCK_TIMING); | ||
673 | } | ||
674 | return false; | ||
675 | } | ||
676 | 402 | ||
677 | ofdmPhyErrCnt = phyCnt1 - ofdm_base; | 403 | ah->stats.ast_ani_cckerrs += phyCnt2 - aniState->cckPhyErrCount; |
678 | ah->stats.ast_ani_ofdmerrs += | 404 | aniState->cckPhyErrCount = phyCnt2; |
679 | ofdmPhyErrCnt - aniState->ofdmPhyErrCount; | ||
680 | aniState->ofdmPhyErrCount = ofdmPhyErrCnt; | ||
681 | 405 | ||
682 | cckPhyErrCnt = phyCnt2 - cck_base; | ||
683 | ah->stats.ast_ani_cckerrs += | ||
684 | cckPhyErrCnt - aniState->cckPhyErrCount; | ||
685 | aniState->cckPhyErrCount = cckPhyErrCnt; | ||
686 | return true; | 406 | return true; |
687 | } | 407 | } |
688 | 408 | ||
@@ -716,21 +436,10 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan) | |||
716 | 436 | ||
717 | if (aniState->listenTime > ah->aniperiod) { | 437 | if (aniState->listenTime > ah->aniperiod) { |
718 | if (cckPhyErrRate < ah->config.cck_trig_low && | 438 | if (cckPhyErrRate < ah->config.cck_trig_low && |
719 | ((ofdmPhyErrRate < ah->config.ofdm_trig_low && | 439 | ofdmPhyErrRate < ah->config.ofdm_trig_low) { |
720 | aniState->ofdmNoiseImmunityLevel < | ||
721 | ATH9K_ANI_OFDM_DEF_LEVEL) || | ||
722 | (ofdmPhyErrRate < ATH9K_ANI_OFDM_TRIG_LOW_ABOVE_INI && | ||
723 | aniState->ofdmNoiseImmunityLevel >= | ||
724 | ATH9K_ANI_OFDM_DEF_LEVEL))) { | ||
725 | ath9k_hw_ani_lower_immunity(ah); | 440 | ath9k_hw_ani_lower_immunity(ah); |
726 | aniState->ofdmsTurn = !aniState->ofdmsTurn; | 441 | aniState->ofdmsTurn = !aniState->ofdmsTurn; |
727 | } else if ((ofdmPhyErrRate > ah->config.ofdm_trig_high && | 442 | } else if (ofdmPhyErrRate > ah->config.ofdm_trig_high) { |
728 | aniState->ofdmNoiseImmunityLevel >= | ||
729 | ATH9K_ANI_OFDM_DEF_LEVEL) || | ||
730 | (ofdmPhyErrRate > | ||
731 | ATH9K_ANI_OFDM_TRIG_HIGH_BELOW_INI && | ||
732 | aniState->ofdmNoiseImmunityLevel < | ||
733 | ATH9K_ANI_OFDM_DEF_LEVEL)) { | ||
734 | ath9k_hw_ani_ofdm_err_trigger(ah); | 443 | ath9k_hw_ani_ofdm_err_trigger(ah); |
735 | aniState->ofdmsTurn = false; | 444 | aniState->ofdmsTurn = false; |
736 | } else if (cckPhyErrRate > ah->config.cck_trig_high) { | 445 | } else if (cckPhyErrRate > ah->config.cck_trig_high) { |
@@ -778,49 +487,6 @@ void ath9k_hw_disable_mib_counters(struct ath_hw *ah) | |||
778 | } | 487 | } |
779 | EXPORT_SYMBOL(ath9k_hw_disable_mib_counters); | 488 | EXPORT_SYMBOL(ath9k_hw_disable_mib_counters); |
780 | 489 | ||
781 | /* | ||
782 | * Process a MIB interrupt. We may potentially be invoked because | ||
783 | * any of the MIB counters overflow/trigger so don't assume we're | ||
784 | * here because a PHY error counter triggered. | ||
785 | */ | ||
786 | void ath9k_hw_proc_mib_event(struct ath_hw *ah) | ||
787 | { | ||
788 | u32 phyCnt1, phyCnt2; | ||
789 | |||
790 | /* Reset these counters regardless */ | ||
791 | REG_WRITE(ah, AR_FILT_OFDM, 0); | ||
792 | REG_WRITE(ah, AR_FILT_CCK, 0); | ||
793 | if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING)) | ||
794 | REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR); | ||
795 | |||
796 | /* Clear the mib counters and save them in the stats */ | ||
797 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); | ||
798 | |||
799 | if (!DO_ANI(ah)) { | ||
800 | /* | ||
801 | * We must always clear the interrupt cause by | ||
802 | * resetting the phy error regs. | ||
803 | */ | ||
804 | REG_WRITE(ah, AR_PHY_ERR_1, 0); | ||
805 | REG_WRITE(ah, AR_PHY_ERR_2, 0); | ||
806 | return; | ||
807 | } | ||
808 | |||
809 | /* NB: these are not reset-on-read */ | ||
810 | phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); | ||
811 | phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); | ||
812 | if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) || | ||
813 | ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) { | ||
814 | |||
815 | if (!use_new_ani(ah)) | ||
816 | ath9k_hw_ani_read_counters(ah); | ||
817 | |||
818 | /* NB: always restart to insure the h/w counters are reset */ | ||
819 | ath9k_ani_restart(ah); | ||
820 | } | ||
821 | } | ||
822 | EXPORT_SYMBOL(ath9k_hw_proc_mib_event); | ||
823 | |||
824 | void ath9k_hw_ani_setup(struct ath_hw *ah) | 490 | void ath9k_hw_ani_setup(struct ath_hw *ah) |
825 | { | 491 | { |
826 | int i; | 492 | int i; |
@@ -845,50 +511,27 @@ void ath9k_hw_ani_init(struct ath_hw *ah) | |||
845 | 511 | ||
846 | ath_dbg(common, ANI, "Initialize ANI\n"); | 512 | ath_dbg(common, ANI, "Initialize ANI\n"); |
847 | 513 | ||
848 | if (use_new_ani(ah)) { | 514 | ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH; |
849 | ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_NEW; | 515 | ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW; |
850 | ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_NEW; | ||
851 | 516 | ||
852 | ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH_NEW; | 517 | ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH; |
853 | ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW_NEW; | 518 | ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW; |
854 | } else { | ||
855 | ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_OLD; | ||
856 | ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_OLD; | ||
857 | |||
858 | ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH_OLD; | ||
859 | ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW_OLD; | ||
860 | } | ||
861 | 519 | ||
862 | for (i = 0; i < ARRAY_SIZE(ah->channels); i++) { | 520 | for (i = 0; i < ARRAY_SIZE(ah->channels); i++) { |
863 | struct ath9k_channel *chan = &ah->channels[i]; | 521 | struct ath9k_channel *chan = &ah->channels[i]; |
864 | struct ar5416AniState *ani = &chan->ani; | 522 | struct ar5416AniState *ani = &chan->ani; |
865 | 523 | ||
866 | if (use_new_ani(ah)) { | 524 | ani->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL; |
867 | ani->spurImmunityLevel = | ||
868 | ATH9K_ANI_SPUR_IMMUNE_LVL_NEW; | ||
869 | 525 | ||
870 | ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW; | 526 | ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL; |
871 | 527 | ||
872 | if (AR_SREV_9300_20_OR_LATER(ah)) | 528 | ani->mrcCCK = AR_SREV_9300_20_OR_LATER(ah) ? true : false; |
873 | ani->mrcCCKOff = | 529 | |
874 | !ATH9K_ANI_ENABLE_MRC_CCK; | 530 | ani->ofdmsTurn = true; |
875 | else | ||
876 | ani->mrcCCKOff = true; | ||
877 | |||
878 | ani->ofdmsTurn = true; | ||
879 | } else { | ||
880 | ani->spurImmunityLevel = | ||
881 | ATH9K_ANI_SPUR_IMMUNE_LVL_OLD; | ||
882 | ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_OLD; | ||
883 | |||
884 | ani->cckWeakSigThreshold = | ||
885 | ATH9K_ANI_CCK_WEAK_SIG_THR; | ||
886 | } | ||
887 | 531 | ||
888 | ani->rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH; | 532 | ani->rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH; |
889 | ani->rssiThrLow = ATH9K_ANI_RSSI_THR_LOW; | 533 | ani->rssiThrLow = ATH9K_ANI_RSSI_THR_LOW; |
890 | ani->ofdmWeakSigDetectOff = | 534 | ani->ofdmWeakSigDetect = ATH9K_ANI_USE_OFDM_WEAK_SIG; |
891 | !ATH9K_ANI_USE_OFDM_WEAK_SIG; | ||
892 | ani->cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL; | 535 | ani->cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL; |
893 | ani->ofdmNoiseImmunityLevel = ATH9K_ANI_OFDM_DEF_LEVEL; | 536 | ani->ofdmNoiseImmunityLevel = ATH9K_ANI_OFDM_DEF_LEVEL; |
894 | ani->update_ani = false; | 537 | ani->update_ani = false; |
@@ -898,13 +541,8 @@ void ath9k_hw_ani_init(struct ath_hw *ah) | |||
898 | * since we expect some ongoing maintenance on the tables, let's sanity | 541 | * since we expect some ongoing maintenance on the tables, let's sanity |
899 | * check here default level should not modify INI setting. | 542 | * check here default level should not modify INI setting. |
900 | */ | 543 | */ |
901 | if (use_new_ani(ah)) { | 544 | ah->aniperiod = ATH9K_ANI_PERIOD; |
902 | ah->aniperiod = ATH9K_ANI_PERIOD_NEW; | 545 | ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL; |
903 | ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_NEW; | ||
904 | } else { | ||
905 | ah->aniperiod = ATH9K_ANI_PERIOD_OLD; | ||
906 | ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_OLD; | ||
907 | } | ||
908 | 546 | ||
909 | if (ah->config.enable_ani) | 547 | if (ah->config.enable_ani) |
910 | ah->proc_phyerr |= HAL_PROCESS_ANI; | 548 | ah->proc_phyerr |= HAL_PROCESS_ANI; |
diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h index 72e2b874e17..e9d841bbe86 100644 --- a/drivers/net/wireless/ath/ath9k/ani.h +++ b/drivers/net/wireless/ath/ath9k/ani.h | |||
@@ -24,42 +24,34 @@ | |||
24 | #define BEACON_RSSI(ahp) (ahp->stats.avgbrssi) | 24 | #define BEACON_RSSI(ahp) (ahp->stats.avgbrssi) |
25 | 25 | ||
26 | /* units are errors per second */ | 26 | /* units are errors per second */ |
27 | #define ATH9K_ANI_OFDM_TRIG_HIGH_OLD 500 | 27 | #define ATH9K_ANI_OFDM_TRIG_HIGH 3500 |
28 | #define ATH9K_ANI_OFDM_TRIG_HIGH_NEW 3500 | ||
29 | #define ATH9K_ANI_OFDM_TRIG_HIGH_BELOW_INI 1000 | 28 | #define ATH9K_ANI_OFDM_TRIG_HIGH_BELOW_INI 1000 |
30 | 29 | ||
31 | /* units are errors per second */ | 30 | /* units are errors per second */ |
32 | #define ATH9K_ANI_OFDM_TRIG_LOW_OLD 200 | 31 | #define ATH9K_ANI_OFDM_TRIG_LOW 400 |
33 | #define ATH9K_ANI_OFDM_TRIG_LOW_NEW 400 | ||
34 | #define ATH9K_ANI_OFDM_TRIG_LOW_ABOVE_INI 900 | 32 | #define ATH9K_ANI_OFDM_TRIG_LOW_ABOVE_INI 900 |
35 | 33 | ||
36 | /* units are errors per second */ | 34 | /* units are errors per second */ |
37 | #define ATH9K_ANI_CCK_TRIG_HIGH_OLD 200 | 35 | #define ATH9K_ANI_CCK_TRIG_HIGH 600 |
38 | #define ATH9K_ANI_CCK_TRIG_HIGH_NEW 600 | ||
39 | 36 | ||
40 | /* units are errors per second */ | 37 | /* units are errors per second */ |
41 | #define ATH9K_ANI_CCK_TRIG_LOW_OLD 100 | 38 | #define ATH9K_ANI_CCK_TRIG_LOW 300 |
42 | #define ATH9K_ANI_CCK_TRIG_LOW_NEW 300 | ||
43 | 39 | ||
44 | #define ATH9K_ANI_NOISE_IMMUNE_LVL 4 | 40 | #define ATH9K_ANI_NOISE_IMMUNE_LVL 4 |
45 | #define ATH9K_ANI_USE_OFDM_WEAK_SIG true | 41 | #define ATH9K_ANI_USE_OFDM_WEAK_SIG true |
46 | #define ATH9K_ANI_CCK_WEAK_SIG_THR false | 42 | #define ATH9K_ANI_CCK_WEAK_SIG_THR false |
47 | 43 | ||
48 | #define ATH9K_ANI_SPUR_IMMUNE_LVL_OLD 7 | 44 | #define ATH9K_ANI_SPUR_IMMUNE_LVL 3 |
49 | #define ATH9K_ANI_SPUR_IMMUNE_LVL_NEW 3 | ||
50 | 45 | ||
51 | #define ATH9K_ANI_FIRSTEP_LVL_OLD 0 | 46 | #define ATH9K_ANI_FIRSTEP_LVL 2 |
52 | #define ATH9K_ANI_FIRSTEP_LVL_NEW 2 | ||
53 | 47 | ||
54 | #define ATH9K_ANI_RSSI_THR_HIGH 40 | 48 | #define ATH9K_ANI_RSSI_THR_HIGH 40 |
55 | #define ATH9K_ANI_RSSI_THR_LOW 7 | 49 | #define ATH9K_ANI_RSSI_THR_LOW 7 |
56 | 50 | ||
57 | #define ATH9K_ANI_PERIOD_OLD 100 | 51 | #define ATH9K_ANI_PERIOD 300 |
58 | #define ATH9K_ANI_PERIOD_NEW 300 | ||
59 | 52 | ||
60 | /* in ms */ | 53 | /* in ms */ |
61 | #define ATH9K_ANI_POLLINTERVAL_OLD 100 | 54 | #define ATH9K_ANI_POLLINTERVAL 1000 |
62 | #define ATH9K_ANI_POLLINTERVAL_NEW 1000 | ||
63 | 55 | ||
64 | #define HAL_NOISE_IMMUNE_MAX 4 | 56 | #define HAL_NOISE_IMMUNE_MAX 4 |
65 | #define HAL_SPUR_IMMUNE_MAX 7 | 57 | #define HAL_SPUR_IMMUNE_MAX 7 |
@@ -70,8 +62,6 @@ | |||
70 | #define ATH9K_SIG_SPUR_IMM_SETTING_MIN 0 | 62 | #define ATH9K_SIG_SPUR_IMM_SETTING_MIN 0 |
71 | #define ATH9K_SIG_SPUR_IMM_SETTING_MAX 22 | 63 | #define ATH9K_SIG_SPUR_IMM_SETTING_MAX 22 |
72 | 64 | ||
73 | #define ATH9K_ANI_ENABLE_MRC_CCK true | ||
74 | |||
75 | /* values here are relative to the INI */ | 65 | /* values here are relative to the INI */ |
76 | 66 | ||
77 | enum ath9k_ani_cmd { | 67 | enum ath9k_ani_cmd { |
@@ -119,16 +109,15 @@ struct ar5416AniState { | |||
119 | u8 ofdmNoiseImmunityLevel; | 109 | u8 ofdmNoiseImmunityLevel; |
120 | u8 cckNoiseImmunityLevel; | 110 | u8 cckNoiseImmunityLevel; |
121 | bool ofdmsTurn; | 111 | bool ofdmsTurn; |
122 | u8 mrcCCKOff; | 112 | u8 mrcCCK; |
123 | u8 spurImmunityLevel; | 113 | u8 spurImmunityLevel; |
124 | u8 firstepLevel; | 114 | u8 firstepLevel; |
125 | u8 ofdmWeakSigDetectOff; | 115 | u8 ofdmWeakSigDetect; |
126 | u8 cckWeakSigThreshold; | 116 | u8 cckWeakSigThreshold; |
127 | bool update_ani; | 117 | bool update_ani; |
128 | u32 listenTime; | 118 | u32 listenTime; |
129 | int32_t rssiThrLow; | 119 | int32_t rssiThrLow; |
130 | int32_t rssiThrHigh; | 120 | int32_t rssiThrHigh; |
131 | u32 noiseFloor; | ||
132 | u32 ofdmPhyErrCount; | 121 | u32 ofdmPhyErrCount; |
133 | u32 cckPhyErrCount; | 122 | u32 cckPhyErrCount; |
134 | int16_t pktRssi[2]; | 123 | int16_t pktRssi[2]; |
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c index c7492c6a251..874186bfda4 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c | |||
@@ -995,141 +995,6 @@ static u32 ar5008_hw_compute_pll_control(struct ath_hw *ah, | |||
995 | return pll; | 995 | return pll; |
996 | } | 996 | } |
997 | 997 | ||
998 | static bool ar5008_hw_ani_control_old(struct ath_hw *ah, | ||
999 | enum ath9k_ani_cmd cmd, | ||
1000 | int param) | ||
1001 | { | ||
1002 | struct ar5416AniState *aniState = &ah->curchan->ani; | ||
1003 | struct ath_common *common = ath9k_hw_common(ah); | ||
1004 | |||
1005 | switch (cmd & ah->ani_function) { | ||
1006 | case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{ | ||
1007 | u32 level = param; | ||
1008 | |||
1009 | if (level >= ARRAY_SIZE(ah->totalSizeDesired)) { | ||
1010 | ath_dbg(common, ANI, "level out of range (%u > %zu)\n", | ||
1011 | level, ARRAY_SIZE(ah->totalSizeDesired)); | ||
1012 | return false; | ||
1013 | } | ||
1014 | |||
1015 | REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, | ||
1016 | AR_PHY_DESIRED_SZ_TOT_DES, | ||
1017 | ah->totalSizeDesired[level]); | ||
1018 | REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1, | ||
1019 | AR_PHY_AGC_CTL1_COARSE_LOW, | ||
1020 | ah->coarse_low[level]); | ||
1021 | REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1, | ||
1022 | AR_PHY_AGC_CTL1_COARSE_HIGH, | ||
1023 | ah->coarse_high[level]); | ||
1024 | REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, | ||
1025 | AR_PHY_FIND_SIG_FIRPWR, | ||
1026 | ah->firpwr[level]); | ||
1027 | |||
1028 | if (level > aniState->noiseImmunityLevel) | ||
1029 | ah->stats.ast_ani_niup++; | ||
1030 | else if (level < aniState->noiseImmunityLevel) | ||
1031 | ah->stats.ast_ani_nidown++; | ||
1032 | aniState->noiseImmunityLevel = level; | ||
1033 | break; | ||
1034 | } | ||
1035 | case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{ | ||
1036 | u32 on = param ? 1 : 0; | ||
1037 | |||
1038 | if (on) | ||
1039 | REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, | ||
1040 | AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); | ||
1041 | else | ||
1042 | REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW, | ||
1043 | AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); | ||
1044 | |||
1045 | if (!on != aniState->ofdmWeakSigDetectOff) { | ||
1046 | if (on) | ||
1047 | ah->stats.ast_ani_ofdmon++; | ||
1048 | else | ||
1049 | ah->stats.ast_ani_ofdmoff++; | ||
1050 | aniState->ofdmWeakSigDetectOff = !on; | ||
1051 | } | ||
1052 | break; | ||
1053 | } | ||
1054 | case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{ | ||
1055 | static const int weakSigThrCck[] = { 8, 6 }; | ||
1056 | u32 high = param ? 1 : 0; | ||
1057 | |||
1058 | REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT, | ||
1059 | AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK, | ||
1060 | weakSigThrCck[high]); | ||
1061 | if (high != aniState->cckWeakSigThreshold) { | ||
1062 | if (high) | ||
1063 | ah->stats.ast_ani_cckhigh++; | ||
1064 | else | ||
1065 | ah->stats.ast_ani_ccklow++; | ||
1066 | aniState->cckWeakSigThreshold = high; | ||
1067 | } | ||
1068 | break; | ||
1069 | } | ||
1070 | case ATH9K_ANI_FIRSTEP_LEVEL:{ | ||
1071 | static const int firstep[] = { 0, 4, 8 }; | ||
1072 | u32 level = param; | ||
1073 | |||
1074 | if (level >= ARRAY_SIZE(firstep)) { | ||
1075 | ath_dbg(common, ANI, "level out of range (%u > %zu)\n", | ||
1076 | level, ARRAY_SIZE(firstep)); | ||
1077 | return false; | ||
1078 | } | ||
1079 | REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, | ||
1080 | AR_PHY_FIND_SIG_FIRSTEP, | ||
1081 | firstep[level]); | ||
1082 | if (level > aniState->firstepLevel) | ||
1083 | ah->stats.ast_ani_stepup++; | ||
1084 | else if (level < aniState->firstepLevel) | ||
1085 | ah->stats.ast_ani_stepdown++; | ||
1086 | aniState->firstepLevel = level; | ||
1087 | break; | ||
1088 | } | ||
1089 | case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{ | ||
1090 | static const int cycpwrThr1[] = { 2, 4, 6, 8, 10, 12, 14, 16 }; | ||
1091 | u32 level = param; | ||
1092 | |||
1093 | if (level >= ARRAY_SIZE(cycpwrThr1)) { | ||
1094 | ath_dbg(common, ANI, "level out of range (%u > %zu)\n", | ||
1095 | level, ARRAY_SIZE(cycpwrThr1)); | ||
1096 | return false; | ||
1097 | } | ||
1098 | REG_RMW_FIELD(ah, AR_PHY_TIMING5, | ||
1099 | AR_PHY_TIMING5_CYCPWR_THR1, | ||
1100 | cycpwrThr1[level]); | ||
1101 | if (level > aniState->spurImmunityLevel) | ||
1102 | ah->stats.ast_ani_spurup++; | ||
1103 | else if (level < aniState->spurImmunityLevel) | ||
1104 | ah->stats.ast_ani_spurdown++; | ||
1105 | aniState->spurImmunityLevel = level; | ||
1106 | break; | ||
1107 | } | ||
1108 | case ATH9K_ANI_PRESENT: | ||
1109 | break; | ||
1110 | default: | ||
1111 | ath_dbg(common, ANI, "invalid cmd %u\n", cmd); | ||
1112 | return false; | ||
1113 | } | ||
1114 | |||
1115 | ath_dbg(common, ANI, "ANI parameters:\n"); | ||
1116 | ath_dbg(common, ANI, | ||
1117 | "noiseImmunityLevel=%d, spurImmunityLevel=%d, ofdmWeakSigDetectOff=%d\n", | ||
1118 | aniState->noiseImmunityLevel, | ||
1119 | aniState->spurImmunityLevel, | ||
1120 | !aniState->ofdmWeakSigDetectOff); | ||
1121 | ath_dbg(common, ANI, | ||
1122 | "cckWeakSigThreshold=%d, firstepLevel=%d, listenTime=%d\n", | ||
1123 | aniState->cckWeakSigThreshold, | ||
1124 | aniState->firstepLevel, | ||
1125 | aniState->listenTime); | ||
1126 | ath_dbg(common, ANI, "ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n", | ||
1127 | aniState->ofdmPhyErrCount, | ||
1128 | aniState->cckPhyErrCount); | ||
1129 | |||
1130 | return true; | ||
1131 | } | ||
1132 | |||
1133 | static bool ar5008_hw_ani_control_new(struct ath_hw *ah, | 998 | static bool ar5008_hw_ani_control_new(struct ath_hw *ah, |
1134 | enum ath9k_ani_cmd cmd, | 999 | enum ath9k_ani_cmd cmd, |
1135 | int param) | 1000 | int param) |
@@ -1206,18 +1071,18 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, | |||
1206 | REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW, | 1071 | REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW, |
1207 | AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); | 1072 | AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); |
1208 | 1073 | ||
1209 | if (!on != aniState->ofdmWeakSigDetectOff) { | 1074 | if (on != aniState->ofdmWeakSigDetect) { |
1210 | ath_dbg(common, ANI, | 1075 | ath_dbg(common, ANI, |
1211 | "** ch %d: ofdm weak signal: %s=>%s\n", | 1076 | "** ch %d: ofdm weak signal: %s=>%s\n", |
1212 | chan->channel, | 1077 | chan->channel, |
1213 | !aniState->ofdmWeakSigDetectOff ? | 1078 | aniState->ofdmWeakSigDetect ? |
1214 | "on" : "off", | 1079 | "on" : "off", |
1215 | on ? "on" : "off"); | 1080 | on ? "on" : "off"); |
1216 | if (on) | 1081 | if (on) |
1217 | ah->stats.ast_ani_ofdmon++; | 1082 | ah->stats.ast_ani_ofdmon++; |
1218 | else | 1083 | else |
1219 | ah->stats.ast_ani_ofdmoff++; | 1084 | ah->stats.ast_ani_ofdmoff++; |
1220 | aniState->ofdmWeakSigDetectOff = !on; | 1085 | aniState->ofdmWeakSigDetect = on; |
1221 | } | 1086 | } |
1222 | break; | 1087 | break; |
1223 | } | 1088 | } |
@@ -1236,7 +1101,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, | |||
1236 | * from INI file & cap value | 1101 | * from INI file & cap value |
1237 | */ | 1102 | */ |
1238 | value = firstep_table[level] - | 1103 | value = firstep_table[level] - |
1239 | firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] + | 1104 | firstep_table[ATH9K_ANI_FIRSTEP_LVL] + |
1240 | aniState->iniDef.firstep; | 1105 | aniState->iniDef.firstep; |
1241 | if (value < ATH9K_SIG_FIRSTEP_SETTING_MIN) | 1106 | if (value < ATH9K_SIG_FIRSTEP_SETTING_MIN) |
1242 | value = ATH9K_SIG_FIRSTEP_SETTING_MIN; | 1107 | value = ATH9K_SIG_FIRSTEP_SETTING_MIN; |
@@ -1251,7 +1116,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, | |||
1251 | * from INI file & cap value | 1116 | * from INI file & cap value |
1252 | */ | 1117 | */ |
1253 | value2 = firstep_table[level] - | 1118 | value2 = firstep_table[level] - |
1254 | firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] + | 1119 | firstep_table[ATH9K_ANI_FIRSTEP_LVL] + |
1255 | aniState->iniDef.firstepLow; | 1120 | aniState->iniDef.firstepLow; |
1256 | if (value2 < ATH9K_SIG_FIRSTEP_SETTING_MIN) | 1121 | if (value2 < ATH9K_SIG_FIRSTEP_SETTING_MIN) |
1257 | value2 = ATH9K_SIG_FIRSTEP_SETTING_MIN; | 1122 | value2 = ATH9K_SIG_FIRSTEP_SETTING_MIN; |
@@ -1267,7 +1132,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, | |||
1267 | chan->channel, | 1132 | chan->channel, |
1268 | aniState->firstepLevel, | 1133 | aniState->firstepLevel, |
1269 | level, | 1134 | level, |
1270 | ATH9K_ANI_FIRSTEP_LVL_NEW, | 1135 | ATH9K_ANI_FIRSTEP_LVL, |
1271 | value, | 1136 | value, |
1272 | aniState->iniDef.firstep); | 1137 | aniState->iniDef.firstep); |
1273 | ath_dbg(common, ANI, | 1138 | ath_dbg(common, ANI, |
@@ -1275,7 +1140,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, | |||
1275 | chan->channel, | 1140 | chan->channel, |
1276 | aniState->firstepLevel, | 1141 | aniState->firstepLevel, |
1277 | level, | 1142 | level, |
1278 | ATH9K_ANI_FIRSTEP_LVL_NEW, | 1143 | ATH9K_ANI_FIRSTEP_LVL, |
1279 | value2, | 1144 | value2, |
1280 | aniState->iniDef.firstepLow); | 1145 | aniState->iniDef.firstepLow); |
1281 | if (level > aniState->firstepLevel) | 1146 | if (level > aniState->firstepLevel) |
@@ -1300,7 +1165,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, | |||
1300 | * from INI file & cap value | 1165 | * from INI file & cap value |
1301 | */ | 1166 | */ |
1302 | value = cycpwrThr1_table[level] - | 1167 | value = cycpwrThr1_table[level] - |
1303 | cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] + | 1168 | cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL] + |
1304 | aniState->iniDef.cycpwrThr1; | 1169 | aniState->iniDef.cycpwrThr1; |
1305 | if (value < ATH9K_SIG_SPUR_IMM_SETTING_MIN) | 1170 | if (value < ATH9K_SIG_SPUR_IMM_SETTING_MIN) |
1306 | value = ATH9K_SIG_SPUR_IMM_SETTING_MIN; | 1171 | value = ATH9K_SIG_SPUR_IMM_SETTING_MIN; |
@@ -1316,7 +1181,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, | |||
1316 | * from INI file & cap value | 1181 | * from INI file & cap value |
1317 | */ | 1182 | */ |
1318 | value2 = cycpwrThr1_table[level] - | 1183 | value2 = cycpwrThr1_table[level] - |
1319 | cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] + | 1184 | cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL] + |
1320 | aniState->iniDef.cycpwrThr1Ext; | 1185 | aniState->iniDef.cycpwrThr1Ext; |
1321 | if (value2 < ATH9K_SIG_SPUR_IMM_SETTING_MIN) | 1186 | if (value2 < ATH9K_SIG_SPUR_IMM_SETTING_MIN) |
1322 | value2 = ATH9K_SIG_SPUR_IMM_SETTING_MIN; | 1187 | value2 = ATH9K_SIG_SPUR_IMM_SETTING_MIN; |
@@ -1331,7 +1196,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, | |||
1331 | chan->channel, | 1196 | chan->channel, |
1332 | aniState->spurImmunityLevel, | 1197 | aniState->spurImmunityLevel, |
1333 | level, | 1198 | level, |
1334 | ATH9K_ANI_SPUR_IMMUNE_LVL_NEW, | 1199 | ATH9K_ANI_SPUR_IMMUNE_LVL, |
1335 | value, | 1200 | value, |
1336 | aniState->iniDef.cycpwrThr1); | 1201 | aniState->iniDef.cycpwrThr1); |
1337 | ath_dbg(common, ANI, | 1202 | ath_dbg(common, ANI, |
@@ -1339,7 +1204,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, | |||
1339 | chan->channel, | 1204 | chan->channel, |
1340 | aniState->spurImmunityLevel, | 1205 | aniState->spurImmunityLevel, |
1341 | level, | 1206 | level, |
1342 | ATH9K_ANI_SPUR_IMMUNE_LVL_NEW, | 1207 | ATH9K_ANI_SPUR_IMMUNE_LVL, |
1343 | value2, | 1208 | value2, |
1344 | aniState->iniDef.cycpwrThr1Ext); | 1209 | aniState->iniDef.cycpwrThr1Ext); |
1345 | if (level > aniState->spurImmunityLevel) | 1210 | if (level > aniState->spurImmunityLevel) |
@@ -1367,9 +1232,9 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, | |||
1367 | ath_dbg(common, ANI, | 1232 | ath_dbg(common, ANI, |
1368 | "ANI parameters: SI=%d, ofdmWS=%s FS=%d MRCcck=%s listenTime=%d ofdmErrs=%d cckErrs=%d\n", | 1233 | "ANI parameters: SI=%d, ofdmWS=%s FS=%d MRCcck=%s listenTime=%d ofdmErrs=%d cckErrs=%d\n", |
1369 | aniState->spurImmunityLevel, | 1234 | aniState->spurImmunityLevel, |
1370 | !aniState->ofdmWeakSigDetectOff ? "on" : "off", | 1235 | aniState->ofdmWeakSigDetect ? "on" : "off", |
1371 | aniState->firstepLevel, | 1236 | aniState->firstepLevel, |
1372 | !aniState->mrcCCKOff ? "on" : "off", | 1237 | aniState->mrcCCK ? "on" : "off", |
1373 | aniState->listenTime, | 1238 | aniState->listenTime, |
1374 | aniState->ofdmPhyErrCount, | 1239 | aniState->ofdmPhyErrCount, |
1375 | aniState->cckPhyErrCount); | 1240 | aniState->cckPhyErrCount); |
@@ -1454,10 +1319,10 @@ static void ar5008_hw_ani_cache_ini_regs(struct ath_hw *ah) | |||
1454 | AR_PHY_EXT_TIMING5_CYCPWR_THR1); | 1319 | AR_PHY_EXT_TIMING5_CYCPWR_THR1); |
1455 | 1320 | ||
1456 | /* these levels just got reset to defaults by the INI */ | 1321 | /* these levels just got reset to defaults by the INI */ |
1457 | aniState->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL_NEW; | 1322 | aniState->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL; |
1458 | aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW; | 1323 | aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL; |
1459 | aniState->ofdmWeakSigDetectOff = !ATH9K_ANI_USE_OFDM_WEAK_SIG; | 1324 | aniState->ofdmWeakSigDetect = ATH9K_ANI_USE_OFDM_WEAK_SIG; |
1460 | aniState->mrcCCKOff = true; /* not available on pre AR9003 */ | 1325 | aniState->mrcCCK = false; /* not available on pre AR9003 */ |
1461 | } | 1326 | } |
1462 | 1327 | ||
1463 | static void ar5008_hw_set_nf_limits(struct ath_hw *ah) | 1328 | static void ar5008_hw_set_nf_limits(struct ath_hw *ah) |
@@ -1545,11 +1410,8 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah) | |||
1545 | priv_ops->do_getnf = ar5008_hw_do_getnf; | 1410 | priv_ops->do_getnf = ar5008_hw_do_getnf; |
1546 | priv_ops->set_radar_params = ar5008_hw_set_radar_params; | 1411 | priv_ops->set_radar_params = ar5008_hw_set_radar_params; |
1547 | 1412 | ||
1548 | if (modparam_force_new_ani) { | 1413 | priv_ops->ani_control = ar5008_hw_ani_control_new; |
1549 | priv_ops->ani_control = ar5008_hw_ani_control_new; | 1414 | priv_ops->ani_cache_ini_regs = ar5008_hw_ani_cache_ini_regs; |
1550 | priv_ops->ani_cache_ini_regs = ar5008_hw_ani_cache_ini_regs; | ||
1551 | } else | ||
1552 | priv_ops->ani_control = ar5008_hw_ani_control_old; | ||
1553 | 1415 | ||
1554 | if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) | 1416 | if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) |
1555 | priv_ops->compute_pll_control = ar9160_hw_compute_pll_control; | 1417 | priv_ops->compute_pll_control = ar9160_hw_compute_pll_control; |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c index d9a69fc470c..edf21ea4fe9 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c | |||
@@ -21,10 +21,6 @@ | |||
21 | #include "ar9002_initvals.h" | 21 | #include "ar9002_initvals.h" |
22 | #include "ar9002_phy.h" | 22 | #include "ar9002_phy.h" |
23 | 23 | ||
24 | int modparam_force_new_ani; | ||
25 | module_param_named(force_new_ani, modparam_force_new_ani, int, 0444); | ||
26 | MODULE_PARM_DESC(force_new_ani, "Force new ANI for AR5008, AR9001, AR9002"); | ||
27 | |||
28 | /* General hardware code for the A5008/AR9001/AR9002 hadware families */ | 24 | /* General hardware code for the A5008/AR9001/AR9002 hadware families */ |
29 | 25 | ||
30 | static void ar9002_hw_init_mode_regs(struct ath_hw *ah) | 26 | static void ar9002_hw_init_mode_regs(struct ath_hw *ah) |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index d9e0824af09..78816b8b217 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c | |||
@@ -181,11 +181,14 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) | |||
181 | u32 mask2 = 0; | 181 | u32 mask2 = 0; |
182 | struct ath9k_hw_capabilities *pCap = &ah->caps; | 182 | struct ath9k_hw_capabilities *pCap = &ah->caps; |
183 | struct ath_common *common = ath9k_hw_common(ah); | 183 | struct ath_common *common = ath9k_hw_common(ah); |
184 | u32 sync_cause = 0, async_cause; | 184 | u32 sync_cause = 0, async_cause, async_mask = AR_INTR_MAC_IRQ; |
185 | |||
186 | if (ath9k_hw_mci_is_enabled(ah)) | ||
187 | async_mask |= AR_INTR_ASYNC_MASK_MCI; | ||
185 | 188 | ||
186 | async_cause = REG_READ(ah, AR_INTR_ASYNC_CAUSE); | 189 | async_cause = REG_READ(ah, AR_INTR_ASYNC_CAUSE); |
187 | 190 | ||
188 | if (async_cause & (AR_INTR_MAC_IRQ | AR_INTR_ASYNC_MASK_MCI)) { | 191 | if (async_cause & async_mask) { |
189 | if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) | 192 | if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) |
190 | == AR_RTC_STATUS_ON) | 193 | == AR_RTC_STATUS_ON) |
191 | isr = REG_READ(ah, AR_ISR); | 194 | isr = REG_READ(ah, AR_ISR); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mci.c b/drivers/net/wireless/ath/ath9k/ar9003_mci.c index b1ced2a76da..61558375bfb 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mci.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mci.c | |||
@@ -321,7 +321,7 @@ void ar9003_mci_set_full_sleep(struct ath_hw *ah) | |||
321 | { | 321 | { |
322 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | 322 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; |
323 | 323 | ||
324 | if (ar9003_mci_state(ah, MCI_STATE_ENABLE, NULL) && | 324 | if (ar9003_mci_state(ah, MCI_STATE_ENABLE) && |
325 | (mci->bt_state != MCI_BT_SLEEP) && | 325 | (mci->bt_state != MCI_BT_SLEEP) && |
326 | !mci->halted_bt_gpm) { | 326 | !mci->halted_bt_gpm) { |
327 | ar9003_mci_send_coex_halt_bt_gpm(ah, true, true); | 327 | ar9003_mci_send_coex_halt_bt_gpm(ah, true, true); |
@@ -484,7 +484,7 @@ static void ar9003_mci_sync_bt_state(struct ath_hw *ah) | |||
484 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | 484 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; |
485 | u32 cur_bt_state; | 485 | u32 cur_bt_state; |
486 | 486 | ||
487 | cur_bt_state = ar9003_mci_state(ah, MCI_STATE_REMOTE_SLEEP, NULL); | 487 | cur_bt_state = ar9003_mci_state(ah, MCI_STATE_REMOTE_SLEEP); |
488 | 488 | ||
489 | if (mci->bt_state != cur_bt_state) | 489 | if (mci->bt_state != cur_bt_state) |
490 | mci->bt_state = cur_bt_state; | 490 | mci->bt_state = cur_bt_state; |
@@ -593,8 +593,7 @@ static u32 ar9003_mci_wait_for_gpm(struct ath_hw *ah, u8 gpm_type, | |||
593 | if (!time_out) | 593 | if (!time_out) |
594 | break; | 594 | break; |
595 | 595 | ||
596 | offset = ar9003_mci_state(ah, MCI_STATE_NEXT_GPM_OFFSET, | 596 | offset = ar9003_mci_get_next_gpm_offset(ah, false, &more_data); |
597 | &more_data); | ||
598 | 597 | ||
599 | if (offset == MCI_GPM_INVALID) | 598 | if (offset == MCI_GPM_INVALID) |
600 | continue; | 599 | continue; |
@@ -658,8 +657,7 @@ static u32 ar9003_mci_wait_for_gpm(struct ath_hw *ah, u8 gpm_type, | |||
658 | time_out = 0; | 657 | time_out = 0; |
659 | 658 | ||
660 | while (more_data == MCI_GPM_MORE) { | 659 | while (more_data == MCI_GPM_MORE) { |
661 | offset = ar9003_mci_state(ah, MCI_STATE_NEXT_GPM_OFFSET, | 660 | offset = ar9003_mci_get_next_gpm_offset(ah, false, &more_data); |
662 | &more_data); | ||
663 | if (offset == MCI_GPM_INVALID) | 661 | if (offset == MCI_GPM_INVALID) |
664 | break; | 662 | break; |
665 | 663 | ||
@@ -769,10 +767,6 @@ static void ar9003_mci_mute_bt(struct ath_hw *ah) | |||
769 | { | 767 | { |
770 | /* disable all MCI messages */ | 768 | /* disable all MCI messages */ |
771 | REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE, 0xffff0000); | 769 | REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE, 0xffff0000); |
772 | REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS0, 0xffffffff); | ||
773 | REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS1, 0xffffffff); | ||
774 | REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS2, 0xffffffff); | ||
775 | REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS3, 0xffffffff); | ||
776 | REG_SET_BIT(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); | 770 | REG_SET_BIT(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); |
777 | 771 | ||
778 | /* wait pending HW messages to flush out */ | 772 | /* wait pending HW messages to flush out */ |
@@ -893,13 +887,16 @@ void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g, | |||
893 | udelay(100); | 887 | udelay(100); |
894 | } | 888 | } |
895 | 889 | ||
890 | /* Check pending GPM msg before MCI Reset Rx */ | ||
891 | ar9003_mci_check_gpm_offset(ah); | ||
892 | |||
896 | regval |= SM(1, AR_MCI_COMMAND2_RESET_RX); | 893 | regval |= SM(1, AR_MCI_COMMAND2_RESET_RX); |
897 | REG_WRITE(ah, AR_MCI_COMMAND2, regval); | 894 | REG_WRITE(ah, AR_MCI_COMMAND2, regval); |
898 | udelay(1); | 895 | udelay(1); |
899 | regval &= ~SM(1, AR_MCI_COMMAND2_RESET_RX); | 896 | regval &= ~SM(1, AR_MCI_COMMAND2_RESET_RX); |
900 | REG_WRITE(ah, AR_MCI_COMMAND2, regval); | 897 | REG_WRITE(ah, AR_MCI_COMMAND2, regval); |
901 | 898 | ||
902 | ar9003_mci_state(ah, MCI_STATE_INIT_GPM_OFFSET, NULL); | 899 | ar9003_mci_get_next_gpm_offset(ah, true, NULL); |
903 | 900 | ||
904 | REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE, | 901 | REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE, |
905 | (SM(0xe801, AR_MCI_MSG_ATTRIBUTES_TABLE_INVALID_HDR) | | 902 | (SM(0xe801, AR_MCI_MSG_ATTRIBUTES_TABLE_INVALID_HDR) | |
@@ -1010,17 +1007,20 @@ static void ar9003_mci_queue_unsent_gpm(struct ath_hw *ah, u8 header, | |||
1010 | } | 1007 | } |
1011 | } | 1008 | } |
1012 | 1009 | ||
1013 | void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool wait_done) | 1010 | void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool force) |
1014 | { | 1011 | { |
1015 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | 1012 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; |
1016 | 1013 | ||
1017 | if (!mci->update_2g5g) | 1014 | if (!mci->update_2g5g && !force) |
1018 | return; | 1015 | return; |
1019 | 1016 | ||
1020 | if (mci->is_2g) { | 1017 | if (mci->is_2g) { |
1021 | ar9003_mci_send_2g5g_status(ah, true); | 1018 | if (!force) { |
1022 | ar9003_mci_send_lna_transfer(ah, true); | 1019 | ar9003_mci_send_2g5g_status(ah, true); |
1023 | udelay(5); | 1020 | |
1021 | ar9003_mci_send_lna_transfer(ah, true); | ||
1022 | udelay(5); | ||
1023 | } | ||
1024 | 1024 | ||
1025 | REG_CLR_BIT(ah, AR_MCI_TX_CTRL, | 1025 | REG_CLR_BIT(ah, AR_MCI_TX_CTRL, |
1026 | AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); | 1026 | AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); |
@@ -1028,20 +1028,21 @@ void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool wait_done) | |||
1028 | AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); | 1028 | AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); |
1029 | 1029 | ||
1030 | if (!(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA)) | 1030 | if (!(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA)) |
1031 | REG_SET_BIT(ah, AR_BTCOEX_CTRL, | 1031 | ar9003_mci_osla_setup(ah, true); |
1032 | AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN); | ||
1033 | } else { | 1032 | } else { |
1034 | ar9003_mci_send_lna_take(ah, true); | 1033 | if (!force) { |
1035 | udelay(5); | 1034 | ar9003_mci_send_lna_take(ah, true); |
1035 | udelay(5); | ||
1036 | } | ||
1036 | 1037 | ||
1037 | REG_SET_BIT(ah, AR_MCI_TX_CTRL, | 1038 | REG_SET_BIT(ah, AR_MCI_TX_CTRL, |
1038 | AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); | 1039 | AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); |
1039 | REG_SET_BIT(ah, AR_PHY_GLB_CONTROL, | 1040 | REG_SET_BIT(ah, AR_PHY_GLB_CONTROL, |
1040 | AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); | 1041 | AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); |
1041 | REG_CLR_BIT(ah, AR_BTCOEX_CTRL, | ||
1042 | AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN); | ||
1043 | 1042 | ||
1044 | ar9003_mci_send_2g5g_status(ah, true); | 1043 | ar9003_mci_osla_setup(ah, false); |
1044 | if (!force) | ||
1045 | ar9003_mci_send_2g5g_status(ah, true); | ||
1045 | } | 1046 | } |
1046 | } | 1047 | } |
1047 | 1048 | ||
@@ -1169,11 +1170,10 @@ void ar9003_mci_cleanup(struct ath_hw *ah) | |||
1169 | } | 1170 | } |
1170 | EXPORT_SYMBOL(ar9003_mci_cleanup); | 1171 | EXPORT_SYMBOL(ar9003_mci_cleanup); |
1171 | 1172 | ||
1172 | u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data) | 1173 | u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type) |
1173 | { | 1174 | { |
1174 | struct ath_common *common = ath9k_hw_common(ah); | ||
1175 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | 1175 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; |
1176 | u32 value = 0, more_gpm = 0, gpm_ptr; | 1176 | u32 value = 0; |
1177 | u8 query_type; | 1177 | u8 query_type; |
1178 | 1178 | ||
1179 | switch (state_type) { | 1179 | switch (state_type) { |
@@ -1186,81 +1186,6 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data) | |||
1186 | } | 1186 | } |
1187 | value &= AR_BTCOEX_CTRL_MCI_MODE_EN; | 1187 | value &= AR_BTCOEX_CTRL_MCI_MODE_EN; |
1188 | break; | 1188 | break; |
1189 | case MCI_STATE_INIT_GPM_OFFSET: | ||
1190 | value = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR); | ||
1191 | mci->gpm_idx = value; | ||
1192 | break; | ||
1193 | case MCI_STATE_NEXT_GPM_OFFSET: | ||
1194 | case MCI_STATE_LAST_GPM_OFFSET: | ||
1195 | /* | ||
1196 | * This could be useful to avoid new GPM message interrupt which | ||
1197 | * may lead to spurious interrupt after power sleep, or multiple | ||
1198 | * entry of ath_mci_intr(). | ||
1199 | * Adding empty GPM check by returning HAL_MCI_GPM_INVALID can | ||
1200 | * alleviate this effect, but clearing GPM RX interrupt bit is | ||
1201 | * safe, because whether this is called from hw or driver code | ||
1202 | * there must be an interrupt bit set/triggered initially | ||
1203 | */ | ||
1204 | REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, | ||
1205 | AR_MCI_INTERRUPT_RX_MSG_GPM); | ||
1206 | |||
1207 | gpm_ptr = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR); | ||
1208 | value = gpm_ptr; | ||
1209 | |||
1210 | if (value == 0) | ||
1211 | value = mci->gpm_len - 1; | ||
1212 | else if (value >= mci->gpm_len) { | ||
1213 | if (value != 0xFFFF) | ||
1214 | value = 0; | ||
1215 | } else { | ||
1216 | value--; | ||
1217 | } | ||
1218 | |||
1219 | if (value == 0xFFFF) { | ||
1220 | value = MCI_GPM_INVALID; | ||
1221 | more_gpm = MCI_GPM_NOMORE; | ||
1222 | } else if (state_type == MCI_STATE_NEXT_GPM_OFFSET) { | ||
1223 | if (gpm_ptr == mci->gpm_idx) { | ||
1224 | value = MCI_GPM_INVALID; | ||
1225 | more_gpm = MCI_GPM_NOMORE; | ||
1226 | } else { | ||
1227 | for (;;) { | ||
1228 | u32 temp_index; | ||
1229 | |||
1230 | /* skip reserved GPM if any */ | ||
1231 | |||
1232 | if (value != mci->gpm_idx) | ||
1233 | more_gpm = MCI_GPM_MORE; | ||
1234 | else | ||
1235 | more_gpm = MCI_GPM_NOMORE; | ||
1236 | |||
1237 | temp_index = mci->gpm_idx; | ||
1238 | mci->gpm_idx++; | ||
1239 | |||
1240 | if (mci->gpm_idx >= | ||
1241 | mci->gpm_len) | ||
1242 | mci->gpm_idx = 0; | ||
1243 | |||
1244 | if (ar9003_mci_is_gpm_valid(ah, | ||
1245 | temp_index)) { | ||
1246 | value = temp_index; | ||
1247 | break; | ||
1248 | } | ||
1249 | |||
1250 | if (more_gpm == MCI_GPM_NOMORE) { | ||
1251 | value = MCI_GPM_INVALID; | ||
1252 | break; | ||
1253 | } | ||
1254 | } | ||
1255 | } | ||
1256 | if (p_data) | ||
1257 | *p_data = more_gpm; | ||
1258 | } | ||
1259 | |||
1260 | if (value != MCI_GPM_INVALID) | ||
1261 | value <<= 4; | ||
1262 | |||
1263 | break; | ||
1264 | case MCI_STATE_LAST_SCHD_MSG_OFFSET: | 1189 | case MCI_STATE_LAST_SCHD_MSG_OFFSET: |
1265 | value = MS(REG_READ(ah, AR_MCI_RX_STATUS), | 1190 | value = MS(REG_READ(ah, AR_MCI_RX_STATUS), |
1266 | AR_MCI_RX_LAST_SCHD_MSG_INDEX); | 1191 | AR_MCI_RX_LAST_SCHD_MSG_INDEX); |
@@ -1272,21 +1197,6 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data) | |||
1272 | AR_MCI_RX_REMOTE_SLEEP) ? | 1197 | AR_MCI_RX_REMOTE_SLEEP) ? |
1273 | MCI_BT_SLEEP : MCI_BT_AWAKE; | 1198 | MCI_BT_SLEEP : MCI_BT_AWAKE; |
1274 | break; | 1199 | break; |
1275 | case MCI_STATE_CONT_RSSI_POWER: | ||
1276 | value = MS(mci->cont_status, AR_MCI_CONT_RSSI_POWER); | ||
1277 | break; | ||
1278 | case MCI_STATE_CONT_PRIORITY: | ||
1279 | value = MS(mci->cont_status, AR_MCI_CONT_RRIORITY); | ||
1280 | break; | ||
1281 | case MCI_STATE_CONT_TXRX: | ||
1282 | value = MS(mci->cont_status, AR_MCI_CONT_TXRX); | ||
1283 | break; | ||
1284 | case MCI_STATE_BT: | ||
1285 | value = mci->bt_state; | ||
1286 | break; | ||
1287 | case MCI_STATE_SET_BT_SLEEP: | ||
1288 | mci->bt_state = MCI_BT_SLEEP; | ||
1289 | break; | ||
1290 | case MCI_STATE_SET_BT_AWAKE: | 1200 | case MCI_STATE_SET_BT_AWAKE: |
1291 | mci->bt_state = MCI_BT_AWAKE; | 1201 | mci->bt_state = MCI_BT_AWAKE; |
1292 | ar9003_mci_send_coex_version_query(ah, true); | 1202 | ar9003_mci_send_coex_version_query(ah, true); |
@@ -1295,7 +1205,7 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data) | |||
1295 | if (mci->unhalt_bt_gpm) | 1205 | if (mci->unhalt_bt_gpm) |
1296 | ar9003_mci_send_coex_halt_bt_gpm(ah, false, true); | 1206 | ar9003_mci_send_coex_halt_bt_gpm(ah, false, true); |
1297 | 1207 | ||
1298 | ar9003_mci_2g5g_switch(ah, true); | 1208 | ar9003_mci_2g5g_switch(ah, false); |
1299 | break; | 1209 | break; |
1300 | case MCI_STATE_SET_BT_CAL_START: | 1210 | case MCI_STATE_SET_BT_CAL_START: |
1301 | mci->bt_state = MCI_BT_CAL_START; | 1211 | mci->bt_state = MCI_BT_CAL_START; |
@@ -1319,34 +1229,6 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data) | |||
1319 | case MCI_STATE_SEND_WLAN_COEX_VERSION: | 1229 | case MCI_STATE_SEND_WLAN_COEX_VERSION: |
1320 | ar9003_mci_send_coex_version_response(ah, true); | 1230 | ar9003_mci_send_coex_version_response(ah, true); |
1321 | break; | 1231 | break; |
1322 | case MCI_STATE_SET_BT_COEX_VERSION: | ||
1323 | if (!p_data) | ||
1324 | ath_dbg(common, MCI, | ||
1325 | "MCI Set BT Coex version with NULL data!!\n"); | ||
1326 | else { | ||
1327 | mci->bt_ver_major = (*p_data >> 8) & 0xff; | ||
1328 | mci->bt_ver_minor = (*p_data) & 0xff; | ||
1329 | mci->bt_version_known = true; | ||
1330 | ath_dbg(common, MCI, "MCI BT version set: %d.%d\n", | ||
1331 | mci->bt_ver_major, mci->bt_ver_minor); | ||
1332 | } | ||
1333 | break; | ||
1334 | case MCI_STATE_SEND_WLAN_CHANNELS: | ||
1335 | if (p_data) { | ||
1336 | if (((mci->wlan_channels[1] & 0xffff0000) == | ||
1337 | (*(p_data + 1) & 0xffff0000)) && | ||
1338 | (mci->wlan_channels[2] == *(p_data + 2)) && | ||
1339 | (mci->wlan_channels[3] == *(p_data + 3))) | ||
1340 | break; | ||
1341 | |||
1342 | mci->wlan_channels[0] = *p_data++; | ||
1343 | mci->wlan_channels[1] = *p_data++; | ||
1344 | mci->wlan_channels[2] = *p_data++; | ||
1345 | mci->wlan_channels[3] = *p_data++; | ||
1346 | } | ||
1347 | mci->wlan_channels_update = true; | ||
1348 | ar9003_mci_send_coex_wlan_channels(ah, true); | ||
1349 | break; | ||
1350 | case MCI_STATE_SEND_VERSION_QUERY: | 1232 | case MCI_STATE_SEND_VERSION_QUERY: |
1351 | ar9003_mci_send_coex_version_query(ah, true); | 1233 | ar9003_mci_send_coex_version_query(ah, true); |
1352 | break; | 1234 | break; |
@@ -1354,29 +1236,12 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data) | |||
1354 | query_type = MCI_GPM_COEX_QUERY_BT_TOPOLOGY; | 1236 | query_type = MCI_GPM_COEX_QUERY_BT_TOPOLOGY; |
1355 | ar9003_mci_send_coex_bt_status_query(ah, true, query_type); | 1237 | ar9003_mci_send_coex_bt_status_query(ah, true, query_type); |
1356 | break; | 1238 | break; |
1357 | case MCI_STATE_NEED_FLUSH_BT_INFO: | ||
1358 | /* | ||
1359 | * btcoex_hw.mci.unhalt_bt_gpm means whether it's | ||
1360 | * needed to send UNHALT message. It's set whenever | ||
1361 | * there's a request to send HALT message. | ||
1362 | * mci_halted_bt_gpm means whether HALT message is sent | ||
1363 | * out successfully. | ||
1364 | * | ||
1365 | * Checking (mci_unhalt_bt_gpm == false) instead of | ||
1366 | * checking (ah->mci_halted_bt_gpm == false) will make | ||
1367 | * sure currently is in UNHALT-ed mode and BT can | ||
1368 | * respond to status query. | ||
1369 | */ | ||
1370 | value = (!mci->unhalt_bt_gpm && mci->need_flush_btinfo) ? 1 : 0; | ||
1371 | if (p_data) | ||
1372 | mci->need_flush_btinfo = (*p_data != 0) ? true : false; | ||
1373 | break; | ||
1374 | case MCI_STATE_RECOVER_RX: | 1239 | case MCI_STATE_RECOVER_RX: |
1375 | ar9003_mci_prep_interface(ah); | 1240 | ar9003_mci_prep_interface(ah); |
1376 | mci->query_bt = true; | 1241 | mci->query_bt = true; |
1377 | mci->need_flush_btinfo = true; | 1242 | mci->need_flush_btinfo = true; |
1378 | ar9003_mci_send_coex_wlan_channels(ah, true); | 1243 | ar9003_mci_send_coex_wlan_channels(ah, true); |
1379 | ar9003_mci_2g5g_switch(ah, true); | 1244 | ar9003_mci_2g5g_switch(ah, false); |
1380 | break; | 1245 | break; |
1381 | case MCI_STATE_NEED_FTP_STOMP: | 1246 | case MCI_STATE_NEED_FTP_STOMP: |
1382 | value = !(mci->config & ATH_MCI_CONFIG_DISABLE_FTP_STOMP); | 1247 | value = !(mci->config & ATH_MCI_CONFIG_DISABLE_FTP_STOMP); |
@@ -1396,6 +1261,9 @@ void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah) | |||
1396 | 1261 | ||
1397 | ath_dbg(common, MCI, "Give LNA and SPDT control to BT\n"); | 1262 | ath_dbg(common, MCI, "Give LNA and SPDT control to BT\n"); |
1398 | 1263 | ||
1264 | ar9003_mci_send_lna_take(ah, true); | ||
1265 | udelay(50); | ||
1266 | |||
1399 | REG_SET_BIT(ah, AR_PHY_GLB_CONTROL, AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); | 1267 | REG_SET_BIT(ah, AR_PHY_GLB_CONTROL, AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); |
1400 | mci->is_2g = false; | 1268 | mci->is_2g = false; |
1401 | mci->update_2g5g = true; | 1269 | mci->update_2g5g = true; |
@@ -1404,3 +1272,154 @@ void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah) | |||
1404 | /* Force another 2g5g update at next scanning */ | 1272 | /* Force another 2g5g update at next scanning */ |
1405 | mci->update_2g5g = true; | 1273 | mci->update_2g5g = true; |
1406 | } | 1274 | } |
1275 | |||
1276 | void ar9003_mci_set_power_awake(struct ath_hw *ah) | ||
1277 | { | ||
1278 | u32 btcoex_ctrl2, diag_sw; | ||
1279 | int i; | ||
1280 | u8 lna_ctrl, bt_sleep; | ||
1281 | |||
1282 | for (i = 0; i < AH_WAIT_TIMEOUT; i++) { | ||
1283 | btcoex_ctrl2 = REG_READ(ah, AR_BTCOEX_CTRL2); | ||
1284 | if (btcoex_ctrl2 != 0xdeadbeef) | ||
1285 | break; | ||
1286 | udelay(AH_TIME_QUANTUM); | ||
1287 | } | ||
1288 | REG_WRITE(ah, AR_BTCOEX_CTRL2, (btcoex_ctrl2 | BIT(23))); | ||
1289 | |||
1290 | for (i = 0; i < AH_WAIT_TIMEOUT; i++) { | ||
1291 | diag_sw = REG_READ(ah, AR_DIAG_SW); | ||
1292 | if (diag_sw != 0xdeadbeef) | ||
1293 | break; | ||
1294 | udelay(AH_TIME_QUANTUM); | ||
1295 | } | ||
1296 | REG_WRITE(ah, AR_DIAG_SW, (diag_sw | BIT(27) | BIT(19) | BIT(18))); | ||
1297 | lna_ctrl = REG_READ(ah, AR_OBS_BUS_CTRL) & 0x3; | ||
1298 | bt_sleep = REG_READ(ah, AR_MCI_RX_STATUS) & AR_MCI_RX_REMOTE_SLEEP; | ||
1299 | |||
1300 | REG_WRITE(ah, AR_BTCOEX_CTRL2, btcoex_ctrl2); | ||
1301 | REG_WRITE(ah, AR_DIAG_SW, diag_sw); | ||
1302 | |||
1303 | if (bt_sleep && (lna_ctrl == 2)) { | ||
1304 | REG_SET_BIT(ah, AR_BTCOEX_RC, 0x1); | ||
1305 | REG_CLR_BIT(ah, AR_BTCOEX_RC, 0x1); | ||
1306 | udelay(50); | ||
1307 | } | ||
1308 | } | ||
1309 | |||
1310 | void ar9003_mci_check_gpm_offset(struct ath_hw *ah) | ||
1311 | { | ||
1312 | struct ath_common *common = ath9k_hw_common(ah); | ||
1313 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | ||
1314 | u32 offset; | ||
1315 | |||
1316 | /* | ||
1317 | * This should only be called before "MAC Warm Reset" or "MCI Reset Rx". | ||
1318 | */ | ||
1319 | offset = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR); | ||
1320 | if (mci->gpm_idx == offset) | ||
1321 | return; | ||
1322 | ath_dbg(common, MCI, "GPM cached write pointer mismatch %d %d\n", | ||
1323 | mci->gpm_idx, offset); | ||
1324 | mci->query_bt = true; | ||
1325 | mci->need_flush_btinfo = true; | ||
1326 | mci->gpm_idx = 0; | ||
1327 | } | ||
1328 | |||
1329 | u32 ar9003_mci_get_next_gpm_offset(struct ath_hw *ah, bool first, u32 *more) | ||
1330 | { | ||
1331 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | ||
1332 | u32 offset, more_gpm = 0, gpm_ptr; | ||
1333 | |||
1334 | if (first) { | ||
1335 | gpm_ptr = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR); | ||
1336 | mci->gpm_idx = gpm_ptr; | ||
1337 | return gpm_ptr; | ||
1338 | } | ||
1339 | |||
1340 | /* | ||
1341 | * This could be useful to avoid new GPM message interrupt which | ||
1342 | * may lead to spurious interrupt after power sleep, or multiple | ||
1343 | * entry of ath_mci_intr(). | ||
1344 | * Adding empty GPM check by returning HAL_MCI_GPM_INVALID can | ||
1345 | * alleviate this effect, but clearing GPM RX interrupt bit is | ||
1346 | * safe, because whether this is called from hw or driver code | ||
1347 | * there must be an interrupt bit set/triggered initially | ||
1348 | */ | ||
1349 | REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, | ||
1350 | AR_MCI_INTERRUPT_RX_MSG_GPM); | ||
1351 | |||
1352 | gpm_ptr = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR); | ||
1353 | offset = gpm_ptr; | ||
1354 | |||
1355 | if (!offset) | ||
1356 | offset = mci->gpm_len - 1; | ||
1357 | else if (offset >= mci->gpm_len) { | ||
1358 | if (offset != 0xFFFF) | ||
1359 | offset = 0; | ||
1360 | } else { | ||
1361 | offset--; | ||
1362 | } | ||
1363 | |||
1364 | if ((offset == 0xFFFF) || (gpm_ptr == mci->gpm_idx)) { | ||
1365 | offset = MCI_GPM_INVALID; | ||
1366 | more_gpm = MCI_GPM_NOMORE; | ||
1367 | goto out; | ||
1368 | } | ||
1369 | for (;;) { | ||
1370 | u32 temp_index; | ||
1371 | |||
1372 | /* skip reserved GPM if any */ | ||
1373 | |||
1374 | if (offset != mci->gpm_idx) | ||
1375 | more_gpm = MCI_GPM_MORE; | ||
1376 | else | ||
1377 | more_gpm = MCI_GPM_NOMORE; | ||
1378 | |||
1379 | temp_index = mci->gpm_idx; | ||
1380 | mci->gpm_idx++; | ||
1381 | |||
1382 | if (mci->gpm_idx >= mci->gpm_len) | ||
1383 | mci->gpm_idx = 0; | ||
1384 | |||
1385 | if (ar9003_mci_is_gpm_valid(ah, temp_index)) { | ||
1386 | offset = temp_index; | ||
1387 | break; | ||
1388 | } | ||
1389 | |||
1390 | if (more_gpm == MCI_GPM_NOMORE) { | ||
1391 | offset = MCI_GPM_INVALID; | ||
1392 | break; | ||
1393 | } | ||
1394 | } | ||
1395 | |||
1396 | if (offset != MCI_GPM_INVALID) | ||
1397 | offset <<= 4; | ||
1398 | out: | ||
1399 | if (more) | ||
1400 | *more = more_gpm; | ||
1401 | |||
1402 | return offset; | ||
1403 | } | ||
1404 | EXPORT_SYMBOL(ar9003_mci_get_next_gpm_offset); | ||
1405 | |||
1406 | void ar9003_mci_set_bt_version(struct ath_hw *ah, u8 major, u8 minor) | ||
1407 | { | ||
1408 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | ||
1409 | |||
1410 | mci->bt_ver_major = major; | ||
1411 | mci->bt_ver_minor = minor; | ||
1412 | mci->bt_version_known = true; | ||
1413 | ath_dbg(ath9k_hw_common(ah), MCI, "MCI BT version set: %d.%d\n", | ||
1414 | mci->bt_ver_major, mci->bt_ver_minor); | ||
1415 | } | ||
1416 | EXPORT_SYMBOL(ar9003_mci_set_bt_version); | ||
1417 | |||
1418 | void ar9003_mci_send_wlan_channels(struct ath_hw *ah) | ||
1419 | { | ||
1420 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | ||
1421 | |||
1422 | mci->wlan_channels_update = true; | ||
1423 | ar9003_mci_send_coex_wlan_channels(ah, true); | ||
1424 | } | ||
1425 | EXPORT_SYMBOL(ar9003_mci_send_wlan_channels); | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mci.h b/drivers/net/wireless/ath/ath9k/ar9003_mci.h index 10282e2bcdc..d33b8e12885 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mci.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_mci.h | |||
@@ -189,26 +189,15 @@ enum mci_bt_state { | |||
189 | /* Type of state query */ | 189 | /* Type of state query */ |
190 | enum mci_state_type { | 190 | enum mci_state_type { |
191 | MCI_STATE_ENABLE, | 191 | MCI_STATE_ENABLE, |
192 | MCI_STATE_INIT_GPM_OFFSET, | ||
193 | MCI_STATE_NEXT_GPM_OFFSET, | ||
194 | MCI_STATE_LAST_GPM_OFFSET, | ||
195 | MCI_STATE_BT, | ||
196 | MCI_STATE_SET_BT_SLEEP, | ||
197 | MCI_STATE_SET_BT_AWAKE, | 192 | MCI_STATE_SET_BT_AWAKE, |
198 | MCI_STATE_SET_BT_CAL_START, | 193 | MCI_STATE_SET_BT_CAL_START, |
199 | MCI_STATE_SET_BT_CAL, | 194 | MCI_STATE_SET_BT_CAL, |
200 | MCI_STATE_LAST_SCHD_MSG_OFFSET, | 195 | MCI_STATE_LAST_SCHD_MSG_OFFSET, |
201 | MCI_STATE_REMOTE_SLEEP, | 196 | MCI_STATE_REMOTE_SLEEP, |
202 | MCI_STATE_CONT_RSSI_POWER, | ||
203 | MCI_STATE_CONT_PRIORITY, | ||
204 | MCI_STATE_CONT_TXRX, | ||
205 | MCI_STATE_RESET_REQ_WAKE, | 197 | MCI_STATE_RESET_REQ_WAKE, |
206 | MCI_STATE_SEND_WLAN_COEX_VERSION, | 198 | MCI_STATE_SEND_WLAN_COEX_VERSION, |
207 | MCI_STATE_SET_BT_COEX_VERSION, | ||
208 | MCI_STATE_SEND_WLAN_CHANNELS, | ||
209 | MCI_STATE_SEND_VERSION_QUERY, | 199 | MCI_STATE_SEND_VERSION_QUERY, |
210 | MCI_STATE_SEND_STATUS_QUERY, | 200 | MCI_STATE_SEND_STATUS_QUERY, |
211 | MCI_STATE_NEED_FLUSH_BT_INFO, | ||
212 | MCI_STATE_SET_CONCUR_TX_PRI, | 201 | MCI_STATE_SET_CONCUR_TX_PRI, |
213 | MCI_STATE_RECOVER_RX, | 202 | MCI_STATE_RECOVER_RX, |
214 | MCI_STATE_NEED_FTP_STOMP, | 203 | MCI_STATE_NEED_FTP_STOMP, |
@@ -259,14 +248,15 @@ enum mci_gpm_coex_opcode { | |||
259 | bool ar9003_mci_send_message(struct ath_hw *ah, u8 header, u32 flag, | 248 | bool ar9003_mci_send_message(struct ath_hw *ah, u8 header, u32 flag, |
260 | u32 *payload, u8 len, bool wait_done, | 249 | u32 *payload, u8 len, bool wait_done, |
261 | bool check_bt); | 250 | bool check_bt); |
262 | u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data); | 251 | u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type); |
263 | void ar9003_mci_setup(struct ath_hw *ah, u32 gpm_addr, void *gpm_buf, | 252 | void ar9003_mci_setup(struct ath_hw *ah, u32 gpm_addr, void *gpm_buf, |
264 | u16 len, u32 sched_addr); | 253 | u16 len, u32 sched_addr); |
265 | void ar9003_mci_cleanup(struct ath_hw *ah); | 254 | void ar9003_mci_cleanup(struct ath_hw *ah); |
266 | void ar9003_mci_get_interrupt(struct ath_hw *ah, u32 *raw_intr, | 255 | void ar9003_mci_get_interrupt(struct ath_hw *ah, u32 *raw_intr, |
267 | u32 *rx_msg_intr); | 256 | u32 *rx_msg_intr); |
268 | void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah); | 257 | u32 ar9003_mci_get_next_gpm_offset(struct ath_hw *ah, bool first, u32 *more); |
269 | 258 | void ar9003_mci_set_bt_version(struct ath_hw *ah, u8 major, u8 minor); | |
259 | void ar9003_mci_send_wlan_channels(struct ath_hw *ah); | ||
270 | /* | 260 | /* |
271 | * These functions are used by ath9k_hw. | 261 | * These functions are used by ath9k_hw. |
272 | */ | 262 | */ |
@@ -277,7 +267,7 @@ void ar9003_mci_stop_bt(struct ath_hw *ah, bool save_fullsleep); | |||
277 | void ar9003_mci_init_cal_req(struct ath_hw *ah, bool *is_reusable); | 267 | void ar9003_mci_init_cal_req(struct ath_hw *ah, bool *is_reusable); |
278 | void ar9003_mci_init_cal_done(struct ath_hw *ah); | 268 | void ar9003_mci_init_cal_done(struct ath_hw *ah); |
279 | void ar9003_mci_set_full_sleep(struct ath_hw *ah); | 269 | void ar9003_mci_set_full_sleep(struct ath_hw *ah); |
280 | void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool wait_done); | 270 | void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool force); |
281 | void ar9003_mci_check_bt(struct ath_hw *ah); | 271 | void ar9003_mci_check_bt(struct ath_hw *ah); |
282 | bool ar9003_mci_start_reset(struct ath_hw *ah, struct ath9k_channel *chan); | 272 | bool ar9003_mci_start_reset(struct ath_hw *ah, struct ath9k_channel *chan); |
283 | int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan, | 273 | int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan, |
@@ -285,6 +275,9 @@ int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
285 | void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g, | 275 | void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g, |
286 | bool is_full_sleep); | 276 | bool is_full_sleep); |
287 | void ar9003_mci_get_isr(struct ath_hw *ah, enum ath9k_int *masked); | 277 | void ar9003_mci_get_isr(struct ath_hw *ah, enum ath9k_int *masked); |
278 | void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah); | ||
279 | void ar9003_mci_set_power_awake(struct ath_hw *ah); | ||
280 | void ar9003_mci_check_gpm_offset(struct ath_hw *ah); | ||
288 | 281 | ||
289 | #else | 282 | #else |
290 | 283 | ||
@@ -322,6 +315,15 @@ static inline void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g, | |||
322 | static inline void ar9003_mci_get_isr(struct ath_hw *ah, enum ath9k_int *masked) | 315 | static inline void ar9003_mci_get_isr(struct ath_hw *ah, enum ath9k_int *masked) |
323 | { | 316 | { |
324 | } | 317 | } |
318 | static inline void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah) | ||
319 | { | ||
320 | } | ||
321 | static inline void ar9003_mci_set_power_awake(struct ath_hw *ah) | ||
322 | { | ||
323 | } | ||
324 | static inline void ar9003_mci_check_gpm_offset(struct ath_hw *ah) | ||
325 | { | ||
326 | } | ||
325 | #endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */ | 327 | #endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */ |
326 | 328 | ||
327 | #endif | 329 | #endif |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index d6baf69cdc1..6b91ebb158f 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c | |||
@@ -173,7 +173,7 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah, | |||
173 | int cur_bb_spur, negative = 0, cck_spur_freq; | 173 | int cur_bb_spur, negative = 0, cck_spur_freq; |
174 | int i; | 174 | int i; |
175 | int range, max_spur_cnts, synth_freq; | 175 | int range, max_spur_cnts, synth_freq; |
176 | u8 *spur_fbin_ptr = NULL; | 176 | u8 *spur_fbin_ptr = ar9003_get_spur_chan_ptr(ah, IS_CHAN_2GHZ(chan)); |
177 | 177 | ||
178 | /* | 178 | /* |
179 | * Need to verify range +/- 10 MHz in control channel, otherwise spur | 179 | * Need to verify range +/- 10 MHz in control channel, otherwise spur |
@@ -181,8 +181,6 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah, | |||
181 | */ | 181 | */ |
182 | 182 | ||
183 | if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah)) { | 183 | if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah)) { |
184 | spur_fbin_ptr = ar9003_get_spur_chan_ptr(ah, | ||
185 | IS_CHAN_2GHZ(chan)); | ||
186 | if (spur_fbin_ptr[0] == 0) /* No spur */ | 184 | if (spur_fbin_ptr[0] == 0) /* No spur */ |
187 | return; | 185 | return; |
188 | max_spur_cnts = 5; | 186 | max_spur_cnts = 5; |
@@ -825,18 +823,18 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, | |||
825 | REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW, | 823 | REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW, |
826 | AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); | 824 | AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); |
827 | 825 | ||
828 | if (!on != aniState->ofdmWeakSigDetectOff) { | 826 | if (on != aniState->ofdmWeakSigDetect) { |
829 | ath_dbg(common, ANI, | 827 | ath_dbg(common, ANI, |
830 | "** ch %d: ofdm weak signal: %s=>%s\n", | 828 | "** ch %d: ofdm weak signal: %s=>%s\n", |
831 | chan->channel, | 829 | chan->channel, |
832 | !aniState->ofdmWeakSigDetectOff ? | 830 | aniState->ofdmWeakSigDetect ? |
833 | "on" : "off", | 831 | "on" : "off", |
834 | on ? "on" : "off"); | 832 | on ? "on" : "off"); |
835 | if (on) | 833 | if (on) |
836 | ah->stats.ast_ani_ofdmon++; | 834 | ah->stats.ast_ani_ofdmon++; |
837 | else | 835 | else |
838 | ah->stats.ast_ani_ofdmoff++; | 836 | ah->stats.ast_ani_ofdmoff++; |
839 | aniState->ofdmWeakSigDetectOff = !on; | 837 | aniState->ofdmWeakSigDetect = on; |
840 | } | 838 | } |
841 | break; | 839 | break; |
842 | } | 840 | } |
@@ -855,7 +853,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, | |||
855 | * from INI file & cap value | 853 | * from INI file & cap value |
856 | */ | 854 | */ |
857 | value = firstep_table[level] - | 855 | value = firstep_table[level] - |
858 | firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] + | 856 | firstep_table[ATH9K_ANI_FIRSTEP_LVL] + |
859 | aniState->iniDef.firstep; | 857 | aniState->iniDef.firstep; |
860 | if (value < ATH9K_SIG_FIRSTEP_SETTING_MIN) | 858 | if (value < ATH9K_SIG_FIRSTEP_SETTING_MIN) |
861 | value = ATH9K_SIG_FIRSTEP_SETTING_MIN; | 859 | value = ATH9K_SIG_FIRSTEP_SETTING_MIN; |
@@ -870,7 +868,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, | |||
870 | * from INI file & cap value | 868 | * from INI file & cap value |
871 | */ | 869 | */ |
872 | value2 = firstep_table[level] - | 870 | value2 = firstep_table[level] - |
873 | firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] + | 871 | firstep_table[ATH9K_ANI_FIRSTEP_LVL] + |
874 | aniState->iniDef.firstepLow; | 872 | aniState->iniDef.firstepLow; |
875 | if (value2 < ATH9K_SIG_FIRSTEP_SETTING_MIN) | 873 | if (value2 < ATH9K_SIG_FIRSTEP_SETTING_MIN) |
876 | value2 = ATH9K_SIG_FIRSTEP_SETTING_MIN; | 874 | value2 = ATH9K_SIG_FIRSTEP_SETTING_MIN; |
@@ -886,7 +884,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, | |||
886 | chan->channel, | 884 | chan->channel, |
887 | aniState->firstepLevel, | 885 | aniState->firstepLevel, |
888 | level, | 886 | level, |
889 | ATH9K_ANI_FIRSTEP_LVL_NEW, | 887 | ATH9K_ANI_FIRSTEP_LVL, |
890 | value, | 888 | value, |
891 | aniState->iniDef.firstep); | 889 | aniState->iniDef.firstep); |
892 | ath_dbg(common, ANI, | 890 | ath_dbg(common, ANI, |
@@ -894,7 +892,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, | |||
894 | chan->channel, | 892 | chan->channel, |
895 | aniState->firstepLevel, | 893 | aniState->firstepLevel, |
896 | level, | 894 | level, |
897 | ATH9K_ANI_FIRSTEP_LVL_NEW, | 895 | ATH9K_ANI_FIRSTEP_LVL, |
898 | value2, | 896 | value2, |
899 | aniState->iniDef.firstepLow); | 897 | aniState->iniDef.firstepLow); |
900 | if (level > aniState->firstepLevel) | 898 | if (level > aniState->firstepLevel) |
@@ -919,7 +917,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, | |||
919 | * from INI file & cap value | 917 | * from INI file & cap value |
920 | */ | 918 | */ |
921 | value = cycpwrThr1_table[level] - | 919 | value = cycpwrThr1_table[level] - |
922 | cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] + | 920 | cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL] + |
923 | aniState->iniDef.cycpwrThr1; | 921 | aniState->iniDef.cycpwrThr1; |
924 | if (value < ATH9K_SIG_SPUR_IMM_SETTING_MIN) | 922 | if (value < ATH9K_SIG_SPUR_IMM_SETTING_MIN) |
925 | value = ATH9K_SIG_SPUR_IMM_SETTING_MIN; | 923 | value = ATH9K_SIG_SPUR_IMM_SETTING_MIN; |
@@ -935,7 +933,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, | |||
935 | * from INI file & cap value | 933 | * from INI file & cap value |
936 | */ | 934 | */ |
937 | value2 = cycpwrThr1_table[level] - | 935 | value2 = cycpwrThr1_table[level] - |
938 | cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] + | 936 | cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL] + |
939 | aniState->iniDef.cycpwrThr1Ext; | 937 | aniState->iniDef.cycpwrThr1Ext; |
940 | if (value2 < ATH9K_SIG_SPUR_IMM_SETTING_MIN) | 938 | if (value2 < ATH9K_SIG_SPUR_IMM_SETTING_MIN) |
941 | value2 = ATH9K_SIG_SPUR_IMM_SETTING_MIN; | 939 | value2 = ATH9K_SIG_SPUR_IMM_SETTING_MIN; |
@@ -950,7 +948,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, | |||
950 | chan->channel, | 948 | chan->channel, |
951 | aniState->spurImmunityLevel, | 949 | aniState->spurImmunityLevel, |
952 | level, | 950 | level, |
953 | ATH9K_ANI_SPUR_IMMUNE_LVL_NEW, | 951 | ATH9K_ANI_SPUR_IMMUNE_LVL, |
954 | value, | 952 | value, |
955 | aniState->iniDef.cycpwrThr1); | 953 | aniState->iniDef.cycpwrThr1); |
956 | ath_dbg(common, ANI, | 954 | ath_dbg(common, ANI, |
@@ -958,7 +956,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, | |||
958 | chan->channel, | 956 | chan->channel, |
959 | aniState->spurImmunityLevel, | 957 | aniState->spurImmunityLevel, |
960 | level, | 958 | level, |
961 | ATH9K_ANI_SPUR_IMMUNE_LVL_NEW, | 959 | ATH9K_ANI_SPUR_IMMUNE_LVL, |
962 | value2, | 960 | value2, |
963 | aniState->iniDef.cycpwrThr1Ext); | 961 | aniState->iniDef.cycpwrThr1Ext); |
964 | if (level > aniState->spurImmunityLevel) | 962 | if (level > aniState->spurImmunityLevel) |
@@ -979,16 +977,16 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, | |||
979 | AR_PHY_MRC_CCK_ENABLE, is_on); | 977 | AR_PHY_MRC_CCK_ENABLE, is_on); |
980 | REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL, | 978 | REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL, |
981 | AR_PHY_MRC_CCK_MUX_REG, is_on); | 979 | AR_PHY_MRC_CCK_MUX_REG, is_on); |
982 | if (!is_on != aniState->mrcCCKOff) { | 980 | if (is_on != aniState->mrcCCK) { |
983 | ath_dbg(common, ANI, "** ch %d: MRC CCK: %s=>%s\n", | 981 | ath_dbg(common, ANI, "** ch %d: MRC CCK: %s=>%s\n", |
984 | chan->channel, | 982 | chan->channel, |
985 | !aniState->mrcCCKOff ? "on" : "off", | 983 | aniState->mrcCCK ? "on" : "off", |
986 | is_on ? "on" : "off"); | 984 | is_on ? "on" : "off"); |
987 | if (is_on) | 985 | if (is_on) |
988 | ah->stats.ast_ani_ccklow++; | 986 | ah->stats.ast_ani_ccklow++; |
989 | else | 987 | else |
990 | ah->stats.ast_ani_cckhigh++; | 988 | ah->stats.ast_ani_cckhigh++; |
991 | aniState->mrcCCKOff = !is_on; | 989 | aniState->mrcCCK = is_on; |
992 | } | 990 | } |
993 | break; | 991 | break; |
994 | } | 992 | } |
@@ -1002,9 +1000,9 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, | |||
1002 | ath_dbg(common, ANI, | 1000 | ath_dbg(common, ANI, |
1003 | "ANI parameters: SI=%d, ofdmWS=%s FS=%d MRCcck=%s listenTime=%d ofdmErrs=%d cckErrs=%d\n", | 1001 | "ANI parameters: SI=%d, ofdmWS=%s FS=%d MRCcck=%s listenTime=%d ofdmErrs=%d cckErrs=%d\n", |
1004 | aniState->spurImmunityLevel, | 1002 | aniState->spurImmunityLevel, |
1005 | !aniState->ofdmWeakSigDetectOff ? "on" : "off", | 1003 | aniState->ofdmWeakSigDetect ? "on" : "off", |
1006 | aniState->firstepLevel, | 1004 | aniState->firstepLevel, |
1007 | !aniState->mrcCCKOff ? "on" : "off", | 1005 | aniState->mrcCCK ? "on" : "off", |
1008 | aniState->listenTime, | 1006 | aniState->listenTime, |
1009 | aniState->ofdmPhyErrCount, | 1007 | aniState->ofdmPhyErrCount, |
1010 | aniState->cckPhyErrCount); | 1008 | aniState->cckPhyErrCount); |
@@ -1111,10 +1109,10 @@ static void ar9003_hw_ani_cache_ini_regs(struct ath_hw *ah) | |||
1111 | AR_PHY_EXT_CYCPWR_THR1); | 1109 | AR_PHY_EXT_CYCPWR_THR1); |
1112 | 1110 | ||
1113 | /* these levels just got reset to defaults by the INI */ | 1111 | /* these levels just got reset to defaults by the INI */ |
1114 | aniState->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL_NEW; | 1112 | aniState->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL; |
1115 | aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW; | 1113 | aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL; |
1116 | aniState->ofdmWeakSigDetectOff = !ATH9K_ANI_USE_OFDM_WEAK_SIG; | 1114 | aniState->ofdmWeakSigDetect = ATH9K_ANI_USE_OFDM_WEAK_SIG; |
1117 | aniState->mrcCCKOff = !ATH9K_ANI_ENABLE_MRC_CCK; | 1115 | aniState->mrcCCK = true; |
1118 | } | 1116 | } |
1119 | 1117 | ||
1120 | static void ar9003_hw_set_radar_params(struct ath_hw *ah, | 1118 | static void ar9003_hw_set_radar_params(struct ath_hw *ah, |
diff --git a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h index a10ece0cb6c..bbf48918a56 100644 --- a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h | |||
@@ -52,7 +52,7 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = { | |||
52 | {0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020}, | 52 | {0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020}, |
53 | {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000d8}, | 53 | {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000d8}, |
54 | {0x00009e10, 0x92c88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec86d2e}, | 54 | {0x00009e10, 0x92c88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec86d2e}, |
55 | {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3376605e, 0x33795d5e}, | 55 | {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3376605e, 0x32395d5e}, |
56 | {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 56 | {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
57 | {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, | 57 | {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, |
58 | {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, | 58 | {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, |
@@ -61,7 +61,7 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = { | |||
61 | {0x00009e44, 0x62321e27, 0x62321e27, 0xfe291e27, 0xfe291e27}, | 61 | {0x00009e44, 0x62321e27, 0x62321e27, 0xfe291e27, 0xfe291e27}, |
62 | {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, | 62 | {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, |
63 | {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, | 63 | {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, |
64 | {0x0000a204, 0x013187c0, 0x013187c4, 0x013187c4, 0x013187c0}, | 64 | {0x0000a204, 0x01318fc0, 0x01318fc4, 0x01318fc4, 0x01318fc0}, |
65 | {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, | 65 | {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, |
66 | {0x0000a22c, 0x01026a2f, 0x01026a27, 0x01026a2f, 0x01026a2f}, | 66 | {0x0000a22c, 0x01026a2f, 0x01026a27, 0x01026a2f, 0x01026a2f}, |
67 | {0x0000a230, 0x0000400a, 0x00004014, 0x00004016, 0x0000400b}, | 67 | {0x0000a230, 0x0000400a, 0x00004014, 0x00004016, 0x0000400b}, |
@@ -1007,6 +1007,7 @@ static const u32 ar9462_2p0_radio_core[][2] = { | |||
1007 | 1007 | ||
1008 | static const u32 ar9462_2p0_soc_preamble[][2] = { | 1008 | static const u32 ar9462_2p0_soc_preamble[][2] = { |
1009 | /* Addr allmodes */ | 1009 | /* Addr allmodes */ |
1010 | {0x000040a4 ,0x00a0c1c9}, | ||
1010 | {0x00007020, 0x00000000}, | 1011 | {0x00007020, 0x00000000}, |
1011 | {0x00007034, 0x00000002}, | 1012 | {0x00007034, 0x00000002}, |
1012 | {0x00007038, 0x000004c2}, | 1013 | {0x00007038, 0x000004c2}, |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 02fc1c1e5ee..4473278efc5 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -698,6 +698,7 @@ struct ath_softc { | |||
698 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT | 698 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT |
699 | struct ath_btcoex btcoex; | 699 | struct ath_btcoex btcoex; |
700 | struct ath_mci_coex mci_coex; | 700 | struct ath_mci_coex mci_coex; |
701 | struct work_struct mci_work; | ||
701 | #endif | 702 | #endif |
702 | 703 | ||
703 | struct ath_descdma txsdma; | 704 | struct ath_descdma txsdma; |
@@ -720,6 +721,7 @@ extern int ath9k_modparam_nohwcrypt; | |||
720 | extern int led_blink; | 721 | extern int led_blink; |
721 | extern bool is_ath9k_unloaded; | 722 | extern bool is_ath9k_unloaded; |
722 | 723 | ||
724 | u8 ath9k_parse_mpdudensity(u8 mpdudensity); | ||
723 | irqreturn_t ath_isr(int irq, void *dev); | 725 | irqreturn_t ath_isr(int irq, void *dev); |
724 | int ath9k_init_device(u16 devid, struct ath_softc *sc, | 726 | int ath9k_init_device(u16 devid, struct ath_softc *sc, |
725 | const struct ath_bus_ops *bus_ops); | 727 | const struct ath_bus_ops *bus_ops); |
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 2831258d950..5c3192ffc19 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -348,8 +348,6 @@ void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status) | |||
348 | sc->debug.stats.istats.txok++; | 348 | sc->debug.stats.istats.txok++; |
349 | if (status & ATH9K_INT_TXURN) | 349 | if (status & ATH9K_INT_TXURN) |
350 | sc->debug.stats.istats.txurn++; | 350 | sc->debug.stats.istats.txurn++; |
351 | if (status & ATH9K_INT_MIB) | ||
352 | sc->debug.stats.istats.mib++; | ||
353 | if (status & ATH9K_INT_RXPHY) | 351 | if (status & ATH9K_INT_RXPHY) |
354 | sc->debug.stats.istats.rxphyerr++; | 352 | sc->debug.stats.istats.rxphyerr++; |
355 | if (status & ATH9K_INT_RXKCM) | 353 | if (status & ATH9K_INT_RXKCM) |
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index af6d2735029..26032cb59b8 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c | |||
@@ -202,7 +202,7 @@ static void ath_btcoex_period_timer(unsigned long data) | |||
202 | 202 | ||
203 | btcoex->bt_wait_time += btcoex->btcoex_period; | 203 | btcoex->bt_wait_time += btcoex->btcoex_period; |
204 | if (btcoex->bt_wait_time > ATH_BTCOEX_RX_WAIT_TIME) { | 204 | if (btcoex->bt_wait_time > ATH_BTCOEX_RX_WAIT_TIME) { |
205 | if (ar9003_mci_state(ah, MCI_STATE_NEED_FTP_STOMP, NULL) && | 205 | if (ar9003_mci_state(ah, MCI_STATE_NEED_FTP_STOMP) && |
206 | (mci->num_pan || mci->num_other_acl)) | 206 | (mci->num_pan || mci->num_other_acl)) |
207 | ah->btcoex_hw.mci.stomp_ftp = | 207 | ah->btcoex_hw.mci.stomp_ftp = |
208 | (sc->rx.num_pkts < ATH_BTCOEX_STOMP_FTP_THRESH); | 208 | (sc->rx.num_pkts < ATH_BTCOEX_STOMP_FTP_THRESH); |
@@ -232,7 +232,7 @@ static void ath_btcoex_period_timer(unsigned long data) | |||
232 | } | 232 | } |
233 | 233 | ||
234 | ath9k_ps_restore(sc); | 234 | ath9k_ps_restore(sc); |
235 | timer_period = btcoex->btcoex_period / 1000; | 235 | timer_period = btcoex->btcoex_period; |
236 | mod_timer(&btcoex->period_timer, jiffies + msecs_to_jiffies(timer_period)); | 236 | mod_timer(&btcoex->period_timer, jiffies + msecs_to_jiffies(timer_period)); |
237 | } | 237 | } |
238 | 238 | ||
@@ -267,10 +267,10 @@ static int ath_init_btcoex_timer(struct ath_softc *sc) | |||
267 | { | 267 | { |
268 | struct ath_btcoex *btcoex = &sc->btcoex; | 268 | struct ath_btcoex *btcoex = &sc->btcoex; |
269 | 269 | ||
270 | btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD * 1000; | 270 | btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD; |
271 | btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) * | 271 | btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) * 1000 * |
272 | btcoex->btcoex_period / 100; | 272 | btcoex->btcoex_period / 100; |
273 | btcoex->btscan_no_stomp = (100 - ATH_BTCOEX_BTSCAN_DUTY_CYCLE) * | 273 | btcoex->btscan_no_stomp = (100 - ATH_BTCOEX_BTSCAN_DUTY_CYCLE) * 1000 * |
274 | btcoex->btcoex_period / 100; | 274 | btcoex->btcoex_period / 100; |
275 | 275 | ||
276 | setup_timer(&btcoex->period_timer, ath_btcoex_period_timer, | 276 | setup_timer(&btcoex->period_timer, ath_btcoex_period_timer, |
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 135795257d9..936e920fb88 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h | |||
@@ -453,7 +453,6 @@ struct ath9k_htc_priv { | |||
453 | u8 num_sta_assoc_vif; | 453 | u8 num_sta_assoc_vif; |
454 | u8 num_ap_vif; | 454 | u8 num_ap_vif; |
455 | 455 | ||
456 | u16 op_flags; | ||
457 | u16 curtxpow; | 456 | u16 curtxpow; |
458 | u16 txpowlimit; | 457 | u16 txpowlimit; |
459 | u16 nvifs; | 458 | u16 nvifs; |
@@ -461,6 +460,7 @@ struct ath9k_htc_priv { | |||
461 | bool rearm_ani; | 460 | bool rearm_ani; |
462 | bool reconfig_beacon; | 461 | bool reconfig_beacon; |
463 | unsigned int rxfilter; | 462 | unsigned int rxfilter; |
463 | unsigned long op_flags; | ||
464 | 464 | ||
465 | struct ath9k_hw_cal_data caldata; | 465 | struct ath9k_hw_cal_data caldata; |
466 | struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; | 466 | struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; |
@@ -572,8 +572,6 @@ bool ath9k_htc_setpower(struct ath9k_htc_priv *priv, | |||
572 | 572 | ||
573 | void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv); | 573 | void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv); |
574 | void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw); | 574 | void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw); |
575 | void ath9k_htc_radio_enable(struct ieee80211_hw *hw); | ||
576 | void ath9k_htc_radio_disable(struct ieee80211_hw *hw); | ||
577 | 575 | ||
578 | #ifdef CONFIG_MAC80211_LEDS | 576 | #ifdef CONFIG_MAC80211_LEDS |
579 | void ath9k_init_leds(struct ath9k_htc_priv *priv); | 577 | void ath9k_init_leds(struct ath9k_htc_priv *priv); |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index 2eadffb7971..77d541feb91 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c | |||
@@ -207,9 +207,9 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv, | |||
207 | else | 207 | else |
208 | priv->ah->config.sw_beacon_response_time = MIN_SWBA_RESPONSE; | 208 | priv->ah->config.sw_beacon_response_time = MIN_SWBA_RESPONSE; |
209 | 209 | ||
210 | if (priv->op_flags & OP_TSF_RESET) { | 210 | if (test_bit(OP_TSF_RESET, &priv->op_flags)) { |
211 | ath9k_hw_reset_tsf(priv->ah); | 211 | ath9k_hw_reset_tsf(priv->ah); |
212 | priv->op_flags &= ~OP_TSF_RESET; | 212 | clear_bit(OP_TSF_RESET, &priv->op_flags); |
213 | } else { | 213 | } else { |
214 | /* | 214 | /* |
215 | * Pull nexttbtt forward to reflect the current TSF. | 215 | * Pull nexttbtt forward to reflect the current TSF. |
@@ -221,7 +221,7 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv, | |||
221 | } while (nexttbtt < tsftu); | 221 | } while (nexttbtt < tsftu); |
222 | } | 222 | } |
223 | 223 | ||
224 | if (priv->op_flags & OP_ENABLE_BEACON) | 224 | if (test_bit(OP_ENABLE_BEACON, &priv->op_flags)) |
225 | imask |= ATH9K_INT_SWBA; | 225 | imask |= ATH9K_INT_SWBA; |
226 | 226 | ||
227 | ath_dbg(common, CONFIG, | 227 | ath_dbg(common, CONFIG, |
@@ -269,7 +269,7 @@ static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv, | |||
269 | else | 269 | else |
270 | priv->ah->config.sw_beacon_response_time = MIN_SWBA_RESPONSE; | 270 | priv->ah->config.sw_beacon_response_time = MIN_SWBA_RESPONSE; |
271 | 271 | ||
272 | if (priv->op_flags & OP_ENABLE_BEACON) | 272 | if (test_bit(OP_ENABLE_BEACON, &priv->op_flags)) |
273 | imask |= ATH9K_INT_SWBA; | 273 | imask |= ATH9K_INT_SWBA; |
274 | 274 | ||
275 | ath_dbg(common, CONFIG, | 275 | ath_dbg(common, CONFIG, |
@@ -365,7 +365,7 @@ static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv, | |||
365 | vif = priv->cur_beacon_conf.bslot[slot]; | 365 | vif = priv->cur_beacon_conf.bslot[slot]; |
366 | avp = (struct ath9k_htc_vif *)vif->drv_priv; | 366 | avp = (struct ath9k_htc_vif *)vif->drv_priv; |
367 | 367 | ||
368 | if (unlikely(priv->op_flags & OP_SCANNING)) { | 368 | if (unlikely(test_bit(OP_SCANNING, &priv->op_flags))) { |
369 | spin_unlock_bh(&priv->beacon_lock); | 369 | spin_unlock_bh(&priv->beacon_lock); |
370 | return; | 370 | return; |
371 | } | 371 | } |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c index 1c10e2e5c23..07df279c8d4 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c | |||
@@ -37,17 +37,18 @@ static void ath_detect_bt_priority(struct ath9k_htc_priv *priv) | |||
37 | 37 | ||
38 | if (time_after(jiffies, btcoex->bt_priority_time + | 38 | if (time_after(jiffies, btcoex->bt_priority_time + |
39 | msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) { | 39 | msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) { |
40 | priv->op_flags &= ~(OP_BT_PRIORITY_DETECTED | OP_BT_SCAN); | 40 | clear_bit(OP_BT_PRIORITY_DETECTED, &priv->op_flags); |
41 | clear_bit(OP_BT_SCAN, &priv->op_flags); | ||
41 | /* Detect if colocated bt started scanning */ | 42 | /* Detect if colocated bt started scanning */ |
42 | if (btcoex->bt_priority_cnt >= ATH_BT_CNT_SCAN_THRESHOLD) { | 43 | if (btcoex->bt_priority_cnt >= ATH_BT_CNT_SCAN_THRESHOLD) { |
43 | ath_dbg(ath9k_hw_common(ah), BTCOEX, | 44 | ath_dbg(ath9k_hw_common(ah), BTCOEX, |
44 | "BT scan detected\n"); | 45 | "BT scan detected\n"); |
45 | priv->op_flags |= (OP_BT_SCAN | | 46 | set_bit(OP_BT_PRIORITY_DETECTED, &priv->op_flags); |
46 | OP_BT_PRIORITY_DETECTED); | 47 | set_bit(OP_BT_SCAN, &priv->op_flags); |
47 | } else if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) { | 48 | } else if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) { |
48 | ath_dbg(ath9k_hw_common(ah), BTCOEX, | 49 | ath_dbg(ath9k_hw_common(ah), BTCOEX, |
49 | "BT priority traffic detected\n"); | 50 | "BT priority traffic detected\n"); |
50 | priv->op_flags |= OP_BT_PRIORITY_DETECTED; | 51 | set_bit(OP_BT_PRIORITY_DETECTED, &priv->op_flags); |
51 | } | 52 | } |
52 | 53 | ||
53 | btcoex->bt_priority_cnt = 0; | 54 | btcoex->bt_priority_cnt = 0; |
@@ -67,26 +68,23 @@ static void ath_btcoex_period_work(struct work_struct *work) | |||
67 | struct ath_btcoex *btcoex = &priv->btcoex; | 68 | struct ath_btcoex *btcoex = &priv->btcoex; |
68 | struct ath_common *common = ath9k_hw_common(priv->ah); | 69 | struct ath_common *common = ath9k_hw_common(priv->ah); |
69 | u32 timer_period; | 70 | u32 timer_period; |
70 | bool is_btscan; | ||
71 | int ret; | 71 | int ret; |
72 | 72 | ||
73 | ath_detect_bt_priority(priv); | 73 | ath_detect_bt_priority(priv); |
74 | 74 | ||
75 | is_btscan = !!(priv->op_flags & OP_BT_SCAN); | ||
76 | |||
77 | ret = ath9k_htc_update_cap_target(priv, | 75 | ret = ath9k_htc_update_cap_target(priv, |
78 | !!(priv->op_flags & OP_BT_PRIORITY_DETECTED)); | 76 | test_bit(OP_BT_PRIORITY_DETECTED, &priv->op_flags)); |
79 | if (ret) { | 77 | if (ret) { |
80 | ath_err(common, "Unable to set BTCOEX parameters\n"); | 78 | ath_err(common, "Unable to set BTCOEX parameters\n"); |
81 | return; | 79 | return; |
82 | } | 80 | } |
83 | 81 | ||
84 | ath9k_hw_btcoex_bt_stomp(priv->ah, is_btscan ? ATH_BTCOEX_STOMP_ALL : | 82 | ath9k_hw_btcoex_bt_stomp(priv->ah, test_bit(OP_BT_SCAN, &priv->op_flags) ? |
85 | btcoex->bt_stomp_type); | 83 | ATH_BTCOEX_STOMP_ALL : btcoex->bt_stomp_type); |
86 | 84 | ||
87 | ath9k_hw_btcoex_enable(priv->ah); | 85 | ath9k_hw_btcoex_enable(priv->ah); |
88 | timer_period = is_btscan ? btcoex->btscan_no_stomp : | 86 | timer_period = test_bit(OP_BT_SCAN, &priv->op_flags) ? |
89 | btcoex->btcoex_no_stomp; | 87 | btcoex->btscan_no_stomp : btcoex->btcoex_no_stomp; |
90 | ieee80211_queue_delayed_work(priv->hw, &priv->duty_cycle_work, | 88 | ieee80211_queue_delayed_work(priv->hw, &priv->duty_cycle_work, |
91 | msecs_to_jiffies(timer_period)); | 89 | msecs_to_jiffies(timer_period)); |
92 | ieee80211_queue_delayed_work(priv->hw, &priv->coex_period_work, | 90 | ieee80211_queue_delayed_work(priv->hw, &priv->coex_period_work, |
@@ -104,14 +102,15 @@ static void ath_btcoex_duty_cycle_work(struct work_struct *work) | |||
104 | struct ath_hw *ah = priv->ah; | 102 | struct ath_hw *ah = priv->ah; |
105 | struct ath_btcoex *btcoex = &priv->btcoex; | 103 | struct ath_btcoex *btcoex = &priv->btcoex; |
106 | struct ath_common *common = ath9k_hw_common(ah); | 104 | struct ath_common *common = ath9k_hw_common(ah); |
107 | bool is_btscan = priv->op_flags & OP_BT_SCAN; | ||
108 | 105 | ||
109 | ath_dbg(common, BTCOEX, "time slice work for bt and wlan\n"); | 106 | ath_dbg(common, BTCOEX, "time slice work for bt and wlan\n"); |
110 | 107 | ||
111 | if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan) | 108 | if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || |
109 | test_bit(OP_BT_SCAN, &priv->op_flags)) | ||
112 | ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE); | 110 | ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE); |
113 | else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) | 111 | else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) |
114 | ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_LOW); | 112 | ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_LOW); |
113 | |||
115 | ath9k_hw_btcoex_enable(priv->ah); | 114 | ath9k_hw_btcoex_enable(priv->ah); |
116 | } | 115 | } |
117 | 116 | ||
@@ -141,7 +140,8 @@ static void ath_htc_resume_btcoex_work(struct ath9k_htc_priv *priv) | |||
141 | 140 | ||
142 | btcoex->bt_priority_cnt = 0; | 141 | btcoex->bt_priority_cnt = 0; |
143 | btcoex->bt_priority_time = jiffies; | 142 | btcoex->bt_priority_time = jiffies; |
144 | priv->op_flags &= ~(OP_BT_PRIORITY_DETECTED | OP_BT_SCAN); | 143 | clear_bit(OP_BT_PRIORITY_DETECTED, &priv->op_flags); |
144 | clear_bit(OP_BT_SCAN, &priv->op_flags); | ||
145 | ieee80211_queue_delayed_work(priv->hw, &priv->coex_period_work, 0); | 145 | ieee80211_queue_delayed_work(priv->hw, &priv->coex_period_work, 0); |
146 | } | 146 | } |
147 | 147 | ||
@@ -310,95 +310,3 @@ void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv) | |||
310 | if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) | 310 | if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) |
311 | wiphy_rfkill_start_polling(priv->hw->wiphy); | 311 | wiphy_rfkill_start_polling(priv->hw->wiphy); |
312 | } | 312 | } |
313 | |||
314 | void ath9k_htc_radio_enable(struct ieee80211_hw *hw) | ||
315 | { | ||
316 | struct ath9k_htc_priv *priv = hw->priv; | ||
317 | struct ath_hw *ah = priv->ah; | ||
318 | struct ath_common *common = ath9k_hw_common(ah); | ||
319 | int ret; | ||
320 | u8 cmd_rsp; | ||
321 | |||
322 | if (!ah->curchan) | ||
323 | ah->curchan = ath9k_cmn_get_curchannel(hw, ah); | ||
324 | |||
325 | /* Reset the HW */ | ||
326 | ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); | ||
327 | if (ret) { | ||
328 | ath_err(common, | ||
329 | "Unable to reset hardware; reset status %d (freq %u MHz)\n", | ||
330 | ret, ah->curchan->channel); | ||
331 | } | ||
332 | |||
333 | ath9k_cmn_update_txpow(ah, priv->curtxpow, priv->txpowlimit, | ||
334 | &priv->curtxpow); | ||
335 | |||
336 | /* Start RX */ | ||
337 | WMI_CMD(WMI_START_RECV_CMDID); | ||
338 | ath9k_host_rx_init(priv); | ||
339 | |||
340 | /* Start TX */ | ||
341 | htc_start(priv->htc); | ||
342 | spin_lock_bh(&priv->tx.tx_lock); | ||
343 | priv->tx.flags &= ~ATH9K_HTC_OP_TX_QUEUES_STOP; | ||
344 | spin_unlock_bh(&priv->tx.tx_lock); | ||
345 | ieee80211_wake_queues(hw); | ||
346 | |||
347 | WMI_CMD(WMI_ENABLE_INTR_CMDID); | ||
348 | |||
349 | /* Enable LED */ | ||
350 | ath9k_hw_cfg_output(ah, ah->led_pin, | ||
351 | AR_GPIO_OUTPUT_MUX_AS_OUTPUT); | ||
352 | ath9k_hw_set_gpio(ah, ah->led_pin, 0); | ||
353 | } | ||
354 | |||
355 | void ath9k_htc_radio_disable(struct ieee80211_hw *hw) | ||
356 | { | ||
357 | struct ath9k_htc_priv *priv = hw->priv; | ||
358 | struct ath_hw *ah = priv->ah; | ||
359 | struct ath_common *common = ath9k_hw_common(ah); | ||
360 | int ret; | ||
361 | u8 cmd_rsp; | ||
362 | |||
363 | ath9k_htc_ps_wakeup(priv); | ||
364 | |||
365 | /* Disable LED */ | ||
366 | ath9k_hw_set_gpio(ah, ah->led_pin, 1); | ||
367 | ath9k_hw_cfg_gpio_input(ah, ah->led_pin); | ||
368 | |||
369 | WMI_CMD(WMI_DISABLE_INTR_CMDID); | ||
370 | |||
371 | /* Stop TX */ | ||
372 | ieee80211_stop_queues(hw); | ||
373 | ath9k_htc_tx_drain(priv); | ||
374 | WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); | ||
375 | |||
376 | /* Stop RX */ | ||
377 | WMI_CMD(WMI_STOP_RECV_CMDID); | ||
378 | |||
379 | /* Clear the WMI event queue */ | ||
380 | ath9k_wmi_event_drain(priv); | ||
381 | |||
382 | /* | ||
383 | * The MIB counters have to be disabled here, | ||
384 | * since the target doesn't do it. | ||
385 | */ | ||
386 | ath9k_hw_disable_mib_counters(ah); | ||
387 | |||
388 | if (!ah->curchan) | ||
389 | ah->curchan = ath9k_cmn_get_curchannel(hw, ah); | ||
390 | |||
391 | /* Reset the HW */ | ||
392 | ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); | ||
393 | if (ret) { | ||
394 | ath_err(common, | ||
395 | "Unable to reset hardware; reset status %d (freq %u MHz)\n", | ||
396 | ret, ah->curchan->channel); | ||
397 | } | ||
398 | |||
399 | /* Disable the PHY */ | ||
400 | ath9k_hw_phy_disable(ah); | ||
401 | |||
402 | ath9k_htc_ps_restore(priv); | ||
403 | ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP); | ||
404 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 25213d521bc..a035a380d66 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c | |||
@@ -611,7 +611,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, | |||
611 | struct ath_common *common; | 611 | struct ath_common *common; |
612 | int i, ret = 0, csz = 0; | 612 | int i, ret = 0, csz = 0; |
613 | 613 | ||
614 | priv->op_flags |= OP_INVALID; | 614 | set_bit(OP_INVALID, &priv->op_flags); |
615 | 615 | ||
616 | ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL); | 616 | ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL); |
617 | if (!ah) | 617 | if (!ah) |
@@ -718,7 +718,7 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, | |||
718 | 718 | ||
719 | hw->queues = 4; | 719 | hw->queues = 4; |
720 | hw->channel_change_time = 5000; | 720 | hw->channel_change_time = 5000; |
721 | hw->max_listen_interval = 10; | 721 | hw->max_listen_interval = 1; |
722 | 722 | ||
723 | hw->vif_data_size = sizeof(struct ath9k_htc_vif); | 723 | hw->vif_data_size = sizeof(struct ath9k_htc_vif); |
724 | hw->sta_data_size = sizeof(struct ath9k_htc_sta); | 724 | hw->sta_data_size = sizeof(struct ath9k_htc_sta); |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 2b8f61c210e..fc8cd828410 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | |||
@@ -75,14 +75,19 @@ unlock: | |||
75 | 75 | ||
76 | void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv) | 76 | void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv) |
77 | { | 77 | { |
78 | bool reset; | ||
79 | |||
78 | mutex_lock(&priv->htc_pm_lock); | 80 | mutex_lock(&priv->htc_pm_lock); |
79 | if (--priv->ps_usecount != 0) | 81 | if (--priv->ps_usecount != 0) |
80 | goto unlock; | 82 | goto unlock; |
81 | 83 | ||
82 | if (priv->ps_idle) | 84 | if (priv->ps_idle) { |
85 | ath9k_hw_setrxabort(priv->ah, true); | ||
86 | ath9k_hw_stopdmarecv(priv->ah, &reset); | ||
83 | ath9k_hw_setpower(priv->ah, ATH9K_PM_FULL_SLEEP); | 87 | ath9k_hw_setpower(priv->ah, ATH9K_PM_FULL_SLEEP); |
84 | else if (priv->ps_enabled) | 88 | } else if (priv->ps_enabled) { |
85 | ath9k_hw_setpower(priv->ah, ATH9K_PM_NETWORK_SLEEP); | 89 | ath9k_hw_setpower(priv->ah, ATH9K_PM_NETWORK_SLEEP); |
90 | } | ||
86 | 91 | ||
87 | unlock: | 92 | unlock: |
88 | mutex_unlock(&priv->htc_pm_lock); | 93 | mutex_unlock(&priv->htc_pm_lock); |
@@ -250,7 +255,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, | |||
250 | u8 cmd_rsp; | 255 | u8 cmd_rsp; |
251 | int ret; | 256 | int ret; |
252 | 257 | ||
253 | if (priv->op_flags & OP_INVALID) | 258 | if (test_bit(OP_INVALID, &priv->op_flags)) |
254 | return -EIO; | 259 | return -EIO; |
255 | 260 | ||
256 | fastcc = !!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL); | 261 | fastcc = !!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL); |
@@ -304,7 +309,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, | |||
304 | 309 | ||
305 | htc_start(priv->htc); | 310 | htc_start(priv->htc); |
306 | 311 | ||
307 | if (!(priv->op_flags & OP_SCANNING) && | 312 | if (!test_bit(OP_SCANNING, &priv->op_flags) && |
308 | !(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) | 313 | !(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) |
309 | ath9k_htc_vif_reconfig(priv); | 314 | ath9k_htc_vif_reconfig(priv); |
310 | 315 | ||
@@ -750,7 +755,7 @@ void ath9k_htc_start_ani(struct ath9k_htc_priv *priv) | |||
750 | common->ani.shortcal_timer = timestamp; | 755 | common->ani.shortcal_timer = timestamp; |
751 | common->ani.checkani_timer = timestamp; | 756 | common->ani.checkani_timer = timestamp; |
752 | 757 | ||
753 | priv->op_flags |= OP_ANI_RUNNING; | 758 | set_bit(OP_ANI_RUNNING, &priv->op_flags); |
754 | 759 | ||
755 | ieee80211_queue_delayed_work(common->hw, &priv->ani_work, | 760 | ieee80211_queue_delayed_work(common->hw, &priv->ani_work, |
756 | msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); | 761 | msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); |
@@ -759,7 +764,7 @@ void ath9k_htc_start_ani(struct ath9k_htc_priv *priv) | |||
759 | void ath9k_htc_stop_ani(struct ath9k_htc_priv *priv) | 764 | void ath9k_htc_stop_ani(struct ath9k_htc_priv *priv) |
760 | { | 765 | { |
761 | cancel_delayed_work_sync(&priv->ani_work); | 766 | cancel_delayed_work_sync(&priv->ani_work); |
762 | priv->op_flags &= ~OP_ANI_RUNNING; | 767 | clear_bit(OP_ANI_RUNNING, &priv->op_flags); |
763 | } | 768 | } |
764 | 769 | ||
765 | void ath9k_htc_ani_work(struct work_struct *work) | 770 | void ath9k_htc_ani_work(struct work_struct *work) |
@@ -944,7 +949,7 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) | |||
944 | ath_dbg(common, CONFIG, | 949 | ath_dbg(common, CONFIG, |
945 | "Failed to update capability in target\n"); | 950 | "Failed to update capability in target\n"); |
946 | 951 | ||
947 | priv->op_flags &= ~OP_INVALID; | 952 | clear_bit(OP_INVALID, &priv->op_flags); |
948 | htc_start(priv->htc); | 953 | htc_start(priv->htc); |
949 | 954 | ||
950 | spin_lock_bh(&priv->tx.tx_lock); | 955 | spin_lock_bh(&priv->tx.tx_lock); |
@@ -973,7 +978,7 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) | |||
973 | 978 | ||
974 | mutex_lock(&priv->mutex); | 979 | mutex_lock(&priv->mutex); |
975 | 980 | ||
976 | if (priv->op_flags & OP_INVALID) { | 981 | if (test_bit(OP_INVALID, &priv->op_flags)) { |
977 | ath_dbg(common, ANY, "Device not present\n"); | 982 | ath_dbg(common, ANY, "Device not present\n"); |
978 | mutex_unlock(&priv->mutex); | 983 | mutex_unlock(&priv->mutex); |
979 | return; | 984 | return; |
@@ -1015,7 +1020,7 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) | |||
1015 | ath9k_htc_ps_restore(priv); | 1020 | ath9k_htc_ps_restore(priv); |
1016 | ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP); | 1021 | ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP); |
1017 | 1022 | ||
1018 | priv->op_flags |= OP_INVALID; | 1023 | set_bit(OP_INVALID, &priv->op_flags); |
1019 | 1024 | ||
1020 | ath_dbg(common, CONFIG, "Driver halt\n"); | 1025 | ath_dbg(common, CONFIG, "Driver halt\n"); |
1021 | mutex_unlock(&priv->mutex); | 1026 | mutex_unlock(&priv->mutex); |
@@ -1105,7 +1110,7 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw, | |||
1105 | ath9k_htc_set_opmode(priv); | 1110 | ath9k_htc_set_opmode(priv); |
1106 | 1111 | ||
1107 | if ((priv->ah->opmode == NL80211_IFTYPE_AP) && | 1112 | if ((priv->ah->opmode == NL80211_IFTYPE_AP) && |
1108 | !(priv->op_flags & OP_ANI_RUNNING)) { | 1113 | !test_bit(OP_ANI_RUNNING, &priv->op_flags)) { |
1109 | ath9k_hw_set_tsfadjust(priv->ah, 1); | 1114 | ath9k_hw_set_tsfadjust(priv->ah, 1); |
1110 | ath9k_htc_start_ani(priv); | 1115 | ath9k_htc_start_ani(priv); |
1111 | } | 1116 | } |
@@ -1178,24 +1183,20 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) | |||
1178 | struct ath9k_htc_priv *priv = hw->priv; | 1183 | struct ath9k_htc_priv *priv = hw->priv; |
1179 | struct ath_common *common = ath9k_hw_common(priv->ah); | 1184 | struct ath_common *common = ath9k_hw_common(priv->ah); |
1180 | struct ieee80211_conf *conf = &hw->conf; | 1185 | struct ieee80211_conf *conf = &hw->conf; |
1186 | bool chip_reset = false; | ||
1187 | int ret = 0; | ||
1181 | 1188 | ||
1182 | mutex_lock(&priv->mutex); | 1189 | mutex_lock(&priv->mutex); |
1190 | ath9k_htc_ps_wakeup(priv); | ||
1183 | 1191 | ||
1184 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { | 1192 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { |
1185 | bool enable_radio = false; | ||
1186 | bool idle = !!(conf->flags & IEEE80211_CONF_IDLE); | ||
1187 | |||
1188 | mutex_lock(&priv->htc_pm_lock); | 1193 | mutex_lock(&priv->htc_pm_lock); |
1189 | if (!idle && priv->ps_idle) | ||
1190 | enable_radio = true; | ||
1191 | priv->ps_idle = idle; | ||
1192 | mutex_unlock(&priv->htc_pm_lock); | ||
1193 | 1194 | ||
1194 | if (enable_radio) { | 1195 | priv->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE); |
1195 | ath_dbg(common, CONFIG, "not-idle: enabling radio\n"); | 1196 | if (priv->ps_idle) |
1196 | ath9k_htc_setpower(priv, ATH9K_PM_AWAKE); | 1197 | chip_reset = true; |
1197 | ath9k_htc_radio_enable(hw); | 1198 | |
1198 | } | 1199 | mutex_unlock(&priv->htc_pm_lock); |
1199 | } | 1200 | } |
1200 | 1201 | ||
1201 | /* | 1202 | /* |
@@ -1210,7 +1211,7 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) | |||
1210 | ath9k_htc_remove_monitor_interface(priv); | 1211 | ath9k_htc_remove_monitor_interface(priv); |
1211 | } | 1212 | } |
1212 | 1213 | ||
1213 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { | 1214 | if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || chip_reset) { |
1214 | struct ieee80211_channel *curchan = hw->conf.channel; | 1215 | struct ieee80211_channel *curchan = hw->conf.channel; |
1215 | int pos = curchan->hw_value; | 1216 | int pos = curchan->hw_value; |
1216 | 1217 | ||
@@ -1223,8 +1224,8 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) | |||
1223 | 1224 | ||
1224 | if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) { | 1225 | if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) { |
1225 | ath_err(common, "Unable to set channel\n"); | 1226 | ath_err(common, "Unable to set channel\n"); |
1226 | mutex_unlock(&priv->mutex); | 1227 | ret = -EINVAL; |
1227 | return -EINVAL; | 1228 | goto out; |
1228 | } | 1229 | } |
1229 | 1230 | ||
1230 | } | 1231 | } |
@@ -1246,21 +1247,10 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) | |||
1246 | priv->txpowlimit, &priv->curtxpow); | 1247 | priv->txpowlimit, &priv->curtxpow); |
1247 | } | 1248 | } |
1248 | 1249 | ||
1249 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { | ||
1250 | mutex_lock(&priv->htc_pm_lock); | ||
1251 | if (!priv->ps_idle) { | ||
1252 | mutex_unlock(&priv->htc_pm_lock); | ||
1253 | goto out; | ||
1254 | } | ||
1255 | mutex_unlock(&priv->htc_pm_lock); | ||
1256 | |||
1257 | ath_dbg(common, CONFIG, "idle: disabling radio\n"); | ||
1258 | ath9k_htc_radio_disable(hw); | ||
1259 | } | ||
1260 | |||
1261 | out: | 1250 | out: |
1251 | ath9k_htc_ps_restore(priv); | ||
1262 | mutex_unlock(&priv->mutex); | 1252 | mutex_unlock(&priv->mutex); |
1263 | return 0; | 1253 | return ret; |
1264 | } | 1254 | } |
1265 | 1255 | ||
1266 | #define SUPPORTED_FILTERS \ | 1256 | #define SUPPORTED_FILTERS \ |
@@ -1285,7 +1275,7 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw, | |||
1285 | changed_flags &= SUPPORTED_FILTERS; | 1275 | changed_flags &= SUPPORTED_FILTERS; |
1286 | *total_flags &= SUPPORTED_FILTERS; | 1276 | *total_flags &= SUPPORTED_FILTERS; |
1287 | 1277 | ||
1288 | if (priv->op_flags & OP_INVALID) { | 1278 | if (test_bit(OP_INVALID, &priv->op_flags)) { |
1289 | ath_dbg(ath9k_hw_common(priv->ah), ANY, | 1279 | ath_dbg(ath9k_hw_common(priv->ah), ANY, |
1290 | "Unable to configure filter on invalid state\n"); | 1280 | "Unable to configure filter on invalid state\n"); |
1291 | mutex_unlock(&priv->mutex); | 1281 | mutex_unlock(&priv->mutex); |
@@ -1517,7 +1507,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, | |||
1517 | ath_dbg(common, CONFIG, "Beacon enabled for BSS: %pM\n", | 1507 | ath_dbg(common, CONFIG, "Beacon enabled for BSS: %pM\n", |
1518 | bss_conf->bssid); | 1508 | bss_conf->bssid); |
1519 | ath9k_htc_set_tsfadjust(priv, vif); | 1509 | ath9k_htc_set_tsfadjust(priv, vif); |
1520 | priv->op_flags |= OP_ENABLE_BEACON; | 1510 | set_bit(OP_ENABLE_BEACON, &priv->op_flags); |
1521 | ath9k_htc_beacon_config(priv, vif); | 1511 | ath9k_htc_beacon_config(priv, vif); |
1522 | } | 1512 | } |
1523 | 1513 | ||
@@ -1530,7 +1520,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, | |||
1530 | ath_dbg(common, CONFIG, | 1520 | ath_dbg(common, CONFIG, |
1531 | "Beacon disabled for BSS: %pM\n", | 1521 | "Beacon disabled for BSS: %pM\n", |
1532 | bss_conf->bssid); | 1522 | bss_conf->bssid); |
1533 | priv->op_flags &= ~OP_ENABLE_BEACON; | 1523 | clear_bit(OP_ENABLE_BEACON, &priv->op_flags); |
1534 | ath9k_htc_beacon_config(priv, vif); | 1524 | ath9k_htc_beacon_config(priv, vif); |
1535 | } | 1525 | } |
1536 | } | 1526 | } |
@@ -1543,7 +1533,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, | |||
1543 | (priv->nvifs == 1) && | 1533 | (priv->nvifs == 1) && |
1544 | (priv->num_ap_vif == 1) && | 1534 | (priv->num_ap_vif == 1) && |
1545 | (vif->type == NL80211_IFTYPE_AP)) { | 1535 | (vif->type == NL80211_IFTYPE_AP)) { |
1546 | priv->op_flags |= OP_TSF_RESET; | 1536 | set_bit(OP_TSF_RESET, &priv->op_flags); |
1547 | } | 1537 | } |
1548 | ath_dbg(common, CONFIG, | 1538 | ath_dbg(common, CONFIG, |
1549 | "Beacon interval changed for BSS: %pM\n", | 1539 | "Beacon interval changed for BSS: %pM\n", |
@@ -1655,7 +1645,7 @@ static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw) | |||
1655 | 1645 | ||
1656 | mutex_lock(&priv->mutex); | 1646 | mutex_lock(&priv->mutex); |
1657 | spin_lock_bh(&priv->beacon_lock); | 1647 | spin_lock_bh(&priv->beacon_lock); |
1658 | priv->op_flags |= OP_SCANNING; | 1648 | set_bit(OP_SCANNING, &priv->op_flags); |
1659 | spin_unlock_bh(&priv->beacon_lock); | 1649 | spin_unlock_bh(&priv->beacon_lock); |
1660 | cancel_work_sync(&priv->ps_work); | 1650 | cancel_work_sync(&priv->ps_work); |
1661 | ath9k_htc_stop_ani(priv); | 1651 | ath9k_htc_stop_ani(priv); |
@@ -1668,7 +1658,7 @@ static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw) | |||
1668 | 1658 | ||
1669 | mutex_lock(&priv->mutex); | 1659 | mutex_lock(&priv->mutex); |
1670 | spin_lock_bh(&priv->beacon_lock); | 1660 | spin_lock_bh(&priv->beacon_lock); |
1671 | priv->op_flags &= ~OP_SCANNING; | 1661 | clear_bit(OP_SCANNING, &priv->op_flags); |
1672 | spin_unlock_bh(&priv->beacon_lock); | 1662 | spin_unlock_bh(&priv->beacon_lock); |
1673 | ath9k_htc_ps_wakeup(priv); | 1663 | ath9k_htc_ps_wakeup(priv); |
1674 | ath9k_htc_vif_reconfig(priv); | 1664 | ath9k_htc_vif_reconfig(priv); |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 3e40a646151..47e61d0da33 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | |||
@@ -916,7 +916,7 @@ void ath9k_host_rx_init(struct ath9k_htc_priv *priv) | |||
916 | { | 916 | { |
917 | ath9k_hw_rxena(priv->ah); | 917 | ath9k_hw_rxena(priv->ah); |
918 | ath9k_htc_opmode_init(priv); | 918 | ath9k_htc_opmode_init(priv); |
919 | ath9k_hw_startpcureceive(priv->ah, (priv->op_flags & OP_SCANNING)); | 919 | ath9k_hw_startpcureceive(priv->ah, test_bit(OP_SCANNING, &priv->op_flags)); |
920 | priv->rx.last_rssi = ATH_RSSI_DUMMY_MARKER; | 920 | priv->rx.last_rssi = ATH_RSSI_DUMMY_MARKER; |
921 | } | 921 | } |
922 | 922 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 45e670087e1..784baee5db8 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -1348,6 +1348,9 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type) | |||
1348 | } | 1348 | } |
1349 | } | 1349 | } |
1350 | 1350 | ||
1351 | if (ath9k_hw_mci_is_enabled(ah)) | ||
1352 | ar9003_mci_check_gpm_offset(ah); | ||
1353 | |||
1351 | REG_WRITE(ah, AR_RTC_RC, rst_flags); | 1354 | REG_WRITE(ah, AR_RTC_RC, rst_flags); |
1352 | 1355 | ||
1353 | REGWRITE_BUFFER_FLUSH(ah); | 1356 | REGWRITE_BUFFER_FLUSH(ah); |
@@ -1708,7 +1711,7 @@ static int ath9k_hw_do_fastcc(struct ath_hw *ah, struct ath9k_channel *chan) | |||
1708 | ath9k_hw_start_nfcal(ah, true); | 1711 | ath9k_hw_start_nfcal(ah, true); |
1709 | 1712 | ||
1710 | if (ath9k_hw_mci_is_enabled(ah)) | 1713 | if (ath9k_hw_mci_is_enabled(ah)) |
1711 | ar9003_mci_2g5g_switch(ah, true); | 1714 | ar9003_mci_2g5g_switch(ah, false); |
1712 | 1715 | ||
1713 | if (AR_SREV_9271(ah)) | 1716 | if (AR_SREV_9271(ah)) |
1714 | ar9002_hw_load_ani_reg(ah, chan); | 1717 | ar9002_hw_load_ani_reg(ah, chan); |
@@ -1912,7 +1915,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1912 | 1915 | ||
1913 | ath9k_hw_set_dma(ah); | 1916 | ath9k_hw_set_dma(ah); |
1914 | 1917 | ||
1915 | REG_WRITE(ah, AR_OBS, 8); | 1918 | if (!ath9k_hw_mci_is_enabled(ah)) |
1919 | REG_WRITE(ah, AR_OBS, 8); | ||
1916 | 1920 | ||
1917 | if (ah->config.rx_intr_mitigation) { | 1921 | if (ah->config.rx_intr_mitigation) { |
1918 | REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500); | 1922 | REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500); |
@@ -2111,6 +2115,9 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah) | |||
2111 | AR_RTC_FORCE_WAKE_EN); | 2115 | AR_RTC_FORCE_WAKE_EN); |
2112 | udelay(50); | 2116 | udelay(50); |
2113 | 2117 | ||
2118 | if (ath9k_hw_mci_is_enabled(ah)) | ||
2119 | ar9003_mci_set_power_awake(ah); | ||
2120 | |||
2114 | for (i = POWER_UP_TIME / 50; i > 0; i--) { | 2121 | for (i = POWER_UP_TIME / 50; i > 0; i--) { |
2115 | val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M; | 2122 | val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M; |
2116 | if (val == AR_RTC_STATUS_ON) | 2123 | if (val == AR_RTC_STATUS_ON) |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 03d590924c6..94096607cbd 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -1019,16 +1019,8 @@ void ar9002_hw_attach_ops(struct ath_hw *ah); | |||
1019 | void ar9003_hw_attach_ops(struct ath_hw *ah); | 1019 | void ar9003_hw_attach_ops(struct ath_hw *ah); |
1020 | 1020 | ||
1021 | void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan); | 1021 | void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan); |
1022 | /* | 1022 | |
1023 | * ANI work can be shared between all families but a next | ||
1024 | * generation implementation of ANI will be used only for AR9003 only | ||
1025 | * for now as the other families still need to be tested with the same | ||
1026 | * next generation ANI. Feel free to start testing it though for the | ||
1027 | * older families (AR5008, AR9001, AR9002) by using modparam_force_new_ani. | ||
1028 | */ | ||
1029 | extern int modparam_force_new_ani; | ||
1030 | void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning); | 1023 | void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning); |
1031 | void ath9k_hw_proc_mib_event(struct ath_hw *ah); | ||
1032 | void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan); | 1024 | void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan); |
1033 | 1025 | ||
1034 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT | 1026 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT |
@@ -1038,7 +1030,8 @@ static inline bool ath9k_hw_btcoex_is_enabled(struct ath_hw *ah) | |||
1038 | } | 1030 | } |
1039 | static inline bool ath9k_hw_mci_is_enabled(struct ath_hw *ah) | 1031 | static inline bool ath9k_hw_mci_is_enabled(struct ath_hw *ah) |
1040 | { | 1032 | { |
1041 | return ah->btcoex_hw.enabled && (ah->caps.hw_caps & ATH9K_HW_CAP_MCI); | 1033 | return ah->common.btcoex_enabled && |
1034 | (ah->caps.hw_caps & ATH9K_HW_CAP_MCI); | ||
1042 | 1035 | ||
1043 | } | 1036 | } |
1044 | void ath9k_hw_btcoex_enable(struct ath_hw *ah); | 1037 | void ath9k_hw_btcoex_enable(struct ath_hw *ah); |
diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c index 0cc4c70f7f0..91650fe5046 100644 --- a/drivers/net/wireless/ath/ath9k/link.c +++ b/drivers/net/wireless/ath/ath9k/link.c | |||
@@ -136,6 +136,14 @@ void ath_hw_pll_work(struct work_struct *work) | |||
136 | u32 pll_sqsum; | 136 | u32 pll_sqsum; |
137 | struct ath_softc *sc = container_of(work, struct ath_softc, | 137 | struct ath_softc *sc = container_of(work, struct ath_softc, |
138 | hw_pll_work.work); | 138 | hw_pll_work.work); |
139 | /* | ||
140 | * ensure that the PLL WAR is executed only | ||
141 | * after the STA is associated (or) if the | ||
142 | * beaconing had started in interfaces that | ||
143 | * uses beacons. | ||
144 | */ | ||
145 | if (!test_bit(SC_OP_BEACONS, &sc->sc_flags)) | ||
146 | return; | ||
139 | 147 | ||
140 | ath9k_ps_wakeup(sc); | 148 | ath9k_ps_wakeup(sc); |
141 | pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah); | 149 | pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah); |
@@ -399,6 +407,7 @@ void ath_ani_calibrate(unsigned long data) | |||
399 | longcal ? "long" : "", shortcal ? "short" : "", | 407 | longcal ? "long" : "", shortcal ? "short" : "", |
400 | aniflag ? "ani" : "", common->ani.caldone ? "true" : "false"); | 408 | aniflag ? "ani" : "", common->ani.caldone ? "true" : "false"); |
401 | 409 | ||
410 | ath9k_debug_samp_bb_mac(sc); | ||
402 | ath9k_ps_restore(sc); | 411 | ath9k_ps_restore(sc); |
403 | 412 | ||
404 | set_timer: | 413 | set_timer: |
@@ -407,7 +416,6 @@ set_timer: | |||
407 | * The interval must be the shortest necessary to satisfy ANI, | 416 | * The interval must be the shortest necessary to satisfy ANI, |
408 | * short calibration and long calibration. | 417 | * short calibration and long calibration. |
409 | */ | 418 | */ |
410 | ath9k_debug_samp_bb_mac(sc); | ||
411 | cal_interval = ATH_LONG_CALINTERVAL; | 419 | cal_interval = ATH_LONG_CALINTERVAL; |
412 | if (sc->sc_ah->config.enable_ani) | 420 | if (sc->sc_ah->config.enable_ani) |
413 | cal_interval = min(cal_interval, | 421 | cal_interval = min(cal_interval, |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index c0f478b0a9a..e4e73f061a2 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -19,7 +19,7 @@ | |||
19 | #include "ath9k.h" | 19 | #include "ath9k.h" |
20 | #include "btcoex.h" | 20 | #include "btcoex.h" |
21 | 21 | ||
22 | static u8 parse_mpdudensity(u8 mpdudensity) | 22 | u8 ath9k_parse_mpdudensity(u8 mpdudensity) |
23 | { | 23 | { |
24 | /* | 24 | /* |
25 | * 802.11n D2.0 defined values for "Minimum MPDU Start Spacing": | 25 | * 802.11n D2.0 defined values for "Minimum MPDU Start Spacing": |
@@ -150,6 +150,11 @@ static void __ath_cancel_work(struct ath_softc *sc) | |||
150 | cancel_work_sync(&sc->hw_check_work); | 150 | cancel_work_sync(&sc->hw_check_work); |
151 | cancel_delayed_work_sync(&sc->tx_complete_work); | 151 | cancel_delayed_work_sync(&sc->tx_complete_work); |
152 | cancel_delayed_work_sync(&sc->hw_pll_work); | 152 | cancel_delayed_work_sync(&sc->hw_pll_work); |
153 | |||
154 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT | ||
155 | if (ath9k_hw_mci_is_enabled(sc->sc_ah)) | ||
156 | cancel_work_sync(&sc->mci_work); | ||
157 | #endif | ||
153 | } | 158 | } |
154 | 159 | ||
155 | static void ath_cancel_work(struct ath_softc *sc) | 160 | static void ath_cancel_work(struct ath_softc *sc) |
@@ -317,6 +322,7 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta, | |||
317 | struct ieee80211_vif *vif) | 322 | struct ieee80211_vif *vif) |
318 | { | 323 | { |
319 | struct ath_node *an; | 324 | struct ath_node *an; |
325 | u8 density; | ||
320 | an = (struct ath_node *)sta->drv_priv; | 326 | an = (struct ath_node *)sta->drv_priv; |
321 | 327 | ||
322 | #ifdef CONFIG_ATH9K_DEBUGFS | 328 | #ifdef CONFIG_ATH9K_DEBUGFS |
@@ -331,7 +337,8 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta, | |||
331 | ath_tx_node_init(sc, an); | 337 | ath_tx_node_init(sc, an); |
332 | an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + | 338 | an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + |
333 | sta->ht_cap.ampdu_factor); | 339 | sta->ht_cap.ampdu_factor); |
334 | an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density); | 340 | density = ath9k_parse_mpdudensity(sta->ht_cap.ampdu_density); |
341 | an->mpdudensity = density; | ||
335 | } | 342 | } |
336 | } | 343 | } |
337 | 344 | ||
@@ -513,24 +520,6 @@ irqreturn_t ath_isr(int irq, void *dev) | |||
513 | ath9k_hw_set_interrupts(ah); | 520 | ath9k_hw_set_interrupts(ah); |
514 | } | 521 | } |
515 | 522 | ||
516 | if (status & ATH9K_INT_MIB) { | ||
517 | /* | ||
518 | * Disable interrupts until we service the MIB | ||
519 | * interrupt; otherwise it will continue to | ||
520 | * fire. | ||
521 | */ | ||
522 | ath9k_hw_disable_interrupts(ah); | ||
523 | /* | ||
524 | * Let the hal handle the event. We assume | ||
525 | * it will clear whatever condition caused | ||
526 | * the interrupt. | ||
527 | */ | ||
528 | spin_lock(&common->cc_lock); | ||
529 | ath9k_hw_proc_mib_event(ah); | ||
530 | spin_unlock(&common->cc_lock); | ||
531 | ath9k_hw_enable_interrupts(ah); | ||
532 | } | ||
533 | |||
534 | if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) | 523 | if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) |
535 | if (status & ATH9K_INT_TIM_TIMER) { | 524 | if (status & ATH9K_INT_TIM_TIMER) { |
536 | if (ATH_DBG_WARN_ON_ONCE(sc->ps_idle)) | 525 | if (ATH_DBG_WARN_ON_ONCE(sc->ps_idle)) |
@@ -956,14 +945,10 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw, | |||
956 | /* | 945 | /* |
957 | * Enable MIB interrupts when there are hardware phy counters. | 946 | * Enable MIB interrupts when there are hardware phy counters. |
958 | */ | 947 | */ |
959 | if ((iter_data.nstations + iter_data.nadhocs + iter_data.nmeshes) > 0) { | 948 | if ((iter_data.nstations + iter_data.nadhocs + iter_data.nmeshes) > 0) |
960 | if (ah->config.enable_ani) | ||
961 | ah->imask |= ATH9K_INT_MIB; | ||
962 | ah->imask |= ATH9K_INT_TSFOOR; | 949 | ah->imask |= ATH9K_INT_TSFOOR; |
963 | } else { | 950 | else |
964 | ah->imask &= ~ATH9K_INT_MIB; | ||
965 | ah->imask &= ~ATH9K_INT_TSFOOR; | 951 | ah->imask &= ~ATH9K_INT_TSFOOR; |
966 | } | ||
967 | 952 | ||
968 | ath9k_hw_set_interrupts(ah); | 953 | ath9k_hw_set_interrupts(ah); |
969 | 954 | ||
@@ -1033,15 +1018,6 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
1033 | } | 1018 | } |
1034 | } | 1019 | } |
1035 | 1020 | ||
1036 | if ((ah->opmode == NL80211_IFTYPE_ADHOC) || | ||
1037 | ((vif->type == NL80211_IFTYPE_ADHOC) && | ||
1038 | sc->nvifs > 0)) { | ||
1039 | ath_err(common, "Cannot create ADHOC interface when other" | ||
1040 | " interfaces already exist.\n"); | ||
1041 | ret = -EINVAL; | ||
1042 | goto out; | ||
1043 | } | ||
1044 | |||
1045 | ath_dbg(common, CONFIG, "Attach a VIF of type: %d\n", vif->type); | 1021 | ath_dbg(common, CONFIG, "Attach a VIF of type: %d\n", vif->type); |
1046 | 1022 | ||
1047 | sc->nvifs++; | 1023 | sc->nvifs++; |
@@ -1066,15 +1042,6 @@ static int ath9k_change_interface(struct ieee80211_hw *hw, | |||
1066 | mutex_lock(&sc->mutex); | 1042 | mutex_lock(&sc->mutex); |
1067 | ath9k_ps_wakeup(sc); | 1043 | ath9k_ps_wakeup(sc); |
1068 | 1044 | ||
1069 | /* See if new interface type is valid. */ | ||
1070 | if ((new_type == NL80211_IFTYPE_ADHOC) && | ||
1071 | (sc->nvifs > 1)) { | ||
1072 | ath_err(common, "When using ADHOC, it must be the only" | ||
1073 | " interface.\n"); | ||
1074 | ret = -EINVAL; | ||
1075 | goto out; | ||
1076 | } | ||
1077 | |||
1078 | if (ath9k_uses_beacons(new_type) && | 1045 | if (ath9k_uses_beacons(new_type) && |
1079 | !ath9k_uses_beacons(vif->type)) { | 1046 | !ath9k_uses_beacons(vif->type)) { |
1080 | if (sc->nbcnvifs >= ATH_BCBUF) { | 1047 | if (sc->nbcnvifs >= ATH_BCBUF) { |
@@ -1258,6 +1225,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
1258 | if (ath_set_channel(sc, hw, &sc->sc_ah->channels[pos]) < 0) { | 1225 | if (ath_set_channel(sc, hw, &sc->sc_ah->channels[pos]) < 0) { |
1259 | ath_err(common, "Unable to set channel\n"); | 1226 | ath_err(common, "Unable to set channel\n"); |
1260 | mutex_unlock(&sc->mutex); | 1227 | mutex_unlock(&sc->mutex); |
1228 | ath9k_ps_restore(sc); | ||
1261 | return -EINVAL; | 1229 | return -EINVAL; |
1262 | } | 1230 | } |
1263 | 1231 | ||
diff --git a/drivers/net/wireless/ath/ath9k/mci.c b/drivers/net/wireless/ath/ath9k/mci.c index 49137f477b0..c40e568b5c2 100644 --- a/drivers/net/wireless/ath/ath9k/mci.c +++ b/drivers/net/wireless/ath/ath9k/mci.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #include "ath9k.h" | 20 | #include "ath9k.h" |
21 | #include "mci.h" | 21 | #include "mci.h" |
22 | 22 | ||
23 | static const u8 ath_mci_duty_cycle[] = { 0, 50, 60, 70, 80, 85, 90, 95, 98 }; | 23 | static const u8 ath_mci_duty_cycle[] = { 55, 50, 60, 70, 80, 85, 90, 95, 98 }; |
24 | 24 | ||
25 | static struct ath_mci_profile_info* | 25 | static struct ath_mci_profile_info* |
26 | ath_mci_find_profile(struct ath_mci_profile *mci, | 26 | ath_mci_find_profile(struct ath_mci_profile *mci, |
@@ -28,11 +28,14 @@ ath_mci_find_profile(struct ath_mci_profile *mci, | |||
28 | { | 28 | { |
29 | struct ath_mci_profile_info *entry; | 29 | struct ath_mci_profile_info *entry; |
30 | 30 | ||
31 | if (list_empty(&mci->info)) | ||
32 | return NULL; | ||
33 | |||
31 | list_for_each_entry(entry, &mci->info, list) { | 34 | list_for_each_entry(entry, &mci->info, list) { |
32 | if (entry->conn_handle == info->conn_handle) | 35 | if (entry->conn_handle == info->conn_handle) |
33 | break; | 36 | return entry; |
34 | } | 37 | } |
35 | return entry; | 38 | return NULL; |
36 | } | 39 | } |
37 | 40 | ||
38 | static bool ath_mci_add_profile(struct ath_common *common, | 41 | static bool ath_mci_add_profile(struct ath_common *common, |
@@ -49,31 +52,21 @@ static bool ath_mci_add_profile(struct ath_common *common, | |||
49 | (info->type != MCI_GPM_COEX_PROFILE_VOICE)) | 52 | (info->type != MCI_GPM_COEX_PROFILE_VOICE)) |
50 | return false; | 53 | return false; |
51 | 54 | ||
52 | entry = ath_mci_find_profile(mci, info); | 55 | entry = kzalloc(sizeof(*entry), GFP_ATOMIC); |
53 | 56 | if (!entry) | |
54 | if (entry) { | 57 | return false; |
55 | memcpy(entry, info, 10); | ||
56 | } else { | ||
57 | entry = kzalloc(sizeof(*entry), GFP_KERNEL); | ||
58 | if (!entry) | ||
59 | return false; | ||
60 | 58 | ||
61 | memcpy(entry, info, 10); | 59 | memcpy(entry, info, 10); |
62 | INC_PROF(mci, info); | 60 | INC_PROF(mci, info); |
63 | list_add_tail(&info->list, &mci->info); | 61 | list_add_tail(&entry->list, &mci->info); |
64 | } | ||
65 | 62 | ||
66 | return true; | 63 | return true; |
67 | } | 64 | } |
68 | 65 | ||
69 | static void ath_mci_del_profile(struct ath_common *common, | 66 | static void ath_mci_del_profile(struct ath_common *common, |
70 | struct ath_mci_profile *mci, | 67 | struct ath_mci_profile *mci, |
71 | struct ath_mci_profile_info *info) | 68 | struct ath_mci_profile_info *entry) |
72 | { | 69 | { |
73 | struct ath_mci_profile_info *entry; | ||
74 | |||
75 | entry = ath_mci_find_profile(mci, info); | ||
76 | |||
77 | if (!entry) | 70 | if (!entry) |
78 | return; | 71 | return; |
79 | 72 | ||
@@ -86,12 +79,16 @@ void ath_mci_flush_profile(struct ath_mci_profile *mci) | |||
86 | { | 79 | { |
87 | struct ath_mci_profile_info *info, *tinfo; | 80 | struct ath_mci_profile_info *info, *tinfo; |
88 | 81 | ||
82 | mci->aggr_limit = 0; | ||
83 | |||
84 | if (list_empty(&mci->info)) | ||
85 | return; | ||
86 | |||
89 | list_for_each_entry_safe(info, tinfo, &mci->info, list) { | 87 | list_for_each_entry_safe(info, tinfo, &mci->info, list) { |
90 | list_del(&info->list); | 88 | list_del(&info->list); |
91 | DEC_PROF(mci, info); | 89 | DEC_PROF(mci, info); |
92 | kfree(info); | 90 | kfree(info); |
93 | } | 91 | } |
94 | mci->aggr_limit = 0; | ||
95 | } | 92 | } |
96 | 93 | ||
97 | static void ath_mci_adjust_aggr_limit(struct ath_btcoex *btcoex) | 94 | static void ath_mci_adjust_aggr_limit(struct ath_btcoex *btcoex) |
@@ -123,6 +120,8 @@ static void ath_mci_update_scheme(struct ath_softc *sc) | |||
123 | if (mci_hw->config & ATH_MCI_CONFIG_DISABLE_TUNING) | 120 | if (mci_hw->config & ATH_MCI_CONFIG_DISABLE_TUNING) |
124 | goto skip_tuning; | 121 | goto skip_tuning; |
125 | 122 | ||
123 | btcoex->duty_cycle = ath_mci_duty_cycle[num_profile]; | ||
124 | |||
126 | if (num_profile == 1) { | 125 | if (num_profile == 1) { |
127 | info = list_first_entry(&mci->info, | 126 | info = list_first_entry(&mci->info, |
128 | struct ath_mci_profile_info, | 127 | struct ath_mci_profile_info, |
@@ -181,12 +180,11 @@ skip_tuning: | |||
181 | if (IS_CHAN_5GHZ(sc->sc_ah->curchan)) | 180 | if (IS_CHAN_5GHZ(sc->sc_ah->curchan)) |
182 | return; | 181 | return; |
183 | 182 | ||
184 | btcoex->duty_cycle += (mci->num_bdr ? ATH_MCI_MAX_DUTY_CYCLE : 0); | 183 | btcoex->duty_cycle += (mci->num_bdr ? ATH_MCI_BDR_DUTY_CYCLE : 0); |
185 | if (btcoex->duty_cycle > ATH_MCI_MAX_DUTY_CYCLE) | 184 | if (btcoex->duty_cycle > ATH_MCI_MAX_DUTY_CYCLE) |
186 | btcoex->duty_cycle = ATH_MCI_MAX_DUTY_CYCLE; | 185 | btcoex->duty_cycle = ATH_MCI_MAX_DUTY_CYCLE; |
187 | 186 | ||
188 | btcoex->btcoex_period *= 1000; | 187 | btcoex->btcoex_no_stomp = btcoex->btcoex_period * 1000 * |
189 | btcoex->btcoex_no_stomp = btcoex->btcoex_period * | ||
190 | (100 - btcoex->duty_cycle) / 100; | 188 | (100 - btcoex->duty_cycle) / 100; |
191 | 189 | ||
192 | ath9k_hw_btcoex_enable(sc->sc_ah); | 190 | ath9k_hw_btcoex_enable(sc->sc_ah); |
@@ -197,20 +195,16 @@ static void ath_mci_cal_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload) | |||
197 | { | 195 | { |
198 | struct ath_hw *ah = sc->sc_ah; | 196 | struct ath_hw *ah = sc->sc_ah; |
199 | struct ath_common *common = ath9k_hw_common(ah); | 197 | struct ath_common *common = ath9k_hw_common(ah); |
198 | struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci; | ||
200 | u32 payload[4] = {0, 0, 0, 0}; | 199 | u32 payload[4] = {0, 0, 0, 0}; |
201 | 200 | ||
202 | switch (opcode) { | 201 | switch (opcode) { |
203 | case MCI_GPM_BT_CAL_REQ: | 202 | case MCI_GPM_BT_CAL_REQ: |
204 | if (ar9003_mci_state(ah, MCI_STATE_BT, NULL) == MCI_BT_AWAKE) { | 203 | if (mci_hw->bt_state == MCI_BT_AWAKE) { |
205 | ar9003_mci_state(ah, MCI_STATE_SET_BT_CAL_START, NULL); | 204 | ar9003_mci_state(ah, MCI_STATE_SET_BT_CAL_START); |
206 | ieee80211_queue_work(sc->hw, &sc->hw_reset_work); | 205 | ieee80211_queue_work(sc->hw, &sc->hw_reset_work); |
207 | } else { | ||
208 | ath_dbg(common, MCI, "MCI State mismatch: %d\n", | ||
209 | ar9003_mci_state(ah, MCI_STATE_BT, NULL)); | ||
210 | } | 206 | } |
211 | break; | 207 | ath_dbg(common, MCI, "MCI State : %d\n", mci_hw->bt_state); |
212 | case MCI_GPM_BT_CAL_DONE: | ||
213 | ar9003_mci_state(ah, MCI_STATE_BT, NULL); | ||
214 | break; | 208 | break; |
215 | case MCI_GPM_BT_CAL_GRANT: | 209 | case MCI_GPM_BT_CAL_GRANT: |
216 | MCI_GPM_SET_CAL_TYPE(payload, MCI_GPM_WLAN_CAL_DONE); | 210 | MCI_GPM_SET_CAL_TYPE(payload, MCI_GPM_WLAN_CAL_DONE); |
@@ -223,32 +217,55 @@ static void ath_mci_cal_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload) | |||
223 | } | 217 | } |
224 | } | 218 | } |
225 | 219 | ||
220 | static void ath9k_mci_work(struct work_struct *work) | ||
221 | { | ||
222 | struct ath_softc *sc = container_of(work, struct ath_softc, mci_work); | ||
223 | |||
224 | ath_mci_update_scheme(sc); | ||
225 | } | ||
226 | |||
226 | static void ath_mci_process_profile(struct ath_softc *sc, | 227 | static void ath_mci_process_profile(struct ath_softc *sc, |
227 | struct ath_mci_profile_info *info) | 228 | struct ath_mci_profile_info *info) |
228 | { | 229 | { |
229 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 230 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
230 | struct ath_btcoex *btcoex = &sc->btcoex; | 231 | struct ath_btcoex *btcoex = &sc->btcoex; |
231 | struct ath_mci_profile *mci = &btcoex->mci; | 232 | struct ath_mci_profile *mci = &btcoex->mci; |
233 | struct ath_mci_profile_info *entry = NULL; | ||
234 | |||
235 | entry = ath_mci_find_profile(mci, info); | ||
236 | if (entry) { | ||
237 | /* | ||
238 | * Two MCI interrupts are generated while connecting to | ||
239 | * headset and A2DP profile, but only one MCI interrupt | ||
240 | * is generated with last added profile type while disconnecting | ||
241 | * both profiles. | ||
242 | * So while adding second profile type decrement | ||
243 | * the first one. | ||
244 | */ | ||
245 | if (entry->type != info->type) { | ||
246 | DEC_PROF(mci, entry); | ||
247 | INC_PROF(mci, info); | ||
248 | } | ||
249 | memcpy(entry, info, 10); | ||
250 | } | ||
232 | 251 | ||
233 | if (info->start) { | 252 | if (info->start) { |
234 | if (!ath_mci_add_profile(common, mci, info)) | 253 | if (!entry && !ath_mci_add_profile(common, mci, info)) |
235 | return; | 254 | return; |
236 | } else | 255 | } else |
237 | ath_mci_del_profile(common, mci, info); | 256 | ath_mci_del_profile(common, mci, entry); |
238 | 257 | ||
239 | btcoex->btcoex_period = ATH_MCI_DEF_BT_PERIOD; | 258 | btcoex->btcoex_period = ATH_MCI_DEF_BT_PERIOD; |
240 | mci->aggr_limit = mci->num_sco ? 6 : 0; | 259 | mci->aggr_limit = mci->num_sco ? 6 : 0; |
241 | 260 | ||
242 | if (NUM_PROF(mci)) { | 261 | btcoex->duty_cycle = ath_mci_duty_cycle[NUM_PROF(mci)]; |
262 | if (NUM_PROF(mci)) | ||
243 | btcoex->bt_stomp_type = ATH_BTCOEX_STOMP_LOW; | 263 | btcoex->bt_stomp_type = ATH_BTCOEX_STOMP_LOW; |
244 | btcoex->duty_cycle = ath_mci_duty_cycle[NUM_PROF(mci)]; | 264 | else |
245 | } else { | ||
246 | btcoex->bt_stomp_type = mci->num_mgmt ? ATH_BTCOEX_STOMP_ALL : | 265 | btcoex->bt_stomp_type = mci->num_mgmt ? ATH_BTCOEX_STOMP_ALL : |
247 | ATH_BTCOEX_STOMP_LOW; | 266 | ATH_BTCOEX_STOMP_LOW; |
248 | btcoex->duty_cycle = ATH_BTCOEX_DEF_DUTY_CYCLE; | ||
249 | } | ||
250 | 267 | ||
251 | ath_mci_update_scheme(sc); | 268 | ieee80211_queue_work(sc->hw, &sc->mci_work); |
252 | } | 269 | } |
253 | 270 | ||
254 | static void ath_mci_process_status(struct ath_softc *sc, | 271 | static void ath_mci_process_status(struct ath_softc *sc, |
@@ -263,8 +280,6 @@ static void ath_mci_process_status(struct ath_softc *sc, | |||
263 | if (status->is_link) | 280 | if (status->is_link) |
264 | return; | 281 | return; |
265 | 282 | ||
266 | memset(&info, 0, sizeof(struct ath_mci_profile_info)); | ||
267 | |||
268 | info.conn_handle = status->conn_handle; | 283 | info.conn_handle = status->conn_handle; |
269 | if (ath_mci_find_profile(mci, &info)) | 284 | if (ath_mci_find_profile(mci, &info)) |
270 | return; | 285 | return; |
@@ -284,7 +299,7 @@ static void ath_mci_process_status(struct ath_softc *sc, | |||
284 | } while (++i < ATH_MCI_MAX_PROFILE); | 299 | } while (++i < ATH_MCI_MAX_PROFILE); |
285 | 300 | ||
286 | if (old_num_mgmt != mci->num_mgmt) | 301 | if (old_num_mgmt != mci->num_mgmt) |
287 | ath_mci_update_scheme(sc); | 302 | ieee80211_queue_work(sc->hw, &sc->mci_work); |
288 | } | 303 | } |
289 | 304 | ||
290 | static void ath_mci_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload) | 305 | static void ath_mci_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload) |
@@ -293,25 +308,20 @@ static void ath_mci_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload) | |||
293 | struct ath_mci_profile_info profile_info; | 308 | struct ath_mci_profile_info profile_info; |
294 | struct ath_mci_profile_status profile_status; | 309 | struct ath_mci_profile_status profile_status; |
295 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 310 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
296 | u32 version; | 311 | u8 major, minor; |
297 | u8 major; | ||
298 | u8 minor; | ||
299 | u32 seq_num; | 312 | u32 seq_num; |
300 | 313 | ||
301 | switch (opcode) { | 314 | switch (opcode) { |
302 | case MCI_GPM_COEX_VERSION_QUERY: | 315 | case MCI_GPM_COEX_VERSION_QUERY: |
303 | version = ar9003_mci_state(ah, MCI_STATE_SEND_WLAN_COEX_VERSION, | 316 | ar9003_mci_state(ah, MCI_STATE_SEND_WLAN_COEX_VERSION); |
304 | NULL); | ||
305 | break; | 317 | break; |
306 | case MCI_GPM_COEX_VERSION_RESPONSE: | 318 | case MCI_GPM_COEX_VERSION_RESPONSE: |
307 | major = *(rx_payload + MCI_GPM_COEX_B_MAJOR_VERSION); | 319 | major = *(rx_payload + MCI_GPM_COEX_B_MAJOR_VERSION); |
308 | minor = *(rx_payload + MCI_GPM_COEX_B_MINOR_VERSION); | 320 | minor = *(rx_payload + MCI_GPM_COEX_B_MINOR_VERSION); |
309 | version = (major << 8) + minor; | 321 | ar9003_mci_set_bt_version(ah, major, minor); |
310 | version = ar9003_mci_state(ah, MCI_STATE_SET_BT_COEX_VERSION, | ||
311 | &version); | ||
312 | break; | 322 | break; |
313 | case MCI_GPM_COEX_STATUS_QUERY: | 323 | case MCI_GPM_COEX_STATUS_QUERY: |
314 | ar9003_mci_state(ah, MCI_STATE_SEND_WLAN_CHANNELS, NULL); | 324 | ar9003_mci_send_wlan_channels(ah); |
315 | break; | 325 | break; |
316 | case MCI_GPM_COEX_BT_PROFILE_INFO: | 326 | case MCI_GPM_COEX_BT_PROFILE_INFO: |
317 | memcpy(&profile_info, | 327 | memcpy(&profile_info, |
@@ -378,6 +388,7 @@ int ath_mci_setup(struct ath_softc *sc) | |||
378 | mci->gpm_buf.bf_addr, (mci->gpm_buf.bf_len >> 4), | 388 | mci->gpm_buf.bf_addr, (mci->gpm_buf.bf_len >> 4), |
379 | mci->sched_buf.bf_paddr); | 389 | mci->sched_buf.bf_paddr); |
380 | 390 | ||
391 | INIT_WORK(&sc->mci_work, ath9k_mci_work); | ||
381 | ath_dbg(common, MCI, "MCI Initialized\n"); | 392 | ath_dbg(common, MCI, "MCI Initialized\n"); |
382 | 393 | ||
383 | return 0; | 394 | return 0; |
@@ -405,6 +416,7 @@ void ath_mci_intr(struct ath_softc *sc) | |||
405 | struct ath_mci_coex *mci = &sc->mci_coex; | 416 | struct ath_mci_coex *mci = &sc->mci_coex; |
406 | struct ath_hw *ah = sc->sc_ah; | 417 | struct ath_hw *ah = sc->sc_ah; |
407 | struct ath_common *common = ath9k_hw_common(ah); | 418 | struct ath_common *common = ath9k_hw_common(ah); |
419 | struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci; | ||
408 | u32 mci_int, mci_int_rxmsg; | 420 | u32 mci_int, mci_int_rxmsg; |
409 | u32 offset, subtype, opcode; | 421 | u32 offset, subtype, opcode; |
410 | u32 *pgpm; | 422 | u32 *pgpm; |
@@ -413,8 +425,8 @@ void ath_mci_intr(struct ath_softc *sc) | |||
413 | 425 | ||
414 | ar9003_mci_get_interrupt(sc->sc_ah, &mci_int, &mci_int_rxmsg); | 426 | ar9003_mci_get_interrupt(sc->sc_ah, &mci_int, &mci_int_rxmsg); |
415 | 427 | ||
416 | if (ar9003_mci_state(ah, MCI_STATE_ENABLE, NULL) == 0) { | 428 | if (ar9003_mci_state(ah, MCI_STATE_ENABLE) == 0) { |
417 | ar9003_mci_state(ah, MCI_STATE_INIT_GPM_OFFSET, NULL); | 429 | ar9003_mci_get_next_gpm_offset(ah, true, NULL); |
418 | return; | 430 | return; |
419 | } | 431 | } |
420 | 432 | ||
@@ -433,46 +445,41 @@ void ath_mci_intr(struct ath_softc *sc) | |||
433 | NULL, 0, true, false); | 445 | NULL, 0, true, false); |
434 | 446 | ||
435 | mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE; | 447 | mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE; |
436 | ar9003_mci_state(ah, MCI_STATE_RESET_REQ_WAKE, NULL); | 448 | ar9003_mci_state(ah, MCI_STATE_RESET_REQ_WAKE); |
437 | 449 | ||
438 | /* | 450 | /* |
439 | * always do this for recovery and 2G/5G toggling and LNA_TRANS | 451 | * always do this for recovery and 2G/5G toggling and LNA_TRANS |
440 | */ | 452 | */ |
441 | ar9003_mci_state(ah, MCI_STATE_SET_BT_AWAKE, NULL); | 453 | ar9003_mci_state(ah, MCI_STATE_SET_BT_AWAKE); |
442 | } | 454 | } |
443 | 455 | ||
444 | if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING) { | 456 | if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING) { |
445 | mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING; | 457 | mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING; |
446 | 458 | ||
447 | if (ar9003_mci_state(ah, MCI_STATE_BT, NULL) == MCI_BT_SLEEP) { | 459 | if ((mci_hw->bt_state == MCI_BT_SLEEP) && |
448 | if (ar9003_mci_state(ah, MCI_STATE_REMOTE_SLEEP, NULL) != | 460 | (ar9003_mci_state(ah, MCI_STATE_REMOTE_SLEEP) != |
449 | MCI_BT_SLEEP) | 461 | MCI_BT_SLEEP)) |
450 | ar9003_mci_state(ah, MCI_STATE_SET_BT_AWAKE, | 462 | ar9003_mci_state(ah, MCI_STATE_SET_BT_AWAKE); |
451 | NULL); | ||
452 | } | ||
453 | } | 463 | } |
454 | 464 | ||
455 | if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING) { | 465 | if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING) { |
456 | mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING; | 466 | mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING; |
457 | 467 | ||
458 | if (ar9003_mci_state(ah, MCI_STATE_BT, NULL) == MCI_BT_AWAKE) { | 468 | if ((mci_hw->bt_state == MCI_BT_AWAKE) && |
459 | if (ar9003_mci_state(ah, MCI_STATE_REMOTE_SLEEP, NULL) != | 469 | (ar9003_mci_state(ah, MCI_STATE_REMOTE_SLEEP) != |
460 | MCI_BT_AWAKE) | 470 | MCI_BT_AWAKE)) |
461 | ar9003_mci_state(ah, MCI_STATE_SET_BT_SLEEP, | 471 | mci_hw->bt_state = MCI_BT_SLEEP; |
462 | NULL); | ||
463 | } | ||
464 | } | 472 | } |
465 | 473 | ||
466 | if ((mci_int & AR_MCI_INTERRUPT_RX_INVALID_HDR) || | 474 | if ((mci_int & AR_MCI_INTERRUPT_RX_INVALID_HDR) || |
467 | (mci_int & AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT)) { | 475 | (mci_int & AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT)) { |
468 | ar9003_mci_state(ah, MCI_STATE_RECOVER_RX, NULL); | 476 | ar9003_mci_state(ah, MCI_STATE_RECOVER_RX); |
469 | skip_gpm = true; | 477 | skip_gpm = true; |
470 | } | 478 | } |
471 | 479 | ||
472 | if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO) { | 480 | if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO) { |
473 | mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO; | 481 | mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO; |
474 | offset = ar9003_mci_state(ah, MCI_STATE_LAST_SCHD_MSG_OFFSET, | 482 | offset = ar9003_mci_state(ah, MCI_STATE_LAST_SCHD_MSG_OFFSET); |
475 | NULL); | ||
476 | } | 483 | } |
477 | 484 | ||
478 | if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_GPM) { | 485 | if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_GPM) { |
@@ -481,8 +488,8 @@ void ath_mci_intr(struct ath_softc *sc) | |||
481 | while (more_data == MCI_GPM_MORE) { | 488 | while (more_data == MCI_GPM_MORE) { |
482 | 489 | ||
483 | pgpm = mci->gpm_buf.bf_addr; | 490 | pgpm = mci->gpm_buf.bf_addr; |
484 | offset = ar9003_mci_state(ah, MCI_STATE_NEXT_GPM_OFFSET, | 491 | offset = ar9003_mci_get_next_gpm_offset(ah, false, |
485 | &more_data); | 492 | &more_data); |
486 | 493 | ||
487 | if (offset == MCI_GPM_INVALID) | 494 | if (offset == MCI_GPM_INVALID) |
488 | break; | 495 | break; |
@@ -523,23 +530,17 @@ void ath_mci_intr(struct ath_softc *sc) | |||
523 | mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_LNA_INFO; | 530 | mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_LNA_INFO; |
524 | 531 | ||
525 | if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_CONT_INFO) { | 532 | if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_CONT_INFO) { |
526 | int value_dbm = ar9003_mci_state(ah, | 533 | int value_dbm = MS(mci_hw->cont_status, |
527 | MCI_STATE_CONT_RSSI_POWER, NULL); | 534 | AR_MCI_CONT_RSSI_POWER); |
528 | 535 | ||
529 | mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_CONT_INFO; | 536 | mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_CONT_INFO; |
530 | 537 | ||
531 | if (ar9003_mci_state(ah, MCI_STATE_CONT_TXRX, NULL)) | 538 | ath_dbg(common, MCI, |
532 | ath_dbg(common, MCI, | 539 | "MCI CONT_INFO: (%s) pri = %d pwr = %d dBm\n", |
533 | "MCI CONT_INFO: (tx) pri = %d, pwr = %d dBm\n", | 540 | MS(mci_hw->cont_status, AR_MCI_CONT_TXRX) ? |
534 | ar9003_mci_state(ah, | 541 | "tx" : "rx", |
535 | MCI_STATE_CONT_PRIORITY, NULL), | 542 | MS(mci_hw->cont_status, AR_MCI_CONT_PRIORITY), |
536 | value_dbm); | 543 | value_dbm); |
537 | else | ||
538 | ath_dbg(common, MCI, | ||
539 | "MCI CONT_INFO: (rx) pri = %d,pwr = %d dBm\n", | ||
540 | ar9003_mci_state(ah, | ||
541 | MCI_STATE_CONT_PRIORITY, NULL), | ||
542 | value_dbm); | ||
543 | } | 544 | } |
544 | 545 | ||
545 | if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_CONT_NACK) | 546 | if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_CONT_NACK) |
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 92a6c0a87f8..e034add9cd5 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c | |||
@@ -770,7 +770,7 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, | |||
770 | struct ieee80211_tx_rate *rates = tx_info->control.rates; | 770 | struct ieee80211_tx_rate *rates = tx_info->control.rates; |
771 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 771 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
772 | __le16 fc = hdr->frame_control; | 772 | __le16 fc = hdr->frame_control; |
773 | u8 try_per_rate, i = 0, rix, high_rix; | 773 | u8 try_per_rate, i = 0, rix; |
774 | int is_probe = 0; | 774 | int is_probe = 0; |
775 | 775 | ||
776 | if (rate_control_send_low(sta, priv_sta, txrc)) | 776 | if (rate_control_send_low(sta, priv_sta, txrc)) |
@@ -791,7 +791,6 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, | |||
791 | rate_table = ath_rc_priv->rate_table; | 791 | rate_table = ath_rc_priv->rate_table; |
792 | rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, | 792 | rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, |
793 | &is_probe, false); | 793 | &is_probe, false); |
794 | high_rix = rix; | ||
795 | 794 | ||
796 | /* | 795 | /* |
797 | * If we're in HT mode and both us and our peer supports LDPC. | 796 | * If we're in HT mode and both us and our peer supports LDPC. |
@@ -839,16 +838,16 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, | |||
839 | try_per_rate = 8; | 838 | try_per_rate = 8; |
840 | 839 | ||
841 | /* | 840 | /* |
842 | * Use a legacy rate as last retry to ensure that the frame | 841 | * If the last rate in the rate series is MCS and has |
843 | * is tried in both MCS and legacy rates. | 842 | * more than 80% of per thresh, then use a legacy rate |
843 | * as last retry to ensure that the frame is tried in both | ||
844 | * MCS and legacy rate. | ||
844 | */ | 845 | */ |
845 | if ((rates[2].flags & IEEE80211_TX_RC_MCS) && | 846 | ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix); |
846 | (!(tx_info->flags & IEEE80211_TX_CTL_AMPDU) || | 847 | if (WLAN_RC_PHY_HT(rate_table->info[rix].phy) && |
847 | (ath_rc_priv->per[high_rix] > 45))) | 848 | (ath_rc_priv->per[rix] > 45)) |
848 | rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, | 849 | rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, |
849 | &is_probe, true); | 850 | &is_probe, true); |
850 | else | ||
851 | ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix); | ||
852 | 851 | ||
853 | /* All other rates in the series have RTS enabled */ | 852 | /* All other rates in the series have RTS enabled */ |
854 | ath_rc_rate_set_series(rate_table, &rates[i], txrc, | 853 | ath_rc_rate_set_series(rate_table, &rates[i], txrc, |
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 560d6effac7..5046b282a93 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h | |||
@@ -2098,8 +2098,8 @@ enum { | |||
2098 | #define AR_MCI_CONT_STATUS 0x1848 | 2098 | #define AR_MCI_CONT_STATUS 0x1848 |
2099 | #define AR_MCI_CONT_RSSI_POWER 0x000000FF | 2099 | #define AR_MCI_CONT_RSSI_POWER 0x000000FF |
2100 | #define AR_MCI_CONT_RSSI_POWER_S 0 | 2100 | #define AR_MCI_CONT_RSSI_POWER_S 0 |
2101 | #define AR_MCI_CONT_RRIORITY 0x0000FF00 | 2101 | #define AR_MCI_CONT_PRIORITY 0x0000FF00 |
2102 | #define AR_MCI_CONT_RRIORITY_S 8 | 2102 | #define AR_MCI_CONT_PRIORITY_S 8 |
2103 | #define AR_MCI_CONT_TXRX 0x00010000 | 2103 | #define AR_MCI_CONT_TXRX 0x00010000 |
2104 | #define AR_MCI_CONT_TXRX_S 16 | 2104 | #define AR_MCI_CONT_TXRX_S 16 |
2105 | 2105 | ||
@@ -2162,10 +2162,6 @@ enum { | |||
2162 | #define AR_BTCOEX_CTRL_SPDT_POLARITY 0x80000000 | 2162 | #define AR_BTCOEX_CTRL_SPDT_POLARITY 0x80000000 |
2163 | #define AR_BTCOEX_CTRL_SPDT_POLARITY_S 31 | 2163 | #define AR_BTCOEX_CTRL_SPDT_POLARITY_S 31 |
2164 | 2164 | ||
2165 | #define AR_BTCOEX_WL_WEIGHTS0 0x18b0 | ||
2166 | #define AR_BTCOEX_WL_WEIGHTS1 0x18b4 | ||
2167 | #define AR_BTCOEX_WL_WEIGHTS2 0x18b8 | ||
2168 | #define AR_BTCOEX_WL_WEIGHTS3 0x18bc | ||
2169 | #define AR_BTCOEX_MAX_TXPWR(_x) (0x18c0 + ((_x) << 2)) | 2165 | #define AR_BTCOEX_MAX_TXPWR(_x) (0x18c0 + ((_x) << 2)) |
2170 | #define AR_BTCOEX_WL_LNA 0x1940 | 2166 | #define AR_BTCOEX_WL_LNA 0x1940 |
2171 | #define AR_BTCOEX_RFGAIN_CTRL 0x1944 | 2167 | #define AR_BTCOEX_RFGAIN_CTRL 0x1944 |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index f777ddcd117..2afc5e289df 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -1175,6 +1175,7 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, | |||
1175 | { | 1175 | { |
1176 | struct ath_atx_tid *txtid; | 1176 | struct ath_atx_tid *txtid; |
1177 | struct ath_node *an; | 1177 | struct ath_node *an; |
1178 | u8 density; | ||
1178 | 1179 | ||
1179 | an = (struct ath_node *)sta->drv_priv; | 1180 | an = (struct ath_node *)sta->drv_priv; |
1180 | txtid = ATH_AN_2_TID(an, tid); | 1181 | txtid = ATH_AN_2_TID(an, tid); |
@@ -1182,6 +1183,17 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, | |||
1182 | if (txtid->state & (AGGR_CLEANUP | AGGR_ADDBA_COMPLETE)) | 1183 | if (txtid->state & (AGGR_CLEANUP | AGGR_ADDBA_COMPLETE)) |
1183 | return -EAGAIN; | 1184 | return -EAGAIN; |
1184 | 1185 | ||
1186 | /* update ampdu factor/density, they may have changed. This may happen | ||
1187 | * in HT IBSS when a beacon with HT-info is received after the station | ||
1188 | * has already been added. | ||
1189 | */ | ||
1190 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) { | ||
1191 | an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + | ||
1192 | sta->ht_cap.ampdu_factor); | ||
1193 | density = ath9k_parse_mpdudensity(sta->ht_cap.ampdu_density); | ||
1194 | an->mpdudensity = density; | ||
1195 | } | ||
1196 | |||
1185 | txtid->state |= AGGR_ADDBA_PROGRESS; | 1197 | txtid->state |= AGGR_ADDBA_PROGRESS; |
1186 | txtid->paused = true; | 1198 | txtid->paused = true; |
1187 | *ssn = txtid->seq_start = txtid->seq_next; | 1199 | *ssn = txtid->seq_start = txtid->seq_next; |
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 67c13af6f20..c06b6cb5c91 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h | |||
@@ -877,6 +877,10 @@ struct b43_wl { | |||
877 | * from the mac80211 subsystem. */ | 877 | * from the mac80211 subsystem. */ |
878 | u16 mac80211_initially_registered_queues; | 878 | u16 mac80211_initially_registered_queues; |
879 | 879 | ||
880 | /* Set this if we call ieee80211_register_hw() and check if we call | ||
881 | * ieee80211_unregister_hw(). */ | ||
882 | bool hw_registred; | ||
883 | |||
880 | /* We can only have one operating interface (802.11 core) | 884 | /* We can only have one operating interface (802.11 core) |
881 | * at a time. General information about this interface follows. | 885 | * at a time. General information about this interface follows. |
882 | */ | 886 | */ |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 5a39b226b2e..acd03a4f973 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -2437,6 +2437,7 @@ start_ieee80211: | |||
2437 | err = ieee80211_register_hw(wl->hw); | 2437 | err = ieee80211_register_hw(wl->hw); |
2438 | if (err) | 2438 | if (err) |
2439 | goto err_one_core_detach; | 2439 | goto err_one_core_detach; |
2440 | wl->hw_registred = true; | ||
2440 | b43_leds_register(wl->current_dev); | 2441 | b43_leds_register(wl->current_dev); |
2441 | goto out; | 2442 | goto out; |
2442 | 2443 | ||
@@ -5299,6 +5300,7 @@ static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev) | |||
5299 | 5300 | ||
5300 | hw->queues = modparam_qos ? B43_QOS_QUEUE_NUM : 1; | 5301 | hw->queues = modparam_qos ? B43_QOS_QUEUE_NUM : 1; |
5301 | wl->mac80211_initially_registered_queues = hw->queues; | 5302 | wl->mac80211_initially_registered_queues = hw->queues; |
5303 | wl->hw_registred = false; | ||
5302 | hw->max_rates = 2; | 5304 | hw->max_rates = 2; |
5303 | SET_IEEE80211_DEV(hw, dev->dev); | 5305 | SET_IEEE80211_DEV(hw, dev->dev); |
5304 | if (is_valid_ether_addr(sprom->et1mac)) | 5306 | if (is_valid_ether_addr(sprom->et1mac)) |
@@ -5370,12 +5372,15 @@ static void b43_bcma_remove(struct bcma_device *core) | |||
5370 | * as the ieee80211 unreg will destroy the workqueue. */ | 5372 | * as the ieee80211 unreg will destroy the workqueue. */ |
5371 | cancel_work_sync(&wldev->restart_work); | 5373 | cancel_work_sync(&wldev->restart_work); |
5372 | 5374 | ||
5373 | /* Restore the queues count before unregistering, because firmware detect | 5375 | B43_WARN_ON(!wl); |
5374 | * might have modified it. Restoring is important, so the networking | 5376 | if (wl->current_dev == wldev && wl->hw_registred) { |
5375 | * stack can properly free resources. */ | 5377 | /* Restore the queues count before unregistering, because firmware detect |
5376 | wl->hw->queues = wl->mac80211_initially_registered_queues; | 5378 | * might have modified it. Restoring is important, so the networking |
5377 | b43_leds_stop(wldev); | 5379 | * stack can properly free resources. */ |
5378 | ieee80211_unregister_hw(wl->hw); | 5380 | wl->hw->queues = wl->mac80211_initially_registered_queues; |
5381 | b43_leds_stop(wldev); | ||
5382 | ieee80211_unregister_hw(wl->hw); | ||
5383 | } | ||
5379 | 5384 | ||
5380 | b43_one_core_detach(wldev->dev); | 5385 | b43_one_core_detach(wldev->dev); |
5381 | 5386 | ||
@@ -5446,7 +5451,7 @@ static void b43_ssb_remove(struct ssb_device *sdev) | |||
5446 | cancel_work_sync(&wldev->restart_work); | 5451 | cancel_work_sync(&wldev->restart_work); |
5447 | 5452 | ||
5448 | B43_WARN_ON(!wl); | 5453 | B43_WARN_ON(!wl); |
5449 | if (wl->current_dev == wldev) { | 5454 | if (wl->current_dev == wldev && wl->hw_registred) { |
5450 | /* Restore the queues count before unregistering, because firmware detect | 5455 | /* Restore the queues count before unregistering, because firmware detect |
5451 | * might have modified it. Restoring is important, so the networking | 5456 | * might have modified it. Restoring is important, so the networking |
5452 | * stack can properly free resources. */ | 5457 | * stack can properly free resources. */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/brcm80211/brcmfmac/Makefile index abb48032753..9d5170b6df5 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/Makefile +++ b/drivers/net/wireless/brcm80211/brcmfmac/Makefile | |||
@@ -34,3 +34,5 @@ brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \ | |||
34 | sdio_chip.o | 34 | sdio_chip.o |
35 | brcmfmac-$(CONFIG_BRCMFMAC_USB) += \ | 35 | brcmfmac-$(CONFIG_BRCMFMAC_USB) += \ |
36 | usb.o | 36 | usb.o |
37 | brcmfmac-$(CONFIG_BRCMDBG) += \ | ||
38 | dhd_dbg.o \ No newline at end of file | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c index 82f51dbd0d6..49765d34b4e 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c | |||
@@ -44,6 +44,7 @@ | |||
44 | 44 | ||
45 | #define SDIO_DEVICE_ID_BROADCOM_4329 0x4329 | 45 | #define SDIO_DEVICE_ID_BROADCOM_4329 0x4329 |
46 | #define SDIO_DEVICE_ID_BROADCOM_4330 0x4330 | 46 | #define SDIO_DEVICE_ID_BROADCOM_4330 0x4330 |
47 | #define SDIO_DEVICE_ID_BROADCOM_4334 0x4334 | ||
47 | 48 | ||
48 | #define SDIO_FUNC1_BLOCKSIZE 64 | 49 | #define SDIO_FUNC1_BLOCKSIZE 64 |
49 | #define SDIO_FUNC2_BLOCKSIZE 512 | 50 | #define SDIO_FUNC2_BLOCKSIZE 512 |
@@ -52,6 +53,7 @@ | |||
52 | static const struct sdio_device_id brcmf_sdmmc_ids[] = { | 53 | static const struct sdio_device_id brcmf_sdmmc_ids[] = { |
53 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)}, | 54 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)}, |
54 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330)}, | 55 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330)}, |
56 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4334)}, | ||
55 | { /* end: all zeroes */ }, | 57 | { /* end: all zeroes */ }, |
56 | }; | 58 | }; |
57 | MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); | 59 | MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h index 9f637014486..a11fe54f595 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h | |||
@@ -613,6 +613,9 @@ struct brcmf_pub { | |||
613 | struct work_struct multicast_work; | 613 | struct work_struct multicast_work; |
614 | u8 macvalue[ETH_ALEN]; | 614 | u8 macvalue[ETH_ALEN]; |
615 | atomic_t pend_8021x_cnt; | 615 | atomic_t pend_8021x_cnt; |
616 | #ifdef DEBUG | ||
617 | struct dentry *dbgfs_dir; | ||
618 | #endif | ||
616 | }; | 619 | }; |
617 | 620 | ||
618 | struct brcmf_if_event { | 621 | struct brcmf_if_event { |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h index 366916494be..537f499cc5d 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h | |||
@@ -36,6 +36,13 @@ struct dngl_stats { | |||
36 | unsigned long multicast; /* multicast packets received */ | 36 | unsigned long multicast; /* multicast packets received */ |
37 | }; | 37 | }; |
38 | 38 | ||
39 | struct brcmf_bus_dcmd { | ||
40 | char *name; | ||
41 | char *param; | ||
42 | int param_len; | ||
43 | struct list_head list; | ||
44 | }; | ||
45 | |||
39 | /* interface structure between common and bus layer */ | 46 | /* interface structure between common and bus layer */ |
40 | struct brcmf_bus { | 47 | struct brcmf_bus { |
41 | u8 type; /* bus type */ | 48 | u8 type; /* bus type */ |
@@ -50,6 +57,7 @@ struct brcmf_bus { | |||
50 | unsigned long tx_realloc; /* Tx packets realloced for headroom */ | 57 | unsigned long tx_realloc; /* Tx packets realloced for headroom */ |
51 | struct dngl_stats dstats; /* Stats for dongle-based data */ | 58 | struct dngl_stats dstats; /* Stats for dongle-based data */ |
52 | u8 align; /* bus alignment requirement */ | 59 | u8 align; /* bus alignment requirement */ |
60 | struct list_head dcmd_list; | ||
53 | 61 | ||
54 | /* interface functions pointers */ | 62 | /* interface functions pointers */ |
55 | /* Stop bus module: clear pending frames, disable data flow */ | 63 | /* Stop bus module: clear pending frames, disable data flow */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c index 236cb9fa460..2621dd3d7dc 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c | |||
@@ -800,13 +800,13 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr) | |||
800 | char iovbuf[BRCMF_EVENTING_MASK_LEN + 12]; /* Room for | 800 | char iovbuf[BRCMF_EVENTING_MASK_LEN + 12]; /* Room for |
801 | "event_msgs" + '\0' + bitvec */ | 801 | "event_msgs" + '\0' + bitvec */ |
802 | char buf[128], *ptr; | 802 | char buf[128], *ptr; |
803 | u32 dongle_align = drvr->bus_if->align; | ||
804 | u32 glom = 0; | ||
805 | u32 roaming = 1; | 803 | u32 roaming = 1; |
806 | uint bcn_timeout = 3; | 804 | uint bcn_timeout = 3; |
807 | int scan_assoc_time = 40; | 805 | int scan_assoc_time = 40; |
808 | int scan_unassoc_time = 40; | 806 | int scan_unassoc_time = 40; |
809 | int i; | 807 | int i; |
808 | struct brcmf_bus_dcmd *cmdlst; | ||
809 | struct list_head *cur, *q; | ||
810 | 810 | ||
811 | mutex_lock(&drvr->proto_block); | 811 | mutex_lock(&drvr->proto_block); |
812 | 812 | ||
@@ -827,17 +827,6 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr) | |||
827 | /* Print fw version info */ | 827 | /* Print fw version info */ |
828 | brcmf_dbg(ERROR, "Firmware version = %s\n", buf); | 828 | brcmf_dbg(ERROR, "Firmware version = %s\n", buf); |
829 | 829 | ||
830 | /* Match Host and Dongle rx alignment */ | ||
831 | brcmf_c_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf, | ||
832 | sizeof(iovbuf)); | ||
833 | brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, | ||
834 | sizeof(iovbuf)); | ||
835 | |||
836 | /* disable glom option per default */ | ||
837 | brcmf_c_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf)); | ||
838 | brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, | ||
839 | sizeof(iovbuf)); | ||
840 | |||
841 | /* Setup timeout if Beacons are lost and roam is off to report | 830 | /* Setup timeout if Beacons are lost and roam is off to report |
842 | link down */ | 831 | link down */ |
843 | brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, | 832 | brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, |
@@ -874,6 +863,20 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr) | |||
874 | 0, true); | 863 | 0, true); |
875 | } | 864 | } |
876 | 865 | ||
866 | /* set bus specific command if there is any */ | ||
867 | list_for_each_safe(cur, q, &drvr->bus_if->dcmd_list) { | ||
868 | cmdlst = list_entry(cur, struct brcmf_bus_dcmd, list); | ||
869 | if (cmdlst->name && cmdlst->param && cmdlst->param_len) { | ||
870 | brcmf_c_mkiovar(cmdlst->name, cmdlst->param, | ||
871 | cmdlst->param_len, iovbuf, | ||
872 | sizeof(iovbuf)); | ||
873 | brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, | ||
874 | iovbuf, sizeof(iovbuf)); | ||
875 | } | ||
876 | list_del(cur); | ||
877 | kfree(cmdlst); | ||
878 | } | ||
879 | |||
877 | mutex_unlock(&drvr->proto_block); | 880 | mutex_unlock(&drvr->proto_block); |
878 | 881 | ||
879 | return 0; | 882 | return 0; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c new file mode 100644 index 00000000000..7f89540b56d --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c | |||
@@ -0,0 +1,126 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 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 | #include <linux/debugfs.h> | ||
17 | #include <linux/if_ether.h> | ||
18 | #include <linux/if.h> | ||
19 | #include <linux/ieee80211.h> | ||
20 | #include <linux/module.h> | ||
21 | |||
22 | #include <defs.h> | ||
23 | #include <brcmu_wifi.h> | ||
24 | #include <brcmu_utils.h> | ||
25 | #include "dhd.h" | ||
26 | #include "dhd_bus.h" | ||
27 | #include "dhd_dbg.h" | ||
28 | |||
29 | static struct dentry *root_folder; | ||
30 | |||
31 | void brcmf_debugfs_init(void) | ||
32 | { | ||
33 | root_folder = debugfs_create_dir(KBUILD_MODNAME, NULL); | ||
34 | if (IS_ERR(root_folder)) | ||
35 | root_folder = NULL; | ||
36 | } | ||
37 | |||
38 | void brcmf_debugfs_exit(void) | ||
39 | { | ||
40 | if (!root_folder) | ||
41 | return; | ||
42 | |||
43 | debugfs_remove_recursive(root_folder); | ||
44 | root_folder = NULL; | ||
45 | } | ||
46 | |||
47 | int brcmf_debugfs_attach(struct brcmf_pub *drvr) | ||
48 | { | ||
49 | if (!root_folder) | ||
50 | return -ENODEV; | ||
51 | |||
52 | drvr->dbgfs_dir = debugfs_create_dir(dev_name(drvr->dev), root_folder); | ||
53 | return PTR_RET(drvr->dbgfs_dir); | ||
54 | } | ||
55 | |||
56 | void brcmf_debugfs_detach(struct brcmf_pub *drvr) | ||
57 | { | ||
58 | if (!IS_ERR_OR_NULL(drvr->dbgfs_dir)) | ||
59 | debugfs_remove_recursive(drvr->dbgfs_dir); | ||
60 | } | ||
61 | |||
62 | struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr) | ||
63 | { | ||
64 | return drvr->dbgfs_dir; | ||
65 | } | ||
66 | |||
67 | static | ||
68 | ssize_t brcmf_debugfs_sdio_counter_read(struct file *f, char __user *data, | ||
69 | size_t count, loff_t *ppos) | ||
70 | { | ||
71 | struct brcmf_sdio_count *sdcnt = f->private_data; | ||
72 | char buf[750]; | ||
73 | int res; | ||
74 | |||
75 | /* only allow read from start */ | ||
76 | if (*ppos > 0) | ||
77 | return 0; | ||
78 | |||
79 | res = scnprintf(buf, sizeof(buf), | ||
80 | "intrcount: %u\nlastintrs: %u\n" | ||
81 | "pollcnt: %u\nregfails: %u\n" | ||
82 | "tx_sderrs: %u\nfcqueued: %u\n" | ||
83 | "rxrtx: %u\nrx_toolong: %u\n" | ||
84 | "rxc_errors: %u\nrx_hdrfail: %u\n" | ||
85 | "rx_badhdr: %u\nrx_badseq: %u\n" | ||
86 | "fc_rcvd: %u\nfc_xoff: %u\n" | ||
87 | "fc_xon: %u\nrxglomfail: %u\n" | ||
88 | "rxglomframes: %u\nrxglompkts: %u\n" | ||
89 | "f2rxhdrs: %u\nf2rxdata: %u\n" | ||
90 | "f2txdata: %u\nf1regdata: %u\n" | ||
91 | "tickcnt: %u\ntx_ctlerrs: %lu\n" | ||
92 | "tx_ctlpkts: %lu\nrx_ctlerrs: %lu\n" | ||
93 | "rx_ctlpkts: %lu\nrx_readahead: %lu\n", | ||
94 | sdcnt->intrcount, sdcnt->lastintrs, | ||
95 | sdcnt->pollcnt, sdcnt->regfails, | ||
96 | sdcnt->tx_sderrs, sdcnt->fcqueued, | ||
97 | sdcnt->rxrtx, sdcnt->rx_toolong, | ||
98 | sdcnt->rxc_errors, sdcnt->rx_hdrfail, | ||
99 | sdcnt->rx_badhdr, sdcnt->rx_badseq, | ||
100 | sdcnt->fc_rcvd, sdcnt->fc_xoff, | ||
101 | sdcnt->fc_xon, sdcnt->rxglomfail, | ||
102 | sdcnt->rxglomframes, sdcnt->rxglompkts, | ||
103 | sdcnt->f2rxhdrs, sdcnt->f2rxdata, | ||
104 | sdcnt->f2txdata, sdcnt->f1regdata, | ||
105 | sdcnt->tickcnt, sdcnt->tx_ctlerrs, | ||
106 | sdcnt->tx_ctlpkts, sdcnt->rx_ctlerrs, | ||
107 | sdcnt->rx_ctlpkts, sdcnt->rx_readahead_cnt); | ||
108 | |||
109 | return simple_read_from_buffer(data, count, ppos, buf, res); | ||
110 | } | ||
111 | |||
112 | static const struct file_operations brcmf_debugfs_sdio_counter_ops = { | ||
113 | .owner = THIS_MODULE, | ||
114 | .open = simple_open, | ||
115 | .read = brcmf_debugfs_sdio_counter_read | ||
116 | }; | ||
117 | |||
118 | void brcmf_debugfs_create_sdio_count(struct brcmf_pub *drvr, | ||
119 | struct brcmf_sdio_count *sdcnt) | ||
120 | { | ||
121 | struct dentry *dentry = drvr->dbgfs_dir; | ||
122 | |||
123 | if (!IS_ERR_OR_NULL(dentry)) | ||
124 | debugfs_create_file("counters", S_IRUGO, dentry, | ||
125 | sdcnt, &brcmf_debugfs_sdio_counter_ops); | ||
126 | } | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h index a2c4576cf9f..b784920532d 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h | |||
@@ -76,4 +76,63 @@ do { \ | |||
76 | 76 | ||
77 | extern int brcmf_msg_level; | 77 | extern int brcmf_msg_level; |
78 | 78 | ||
79 | /* | ||
80 | * hold counter variables used in brcmfmac sdio driver. | ||
81 | */ | ||
82 | struct brcmf_sdio_count { | ||
83 | uint intrcount; /* Count of device interrupt callbacks */ | ||
84 | uint lastintrs; /* Count as of last watchdog timer */ | ||
85 | uint pollcnt; /* Count of active polls */ | ||
86 | uint regfails; /* Count of R_REG failures */ | ||
87 | uint tx_sderrs; /* Count of tx attempts with sd errors */ | ||
88 | uint fcqueued; /* Tx packets that got queued */ | ||
89 | uint rxrtx; /* Count of rtx requests (NAK to dongle) */ | ||
90 | uint rx_toolong; /* Receive frames too long to receive */ | ||
91 | uint rxc_errors; /* SDIO errors when reading control frames */ | ||
92 | uint rx_hdrfail; /* SDIO errors on header reads */ | ||
93 | uint rx_badhdr; /* Bad received headers (roosync?) */ | ||
94 | uint rx_badseq; /* Mismatched rx sequence number */ | ||
95 | uint fc_rcvd; /* Number of flow-control events received */ | ||
96 | uint fc_xoff; /* Number which turned on flow-control */ | ||
97 | uint fc_xon; /* Number which turned off flow-control */ | ||
98 | uint rxglomfail; /* Failed deglom attempts */ | ||
99 | uint rxglomframes; /* Number of glom frames (superframes) */ | ||
100 | uint rxglompkts; /* Number of packets from glom frames */ | ||
101 | uint f2rxhdrs; /* Number of header reads */ | ||
102 | uint f2rxdata; /* Number of frame data reads */ | ||
103 | uint f2txdata; /* Number of f2 frame writes */ | ||
104 | uint f1regdata; /* Number of f1 register accesses */ | ||
105 | uint tickcnt; /* Number of watchdog been schedule */ | ||
106 | ulong tx_ctlerrs; /* Err of sending ctrl frames */ | ||
107 | ulong tx_ctlpkts; /* Ctrl frames sent to dongle */ | ||
108 | ulong rx_ctlerrs; /* Err of processing rx ctrl frames */ | ||
109 | ulong rx_ctlpkts; /* Ctrl frames processed from dongle */ | ||
110 | ulong rx_readahead_cnt; /* packets where header read-ahead was used */ | ||
111 | }; | ||
112 | |||
113 | struct brcmf_pub; | ||
114 | #ifdef DEBUG | ||
115 | void brcmf_debugfs_init(void); | ||
116 | void brcmf_debugfs_exit(void); | ||
117 | int brcmf_debugfs_attach(struct brcmf_pub *drvr); | ||
118 | void brcmf_debugfs_detach(struct brcmf_pub *drvr); | ||
119 | struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr); | ||
120 | void brcmf_debugfs_create_sdio_count(struct brcmf_pub *drvr, | ||
121 | struct brcmf_sdio_count *sdcnt); | ||
122 | #else | ||
123 | static inline void brcmf_debugfs_init(void) | ||
124 | { | ||
125 | } | ||
126 | static inline void brcmf_debugfs_exit(void) | ||
127 | { | ||
128 | } | ||
129 | static inline int brcmf_debugfs_attach(struct brcmf_pub *drvr) | ||
130 | { | ||
131 | return 0; | ||
132 | } | ||
133 | static inline void brcmf_debugfs_detach(struct brcmf_pub *drvr) | ||
134 | { | ||
135 | } | ||
136 | #endif | ||
137 | |||
79 | #endif /* _BRCMF_DBG_H_ */ | 138 | #endif /* _BRCMF_DBG_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index 8933f9b31a9..57bf1d7ee80 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c | |||
@@ -1007,6 +1007,9 @@ int brcmf_attach(uint bus_hdrlen, struct device *dev) | |||
1007 | drvr->bus_if->drvr = drvr; | 1007 | drvr->bus_if->drvr = drvr; |
1008 | drvr->dev = dev; | 1008 | drvr->dev = dev; |
1009 | 1009 | ||
1010 | /* create device debugfs folder */ | ||
1011 | brcmf_debugfs_attach(drvr); | ||
1012 | |||
1010 | /* Attach and link in the protocol */ | 1013 | /* Attach and link in the protocol */ |
1011 | ret = brcmf_proto_attach(drvr); | 1014 | ret = brcmf_proto_attach(drvr); |
1012 | if (ret != 0) { | 1015 | if (ret != 0) { |
@@ -1017,6 +1020,8 @@ int brcmf_attach(uint bus_hdrlen, struct device *dev) | |||
1017 | INIT_WORK(&drvr->setmacaddr_work, _brcmf_set_mac_address); | 1020 | INIT_WORK(&drvr->setmacaddr_work, _brcmf_set_mac_address); |
1018 | INIT_WORK(&drvr->multicast_work, _brcmf_set_multicast_list); | 1021 | INIT_WORK(&drvr->multicast_work, _brcmf_set_multicast_list); |
1019 | 1022 | ||
1023 | INIT_LIST_HEAD(&drvr->bus_if->dcmd_list); | ||
1024 | |||
1020 | return ret; | 1025 | return ret; |
1021 | 1026 | ||
1022 | fail: | 1027 | fail: |
@@ -1123,6 +1128,7 @@ void brcmf_detach(struct device *dev) | |||
1123 | brcmf_proto_detach(drvr); | 1128 | brcmf_proto_detach(drvr); |
1124 | } | 1129 | } |
1125 | 1130 | ||
1131 | brcmf_debugfs_detach(drvr); | ||
1126 | bus_if->drvr = NULL; | 1132 | bus_if->drvr = NULL; |
1127 | kfree(drvr); | 1133 | kfree(drvr); |
1128 | } | 1134 | } |
@@ -1192,6 +1198,8 @@ exit: | |||
1192 | 1198 | ||
1193 | static void brcmf_driver_init(struct work_struct *work) | 1199 | static void brcmf_driver_init(struct work_struct *work) |
1194 | { | 1200 | { |
1201 | brcmf_debugfs_init(); | ||
1202 | |||
1195 | #ifdef CONFIG_BRCMFMAC_SDIO | 1203 | #ifdef CONFIG_BRCMFMAC_SDIO |
1196 | brcmf_sdio_init(); | 1204 | brcmf_sdio_init(); |
1197 | #endif | 1205 | #endif |
@@ -1219,6 +1227,7 @@ static void __exit brcmfmac_module_exit(void) | |||
1219 | #ifdef CONFIG_BRCMFMAC_USB | 1227 | #ifdef CONFIG_BRCMFMAC_USB |
1220 | brcmf_usb_exit(); | 1228 | brcmf_usb_exit(); |
1221 | #endif | 1229 | #endif |
1230 | brcmf_debugfs_exit(); | ||
1222 | } | 1231 | } |
1223 | 1232 | ||
1224 | module_init(brcmfmac_module_init); | 1233 | module_init(brcmfmac_module_init); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index 1dbf2be478c..5c868bac1c1 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | |||
@@ -31,6 +31,8 @@ | |||
31 | #include <linux/firmware.h> | 31 | #include <linux/firmware.h> |
32 | #include <linux/module.h> | 32 | #include <linux/module.h> |
33 | #include <linux/bcma/bcma.h> | 33 | #include <linux/bcma/bcma.h> |
34 | #include <linux/debugfs.h> | ||
35 | #include <linux/vmalloc.h> | ||
34 | #include <asm/unaligned.h> | 36 | #include <asm/unaligned.h> |
35 | #include <defs.h> | 37 | #include <defs.h> |
36 | #include <brcmu_wifi.h> | 38 | #include <brcmu_wifi.h> |
@@ -48,6 +50,9 @@ | |||
48 | 50 | ||
49 | #define CBUF_LEN (128) | 51 | #define CBUF_LEN (128) |
50 | 52 | ||
53 | /* Device console log buffer state */ | ||
54 | #define CONSOLE_BUFFER_MAX 2024 | ||
55 | |||
51 | struct rte_log_le { | 56 | struct rte_log_le { |
52 | __le32 buf; /* Can't be pointer on (64-bit) hosts */ | 57 | __le32 buf; /* Can't be pointer on (64-bit) hosts */ |
53 | __le32 buf_size; | 58 | __le32 buf_size; |
@@ -281,7 +286,7 @@ struct rte_console { | |||
281 | * Shared structure between dongle and the host. | 286 | * Shared structure between dongle and the host. |
282 | * The structure contains pointers to trap or assert information. | 287 | * The structure contains pointers to trap or assert information. |
283 | */ | 288 | */ |
284 | #define SDPCM_SHARED_VERSION 0x0002 | 289 | #define SDPCM_SHARED_VERSION 0x0003 |
285 | #define SDPCM_SHARED_VERSION_MASK 0x00FF | 290 | #define SDPCM_SHARED_VERSION_MASK 0x00FF |
286 | #define SDPCM_SHARED_ASSERT_BUILT 0x0100 | 291 | #define SDPCM_SHARED_ASSERT_BUILT 0x0100 |
287 | #define SDPCM_SHARED_ASSERT 0x0200 | 292 | #define SDPCM_SHARED_ASSERT 0x0200 |
@@ -428,6 +433,29 @@ struct brcmf_console { | |||
428 | u8 *buf; /* Log buffer (host copy) */ | 433 | u8 *buf; /* Log buffer (host copy) */ |
429 | uint last; /* Last buffer read index */ | 434 | uint last; /* Last buffer read index */ |
430 | }; | 435 | }; |
436 | |||
437 | struct brcmf_trap_info { | ||
438 | __le32 type; | ||
439 | __le32 epc; | ||
440 | __le32 cpsr; | ||
441 | __le32 spsr; | ||
442 | __le32 r0; /* a1 */ | ||
443 | __le32 r1; /* a2 */ | ||
444 | __le32 r2; /* a3 */ | ||
445 | __le32 r3; /* a4 */ | ||
446 | __le32 r4; /* v1 */ | ||
447 | __le32 r5; /* v2 */ | ||
448 | __le32 r6; /* v3 */ | ||
449 | __le32 r7; /* v4 */ | ||
450 | __le32 r8; /* v5 */ | ||
451 | __le32 r9; /* sb/v6 */ | ||
452 | __le32 r10; /* sl/v7 */ | ||
453 | __le32 r11; /* fp/v8 */ | ||
454 | __le32 r12; /* ip */ | ||
455 | __le32 r13; /* sp */ | ||
456 | __le32 r14; /* lr */ | ||
457 | __le32 pc; /* r15 */ | ||
458 | }; | ||
431 | #endif /* DEBUG */ | 459 | #endif /* DEBUG */ |
432 | 460 | ||
433 | struct sdpcm_shared { | 461 | struct sdpcm_shared { |
@@ -439,6 +467,7 @@ struct sdpcm_shared { | |||
439 | u32 console_addr; /* Address of struct rte_console */ | 467 | u32 console_addr; /* Address of struct rte_console */ |
440 | u32 msgtrace_addr; | 468 | u32 msgtrace_addr; |
441 | u8 tag[32]; | 469 | u8 tag[32]; |
470 | u32 brpt_addr; | ||
442 | }; | 471 | }; |
443 | 472 | ||
444 | struct sdpcm_shared_le { | 473 | struct sdpcm_shared_le { |
@@ -450,6 +479,7 @@ struct sdpcm_shared_le { | |||
450 | __le32 console_addr; /* Address of struct rte_console */ | 479 | __le32 console_addr; /* Address of struct rte_console */ |
451 | __le32 msgtrace_addr; | 480 | __le32 msgtrace_addr; |
452 | u8 tag[32]; | 481 | u8 tag[32]; |
482 | __le32 brpt_addr; | ||
453 | }; | 483 | }; |
454 | 484 | ||
455 | 485 | ||
@@ -502,12 +532,9 @@ struct brcmf_sdio { | |||
502 | bool intr; /* Use interrupts */ | 532 | bool intr; /* Use interrupts */ |
503 | bool poll; /* Use polling */ | 533 | bool poll; /* Use polling */ |
504 | bool ipend; /* Device interrupt is pending */ | 534 | bool ipend; /* Device interrupt is pending */ |
505 | uint intrcount; /* Count of device interrupt callbacks */ | ||
506 | uint lastintrs; /* Count as of last watchdog timer */ | ||
507 | uint spurious; /* Count of spurious interrupts */ | 535 | uint spurious; /* Count of spurious interrupts */ |
508 | uint pollrate; /* Ticks between device polls */ | 536 | uint pollrate; /* Ticks between device polls */ |
509 | uint polltick; /* Tick counter */ | 537 | uint polltick; /* Tick counter */ |
510 | uint pollcnt; /* Count of active polls */ | ||
511 | 538 | ||
512 | #ifdef DEBUG | 539 | #ifdef DEBUG |
513 | uint console_interval; | 540 | uint console_interval; |
@@ -515,8 +542,6 @@ struct brcmf_sdio { | |||
515 | uint console_addr; /* Console address from shared struct */ | 542 | uint console_addr; /* Console address from shared struct */ |
516 | #endif /* DEBUG */ | 543 | #endif /* DEBUG */ |
517 | 544 | ||
518 | uint regfails; /* Count of R_REG failures */ | ||
519 | |||
520 | uint clkstate; /* State of sd and backplane clock(s) */ | 545 | uint clkstate; /* State of sd and backplane clock(s) */ |
521 | bool activity; /* Activity flag for clock down */ | 546 | bool activity; /* Activity flag for clock down */ |
522 | s32 idletime; /* Control for activity timeout */ | 547 | s32 idletime; /* Control for activity timeout */ |
@@ -531,33 +556,6 @@ struct brcmf_sdio { | |||
531 | /* Field to decide if rx of control frames happen in rxbuf or lb-pool */ | 556 | /* Field to decide if rx of control frames happen in rxbuf or lb-pool */ |
532 | bool usebufpool; | 557 | bool usebufpool; |
533 | 558 | ||
534 | /* Some additional counters */ | ||
535 | uint tx_sderrs; /* Count of tx attempts with sd errors */ | ||
536 | uint fcqueued; /* Tx packets that got queued */ | ||
537 | uint rxrtx; /* Count of rtx requests (NAK to dongle) */ | ||
538 | uint rx_toolong; /* Receive frames too long to receive */ | ||
539 | uint rxc_errors; /* SDIO errors when reading control frames */ | ||
540 | uint rx_hdrfail; /* SDIO errors on header reads */ | ||
541 | uint rx_badhdr; /* Bad received headers (roosync?) */ | ||
542 | uint rx_badseq; /* Mismatched rx sequence number */ | ||
543 | uint fc_rcvd; /* Number of flow-control events received */ | ||
544 | uint fc_xoff; /* Number which turned on flow-control */ | ||
545 | uint fc_xon; /* Number which turned off flow-control */ | ||
546 | uint rxglomfail; /* Failed deglom attempts */ | ||
547 | uint rxglomframes; /* Number of glom frames (superframes) */ | ||
548 | uint rxglompkts; /* Number of packets from glom frames */ | ||
549 | uint f2rxhdrs; /* Number of header reads */ | ||
550 | uint f2rxdata; /* Number of frame data reads */ | ||
551 | uint f2txdata; /* Number of f2 frame writes */ | ||
552 | uint f1regdata; /* Number of f1 register accesses */ | ||
553 | uint tickcnt; /* Number of watchdog been schedule */ | ||
554 | unsigned long tx_ctlerrs; /* Err of sending ctrl frames */ | ||
555 | unsigned long tx_ctlpkts; /* Ctrl frames sent to dongle */ | ||
556 | unsigned long rx_ctlerrs; /* Err of processing rx ctrl frames */ | ||
557 | unsigned long rx_ctlpkts; /* Ctrl frames processed from dongle */ | ||
558 | unsigned long rx_readahead_cnt; /* Number of packets where header | ||
559 | * read-ahead was used. */ | ||
560 | |||
561 | u8 *ctrl_frame_buf; | 559 | u8 *ctrl_frame_buf; |
562 | u32 ctrl_frame_len; | 560 | u32 ctrl_frame_len; |
563 | bool ctrl_frame_stat; | 561 | bool ctrl_frame_stat; |
@@ -583,6 +581,7 @@ struct brcmf_sdio { | |||
583 | u32 fw_ptr; | 581 | u32 fw_ptr; |
584 | 582 | ||
585 | bool txoff; /* Transmit flow-controlled */ | 583 | bool txoff; /* Transmit flow-controlled */ |
584 | struct brcmf_sdio_count sdcnt; | ||
586 | }; | 585 | }; |
587 | 586 | ||
588 | /* clkstate */ | 587 | /* clkstate */ |
@@ -945,7 +944,7 @@ static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus) | |||
945 | if (ret == 0) | 944 | if (ret == 0) |
946 | w_sdreg32(bus, SMB_INT_ACK, | 945 | w_sdreg32(bus, SMB_INT_ACK, |
947 | offsetof(struct sdpcmd_regs, tosbmailbox)); | 946 | offsetof(struct sdpcmd_regs, tosbmailbox)); |
948 | bus->f1regdata += 2; | 947 | bus->sdcnt.f1regdata += 2; |
949 | 948 | ||
950 | /* Dongle recomposed rx frames, accept them again */ | 949 | /* Dongle recomposed rx frames, accept them again */ |
951 | if (hmb_data & HMB_DATA_NAKHANDLED) { | 950 | if (hmb_data & HMB_DATA_NAKHANDLED) { |
@@ -984,12 +983,12 @@ static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus) | |||
984 | HMB_DATA_FCDATA_SHIFT; | 983 | HMB_DATA_FCDATA_SHIFT; |
985 | 984 | ||
986 | if (fcbits & ~bus->flowcontrol) | 985 | if (fcbits & ~bus->flowcontrol) |
987 | bus->fc_xoff++; | 986 | bus->sdcnt.fc_xoff++; |
988 | 987 | ||
989 | if (bus->flowcontrol & ~fcbits) | 988 | if (bus->flowcontrol & ~fcbits) |
990 | bus->fc_xon++; | 989 | bus->sdcnt.fc_xon++; |
991 | 990 | ||
992 | bus->fc_rcvd++; | 991 | bus->sdcnt.fc_rcvd++; |
993 | bus->flowcontrol = fcbits; | 992 | bus->flowcontrol = fcbits; |
994 | } | 993 | } |
995 | 994 | ||
@@ -1021,7 +1020,7 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx) | |||
1021 | 1020 | ||
1022 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL, | 1021 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL, |
1023 | SFC_RF_TERM, &err); | 1022 | SFC_RF_TERM, &err); |
1024 | bus->f1regdata++; | 1023 | bus->sdcnt.f1regdata++; |
1025 | 1024 | ||
1026 | /* Wait until the packet has been flushed (device/FIFO stable) */ | 1025 | /* Wait until the packet has been flushed (device/FIFO stable) */ |
1027 | for (lastrbc = retries = 0xffff; retries > 0; retries--) { | 1026 | for (lastrbc = retries = 0xffff; retries > 0; retries--) { |
@@ -1029,7 +1028,7 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx) | |||
1029 | SBSDIO_FUNC1_RFRAMEBCHI, &err); | 1028 | SBSDIO_FUNC1_RFRAMEBCHI, &err); |
1030 | lo = brcmf_sdio_regrb(bus->sdiodev, | 1029 | lo = brcmf_sdio_regrb(bus->sdiodev, |
1031 | SBSDIO_FUNC1_RFRAMEBCLO, &err); | 1030 | SBSDIO_FUNC1_RFRAMEBCLO, &err); |
1032 | bus->f1regdata += 2; | 1031 | bus->sdcnt.f1regdata += 2; |
1033 | 1032 | ||
1034 | if ((hi == 0) && (lo == 0)) | 1033 | if ((hi == 0) && (lo == 0)) |
1035 | break; | 1034 | break; |
@@ -1047,11 +1046,11 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx) | |||
1047 | brcmf_dbg(INFO, "flush took %d iterations\n", 0xffff - retries); | 1046 | brcmf_dbg(INFO, "flush took %d iterations\n", 0xffff - retries); |
1048 | 1047 | ||
1049 | if (rtx) { | 1048 | if (rtx) { |
1050 | bus->rxrtx++; | 1049 | bus->sdcnt.rxrtx++; |
1051 | err = w_sdreg32(bus, SMB_NAK, | 1050 | err = w_sdreg32(bus, SMB_NAK, |
1052 | offsetof(struct sdpcmd_regs, tosbmailbox)); | 1051 | offsetof(struct sdpcmd_regs, tosbmailbox)); |
1053 | 1052 | ||
1054 | bus->f1regdata++; | 1053 | bus->sdcnt.f1regdata++; |
1055 | if (err == 0) | 1054 | if (err == 0) |
1056 | bus->rxskip = true; | 1055 | bus->rxskip = true; |
1057 | } | 1056 | } |
@@ -1243,7 +1242,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
1243 | dlen); | 1242 | dlen); |
1244 | errcode = -1; | 1243 | errcode = -1; |
1245 | } | 1244 | } |
1246 | bus->f2rxdata++; | 1245 | bus->sdcnt.f2rxdata++; |
1247 | 1246 | ||
1248 | /* On failure, kill the superframe, allow a couple retries */ | 1247 | /* On failure, kill the superframe, allow a couple retries */ |
1249 | if (errcode < 0) { | 1248 | if (errcode < 0) { |
@@ -1256,7 +1255,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
1256 | } else { | 1255 | } else { |
1257 | bus->glomerr = 0; | 1256 | bus->glomerr = 0; |
1258 | brcmf_sdbrcm_rxfail(bus, true, false); | 1257 | brcmf_sdbrcm_rxfail(bus, true, false); |
1259 | bus->rxglomfail++; | 1258 | bus->sdcnt.rxglomfail++; |
1260 | brcmf_sdbrcm_free_glom(bus); | 1259 | brcmf_sdbrcm_free_glom(bus); |
1261 | } | 1260 | } |
1262 | return 0; | 1261 | return 0; |
@@ -1312,7 +1311,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
1312 | if (rxseq != seq) { | 1311 | if (rxseq != seq) { |
1313 | brcmf_dbg(INFO, "(superframe) rx_seq %d, expected %d\n", | 1312 | brcmf_dbg(INFO, "(superframe) rx_seq %d, expected %d\n", |
1314 | seq, rxseq); | 1313 | seq, rxseq); |
1315 | bus->rx_badseq++; | 1314 | bus->sdcnt.rx_badseq++; |
1316 | rxseq = seq; | 1315 | rxseq = seq; |
1317 | } | 1316 | } |
1318 | 1317 | ||
@@ -1376,7 +1375,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
1376 | } else { | 1375 | } else { |
1377 | bus->glomerr = 0; | 1376 | bus->glomerr = 0; |
1378 | brcmf_sdbrcm_rxfail(bus, true, false); | 1377 | brcmf_sdbrcm_rxfail(bus, true, false); |
1379 | bus->rxglomfail++; | 1378 | bus->sdcnt.rxglomfail++; |
1380 | brcmf_sdbrcm_free_glom(bus); | 1379 | brcmf_sdbrcm_free_glom(bus); |
1381 | } | 1380 | } |
1382 | bus->nextlen = 0; | 1381 | bus->nextlen = 0; |
@@ -1402,7 +1401,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
1402 | if (rxseq != seq) { | 1401 | if (rxseq != seq) { |
1403 | brcmf_dbg(GLOM, "rx_seq %d, expected %d\n", | 1402 | brcmf_dbg(GLOM, "rx_seq %d, expected %d\n", |
1404 | seq, rxseq); | 1403 | seq, rxseq); |
1405 | bus->rx_badseq++; | 1404 | bus->sdcnt.rx_badseq++; |
1406 | rxseq = seq; | 1405 | rxseq = seq; |
1407 | } | 1406 | } |
1408 | rxseq++; | 1407 | rxseq++; |
@@ -1441,8 +1440,8 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
1441 | down(&bus->sdsem); | 1440 | down(&bus->sdsem); |
1442 | } | 1441 | } |
1443 | 1442 | ||
1444 | bus->rxglomframes++; | 1443 | bus->sdcnt.rxglomframes++; |
1445 | bus->rxglompkts += bus->glom.qlen; | 1444 | bus->sdcnt.rxglompkts += bus->glom.qlen; |
1446 | } | 1445 | } |
1447 | return num; | 1446 | return num; |
1448 | } | 1447 | } |
@@ -1526,7 +1525,7 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff) | |||
1526 | brcmf_dbg(ERROR, "%d-byte ctl frame (%d-byte ctl data) exceeds %d-byte limit\n", | 1525 | brcmf_dbg(ERROR, "%d-byte ctl frame (%d-byte ctl data) exceeds %d-byte limit\n", |
1527 | len, len - doff, bus->sdiodev->bus_if->maxctl); | 1526 | len, len - doff, bus->sdiodev->bus_if->maxctl); |
1528 | bus->sdiodev->bus_if->dstats.rx_errors++; | 1527 | bus->sdiodev->bus_if->dstats.rx_errors++; |
1529 | bus->rx_toolong++; | 1528 | bus->sdcnt.rx_toolong++; |
1530 | brcmf_sdbrcm_rxfail(bus, false, false); | 1529 | brcmf_sdbrcm_rxfail(bus, false, false); |
1531 | goto done; | 1530 | goto done; |
1532 | } | 1531 | } |
@@ -1536,13 +1535,13 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff) | |||
1536 | bus->sdiodev->sbwad, | 1535 | bus->sdiodev->sbwad, |
1537 | SDIO_FUNC_2, | 1536 | SDIO_FUNC_2, |
1538 | F2SYNC, (bus->rxctl + BRCMF_FIRSTREAD), rdlen); | 1537 | F2SYNC, (bus->rxctl + BRCMF_FIRSTREAD), rdlen); |
1539 | bus->f2rxdata++; | 1538 | bus->sdcnt.f2rxdata++; |
1540 | 1539 | ||
1541 | /* Control frame failures need retransmission */ | 1540 | /* Control frame failures need retransmission */ |
1542 | if (sdret < 0) { | 1541 | if (sdret < 0) { |
1543 | brcmf_dbg(ERROR, "read %d control bytes failed: %d\n", | 1542 | brcmf_dbg(ERROR, "read %d control bytes failed: %d\n", |
1544 | rdlen, sdret); | 1543 | rdlen, sdret); |
1545 | bus->rxc_errors++; | 1544 | bus->sdcnt.rxc_errors++; |
1546 | brcmf_sdbrcm_rxfail(bus, true, true); | 1545 | brcmf_sdbrcm_rxfail(bus, true, true); |
1547 | goto done; | 1546 | goto done; |
1548 | } | 1547 | } |
@@ -1589,7 +1588,7 @@ brcmf_alloc_pkt_and_read(struct brcmf_sdio *bus, u16 rdlen, | |||
1589 | /* Read the entire frame */ | 1588 | /* Read the entire frame */ |
1590 | sdret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad, | 1589 | sdret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad, |
1591 | SDIO_FUNC_2, F2SYNC, *pkt); | 1590 | SDIO_FUNC_2, F2SYNC, *pkt); |
1592 | bus->f2rxdata++; | 1591 | bus->sdcnt.f2rxdata++; |
1593 | 1592 | ||
1594 | if (sdret < 0) { | 1593 | if (sdret < 0) { |
1595 | brcmf_dbg(ERROR, "(nextlen): read %d bytes failed: %d\n", | 1594 | brcmf_dbg(ERROR, "(nextlen): read %d bytes failed: %d\n", |
@@ -1630,7 +1629,7 @@ brcmf_check_rxbuf(struct brcmf_sdio *bus, struct sk_buff *pkt, u8 *rxbuf, | |||
1630 | if ((u16)~(*len ^ check)) { | 1629 | if ((u16)~(*len ^ check)) { |
1631 | brcmf_dbg(ERROR, "(nextlen): HW hdr error: nextlen/len/check 0x%04x/0x%04x/0x%04x\n", | 1630 | brcmf_dbg(ERROR, "(nextlen): HW hdr error: nextlen/len/check 0x%04x/0x%04x/0x%04x\n", |
1632 | nextlen, *len, check); | 1631 | nextlen, *len, check); |
1633 | bus->rx_badhdr++; | 1632 | bus->sdcnt.rx_badhdr++; |
1634 | brcmf_sdbrcm_rxfail(bus, false, false); | 1633 | brcmf_sdbrcm_rxfail(bus, false, false); |
1635 | goto fail; | 1634 | goto fail; |
1636 | } | 1635 | } |
@@ -1746,7 +1745,7 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished) | |||
1746 | bus->nextlen = 0; | 1745 | bus->nextlen = 0; |
1747 | } | 1746 | } |
1748 | 1747 | ||
1749 | bus->rx_readahead_cnt++; | 1748 | bus->sdcnt.rx_readahead_cnt++; |
1750 | 1749 | ||
1751 | /* Handle Flow Control */ | 1750 | /* Handle Flow Control */ |
1752 | fcbits = SDPCM_FCMASK_VALUE( | 1751 | fcbits = SDPCM_FCMASK_VALUE( |
@@ -1754,12 +1753,12 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished) | |||
1754 | 1753 | ||
1755 | if (bus->flowcontrol != fcbits) { | 1754 | if (bus->flowcontrol != fcbits) { |
1756 | if (~bus->flowcontrol & fcbits) | 1755 | if (~bus->flowcontrol & fcbits) |
1757 | bus->fc_xoff++; | 1756 | bus->sdcnt.fc_xoff++; |
1758 | 1757 | ||
1759 | if (bus->flowcontrol & ~fcbits) | 1758 | if (bus->flowcontrol & ~fcbits) |
1760 | bus->fc_xon++; | 1759 | bus->sdcnt.fc_xon++; |
1761 | 1760 | ||
1762 | bus->fc_rcvd++; | 1761 | bus->sdcnt.fc_rcvd++; |
1763 | bus->flowcontrol = fcbits; | 1762 | bus->flowcontrol = fcbits; |
1764 | } | 1763 | } |
1765 | 1764 | ||
@@ -1767,7 +1766,7 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished) | |||
1767 | if (rxseq != seq) { | 1766 | if (rxseq != seq) { |
1768 | brcmf_dbg(INFO, "(nextlen): rx_seq %d, expected %d\n", | 1767 | brcmf_dbg(INFO, "(nextlen): rx_seq %d, expected %d\n", |
1769 | seq, rxseq); | 1768 | seq, rxseq); |
1770 | bus->rx_badseq++; | 1769 | bus->sdcnt.rx_badseq++; |
1771 | rxseq = seq; | 1770 | rxseq = seq; |
1772 | } | 1771 | } |
1773 | 1772 | ||
@@ -1814,11 +1813,11 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished) | |||
1814 | sdret = brcmf_sdcard_recv_buf(bus->sdiodev, bus->sdiodev->sbwad, | 1813 | sdret = brcmf_sdcard_recv_buf(bus->sdiodev, bus->sdiodev->sbwad, |
1815 | SDIO_FUNC_2, F2SYNC, bus->rxhdr, | 1814 | SDIO_FUNC_2, F2SYNC, bus->rxhdr, |
1816 | BRCMF_FIRSTREAD); | 1815 | BRCMF_FIRSTREAD); |
1817 | bus->f2rxhdrs++; | 1816 | bus->sdcnt.f2rxhdrs++; |
1818 | 1817 | ||
1819 | if (sdret < 0) { | 1818 | if (sdret < 0) { |
1820 | brcmf_dbg(ERROR, "RXHEADER FAILED: %d\n", sdret); | 1819 | brcmf_dbg(ERROR, "RXHEADER FAILED: %d\n", sdret); |
1821 | bus->rx_hdrfail++; | 1820 | bus->sdcnt.rx_hdrfail++; |
1822 | brcmf_sdbrcm_rxfail(bus, true, true); | 1821 | brcmf_sdbrcm_rxfail(bus, true, true); |
1823 | continue; | 1822 | continue; |
1824 | } | 1823 | } |
@@ -1840,7 +1839,7 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished) | |||
1840 | if ((u16) ~(len ^ check)) { | 1839 | if ((u16) ~(len ^ check)) { |
1841 | brcmf_dbg(ERROR, "HW hdr err: len/check 0x%04x/0x%04x\n", | 1840 | brcmf_dbg(ERROR, "HW hdr err: len/check 0x%04x/0x%04x\n", |
1842 | len, check); | 1841 | len, check); |
1843 | bus->rx_badhdr++; | 1842 | bus->sdcnt.rx_badhdr++; |
1844 | brcmf_sdbrcm_rxfail(bus, false, false); | 1843 | brcmf_sdbrcm_rxfail(bus, false, false); |
1845 | continue; | 1844 | continue; |
1846 | } | 1845 | } |
@@ -1861,7 +1860,7 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished) | |||
1861 | if ((doff < SDPCM_HDRLEN) || (doff > len)) { | 1860 | if ((doff < SDPCM_HDRLEN) || (doff > len)) { |
1862 | brcmf_dbg(ERROR, "Bad data offset %d: HW len %d, min %d seq %d\n", | 1861 | brcmf_dbg(ERROR, "Bad data offset %d: HW len %d, min %d seq %d\n", |
1863 | doff, len, SDPCM_HDRLEN, seq); | 1862 | doff, len, SDPCM_HDRLEN, seq); |
1864 | bus->rx_badhdr++; | 1863 | bus->sdcnt.rx_badhdr++; |
1865 | brcmf_sdbrcm_rxfail(bus, false, false); | 1864 | brcmf_sdbrcm_rxfail(bus, false, false); |
1866 | continue; | 1865 | continue; |
1867 | } | 1866 | } |
@@ -1880,19 +1879,19 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished) | |||
1880 | 1879 | ||
1881 | if (bus->flowcontrol != fcbits) { | 1880 | if (bus->flowcontrol != fcbits) { |
1882 | if (~bus->flowcontrol & fcbits) | 1881 | if (~bus->flowcontrol & fcbits) |
1883 | bus->fc_xoff++; | 1882 | bus->sdcnt.fc_xoff++; |
1884 | 1883 | ||
1885 | if (bus->flowcontrol & ~fcbits) | 1884 | if (bus->flowcontrol & ~fcbits) |
1886 | bus->fc_xon++; | 1885 | bus->sdcnt.fc_xon++; |
1887 | 1886 | ||
1888 | bus->fc_rcvd++; | 1887 | bus->sdcnt.fc_rcvd++; |
1889 | bus->flowcontrol = fcbits; | 1888 | bus->flowcontrol = fcbits; |
1890 | } | 1889 | } |
1891 | 1890 | ||
1892 | /* Check and update sequence number */ | 1891 | /* Check and update sequence number */ |
1893 | if (rxseq != seq) { | 1892 | if (rxseq != seq) { |
1894 | brcmf_dbg(INFO, "rx_seq %d, expected %d\n", seq, rxseq); | 1893 | brcmf_dbg(INFO, "rx_seq %d, expected %d\n", seq, rxseq); |
1895 | bus->rx_badseq++; | 1894 | bus->sdcnt.rx_badseq++; |
1896 | rxseq = seq; | 1895 | rxseq = seq; |
1897 | } | 1896 | } |
1898 | 1897 | ||
@@ -1937,7 +1936,7 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished) | |||
1937 | brcmf_dbg(ERROR, "too long: len %d rdlen %d\n", | 1936 | brcmf_dbg(ERROR, "too long: len %d rdlen %d\n", |
1938 | len, rdlen); | 1937 | len, rdlen); |
1939 | bus->sdiodev->bus_if->dstats.rx_errors++; | 1938 | bus->sdiodev->bus_if->dstats.rx_errors++; |
1940 | bus->rx_toolong++; | 1939 | bus->sdcnt.rx_toolong++; |
1941 | brcmf_sdbrcm_rxfail(bus, false, false); | 1940 | brcmf_sdbrcm_rxfail(bus, false, false); |
1942 | continue; | 1941 | continue; |
1943 | } | 1942 | } |
@@ -1960,7 +1959,7 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished) | |||
1960 | /* Read the remaining frame data */ | 1959 | /* Read the remaining frame data */ |
1961 | sdret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad, | 1960 | sdret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad, |
1962 | SDIO_FUNC_2, F2SYNC, pkt); | 1961 | SDIO_FUNC_2, F2SYNC, pkt); |
1963 | bus->f2rxdata++; | 1962 | bus->sdcnt.f2rxdata++; |
1964 | 1963 | ||
1965 | if (sdret < 0) { | 1964 | if (sdret < 0) { |
1966 | brcmf_dbg(ERROR, "read %d %s bytes failed: %d\n", rdlen, | 1965 | brcmf_dbg(ERROR, "read %d %s bytes failed: %d\n", rdlen, |
@@ -2147,18 +2146,18 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt, | |||
2147 | 2146 | ||
2148 | ret = brcmf_sdcard_send_pkt(bus->sdiodev, bus->sdiodev->sbwad, | 2147 | ret = brcmf_sdcard_send_pkt(bus->sdiodev, bus->sdiodev->sbwad, |
2149 | SDIO_FUNC_2, F2SYNC, pkt); | 2148 | SDIO_FUNC_2, F2SYNC, pkt); |
2150 | bus->f2txdata++; | 2149 | bus->sdcnt.f2txdata++; |
2151 | 2150 | ||
2152 | if (ret < 0) { | 2151 | if (ret < 0) { |
2153 | /* On failure, abort the command and terminate the frame */ | 2152 | /* On failure, abort the command and terminate the frame */ |
2154 | brcmf_dbg(INFO, "sdio error %d, abort command and terminate frame\n", | 2153 | brcmf_dbg(INFO, "sdio error %d, abort command and terminate frame\n", |
2155 | ret); | 2154 | ret); |
2156 | bus->tx_sderrs++; | 2155 | bus->sdcnt.tx_sderrs++; |
2157 | 2156 | ||
2158 | brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); | 2157 | brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); |
2159 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL, | 2158 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL, |
2160 | SFC_WF_TERM, NULL); | 2159 | SFC_WF_TERM, NULL); |
2161 | bus->f1regdata++; | 2160 | bus->sdcnt.f1regdata++; |
2162 | 2161 | ||
2163 | for (i = 0; i < 3; i++) { | 2162 | for (i = 0; i < 3; i++) { |
2164 | u8 hi, lo; | 2163 | u8 hi, lo; |
@@ -2166,7 +2165,7 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt, | |||
2166 | SBSDIO_FUNC1_WFRAMEBCHI, NULL); | 2165 | SBSDIO_FUNC1_WFRAMEBCHI, NULL); |
2167 | lo = brcmf_sdio_regrb(bus->sdiodev, | 2166 | lo = brcmf_sdio_regrb(bus->sdiodev, |
2168 | SBSDIO_FUNC1_WFRAMEBCLO, NULL); | 2167 | SBSDIO_FUNC1_WFRAMEBCLO, NULL); |
2169 | bus->f1regdata += 2; | 2168 | bus->sdcnt.f1regdata += 2; |
2170 | if ((hi == 0) && (lo == 0)) | 2169 | if ((hi == 0) && (lo == 0)) |
2171 | break; | 2170 | break; |
2172 | } | 2171 | } |
@@ -2224,7 +2223,7 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes) | |||
2224 | ret = r_sdreg32(bus, &intstatus, | 2223 | ret = r_sdreg32(bus, &intstatus, |
2225 | offsetof(struct sdpcmd_regs, | 2224 | offsetof(struct sdpcmd_regs, |
2226 | intstatus)); | 2225 | intstatus)); |
2227 | bus->f2txdata++; | 2226 | bus->sdcnt.f2txdata++; |
2228 | if (ret != 0) | 2227 | if (ret != 0) |
2229 | break; | 2228 | break; |
2230 | if (intstatus & bus->hostintmask) | 2229 | if (intstatus & bus->hostintmask) |
@@ -2417,7 +2416,7 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
2417 | bus->ipend = false; | 2416 | bus->ipend = false; |
2418 | err = r_sdreg32(bus, &newstatus, | 2417 | err = r_sdreg32(bus, &newstatus, |
2419 | offsetof(struct sdpcmd_regs, intstatus)); | 2418 | offsetof(struct sdpcmd_regs, intstatus)); |
2420 | bus->f1regdata++; | 2419 | bus->sdcnt.f1regdata++; |
2421 | if (err != 0) | 2420 | if (err != 0) |
2422 | newstatus = 0; | 2421 | newstatus = 0; |
2423 | newstatus &= bus->hostintmask; | 2422 | newstatus &= bus->hostintmask; |
@@ -2426,7 +2425,7 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
2426 | err = w_sdreg32(bus, newstatus, | 2425 | err = w_sdreg32(bus, newstatus, |
2427 | offsetof(struct sdpcmd_regs, | 2426 | offsetof(struct sdpcmd_regs, |
2428 | intstatus)); | 2427 | intstatus)); |
2429 | bus->f1regdata++; | 2428 | bus->sdcnt.f1regdata++; |
2430 | } | 2429 | } |
2431 | } | 2430 | } |
2432 | 2431 | ||
@@ -2445,7 +2444,7 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
2445 | 2444 | ||
2446 | err = r_sdreg32(bus, &newstatus, | 2445 | err = r_sdreg32(bus, &newstatus, |
2447 | offsetof(struct sdpcmd_regs, intstatus)); | 2446 | offsetof(struct sdpcmd_regs, intstatus)); |
2448 | bus->f1regdata += 2; | 2447 | bus->sdcnt.f1regdata += 2; |
2449 | bus->fcstate = | 2448 | bus->fcstate = |
2450 | !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE)); | 2449 | !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE)); |
2451 | intstatus |= (newstatus & bus->hostintmask); | 2450 | intstatus |= (newstatus & bus->hostintmask); |
@@ -2510,13 +2509,13 @@ clkwait: | |||
2510 | terminate the frame */ | 2509 | terminate the frame */ |
2511 | brcmf_dbg(INFO, "sdio error %d, abort command and terminate frame\n", | 2510 | brcmf_dbg(INFO, "sdio error %d, abort command and terminate frame\n", |
2512 | ret); | 2511 | ret); |
2513 | bus->tx_sderrs++; | 2512 | bus->sdcnt.tx_sderrs++; |
2514 | 2513 | ||
2515 | brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); | 2514 | brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); |
2516 | 2515 | ||
2517 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL, | 2516 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL, |
2518 | SFC_WF_TERM, &err); | 2517 | SFC_WF_TERM, &err); |
2519 | bus->f1regdata++; | 2518 | bus->sdcnt.f1regdata++; |
2520 | 2519 | ||
2521 | for (i = 0; i < 3; i++) { | 2520 | for (i = 0; i < 3; i++) { |
2522 | u8 hi, lo; | 2521 | u8 hi, lo; |
@@ -2526,7 +2525,7 @@ clkwait: | |||
2526 | lo = brcmf_sdio_regrb(bus->sdiodev, | 2525 | lo = brcmf_sdio_regrb(bus->sdiodev, |
2527 | SBSDIO_FUNC1_WFRAMEBCLO, | 2526 | SBSDIO_FUNC1_WFRAMEBCLO, |
2528 | &err); | 2527 | &err); |
2529 | bus->f1regdata += 2; | 2528 | bus->sdcnt.f1regdata += 2; |
2530 | if ((hi == 0) && (lo == 0)) | 2529 | if ((hi == 0) && (lo == 0)) |
2531 | break; | 2530 | break; |
2532 | } | 2531 | } |
@@ -2657,7 +2656,7 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt) | |||
2657 | /* Check for existing queue, current flow-control, | 2656 | /* Check for existing queue, current flow-control, |
2658 | pending event, or pending clock */ | 2657 | pending event, or pending clock */ |
2659 | brcmf_dbg(TRACE, "deferring pktq len %d\n", pktq_len(&bus->txq)); | 2658 | brcmf_dbg(TRACE, "deferring pktq len %d\n", pktq_len(&bus->txq)); |
2660 | bus->fcqueued++; | 2659 | bus->sdcnt.fcqueued++; |
2661 | 2660 | ||
2662 | /* Priority based enq */ | 2661 | /* Priority based enq */ |
2663 | spin_lock_bh(&bus->txqlock); | 2662 | spin_lock_bh(&bus->txqlock); |
@@ -2845,13 +2844,13 @@ static int brcmf_tx_frame(struct brcmf_sdio *bus, u8 *frame, u16 len) | |||
2845 | /* On failure, abort the command and terminate the frame */ | 2844 | /* On failure, abort the command and terminate the frame */ |
2846 | brcmf_dbg(INFO, "sdio error %d, abort command and terminate frame\n", | 2845 | brcmf_dbg(INFO, "sdio error %d, abort command and terminate frame\n", |
2847 | ret); | 2846 | ret); |
2848 | bus->tx_sderrs++; | 2847 | bus->sdcnt.tx_sderrs++; |
2849 | 2848 | ||
2850 | brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); | 2849 | brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); |
2851 | 2850 | ||
2852 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL, | 2851 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL, |
2853 | SFC_WF_TERM, NULL); | 2852 | SFC_WF_TERM, NULL); |
2854 | bus->f1regdata++; | 2853 | bus->sdcnt.f1regdata++; |
2855 | 2854 | ||
2856 | for (i = 0; i < 3; i++) { | 2855 | for (i = 0; i < 3; i++) { |
2857 | u8 hi, lo; | 2856 | u8 hi, lo; |
@@ -2859,7 +2858,7 @@ static int brcmf_tx_frame(struct brcmf_sdio *bus, u8 *frame, u16 len) | |||
2859 | SBSDIO_FUNC1_WFRAMEBCHI, NULL); | 2858 | SBSDIO_FUNC1_WFRAMEBCHI, NULL); |
2860 | lo = brcmf_sdio_regrb(bus->sdiodev, | 2859 | lo = brcmf_sdio_regrb(bus->sdiodev, |
2861 | SBSDIO_FUNC1_WFRAMEBCLO, NULL); | 2860 | SBSDIO_FUNC1_WFRAMEBCLO, NULL); |
2862 | bus->f1regdata += 2; | 2861 | bus->sdcnt.f1regdata += 2; |
2863 | if (hi == 0 && lo == 0) | 2862 | if (hi == 0 && lo == 0) |
2864 | break; | 2863 | break; |
2865 | } | 2864 | } |
@@ -2976,13 +2975,324 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) | |||
2976 | up(&bus->sdsem); | 2975 | up(&bus->sdsem); |
2977 | 2976 | ||
2978 | if (ret) | 2977 | if (ret) |
2979 | bus->tx_ctlerrs++; | 2978 | bus->sdcnt.tx_ctlerrs++; |
2980 | else | 2979 | else |
2981 | bus->tx_ctlpkts++; | 2980 | bus->sdcnt.tx_ctlpkts++; |
2982 | 2981 | ||
2983 | return ret ? -EIO : 0; | 2982 | return ret ? -EIO : 0; |
2984 | } | 2983 | } |
2985 | 2984 | ||
2985 | #ifdef DEBUG | ||
2986 | static inline bool brcmf_sdio_valid_shared_address(u32 addr) | ||
2987 | { | ||
2988 | return !(addr == 0 || ((~addr >> 16) & 0xffff) == (addr & 0xffff)); | ||
2989 | } | ||
2990 | |||
2991 | static int brcmf_sdio_readshared(struct brcmf_sdio *bus, | ||
2992 | struct sdpcm_shared *sh) | ||
2993 | { | ||
2994 | u32 addr; | ||
2995 | int rv; | ||
2996 | u32 shaddr = 0; | ||
2997 | struct sdpcm_shared_le sh_le; | ||
2998 | __le32 addr_le; | ||
2999 | |||
3000 | shaddr = bus->ramsize - 4; | ||
3001 | |||
3002 | /* | ||
3003 | * Read last word in socram to determine | ||
3004 | * address of sdpcm_shared structure | ||
3005 | */ | ||
3006 | rv = brcmf_sdbrcm_membytes(bus, false, shaddr, | ||
3007 | (u8 *)&addr_le, 4); | ||
3008 | if (rv < 0) | ||
3009 | return rv; | ||
3010 | |||
3011 | addr = le32_to_cpu(addr_le); | ||
3012 | |||
3013 | brcmf_dbg(INFO, "sdpcm_shared address 0x%08X\n", addr); | ||
3014 | |||
3015 | /* | ||
3016 | * Check if addr is valid. | ||
3017 | * NVRAM length at the end of memory should have been overwritten. | ||
3018 | */ | ||
3019 | if (!brcmf_sdio_valid_shared_address(addr)) { | ||
3020 | brcmf_dbg(ERROR, "invalid sdpcm_shared address 0x%08X\n", | ||
3021 | addr); | ||
3022 | return -EINVAL; | ||
3023 | } | ||
3024 | |||
3025 | /* Read hndrte_shared structure */ | ||
3026 | rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *)&sh_le, | ||
3027 | sizeof(struct sdpcm_shared_le)); | ||
3028 | if (rv < 0) | ||
3029 | return rv; | ||
3030 | |||
3031 | /* Endianness */ | ||
3032 | sh->flags = le32_to_cpu(sh_le.flags); | ||
3033 | sh->trap_addr = le32_to_cpu(sh_le.trap_addr); | ||
3034 | sh->assert_exp_addr = le32_to_cpu(sh_le.assert_exp_addr); | ||
3035 | sh->assert_file_addr = le32_to_cpu(sh_le.assert_file_addr); | ||
3036 | sh->assert_line = le32_to_cpu(sh_le.assert_line); | ||
3037 | sh->console_addr = le32_to_cpu(sh_le.console_addr); | ||
3038 | sh->msgtrace_addr = le32_to_cpu(sh_le.msgtrace_addr); | ||
3039 | |||
3040 | if ((sh->flags & SDPCM_SHARED_VERSION_MASK) != SDPCM_SHARED_VERSION) { | ||
3041 | brcmf_dbg(ERROR, | ||
3042 | "sdpcm_shared version mismatch: dhd %d dongle %d\n", | ||
3043 | SDPCM_SHARED_VERSION, | ||
3044 | sh->flags & SDPCM_SHARED_VERSION_MASK); | ||
3045 | return -EPROTO; | ||
3046 | } | ||
3047 | |||
3048 | return 0; | ||
3049 | } | ||
3050 | |||
3051 | static int brcmf_sdio_dump_console(struct brcmf_sdio *bus, | ||
3052 | struct sdpcm_shared *sh, char __user *data, | ||
3053 | size_t count) | ||
3054 | { | ||
3055 | u32 addr, console_ptr, console_size, console_index; | ||
3056 | char *conbuf = NULL; | ||
3057 | __le32 sh_val; | ||
3058 | int rv; | ||
3059 | loff_t pos = 0; | ||
3060 | int nbytes = 0; | ||
3061 | |||
3062 | /* obtain console information from device memory */ | ||
3063 | addr = sh->console_addr + offsetof(struct rte_console, log_le); | ||
3064 | rv = brcmf_sdbrcm_membytes(bus, false, addr, | ||
3065 | (u8 *)&sh_val, sizeof(u32)); | ||
3066 | if (rv < 0) | ||
3067 | return rv; | ||
3068 | console_ptr = le32_to_cpu(sh_val); | ||
3069 | |||
3070 | addr = sh->console_addr + offsetof(struct rte_console, log_le.buf_size); | ||
3071 | rv = brcmf_sdbrcm_membytes(bus, false, addr, | ||
3072 | (u8 *)&sh_val, sizeof(u32)); | ||
3073 | if (rv < 0) | ||
3074 | return rv; | ||
3075 | console_size = le32_to_cpu(sh_val); | ||
3076 | |||
3077 | addr = sh->console_addr + offsetof(struct rte_console, log_le.idx); | ||
3078 | rv = brcmf_sdbrcm_membytes(bus, false, addr, | ||
3079 | (u8 *)&sh_val, sizeof(u32)); | ||
3080 | if (rv < 0) | ||
3081 | return rv; | ||
3082 | console_index = le32_to_cpu(sh_val); | ||
3083 | |||
3084 | /* allocate buffer for console data */ | ||
3085 | if (console_size <= CONSOLE_BUFFER_MAX) | ||
3086 | conbuf = vzalloc(console_size+1); | ||
3087 | |||
3088 | if (!conbuf) | ||
3089 | return -ENOMEM; | ||
3090 | |||
3091 | /* obtain the console data from device */ | ||
3092 | conbuf[console_size] = '\0'; | ||
3093 | rv = brcmf_sdbrcm_membytes(bus, false, console_ptr, (u8 *)conbuf, | ||
3094 | console_size); | ||
3095 | if (rv < 0) | ||
3096 | goto done; | ||
3097 | |||
3098 | rv = simple_read_from_buffer(data, count, &pos, | ||
3099 | conbuf + console_index, | ||
3100 | console_size - console_index); | ||
3101 | if (rv < 0) | ||
3102 | goto done; | ||
3103 | |||
3104 | nbytes = rv; | ||
3105 | if (console_index > 0) { | ||
3106 | pos = 0; | ||
3107 | rv = simple_read_from_buffer(data+nbytes, count, &pos, | ||
3108 | conbuf, console_index - 1); | ||
3109 | if (rv < 0) | ||
3110 | goto done; | ||
3111 | rv += nbytes; | ||
3112 | } | ||
3113 | done: | ||
3114 | vfree(conbuf); | ||
3115 | return rv; | ||
3116 | } | ||
3117 | |||
3118 | static int brcmf_sdio_trap_info(struct brcmf_sdio *bus, struct sdpcm_shared *sh, | ||
3119 | char __user *data, size_t count) | ||
3120 | { | ||
3121 | int error, res; | ||
3122 | char buf[350]; | ||
3123 | struct brcmf_trap_info tr; | ||
3124 | int nbytes; | ||
3125 | loff_t pos = 0; | ||
3126 | |||
3127 | if ((sh->flags & SDPCM_SHARED_TRAP) == 0) | ||
3128 | return 0; | ||
3129 | |||
3130 | error = brcmf_sdbrcm_membytes(bus, false, sh->trap_addr, (u8 *)&tr, | ||
3131 | sizeof(struct brcmf_trap_info)); | ||
3132 | if (error < 0) | ||
3133 | return error; | ||
3134 | |||
3135 | nbytes = brcmf_sdio_dump_console(bus, sh, data, count); | ||
3136 | if (nbytes < 0) | ||
3137 | return nbytes; | ||
3138 | |||
3139 | res = scnprintf(buf, sizeof(buf), | ||
3140 | "dongle trap info: type 0x%x @ epc 0x%08x\n" | ||
3141 | " cpsr 0x%08x spsr 0x%08x sp 0x%08x\n" | ||
3142 | " lr 0x%08x pc 0x%08x offset 0x%x\n" | ||
3143 | " r0 0x%08x r1 0x%08x r2 0x%08x r3 0x%08x\n" | ||
3144 | " r4 0x%08x r5 0x%08x r6 0x%08x r7 0x%08x\n", | ||
3145 | le32_to_cpu(tr.type), le32_to_cpu(tr.epc), | ||
3146 | le32_to_cpu(tr.cpsr), le32_to_cpu(tr.spsr), | ||
3147 | le32_to_cpu(tr.r13), le32_to_cpu(tr.r14), | ||
3148 | le32_to_cpu(tr.pc), sh->trap_addr, | ||
3149 | le32_to_cpu(tr.r0), le32_to_cpu(tr.r1), | ||
3150 | le32_to_cpu(tr.r2), le32_to_cpu(tr.r3), | ||
3151 | le32_to_cpu(tr.r4), le32_to_cpu(tr.r5), | ||
3152 | le32_to_cpu(tr.r6), le32_to_cpu(tr.r7)); | ||
3153 | |||
3154 | error = simple_read_from_buffer(data+nbytes, count, &pos, buf, res); | ||
3155 | if (error < 0) | ||
3156 | return error; | ||
3157 | |||
3158 | nbytes += error; | ||
3159 | return nbytes; | ||
3160 | } | ||
3161 | |||
3162 | static int brcmf_sdio_assert_info(struct brcmf_sdio *bus, | ||
3163 | struct sdpcm_shared *sh, char __user *data, | ||
3164 | size_t count) | ||
3165 | { | ||
3166 | int error = 0; | ||
3167 | char buf[200]; | ||
3168 | char file[80] = "?"; | ||
3169 | char expr[80] = "<???>"; | ||
3170 | int res; | ||
3171 | loff_t pos = 0; | ||
3172 | |||
3173 | if ((sh->flags & SDPCM_SHARED_ASSERT_BUILT) == 0) { | ||
3174 | brcmf_dbg(INFO, "firmware not built with -assert\n"); | ||
3175 | return 0; | ||
3176 | } else if ((sh->flags & SDPCM_SHARED_ASSERT) == 0) { | ||
3177 | brcmf_dbg(INFO, "no assert in dongle\n"); | ||
3178 | return 0; | ||
3179 | } | ||
3180 | |||
3181 | if (sh->assert_file_addr != 0) { | ||
3182 | error = brcmf_sdbrcm_membytes(bus, false, sh->assert_file_addr, | ||
3183 | (u8 *)file, 80); | ||
3184 | if (error < 0) | ||
3185 | return error; | ||
3186 | } | ||
3187 | if (sh->assert_exp_addr != 0) { | ||
3188 | error = brcmf_sdbrcm_membytes(bus, false, sh->assert_exp_addr, | ||
3189 | (u8 *)expr, 80); | ||
3190 | if (error < 0) | ||
3191 | return error; | ||
3192 | } | ||
3193 | |||
3194 | res = scnprintf(buf, sizeof(buf), | ||
3195 | "dongle assert: %s:%d: assert(%s)\n", | ||
3196 | file, sh->assert_line, expr); | ||
3197 | return simple_read_from_buffer(data, count, &pos, buf, res); | ||
3198 | } | ||
3199 | |||
3200 | static int brcmf_sdbrcm_checkdied(struct brcmf_sdio *bus) | ||
3201 | { | ||
3202 | int error; | ||
3203 | struct sdpcm_shared sh; | ||
3204 | |||
3205 | down(&bus->sdsem); | ||
3206 | error = brcmf_sdio_readshared(bus, &sh); | ||
3207 | up(&bus->sdsem); | ||
3208 | |||
3209 | if (error < 0) | ||
3210 | return error; | ||
3211 | |||
3212 | if ((sh.flags & SDPCM_SHARED_ASSERT_BUILT) == 0) | ||
3213 | brcmf_dbg(INFO, "firmware not built with -assert\n"); | ||
3214 | else if (sh.flags & SDPCM_SHARED_ASSERT) | ||
3215 | brcmf_dbg(ERROR, "assertion in dongle\n"); | ||
3216 | |||
3217 | if (sh.flags & SDPCM_SHARED_TRAP) | ||
3218 | brcmf_dbg(ERROR, "firmware trap in dongle\n"); | ||
3219 | |||
3220 | return 0; | ||
3221 | } | ||
3222 | |||
3223 | static int brcmf_sdbrcm_died_dump(struct brcmf_sdio *bus, char __user *data, | ||
3224 | size_t count, loff_t *ppos) | ||
3225 | { | ||
3226 | int error = 0; | ||
3227 | struct sdpcm_shared sh; | ||
3228 | int nbytes = 0; | ||
3229 | loff_t pos = *ppos; | ||
3230 | |||
3231 | if (pos != 0) | ||
3232 | return 0; | ||
3233 | |||
3234 | down(&bus->sdsem); | ||
3235 | error = brcmf_sdio_readshared(bus, &sh); | ||
3236 | if (error < 0) | ||
3237 | goto done; | ||
3238 | |||
3239 | error = brcmf_sdio_assert_info(bus, &sh, data, count); | ||
3240 | if (error < 0) | ||
3241 | goto done; | ||
3242 | |||
3243 | nbytes = error; | ||
3244 | error = brcmf_sdio_trap_info(bus, &sh, data, count); | ||
3245 | if (error < 0) | ||
3246 | goto done; | ||
3247 | |||
3248 | error += nbytes; | ||
3249 | *ppos += error; | ||
3250 | done: | ||
3251 | up(&bus->sdsem); | ||
3252 | return error; | ||
3253 | } | ||
3254 | |||
3255 | static ssize_t brcmf_sdio_forensic_read(struct file *f, char __user *data, | ||
3256 | size_t count, loff_t *ppos) | ||
3257 | { | ||
3258 | struct brcmf_sdio *bus = f->private_data; | ||
3259 | int res; | ||
3260 | |||
3261 | res = brcmf_sdbrcm_died_dump(bus, data, count, ppos); | ||
3262 | if (res > 0) | ||
3263 | *ppos += res; | ||
3264 | return (ssize_t)res; | ||
3265 | } | ||
3266 | |||
3267 | static const struct file_operations brcmf_sdio_forensic_ops = { | ||
3268 | .owner = THIS_MODULE, | ||
3269 | .open = simple_open, | ||
3270 | .read = brcmf_sdio_forensic_read | ||
3271 | }; | ||
3272 | |||
3273 | static void brcmf_sdio_debugfs_create(struct brcmf_sdio *bus) | ||
3274 | { | ||
3275 | struct brcmf_pub *drvr = bus->sdiodev->bus_if->drvr; | ||
3276 | struct dentry *dentry = brcmf_debugfs_get_devdir(drvr); | ||
3277 | |||
3278 | if (IS_ERR_OR_NULL(dentry)) | ||
3279 | return; | ||
3280 | |||
3281 | debugfs_create_file("forensics", S_IRUGO, dentry, bus, | ||
3282 | &brcmf_sdio_forensic_ops); | ||
3283 | brcmf_debugfs_create_sdio_count(drvr, &bus->sdcnt); | ||
3284 | } | ||
3285 | #else | ||
3286 | static int brcmf_sdbrcm_checkdied(struct brcmf_sdio *bus) | ||
3287 | { | ||
3288 | return 0; | ||
3289 | } | ||
3290 | |||
3291 | static void brcmf_sdio_debugfs_create(struct brcmf_sdio *bus) | ||
3292 | { | ||
3293 | } | ||
3294 | #endif /* DEBUG */ | ||
3295 | |||
2986 | static int | 3296 | static int |
2987 | brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen) | 3297 | brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen) |
2988 | { | 3298 | { |
@@ -3009,60 +3319,27 @@ brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen) | |||
3009 | rxlen, msglen); | 3319 | rxlen, msglen); |
3010 | } else if (timeleft == 0) { | 3320 | } else if (timeleft == 0) { |
3011 | brcmf_dbg(ERROR, "resumed on timeout\n"); | 3321 | brcmf_dbg(ERROR, "resumed on timeout\n"); |
3322 | brcmf_sdbrcm_checkdied(bus); | ||
3012 | } else if (pending) { | 3323 | } else if (pending) { |
3013 | brcmf_dbg(CTL, "cancelled\n"); | 3324 | brcmf_dbg(CTL, "cancelled\n"); |
3014 | return -ERESTARTSYS; | 3325 | return -ERESTARTSYS; |
3015 | } else { | 3326 | } else { |
3016 | brcmf_dbg(CTL, "resumed for unknown reason?\n"); | 3327 | brcmf_dbg(CTL, "resumed for unknown reason?\n"); |
3328 | brcmf_sdbrcm_checkdied(bus); | ||
3017 | } | 3329 | } |
3018 | 3330 | ||
3019 | if (rxlen) | 3331 | if (rxlen) |
3020 | bus->rx_ctlpkts++; | 3332 | bus->sdcnt.rx_ctlpkts++; |
3021 | else | 3333 | else |
3022 | bus->rx_ctlerrs++; | 3334 | bus->sdcnt.rx_ctlerrs++; |
3023 | 3335 | ||
3024 | return rxlen ? (int)rxlen : -ETIMEDOUT; | 3336 | return rxlen ? (int)rxlen : -ETIMEDOUT; |
3025 | } | 3337 | } |
3026 | 3338 | ||
3027 | static int brcmf_sdbrcm_downloadvars(struct brcmf_sdio *bus, void *arg, int len) | ||
3028 | { | ||
3029 | int bcmerror = 0; | ||
3030 | |||
3031 | brcmf_dbg(TRACE, "Enter\n"); | ||
3032 | |||
3033 | /* Basic sanity checks */ | ||
3034 | if (bus->sdiodev->bus_if->drvr_up) { | ||
3035 | bcmerror = -EISCONN; | ||
3036 | goto err; | ||
3037 | } | ||
3038 | if (!len) { | ||
3039 | bcmerror = -EOVERFLOW; | ||
3040 | goto err; | ||
3041 | } | ||
3042 | |||
3043 | /* Free the old ones and replace with passed variables */ | ||
3044 | kfree(bus->vars); | ||
3045 | |||
3046 | bus->vars = kmalloc(len, GFP_ATOMIC); | ||
3047 | bus->varsz = bus->vars ? len : 0; | ||
3048 | if (bus->vars == NULL) { | ||
3049 | bcmerror = -ENOMEM; | ||
3050 | goto err; | ||
3051 | } | ||
3052 | |||
3053 | /* Copy the passed variables, which should include the | ||
3054 | terminating double-null */ | ||
3055 | memcpy(bus->vars, arg, bus->varsz); | ||
3056 | err: | ||
3057 | return bcmerror; | ||
3058 | } | ||
3059 | |||
3060 | static int brcmf_sdbrcm_write_vars(struct brcmf_sdio *bus) | 3339 | static int brcmf_sdbrcm_write_vars(struct brcmf_sdio *bus) |
3061 | { | 3340 | { |
3062 | int bcmerror = 0; | 3341 | int bcmerror = 0; |
3063 | u32 varsize; | ||
3064 | u32 varaddr; | 3342 | u32 varaddr; |
3065 | u8 *vbuffer; | ||
3066 | u32 varsizew; | 3343 | u32 varsizew; |
3067 | __le32 varsizew_le; | 3344 | __le32 varsizew_le; |
3068 | #ifdef DEBUG | 3345 | #ifdef DEBUG |
@@ -3071,56 +3348,44 @@ static int brcmf_sdbrcm_write_vars(struct brcmf_sdio *bus) | |||
3071 | 3348 | ||
3072 | /* Even if there are no vars are to be written, we still | 3349 | /* Even if there are no vars are to be written, we still |
3073 | need to set the ramsize. */ | 3350 | need to set the ramsize. */ |
3074 | varsize = bus->varsz ? roundup(bus->varsz, 4) : 0; | 3351 | varaddr = (bus->ramsize - 4) - bus->varsz; |
3075 | varaddr = (bus->ramsize - 4) - varsize; | ||
3076 | 3352 | ||
3077 | if (bus->vars) { | 3353 | if (bus->vars) { |
3078 | vbuffer = kzalloc(varsize, GFP_ATOMIC); | ||
3079 | if (!vbuffer) | ||
3080 | return -ENOMEM; | ||
3081 | |||
3082 | memcpy(vbuffer, bus->vars, bus->varsz); | ||
3083 | |||
3084 | /* Write the vars list */ | 3354 | /* Write the vars list */ |
3085 | bcmerror = | 3355 | bcmerror = brcmf_sdbrcm_membytes(bus, true, varaddr, |
3086 | brcmf_sdbrcm_membytes(bus, true, varaddr, vbuffer, varsize); | 3356 | bus->vars, bus->varsz); |
3087 | #ifdef DEBUG | 3357 | #ifdef DEBUG |
3088 | /* Verify NVRAM bytes */ | 3358 | /* Verify NVRAM bytes */ |
3089 | brcmf_dbg(INFO, "Compare NVRAM dl & ul; varsize=%d\n", varsize); | 3359 | brcmf_dbg(INFO, "Compare NVRAM dl & ul; varsize=%d\n", |
3090 | nvram_ularray = kmalloc(varsize, GFP_ATOMIC); | 3360 | bus->varsz); |
3091 | if (!nvram_ularray) { | 3361 | nvram_ularray = kmalloc(bus->varsz, GFP_ATOMIC); |
3092 | kfree(vbuffer); | 3362 | if (!nvram_ularray) |
3093 | return -ENOMEM; | 3363 | return -ENOMEM; |
3094 | } | ||
3095 | 3364 | ||
3096 | /* Upload image to verify downloaded contents. */ | 3365 | /* Upload image to verify downloaded contents. */ |
3097 | memset(nvram_ularray, 0xaa, varsize); | 3366 | memset(nvram_ularray, 0xaa, bus->varsz); |
3098 | 3367 | ||
3099 | /* Read the vars list to temp buffer for comparison */ | 3368 | /* Read the vars list to temp buffer for comparison */ |
3100 | bcmerror = | 3369 | bcmerror = brcmf_sdbrcm_membytes(bus, false, varaddr, |
3101 | brcmf_sdbrcm_membytes(bus, false, varaddr, nvram_ularray, | 3370 | nvram_ularray, bus->varsz); |
3102 | varsize); | ||
3103 | if (bcmerror) { | 3371 | if (bcmerror) { |
3104 | brcmf_dbg(ERROR, "error %d on reading %d nvram bytes at 0x%08x\n", | 3372 | brcmf_dbg(ERROR, "error %d on reading %d nvram bytes at 0x%08x\n", |
3105 | bcmerror, varsize, varaddr); | 3373 | bcmerror, bus->varsz, varaddr); |
3106 | } | 3374 | } |
3107 | /* Compare the org NVRAM with the one read from RAM */ | 3375 | /* Compare the org NVRAM with the one read from RAM */ |
3108 | if (memcmp(vbuffer, nvram_ularray, varsize)) | 3376 | if (memcmp(bus->vars, nvram_ularray, bus->varsz)) |
3109 | brcmf_dbg(ERROR, "Downloaded NVRAM image is corrupted\n"); | 3377 | brcmf_dbg(ERROR, "Downloaded NVRAM image is corrupted\n"); |
3110 | else | 3378 | else |
3111 | brcmf_dbg(ERROR, "Download/Upload/Compare of NVRAM ok\n"); | 3379 | brcmf_dbg(ERROR, "Download/Upload/Compare of NVRAM ok\n"); |
3112 | 3380 | ||
3113 | kfree(nvram_ularray); | 3381 | kfree(nvram_ularray); |
3114 | #endif /* DEBUG */ | 3382 | #endif /* DEBUG */ |
3115 | |||
3116 | kfree(vbuffer); | ||
3117 | } | 3383 | } |
3118 | 3384 | ||
3119 | /* adjust to the user specified RAM */ | 3385 | /* adjust to the user specified RAM */ |
3120 | brcmf_dbg(INFO, "Physical memory size: %d\n", bus->ramsize); | 3386 | brcmf_dbg(INFO, "Physical memory size: %d\n", bus->ramsize); |
3121 | brcmf_dbg(INFO, "Vars are at %d, orig varsize is %d\n", | 3387 | brcmf_dbg(INFO, "Vars are at %d, orig varsize is %d\n", |
3122 | varaddr, varsize); | 3388 | varaddr, bus->varsz); |
3123 | varsize = ((bus->ramsize - 4) - varaddr); | ||
3124 | 3389 | ||
3125 | /* | 3390 | /* |
3126 | * Determine the length token: | 3391 | * Determine the length token: |
@@ -3131,13 +3396,13 @@ static int brcmf_sdbrcm_write_vars(struct brcmf_sdio *bus) | |||
3131 | varsizew = 0; | 3396 | varsizew = 0; |
3132 | varsizew_le = cpu_to_le32(0); | 3397 | varsizew_le = cpu_to_le32(0); |
3133 | } else { | 3398 | } else { |
3134 | varsizew = varsize / 4; | 3399 | varsizew = bus->varsz / 4; |
3135 | varsizew = (~varsizew << 16) | (varsizew & 0x0000FFFF); | 3400 | varsizew = (~varsizew << 16) | (varsizew & 0x0000FFFF); |
3136 | varsizew_le = cpu_to_le32(varsizew); | 3401 | varsizew_le = cpu_to_le32(varsizew); |
3137 | } | 3402 | } |
3138 | 3403 | ||
3139 | brcmf_dbg(INFO, "New varsize is %d, length token=0x%08x\n", | 3404 | brcmf_dbg(INFO, "New varsize is %d, length token=0x%08x\n", |
3140 | varsize, varsizew); | 3405 | bus->varsz, varsizew); |
3141 | 3406 | ||
3142 | /* Write the length token to the last word */ | 3407 | /* Write the length token to the last word */ |
3143 | bcmerror = brcmf_sdbrcm_membytes(bus, true, (bus->ramsize - 4), | 3408 | bcmerror = brcmf_sdbrcm_membytes(bus, true, (bus->ramsize - 4), |
@@ -3261,13 +3526,21 @@ err: | |||
3261 | * by two NULs. | 3526 | * by two NULs. |
3262 | */ | 3527 | */ |
3263 | 3528 | ||
3264 | static uint brcmf_process_nvram_vars(char *varbuf, uint len) | 3529 | static int brcmf_process_nvram_vars(struct brcmf_sdio *bus) |
3265 | { | 3530 | { |
3531 | char *varbuf; | ||
3266 | char *dp; | 3532 | char *dp; |
3267 | bool findNewline; | 3533 | bool findNewline; |
3268 | int column; | 3534 | int column; |
3269 | uint buf_len, n; | 3535 | int ret = 0; |
3536 | uint buf_len, n, len; | ||
3270 | 3537 | ||
3538 | len = bus->firmware->size; | ||
3539 | varbuf = vmalloc(len); | ||
3540 | if (!varbuf) | ||
3541 | return -ENOMEM; | ||
3542 | |||
3543 | memcpy(varbuf, bus->firmware->data, len); | ||
3271 | dp = varbuf; | 3544 | dp = varbuf; |
3272 | 3545 | ||
3273 | findNewline = false; | 3546 | findNewline = false; |
@@ -3296,56 +3569,44 @@ static uint brcmf_process_nvram_vars(char *varbuf, uint len) | |||
3296 | column++; | 3569 | column++; |
3297 | } | 3570 | } |
3298 | buf_len = dp - varbuf; | 3571 | buf_len = dp - varbuf; |
3299 | |||
3300 | while (dp < varbuf + n) | 3572 | while (dp < varbuf + n) |
3301 | *dp++ = 0; | 3573 | *dp++ = 0; |
3302 | 3574 | ||
3303 | return buf_len; | 3575 | kfree(bus->vars); |
3576 | /* roundup needed for download to device */ | ||
3577 | bus->varsz = roundup(buf_len + 1, 4); | ||
3578 | bus->vars = kmalloc(bus->varsz, GFP_KERNEL); | ||
3579 | if (bus->vars == NULL) { | ||
3580 | bus->varsz = 0; | ||
3581 | ret = -ENOMEM; | ||
3582 | goto err; | ||
3583 | } | ||
3584 | |||
3585 | /* copy the processed variables and add null termination */ | ||
3586 | memcpy(bus->vars, varbuf, buf_len); | ||
3587 | bus->vars[buf_len] = 0; | ||
3588 | err: | ||
3589 | vfree(varbuf); | ||
3590 | return ret; | ||
3304 | } | 3591 | } |
3305 | 3592 | ||
3306 | static int brcmf_sdbrcm_download_nvram(struct brcmf_sdio *bus) | 3593 | static int brcmf_sdbrcm_download_nvram(struct brcmf_sdio *bus) |
3307 | { | 3594 | { |
3308 | uint len; | ||
3309 | char *memblock = NULL; | ||
3310 | char *bufp; | ||
3311 | int ret; | 3595 | int ret; |
3312 | 3596 | ||
3597 | if (bus->sdiodev->bus_if->drvr_up) | ||
3598 | return -EISCONN; | ||
3599 | |||
3313 | ret = request_firmware(&bus->firmware, BRCMF_SDIO_NV_NAME, | 3600 | ret = request_firmware(&bus->firmware, BRCMF_SDIO_NV_NAME, |
3314 | &bus->sdiodev->func[2]->dev); | 3601 | &bus->sdiodev->func[2]->dev); |
3315 | if (ret) { | 3602 | if (ret) { |
3316 | brcmf_dbg(ERROR, "Fail to request nvram %d\n", ret); | 3603 | brcmf_dbg(ERROR, "Fail to request nvram %d\n", ret); |
3317 | return ret; | 3604 | return ret; |
3318 | } | 3605 | } |
3319 | bus->fw_ptr = 0; | ||
3320 | |||
3321 | memblock = kmalloc(MEMBLOCK, GFP_ATOMIC); | ||
3322 | if (memblock == NULL) { | ||
3323 | ret = -ENOMEM; | ||
3324 | goto err; | ||
3325 | } | ||
3326 | |||
3327 | len = brcmf_sdbrcm_get_image(memblock, MEMBLOCK, bus); | ||
3328 | |||
3329 | if (len > 0 && len < MEMBLOCK) { | ||
3330 | bufp = (char *)memblock; | ||
3331 | bufp[len] = 0; | ||
3332 | len = brcmf_process_nvram_vars(bufp, len); | ||
3333 | bufp += len; | ||
3334 | *bufp++ = 0; | ||
3335 | if (len) | ||
3336 | ret = brcmf_sdbrcm_downloadvars(bus, memblock, len + 1); | ||
3337 | if (ret) | ||
3338 | brcmf_dbg(ERROR, "error downloading vars: %d\n", ret); | ||
3339 | } else { | ||
3340 | brcmf_dbg(ERROR, "error reading nvram file: %d\n", len); | ||
3341 | ret = -EIO; | ||
3342 | } | ||
3343 | 3606 | ||
3344 | err: | 3607 | ret = brcmf_process_nvram_vars(bus); |
3345 | kfree(memblock); | ||
3346 | 3608 | ||
3347 | release_firmware(bus->firmware); | 3609 | release_firmware(bus->firmware); |
3348 | bus->fw_ptr = 0; | ||
3349 | 3610 | ||
3350 | return ret; | 3611 | return ret; |
3351 | } | 3612 | } |
@@ -3419,7 +3680,7 @@ static int brcmf_sdbrcm_bus_init(struct device *dev) | |||
3419 | return 0; | 3680 | return 0; |
3420 | 3681 | ||
3421 | /* Start the watchdog timer */ | 3682 | /* Start the watchdog timer */ |
3422 | bus->tickcnt = 0; | 3683 | bus->sdcnt.tickcnt = 0; |
3423 | brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS); | 3684 | brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS); |
3424 | 3685 | ||
3425 | down(&bus->sdsem); | 3686 | down(&bus->sdsem); |
@@ -3512,7 +3773,7 @@ void brcmf_sdbrcm_isr(void *arg) | |||
3512 | return; | 3773 | return; |
3513 | } | 3774 | } |
3514 | /* Count the interrupt call */ | 3775 | /* Count the interrupt call */ |
3515 | bus->intrcount++; | 3776 | bus->sdcnt.intrcount++; |
3516 | bus->ipend = true; | 3777 | bus->ipend = true; |
3517 | 3778 | ||
3518 | /* Shouldn't get this interrupt if we're sleeping? */ | 3779 | /* Shouldn't get this interrupt if we're sleeping? */ |
@@ -3554,7 +3815,8 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) | |||
3554 | bus->polltick = 0; | 3815 | bus->polltick = 0; |
3555 | 3816 | ||
3556 | /* Check device if no interrupts */ | 3817 | /* Check device if no interrupts */ |
3557 | if (!bus->intr || (bus->intrcount == bus->lastintrs)) { | 3818 | if (!bus->intr || |
3819 | (bus->sdcnt.intrcount == bus->sdcnt.lastintrs)) { | ||
3558 | 3820 | ||
3559 | if (!bus->dpc_sched) { | 3821 | if (!bus->dpc_sched) { |
3560 | u8 devpend; | 3822 | u8 devpend; |
@@ -3569,7 +3831,7 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) | |||
3569 | /* If there is something, make like the ISR and | 3831 | /* If there is something, make like the ISR and |
3570 | schedule the DPC */ | 3832 | schedule the DPC */ |
3571 | if (intstatus) { | 3833 | if (intstatus) { |
3572 | bus->pollcnt++; | 3834 | bus->sdcnt.pollcnt++; |
3573 | bus->ipend = true; | 3835 | bus->ipend = true; |
3574 | 3836 | ||
3575 | bus->dpc_sched = true; | 3837 | bus->dpc_sched = true; |
@@ -3581,7 +3843,7 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) | |||
3581 | } | 3843 | } |
3582 | 3844 | ||
3583 | /* Update interrupt tracking */ | 3845 | /* Update interrupt tracking */ |
3584 | bus->lastintrs = bus->intrcount; | 3846 | bus->sdcnt.lastintrs = bus->sdcnt.intrcount; |
3585 | } | 3847 | } |
3586 | #ifdef DEBUG | 3848 | #ifdef DEBUG |
3587 | /* Poll for console output periodically */ | 3849 | /* Poll for console output periodically */ |
@@ -3623,6 +3885,8 @@ static bool brcmf_sdbrcm_chipmatch(u16 chipid) | |||
3623 | return true; | 3885 | return true; |
3624 | if (chipid == BCM4330_CHIP_ID) | 3886 | if (chipid == BCM4330_CHIP_ID) |
3625 | return true; | 3887 | return true; |
3888 | if (chipid == BCM4334_CHIP_ID) | ||
3889 | return true; | ||
3626 | return false; | 3890 | return false; |
3627 | } | 3891 | } |
3628 | 3892 | ||
@@ -3793,7 +4057,7 @@ brcmf_sdbrcm_watchdog_thread(void *data) | |||
3793 | if (!wait_for_completion_interruptible(&bus->watchdog_wait)) { | 4057 | if (!wait_for_completion_interruptible(&bus->watchdog_wait)) { |
3794 | brcmf_sdbrcm_bus_watchdog(bus); | 4058 | brcmf_sdbrcm_bus_watchdog(bus); |
3795 | /* Count the tick for reference */ | 4059 | /* Count the tick for reference */ |
3796 | bus->tickcnt++; | 4060 | bus->sdcnt.tickcnt++; |
3797 | } else | 4061 | } else |
3798 | break; | 4062 | break; |
3799 | } | 4063 | } |
@@ -3856,6 +4120,10 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) | |||
3856 | { | 4120 | { |
3857 | int ret; | 4121 | int ret; |
3858 | struct brcmf_sdio *bus; | 4122 | struct brcmf_sdio *bus; |
4123 | struct brcmf_bus_dcmd *dlst; | ||
4124 | u32 dngl_txglom; | ||
4125 | u32 dngl_txglomalign; | ||
4126 | u8 idx; | ||
3859 | 4127 | ||
3860 | brcmf_dbg(TRACE, "Enter\n"); | 4128 | brcmf_dbg(TRACE, "Enter\n"); |
3861 | 4129 | ||
@@ -3938,8 +4206,29 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) | |||
3938 | goto fail; | 4206 | goto fail; |
3939 | } | 4207 | } |
3940 | 4208 | ||
4209 | brcmf_sdio_debugfs_create(bus); | ||
3941 | brcmf_dbg(INFO, "completed!!\n"); | 4210 | brcmf_dbg(INFO, "completed!!\n"); |
3942 | 4211 | ||
4212 | /* sdio bus core specific dcmd */ | ||
4213 | idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV); | ||
4214 | dlst = kzalloc(sizeof(struct brcmf_bus_dcmd), GFP_KERNEL); | ||
4215 | if (dlst) { | ||
4216 | if (bus->ci->c_inf[idx].rev < 12) { | ||
4217 | /* for sdio core rev < 12, disable txgloming */ | ||
4218 | dngl_txglom = 0; | ||
4219 | dlst->name = "bus:txglom"; | ||
4220 | dlst->param = (char *)&dngl_txglom; | ||
4221 | dlst->param_len = sizeof(u32); | ||
4222 | } else { | ||
4223 | /* otherwise, set txglomalign */ | ||
4224 | dngl_txglomalign = bus->sdiodev->bus_if->align; | ||
4225 | dlst->name = "bus:txglomalign"; | ||
4226 | dlst->param = (char *)&dngl_txglomalign; | ||
4227 | dlst->param_len = sizeof(u32); | ||
4228 | } | ||
4229 | list_add(&dlst->list, &bus->sdiodev->bus_if->dcmd_list); | ||
4230 | } | ||
4231 | |||
3943 | /* if firmware path present try to download and bring up bus */ | 4232 | /* if firmware path present try to download and bring up bus */ |
3944 | ret = brcmf_bus_start(bus->sdiodev->dev); | 4233 | ret = brcmf_bus_start(bus->sdiodev->dev); |
3945 | if (ret != 0) { | 4234 | if (ret != 0) { |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c index f8e1f1c84d0..58155e23d22 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c | |||
@@ -403,6 +403,23 @@ static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev, | |||
403 | ci->c_inf[3].cib = 0x03004211; | 403 | ci->c_inf[3].cib = 0x03004211; |
404 | ci->ramsize = 0x48000; | 404 | ci->ramsize = 0x48000; |
405 | break; | 405 | break; |
406 | case BCM4334_CHIP_ID: | ||
407 | ci->c_inf[0].wrapbase = 0x18100000; | ||
408 | ci->c_inf[0].cib = 0x29004211; | ||
409 | ci->c_inf[1].id = BCMA_CORE_SDIO_DEV; | ||
410 | ci->c_inf[1].base = 0x18002000; | ||
411 | ci->c_inf[1].wrapbase = 0x18102000; | ||
412 | ci->c_inf[1].cib = 0x0d004211; | ||
413 | ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM; | ||
414 | ci->c_inf[2].base = 0x18004000; | ||
415 | ci->c_inf[2].wrapbase = 0x18104000; | ||
416 | ci->c_inf[2].cib = 0x13080401; | ||
417 | ci->c_inf[3].id = BCMA_CORE_ARM_CM3; | ||
418 | ci->c_inf[3].base = 0x18003000; | ||
419 | ci->c_inf[3].wrapbase = 0x18103000; | ||
420 | ci->c_inf[3].cib = 0x07004211; | ||
421 | ci->ramsize = 0x80000; | ||
422 | break; | ||
406 | default: | 423 | default: |
407 | brcmf_dbg(ERROR, "chipid 0x%x is not supported\n", ci->chip); | 424 | brcmf_dbg(ERROR, "chipid 0x%x is not supported\n", ci->chip); |
408 | return -ENODEV; | 425 | return -ENODEV; |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c index 95b5902bc4b..01b190a25d9 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c | |||
@@ -735,10 +735,8 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi, | |||
735 | * a candidate for aggregation | 735 | * a candidate for aggregation |
736 | */ | 736 | */ |
737 | p = pktq_ppeek(&qi->q, prec); | 737 | p = pktq_ppeek(&qi->q, prec); |
738 | /* tx_info must be checked with current p */ | ||
739 | tx_info = IEEE80211_SKB_CB(p); | ||
740 | |||
741 | if (p) { | 738 | if (p) { |
739 | tx_info = IEEE80211_SKB_CB(p); | ||
742 | if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && | 740 | if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && |
743 | ((u8) (p->priority) == tid)) { | 741 | ((u8) (p->priority) == tid)) { |
744 | plen = p->len + AMPDU_MAX_MPDU_OVERHEAD; | 742 | plen = p->len + AMPDU_MAX_MPDU_OVERHEAD; |
@@ -759,6 +757,7 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi, | |||
759 | p = NULL; | 757 | p = NULL; |
760 | continue; | 758 | continue; |
761 | } | 759 | } |
760 | /* next packet fit for aggregation so dequeue */ | ||
762 | p = brcmu_pktq_pdeq(&qi->q, prec); | 761 | p = brcmu_pktq_pdeq(&qi->q, prec); |
763 | } else { | 762 | } else { |
764 | p = NULL; | 763 | p = NULL; |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.c b/drivers/net/wireless/brcm80211/brcmsmac/channel.c index eb77ac3cfb6..2d365d3486d 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c | |||
@@ -15,7 +15,9 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/types.h> | 17 | #include <linux/types.h> |
18 | #include <net/cfg80211.h> | ||
18 | #include <net/mac80211.h> | 19 | #include <net/mac80211.h> |
20 | #include <net/regulatory.h> | ||
19 | 21 | ||
20 | #include <defs.h> | 22 | #include <defs.h> |
21 | #include "pub.h" | 23 | #include "pub.h" |
@@ -23,73 +25,17 @@ | |||
23 | #include "main.h" | 25 | #include "main.h" |
24 | #include "stf.h" | 26 | #include "stf.h" |
25 | #include "channel.h" | 27 | #include "channel.h" |
28 | #include "mac80211_if.h" | ||
26 | 29 | ||
27 | /* QDB() macro takes a dB value and converts to a quarter dB value */ | 30 | /* QDB() macro takes a dB value and converts to a quarter dB value */ |
28 | #define QDB(n) ((n) * BRCMS_TXPWR_DB_FACTOR) | 31 | #define QDB(n) ((n) * BRCMS_TXPWR_DB_FACTOR) |
29 | 32 | ||
30 | #define LOCALE_CHAN_01_11 (1<<0) | ||
31 | #define LOCALE_CHAN_12_13 (1<<1) | ||
32 | #define LOCALE_CHAN_14 (1<<2) | ||
33 | #define LOCALE_SET_5G_LOW_JP1 (1<<3) /* 34-48, step 2 */ | ||
34 | #define LOCALE_SET_5G_LOW_JP2 (1<<4) /* 34-46, step 4 */ | ||
35 | #define LOCALE_SET_5G_LOW1 (1<<5) /* 36-48, step 4 */ | ||
36 | #define LOCALE_SET_5G_LOW2 (1<<6) /* 52 */ | ||
37 | #define LOCALE_SET_5G_LOW3 (1<<7) /* 56-64, step 4 */ | ||
38 | #define LOCALE_SET_5G_MID1 (1<<8) /* 100-116, step 4 */ | ||
39 | #define LOCALE_SET_5G_MID2 (1<<9) /* 120-124, step 4 */ | ||
40 | #define LOCALE_SET_5G_MID3 (1<<10) /* 128 */ | ||
41 | #define LOCALE_SET_5G_HIGH1 (1<<11) /* 132-140, step 4 */ | ||
42 | #define LOCALE_SET_5G_HIGH2 (1<<12) /* 149-161, step 4 */ | ||
43 | #define LOCALE_SET_5G_HIGH3 (1<<13) /* 165 */ | ||
44 | #define LOCALE_CHAN_52_140_ALL (1<<14) | ||
45 | #define LOCALE_SET_5G_HIGH4 (1<<15) /* 184-216 */ | ||
46 | |||
47 | #define LOCALE_CHAN_36_64 (LOCALE_SET_5G_LOW1 | \ | ||
48 | LOCALE_SET_5G_LOW2 | \ | ||
49 | LOCALE_SET_5G_LOW3) | ||
50 | #define LOCALE_CHAN_52_64 (LOCALE_SET_5G_LOW2 | LOCALE_SET_5G_LOW3) | ||
51 | #define LOCALE_CHAN_100_124 (LOCALE_SET_5G_MID1 | LOCALE_SET_5G_MID2) | ||
52 | #define LOCALE_CHAN_100_140 (LOCALE_SET_5G_MID1 | LOCALE_SET_5G_MID2 | \ | ||
53 | LOCALE_SET_5G_MID3 | LOCALE_SET_5G_HIGH1) | ||
54 | #define LOCALE_CHAN_149_165 (LOCALE_SET_5G_HIGH2 | LOCALE_SET_5G_HIGH3) | ||
55 | #define LOCALE_CHAN_184_216 LOCALE_SET_5G_HIGH4 | ||
56 | |||
57 | #define LOCALE_CHAN_01_14 (LOCALE_CHAN_01_11 | \ | ||
58 | LOCALE_CHAN_12_13 | \ | ||
59 | LOCALE_CHAN_14) | ||
60 | |||
61 | #define LOCALE_RADAR_SET_NONE 0 | ||
62 | #define LOCALE_RADAR_SET_1 1 | ||
63 | |||
64 | #define LOCALE_RESTRICTED_NONE 0 | ||
65 | #define LOCALE_RESTRICTED_SET_2G_SHORT 1 | ||
66 | #define LOCALE_RESTRICTED_CHAN_165 2 | ||
67 | #define LOCALE_CHAN_ALL_5G 3 | ||
68 | #define LOCALE_RESTRICTED_JAPAN_LEGACY 4 | ||
69 | #define LOCALE_RESTRICTED_11D_2G 5 | ||
70 | #define LOCALE_RESTRICTED_11D_5G 6 | ||
71 | #define LOCALE_RESTRICTED_LOW_HI 7 | ||
72 | #define LOCALE_RESTRICTED_12_13_14 8 | ||
73 | |||
74 | #define LOCALE_2G_IDX_i 0 | ||
75 | #define LOCALE_5G_IDX_11 0 | ||
76 | #define LOCALE_MIMO_IDX_bn 0 | 33 | #define LOCALE_MIMO_IDX_bn 0 |
77 | #define LOCALE_MIMO_IDX_11n 0 | 34 | #define LOCALE_MIMO_IDX_11n 0 |
78 | 35 | ||
79 | /* max of BAND_5G_PWR_LVLS and 6 for 2.4 GHz */ | ||
80 | #define BRCMS_MAXPWR_TBL_SIZE 6 | ||
81 | /* max of BAND_5G_PWR_LVLS and 14 for 2.4 GHz */ | 36 | /* max of BAND_5G_PWR_LVLS and 14 for 2.4 GHz */ |
82 | #define BRCMS_MAXPWR_MIMO_TBL_SIZE 14 | 37 | #define BRCMS_MAXPWR_MIMO_TBL_SIZE 14 |
83 | 38 | ||
84 | /* power level in group of 2.4GHz band channels: | ||
85 | * maxpwr[0] - CCK channels [1] | ||
86 | * maxpwr[1] - CCK channels [2-10] | ||
87 | * maxpwr[2] - CCK channels [11-14] | ||
88 | * maxpwr[3] - OFDM channels [1] | ||
89 | * maxpwr[4] - OFDM channels [2-10] | ||
90 | * maxpwr[5] - OFDM channels [11-14] | ||
91 | */ | ||
92 | |||
93 | /* maxpwr mapping to 5GHz band channels: | 39 | /* maxpwr mapping to 5GHz band channels: |
94 | * maxpwr[0] - channels [34-48] | 40 | * maxpwr[0] - channels [34-48] |
95 | * maxpwr[1] - channels [52-60] | 41 | * maxpwr[1] - channels [52-60] |
@@ -101,16 +47,8 @@ | |||
101 | 47 | ||
102 | #define LC(id) LOCALE_MIMO_IDX_ ## id | 48 | #define LC(id) LOCALE_MIMO_IDX_ ## id |
103 | 49 | ||
104 | #define LC_2G(id) LOCALE_2G_IDX_ ## id | 50 | #define LOCALES(mimo2, mimo5) \ |
105 | 51 | {LC(mimo2), LC(mimo5)} | |
106 | #define LC_5G(id) LOCALE_5G_IDX_ ## id | ||
107 | |||
108 | #define LOCALES(band2, band5, mimo2, mimo5) \ | ||
109 | {LC_2G(band2), LC_5G(band5), LC(mimo2), LC(mimo5)} | ||
110 | |||
111 | /* macro to get 2.4 GHz channel group index for tx power */ | ||
112 | #define CHANNEL_POWER_IDX_2G_CCK(c) (((c) < 2) ? 0 : (((c) < 11) ? 1 : 2)) | ||
113 | #define CHANNEL_POWER_IDX_2G_OFDM(c) (((c) < 2) ? 3 : (((c) < 11) ? 4 : 5)) | ||
114 | 52 | ||
115 | /* macro to get 5 GHz channel group index for tx power */ | 53 | /* macro to get 5 GHz channel group index for tx power */ |
116 | #define CHANNEL_POWER_IDX_5G(c) (((c) < 52) ? 0 : \ | 54 | #define CHANNEL_POWER_IDX_5G(c) (((c) < 52) ? 0 : \ |
@@ -118,18 +56,37 @@ | |||
118 | (((c) < 100) ? 2 : \ | 56 | (((c) < 100) ? 2 : \ |
119 | (((c) < 149) ? 3 : 4)))) | 57 | (((c) < 149) ? 3 : 4)))) |
120 | 58 | ||
121 | #define ISDFS_EU(fl) (((fl) & BRCMS_DFS_EU) == BRCMS_DFS_EU) | 59 | #define BRCM_2GHZ_2412_2462 REG_RULE(2412-10, 2462+10, 40, 0, 19, 0) |
122 | 60 | #define BRCM_2GHZ_2467_2472 REG_RULE(2467-10, 2472+10, 20, 0, 19, \ | |
123 | struct brcms_cm_band { | 61 | NL80211_RRF_PASSIVE_SCAN | \ |
124 | /* struct locale_info flags */ | 62 | NL80211_RRF_NO_IBSS) |
125 | u8 locale_flags; | 63 | |
126 | /* List of valid channels in the country */ | 64 | #define BRCM_5GHZ_5180_5240 REG_RULE(5180-10, 5240+10, 40, 0, 21, \ |
127 | struct brcms_chanvec valid_channels; | 65 | NL80211_RRF_PASSIVE_SCAN | \ |
128 | /* List of restricted use channels */ | 66 | NL80211_RRF_NO_IBSS) |
129 | const struct brcms_chanvec *restricted_channels; | 67 | #define BRCM_5GHZ_5260_5320 REG_RULE(5260-10, 5320+10, 40, 0, 21, \ |
130 | /* List of radar sensitive channels */ | 68 | NL80211_RRF_PASSIVE_SCAN | \ |
131 | const struct brcms_chanvec *radar_channels; | 69 | NL80211_RRF_DFS | \ |
132 | u8 PAD[8]; | 70 | NL80211_RRF_NO_IBSS) |
71 | #define BRCM_5GHZ_5500_5700 REG_RULE(5500-10, 5700+10, 40, 0, 21, \ | ||
72 | NL80211_RRF_PASSIVE_SCAN | \ | ||
73 | NL80211_RRF_DFS | \ | ||
74 | NL80211_RRF_NO_IBSS) | ||
75 | #define BRCM_5GHZ_5745_5825 REG_RULE(5745-10, 5825+10, 40, 0, 21, \ | ||
76 | NL80211_RRF_PASSIVE_SCAN | \ | ||
77 | NL80211_RRF_NO_IBSS) | ||
78 | |||
79 | static const struct ieee80211_regdomain brcms_regdom_x2 = { | ||
80 | .n_reg_rules = 7, | ||
81 | .alpha2 = "X2", | ||
82 | .reg_rules = { | ||
83 | BRCM_2GHZ_2412_2462, | ||
84 | BRCM_2GHZ_2467_2472, | ||
85 | BRCM_5GHZ_5180_5240, | ||
86 | BRCM_5GHZ_5260_5320, | ||
87 | BRCM_5GHZ_5500_5700, | ||
88 | BRCM_5GHZ_5745_5825, | ||
89 | } | ||
133 | }; | 90 | }; |
134 | 91 | ||
135 | /* locale per-channel tx power limits for MIMO frames | 92 | /* locale per-channel tx power limits for MIMO frames |
@@ -141,337 +98,23 @@ struct locale_mimo_info { | |||
141 | s8 maxpwr20[BRCMS_MAXPWR_MIMO_TBL_SIZE]; | 98 | s8 maxpwr20[BRCMS_MAXPWR_MIMO_TBL_SIZE]; |
142 | /* tx 40 MHz power limits, qdBm units */ | 99 | /* tx 40 MHz power limits, qdBm units */ |
143 | s8 maxpwr40[BRCMS_MAXPWR_MIMO_TBL_SIZE]; | 100 | s8 maxpwr40[BRCMS_MAXPWR_MIMO_TBL_SIZE]; |
144 | u8 flags; | ||
145 | }; | 101 | }; |
146 | 102 | ||
147 | /* Country names and abbreviations with locale defined from ISO 3166 */ | 103 | /* Country names and abbreviations with locale defined from ISO 3166 */ |
148 | struct country_info { | 104 | struct country_info { |
149 | const u8 locale_2G; /* 2.4G band locale */ | ||
150 | const u8 locale_5G; /* 5G band locale */ | ||
151 | const u8 locale_mimo_2G; /* 2.4G mimo info */ | 105 | const u8 locale_mimo_2G; /* 2.4G mimo info */ |
152 | const u8 locale_mimo_5G; /* 5G mimo info */ | 106 | const u8 locale_mimo_5G; /* 5G mimo info */ |
153 | }; | 107 | }; |
154 | 108 | ||
109 | struct brcms_regd { | ||
110 | struct country_info country; | ||
111 | const struct ieee80211_regdomain *regdomain; | ||
112 | }; | ||
113 | |||
155 | struct brcms_cm_info { | 114 | struct brcms_cm_info { |
156 | struct brcms_pub *pub; | 115 | struct brcms_pub *pub; |
157 | struct brcms_c_info *wlc; | 116 | struct brcms_c_info *wlc; |
158 | char srom_ccode[BRCM_CNTRY_BUF_SZ]; /* Country Code in SROM */ | 117 | const struct brcms_regd *world_regd; |
159 | uint srom_regrev; /* Regulatory Rev for the SROM ccode */ | ||
160 | const struct country_info *country; /* current country def */ | ||
161 | char ccode[BRCM_CNTRY_BUF_SZ]; /* current internal Country Code */ | ||
162 | uint regrev; /* current Regulatory Revision */ | ||
163 | char country_abbrev[BRCM_CNTRY_BUF_SZ]; /* current advertised ccode */ | ||
164 | /* per-band state (one per phy/radio) */ | ||
165 | struct brcms_cm_band bandstate[MAXBANDS]; | ||
166 | /* quiet channels currently for radar sensitivity or 11h support */ | ||
167 | /* channels on which we cannot transmit */ | ||
168 | struct brcms_chanvec quiet_channels; | ||
169 | }; | ||
170 | |||
171 | /* locale channel and power info. */ | ||
172 | struct locale_info { | ||
173 | u32 valid_channels; | ||
174 | /* List of radar sensitive channels */ | ||
175 | u8 radar_channels; | ||
176 | /* List of channels used only if APs are detected */ | ||
177 | u8 restricted_channels; | ||
178 | /* Max tx pwr in qdBm for each sub-band */ | ||
179 | s8 maxpwr[BRCMS_MAXPWR_TBL_SIZE]; | ||
180 | /* Country IE advertised max tx pwr in dBm per sub-band */ | ||
181 | s8 pub_maxpwr[BAND_5G_PWR_LVLS]; | ||
182 | u8 flags; | ||
183 | }; | ||
184 | |||
185 | /* Regulatory Matrix Spreadsheet (CLM) MIMO v3.7.9 */ | ||
186 | |||
187 | /* | ||
188 | * Some common channel sets | ||
189 | */ | ||
190 | |||
191 | /* No channels */ | ||
192 | static const struct brcms_chanvec chanvec_none = { | ||
193 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
194 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
195 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
196 | 0x00, 0x00, 0x00, 0x00} | ||
197 | }; | ||
198 | |||
199 | /* All 2.4 GHz HW channels */ | ||
200 | static const struct brcms_chanvec chanvec_all_2G = { | ||
201 | {0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
202 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
203 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
204 | 0x00, 0x00, 0x00, 0x00} | ||
205 | }; | ||
206 | |||
207 | /* All 5 GHz HW channels */ | ||
208 | static const struct brcms_chanvec chanvec_all_5G = { | ||
209 | {0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x11, 0x11, | ||
210 | 0x01, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11, | ||
211 | 0x11, 0x11, 0x20, 0x22, 0x22, 0x00, 0x00, 0x11, | ||
212 | 0x11, 0x11, 0x11, 0x01} | ||
213 | }; | ||
214 | |||
215 | /* | ||
216 | * Radar channel sets | ||
217 | */ | ||
218 | |||
219 | /* Channels 52 - 64, 100 - 140 */ | ||
220 | static const struct brcms_chanvec radar_set1 = { | ||
221 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, /* 52 - 60 */ | ||
222 | 0x01, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11, /* 64, 100 - 124 */ | ||
223 | 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 128 - 140 */ | ||
224 | 0x00, 0x00, 0x00, 0x00} | ||
225 | }; | ||
226 | |||
227 | /* | ||
228 | * Restricted channel sets | ||
229 | */ | ||
230 | |||
231 | /* Channels 34, 38, 42, 46 */ | ||
232 | static const struct brcms_chanvec restricted_set_japan_legacy = { | ||
233 | {0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, | ||
234 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
235 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
236 | 0x00, 0x00, 0x00, 0x00} | ||
237 | }; | ||
238 | |||
239 | /* Channels 12, 13 */ | ||
240 | static const struct brcms_chanvec restricted_set_2g_short = { | ||
241 | {0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
242 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
243 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
244 | 0x00, 0x00, 0x00, 0x00} | ||
245 | }; | ||
246 | |||
247 | /* Channel 165 */ | ||
248 | static const struct brcms_chanvec restricted_chan_165 = { | ||
249 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
250 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
251 | 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, | ||
252 | 0x00, 0x00, 0x00, 0x00} | ||
253 | }; | ||
254 | |||
255 | /* Channels 36 - 48 & 149 - 165 */ | ||
256 | static const struct brcms_chanvec restricted_low_hi = { | ||
257 | {0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x01, 0x00, | ||
258 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
259 | 0x00, 0x00, 0x20, 0x22, 0x22, 0x00, 0x00, 0x00, | ||
260 | 0x00, 0x00, 0x00, 0x00} | ||
261 | }; | ||
262 | |||
263 | /* Channels 12 - 14 */ | ||
264 | static const struct brcms_chanvec restricted_set_12_13_14 = { | ||
265 | {0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
266 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
267 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
268 | 0x00, 0x00, 0x00, 0x00} | ||
269 | }; | ||
270 | |||
271 | /* global memory to provide working buffer for expanded locale */ | ||
272 | |||
273 | static const struct brcms_chanvec *g_table_radar_set[] = { | ||
274 | &chanvec_none, | ||
275 | &radar_set1 | ||
276 | }; | ||
277 | |||
278 | static const struct brcms_chanvec *g_table_restricted_chan[] = { | ||
279 | &chanvec_none, /* restricted_set_none */ | ||
280 | &restricted_set_2g_short, | ||
281 | &restricted_chan_165, | ||
282 | &chanvec_all_5G, | ||
283 | &restricted_set_japan_legacy, | ||
284 | &chanvec_all_2G, /* restricted_set_11d_2G */ | ||
285 | &chanvec_all_5G, /* restricted_set_11d_5G */ | ||
286 | &restricted_low_hi, | ||
287 | &restricted_set_12_13_14 | ||
288 | }; | ||
289 | |||
290 | static const struct brcms_chanvec locale_2g_01_11 = { | ||
291 | {0xfe, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
292 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
293 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
294 | 0x00, 0x00, 0x00, 0x00} | ||
295 | }; | ||
296 | |||
297 | static const struct brcms_chanvec locale_2g_12_13 = { | ||
298 | {0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
299 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
300 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
301 | 0x00, 0x00, 0x00, 0x00} | ||
302 | }; | ||
303 | |||
304 | static const struct brcms_chanvec locale_2g_14 = { | ||
305 | {0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
306 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
307 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
308 | 0x00, 0x00, 0x00, 0x00} | ||
309 | }; | ||
310 | |||
311 | static const struct brcms_chanvec locale_5g_LOW_JP1 = { | ||
312 | {0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x01, 0x00, | ||
313 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
314 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
315 | 0x00, 0x00, 0x00, 0x00} | ||
316 | }; | ||
317 | |||
318 | static const struct brcms_chanvec locale_5g_LOW_JP2 = { | ||
319 | {0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, | ||
320 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
321 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
322 | 0x00, 0x00, 0x00, 0x00} | ||
323 | }; | ||
324 | |||
325 | static const struct brcms_chanvec locale_5g_LOW1 = { | ||
326 | {0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x01, 0x00, | ||
327 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
328 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
329 | 0x00, 0x00, 0x00, 0x00} | ||
330 | }; | ||
331 | |||
332 | static const struct brcms_chanvec locale_5g_LOW2 = { | ||
333 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, | ||
334 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
335 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
336 | 0x00, 0x00, 0x00, 0x00} | ||
337 | }; | ||
338 | |||
339 | static const struct brcms_chanvec locale_5g_LOW3 = { | ||
340 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, | ||
341 | 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
342 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
343 | 0x00, 0x00, 0x00, 0x00} | ||
344 | }; | ||
345 | |||
346 | static const struct brcms_chanvec locale_5g_MID1 = { | ||
347 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
348 | 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x00, | ||
349 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
350 | 0x00, 0x00, 0x00, 0x00} | ||
351 | }; | ||
352 | |||
353 | static const struct brcms_chanvec locale_5g_MID2 = { | ||
354 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
355 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, | ||
356 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
357 | 0x00, 0x00, 0x00, 0x00} | ||
358 | }; | ||
359 | |||
360 | static const struct brcms_chanvec locale_5g_MID3 = { | ||
361 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
362 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
363 | 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
364 | 0x00, 0x00, 0x00, 0x00} | ||
365 | }; | ||
366 | |||
367 | static const struct brcms_chanvec locale_5g_HIGH1 = { | ||
368 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
369 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
370 | 0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
371 | 0x00, 0x00, 0x00, 0x00} | ||
372 | }; | ||
373 | |||
374 | static const struct brcms_chanvec locale_5g_HIGH2 = { | ||
375 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
376 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
377 | 0x00, 0x00, 0x20, 0x22, 0x02, 0x00, 0x00, 0x00, | ||
378 | 0x00, 0x00, 0x00, 0x00} | ||
379 | }; | ||
380 | |||
381 | static const struct brcms_chanvec locale_5g_HIGH3 = { | ||
382 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
383 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
384 | 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, | ||
385 | 0x00, 0x00, 0x00, 0x00} | ||
386 | }; | ||
387 | |||
388 | static const struct brcms_chanvec locale_5g_52_140_ALL = { | ||
389 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, | ||
390 | 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, | ||
391 | 0x11, 0x11, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, | ||
392 | 0x00, 0x00, 0x00, 0x00} | ||
393 | }; | ||
394 | |||
395 | static const struct brcms_chanvec locale_5g_HIGH4 = { | ||
396 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
397 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
398 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, | ||
399 | 0x11, 0x11, 0x11, 0x11} | ||
400 | }; | ||
401 | |||
402 | static const struct brcms_chanvec *g_table_locale_base[] = { | ||
403 | &locale_2g_01_11, | ||
404 | &locale_2g_12_13, | ||
405 | &locale_2g_14, | ||
406 | &locale_5g_LOW_JP1, | ||
407 | &locale_5g_LOW_JP2, | ||
408 | &locale_5g_LOW1, | ||
409 | &locale_5g_LOW2, | ||
410 | &locale_5g_LOW3, | ||
411 | &locale_5g_MID1, | ||
412 | &locale_5g_MID2, | ||
413 | &locale_5g_MID3, | ||
414 | &locale_5g_HIGH1, | ||
415 | &locale_5g_HIGH2, | ||
416 | &locale_5g_HIGH3, | ||
417 | &locale_5g_52_140_ALL, | ||
418 | &locale_5g_HIGH4 | ||
419 | }; | ||
420 | |||
421 | static void brcms_c_locale_add_channels(struct brcms_chanvec *target, | ||
422 | const struct brcms_chanvec *channels) | ||
423 | { | ||
424 | u8 i; | ||
425 | for (i = 0; i < sizeof(struct brcms_chanvec); i++) | ||
426 | target->vec[i] |= channels->vec[i]; | ||
427 | } | ||
428 | |||
429 | static void brcms_c_locale_get_channels(const struct locale_info *locale, | ||
430 | struct brcms_chanvec *channels) | ||
431 | { | ||
432 | u8 i; | ||
433 | |||
434 | memset(channels, 0, sizeof(struct brcms_chanvec)); | ||
435 | |||
436 | for (i = 0; i < ARRAY_SIZE(g_table_locale_base); i++) { | ||
437 | if (locale->valid_channels & (1 << i)) | ||
438 | brcms_c_locale_add_channels(channels, | ||
439 | g_table_locale_base[i]); | ||
440 | } | ||
441 | } | ||
442 | |||
443 | /* | ||
444 | * Locale Definitions - 2.4 GHz | ||
445 | */ | ||
446 | static const struct locale_info locale_i = { /* locale i. channel 1 - 13 */ | ||
447 | LOCALE_CHAN_01_11 | LOCALE_CHAN_12_13, | ||
448 | LOCALE_RADAR_SET_NONE, | ||
449 | LOCALE_RESTRICTED_SET_2G_SHORT, | ||
450 | {QDB(19), QDB(19), QDB(19), | ||
451 | QDB(19), QDB(19), QDB(19)}, | ||
452 | {20, 20, 20, 0}, | ||
453 | BRCMS_EIRP | ||
454 | }; | ||
455 | |||
456 | /* | ||
457 | * Locale Definitions - 5 GHz | ||
458 | */ | ||
459 | static const struct locale_info locale_11 = { | ||
460 | /* locale 11. channel 36 - 48, 52 - 64, 100 - 140, 149 - 165 */ | ||
461 | LOCALE_CHAN_36_64 | LOCALE_CHAN_100_140 | LOCALE_CHAN_149_165, | ||
462 | LOCALE_RADAR_SET_1, | ||
463 | LOCALE_RESTRICTED_NONE, | ||
464 | {QDB(21), QDB(21), QDB(21), QDB(21), QDB(21)}, | ||
465 | {23, 23, 23, 30, 30}, | ||
466 | BRCMS_EIRP | BRCMS_DFS_EU | ||
467 | }; | ||
468 | |||
469 | static const struct locale_info *g_locale_2g_table[] = { | ||
470 | &locale_i | ||
471 | }; | ||
472 | |||
473 | static const struct locale_info *g_locale_5g_table[] = { | ||
474 | &locale_11 | ||
475 | }; | 118 | }; |
476 | 119 | ||
477 | /* | 120 | /* |
@@ -484,7 +127,6 @@ static const struct locale_mimo_info locale_bn = { | |||
484 | {0, 0, QDB(13), QDB(13), QDB(13), | 127 | {0, 0, QDB(13), QDB(13), QDB(13), |
485 | QDB(13), QDB(13), QDB(13), QDB(13), QDB(13), | 128 | QDB(13), QDB(13), QDB(13), QDB(13), QDB(13), |
486 | QDB(13), 0, 0}, | 129 | QDB(13), 0, 0}, |
487 | 0 | ||
488 | }; | 130 | }; |
489 | 131 | ||
490 | static const struct locale_mimo_info *g_mimo_2g_table[] = { | 132 | static const struct locale_mimo_info *g_mimo_2g_table[] = { |
@@ -497,114 +139,20 @@ static const struct locale_mimo_info *g_mimo_2g_table[] = { | |||
497 | static const struct locale_mimo_info locale_11n = { | 139 | static const struct locale_mimo_info locale_11n = { |
498 | { /* 12.5 dBm */ 50, 50, 50, QDB(15), QDB(15)}, | 140 | { /* 12.5 dBm */ 50, 50, 50, QDB(15), QDB(15)}, |
499 | {QDB(14), QDB(15), QDB(15), QDB(15), QDB(15)}, | 141 | {QDB(14), QDB(15), QDB(15), QDB(15), QDB(15)}, |
500 | 0 | ||
501 | }; | 142 | }; |
502 | 143 | ||
503 | static const struct locale_mimo_info *g_mimo_5g_table[] = { | 144 | static const struct locale_mimo_info *g_mimo_5g_table[] = { |
504 | &locale_11n | 145 | &locale_11n |
505 | }; | 146 | }; |
506 | 147 | ||
507 | static const struct { | 148 | static const struct brcms_regd cntry_locales[] = { |
508 | char abbrev[BRCM_CNTRY_BUF_SZ]; /* country abbreviation */ | 149 | /* Worldwide RoW 2, must always be at index 0 */ |
509 | struct country_info country; | ||
510 | } cntry_locales[] = { | ||
511 | { | 150 | { |
512 | "X2", LOCALES(i, 11, bn, 11n)}, /* Worldwide RoW 2 */ | 151 | .country = LOCALES(bn, 11n), |
513 | }; | 152 | .regdomain = &brcms_regdom_x2, |
514 | 153 | }, | |
515 | #ifdef SUPPORT_40MHZ | ||
516 | /* 20MHz channel info for 40MHz pairing support */ | ||
517 | struct chan20_info { | ||
518 | u8 sb; | ||
519 | u8 adj_sbs; | ||
520 | }; | 154 | }; |
521 | 155 | ||
522 | /* indicates adjacent channels that are allowed for a 40 Mhz channel and | ||
523 | * those that permitted by the HT | ||
524 | */ | ||
525 | struct chan20_info chan20_info[] = { | ||
526 | /* 11b/11g */ | ||
527 | /* 0 */ {1, (CH_UPPER_SB | CH_EWA_VALID)}, | ||
528 | /* 1 */ {2, (CH_UPPER_SB | CH_EWA_VALID)}, | ||
529 | /* 2 */ {3, (CH_UPPER_SB | CH_EWA_VALID)}, | ||
530 | /* 3 */ {4, (CH_UPPER_SB | CH_EWA_VALID)}, | ||
531 | /* 4 */ {5, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)}, | ||
532 | /* 5 */ {6, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)}, | ||
533 | /* 6 */ {7, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)}, | ||
534 | /* 7 */ {8, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)}, | ||
535 | /* 8 */ {9, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)}, | ||
536 | /* 9 */ {10, (CH_LOWER_SB | CH_EWA_VALID)}, | ||
537 | /* 10 */ {11, (CH_LOWER_SB | CH_EWA_VALID)}, | ||
538 | /* 11 */ {12, (CH_LOWER_SB)}, | ||
539 | /* 12 */ {13, (CH_LOWER_SB)}, | ||
540 | /* 13 */ {14, (CH_LOWER_SB)}, | ||
541 | |||
542 | /* 11a japan high */ | ||
543 | /* 14 */ {34, (CH_UPPER_SB)}, | ||
544 | /* 15 */ {38, (CH_LOWER_SB)}, | ||
545 | /* 16 */ {42, (CH_LOWER_SB)}, | ||
546 | /* 17 */ {46, (CH_LOWER_SB)}, | ||
547 | |||
548 | /* 11a usa low */ | ||
549 | /* 18 */ {36, (CH_UPPER_SB | CH_EWA_VALID)}, | ||
550 | /* 19 */ {40, (CH_LOWER_SB | CH_EWA_VALID)}, | ||
551 | /* 20 */ {44, (CH_UPPER_SB | CH_EWA_VALID)}, | ||
552 | /* 21 */ {48, (CH_LOWER_SB | CH_EWA_VALID)}, | ||
553 | /* 22 */ {52, (CH_UPPER_SB | CH_EWA_VALID)}, | ||
554 | /* 23 */ {56, (CH_LOWER_SB | CH_EWA_VALID)}, | ||
555 | /* 24 */ {60, (CH_UPPER_SB | CH_EWA_VALID)}, | ||
556 | /* 25 */ {64, (CH_LOWER_SB | CH_EWA_VALID)}, | ||
557 | |||
558 | /* 11a Europe */ | ||
559 | /* 26 */ {100, (CH_UPPER_SB | CH_EWA_VALID)}, | ||
560 | /* 27 */ {104, (CH_LOWER_SB | CH_EWA_VALID)}, | ||
561 | /* 28 */ {108, (CH_UPPER_SB | CH_EWA_VALID)}, | ||
562 | /* 29 */ {112, (CH_LOWER_SB | CH_EWA_VALID)}, | ||
563 | /* 30 */ {116, (CH_UPPER_SB | CH_EWA_VALID)}, | ||
564 | /* 31 */ {120, (CH_LOWER_SB | CH_EWA_VALID)}, | ||
565 | /* 32 */ {124, (CH_UPPER_SB | CH_EWA_VALID)}, | ||
566 | /* 33 */ {128, (CH_LOWER_SB | CH_EWA_VALID)}, | ||
567 | /* 34 */ {132, (CH_UPPER_SB | CH_EWA_VALID)}, | ||
568 | /* 35 */ {136, (CH_LOWER_SB | CH_EWA_VALID)}, | ||
569 | /* 36 */ {140, (CH_LOWER_SB)}, | ||
570 | |||
571 | /* 11a usa high, ref5 only */ | ||
572 | /* The 0x80 bit in pdiv means these are REF5, other entries are REF20 */ | ||
573 | /* 37 */ {149, (CH_UPPER_SB | CH_EWA_VALID)}, | ||
574 | /* 38 */ {153, (CH_LOWER_SB | CH_EWA_VALID)}, | ||
575 | /* 39 */ {157, (CH_UPPER_SB | CH_EWA_VALID)}, | ||
576 | /* 40 */ {161, (CH_LOWER_SB | CH_EWA_VALID)}, | ||
577 | /* 41 */ {165, (CH_LOWER_SB)}, | ||
578 | |||
579 | /* 11a japan */ | ||
580 | /* 42 */ {184, (CH_UPPER_SB)}, | ||
581 | /* 43 */ {188, (CH_LOWER_SB)}, | ||
582 | /* 44 */ {192, (CH_UPPER_SB)}, | ||
583 | /* 45 */ {196, (CH_LOWER_SB)}, | ||
584 | /* 46 */ {200, (CH_UPPER_SB)}, | ||
585 | /* 47 */ {204, (CH_LOWER_SB)}, | ||
586 | /* 48 */ {208, (CH_UPPER_SB)}, | ||
587 | /* 49 */ {212, (CH_LOWER_SB)}, | ||
588 | /* 50 */ {216, (CH_LOWER_SB)} | ||
589 | }; | ||
590 | #endif /* SUPPORT_40MHZ */ | ||
591 | |||
592 | static const struct locale_info *brcms_c_get_locale_2g(u8 locale_idx) | ||
593 | { | ||
594 | if (locale_idx >= ARRAY_SIZE(g_locale_2g_table)) | ||
595 | return NULL; /* error condition */ | ||
596 | |||
597 | return g_locale_2g_table[locale_idx]; | ||
598 | } | ||
599 | |||
600 | static const struct locale_info *brcms_c_get_locale_5g(u8 locale_idx) | ||
601 | { | ||
602 | if (locale_idx >= ARRAY_SIZE(g_locale_5g_table)) | ||
603 | return NULL; /* error condition */ | ||
604 | |||
605 | return g_locale_5g_table[locale_idx]; | ||
606 | } | ||
607 | |||
608 | static const struct locale_mimo_info *brcms_c_get_mimo_2g(u8 locale_idx) | 156 | static const struct locale_mimo_info *brcms_c_get_mimo_2g(u8 locale_idx) |
609 | { | 157 | { |
610 | if (locale_idx >= ARRAY_SIZE(g_mimo_2g_table)) | 158 | if (locale_idx >= ARRAY_SIZE(g_mimo_2g_table)) |
@@ -621,13 +169,6 @@ static const struct locale_mimo_info *brcms_c_get_mimo_5g(u8 locale_idx) | |||
621 | return g_mimo_5g_table[locale_idx]; | 169 | return g_mimo_5g_table[locale_idx]; |
622 | } | 170 | } |
623 | 171 | ||
624 | static int | ||
625 | brcms_c_country_aggregate_map(struct brcms_cm_info *wlc_cm, const char *ccode, | ||
626 | char *mapped_ccode, uint *mapped_regrev) | ||
627 | { | ||
628 | return false; | ||
629 | } | ||
630 | |||
631 | /* | 172 | /* |
632 | * Indicates whether the country provided is valid to pass | 173 | * Indicates whether the country provided is valid to pass |
633 | * to cfg80211 or not. | 174 | * to cfg80211 or not. |
@@ -662,155 +203,24 @@ static bool brcms_c_country_valid(const char *ccode) | |||
662 | return true; | 203 | return true; |
663 | } | 204 | } |
664 | 205 | ||
665 | /* Lookup a country info structure from a null terminated country | 206 | static const struct brcms_regd *brcms_world_regd(const char *regdom, int len) |
666 | * abbreviation and regrev directly with no translation. | ||
667 | */ | ||
668 | static const struct country_info * | ||
669 | brcms_c_country_lookup_direct(const char *ccode, uint regrev) | ||
670 | { | 207 | { |
671 | uint size, i; | 208 | const struct brcms_regd *regd = NULL; |
672 | 209 | int i; | |
673 | /* Should just return 0 for single locale driver. */ | ||
674 | /* Keep it this way in case we add more locales. (for now anyway) */ | ||
675 | |||
676 | /* | ||
677 | * all other country def arrays are for regrev == 0, so if | ||
678 | * regrev is non-zero, fail | ||
679 | */ | ||
680 | if (regrev > 0) | ||
681 | return NULL; | ||
682 | |||
683 | /* find matched table entry from country code */ | ||
684 | size = ARRAY_SIZE(cntry_locales); | ||
685 | for (i = 0; i < size; i++) { | ||
686 | if (strcmp(ccode, cntry_locales[i].abbrev) == 0) | ||
687 | return &cntry_locales[i].country; | ||
688 | } | ||
689 | return NULL; | ||
690 | } | ||
691 | |||
692 | static const struct country_info * | ||
693 | brcms_c_countrycode_map(struct brcms_cm_info *wlc_cm, const char *ccode, | ||
694 | char *mapped_ccode, uint *mapped_regrev) | ||
695 | { | ||
696 | struct brcms_c_info *wlc = wlc_cm->wlc; | ||
697 | const struct country_info *country; | ||
698 | uint srom_regrev = wlc_cm->srom_regrev; | ||
699 | const char *srom_ccode = wlc_cm->srom_ccode; | ||
700 | int mapped; | ||
701 | |||
702 | /* check for currently supported ccode size */ | ||
703 | if (strlen(ccode) > (BRCM_CNTRY_BUF_SZ - 1)) { | ||
704 | wiphy_err(wlc->wiphy, "wl%d: %s: ccode \"%s\" too long for " | ||
705 | "match\n", wlc->pub->unit, __func__, ccode); | ||
706 | return NULL; | ||
707 | } | ||
708 | |||
709 | /* default mapping is the given ccode and regrev 0 */ | ||
710 | strncpy(mapped_ccode, ccode, BRCM_CNTRY_BUF_SZ); | ||
711 | *mapped_regrev = 0; | ||
712 | |||
713 | /* If the desired country code matches the srom country code, | ||
714 | * then the mapped country is the srom regulatory rev. | ||
715 | * Otherwise look for an aggregate mapping. | ||
716 | */ | ||
717 | if (!strcmp(srom_ccode, ccode)) { | ||
718 | *mapped_regrev = srom_regrev; | ||
719 | mapped = 0; | ||
720 | wiphy_err(wlc->wiphy, "srom_code == ccode %s\n", __func__); | ||
721 | } else { | ||
722 | mapped = | ||
723 | brcms_c_country_aggregate_map(wlc_cm, ccode, mapped_ccode, | ||
724 | mapped_regrev); | ||
725 | } | ||
726 | |||
727 | /* find the matching built-in country definition */ | ||
728 | country = brcms_c_country_lookup_direct(mapped_ccode, *mapped_regrev); | ||
729 | |||
730 | /* if there is not an exact rev match, default to rev zero */ | ||
731 | if (country == NULL && *mapped_regrev != 0) { | ||
732 | *mapped_regrev = 0; | ||
733 | country = | ||
734 | brcms_c_country_lookup_direct(mapped_ccode, *mapped_regrev); | ||
735 | } | ||
736 | |||
737 | return country; | ||
738 | } | ||
739 | |||
740 | /* Lookup a country info structure from a null terminated country code | ||
741 | * The lookup is case sensitive. | ||
742 | */ | ||
743 | static const struct country_info * | ||
744 | brcms_c_country_lookup(struct brcms_c_info *wlc, const char *ccode) | ||
745 | { | ||
746 | const struct country_info *country; | ||
747 | char mapped_ccode[BRCM_CNTRY_BUF_SZ]; | ||
748 | uint mapped_regrev; | ||
749 | |||
750 | /* | ||
751 | * map the country code to a built-in country code, regrev, and | ||
752 | * country_info struct | ||
753 | */ | ||
754 | country = brcms_c_countrycode_map(wlc->cmi, ccode, mapped_ccode, | ||
755 | &mapped_regrev); | ||
756 | |||
757 | return country; | ||
758 | } | ||
759 | |||
760 | /* | ||
761 | * reset the quiet channels vector to the union | ||
762 | * of the restricted and radar channel sets | ||
763 | */ | ||
764 | static void brcms_c_quiet_channels_reset(struct brcms_cm_info *wlc_cm) | ||
765 | { | ||
766 | struct brcms_c_info *wlc = wlc_cm->wlc; | ||
767 | uint i, j; | ||
768 | struct brcms_band *band; | ||
769 | const struct brcms_chanvec *chanvec; | ||
770 | |||
771 | memset(&wlc_cm->quiet_channels, 0, sizeof(struct brcms_chanvec)); | ||
772 | |||
773 | band = wlc->band; | ||
774 | for (i = 0; i < wlc->pub->_nbands; | ||
775 | i++, band = wlc->bandstate[OTHERBANDUNIT(wlc)]) { | ||
776 | |||
777 | /* initialize quiet channels for restricted channels */ | ||
778 | chanvec = wlc_cm->bandstate[band->bandunit].restricted_channels; | ||
779 | for (j = 0; j < sizeof(struct brcms_chanvec); j++) | ||
780 | wlc_cm->quiet_channels.vec[j] |= chanvec->vec[j]; | ||
781 | 210 | ||
211 | for (i = 0; i < ARRAY_SIZE(cntry_locales); i++) { | ||
212 | if (!strncmp(regdom, cntry_locales[i].regdomain->alpha2, len)) { | ||
213 | regd = &cntry_locales[i]; | ||
214 | break; | ||
215 | } | ||
782 | } | 216 | } |
783 | } | ||
784 | |||
785 | /* Is the channel valid for the current locale and current band? */ | ||
786 | static bool brcms_c_valid_channel20(struct brcms_cm_info *wlc_cm, uint val) | ||
787 | { | ||
788 | struct brcms_c_info *wlc = wlc_cm->wlc; | ||
789 | 217 | ||
790 | return ((val < MAXCHANNEL) && | 218 | return regd; |
791 | isset(wlc_cm->bandstate[wlc->band->bandunit].valid_channels.vec, | ||
792 | val)); | ||
793 | } | 219 | } |
794 | 220 | ||
795 | /* Is the channel valid for the current locale and specified band? */ | 221 | static const struct brcms_regd *brcms_default_world_regd(void) |
796 | static bool brcms_c_valid_channel20_in_band(struct brcms_cm_info *wlc_cm, | ||
797 | uint bandunit, uint val) | ||
798 | { | ||
799 | return ((val < MAXCHANNEL) | ||
800 | && isset(wlc_cm->bandstate[bandunit].valid_channels.vec, val)); | ||
801 | } | ||
802 | |||
803 | /* Is the channel valid for the current locale? (but don't consider channels not | ||
804 | * available due to bandlocking) | ||
805 | */ | ||
806 | static bool brcms_c_valid_channel20_db(struct brcms_cm_info *wlc_cm, uint val) | ||
807 | { | 222 | { |
808 | struct brcms_c_info *wlc = wlc_cm->wlc; | 223 | return &cntry_locales[0]; |
809 | |||
810 | return brcms_c_valid_channel20(wlc->cmi, val) || | ||
811 | (!wlc->bandlocked | ||
812 | && brcms_c_valid_channel20_in_band(wlc->cmi, | ||
813 | OTHERBANDUNIT(wlc), val)); | ||
814 | } | 224 | } |
815 | 225 | ||
816 | /* JP, J1 - J10 are Japan ccodes */ | 226 | /* JP, J1 - J10 are Japan ccodes */ |
@@ -820,12 +230,6 @@ static bool brcms_c_japan_ccode(const char *ccode) | |||
820 | (ccode[1] == 'P' || (ccode[1] >= '1' && ccode[1] <= '9'))); | 230 | (ccode[1] == 'P' || (ccode[1] >= '1' && ccode[1] <= '9'))); |
821 | } | 231 | } |
822 | 232 | ||
823 | /* Returns true if currently set country is Japan or variant */ | ||
824 | static bool brcms_c_japan(struct brcms_c_info *wlc) | ||
825 | { | ||
826 | return brcms_c_japan_ccode(wlc->cmi->country_abbrev); | ||
827 | } | ||
828 | |||
829 | static void | 233 | static void |
830 | brcms_c_channel_min_txpower_limits_with_local_constraint( | 234 | brcms_c_channel_min_txpower_limits_with_local_constraint( |
831 | struct brcms_cm_info *wlc_cm, struct txpwr_limits *txpwr, | 235 | struct brcms_cm_info *wlc_cm, struct txpwr_limits *txpwr, |
@@ -901,140 +305,16 @@ brcms_c_channel_min_txpower_limits_with_local_constraint( | |||
901 | 305 | ||
902 | } | 306 | } |
903 | 307 | ||
904 | /* Update the radio state (enable/disable) and tx power targets | ||
905 | * based on a new set of channel/regulatory information | ||
906 | */ | ||
907 | static void brcms_c_channels_commit(struct brcms_cm_info *wlc_cm) | ||
908 | { | ||
909 | struct brcms_c_info *wlc = wlc_cm->wlc; | ||
910 | uint chan; | ||
911 | struct txpwr_limits txpwr; | ||
912 | |||
913 | /* search for the existence of any valid channel */ | ||
914 | for (chan = 0; chan < MAXCHANNEL; chan++) { | ||
915 | if (brcms_c_valid_channel20_db(wlc->cmi, chan)) | ||
916 | break; | ||
917 | } | ||
918 | if (chan == MAXCHANNEL) | ||
919 | chan = INVCHANNEL; | ||
920 | |||
921 | /* | ||
922 | * based on the channel search above, set or | ||
923 | * clear WL_RADIO_COUNTRY_DISABLE. | ||
924 | */ | ||
925 | if (chan == INVCHANNEL) { | ||
926 | /* | ||
927 | * country/locale with no valid channels, set | ||
928 | * the radio disable bit | ||
929 | */ | ||
930 | mboolset(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE); | ||
931 | wiphy_err(wlc->wiphy, "wl%d: %s: no valid channel for \"%s\" " | ||
932 | "nbands %d bandlocked %d\n", wlc->pub->unit, | ||
933 | __func__, wlc_cm->country_abbrev, wlc->pub->_nbands, | ||
934 | wlc->bandlocked); | ||
935 | } else if (mboolisset(wlc->pub->radio_disabled, | ||
936 | WL_RADIO_COUNTRY_DISABLE)) { | ||
937 | /* | ||
938 | * country/locale with valid channel, clear | ||
939 | * the radio disable bit | ||
940 | */ | ||
941 | mboolclr(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE); | ||
942 | } | ||
943 | |||
944 | /* | ||
945 | * Now that the country abbreviation is set, if the radio supports 2G, | ||
946 | * then set channel 14 restrictions based on the new locale. | ||
947 | */ | ||
948 | if (wlc->pub->_nbands > 1 || wlc->band->bandtype == BRCM_BAND_2G) | ||
949 | wlc_phy_chanspec_ch14_widefilter_set(wlc->band->pi, | ||
950 | brcms_c_japan(wlc) ? true : | ||
951 | false); | ||
952 | |||
953 | if (wlc->pub->up && chan != INVCHANNEL) { | ||
954 | brcms_c_channel_reg_limits(wlc_cm, wlc->chanspec, &txpwr); | ||
955 | brcms_c_channel_min_txpower_limits_with_local_constraint(wlc_cm, | ||
956 | &txpwr, BRCMS_TXPWR_MAX); | ||
957 | wlc_phy_txpower_limit_set(wlc->band->pi, &txpwr, wlc->chanspec); | ||
958 | } | ||
959 | } | ||
960 | |||
961 | static int | ||
962 | brcms_c_channels_init(struct brcms_cm_info *wlc_cm, | ||
963 | const struct country_info *country) | ||
964 | { | ||
965 | struct brcms_c_info *wlc = wlc_cm->wlc; | ||
966 | uint i, j; | ||
967 | struct brcms_band *band; | ||
968 | const struct locale_info *li; | ||
969 | struct brcms_chanvec sup_chan; | ||
970 | const struct locale_mimo_info *li_mimo; | ||
971 | |||
972 | band = wlc->band; | ||
973 | for (i = 0; i < wlc->pub->_nbands; | ||
974 | i++, band = wlc->bandstate[OTHERBANDUNIT(wlc)]) { | ||
975 | |||
976 | li = (band->bandtype == BRCM_BAND_5G) ? | ||
977 | brcms_c_get_locale_5g(country->locale_5G) : | ||
978 | brcms_c_get_locale_2g(country->locale_2G); | ||
979 | wlc_cm->bandstate[band->bandunit].locale_flags = li->flags; | ||
980 | li_mimo = (band->bandtype == BRCM_BAND_5G) ? | ||
981 | brcms_c_get_mimo_5g(country->locale_mimo_5G) : | ||
982 | brcms_c_get_mimo_2g(country->locale_mimo_2G); | ||
983 | |||
984 | /* merge the mimo non-mimo locale flags */ | ||
985 | wlc_cm->bandstate[band->bandunit].locale_flags |= | ||
986 | li_mimo->flags; | ||
987 | |||
988 | wlc_cm->bandstate[band->bandunit].restricted_channels = | ||
989 | g_table_restricted_chan[li->restricted_channels]; | ||
990 | wlc_cm->bandstate[band->bandunit].radar_channels = | ||
991 | g_table_radar_set[li->radar_channels]; | ||
992 | |||
993 | /* | ||
994 | * set the channel availability, masking out the channels | ||
995 | * that may not be supported on this phy. | ||
996 | */ | ||
997 | wlc_phy_chanspec_band_validch(band->pi, band->bandtype, | ||
998 | &sup_chan); | ||
999 | brcms_c_locale_get_channels(li, | ||
1000 | &wlc_cm->bandstate[band->bandunit]. | ||
1001 | valid_channels); | ||
1002 | for (j = 0; j < sizeof(struct brcms_chanvec); j++) | ||
1003 | wlc_cm->bandstate[band->bandunit].valid_channels. | ||
1004 | vec[j] &= sup_chan.vec[j]; | ||
1005 | } | ||
1006 | |||
1007 | brcms_c_quiet_channels_reset(wlc_cm); | ||
1008 | brcms_c_channels_commit(wlc_cm); | ||
1009 | |||
1010 | return 0; | ||
1011 | } | ||
1012 | |||
1013 | /* | 308 | /* |
1014 | * set the driver's current country and regulatory information | 309 | * set the driver's current country and regulatory information |
1015 | * using a country code as the source. Look up built in country | 310 | * using a country code as the source. Look up built in country |
1016 | * information found with the country code. | 311 | * information found with the country code. |
1017 | */ | 312 | */ |
1018 | static void | 313 | static void |
1019 | brcms_c_set_country_common(struct brcms_cm_info *wlc_cm, | 314 | brcms_c_set_country(struct brcms_cm_info *wlc_cm, |
1020 | const char *country_abbrev, | 315 | const struct brcms_regd *regd) |
1021 | const char *ccode, uint regrev, | ||
1022 | const struct country_info *country) | ||
1023 | { | 316 | { |
1024 | const struct locale_info *locale; | ||
1025 | struct brcms_c_info *wlc = wlc_cm->wlc; | 317 | struct brcms_c_info *wlc = wlc_cm->wlc; |
1026 | char prev_country_abbrev[BRCM_CNTRY_BUF_SZ]; | ||
1027 | |||
1028 | /* save current country state */ | ||
1029 | wlc_cm->country = country; | ||
1030 | |||
1031 | memset(&prev_country_abbrev, 0, BRCM_CNTRY_BUF_SZ); | ||
1032 | strncpy(prev_country_abbrev, wlc_cm->country_abbrev, | ||
1033 | BRCM_CNTRY_BUF_SZ - 1); | ||
1034 | |||
1035 | strncpy(wlc_cm->country_abbrev, country_abbrev, BRCM_CNTRY_BUF_SZ - 1); | ||
1036 | strncpy(wlc_cm->ccode, ccode, BRCM_CNTRY_BUF_SZ - 1); | ||
1037 | wlc_cm->regrev = regrev; | ||
1038 | 318 | ||
1039 | if ((wlc->pub->_n_enab & SUPPORT_11N) != | 319 | if ((wlc->pub->_n_enab & SUPPORT_11N) != |
1040 | wlc->protection->nmode_user) | 320 | wlc->protection->nmode_user) |
@@ -1042,75 +322,19 @@ brcms_c_set_country_common(struct brcms_cm_info *wlc_cm, | |||
1042 | 322 | ||
1043 | brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]); | 323 | brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]); |
1044 | brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]); | 324 | brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]); |
1045 | /* set or restore gmode as required by regulatory */ | ||
1046 | locale = brcms_c_get_locale_2g(country->locale_2G); | ||
1047 | if (locale && (locale->flags & BRCMS_NO_OFDM)) | ||
1048 | brcms_c_set_gmode(wlc, GMODE_LEGACY_B, false); | ||
1049 | else | ||
1050 | brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false); | ||
1051 | 325 | ||
1052 | brcms_c_channels_init(wlc_cm, country); | 326 | brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false); |
1053 | 327 | ||
1054 | return; | 328 | return; |
1055 | } | 329 | } |
1056 | 330 | ||
1057 | static int | ||
1058 | brcms_c_set_countrycode_rev(struct brcms_cm_info *wlc_cm, | ||
1059 | const char *country_abbrev, | ||
1060 | const char *ccode, int regrev) | ||
1061 | { | ||
1062 | const struct country_info *country; | ||
1063 | char mapped_ccode[BRCM_CNTRY_BUF_SZ]; | ||
1064 | uint mapped_regrev; | ||
1065 | |||
1066 | /* if regrev is -1, lookup the mapped country code, | ||
1067 | * otherwise use the ccode and regrev directly | ||
1068 | */ | ||
1069 | if (regrev == -1) { | ||
1070 | /* | ||
1071 | * map the country code to a built-in country | ||
1072 | * code, regrev, and country_info | ||
1073 | */ | ||
1074 | country = | ||
1075 | brcms_c_countrycode_map(wlc_cm, ccode, mapped_ccode, | ||
1076 | &mapped_regrev); | ||
1077 | } else { | ||
1078 | /* find the matching built-in country definition */ | ||
1079 | country = brcms_c_country_lookup_direct(ccode, regrev); | ||
1080 | strncpy(mapped_ccode, ccode, BRCM_CNTRY_BUF_SZ); | ||
1081 | mapped_regrev = regrev; | ||
1082 | } | ||
1083 | |||
1084 | if (country == NULL) | ||
1085 | return -EINVAL; | ||
1086 | |||
1087 | /* set the driver state for the country */ | ||
1088 | brcms_c_set_country_common(wlc_cm, country_abbrev, mapped_ccode, | ||
1089 | mapped_regrev, country); | ||
1090 | |||
1091 | return 0; | ||
1092 | } | ||
1093 | |||
1094 | /* | ||
1095 | * set the driver's current country and regulatory information using | ||
1096 | * a country code as the source. Lookup built in country information | ||
1097 | * found with the country code. | ||
1098 | */ | ||
1099 | static int | ||
1100 | brcms_c_set_countrycode(struct brcms_cm_info *wlc_cm, const char *ccode) | ||
1101 | { | ||
1102 | char country_abbrev[BRCM_CNTRY_BUF_SZ]; | ||
1103 | strncpy(country_abbrev, ccode, BRCM_CNTRY_BUF_SZ); | ||
1104 | return brcms_c_set_countrycode_rev(wlc_cm, country_abbrev, ccode, -1); | ||
1105 | } | ||
1106 | |||
1107 | struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc) | 331 | struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc) |
1108 | { | 332 | { |
1109 | struct brcms_cm_info *wlc_cm; | 333 | struct brcms_cm_info *wlc_cm; |
1110 | char country_abbrev[BRCM_CNTRY_BUF_SZ]; | ||
1111 | const struct country_info *country; | ||
1112 | struct brcms_pub *pub = wlc->pub; | 334 | struct brcms_pub *pub = wlc->pub; |
1113 | struct ssb_sprom *sprom = &wlc->hw->d11core->bus->sprom; | 335 | struct ssb_sprom *sprom = &wlc->hw->d11core->bus->sprom; |
336 | const char *ccode = sprom->alpha2; | ||
337 | int ccode_len = sizeof(sprom->alpha2); | ||
1114 | 338 | ||
1115 | BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); | 339 | BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); |
1116 | 340 | ||
@@ -1122,24 +346,27 @@ struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc) | |||
1122 | wlc->cmi = wlc_cm; | 346 | wlc->cmi = wlc_cm; |
1123 | 347 | ||
1124 | /* store the country code for passing up as a regulatory hint */ | 348 | /* store the country code for passing up as a regulatory hint */ |
1125 | if (sprom->alpha2 && brcms_c_country_valid(sprom->alpha2)) | 349 | wlc_cm->world_regd = brcms_world_regd(ccode, ccode_len); |
1126 | strncpy(wlc->pub->srom_ccode, sprom->alpha2, sizeof(sprom->alpha2)); | 350 | if (brcms_c_country_valid(ccode)) |
351 | strncpy(wlc->pub->srom_ccode, ccode, ccode_len); | ||
1127 | 352 | ||
1128 | /* | 353 | /* |
1129 | * internal country information which must match | 354 | * If no custom world domain is found in the SROM, use the |
1130 | * regulatory constraints in firmware | 355 | * default "X2" domain. |
1131 | */ | 356 | */ |
1132 | memset(country_abbrev, 0, BRCM_CNTRY_BUF_SZ); | 357 | if (!wlc_cm->world_regd) { |
1133 | strncpy(country_abbrev, "X2", sizeof(country_abbrev) - 1); | 358 | wlc_cm->world_regd = brcms_default_world_regd(); |
1134 | country = brcms_c_country_lookup(wlc, country_abbrev); | 359 | ccode = wlc_cm->world_regd->regdomain->alpha2; |
360 | ccode_len = BRCM_CNTRY_BUF_SZ - 1; | ||
361 | } | ||
1135 | 362 | ||
1136 | /* save default country for exiting 11d regulatory mode */ | 363 | /* save default country for exiting 11d regulatory mode */ |
1137 | strncpy(wlc->country_default, country_abbrev, BRCM_CNTRY_BUF_SZ - 1); | 364 | strncpy(wlc->country_default, ccode, ccode_len); |
1138 | 365 | ||
1139 | /* initialize autocountry_default to driver default */ | 366 | /* initialize autocountry_default to driver default */ |
1140 | strncpy(wlc->autocountry_default, "X2", BRCM_CNTRY_BUF_SZ - 1); | 367 | strncpy(wlc->autocountry_default, ccode, ccode_len); |
1141 | 368 | ||
1142 | brcms_c_set_countrycode(wlc_cm, country_abbrev); | 369 | brcms_c_set_country(wlc_cm, wlc_cm->world_regd); |
1143 | 370 | ||
1144 | return wlc_cm; | 371 | return wlc_cm; |
1145 | } | 372 | } |
@@ -1149,31 +376,15 @@ void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm) | |||
1149 | kfree(wlc_cm); | 376 | kfree(wlc_cm); |
1150 | } | 377 | } |
1151 | 378 | ||
1152 | u8 | ||
1153 | brcms_c_channel_locale_flags_in_band(struct brcms_cm_info *wlc_cm, | ||
1154 | uint bandunit) | ||
1155 | { | ||
1156 | return wlc_cm->bandstate[bandunit].locale_flags; | ||
1157 | } | ||
1158 | |||
1159 | static bool | ||
1160 | brcms_c_quiet_chanspec(struct brcms_cm_info *wlc_cm, u16 chspec) | ||
1161 | { | ||
1162 | return (wlc_cm->wlc->pub->_n_enab & SUPPORT_11N) && | ||
1163 | CHSPEC_IS40(chspec) ? | ||
1164 | (isset(wlc_cm->quiet_channels.vec, | ||
1165 | lower_20_sb(CHSPEC_CHANNEL(chspec))) || | ||
1166 | isset(wlc_cm->quiet_channels.vec, | ||
1167 | upper_20_sb(CHSPEC_CHANNEL(chspec)))) : | ||
1168 | isset(wlc_cm->quiet_channels.vec, CHSPEC_CHANNEL(chspec)); | ||
1169 | } | ||
1170 | |||
1171 | void | 379 | void |
1172 | brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec, | 380 | brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec, |
1173 | u8 local_constraint_qdbm) | 381 | u8 local_constraint_qdbm) |
1174 | { | 382 | { |
1175 | struct brcms_c_info *wlc = wlc_cm->wlc; | 383 | struct brcms_c_info *wlc = wlc_cm->wlc; |
384 | struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.channel; | ||
385 | const struct ieee80211_reg_rule *reg_rule; | ||
1176 | struct txpwr_limits txpwr; | 386 | struct txpwr_limits txpwr; |
387 | int ret; | ||
1177 | 388 | ||
1178 | brcms_c_channel_reg_limits(wlc_cm, chanspec, &txpwr); | 389 | brcms_c_channel_reg_limits(wlc_cm, chanspec, &txpwr); |
1179 | 390 | ||
@@ -1181,8 +392,15 @@ brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec, | |||
1181 | wlc_cm, &txpwr, local_constraint_qdbm | 392 | wlc_cm, &txpwr, local_constraint_qdbm |
1182 | ); | 393 | ); |
1183 | 394 | ||
395 | /* set or restore gmode as required by regulatory */ | ||
396 | ret = freq_reg_info(wlc->wiphy, ch->center_freq, 0, ®_rule); | ||
397 | if (!ret && (reg_rule->flags & NL80211_RRF_NO_OFDM)) | ||
398 | brcms_c_set_gmode(wlc, GMODE_LEGACY_B, false); | ||
399 | else | ||
400 | brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false); | ||
401 | |||
1184 | brcms_b_set_chanspec(wlc->hw, chanspec, | 402 | brcms_b_set_chanspec(wlc->hw, chanspec, |
1185 | (brcms_c_quiet_chanspec(wlc_cm, chanspec) != 0), | 403 | !!(ch->flags & IEEE80211_CHAN_PASSIVE_SCAN), |
1186 | &txpwr); | 404 | &txpwr); |
1187 | } | 405 | } |
1188 | 406 | ||
@@ -1191,15 +409,14 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec, | |||
1191 | struct txpwr_limits *txpwr) | 409 | struct txpwr_limits *txpwr) |
1192 | { | 410 | { |
1193 | struct brcms_c_info *wlc = wlc_cm->wlc; | 411 | struct brcms_c_info *wlc = wlc_cm->wlc; |
412 | struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.channel; | ||
1194 | uint i; | 413 | uint i; |
1195 | uint chan; | 414 | uint chan; |
1196 | int maxpwr; | 415 | int maxpwr; |
1197 | int delta; | 416 | int delta; |
1198 | const struct country_info *country; | 417 | const struct country_info *country; |
1199 | struct brcms_band *band; | 418 | struct brcms_band *band; |
1200 | const struct locale_info *li; | ||
1201 | int conducted_max = BRCMS_TXPWR_MAX; | 419 | int conducted_max = BRCMS_TXPWR_MAX; |
1202 | int conducted_ofdm_max = BRCMS_TXPWR_MAX; | ||
1203 | const struct locale_mimo_info *li_mimo; | 420 | const struct locale_mimo_info *li_mimo; |
1204 | int maxpwr20, maxpwr40; | 421 | int maxpwr20, maxpwr40; |
1205 | int maxpwr_idx; | 422 | int maxpwr_idx; |
@@ -1207,67 +424,35 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec, | |||
1207 | 424 | ||
1208 | memset(txpwr, 0, sizeof(struct txpwr_limits)); | 425 | memset(txpwr, 0, sizeof(struct txpwr_limits)); |
1209 | 426 | ||
1210 | if (!brcms_c_valid_chanspec_db(wlc_cm, chanspec)) { | 427 | if (WARN_ON(!ch)) |
1211 | country = brcms_c_country_lookup(wlc, wlc->autocountry_default); | 428 | return; |
1212 | if (country == NULL) | 429 | |
1213 | return; | 430 | country = &wlc_cm->world_regd->country; |
1214 | } else { | ||
1215 | country = wlc_cm->country; | ||
1216 | } | ||
1217 | 431 | ||
1218 | chan = CHSPEC_CHANNEL(chanspec); | 432 | chan = CHSPEC_CHANNEL(chanspec); |
1219 | band = wlc->bandstate[chspec_bandunit(chanspec)]; | 433 | band = wlc->bandstate[chspec_bandunit(chanspec)]; |
1220 | li = (band->bandtype == BRCM_BAND_5G) ? | ||
1221 | brcms_c_get_locale_5g(country->locale_5G) : | ||
1222 | brcms_c_get_locale_2g(country->locale_2G); | ||
1223 | |||
1224 | li_mimo = (band->bandtype == BRCM_BAND_5G) ? | 434 | li_mimo = (band->bandtype == BRCM_BAND_5G) ? |
1225 | brcms_c_get_mimo_5g(country->locale_mimo_5G) : | 435 | brcms_c_get_mimo_5g(country->locale_mimo_5G) : |
1226 | brcms_c_get_mimo_2g(country->locale_mimo_2G); | 436 | brcms_c_get_mimo_2g(country->locale_mimo_2G); |
1227 | 437 | ||
1228 | if (li->flags & BRCMS_EIRP) { | 438 | delta = band->antgain; |
1229 | delta = band->antgain; | ||
1230 | } else { | ||
1231 | delta = 0; | ||
1232 | if (band->antgain > QDB(6)) | ||
1233 | delta = band->antgain - QDB(6); /* Excess over 6 dB */ | ||
1234 | } | ||
1235 | 439 | ||
1236 | if (li == &locale_i) { | 440 | if (band->bandtype == BRCM_BAND_2G) |
1237 | conducted_max = QDB(22); | 441 | conducted_max = QDB(22); |
1238 | conducted_ofdm_max = QDB(22); | 442 | |
1239 | } | 443 | maxpwr = QDB(ch->max_power) - delta; |
444 | maxpwr = max(maxpwr, 0); | ||
445 | maxpwr = min(maxpwr, conducted_max); | ||
1240 | 446 | ||
1241 | /* CCK txpwr limits for 2.4G band */ | 447 | /* CCK txpwr limits for 2.4G band */ |
1242 | if (band->bandtype == BRCM_BAND_2G) { | 448 | if (band->bandtype == BRCM_BAND_2G) { |
1243 | maxpwr = li->maxpwr[CHANNEL_POWER_IDX_2G_CCK(chan)]; | ||
1244 | |||
1245 | maxpwr = maxpwr - delta; | ||
1246 | maxpwr = max(maxpwr, 0); | ||
1247 | maxpwr = min(maxpwr, conducted_max); | ||
1248 | |||
1249 | for (i = 0; i < BRCMS_NUM_RATES_CCK; i++) | 449 | for (i = 0; i < BRCMS_NUM_RATES_CCK; i++) |
1250 | txpwr->cck[i] = (u8) maxpwr; | 450 | txpwr->cck[i] = (u8) maxpwr; |
1251 | } | 451 | } |
1252 | 452 | ||
1253 | /* OFDM txpwr limits for 2.4G or 5G bands */ | 453 | for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) { |
1254 | if (band->bandtype == BRCM_BAND_2G) | ||
1255 | maxpwr = li->maxpwr[CHANNEL_POWER_IDX_2G_OFDM(chan)]; | ||
1256 | else | ||
1257 | maxpwr = li->maxpwr[CHANNEL_POWER_IDX_5G(chan)]; | ||
1258 | |||
1259 | maxpwr = maxpwr - delta; | ||
1260 | maxpwr = max(maxpwr, 0); | ||
1261 | maxpwr = min(maxpwr, conducted_ofdm_max); | ||
1262 | |||
1263 | /* Keep OFDM lmit below CCK limit */ | ||
1264 | if (band->bandtype == BRCM_BAND_2G) | ||
1265 | maxpwr = min_t(int, maxpwr, txpwr->cck[0]); | ||
1266 | |||
1267 | for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) | ||
1268 | txpwr->ofdm[i] = (u8) maxpwr; | 454 | txpwr->ofdm[i] = (u8) maxpwr; |
1269 | 455 | ||
1270 | for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) { | ||
1271 | /* | 456 | /* |
1272 | * OFDM 40 MHz SISO has the same power as the corresponding | 457 | * OFDM 40 MHz SISO has the same power as the corresponding |
1273 | * MCS0-7 rate unless overriden by the locale specific code. | 458 | * MCS0-7 rate unless overriden by the locale specific code. |
@@ -1282,14 +467,9 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec, | |||
1282 | txpwr->ofdm_40_cdd[i] = 0; | 467 | txpwr->ofdm_40_cdd[i] = 0; |
1283 | } | 468 | } |
1284 | 469 | ||
1285 | /* MIMO/HT specific limits */ | 470 | delta = 0; |
1286 | if (li_mimo->flags & BRCMS_EIRP) { | 471 | if (band->antgain > QDB(6)) |
1287 | delta = band->antgain; | 472 | delta = band->antgain - QDB(6); /* Excess over 6 dB */ |
1288 | } else { | ||
1289 | delta = 0; | ||
1290 | if (band->antgain > QDB(6)) | ||
1291 | delta = band->antgain - QDB(6); /* Excess over 6 dB */ | ||
1292 | } | ||
1293 | 473 | ||
1294 | if (band->bandtype == BRCM_BAND_2G) | 474 | if (band->bandtype == BRCM_BAND_2G) |
1295 | maxpwr_idx = (chan - 1); | 475 | maxpwr_idx = (chan - 1); |
@@ -1431,8 +611,7 @@ static bool brcms_c_chspec_malformed(u16 chanspec) | |||
1431 | * and they are also a legal HT combination | 611 | * and they are also a legal HT combination |
1432 | */ | 612 | */ |
1433 | static bool | 613 | static bool |
1434 | brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, u16 chspec, | 614 | brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, u16 chspec) |
1435 | bool dualband) | ||
1436 | { | 615 | { |
1437 | struct brcms_c_info *wlc = wlc_cm->wlc; | 616 | struct brcms_c_info *wlc = wlc_cm->wlc; |
1438 | u8 channel = CHSPEC_CHANNEL(chspec); | 617 | u8 channel = CHSPEC_CHANNEL(chspec); |
@@ -1448,59 +627,166 @@ brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, u16 chspec, | |||
1448 | chspec_bandunit(chspec)) | 627 | chspec_bandunit(chspec)) |
1449 | return false; | 628 | return false; |
1450 | 629 | ||
1451 | /* Check a 20Mhz channel */ | 630 | return true; |
1452 | if (CHSPEC_IS20(chspec)) { | 631 | } |
1453 | if (dualband) | 632 | |
1454 | return brcms_c_valid_channel20_db(wlc_cm->wlc->cmi, | 633 | bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm, u16 chspec) |
1455 | channel); | 634 | { |
1456 | else | 635 | return brcms_c_valid_chanspec_ext(wlc_cm, chspec); |
1457 | return brcms_c_valid_channel20(wlc_cm->wlc->cmi, | 636 | } |
1458 | channel); | 637 | |
638 | static bool brcms_is_radar_freq(u16 center_freq) | ||
639 | { | ||
640 | return center_freq >= 5260 && center_freq <= 5700; | ||
641 | } | ||
642 | |||
643 | static void brcms_reg_apply_radar_flags(struct wiphy *wiphy) | ||
644 | { | ||
645 | struct ieee80211_supported_band *sband; | ||
646 | struct ieee80211_channel *ch; | ||
647 | int i; | ||
648 | |||
649 | sband = wiphy->bands[IEEE80211_BAND_5GHZ]; | ||
650 | if (!sband) | ||
651 | return; | ||
652 | |||
653 | for (i = 0; i < sband->n_channels; i++) { | ||
654 | ch = &sband->channels[i]; | ||
655 | |||
656 | if (!brcms_is_radar_freq(ch->center_freq)) | ||
657 | continue; | ||
658 | |||
659 | /* | ||
660 | * All channels in this range should be passive and have | ||
661 | * DFS enabled. | ||
662 | */ | ||
663 | if (!(ch->flags & IEEE80211_CHAN_DISABLED)) | ||
664 | ch->flags |= IEEE80211_CHAN_RADAR | | ||
665 | IEEE80211_CHAN_NO_IBSS | | ||
666 | IEEE80211_CHAN_PASSIVE_SCAN; | ||
1459 | } | 667 | } |
1460 | #ifdef SUPPORT_40MHZ | 668 | } |
1461 | /* | 669 | |
1462 | * We know we are now checking a 40MHZ channel, so we should | 670 | static void |
1463 | * only be here for NPHYS | 671 | brcms_reg_apply_beaconing_flags(struct wiphy *wiphy, |
1464 | */ | 672 | enum nl80211_reg_initiator initiator) |
1465 | if (BRCMS_ISNPHY(wlc->band) || BRCMS_ISSSLPNPHY(wlc->band)) { | 673 | { |
1466 | u8 upper_sideband = 0, idx; | 674 | struct ieee80211_supported_band *sband; |
1467 | u8 num_ch20_entries = | 675 | struct ieee80211_channel *ch; |
1468 | sizeof(chan20_info) / sizeof(struct chan20_info); | 676 | const struct ieee80211_reg_rule *rule; |
1469 | 677 | int band, i, ret; | |
1470 | if (!VALID_40CHANSPEC_IN_BAND(wlc, chspec_bandunit(chspec))) | 678 | |
1471 | return false; | 679 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { |
1472 | 680 | sband = wiphy->bands[band]; | |
1473 | if (dualband) { | 681 | if (!sband) |
1474 | if (!brcms_c_valid_channel20_db(wlc->cmi, | 682 | continue; |
1475 | lower_20_sb(channel)) || | 683 | |
1476 | !brcms_c_valid_channel20_db(wlc->cmi, | 684 | for (i = 0; i < sband->n_channels; i++) { |
1477 | upper_20_sb(channel))) | 685 | ch = &sband->channels[i]; |
1478 | return false; | 686 | |
1479 | } else { | 687 | if (ch->flags & |
1480 | if (!brcms_c_valid_channel20(wlc->cmi, | 688 | (IEEE80211_CHAN_DISABLED | IEEE80211_CHAN_RADAR)) |
1481 | lower_20_sb(channel)) || | 689 | continue; |
1482 | !brcms_c_valid_channel20(wlc->cmi, | 690 | |
1483 | upper_20_sb(channel))) | 691 | if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) { |
1484 | return false; | 692 | ret = freq_reg_info(wiphy, ch->center_freq, |
693 | 0, &rule); | ||
694 | if (ret) | ||
695 | continue; | ||
696 | |||
697 | if (!(rule->flags & NL80211_RRF_NO_IBSS)) | ||
698 | ch->flags &= ~IEEE80211_CHAN_NO_IBSS; | ||
699 | if (!(rule->flags & NL80211_RRF_PASSIVE_SCAN)) | ||
700 | ch->flags &= | ||
701 | ~IEEE80211_CHAN_PASSIVE_SCAN; | ||
702 | } else if (ch->beacon_found) { | ||
703 | ch->flags &= ~(IEEE80211_CHAN_NO_IBSS | | ||
704 | IEEE80211_CHAN_PASSIVE_SCAN); | ||
705 | } | ||
1485 | } | 706 | } |
707 | } | ||
708 | } | ||
1486 | 709 | ||
1487 | /* find the lower sideband info in the sideband array */ | 710 | static int brcms_reg_notifier(struct wiphy *wiphy, |
1488 | for (idx = 0; idx < num_ch20_entries; idx++) { | 711 | struct regulatory_request *request) |
1489 | if (chan20_info[idx].sb == lower_20_sb(channel)) | 712 | { |
1490 | upper_sideband = chan20_info[idx].adj_sbs; | 713 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); |
714 | struct brcms_info *wl = hw->priv; | ||
715 | struct brcms_c_info *wlc = wl->wlc; | ||
716 | struct ieee80211_supported_band *sband; | ||
717 | struct ieee80211_channel *ch; | ||
718 | int band, i; | ||
719 | bool ch_found = false; | ||
720 | |||
721 | brcms_reg_apply_radar_flags(wiphy); | ||
722 | |||
723 | if (request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) | ||
724 | brcms_reg_apply_beaconing_flags(wiphy, request->initiator); | ||
725 | |||
726 | /* Disable radio if all channels disallowed by regulatory */ | ||
727 | for (band = 0; !ch_found && band < IEEE80211_NUM_BANDS; band++) { | ||
728 | sband = wiphy->bands[band]; | ||
729 | if (!sband) | ||
730 | continue; | ||
731 | |||
732 | for (i = 0; !ch_found && i < sband->n_channels; i++) { | ||
733 | ch = &sband->channels[i]; | ||
734 | |||
735 | if (!(ch->flags & IEEE80211_CHAN_DISABLED)) | ||
736 | ch_found = true; | ||
1491 | } | 737 | } |
1492 | /* check that the lower sideband allows an upper sideband */ | ||
1493 | if ((upper_sideband & (CH_UPPER_SB | CH_EWA_VALID)) == | ||
1494 | (CH_UPPER_SB | CH_EWA_VALID)) | ||
1495 | return true; | ||
1496 | return false; | ||
1497 | } | 738 | } |
1498 | #endif /* 40 MHZ */ | ||
1499 | 739 | ||
1500 | return false; | 740 | if (ch_found) { |
741 | mboolclr(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE); | ||
742 | } else { | ||
743 | mboolset(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE); | ||
744 | wiphy_err(wlc->wiphy, "wl%d: %s: no valid channel for \"%s\"\n", | ||
745 | wlc->pub->unit, __func__, request->alpha2); | ||
746 | } | ||
747 | |||
748 | if (wlc->pub->_nbands > 1 || wlc->band->bandtype == BRCM_BAND_2G) | ||
749 | wlc_phy_chanspec_ch14_widefilter_set(wlc->band->pi, | ||
750 | brcms_c_japan_ccode(request->alpha2)); | ||
751 | |||
752 | return 0; | ||
1501 | } | 753 | } |
1502 | 754 | ||
1503 | bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm, u16 chspec) | 755 | void brcms_c_regd_init(struct brcms_c_info *wlc) |
1504 | { | 756 | { |
1505 | return brcms_c_valid_chanspec_ext(wlc_cm, chspec, true); | 757 | struct wiphy *wiphy = wlc->wiphy; |
758 | const struct brcms_regd *regd = wlc->cmi->world_regd; | ||
759 | struct ieee80211_supported_band *sband; | ||
760 | struct ieee80211_channel *ch; | ||
761 | struct brcms_chanvec sup_chan; | ||
762 | struct brcms_band *band; | ||
763 | int band_idx, i; | ||
764 | |||
765 | /* Disable any channels not supported by the phy */ | ||
766 | for (band_idx = 0; band_idx < IEEE80211_NUM_BANDS; band_idx++) { | ||
767 | if (band_idx == IEEE80211_BAND_2GHZ) | ||
768 | band = wlc->bandstate[BAND_2G_INDEX]; | ||
769 | else | ||
770 | band = wlc->bandstate[BAND_5G_INDEX]; | ||
771 | |||
772 | /* skip if band not initialized */ | ||
773 | if (band->pi == NULL) | ||
774 | continue; | ||
775 | |||
776 | wlc_phy_chanspec_band_validch(band->pi, band->bandtype, | ||
777 | &sup_chan); | ||
778 | |||
779 | sband = wiphy->bands[band_idx]; | ||
780 | for (i = 0; i < sband->n_channels; i++) { | ||
781 | ch = &sband->channels[i]; | ||
782 | if (!isset(sup_chan.vec, ch->hw_value)) | ||
783 | ch->flags |= IEEE80211_CHAN_DISABLED; | ||
784 | } | ||
785 | } | ||
786 | |||
787 | wlc->wiphy->reg_notifier = brcms_reg_notifier; | ||
788 | wlc->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | | ||
789 | WIPHY_FLAG_STRICT_REGULATORY; | ||
790 | wiphy_apply_custom_regulatory(wlc->wiphy, regd->regdomain); | ||
791 | brcms_reg_apply_beaconing_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER); | ||
1506 | } | 792 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.h b/drivers/net/wireless/brcm80211/brcmsmac/channel.h index 808cb4fbfbe..006483a0abe 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/channel.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.h | |||
@@ -37,9 +37,6 @@ brcms_c_channel_mgr_attach(struct brcms_c_info *wlc); | |||
37 | 37 | ||
38 | extern void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm); | 38 | extern void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm); |
39 | 39 | ||
40 | extern u8 brcms_c_channel_locale_flags_in_band(struct brcms_cm_info *wlc_cm, | ||
41 | uint bandunit); | ||
42 | |||
43 | extern bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm, | 40 | extern bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm, |
44 | u16 chspec); | 41 | u16 chspec); |
45 | 42 | ||
@@ -49,5 +46,6 @@ extern void brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, | |||
49 | extern void brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, | 46 | extern void brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, |
50 | u16 chanspec, | 47 | u16 chanspec, |
51 | u8 local_constraint_qdbm); | 48 | u8 local_constraint_qdbm); |
49 | extern void brcms_c_regd_init(struct brcms_c_info *wlc); | ||
52 | 50 | ||
53 | #endif /* _WLC_CHANNEL_H */ | 51 | #endif /* _WLC_CHANNEL_H */ |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index 50f92a0b7c4..2d5a4041269 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | |||
@@ -721,14 +721,6 @@ static const struct ieee80211_ops brcms_ops = { | |||
721 | .flush = brcms_ops_flush, | 721 | .flush = brcms_ops_flush, |
722 | }; | 722 | }; |
723 | 723 | ||
724 | /* | ||
725 | * is called in brcms_bcma_probe() context, therefore no locking required. | ||
726 | */ | ||
727 | static int brcms_set_hint(struct brcms_info *wl, char *abbrev) | ||
728 | { | ||
729 | return regulatory_hint(wl->pub->ieee_hw->wiphy, abbrev); | ||
730 | } | ||
731 | |||
732 | void brcms_dpc(unsigned long data) | 724 | void brcms_dpc(unsigned long data) |
733 | { | 725 | { |
734 | struct brcms_info *wl; | 726 | struct brcms_info *wl; |
@@ -1058,6 +1050,8 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev) | |||
1058 | goto fail; | 1050 | goto fail; |
1059 | } | 1051 | } |
1060 | 1052 | ||
1053 | brcms_c_regd_init(wl->wlc); | ||
1054 | |||
1061 | memcpy(perm, &wl->pub->cur_etheraddr, ETH_ALEN); | 1055 | memcpy(perm, &wl->pub->cur_etheraddr, ETH_ALEN); |
1062 | if (WARN_ON(!is_valid_ether_addr(perm))) | 1056 | if (WARN_ON(!is_valid_ether_addr(perm))) |
1063 | goto fail; | 1057 | goto fail; |
@@ -1068,9 +1062,9 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev) | |||
1068 | wiphy_err(wl->wiphy, "%s: ieee80211_register_hw failed, status" | 1062 | wiphy_err(wl->wiphy, "%s: ieee80211_register_hw failed, status" |
1069 | "%d\n", __func__, err); | 1063 | "%d\n", __func__, err); |
1070 | 1064 | ||
1071 | if (wl->pub->srom_ccode[0] && brcms_set_hint(wl, wl->pub->srom_ccode)) | 1065 | if (wl->pub->srom_ccode[0] && |
1072 | wiphy_err(wl->wiphy, "%s: regulatory_hint failed, status %d\n", | 1066 | regulatory_hint(wl->wiphy, wl->pub->srom_ccode)) |
1073 | __func__, err); | 1067 | wiphy_err(wl->wiphy, "%s: regulatory hint failed\n", __func__); |
1074 | 1068 | ||
1075 | n_adapters_found++; | 1069 | n_adapters_found++; |
1076 | return wl; | 1070 | return wl; |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c index 19db4052c44..8776fbc8dcf 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c | |||
@@ -18,6 +18,7 @@ | |||
18 | 18 | ||
19 | #include <linux/pci_ids.h> | 19 | #include <linux/pci_ids.h> |
20 | #include <linux/if_ether.h> | 20 | #include <linux/if_ether.h> |
21 | #include <net/cfg80211.h> | ||
21 | #include <net/mac80211.h> | 22 | #include <net/mac80211.h> |
22 | #include <brcm_hw_ids.h> | 23 | #include <brcm_hw_ids.h> |
23 | #include <aiutils.h> | 24 | #include <aiutils.h> |
@@ -3139,20 +3140,6 @@ void brcms_c_reset(struct brcms_c_info *wlc) | |||
3139 | brcms_b_reset(wlc->hw); | 3140 | brcms_b_reset(wlc->hw); |
3140 | } | 3141 | } |
3141 | 3142 | ||
3142 | /* Return the channel the driver should initialize during brcms_c_init. | ||
3143 | * the channel may have to be changed from the currently configured channel | ||
3144 | * if other configurations are in conflict (bandlocked, 11n mode disabled, | ||
3145 | * invalid channel for current country, etc.) | ||
3146 | */ | ||
3147 | static u16 brcms_c_init_chanspec(struct brcms_c_info *wlc) | ||
3148 | { | ||
3149 | u16 chanspec = | ||
3150 | 1 | WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE | | ||
3151 | WL_CHANSPEC_BAND_2G; | ||
3152 | |||
3153 | return chanspec; | ||
3154 | } | ||
3155 | |||
3156 | void brcms_c_init_scb(struct scb *scb) | 3143 | void brcms_c_init_scb(struct scb *scb) |
3157 | { | 3144 | { |
3158 | int i; | 3145 | int i; |
@@ -5129,6 +5116,8 @@ static void brcms_c_wme_retries_write(struct brcms_c_info *wlc) | |||
5129 | /* make interface operational */ | 5116 | /* make interface operational */ |
5130 | int brcms_c_up(struct brcms_c_info *wlc) | 5117 | int brcms_c_up(struct brcms_c_info *wlc) |
5131 | { | 5118 | { |
5119 | struct ieee80211_channel *ch; | ||
5120 | |||
5132 | BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); | 5121 | BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); |
5133 | 5122 | ||
5134 | /* HW is turned off so don't try to access it */ | 5123 | /* HW is turned off so don't try to access it */ |
@@ -5195,8 +5184,9 @@ int brcms_c_up(struct brcms_c_info *wlc) | |||
5195 | wlc->pub->up = true; | 5184 | wlc->pub->up = true; |
5196 | 5185 | ||
5197 | if (wlc->bandinit_pending) { | 5186 | if (wlc->bandinit_pending) { |
5187 | ch = wlc->pub->ieee_hw->conf.channel; | ||
5198 | brcms_c_suspend_mac_and_wait(wlc); | 5188 | brcms_c_suspend_mac_and_wait(wlc); |
5199 | brcms_c_set_chanspec(wlc, wlc->default_bss->chanspec); | 5189 | brcms_c_set_chanspec(wlc, ch20mhz_chspec(ch->hw_value)); |
5200 | wlc->bandinit_pending = false; | 5190 | wlc->bandinit_pending = false; |
5201 | brcms_c_enable_mac(wlc); | 5191 | brcms_c_enable_mac(wlc); |
5202 | } | 5192 | } |
@@ -5397,11 +5387,6 @@ int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config) | |||
5397 | else | 5387 | else |
5398 | return -EINVAL; | 5388 | return -EINVAL; |
5399 | 5389 | ||
5400 | /* Legacy or bust when no OFDM is supported by regulatory */ | ||
5401 | if ((brcms_c_channel_locale_flags_in_band(wlc->cmi, band->bandunit) & | ||
5402 | BRCMS_NO_OFDM) && (gmode != GMODE_LEGACY_B)) | ||
5403 | return -EINVAL; | ||
5404 | |||
5405 | /* update configuration value */ | 5390 | /* update configuration value */ |
5406 | if (config) | 5391 | if (config) |
5407 | brcms_c_protection_upd(wlc, BRCMS_PROT_G_USER, gmode); | 5392 | brcms_c_protection_upd(wlc, BRCMS_PROT_G_USER, gmode); |
@@ -8201,19 +8186,12 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded) | |||
8201 | void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx) | 8186 | void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx) |
8202 | { | 8187 | { |
8203 | struct bcma_device *core = wlc->hw->d11core; | 8188 | struct bcma_device *core = wlc->hw->d11core; |
8189 | struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.channel; | ||
8204 | u16 chanspec; | 8190 | u16 chanspec; |
8205 | 8191 | ||
8206 | BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); | 8192 | BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); |
8207 | 8193 | ||
8208 | /* | 8194 | chanspec = ch20mhz_chspec(ch->hw_value); |
8209 | * This will happen if a big-hammer was executed. In | ||
8210 | * that case, we want to go back to the channel that | ||
8211 | * we were on and not new channel | ||
8212 | */ | ||
8213 | if (wlc->pub->associated) | ||
8214 | chanspec = wlc->home_chanspec; | ||
8215 | else | ||
8216 | chanspec = brcms_c_init_chanspec(wlc); | ||
8217 | 8195 | ||
8218 | brcms_b_init(wlc->hw, chanspec); | 8196 | brcms_b_init(wlc->hw, chanspec); |
8219 | 8197 | ||
diff --git a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h index 333193f20e1..bcc79b4e326 100644 --- a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h +++ b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h | |||
@@ -37,5 +37,6 @@ | |||
37 | #define BCM4329_CHIP_ID 0x4329 | 37 | #define BCM4329_CHIP_ID 0x4329 |
38 | #define BCM4330_CHIP_ID 0x4330 | 38 | #define BCM4330_CHIP_ID 0x4330 |
39 | #define BCM4331_CHIP_ID 0x4331 | 39 | #define BCM4331_CHIP_ID 0x4331 |
40 | #define BCM4334_CHIP_ID 0x4334 | ||
40 | 41 | ||
41 | #endif /* _BRCM_HW_IDS_H_ */ | 42 | #endif /* _BRCM_HW_IDS_H_ */ |
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 9cfae0c0870..95aa8e1683e 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c | |||
@@ -1903,14 +1903,6 @@ static void ipw2100_down(struct ipw2100_priv *priv) | |||
1903 | netif_stop_queue(priv->net_dev); | 1903 | netif_stop_queue(priv->net_dev); |
1904 | } | 1904 | } |
1905 | 1905 | ||
1906 | /* Called by register_netdev() */ | ||
1907 | static int ipw2100_net_init(struct net_device *dev) | ||
1908 | { | ||
1909 | struct ipw2100_priv *priv = libipw_priv(dev); | ||
1910 | |||
1911 | return ipw2100_up(priv, 1); | ||
1912 | } | ||
1913 | |||
1914 | static int ipw2100_wdev_init(struct net_device *dev) | 1906 | static int ipw2100_wdev_init(struct net_device *dev) |
1915 | { | 1907 | { |
1916 | struct ipw2100_priv *priv = libipw_priv(dev); | 1908 | struct ipw2100_priv *priv = libipw_priv(dev); |
@@ -6087,7 +6079,6 @@ static const struct net_device_ops ipw2100_netdev_ops = { | |||
6087 | .ndo_stop = ipw2100_close, | 6079 | .ndo_stop = ipw2100_close, |
6088 | .ndo_start_xmit = libipw_xmit, | 6080 | .ndo_start_xmit = libipw_xmit, |
6089 | .ndo_change_mtu = libipw_change_mtu, | 6081 | .ndo_change_mtu = libipw_change_mtu, |
6090 | .ndo_init = ipw2100_net_init, | ||
6091 | .ndo_tx_timeout = ipw2100_tx_timeout, | 6082 | .ndo_tx_timeout = ipw2100_tx_timeout, |
6092 | .ndo_set_mac_address = ipw2100_set_address, | 6083 | .ndo_set_mac_address = ipw2100_set_address, |
6093 | .ndo_validate_addr = eth_validate_addr, | 6084 | .ndo_validate_addr = eth_validate_addr, |
@@ -6329,6 +6320,10 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, | |||
6329 | printk(KERN_INFO DRV_NAME | 6320 | printk(KERN_INFO DRV_NAME |
6330 | ": Detected Intel PRO/Wireless 2100 Network Connection\n"); | 6321 | ": Detected Intel PRO/Wireless 2100 Network Connection\n"); |
6331 | 6322 | ||
6323 | err = ipw2100_up(priv, 1); | ||
6324 | if (err) | ||
6325 | goto fail; | ||
6326 | |||
6332 | err = ipw2100_wdev_init(dev); | 6327 | err = ipw2100_wdev_init(dev); |
6333 | if (err) | 6328 | if (err) |
6334 | goto fail; | 6329 | goto fail; |
@@ -6338,12 +6333,7 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, | |||
6338 | * network device we would call ipw2100_up. This introduced a race | 6333 | * network device we would call ipw2100_up. This introduced a race |
6339 | * condition with newer hotplug configurations (network was coming | 6334 | * condition with newer hotplug configurations (network was coming |
6340 | * up and making calls before the device was initialized). | 6335 | * up and making calls before the device was initialized). |
6341 | * | 6336 | */ |
6342 | * If we called ipw2100_up before we registered the device, then the | ||
6343 | * device name wasn't registered. So, we instead use the net_dev->init | ||
6344 | * member to call a function that then just turns and calls ipw2100_up. | ||
6345 | * net_dev->init is called after name allocation but before the | ||
6346 | * notifier chain is called */ | ||
6347 | err = register_netdev(dev); | 6337 | err = register_netdev(dev); |
6348 | if (err) { | 6338 | if (err) { |
6349 | printk(KERN_WARNING DRV_NAME | 6339 | printk(KERN_WARNING DRV_NAME |
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 931002738c9..170ec330d2a 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile | |||
@@ -1,31 +1,19 @@ | |||
1 | # DVM | 1 | # common |
2 | obj-$(CONFIG_IWLDVM) += iwldvm.o | ||
3 | iwldvm-objs := iwl-agn.o iwl-agn-rs.o iwl-mac80211.o | ||
4 | iwldvm-objs += iwl-ucode.o iwl-agn-tx.o | ||
5 | iwldvm-objs += iwl-agn-lib.o iwl-agn-calib.o | ||
6 | iwldvm-objs += iwl-agn-tt.o iwl-agn-sta.o iwl-agn-rx.o | ||
7 | iwldvm-objs += iwl-eeprom.o iwl-power.o | ||
8 | iwldvm-objs += iwl-scan.o iwl-led.o | ||
9 | iwldvm-objs += iwl-agn-rxon.o iwl-agn-devices.o | ||
10 | |||
11 | iwldvm-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o | ||
12 | iwldvm-$(CONFIG_IWLWIFI_DEVICE_TESTMODE) += iwl-testmode.o | ||
13 | |||
14 | CFLAGS_iwl-devtrace.o := -I$(src) | ||
15 | |||
16 | # WIFI | ||
17 | obj-$(CONFIG_IWLWIFI) += iwlwifi.o | 2 | obj-$(CONFIG_IWLWIFI) += iwlwifi.o |
18 | iwlwifi-objs += iwl-5000.o | ||
19 | iwlwifi-objs += iwl-6000.o | ||
20 | iwlwifi-objs += iwl-1000.o | ||
21 | iwlwifi-objs += iwl-2000.o | ||
22 | iwlwifi-objs += iwl-io.o | 3 | iwlwifi-objs += iwl-io.o |
23 | iwlwifi-objs += iwl-pci.o | ||
24 | iwlwifi-objs += iwl-drv.o | 4 | iwlwifi-objs += iwl-drv.o |
25 | iwlwifi-objs += iwl-debug.o | 5 | iwlwifi-objs += iwl-debug.o |
26 | iwlwifi-objs += iwl-notif-wait.o | 6 | iwlwifi-objs += iwl-notif-wait.o |
27 | iwlwifi-objs += iwl-trans-pcie.o iwl-trans-pcie-rx.o iwl-trans-pcie-tx.o | 7 | iwlwifi-objs += iwl-eeprom-read.o iwl-eeprom-parse.o |
8 | iwlwifi-objs += pcie/drv.o pcie/rx.o pcie/tx.o pcie/trans.o | ||
9 | iwlwifi-objs += pcie/1000.o pcie/2000.o pcie/5000.o pcie/6000.o | ||
28 | 10 | ||
29 | iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o | 11 | iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o |
12 | iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TESTMODE) += iwl-test.o | ||
30 | 13 | ||
31 | ccflags-y += -D__CHECK_ENDIAN__ | 14 | ccflags-y += -D__CHECK_ENDIAN__ -I$(src) |
15 | |||
16 | |||
17 | obj-$(CONFIG_IWLDVM) += dvm/ | ||
18 | |||
19 | CFLAGS_iwl-devtrace.o := -I$(src) | ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/Makefile b/drivers/net/wireless/iwlwifi/dvm/Makefile new file mode 100644 index 00000000000..5ff76b20414 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/dvm/Makefile | |||
@@ -0,0 +1,13 @@ | |||
1 | # DVM | ||
2 | obj-$(CONFIG_IWLDVM) += iwldvm.o | ||
3 | iwldvm-objs += main.o rs.o mac80211.o ucode.o tx.o | ||
4 | iwldvm-objs += lib.o calib.o tt.o sta.o rx.o | ||
5 | |||
6 | iwldvm-objs += power.o | ||
7 | iwldvm-objs += scan.o led.o | ||
8 | iwldvm-objs += rxon.o devices.o | ||
9 | |||
10 | iwldvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o | ||
11 | iwldvm-$(CONFIG_IWLWIFI_DEVICE_TESTMODE) += testmode.o | ||
12 | |||
13 | ccflags-y += -D__CHECK_ENDIAN__ -I$(src)/../ | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/dvm/agn.h index 79c0fe06f4d..9bb16bdf6d2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/dvm/agn.h | |||
@@ -63,9 +63,10 @@ | |||
63 | #ifndef __iwl_agn_h__ | 63 | #ifndef __iwl_agn_h__ |
64 | #define __iwl_agn_h__ | 64 | #define __iwl_agn_h__ |
65 | 65 | ||
66 | #include "iwl-dev.h" | ||
67 | #include "iwl-config.h" | 66 | #include "iwl-config.h" |
68 | 67 | ||
68 | #include "dev.h" | ||
69 | |||
69 | /* The first 11 queues (0-10) are used otherwise */ | 70 | /* The first 11 queues (0-10) are used otherwise */ |
70 | #define IWLAGN_FIRST_AMPDU_QUEUE 11 | 71 | #define IWLAGN_FIRST_AMPDU_QUEUE 11 |
71 | 72 | ||
@@ -91,7 +92,6 @@ extern struct iwl_lib_ops iwl6030_lib; | |||
91 | #define STATUS_CT_KILL 1 | 92 | #define STATUS_CT_KILL 1 |
92 | #define STATUS_ALIVE 2 | 93 | #define STATUS_ALIVE 2 |
93 | #define STATUS_READY 3 | 94 | #define STATUS_READY 3 |
94 | #define STATUS_GEO_CONFIGURED 4 | ||
95 | #define STATUS_EXIT_PENDING 5 | 95 | #define STATUS_EXIT_PENDING 5 |
96 | #define STATUS_STATISTICS 6 | 96 | #define STATUS_STATISTICS 6 |
97 | #define STATUS_SCANNING 7 | 97 | #define STATUS_SCANNING 7 |
@@ -101,6 +101,7 @@ extern struct iwl_lib_ops iwl6030_lib; | |||
101 | #define STATUS_CHANNEL_SWITCH_PENDING 11 | 101 | #define STATUS_CHANNEL_SWITCH_PENDING 11 |
102 | #define STATUS_SCAN_COMPLETE 12 | 102 | #define STATUS_SCAN_COMPLETE 12 |
103 | #define STATUS_POWER_PMI 13 | 103 | #define STATUS_POWER_PMI 13 |
104 | #define STATUS_SCAN_ROC_EXPIRED 14 | ||
104 | 105 | ||
105 | struct iwl_ucode_capabilities; | 106 | struct iwl_ucode_capabilities; |
106 | 107 | ||
@@ -255,6 +256,10 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv, | |||
255 | enum iwl_scan_type scan_type, | 256 | enum iwl_scan_type scan_type, |
256 | enum ieee80211_band band); | 257 | enum ieee80211_band band); |
257 | 258 | ||
259 | void iwl_scan_roc_expired(struct iwl_priv *priv); | ||
260 | void iwl_scan_offchannel_skb(struct iwl_priv *priv); | ||
261 | void iwl_scan_offchannel_skb_status(struct iwl_priv *priv); | ||
262 | |||
258 | /* For faster active scanning, scan will move to the next channel if fewer than | 263 | /* For faster active scanning, scan will move to the next channel if fewer than |
259 | * PLCP_QUIET_THRESH packets are heard on this channel within | 264 | * PLCP_QUIET_THRESH packets are heard on this channel within |
260 | * ACTIVE_QUIET_TIME after sending probe request. This shortens the dwell | 265 | * ACTIVE_QUIET_TIME after sending probe request. This shortens the dwell |
@@ -264,7 +269,7 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv, | |||
264 | #define IWL_ACTIVE_QUIET_TIME cpu_to_le16(10) /* msec */ | 269 | #define IWL_ACTIVE_QUIET_TIME cpu_to_le16(10) /* msec */ |
265 | #define IWL_PLCP_QUIET_THRESH cpu_to_le16(1) /* packets */ | 270 | #define IWL_PLCP_QUIET_THRESH cpu_to_le16(1) /* packets */ |
266 | 271 | ||
267 | #define IWL_SCAN_CHECK_WATCHDOG (HZ * 7) | 272 | #define IWL_SCAN_CHECK_WATCHDOG (HZ * 15) |
268 | 273 | ||
269 | 274 | ||
270 | /* bt coex */ | 275 | /* bt coex */ |
@@ -390,8 +395,10 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags) | |||
390 | } | 395 | } |
391 | 396 | ||
392 | extern int iwl_alive_start(struct iwl_priv *priv); | 397 | extern int iwl_alive_start(struct iwl_priv *priv); |
393 | /* svtool */ | 398 | |
399 | /* testmode support */ | ||
394 | #ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE | 400 | #ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE |
401 | |||
395 | extern int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, | 402 | extern int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, |
396 | int len); | 403 | int len); |
397 | extern int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, | 404 | extern int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, |
@@ -399,13 +406,16 @@ extern int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, | |||
399 | struct netlink_callback *cb, | 406 | struct netlink_callback *cb, |
400 | void *data, int len); | 407 | void *data, int len); |
401 | extern void iwl_testmode_init(struct iwl_priv *priv); | 408 | extern void iwl_testmode_init(struct iwl_priv *priv); |
402 | extern void iwl_testmode_cleanup(struct iwl_priv *priv); | 409 | extern void iwl_testmode_free(struct iwl_priv *priv); |
410 | |||
403 | #else | 411 | #else |
412 | |||
404 | static inline | 413 | static inline |
405 | int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) | 414 | int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) |
406 | { | 415 | { |
407 | return -ENOSYS; | 416 | return -ENOSYS; |
408 | } | 417 | } |
418 | |||
409 | static inline | 419 | static inline |
410 | int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb, | 420 | int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb, |
411 | struct netlink_callback *cb, | 421 | struct netlink_callback *cb, |
@@ -413,12 +423,12 @@ int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
413 | { | 423 | { |
414 | return -ENOSYS; | 424 | return -ENOSYS; |
415 | } | 425 | } |
416 | static inline | 426 | |
417 | void iwl_testmode_init(struct iwl_priv *priv) | 427 | static inline void iwl_testmode_init(struct iwl_priv *priv) |
418 | { | 428 | { |
419 | } | 429 | } |
420 | static inline | 430 | |
421 | void iwl_testmode_cleanup(struct iwl_priv *priv) | 431 | static inline void iwl_testmode_free(struct iwl_priv *priv) |
422 | { | 432 | { |
423 | } | 433 | } |
424 | #endif | 434 | #endif |
@@ -437,10 +447,8 @@ static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv, | |||
437 | 447 | ||
438 | static inline int iwl_is_ready(struct iwl_priv *priv) | 448 | static inline int iwl_is_ready(struct iwl_priv *priv) |
439 | { | 449 | { |
440 | /* The adapter is 'ready' if READY and GEO_CONFIGURED bits are | 450 | /* The adapter is 'ready' if READY EXIT_PENDING is not set */ |
441 | * set but EXIT_PENDING is not */ | ||
442 | return test_bit(STATUS_READY, &priv->status) && | 451 | return test_bit(STATUS_READY, &priv->status) && |
443 | test_bit(STATUS_GEO_CONFIGURED, &priv->status) && | ||
444 | !test_bit(STATUS_EXIT_PENDING, &priv->status); | 452 | !test_bit(STATUS_EXIT_PENDING, &priv->status); |
445 | } | 453 | } |
446 | 454 | ||
@@ -518,85 +526,4 @@ static inline const char *iwl_dvm_get_cmd_string(u8 cmd) | |||
518 | return s; | 526 | return s; |
519 | return "UNKNOWN"; | 527 | return "UNKNOWN"; |
520 | } | 528 | } |
521 | |||
522 | /* API method exported for mvm hybrid state */ | ||
523 | void iwl_setup_deferred_work(struct iwl_priv *priv); | ||
524 | int iwl_send_wimax_coex(struct iwl_priv *priv); | ||
525 | int iwl_send_bt_env(struct iwl_priv *priv, u8 action, u8 type); | ||
526 | void iwl_option_config(struct iwl_priv *priv); | ||
527 | void iwl_set_hw_params(struct iwl_priv *priv); | ||
528 | void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags); | ||
529 | int iwl_init_drv(struct iwl_priv *priv); | ||
530 | void iwl_uninit_drv(struct iwl_priv *priv); | ||
531 | void iwl_send_bt_config(struct iwl_priv *priv); | ||
532 | void iwl_rf_kill_ct_config(struct iwl_priv *priv); | ||
533 | int iwl_setup_interface(struct iwl_priv *priv, struct iwl_rxon_context *ctx); | ||
534 | void iwl_teardown_interface(struct iwl_priv *priv, | ||
535 | struct ieee80211_vif *vif, | ||
536 | bool mode_change); | ||
537 | int iwl_full_rxon_required(struct iwl_priv *priv, struct iwl_rxon_context *ctx); | ||
538 | void iwlagn_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx); | ||
539 | void iwlagn_check_needed_chains(struct iwl_priv *priv, | ||
540 | struct iwl_rxon_context *ctx, | ||
541 | struct ieee80211_bss_conf *bss_conf); | ||
542 | void iwlagn_chain_noise_reset(struct iwl_priv *priv); | ||
543 | int iwlagn_update_beacon(struct iwl_priv *priv, | ||
544 | struct ieee80211_vif *vif); | ||
545 | void iwl_tt_handler(struct iwl_priv *priv); | ||
546 | void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode); | ||
547 | void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, int queue); | ||
548 | void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state); | ||
549 | void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb); | ||
550 | void iwl_nic_error(struct iwl_op_mode *op_mode); | ||
551 | void iwl_cmd_queue_full(struct iwl_op_mode *op_mode); | ||
552 | void iwl_nic_config(struct iwl_op_mode *op_mode); | ||
553 | int iwlagn_mac_set_tim(struct ieee80211_hw *hw, | ||
554 | struct ieee80211_sta *sta, bool set); | ||
555 | void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw, | ||
556 | enum ieee80211_rssi_event rssi_event); | ||
557 | int iwlagn_mac_cancel_remain_on_channel(struct ieee80211_hw *hw); | ||
558 | int iwlagn_mac_tx_last_beacon(struct ieee80211_hw *hw); | ||
559 | void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop); | ||
560 | void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, int queue); | ||
561 | void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, | ||
562 | struct ieee80211_channel_switch *ch_switch); | ||
563 | int iwlagn_mac_sta_state(struct ieee80211_hw *hw, | ||
564 | struct ieee80211_vif *vif, | ||
565 | struct ieee80211_sta *sta, | ||
566 | enum ieee80211_sta_state old_state, | ||
567 | enum ieee80211_sta_state new_state); | ||
568 | int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, | ||
569 | struct ieee80211_vif *vif, | ||
570 | enum ieee80211_ampdu_mlme_action action, | ||
571 | struct ieee80211_sta *sta, u16 tid, u16 *ssn, | ||
572 | u8 buf_size); | ||
573 | int iwlagn_mac_hw_scan(struct ieee80211_hw *hw, | ||
574 | struct ieee80211_vif *vif, | ||
575 | struct cfg80211_scan_request *req); | ||
576 | void iwlagn_mac_sta_notify(struct ieee80211_hw *hw, | ||
577 | struct ieee80211_vif *vif, | ||
578 | enum sta_notify_cmd cmd, | ||
579 | struct ieee80211_sta *sta); | ||
580 | void iwlagn_configure_filter(struct ieee80211_hw *hw, | ||
581 | unsigned int changed_flags, | ||
582 | unsigned int *total_flags, | ||
583 | u64 multicast); | ||
584 | int iwlagn_mac_conf_tx(struct ieee80211_hw *hw, | ||
585 | struct ieee80211_vif *vif, u16 queue, | ||
586 | const struct ieee80211_tx_queue_params *params); | ||
587 | void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw, | ||
588 | struct ieee80211_vif *vif, | ||
589 | struct cfg80211_gtk_rekey_data *data); | ||
590 | void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw, | ||
591 | struct ieee80211_vif *vif, | ||
592 | struct ieee80211_key_conf *keyconf, | ||
593 | struct ieee80211_sta *sta, | ||
594 | u32 iv32, u16 *phase1key); | ||
595 | int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | ||
596 | struct ieee80211_vif *vif, | ||
597 | struct ieee80211_sta *sta, | ||
598 | struct ieee80211_key_conf *key); | ||
599 | void iwlagn_mac_stop(struct ieee80211_hw *hw); | ||
600 | void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb); | ||
601 | int iwlagn_mac_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan); | ||
602 | #endif /* __iwl_agn_h__ */ | 529 | #endif /* __iwl_agn_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/dvm/calib.c index 95f27f1a423..f2dd671d7dc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/dvm/calib.c | |||
@@ -63,10 +63,11 @@ | |||
63 | #include <linux/slab.h> | 63 | #include <linux/slab.h> |
64 | #include <net/mac80211.h> | 64 | #include <net/mac80211.h> |
65 | 65 | ||
66 | #include "iwl-dev.h" | ||
67 | #include "iwl-agn-calib.h" | ||
68 | #include "iwl-trans.h" | 66 | #include "iwl-trans.h" |
69 | #include "iwl-agn.h" | 67 | |
68 | #include "dev.h" | ||
69 | #include "calib.h" | ||
70 | #include "agn.h" | ||
70 | 71 | ||
71 | /***************************************************************************** | 72 | /***************************************************************************** |
72 | * INIT calibrations framework | 73 | * INIT calibrations framework |
@@ -832,14 +833,14 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig, | |||
832 | * To be safe, simply mask out any chains that we know | 833 | * To be safe, simply mask out any chains that we know |
833 | * are not on the device. | 834 | * are not on the device. |
834 | */ | 835 | */ |
835 | active_chains &= priv->hw_params.valid_rx_ant; | 836 | active_chains &= priv->eeprom_data->valid_rx_ant; |
836 | 837 | ||
837 | num_tx_chains = 0; | 838 | num_tx_chains = 0; |
838 | for (i = 0; i < NUM_RX_CHAINS; i++) { | 839 | for (i = 0; i < NUM_RX_CHAINS; i++) { |
839 | /* loops on all the bits of | 840 | /* loops on all the bits of |
840 | * priv->hw_setting.valid_tx_ant */ | 841 | * priv->hw_setting.valid_tx_ant */ |
841 | u8 ant_msk = (1 << i); | 842 | u8 ant_msk = (1 << i); |
842 | if (!(priv->hw_params.valid_tx_ant & ant_msk)) | 843 | if (!(priv->eeprom_data->valid_tx_ant & ant_msk)) |
843 | continue; | 844 | continue; |
844 | 845 | ||
845 | num_tx_chains++; | 846 | num_tx_chains++; |
@@ -853,7 +854,7 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig, | |||
853 | * connect the first valid tx chain | 854 | * connect the first valid tx chain |
854 | */ | 855 | */ |
855 | first_chain = | 856 | first_chain = |
856 | find_first_chain(priv->hw_params.valid_tx_ant); | 857 | find_first_chain(priv->eeprom_data->valid_tx_ant); |
857 | data->disconn_array[first_chain] = 0; | 858 | data->disconn_array[first_chain] = 0; |
858 | active_chains |= BIT(first_chain); | 859 | active_chains |= BIT(first_chain); |
859 | IWL_DEBUG_CALIB(priv, | 860 | IWL_DEBUG_CALIB(priv, |
@@ -863,13 +864,13 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig, | |||
863 | } | 864 | } |
864 | } | 865 | } |
865 | 866 | ||
866 | if (active_chains != priv->hw_params.valid_rx_ant && | 867 | if (active_chains != priv->eeprom_data->valid_rx_ant && |
867 | active_chains != priv->chain_noise_data.active_chains) | 868 | active_chains != priv->chain_noise_data.active_chains) |
868 | IWL_DEBUG_CALIB(priv, | 869 | IWL_DEBUG_CALIB(priv, |
869 | "Detected that not all antennas are connected! " | 870 | "Detected that not all antennas are connected! " |
870 | "Connected: %#x, valid: %#x.\n", | 871 | "Connected: %#x, valid: %#x.\n", |
871 | active_chains, | 872 | active_chains, |
872 | priv->hw_params.valid_rx_ant); | 873 | priv->eeprom_data->valid_rx_ant); |
873 | 874 | ||
874 | /* Save for use within RXON, TX, SCAN commands, etc. */ | 875 | /* Save for use within RXON, TX, SCAN commands, etc. */ |
875 | data->active_chains = active_chains; | 876 | data->active_chains = active_chains; |
@@ -1054,7 +1055,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv) | |||
1054 | priv->cfg->bt_params->advanced_bt_coexist) { | 1055 | priv->cfg->bt_params->advanced_bt_coexist) { |
1055 | /* Disable disconnected antenna algorithm for advanced | 1056 | /* Disable disconnected antenna algorithm for advanced |
1056 | bt coex, assuming valid antennas are connected */ | 1057 | bt coex, assuming valid antennas are connected */ |
1057 | data->active_chains = priv->hw_params.valid_rx_ant; | 1058 | data->active_chains = priv->eeprom_data->valid_rx_ant; |
1058 | for (i = 0; i < NUM_RX_CHAINS; i++) | 1059 | for (i = 0; i < NUM_RX_CHAINS; i++) |
1059 | if (!(data->active_chains & (1<<i))) | 1060 | if (!(data->active_chains & (1<<i))) |
1060 | data->disconn_array[i] = 1; | 1061 | data->disconn_array[i] = 1; |
@@ -1083,8 +1084,9 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv) | |||
1083 | IWL_DEBUG_CALIB(priv, "min_average_noise = %d, antenna %d\n", | 1084 | IWL_DEBUG_CALIB(priv, "min_average_noise = %d, antenna %d\n", |
1084 | min_average_noise, min_average_noise_antenna_i); | 1085 | min_average_noise, min_average_noise_antenna_i); |
1085 | 1086 | ||
1086 | iwlagn_gain_computation(priv, average_noise, | 1087 | iwlagn_gain_computation( |
1087 | find_first_chain(priv->hw_params.valid_rx_ant)); | 1088 | priv, average_noise, |
1089 | find_first_chain(priv->eeprom_data->valid_rx_ant)); | ||
1088 | 1090 | ||
1089 | /* Some power changes may have been made during the calibration. | 1091 | /* Some power changes may have been made during the calibration. |
1090 | * Update and commit the RXON | 1092 | * Update and commit the RXON |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.h b/drivers/net/wireless/iwlwifi/dvm/calib.h index dbe13787f27..2349f393cc4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.h +++ b/drivers/net/wireless/iwlwifi/dvm/calib.h | |||
@@ -62,8 +62,8 @@ | |||
62 | #ifndef __iwl_calib_h__ | 62 | #ifndef __iwl_calib_h__ |
63 | #define __iwl_calib_h__ | 63 | #define __iwl_calib_h__ |
64 | 64 | ||
65 | #include "iwl-dev.h" | 65 | #include "dev.h" |
66 | #include "iwl-commands.h" | 66 | #include "commands.h" |
67 | 67 | ||
68 | void iwl_chain_noise_calibration(struct iwl_priv *priv); | 68 | void iwl_chain_noise_calibration(struct iwl_priv *priv); |
69 | void iwl_sensitivity_calibration(struct iwl_priv *priv); | 69 | void iwl_sensitivity_calibration(struct iwl_priv *priv); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/dvm/commands.h index b9f7361d242..64811cd9163 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/dvm/commands.h | |||
@@ -61,9 +61,9 @@ | |||
61 | * | 61 | * |
62 | *****************************************************************************/ | 62 | *****************************************************************************/ |
63 | /* | 63 | /* |
64 | * Please use this file (iwl-commands.h) only for uCode API definitions. | 64 | * Please use this file (commands.h) only for uCode API definitions. |
65 | * Please use iwl-xxxx-hw.h for hardware-related definitions. | 65 | * Please use iwl-xxxx-hw.h for hardware-related definitions. |
66 | * Please use iwl-dev.h for driver implementation definitions. | 66 | * Please use dev.h for driver implementation definitions. |
67 | */ | 67 | */ |
68 | 68 | ||
69 | #ifndef __iwl_commands_h__ | 69 | #ifndef __iwl_commands_h__ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/dvm/debugfs.c index e7c157e5ebe..8a2d9e643b1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/dvm/debugfs.c | |||
@@ -30,16 +30,12 @@ | |||
30 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/debugfs.h> | 32 | #include <linux/debugfs.h> |
33 | |||
34 | #include <linux/ieee80211.h> | 33 | #include <linux/ieee80211.h> |
35 | #include <net/mac80211.h> | 34 | #include <net/mac80211.h> |
36 | |||
37 | |||
38 | #include "iwl-dev.h" | ||
39 | #include "iwl-debug.h" | 35 | #include "iwl-debug.h" |
40 | #include "iwl-io.h" | 36 | #include "iwl-io.h" |
41 | #include "iwl-agn.h" | 37 | #include "dev.h" |
42 | #include "iwl-modparams.h" | 38 | #include "agn.h" |
43 | 39 | ||
44 | /* create and remove of files */ | 40 | /* create and remove of files */ |
45 | #define DEBUGFS_ADD_FILE(name, parent, mode) do { \ | 41 | #define DEBUGFS_ADD_FILE(name, parent, mode) do { \ |
@@ -307,13 +303,13 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file, | |||
307 | const u8 *ptr; | 303 | const u8 *ptr; |
308 | char *buf; | 304 | char *buf; |
309 | u16 eeprom_ver; | 305 | u16 eeprom_ver; |
310 | size_t eeprom_len = priv->cfg->base_params->eeprom_size; | 306 | size_t eeprom_len = priv->eeprom_blob_size; |
311 | buf_size = 4 * eeprom_len + 256; | 307 | buf_size = 4 * eeprom_len + 256; |
312 | 308 | ||
313 | if (eeprom_len % 16) | 309 | if (eeprom_len % 16) |
314 | return -ENODATA; | 310 | return -ENODATA; |
315 | 311 | ||
316 | ptr = priv->eeprom; | 312 | ptr = priv->eeprom_blob; |
317 | if (!ptr) | 313 | if (!ptr) |
318 | return -ENOMEM; | 314 | return -ENOMEM; |
319 | 315 | ||
@@ -322,11 +318,9 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file, | |||
322 | if (!buf) | 318 | if (!buf) |
323 | return -ENOMEM; | 319 | return -ENOMEM; |
324 | 320 | ||
325 | eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION); | 321 | eeprom_ver = priv->eeprom_data->eeprom_version; |
326 | pos += scnprintf(buf + pos, buf_size - pos, "NVM Type: %s, " | 322 | pos += scnprintf(buf + pos, buf_size - pos, |
327 | "version: 0x%x\n", | 323 | "NVM version: 0x%x\n", eeprom_ver); |
328 | (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) | ||
329 | ? "OTP" : "EEPROM", eeprom_ver); | ||
330 | for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) { | 324 | for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) { |
331 | pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs); | 325 | pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs); |
332 | hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos, | 326 | hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos, |
@@ -351,9 +345,6 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, | |||
351 | char *buf; | 345 | char *buf; |
352 | ssize_t ret; | 346 | ssize_t ret; |
353 | 347 | ||
354 | if (!test_bit(STATUS_GEO_CONFIGURED, &priv->status)) | ||
355 | return -EAGAIN; | ||
356 | |||
357 | buf = kzalloc(bufsz, GFP_KERNEL); | 348 | buf = kzalloc(bufsz, GFP_KERNEL); |
358 | if (!buf) | 349 | if (!buf) |
359 | return -ENOMEM; | 350 | return -ENOMEM; |
@@ -426,8 +417,6 @@ static ssize_t iwl_dbgfs_status_read(struct file *file, | |||
426 | test_bit(STATUS_ALIVE, &priv->status)); | 417 | test_bit(STATUS_ALIVE, &priv->status)); |
427 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n", | 418 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n", |
428 | test_bit(STATUS_READY, &priv->status)); | 419 | test_bit(STATUS_READY, &priv->status)); |
429 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_GEO_CONFIGURED:\t %d\n", | ||
430 | test_bit(STATUS_GEO_CONFIGURED, &priv->status)); | ||
431 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n", | 420 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n", |
432 | test_bit(STATUS_EXIT_PENDING, &priv->status)); | 421 | test_bit(STATUS_EXIT_PENDING, &priv->status)); |
433 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n", | 422 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n", |
@@ -1341,17 +1330,17 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, | |||
1341 | if (tx->tx_power.ant_a || tx->tx_power.ant_b || tx->tx_power.ant_c) { | 1330 | if (tx->tx_power.ant_a || tx->tx_power.ant_b || tx->tx_power.ant_c) { |
1342 | pos += scnprintf(buf + pos, bufsz - pos, | 1331 | pos += scnprintf(buf + pos, bufsz - pos, |
1343 | "tx power: (1/2 dB step)\n"); | 1332 | "tx power: (1/2 dB step)\n"); |
1344 | if ((priv->hw_params.valid_tx_ant & ANT_A) && | 1333 | if ((priv->eeprom_data->valid_tx_ant & ANT_A) && |
1345 | tx->tx_power.ant_a) | 1334 | tx->tx_power.ant_a) |
1346 | pos += scnprintf(buf + pos, bufsz - pos, | 1335 | pos += scnprintf(buf + pos, bufsz - pos, |
1347 | fmt_hex, "antenna A:", | 1336 | fmt_hex, "antenna A:", |
1348 | tx->tx_power.ant_a); | 1337 | tx->tx_power.ant_a); |
1349 | if ((priv->hw_params.valid_tx_ant & ANT_B) && | 1338 | if ((priv->eeprom_data->valid_tx_ant & ANT_B) && |
1350 | tx->tx_power.ant_b) | 1339 | tx->tx_power.ant_b) |
1351 | pos += scnprintf(buf + pos, bufsz - pos, | 1340 | pos += scnprintf(buf + pos, bufsz - pos, |
1352 | fmt_hex, "antenna B:", | 1341 | fmt_hex, "antenna B:", |
1353 | tx->tx_power.ant_b); | 1342 | tx->tx_power.ant_b); |
1354 | if ((priv->hw_params.valid_tx_ant & ANT_C) && | 1343 | if ((priv->eeprom_data->valid_tx_ant & ANT_C) && |
1355 | tx->tx_power.ant_c) | 1344 | tx->tx_power.ant_c) |
1356 | pos += scnprintf(buf + pos, bufsz - pos, | 1345 | pos += scnprintf(buf + pos, bufsz - pos, |
1357 | fmt_hex, "antenna C:", | 1346 | fmt_hex, "antenna C:", |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/dvm/dev.h index 70062379d0e..54cf085ddc8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/dvm/dev.h | |||
@@ -24,8 +24,8 @@ | |||
24 | * | 24 | * |
25 | *****************************************************************************/ | 25 | *****************************************************************************/ |
26 | /* | 26 | /* |
27 | * Please use this file (iwl-dev.h) for driver implementation definitions. | 27 | * Please use this file (dev.h) for driver implementation definitions. |
28 | * Please use iwl-commands.h for uCode API definitions. | 28 | * Please use commands.h for uCode API definitions. |
29 | */ | 29 | */ |
30 | 30 | ||
31 | #ifndef __iwl_dev_h__ | 31 | #ifndef __iwl_dev_h__ |
@@ -39,17 +39,20 @@ | |||
39 | #include <linux/mutex.h> | 39 | #include <linux/mutex.h> |
40 | 40 | ||
41 | #include "iwl-fw.h" | 41 | #include "iwl-fw.h" |
42 | #include "iwl-eeprom.h" | 42 | #include "iwl-eeprom-parse.h" |
43 | #include "iwl-csr.h" | 43 | #include "iwl-csr.h" |
44 | #include "iwl-debug.h" | 44 | #include "iwl-debug.h" |
45 | #include "iwl-agn-hw.h" | 45 | #include "iwl-agn-hw.h" |
46 | #include "iwl-led.h" | ||
47 | #include "iwl-power.h" | ||
48 | #include "iwl-agn-rs.h" | ||
49 | #include "iwl-agn-tt.h" | ||
50 | #include "iwl-trans.h" | ||
51 | #include "iwl-op-mode.h" | 46 | #include "iwl-op-mode.h" |
52 | #include "iwl-notif-wait.h" | 47 | #include "iwl-notif-wait.h" |
48 | #include "iwl-trans.h" | ||
49 | |||
50 | #include "led.h" | ||
51 | #include "power.h" | ||
52 | #include "rs.h" | ||
53 | #include "tt.h" | ||
54 | |||
55 | #include "iwl-test.h" | ||
53 | 56 | ||
54 | /* CT-KILL constants */ | 57 | /* CT-KILL constants */ |
55 | #define CT_KILL_THRESHOLD_LEGACY 110 /* in Celsius */ | 58 | #define CT_KILL_THRESHOLD_LEGACY 110 /* in Celsius */ |
@@ -88,33 +91,6 @@ | |||
88 | #define IWL_NUM_SCAN_RATES (2) | 91 | #define IWL_NUM_SCAN_RATES (2) |
89 | 92 | ||
90 | /* | 93 | /* |
91 | * One for each channel, holds all channel setup data | ||
92 | * Some of the fields (e.g. eeprom and flags/max_power_avg) are redundant | ||
93 | * with one another! | ||
94 | */ | ||
95 | struct iwl_channel_info { | ||
96 | struct iwl_eeprom_channel eeprom; /* EEPROM regulatory limit */ | ||
97 | struct iwl_eeprom_channel ht40_eeprom; /* EEPROM regulatory limit for | ||
98 | * HT40 channel */ | ||
99 | |||
100 | u8 channel; /* channel number */ | ||
101 | u8 flags; /* flags copied from EEPROM */ | ||
102 | s8 max_power_avg; /* (dBm) regul. eeprom, normal Tx, any rate */ | ||
103 | s8 curr_txpow; /* (dBm) regulatory/spectrum/user (not h/w) limit */ | ||
104 | s8 min_power; /* always 0 */ | ||
105 | s8 scan_power; /* (dBm) regul. eeprom, direct scans, any rate */ | ||
106 | |||
107 | u8 group_index; /* 0-4, maps channel to group1/2/3/4/5 */ | ||
108 | u8 band_index; /* 0-4, maps channel to band1/2/3/4/5 */ | ||
109 | enum ieee80211_band band; | ||
110 | |||
111 | /* HT40 channel info */ | ||
112 | s8 ht40_max_power_avg; /* (dBm) regul. eeprom, normal Tx, any rate */ | ||
113 | u8 ht40_flags; /* flags copied from EEPROM */ | ||
114 | u8 ht40_extension_channel; /* HT_IE_EXT_CHANNEL_* */ | ||
115 | }; | ||
116 | |||
117 | /* | ||
118 | * Minimum number of queues. MAX_NUM is defined in hw specific files. | 94 | * Minimum number of queues. MAX_NUM is defined in hw specific files. |
119 | * Set the minimum to accommodate | 95 | * Set the minimum to accommodate |
120 | * - 4 standard TX queues | 96 | * - 4 standard TX queues |
@@ -153,29 +129,6 @@ union iwl_ht_rate_supp { | |||
153 | }; | 129 | }; |
154 | }; | 130 | }; |
155 | 131 | ||
156 | #define CFG_HT_RX_AMPDU_FACTOR_8K (0x0) | ||
157 | #define CFG_HT_RX_AMPDU_FACTOR_16K (0x1) | ||
158 | #define CFG_HT_RX_AMPDU_FACTOR_32K (0x2) | ||
159 | #define CFG_HT_RX_AMPDU_FACTOR_64K (0x3) | ||
160 | #define CFG_HT_RX_AMPDU_FACTOR_DEF CFG_HT_RX_AMPDU_FACTOR_64K | ||
161 | #define CFG_HT_RX_AMPDU_FACTOR_MAX CFG_HT_RX_AMPDU_FACTOR_64K | ||
162 | #define CFG_HT_RX_AMPDU_FACTOR_MIN CFG_HT_RX_AMPDU_FACTOR_8K | ||
163 | |||
164 | /* | ||
165 | * Maximal MPDU density for TX aggregation | ||
166 | * 4 - 2us density | ||
167 | * 5 - 4us density | ||
168 | * 6 - 8us density | ||
169 | * 7 - 16us density | ||
170 | */ | ||
171 | #define CFG_HT_MPDU_DENSITY_2USEC (0x4) | ||
172 | #define CFG_HT_MPDU_DENSITY_4USEC (0x5) | ||
173 | #define CFG_HT_MPDU_DENSITY_8USEC (0x6) | ||
174 | #define CFG_HT_MPDU_DENSITY_16USEC (0x7) | ||
175 | #define CFG_HT_MPDU_DENSITY_DEF CFG_HT_MPDU_DENSITY_4USEC | ||
176 | #define CFG_HT_MPDU_DENSITY_MAX CFG_HT_MPDU_DENSITY_16USEC | ||
177 | #define CFG_HT_MPDU_DENSITY_MIN (0x1) | ||
178 | |||
179 | struct iwl_ht_config { | 132 | struct iwl_ht_config { |
180 | bool single_chain_sufficient; | 133 | bool single_chain_sufficient; |
181 | enum ieee80211_smps_mode smps; /* current smps mode */ | 134 | enum ieee80211_smps_mode smps; /* current smps mode */ |
@@ -445,23 +398,6 @@ enum { | |||
445 | MEASUREMENT_ACTIVE = (1 << 1), | 398 | MEASUREMENT_ACTIVE = (1 << 1), |
446 | }; | 399 | }; |
447 | 400 | ||
448 | enum iwl_nvm_type { | ||
449 | NVM_DEVICE_TYPE_EEPROM = 0, | ||
450 | NVM_DEVICE_TYPE_OTP, | ||
451 | }; | ||
452 | |||
453 | /* | ||
454 | * Two types of OTP memory access modes | ||
455 | * IWL_OTP_ACCESS_ABSOLUTE - absolute address mode, | ||
456 | * based on physical memory addressing | ||
457 | * IWL_OTP_ACCESS_RELATIVE - relative address mode, | ||
458 | * based on logical memory addressing | ||
459 | */ | ||
460 | enum iwl_access_mode { | ||
461 | IWL_OTP_ACCESS_ABSOLUTE, | ||
462 | IWL_OTP_ACCESS_RELATIVE, | ||
463 | }; | ||
464 | |||
465 | /* reply_tx_statistics (for _agn devices) */ | 401 | /* reply_tx_statistics (for _agn devices) */ |
466 | struct reply_tx_error_statistics { | 402 | struct reply_tx_error_statistics { |
467 | u32 pp_delay; | 403 | u32 pp_delay; |
@@ -632,10 +568,6 @@ enum iwl_scan_type { | |||
632 | * | 568 | * |
633 | * @tx_chains_num: Number of TX chains | 569 | * @tx_chains_num: Number of TX chains |
634 | * @rx_chains_num: Number of RX chains | 570 | * @rx_chains_num: Number of RX chains |
635 | * @valid_tx_ant: usable antennas for TX | ||
636 | * @valid_rx_ant: usable antennas for RX | ||
637 | * @ht40_channel: is 40MHz width possible: BIT(IEEE80211_BAND_XXX) | ||
638 | * @sku: sku read from EEPROM | ||
639 | * @ct_kill_threshold: temperature threshold - in hw dependent unit | 571 | * @ct_kill_threshold: temperature threshold - in hw dependent unit |
640 | * @ct_kill_exit_threshold: when to reeable the device - in hw dependent unit | 572 | * @ct_kill_exit_threshold: when to reeable the device - in hw dependent unit |
641 | * relevant for 1000, 6000 and up | 573 | * relevant for 1000, 6000 and up |
@@ -645,11 +577,7 @@ enum iwl_scan_type { | |||
645 | struct iwl_hw_params { | 577 | struct iwl_hw_params { |
646 | u8 tx_chains_num; | 578 | u8 tx_chains_num; |
647 | u8 rx_chains_num; | 579 | u8 rx_chains_num; |
648 | u8 valid_tx_ant; | ||
649 | u8 valid_rx_ant; | ||
650 | u8 ht40_channel; | ||
651 | bool use_rts_for_aggregation; | 580 | bool use_rts_for_aggregation; |
652 | u16 sku; | ||
653 | u32 ct_kill_threshold; | 581 | u32 ct_kill_threshold; |
654 | u32 ct_kill_exit_threshold; | 582 | u32 ct_kill_exit_threshold; |
655 | 583 | ||
@@ -664,31 +592,10 @@ struct iwl_lib_ops { | |||
664 | /* device specific configuration */ | 592 | /* device specific configuration */ |
665 | void (*nic_config)(struct iwl_priv *priv); | 593 | void (*nic_config)(struct iwl_priv *priv); |
666 | 594 | ||
667 | /* eeprom operations (as defined in iwl-eeprom.h) */ | ||
668 | struct iwl_eeprom_ops eeprom_ops; | ||
669 | |||
670 | /* temperature */ | 595 | /* temperature */ |
671 | void (*temperature)(struct iwl_priv *priv); | 596 | void (*temperature)(struct iwl_priv *priv); |
672 | }; | 597 | }; |
673 | 598 | ||
674 | #ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE | ||
675 | struct iwl_testmode_trace { | ||
676 | u32 buff_size; | ||
677 | u32 total_size; | ||
678 | u32 num_chunks; | ||
679 | u8 *cpu_addr; | ||
680 | u8 *trace_addr; | ||
681 | dma_addr_t dma_addr; | ||
682 | bool trace_enabled; | ||
683 | }; | ||
684 | struct iwl_testmode_mem { | ||
685 | u32 buff_size; | ||
686 | u32 num_chunks; | ||
687 | u8 *buff_addr; | ||
688 | bool read_in_progress; | ||
689 | }; | ||
690 | #endif | ||
691 | |||
692 | struct iwl_wipan_noa_data { | 599 | struct iwl_wipan_noa_data { |
693 | struct rcu_head rcu_head; | 600 | struct rcu_head rcu_head; |
694 | u32 length; | 601 | u32 length; |
@@ -735,8 +642,6 @@ struct iwl_priv { | |||
735 | 642 | ||
736 | /* ieee device used by generic ieee processing code */ | 643 | /* ieee device used by generic ieee processing code */ |
737 | struct ieee80211_hw *hw; | 644 | struct ieee80211_hw *hw; |
738 | struct ieee80211_channel *ieee_channels; | ||
739 | struct ieee80211_rate *ieee_rates; | ||
740 | 645 | ||
741 | struct list_head calib_results; | 646 | struct list_head calib_results; |
742 | 647 | ||
@@ -747,16 +652,12 @@ struct iwl_priv { | |||
747 | enum ieee80211_band band; | 652 | enum ieee80211_band band; |
748 | u8 valid_contexts; | 653 | u8 valid_contexts; |
749 | 654 | ||
750 | void (*pre_rx_handler)(struct iwl_priv *priv, | ||
751 | struct iwl_rx_cmd_buffer *rxb); | ||
752 | int (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv, | 655 | int (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv, |
753 | struct iwl_rx_cmd_buffer *rxb, | 656 | struct iwl_rx_cmd_buffer *rxb, |
754 | struct iwl_device_cmd *cmd); | 657 | struct iwl_device_cmd *cmd); |
755 | 658 | ||
756 | struct iwl_notif_wait_data notif_wait; | 659 | struct iwl_notif_wait_data notif_wait; |
757 | 660 | ||
758 | struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; | ||
759 | |||
760 | /* spectrum measurement report caching */ | 661 | /* spectrum measurement report caching */ |
761 | struct iwl_spectrum_notification measure_report; | 662 | struct iwl_spectrum_notification measure_report; |
762 | u8 measurement_status; | 663 | u8 measurement_status; |
@@ -787,11 +688,6 @@ struct iwl_priv { | |||
787 | bool ucode_loaded; | 688 | bool ucode_loaded; |
788 | bool init_ucode_run; /* Don't run init uCode again */ | 689 | bool init_ucode_run; /* Don't run init uCode again */ |
789 | 690 | ||
790 | /* we allocate array of iwl_channel_info for NIC's valid channels. | ||
791 | * Access via channel # using indirect index array */ | ||
792 | struct iwl_channel_info *channel_info; /* channel info array */ | ||
793 | u8 channel_count; /* # of channels */ | ||
794 | |||
795 | u8 plcp_delta_threshold; | 691 | u8 plcp_delta_threshold; |
796 | 692 | ||
797 | /* thermal calibration */ | 693 | /* thermal calibration */ |
@@ -846,6 +742,7 @@ struct iwl_priv { | |||
846 | struct iwl_station_entry stations[IWLAGN_STATION_COUNT]; | 742 | struct iwl_station_entry stations[IWLAGN_STATION_COUNT]; |
847 | unsigned long ucode_key_table; | 743 | unsigned long ucode_key_table; |
848 | struct iwl_tid_data tid_data[IWLAGN_STATION_COUNT][IWL_MAX_TID_COUNT]; | 744 | struct iwl_tid_data tid_data[IWLAGN_STATION_COUNT][IWL_MAX_TID_COUNT]; |
745 | atomic_t num_aux_in_flight; | ||
849 | 746 | ||
850 | u8 mac80211_registered; | 747 | u8 mac80211_registered; |
851 | 748 | ||
@@ -950,10 +847,8 @@ struct iwl_priv { | |||
950 | 847 | ||
951 | struct delayed_work scan_check; | 848 | struct delayed_work scan_check; |
952 | 849 | ||
953 | /* TX Power */ | 850 | /* TX Power settings */ |
954 | s8 tx_power_user_lmt; | 851 | s8 tx_power_user_lmt; |
955 | s8 tx_power_device_lmt; | ||
956 | s8 tx_power_lmt_in_half_dbm; /* max tx power in half-dBm format */ | ||
957 | s8 tx_power_next; | 852 | s8 tx_power_next; |
958 | 853 | ||
959 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 854 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
@@ -964,9 +859,10 @@ struct iwl_priv { | |||
964 | void *wowlan_sram; | 859 | void *wowlan_sram; |
965 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ | 860 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ |
966 | 861 | ||
967 | /* eeprom -- this is in the card's little endian byte order */ | 862 | struct iwl_eeprom_data *eeprom_data; |
968 | u8 *eeprom; | 863 | /* eeprom blob for debugfs/testmode */ |
969 | enum iwl_nvm_type nvm_device_type; | 864 | u8 *eeprom_blob; |
865 | size_t eeprom_blob_size; | ||
970 | 866 | ||
971 | struct work_struct txpower_work; | 867 | struct work_struct txpower_work; |
972 | u32 calib_disabled; | 868 | u32 calib_disabled; |
@@ -979,9 +875,9 @@ struct iwl_priv { | |||
979 | struct led_classdev led; | 875 | struct led_classdev led; |
980 | unsigned long blink_on, blink_off; | 876 | unsigned long blink_on, blink_off; |
981 | bool led_registered; | 877 | bool led_registered; |
878 | |||
982 | #ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE | 879 | #ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE |
983 | struct iwl_testmode_trace testmode_trace; | 880 | struct iwl_test tst; |
984 | struct iwl_testmode_mem testmode_mem; | ||
985 | u32 tm_fixed_rate; | 881 | u32 tm_fixed_rate; |
986 | #endif | 882 | #endif |
987 | 883 | ||
@@ -1001,8 +897,6 @@ struct iwl_priv { | |||
1001 | enum iwl_ucode_type cur_ucode; | 897 | enum iwl_ucode_type cur_ucode; |
1002 | }; /*iwl_priv */ | 898 | }; /*iwl_priv */ |
1003 | 899 | ||
1004 | extern struct kmem_cache *iwl_tx_cmd_pool; | ||
1005 | |||
1006 | static inline struct iwl_rxon_context * | 900 | static inline struct iwl_rxon_context * |
1007 | iwl_rxon_ctx_from_vif(struct ieee80211_vif *vif) | 901 | iwl_rxon_ctx_from_vif(struct ieee80211_vif *vif) |
1008 | { | 902 | { |
@@ -1036,36 +930,4 @@ static inline int iwl_is_any_associated(struct iwl_priv *priv) | |||
1036 | return false; | 930 | return false; |
1037 | } | 931 | } |
1038 | 932 | ||
1039 | static inline int is_channel_valid(const struct iwl_channel_info *ch_info) | ||
1040 | { | ||
1041 | if (ch_info == NULL) | ||
1042 | return 0; | ||
1043 | return (ch_info->flags & EEPROM_CHANNEL_VALID) ? 1 : 0; | ||
1044 | } | ||
1045 | |||
1046 | static inline int is_channel_radar(const struct iwl_channel_info *ch_info) | ||
1047 | { | ||
1048 | return (ch_info->flags & EEPROM_CHANNEL_RADAR) ? 1 : 0; | ||
1049 | } | ||
1050 | |||
1051 | static inline u8 is_channel_a_band(const struct iwl_channel_info *ch_info) | ||
1052 | { | ||
1053 | return ch_info->band == IEEE80211_BAND_5GHZ; | ||
1054 | } | ||
1055 | |||
1056 | static inline u8 is_channel_bg_band(const struct iwl_channel_info *ch_info) | ||
1057 | { | ||
1058 | return ch_info->band == IEEE80211_BAND_2GHZ; | ||
1059 | } | ||
1060 | |||
1061 | static inline int is_channel_passive(const struct iwl_channel_info *ch) | ||
1062 | { | ||
1063 | return (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) ? 1 : 0; | ||
1064 | } | ||
1065 | |||
1066 | static inline int is_channel_ibss(const struct iwl_channel_info *ch) | ||
1067 | { | ||
1068 | return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0; | ||
1069 | } | ||
1070 | |||
1071 | #endif /* __iwl_dev_h__ */ | 933 | #endif /* __iwl_dev_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-devices.c b/drivers/net/wireless/iwlwifi/dvm/devices.c index 48533b3a0f9..349c205d5f6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-devices.c +++ b/drivers/net/wireless/iwlwifi/dvm/devices.c | |||
@@ -27,11 +27,14 @@ | |||
27 | /* | 27 | /* |
28 | * DVM device-specific data & functions | 28 | * DVM device-specific data & functions |
29 | */ | 29 | */ |
30 | #include "iwl-agn.h" | ||
31 | #include "iwl-dev.h" | ||
32 | #include "iwl-commands.h" | ||
33 | #include "iwl-io.h" | 30 | #include "iwl-io.h" |
34 | #include "iwl-prph.h" | 31 | #include "iwl-prph.h" |
32 | #include "iwl-eeprom-parse.h" | ||
33 | |||
34 | #include "agn.h" | ||
35 | #include "dev.h" | ||
36 | #include "commands.h" | ||
37 | |||
35 | 38 | ||
36 | /* | 39 | /* |
37 | * 1000 series | 40 | * 1000 series |
@@ -58,11 +61,6 @@ static void iwl1000_set_ct_threshold(struct iwl_priv *priv) | |||
58 | /* NIC configuration for 1000 series */ | 61 | /* NIC configuration for 1000 series */ |
59 | static void iwl1000_nic_config(struct iwl_priv *priv) | 62 | static void iwl1000_nic_config(struct iwl_priv *priv) |
60 | { | 63 | { |
61 | /* set CSR_HW_CONFIG_REG for uCode use */ | ||
62 | iwl_set_bit(priv->trans, CSR_HW_IF_CONFIG_REG, | ||
63 | CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | | ||
64 | CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); | ||
65 | |||
66 | /* Setting digital SVR for 1000 card to 1.32V */ | 64 | /* Setting digital SVR for 1000 card to 1.32V */ |
67 | /* locking is acquired in iwl_set_bits_mask_prph() function */ | 65 | /* locking is acquired in iwl_set_bits_mask_prph() function */ |
68 | iwl_set_bits_mask_prph(priv->trans, APMG_DIGITAL_SVR_REG, | 66 | iwl_set_bits_mask_prph(priv->trans, APMG_DIGITAL_SVR_REG, |
@@ -170,16 +168,6 @@ static const struct iwl_sensitivity_ranges iwl1000_sensitivity = { | |||
170 | 168 | ||
171 | static void iwl1000_hw_set_hw_params(struct iwl_priv *priv) | 169 | static void iwl1000_hw_set_hw_params(struct iwl_priv *priv) |
172 | { | 170 | { |
173 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ); | ||
174 | |||
175 | priv->hw_params.tx_chains_num = | ||
176 | num_of_ant(priv->hw_params.valid_tx_ant); | ||
177 | if (priv->cfg->rx_with_siso_diversity) | ||
178 | priv->hw_params.rx_chains_num = 1; | ||
179 | else | ||
180 | priv->hw_params.rx_chains_num = | ||
181 | num_of_ant(priv->hw_params.valid_rx_ant); | ||
182 | |||
183 | iwl1000_set_ct_threshold(priv); | 171 | iwl1000_set_ct_threshold(priv); |
184 | 172 | ||
185 | /* Set initial sensitivity parameters */ | 173 | /* Set initial sensitivity parameters */ |
@@ -189,17 +177,6 @@ static void iwl1000_hw_set_hw_params(struct iwl_priv *priv) | |||
189 | struct iwl_lib_ops iwl1000_lib = { | 177 | struct iwl_lib_ops iwl1000_lib = { |
190 | .set_hw_params = iwl1000_hw_set_hw_params, | 178 | .set_hw_params = iwl1000_hw_set_hw_params, |
191 | .nic_config = iwl1000_nic_config, | 179 | .nic_config = iwl1000_nic_config, |
192 | .eeprom_ops = { | ||
193 | .regulatory_bands = { | ||
194 | EEPROM_REG_BAND_1_CHANNELS, | ||
195 | EEPROM_REG_BAND_2_CHANNELS, | ||
196 | EEPROM_REG_BAND_3_CHANNELS, | ||
197 | EEPROM_REG_BAND_4_CHANNELS, | ||
198 | EEPROM_REG_BAND_5_CHANNELS, | ||
199 | EEPROM_REG_BAND_24_HT40_CHANNELS, | ||
200 | EEPROM_REGULATORY_BAND_NO_HT40, | ||
201 | }, | ||
202 | }, | ||
203 | .temperature = iwlagn_temperature, | 180 | .temperature = iwlagn_temperature, |
204 | }; | 181 | }; |
205 | 182 | ||
@@ -219,8 +196,6 @@ static void iwl2000_set_ct_threshold(struct iwl_priv *priv) | |||
219 | /* NIC configuration for 2000 series */ | 196 | /* NIC configuration for 2000 series */ |
220 | static void iwl2000_nic_config(struct iwl_priv *priv) | 197 | static void iwl2000_nic_config(struct iwl_priv *priv) |
221 | { | 198 | { |
222 | iwl_rf_config(priv); | ||
223 | |||
224 | iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG, | 199 | iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG, |
225 | CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER); | 200 | CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER); |
226 | } | 201 | } |
@@ -251,16 +226,6 @@ static const struct iwl_sensitivity_ranges iwl2000_sensitivity = { | |||
251 | 226 | ||
252 | static void iwl2000_hw_set_hw_params(struct iwl_priv *priv) | 227 | static void iwl2000_hw_set_hw_params(struct iwl_priv *priv) |
253 | { | 228 | { |
254 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ); | ||
255 | |||
256 | priv->hw_params.tx_chains_num = | ||
257 | num_of_ant(priv->hw_params.valid_tx_ant); | ||
258 | if (priv->cfg->rx_with_siso_diversity) | ||
259 | priv->hw_params.rx_chains_num = 1; | ||
260 | else | ||
261 | priv->hw_params.rx_chains_num = | ||
262 | num_of_ant(priv->hw_params.valid_rx_ant); | ||
263 | |||
264 | iwl2000_set_ct_threshold(priv); | 229 | iwl2000_set_ct_threshold(priv); |
265 | 230 | ||
266 | /* Set initial sensitivity parameters */ | 231 | /* Set initial sensitivity parameters */ |
@@ -270,36 +235,12 @@ static void iwl2000_hw_set_hw_params(struct iwl_priv *priv) | |||
270 | struct iwl_lib_ops iwl2000_lib = { | 235 | struct iwl_lib_ops iwl2000_lib = { |
271 | .set_hw_params = iwl2000_hw_set_hw_params, | 236 | .set_hw_params = iwl2000_hw_set_hw_params, |
272 | .nic_config = iwl2000_nic_config, | 237 | .nic_config = iwl2000_nic_config, |
273 | .eeprom_ops = { | ||
274 | .regulatory_bands = { | ||
275 | EEPROM_REG_BAND_1_CHANNELS, | ||
276 | EEPROM_REG_BAND_2_CHANNELS, | ||
277 | EEPROM_REG_BAND_3_CHANNELS, | ||
278 | EEPROM_REG_BAND_4_CHANNELS, | ||
279 | EEPROM_REG_BAND_5_CHANNELS, | ||
280 | EEPROM_6000_REG_BAND_24_HT40_CHANNELS, | ||
281 | EEPROM_REGULATORY_BAND_NO_HT40, | ||
282 | }, | ||
283 | .enhanced_txpower = true, | ||
284 | }, | ||
285 | .temperature = iwlagn_temperature, | 238 | .temperature = iwlagn_temperature, |
286 | }; | 239 | }; |
287 | 240 | ||
288 | struct iwl_lib_ops iwl2030_lib = { | 241 | struct iwl_lib_ops iwl2030_lib = { |
289 | .set_hw_params = iwl2000_hw_set_hw_params, | 242 | .set_hw_params = iwl2000_hw_set_hw_params, |
290 | .nic_config = iwl2000_nic_config, | 243 | .nic_config = iwl2000_nic_config, |
291 | .eeprom_ops = { | ||
292 | .regulatory_bands = { | ||
293 | EEPROM_REG_BAND_1_CHANNELS, | ||
294 | EEPROM_REG_BAND_2_CHANNELS, | ||
295 | EEPROM_REG_BAND_3_CHANNELS, | ||
296 | EEPROM_REG_BAND_4_CHANNELS, | ||
297 | EEPROM_REG_BAND_5_CHANNELS, | ||
298 | EEPROM_6000_REG_BAND_24_HT40_CHANNELS, | ||
299 | EEPROM_REGULATORY_BAND_NO_HT40, | ||
300 | }, | ||
301 | .enhanced_txpower = true, | ||
302 | }, | ||
303 | .temperature = iwlagn_temperature, | 244 | .temperature = iwlagn_temperature, |
304 | }; | 245 | }; |
305 | 246 | ||
@@ -309,19 +250,6 @@ struct iwl_lib_ops iwl2030_lib = { | |||
309 | */ | 250 | */ |
310 | 251 | ||
311 | /* NIC configuration for 5000 series */ | 252 | /* NIC configuration for 5000 series */ |
312 | static void iwl5000_nic_config(struct iwl_priv *priv) | ||
313 | { | ||
314 | iwl_rf_config(priv); | ||
315 | |||
316 | /* W/A : NIC is stuck in a reset state after Early PCIe power off | ||
317 | * (PCIe power is lost before PERST# is asserted), | ||
318 | * causing ME FW to lose ownership and not being able to obtain it back. | ||
319 | */ | ||
320 | iwl_set_bits_mask_prph(priv->trans, APMG_PS_CTRL_REG, | ||
321 | APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS, | ||
322 | ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS); | ||
323 | } | ||
324 | |||
325 | static const struct iwl_sensitivity_ranges iwl5000_sensitivity = { | 253 | static const struct iwl_sensitivity_ranges iwl5000_sensitivity = { |
326 | .min_nrg_cck = 100, | 254 | .min_nrg_cck = 100, |
327 | .auto_corr_min_ofdm = 90, | 255 | .auto_corr_min_ofdm = 90, |
@@ -376,11 +304,9 @@ static struct iwl_sensitivity_ranges iwl5150_sensitivity = { | |||
376 | static s32 iwl_temp_calib_to_offset(struct iwl_priv *priv) | 304 | static s32 iwl_temp_calib_to_offset(struct iwl_priv *priv) |
377 | { | 305 | { |
378 | u16 temperature, voltage; | 306 | u16 temperature, voltage; |
379 | __le16 *temp_calib = (__le16 *)iwl_eeprom_query_addr(priv, | ||
380 | EEPROM_KELVIN_TEMPERATURE); | ||
381 | 307 | ||
382 | temperature = le16_to_cpu(temp_calib[0]); | 308 | temperature = le16_to_cpu(priv->eeprom_data->kelvin_temperature); |
383 | voltage = le16_to_cpu(temp_calib[1]); | 309 | voltage = le16_to_cpu(priv->eeprom_data->kelvin_voltage); |
384 | 310 | ||
385 | /* offset = temp - volt / coeff */ | 311 | /* offset = temp - volt / coeff */ |
386 | return (s32)(temperature - | 312 | return (s32)(temperature - |
@@ -404,14 +330,6 @@ static void iwl5000_set_ct_threshold(struct iwl_priv *priv) | |||
404 | 330 | ||
405 | static void iwl5000_hw_set_hw_params(struct iwl_priv *priv) | 331 | static void iwl5000_hw_set_hw_params(struct iwl_priv *priv) |
406 | { | 332 | { |
407 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | | ||
408 | BIT(IEEE80211_BAND_5GHZ); | ||
409 | |||
410 | priv->hw_params.tx_chains_num = | ||
411 | num_of_ant(priv->hw_params.valid_tx_ant); | ||
412 | priv->hw_params.rx_chains_num = | ||
413 | num_of_ant(priv->hw_params.valid_rx_ant); | ||
414 | |||
415 | iwl5000_set_ct_threshold(priv); | 333 | iwl5000_set_ct_threshold(priv); |
416 | 334 | ||
417 | /* Set initial sensitivity parameters */ | 335 | /* Set initial sensitivity parameters */ |
@@ -420,14 +338,6 @@ static void iwl5000_hw_set_hw_params(struct iwl_priv *priv) | |||
420 | 338 | ||
421 | static void iwl5150_hw_set_hw_params(struct iwl_priv *priv) | 339 | static void iwl5150_hw_set_hw_params(struct iwl_priv *priv) |
422 | { | 340 | { |
423 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | | ||
424 | BIT(IEEE80211_BAND_5GHZ); | ||
425 | |||
426 | priv->hw_params.tx_chains_num = | ||
427 | num_of_ant(priv->hw_params.valid_tx_ant); | ||
428 | priv->hw_params.rx_chains_num = | ||
429 | num_of_ant(priv->hw_params.valid_rx_ant); | ||
430 | |||
431 | iwl5150_set_ct_threshold(priv); | 341 | iwl5150_set_ct_threshold(priv); |
432 | 342 | ||
433 | /* Set initial sensitivity parameters */ | 343 | /* Set initial sensitivity parameters */ |
@@ -455,7 +365,6 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, | |||
455 | */ | 365 | */ |
456 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | 366 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; |
457 | struct iwl5000_channel_switch_cmd cmd; | 367 | struct iwl5000_channel_switch_cmd cmd; |
458 | const struct iwl_channel_info *ch_info; | ||
459 | u32 switch_time_in_usec, ucode_switch_time; | 368 | u32 switch_time_in_usec, ucode_switch_time; |
460 | u16 ch; | 369 | u16 ch; |
461 | u32 tsf_low; | 370 | u32 tsf_low; |
@@ -505,14 +414,7 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, | |||
505 | } | 414 | } |
506 | IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", | 415 | IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", |
507 | cmd.switch_time); | 416 | cmd.switch_time); |
508 | ch_info = iwl_get_channel_info(priv, priv->band, ch); | 417 | cmd.expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR; |
509 | if (ch_info) | ||
510 | cmd.expect_beacon = is_channel_radar(ch_info); | ||
511 | else { | ||
512 | IWL_ERR(priv, "invalid channel switch from %u to %u\n", | ||
513 | ctx->active.channel, ch); | ||
514 | return -EFAULT; | ||
515 | } | ||
516 | 418 | ||
517 | return iwl_dvm_send_cmd(priv, &hcmd); | 419 | return iwl_dvm_send_cmd(priv, &hcmd); |
518 | } | 420 | } |
@@ -520,36 +422,12 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, | |||
520 | struct iwl_lib_ops iwl5000_lib = { | 422 | struct iwl_lib_ops iwl5000_lib = { |
521 | .set_hw_params = iwl5000_hw_set_hw_params, | 423 | .set_hw_params = iwl5000_hw_set_hw_params, |
522 | .set_channel_switch = iwl5000_hw_channel_switch, | 424 | .set_channel_switch = iwl5000_hw_channel_switch, |
523 | .nic_config = iwl5000_nic_config, | ||
524 | .eeprom_ops = { | ||
525 | .regulatory_bands = { | ||
526 | EEPROM_REG_BAND_1_CHANNELS, | ||
527 | EEPROM_REG_BAND_2_CHANNELS, | ||
528 | EEPROM_REG_BAND_3_CHANNELS, | ||
529 | EEPROM_REG_BAND_4_CHANNELS, | ||
530 | EEPROM_REG_BAND_5_CHANNELS, | ||
531 | EEPROM_REG_BAND_24_HT40_CHANNELS, | ||
532 | EEPROM_REG_BAND_52_HT40_CHANNELS | ||
533 | }, | ||
534 | }, | ||
535 | .temperature = iwlagn_temperature, | 425 | .temperature = iwlagn_temperature, |
536 | }; | 426 | }; |
537 | 427 | ||
538 | struct iwl_lib_ops iwl5150_lib = { | 428 | struct iwl_lib_ops iwl5150_lib = { |
539 | .set_hw_params = iwl5150_hw_set_hw_params, | 429 | .set_hw_params = iwl5150_hw_set_hw_params, |
540 | .set_channel_switch = iwl5000_hw_channel_switch, | 430 | .set_channel_switch = iwl5000_hw_channel_switch, |
541 | .nic_config = iwl5000_nic_config, | ||
542 | .eeprom_ops = { | ||
543 | .regulatory_bands = { | ||
544 | EEPROM_REG_BAND_1_CHANNELS, | ||
545 | EEPROM_REG_BAND_2_CHANNELS, | ||
546 | EEPROM_REG_BAND_3_CHANNELS, | ||
547 | EEPROM_REG_BAND_4_CHANNELS, | ||
548 | EEPROM_REG_BAND_5_CHANNELS, | ||
549 | EEPROM_REG_BAND_24_HT40_CHANNELS, | ||
550 | EEPROM_REG_BAND_52_HT40_CHANNELS | ||
551 | }, | ||
552 | }, | ||
553 | .temperature = iwl5150_temperature, | 431 | .temperature = iwl5150_temperature, |
554 | }; | 432 | }; |
555 | 433 | ||
@@ -570,8 +448,6 @@ static void iwl6000_set_ct_threshold(struct iwl_priv *priv) | |||
570 | /* NIC configuration for 6000 series */ | 448 | /* NIC configuration for 6000 series */ |
571 | static void iwl6000_nic_config(struct iwl_priv *priv) | 449 | static void iwl6000_nic_config(struct iwl_priv *priv) |
572 | { | 450 | { |
573 | iwl_rf_config(priv); | ||
574 | |||
575 | switch (priv->cfg->device_family) { | 451 | switch (priv->cfg->device_family) { |
576 | case IWL_DEVICE_FAMILY_6005: | 452 | case IWL_DEVICE_FAMILY_6005: |
577 | case IWL_DEVICE_FAMILY_6030: | 453 | case IWL_DEVICE_FAMILY_6030: |
@@ -584,13 +460,13 @@ static void iwl6000_nic_config(struct iwl_priv *priv) | |||
584 | break; | 460 | break; |
585 | case IWL_DEVICE_FAMILY_6050: | 461 | case IWL_DEVICE_FAMILY_6050: |
586 | /* Indicate calibration version to uCode. */ | 462 | /* Indicate calibration version to uCode. */ |
587 | if (iwl_eeprom_calib_version(priv) >= 6) | 463 | if (priv->eeprom_data->calib_version >= 6) |
588 | iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG, | 464 | iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG, |
589 | CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); | 465 | CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); |
590 | break; | 466 | break; |
591 | case IWL_DEVICE_FAMILY_6150: | 467 | case IWL_DEVICE_FAMILY_6150: |
592 | /* Indicate calibration version to uCode. */ | 468 | /* Indicate calibration version to uCode. */ |
593 | if (iwl_eeprom_calib_version(priv) >= 6) | 469 | if (priv->eeprom_data->calib_version >= 6) |
594 | iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG, | 470 | iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG, |
595 | CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); | 471 | CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); |
596 | iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG, | 472 | iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG, |
@@ -627,17 +503,6 @@ static const struct iwl_sensitivity_ranges iwl6000_sensitivity = { | |||
627 | 503 | ||
628 | static void iwl6000_hw_set_hw_params(struct iwl_priv *priv) | 504 | static void iwl6000_hw_set_hw_params(struct iwl_priv *priv) |
629 | { | 505 | { |
630 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | | ||
631 | BIT(IEEE80211_BAND_5GHZ); | ||
632 | |||
633 | priv->hw_params.tx_chains_num = | ||
634 | num_of_ant(priv->hw_params.valid_tx_ant); | ||
635 | if (priv->cfg->rx_with_siso_diversity) | ||
636 | priv->hw_params.rx_chains_num = 1; | ||
637 | else | ||
638 | priv->hw_params.rx_chains_num = | ||
639 | num_of_ant(priv->hw_params.valid_rx_ant); | ||
640 | |||
641 | iwl6000_set_ct_threshold(priv); | 506 | iwl6000_set_ct_threshold(priv); |
642 | 507 | ||
643 | /* Set initial sensitivity parameters */ | 508 | /* Set initial sensitivity parameters */ |
@@ -654,7 +519,6 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, | |||
654 | */ | 519 | */ |
655 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | 520 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; |
656 | struct iwl6000_channel_switch_cmd cmd; | 521 | struct iwl6000_channel_switch_cmd cmd; |
657 | const struct iwl_channel_info *ch_info; | ||
658 | u32 switch_time_in_usec, ucode_switch_time; | 522 | u32 switch_time_in_usec, ucode_switch_time; |
659 | u16 ch; | 523 | u16 ch; |
660 | u32 tsf_low; | 524 | u32 tsf_low; |
@@ -704,14 +568,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, | |||
704 | } | 568 | } |
705 | IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", | 569 | IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", |
706 | cmd.switch_time); | 570 | cmd.switch_time); |
707 | ch_info = iwl_get_channel_info(priv, priv->band, ch); | 571 | cmd.expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR; |
708 | if (ch_info) | ||
709 | cmd.expect_beacon = is_channel_radar(ch_info); | ||
710 | else { | ||
711 | IWL_ERR(priv, "invalid channel switch from %u to %u\n", | ||
712 | ctx->active.channel, ch); | ||
713 | return -EFAULT; | ||
714 | } | ||
715 | 572 | ||
716 | return iwl_dvm_send_cmd(priv, &hcmd); | 573 | return iwl_dvm_send_cmd(priv, &hcmd); |
717 | } | 574 | } |
@@ -720,18 +577,6 @@ struct iwl_lib_ops iwl6000_lib = { | |||
720 | .set_hw_params = iwl6000_hw_set_hw_params, | 577 | .set_hw_params = iwl6000_hw_set_hw_params, |
721 | .set_channel_switch = iwl6000_hw_channel_switch, | 578 | .set_channel_switch = iwl6000_hw_channel_switch, |
722 | .nic_config = iwl6000_nic_config, | 579 | .nic_config = iwl6000_nic_config, |
723 | .eeprom_ops = { | ||
724 | .regulatory_bands = { | ||
725 | EEPROM_REG_BAND_1_CHANNELS, | ||
726 | EEPROM_REG_BAND_2_CHANNELS, | ||
727 | EEPROM_REG_BAND_3_CHANNELS, | ||
728 | EEPROM_REG_BAND_4_CHANNELS, | ||
729 | EEPROM_REG_BAND_5_CHANNELS, | ||
730 | EEPROM_6000_REG_BAND_24_HT40_CHANNELS, | ||
731 | EEPROM_REG_BAND_52_HT40_CHANNELS | ||
732 | }, | ||
733 | .enhanced_txpower = true, | ||
734 | }, | ||
735 | .temperature = iwlagn_temperature, | 580 | .temperature = iwlagn_temperature, |
736 | }; | 581 | }; |
737 | 582 | ||
@@ -739,17 +584,5 @@ struct iwl_lib_ops iwl6030_lib = { | |||
739 | .set_hw_params = iwl6000_hw_set_hw_params, | 584 | .set_hw_params = iwl6000_hw_set_hw_params, |
740 | .set_channel_switch = iwl6000_hw_channel_switch, | 585 | .set_channel_switch = iwl6000_hw_channel_switch, |
741 | .nic_config = iwl6000_nic_config, | 586 | .nic_config = iwl6000_nic_config, |
742 | .eeprom_ops = { | ||
743 | .regulatory_bands = { | ||
744 | EEPROM_REG_BAND_1_CHANNELS, | ||
745 | EEPROM_REG_BAND_2_CHANNELS, | ||
746 | EEPROM_REG_BAND_3_CHANNELS, | ||
747 | EEPROM_REG_BAND_4_CHANNELS, | ||
748 | EEPROM_REG_BAND_5_CHANNELS, | ||
749 | EEPROM_6000_REG_BAND_24_HT40_CHANNELS, | ||
750 | EEPROM_REG_BAND_52_HT40_CHANNELS | ||
751 | }, | ||
752 | .enhanced_txpower = true, | ||
753 | }, | ||
754 | .temperature = iwlagn_temperature, | 587 | .temperature = iwlagn_temperature, |
755 | }; | 588 | }; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/dvm/led.c index 47000419f91..bf479f70909 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/dvm/led.c | |||
@@ -34,12 +34,11 @@ | |||
34 | #include <net/mac80211.h> | 34 | #include <net/mac80211.h> |
35 | #include <linux/etherdevice.h> | 35 | #include <linux/etherdevice.h> |
36 | #include <asm/unaligned.h> | 36 | #include <asm/unaligned.h> |
37 | |||
38 | #include "iwl-dev.h" | ||
39 | #include "iwl-agn.h" | ||
40 | #include "iwl-io.h" | 37 | #include "iwl-io.h" |
41 | #include "iwl-trans.h" | 38 | #include "iwl-trans.h" |
42 | #include "iwl-modparams.h" | 39 | #include "iwl-modparams.h" |
40 | #include "dev.h" | ||
41 | #include "agn.h" | ||
43 | 42 | ||
44 | /* Throughput OFF time(ms) ON time (ms) | 43 | /* Throughput OFF time(ms) ON time (ms) |
45 | * >300 25 25 | 44 | * >300 25 25 |
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.h b/drivers/net/wireless/iwlwifi/dvm/led.h index b02a853103d..b02a853103d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.h +++ b/drivers/net/wireless/iwlwifi/dvm/led.h | |||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/dvm/lib.c index e55ec6c8a92..207ae91a83a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/dvm/lib.c | |||
@@ -33,13 +33,14 @@ | |||
33 | #include <linux/sched.h> | 33 | #include <linux/sched.h> |
34 | #include <net/mac80211.h> | 34 | #include <net/mac80211.h> |
35 | 35 | ||
36 | #include "iwl-dev.h" | ||
37 | #include "iwl-io.h" | 36 | #include "iwl-io.h" |
38 | #include "iwl-agn-hw.h" | 37 | #include "iwl-agn-hw.h" |
39 | #include "iwl-agn.h" | ||
40 | #include "iwl-trans.h" | 38 | #include "iwl-trans.h" |
41 | #include "iwl-modparams.h" | 39 | #include "iwl-modparams.h" |
42 | 40 | ||
41 | #include "dev.h" | ||
42 | #include "agn.h" | ||
43 | |||
43 | int iwlagn_hw_valid_rtc_data_addr(u32 addr) | 44 | int iwlagn_hw_valid_rtc_data_addr(u32 addr) |
44 | { | 45 | { |
45 | return (addr >= IWLAGN_RTC_DATA_LOWER_BOUND) && | 46 | return (addr >= IWLAGN_RTC_DATA_LOWER_BOUND) && |
@@ -58,8 +59,7 @@ int iwlagn_send_tx_power(struct iwl_priv *priv) | |||
58 | /* half dBm need to multiply */ | 59 | /* half dBm need to multiply */ |
59 | tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt); | 60 | tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt); |
60 | 61 | ||
61 | if (priv->tx_power_lmt_in_half_dbm && | 62 | if (tx_power_cmd.global_lmt > priv->eeprom_data->max_tx_pwr_half_dbm) { |
62 | priv->tx_power_lmt_in_half_dbm < tx_power_cmd.global_lmt) { | ||
63 | /* | 63 | /* |
64 | * For the newer devices which using enhanced/extend tx power | 64 | * For the newer devices which using enhanced/extend tx power |
65 | * table in EEPROM, the format is in half dBm. driver need to | 65 | * table in EEPROM, the format is in half dBm. driver need to |
@@ -71,7 +71,8 @@ int iwlagn_send_tx_power(struct iwl_priv *priv) | |||
71 | * "tx_power_user_lmt" is higher than EEPROM value (in | 71 | * "tx_power_user_lmt" is higher than EEPROM value (in |
72 | * half-dBm format), lower the tx power based on EEPROM | 72 | * half-dBm format), lower the tx power based on EEPROM |
73 | */ | 73 | */ |
74 | tx_power_cmd.global_lmt = priv->tx_power_lmt_in_half_dbm; | 74 | tx_power_cmd.global_lmt = |
75 | priv->eeprom_data->max_tx_pwr_half_dbm; | ||
75 | } | 76 | } |
76 | tx_power_cmd.flags = IWLAGN_TX_POWER_NO_CLOSED; | 77 | tx_power_cmd.flags = IWLAGN_TX_POWER_NO_CLOSED; |
77 | tx_power_cmd.srv_chan_lmt = IWLAGN_TX_POWER_AUTO; | 78 | tx_power_cmd.srv_chan_lmt = IWLAGN_TX_POWER_AUTO; |
@@ -159,7 +160,7 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control) | |||
159 | IWL_PAN_SCD_BK_MSK | IWL_PAN_SCD_MGMT_MSK | | 160 | IWL_PAN_SCD_BK_MSK | IWL_PAN_SCD_MGMT_MSK | |
160 | IWL_PAN_SCD_MULTICAST_MSK; | 161 | IWL_PAN_SCD_MULTICAST_MSK; |
161 | 162 | ||
162 | if (priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE) | 163 | if (priv->eeprom_data->sku & EEPROM_SKU_CAP_11N_ENABLE) |
163 | flush_cmd.fifo_control |= IWL_AGG_TX_QUEUE_MSK; | 164 | flush_cmd.fifo_control |= IWL_AGG_TX_QUEUE_MSK; |
164 | 165 | ||
165 | IWL_DEBUG_INFO(priv, "fifo queue control: 0X%x\n", | 166 | IWL_DEBUG_INFO(priv, "fifo queue control: 0X%x\n", |
@@ -617,6 +618,11 @@ static bool iwlagn_fill_txpower_mode(struct iwl_priv *priv, | |||
617 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | 618 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; |
618 | int ave_rssi; | 619 | int ave_rssi; |
619 | 620 | ||
621 | if (!ctx->vif || (ctx->vif->type != NL80211_IFTYPE_STATION)) { | ||
622 | IWL_DEBUG_INFO(priv, "BSS ctx not active or not in sta mode\n"); | ||
623 | return false; | ||
624 | } | ||
625 | |||
620 | ave_rssi = ieee80211_ave_rssi(ctx->vif); | 626 | ave_rssi = ieee80211_ave_rssi(ctx->vif); |
621 | if (!ave_rssi) { | 627 | if (!ave_rssi) { |
622 | /* no rssi data, no changes to reduce tx power */ | 628 | /* no rssi data, no changes to reduce tx power */ |
@@ -818,7 +824,7 @@ void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | |||
818 | if (priv->chain_noise_data.active_chains) | 824 | if (priv->chain_noise_data.active_chains) |
819 | active_chains = priv->chain_noise_data.active_chains; | 825 | active_chains = priv->chain_noise_data.active_chains; |
820 | else | 826 | else |
821 | active_chains = priv->hw_params.valid_rx_ant; | 827 | active_chains = priv->eeprom_data->valid_rx_ant; |
822 | 828 | ||
823 | if (priv->cfg->bt_params && | 829 | if (priv->cfg->bt_params && |
824 | priv->cfg->bt_params->advanced_bt_coexist && | 830 | priv->cfg->bt_params->advanced_bt_coexist && |
@@ -1259,7 +1265,7 @@ int iwl_dvm_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
1259 | * the mutex, this ensures we don't try to send two | 1265 | * the mutex, this ensures we don't try to send two |
1260 | * (or more) synchronous commands at a time. | 1266 | * (or more) synchronous commands at a time. |
1261 | */ | 1267 | */ |
1262 | if (cmd->flags & CMD_SYNC) | 1268 | if (!(cmd->flags & CMD_ASYNC)) |
1263 | lockdep_assert_held(&priv->mutex); | 1269 | lockdep_assert_held(&priv->mutex); |
1264 | 1270 | ||
1265 | if (priv->ucode_owner == IWL_OWNERSHIP_TM && | 1271 | if (priv->ucode_owner == IWL_OWNERSHIP_TM && |
diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index a55012609ca..b83ca358eb1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c | |||
@@ -38,19 +38,20 @@ | |||
38 | #include <linux/etherdevice.h> | 38 | #include <linux/etherdevice.h> |
39 | #include <linux/if_arp.h> | 39 | #include <linux/if_arp.h> |
40 | 40 | ||
41 | #include <net/ieee80211_radiotap.h> | ||
41 | #include <net/mac80211.h> | 42 | #include <net/mac80211.h> |
42 | 43 | ||
43 | #include <asm/div64.h> | 44 | #include <asm/div64.h> |
44 | 45 | ||
45 | #include "iwl-eeprom.h" | ||
46 | #include "iwl-dev.h" | ||
47 | #include "iwl-io.h" | 46 | #include "iwl-io.h" |
48 | #include "iwl-agn-calib.h" | ||
49 | #include "iwl-agn.h" | ||
50 | #include "iwl-trans.h" | 47 | #include "iwl-trans.h" |
51 | #include "iwl-op-mode.h" | 48 | #include "iwl-op-mode.h" |
52 | #include "iwl-modparams.h" | 49 | #include "iwl-modparams.h" |
53 | 50 | ||
51 | #include "dev.h" | ||
52 | #include "calib.h" | ||
53 | #include "agn.h" | ||
54 | |||
54 | /***************************************************************************** | 55 | /***************************************************************************** |
55 | * | 56 | * |
56 | * mac80211 entry point functions | 57 | * mac80211 entry point functions |
@@ -154,6 +155,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, | |||
154 | IEEE80211_HW_SCAN_WHILE_IDLE; | 155 | IEEE80211_HW_SCAN_WHILE_IDLE; |
155 | 156 | ||
156 | hw->offchannel_tx_hw_queue = IWL_AUX_QUEUE; | 157 | hw->offchannel_tx_hw_queue = IWL_AUX_QUEUE; |
158 | hw->radiotap_mcs_details |= IEEE80211_RADIOTAP_MCS_HAVE_FMT; | ||
157 | 159 | ||
158 | /* | 160 | /* |
159 | * Including the following line will crash some AP's. This | 161 | * Including the following line will crash some AP's. This |
@@ -162,7 +164,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, | |||
162 | hw->max_tx_aggregation_subframes = LINK_QUAL_AGG_FRAME_LIMIT_DEF; | 164 | hw->max_tx_aggregation_subframes = LINK_QUAL_AGG_FRAME_LIMIT_DEF; |
163 | */ | 165 | */ |
164 | 166 | ||
165 | if (priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE) | 167 | if (priv->eeprom_data->sku & EEPROM_SKU_CAP_11N_ENABLE) |
166 | hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | | 168 | hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | |
167 | IEEE80211_HW_SUPPORTS_STATIC_SMPS; | 169 | IEEE80211_HW_SUPPORTS_STATIC_SMPS; |
168 | 170 | ||
@@ -237,12 +239,12 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, | |||
237 | 239 | ||
238 | hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL; | 240 | hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL; |
239 | 241 | ||
240 | if (priv->bands[IEEE80211_BAND_2GHZ].n_channels) | 242 | if (priv->eeprom_data->bands[IEEE80211_BAND_2GHZ].n_channels) |
241 | priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = | 243 | priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = |
242 | &priv->bands[IEEE80211_BAND_2GHZ]; | 244 | &priv->eeprom_data->bands[IEEE80211_BAND_2GHZ]; |
243 | if (priv->bands[IEEE80211_BAND_5GHZ].n_channels) | 245 | if (priv->eeprom_data->bands[IEEE80211_BAND_5GHZ].n_channels) |
244 | priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = | 246 | priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = |
245 | &priv->bands[IEEE80211_BAND_5GHZ]; | 247 | &priv->eeprom_data->bands[IEEE80211_BAND_5GHZ]; |
246 | 248 | ||
247 | hw->wiphy->hw_version = priv->trans->hw_id; | 249 | hw->wiphy->hw_version = priv->trans->hw_id; |
248 | 250 | ||
@@ -341,7 +343,7 @@ static int iwlagn_mac_start(struct ieee80211_hw *hw) | |||
341 | return 0; | 343 | return 0; |
342 | } | 344 | } |
343 | 345 | ||
344 | void iwlagn_mac_stop(struct ieee80211_hw *hw) | 346 | static void iwlagn_mac_stop(struct ieee80211_hw *hw) |
345 | { | 347 | { |
346 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 348 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
347 | 349 | ||
@@ -369,9 +371,9 @@ void iwlagn_mac_stop(struct ieee80211_hw *hw) | |||
369 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 371 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
370 | } | 372 | } |
371 | 373 | ||
372 | void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw, | 374 | static void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw, |
373 | struct ieee80211_vif *vif, | 375 | struct ieee80211_vif *vif, |
374 | struct cfg80211_gtk_rekey_data *data) | 376 | struct cfg80211_gtk_rekey_data *data) |
375 | { | 377 | { |
376 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 378 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
377 | 379 | ||
@@ -397,7 +399,8 @@ void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw, | |||
397 | 399 | ||
398 | #ifdef CONFIG_PM_SLEEP | 400 | #ifdef CONFIG_PM_SLEEP |
399 | 401 | ||
400 | int iwlagn_mac_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | 402 | static int iwlagn_mac_suspend(struct ieee80211_hw *hw, |
403 | struct cfg80211_wowlan *wowlan) | ||
401 | { | 404 | { |
402 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 405 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
403 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | 406 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; |
@@ -473,7 +476,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) | |||
473 | } | 476 | } |
474 | 477 | ||
475 | if (priv->wowlan_sram) | 478 | if (priv->wowlan_sram) |
476 | _iwl_read_targ_mem_words( | 479 | _iwl_read_targ_mem_dwords( |
477 | priv->trans, 0x800000, | 480 | priv->trans, 0x800000, |
478 | priv->wowlan_sram, | 481 | priv->wowlan_sram, |
479 | img->sec[IWL_UCODE_SECTION_DATA].len / 4); | 482 | img->sec[IWL_UCODE_SECTION_DATA].len / 4); |
@@ -508,7 +511,7 @@ static void iwlagn_mac_set_wakeup(struct ieee80211_hw *hw, bool enabled) | |||
508 | } | 511 | } |
509 | #endif | 512 | #endif |
510 | 513 | ||
511 | void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | 514 | static void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) |
512 | { | 515 | { |
513 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 516 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
514 | 517 | ||
@@ -519,21 +522,21 @@ void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
519 | dev_kfree_skb_any(skb); | 522 | dev_kfree_skb_any(skb); |
520 | } | 523 | } |
521 | 524 | ||
522 | void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw, | 525 | static void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw, |
523 | struct ieee80211_vif *vif, | 526 | struct ieee80211_vif *vif, |
524 | struct ieee80211_key_conf *keyconf, | 527 | struct ieee80211_key_conf *keyconf, |
525 | struct ieee80211_sta *sta, | 528 | struct ieee80211_sta *sta, |
526 | u32 iv32, u16 *phase1key) | 529 | u32 iv32, u16 *phase1key) |
527 | { | 530 | { |
528 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 531 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
529 | 532 | ||
530 | iwl_update_tkip_key(priv, vif, keyconf, sta, iv32, phase1key); | 533 | iwl_update_tkip_key(priv, vif, keyconf, sta, iv32, phase1key); |
531 | } | 534 | } |
532 | 535 | ||
533 | int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | 536 | static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, |
534 | struct ieee80211_vif *vif, | 537 | struct ieee80211_vif *vif, |
535 | struct ieee80211_sta *sta, | 538 | struct ieee80211_sta *sta, |
536 | struct ieee80211_key_conf *key) | 539 | struct ieee80211_key_conf *key) |
537 | { | 540 | { |
538 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 541 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
539 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; | 542 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; |
@@ -633,11 +636,11 @@ int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
633 | return ret; | 636 | return ret; |
634 | } | 637 | } |
635 | 638 | ||
636 | int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, | 639 | static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, |
637 | struct ieee80211_vif *vif, | 640 | struct ieee80211_vif *vif, |
638 | enum ieee80211_ampdu_mlme_action action, | 641 | enum ieee80211_ampdu_mlme_action action, |
639 | struct ieee80211_sta *sta, u16 tid, u16 *ssn, | 642 | struct ieee80211_sta *sta, u16 tid, u16 *ssn, |
640 | u8 buf_size) | 643 | u8 buf_size) |
641 | { | 644 | { |
642 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 645 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
643 | int ret = -EINVAL; | 646 | int ret = -EINVAL; |
@@ -646,7 +649,7 @@ int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, | |||
646 | IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n", | 649 | IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n", |
647 | sta->addr, tid); | 650 | sta->addr, tid); |
648 | 651 | ||
649 | if (!(priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE)) | 652 | if (!(priv->eeprom_data->sku & EEPROM_SKU_CAP_11N_ENABLE)) |
650 | return -EACCES; | 653 | return -EACCES; |
651 | 654 | ||
652 | IWL_DEBUG_MAC80211(priv, "enter\n"); | 655 | IWL_DEBUG_MAC80211(priv, "enter\n"); |
@@ -664,7 +667,7 @@ int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, | |||
664 | ret = iwl_sta_rx_agg_stop(priv, sta, tid); | 667 | ret = iwl_sta_rx_agg_stop(priv, sta, tid); |
665 | break; | 668 | break; |
666 | case IEEE80211_AMPDU_TX_START: | 669 | case IEEE80211_AMPDU_TX_START: |
667 | if (!priv->trans->ops->tx_agg_setup) | 670 | if (!priv->trans->ops->txq_enable) |
668 | break; | 671 | break; |
669 | if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG) | 672 | if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG) |
670 | break; | 673 | break; |
@@ -759,11 +762,11 @@ static int iwlagn_mac_sta_remove(struct ieee80211_hw *hw, | |||
759 | return ret; | 762 | return ret; |
760 | } | 763 | } |
761 | 764 | ||
762 | int iwlagn_mac_sta_state(struct ieee80211_hw *hw, | 765 | static int iwlagn_mac_sta_state(struct ieee80211_hw *hw, |
763 | struct ieee80211_vif *vif, | 766 | struct ieee80211_vif *vif, |
764 | struct ieee80211_sta *sta, | 767 | struct ieee80211_sta *sta, |
765 | enum ieee80211_sta_state old_state, | 768 | enum ieee80211_sta_state old_state, |
766 | enum ieee80211_sta_state new_state) | 769 | enum ieee80211_sta_state new_state) |
767 | { | 770 | { |
768 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 771 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
769 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; | 772 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; |
@@ -842,11 +845,10 @@ int iwlagn_mac_sta_state(struct ieee80211_hw *hw, | |||
842 | return ret; | 845 | return ret; |
843 | } | 846 | } |
844 | 847 | ||
845 | void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, | 848 | static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, |
846 | struct ieee80211_channel_switch *ch_switch) | 849 | struct ieee80211_channel_switch *ch_switch) |
847 | { | 850 | { |
848 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 851 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
849 | const struct iwl_channel_info *ch_info; | ||
850 | struct ieee80211_conf *conf = &hw->conf; | 852 | struct ieee80211_conf *conf = &hw->conf; |
851 | struct ieee80211_channel *channel = ch_switch->channel; | 853 | struct ieee80211_channel *channel = ch_switch->channel; |
852 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; | 854 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; |
@@ -883,12 +885,6 @@ void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, | |||
883 | if (le16_to_cpu(ctx->active.channel) == ch) | 885 | if (le16_to_cpu(ctx->active.channel) == ch) |
884 | goto out; | 886 | goto out; |
885 | 887 | ||
886 | ch_info = iwl_get_channel_info(priv, channel->band, ch); | ||
887 | if (!is_channel_valid(ch_info)) { | ||
888 | IWL_DEBUG_MAC80211(priv, "invalid channel\n"); | ||
889 | goto out; | ||
890 | } | ||
891 | |||
892 | priv->current_ht_config.smps = conf->smps_mode; | 888 | priv->current_ht_config.smps = conf->smps_mode; |
893 | 889 | ||
894 | /* Configure HT40 channels */ | 890 | /* Configure HT40 channels */ |
@@ -937,10 +933,10 @@ void iwl_chswitch_done(struct iwl_priv *priv, bool is_success) | |||
937 | ieee80211_chswitch_done(ctx->vif, is_success); | 933 | ieee80211_chswitch_done(ctx->vif, is_success); |
938 | } | 934 | } |
939 | 935 | ||
940 | void iwlagn_configure_filter(struct ieee80211_hw *hw, | 936 | static void iwlagn_configure_filter(struct ieee80211_hw *hw, |
941 | unsigned int changed_flags, | 937 | unsigned int changed_flags, |
942 | unsigned int *total_flags, | 938 | unsigned int *total_flags, |
943 | u64 multicast) | 939 | u64 multicast) |
944 | { | 940 | { |
945 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 941 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
946 | __le32 filter_or = 0, filter_nand = 0; | 942 | __le32 filter_or = 0, filter_nand = 0; |
@@ -987,7 +983,7 @@ void iwlagn_configure_filter(struct ieee80211_hw *hw, | |||
987 | FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; | 983 | FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; |
988 | } | 984 | } |
989 | 985 | ||
990 | void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop) | 986 | static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop) |
991 | { | 987 | { |
992 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 988 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
993 | 989 | ||
@@ -1040,8 +1036,18 @@ static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw, | |||
1040 | mutex_lock(&priv->mutex); | 1036 | mutex_lock(&priv->mutex); |
1041 | 1037 | ||
1042 | if (test_bit(STATUS_SCAN_HW, &priv->status)) { | 1038 | if (test_bit(STATUS_SCAN_HW, &priv->status)) { |
1043 | err = -EBUSY; | 1039 | /* mac80211 should not scan while ROC or ROC while scanning */ |
1044 | goto out; | 1040 | if (WARN_ON_ONCE(priv->scan_type != IWL_SCAN_RADIO_RESET)) { |
1041 | err = -EBUSY; | ||
1042 | goto out; | ||
1043 | } | ||
1044 | |||
1045 | iwl_scan_cancel_timeout(priv, 100); | ||
1046 | |||
1047 | if (test_bit(STATUS_SCAN_HW, &priv->status)) { | ||
1048 | err = -EBUSY; | ||
1049 | goto out; | ||
1050 | } | ||
1045 | } | 1051 | } |
1046 | 1052 | ||
1047 | priv->hw_roc_channel = channel; | 1053 | priv->hw_roc_channel = channel; |
@@ -1114,7 +1120,7 @@ static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw, | |||
1114 | return err; | 1120 | return err; |
1115 | } | 1121 | } |
1116 | 1122 | ||
1117 | int iwlagn_mac_cancel_remain_on_channel(struct ieee80211_hw *hw) | 1123 | static int iwlagn_mac_cancel_remain_on_channel(struct ieee80211_hw *hw) |
1118 | { | 1124 | { |
1119 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 1125 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
1120 | 1126 | ||
@@ -1131,8 +1137,8 @@ int iwlagn_mac_cancel_remain_on_channel(struct ieee80211_hw *hw) | |||
1131 | return 0; | 1137 | return 0; |
1132 | } | 1138 | } |
1133 | 1139 | ||
1134 | void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw, | 1140 | static void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw, |
1135 | enum ieee80211_rssi_event rssi_event) | 1141 | enum ieee80211_rssi_event rssi_event) |
1136 | { | 1142 | { |
1137 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 1143 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
1138 | 1144 | ||
@@ -1156,8 +1162,8 @@ void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw, | |||
1156 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 1162 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
1157 | } | 1163 | } |
1158 | 1164 | ||
1159 | int iwlagn_mac_set_tim(struct ieee80211_hw *hw, | 1165 | static int iwlagn_mac_set_tim(struct ieee80211_hw *hw, |
1160 | struct ieee80211_sta *sta, bool set) | 1166 | struct ieee80211_sta *sta, bool set) |
1161 | { | 1167 | { |
1162 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 1168 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
1163 | 1169 | ||
@@ -1166,9 +1172,9 @@ int iwlagn_mac_set_tim(struct ieee80211_hw *hw, | |||
1166 | return 0; | 1172 | return 0; |
1167 | } | 1173 | } |
1168 | 1174 | ||
1169 | int iwlagn_mac_conf_tx(struct ieee80211_hw *hw, | 1175 | static int iwlagn_mac_conf_tx(struct ieee80211_hw *hw, |
1170 | struct ieee80211_vif *vif, u16 queue, | 1176 | struct ieee80211_vif *vif, u16 queue, |
1171 | const struct ieee80211_tx_queue_params *params) | 1177 | const struct ieee80211_tx_queue_params *params) |
1172 | { | 1178 | { |
1173 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 1179 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
1174 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; | 1180 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; |
@@ -1210,7 +1216,7 @@ int iwlagn_mac_conf_tx(struct ieee80211_hw *hw, | |||
1210 | return 0; | 1216 | return 0; |
1211 | } | 1217 | } |
1212 | 1218 | ||
1213 | int iwlagn_mac_tx_last_beacon(struct ieee80211_hw *hw) | 1219 | static int iwlagn_mac_tx_last_beacon(struct ieee80211_hw *hw) |
1214 | { | 1220 | { |
1215 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 1221 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
1216 | 1222 | ||
@@ -1226,7 +1232,8 @@ static int iwl_set_mode(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | |||
1226 | return iwlagn_commit_rxon(priv, ctx); | 1232 | return iwlagn_commit_rxon(priv, ctx); |
1227 | } | 1233 | } |
1228 | 1234 | ||
1229 | int iwl_setup_interface(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | 1235 | static int iwl_setup_interface(struct iwl_priv *priv, |
1236 | struct iwl_rxon_context *ctx) | ||
1230 | { | 1237 | { |
1231 | struct ieee80211_vif *vif = ctx->vif; | 1238 | struct ieee80211_vif *vif = ctx->vif; |
1232 | int err, ac; | 1239 | int err, ac; |
@@ -1346,9 +1353,9 @@ static int iwlagn_mac_add_interface(struct ieee80211_hw *hw, | |||
1346 | return err; | 1353 | return err; |
1347 | } | 1354 | } |
1348 | 1355 | ||
1349 | void iwl_teardown_interface(struct iwl_priv *priv, | 1356 | static void iwl_teardown_interface(struct iwl_priv *priv, |
1350 | struct ieee80211_vif *vif, | 1357 | struct ieee80211_vif *vif, |
1351 | bool mode_change) | 1358 | bool mode_change) |
1352 | { | 1359 | { |
1353 | struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); | 1360 | struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); |
1354 | 1361 | ||
@@ -1404,13 +1411,11 @@ static void iwlagn_mac_remove_interface(struct ieee80211_hw *hw, | |||
1404 | } | 1411 | } |
1405 | 1412 | ||
1406 | static int iwlagn_mac_change_interface(struct ieee80211_hw *hw, | 1413 | static int iwlagn_mac_change_interface(struct ieee80211_hw *hw, |
1407 | struct ieee80211_vif *vif, | 1414 | struct ieee80211_vif *vif, |
1408 | enum nl80211_iftype newtype, bool newp2p) | 1415 | enum nl80211_iftype newtype, bool newp2p) |
1409 | { | 1416 | { |
1410 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 1417 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
1411 | struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); | 1418 | struct iwl_rxon_context *ctx, *tmp; |
1412 | struct iwl_rxon_context *bss_ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
1413 | struct iwl_rxon_context *tmp; | ||
1414 | enum nl80211_iftype newviftype = newtype; | 1419 | enum nl80211_iftype newviftype = newtype; |
1415 | u32 interface_modes; | 1420 | u32 interface_modes; |
1416 | int err; | 1421 | int err; |
@@ -1421,6 +1426,18 @@ static int iwlagn_mac_change_interface(struct ieee80211_hw *hw, | |||
1421 | 1426 | ||
1422 | mutex_lock(&priv->mutex); | 1427 | mutex_lock(&priv->mutex); |
1423 | 1428 | ||
1429 | ctx = iwl_rxon_ctx_from_vif(vif); | ||
1430 | |||
1431 | /* | ||
1432 | * To simplify this code, only support changes on the | ||
1433 | * BSS context. The PAN context is usually reassigned | ||
1434 | * by creating/removing P2P interfaces anyway. | ||
1435 | */ | ||
1436 | if (ctx->ctxid != IWL_RXON_CTX_BSS) { | ||
1437 | err = -EBUSY; | ||
1438 | goto out; | ||
1439 | } | ||
1440 | |||
1424 | if (!ctx->vif || !iwl_is_ready_rf(priv)) { | 1441 | if (!ctx->vif || !iwl_is_ready_rf(priv)) { |
1425 | /* | 1442 | /* |
1426 | * Huh? But wait ... this can maybe happen when | 1443 | * Huh? But wait ... this can maybe happen when |
@@ -1430,32 +1447,19 @@ static int iwlagn_mac_change_interface(struct ieee80211_hw *hw, | |||
1430 | goto out; | 1447 | goto out; |
1431 | } | 1448 | } |
1432 | 1449 | ||
1450 | /* Check if the switch is supported in the same context */ | ||
1433 | interface_modes = ctx->interface_modes | ctx->exclusive_interface_modes; | 1451 | interface_modes = ctx->interface_modes | ctx->exclusive_interface_modes; |
1434 | |||
1435 | if (!(interface_modes & BIT(newtype))) { | 1452 | if (!(interface_modes & BIT(newtype))) { |
1436 | err = -EBUSY; | 1453 | err = -EBUSY; |
1437 | goto out; | 1454 | goto out; |
1438 | } | 1455 | } |
1439 | 1456 | ||
1440 | /* | ||
1441 | * Refuse a change that should be done by moving from the PAN | ||
1442 | * context to the BSS context instead, if the BSS context is | ||
1443 | * available and can support the new interface type. | ||
1444 | */ | ||
1445 | if (ctx->ctxid == IWL_RXON_CTX_PAN && !bss_ctx->vif && | ||
1446 | (bss_ctx->interface_modes & BIT(newtype) || | ||
1447 | bss_ctx->exclusive_interface_modes & BIT(newtype))) { | ||
1448 | BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); | ||
1449 | err = -EBUSY; | ||
1450 | goto out; | ||
1451 | } | ||
1452 | |||
1453 | if (ctx->exclusive_interface_modes & BIT(newtype)) { | 1457 | if (ctx->exclusive_interface_modes & BIT(newtype)) { |
1454 | for_each_context(priv, tmp) { | 1458 | for_each_context(priv, tmp) { |
1455 | if (ctx == tmp) | 1459 | if (ctx == tmp) |
1456 | continue; | 1460 | continue; |
1457 | 1461 | ||
1458 | if (!tmp->vif) | 1462 | if (!tmp->is_active) |
1459 | continue; | 1463 | continue; |
1460 | 1464 | ||
1461 | /* | 1465 | /* |
@@ -1489,9 +1493,9 @@ static int iwlagn_mac_change_interface(struct ieee80211_hw *hw, | |||
1489 | return err; | 1493 | return err; |
1490 | } | 1494 | } |
1491 | 1495 | ||
1492 | int iwlagn_mac_hw_scan(struct ieee80211_hw *hw, | 1496 | static int iwlagn_mac_hw_scan(struct ieee80211_hw *hw, |
1493 | struct ieee80211_vif *vif, | 1497 | struct ieee80211_vif *vif, |
1494 | struct cfg80211_scan_request *req) | 1498 | struct cfg80211_scan_request *req) |
1495 | { | 1499 | { |
1496 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 1500 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
1497 | int ret; | 1501 | int ret; |
@@ -1546,10 +1550,10 @@ static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id) | |||
1546 | iwl_send_add_sta(priv, &cmd, CMD_ASYNC); | 1550 | iwl_send_add_sta(priv, &cmd, CMD_ASYNC); |
1547 | } | 1551 | } |
1548 | 1552 | ||
1549 | void iwlagn_mac_sta_notify(struct ieee80211_hw *hw, | 1553 | static void iwlagn_mac_sta_notify(struct ieee80211_hw *hw, |
1550 | struct ieee80211_vif *vif, | 1554 | struct ieee80211_vif *vif, |
1551 | enum sta_notify_cmd cmd, | 1555 | enum sta_notify_cmd cmd, |
1552 | struct ieee80211_sta *sta) | 1556 | struct ieee80211_sta *sta) |
1553 | { | 1557 | { |
1554 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 1558 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
1555 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; | 1559 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/dvm/main.c index 5149e6f7294..abfd7916bde 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/dvm/main.c | |||
@@ -44,15 +44,19 @@ | |||
44 | 44 | ||
45 | #include <asm/div64.h> | 45 | #include <asm/div64.h> |
46 | 46 | ||
47 | #include "iwl-eeprom.h" | 47 | #include "iwl-eeprom-read.h" |
48 | #include "iwl-dev.h" | 48 | #include "iwl-eeprom-parse.h" |
49 | #include "iwl-io.h" | 49 | #include "iwl-io.h" |
50 | #include "iwl-agn-calib.h" | ||
51 | #include "iwl-agn.h" | ||
52 | #include "iwl-trans.h" | 50 | #include "iwl-trans.h" |
53 | #include "iwl-op-mode.h" | 51 | #include "iwl-op-mode.h" |
54 | #include "iwl-drv.h" | 52 | #include "iwl-drv.h" |
55 | #include "iwl-modparams.h" | 53 | #include "iwl-modparams.h" |
54 | #include "iwl-prph.h" | ||
55 | |||
56 | #include "dev.h" | ||
57 | #include "calib.h" | ||
58 | #include "agn.h" | ||
59 | |||
56 | 60 | ||
57 | /****************************************************************************** | 61 | /****************************************************************************** |
58 | * | 62 | * |
@@ -79,6 +83,8 @@ MODULE_VERSION(DRV_VERSION); | |||
79 | MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); | 83 | MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); |
80 | MODULE_LICENSE("GPL"); | 84 | MODULE_LICENSE("GPL"); |
81 | 85 | ||
86 | static const struct iwl_op_mode_ops iwl_dvm_ops; | ||
87 | |||
82 | void iwl_update_chain_flags(struct iwl_priv *priv) | 88 | void iwl_update_chain_flags(struct iwl_priv *priv) |
83 | { | 89 | { |
84 | struct iwl_rxon_context *ctx; | 90 | struct iwl_rxon_context *ctx; |
@@ -179,7 +185,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) | |||
179 | rate = info->control.rates[0].idx; | 185 | rate = info->control.rates[0].idx; |
180 | 186 | ||
181 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, | 187 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, |
182 | priv->hw_params.valid_tx_ant); | 188 | priv->eeprom_data->valid_tx_ant); |
183 | rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant); | 189 | rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant); |
184 | 190 | ||
185 | /* In mac80211, rates for 5 GHz start at 0 */ | 191 | /* In mac80211, rates for 5 GHz start at 0 */ |
@@ -402,7 +408,7 @@ static void iwl_continuous_event_trace(struct iwl_priv *priv) | |||
402 | 408 | ||
403 | base = priv->device_pointers.log_event_table; | 409 | base = priv->device_pointers.log_event_table; |
404 | if (iwlagn_hw_valid_rtc_data_addr(base)) { | 410 | if (iwlagn_hw_valid_rtc_data_addr(base)) { |
405 | iwl_read_targ_mem_words(priv->trans, base, &read, sizeof(read)); | 411 | iwl_read_targ_mem_bytes(priv->trans, base, &read, sizeof(read)); |
406 | capacity = read.capacity; | 412 | capacity = read.capacity; |
407 | mode = read.mode; | 413 | mode = read.mode; |
408 | num_wraps = read.wrap_counter; | 414 | num_wraps = read.wrap_counter; |
@@ -577,7 +583,7 @@ static const u8 iwlagn_pan_ac_to_queue[] = { | |||
577 | 7, 6, 5, 4, | 583 | 7, 6, 5, 4, |
578 | }; | 584 | }; |
579 | 585 | ||
580 | void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) | 586 | static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) |
581 | { | 587 | { |
582 | int i; | 588 | int i; |
583 | 589 | ||
@@ -644,7 +650,7 @@ void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) | |||
644 | BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); | 650 | BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); |
645 | } | 651 | } |
646 | 652 | ||
647 | void iwl_rf_kill_ct_config(struct iwl_priv *priv) | 653 | static void iwl_rf_kill_ct_config(struct iwl_priv *priv) |
648 | { | 654 | { |
649 | struct iwl_ct_kill_config cmd; | 655 | struct iwl_ct_kill_config cmd; |
650 | struct iwl_ct_kill_throttling_config adv_cmd; | 656 | struct iwl_ct_kill_throttling_config adv_cmd; |
@@ -725,7 +731,7 @@ static int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant) | |||
725 | } | 731 | } |
726 | } | 732 | } |
727 | 733 | ||
728 | void iwl_send_bt_config(struct iwl_priv *priv) | 734 | static void iwl_send_bt_config(struct iwl_priv *priv) |
729 | { | 735 | { |
730 | struct iwl_bt_cmd bt_cmd = { | 736 | struct iwl_bt_cmd bt_cmd = { |
731 | .lead_time = BT_LEAD_TIME_DEF, | 737 | .lead_time = BT_LEAD_TIME_DEF, |
@@ -813,7 +819,7 @@ int iwl_alive_start(struct iwl_priv *priv) | |||
813 | ieee80211_wake_queues(priv->hw); | 819 | ieee80211_wake_queues(priv->hw); |
814 | 820 | ||
815 | /* Configure Tx antenna selection based on H/W config */ | 821 | /* Configure Tx antenna selection based on H/W config */ |
816 | iwlagn_send_tx_ant_config(priv, priv->hw_params.valid_tx_ant); | 822 | iwlagn_send_tx_ant_config(priv, priv->eeprom_data->valid_tx_ant); |
817 | 823 | ||
818 | if (iwl_is_associated_ctx(ctx) && !priv->wowlan) { | 824 | if (iwl_is_associated_ctx(ctx) && !priv->wowlan) { |
819 | struct iwl_rxon_cmd *active_rxon = | 825 | struct iwl_rxon_cmd *active_rxon = |
@@ -931,11 +937,12 @@ void iwl_down(struct iwl_priv *priv) | |||
931 | priv->ucode_loaded = false; | 937 | priv->ucode_loaded = false; |
932 | iwl_trans_stop_device(priv->trans); | 938 | iwl_trans_stop_device(priv->trans); |
933 | 939 | ||
940 | /* Set num_aux_in_flight must be done after the transport is stopped */ | ||
941 | atomic_set(&priv->num_aux_in_flight, 0); | ||
942 | |||
934 | /* Clear out all status bits but a few that are stable across reset */ | 943 | /* Clear out all status bits but a few that are stable across reset */ |
935 | priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) << | 944 | priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) << |
936 | STATUS_RF_KILL_HW | | 945 | STATUS_RF_KILL_HW | |
937 | test_bit(STATUS_GEO_CONFIGURED, &priv->status) << | ||
938 | STATUS_GEO_CONFIGURED | | ||
939 | test_bit(STATUS_FW_ERROR, &priv->status) << | 946 | test_bit(STATUS_FW_ERROR, &priv->status) << |
940 | STATUS_FW_ERROR | | 947 | STATUS_FW_ERROR | |
941 | test_bit(STATUS_EXIT_PENDING, &priv->status) << | 948 | test_bit(STATUS_EXIT_PENDING, &priv->status) << |
@@ -1077,7 +1084,7 @@ static void iwlagn_disable_roc_work(struct work_struct *work) | |||
1077 | * | 1084 | * |
1078 | *****************************************************************************/ | 1085 | *****************************************************************************/ |
1079 | 1086 | ||
1080 | void iwl_setup_deferred_work(struct iwl_priv *priv) | 1087 | static void iwl_setup_deferred_work(struct iwl_priv *priv) |
1081 | { | 1088 | { |
1082 | priv->workqueue = create_singlethread_workqueue(DRV_NAME); | 1089 | priv->workqueue = create_singlethread_workqueue(DRV_NAME); |
1083 | 1090 | ||
@@ -1122,224 +1129,14 @@ void iwl_cancel_deferred_work(struct iwl_priv *priv) | |||
1122 | del_timer_sync(&priv->ucode_trace); | 1129 | del_timer_sync(&priv->ucode_trace); |
1123 | } | 1130 | } |
1124 | 1131 | ||
1125 | static void iwl_init_hw_rates(struct ieee80211_rate *rates) | 1132 | static int iwl_init_drv(struct iwl_priv *priv) |
1126 | { | ||
1127 | int i; | ||
1128 | |||
1129 | for (i = 0; i < IWL_RATE_COUNT_LEGACY; i++) { | ||
1130 | rates[i].bitrate = iwl_rates[i].ieee * 5; | ||
1131 | rates[i].hw_value = i; /* Rate scaling will work on indexes */ | ||
1132 | rates[i].hw_value_short = i; | ||
1133 | rates[i].flags = 0; | ||
1134 | if ((i >= IWL_FIRST_CCK_RATE) && (i <= IWL_LAST_CCK_RATE)) { | ||
1135 | /* | ||
1136 | * If CCK != 1M then set short preamble rate flag. | ||
1137 | */ | ||
1138 | rates[i].flags |= | ||
1139 | (iwl_rates[i].plcp == IWL_RATE_1M_PLCP) ? | ||
1140 | 0 : IEEE80211_RATE_SHORT_PREAMBLE; | ||
1141 | } | ||
1142 | } | ||
1143 | } | ||
1144 | |||
1145 | #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */ | ||
1146 | #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */ | ||
1147 | static void iwl_init_ht_hw_capab(const struct iwl_priv *priv, | ||
1148 | struct ieee80211_sta_ht_cap *ht_info, | ||
1149 | enum ieee80211_band band) | ||
1150 | { | 1133 | { |
1151 | u16 max_bit_rate = 0; | ||
1152 | u8 rx_chains_num = priv->hw_params.rx_chains_num; | ||
1153 | u8 tx_chains_num = priv->hw_params.tx_chains_num; | ||
1154 | |||
1155 | ht_info->cap = 0; | ||
1156 | memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); | ||
1157 | |||
1158 | ht_info->ht_supported = true; | ||
1159 | |||
1160 | if (priv->cfg->ht_params && | ||
1161 | priv->cfg->ht_params->ht_greenfield_support) | ||
1162 | ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; | ||
1163 | ht_info->cap |= IEEE80211_HT_CAP_SGI_20; | ||
1164 | max_bit_rate = MAX_BIT_RATE_20_MHZ; | ||
1165 | if (priv->hw_params.ht40_channel & BIT(band)) { | ||
1166 | ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
1167 | ht_info->cap |= IEEE80211_HT_CAP_SGI_40; | ||
1168 | ht_info->mcs.rx_mask[4] = 0x01; | ||
1169 | max_bit_rate = MAX_BIT_RATE_40_MHZ; | ||
1170 | } | ||
1171 | |||
1172 | if (iwlwifi_mod_params.amsdu_size_8K) | ||
1173 | ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU; | ||
1174 | |||
1175 | ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF; | ||
1176 | ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF; | ||
1177 | |||
1178 | ht_info->mcs.rx_mask[0] = 0xFF; | ||
1179 | if (rx_chains_num >= 2) | ||
1180 | ht_info->mcs.rx_mask[1] = 0xFF; | ||
1181 | if (rx_chains_num >= 3) | ||
1182 | ht_info->mcs.rx_mask[2] = 0xFF; | ||
1183 | |||
1184 | /* Highest supported Rx data rate */ | ||
1185 | max_bit_rate *= rx_chains_num; | ||
1186 | WARN_ON(max_bit_rate & ~IEEE80211_HT_MCS_RX_HIGHEST_MASK); | ||
1187 | ht_info->mcs.rx_highest = cpu_to_le16(max_bit_rate); | ||
1188 | |||
1189 | /* Tx MCS capabilities */ | ||
1190 | ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; | ||
1191 | if (tx_chains_num != rx_chains_num) { | ||
1192 | ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; | ||
1193 | ht_info->mcs.tx_params |= ((tx_chains_num - 1) << | ||
1194 | IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); | ||
1195 | } | ||
1196 | } | ||
1197 | |||
1198 | /** | ||
1199 | * iwl_init_geos - Initialize mac80211's geo/channel info based from eeprom | ||
1200 | */ | ||
1201 | static int iwl_init_geos(struct iwl_priv *priv) | ||
1202 | { | ||
1203 | struct iwl_channel_info *ch; | ||
1204 | struct ieee80211_supported_band *sband; | ||
1205 | struct ieee80211_channel *channels; | ||
1206 | struct ieee80211_channel *geo_ch; | ||
1207 | struct ieee80211_rate *rates; | ||
1208 | int i = 0; | ||
1209 | s8 max_tx_power = IWLAGN_TX_POWER_TARGET_POWER_MIN; | ||
1210 | |||
1211 | if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates || | ||
1212 | priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) { | ||
1213 | IWL_DEBUG_INFO(priv, "Geography modes already initialized.\n"); | ||
1214 | set_bit(STATUS_GEO_CONFIGURED, &priv->status); | ||
1215 | return 0; | ||
1216 | } | ||
1217 | |||
1218 | channels = kcalloc(priv->channel_count, | ||
1219 | sizeof(struct ieee80211_channel), GFP_KERNEL); | ||
1220 | if (!channels) | ||
1221 | return -ENOMEM; | ||
1222 | |||
1223 | rates = kcalloc(IWL_RATE_COUNT_LEGACY, sizeof(struct ieee80211_rate), | ||
1224 | GFP_KERNEL); | ||
1225 | if (!rates) { | ||
1226 | kfree(channels); | ||
1227 | return -ENOMEM; | ||
1228 | } | ||
1229 | |||
1230 | /* 5.2GHz channels start after the 2.4GHz channels */ | ||
1231 | sband = &priv->bands[IEEE80211_BAND_5GHZ]; | ||
1232 | sband->channels = &channels[ARRAY_SIZE(iwl_eeprom_band_1)]; | ||
1233 | /* just OFDM */ | ||
1234 | sband->bitrates = &rates[IWL_FIRST_OFDM_RATE]; | ||
1235 | sband->n_bitrates = IWL_RATE_COUNT_LEGACY - IWL_FIRST_OFDM_RATE; | ||
1236 | |||
1237 | if (priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE) | ||
1238 | iwl_init_ht_hw_capab(priv, &sband->ht_cap, | ||
1239 | IEEE80211_BAND_5GHZ); | ||
1240 | |||
1241 | sband = &priv->bands[IEEE80211_BAND_2GHZ]; | ||
1242 | sband->channels = channels; | ||
1243 | /* OFDM & CCK */ | ||
1244 | sband->bitrates = rates; | ||
1245 | sband->n_bitrates = IWL_RATE_COUNT_LEGACY; | ||
1246 | |||
1247 | if (priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE) | ||
1248 | iwl_init_ht_hw_capab(priv, &sband->ht_cap, | ||
1249 | IEEE80211_BAND_2GHZ); | ||
1250 | |||
1251 | priv->ieee_channels = channels; | ||
1252 | priv->ieee_rates = rates; | ||
1253 | |||
1254 | for (i = 0; i < priv->channel_count; i++) { | ||
1255 | ch = &priv->channel_info[i]; | ||
1256 | |||
1257 | /* FIXME: might be removed if scan is OK */ | ||
1258 | if (!is_channel_valid(ch)) | ||
1259 | continue; | ||
1260 | |||
1261 | sband = &priv->bands[ch->band]; | ||
1262 | |||
1263 | geo_ch = &sband->channels[sband->n_channels++]; | ||
1264 | |||
1265 | geo_ch->center_freq = | ||
1266 | ieee80211_channel_to_frequency(ch->channel, ch->band); | ||
1267 | geo_ch->max_power = ch->max_power_avg; | ||
1268 | geo_ch->max_antenna_gain = 0xff; | ||
1269 | geo_ch->hw_value = ch->channel; | ||
1270 | |||
1271 | if (is_channel_valid(ch)) { | ||
1272 | if (!(ch->flags & EEPROM_CHANNEL_IBSS)) | ||
1273 | geo_ch->flags |= IEEE80211_CHAN_NO_IBSS; | ||
1274 | |||
1275 | if (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) | ||
1276 | geo_ch->flags |= IEEE80211_CHAN_PASSIVE_SCAN; | ||
1277 | |||
1278 | if (ch->flags & EEPROM_CHANNEL_RADAR) | ||
1279 | geo_ch->flags |= IEEE80211_CHAN_RADAR; | ||
1280 | |||
1281 | geo_ch->flags |= ch->ht40_extension_channel; | ||
1282 | |||
1283 | if (ch->max_power_avg > max_tx_power) | ||
1284 | max_tx_power = ch->max_power_avg; | ||
1285 | } else { | ||
1286 | geo_ch->flags |= IEEE80211_CHAN_DISABLED; | ||
1287 | } | ||
1288 | |||
1289 | IWL_DEBUG_INFO(priv, "Channel %d Freq=%d[%sGHz] %s flag=0x%X\n", | ||
1290 | ch->channel, geo_ch->center_freq, | ||
1291 | is_channel_a_band(ch) ? "5.2" : "2.4", | ||
1292 | geo_ch->flags & IEEE80211_CHAN_DISABLED ? | ||
1293 | "restricted" : "valid", | ||
1294 | geo_ch->flags); | ||
1295 | } | ||
1296 | |||
1297 | priv->tx_power_device_lmt = max_tx_power; | ||
1298 | priv->tx_power_user_lmt = max_tx_power; | ||
1299 | priv->tx_power_next = max_tx_power; | ||
1300 | |||
1301 | if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && | ||
1302 | priv->hw_params.sku & EEPROM_SKU_CAP_BAND_52GHZ) { | ||
1303 | IWL_INFO(priv, "Incorrectly detected BG card as ABG. " | ||
1304 | "Please send your %s to maintainer.\n", | ||
1305 | priv->trans->hw_id_str); | ||
1306 | priv->hw_params.sku &= ~EEPROM_SKU_CAP_BAND_52GHZ; | ||
1307 | } | ||
1308 | |||
1309 | if (iwlwifi_mod_params.disable_5ghz) | ||
1310 | priv->bands[IEEE80211_BAND_5GHZ].n_channels = 0; | ||
1311 | |||
1312 | IWL_INFO(priv, "Tunable channels: %d 802.11bg, %d 802.11a channels\n", | ||
1313 | priv->bands[IEEE80211_BAND_2GHZ].n_channels, | ||
1314 | priv->bands[IEEE80211_BAND_5GHZ].n_channels); | ||
1315 | |||
1316 | set_bit(STATUS_GEO_CONFIGURED, &priv->status); | ||
1317 | |||
1318 | return 0; | ||
1319 | } | ||
1320 | |||
1321 | /* | ||
1322 | * iwl_free_geos - undo allocations in iwl_init_geos | ||
1323 | */ | ||
1324 | static void iwl_free_geos(struct iwl_priv *priv) | ||
1325 | { | ||
1326 | kfree(priv->ieee_channels); | ||
1327 | kfree(priv->ieee_rates); | ||
1328 | clear_bit(STATUS_GEO_CONFIGURED, &priv->status); | ||
1329 | } | ||
1330 | |||
1331 | int iwl_init_drv(struct iwl_priv *priv) | ||
1332 | { | ||
1333 | int ret; | ||
1334 | |||
1335 | spin_lock_init(&priv->sta_lock); | 1134 | spin_lock_init(&priv->sta_lock); |
1336 | 1135 | ||
1337 | mutex_init(&priv->mutex); | 1136 | mutex_init(&priv->mutex); |
1338 | 1137 | ||
1339 | INIT_LIST_HEAD(&priv->calib_results); | 1138 | INIT_LIST_HEAD(&priv->calib_results); |
1340 | 1139 | ||
1341 | priv->ieee_channels = NULL; | ||
1342 | priv->ieee_rates = NULL; | ||
1343 | priv->band = IEEE80211_BAND_2GHZ; | 1140 | priv->band = IEEE80211_BAND_2GHZ; |
1344 | 1141 | ||
1345 | priv->plcp_delta_threshold = | 1142 | priv->plcp_delta_threshold = |
@@ -1370,31 +1167,11 @@ int iwl_init_drv(struct iwl_priv *priv) | |||
1370 | priv->dynamic_frag_thresh = BT_FRAG_THRESHOLD_DEF; | 1167 | priv->dynamic_frag_thresh = BT_FRAG_THRESHOLD_DEF; |
1371 | } | 1168 | } |
1372 | 1169 | ||
1373 | ret = iwl_init_channel_map(priv); | ||
1374 | if (ret) { | ||
1375 | IWL_ERR(priv, "initializing regulatory failed: %d\n", ret); | ||
1376 | goto err; | ||
1377 | } | ||
1378 | |||
1379 | ret = iwl_init_geos(priv); | ||
1380 | if (ret) { | ||
1381 | IWL_ERR(priv, "initializing geos failed: %d\n", ret); | ||
1382 | goto err_free_channel_map; | ||
1383 | } | ||
1384 | iwl_init_hw_rates(priv->ieee_rates); | ||
1385 | |||
1386 | return 0; | 1170 | return 0; |
1387 | |||
1388 | err_free_channel_map: | ||
1389 | iwl_free_channel_map(priv); | ||
1390 | err: | ||
1391 | return ret; | ||
1392 | } | 1171 | } |
1393 | 1172 | ||
1394 | void iwl_uninit_drv(struct iwl_priv *priv) | 1173 | static void iwl_uninit_drv(struct iwl_priv *priv) |
1395 | { | 1174 | { |
1396 | iwl_free_geos(priv); | ||
1397 | iwl_free_channel_map(priv); | ||
1398 | kfree(priv->scan_cmd); | 1175 | kfree(priv->scan_cmd); |
1399 | kfree(priv->beacon_cmd); | 1176 | kfree(priv->beacon_cmd); |
1400 | kfree(rcu_dereference_raw(priv->noa_data)); | 1177 | kfree(rcu_dereference_raw(priv->noa_data)); |
@@ -1404,15 +1181,12 @@ void iwl_uninit_drv(struct iwl_priv *priv) | |||
1404 | #endif | 1181 | #endif |
1405 | } | 1182 | } |
1406 | 1183 | ||
1407 | void iwl_set_hw_params(struct iwl_priv *priv) | 1184 | static void iwl_set_hw_params(struct iwl_priv *priv) |
1408 | { | 1185 | { |
1409 | if (priv->cfg->ht_params) | 1186 | if (priv->cfg->ht_params) |
1410 | priv->hw_params.use_rts_for_aggregation = | 1187 | priv->hw_params.use_rts_for_aggregation = |
1411 | priv->cfg->ht_params->use_rts_for_aggregation; | 1188 | priv->cfg->ht_params->use_rts_for_aggregation; |
1412 | 1189 | ||
1413 | if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_ALL) | ||
1414 | priv->hw_params.sku &= ~EEPROM_SKU_CAP_11N_ENABLE; | ||
1415 | |||
1416 | /* Device-specific setup */ | 1190 | /* Device-specific setup */ |
1417 | priv->lib->set_hw_params(priv); | 1191 | priv->lib->set_hw_params(priv); |
1418 | } | 1192 | } |
@@ -1420,7 +1194,7 @@ void iwl_set_hw_params(struct iwl_priv *priv) | |||
1420 | 1194 | ||
1421 | 1195 | ||
1422 | /* show what optional capabilities we have */ | 1196 | /* show what optional capabilities we have */ |
1423 | void iwl_option_config(struct iwl_priv *priv) | 1197 | static void iwl_option_config(struct iwl_priv *priv) |
1424 | { | 1198 | { |
1425 | #ifdef CONFIG_IWLWIFI_DEBUG | 1199 | #ifdef CONFIG_IWLWIFI_DEBUG |
1426 | IWL_INFO(priv, "CONFIG_IWLWIFI_DEBUG enabled\n"); | 1200 | IWL_INFO(priv, "CONFIG_IWLWIFI_DEBUG enabled\n"); |
@@ -1453,6 +1227,42 @@ void iwl_option_config(struct iwl_priv *priv) | |||
1453 | #endif | 1227 | #endif |
1454 | } | 1228 | } |
1455 | 1229 | ||
1230 | static int iwl_eeprom_init_hw_params(struct iwl_priv *priv) | ||
1231 | { | ||
1232 | u16 radio_cfg; | ||
1233 | |||
1234 | priv->eeprom_data->sku = priv->eeprom_data->sku; | ||
1235 | |||
1236 | if (priv->eeprom_data->sku & EEPROM_SKU_CAP_11N_ENABLE && | ||
1237 | !priv->cfg->ht_params) { | ||
1238 | IWL_ERR(priv, "Invalid 11n configuration\n"); | ||
1239 | return -EINVAL; | ||
1240 | } | ||
1241 | |||
1242 | if (!priv->eeprom_data->sku) { | ||
1243 | IWL_ERR(priv, "Invalid device sku\n"); | ||
1244 | return -EINVAL; | ||
1245 | } | ||
1246 | |||
1247 | IWL_INFO(priv, "Device SKU: 0x%X\n", priv->eeprom_data->sku); | ||
1248 | |||
1249 | radio_cfg = priv->eeprom_data->radio_cfg; | ||
1250 | |||
1251 | priv->hw_params.tx_chains_num = | ||
1252 | num_of_ant(priv->eeprom_data->valid_tx_ant); | ||
1253 | if (priv->cfg->rx_with_siso_diversity) | ||
1254 | priv->hw_params.rx_chains_num = 1; | ||
1255 | else | ||
1256 | priv->hw_params.rx_chains_num = | ||
1257 | num_of_ant(priv->eeprom_data->valid_rx_ant); | ||
1258 | |||
1259 | IWL_INFO(priv, "Valid Tx ant: 0x%X, Valid Rx ant: 0x%X\n", | ||
1260 | priv->eeprom_data->valid_tx_ant, | ||
1261 | priv->eeprom_data->valid_rx_ant); | ||
1262 | |||
1263 | return 0; | ||
1264 | } | ||
1265 | |||
1456 | static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, | 1266 | static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, |
1457 | const struct iwl_cfg *cfg, | 1267 | const struct iwl_cfg *cfg, |
1458 | const struct iwl_fw *fw) | 1268 | const struct iwl_fw *fw) |
@@ -1538,9 +1348,12 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, | |||
1538 | trans_cfg.queue_watchdog_timeout = | 1348 | trans_cfg.queue_watchdog_timeout = |
1539 | priv->cfg->base_params->wd_timeout; | 1349 | priv->cfg->base_params->wd_timeout; |
1540 | else | 1350 | else |
1541 | trans_cfg.queue_watchdog_timeout = IWL_WATCHHDOG_DISABLED; | 1351 | trans_cfg.queue_watchdog_timeout = IWL_WATCHDOG_DISABLED; |
1542 | trans_cfg.command_names = iwl_dvm_cmd_strings; | 1352 | trans_cfg.command_names = iwl_dvm_cmd_strings; |
1543 | 1353 | ||
1354 | WARN_ON(sizeof(priv->transport_queue_stop) * BITS_PER_BYTE < | ||
1355 | priv->cfg->base_params->num_of_queues); | ||
1356 | |||
1544 | ucode_flags = fw->ucode_capa.flags; | 1357 | ucode_flags = fw->ucode_capa.flags; |
1545 | 1358 | ||
1546 | #ifndef CONFIG_IWLWIFI_P2P | 1359 | #ifndef CONFIG_IWLWIFI_P2P |
@@ -1598,25 +1411,33 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, | |||
1598 | goto out_free_hw; | 1411 | goto out_free_hw; |
1599 | 1412 | ||
1600 | /* Read the EEPROM */ | 1413 | /* Read the EEPROM */ |
1601 | if (iwl_eeprom_init(priv, priv->trans->hw_rev)) { | 1414 | if (iwl_read_eeprom(priv->trans, &priv->eeprom_blob, |
1415 | &priv->eeprom_blob_size)) { | ||
1602 | IWL_ERR(priv, "Unable to init EEPROM\n"); | 1416 | IWL_ERR(priv, "Unable to init EEPROM\n"); |
1603 | goto out_free_hw; | 1417 | goto out_free_hw; |
1604 | } | 1418 | } |
1419 | |||
1605 | /* Reset chip to save power until we load uCode during "up". */ | 1420 | /* Reset chip to save power until we load uCode during "up". */ |
1606 | iwl_trans_stop_hw(priv->trans, false); | 1421 | iwl_trans_stop_hw(priv->trans, false); |
1607 | 1422 | ||
1608 | if (iwl_eeprom_check_version(priv)) | 1423 | priv->eeprom_data = iwl_parse_eeprom_data(priv->trans->dev, priv->cfg, |
1424 | priv->eeprom_blob, | ||
1425 | priv->eeprom_blob_size); | ||
1426 | if (!priv->eeprom_data) | ||
1427 | goto out_free_eeprom_blob; | ||
1428 | |||
1429 | if (iwl_eeprom_check_version(priv->eeprom_data, priv->trans)) | ||
1609 | goto out_free_eeprom; | 1430 | goto out_free_eeprom; |
1610 | 1431 | ||
1611 | if (iwl_eeprom_init_hw_params(priv)) | 1432 | if (iwl_eeprom_init_hw_params(priv)) |
1612 | goto out_free_eeprom; | 1433 | goto out_free_eeprom; |
1613 | 1434 | ||
1614 | /* extract MAC Address */ | 1435 | /* extract MAC Address */ |
1615 | iwl_eeprom_get_mac(priv, priv->addresses[0].addr); | 1436 | memcpy(priv->addresses[0].addr, priv->eeprom_data->hw_addr, ETH_ALEN); |
1616 | IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->addresses[0].addr); | 1437 | IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->addresses[0].addr); |
1617 | priv->hw->wiphy->addresses = priv->addresses; | 1438 | priv->hw->wiphy->addresses = priv->addresses; |
1618 | priv->hw->wiphy->n_addresses = 1; | 1439 | priv->hw->wiphy->n_addresses = 1; |
1619 | num_mac = iwl_eeprom_query16(priv, EEPROM_NUM_MAC_ADDRESS); | 1440 | num_mac = priv->eeprom_data->n_hw_addrs; |
1620 | if (num_mac > 1) { | 1441 | if (num_mac > 1) { |
1621 | memcpy(priv->addresses[1].addr, priv->addresses[0].addr, | 1442 | memcpy(priv->addresses[1].addr, priv->addresses[0].addr, |
1622 | ETH_ALEN); | 1443 | ETH_ALEN); |
@@ -1629,7 +1450,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, | |||
1629 | ************************/ | 1450 | ************************/ |
1630 | iwl_set_hw_params(priv); | 1451 | iwl_set_hw_params(priv); |
1631 | 1452 | ||
1632 | if (!(priv->hw_params.sku & EEPROM_SKU_CAP_IPAN_ENABLE)) { | 1453 | if (!(priv->eeprom_data->sku & EEPROM_SKU_CAP_IPAN_ENABLE)) { |
1633 | IWL_DEBUG_INFO(priv, "Your EEPROM disabled PAN"); | 1454 | IWL_DEBUG_INFO(priv, "Your EEPROM disabled PAN"); |
1634 | ucode_flags &= ~IWL_UCODE_TLV_FLAGS_PAN; | 1455 | ucode_flags &= ~IWL_UCODE_TLV_FLAGS_PAN; |
1635 | /* | 1456 | /* |
@@ -1710,8 +1531,10 @@ out_destroy_workqueue: | |||
1710 | destroy_workqueue(priv->workqueue); | 1531 | destroy_workqueue(priv->workqueue); |
1711 | priv->workqueue = NULL; | 1532 | priv->workqueue = NULL; |
1712 | iwl_uninit_drv(priv); | 1533 | iwl_uninit_drv(priv); |
1534 | out_free_eeprom_blob: | ||
1535 | kfree(priv->eeprom_blob); | ||
1713 | out_free_eeprom: | 1536 | out_free_eeprom: |
1714 | iwl_eeprom_free(priv); | 1537 | iwl_free_eeprom_data(priv->eeprom_data); |
1715 | out_free_hw: | 1538 | out_free_hw: |
1716 | ieee80211_free_hw(priv->hw); | 1539 | ieee80211_free_hw(priv->hw); |
1717 | out: | 1540 | out: |
@@ -1719,7 +1542,7 @@ out: | |||
1719 | return op_mode; | 1542 | return op_mode; |
1720 | } | 1543 | } |
1721 | 1544 | ||
1722 | void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode) | 1545 | static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode) |
1723 | { | 1546 | { |
1724 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | 1547 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); |
1725 | 1548 | ||
@@ -1727,7 +1550,7 @@ void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode) | |||
1727 | 1550 | ||
1728 | iwl_dbgfs_unregister(priv); | 1551 | iwl_dbgfs_unregister(priv); |
1729 | 1552 | ||
1730 | iwl_testmode_cleanup(priv); | 1553 | iwl_testmode_free(priv); |
1731 | iwlagn_mac_unregister(priv); | 1554 | iwlagn_mac_unregister(priv); |
1732 | 1555 | ||
1733 | iwl_tt_exit(priv); | 1556 | iwl_tt_exit(priv); |
@@ -1736,7 +1559,8 @@ void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode) | |||
1736 | priv->ucode_loaded = false; | 1559 | priv->ucode_loaded = false; |
1737 | iwl_trans_stop_device(priv->trans); | 1560 | iwl_trans_stop_device(priv->trans); |
1738 | 1561 | ||
1739 | iwl_eeprom_free(priv); | 1562 | kfree(priv->eeprom_blob); |
1563 | iwl_free_eeprom_data(priv->eeprom_data); | ||
1740 | 1564 | ||
1741 | /*netif_stop_queue(dev); */ | 1565 | /*netif_stop_queue(dev); */ |
1742 | flush_workqueue(priv->workqueue); | 1566 | flush_workqueue(priv->workqueue); |
@@ -1849,7 +1673,7 @@ static void iwl_dump_nic_error_log(struct iwl_priv *priv) | |||
1849 | } | 1673 | } |
1850 | 1674 | ||
1851 | /*TODO: Update dbgfs with ISR error stats obtained below */ | 1675 | /*TODO: Update dbgfs with ISR error stats obtained below */ |
1852 | iwl_read_targ_mem_words(trans, base, &table, sizeof(table)); | 1676 | iwl_read_targ_mem_bytes(trans, base, &table, sizeof(table)); |
1853 | 1677 | ||
1854 | if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) { | 1678 | if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) { |
1855 | IWL_ERR(trans, "Start IWL Error Log Dump:\n"); | 1679 | IWL_ERR(trans, "Start IWL Error Log Dump:\n"); |
@@ -2184,7 +2008,7 @@ static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) | |||
2184 | } | 2008 | } |
2185 | } | 2009 | } |
2186 | 2010 | ||
2187 | void iwl_nic_error(struct iwl_op_mode *op_mode) | 2011 | static void iwl_nic_error(struct iwl_op_mode *op_mode) |
2188 | { | 2012 | { |
2189 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | 2013 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); |
2190 | 2014 | ||
@@ -2197,7 +2021,7 @@ void iwl_nic_error(struct iwl_op_mode *op_mode) | |||
2197 | iwlagn_fw_error(priv, false); | 2021 | iwlagn_fw_error(priv, false); |
2198 | } | 2022 | } |
2199 | 2023 | ||
2200 | void iwl_cmd_queue_full(struct iwl_op_mode *op_mode) | 2024 | static void iwl_cmd_queue_full(struct iwl_op_mode *op_mode) |
2201 | { | 2025 | { |
2202 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | 2026 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); |
2203 | 2027 | ||
@@ -2207,11 +2031,60 @@ void iwl_cmd_queue_full(struct iwl_op_mode *op_mode) | |||
2207 | } | 2031 | } |
2208 | } | 2032 | } |
2209 | 2033 | ||
2210 | void iwl_nic_config(struct iwl_op_mode *op_mode) | 2034 | #define EEPROM_RF_CONFIG_TYPE_MAX 0x3 |
2035 | |||
2036 | static void iwl_nic_config(struct iwl_op_mode *op_mode) | ||
2211 | { | 2037 | { |
2212 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | 2038 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); |
2039 | u16 radio_cfg = priv->eeprom_data->radio_cfg; | ||
2040 | |||
2041 | /* SKU Control */ | ||
2042 | iwl_set_bits_mask(priv->trans, CSR_HW_IF_CONFIG_REG, | ||
2043 | CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH | | ||
2044 | CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP, | ||
2045 | (CSR_HW_REV_STEP(priv->trans->hw_rev) << | ||
2046 | CSR_HW_IF_CONFIG_REG_POS_MAC_STEP) | | ||
2047 | (CSR_HW_REV_DASH(priv->trans->hw_rev) << | ||
2048 | CSR_HW_IF_CONFIG_REG_POS_MAC_DASH)); | ||
2049 | |||
2050 | /* write radio config values to register */ | ||
2051 | if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX) { | ||
2052 | u32 reg_val = | ||
2053 | EEPROM_RF_CFG_TYPE_MSK(radio_cfg) << | ||
2054 | CSR_HW_IF_CONFIG_REG_POS_PHY_TYPE | | ||
2055 | EEPROM_RF_CFG_STEP_MSK(radio_cfg) << | ||
2056 | CSR_HW_IF_CONFIG_REG_POS_PHY_STEP | | ||
2057 | EEPROM_RF_CFG_DASH_MSK(radio_cfg) << | ||
2058 | CSR_HW_IF_CONFIG_REG_POS_PHY_DASH; | ||
2059 | |||
2060 | iwl_set_bits_mask(priv->trans, CSR_HW_IF_CONFIG_REG, | ||
2061 | CSR_HW_IF_CONFIG_REG_MSK_PHY_TYPE | | ||
2062 | CSR_HW_IF_CONFIG_REG_MSK_PHY_STEP | | ||
2063 | CSR_HW_IF_CONFIG_REG_MSK_PHY_DASH, reg_val); | ||
2064 | |||
2065 | IWL_INFO(priv, "Radio type=0x%x-0x%x-0x%x\n", | ||
2066 | EEPROM_RF_CFG_TYPE_MSK(radio_cfg), | ||
2067 | EEPROM_RF_CFG_STEP_MSK(radio_cfg), | ||
2068 | EEPROM_RF_CFG_DASH_MSK(radio_cfg)); | ||
2069 | } else { | ||
2070 | WARN_ON(1); | ||
2071 | } | ||
2213 | 2072 | ||
2214 | priv->lib->nic_config(priv); | 2073 | /* set CSR_HW_CONFIG_REG for uCode use */ |
2074 | iwl_set_bit(priv->trans, CSR_HW_IF_CONFIG_REG, | ||
2075 | CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | | ||
2076 | CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); | ||
2077 | |||
2078 | /* W/A : NIC is stuck in a reset state after Early PCIe power off | ||
2079 | * (PCIe power is lost before PERST# is asserted), | ||
2080 | * causing ME FW to lose ownership and not being able to obtain it back. | ||
2081 | */ | ||
2082 | iwl_set_bits_mask_prph(priv->trans, APMG_PS_CTRL_REG, | ||
2083 | APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS, | ||
2084 | ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS); | ||
2085 | |||
2086 | if (priv->lib->nic_config) | ||
2087 | priv->lib->nic_config(priv); | ||
2215 | } | 2088 | } |
2216 | 2089 | ||
2217 | static void iwl_wimax_active(struct iwl_op_mode *op_mode) | 2090 | static void iwl_wimax_active(struct iwl_op_mode *op_mode) |
@@ -2222,7 +2095,7 @@ static void iwl_wimax_active(struct iwl_op_mode *op_mode) | |||
2222 | IWL_ERR(priv, "RF is used by WiMAX\n"); | 2095 | IWL_ERR(priv, "RF is used by WiMAX\n"); |
2223 | } | 2096 | } |
2224 | 2097 | ||
2225 | void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, int queue) | 2098 | static void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, int queue) |
2226 | { | 2099 | { |
2227 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | 2100 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); |
2228 | int mq = priv->queue_to_mac80211[queue]; | 2101 | int mq = priv->queue_to_mac80211[queue]; |
@@ -2241,7 +2114,7 @@ void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, int queue) | |||
2241 | ieee80211_stop_queue(priv->hw, mq); | 2114 | ieee80211_stop_queue(priv->hw, mq); |
2242 | } | 2115 | } |
2243 | 2116 | ||
2244 | void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, int queue) | 2117 | static void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, int queue) |
2245 | { | 2118 | { |
2246 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | 2119 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); |
2247 | int mq = priv->queue_to_mac80211[queue]; | 2120 | int mq = priv->queue_to_mac80211[queue]; |
@@ -2281,16 +2154,17 @@ void iwlagn_lift_passive_no_rx(struct iwl_priv *priv) | |||
2281 | priv->passive_no_rx = false; | 2154 | priv->passive_no_rx = false; |
2282 | } | 2155 | } |
2283 | 2156 | ||
2284 | void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb) | 2157 | static void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb) |
2285 | { | 2158 | { |
2159 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | ||
2286 | struct ieee80211_tx_info *info; | 2160 | struct ieee80211_tx_info *info; |
2287 | 2161 | ||
2288 | info = IEEE80211_SKB_CB(skb); | 2162 | info = IEEE80211_SKB_CB(skb); |
2289 | kmem_cache_free(iwl_tx_cmd_pool, (info->driver_data[1])); | 2163 | iwl_trans_free_tx_cmd(priv->trans, info->driver_data[1]); |
2290 | dev_kfree_skb_any(skb); | 2164 | dev_kfree_skb_any(skb); |
2291 | } | 2165 | } |
2292 | 2166 | ||
2293 | void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) | 2167 | static void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) |
2294 | { | 2168 | { |
2295 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | 2169 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); |
2296 | 2170 | ||
@@ -2302,7 +2176,7 @@ void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) | |||
2302 | wiphy_rfkill_set_hw_state(priv->hw->wiphy, state); | 2176 | wiphy_rfkill_set_hw_state(priv->hw->wiphy, state); |
2303 | } | 2177 | } |
2304 | 2178 | ||
2305 | const struct iwl_op_mode_ops iwl_dvm_ops = { | 2179 | static const struct iwl_op_mode_ops iwl_dvm_ops = { |
2306 | .start = iwl_op_mode_dvm_start, | 2180 | .start = iwl_op_mode_dvm_start, |
2307 | .stop = iwl_op_mode_dvm_stop, | 2181 | .stop = iwl_op_mode_dvm_stop, |
2308 | .rx = iwl_rx_dispatch, | 2182 | .rx = iwl_rx_dispatch, |
@@ -2321,9 +2195,6 @@ const struct iwl_op_mode_ops iwl_dvm_ops = { | |||
2321 | * driver and module entry point | 2195 | * driver and module entry point |
2322 | * | 2196 | * |
2323 | *****************************************************************************/ | 2197 | *****************************************************************************/ |
2324 | |||
2325 | struct kmem_cache *iwl_tx_cmd_pool; | ||
2326 | |||
2327 | static int __init iwl_init(void) | 2198 | static int __init iwl_init(void) |
2328 | { | 2199 | { |
2329 | 2200 | ||
@@ -2331,29 +2202,18 @@ static int __init iwl_init(void) | |||
2331 | pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n"); | 2202 | pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n"); |
2332 | pr_info(DRV_COPYRIGHT "\n"); | 2203 | pr_info(DRV_COPYRIGHT "\n"); |
2333 | 2204 | ||
2334 | iwl_tx_cmd_pool = kmem_cache_create("iwl_dev_cmd", | ||
2335 | sizeof(struct iwl_device_cmd), | ||
2336 | sizeof(void *), 0, NULL); | ||
2337 | if (!iwl_tx_cmd_pool) | ||
2338 | return -ENOMEM; | ||
2339 | |||
2340 | ret = iwlagn_rate_control_register(); | 2205 | ret = iwlagn_rate_control_register(); |
2341 | if (ret) { | 2206 | if (ret) { |
2342 | pr_err("Unable to register rate control algorithm: %d\n", ret); | 2207 | pr_err("Unable to register rate control algorithm: %d\n", ret); |
2343 | goto error_rc_register; | 2208 | return ret; |
2344 | } | 2209 | } |
2345 | 2210 | ||
2346 | ret = iwl_opmode_register("iwldvm", &iwl_dvm_ops); | 2211 | ret = iwl_opmode_register("iwldvm", &iwl_dvm_ops); |
2347 | if (ret) { | 2212 | if (ret) { |
2348 | pr_err("Unable to register op_mode: %d\n", ret); | 2213 | pr_err("Unable to register op_mode: %d\n", ret); |
2349 | goto error_opmode_register; | 2214 | iwlagn_rate_control_unregister(); |
2350 | } | 2215 | } |
2351 | return ret; | ||
2352 | 2216 | ||
2353 | error_opmode_register: | ||
2354 | iwlagn_rate_control_unregister(); | ||
2355 | error_rc_register: | ||
2356 | kmem_cache_destroy(iwl_tx_cmd_pool); | ||
2357 | return ret; | 2217 | return ret; |
2358 | } | 2218 | } |
2359 | module_init(iwl_init); | 2219 | module_init(iwl_init); |
@@ -2362,6 +2222,5 @@ static void __exit iwl_exit(void) | |||
2362 | { | 2222 | { |
2363 | iwl_opmode_deregister("iwldvm"); | 2223 | iwl_opmode_deregister("iwldvm"); |
2364 | iwlagn_rate_control_unregister(); | 2224 | iwlagn_rate_control_unregister(); |
2365 | kmem_cache_destroy(iwl_tx_cmd_pool); | ||
2366 | } | 2225 | } |
2367 | module_exit(iwl_exit); | 2226 | module_exit(iwl_exit); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/dvm/power.c index 544ddf17f5b..518cf371580 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/dvm/power.c | |||
@@ -31,18 +31,15 @@ | |||
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
33 | #include <linux/init.h> | 33 | #include <linux/init.h> |
34 | |||
35 | #include <net/mac80211.h> | 34 | #include <net/mac80211.h> |
36 | |||
37 | #include "iwl-eeprom.h" | ||
38 | #include "iwl-dev.h" | ||
39 | #include "iwl-agn.h" | ||
40 | #include "iwl-io.h" | 35 | #include "iwl-io.h" |
41 | #include "iwl-commands.h" | ||
42 | #include "iwl-debug.h" | 36 | #include "iwl-debug.h" |
43 | #include "iwl-power.h" | ||
44 | #include "iwl-trans.h" | 37 | #include "iwl-trans.h" |
45 | #include "iwl-modparams.h" | 38 | #include "iwl-modparams.h" |
39 | #include "dev.h" | ||
40 | #include "agn.h" | ||
41 | #include "commands.h" | ||
42 | #include "power.h" | ||
46 | 43 | ||
47 | /* | 44 | /* |
48 | * Setting power level allows the card to go to sleep when not busy. | 45 | * Setting power level allows the card to go to sleep when not busy. |
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/dvm/power.h index 21afc92efac..a2cee7f0484 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.h +++ b/drivers/net/wireless/iwlwifi/dvm/power.h | |||
@@ -28,7 +28,7 @@ | |||
28 | #ifndef __iwl_power_setting_h__ | 28 | #ifndef __iwl_power_setting_h__ |
29 | #define __iwl_power_setting_h__ | 29 | #define __iwl_power_setting_h__ |
30 | 30 | ||
31 | #include "iwl-commands.h" | 31 | #include "commands.h" |
32 | 32 | ||
33 | struct iwl_power_mgr { | 33 | struct iwl_power_mgr { |
34 | struct iwl_powertable_cmd sleep_cmd; | 34 | struct iwl_powertable_cmd sleep_cmd; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/dvm/rs.c index 8cebd7c363f..6fddd2785e6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/dvm/rs.c | |||
@@ -35,10 +35,8 @@ | |||
35 | 35 | ||
36 | #include <linux/workqueue.h> | 36 | #include <linux/workqueue.h> |
37 | 37 | ||
38 | #include "iwl-dev.h" | 38 | #include "dev.h" |
39 | #include "iwl-agn.h" | 39 | #include "agn.h" |
40 | #include "iwl-op-mode.h" | ||
41 | #include "iwl-modparams.h" | ||
42 | 40 | ||
43 | #define RS_NAME "iwl-agn-rs" | 41 | #define RS_NAME "iwl-agn-rs" |
44 | 42 | ||
@@ -819,7 +817,7 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta, | |||
819 | 817 | ||
820 | if (num_of_ant(tbl->ant_type) > 1) | 818 | if (num_of_ant(tbl->ant_type) > 1) |
821 | tbl->ant_type = | 819 | tbl->ant_type = |
822 | first_antenna(priv->hw_params.valid_tx_ant); | 820 | first_antenna(priv->eeprom_data->valid_tx_ant); |
823 | 821 | ||
824 | tbl->is_ht40 = 0; | 822 | tbl->is_ht40 = 0; |
825 | tbl->is_SGI = 0; | 823 | tbl->is_SGI = 0; |
@@ -1447,7 +1445,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv, | |||
1447 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 1445 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - |
1448 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 1446 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); |
1449 | u8 start_action; | 1447 | u8 start_action; |
1450 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; | 1448 | u8 valid_tx_ant = priv->eeprom_data->valid_tx_ant; |
1451 | u8 tx_chains_num = priv->hw_params.tx_chains_num; | 1449 | u8 tx_chains_num = priv->hw_params.tx_chains_num; |
1452 | int ret = 0; | 1450 | int ret = 0; |
1453 | u8 update_search_tbl_counter = 0; | 1451 | u8 update_search_tbl_counter = 0; |
@@ -1465,7 +1463,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv, | |||
1465 | case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: | 1463 | case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: |
1466 | /* avoid antenna B and MIMO */ | 1464 | /* avoid antenna B and MIMO */ |
1467 | valid_tx_ant = | 1465 | valid_tx_ant = |
1468 | first_antenna(priv->hw_params.valid_tx_ant); | 1466 | first_antenna(priv->eeprom_data->valid_tx_ant); |
1469 | if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2 && | 1467 | if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2 && |
1470 | tbl->action != IWL_LEGACY_SWITCH_SISO) | 1468 | tbl->action != IWL_LEGACY_SWITCH_SISO) |
1471 | tbl->action = IWL_LEGACY_SWITCH_SISO; | 1469 | tbl->action = IWL_LEGACY_SWITCH_SISO; |
@@ -1489,7 +1487,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv, | |||
1489 | else if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2) | 1487 | else if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2) |
1490 | tbl->action = IWL_LEGACY_SWITCH_SISO; | 1488 | tbl->action = IWL_LEGACY_SWITCH_SISO; |
1491 | valid_tx_ant = | 1489 | valid_tx_ant = |
1492 | first_antenna(priv->hw_params.valid_tx_ant); | 1490 | first_antenna(priv->eeprom_data->valid_tx_ant); |
1493 | } | 1491 | } |
1494 | 1492 | ||
1495 | start_action = tbl->action; | 1493 | start_action = tbl->action; |
@@ -1623,7 +1621,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, | |||
1623 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 1621 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - |
1624 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 1622 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); |
1625 | u8 start_action; | 1623 | u8 start_action; |
1626 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; | 1624 | u8 valid_tx_ant = priv->eeprom_data->valid_tx_ant; |
1627 | u8 tx_chains_num = priv->hw_params.tx_chains_num; | 1625 | u8 tx_chains_num = priv->hw_params.tx_chains_num; |
1628 | u8 update_search_tbl_counter = 0; | 1626 | u8 update_search_tbl_counter = 0; |
1629 | int ret; | 1627 | int ret; |
@@ -1641,7 +1639,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, | |||
1641 | case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: | 1639 | case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: |
1642 | /* avoid antenna B and MIMO */ | 1640 | /* avoid antenna B and MIMO */ |
1643 | valid_tx_ant = | 1641 | valid_tx_ant = |
1644 | first_antenna(priv->hw_params.valid_tx_ant); | 1642 | first_antenna(priv->eeprom_data->valid_tx_ant); |
1645 | if (tbl->action != IWL_SISO_SWITCH_ANTENNA1) | 1643 | if (tbl->action != IWL_SISO_SWITCH_ANTENNA1) |
1646 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; | 1644 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; |
1647 | break; | 1645 | break; |
@@ -1659,7 +1657,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, | |||
1659 | /* configure as 1x1 if bt full concurrency */ | 1657 | /* configure as 1x1 if bt full concurrency */ |
1660 | if (priv->bt_full_concurrent) { | 1658 | if (priv->bt_full_concurrent) { |
1661 | valid_tx_ant = | 1659 | valid_tx_ant = |
1662 | first_antenna(priv->hw_params.valid_tx_ant); | 1660 | first_antenna(priv->eeprom_data->valid_tx_ant); |
1663 | if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2) | 1661 | if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2) |
1664 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; | 1662 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; |
1665 | } | 1663 | } |
@@ -1795,7 +1793,7 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv, | |||
1795 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 1793 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - |
1796 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 1794 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); |
1797 | u8 start_action; | 1795 | u8 start_action; |
1798 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; | 1796 | u8 valid_tx_ant = priv->eeprom_data->valid_tx_ant; |
1799 | u8 tx_chains_num = priv->hw_params.tx_chains_num; | 1797 | u8 tx_chains_num = priv->hw_params.tx_chains_num; |
1800 | u8 update_search_tbl_counter = 0; | 1798 | u8 update_search_tbl_counter = 0; |
1801 | int ret; | 1799 | int ret; |
@@ -1965,7 +1963,7 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv, | |||
1965 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 1963 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - |
1966 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 1964 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); |
1967 | u8 start_action; | 1965 | u8 start_action; |
1968 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; | 1966 | u8 valid_tx_ant = priv->eeprom_data->valid_tx_ant; |
1969 | u8 tx_chains_num = priv->hw_params.tx_chains_num; | 1967 | u8 tx_chains_num = priv->hw_params.tx_chains_num; |
1970 | int ret; | 1968 | int ret; |
1971 | u8 update_search_tbl_counter = 0; | 1969 | u8 update_search_tbl_counter = 0; |
@@ -2699,7 +2697,7 @@ static void rs_initialize_lq(struct iwl_priv *priv, | |||
2699 | 2697 | ||
2700 | i = lq_sta->last_txrate_idx; | 2698 | i = lq_sta->last_txrate_idx; |
2701 | 2699 | ||
2702 | valid_tx_ant = priv->hw_params.valid_tx_ant; | 2700 | valid_tx_ant = priv->eeprom_data->valid_tx_ant; |
2703 | 2701 | ||
2704 | if (!lq_sta->search_better_tbl) | 2702 | if (!lq_sta->search_better_tbl) |
2705 | active_tbl = lq_sta->active_tbl; | 2703 | active_tbl = lq_sta->active_tbl; |
@@ -2893,15 +2891,15 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i | |||
2893 | 2891 | ||
2894 | /* These values will be overridden later */ | 2892 | /* These values will be overridden later */ |
2895 | lq_sta->lq.general_params.single_stream_ant_msk = | 2893 | lq_sta->lq.general_params.single_stream_ant_msk = |
2896 | first_antenna(priv->hw_params.valid_tx_ant); | 2894 | first_antenna(priv->eeprom_data->valid_tx_ant); |
2897 | lq_sta->lq.general_params.dual_stream_ant_msk = | 2895 | lq_sta->lq.general_params.dual_stream_ant_msk = |
2898 | priv->hw_params.valid_tx_ant & | 2896 | priv->eeprom_data->valid_tx_ant & |
2899 | ~first_antenna(priv->hw_params.valid_tx_ant); | 2897 | ~first_antenna(priv->eeprom_data->valid_tx_ant); |
2900 | if (!lq_sta->lq.general_params.dual_stream_ant_msk) { | 2898 | if (!lq_sta->lq.general_params.dual_stream_ant_msk) { |
2901 | lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB; | 2899 | lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB; |
2902 | } else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) { | 2900 | } else if (num_of_ant(priv->eeprom_data->valid_tx_ant) == 2) { |
2903 | lq_sta->lq.general_params.dual_stream_ant_msk = | 2901 | lq_sta->lq.general_params.dual_stream_ant_msk = |
2904 | priv->hw_params.valid_tx_ant; | 2902 | priv->eeprom_data->valid_tx_ant; |
2905 | } | 2903 | } |
2906 | 2904 | ||
2907 | /* as default allow aggregation for all tids */ | 2905 | /* as default allow aggregation for all tids */ |
@@ -2947,7 +2945,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, | |||
2947 | if (priv && priv->bt_full_concurrent) { | 2945 | if (priv && priv->bt_full_concurrent) { |
2948 | /* 1x1 only */ | 2946 | /* 1x1 only */ |
2949 | tbl_type.ant_type = | 2947 | tbl_type.ant_type = |
2950 | first_antenna(priv->hw_params.valid_tx_ant); | 2948 | first_antenna(priv->eeprom_data->valid_tx_ant); |
2951 | } | 2949 | } |
2952 | 2950 | ||
2953 | /* How many times should we repeat the initial rate? */ | 2951 | /* How many times should we repeat the initial rate? */ |
@@ -2979,7 +2977,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, | |||
2979 | if (priv->bt_full_concurrent) | 2977 | if (priv->bt_full_concurrent) |
2980 | valid_tx_ant = ANT_A; | 2978 | valid_tx_ant = ANT_A; |
2981 | else | 2979 | else |
2982 | valid_tx_ant = priv->hw_params.valid_tx_ant; | 2980 | valid_tx_ant = priv->eeprom_data->valid_tx_ant; |
2983 | } | 2981 | } |
2984 | 2982 | ||
2985 | /* Fill rest of rate table */ | 2983 | /* Fill rest of rate table */ |
@@ -3013,7 +3011,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, | |||
3013 | if (priv && priv->bt_full_concurrent) { | 3011 | if (priv && priv->bt_full_concurrent) { |
3014 | /* 1x1 only */ | 3012 | /* 1x1 only */ |
3015 | tbl_type.ant_type = | 3013 | tbl_type.ant_type = |
3016 | first_antenna(priv->hw_params.valid_tx_ant); | 3014 | first_antenna(priv->eeprom_data->valid_tx_ant); |
3017 | } | 3015 | } |
3018 | 3016 | ||
3019 | /* Indicate to uCode which entries might be MIMO. | 3017 | /* Indicate to uCode which entries might be MIMO. |
@@ -3100,7 +3098,7 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, | |||
3100 | u8 ant_sel_tx; | 3098 | u8 ant_sel_tx; |
3101 | 3099 | ||
3102 | priv = lq_sta->drv; | 3100 | priv = lq_sta->drv; |
3103 | valid_tx_ant = priv->hw_params.valid_tx_ant; | 3101 | valid_tx_ant = priv->eeprom_data->valid_tx_ant; |
3104 | if (lq_sta->dbg_fixed_rate) { | 3102 | if (lq_sta->dbg_fixed_rate) { |
3105 | ant_sel_tx = | 3103 | ant_sel_tx = |
3106 | ((lq_sta->dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK) | 3104 | ((lq_sta->dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK) |
@@ -3171,9 +3169,9 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, | |||
3171 | desc += sprintf(buff+desc, "fixed rate 0x%X\n", | 3169 | desc += sprintf(buff+desc, "fixed rate 0x%X\n", |
3172 | lq_sta->dbg_fixed_rate); | 3170 | lq_sta->dbg_fixed_rate); |
3173 | desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n", | 3171 | desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n", |
3174 | (priv->hw_params.valid_tx_ant & ANT_A) ? "ANT_A," : "", | 3172 | (priv->eeprom_data->valid_tx_ant & ANT_A) ? "ANT_A," : "", |
3175 | (priv->hw_params.valid_tx_ant & ANT_B) ? "ANT_B," : "", | 3173 | (priv->eeprom_data->valid_tx_ant & ANT_B) ? "ANT_B," : "", |
3176 | (priv->hw_params.valid_tx_ant & ANT_C) ? "ANT_C" : ""); | 3174 | (priv->eeprom_data->valid_tx_ant & ANT_C) ? "ANT_C" : ""); |
3177 | desc += sprintf(buff+desc, "lq type %s\n", | 3175 | desc += sprintf(buff+desc, "lq type %s\n", |
3178 | (is_legacy(tbl->lq_type)) ? "legacy" : "HT"); | 3176 | (is_legacy(tbl->lq_type)) ? "legacy" : "HT"); |
3179 | if (is_Ht(tbl->lq_type)) { | 3177 | if (is_Ht(tbl->lq_type)) { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/dvm/rs.h index 82d02e1ae89..ad3aea8f626 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h +++ b/drivers/net/wireless/iwlwifi/dvm/rs.h | |||
@@ -29,9 +29,10 @@ | |||
29 | 29 | ||
30 | #include <net/mac80211.h> | 30 | #include <net/mac80211.h> |
31 | 31 | ||
32 | #include "iwl-commands.h" | ||
33 | #include "iwl-config.h" | 32 | #include "iwl-config.h" |
34 | 33 | ||
34 | #include "commands.h" | ||
35 | |||
35 | struct iwl_rate_info { | 36 | struct iwl_rate_info { |
36 | u8 plcp; /* uCode API: IWL_RATE_6M_PLCP, etc. */ | 37 | u8 plcp; /* uCode API: IWL_RATE_6M_PLCP, etc. */ |
37 | u8 plcp_siso; /* uCode API: IWL_RATE_SISO_6M_PLCP, etc. */ | 38 | u8 plcp_siso; /* uCode API: IWL_RATE_SISO_6M_PLCP, etc. */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/dvm/rx.c index 403de96f974..c1f7a18e08d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c +++ b/drivers/net/wireless/iwlwifi/dvm/rx.c | |||
@@ -32,12 +32,10 @@ | |||
32 | #include <linux/sched.h> | 32 | #include <linux/sched.h> |
33 | #include <net/mac80211.h> | 33 | #include <net/mac80211.h> |
34 | #include <asm/unaligned.h> | 34 | #include <asm/unaligned.h> |
35 | #include "iwl-eeprom.h" | ||
36 | #include "iwl-dev.h" | ||
37 | #include "iwl-io.h" | 35 | #include "iwl-io.h" |
38 | #include "iwl-agn-calib.h" | 36 | #include "dev.h" |
39 | #include "iwl-agn.h" | 37 | #include "calib.h" |
40 | #include "iwl-modparams.h" | 38 | #include "agn.h" |
41 | 39 | ||
42 | #define IWL_CMD_ENTRY(x) [x] = #x | 40 | #define IWL_CMD_ENTRY(x) [x] = #x |
43 | 41 | ||
@@ -1012,6 +1010,8 @@ static int iwlagn_rx_reply_rx(struct iwl_priv *priv, | |||
1012 | rx_status.flag |= RX_FLAG_40MHZ; | 1010 | rx_status.flag |= RX_FLAG_40MHZ; |
1013 | if (rate_n_flags & RATE_MCS_SGI_MSK) | 1011 | if (rate_n_flags & RATE_MCS_SGI_MSK) |
1014 | rx_status.flag |= RX_FLAG_SHORT_GI; | 1012 | rx_status.flag |= RX_FLAG_SHORT_GI; |
1013 | if (rate_n_flags & RATE_MCS_GF_MSK) | ||
1014 | rx_status.flag |= RX_FLAG_HT_GF; | ||
1015 | 1015 | ||
1016 | iwlagn_pass_packet_to_mac80211(priv, header, len, ampdu_status, | 1016 | iwlagn_pass_packet_to_mac80211(priv, header, len, ampdu_status, |
1017 | rxb, &rx_status); | 1017 | rxb, &rx_status); |
@@ -1124,8 +1124,6 @@ int iwl_rx_dispatch(struct iwl_op_mode *op_mode, struct iwl_rx_cmd_buffer *rxb, | |||
1124 | { | 1124 | { |
1125 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 1125 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
1126 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | 1126 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); |
1127 | void (*pre_rx_handler)(struct iwl_priv *, | ||
1128 | struct iwl_rx_cmd_buffer *); | ||
1129 | int err = 0; | 1127 | int err = 0; |
1130 | 1128 | ||
1131 | /* | 1129 | /* |
@@ -1135,19 +1133,19 @@ int iwl_rx_dispatch(struct iwl_op_mode *op_mode, struct iwl_rx_cmd_buffer *rxb, | |||
1135 | */ | 1133 | */ |
1136 | iwl_notification_wait_notify(&priv->notif_wait, pkt); | 1134 | iwl_notification_wait_notify(&priv->notif_wait, pkt); |
1137 | 1135 | ||
1138 | /* RX data may be forwarded to userspace (using pre_rx_handler) in one | 1136 | #ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE |
1139 | * of two cases: the first, that the user owns the uCode through | 1137 | /* |
1140 | * testmode - in such case the pre_rx_handler is set and no further | 1138 | * RX data may be forwarded to userspace in one |
1141 | * processing takes place. The other case is when the user want to | 1139 | * of two cases: the user owns the fw through testmode or when |
1142 | * monitor the rx w/o affecting the regular flow - the pre_rx_handler | 1140 | * the user requested to monitor the rx w/o affecting the regular flow. |
1143 | * will be set but the ownership flag != IWL_OWNERSHIP_TM and the flow | 1141 | * In these cases the iwl_test object will handle forwarding the rx |
1142 | * data to user space. | ||
1143 | * Note that if the ownership flag != IWL_OWNERSHIP_TM the flow | ||
1144 | * continues. | 1144 | * continues. |
1145 | * We need to use ACCESS_ONCE to prevent a case where the handler | ||
1146 | * changes between the check and the call. | ||
1147 | */ | 1145 | */ |
1148 | pre_rx_handler = ACCESS_ONCE(priv->pre_rx_handler); | 1146 | iwl_test_rx(&priv->tst, rxb); |
1149 | if (pre_rx_handler) | 1147 | #endif |
1150 | pre_rx_handler(priv, rxb); | 1148 | |
1151 | if (priv->ucode_owner != IWL_OWNERSHIP_TM) { | 1149 | if (priv->ucode_owner != IWL_OWNERSHIP_TM) { |
1152 | /* Based on type of command response or notification, | 1150 | /* Based on type of command response or notification, |
1153 | * handle those that need handling via function in | 1151 | * handle those that need handling via function in |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/dvm/rxon.c index 0a3aa7c8300..6ee940f497f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/dvm/rxon.c | |||
@@ -25,11 +25,11 @@ | |||
25 | *****************************************************************************/ | 25 | *****************************************************************************/ |
26 | 26 | ||
27 | #include <linux/etherdevice.h> | 27 | #include <linux/etherdevice.h> |
28 | #include "iwl-dev.h" | ||
29 | #include "iwl-agn.h" | ||
30 | #include "iwl-agn-calib.h" | ||
31 | #include "iwl-trans.h" | 28 | #include "iwl-trans.h" |
32 | #include "iwl-modparams.h" | 29 | #include "iwl-modparams.h" |
30 | #include "dev.h" | ||
31 | #include "agn.h" | ||
32 | #include "calib.h" | ||
33 | 33 | ||
34 | /* | 34 | /* |
35 | * initialize rxon structure with default values from eeprom | 35 | * initialize rxon structure with default values from eeprom |
@@ -37,8 +37,6 @@ | |||
37 | void iwl_connection_init_rx_config(struct iwl_priv *priv, | 37 | void iwl_connection_init_rx_config(struct iwl_priv *priv, |
38 | struct iwl_rxon_context *ctx) | 38 | struct iwl_rxon_context *ctx) |
39 | { | 39 | { |
40 | const struct iwl_channel_info *ch_info; | ||
41 | |||
42 | memset(&ctx->staging, 0, sizeof(ctx->staging)); | 40 | memset(&ctx->staging, 0, sizeof(ctx->staging)); |
43 | 41 | ||
44 | if (!ctx->vif) { | 42 | if (!ctx->vif) { |
@@ -80,14 +78,8 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv, | |||
80 | ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; | 78 | ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; |
81 | #endif | 79 | #endif |
82 | 80 | ||
83 | ch_info = iwl_get_channel_info(priv, priv->band, | 81 | ctx->staging.channel = cpu_to_le16(priv->hw->conf.channel->hw_value); |
84 | le16_to_cpu(ctx->active.channel)); | 82 | priv->band = priv->hw->conf.channel->band; |
85 | |||
86 | if (!ch_info) | ||
87 | ch_info = &priv->channel_info[0]; | ||
88 | |||
89 | ctx->staging.channel = cpu_to_le16(ch_info->channel); | ||
90 | priv->band = ch_info->band; | ||
91 | 83 | ||
92 | iwl_set_flags_for_band(priv, ctx, priv->band, ctx->vif); | 84 | iwl_set_flags_for_band(priv, ctx, priv->band, ctx->vif); |
93 | 85 | ||
@@ -175,7 +167,8 @@ static int iwlagn_disconn_pan(struct iwl_priv *priv, | |||
175 | return ret; | 167 | return ret; |
176 | } | 168 | } |
177 | 169 | ||
178 | void iwlagn_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | 170 | static void iwlagn_update_qos(struct iwl_priv *priv, |
171 | struct iwl_rxon_context *ctx) | ||
179 | { | 172 | { |
180 | int ret; | 173 | int ret; |
181 | 174 | ||
@@ -202,8 +195,8 @@ void iwlagn_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | |||
202 | IWL_DEBUG_QUIET_RFKILL(priv, "Failed to update QoS\n"); | 195 | IWL_DEBUG_QUIET_RFKILL(priv, "Failed to update QoS\n"); |
203 | } | 196 | } |
204 | 197 | ||
205 | int iwlagn_update_beacon(struct iwl_priv *priv, | 198 | static int iwlagn_update_beacon(struct iwl_priv *priv, |
206 | struct ieee80211_vif *vif) | 199 | struct ieee80211_vif *vif) |
207 | { | 200 | { |
208 | lockdep_assert_held(&priv->mutex); | 201 | lockdep_assert_held(&priv->mutex); |
209 | 202 | ||
@@ -215,7 +208,7 @@ int iwlagn_update_beacon(struct iwl_priv *priv, | |||
215 | } | 208 | } |
216 | 209 | ||
217 | static int iwlagn_send_rxon_assoc(struct iwl_priv *priv, | 210 | static int iwlagn_send_rxon_assoc(struct iwl_priv *priv, |
218 | struct iwl_rxon_context *ctx) | 211 | struct iwl_rxon_context *ctx) |
219 | { | 212 | { |
220 | int ret = 0; | 213 | int ret = 0; |
221 | struct iwl_rxon_assoc_cmd rxon_assoc; | 214 | struct iwl_rxon_assoc_cmd rxon_assoc; |
@@ -427,10 +420,10 @@ static int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) | |||
427 | return -EINVAL; | 420 | return -EINVAL; |
428 | } | 421 | } |
429 | 422 | ||
430 | if (tx_power > priv->tx_power_device_lmt) { | 423 | if (tx_power > DIV_ROUND_UP(priv->eeprom_data->max_tx_pwr_half_dbm, 2)) { |
431 | IWL_WARN(priv, | 424 | IWL_WARN(priv, |
432 | "Requested user TXPOWER %d above upper limit %d.\n", | 425 | "Requested user TXPOWER %d above upper limit %d.\n", |
433 | tx_power, priv->tx_power_device_lmt); | 426 | tx_power, priv->eeprom_data->max_tx_pwr_half_dbm); |
434 | return -EINVAL; | 427 | return -EINVAL; |
435 | } | 428 | } |
436 | 429 | ||
@@ -863,8 +856,8 @@ static int iwl_check_rxon_cmd(struct iwl_priv *priv, | |||
863 | * or is clearing the RXON_FILTER_ASSOC_MSK, then return 1 to indicate that | 856 | * or is clearing the RXON_FILTER_ASSOC_MSK, then return 1 to indicate that |
864 | * a new tune (full RXON command, rather than RXON_ASSOC cmd) is required. | 857 | * a new tune (full RXON command, rather than RXON_ASSOC cmd) is required. |
865 | */ | 858 | */ |
866 | int iwl_full_rxon_required(struct iwl_priv *priv, | 859 | static int iwl_full_rxon_required(struct iwl_priv *priv, |
867 | struct iwl_rxon_context *ctx) | 860 | struct iwl_rxon_context *ctx) |
868 | { | 861 | { |
869 | const struct iwl_rxon_cmd *staging = &ctx->staging; | 862 | const struct iwl_rxon_cmd *staging = &ctx->staging; |
870 | const struct iwl_rxon_cmd *active = &ctx->active; | 863 | const struct iwl_rxon_cmd *active = &ctx->active; |
@@ -1189,7 +1182,6 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
1189 | struct iwl_rxon_context *ctx; | 1182 | struct iwl_rxon_context *ctx; |
1190 | struct ieee80211_conf *conf = &hw->conf; | 1183 | struct ieee80211_conf *conf = &hw->conf; |
1191 | struct ieee80211_channel *channel = conf->channel; | 1184 | struct ieee80211_channel *channel = conf->channel; |
1192 | const struct iwl_channel_info *ch_info; | ||
1193 | int ret = 0; | 1185 | int ret = 0; |
1194 | 1186 | ||
1195 | IWL_DEBUG_MAC80211(priv, "enter: changed %#x\n", changed); | 1187 | IWL_DEBUG_MAC80211(priv, "enter: changed %#x\n", changed); |
@@ -1223,14 +1215,6 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
1223 | } | 1215 | } |
1224 | 1216 | ||
1225 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { | 1217 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { |
1226 | ch_info = iwl_get_channel_info(priv, channel->band, | ||
1227 | channel->hw_value); | ||
1228 | if (!is_channel_valid(ch_info)) { | ||
1229 | IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n"); | ||
1230 | ret = -EINVAL; | ||
1231 | goto out; | ||
1232 | } | ||
1233 | |||
1234 | for_each_context(priv, ctx) { | 1218 | for_each_context(priv, ctx) { |
1235 | /* Configure HT40 channels */ | 1219 | /* Configure HT40 channels */ |
1236 | if (ctx->ht.enabled != conf_is_ht(conf)) | 1220 | if (ctx->ht.enabled != conf_is_ht(conf)) |
@@ -1294,9 +1278,9 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
1294 | return ret; | 1278 | return ret; |
1295 | } | 1279 | } |
1296 | 1280 | ||
1297 | void iwlagn_check_needed_chains(struct iwl_priv *priv, | 1281 | static void iwlagn_check_needed_chains(struct iwl_priv *priv, |
1298 | struct iwl_rxon_context *ctx, | 1282 | struct iwl_rxon_context *ctx, |
1299 | struct ieee80211_bss_conf *bss_conf) | 1283 | struct ieee80211_bss_conf *bss_conf) |
1300 | { | 1284 | { |
1301 | struct ieee80211_vif *vif = ctx->vif; | 1285 | struct ieee80211_vif *vif = ctx->vif; |
1302 | struct iwl_rxon_context *tmp; | 1286 | struct iwl_rxon_context *tmp; |
@@ -1388,7 +1372,7 @@ void iwlagn_check_needed_chains(struct iwl_priv *priv, | |||
1388 | ht_conf->single_chain_sufficient = !need_multiple; | 1372 | ht_conf->single_chain_sufficient = !need_multiple; |
1389 | } | 1373 | } |
1390 | 1374 | ||
1391 | void iwlagn_chain_noise_reset(struct iwl_priv *priv) | 1375 | static void iwlagn_chain_noise_reset(struct iwl_priv *priv) |
1392 | { | 1376 | { |
1393 | struct iwl_chain_noise_data *data = &priv->chain_noise_data; | 1377 | struct iwl_chain_noise_data *data = &priv->chain_noise_data; |
1394 | int ret; | 1378 | int ret; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/dvm/scan.c index 031d8e21f82..6633074258c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/dvm/scan.c | |||
@@ -30,11 +30,8 @@ | |||
30 | #include <linux/etherdevice.h> | 30 | #include <linux/etherdevice.h> |
31 | #include <net/mac80211.h> | 31 | #include <net/mac80211.h> |
32 | 32 | ||
33 | #include "iwl-eeprom.h" | 33 | #include "dev.h" |
34 | #include "iwl-dev.h" | 34 | #include "agn.h" |
35 | #include "iwl-io.h" | ||
36 | #include "iwl-agn.h" | ||
37 | #include "iwl-trans.h" | ||
38 | 35 | ||
39 | /* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after | 36 | /* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after |
40 | * sending probe req. This should be set long enough to hear probe responses | 37 | * sending probe req. This should be set long enough to hear probe responses |
@@ -54,6 +51,9 @@ | |||
54 | #define IWL_CHANNEL_TUNE_TIME 5 | 51 | #define IWL_CHANNEL_TUNE_TIME 5 |
55 | #define MAX_SCAN_CHANNEL 50 | 52 | #define MAX_SCAN_CHANNEL 50 |
56 | 53 | ||
54 | /* For reset radio, need minimal dwell time only */ | ||
55 | #define IWL_RADIO_RESET_DWELL_TIME 5 | ||
56 | |||
57 | static int iwl_send_scan_abort(struct iwl_priv *priv) | 57 | static int iwl_send_scan_abort(struct iwl_priv *priv) |
58 | { | 58 | { |
59 | int ret; | 59 | int ret; |
@@ -67,7 +67,6 @@ static int iwl_send_scan_abort(struct iwl_priv *priv) | |||
67 | * to receive scan abort command or it does not perform | 67 | * to receive scan abort command or it does not perform |
68 | * hardware scan currently */ | 68 | * hardware scan currently */ |
69 | if (!test_bit(STATUS_READY, &priv->status) || | 69 | if (!test_bit(STATUS_READY, &priv->status) || |
70 | !test_bit(STATUS_GEO_CONFIGURED, &priv->status) || | ||
71 | !test_bit(STATUS_SCAN_HW, &priv->status) || | 70 | !test_bit(STATUS_SCAN_HW, &priv->status) || |
72 | test_bit(STATUS_FW_ERROR, &priv->status)) | 71 | test_bit(STATUS_FW_ERROR, &priv->status)) |
73 | return -EIO; | 72 | return -EIO; |
@@ -101,11 +100,8 @@ static void iwl_complete_scan(struct iwl_priv *priv, bool aborted) | |||
101 | ieee80211_scan_completed(priv->hw, aborted); | 100 | ieee80211_scan_completed(priv->hw, aborted); |
102 | } | 101 | } |
103 | 102 | ||
104 | if (priv->scan_type == IWL_SCAN_ROC) { | 103 | if (priv->scan_type == IWL_SCAN_ROC) |
105 | ieee80211_remain_on_channel_expired(priv->hw); | 104 | iwl_scan_roc_expired(priv); |
106 | priv->hw_roc_channel = NULL; | ||
107 | schedule_delayed_work(&priv->hw_roc_disable_work, 10 * HZ); | ||
108 | } | ||
109 | 105 | ||
110 | priv->scan_type = IWL_SCAN_NORMAL; | 106 | priv->scan_type = IWL_SCAN_NORMAL; |
111 | priv->scan_vif = NULL; | 107 | priv->scan_vif = NULL; |
@@ -134,11 +130,8 @@ static void iwl_process_scan_complete(struct iwl_priv *priv) | |||
134 | goto out_settings; | 130 | goto out_settings; |
135 | } | 131 | } |
136 | 132 | ||
137 | if (priv->scan_type == IWL_SCAN_ROC) { | 133 | if (priv->scan_type == IWL_SCAN_ROC) |
138 | ieee80211_remain_on_channel_expired(priv->hw); | 134 | iwl_scan_roc_expired(priv); |
139 | priv->hw_roc_channel = NULL; | ||
140 | schedule_delayed_work(&priv->hw_roc_disable_work, 10 * HZ); | ||
141 | } | ||
142 | 135 | ||
143 | if (priv->scan_type != IWL_SCAN_NORMAL && !aborted) { | 136 | if (priv->scan_type != IWL_SCAN_NORMAL && !aborted) { |
144 | int err; | 137 | int err; |
@@ -453,27 +446,17 @@ static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, | |||
453 | 446 | ||
454 | /* Return valid, unused, channel for a passive scan to reset the RF */ | 447 | /* Return valid, unused, channel for a passive scan to reset the RF */ |
455 | static u8 iwl_get_single_channel_number(struct iwl_priv *priv, | 448 | static u8 iwl_get_single_channel_number(struct iwl_priv *priv, |
456 | enum ieee80211_band band) | 449 | enum ieee80211_band band) |
457 | { | 450 | { |
458 | const struct iwl_channel_info *ch_info; | 451 | struct ieee80211_supported_band *sband = priv->hw->wiphy->bands[band]; |
459 | int i; | ||
460 | u8 channel = 0; | ||
461 | u8 min, max; | ||
462 | struct iwl_rxon_context *ctx; | 452 | struct iwl_rxon_context *ctx; |
453 | int i; | ||
463 | 454 | ||
464 | if (band == IEEE80211_BAND_5GHZ) { | 455 | for (i = 0; i < sband->n_channels; i++) { |
465 | min = 14; | ||
466 | max = priv->channel_count; | ||
467 | } else { | ||
468 | min = 0; | ||
469 | max = 14; | ||
470 | } | ||
471 | |||
472 | for (i = min; i < max; i++) { | ||
473 | bool busy = false; | 456 | bool busy = false; |
474 | 457 | ||
475 | for_each_context(priv, ctx) { | 458 | for_each_context(priv, ctx) { |
476 | busy = priv->channel_info[i].channel == | 459 | busy = sband->channels[i].hw_value == |
477 | le16_to_cpu(ctx->staging.channel); | 460 | le16_to_cpu(ctx->staging.channel); |
478 | if (busy) | 461 | if (busy) |
479 | break; | 462 | break; |
@@ -482,54 +465,46 @@ static u8 iwl_get_single_channel_number(struct iwl_priv *priv, | |||
482 | if (busy) | 465 | if (busy) |
483 | continue; | 466 | continue; |
484 | 467 | ||
485 | channel = priv->channel_info[i].channel; | 468 | if (!(sband->channels[i].flags & IEEE80211_CHAN_DISABLED)) |
486 | ch_info = iwl_get_channel_info(priv, band, channel); | 469 | return sband->channels[i].hw_value; |
487 | if (is_channel_valid(ch_info)) | ||
488 | break; | ||
489 | } | 470 | } |
490 | 471 | ||
491 | return channel; | 472 | return 0; |
492 | } | 473 | } |
493 | 474 | ||
494 | static int iwl_get_single_channel_for_scan(struct iwl_priv *priv, | 475 | static int iwl_get_channel_for_reset_scan(struct iwl_priv *priv, |
495 | struct ieee80211_vif *vif, | 476 | struct ieee80211_vif *vif, |
496 | enum ieee80211_band band, | 477 | enum ieee80211_band band, |
497 | struct iwl_scan_channel *scan_ch) | 478 | struct iwl_scan_channel *scan_ch) |
498 | { | 479 | { |
499 | const struct ieee80211_supported_band *sband; | 480 | const struct ieee80211_supported_band *sband; |
500 | u16 passive_dwell = 0; | 481 | u16 channel; |
501 | u16 active_dwell = 0; | ||
502 | int added = 0; | ||
503 | u16 channel = 0; | ||
504 | 482 | ||
505 | sband = iwl_get_hw_mode(priv, band); | 483 | sband = iwl_get_hw_mode(priv, band); |
506 | if (!sband) { | 484 | if (!sband) { |
507 | IWL_ERR(priv, "invalid band\n"); | 485 | IWL_ERR(priv, "invalid band\n"); |
508 | return added; | 486 | return 0; |
509 | } | 487 | } |
510 | 488 | ||
511 | active_dwell = iwl_get_active_dwell_time(priv, band, 0); | ||
512 | passive_dwell = iwl_get_passive_dwell_time(priv, band); | ||
513 | |||
514 | if (passive_dwell <= active_dwell) | ||
515 | passive_dwell = active_dwell + 1; | ||
516 | |||
517 | channel = iwl_get_single_channel_number(priv, band); | 489 | channel = iwl_get_single_channel_number(priv, band); |
518 | if (channel) { | 490 | if (channel) { |
519 | scan_ch->channel = cpu_to_le16(channel); | 491 | scan_ch->channel = cpu_to_le16(channel); |
520 | scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; | 492 | scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; |
521 | scan_ch->active_dwell = cpu_to_le16(active_dwell); | 493 | scan_ch->active_dwell = |
522 | scan_ch->passive_dwell = cpu_to_le16(passive_dwell); | 494 | cpu_to_le16(IWL_RADIO_RESET_DWELL_TIME); |
495 | scan_ch->passive_dwell = | ||
496 | cpu_to_le16(IWL_RADIO_RESET_DWELL_TIME); | ||
523 | /* Set txpower levels to defaults */ | 497 | /* Set txpower levels to defaults */ |
524 | scan_ch->dsp_atten = 110; | 498 | scan_ch->dsp_atten = 110; |
525 | if (band == IEEE80211_BAND_5GHZ) | 499 | if (band == IEEE80211_BAND_5GHZ) |
526 | scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; | 500 | scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; |
527 | else | 501 | else |
528 | scan_ch->tx_gain = ((1 << 5) | (5 << 3)); | 502 | scan_ch->tx_gain = ((1 << 5) | (5 << 3)); |
529 | added++; | 503 | return 1; |
530 | } else | 504 | } |
531 | IWL_ERR(priv, "no valid channel found\n"); | 505 | |
532 | return added; | 506 | IWL_ERR(priv, "no valid channel found\n"); |
507 | return 0; | ||
533 | } | 508 | } |
534 | 509 | ||
535 | static int iwl_get_channels_for_scan(struct iwl_priv *priv, | 510 | static int iwl_get_channels_for_scan(struct iwl_priv *priv, |
@@ -540,7 +515,6 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, | |||
540 | { | 515 | { |
541 | struct ieee80211_channel *chan; | 516 | struct ieee80211_channel *chan; |
542 | const struct ieee80211_supported_band *sband; | 517 | const struct ieee80211_supported_band *sband; |
543 | const struct iwl_channel_info *ch_info; | ||
544 | u16 passive_dwell = 0; | 518 | u16 passive_dwell = 0; |
545 | u16 active_dwell = 0; | 519 | u16 active_dwell = 0; |
546 | int added, i; | 520 | int added, i; |
@@ -565,16 +539,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, | |||
565 | channel = chan->hw_value; | 539 | channel = chan->hw_value; |
566 | scan_ch->channel = cpu_to_le16(channel); | 540 | scan_ch->channel = cpu_to_le16(channel); |
567 | 541 | ||
568 | ch_info = iwl_get_channel_info(priv, band, channel); | 542 | if (!is_active || (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) |
569 | if (!is_channel_valid(ch_info)) { | ||
570 | IWL_DEBUG_SCAN(priv, | ||
571 | "Channel %d is INVALID for this band.\n", | ||
572 | channel); | ||
573 | continue; | ||
574 | } | ||
575 | |||
576 | if (!is_active || is_channel_passive(ch_info) || | ||
577 | (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) | ||
578 | scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; | 543 | scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; |
579 | else | 544 | else |
580 | scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE; | 545 | scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE; |
@@ -678,12 +643,12 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
678 | u16 rx_chain = 0; | 643 | u16 rx_chain = 0; |
679 | enum ieee80211_band band; | 644 | enum ieee80211_band band; |
680 | u8 n_probes = 0; | 645 | u8 n_probes = 0; |
681 | u8 rx_ant = priv->hw_params.valid_rx_ant; | 646 | u8 rx_ant = priv->eeprom_data->valid_rx_ant; |
682 | u8 rate; | 647 | u8 rate; |
683 | bool is_active = false; | 648 | bool is_active = false; |
684 | int chan_mod; | 649 | int chan_mod; |
685 | u8 active_chains; | 650 | u8 active_chains; |
686 | u8 scan_tx_antennas = priv->hw_params.valid_tx_ant; | 651 | u8 scan_tx_antennas = priv->eeprom_data->valid_tx_ant; |
687 | int ret; | 652 | int ret; |
688 | int scan_cmd_size = sizeof(struct iwl_scan_cmd) + | 653 | int scan_cmd_size = sizeof(struct iwl_scan_cmd) + |
689 | MAX_SCAN_CHANNEL * sizeof(struct iwl_scan_channel) + | 654 | MAX_SCAN_CHANNEL * sizeof(struct iwl_scan_channel) + |
@@ -755,6 +720,12 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
755 | switch (priv->scan_type) { | 720 | switch (priv->scan_type) { |
756 | case IWL_SCAN_RADIO_RESET: | 721 | case IWL_SCAN_RADIO_RESET: |
757 | IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n"); | 722 | IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n"); |
723 | /* | ||
724 | * Override quiet time as firmware checks that active | ||
725 | * dwell is >= quiet; since we use passive scan it'll | ||
726 | * not actually be used. | ||
727 | */ | ||
728 | scan->quiet_time = cpu_to_le16(IWL_RADIO_RESET_DWELL_TIME); | ||
758 | break; | 729 | break; |
759 | case IWL_SCAN_NORMAL: | 730 | case IWL_SCAN_NORMAL: |
760 | if (priv->scan_request->n_ssids) { | 731 | if (priv->scan_request->n_ssids) { |
@@ -893,7 +864,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
893 | 864 | ||
894 | /* MIMO is not used here, but value is required */ | 865 | /* MIMO is not used here, but value is required */ |
895 | rx_chain |= | 866 | rx_chain |= |
896 | priv->hw_params.valid_rx_ant << RXON_RX_CHAIN_VALID_POS; | 867 | priv->eeprom_data->valid_rx_ant << RXON_RX_CHAIN_VALID_POS; |
897 | rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; | 868 | rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; |
898 | rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS; | 869 | rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS; |
899 | rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; | 870 | rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; |
@@ -928,7 +899,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
928 | switch (priv->scan_type) { | 899 | switch (priv->scan_type) { |
929 | case IWL_SCAN_RADIO_RESET: | 900 | case IWL_SCAN_RADIO_RESET: |
930 | scan->channel_count = | 901 | scan->channel_count = |
931 | iwl_get_single_channel_for_scan(priv, vif, band, | 902 | iwl_get_channel_for_reset_scan(priv, vif, band, |
932 | (void *)&scan->data[cmd_len]); | 903 | (void *)&scan->data[cmd_len]); |
933 | break; | 904 | break; |
934 | case IWL_SCAN_NORMAL: | 905 | case IWL_SCAN_NORMAL: |
@@ -994,8 +965,10 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
994 | set_bit(STATUS_SCAN_HW, &priv->status); | 965 | set_bit(STATUS_SCAN_HW, &priv->status); |
995 | 966 | ||
996 | ret = iwlagn_set_pan_params(priv); | 967 | ret = iwlagn_set_pan_params(priv); |
997 | if (ret) | 968 | if (ret) { |
969 | clear_bit(STATUS_SCAN_HW, &priv->status); | ||
998 | return ret; | 970 | return ret; |
971 | } | ||
999 | 972 | ||
1000 | ret = iwl_dvm_send_cmd(priv, &cmd); | 973 | ret = iwl_dvm_send_cmd(priv, &cmd); |
1001 | if (ret) { | 974 | if (ret) { |
@@ -1008,7 +981,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
1008 | 981 | ||
1009 | void iwl_init_scan_params(struct iwl_priv *priv) | 982 | void iwl_init_scan_params(struct iwl_priv *priv) |
1010 | { | 983 | { |
1011 | u8 ant_idx = fls(priv->hw_params.valid_tx_ant) - 1; | 984 | u8 ant_idx = fls(priv->eeprom_data->valid_tx_ant) - 1; |
1012 | if (!priv->scan_tx_ant[IEEE80211_BAND_5GHZ]) | 985 | if (!priv->scan_tx_ant[IEEE80211_BAND_5GHZ]) |
1013 | priv->scan_tx_ant[IEEE80211_BAND_5GHZ] = ant_idx; | 986 | priv->scan_tx_ant[IEEE80211_BAND_5GHZ] = ant_idx; |
1014 | if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ]) | 987 | if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ]) |
@@ -1158,3 +1131,40 @@ void iwl_cancel_scan_deferred_work(struct iwl_priv *priv) | |||
1158 | mutex_unlock(&priv->mutex); | 1131 | mutex_unlock(&priv->mutex); |
1159 | } | 1132 | } |
1160 | } | 1133 | } |
1134 | |||
1135 | void iwl_scan_roc_expired(struct iwl_priv *priv) | ||
1136 | { | ||
1137 | /* | ||
1138 | * The status bit should be set here, to prevent a race | ||
1139 | * where the atomic_read returns 1, but before the execution continues | ||
1140 | * iwl_scan_offchannel_skb_status() checks if the status bit is set | ||
1141 | */ | ||
1142 | set_bit(STATUS_SCAN_ROC_EXPIRED, &priv->status); | ||
1143 | |||
1144 | if (atomic_read(&priv->num_aux_in_flight) == 0) { | ||
1145 | ieee80211_remain_on_channel_expired(priv->hw); | ||
1146 | priv->hw_roc_channel = NULL; | ||
1147 | schedule_delayed_work(&priv->hw_roc_disable_work, | ||
1148 | 10 * HZ); | ||
1149 | |||
1150 | clear_bit(STATUS_SCAN_ROC_EXPIRED, &priv->status); | ||
1151 | } else { | ||
1152 | IWL_DEBUG_SCAN(priv, "ROC done with %d frames in aux\n", | ||
1153 | atomic_read(&priv->num_aux_in_flight)); | ||
1154 | } | ||
1155 | } | ||
1156 | |||
1157 | void iwl_scan_offchannel_skb(struct iwl_priv *priv) | ||
1158 | { | ||
1159 | WARN_ON(!priv->hw_roc_start_notified); | ||
1160 | atomic_inc(&priv->num_aux_in_flight); | ||
1161 | } | ||
1162 | |||
1163 | void iwl_scan_offchannel_skb_status(struct iwl_priv *priv) | ||
1164 | { | ||
1165 | if (atomic_dec_return(&priv->num_aux_in_flight) == 0 && | ||
1166 | test_bit(STATUS_SCAN_ROC_EXPIRED, &priv->status)) { | ||
1167 | IWL_DEBUG_SCAN(priv, "0 aux frames. Calling ROC expired\n"); | ||
1168 | iwl_scan_roc_expired(priv); | ||
1169 | } | ||
1170 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/dvm/sta.c index 36055ed1c06..b29b798f755 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/dvm/sta.c | |||
@@ -28,10 +28,9 @@ | |||
28 | *****************************************************************************/ | 28 | *****************************************************************************/ |
29 | #include <linux/etherdevice.h> | 29 | #include <linux/etherdevice.h> |
30 | #include <net/mac80211.h> | 30 | #include <net/mac80211.h> |
31 | |||
32 | #include "iwl-dev.h" | ||
33 | #include "iwl-agn.h" | ||
34 | #include "iwl-trans.h" | 31 | #include "iwl-trans.h" |
32 | #include "dev.h" | ||
33 | #include "agn.h" | ||
35 | 34 | ||
36 | const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; | 35 | const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; |
37 | 36 | ||
@@ -171,26 +170,6 @@ int iwl_send_add_sta(struct iwl_priv *priv, | |||
171 | return cmd.handler_status; | 170 | return cmd.handler_status; |
172 | } | 171 | } |
173 | 172 | ||
174 | static bool iwl_is_channel_extension(struct iwl_priv *priv, | ||
175 | enum ieee80211_band band, | ||
176 | u16 channel, u8 extension_chan_offset) | ||
177 | { | ||
178 | const struct iwl_channel_info *ch_info; | ||
179 | |||
180 | ch_info = iwl_get_channel_info(priv, band, channel); | ||
181 | if (!is_channel_valid(ch_info)) | ||
182 | return false; | ||
183 | |||
184 | if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE) | ||
185 | return !(ch_info->ht40_extension_channel & | ||
186 | IEEE80211_CHAN_NO_HT40PLUS); | ||
187 | else if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW) | ||
188 | return !(ch_info->ht40_extension_channel & | ||
189 | IEEE80211_CHAN_NO_HT40MINUS); | ||
190 | |||
191 | return false; | ||
192 | } | ||
193 | |||
194 | bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv, | 173 | bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv, |
195 | struct iwl_rxon_context *ctx, | 174 | struct iwl_rxon_context *ctx, |
196 | struct ieee80211_sta_ht_cap *ht_cap) | 175 | struct ieee80211_sta_ht_cap *ht_cap) |
@@ -198,21 +177,25 @@ bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv, | |||
198 | if (!ctx->ht.enabled || !ctx->ht.is_40mhz) | 177 | if (!ctx->ht.enabled || !ctx->ht.is_40mhz) |
199 | return false; | 178 | return false; |
200 | 179 | ||
180 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
181 | if (priv->disable_ht40) | ||
182 | return false; | ||
183 | #endif | ||
184 | |||
201 | /* | 185 | /* |
202 | * We do not check for IEEE80211_HT_CAP_SUP_WIDTH_20_40 | 186 | * Remainder of this function checks ht_cap, but if it's |
203 | * the bit will not set if it is pure 40MHz case | 187 | * NULL then we can do HT40 (special case for RXON) |
204 | */ | 188 | */ |
205 | if (ht_cap && !ht_cap->ht_supported) | 189 | if (!ht_cap) |
190 | return true; | ||
191 | |||
192 | if (!ht_cap->ht_supported) | ||
206 | return false; | 193 | return false; |
207 | 194 | ||
208 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 195 | if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) |
209 | if (priv->disable_ht40) | ||
210 | return false; | 196 | return false; |
211 | #endif | ||
212 | 197 | ||
213 | return iwl_is_channel_extension(priv, priv->band, | 198 | return true; |
214 | le16_to_cpu(ctx->staging.channel), | ||
215 | ctx->ht.extension_chan_offset); | ||
216 | } | 199 | } |
217 | 200 | ||
218 | static void iwl_sta_calc_ht_flags(struct iwl_priv *priv, | 201 | static void iwl_sta_calc_ht_flags(struct iwl_priv *priv, |
@@ -650,23 +633,23 @@ static void iwl_sta_fill_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, | |||
650 | if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE) | 633 | if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE) |
651 | rate_flags |= RATE_MCS_CCK_MSK; | 634 | rate_flags |= RATE_MCS_CCK_MSK; |
652 | 635 | ||
653 | rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) << | 636 | rate_flags |= first_antenna(priv->eeprom_data->valid_tx_ant) << |
654 | RATE_MCS_ANT_POS; | 637 | RATE_MCS_ANT_POS; |
655 | rate_n_flags = iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags); | 638 | rate_n_flags = iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags); |
656 | for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) | 639 | for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) |
657 | link_cmd->rs_table[i].rate_n_flags = rate_n_flags; | 640 | link_cmd->rs_table[i].rate_n_flags = rate_n_flags; |
658 | 641 | ||
659 | link_cmd->general_params.single_stream_ant_msk = | 642 | link_cmd->general_params.single_stream_ant_msk = |
660 | first_antenna(priv->hw_params.valid_tx_ant); | 643 | first_antenna(priv->eeprom_data->valid_tx_ant); |
661 | 644 | ||
662 | link_cmd->general_params.dual_stream_ant_msk = | 645 | link_cmd->general_params.dual_stream_ant_msk = |
663 | priv->hw_params.valid_tx_ant & | 646 | priv->eeprom_data->valid_tx_ant & |
664 | ~first_antenna(priv->hw_params.valid_tx_ant); | 647 | ~first_antenna(priv->eeprom_data->valid_tx_ant); |
665 | if (!link_cmd->general_params.dual_stream_ant_msk) { | 648 | if (!link_cmd->general_params.dual_stream_ant_msk) { |
666 | link_cmd->general_params.dual_stream_ant_msk = ANT_AB; | 649 | link_cmd->general_params.dual_stream_ant_msk = ANT_AB; |
667 | } else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) { | 650 | } else if (num_of_ant(priv->eeprom_data->valid_tx_ant) == 2) { |
668 | link_cmd->general_params.dual_stream_ant_msk = | 651 | link_cmd->general_params.dual_stream_ant_msk = |
669 | priv->hw_params.valid_tx_ant; | 652 | priv->eeprom_data->valid_tx_ant; |
670 | } | 653 | } |
671 | 654 | ||
672 | link_cmd->agg_params.agg_dis_start_th = | 655 | link_cmd->agg_params.agg_dis_start_th = |
@@ -1268,7 +1251,7 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, | |||
1268 | key_flags |= STA_KEY_MULTICAST_MSK; | 1251 | key_flags |= STA_KEY_MULTICAST_MSK; |
1269 | 1252 | ||
1270 | sta_cmd.key.key_flags = key_flags; | 1253 | sta_cmd.key.key_flags = key_flags; |
1271 | sta_cmd.key.key_offset = WEP_INVALID_OFFSET; | 1254 | sta_cmd.key.key_offset = keyconf->hw_key_idx; |
1272 | sta_cmd.sta.modify_mask = STA_MODIFY_KEY_MASK; | 1255 | sta_cmd.sta.modify_mask = STA_MODIFY_KEY_MASK; |
1273 | sta_cmd.mode = STA_CONTROL_MODIFY_MSK; | 1256 | sta_cmd.mode = STA_CONTROL_MODIFY_MSK; |
1274 | 1257 | ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/testmode.c b/drivers/net/wireless/iwlwifi/dvm/testmode.c new file mode 100644 index 00000000000..57b918ce3b5 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/dvm/testmode.c | |||
@@ -0,0 +1,471 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2010 - 2012 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2010 - 2012 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | * | ||
62 | *****************************************************************************/ | ||
63 | |||
64 | #include <linux/init.h> | ||
65 | #include <linux/kernel.h> | ||
66 | #include <linux/module.h> | ||
67 | #include <linux/dma-mapping.h> | ||
68 | #include <net/net_namespace.h> | ||
69 | #include <linux/netdevice.h> | ||
70 | #include <net/cfg80211.h> | ||
71 | #include <net/mac80211.h> | ||
72 | #include <net/netlink.h> | ||
73 | |||
74 | #include "iwl-debug.h" | ||
75 | #include "iwl-trans.h" | ||
76 | #include "dev.h" | ||
77 | #include "agn.h" | ||
78 | #include "iwl-test.h" | ||
79 | #include "iwl-testmode.h" | ||
80 | |||
81 | static int iwl_testmode_send_cmd(struct iwl_op_mode *op_mode, | ||
82 | struct iwl_host_cmd *cmd) | ||
83 | { | ||
84 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | ||
85 | return iwl_dvm_send_cmd(priv, cmd); | ||
86 | } | ||
87 | |||
88 | static bool iwl_testmode_valid_hw_addr(u32 addr) | ||
89 | { | ||
90 | if (iwlagn_hw_valid_rtc_data_addr(addr)) | ||
91 | return true; | ||
92 | |||
93 | if (IWLAGN_RTC_INST_LOWER_BOUND <= addr && | ||
94 | addr < IWLAGN_RTC_INST_UPPER_BOUND) | ||
95 | return true; | ||
96 | |||
97 | return false; | ||
98 | } | ||
99 | |||
100 | static u32 iwl_testmode_get_fw_ver(struct iwl_op_mode *op_mode) | ||
101 | { | ||
102 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | ||
103 | return priv->fw->ucode_ver; | ||
104 | } | ||
105 | |||
106 | static struct sk_buff* | ||
107 | iwl_testmode_alloc_reply(struct iwl_op_mode *op_mode, int len) | ||
108 | { | ||
109 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | ||
110 | return cfg80211_testmode_alloc_reply_skb(priv->hw->wiphy, len); | ||
111 | } | ||
112 | |||
113 | static int iwl_testmode_reply(struct iwl_op_mode *op_mode, struct sk_buff *skb) | ||
114 | { | ||
115 | return cfg80211_testmode_reply(skb); | ||
116 | } | ||
117 | |||
118 | static struct sk_buff *iwl_testmode_alloc_event(struct iwl_op_mode *op_mode, | ||
119 | int len) | ||
120 | { | ||
121 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | ||
122 | return cfg80211_testmode_alloc_event_skb(priv->hw->wiphy, len, | ||
123 | GFP_ATOMIC); | ||
124 | } | ||
125 | |||
126 | static void iwl_testmode_event(struct iwl_op_mode *op_mode, struct sk_buff *skb) | ||
127 | { | ||
128 | return cfg80211_testmode_event(skb, GFP_ATOMIC); | ||
129 | } | ||
130 | |||
131 | static struct iwl_test_ops tst_ops = { | ||
132 | .send_cmd = iwl_testmode_send_cmd, | ||
133 | .valid_hw_addr = iwl_testmode_valid_hw_addr, | ||
134 | .get_fw_ver = iwl_testmode_get_fw_ver, | ||
135 | .alloc_reply = iwl_testmode_alloc_reply, | ||
136 | .reply = iwl_testmode_reply, | ||
137 | .alloc_event = iwl_testmode_alloc_event, | ||
138 | .event = iwl_testmode_event, | ||
139 | }; | ||
140 | |||
141 | void iwl_testmode_init(struct iwl_priv *priv) | ||
142 | { | ||
143 | iwl_test_init(&priv->tst, priv->trans, &tst_ops); | ||
144 | } | ||
145 | |||
146 | void iwl_testmode_free(struct iwl_priv *priv) | ||
147 | { | ||
148 | iwl_test_free(&priv->tst); | ||
149 | } | ||
150 | |||
151 | static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv) | ||
152 | { | ||
153 | struct iwl_notification_wait calib_wait; | ||
154 | static const u8 calib_complete[] = { | ||
155 | CALIBRATION_COMPLETE_NOTIFICATION | ||
156 | }; | ||
157 | int ret; | ||
158 | |||
159 | iwl_init_notification_wait(&priv->notif_wait, &calib_wait, | ||
160 | calib_complete, ARRAY_SIZE(calib_complete), | ||
161 | NULL, NULL); | ||
162 | ret = iwl_init_alive_start(priv); | ||
163 | if (ret) { | ||
164 | IWL_ERR(priv, "Fail init calibration: %d\n", ret); | ||
165 | goto cfg_init_calib_error; | ||
166 | } | ||
167 | |||
168 | ret = iwl_wait_notification(&priv->notif_wait, &calib_wait, 2 * HZ); | ||
169 | if (ret) | ||
170 | IWL_ERR(priv, "Error detecting" | ||
171 | " CALIBRATION_COMPLETE_NOTIFICATION: %d\n", ret); | ||
172 | return ret; | ||
173 | |||
174 | cfg_init_calib_error: | ||
175 | iwl_remove_notification(&priv->notif_wait, &calib_wait); | ||
176 | return ret; | ||
177 | } | ||
178 | |||
179 | /* | ||
180 | * This function handles the user application commands for driver. | ||
181 | * | ||
182 | * It retrieves command ID carried with IWL_TM_ATTR_COMMAND and calls to the | ||
183 | * handlers respectively. | ||
184 | * | ||
185 | * If it's an unknown commdn ID, -ENOSYS is replied; otherwise, the returned | ||
186 | * value of the actual command execution is replied to the user application. | ||
187 | * | ||
188 | * If there's any message responding to the user space, IWL_TM_ATTR_SYNC_RSP | ||
189 | * is used for carry the message while IWL_TM_ATTR_COMMAND must set to | ||
190 | * IWL_TM_CMD_DEV2APP_SYNC_RSP. | ||
191 | * | ||
192 | * @hw: ieee80211_hw object that represents the device | ||
193 | * @tb: gnl message fields from the user space | ||
194 | */ | ||
195 | static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) | ||
196 | { | ||
197 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | ||
198 | struct iwl_trans *trans = priv->trans; | ||
199 | struct sk_buff *skb; | ||
200 | unsigned char *rsp_data_ptr = NULL; | ||
201 | int status = 0, rsp_data_len = 0; | ||
202 | u32 inst_size = 0, data_size = 0; | ||
203 | const struct fw_img *img; | ||
204 | |||
205 | switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { | ||
206 | case IWL_TM_CMD_APP2DEV_GET_DEVICENAME: | ||
207 | rsp_data_ptr = (unsigned char *)priv->cfg->name; | ||
208 | rsp_data_len = strlen(priv->cfg->name); | ||
209 | skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, | ||
210 | rsp_data_len + 20); | ||
211 | if (!skb) { | ||
212 | IWL_ERR(priv, "Memory allocation fail\n"); | ||
213 | return -ENOMEM; | ||
214 | } | ||
215 | if (nla_put_u32(skb, IWL_TM_ATTR_COMMAND, | ||
216 | IWL_TM_CMD_DEV2APP_SYNC_RSP) || | ||
217 | nla_put(skb, IWL_TM_ATTR_SYNC_RSP, | ||
218 | rsp_data_len, rsp_data_ptr)) | ||
219 | goto nla_put_failure; | ||
220 | status = cfg80211_testmode_reply(skb); | ||
221 | if (status < 0) | ||
222 | IWL_ERR(priv, "Error sending msg : %d\n", status); | ||
223 | break; | ||
224 | |||
225 | case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW: | ||
226 | status = iwl_load_ucode_wait_alive(priv, IWL_UCODE_INIT); | ||
227 | if (status) | ||
228 | IWL_ERR(priv, "Error loading init ucode: %d\n", status); | ||
229 | break; | ||
230 | |||
231 | case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB: | ||
232 | iwl_testmode_cfg_init_calib(priv); | ||
233 | priv->ucode_loaded = false; | ||
234 | iwl_trans_stop_device(trans); | ||
235 | break; | ||
236 | |||
237 | case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW: | ||
238 | status = iwl_load_ucode_wait_alive(priv, IWL_UCODE_REGULAR); | ||
239 | if (status) { | ||
240 | IWL_ERR(priv, | ||
241 | "Error loading runtime ucode: %d\n", status); | ||
242 | break; | ||
243 | } | ||
244 | status = iwl_alive_start(priv); | ||
245 | if (status) | ||
246 | IWL_ERR(priv, | ||
247 | "Error starting the device: %d\n", status); | ||
248 | break; | ||
249 | |||
250 | case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW: | ||
251 | iwl_scan_cancel_timeout(priv, 200); | ||
252 | priv->ucode_loaded = false; | ||
253 | iwl_trans_stop_device(trans); | ||
254 | status = iwl_load_ucode_wait_alive(priv, IWL_UCODE_WOWLAN); | ||
255 | if (status) { | ||
256 | IWL_ERR(priv, | ||
257 | "Error loading WOWLAN ucode: %d\n", status); | ||
258 | break; | ||
259 | } | ||
260 | status = iwl_alive_start(priv); | ||
261 | if (status) | ||
262 | IWL_ERR(priv, | ||
263 | "Error starting the device: %d\n", status); | ||
264 | break; | ||
265 | |||
266 | case IWL_TM_CMD_APP2DEV_GET_EEPROM: | ||
267 | if (priv->eeprom_blob) { | ||
268 | skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, | ||
269 | priv->eeprom_blob_size + 20); | ||
270 | if (!skb) { | ||
271 | IWL_ERR(priv, "Memory allocation fail\n"); | ||
272 | return -ENOMEM; | ||
273 | } | ||
274 | if (nla_put_u32(skb, IWL_TM_ATTR_COMMAND, | ||
275 | IWL_TM_CMD_DEV2APP_EEPROM_RSP) || | ||
276 | nla_put(skb, IWL_TM_ATTR_EEPROM, | ||
277 | priv->eeprom_blob_size, | ||
278 | priv->eeprom_blob)) | ||
279 | goto nla_put_failure; | ||
280 | status = cfg80211_testmode_reply(skb); | ||
281 | if (status < 0) | ||
282 | IWL_ERR(priv, "Error sending msg : %d\n", | ||
283 | status); | ||
284 | } else | ||
285 | return -ENODATA; | ||
286 | break; | ||
287 | |||
288 | case IWL_TM_CMD_APP2DEV_FIXRATE_REQ: | ||
289 | if (!tb[IWL_TM_ATTR_FIXRATE]) { | ||
290 | IWL_ERR(priv, "Missing fixrate setting\n"); | ||
291 | return -ENOMSG; | ||
292 | } | ||
293 | priv->tm_fixed_rate = nla_get_u32(tb[IWL_TM_ATTR_FIXRATE]); | ||
294 | break; | ||
295 | |||
296 | case IWL_TM_CMD_APP2DEV_GET_FW_INFO: | ||
297 | skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20 + 8); | ||
298 | if (!skb) { | ||
299 | IWL_ERR(priv, "Memory allocation fail\n"); | ||
300 | return -ENOMEM; | ||
301 | } | ||
302 | if (!priv->ucode_loaded) { | ||
303 | IWL_ERR(priv, "No uCode has not been loaded\n"); | ||
304 | return -EINVAL; | ||
305 | } else { | ||
306 | img = &priv->fw->img[priv->cur_ucode]; | ||
307 | inst_size = img->sec[IWL_UCODE_SECTION_INST].len; | ||
308 | data_size = img->sec[IWL_UCODE_SECTION_DATA].len; | ||
309 | } | ||
310 | if (nla_put_u32(skb, IWL_TM_ATTR_FW_TYPE, priv->cur_ucode) || | ||
311 | nla_put_u32(skb, IWL_TM_ATTR_FW_INST_SIZE, inst_size) || | ||
312 | nla_put_u32(skb, IWL_TM_ATTR_FW_DATA_SIZE, data_size)) | ||
313 | goto nla_put_failure; | ||
314 | status = cfg80211_testmode_reply(skb); | ||
315 | if (status < 0) | ||
316 | IWL_ERR(priv, "Error sending msg : %d\n", status); | ||
317 | break; | ||
318 | |||
319 | default: | ||
320 | IWL_ERR(priv, "Unknown testmode driver command ID\n"); | ||
321 | return -ENOSYS; | ||
322 | } | ||
323 | return status; | ||
324 | |||
325 | nla_put_failure: | ||
326 | kfree_skb(skb); | ||
327 | return -EMSGSIZE; | ||
328 | } | ||
329 | |||
330 | /* | ||
331 | * This function handles the user application switch ucode ownership. | ||
332 | * | ||
333 | * It retrieves the mandatory fields IWL_TM_ATTR_UCODE_OWNER and | ||
334 | * decide who the current owner of the uCode | ||
335 | * | ||
336 | * If the current owner is OWNERSHIP_TM, then the only host command | ||
337 | * can deliver to uCode is from testmode, all the other host commands | ||
338 | * will dropped. | ||
339 | * | ||
340 | * default driver is the owner of uCode in normal operational mode | ||
341 | * | ||
342 | * @hw: ieee80211_hw object that represents the device | ||
343 | * @tb: gnl message fields from the user space | ||
344 | */ | ||
345 | static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb) | ||
346 | { | ||
347 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | ||
348 | u8 owner; | ||
349 | |||
350 | if (!tb[IWL_TM_ATTR_UCODE_OWNER]) { | ||
351 | IWL_ERR(priv, "Missing ucode owner\n"); | ||
352 | return -ENOMSG; | ||
353 | } | ||
354 | |||
355 | owner = nla_get_u8(tb[IWL_TM_ATTR_UCODE_OWNER]); | ||
356 | if (owner == IWL_OWNERSHIP_DRIVER) { | ||
357 | priv->ucode_owner = owner; | ||
358 | iwl_test_enable_notifications(&priv->tst, false); | ||
359 | } else if (owner == IWL_OWNERSHIP_TM) { | ||
360 | priv->ucode_owner = owner; | ||
361 | iwl_test_enable_notifications(&priv->tst, true); | ||
362 | } else { | ||
363 | IWL_ERR(priv, "Invalid owner\n"); | ||
364 | return -EINVAL; | ||
365 | } | ||
366 | return 0; | ||
367 | } | ||
368 | |||
369 | /* The testmode gnl message handler that takes the gnl message from the | ||
370 | * user space and parses it per the policy iwl_testmode_gnl_msg_policy, then | ||
371 | * invoke the corresponding handlers. | ||
372 | * | ||
373 | * This function is invoked when there is user space application sending | ||
374 | * gnl message through the testmode tunnel NL80211_CMD_TESTMODE regulated | ||
375 | * by nl80211. | ||
376 | * | ||
377 | * It retrieves the mandatory field, IWL_TM_ATTR_COMMAND, before | ||
378 | * dispatching it to the corresponding handler. | ||
379 | * | ||
380 | * If IWL_TM_ATTR_COMMAND is missing, -ENOMSG is replied to user application; | ||
381 | * -ENOSYS is replied to the user application if the command is unknown; | ||
382 | * Otherwise, the command is dispatched to the respective handler. | ||
383 | * | ||
384 | * @hw: ieee80211_hw object that represents the device | ||
385 | * @data: pointer to user space message | ||
386 | * @len: length in byte of @data | ||
387 | */ | ||
388 | int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) | ||
389 | { | ||
390 | struct nlattr *tb[IWL_TM_ATTR_MAX]; | ||
391 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | ||
392 | int result; | ||
393 | |||
394 | result = iwl_test_parse(&priv->tst, tb, data, len); | ||
395 | if (result) | ||
396 | return result; | ||
397 | |||
398 | /* in case multiple accesses to the device happens */ | ||
399 | mutex_lock(&priv->mutex); | ||
400 | switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { | ||
401 | case IWL_TM_CMD_APP2DEV_UCODE: | ||
402 | case IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32: | ||
403 | case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32: | ||
404 | case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8: | ||
405 | case IWL_TM_CMD_APP2DEV_BEGIN_TRACE: | ||
406 | case IWL_TM_CMD_APP2DEV_END_TRACE: | ||
407 | case IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_READ: | ||
408 | case IWL_TM_CMD_APP2DEV_NOTIFICATIONS: | ||
409 | case IWL_TM_CMD_APP2DEV_GET_FW_VERSION: | ||
410 | case IWL_TM_CMD_APP2DEV_GET_DEVICE_ID: | ||
411 | case IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_WRITE: | ||
412 | result = iwl_test_handle_cmd(&priv->tst, tb); | ||
413 | break; | ||
414 | |||
415 | case IWL_TM_CMD_APP2DEV_GET_DEVICENAME: | ||
416 | case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW: | ||
417 | case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB: | ||
418 | case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW: | ||
419 | case IWL_TM_CMD_APP2DEV_GET_EEPROM: | ||
420 | case IWL_TM_CMD_APP2DEV_FIXRATE_REQ: | ||
421 | case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW: | ||
422 | case IWL_TM_CMD_APP2DEV_GET_FW_INFO: | ||
423 | IWL_DEBUG_INFO(priv, "testmode cmd to driver\n"); | ||
424 | result = iwl_testmode_driver(hw, tb); | ||
425 | break; | ||
426 | |||
427 | case IWL_TM_CMD_APP2DEV_OWNERSHIP: | ||
428 | IWL_DEBUG_INFO(priv, "testmode change uCode ownership\n"); | ||
429 | result = iwl_testmode_ownership(hw, tb); | ||
430 | break; | ||
431 | |||
432 | default: | ||
433 | IWL_ERR(priv, "Unknown testmode command\n"); | ||
434 | result = -ENOSYS; | ||
435 | break; | ||
436 | } | ||
437 | mutex_unlock(&priv->mutex); | ||
438 | |||
439 | if (result) | ||
440 | IWL_ERR(priv, "Test cmd failed result=%d\n", result); | ||
441 | return result; | ||
442 | } | ||
443 | |||
444 | int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb, | ||
445 | struct netlink_callback *cb, | ||
446 | void *data, int len) | ||
447 | { | ||
448 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | ||
449 | int result; | ||
450 | u32 cmd; | ||
451 | |||
452 | if (cb->args[3]) { | ||
453 | /* offset by 1 since commands start at 0 */ | ||
454 | cmd = cb->args[3] - 1; | ||
455 | } else { | ||
456 | struct nlattr *tb[IWL_TM_ATTR_MAX]; | ||
457 | |||
458 | result = iwl_test_parse(&priv->tst, tb, data, len); | ||
459 | if (result) | ||
460 | return result; | ||
461 | |||
462 | cmd = nla_get_u32(tb[IWL_TM_ATTR_COMMAND]); | ||
463 | cb->args[3] = cmd + 1; | ||
464 | } | ||
465 | |||
466 | /* in case multiple accesses to the device happens */ | ||
467 | mutex_lock(&priv->mutex); | ||
468 | result = iwl_test_dump(&priv->tst, cmd, skb, cb); | ||
469 | mutex_unlock(&priv->mutex); | ||
470 | return result; | ||
471 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/drivers/net/wireless/iwlwifi/dvm/tt.c index a5cfe0aceed..eb864433e59 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c +++ b/drivers/net/wireless/iwlwifi/dvm/tt.c | |||
@@ -31,17 +31,14 @@ | |||
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
33 | #include <linux/init.h> | 33 | #include <linux/init.h> |
34 | |||
35 | #include <net/mac80211.h> | 34 | #include <net/mac80211.h> |
36 | |||
37 | #include "iwl-agn.h" | ||
38 | #include "iwl-eeprom.h" | ||
39 | #include "iwl-dev.h" | ||
40 | #include "iwl-io.h" | 35 | #include "iwl-io.h" |
41 | #include "iwl-commands.h" | ||
42 | #include "iwl-debug.h" | ||
43 | #include "iwl-agn-tt.h" | ||
44 | #include "iwl-modparams.h" | 36 | #include "iwl-modparams.h" |
37 | #include "iwl-debug.h" | ||
38 | #include "agn.h" | ||
39 | #include "dev.h" | ||
40 | #include "commands.h" | ||
41 | #include "tt.h" | ||
45 | 42 | ||
46 | /* default Thermal Throttling transaction table | 43 | /* default Thermal Throttling transaction table |
47 | * Current state | Throttling Down | Throttling Up | 44 | * Current state | Throttling Down | Throttling Up |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.h b/drivers/net/wireless/iwlwifi/dvm/tt.h index 86bbf47501c..44c7c8f30a2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tt.h +++ b/drivers/net/wireless/iwlwifi/dvm/tt.h | |||
@@ -28,7 +28,7 @@ | |||
28 | #ifndef __iwl_tt_setting_h__ | 28 | #ifndef __iwl_tt_setting_h__ |
29 | #define __iwl_tt_setting_h__ | 29 | #define __iwl_tt_setting_h__ |
30 | 30 | ||
31 | #include "iwl-commands.h" | 31 | #include "commands.h" |
32 | 32 | ||
33 | #define IWL_ABSOLUTE_ZERO 0 | 33 | #define IWL_ABSOLUTE_ZERO 0 |
34 | #define IWL_ABSOLUTE_MAX 0xFFFFFFFF | 34 | #define IWL_ABSOLUTE_MAX 0xFFFFFFFF |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c index 3366e2e2f00..5971a23aa47 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/dvm/tx.c | |||
@@ -32,12 +32,11 @@ | |||
32 | #include <linux/init.h> | 32 | #include <linux/init.h> |
33 | #include <linux/sched.h> | 33 | #include <linux/sched.h> |
34 | #include <linux/ieee80211.h> | 34 | #include <linux/ieee80211.h> |
35 | |||
36 | #include "iwl-dev.h" | ||
37 | #include "iwl-io.h" | 35 | #include "iwl-io.h" |
38 | #include "iwl-agn-hw.h" | ||
39 | #include "iwl-agn.h" | ||
40 | #include "iwl-trans.h" | 36 | #include "iwl-trans.h" |
37 | #include "iwl-agn-hw.h" | ||
38 | #include "dev.h" | ||
39 | #include "agn.h" | ||
41 | 40 | ||
42 | static const u8 tid_to_ac[] = { | 41 | static const u8 tid_to_ac[] = { |
43 | IEEE80211_AC_BE, | 42 | IEEE80211_AC_BE, |
@@ -187,7 +186,8 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, | |||
187 | rate_idx = info->control.rates[0].idx; | 186 | rate_idx = info->control.rates[0].idx; |
188 | if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS || | 187 | if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS || |
189 | (rate_idx < 0) || (rate_idx > IWL_RATE_COUNT_LEGACY)) | 188 | (rate_idx < 0) || (rate_idx > IWL_RATE_COUNT_LEGACY)) |
190 | rate_idx = rate_lowest_index(&priv->bands[info->band], | 189 | rate_idx = rate_lowest_index( |
190 | &priv->eeprom_data->bands[info->band], | ||
191 | info->control.sta); | 191 | info->control.sta); |
192 | /* For 5 GHZ band, remap mac80211 rate indices into driver indices */ | 192 | /* For 5 GHZ band, remap mac80211 rate indices into driver indices */ |
193 | if (info->band == IEEE80211_BAND_5GHZ) | 193 | if (info->band == IEEE80211_BAND_5GHZ) |
@@ -207,10 +207,11 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, | |||
207 | priv->bt_full_concurrent) { | 207 | priv->bt_full_concurrent) { |
208 | /* operated as 1x1 in full concurrency mode */ | 208 | /* operated as 1x1 in full concurrency mode */ |
209 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, | 209 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, |
210 | first_antenna(priv->hw_params.valid_tx_ant)); | 210 | first_antenna(priv->eeprom_data->valid_tx_ant)); |
211 | } else | 211 | } else |
212 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, | 212 | priv->mgmt_tx_ant = iwl_toggle_tx_ant( |
213 | priv->hw_params.valid_tx_ant); | 213 | priv, priv->mgmt_tx_ant, |
214 | priv->eeprom_data->valid_tx_ant); | ||
214 | rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant); | 215 | rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant); |
215 | 216 | ||
216 | /* Set the rate in the TX cmd */ | 217 | /* Set the rate in the TX cmd */ |
@@ -296,7 +297,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
296 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 297 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
297 | struct iwl_station_priv *sta_priv = NULL; | 298 | struct iwl_station_priv *sta_priv = NULL; |
298 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | 299 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; |
299 | struct iwl_device_cmd *dev_cmd = NULL; | 300 | struct iwl_device_cmd *dev_cmd; |
300 | struct iwl_tx_cmd *tx_cmd; | 301 | struct iwl_tx_cmd *tx_cmd; |
301 | __le16 fc; | 302 | __le16 fc; |
302 | u8 hdr_len; | 303 | u8 hdr_len; |
@@ -378,7 +379,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
378 | if (info->flags & IEEE80211_TX_CTL_AMPDU) | 379 | if (info->flags & IEEE80211_TX_CTL_AMPDU) |
379 | is_agg = true; | 380 | is_agg = true; |
380 | 381 | ||
381 | dev_cmd = kmem_cache_alloc(iwl_tx_cmd_pool, GFP_ATOMIC); | 382 | dev_cmd = iwl_trans_alloc_tx_cmd(priv->trans); |
382 | 383 | ||
383 | if (unlikely(!dev_cmd)) | 384 | if (unlikely(!dev_cmd)) |
384 | goto drop_unlock_priv; | 385 | goto drop_unlock_priv; |
@@ -402,6 +403,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
402 | 403 | ||
403 | info->driver_data[0] = ctx; | 404 | info->driver_data[0] = ctx; |
404 | info->driver_data[1] = dev_cmd; | 405 | info->driver_data[1] = dev_cmd; |
406 | /* From now on, we cannot access info->control */ | ||
405 | 407 | ||
406 | spin_lock(&priv->sta_lock); | 408 | spin_lock(&priv->sta_lock); |
407 | 409 | ||
@@ -486,11 +488,14 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
486 | if (sta_priv && sta_priv->client && !is_agg) | 488 | if (sta_priv && sta_priv->client && !is_agg) |
487 | atomic_inc(&sta_priv->pending_frames); | 489 | atomic_inc(&sta_priv->pending_frames); |
488 | 490 | ||
491 | if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) | ||
492 | iwl_scan_offchannel_skb(priv); | ||
493 | |||
489 | return 0; | 494 | return 0; |
490 | 495 | ||
491 | drop_unlock_sta: | 496 | drop_unlock_sta: |
492 | if (dev_cmd) | 497 | if (dev_cmd) |
493 | kmem_cache_free(iwl_tx_cmd_pool, dev_cmd); | 498 | iwl_trans_free_tx_cmd(priv->trans, dev_cmd); |
494 | spin_unlock(&priv->sta_lock); | 499 | spin_unlock(&priv->sta_lock); |
495 | drop_unlock_priv: | 500 | drop_unlock_priv: |
496 | return -1; | 501 | return -1; |
@@ -597,7 +602,7 @@ turn_off: | |||
597 | * time, or we hadn't time to drain the AC queues. | 602 | * time, or we hadn't time to drain the AC queues. |
598 | */ | 603 | */ |
599 | if (agg_state == IWL_AGG_ON) | 604 | if (agg_state == IWL_AGG_ON) |
600 | iwl_trans_tx_agg_disable(priv->trans, txq_id); | 605 | iwl_trans_txq_disable(priv->trans, txq_id); |
601 | else | 606 | else |
602 | IWL_DEBUG_TX_QUEUES(priv, "Don't disable tx agg: %d\n", | 607 | IWL_DEBUG_TX_QUEUES(priv, "Don't disable tx agg: %d\n", |
603 | agg_state); | 608 | agg_state); |
@@ -686,9 +691,8 @@ int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
686 | 691 | ||
687 | fifo = ctx->ac_to_fifo[tid_to_ac[tid]]; | 692 | fifo = ctx->ac_to_fifo[tid_to_ac[tid]]; |
688 | 693 | ||
689 | iwl_trans_tx_agg_setup(priv->trans, q, fifo, | 694 | iwl_trans_txq_enable(priv->trans, q, fifo, sta_priv->sta_id, tid, |
690 | sta_priv->sta_id, tid, | 695 | buf_size, ssn); |
691 | buf_size, ssn); | ||
692 | 696 | ||
693 | /* | 697 | /* |
694 | * If the limit is 0, then it wasn't initialised yet, | 698 | * If the limit is 0, then it wasn't initialised yet, |
@@ -753,8 +757,8 @@ static void iwlagn_check_ratid_empty(struct iwl_priv *priv, int sta_id, u8 tid) | |||
753 | IWL_DEBUG_TX_QUEUES(priv, | 757 | IWL_DEBUG_TX_QUEUES(priv, |
754 | "Can continue DELBA flow ssn = next_recl =" | 758 | "Can continue DELBA flow ssn = next_recl =" |
755 | " %d", tid_data->next_reclaimed); | 759 | " %d", tid_data->next_reclaimed); |
756 | iwl_trans_tx_agg_disable(priv->trans, | 760 | iwl_trans_txq_disable(priv->trans, |
757 | tid_data->agg.txq_id); | 761 | tid_data->agg.txq_id); |
758 | iwlagn_dealloc_agg_txq(priv, tid_data->agg.txq_id); | 762 | iwlagn_dealloc_agg_txq(priv, tid_data->agg.txq_id); |
759 | tid_data->agg.state = IWL_AGG_OFF; | 763 | tid_data->agg.state = IWL_AGG_OFF; |
760 | ieee80211_stop_tx_ba_cb_irqsafe(vif, addr, tid); | 764 | ieee80211_stop_tx_ba_cb_irqsafe(vif, addr, tid); |
@@ -1136,6 +1140,7 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, | |||
1136 | struct sk_buff *skb; | 1140 | struct sk_buff *skb; |
1137 | struct iwl_rxon_context *ctx; | 1141 | struct iwl_rxon_context *ctx; |
1138 | bool is_agg = (txq_id >= IWLAGN_FIRST_AMPDU_QUEUE); | 1142 | bool is_agg = (txq_id >= IWLAGN_FIRST_AMPDU_QUEUE); |
1143 | bool is_offchannel_skb; | ||
1139 | 1144 | ||
1140 | tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >> | 1145 | tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >> |
1141 | IWLAGN_TX_RES_TID_POS; | 1146 | IWLAGN_TX_RES_TID_POS; |
@@ -1149,6 +1154,8 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, | |||
1149 | 1154 | ||
1150 | __skb_queue_head_init(&skbs); | 1155 | __skb_queue_head_init(&skbs); |
1151 | 1156 | ||
1157 | is_offchannel_skb = false; | ||
1158 | |||
1152 | if (tx_resp->frame_count == 1) { | 1159 | if (tx_resp->frame_count == 1) { |
1153 | u16 next_reclaimed = le16_to_cpu(tx_resp->seq_ctl); | 1160 | u16 next_reclaimed = le16_to_cpu(tx_resp->seq_ctl); |
1154 | next_reclaimed = SEQ_TO_SN(next_reclaimed + 0x10); | 1161 | next_reclaimed = SEQ_TO_SN(next_reclaimed + 0x10); |
@@ -1176,7 +1183,8 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, | |||
1176 | } | 1183 | } |
1177 | 1184 | ||
1178 | /*we can free until ssn % q.n_bd not inclusive */ | 1185 | /*we can free until ssn % q.n_bd not inclusive */ |
1179 | WARN_ON(iwl_reclaim(priv, sta_id, tid, txq_id, ssn, &skbs)); | 1186 | WARN_ON_ONCE(iwl_reclaim(priv, sta_id, tid, |
1187 | txq_id, ssn, &skbs)); | ||
1180 | iwlagn_check_ratid_empty(priv, sta_id, tid); | 1188 | iwlagn_check_ratid_empty(priv, sta_id, tid); |
1181 | freed = 0; | 1189 | freed = 0; |
1182 | 1190 | ||
@@ -1189,8 +1197,8 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, | |||
1189 | 1197 | ||
1190 | info = IEEE80211_SKB_CB(skb); | 1198 | info = IEEE80211_SKB_CB(skb); |
1191 | ctx = info->driver_data[0]; | 1199 | ctx = info->driver_data[0]; |
1192 | kmem_cache_free(iwl_tx_cmd_pool, | 1200 | iwl_trans_free_tx_cmd(priv->trans, |
1193 | (info->driver_data[1])); | 1201 | info->driver_data[1]); |
1194 | 1202 | ||
1195 | memset(&info->status, 0, sizeof(info->status)); | 1203 | memset(&info->status, 0, sizeof(info->status)); |
1196 | 1204 | ||
@@ -1225,10 +1233,19 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, | |||
1225 | if (!is_agg) | 1233 | if (!is_agg) |
1226 | iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1); | 1234 | iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1); |
1227 | 1235 | ||
1236 | is_offchannel_skb = | ||
1237 | (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN); | ||
1228 | freed++; | 1238 | freed++; |
1229 | } | 1239 | } |
1230 | 1240 | ||
1231 | WARN_ON(!is_agg && freed != 1); | 1241 | WARN_ON(!is_agg && freed != 1); |
1242 | |||
1243 | /* | ||
1244 | * An offchannel frame can be send only on the AUX queue, where | ||
1245 | * there is no aggregation (and reordering) so it only is single | ||
1246 | * skb is expected to be processed. | ||
1247 | */ | ||
1248 | WARN_ON(is_offchannel_skb && freed != 1); | ||
1232 | } | 1249 | } |
1233 | 1250 | ||
1234 | iwl_check_abort_status(priv, tx_resp->frame_count, status); | 1251 | iwl_check_abort_status(priv, tx_resp->frame_count, status); |
@@ -1239,6 +1256,9 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, | |||
1239 | ieee80211_tx_status(priv->hw, skb); | 1256 | ieee80211_tx_status(priv->hw, skb); |
1240 | } | 1257 | } |
1241 | 1258 | ||
1259 | if (is_offchannel_skb) | ||
1260 | iwl_scan_offchannel_skb_status(priv); | ||
1261 | |||
1242 | return 0; | 1262 | return 0; |
1243 | } | 1263 | } |
1244 | 1264 | ||
@@ -1341,7 +1361,7 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, | |||
1341 | WARN_ON_ONCE(1); | 1361 | WARN_ON_ONCE(1); |
1342 | 1362 | ||
1343 | info = IEEE80211_SKB_CB(skb); | 1363 | info = IEEE80211_SKB_CB(skb); |
1344 | kmem_cache_free(iwl_tx_cmd_pool, (info->driver_data[1])); | 1364 | iwl_trans_free_tx_cmd(priv->trans, info->driver_data[1]); |
1345 | 1365 | ||
1346 | if (freed == 1) { | 1366 | if (freed == 1) { |
1347 | /* this is the first skb we deliver in this batch */ | 1367 | /* this is the first skb we deliver in this batch */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/dvm/ucode.c index bc40dc68b0f..b3a314ba48c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-ucode.c +++ b/drivers/net/wireless/iwlwifi/dvm/ucode.c | |||
@@ -30,15 +30,16 @@ | |||
30 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
31 | #include <linux/init.h> | 31 | #include <linux/init.h> |
32 | 32 | ||
33 | #include "iwl-dev.h" | ||
34 | #include "iwl-io.h" | 33 | #include "iwl-io.h" |
35 | #include "iwl-agn-hw.h" | 34 | #include "iwl-agn-hw.h" |
36 | #include "iwl-agn.h" | ||
37 | #include "iwl-agn-calib.h" | ||
38 | #include "iwl-trans.h" | 35 | #include "iwl-trans.h" |
39 | #include "iwl-fh.h" | 36 | #include "iwl-fh.h" |
40 | #include "iwl-op-mode.h" | 37 | #include "iwl-op-mode.h" |
41 | 38 | ||
39 | #include "dev.h" | ||
40 | #include "agn.h" | ||
41 | #include "calib.h" | ||
42 | |||
42 | /****************************************************************************** | 43 | /****************************************************************************** |
43 | * | 44 | * |
44 | * uCode download functions | 45 | * uCode download functions |
@@ -60,8 +61,7 @@ iwl_get_ucode_image(struct iwl_priv *priv, enum iwl_ucode_type ucode_type) | |||
60 | static int iwl_set_Xtal_calib(struct iwl_priv *priv) | 61 | static int iwl_set_Xtal_calib(struct iwl_priv *priv) |
61 | { | 62 | { |
62 | struct iwl_calib_xtal_freq_cmd cmd; | 63 | struct iwl_calib_xtal_freq_cmd cmd; |
63 | __le16 *xtal_calib = | 64 | __le16 *xtal_calib = priv->eeprom_data->xtal_calib; |
64 | (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_XTAL); | ||
65 | 65 | ||
66 | iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD); | 66 | iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD); |
67 | cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]); | 67 | cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]); |
@@ -72,12 +72,10 @@ static int iwl_set_Xtal_calib(struct iwl_priv *priv) | |||
72 | static int iwl_set_temperature_offset_calib(struct iwl_priv *priv) | 72 | static int iwl_set_temperature_offset_calib(struct iwl_priv *priv) |
73 | { | 73 | { |
74 | struct iwl_calib_temperature_offset_cmd cmd; | 74 | struct iwl_calib_temperature_offset_cmd cmd; |
75 | __le16 *offset_calib = | ||
76 | (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_RAW_TEMPERATURE); | ||
77 | 75 | ||
78 | memset(&cmd, 0, sizeof(cmd)); | 76 | memset(&cmd, 0, sizeof(cmd)); |
79 | iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); | 77 | iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); |
80 | memcpy(&cmd.radio_sensor_offset, offset_calib, sizeof(*offset_calib)); | 78 | cmd.radio_sensor_offset = priv->eeprom_data->raw_temperature; |
81 | if (!(cmd.radio_sensor_offset)) | 79 | if (!(cmd.radio_sensor_offset)) |
82 | cmd.radio_sensor_offset = DEFAULT_RADIO_SENSOR_OFFSET; | 80 | cmd.radio_sensor_offset = DEFAULT_RADIO_SENSOR_OFFSET; |
83 | 81 | ||
@@ -89,27 +87,17 @@ static int iwl_set_temperature_offset_calib(struct iwl_priv *priv) | |||
89 | static int iwl_set_temperature_offset_calib_v2(struct iwl_priv *priv) | 87 | static int iwl_set_temperature_offset_calib_v2(struct iwl_priv *priv) |
90 | { | 88 | { |
91 | struct iwl_calib_temperature_offset_v2_cmd cmd; | 89 | struct iwl_calib_temperature_offset_v2_cmd cmd; |
92 | __le16 *offset_calib_high = (__le16 *)iwl_eeprom_query_addr(priv, | ||
93 | EEPROM_KELVIN_TEMPERATURE); | ||
94 | __le16 *offset_calib_low = | ||
95 | (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_RAW_TEMPERATURE); | ||
96 | struct iwl_eeprom_calib_hdr *hdr; | ||
97 | 90 | ||
98 | memset(&cmd, 0, sizeof(cmd)); | 91 | memset(&cmd, 0, sizeof(cmd)); |
99 | iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); | 92 | iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); |
100 | hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv, | 93 | cmd.radio_sensor_offset_high = priv->eeprom_data->kelvin_temperature; |
101 | EEPROM_CALIB_ALL); | 94 | cmd.radio_sensor_offset_low = priv->eeprom_data->raw_temperature; |
102 | memcpy(&cmd.radio_sensor_offset_high, offset_calib_high, | 95 | if (!cmd.radio_sensor_offset_low) { |
103 | sizeof(*offset_calib_high)); | ||
104 | memcpy(&cmd.radio_sensor_offset_low, offset_calib_low, | ||
105 | sizeof(*offset_calib_low)); | ||
106 | if (!(cmd.radio_sensor_offset_low)) { | ||
107 | IWL_DEBUG_CALIB(priv, "no info in EEPROM, use default\n"); | 96 | IWL_DEBUG_CALIB(priv, "no info in EEPROM, use default\n"); |
108 | cmd.radio_sensor_offset_low = DEFAULT_RADIO_SENSOR_OFFSET; | 97 | cmd.radio_sensor_offset_low = DEFAULT_RADIO_SENSOR_OFFSET; |
109 | cmd.radio_sensor_offset_high = DEFAULT_RADIO_SENSOR_OFFSET; | 98 | cmd.radio_sensor_offset_high = DEFAULT_RADIO_SENSOR_OFFSET; |
110 | } | 99 | } |
111 | memcpy(&cmd.burntVoltageRef, &hdr->voltage, | 100 | cmd.burntVoltageRef = priv->eeprom_data->calib_voltage; |
112 | sizeof(hdr->voltage)); | ||
113 | 101 | ||
114 | IWL_DEBUG_CALIB(priv, "Radio sensor offset high: %d\n", | 102 | IWL_DEBUG_CALIB(priv, "Radio sensor offset high: %d\n", |
115 | le16_to_cpu(cmd.radio_sensor_offset_high)); | 103 | le16_to_cpu(cmd.radio_sensor_offset_high)); |
@@ -177,7 +165,7 @@ int iwl_init_alive_start(struct iwl_priv *priv) | |||
177 | return 0; | 165 | return 0; |
178 | } | 166 | } |
179 | 167 | ||
180 | int iwl_send_wimax_coex(struct iwl_priv *priv) | 168 | static int iwl_send_wimax_coex(struct iwl_priv *priv) |
181 | { | 169 | { |
182 | struct iwl_wimax_coex_cmd coex_cmd; | 170 | struct iwl_wimax_coex_cmd coex_cmd; |
183 | 171 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h index a52818bbfe9..10e47938b63 100644 --- a/drivers/net/wireless/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/iwlwifi/iwl-config.h | |||
@@ -113,7 +113,7 @@ enum iwl_led_mode { | |||
113 | #define IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE 0 | 113 | #define IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE 0 |
114 | 114 | ||
115 | /* TX queue watchdog timeouts in mSecs */ | 115 | /* TX queue watchdog timeouts in mSecs */ |
116 | #define IWL_WATCHHDOG_DISABLED 0 | 116 | #define IWL_WATCHDOG_DISABLED 0 |
117 | #define IWL_DEF_WD_TIMEOUT 2000 | 117 | #define IWL_DEF_WD_TIMEOUT 2000 |
118 | #define IWL_LONG_WD_TIMEOUT 10000 | 118 | #define IWL_LONG_WD_TIMEOUT 10000 |
119 | #define IWL_MAX_WD_TIMEOUT 120000 | 119 | #define IWL_MAX_WD_TIMEOUT 120000 |
@@ -182,13 +182,34 @@ struct iwl_bt_params { | |||
182 | bool bt_sco_disable; | 182 | bool bt_sco_disable; |
183 | bool bt_session_2; | 183 | bool bt_session_2; |
184 | }; | 184 | }; |
185 | |||
185 | /* | 186 | /* |
186 | * @use_rts_for_aggregation: use rts/cts protection for HT traffic | 187 | * @use_rts_for_aggregation: use rts/cts protection for HT traffic |
188 | * @ht40_bands: bitmap of bands (using %IEEE80211_BAND_*) that support HT40 | ||
187 | */ | 189 | */ |
188 | struct iwl_ht_params { | 190 | struct iwl_ht_params { |
191 | enum ieee80211_smps_mode smps_mode; | ||
189 | const bool ht_greenfield_support; /* if used set to true */ | 192 | const bool ht_greenfield_support; /* if used set to true */ |
190 | bool use_rts_for_aggregation; | 193 | bool use_rts_for_aggregation; |
191 | enum ieee80211_smps_mode smps_mode; | 194 | u8 ht40_bands; |
195 | }; | ||
196 | |||
197 | /* | ||
198 | * information on how to parse the EEPROM | ||
199 | */ | ||
200 | #define EEPROM_REG_BAND_1_CHANNELS 0x08 | ||
201 | #define EEPROM_REG_BAND_2_CHANNELS 0x26 | ||
202 | #define EEPROM_REG_BAND_3_CHANNELS 0x42 | ||
203 | #define EEPROM_REG_BAND_4_CHANNELS 0x5C | ||
204 | #define EEPROM_REG_BAND_5_CHANNELS 0x74 | ||
205 | #define EEPROM_REG_BAND_24_HT40_CHANNELS 0x82 | ||
206 | #define EEPROM_REG_BAND_52_HT40_CHANNELS 0x92 | ||
207 | #define EEPROM_6000_REG_BAND_24_HT40_CHANNELS 0x80 | ||
208 | #define EEPROM_REGULATORY_BAND_NO_HT40 0 | ||
209 | |||
210 | struct iwl_eeprom_params { | ||
211 | const u8 regulatory_bands[7]; | ||
212 | bool enhanced_txpower; | ||
192 | }; | 213 | }; |
193 | 214 | ||
194 | /** | 215 | /** |
@@ -243,6 +264,7 @@ struct iwl_cfg { | |||
243 | /* params likely to change within a device family */ | 264 | /* params likely to change within a device family */ |
244 | const struct iwl_ht_params *ht_params; | 265 | const struct iwl_ht_params *ht_params; |
245 | const struct iwl_bt_params *bt_params; | 266 | const struct iwl_bt_params *bt_params; |
267 | const struct iwl_eeprom_params *eeprom_params; | ||
246 | const bool need_temp_offset_calib; /* if used set to true */ | 268 | const bool need_temp_offset_calib; /* if used set to true */ |
247 | const bool no_xtal_calib; | 269 | const bool no_xtal_calib; |
248 | enum iwl_led_mode led_mode; | 270 | enum iwl_led_mode led_mode; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index 59750543fce..34a5287dfc2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h | |||
@@ -97,13 +97,10 @@ | |||
97 | /* | 97 | /* |
98 | * Hardware revision info | 98 | * Hardware revision info |
99 | * Bit fields: | 99 | * Bit fields: |
100 | * 31-8: Reserved | 100 | * 31-16: Reserved |
101 | * 7-4: Type of device: see CSR_HW_REV_TYPE_xxx definitions | 101 | * 15-4: Type of device: see CSR_HW_REV_TYPE_xxx definitions |
102 | * 3-2: Revision step: 0 = A, 1 = B, 2 = C, 3 = D | 102 | * 3-2: Revision step: 0 = A, 1 = B, 2 = C, 3 = D |
103 | * 1-0: "Dash" (-) value, as in A-1, etc. | 103 | * 1-0: "Dash" (-) value, as in A-1, etc. |
104 | * | ||
105 | * NOTE: Revision step affects calculation of CCK txpower for 4965. | ||
106 | * NOTE: See also CSR_HW_REV_WA_REG (work-around for bug in 4965). | ||
107 | */ | 104 | */ |
108 | #define CSR_HW_REV (CSR_BASE+0x028) | 105 | #define CSR_HW_REV (CSR_BASE+0x028) |
109 | 106 | ||
@@ -155,9 +152,21 @@ | |||
155 | #define CSR_DBG_LINK_PWR_MGMT_REG (CSR_BASE+0x250) | 152 | #define CSR_DBG_LINK_PWR_MGMT_REG (CSR_BASE+0x250) |
156 | 153 | ||
157 | /* Bits for CSR_HW_IF_CONFIG_REG */ | 154 | /* Bits for CSR_HW_IF_CONFIG_REG */ |
158 | #define CSR_HW_IF_CONFIG_REG_MSK_BOARD_VER (0x00000C00) | 155 | #define CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH (0x00000003) |
159 | #define CSR_HW_IF_CONFIG_REG_BIT_MAC_SI (0x00000100) | 156 | #define CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP (0x0000000C) |
157 | #define CSR_HW_IF_CONFIG_REG_MSK_BOARD_VER (0x000000C0) | ||
158 | #define CSR_HW_IF_CONFIG_REG_BIT_MAC_SI (0x00000100) | ||
160 | #define CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI (0x00000200) | 159 | #define CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI (0x00000200) |
160 | #define CSR_HW_IF_CONFIG_REG_MSK_PHY_TYPE (0x00000C00) | ||
161 | #define CSR_HW_IF_CONFIG_REG_MSK_PHY_DASH (0x00003000) | ||
162 | #define CSR_HW_IF_CONFIG_REG_MSK_PHY_STEP (0x0000C000) | ||
163 | |||
164 | #define CSR_HW_IF_CONFIG_REG_POS_MAC_DASH (0) | ||
165 | #define CSR_HW_IF_CONFIG_REG_POS_MAC_STEP (2) | ||
166 | #define CSR_HW_IF_CONFIG_REG_POS_BOARD_VER (6) | ||
167 | #define CSR_HW_IF_CONFIG_REG_POS_PHY_TYPE (10) | ||
168 | #define CSR_HW_IF_CONFIG_REG_POS_PHY_DASH (12) | ||
169 | #define CSR_HW_IF_CONFIG_REG_POS_PHY_STEP (14) | ||
161 | 170 | ||
162 | #define CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A (0x00080000) | 171 | #define CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A (0x00080000) |
163 | #define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000) | 172 | #define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000) |
@@ -270,7 +279,10 @@ | |||
270 | 279 | ||
271 | 280 | ||
272 | /* HW REV */ | 281 | /* HW REV */ |
273 | #define CSR_HW_REV_TYPE_MSK (0x00001F0) | 282 | #define CSR_HW_REV_DASH(_val) (((_val) & 0x0000003) >> 0) |
283 | #define CSR_HW_REV_STEP(_val) (((_val) & 0x000000C) >> 2) | ||
284 | |||
285 | #define CSR_HW_REV_TYPE_MSK (0x000FFF0) | ||
274 | #define CSR_HW_REV_TYPE_5300 (0x0000020) | 286 | #define CSR_HW_REV_TYPE_5300 (0x0000020) |
275 | #define CSR_HW_REV_TYPE_5350 (0x0000030) | 287 | #define CSR_HW_REV_TYPE_5350 (0x0000030) |
276 | #define CSR_HW_REV_TYPE_5100 (0x0000050) | 288 | #define CSR_HW_REV_TYPE_5100 (0x0000050) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index f6bf91c8f77..42b20b0e83b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h | |||
@@ -45,6 +45,7 @@ void __iwl_crit(struct device *dev, const char *fmt, ...) __printf(2, 3); | |||
45 | 45 | ||
46 | /* No matter what is m (priv, bus, trans), this will work */ | 46 | /* No matter what is m (priv, bus, trans), this will work */ |
47 | #define IWL_ERR(m, f, a...) __iwl_err((m)->dev, false, false, f, ## a) | 47 | #define IWL_ERR(m, f, a...) __iwl_err((m)->dev, false, false, f, ## a) |
48 | #define IWL_ERR_DEV(d, f, a...) __iwl_err((d), false, false, f, ## a) | ||
48 | #define IWL_WARN(m, f, a...) __iwl_warn((m)->dev, f, ## a) | 49 | #define IWL_WARN(m, f, a...) __iwl_warn((m)->dev, f, ## a) |
49 | #define IWL_INFO(m, f, a...) __iwl_info((m)->dev, f, ## a) | 50 | #define IWL_INFO(m, f, a...) __iwl_info((m)->dev, f, ## a) |
50 | #define IWL_CRIT(m, f, a...) __iwl_crit((m)->dev, f, ## a) | 51 | #define IWL_CRIT(m, f, a...) __iwl_crit((m)->dev, f, ## a) |
@@ -69,6 +70,8 @@ do { \ | |||
69 | 70 | ||
70 | #define IWL_DEBUG(m, level, fmt, args...) \ | 71 | #define IWL_DEBUG(m, level, fmt, args...) \ |
71 | __iwl_dbg((m)->dev, level, false, __func__, fmt, ##args) | 72 | __iwl_dbg((m)->dev, level, false, __func__, fmt, ##args) |
73 | #define IWL_DEBUG_DEV(dev, level, fmt, args...) \ | ||
74 | __iwl_dbg((dev), level, false, __func__, fmt, ##args) | ||
72 | #define IWL_DEBUG_LIMIT(m, level, fmt, args...) \ | 75 | #define IWL_DEBUG_LIMIT(m, level, fmt, args...) \ |
73 | __iwl_dbg((m)->dev, level, true, __func__, fmt, ##args) | 76 | __iwl_dbg((m)->dev, level, true, __func__, fmt, ##args) |
74 | 77 | ||
@@ -153,7 +156,7 @@ do { \ | |||
153 | #define IWL_DEBUG_LED(p, f, a...) IWL_DEBUG(p, IWL_DL_LED, f, ## a) | 156 | #define IWL_DEBUG_LED(p, f, a...) IWL_DEBUG(p, IWL_DL_LED, f, ## a) |
154 | #define IWL_DEBUG_WEP(p, f, a...) IWL_DEBUG(p, IWL_DL_WEP, f, ## a) | 157 | #define IWL_DEBUG_WEP(p, f, a...) IWL_DEBUG(p, IWL_DL_WEP, f, ## a) |
155 | #define IWL_DEBUG_HC(p, f, a...) IWL_DEBUG(p, IWL_DL_HCMD, f, ## a) | 158 | #define IWL_DEBUG_HC(p, f, a...) IWL_DEBUG(p, IWL_DL_HCMD, f, ## a) |
156 | #define IWL_DEBUG_EEPROM(p, f, a...) IWL_DEBUG(p, IWL_DL_EEPROM, f, ## a) | 159 | #define IWL_DEBUG_EEPROM(d, f, a...) IWL_DEBUG_DEV(d, IWL_DL_EEPROM, f, ## a) |
157 | #define IWL_DEBUG_CALIB(p, f, a...) IWL_DEBUG(p, IWL_DL_CALIB, f, ## a) | 160 | #define IWL_DEBUG_CALIB(p, f, a...) IWL_DEBUG(p, IWL_DL_CALIB, f, ## a) |
158 | #define IWL_DEBUG_FW(p, f, a...) IWL_DEBUG(p, IWL_DL_FW, f, ## a) | 161 | #define IWL_DEBUG_FW(p, f, a...) IWL_DEBUG(p, IWL_DL_FW, f, ## a) |
159 | #define IWL_DEBUG_RF_KILL(p, f, a...) IWL_DEBUG(p, IWL_DL_RF_KILL, f, ## a) | 162 | #define IWL_DEBUG_RF_KILL(p, f, a...) IWL_DEBUG(p, IWL_DL_RF_KILL, f, ## a) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h index 06203d6a1d8..65364793021 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h | |||
@@ -28,6 +28,7 @@ | |||
28 | #define __IWLWIFI_DEVICE_TRACE | 28 | #define __IWLWIFI_DEVICE_TRACE |
29 | 29 | ||
30 | #include <linux/tracepoint.h> | 30 | #include <linux/tracepoint.h> |
31 | #include <linux/device.h> | ||
31 | 32 | ||
32 | 33 | ||
33 | #if !defined(CONFIG_IWLWIFI_DEVICE_TRACING) || defined(__CHECKER__) | 34 | #if !defined(CONFIG_IWLWIFI_DEVICE_TRACING) || defined(__CHECKER__) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index 49df0e9d5c5..a175997e782 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c | |||
@@ -131,6 +131,8 @@ struct iwl_drv { | |||
131 | #define DVM_OP_MODE 0 | 131 | #define DVM_OP_MODE 0 |
132 | #define MVM_OP_MODE 1 | 132 | #define MVM_OP_MODE 1 |
133 | 133 | ||
134 | /* Protects the table contents, i.e. the ops pointer & drv list */ | ||
135 | static struct mutex iwlwifi_opmode_table_mtx; | ||
134 | static struct iwlwifi_opmode_table { | 136 | static struct iwlwifi_opmode_table { |
135 | const char *name; /* name: iwldvm, iwlmvm, etc */ | 137 | const char *name; /* name: iwldvm, iwlmvm, etc */ |
136 | const struct iwl_op_mode_ops *ops; /* pointer to op_mode ops */ | 138 | const struct iwl_op_mode_ops *ops; /* pointer to op_mode ops */ |
@@ -776,6 +778,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
776 | const unsigned int api_min = drv->cfg->ucode_api_min; | 778 | const unsigned int api_min = drv->cfg->ucode_api_min; |
777 | u32 api_ver; | 779 | u32 api_ver; |
778 | int i; | 780 | int i; |
781 | bool load_module = false; | ||
779 | 782 | ||
780 | fw->ucode_capa.max_probe_length = 200; | 783 | fw->ucode_capa.max_probe_length = 200; |
781 | fw->ucode_capa.standard_phy_calibration_size = | 784 | fw->ucode_capa.standard_phy_calibration_size = |
@@ -898,6 +901,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
898 | /* We have our copies now, allow OS release its copies */ | 901 | /* We have our copies now, allow OS release its copies */ |
899 | release_firmware(ucode_raw); | 902 | release_firmware(ucode_raw); |
900 | 903 | ||
904 | mutex_lock(&iwlwifi_opmode_table_mtx); | ||
901 | op = &iwlwifi_opmode_table[DVM_OP_MODE]; | 905 | op = &iwlwifi_opmode_table[DVM_OP_MODE]; |
902 | 906 | ||
903 | /* add this device to the list of devices using this op_mode */ | 907 | /* add this device to the list of devices using this op_mode */ |
@@ -907,11 +911,14 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
907 | const struct iwl_op_mode_ops *ops = op->ops; | 911 | const struct iwl_op_mode_ops *ops = op->ops; |
908 | drv->op_mode = ops->start(drv->trans, drv->cfg, &drv->fw); | 912 | drv->op_mode = ops->start(drv->trans, drv->cfg, &drv->fw); |
909 | 913 | ||
910 | if (!drv->op_mode) | 914 | if (!drv->op_mode) { |
915 | mutex_unlock(&iwlwifi_opmode_table_mtx); | ||
911 | goto out_unbind; | 916 | goto out_unbind; |
917 | } | ||
912 | } else { | 918 | } else { |
913 | request_module_nowait("%s", op->name); | 919 | load_module = true; |
914 | } | 920 | } |
921 | mutex_unlock(&iwlwifi_opmode_table_mtx); | ||
915 | 922 | ||
916 | /* | 923 | /* |
917 | * Complete the firmware request last so that | 924 | * Complete the firmware request last so that |
@@ -919,6 +926,14 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
919 | * are doing the start() above. | 926 | * are doing the start() above. |
920 | */ | 927 | */ |
921 | complete(&drv->request_firmware_complete); | 928 | complete(&drv->request_firmware_complete); |
929 | |||
930 | /* | ||
931 | * Load the module last so we don't block anything | ||
932 | * else from proceeding if the module fails to load | ||
933 | * or hangs loading. | ||
934 | */ | ||
935 | if (load_module) | ||
936 | request_module("%s", op->name); | ||
922 | return; | 937 | return; |
923 | 938 | ||
924 | try_again: | 939 | try_again: |
@@ -952,6 +967,7 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans, | |||
952 | drv->cfg = cfg; | 967 | drv->cfg = cfg; |
953 | 968 | ||
954 | init_completion(&drv->request_firmware_complete); | 969 | init_completion(&drv->request_firmware_complete); |
970 | INIT_LIST_HEAD(&drv->list); | ||
955 | 971 | ||
956 | ret = iwl_request_firmware(drv, true); | 972 | ret = iwl_request_firmware(drv, true); |
957 | 973 | ||
@@ -974,6 +990,16 @@ void iwl_drv_stop(struct iwl_drv *drv) | |||
974 | 990 | ||
975 | iwl_dealloc_ucode(drv); | 991 | iwl_dealloc_ucode(drv); |
976 | 992 | ||
993 | mutex_lock(&iwlwifi_opmode_table_mtx); | ||
994 | /* | ||
995 | * List is empty (this item wasn't added) | ||
996 | * when firmware loading failed -- in that | ||
997 | * case we can't remove it from any list. | ||
998 | */ | ||
999 | if (!list_empty(&drv->list)) | ||
1000 | list_del(&drv->list); | ||
1001 | mutex_unlock(&iwlwifi_opmode_table_mtx); | ||
1002 | |||
977 | kfree(drv); | 1003 | kfree(drv); |
978 | } | 1004 | } |
979 | 1005 | ||
@@ -996,6 +1022,7 @@ int iwl_opmode_register(const char *name, const struct iwl_op_mode_ops *ops) | |||
996 | int i; | 1022 | int i; |
997 | struct iwl_drv *drv; | 1023 | struct iwl_drv *drv; |
998 | 1024 | ||
1025 | mutex_lock(&iwlwifi_opmode_table_mtx); | ||
999 | for (i = 0; i < ARRAY_SIZE(iwlwifi_opmode_table); i++) { | 1026 | for (i = 0; i < ARRAY_SIZE(iwlwifi_opmode_table); i++) { |
1000 | if (strcmp(iwlwifi_opmode_table[i].name, name)) | 1027 | if (strcmp(iwlwifi_opmode_table[i].name, name)) |
1001 | continue; | 1028 | continue; |
@@ -1003,8 +1030,10 @@ int iwl_opmode_register(const char *name, const struct iwl_op_mode_ops *ops) | |||
1003 | list_for_each_entry(drv, &iwlwifi_opmode_table[i].drv, list) | 1030 | list_for_each_entry(drv, &iwlwifi_opmode_table[i].drv, list) |
1004 | drv->op_mode = ops->start(drv->trans, drv->cfg, | 1031 | drv->op_mode = ops->start(drv->trans, drv->cfg, |
1005 | &drv->fw); | 1032 | &drv->fw); |
1033 | mutex_unlock(&iwlwifi_opmode_table_mtx); | ||
1006 | return 0; | 1034 | return 0; |
1007 | } | 1035 | } |
1036 | mutex_unlock(&iwlwifi_opmode_table_mtx); | ||
1008 | return -EIO; | 1037 | return -EIO; |
1009 | } | 1038 | } |
1010 | EXPORT_SYMBOL_GPL(iwl_opmode_register); | 1039 | EXPORT_SYMBOL_GPL(iwl_opmode_register); |
@@ -1014,6 +1043,7 @@ void iwl_opmode_deregister(const char *name) | |||
1014 | int i; | 1043 | int i; |
1015 | struct iwl_drv *drv; | 1044 | struct iwl_drv *drv; |
1016 | 1045 | ||
1046 | mutex_lock(&iwlwifi_opmode_table_mtx); | ||
1017 | for (i = 0; i < ARRAY_SIZE(iwlwifi_opmode_table); i++) { | 1047 | for (i = 0; i < ARRAY_SIZE(iwlwifi_opmode_table); i++) { |
1018 | if (strcmp(iwlwifi_opmode_table[i].name, name)) | 1048 | if (strcmp(iwlwifi_opmode_table[i].name, name)) |
1019 | continue; | 1049 | continue; |
@@ -1026,8 +1056,10 @@ void iwl_opmode_deregister(const char *name) | |||
1026 | drv->op_mode = NULL; | 1056 | drv->op_mode = NULL; |
1027 | } | 1057 | } |
1028 | } | 1058 | } |
1059 | mutex_unlock(&iwlwifi_opmode_table_mtx); | ||
1029 | return; | 1060 | return; |
1030 | } | 1061 | } |
1062 | mutex_unlock(&iwlwifi_opmode_table_mtx); | ||
1031 | } | 1063 | } |
1032 | EXPORT_SYMBOL_GPL(iwl_opmode_deregister); | 1064 | EXPORT_SYMBOL_GPL(iwl_opmode_deregister); |
1033 | 1065 | ||
@@ -1035,6 +1067,8 @@ static int __init iwl_drv_init(void) | |||
1035 | { | 1067 | { |
1036 | int i; | 1068 | int i; |
1037 | 1069 | ||
1070 | mutex_init(&iwlwifi_opmode_table_mtx); | ||
1071 | |||
1038 | for (i = 0; i < ARRAY_SIZE(iwlwifi_opmode_table); i++) | 1072 | for (i = 0; i < ARRAY_SIZE(iwlwifi_opmode_table); i++) |
1039 | INIT_LIST_HEAD(&iwlwifi_opmode_table[i].drv); | 1073 | INIT_LIST_HEAD(&iwlwifi_opmode_table[i].drv); |
1040 | 1074 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c new file mode 100644 index 00000000000..f10170fe879 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c | |||
@@ -0,0 +1,903 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | *****************************************************************************/ | ||
62 | #include <linux/types.h> | ||
63 | #include <linux/slab.h> | ||
64 | #include <linux/export.h> | ||
65 | #include "iwl-modparams.h" | ||
66 | #include "iwl-eeprom-parse.h" | ||
67 | |||
68 | /* EEPROM offset definitions */ | ||
69 | |||
70 | /* indirect access definitions */ | ||
71 | #define ADDRESS_MSK 0x0000FFFF | ||
72 | #define INDIRECT_TYPE_MSK 0x000F0000 | ||
73 | #define INDIRECT_HOST 0x00010000 | ||
74 | #define INDIRECT_GENERAL 0x00020000 | ||
75 | #define INDIRECT_REGULATORY 0x00030000 | ||
76 | #define INDIRECT_CALIBRATION 0x00040000 | ||
77 | #define INDIRECT_PROCESS_ADJST 0x00050000 | ||
78 | #define INDIRECT_OTHERS 0x00060000 | ||
79 | #define INDIRECT_TXP_LIMIT 0x00070000 | ||
80 | #define INDIRECT_TXP_LIMIT_SIZE 0x00080000 | ||
81 | #define INDIRECT_ADDRESS 0x00100000 | ||
82 | |||
83 | /* corresponding link offsets in EEPROM */ | ||
84 | #define EEPROM_LINK_HOST (2*0x64) | ||
85 | #define EEPROM_LINK_GENERAL (2*0x65) | ||
86 | #define EEPROM_LINK_REGULATORY (2*0x66) | ||
87 | #define EEPROM_LINK_CALIBRATION (2*0x67) | ||
88 | #define EEPROM_LINK_PROCESS_ADJST (2*0x68) | ||
89 | #define EEPROM_LINK_OTHERS (2*0x69) | ||
90 | #define EEPROM_LINK_TXP_LIMIT (2*0x6a) | ||
91 | #define EEPROM_LINK_TXP_LIMIT_SIZE (2*0x6b) | ||
92 | |||
93 | /* General */ | ||
94 | #define EEPROM_DEVICE_ID (2*0x08) /* 2 bytes */ | ||
95 | #define EEPROM_SUBSYSTEM_ID (2*0x0A) /* 2 bytes */ | ||
96 | #define EEPROM_MAC_ADDRESS (2*0x15) /* 6 bytes */ | ||
97 | #define EEPROM_BOARD_REVISION (2*0x35) /* 2 bytes */ | ||
98 | #define EEPROM_BOARD_PBA_NUMBER (2*0x3B+1) /* 9 bytes */ | ||
99 | #define EEPROM_VERSION (2*0x44) /* 2 bytes */ | ||
100 | #define EEPROM_SKU_CAP (2*0x45) /* 2 bytes */ | ||
101 | #define EEPROM_OEM_MODE (2*0x46) /* 2 bytes */ | ||
102 | #define EEPROM_RADIO_CONFIG (2*0x48) /* 2 bytes */ | ||
103 | #define EEPROM_NUM_MAC_ADDRESS (2*0x4C) /* 2 bytes */ | ||
104 | |||
105 | /* calibration */ | ||
106 | struct iwl_eeprom_calib_hdr { | ||
107 | u8 version; | ||
108 | u8 pa_type; | ||
109 | __le16 voltage; | ||
110 | } __packed; | ||
111 | |||
112 | #define EEPROM_CALIB_ALL (INDIRECT_ADDRESS | INDIRECT_CALIBRATION) | ||
113 | #define EEPROM_XTAL ((2*0x128) | EEPROM_CALIB_ALL) | ||
114 | |||
115 | /* temperature */ | ||
116 | #define EEPROM_KELVIN_TEMPERATURE ((2*0x12A) | EEPROM_CALIB_ALL) | ||
117 | #define EEPROM_RAW_TEMPERATURE ((2*0x12B) | EEPROM_CALIB_ALL) | ||
118 | |||
119 | /* | ||
120 | * EEPROM bands | ||
121 | * These are the channel numbers from each band in the order | ||
122 | * that they are stored in the EEPROM band information. Note | ||
123 | * that EEPROM bands aren't the same as mac80211 bands, and | ||
124 | * there are even special "ht40 bands" in the EEPROM. | ||
125 | */ | ||
126 | static const u8 iwl_eeprom_band_1[14] = { /* 2.4 GHz */ | ||
127 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 | ||
128 | }; | ||
129 | |||
130 | static const u8 iwl_eeprom_band_2[] = { /* 4915-5080MHz */ | ||
131 | 183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16 | ||
132 | }; | ||
133 | |||
134 | static const u8 iwl_eeprom_band_3[] = { /* 5170-5320MHz */ | ||
135 | 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64 | ||
136 | }; | ||
137 | |||
138 | static const u8 iwl_eeprom_band_4[] = { /* 5500-5700MHz */ | ||
139 | 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 | ||
140 | }; | ||
141 | |||
142 | static const u8 iwl_eeprom_band_5[] = { /* 5725-5825MHz */ | ||
143 | 145, 149, 153, 157, 161, 165 | ||
144 | }; | ||
145 | |||
146 | static const u8 iwl_eeprom_band_6[] = { /* 2.4 ht40 channel */ | ||
147 | 1, 2, 3, 4, 5, 6, 7 | ||
148 | }; | ||
149 | |||
150 | static const u8 iwl_eeprom_band_7[] = { /* 5.2 ht40 channel */ | ||
151 | 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157 | ||
152 | }; | ||
153 | |||
154 | #define IWL_NUM_CHANNELS (ARRAY_SIZE(iwl_eeprom_band_1) + \ | ||
155 | ARRAY_SIZE(iwl_eeprom_band_2) + \ | ||
156 | ARRAY_SIZE(iwl_eeprom_band_3) + \ | ||
157 | ARRAY_SIZE(iwl_eeprom_band_4) + \ | ||
158 | ARRAY_SIZE(iwl_eeprom_band_5)) | ||
159 | |||
160 | /* rate data (static) */ | ||
161 | static struct ieee80211_rate iwl_cfg80211_rates[] = { | ||
162 | { .bitrate = 1 * 10, .hw_value = 0, .hw_value_short = 0, }, | ||
163 | { .bitrate = 2 * 10, .hw_value = 1, .hw_value_short = 1, | ||
164 | .flags = IEEE80211_RATE_SHORT_PREAMBLE, }, | ||
165 | { .bitrate = 5.5 * 10, .hw_value = 2, .hw_value_short = 2, | ||
166 | .flags = IEEE80211_RATE_SHORT_PREAMBLE, }, | ||
167 | { .bitrate = 11 * 10, .hw_value = 3, .hw_value_short = 3, | ||
168 | .flags = IEEE80211_RATE_SHORT_PREAMBLE, }, | ||
169 | { .bitrate = 6 * 10, .hw_value = 4, .hw_value_short = 4, }, | ||
170 | { .bitrate = 9 * 10, .hw_value = 5, .hw_value_short = 5, }, | ||
171 | { .bitrate = 12 * 10, .hw_value = 6, .hw_value_short = 6, }, | ||
172 | { .bitrate = 18 * 10, .hw_value = 7, .hw_value_short = 7, }, | ||
173 | { .bitrate = 24 * 10, .hw_value = 8, .hw_value_short = 8, }, | ||
174 | { .bitrate = 36 * 10, .hw_value = 9, .hw_value_short = 9, }, | ||
175 | { .bitrate = 48 * 10, .hw_value = 10, .hw_value_short = 10, }, | ||
176 | { .bitrate = 54 * 10, .hw_value = 11, .hw_value_short = 11, }, | ||
177 | }; | ||
178 | #define RATES_24_OFFS 0 | ||
179 | #define N_RATES_24 ARRAY_SIZE(iwl_cfg80211_rates) | ||
180 | #define RATES_52_OFFS 4 | ||
181 | #define N_RATES_52 (N_RATES_24 - RATES_52_OFFS) | ||
182 | |||
183 | /* EEPROM reading functions */ | ||
184 | |||
185 | static u16 iwl_eeprom_query16(const u8 *eeprom, size_t eeprom_size, int offset) | ||
186 | { | ||
187 | if (WARN_ON(offset + sizeof(u16) > eeprom_size)) | ||
188 | return 0; | ||
189 | return le16_to_cpup((__le16 *)(eeprom + offset)); | ||
190 | } | ||
191 | |||
192 | static u32 eeprom_indirect_address(const u8 *eeprom, size_t eeprom_size, | ||
193 | u32 address) | ||
194 | { | ||
195 | u16 offset = 0; | ||
196 | |||
197 | if ((address & INDIRECT_ADDRESS) == 0) | ||
198 | return address; | ||
199 | |||
200 | switch (address & INDIRECT_TYPE_MSK) { | ||
201 | case INDIRECT_HOST: | ||
202 | offset = iwl_eeprom_query16(eeprom, eeprom_size, | ||
203 | EEPROM_LINK_HOST); | ||
204 | break; | ||
205 | case INDIRECT_GENERAL: | ||
206 | offset = iwl_eeprom_query16(eeprom, eeprom_size, | ||
207 | EEPROM_LINK_GENERAL); | ||
208 | break; | ||
209 | case INDIRECT_REGULATORY: | ||
210 | offset = iwl_eeprom_query16(eeprom, eeprom_size, | ||
211 | EEPROM_LINK_REGULATORY); | ||
212 | break; | ||
213 | case INDIRECT_TXP_LIMIT: | ||
214 | offset = iwl_eeprom_query16(eeprom, eeprom_size, | ||
215 | EEPROM_LINK_TXP_LIMIT); | ||
216 | break; | ||
217 | case INDIRECT_TXP_LIMIT_SIZE: | ||
218 | offset = iwl_eeprom_query16(eeprom, eeprom_size, | ||
219 | EEPROM_LINK_TXP_LIMIT_SIZE); | ||
220 | break; | ||
221 | case INDIRECT_CALIBRATION: | ||
222 | offset = iwl_eeprom_query16(eeprom, eeprom_size, | ||
223 | EEPROM_LINK_CALIBRATION); | ||
224 | break; | ||
225 | case INDIRECT_PROCESS_ADJST: | ||
226 | offset = iwl_eeprom_query16(eeprom, eeprom_size, | ||
227 | EEPROM_LINK_PROCESS_ADJST); | ||
228 | break; | ||
229 | case INDIRECT_OTHERS: | ||
230 | offset = iwl_eeprom_query16(eeprom, eeprom_size, | ||
231 | EEPROM_LINK_OTHERS); | ||
232 | break; | ||
233 | default: | ||
234 | WARN_ON(1); | ||
235 | break; | ||
236 | } | ||
237 | |||
238 | /* translate the offset from words to byte */ | ||
239 | return (address & ADDRESS_MSK) + (offset << 1); | ||
240 | } | ||
241 | |||
242 | static const u8 *iwl_eeprom_query_addr(const u8 *eeprom, size_t eeprom_size, | ||
243 | u32 offset) | ||
244 | { | ||
245 | u32 address = eeprom_indirect_address(eeprom, eeprom_size, offset); | ||
246 | |||
247 | if (WARN_ON(address >= eeprom_size)) | ||
248 | return NULL; | ||
249 | |||
250 | return &eeprom[address]; | ||
251 | } | ||
252 | |||
253 | static int iwl_eeprom_read_calib(const u8 *eeprom, size_t eeprom_size, | ||
254 | struct iwl_eeprom_data *data) | ||
255 | { | ||
256 | struct iwl_eeprom_calib_hdr *hdr; | ||
257 | |||
258 | hdr = (void *)iwl_eeprom_query_addr(eeprom, eeprom_size, | ||
259 | EEPROM_CALIB_ALL); | ||
260 | if (!hdr) | ||
261 | return -ENODATA; | ||
262 | data->calib_version = hdr->version; | ||
263 | data->calib_voltage = hdr->voltage; | ||
264 | |||
265 | return 0; | ||
266 | } | ||
267 | |||
268 | /** | ||
269 | * enum iwl_eeprom_channel_flags - channel flags in EEPROM | ||
270 | * @EEPROM_CHANNEL_VALID: channel is usable for this SKU/geo | ||
271 | * @EEPROM_CHANNEL_IBSS: usable as an IBSS channel | ||
272 | * @EEPROM_CHANNEL_ACTIVE: active scanning allowed | ||
273 | * @EEPROM_CHANNEL_RADAR: radar detection required | ||
274 | * @EEPROM_CHANNEL_WIDE: 20 MHz channel okay (?) | ||
275 | * @EEPROM_CHANNEL_DFS: dynamic freq selection candidate | ||
276 | */ | ||
277 | enum iwl_eeprom_channel_flags { | ||
278 | EEPROM_CHANNEL_VALID = BIT(0), | ||
279 | EEPROM_CHANNEL_IBSS = BIT(1), | ||
280 | EEPROM_CHANNEL_ACTIVE = BIT(3), | ||
281 | EEPROM_CHANNEL_RADAR = BIT(4), | ||
282 | EEPROM_CHANNEL_WIDE = BIT(5), | ||
283 | EEPROM_CHANNEL_DFS = BIT(7), | ||
284 | }; | ||
285 | |||
286 | /** | ||
287 | * struct iwl_eeprom_channel - EEPROM channel data | ||
288 | * @flags: %EEPROM_CHANNEL_* flags | ||
289 | * @max_power_avg: max power (in dBm) on this channel, at most 31 dBm | ||
290 | */ | ||
291 | struct iwl_eeprom_channel { | ||
292 | u8 flags; | ||
293 | s8 max_power_avg; | ||
294 | } __packed; | ||
295 | |||
296 | |||
297 | enum iwl_eeprom_enhanced_txpwr_flags { | ||
298 | IWL_EEPROM_ENH_TXP_FL_VALID = BIT(0), | ||
299 | IWL_EEPROM_ENH_TXP_FL_BAND_52G = BIT(1), | ||
300 | IWL_EEPROM_ENH_TXP_FL_OFDM = BIT(2), | ||
301 | IWL_EEPROM_ENH_TXP_FL_40MHZ = BIT(3), | ||
302 | IWL_EEPROM_ENH_TXP_FL_HT_AP = BIT(4), | ||
303 | IWL_EEPROM_ENH_TXP_FL_RES1 = BIT(5), | ||
304 | IWL_EEPROM_ENH_TXP_FL_RES2 = BIT(6), | ||
305 | IWL_EEPROM_ENH_TXP_FL_COMMON_TYPE = BIT(7), | ||
306 | }; | ||
307 | |||
308 | /** | ||
309 | * iwl_eeprom_enhanced_txpwr structure | ||
310 | * @flags: entry flags | ||
311 | * @channel: channel number | ||
312 | * @chain_a_max_pwr: chain a max power in 1/2 dBm | ||
313 | * @chain_b_max_pwr: chain b max power in 1/2 dBm | ||
314 | * @chain_c_max_pwr: chain c max power in 1/2 dBm | ||
315 | * @delta_20_in_40: 20-in-40 deltas (hi/lo) | ||
316 | * @mimo2_max_pwr: mimo2 max power in 1/2 dBm | ||
317 | * @mimo3_max_pwr: mimo3 max power in 1/2 dBm | ||
318 | * | ||
319 | * This structure presents the enhanced regulatory tx power limit layout | ||
320 | * in an EEPROM image. | ||
321 | */ | ||
322 | struct iwl_eeprom_enhanced_txpwr { | ||
323 | u8 flags; | ||
324 | u8 channel; | ||
325 | s8 chain_a_max; | ||
326 | s8 chain_b_max; | ||
327 | s8 chain_c_max; | ||
328 | u8 delta_20_in_40; | ||
329 | s8 mimo2_max; | ||
330 | s8 mimo3_max; | ||
331 | } __packed; | ||
332 | |||
333 | static s8 iwl_get_max_txpwr_half_dbm(const struct iwl_eeprom_data *data, | ||
334 | struct iwl_eeprom_enhanced_txpwr *txp) | ||
335 | { | ||
336 | s8 result = 0; /* (.5 dBm) */ | ||
337 | |||
338 | /* Take the highest tx power from any valid chains */ | ||
339 | if (data->valid_tx_ant & ANT_A && txp->chain_a_max > result) | ||
340 | result = txp->chain_a_max; | ||
341 | |||
342 | if (data->valid_tx_ant & ANT_B && txp->chain_b_max > result) | ||
343 | result = txp->chain_b_max; | ||
344 | |||
345 | if (data->valid_tx_ant & ANT_C && txp->chain_c_max > result) | ||
346 | result = txp->chain_c_max; | ||
347 | |||
348 | if ((data->valid_tx_ant == ANT_AB || | ||
349 | data->valid_tx_ant == ANT_BC || | ||
350 | data->valid_tx_ant == ANT_AC) && txp->mimo2_max > result) | ||
351 | result = txp->mimo2_max; | ||
352 | |||
353 | if (data->valid_tx_ant == ANT_ABC && txp->mimo3_max > result) | ||
354 | result = txp->mimo3_max; | ||
355 | |||
356 | return result; | ||
357 | } | ||
358 | |||
359 | #define EEPROM_TXP_OFFS (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT) | ||
360 | #define EEPROM_TXP_ENTRY_LEN sizeof(struct iwl_eeprom_enhanced_txpwr) | ||
361 | #define EEPROM_TXP_SZ_OFFS (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT_SIZE) | ||
362 | |||
363 | #define TXP_CHECK_AND_PRINT(x) \ | ||
364 | ((txp->flags & IWL_EEPROM_ENH_TXP_FL_##x) ? # x " " : "") | ||
365 | |||
366 | static void | ||
367 | iwl_eeprom_enh_txp_read_element(struct iwl_eeprom_data *data, | ||
368 | struct iwl_eeprom_enhanced_txpwr *txp, | ||
369 | int n_channels, s8 max_txpower_avg) | ||
370 | { | ||
371 | int ch_idx; | ||
372 | enum ieee80211_band band; | ||
373 | |||
374 | band = txp->flags & IWL_EEPROM_ENH_TXP_FL_BAND_52G ? | ||
375 | IEEE80211_BAND_5GHZ : IEEE80211_BAND_2GHZ; | ||
376 | |||
377 | for (ch_idx = 0; ch_idx < n_channels; ch_idx++) { | ||
378 | struct ieee80211_channel *chan = &data->channels[ch_idx]; | ||
379 | |||
380 | /* update matching channel or from common data only */ | ||
381 | if (txp->channel != 0 && chan->hw_value != txp->channel) | ||
382 | continue; | ||
383 | |||
384 | /* update matching band only */ | ||
385 | if (band != chan->band) | ||
386 | continue; | ||
387 | |||
388 | if (chan->max_power < max_txpower_avg && | ||
389 | !(txp->flags & IWL_EEPROM_ENH_TXP_FL_40MHZ)) | ||
390 | chan->max_power = max_txpower_avg; | ||
391 | } | ||
392 | } | ||
393 | |||
394 | static void iwl_eeprom_enhanced_txpower(struct device *dev, | ||
395 | struct iwl_eeprom_data *data, | ||
396 | const u8 *eeprom, size_t eeprom_size, | ||
397 | int n_channels) | ||
398 | { | ||
399 | struct iwl_eeprom_enhanced_txpwr *txp_array, *txp; | ||
400 | int idx, entries; | ||
401 | __le16 *txp_len; | ||
402 | s8 max_txp_avg_halfdbm; | ||
403 | |||
404 | BUILD_BUG_ON(sizeof(struct iwl_eeprom_enhanced_txpwr) != 8); | ||
405 | |||
406 | /* the length is in 16-bit words, but we want entries */ | ||
407 | txp_len = (__le16 *)iwl_eeprom_query_addr(eeprom, eeprom_size, | ||
408 | EEPROM_TXP_SZ_OFFS); | ||
409 | entries = le16_to_cpup(txp_len) * 2 / EEPROM_TXP_ENTRY_LEN; | ||
410 | |||
411 | txp_array = (void *)iwl_eeprom_query_addr(eeprom, eeprom_size, | ||
412 | EEPROM_TXP_OFFS); | ||
413 | |||
414 | for (idx = 0; idx < entries; idx++) { | ||
415 | txp = &txp_array[idx]; | ||
416 | /* skip invalid entries */ | ||
417 | if (!(txp->flags & IWL_EEPROM_ENH_TXP_FL_VALID)) | ||
418 | continue; | ||
419 | |||
420 | IWL_DEBUG_EEPROM(dev, "%s %d:\t %s%s%s%s%s%s%s%s (0x%02x)\n", | ||
421 | (txp->channel && (txp->flags & | ||
422 | IWL_EEPROM_ENH_TXP_FL_COMMON_TYPE)) ? | ||
423 | "Common " : (txp->channel) ? | ||
424 | "Channel" : "Common", | ||
425 | (txp->channel), | ||
426 | TXP_CHECK_AND_PRINT(VALID), | ||
427 | TXP_CHECK_AND_PRINT(BAND_52G), | ||
428 | TXP_CHECK_AND_PRINT(OFDM), | ||
429 | TXP_CHECK_AND_PRINT(40MHZ), | ||
430 | TXP_CHECK_AND_PRINT(HT_AP), | ||
431 | TXP_CHECK_AND_PRINT(RES1), | ||
432 | TXP_CHECK_AND_PRINT(RES2), | ||
433 | TXP_CHECK_AND_PRINT(COMMON_TYPE), | ||
434 | txp->flags); | ||
435 | IWL_DEBUG_EEPROM(dev, | ||
436 | "\t\t chain_A: 0x%02x chain_B: 0X%02x chain_C: 0X%02x\n", | ||
437 | txp->chain_a_max, txp->chain_b_max, | ||
438 | txp->chain_c_max); | ||
439 | IWL_DEBUG_EEPROM(dev, | ||
440 | "\t\t MIMO2: 0x%02x MIMO3: 0x%02x High 20_on_40: 0x%02x Low 20_on_40: 0x%02x\n", | ||
441 | txp->mimo2_max, txp->mimo3_max, | ||
442 | ((txp->delta_20_in_40 & 0xf0) >> 4), | ||
443 | (txp->delta_20_in_40 & 0x0f)); | ||
444 | |||
445 | max_txp_avg_halfdbm = iwl_get_max_txpwr_half_dbm(data, txp); | ||
446 | |||
447 | iwl_eeprom_enh_txp_read_element(data, txp, n_channels, | ||
448 | DIV_ROUND_UP(max_txp_avg_halfdbm, 2)); | ||
449 | |||
450 | if (max_txp_avg_halfdbm > data->max_tx_pwr_half_dbm) | ||
451 | data->max_tx_pwr_half_dbm = max_txp_avg_halfdbm; | ||
452 | } | ||
453 | } | ||
454 | |||
455 | static void iwl_init_band_reference(const struct iwl_cfg *cfg, | ||
456 | const u8 *eeprom, size_t eeprom_size, | ||
457 | int eeprom_band, int *eeprom_ch_count, | ||
458 | const struct iwl_eeprom_channel **ch_info, | ||
459 | const u8 **eeprom_ch_array) | ||
460 | { | ||
461 | u32 offset = cfg->eeprom_params->regulatory_bands[eeprom_band - 1]; | ||
462 | |||
463 | offset |= INDIRECT_ADDRESS | INDIRECT_REGULATORY; | ||
464 | |||
465 | *ch_info = (void *)iwl_eeprom_query_addr(eeprom, eeprom_size, offset); | ||
466 | |||
467 | switch (eeprom_band) { | ||
468 | case 1: /* 2.4GHz band */ | ||
469 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_1); | ||
470 | *eeprom_ch_array = iwl_eeprom_band_1; | ||
471 | break; | ||
472 | case 2: /* 4.9GHz band */ | ||
473 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_2); | ||
474 | *eeprom_ch_array = iwl_eeprom_band_2; | ||
475 | break; | ||
476 | case 3: /* 5.2GHz band */ | ||
477 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_3); | ||
478 | *eeprom_ch_array = iwl_eeprom_band_3; | ||
479 | break; | ||
480 | case 4: /* 5.5GHz band */ | ||
481 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_4); | ||
482 | *eeprom_ch_array = iwl_eeprom_band_4; | ||
483 | break; | ||
484 | case 5: /* 5.7GHz band */ | ||
485 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_5); | ||
486 | *eeprom_ch_array = iwl_eeprom_band_5; | ||
487 | break; | ||
488 | case 6: /* 2.4GHz ht40 channels */ | ||
489 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_6); | ||
490 | *eeprom_ch_array = iwl_eeprom_band_6; | ||
491 | break; | ||
492 | case 7: /* 5 GHz ht40 channels */ | ||
493 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_7); | ||
494 | *eeprom_ch_array = iwl_eeprom_band_7; | ||
495 | break; | ||
496 | default: | ||
497 | *eeprom_ch_count = 0; | ||
498 | *eeprom_ch_array = NULL; | ||
499 | WARN_ON(1); | ||
500 | } | ||
501 | } | ||
502 | |||
503 | #define CHECK_AND_PRINT(x) \ | ||
504 | ((eeprom_ch->flags & EEPROM_CHANNEL_##x) ? # x " " : "") | ||
505 | |||
506 | static void iwl_mod_ht40_chan_info(struct device *dev, | ||
507 | struct iwl_eeprom_data *data, int n_channels, | ||
508 | enum ieee80211_band band, u16 channel, | ||
509 | const struct iwl_eeprom_channel *eeprom_ch, | ||
510 | u8 clear_ht40_extension_channel) | ||
511 | { | ||
512 | struct ieee80211_channel *chan = NULL; | ||
513 | int i; | ||
514 | |||
515 | for (i = 0; i < n_channels; i++) { | ||
516 | if (data->channels[i].band != band) | ||
517 | continue; | ||
518 | if (data->channels[i].hw_value != channel) | ||
519 | continue; | ||
520 | chan = &data->channels[i]; | ||
521 | break; | ||
522 | } | ||
523 | |||
524 | if (!chan) | ||
525 | return; | ||
526 | |||
527 | IWL_DEBUG_EEPROM(dev, | ||
528 | "HT40 Ch. %d [%sGHz] %s%s%s%s%s(0x%02x %ddBm): Ad-Hoc %ssupported\n", | ||
529 | channel, | ||
530 | band == IEEE80211_BAND_5GHZ ? "5.2" : "2.4", | ||
531 | CHECK_AND_PRINT(IBSS), | ||
532 | CHECK_AND_PRINT(ACTIVE), | ||
533 | CHECK_AND_PRINT(RADAR), | ||
534 | CHECK_AND_PRINT(WIDE), | ||
535 | CHECK_AND_PRINT(DFS), | ||
536 | eeprom_ch->flags, | ||
537 | eeprom_ch->max_power_avg, | ||
538 | ((eeprom_ch->flags & EEPROM_CHANNEL_IBSS) && | ||
539 | !(eeprom_ch->flags & EEPROM_CHANNEL_RADAR)) ? "" | ||
540 | : "not "); | ||
541 | |||
542 | if (eeprom_ch->flags & EEPROM_CHANNEL_VALID) | ||
543 | chan->flags &= ~clear_ht40_extension_channel; | ||
544 | } | ||
545 | |||
546 | #define CHECK_AND_PRINT_I(x) \ | ||
547 | ((eeprom_ch_info[ch_idx].flags & EEPROM_CHANNEL_##x) ? # x " " : "") | ||
548 | |||
549 | static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, | ||
550 | struct iwl_eeprom_data *data, | ||
551 | const u8 *eeprom, size_t eeprom_size) | ||
552 | { | ||
553 | int band, ch_idx; | ||
554 | const struct iwl_eeprom_channel *eeprom_ch_info; | ||
555 | const u8 *eeprom_ch_array; | ||
556 | int eeprom_ch_count; | ||
557 | int n_channels = 0; | ||
558 | |||
559 | /* | ||
560 | * Loop through the 5 EEPROM bands and add them to the parse list | ||
561 | */ | ||
562 | for (band = 1; band <= 5; band++) { | ||
563 | struct ieee80211_channel *channel; | ||
564 | |||
565 | iwl_init_band_reference(cfg, eeprom, eeprom_size, band, | ||
566 | &eeprom_ch_count, &eeprom_ch_info, | ||
567 | &eeprom_ch_array); | ||
568 | |||
569 | /* Loop through each band adding each of the channels */ | ||
570 | for (ch_idx = 0; ch_idx < eeprom_ch_count; ch_idx++) { | ||
571 | const struct iwl_eeprom_channel *eeprom_ch; | ||
572 | |||
573 | eeprom_ch = &eeprom_ch_info[ch_idx]; | ||
574 | |||
575 | if (!(eeprom_ch->flags & EEPROM_CHANNEL_VALID)) { | ||
576 | IWL_DEBUG_EEPROM(dev, | ||
577 | "Ch. %d Flags %x [%sGHz] - No traffic\n", | ||
578 | eeprom_ch_array[ch_idx], | ||
579 | eeprom_ch_info[ch_idx].flags, | ||
580 | (band != 1) ? "5.2" : "2.4"); | ||
581 | continue; | ||
582 | } | ||
583 | |||
584 | channel = &data->channels[n_channels]; | ||
585 | n_channels++; | ||
586 | |||
587 | channel->hw_value = eeprom_ch_array[ch_idx]; | ||
588 | channel->band = (band == 1) ? IEEE80211_BAND_2GHZ | ||
589 | : IEEE80211_BAND_5GHZ; | ||
590 | channel->center_freq = | ||
591 | ieee80211_channel_to_frequency( | ||
592 | channel->hw_value, channel->band); | ||
593 | |||
594 | /* set no-HT40, will enable as appropriate later */ | ||
595 | channel->flags = IEEE80211_CHAN_NO_HT40; | ||
596 | |||
597 | if (!(eeprom_ch->flags & EEPROM_CHANNEL_IBSS)) | ||
598 | channel->flags |= IEEE80211_CHAN_NO_IBSS; | ||
599 | |||
600 | if (!(eeprom_ch->flags & EEPROM_CHANNEL_ACTIVE)) | ||
601 | channel->flags |= IEEE80211_CHAN_PASSIVE_SCAN; | ||
602 | |||
603 | if (eeprom_ch->flags & EEPROM_CHANNEL_RADAR) | ||
604 | channel->flags |= IEEE80211_CHAN_RADAR; | ||
605 | |||
606 | /* Initialize regulatory-based run-time data */ | ||
607 | channel->max_power = | ||
608 | eeprom_ch_info[ch_idx].max_power_avg; | ||
609 | IWL_DEBUG_EEPROM(dev, | ||
610 | "Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x %ddBm): Ad-Hoc %ssupported\n", | ||
611 | channel->hw_value, | ||
612 | (band != 1) ? "5.2" : "2.4", | ||
613 | CHECK_AND_PRINT_I(VALID), | ||
614 | CHECK_AND_PRINT_I(IBSS), | ||
615 | CHECK_AND_PRINT_I(ACTIVE), | ||
616 | CHECK_AND_PRINT_I(RADAR), | ||
617 | CHECK_AND_PRINT_I(WIDE), | ||
618 | CHECK_AND_PRINT_I(DFS), | ||
619 | eeprom_ch_info[ch_idx].flags, | ||
620 | eeprom_ch_info[ch_idx].max_power_avg, | ||
621 | ((eeprom_ch_info[ch_idx].flags & | ||
622 | EEPROM_CHANNEL_IBSS) && | ||
623 | !(eeprom_ch_info[ch_idx].flags & | ||
624 | EEPROM_CHANNEL_RADAR)) | ||
625 | ? "" : "not "); | ||
626 | } | ||
627 | } | ||
628 | |||
629 | if (cfg->eeprom_params->enhanced_txpower) { | ||
630 | /* | ||
631 | * for newer device (6000 series and up) | ||
632 | * EEPROM contain enhanced tx power information | ||
633 | * driver need to process addition information | ||
634 | * to determine the max channel tx power limits | ||
635 | */ | ||
636 | iwl_eeprom_enhanced_txpower(dev, data, eeprom, eeprom_size, | ||
637 | n_channels); | ||
638 | } else { | ||
639 | /* All others use data from channel map */ | ||
640 | int i; | ||
641 | |||
642 | data->max_tx_pwr_half_dbm = -128; | ||
643 | |||
644 | for (i = 0; i < n_channels; i++) | ||
645 | data->max_tx_pwr_half_dbm = | ||
646 | max_t(s8, data->max_tx_pwr_half_dbm, | ||
647 | data->channels[i].max_power * 2); | ||
648 | } | ||
649 | |||
650 | /* Check if we do have HT40 channels */ | ||
651 | if (cfg->eeprom_params->regulatory_bands[5] == | ||
652 | EEPROM_REGULATORY_BAND_NO_HT40 && | ||
653 | cfg->eeprom_params->regulatory_bands[6] == | ||
654 | EEPROM_REGULATORY_BAND_NO_HT40) | ||
655 | return n_channels; | ||
656 | |||
657 | /* Two additional EEPROM bands for 2.4 and 5 GHz HT40 channels */ | ||
658 | for (band = 6; band <= 7; band++) { | ||
659 | enum ieee80211_band ieeeband; | ||
660 | |||
661 | iwl_init_band_reference(cfg, eeprom, eeprom_size, band, | ||
662 | &eeprom_ch_count, &eeprom_ch_info, | ||
663 | &eeprom_ch_array); | ||
664 | |||
665 | /* EEPROM band 6 is 2.4, band 7 is 5 GHz */ | ||
666 | ieeeband = (band == 6) ? IEEE80211_BAND_2GHZ | ||
667 | : IEEE80211_BAND_5GHZ; | ||
668 | |||
669 | /* Loop through each band adding each of the channels */ | ||
670 | for (ch_idx = 0; ch_idx < eeprom_ch_count; ch_idx++) { | ||
671 | /* Set up driver's info for lower half */ | ||
672 | iwl_mod_ht40_chan_info(dev, data, n_channels, ieeeband, | ||
673 | eeprom_ch_array[ch_idx], | ||
674 | &eeprom_ch_info[ch_idx], | ||
675 | IEEE80211_CHAN_NO_HT40PLUS); | ||
676 | |||
677 | /* Set up driver's info for upper half */ | ||
678 | iwl_mod_ht40_chan_info(dev, data, n_channels, ieeeband, | ||
679 | eeprom_ch_array[ch_idx] + 4, | ||
680 | &eeprom_ch_info[ch_idx], | ||
681 | IEEE80211_CHAN_NO_HT40MINUS); | ||
682 | } | ||
683 | } | ||
684 | |||
685 | return n_channels; | ||
686 | } | ||
687 | |||
688 | static int iwl_init_sband_channels(struct iwl_eeprom_data *data, | ||
689 | struct ieee80211_supported_band *sband, | ||
690 | int n_channels, enum ieee80211_band band) | ||
691 | { | ||
692 | struct ieee80211_channel *chan = &data->channels[0]; | ||
693 | int n = 0, idx = 0; | ||
694 | |||
695 | while (chan->band != band && idx < n_channels) | ||
696 | chan = &data->channels[++idx]; | ||
697 | |||
698 | sband->channels = &data->channels[idx]; | ||
699 | |||
700 | while (chan->band == band && idx < n_channels) { | ||
701 | chan = &data->channels[++idx]; | ||
702 | n++; | ||
703 | } | ||
704 | |||
705 | sband->n_channels = n; | ||
706 | |||
707 | return n; | ||
708 | } | ||
709 | |||
710 | #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */ | ||
711 | #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */ | ||
712 | |||
713 | static void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg, | ||
714 | struct iwl_eeprom_data *data, | ||
715 | struct ieee80211_sta_ht_cap *ht_info, | ||
716 | enum ieee80211_band band) | ||
717 | { | ||
718 | int max_bit_rate = 0; | ||
719 | u8 rx_chains; | ||
720 | u8 tx_chains; | ||
721 | |||
722 | tx_chains = hweight8(data->valid_tx_ant); | ||
723 | if (cfg->rx_with_siso_diversity) | ||
724 | rx_chains = 1; | ||
725 | else | ||
726 | rx_chains = hweight8(data->valid_rx_ant); | ||
727 | |||
728 | if (!(data->sku & EEPROM_SKU_CAP_11N_ENABLE) || !cfg->ht_params) { | ||
729 | ht_info->ht_supported = false; | ||
730 | return; | ||
731 | } | ||
732 | |||
733 | ht_info->ht_supported = true; | ||
734 | ht_info->cap = 0; | ||
735 | |||
736 | if (iwlwifi_mod_params.amsdu_size_8K) | ||
737 | ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU; | ||
738 | |||
739 | ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; | ||
740 | ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_4; | ||
741 | |||
742 | ht_info->mcs.rx_mask[0] = 0xFF; | ||
743 | if (rx_chains >= 2) | ||
744 | ht_info->mcs.rx_mask[1] = 0xFF; | ||
745 | if (rx_chains >= 3) | ||
746 | ht_info->mcs.rx_mask[2] = 0xFF; | ||
747 | |||
748 | if (cfg->ht_params->ht_greenfield_support) | ||
749 | ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; | ||
750 | ht_info->cap |= IEEE80211_HT_CAP_SGI_20; | ||
751 | |||
752 | max_bit_rate = MAX_BIT_RATE_20_MHZ; | ||
753 | |||
754 | if (cfg->ht_params->ht40_bands & BIT(band)) { | ||
755 | ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
756 | ht_info->cap |= IEEE80211_HT_CAP_SGI_40; | ||
757 | ht_info->mcs.rx_mask[4] = 0x01; | ||
758 | max_bit_rate = MAX_BIT_RATE_40_MHZ; | ||
759 | } | ||
760 | |||
761 | /* Highest supported Rx data rate */ | ||
762 | max_bit_rate *= rx_chains; | ||
763 | WARN_ON(max_bit_rate & ~IEEE80211_HT_MCS_RX_HIGHEST_MASK); | ||
764 | ht_info->mcs.rx_highest = cpu_to_le16(max_bit_rate); | ||
765 | |||
766 | /* Tx MCS capabilities */ | ||
767 | ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; | ||
768 | if (tx_chains != rx_chains) { | ||
769 | ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; | ||
770 | ht_info->mcs.tx_params |= ((tx_chains - 1) << | ||
771 | IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); | ||
772 | } | ||
773 | } | ||
774 | |||
775 | static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, | ||
776 | struct iwl_eeprom_data *data, | ||
777 | const u8 *eeprom, size_t eeprom_size) | ||
778 | { | ||
779 | int n_channels = iwl_init_channel_map(dev, cfg, data, | ||
780 | eeprom, eeprom_size); | ||
781 | int n_used = 0; | ||
782 | struct ieee80211_supported_band *sband; | ||
783 | |||
784 | sband = &data->bands[IEEE80211_BAND_2GHZ]; | ||
785 | sband->band = IEEE80211_BAND_2GHZ; | ||
786 | sband->bitrates = &iwl_cfg80211_rates[RATES_24_OFFS]; | ||
787 | sband->n_bitrates = N_RATES_24; | ||
788 | n_used += iwl_init_sband_channels(data, sband, n_channels, | ||
789 | IEEE80211_BAND_2GHZ); | ||
790 | iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_2GHZ); | ||
791 | |||
792 | sband = &data->bands[IEEE80211_BAND_5GHZ]; | ||
793 | sband->band = IEEE80211_BAND_5GHZ; | ||
794 | sband->bitrates = &iwl_cfg80211_rates[RATES_52_OFFS]; | ||
795 | sband->n_bitrates = N_RATES_52; | ||
796 | n_used += iwl_init_sband_channels(data, sband, n_channels, | ||
797 | IEEE80211_BAND_5GHZ); | ||
798 | iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_5GHZ); | ||
799 | |||
800 | if (n_channels != n_used) | ||
801 | IWL_ERR_DEV(dev, "EEPROM: used only %d of %d channels\n", | ||
802 | n_used, n_channels); | ||
803 | } | ||
804 | |||
805 | /* EEPROM data functions */ | ||
806 | |||
807 | struct iwl_eeprom_data * | ||
808 | iwl_parse_eeprom_data(struct device *dev, const struct iwl_cfg *cfg, | ||
809 | const u8 *eeprom, size_t eeprom_size) | ||
810 | { | ||
811 | struct iwl_eeprom_data *data; | ||
812 | const void *tmp; | ||
813 | |||
814 | if (WARN_ON(!cfg || !cfg->eeprom_params)) | ||
815 | return NULL; | ||
816 | |||
817 | data = kzalloc(sizeof(*data) + | ||
818 | sizeof(struct ieee80211_channel) * IWL_NUM_CHANNELS, | ||
819 | GFP_KERNEL); | ||
820 | if (!data) | ||
821 | return NULL; | ||
822 | |||
823 | /* get MAC address(es) */ | ||
824 | tmp = iwl_eeprom_query_addr(eeprom, eeprom_size, EEPROM_MAC_ADDRESS); | ||
825 | if (!tmp) | ||
826 | goto err_free; | ||
827 | memcpy(data->hw_addr, tmp, ETH_ALEN); | ||
828 | data->n_hw_addrs = iwl_eeprom_query16(eeprom, eeprom_size, | ||
829 | EEPROM_NUM_MAC_ADDRESS); | ||
830 | |||
831 | if (iwl_eeprom_read_calib(eeprom, eeprom_size, data)) | ||
832 | goto err_free; | ||
833 | |||
834 | tmp = iwl_eeprom_query_addr(eeprom, eeprom_size, EEPROM_XTAL); | ||
835 | if (!tmp) | ||
836 | goto err_free; | ||
837 | memcpy(data->xtal_calib, tmp, sizeof(data->xtal_calib)); | ||
838 | |||
839 | tmp = iwl_eeprom_query_addr(eeprom, eeprom_size, | ||
840 | EEPROM_RAW_TEMPERATURE); | ||
841 | if (!tmp) | ||
842 | goto err_free; | ||
843 | data->raw_temperature = *(__le16 *)tmp; | ||
844 | |||
845 | tmp = iwl_eeprom_query_addr(eeprom, eeprom_size, | ||
846 | EEPROM_KELVIN_TEMPERATURE); | ||
847 | if (!tmp) | ||
848 | goto err_free; | ||
849 | data->kelvin_temperature = *(__le16 *)tmp; | ||
850 | data->kelvin_voltage = *((__le16 *)tmp + 1); | ||
851 | |||
852 | data->radio_cfg = iwl_eeprom_query16(eeprom, eeprom_size, | ||
853 | EEPROM_RADIO_CONFIG); | ||
854 | data->sku = iwl_eeprom_query16(eeprom, eeprom_size, | ||
855 | EEPROM_SKU_CAP); | ||
856 | if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_ALL) | ||
857 | data->sku &= ~EEPROM_SKU_CAP_11N_ENABLE; | ||
858 | |||
859 | data->eeprom_version = iwl_eeprom_query16(eeprom, eeprom_size, | ||
860 | EEPROM_VERSION); | ||
861 | |||
862 | data->valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(data->radio_cfg); | ||
863 | data->valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(data->radio_cfg); | ||
864 | |||
865 | /* check overrides (some devices have wrong EEPROM) */ | ||
866 | if (cfg->valid_tx_ant) | ||
867 | data->valid_tx_ant = cfg->valid_tx_ant; | ||
868 | if (cfg->valid_rx_ant) | ||
869 | data->valid_rx_ant = cfg->valid_rx_ant; | ||
870 | |||
871 | if (!data->valid_tx_ant || !data->valid_rx_ant) { | ||
872 | IWL_ERR_DEV(dev, "invalid antennas (0x%x, 0x%x)\n", | ||
873 | data->valid_tx_ant, data->valid_rx_ant); | ||
874 | goto err_free; | ||
875 | } | ||
876 | |||
877 | iwl_init_sbands(dev, cfg, data, eeprom, eeprom_size); | ||
878 | |||
879 | return data; | ||
880 | err_free: | ||
881 | kfree(data); | ||
882 | return NULL; | ||
883 | } | ||
884 | EXPORT_SYMBOL_GPL(iwl_parse_eeprom_data); | ||
885 | |||
886 | /* helper functions */ | ||
887 | int iwl_eeprom_check_version(struct iwl_eeprom_data *data, | ||
888 | struct iwl_trans *trans) | ||
889 | { | ||
890 | if (data->eeprom_version >= trans->cfg->eeprom_ver || | ||
891 | data->calib_version >= trans->cfg->eeprom_calib_ver) { | ||
892 | IWL_INFO(trans, "device EEPROM VER=0x%x, CALIB=0x%x\n", | ||
893 | data->eeprom_version, data->calib_version); | ||
894 | return 0; | ||
895 | } | ||
896 | |||
897 | IWL_ERR(trans, | ||
898 | "Unsupported (too old) EEPROM VER=0x%x < 0x%x CALIB=0x%x < 0x%x\n", | ||
899 | data->eeprom_version, trans->cfg->eeprom_ver, | ||
900 | data->calib_version, trans->cfg->eeprom_calib_ver); | ||
901 | return -EINVAL; | ||
902 | } | ||
903 | EXPORT_SYMBOL_GPL(iwl_eeprom_check_version); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h new file mode 100644 index 00000000000..9c07c670a1c --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h | |||
@@ -0,0 +1,138 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | *****************************************************************************/ | ||
62 | #ifndef __iwl_eeprom_parse_h__ | ||
63 | #define __iwl_eeprom_parse_h__ | ||
64 | |||
65 | #include <linux/types.h> | ||
66 | #include <linux/if_ether.h> | ||
67 | #include "iwl-trans.h" | ||
68 | |||
69 | /* SKU Capabilities (actual values from EEPROM definition) */ | ||
70 | #define EEPROM_SKU_CAP_BAND_24GHZ (1 << 4) | ||
71 | #define EEPROM_SKU_CAP_BAND_52GHZ (1 << 5) | ||
72 | #define EEPROM_SKU_CAP_11N_ENABLE (1 << 6) | ||
73 | #define EEPROM_SKU_CAP_AMT_ENABLE (1 << 7) | ||
74 | #define EEPROM_SKU_CAP_IPAN_ENABLE (1 << 8) | ||
75 | |||
76 | /* radio config bits (actual values from EEPROM definition) */ | ||
77 | #define EEPROM_RF_CFG_TYPE_MSK(x) (x & 0x3) /* bits 0-1 */ | ||
78 | #define EEPROM_RF_CFG_STEP_MSK(x) ((x >> 2) & 0x3) /* bits 2-3 */ | ||
79 | #define EEPROM_RF_CFG_DASH_MSK(x) ((x >> 4) & 0x3) /* bits 4-5 */ | ||
80 | #define EEPROM_RF_CFG_PNUM_MSK(x) ((x >> 6) & 0x3) /* bits 6-7 */ | ||
81 | #define EEPROM_RF_CFG_TX_ANT_MSK(x) ((x >> 8) & 0xF) /* bits 8-11 */ | ||
82 | #define EEPROM_RF_CFG_RX_ANT_MSK(x) ((x >> 12) & 0xF) /* bits 12-15 */ | ||
83 | |||
84 | struct iwl_eeprom_data { | ||
85 | int n_hw_addrs; | ||
86 | u8 hw_addr[ETH_ALEN]; | ||
87 | |||
88 | u16 radio_config; | ||
89 | |||
90 | u8 calib_version; | ||
91 | __le16 calib_voltage; | ||
92 | |||
93 | __le16 raw_temperature; | ||
94 | __le16 kelvin_temperature; | ||
95 | __le16 kelvin_voltage; | ||
96 | __le16 xtal_calib[2]; | ||
97 | |||
98 | u16 sku; | ||
99 | u16 radio_cfg; | ||
100 | u16 eeprom_version; | ||
101 | s8 max_tx_pwr_half_dbm; | ||
102 | |||
103 | u8 valid_tx_ant, valid_rx_ant; | ||
104 | |||
105 | struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; | ||
106 | struct ieee80211_channel channels[]; | ||
107 | }; | ||
108 | |||
109 | /** | ||
110 | * iwl_parse_eeprom_data - parse EEPROM data and return values | ||
111 | * | ||
112 | * @dev: device pointer we're parsing for, for debug only | ||
113 | * @cfg: device configuration for parsing and overrides | ||
114 | * @eeprom: the EEPROM data | ||
115 | * @eeprom_size: length of the EEPROM data | ||
116 | * | ||
117 | * This function parses all EEPROM values we need and then | ||
118 | * returns a (newly allocated) struct containing all the | ||
119 | * relevant values for driver use. The struct must be freed | ||
120 | * later with iwl_free_eeprom_data(). | ||
121 | */ | ||
122 | struct iwl_eeprom_data * | ||
123 | iwl_parse_eeprom_data(struct device *dev, const struct iwl_cfg *cfg, | ||
124 | const u8 *eeprom, size_t eeprom_size); | ||
125 | |||
126 | /** | ||
127 | * iwl_free_eeprom_data - free EEPROM data | ||
128 | * @data: the data to free | ||
129 | */ | ||
130 | static inline void iwl_free_eeprom_data(struct iwl_eeprom_data *data) | ||
131 | { | ||
132 | kfree(data); | ||
133 | } | ||
134 | |||
135 | int iwl_eeprom_check_version(struct iwl_eeprom_data *data, | ||
136 | struct iwl_trans *trans); | ||
137 | |||
138 | #endif /* __iwl_eeprom_parse_h__ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-read.c b/drivers/net/wireless/iwlwifi/iwl-eeprom-read.c new file mode 100644 index 00000000000..27c7da3c6ed --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-read.c | |||
@@ -0,0 +1,463 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | *****************************************************************************/ | ||
62 | #include <linux/types.h> | ||
63 | #include <linux/slab.h> | ||
64 | #include <linux/export.h> | ||
65 | |||
66 | #include "iwl-debug.h" | ||
67 | #include "iwl-eeprom-read.h" | ||
68 | #include "iwl-io.h" | ||
69 | #include "iwl-prph.h" | ||
70 | #include "iwl-csr.h" | ||
71 | |||
72 | /* | ||
73 | * EEPROM access time values: | ||
74 | * | ||
75 | * Driver initiates EEPROM read by writing byte address << 1 to CSR_EEPROM_REG. | ||
76 | * Driver then polls CSR_EEPROM_REG for CSR_EEPROM_REG_READ_VALID_MSK (0x1). | ||
77 | * When polling, wait 10 uSec between polling loops, up to a maximum 5000 uSec. | ||
78 | * Driver reads 16-bit value from bits 31-16 of CSR_EEPROM_REG. | ||
79 | */ | ||
80 | #define IWL_EEPROM_ACCESS_TIMEOUT 5000 /* uSec */ | ||
81 | |||
82 | #define IWL_EEPROM_SEM_TIMEOUT 10 /* microseconds */ | ||
83 | #define IWL_EEPROM_SEM_RETRY_LIMIT 1000 /* number of attempts (not time) */ | ||
84 | |||
85 | |||
86 | /* | ||
87 | * The device's EEPROM semaphore prevents conflicts between driver and uCode | ||
88 | * when accessing the EEPROM; each access is a series of pulses to/from the | ||
89 | * EEPROM chip, not a single event, so even reads could conflict if they | ||
90 | * weren't arbitrated by the semaphore. | ||
91 | */ | ||
92 | |||
93 | #define EEPROM_SEM_TIMEOUT 10 /* milliseconds */ | ||
94 | #define EEPROM_SEM_RETRY_LIMIT 1000 /* number of attempts (not time) */ | ||
95 | |||
96 | static int iwl_eeprom_acquire_semaphore(struct iwl_trans *trans) | ||
97 | { | ||
98 | u16 count; | ||
99 | int ret; | ||
100 | |||
101 | for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) { | ||
102 | /* Request semaphore */ | ||
103 | iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, | ||
104 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); | ||
105 | |||
106 | /* See if we got it */ | ||
107 | ret = iwl_poll_bit(trans, CSR_HW_IF_CONFIG_REG, | ||
108 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, | ||
109 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, | ||
110 | EEPROM_SEM_TIMEOUT); | ||
111 | if (ret >= 0) { | ||
112 | IWL_DEBUG_EEPROM(trans->dev, | ||
113 | "Acquired semaphore after %d tries.\n", | ||
114 | count+1); | ||
115 | return ret; | ||
116 | } | ||
117 | } | ||
118 | |||
119 | return ret; | ||
120 | } | ||
121 | |||
122 | static void iwl_eeprom_release_semaphore(struct iwl_trans *trans) | ||
123 | { | ||
124 | iwl_clear_bit(trans, CSR_HW_IF_CONFIG_REG, | ||
125 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); | ||
126 | } | ||
127 | |||
128 | static int iwl_eeprom_verify_signature(struct iwl_trans *trans, bool nvm_is_otp) | ||
129 | { | ||
130 | u32 gp = iwl_read32(trans, CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK; | ||
131 | |||
132 | IWL_DEBUG_EEPROM(trans->dev, "EEPROM signature=0x%08x\n", gp); | ||
133 | |||
134 | switch (gp) { | ||
135 | case CSR_EEPROM_GP_BAD_SIG_EEP_GOOD_SIG_OTP: | ||
136 | if (!nvm_is_otp) { | ||
137 | IWL_ERR(trans, "EEPROM with bad signature: 0x%08x\n", | ||
138 | gp); | ||
139 | return -ENOENT; | ||
140 | } | ||
141 | return 0; | ||
142 | case CSR_EEPROM_GP_GOOD_SIG_EEP_LESS_THAN_4K: | ||
143 | case CSR_EEPROM_GP_GOOD_SIG_EEP_MORE_THAN_4K: | ||
144 | if (nvm_is_otp) { | ||
145 | IWL_ERR(trans, "OTP with bad signature: 0x%08x\n", gp); | ||
146 | return -ENOENT; | ||
147 | } | ||
148 | return 0; | ||
149 | case CSR_EEPROM_GP_BAD_SIGNATURE_BOTH_EEP_AND_OTP: | ||
150 | default: | ||
151 | IWL_ERR(trans, | ||
152 | "bad EEPROM/OTP signature, type=%s, EEPROM_GP=0x%08x\n", | ||
153 | nvm_is_otp ? "OTP" : "EEPROM", gp); | ||
154 | return -ENOENT; | ||
155 | } | ||
156 | } | ||
157 | |||
158 | /****************************************************************************** | ||
159 | * | ||
160 | * OTP related functions | ||
161 | * | ||
162 | ******************************************************************************/ | ||
163 | |||
164 | static void iwl_set_otp_access_absolute(struct iwl_trans *trans) | ||
165 | { | ||
166 | iwl_read32(trans, CSR_OTP_GP_REG); | ||
167 | |||
168 | iwl_clear_bit(trans, CSR_OTP_GP_REG, | ||
169 | CSR_OTP_GP_REG_OTP_ACCESS_MODE); | ||
170 | } | ||
171 | |||
172 | static int iwl_nvm_is_otp(struct iwl_trans *trans) | ||
173 | { | ||
174 | u32 otpgp; | ||
175 | |||
176 | /* OTP only valid for CP/PP and after */ | ||
177 | switch (trans->hw_rev & CSR_HW_REV_TYPE_MSK) { | ||
178 | case CSR_HW_REV_TYPE_NONE: | ||
179 | IWL_ERR(trans, "Unknown hardware type\n"); | ||
180 | return -EIO; | ||
181 | case CSR_HW_REV_TYPE_5300: | ||
182 | case CSR_HW_REV_TYPE_5350: | ||
183 | case CSR_HW_REV_TYPE_5100: | ||
184 | case CSR_HW_REV_TYPE_5150: | ||
185 | return 0; | ||
186 | default: | ||
187 | otpgp = iwl_read32(trans, CSR_OTP_GP_REG); | ||
188 | if (otpgp & CSR_OTP_GP_REG_DEVICE_SELECT) | ||
189 | return 1; | ||
190 | return 0; | ||
191 | } | ||
192 | } | ||
193 | |||
194 | static int iwl_init_otp_access(struct iwl_trans *trans) | ||
195 | { | ||
196 | int ret; | ||
197 | |||
198 | /* Enable 40MHz radio clock */ | ||
199 | iwl_write32(trans, CSR_GP_CNTRL, | ||
200 | iwl_read32(trans, CSR_GP_CNTRL) | | ||
201 | CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
202 | |||
203 | /* wait for clock to be ready */ | ||
204 | ret = iwl_poll_bit(trans, CSR_GP_CNTRL, | ||
205 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||
206 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||
207 | 25000); | ||
208 | if (ret < 0) { | ||
209 | IWL_ERR(trans, "Time out access OTP\n"); | ||
210 | } else { | ||
211 | iwl_set_bits_prph(trans, APMG_PS_CTRL_REG, | ||
212 | APMG_PS_CTRL_VAL_RESET_REQ); | ||
213 | udelay(5); | ||
214 | iwl_clear_bits_prph(trans, APMG_PS_CTRL_REG, | ||
215 | APMG_PS_CTRL_VAL_RESET_REQ); | ||
216 | |||
217 | /* | ||
218 | * CSR auto clock gate disable bit - | ||
219 | * this is only applicable for HW with OTP shadow RAM | ||
220 | */ | ||
221 | if (trans->cfg->base_params->shadow_ram_support) | ||
222 | iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG, | ||
223 | CSR_RESET_LINK_PWR_MGMT_DISABLED); | ||
224 | } | ||
225 | return ret; | ||
226 | } | ||
227 | |||
228 | static int iwl_read_otp_word(struct iwl_trans *trans, u16 addr, | ||
229 | __le16 *eeprom_data) | ||
230 | { | ||
231 | int ret = 0; | ||
232 | u32 r; | ||
233 | u32 otpgp; | ||
234 | |||
235 | iwl_write32(trans, CSR_EEPROM_REG, | ||
236 | CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); | ||
237 | ret = iwl_poll_bit(trans, CSR_EEPROM_REG, | ||
238 | CSR_EEPROM_REG_READ_VALID_MSK, | ||
239 | CSR_EEPROM_REG_READ_VALID_MSK, | ||
240 | IWL_EEPROM_ACCESS_TIMEOUT); | ||
241 | if (ret < 0) { | ||
242 | IWL_ERR(trans, "Time out reading OTP[%d]\n", addr); | ||
243 | return ret; | ||
244 | } | ||
245 | r = iwl_read32(trans, CSR_EEPROM_REG); | ||
246 | /* check for ECC errors: */ | ||
247 | otpgp = iwl_read32(trans, CSR_OTP_GP_REG); | ||
248 | if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) { | ||
249 | /* stop in this case */ | ||
250 | /* set the uncorrectable OTP ECC bit for acknowledgement */ | ||
251 | iwl_set_bit(trans, CSR_OTP_GP_REG, | ||
252 | CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); | ||
253 | IWL_ERR(trans, "Uncorrectable OTP ECC error, abort OTP read\n"); | ||
254 | return -EINVAL; | ||
255 | } | ||
256 | if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) { | ||
257 | /* continue in this case */ | ||
258 | /* set the correctable OTP ECC bit for acknowledgement */ | ||
259 | iwl_set_bit(trans, CSR_OTP_GP_REG, | ||
260 | CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK); | ||
261 | IWL_ERR(trans, "Correctable OTP ECC error, continue read\n"); | ||
262 | } | ||
263 | *eeprom_data = cpu_to_le16(r >> 16); | ||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | /* | ||
268 | * iwl_is_otp_empty: check for empty OTP | ||
269 | */ | ||
270 | static bool iwl_is_otp_empty(struct iwl_trans *trans) | ||
271 | { | ||
272 | u16 next_link_addr = 0; | ||
273 | __le16 link_value; | ||
274 | bool is_empty = false; | ||
275 | |||
276 | /* locate the beginning of OTP link list */ | ||
277 | if (!iwl_read_otp_word(trans, next_link_addr, &link_value)) { | ||
278 | if (!link_value) { | ||
279 | IWL_ERR(trans, "OTP is empty\n"); | ||
280 | is_empty = true; | ||
281 | } | ||
282 | } else { | ||
283 | IWL_ERR(trans, "Unable to read first block of OTP list.\n"); | ||
284 | is_empty = true; | ||
285 | } | ||
286 | |||
287 | return is_empty; | ||
288 | } | ||
289 | |||
290 | |||
291 | /* | ||
292 | * iwl_find_otp_image: find EEPROM image in OTP | ||
293 | * finding the OTP block that contains the EEPROM image. | ||
294 | * the last valid block on the link list (the block _before_ the last block) | ||
295 | * is the block we should read and used to configure the device. | ||
296 | * If all the available OTP blocks are full, the last block will be the block | ||
297 | * we should read and used to configure the device. | ||
298 | * only perform this operation if shadow RAM is disabled | ||
299 | */ | ||
300 | static int iwl_find_otp_image(struct iwl_trans *trans, | ||
301 | u16 *validblockaddr) | ||
302 | { | ||
303 | u16 next_link_addr = 0, valid_addr; | ||
304 | __le16 link_value = 0; | ||
305 | int usedblocks = 0; | ||
306 | |||
307 | /* set addressing mode to absolute to traverse the link list */ | ||
308 | iwl_set_otp_access_absolute(trans); | ||
309 | |||
310 | /* checking for empty OTP or error */ | ||
311 | if (iwl_is_otp_empty(trans)) | ||
312 | return -EINVAL; | ||
313 | |||
314 | /* | ||
315 | * start traverse link list | ||
316 | * until reach the max number of OTP blocks | ||
317 | * different devices have different number of OTP blocks | ||
318 | */ | ||
319 | do { | ||
320 | /* save current valid block address | ||
321 | * check for more block on the link list | ||
322 | */ | ||
323 | valid_addr = next_link_addr; | ||
324 | next_link_addr = le16_to_cpu(link_value) * sizeof(u16); | ||
325 | IWL_DEBUG_EEPROM(trans->dev, "OTP blocks %d addr 0x%x\n", | ||
326 | usedblocks, next_link_addr); | ||
327 | if (iwl_read_otp_word(trans, next_link_addr, &link_value)) | ||
328 | return -EINVAL; | ||
329 | if (!link_value) { | ||
330 | /* | ||
331 | * reach the end of link list, return success and | ||
332 | * set address point to the starting address | ||
333 | * of the image | ||
334 | */ | ||
335 | *validblockaddr = valid_addr; | ||
336 | /* skip first 2 bytes (link list pointer) */ | ||
337 | *validblockaddr += 2; | ||
338 | return 0; | ||
339 | } | ||
340 | /* more in the link list, continue */ | ||
341 | usedblocks++; | ||
342 | } while (usedblocks <= trans->cfg->base_params->max_ll_items); | ||
343 | |||
344 | /* OTP has no valid blocks */ | ||
345 | IWL_DEBUG_EEPROM(trans->dev, "OTP has no valid blocks\n"); | ||
346 | return -EINVAL; | ||
347 | } | ||
348 | |||
349 | /** | ||
350 | * iwl_read_eeprom - read EEPROM contents | ||
351 | * | ||
352 | * Load the EEPROM contents from adapter and return it | ||
353 | * and its size. | ||
354 | * | ||
355 | * NOTE: This routine uses the non-debug IO access functions. | ||
356 | */ | ||
357 | int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size) | ||
358 | { | ||
359 | __le16 *e; | ||
360 | u32 gp = iwl_read32(trans, CSR_EEPROM_GP); | ||
361 | int sz; | ||
362 | int ret; | ||
363 | u16 addr; | ||
364 | u16 validblockaddr = 0; | ||
365 | u16 cache_addr = 0; | ||
366 | int nvm_is_otp; | ||
367 | |||
368 | if (!eeprom || !eeprom_size) | ||
369 | return -EINVAL; | ||
370 | |||
371 | nvm_is_otp = iwl_nvm_is_otp(trans); | ||
372 | if (nvm_is_otp < 0) | ||
373 | return nvm_is_otp; | ||
374 | |||
375 | sz = trans->cfg->base_params->eeprom_size; | ||
376 | IWL_DEBUG_EEPROM(trans->dev, "NVM size = %d\n", sz); | ||
377 | |||
378 | e = kmalloc(sz, GFP_KERNEL); | ||
379 | if (!e) | ||
380 | return -ENOMEM; | ||
381 | |||
382 | ret = iwl_eeprom_verify_signature(trans, nvm_is_otp); | ||
383 | if (ret < 0) { | ||
384 | IWL_ERR(trans, "EEPROM not found, EEPROM_GP=0x%08x\n", gp); | ||
385 | goto err_free; | ||
386 | } | ||
387 | |||
388 | /* Make sure driver (instead of uCode) is allowed to read EEPROM */ | ||
389 | ret = iwl_eeprom_acquire_semaphore(trans); | ||
390 | if (ret < 0) { | ||
391 | IWL_ERR(trans, "Failed to acquire EEPROM semaphore.\n"); | ||
392 | goto err_free; | ||
393 | } | ||
394 | |||
395 | if (nvm_is_otp) { | ||
396 | ret = iwl_init_otp_access(trans); | ||
397 | if (ret) { | ||
398 | IWL_ERR(trans, "Failed to initialize OTP access.\n"); | ||
399 | goto err_unlock; | ||
400 | } | ||
401 | |||
402 | iwl_write32(trans, CSR_EEPROM_GP, | ||
403 | iwl_read32(trans, CSR_EEPROM_GP) & | ||
404 | ~CSR_EEPROM_GP_IF_OWNER_MSK); | ||
405 | |||
406 | iwl_set_bit(trans, CSR_OTP_GP_REG, | ||
407 | CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK | | ||
408 | CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); | ||
409 | /* traversing the linked list if no shadow ram supported */ | ||
410 | if (!trans->cfg->base_params->shadow_ram_support) { | ||
411 | ret = iwl_find_otp_image(trans, &validblockaddr); | ||
412 | if (ret) | ||
413 | goto err_unlock; | ||
414 | } | ||
415 | for (addr = validblockaddr; addr < validblockaddr + sz; | ||
416 | addr += sizeof(u16)) { | ||
417 | __le16 eeprom_data; | ||
418 | |||
419 | ret = iwl_read_otp_word(trans, addr, &eeprom_data); | ||
420 | if (ret) | ||
421 | goto err_unlock; | ||
422 | e[cache_addr / 2] = eeprom_data; | ||
423 | cache_addr += sizeof(u16); | ||
424 | } | ||
425 | } else { | ||
426 | /* eeprom is an array of 16bit values */ | ||
427 | for (addr = 0; addr < sz; addr += sizeof(u16)) { | ||
428 | u32 r; | ||
429 | |||
430 | iwl_write32(trans, CSR_EEPROM_REG, | ||
431 | CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); | ||
432 | |||
433 | ret = iwl_poll_bit(trans, CSR_EEPROM_REG, | ||
434 | CSR_EEPROM_REG_READ_VALID_MSK, | ||
435 | CSR_EEPROM_REG_READ_VALID_MSK, | ||
436 | IWL_EEPROM_ACCESS_TIMEOUT); | ||
437 | if (ret < 0) { | ||
438 | IWL_ERR(trans, | ||
439 | "Time out reading EEPROM[%d]\n", addr); | ||
440 | goto err_unlock; | ||
441 | } | ||
442 | r = iwl_read32(trans, CSR_EEPROM_REG); | ||
443 | e[addr / 2] = cpu_to_le16(r >> 16); | ||
444 | } | ||
445 | } | ||
446 | |||
447 | IWL_DEBUG_EEPROM(trans->dev, "NVM Type: %s\n", | ||
448 | nvm_is_otp ? "OTP" : "EEPROM"); | ||
449 | |||
450 | iwl_eeprom_release_semaphore(trans); | ||
451 | |||
452 | *eeprom_size = sz; | ||
453 | *eeprom = (u8 *)e; | ||
454 | return 0; | ||
455 | |||
456 | err_unlock: | ||
457 | iwl_eeprom_release_semaphore(trans); | ||
458 | err_free: | ||
459 | kfree(e); | ||
460 | |||
461 | return ret; | ||
462 | } | ||
463 | EXPORT_SYMBOL_GPL(iwl_read_eeprom); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-read.h b/drivers/net/wireless/iwlwifi/iwl-eeprom-read.h new file mode 100644 index 00000000000..1337c9d36fe --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-read.h | |||
@@ -0,0 +1,70 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | *****************************************************************************/ | ||
62 | |||
63 | #ifndef __iwl_eeprom_h__ | ||
64 | #define __iwl_eeprom_h__ | ||
65 | |||
66 | #include "iwl-trans.h" | ||
67 | |||
68 | int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size); | ||
69 | |||
70 | #endif /* __iwl_eeprom_h__ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c deleted file mode 100644 index b8e2b223ac3..00000000000 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ /dev/null | |||
@@ -1,1148 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | *****************************************************************************/ | ||
62 | |||
63 | |||
64 | #include <linux/kernel.h> | ||
65 | #include <linux/module.h> | ||
66 | #include <linux/slab.h> | ||
67 | #include <linux/init.h> | ||
68 | |||
69 | #include <net/mac80211.h> | ||
70 | |||
71 | #include "iwl-dev.h" | ||
72 | #include "iwl-debug.h" | ||
73 | #include "iwl-agn.h" | ||
74 | #include "iwl-eeprom.h" | ||
75 | #include "iwl-io.h" | ||
76 | #include "iwl-prph.h" | ||
77 | |||
78 | /************************** EEPROM BANDS **************************** | ||
79 | * | ||
80 | * The iwl_eeprom_band definitions below provide the mapping from the | ||
81 | * EEPROM contents to the specific channel number supported for each | ||
82 | * band. | ||
83 | * | ||
84 | * For example, iwl_priv->eeprom.band_3_channels[4] from the band_3 | ||
85 | * definition below maps to physical channel 42 in the 5.2GHz spectrum. | ||
86 | * The specific geography and calibration information for that channel | ||
87 | * is contained in the eeprom map itself. | ||
88 | * | ||
89 | * During init, we copy the eeprom information and channel map | ||
90 | * information into priv->channel_info_24/52 and priv->channel_map_24/52 | ||
91 | * | ||
92 | * channel_map_24/52 provides the index in the channel_info array for a | ||
93 | * given channel. We have to have two separate maps as there is channel | ||
94 | * overlap with the 2.4GHz and 5.2GHz spectrum as seen in band_1 and | ||
95 | * band_2 | ||
96 | * | ||
97 | * A value of 0xff stored in the channel_map indicates that the channel | ||
98 | * is not supported by the hardware at all. | ||
99 | * | ||
100 | * A value of 0xfe in the channel_map indicates that the channel is not | ||
101 | * valid for Tx with the current hardware. This means that | ||
102 | * while the system can tune and receive on a given channel, it may not | ||
103 | * be able to associate or transmit any frames on that | ||
104 | * channel. There is no corresponding channel information for that | ||
105 | * entry. | ||
106 | * | ||
107 | *********************************************************************/ | ||
108 | |||
109 | /* 2.4 GHz */ | ||
110 | const u8 iwl_eeprom_band_1[14] = { | ||
111 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 | ||
112 | }; | ||
113 | |||
114 | /* 5.2 GHz bands */ | ||
115 | static const u8 iwl_eeprom_band_2[] = { /* 4915-5080MHz */ | ||
116 | 183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16 | ||
117 | }; | ||
118 | |||
119 | static const u8 iwl_eeprom_band_3[] = { /* 5170-5320MHz */ | ||
120 | 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64 | ||
121 | }; | ||
122 | |||
123 | static const u8 iwl_eeprom_band_4[] = { /* 5500-5700MHz */ | ||
124 | 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 | ||
125 | }; | ||
126 | |||
127 | static const u8 iwl_eeprom_band_5[] = { /* 5725-5825MHz */ | ||
128 | 145, 149, 153, 157, 161, 165 | ||
129 | }; | ||
130 | |||
131 | static const u8 iwl_eeprom_band_6[] = { /* 2.4 ht40 channel */ | ||
132 | 1, 2, 3, 4, 5, 6, 7 | ||
133 | }; | ||
134 | |||
135 | static const u8 iwl_eeprom_band_7[] = { /* 5.2 ht40 channel */ | ||
136 | 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157 | ||
137 | }; | ||
138 | |||
139 | /****************************************************************************** | ||
140 | * | ||
141 | * generic NVM functions | ||
142 | * | ||
143 | ******************************************************************************/ | ||
144 | |||
145 | /* | ||
146 | * The device's EEPROM semaphore prevents conflicts between driver and uCode | ||
147 | * when accessing the EEPROM; each access is a series of pulses to/from the | ||
148 | * EEPROM chip, not a single event, so even reads could conflict if they | ||
149 | * weren't arbitrated by the semaphore. | ||
150 | */ | ||
151 | |||
152 | #define EEPROM_SEM_TIMEOUT 10 /* milliseconds */ | ||
153 | #define EEPROM_SEM_RETRY_LIMIT 1000 /* number of attempts (not time) */ | ||
154 | |||
155 | static int iwl_eeprom_acquire_semaphore(struct iwl_trans *trans) | ||
156 | { | ||
157 | u16 count; | ||
158 | int ret; | ||
159 | |||
160 | for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) { | ||
161 | /* Request semaphore */ | ||
162 | iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, | ||
163 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); | ||
164 | |||
165 | /* See if we got it */ | ||
166 | ret = iwl_poll_bit(trans, CSR_HW_IF_CONFIG_REG, | ||
167 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, | ||
168 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, | ||
169 | EEPROM_SEM_TIMEOUT); | ||
170 | if (ret >= 0) { | ||
171 | IWL_DEBUG_EEPROM(trans, | ||
172 | "Acquired semaphore after %d tries.\n", | ||
173 | count+1); | ||
174 | return ret; | ||
175 | } | ||
176 | } | ||
177 | |||
178 | return ret; | ||
179 | } | ||
180 | |||
181 | static void iwl_eeprom_release_semaphore(struct iwl_trans *trans) | ||
182 | { | ||
183 | iwl_clear_bit(trans, CSR_HW_IF_CONFIG_REG, | ||
184 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); | ||
185 | |||
186 | } | ||
187 | |||
188 | static int iwl_eeprom_verify_signature(struct iwl_priv *priv) | ||
189 | { | ||
190 | u32 gp = iwl_read32(priv->trans, CSR_EEPROM_GP) & | ||
191 | CSR_EEPROM_GP_VALID_MSK; | ||
192 | int ret = 0; | ||
193 | |||
194 | IWL_DEBUG_EEPROM(priv, "EEPROM signature=0x%08x\n", gp); | ||
195 | switch (gp) { | ||
196 | case CSR_EEPROM_GP_BAD_SIG_EEP_GOOD_SIG_OTP: | ||
197 | if (priv->nvm_device_type != NVM_DEVICE_TYPE_OTP) { | ||
198 | IWL_ERR(priv, "EEPROM with bad signature: 0x%08x\n", | ||
199 | gp); | ||
200 | ret = -ENOENT; | ||
201 | } | ||
202 | break; | ||
203 | case CSR_EEPROM_GP_GOOD_SIG_EEP_LESS_THAN_4K: | ||
204 | case CSR_EEPROM_GP_GOOD_SIG_EEP_MORE_THAN_4K: | ||
205 | if (priv->nvm_device_type != NVM_DEVICE_TYPE_EEPROM) { | ||
206 | IWL_ERR(priv, "OTP with bad signature: 0x%08x\n", gp); | ||
207 | ret = -ENOENT; | ||
208 | } | ||
209 | break; | ||
210 | case CSR_EEPROM_GP_BAD_SIGNATURE_BOTH_EEP_AND_OTP: | ||
211 | default: | ||
212 | IWL_ERR(priv, "bad EEPROM/OTP signature, type=%s, " | ||
213 | "EEPROM_GP=0x%08x\n", | ||
214 | (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) | ||
215 | ? "OTP" : "EEPROM", gp); | ||
216 | ret = -ENOENT; | ||
217 | break; | ||
218 | } | ||
219 | return ret; | ||
220 | } | ||
221 | |||
222 | u16 iwl_eeprom_query16(struct iwl_priv *priv, size_t offset) | ||
223 | { | ||
224 | if (!priv->eeprom) | ||
225 | return 0; | ||
226 | return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8); | ||
227 | } | ||
228 | |||
229 | int iwl_eeprom_check_version(struct iwl_priv *priv) | ||
230 | { | ||
231 | u16 eeprom_ver; | ||
232 | u16 calib_ver; | ||
233 | |||
234 | eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION); | ||
235 | calib_ver = iwl_eeprom_calib_version(priv); | ||
236 | |||
237 | if (eeprom_ver < priv->cfg->eeprom_ver || | ||
238 | calib_ver < priv->cfg->eeprom_calib_ver) | ||
239 | goto err; | ||
240 | |||
241 | IWL_INFO(priv, "device EEPROM VER=0x%x, CALIB=0x%x\n", | ||
242 | eeprom_ver, calib_ver); | ||
243 | |||
244 | return 0; | ||
245 | err: | ||
246 | IWL_ERR(priv, "Unsupported (too old) EEPROM VER=0x%x < 0x%x " | ||
247 | "CALIB=0x%x < 0x%x\n", | ||
248 | eeprom_ver, priv->cfg->eeprom_ver, | ||
249 | calib_ver, priv->cfg->eeprom_calib_ver); | ||
250 | return -EINVAL; | ||
251 | |||
252 | } | ||
253 | |||
254 | int iwl_eeprom_init_hw_params(struct iwl_priv *priv) | ||
255 | { | ||
256 | u16 radio_cfg; | ||
257 | |||
258 | priv->hw_params.sku = iwl_eeprom_query16(priv, EEPROM_SKU_CAP); | ||
259 | if (priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE && | ||
260 | !priv->cfg->ht_params) { | ||
261 | IWL_ERR(priv, "Invalid 11n configuration\n"); | ||
262 | return -EINVAL; | ||
263 | } | ||
264 | |||
265 | if (!priv->hw_params.sku) { | ||
266 | IWL_ERR(priv, "Invalid device sku\n"); | ||
267 | return -EINVAL; | ||
268 | } | ||
269 | |||
270 | IWL_INFO(priv, "Device SKU: 0x%X\n", priv->hw_params.sku); | ||
271 | |||
272 | radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); | ||
273 | |||
274 | priv->hw_params.valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg); | ||
275 | priv->hw_params.valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(radio_cfg); | ||
276 | |||
277 | /* check overrides (some devices have wrong EEPROM) */ | ||
278 | if (priv->cfg->valid_tx_ant) | ||
279 | priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; | ||
280 | if (priv->cfg->valid_rx_ant) | ||
281 | priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; | ||
282 | |||
283 | if (!priv->hw_params.valid_tx_ant || !priv->hw_params.valid_rx_ant) { | ||
284 | IWL_ERR(priv, "Invalid chain (0x%X, 0x%X)\n", | ||
285 | priv->hw_params.valid_tx_ant, | ||
286 | priv->hw_params.valid_rx_ant); | ||
287 | return -EINVAL; | ||
288 | } | ||
289 | |||
290 | IWL_INFO(priv, "Valid Tx ant: 0x%X, Valid Rx ant: 0x%X\n", | ||
291 | priv->hw_params.valid_tx_ant, priv->hw_params.valid_rx_ant); | ||
292 | |||
293 | return 0; | ||
294 | } | ||
295 | |||
296 | u16 iwl_eeprom_calib_version(struct iwl_priv *priv) | ||
297 | { | ||
298 | struct iwl_eeprom_calib_hdr *hdr; | ||
299 | |||
300 | hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv, | ||
301 | EEPROM_CALIB_ALL); | ||
302 | return hdr->version; | ||
303 | } | ||
304 | |||
305 | static u32 eeprom_indirect_address(struct iwl_priv *priv, u32 address) | ||
306 | { | ||
307 | u16 offset = 0; | ||
308 | |||
309 | if ((address & INDIRECT_ADDRESS) == 0) | ||
310 | return address; | ||
311 | |||
312 | switch (address & INDIRECT_TYPE_MSK) { | ||
313 | case INDIRECT_HOST: | ||
314 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_HOST); | ||
315 | break; | ||
316 | case INDIRECT_GENERAL: | ||
317 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_GENERAL); | ||
318 | break; | ||
319 | case INDIRECT_REGULATORY: | ||
320 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_REGULATORY); | ||
321 | break; | ||
322 | case INDIRECT_TXP_LIMIT: | ||
323 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_TXP_LIMIT); | ||
324 | break; | ||
325 | case INDIRECT_TXP_LIMIT_SIZE: | ||
326 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_TXP_LIMIT_SIZE); | ||
327 | break; | ||
328 | case INDIRECT_CALIBRATION: | ||
329 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_CALIBRATION); | ||
330 | break; | ||
331 | case INDIRECT_PROCESS_ADJST: | ||
332 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_PROCESS_ADJST); | ||
333 | break; | ||
334 | case INDIRECT_OTHERS: | ||
335 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_OTHERS); | ||
336 | break; | ||
337 | default: | ||
338 | IWL_ERR(priv, "illegal indirect type: 0x%X\n", | ||
339 | address & INDIRECT_TYPE_MSK); | ||
340 | break; | ||
341 | } | ||
342 | |||
343 | /* translate the offset from words to byte */ | ||
344 | return (address & ADDRESS_MSK) + (offset << 1); | ||
345 | } | ||
346 | |||
347 | const u8 *iwl_eeprom_query_addr(struct iwl_priv *priv, size_t offset) | ||
348 | { | ||
349 | u32 address = eeprom_indirect_address(priv, offset); | ||
350 | BUG_ON(address >= priv->cfg->base_params->eeprom_size); | ||
351 | return &priv->eeprom[address]; | ||
352 | } | ||
353 | |||
354 | void iwl_eeprom_get_mac(struct iwl_priv *priv, u8 *mac) | ||
355 | { | ||
356 | const u8 *addr = iwl_eeprom_query_addr(priv, | ||
357 | EEPROM_MAC_ADDRESS); | ||
358 | memcpy(mac, addr, ETH_ALEN); | ||
359 | } | ||
360 | |||
361 | /****************************************************************************** | ||
362 | * | ||
363 | * OTP related functions | ||
364 | * | ||
365 | ******************************************************************************/ | ||
366 | |||
367 | static void iwl_set_otp_access(struct iwl_trans *trans, | ||
368 | enum iwl_access_mode mode) | ||
369 | { | ||
370 | iwl_read32(trans, CSR_OTP_GP_REG); | ||
371 | |||
372 | if (mode == IWL_OTP_ACCESS_ABSOLUTE) | ||
373 | iwl_clear_bit(trans, CSR_OTP_GP_REG, | ||
374 | CSR_OTP_GP_REG_OTP_ACCESS_MODE); | ||
375 | else | ||
376 | iwl_set_bit(trans, CSR_OTP_GP_REG, | ||
377 | CSR_OTP_GP_REG_OTP_ACCESS_MODE); | ||
378 | } | ||
379 | |||
380 | static int iwl_get_nvm_type(struct iwl_trans *trans, u32 hw_rev) | ||
381 | { | ||
382 | u32 otpgp; | ||
383 | int nvm_type; | ||
384 | |||
385 | /* OTP only valid for CP/PP and after */ | ||
386 | switch (hw_rev & CSR_HW_REV_TYPE_MSK) { | ||
387 | case CSR_HW_REV_TYPE_NONE: | ||
388 | IWL_ERR(trans, "Unknown hardware type\n"); | ||
389 | return -ENOENT; | ||
390 | case CSR_HW_REV_TYPE_5300: | ||
391 | case CSR_HW_REV_TYPE_5350: | ||
392 | case CSR_HW_REV_TYPE_5100: | ||
393 | case CSR_HW_REV_TYPE_5150: | ||
394 | nvm_type = NVM_DEVICE_TYPE_EEPROM; | ||
395 | break; | ||
396 | default: | ||
397 | otpgp = iwl_read32(trans, CSR_OTP_GP_REG); | ||
398 | if (otpgp & CSR_OTP_GP_REG_DEVICE_SELECT) | ||
399 | nvm_type = NVM_DEVICE_TYPE_OTP; | ||
400 | else | ||
401 | nvm_type = NVM_DEVICE_TYPE_EEPROM; | ||
402 | break; | ||
403 | } | ||
404 | return nvm_type; | ||
405 | } | ||
406 | |||
407 | static int iwl_init_otp_access(struct iwl_trans *trans) | ||
408 | { | ||
409 | int ret; | ||
410 | |||
411 | /* Enable 40MHz radio clock */ | ||
412 | iwl_write32(trans, CSR_GP_CNTRL, | ||
413 | iwl_read32(trans, CSR_GP_CNTRL) | | ||
414 | CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
415 | |||
416 | /* wait for clock to be ready */ | ||
417 | ret = iwl_poll_bit(trans, CSR_GP_CNTRL, | ||
418 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||
419 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||
420 | 25000); | ||
421 | if (ret < 0) | ||
422 | IWL_ERR(trans, "Time out access OTP\n"); | ||
423 | else { | ||
424 | iwl_set_bits_prph(trans, APMG_PS_CTRL_REG, | ||
425 | APMG_PS_CTRL_VAL_RESET_REQ); | ||
426 | udelay(5); | ||
427 | iwl_clear_bits_prph(trans, APMG_PS_CTRL_REG, | ||
428 | APMG_PS_CTRL_VAL_RESET_REQ); | ||
429 | |||
430 | /* | ||
431 | * CSR auto clock gate disable bit - | ||
432 | * this is only applicable for HW with OTP shadow RAM | ||
433 | */ | ||
434 | if (trans->cfg->base_params->shadow_ram_support) | ||
435 | iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG, | ||
436 | CSR_RESET_LINK_PWR_MGMT_DISABLED); | ||
437 | } | ||
438 | return ret; | ||
439 | } | ||
440 | |||
441 | static int iwl_read_otp_word(struct iwl_trans *trans, u16 addr, | ||
442 | __le16 *eeprom_data) | ||
443 | { | ||
444 | int ret = 0; | ||
445 | u32 r; | ||
446 | u32 otpgp; | ||
447 | |||
448 | iwl_write32(trans, CSR_EEPROM_REG, | ||
449 | CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); | ||
450 | ret = iwl_poll_bit(trans, CSR_EEPROM_REG, | ||
451 | CSR_EEPROM_REG_READ_VALID_MSK, | ||
452 | CSR_EEPROM_REG_READ_VALID_MSK, | ||
453 | IWL_EEPROM_ACCESS_TIMEOUT); | ||
454 | if (ret < 0) { | ||
455 | IWL_ERR(trans, "Time out reading OTP[%d]\n", addr); | ||
456 | return ret; | ||
457 | } | ||
458 | r = iwl_read32(trans, CSR_EEPROM_REG); | ||
459 | /* check for ECC errors: */ | ||
460 | otpgp = iwl_read32(trans, CSR_OTP_GP_REG); | ||
461 | if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) { | ||
462 | /* stop in this case */ | ||
463 | /* set the uncorrectable OTP ECC bit for acknowledgement */ | ||
464 | iwl_set_bit(trans, CSR_OTP_GP_REG, | ||
465 | CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); | ||
466 | IWL_ERR(trans, "Uncorrectable OTP ECC error, abort OTP read\n"); | ||
467 | return -EINVAL; | ||
468 | } | ||
469 | if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) { | ||
470 | /* continue in this case */ | ||
471 | /* set the correctable OTP ECC bit for acknowledgement */ | ||
472 | iwl_set_bit(trans, CSR_OTP_GP_REG, | ||
473 | CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK); | ||
474 | IWL_ERR(trans, "Correctable OTP ECC error, continue read\n"); | ||
475 | } | ||
476 | *eeprom_data = cpu_to_le16(r >> 16); | ||
477 | return 0; | ||
478 | } | ||
479 | |||
480 | /* | ||
481 | * iwl_is_otp_empty: check for empty OTP | ||
482 | */ | ||
483 | static bool iwl_is_otp_empty(struct iwl_trans *trans) | ||
484 | { | ||
485 | u16 next_link_addr = 0; | ||
486 | __le16 link_value; | ||
487 | bool is_empty = false; | ||
488 | |||
489 | /* locate the beginning of OTP link list */ | ||
490 | if (!iwl_read_otp_word(trans, next_link_addr, &link_value)) { | ||
491 | if (!link_value) { | ||
492 | IWL_ERR(trans, "OTP is empty\n"); | ||
493 | is_empty = true; | ||
494 | } | ||
495 | } else { | ||
496 | IWL_ERR(trans, "Unable to read first block of OTP list.\n"); | ||
497 | is_empty = true; | ||
498 | } | ||
499 | |||
500 | return is_empty; | ||
501 | } | ||
502 | |||
503 | |||
504 | /* | ||
505 | * iwl_find_otp_image: find EEPROM image in OTP | ||
506 | * finding the OTP block that contains the EEPROM image. | ||
507 | * the last valid block on the link list (the block _before_ the last block) | ||
508 | * is the block we should read and used to configure the device. | ||
509 | * If all the available OTP blocks are full, the last block will be the block | ||
510 | * we should read and used to configure the device. | ||
511 | * only perform this operation if shadow RAM is disabled | ||
512 | */ | ||
513 | static int iwl_find_otp_image(struct iwl_trans *trans, | ||
514 | u16 *validblockaddr) | ||
515 | { | ||
516 | u16 next_link_addr = 0, valid_addr; | ||
517 | __le16 link_value = 0; | ||
518 | int usedblocks = 0; | ||
519 | |||
520 | /* set addressing mode to absolute to traverse the link list */ | ||
521 | iwl_set_otp_access(trans, IWL_OTP_ACCESS_ABSOLUTE); | ||
522 | |||
523 | /* checking for empty OTP or error */ | ||
524 | if (iwl_is_otp_empty(trans)) | ||
525 | return -EINVAL; | ||
526 | |||
527 | /* | ||
528 | * start traverse link list | ||
529 | * until reach the max number of OTP blocks | ||
530 | * different devices have different number of OTP blocks | ||
531 | */ | ||
532 | do { | ||
533 | /* save current valid block address | ||
534 | * check for more block on the link list | ||
535 | */ | ||
536 | valid_addr = next_link_addr; | ||
537 | next_link_addr = le16_to_cpu(link_value) * sizeof(u16); | ||
538 | IWL_DEBUG_EEPROM(trans, "OTP blocks %d addr 0x%x\n", | ||
539 | usedblocks, next_link_addr); | ||
540 | if (iwl_read_otp_word(trans, next_link_addr, &link_value)) | ||
541 | return -EINVAL; | ||
542 | if (!link_value) { | ||
543 | /* | ||
544 | * reach the end of link list, return success and | ||
545 | * set address point to the starting address | ||
546 | * of the image | ||
547 | */ | ||
548 | *validblockaddr = valid_addr; | ||
549 | /* skip first 2 bytes (link list pointer) */ | ||
550 | *validblockaddr += 2; | ||
551 | return 0; | ||
552 | } | ||
553 | /* more in the link list, continue */ | ||
554 | usedblocks++; | ||
555 | } while (usedblocks <= trans->cfg->base_params->max_ll_items); | ||
556 | |||
557 | /* OTP has no valid blocks */ | ||
558 | IWL_DEBUG_EEPROM(trans, "OTP has no valid blocks\n"); | ||
559 | return -EINVAL; | ||
560 | } | ||
561 | |||
562 | /****************************************************************************** | ||
563 | * | ||
564 | * Tx Power related functions | ||
565 | * | ||
566 | ******************************************************************************/ | ||
567 | /** | ||
568 | * iwl_get_max_txpower_avg - get the highest tx power from all chains. | ||
569 | * find the highest tx power from all chains for the channel | ||
570 | */ | ||
571 | static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv, | ||
572 | struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, | ||
573 | int element, s8 *max_txpower_in_half_dbm) | ||
574 | { | ||
575 | s8 max_txpower_avg = 0; /* (dBm) */ | ||
576 | |||
577 | /* Take the highest tx power from any valid chains */ | ||
578 | if ((priv->hw_params.valid_tx_ant & ANT_A) && | ||
579 | (enhanced_txpower[element].chain_a_max > max_txpower_avg)) | ||
580 | max_txpower_avg = enhanced_txpower[element].chain_a_max; | ||
581 | if ((priv->hw_params.valid_tx_ant & ANT_B) && | ||
582 | (enhanced_txpower[element].chain_b_max > max_txpower_avg)) | ||
583 | max_txpower_avg = enhanced_txpower[element].chain_b_max; | ||
584 | if ((priv->hw_params.valid_tx_ant & ANT_C) && | ||
585 | (enhanced_txpower[element].chain_c_max > max_txpower_avg)) | ||
586 | max_txpower_avg = enhanced_txpower[element].chain_c_max; | ||
587 | if (((priv->hw_params.valid_tx_ant == ANT_AB) | | ||
588 | (priv->hw_params.valid_tx_ant == ANT_BC) | | ||
589 | (priv->hw_params.valid_tx_ant == ANT_AC)) && | ||
590 | (enhanced_txpower[element].mimo2_max > max_txpower_avg)) | ||
591 | max_txpower_avg = enhanced_txpower[element].mimo2_max; | ||
592 | if ((priv->hw_params.valid_tx_ant == ANT_ABC) && | ||
593 | (enhanced_txpower[element].mimo3_max > max_txpower_avg)) | ||
594 | max_txpower_avg = enhanced_txpower[element].mimo3_max; | ||
595 | |||
596 | /* | ||
597 | * max. tx power in EEPROM is in 1/2 dBm format | ||
598 | * convert from 1/2 dBm to dBm (round-up convert) | ||
599 | * but we also do not want to loss 1/2 dBm resolution which | ||
600 | * will impact performance | ||
601 | */ | ||
602 | *max_txpower_in_half_dbm = max_txpower_avg; | ||
603 | return (max_txpower_avg & 0x01) + (max_txpower_avg >> 1); | ||
604 | } | ||
605 | |||
606 | static void | ||
607 | iwl_eeprom_enh_txp_read_element(struct iwl_priv *priv, | ||
608 | struct iwl_eeprom_enhanced_txpwr *txp, | ||
609 | s8 max_txpower_avg) | ||
610 | { | ||
611 | int ch_idx; | ||
612 | bool is_ht40 = txp->flags & IWL_EEPROM_ENH_TXP_FL_40MHZ; | ||
613 | enum ieee80211_band band; | ||
614 | |||
615 | band = txp->flags & IWL_EEPROM_ENH_TXP_FL_BAND_52G ? | ||
616 | IEEE80211_BAND_5GHZ : IEEE80211_BAND_2GHZ; | ||
617 | |||
618 | for (ch_idx = 0; ch_idx < priv->channel_count; ch_idx++) { | ||
619 | struct iwl_channel_info *ch_info = &priv->channel_info[ch_idx]; | ||
620 | |||
621 | /* update matching channel or from common data only */ | ||
622 | if (txp->channel != 0 && ch_info->channel != txp->channel) | ||
623 | continue; | ||
624 | |||
625 | /* update matching band only */ | ||
626 | if (band != ch_info->band) | ||
627 | continue; | ||
628 | |||
629 | if (ch_info->max_power_avg < max_txpower_avg && !is_ht40) { | ||
630 | ch_info->max_power_avg = max_txpower_avg; | ||
631 | ch_info->curr_txpow = max_txpower_avg; | ||
632 | ch_info->scan_power = max_txpower_avg; | ||
633 | } | ||
634 | |||
635 | if (is_ht40 && ch_info->ht40_max_power_avg < max_txpower_avg) | ||
636 | ch_info->ht40_max_power_avg = max_txpower_avg; | ||
637 | } | ||
638 | } | ||
639 | |||
640 | #define EEPROM_TXP_OFFS (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT) | ||
641 | #define EEPROM_TXP_ENTRY_LEN sizeof(struct iwl_eeprom_enhanced_txpwr) | ||
642 | #define EEPROM_TXP_SZ_OFFS (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT_SIZE) | ||
643 | |||
644 | #define TXP_CHECK_AND_PRINT(x) ((txp->flags & IWL_EEPROM_ENH_TXP_FL_##x) \ | ||
645 | ? # x " " : "") | ||
646 | |||
647 | static void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv) | ||
648 | { | ||
649 | struct iwl_eeprom_enhanced_txpwr *txp_array, *txp; | ||
650 | int idx, entries; | ||
651 | __le16 *txp_len; | ||
652 | s8 max_txp_avg, max_txp_avg_halfdbm; | ||
653 | |||
654 | BUILD_BUG_ON(sizeof(struct iwl_eeprom_enhanced_txpwr) != 8); | ||
655 | |||
656 | /* the length is in 16-bit words, but we want entries */ | ||
657 | txp_len = (__le16 *) iwl_eeprom_query_addr(priv, EEPROM_TXP_SZ_OFFS); | ||
658 | entries = le16_to_cpup(txp_len) * 2 / EEPROM_TXP_ENTRY_LEN; | ||
659 | |||
660 | txp_array = (void *) iwl_eeprom_query_addr(priv, EEPROM_TXP_OFFS); | ||
661 | |||
662 | for (idx = 0; idx < entries; idx++) { | ||
663 | txp = &txp_array[idx]; | ||
664 | /* skip invalid entries */ | ||
665 | if (!(txp->flags & IWL_EEPROM_ENH_TXP_FL_VALID)) | ||
666 | continue; | ||
667 | |||
668 | IWL_DEBUG_EEPROM(priv, "%s %d:\t %s%s%s%s%s%s%s%s (0x%02x)\n", | ||
669 | (txp->channel && (txp->flags & | ||
670 | IWL_EEPROM_ENH_TXP_FL_COMMON_TYPE)) ? | ||
671 | "Common " : (txp->channel) ? | ||
672 | "Channel" : "Common", | ||
673 | (txp->channel), | ||
674 | TXP_CHECK_AND_PRINT(VALID), | ||
675 | TXP_CHECK_AND_PRINT(BAND_52G), | ||
676 | TXP_CHECK_AND_PRINT(OFDM), | ||
677 | TXP_CHECK_AND_PRINT(40MHZ), | ||
678 | TXP_CHECK_AND_PRINT(HT_AP), | ||
679 | TXP_CHECK_AND_PRINT(RES1), | ||
680 | TXP_CHECK_AND_PRINT(RES2), | ||
681 | TXP_CHECK_AND_PRINT(COMMON_TYPE), | ||
682 | txp->flags); | ||
683 | IWL_DEBUG_EEPROM(priv, "\t\t chain_A: 0x%02x " | ||
684 | "chain_B: 0X%02x chain_C: 0X%02x\n", | ||
685 | txp->chain_a_max, txp->chain_b_max, | ||
686 | txp->chain_c_max); | ||
687 | IWL_DEBUG_EEPROM(priv, "\t\t MIMO2: 0x%02x " | ||
688 | "MIMO3: 0x%02x High 20_on_40: 0x%02x " | ||
689 | "Low 20_on_40: 0x%02x\n", | ||
690 | txp->mimo2_max, txp->mimo3_max, | ||
691 | ((txp->delta_20_in_40 & 0xf0) >> 4), | ||
692 | (txp->delta_20_in_40 & 0x0f)); | ||
693 | |||
694 | max_txp_avg = iwl_get_max_txpower_avg(priv, txp_array, idx, | ||
695 | &max_txp_avg_halfdbm); | ||
696 | |||
697 | /* | ||
698 | * Update the user limit values values to the highest | ||
699 | * power supported by any channel | ||
700 | */ | ||
701 | if (max_txp_avg > priv->tx_power_user_lmt) | ||
702 | priv->tx_power_user_lmt = max_txp_avg; | ||
703 | if (max_txp_avg_halfdbm > priv->tx_power_lmt_in_half_dbm) | ||
704 | priv->tx_power_lmt_in_half_dbm = max_txp_avg_halfdbm; | ||
705 | |||
706 | iwl_eeprom_enh_txp_read_element(priv, txp, max_txp_avg); | ||
707 | } | ||
708 | } | ||
709 | |||
710 | /** | ||
711 | * iwl_eeprom_init - read EEPROM contents | ||
712 | * | ||
713 | * Load the EEPROM contents from adapter into priv->eeprom | ||
714 | * | ||
715 | * NOTE: This routine uses the non-debug IO access functions. | ||
716 | */ | ||
717 | int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) | ||
718 | { | ||
719 | __le16 *e; | ||
720 | u32 gp = iwl_read32(priv->trans, CSR_EEPROM_GP); | ||
721 | int sz; | ||
722 | int ret; | ||
723 | u16 addr; | ||
724 | u16 validblockaddr = 0; | ||
725 | u16 cache_addr = 0; | ||
726 | |||
727 | priv->nvm_device_type = iwl_get_nvm_type(priv->trans, hw_rev); | ||
728 | if (priv->nvm_device_type == -ENOENT) | ||
729 | return -ENOENT; | ||
730 | /* allocate eeprom */ | ||
731 | sz = priv->cfg->base_params->eeprom_size; | ||
732 | IWL_DEBUG_EEPROM(priv, "NVM size = %d\n", sz); | ||
733 | priv->eeprom = kzalloc(sz, GFP_KERNEL); | ||
734 | if (!priv->eeprom) { | ||
735 | ret = -ENOMEM; | ||
736 | goto alloc_err; | ||
737 | } | ||
738 | e = (__le16 *)priv->eeprom; | ||
739 | |||
740 | ret = iwl_eeprom_verify_signature(priv); | ||
741 | if (ret < 0) { | ||
742 | IWL_ERR(priv, "EEPROM not found, EEPROM_GP=0x%08x\n", gp); | ||
743 | ret = -ENOENT; | ||
744 | goto err; | ||
745 | } | ||
746 | |||
747 | /* Make sure driver (instead of uCode) is allowed to read EEPROM */ | ||
748 | ret = iwl_eeprom_acquire_semaphore(priv->trans); | ||
749 | if (ret < 0) { | ||
750 | IWL_ERR(priv, "Failed to acquire EEPROM semaphore.\n"); | ||
751 | ret = -ENOENT; | ||
752 | goto err; | ||
753 | } | ||
754 | |||
755 | if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) { | ||
756 | |||
757 | ret = iwl_init_otp_access(priv->trans); | ||
758 | if (ret) { | ||
759 | IWL_ERR(priv, "Failed to initialize OTP access.\n"); | ||
760 | ret = -ENOENT; | ||
761 | goto done; | ||
762 | } | ||
763 | iwl_write32(priv->trans, CSR_EEPROM_GP, | ||
764 | iwl_read32(priv->trans, CSR_EEPROM_GP) & | ||
765 | ~CSR_EEPROM_GP_IF_OWNER_MSK); | ||
766 | |||
767 | iwl_set_bit(priv->trans, CSR_OTP_GP_REG, | ||
768 | CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK | | ||
769 | CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); | ||
770 | /* traversing the linked list if no shadow ram supported */ | ||
771 | if (!priv->cfg->base_params->shadow_ram_support) { | ||
772 | if (iwl_find_otp_image(priv->trans, &validblockaddr)) { | ||
773 | ret = -ENOENT; | ||
774 | goto done; | ||
775 | } | ||
776 | } | ||
777 | for (addr = validblockaddr; addr < validblockaddr + sz; | ||
778 | addr += sizeof(u16)) { | ||
779 | __le16 eeprom_data; | ||
780 | |||
781 | ret = iwl_read_otp_word(priv->trans, addr, | ||
782 | &eeprom_data); | ||
783 | if (ret) | ||
784 | goto done; | ||
785 | e[cache_addr / 2] = eeprom_data; | ||
786 | cache_addr += sizeof(u16); | ||
787 | } | ||
788 | } else { | ||
789 | /* eeprom is an array of 16bit values */ | ||
790 | for (addr = 0; addr < sz; addr += sizeof(u16)) { | ||
791 | u32 r; | ||
792 | |||
793 | iwl_write32(priv->trans, CSR_EEPROM_REG, | ||
794 | CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); | ||
795 | |||
796 | ret = iwl_poll_bit(priv->trans, CSR_EEPROM_REG, | ||
797 | CSR_EEPROM_REG_READ_VALID_MSK, | ||
798 | CSR_EEPROM_REG_READ_VALID_MSK, | ||
799 | IWL_EEPROM_ACCESS_TIMEOUT); | ||
800 | if (ret < 0) { | ||
801 | IWL_ERR(priv, | ||
802 | "Time out reading EEPROM[%d]\n", addr); | ||
803 | goto done; | ||
804 | } | ||
805 | r = iwl_read32(priv->trans, CSR_EEPROM_REG); | ||
806 | e[addr / 2] = cpu_to_le16(r >> 16); | ||
807 | } | ||
808 | } | ||
809 | |||
810 | IWL_DEBUG_EEPROM(priv, "NVM Type: %s, version: 0x%x\n", | ||
811 | (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) | ||
812 | ? "OTP" : "EEPROM", | ||
813 | iwl_eeprom_query16(priv, EEPROM_VERSION)); | ||
814 | |||
815 | ret = 0; | ||
816 | done: | ||
817 | iwl_eeprom_release_semaphore(priv->trans); | ||
818 | |||
819 | err: | ||
820 | if (ret) | ||
821 | iwl_eeprom_free(priv); | ||
822 | alloc_err: | ||
823 | return ret; | ||
824 | } | ||
825 | |||
826 | void iwl_eeprom_free(struct iwl_priv *priv) | ||
827 | { | ||
828 | kfree(priv->eeprom); | ||
829 | priv->eeprom = NULL; | ||
830 | } | ||
831 | |||
832 | static void iwl_init_band_reference(struct iwl_priv *priv, | ||
833 | int eep_band, int *eeprom_ch_count, | ||
834 | const struct iwl_eeprom_channel **eeprom_ch_info, | ||
835 | const u8 **eeprom_ch_index) | ||
836 | { | ||
837 | u32 offset = priv->lib-> | ||
838 | eeprom_ops.regulatory_bands[eep_band - 1]; | ||
839 | switch (eep_band) { | ||
840 | case 1: /* 2.4GHz band */ | ||
841 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_1); | ||
842 | *eeprom_ch_info = (struct iwl_eeprom_channel *) | ||
843 | iwl_eeprom_query_addr(priv, offset); | ||
844 | *eeprom_ch_index = iwl_eeprom_band_1; | ||
845 | break; | ||
846 | case 2: /* 4.9GHz band */ | ||
847 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_2); | ||
848 | *eeprom_ch_info = (struct iwl_eeprom_channel *) | ||
849 | iwl_eeprom_query_addr(priv, offset); | ||
850 | *eeprom_ch_index = iwl_eeprom_band_2; | ||
851 | break; | ||
852 | case 3: /* 5.2GHz band */ | ||
853 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_3); | ||
854 | *eeprom_ch_info = (struct iwl_eeprom_channel *) | ||
855 | iwl_eeprom_query_addr(priv, offset); | ||
856 | *eeprom_ch_index = iwl_eeprom_band_3; | ||
857 | break; | ||
858 | case 4: /* 5.5GHz band */ | ||
859 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_4); | ||
860 | *eeprom_ch_info = (struct iwl_eeprom_channel *) | ||
861 | iwl_eeprom_query_addr(priv, offset); | ||
862 | *eeprom_ch_index = iwl_eeprom_band_4; | ||
863 | break; | ||
864 | case 5: /* 5.7GHz band */ | ||
865 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_5); | ||
866 | *eeprom_ch_info = (struct iwl_eeprom_channel *) | ||
867 | iwl_eeprom_query_addr(priv, offset); | ||
868 | *eeprom_ch_index = iwl_eeprom_band_5; | ||
869 | break; | ||
870 | case 6: /* 2.4GHz ht40 channels */ | ||
871 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_6); | ||
872 | *eeprom_ch_info = (struct iwl_eeprom_channel *) | ||
873 | iwl_eeprom_query_addr(priv, offset); | ||
874 | *eeprom_ch_index = iwl_eeprom_band_6; | ||
875 | break; | ||
876 | case 7: /* 5 GHz ht40 channels */ | ||
877 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_7); | ||
878 | *eeprom_ch_info = (struct iwl_eeprom_channel *) | ||
879 | iwl_eeprom_query_addr(priv, offset); | ||
880 | *eeprom_ch_index = iwl_eeprom_band_7; | ||
881 | break; | ||
882 | default: | ||
883 | BUG(); | ||
884 | return; | ||
885 | } | ||
886 | } | ||
887 | |||
888 | #define CHECK_AND_PRINT(x) ((eeprom_ch->flags & EEPROM_CHANNEL_##x) \ | ||
889 | ? # x " " : "") | ||
890 | /** | ||
891 | * iwl_mod_ht40_chan_info - Copy ht40 channel info into driver's priv. | ||
892 | * | ||
893 | * Does not set up a command, or touch hardware. | ||
894 | */ | ||
895 | static int iwl_mod_ht40_chan_info(struct iwl_priv *priv, | ||
896 | enum ieee80211_band band, u16 channel, | ||
897 | const struct iwl_eeprom_channel *eeprom_ch, | ||
898 | u8 clear_ht40_extension_channel) | ||
899 | { | ||
900 | struct iwl_channel_info *ch_info; | ||
901 | |||
902 | ch_info = (struct iwl_channel_info *) | ||
903 | iwl_get_channel_info(priv, band, channel); | ||
904 | |||
905 | if (!is_channel_valid(ch_info)) | ||
906 | return -1; | ||
907 | |||
908 | IWL_DEBUG_EEPROM(priv, "HT40 Ch. %d [%sGHz] %s%s%s%s%s(0x%02x %ddBm):" | ||
909 | " Ad-Hoc %ssupported\n", | ||
910 | ch_info->channel, | ||
911 | is_channel_a_band(ch_info) ? | ||
912 | "5.2" : "2.4", | ||
913 | CHECK_AND_PRINT(IBSS), | ||
914 | CHECK_AND_PRINT(ACTIVE), | ||
915 | CHECK_AND_PRINT(RADAR), | ||
916 | CHECK_AND_PRINT(WIDE), | ||
917 | CHECK_AND_PRINT(DFS), | ||
918 | eeprom_ch->flags, | ||
919 | eeprom_ch->max_power_avg, | ||
920 | ((eeprom_ch->flags & EEPROM_CHANNEL_IBSS) | ||
921 | && !(eeprom_ch->flags & EEPROM_CHANNEL_RADAR)) ? | ||
922 | "" : "not "); | ||
923 | |||
924 | ch_info->ht40_eeprom = *eeprom_ch; | ||
925 | ch_info->ht40_max_power_avg = eeprom_ch->max_power_avg; | ||
926 | ch_info->ht40_flags = eeprom_ch->flags; | ||
927 | if (eeprom_ch->flags & EEPROM_CHANNEL_VALID) | ||
928 | ch_info->ht40_extension_channel &= ~clear_ht40_extension_channel; | ||
929 | |||
930 | return 0; | ||
931 | } | ||
932 | |||
933 | #define CHECK_AND_PRINT_I(x) ((eeprom_ch_info[ch].flags & EEPROM_CHANNEL_##x) \ | ||
934 | ? # x " " : "") | ||
935 | |||
936 | /** | ||
937 | * iwl_init_channel_map - Set up driver's info for all possible channels | ||
938 | */ | ||
939 | int iwl_init_channel_map(struct iwl_priv *priv) | ||
940 | { | ||
941 | int eeprom_ch_count = 0; | ||
942 | const u8 *eeprom_ch_index = NULL; | ||
943 | const struct iwl_eeprom_channel *eeprom_ch_info = NULL; | ||
944 | int band, ch; | ||
945 | struct iwl_channel_info *ch_info; | ||
946 | |||
947 | if (priv->channel_count) { | ||
948 | IWL_DEBUG_EEPROM(priv, "Channel map already initialized.\n"); | ||
949 | return 0; | ||
950 | } | ||
951 | |||
952 | IWL_DEBUG_EEPROM(priv, "Initializing regulatory info from EEPROM\n"); | ||
953 | |||
954 | priv->channel_count = | ||
955 | ARRAY_SIZE(iwl_eeprom_band_1) + | ||
956 | ARRAY_SIZE(iwl_eeprom_band_2) + | ||
957 | ARRAY_SIZE(iwl_eeprom_band_3) + | ||
958 | ARRAY_SIZE(iwl_eeprom_band_4) + | ||
959 | ARRAY_SIZE(iwl_eeprom_band_5); | ||
960 | |||
961 | IWL_DEBUG_EEPROM(priv, "Parsing data for %d channels.\n", | ||
962 | priv->channel_count); | ||
963 | |||
964 | priv->channel_info = kcalloc(priv->channel_count, | ||
965 | sizeof(struct iwl_channel_info), | ||
966 | GFP_KERNEL); | ||
967 | if (!priv->channel_info) { | ||
968 | IWL_ERR(priv, "Could not allocate channel_info\n"); | ||
969 | priv->channel_count = 0; | ||
970 | return -ENOMEM; | ||
971 | } | ||
972 | |||
973 | ch_info = priv->channel_info; | ||
974 | |||
975 | /* Loop through the 5 EEPROM bands adding them in order to the | ||
976 | * channel map we maintain (that contains additional information than | ||
977 | * what just in the EEPROM) */ | ||
978 | for (band = 1; band <= 5; band++) { | ||
979 | |||
980 | iwl_init_band_reference(priv, band, &eeprom_ch_count, | ||
981 | &eeprom_ch_info, &eeprom_ch_index); | ||
982 | |||
983 | /* Loop through each band adding each of the channels */ | ||
984 | for (ch = 0; ch < eeprom_ch_count; ch++) { | ||
985 | ch_info->channel = eeprom_ch_index[ch]; | ||
986 | ch_info->band = (band == 1) ? IEEE80211_BAND_2GHZ : | ||
987 | IEEE80211_BAND_5GHZ; | ||
988 | |||
989 | /* permanently store EEPROM's channel regulatory flags | ||
990 | * and max power in channel info database. */ | ||
991 | ch_info->eeprom = eeprom_ch_info[ch]; | ||
992 | |||
993 | /* Copy the run-time flags so they are there even on | ||
994 | * invalid channels */ | ||
995 | ch_info->flags = eeprom_ch_info[ch].flags; | ||
996 | /* First write that ht40 is not enabled, and then enable | ||
997 | * one by one */ | ||
998 | ch_info->ht40_extension_channel = | ||
999 | IEEE80211_CHAN_NO_HT40; | ||
1000 | |||
1001 | if (!(is_channel_valid(ch_info))) { | ||
1002 | IWL_DEBUG_EEPROM(priv, | ||
1003 | "Ch. %d Flags %x [%sGHz] - " | ||
1004 | "No traffic\n", | ||
1005 | ch_info->channel, | ||
1006 | ch_info->flags, | ||
1007 | is_channel_a_band(ch_info) ? | ||
1008 | "5.2" : "2.4"); | ||
1009 | ch_info++; | ||
1010 | continue; | ||
1011 | } | ||
1012 | |||
1013 | /* Initialize regulatory-based run-time data */ | ||
1014 | ch_info->max_power_avg = ch_info->curr_txpow = | ||
1015 | eeprom_ch_info[ch].max_power_avg; | ||
1016 | ch_info->scan_power = eeprom_ch_info[ch].max_power_avg; | ||
1017 | ch_info->min_power = 0; | ||
1018 | |||
1019 | IWL_DEBUG_EEPROM(priv, "Ch. %d [%sGHz] " | ||
1020 | "%s%s%s%s%s%s(0x%02x %ddBm):" | ||
1021 | " Ad-Hoc %ssupported\n", | ||
1022 | ch_info->channel, | ||
1023 | is_channel_a_band(ch_info) ? | ||
1024 | "5.2" : "2.4", | ||
1025 | CHECK_AND_PRINT_I(VALID), | ||
1026 | CHECK_AND_PRINT_I(IBSS), | ||
1027 | CHECK_AND_PRINT_I(ACTIVE), | ||
1028 | CHECK_AND_PRINT_I(RADAR), | ||
1029 | CHECK_AND_PRINT_I(WIDE), | ||
1030 | CHECK_AND_PRINT_I(DFS), | ||
1031 | eeprom_ch_info[ch].flags, | ||
1032 | eeprom_ch_info[ch].max_power_avg, | ||
1033 | ((eeprom_ch_info[ch]. | ||
1034 | flags & EEPROM_CHANNEL_IBSS) | ||
1035 | && !(eeprom_ch_info[ch]. | ||
1036 | flags & EEPROM_CHANNEL_RADAR)) | ||
1037 | ? "" : "not "); | ||
1038 | |||
1039 | ch_info++; | ||
1040 | } | ||
1041 | } | ||
1042 | |||
1043 | /* Check if we do have HT40 channels */ | ||
1044 | if (priv->lib->eeprom_ops.regulatory_bands[5] == | ||
1045 | EEPROM_REGULATORY_BAND_NO_HT40 && | ||
1046 | priv->lib->eeprom_ops.regulatory_bands[6] == | ||
1047 | EEPROM_REGULATORY_BAND_NO_HT40) | ||
1048 | return 0; | ||
1049 | |||
1050 | /* Two additional EEPROM bands for 2.4 and 5 GHz HT40 channels */ | ||
1051 | for (band = 6; band <= 7; band++) { | ||
1052 | enum ieee80211_band ieeeband; | ||
1053 | |||
1054 | iwl_init_band_reference(priv, band, &eeprom_ch_count, | ||
1055 | &eeprom_ch_info, &eeprom_ch_index); | ||
1056 | |||
1057 | /* EEPROM band 6 is 2.4, band 7 is 5 GHz */ | ||
1058 | ieeeband = | ||
1059 | (band == 6) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; | ||
1060 | |||
1061 | /* Loop through each band adding each of the channels */ | ||
1062 | for (ch = 0; ch < eeprom_ch_count; ch++) { | ||
1063 | /* Set up driver's info for lower half */ | ||
1064 | iwl_mod_ht40_chan_info(priv, ieeeband, | ||
1065 | eeprom_ch_index[ch], | ||
1066 | &eeprom_ch_info[ch], | ||
1067 | IEEE80211_CHAN_NO_HT40PLUS); | ||
1068 | |||
1069 | /* Set up driver's info for upper half */ | ||
1070 | iwl_mod_ht40_chan_info(priv, ieeeband, | ||
1071 | eeprom_ch_index[ch] + 4, | ||
1072 | &eeprom_ch_info[ch], | ||
1073 | IEEE80211_CHAN_NO_HT40MINUS); | ||
1074 | } | ||
1075 | } | ||
1076 | |||
1077 | /* for newer device (6000 series and up) | ||
1078 | * EEPROM contain enhanced tx power information | ||
1079 | * driver need to process addition information | ||
1080 | * to determine the max channel tx power limits | ||
1081 | */ | ||
1082 | if (priv->lib->eeprom_ops.enhanced_txpower) | ||
1083 | iwl_eeprom_enhanced_txpower(priv); | ||
1084 | |||
1085 | return 0; | ||
1086 | } | ||
1087 | |||
1088 | /* | ||
1089 | * iwl_free_channel_map - undo allocations in iwl_init_channel_map | ||
1090 | */ | ||
1091 | void iwl_free_channel_map(struct iwl_priv *priv) | ||
1092 | { | ||
1093 | kfree(priv->channel_info); | ||
1094 | priv->channel_count = 0; | ||
1095 | } | ||
1096 | |||
1097 | /** | ||
1098 | * iwl_get_channel_info - Find driver's private channel info | ||
1099 | * | ||
1100 | * Based on band and channel number. | ||
1101 | */ | ||
1102 | const struct iwl_channel_info *iwl_get_channel_info(const struct iwl_priv *priv, | ||
1103 | enum ieee80211_band band, u16 channel) | ||
1104 | { | ||
1105 | int i; | ||
1106 | |||
1107 | switch (band) { | ||
1108 | case IEEE80211_BAND_5GHZ: | ||
1109 | for (i = 14; i < priv->channel_count; i++) { | ||
1110 | if (priv->channel_info[i].channel == channel) | ||
1111 | return &priv->channel_info[i]; | ||
1112 | } | ||
1113 | break; | ||
1114 | case IEEE80211_BAND_2GHZ: | ||
1115 | if (channel >= 1 && channel <= 14) | ||
1116 | return &priv->channel_info[channel - 1]; | ||
1117 | break; | ||
1118 | default: | ||
1119 | BUG(); | ||
1120 | } | ||
1121 | |||
1122 | return NULL; | ||
1123 | } | ||
1124 | |||
1125 | void iwl_rf_config(struct iwl_priv *priv) | ||
1126 | { | ||
1127 | u16 radio_cfg; | ||
1128 | |||
1129 | radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); | ||
1130 | |||
1131 | /* write radio config values to register */ | ||
1132 | if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX) { | ||
1133 | iwl_set_bit(priv->trans, CSR_HW_IF_CONFIG_REG, | ||
1134 | EEPROM_RF_CFG_TYPE_MSK(radio_cfg) | | ||
1135 | EEPROM_RF_CFG_STEP_MSK(radio_cfg) | | ||
1136 | EEPROM_RF_CFG_DASH_MSK(radio_cfg)); | ||
1137 | IWL_INFO(priv, "Radio type=0x%x-0x%x-0x%x\n", | ||
1138 | EEPROM_RF_CFG_TYPE_MSK(radio_cfg), | ||
1139 | EEPROM_RF_CFG_STEP_MSK(radio_cfg), | ||
1140 | EEPROM_RF_CFG_DASH_MSK(radio_cfg)); | ||
1141 | } else | ||
1142 | WARN_ON(1); | ||
1143 | |||
1144 | /* set CSR_HW_CONFIG_REG for uCode use */ | ||
1145 | iwl_set_bit(priv->trans, CSR_HW_IF_CONFIG_REG, | ||
1146 | CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | | ||
1147 | CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); | ||
1148 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h deleted file mode 100644 index 64bfd947cae..00000000000 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ /dev/null | |||
@@ -1,269 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | *****************************************************************************/ | ||
62 | |||
63 | #ifndef __iwl_eeprom_h__ | ||
64 | #define __iwl_eeprom_h__ | ||
65 | |||
66 | #include <net/mac80211.h> | ||
67 | |||
68 | struct iwl_priv; | ||
69 | |||
70 | /* | ||
71 | * EEPROM access time values: | ||
72 | * | ||
73 | * Driver initiates EEPROM read by writing byte address << 1 to CSR_EEPROM_REG. | ||
74 | * Driver then polls CSR_EEPROM_REG for CSR_EEPROM_REG_READ_VALID_MSK (0x1). | ||
75 | * When polling, wait 10 uSec between polling loops, up to a maximum 5000 uSec. | ||
76 | * Driver reads 16-bit value from bits 31-16 of CSR_EEPROM_REG. | ||
77 | */ | ||
78 | #define IWL_EEPROM_ACCESS_TIMEOUT 5000 /* uSec */ | ||
79 | |||
80 | #define IWL_EEPROM_SEM_TIMEOUT 10 /* microseconds */ | ||
81 | #define IWL_EEPROM_SEM_RETRY_LIMIT 1000 /* number of attempts (not time) */ | ||
82 | |||
83 | |||
84 | /* | ||
85 | * Regulatory channel usage flags in EEPROM struct iwl4965_eeprom_channel.flags. | ||
86 | * | ||
87 | * IBSS and/or AP operation is allowed *only* on those channels with | ||
88 | * (VALID && IBSS && ACTIVE && !RADAR). This restriction is in place because | ||
89 | * RADAR detection is not supported by the 4965 driver, but is a | ||
90 | * requirement for establishing a new network for legal operation on channels | ||
91 | * requiring RADAR detection or restricting ACTIVE scanning. | ||
92 | * | ||
93 | * NOTE: "WIDE" flag does not indicate anything about "HT40" 40 MHz channels. | ||
94 | * It only indicates that 20 MHz channel use is supported; HT40 channel | ||
95 | * usage is indicated by a separate set of regulatory flags for each | ||
96 | * HT40 channel pair. | ||
97 | * | ||
98 | * NOTE: Using a channel inappropriately will result in a uCode error! | ||
99 | */ | ||
100 | #define IWL_NUM_TX_CALIB_GROUPS 5 | ||
101 | enum { | ||
102 | EEPROM_CHANNEL_VALID = (1 << 0), /* usable for this SKU/geo */ | ||
103 | EEPROM_CHANNEL_IBSS = (1 << 1), /* usable as an IBSS channel */ | ||
104 | /* Bit 2 Reserved */ | ||
105 | EEPROM_CHANNEL_ACTIVE = (1 << 3), /* active scanning allowed */ | ||
106 | EEPROM_CHANNEL_RADAR = (1 << 4), /* radar detection required */ | ||
107 | EEPROM_CHANNEL_WIDE = (1 << 5), /* 20 MHz channel okay */ | ||
108 | /* Bit 6 Reserved (was Narrow Channel) */ | ||
109 | EEPROM_CHANNEL_DFS = (1 << 7), /* dynamic freq selection candidate */ | ||
110 | }; | ||
111 | |||
112 | /* SKU Capabilities */ | ||
113 | #define EEPROM_SKU_CAP_BAND_24GHZ (1 << 4) | ||
114 | #define EEPROM_SKU_CAP_BAND_52GHZ (1 << 5) | ||
115 | #define EEPROM_SKU_CAP_11N_ENABLE (1 << 6) | ||
116 | #define EEPROM_SKU_CAP_AMT_ENABLE (1 << 7) | ||
117 | #define EEPROM_SKU_CAP_IPAN_ENABLE (1 << 8) | ||
118 | |||
119 | /* *regulatory* channel data format in eeprom, one for each channel. | ||
120 | * There are separate entries for HT40 (40 MHz) vs. normal (20 MHz) channels. */ | ||
121 | struct iwl_eeprom_channel { | ||
122 | u8 flags; /* EEPROM_CHANNEL_* flags copied from EEPROM */ | ||
123 | s8 max_power_avg; /* max power (dBm) on this chnl, limit 31 */ | ||
124 | } __packed; | ||
125 | |||
126 | enum iwl_eeprom_enhanced_txpwr_flags { | ||
127 | IWL_EEPROM_ENH_TXP_FL_VALID = BIT(0), | ||
128 | IWL_EEPROM_ENH_TXP_FL_BAND_52G = BIT(1), | ||
129 | IWL_EEPROM_ENH_TXP_FL_OFDM = BIT(2), | ||
130 | IWL_EEPROM_ENH_TXP_FL_40MHZ = BIT(3), | ||
131 | IWL_EEPROM_ENH_TXP_FL_HT_AP = BIT(4), | ||
132 | IWL_EEPROM_ENH_TXP_FL_RES1 = BIT(5), | ||
133 | IWL_EEPROM_ENH_TXP_FL_RES2 = BIT(6), | ||
134 | IWL_EEPROM_ENH_TXP_FL_COMMON_TYPE = BIT(7), | ||
135 | }; | ||
136 | |||
137 | /** | ||
138 | * iwl_eeprom_enhanced_txpwr structure | ||
139 | * This structure presents the enhanced regulatory tx power limit layout | ||
140 | * in eeprom image | ||
141 | * Enhanced regulatory tx power portion of eeprom image can be broken down | ||
142 | * into individual structures; each one is 8 bytes in size and contain the | ||
143 | * following information | ||
144 | * @flags: entry flags | ||
145 | * @channel: channel number | ||
146 | * @chain_a_max_pwr: chain a max power in 1/2 dBm | ||
147 | * @chain_b_max_pwr: chain b max power in 1/2 dBm | ||
148 | * @chain_c_max_pwr: chain c max power in 1/2 dBm | ||
149 | * @delta_20_in_40: 20-in-40 deltas (hi/lo) | ||
150 | * @mimo2_max_pwr: mimo2 max power in 1/2 dBm | ||
151 | * @mimo3_max_pwr: mimo3 max power in 1/2 dBm | ||
152 | * | ||
153 | */ | ||
154 | struct iwl_eeprom_enhanced_txpwr { | ||
155 | u8 flags; | ||
156 | u8 channel; | ||
157 | s8 chain_a_max; | ||
158 | s8 chain_b_max; | ||
159 | s8 chain_c_max; | ||
160 | u8 delta_20_in_40; | ||
161 | s8 mimo2_max; | ||
162 | s8 mimo3_max; | ||
163 | } __packed; | ||
164 | |||
165 | /* calibration */ | ||
166 | struct iwl_eeprom_calib_hdr { | ||
167 | u8 version; | ||
168 | u8 pa_type; | ||
169 | __le16 voltage; | ||
170 | } __packed; | ||
171 | |||
172 | #define EEPROM_CALIB_ALL (INDIRECT_ADDRESS | INDIRECT_CALIBRATION) | ||
173 | #define EEPROM_XTAL ((2*0x128) | EEPROM_CALIB_ALL) | ||
174 | |||
175 | /* temperature */ | ||
176 | #define EEPROM_KELVIN_TEMPERATURE ((2*0x12A) | EEPROM_CALIB_ALL) | ||
177 | #define EEPROM_RAW_TEMPERATURE ((2*0x12B) | EEPROM_CALIB_ALL) | ||
178 | |||
179 | |||
180 | /* agn links */ | ||
181 | #define EEPROM_LINK_HOST (2*0x64) | ||
182 | #define EEPROM_LINK_GENERAL (2*0x65) | ||
183 | #define EEPROM_LINK_REGULATORY (2*0x66) | ||
184 | #define EEPROM_LINK_CALIBRATION (2*0x67) | ||
185 | #define EEPROM_LINK_PROCESS_ADJST (2*0x68) | ||
186 | #define EEPROM_LINK_OTHERS (2*0x69) | ||
187 | #define EEPROM_LINK_TXP_LIMIT (2*0x6a) | ||
188 | #define EEPROM_LINK_TXP_LIMIT_SIZE (2*0x6b) | ||
189 | |||
190 | /* agn regulatory - indirect access */ | ||
191 | #define EEPROM_REG_BAND_1_CHANNELS ((0x08)\ | ||
192 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 28 bytes */ | ||
193 | #define EEPROM_REG_BAND_2_CHANNELS ((0x26)\ | ||
194 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 26 bytes */ | ||
195 | #define EEPROM_REG_BAND_3_CHANNELS ((0x42)\ | ||
196 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 24 bytes */ | ||
197 | #define EEPROM_REG_BAND_4_CHANNELS ((0x5C)\ | ||
198 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 22 bytes */ | ||
199 | #define EEPROM_REG_BAND_5_CHANNELS ((0x74)\ | ||
200 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 12 bytes */ | ||
201 | #define EEPROM_REG_BAND_24_HT40_CHANNELS ((0x82)\ | ||
202 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 14 bytes */ | ||
203 | #define EEPROM_REG_BAND_52_HT40_CHANNELS ((0x92)\ | ||
204 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 22 bytes */ | ||
205 | |||
206 | /* 6000 regulatory - indirect access */ | ||
207 | #define EEPROM_6000_REG_BAND_24_HT40_CHANNELS ((0x80)\ | ||
208 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 14 bytes */ | ||
209 | /* 2.4 GHz */ | ||
210 | extern const u8 iwl_eeprom_band_1[14]; | ||
211 | |||
212 | #define ADDRESS_MSK 0x0000FFFF | ||
213 | #define INDIRECT_TYPE_MSK 0x000F0000 | ||
214 | #define INDIRECT_HOST 0x00010000 | ||
215 | #define INDIRECT_GENERAL 0x00020000 | ||
216 | #define INDIRECT_REGULATORY 0x00030000 | ||
217 | #define INDIRECT_CALIBRATION 0x00040000 | ||
218 | #define INDIRECT_PROCESS_ADJST 0x00050000 | ||
219 | #define INDIRECT_OTHERS 0x00060000 | ||
220 | #define INDIRECT_TXP_LIMIT 0x00070000 | ||
221 | #define INDIRECT_TXP_LIMIT_SIZE 0x00080000 | ||
222 | #define INDIRECT_ADDRESS 0x00100000 | ||
223 | |||
224 | /* General */ | ||
225 | #define EEPROM_DEVICE_ID (2*0x08) /* 2 bytes */ | ||
226 | #define EEPROM_SUBSYSTEM_ID (2*0x0A) /* 2 bytes */ | ||
227 | #define EEPROM_MAC_ADDRESS (2*0x15) /* 6 bytes */ | ||
228 | #define EEPROM_BOARD_REVISION (2*0x35) /* 2 bytes */ | ||
229 | #define EEPROM_BOARD_PBA_NUMBER (2*0x3B+1) /* 9 bytes */ | ||
230 | #define EEPROM_VERSION (2*0x44) /* 2 bytes */ | ||
231 | #define EEPROM_SKU_CAP (2*0x45) /* 2 bytes */ | ||
232 | #define EEPROM_OEM_MODE (2*0x46) /* 2 bytes */ | ||
233 | #define EEPROM_RADIO_CONFIG (2*0x48) /* 2 bytes */ | ||
234 | #define EEPROM_NUM_MAC_ADDRESS (2*0x4C) /* 2 bytes */ | ||
235 | |||
236 | /* The following masks are to be applied on EEPROM_RADIO_CONFIG */ | ||
237 | #define EEPROM_RF_CFG_TYPE_MSK(x) (x & 0x3) /* bits 0-1 */ | ||
238 | #define EEPROM_RF_CFG_STEP_MSK(x) ((x >> 2) & 0x3) /* bits 2-3 */ | ||
239 | #define EEPROM_RF_CFG_DASH_MSK(x) ((x >> 4) & 0x3) /* bits 4-5 */ | ||
240 | #define EEPROM_RF_CFG_PNUM_MSK(x) ((x >> 6) & 0x3) /* bits 6-7 */ | ||
241 | #define EEPROM_RF_CFG_TX_ANT_MSK(x) ((x >> 8) & 0xF) /* bits 8-11 */ | ||
242 | #define EEPROM_RF_CFG_RX_ANT_MSK(x) ((x >> 12) & 0xF) /* bits 12-15 */ | ||
243 | |||
244 | #define EEPROM_RF_CONFIG_TYPE_MAX 0x3 | ||
245 | |||
246 | #define EEPROM_REGULATORY_BAND_NO_HT40 (0) | ||
247 | |||
248 | struct iwl_eeprom_ops { | ||
249 | const u32 regulatory_bands[7]; | ||
250 | bool enhanced_txpower; | ||
251 | }; | ||
252 | |||
253 | |||
254 | int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev); | ||
255 | void iwl_eeprom_free(struct iwl_priv *priv); | ||
256 | int iwl_eeprom_check_version(struct iwl_priv *priv); | ||
257 | int iwl_eeprom_init_hw_params(struct iwl_priv *priv); | ||
258 | u16 iwl_eeprom_calib_version(struct iwl_priv *priv); | ||
259 | const u8 *iwl_eeprom_query_addr(struct iwl_priv *priv, size_t offset); | ||
260 | u16 iwl_eeprom_query16(struct iwl_priv *priv, size_t offset); | ||
261 | void iwl_eeprom_get_mac(struct iwl_priv *priv, u8 *mac); | ||
262 | int iwl_init_channel_map(struct iwl_priv *priv); | ||
263 | void iwl_free_channel_map(struct iwl_priv *priv); | ||
264 | const struct iwl_channel_info *iwl_get_channel_info( | ||
265 | const struct iwl_priv *priv, | ||
266 | enum ieee80211_band band, u16 channel); | ||
267 | void iwl_rf_config(struct iwl_priv *priv); | ||
268 | |||
269 | #endif /* __iwl_eeprom_h__ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h index 74bce97a860..80604664174 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/iwlwifi/iwl-fh.h | |||
@@ -421,6 +421,8 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(unsigned int chnl) | |||
421 | (FH_SRVC_LOWER_BOUND + ((_chnl) - 9) * 0x4) | 421 | (FH_SRVC_LOWER_BOUND + ((_chnl) - 9) * 0x4) |
422 | 422 | ||
423 | #define FH_TX_CHICKEN_BITS_REG (FH_MEM_LOWER_BOUND + 0xE98) | 423 | #define FH_TX_CHICKEN_BITS_REG (FH_MEM_LOWER_BOUND + 0xE98) |
424 | #define FH_TX_TRB_REG(_chan) (FH_MEM_LOWER_BOUND + 0x958 + (_chan) * 4) | ||
425 | |||
424 | /* Instruct FH to increment the retry count of a packet when | 426 | /* Instruct FH to increment the retry count of a packet when |
425 | * it is brought from the memory to TX-FIFO | 427 | * it is brought from the memory to TX-FIFO |
426 | */ | 428 | */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c index ee93274214d..66c873399ab 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/iwlwifi/iwl-io.c | |||
@@ -65,6 +65,24 @@ void iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask) | |||
65 | } | 65 | } |
66 | EXPORT_SYMBOL_GPL(iwl_clear_bit); | 66 | EXPORT_SYMBOL_GPL(iwl_clear_bit); |
67 | 67 | ||
68 | void iwl_set_bits_mask(struct iwl_trans *trans, u32 reg, u32 mask, u32 value) | ||
69 | { | ||
70 | unsigned long flags; | ||
71 | u32 v; | ||
72 | |||
73 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
74 | WARN_ON_ONCE(value & ~mask); | ||
75 | #endif | ||
76 | |||
77 | spin_lock_irqsave(&trans->reg_lock, flags); | ||
78 | v = iwl_read32(trans, reg); | ||
79 | v &= ~mask; | ||
80 | v |= value; | ||
81 | iwl_write32(trans, reg, v); | ||
82 | spin_unlock_irqrestore(&trans->reg_lock, flags); | ||
83 | } | ||
84 | EXPORT_SYMBOL_GPL(iwl_set_bits_mask); | ||
85 | |||
68 | int iwl_poll_bit(struct iwl_trans *trans, u32 addr, | 86 | int iwl_poll_bit(struct iwl_trans *trans, u32 addr, |
69 | u32 bits, u32 mask, int timeout) | 87 | u32 bits, u32 mask, int timeout) |
70 | { | 88 | { |
@@ -280,8 +298,8 @@ void iwl_clear_bits_prph(struct iwl_trans *trans, u32 reg, u32 mask) | |||
280 | } | 298 | } |
281 | EXPORT_SYMBOL_GPL(iwl_clear_bits_prph); | 299 | EXPORT_SYMBOL_GPL(iwl_clear_bits_prph); |
282 | 300 | ||
283 | void _iwl_read_targ_mem_words(struct iwl_trans *trans, u32 addr, | 301 | void _iwl_read_targ_mem_dwords(struct iwl_trans *trans, u32 addr, |
284 | void *buf, int words) | 302 | void *buf, int dwords) |
285 | { | 303 | { |
286 | unsigned long flags; | 304 | unsigned long flags; |
287 | int offs; | 305 | int offs; |
@@ -290,26 +308,26 @@ void _iwl_read_targ_mem_words(struct iwl_trans *trans, u32 addr, | |||
290 | spin_lock_irqsave(&trans->reg_lock, flags); | 308 | spin_lock_irqsave(&trans->reg_lock, flags); |
291 | if (likely(iwl_grab_nic_access(trans))) { | 309 | if (likely(iwl_grab_nic_access(trans))) { |
292 | iwl_write32(trans, HBUS_TARG_MEM_RADDR, addr); | 310 | iwl_write32(trans, HBUS_TARG_MEM_RADDR, addr); |
293 | for (offs = 0; offs < words; offs++) | 311 | for (offs = 0; offs < dwords; offs++) |
294 | vals[offs] = iwl_read32(trans, HBUS_TARG_MEM_RDAT); | 312 | vals[offs] = iwl_read32(trans, HBUS_TARG_MEM_RDAT); |
295 | iwl_release_nic_access(trans); | 313 | iwl_release_nic_access(trans); |
296 | } | 314 | } |
297 | spin_unlock_irqrestore(&trans->reg_lock, flags); | 315 | spin_unlock_irqrestore(&trans->reg_lock, flags); |
298 | } | 316 | } |
299 | EXPORT_SYMBOL_GPL(_iwl_read_targ_mem_words); | 317 | EXPORT_SYMBOL_GPL(_iwl_read_targ_mem_dwords); |
300 | 318 | ||
301 | u32 iwl_read_targ_mem(struct iwl_trans *trans, u32 addr) | 319 | u32 iwl_read_targ_mem(struct iwl_trans *trans, u32 addr) |
302 | { | 320 | { |
303 | u32 value; | 321 | u32 value; |
304 | 322 | ||
305 | _iwl_read_targ_mem_words(trans, addr, &value, 1); | 323 | _iwl_read_targ_mem_dwords(trans, addr, &value, 1); |
306 | 324 | ||
307 | return value; | 325 | return value; |
308 | } | 326 | } |
309 | EXPORT_SYMBOL_GPL(iwl_read_targ_mem); | 327 | EXPORT_SYMBOL_GPL(iwl_read_targ_mem); |
310 | 328 | ||
311 | int _iwl_write_targ_mem_words(struct iwl_trans *trans, u32 addr, | 329 | int _iwl_write_targ_mem_dwords(struct iwl_trans *trans, u32 addr, |
312 | void *buf, int words) | 330 | void *buf, int dwords) |
313 | { | 331 | { |
314 | unsigned long flags; | 332 | unsigned long flags; |
315 | int offs, result = 0; | 333 | int offs, result = 0; |
@@ -318,7 +336,7 @@ int _iwl_write_targ_mem_words(struct iwl_trans *trans, u32 addr, | |||
318 | spin_lock_irqsave(&trans->reg_lock, flags); | 336 | spin_lock_irqsave(&trans->reg_lock, flags); |
319 | if (likely(iwl_grab_nic_access(trans))) { | 337 | if (likely(iwl_grab_nic_access(trans))) { |
320 | iwl_write32(trans, HBUS_TARG_MEM_WADDR, addr); | 338 | iwl_write32(trans, HBUS_TARG_MEM_WADDR, addr); |
321 | for (offs = 0; offs < words; offs++) | 339 | for (offs = 0; offs < dwords; offs++) |
322 | iwl_write32(trans, HBUS_TARG_MEM_WDAT, vals[offs]); | 340 | iwl_write32(trans, HBUS_TARG_MEM_WDAT, vals[offs]); |
323 | iwl_release_nic_access(trans); | 341 | iwl_release_nic_access(trans); |
324 | } else | 342 | } else |
@@ -327,10 +345,10 @@ int _iwl_write_targ_mem_words(struct iwl_trans *trans, u32 addr, | |||
327 | 345 | ||
328 | return result; | 346 | return result; |
329 | } | 347 | } |
330 | EXPORT_SYMBOL_GPL(_iwl_write_targ_mem_words); | 348 | EXPORT_SYMBOL_GPL(_iwl_write_targ_mem_dwords); |
331 | 349 | ||
332 | int iwl_write_targ_mem(struct iwl_trans *trans, u32 addr, u32 val) | 350 | int iwl_write_targ_mem(struct iwl_trans *trans, u32 addr, u32 val) |
333 | { | 351 | { |
334 | return _iwl_write_targ_mem_words(trans, addr, &val, 1); | 352 | return _iwl_write_targ_mem_dwords(trans, addr, &val, 1); |
335 | } | 353 | } |
336 | EXPORT_SYMBOL_GPL(iwl_write_targ_mem); | 354 | EXPORT_SYMBOL_GPL(iwl_write_targ_mem); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index abb3250164b..50d3819739d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h | |||
@@ -54,6 +54,8 @@ static inline u32 iwl_read32(struct iwl_trans *trans, u32 ofs) | |||
54 | void iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask); | 54 | void iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask); |
55 | void iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask); | 55 | void iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask); |
56 | 56 | ||
57 | void iwl_set_bits_mask(struct iwl_trans *trans, u32 reg, u32 mask, u32 value); | ||
58 | |||
57 | int iwl_poll_bit(struct iwl_trans *trans, u32 addr, | 59 | int iwl_poll_bit(struct iwl_trans *trans, u32 addr, |
58 | u32 bits, u32 mask, int timeout); | 60 | u32 bits, u32 mask, int timeout); |
59 | int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask, | 61 | int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask, |
@@ -74,18 +76,18 @@ void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 reg, | |||
74 | u32 bits, u32 mask); | 76 | u32 bits, u32 mask); |
75 | void iwl_clear_bits_prph(struct iwl_trans *trans, u32 reg, u32 mask); | 77 | void iwl_clear_bits_prph(struct iwl_trans *trans, u32 reg, u32 mask); |
76 | 78 | ||
77 | void _iwl_read_targ_mem_words(struct iwl_trans *trans, u32 addr, | 79 | void _iwl_read_targ_mem_dwords(struct iwl_trans *trans, u32 addr, |
78 | void *buf, int words); | 80 | void *buf, int dwords); |
79 | 81 | ||
80 | #define iwl_read_targ_mem_words(trans, addr, buf, bufsize) \ | 82 | #define iwl_read_targ_mem_bytes(trans, addr, buf, bufsize) \ |
81 | do { \ | 83 | do { \ |
82 | BUILD_BUG_ON((bufsize) % sizeof(u32)); \ | 84 | BUILD_BUG_ON((bufsize) % sizeof(u32)); \ |
83 | _iwl_read_targ_mem_words(trans, addr, buf, \ | 85 | _iwl_read_targ_mem_dwords(trans, addr, buf, \ |
84 | (bufsize) / sizeof(u32));\ | 86 | (bufsize) / sizeof(u32));\ |
85 | } while (0) | 87 | } while (0) |
86 | 88 | ||
87 | int _iwl_write_targ_mem_words(struct iwl_trans *trans, u32 addr, | 89 | int _iwl_write_targ_mem_dwords(struct iwl_trans *trans, u32 addr, |
88 | void *buf, int words); | 90 | void *buf, int dwords); |
89 | 91 | ||
90 | u32 iwl_read_targ_mem(struct iwl_trans *trans, u32 addr); | 92 | u32 iwl_read_targ_mem(struct iwl_trans *trans, u32 addr); |
91 | int iwl_write_targ_mem(struct iwl_trans *trans, u32 addr, u32 val); | 93 | int iwl_write_targ_mem(struct iwl_trans *trans, u32 addr, u32 val); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-notif-wait.c b/drivers/net/wireless/iwlwifi/iwl-notif-wait.c index 5cfed29b1b1..c61f2070f15 100644 --- a/drivers/net/wireless/iwlwifi/iwl-notif-wait.c +++ b/drivers/net/wireless/iwlwifi/iwl-notif-wait.c | |||
@@ -121,13 +121,12 @@ EXPORT_SYMBOL_GPL(iwl_notification_wait_notify); | |||
121 | 121 | ||
122 | void iwl_abort_notification_waits(struct iwl_notif_wait_data *notif_wait) | 122 | void iwl_abort_notification_waits(struct iwl_notif_wait_data *notif_wait) |
123 | { | 123 | { |
124 | unsigned long flags; | ||
125 | struct iwl_notification_wait *wait_entry; | 124 | struct iwl_notification_wait *wait_entry; |
126 | 125 | ||
127 | spin_lock_irqsave(¬if_wait->notif_wait_lock, flags); | 126 | spin_lock(¬if_wait->notif_wait_lock); |
128 | list_for_each_entry(wait_entry, ¬if_wait->notif_waits, list) | 127 | list_for_each_entry(wait_entry, ¬if_wait->notif_waits, list) |
129 | wait_entry->aborted = true; | 128 | wait_entry->aborted = true; |
130 | spin_unlock_irqrestore(¬if_wait->notif_wait_lock, flags); | 129 | spin_unlock(¬if_wait->notif_wait_lock); |
131 | 130 | ||
132 | wake_up_all(¬if_wait->notif_waitq); | 131 | wake_up_all(¬if_wait->notif_waitq); |
133 | } | 132 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-op-mode.h b/drivers/net/wireless/iwlwifi/iwl-op-mode.h index cec133c87ad..64886f95664 100644 --- a/drivers/net/wireless/iwlwifi/iwl-op-mode.h +++ b/drivers/net/wireless/iwlwifi/iwl-op-mode.h | |||
@@ -111,22 +111,25 @@ struct iwl_cfg; | |||
111 | * May sleep | 111 | * May sleep |
112 | * @rx: Rx notification to the op_mode. rxb is the Rx buffer itself. Cmd is the | 112 | * @rx: Rx notification to the op_mode. rxb is the Rx buffer itself. Cmd is the |
113 | * HCMD the this Rx responds to. | 113 | * HCMD the this Rx responds to. |
114 | * Must be atomic. | 114 | * Must be atomic and called with BH disabled. |
115 | * @queue_full: notifies that a HW queue is full. | 115 | * @queue_full: notifies that a HW queue is full. |
116 | * Must be atomic | 116 | * Must be atomic and called with BH disabled. |
117 | * @queue_not_full: notifies that a HW queue is not full any more. | 117 | * @queue_not_full: notifies that a HW queue is not full any more. |
118 | * Must be atomic | 118 | * Must be atomic and called with BH disabled. |
119 | * @hw_rf_kill:notifies of a change in the HW rf kill switch. True means that | 119 | * @hw_rf_kill:notifies of a change in the HW rf kill switch. True means that |
120 | * the radio is killed. Must be atomic. | 120 | * the radio is killed. Must be atomic. |
121 | * @free_skb: allows the transport layer to free skbs that haven't been | 121 | * @free_skb: allows the transport layer to free skbs that haven't been |
122 | * reclaimed by the op_mode. This can happen when the driver is freed and | 122 | * reclaimed by the op_mode. This can happen when the driver is freed and |
123 | * there are Tx packets pending in the transport layer. | 123 | * there are Tx packets pending in the transport layer. |
124 | * Must be atomic | 124 | * Must be atomic |
125 | * @nic_error: error notification. Must be atomic | 125 | * @nic_error: error notification. Must be atomic and must be called with BH |
126 | * @cmd_queue_full: Called when the command queue gets full. Must be atomic. | 126 | * disabled. |
127 | * @cmd_queue_full: Called when the command queue gets full. Must be atomic and | ||
128 | * called with BH disabled. | ||
127 | * @nic_config: configure NIC, called before firmware is started. | 129 | * @nic_config: configure NIC, called before firmware is started. |
128 | * May sleep | 130 | * May sleep |
129 | * @wimax_active: invoked when WiMax becomes active. Must be atomic. | 131 | * @wimax_active: invoked when WiMax becomes active. Must be atomic and called |
132 | * with BH disabled. | ||
130 | */ | 133 | */ |
131 | struct iwl_op_mode_ops { | 134 | struct iwl_op_mode_ops { |
132 | struct iwl_op_mode *(*start)(struct iwl_trans *trans, | 135 | struct iwl_op_mode *(*start)(struct iwl_trans *trans, |
@@ -165,7 +168,6 @@ struct iwl_op_mode { | |||
165 | static inline void iwl_op_mode_stop(struct iwl_op_mode *op_mode) | 168 | static inline void iwl_op_mode_stop(struct iwl_op_mode *op_mode) |
166 | { | 169 | { |
167 | might_sleep(); | 170 | might_sleep(); |
168 | |||
169 | op_mode->ops->stop(op_mode); | 171 | op_mode->ops->stop(op_mode); |
170 | } | 172 | } |
171 | 173 | ||
@@ -221,9 +223,4 @@ static inline void iwl_op_mode_wimax_active(struct iwl_op_mode *op_mode) | |||
221 | op_mode->ops->wimax_active(op_mode); | 223 | op_mode->ops->wimax_active(op_mode); |
222 | } | 224 | } |
223 | 225 | ||
224 | /***************************************************** | ||
225 | * Op mode layers implementations | ||
226 | ******************************************************/ | ||
227 | extern const struct iwl_op_mode_ops iwl_dvm_ops; | ||
228 | |||
229 | #endif /* __iwl_op_mode_h__ */ | 226 | #endif /* __iwl_op_mode_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index 3b1069290fa..9253ef1dba7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h | |||
@@ -187,7 +187,7 @@ | |||
187 | #define SCD_QUEUE_STTS_REG_POS_ACTIVE (3) | 187 | #define SCD_QUEUE_STTS_REG_POS_ACTIVE (3) |
188 | #define SCD_QUEUE_STTS_REG_POS_WSL (4) | 188 | #define SCD_QUEUE_STTS_REG_POS_WSL (4) |
189 | #define SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN (19) | 189 | #define SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN (19) |
190 | #define SCD_QUEUE_STTS_REG_MSK (0x00FF0000) | 190 | #define SCD_QUEUE_STTS_REG_MSK (0x017F0000) |
191 | 191 | ||
192 | #define SCD_QUEUE_CTX_REG1_CREDIT_POS (8) | 192 | #define SCD_QUEUE_CTX_REG1_CREDIT_POS (8) |
193 | #define SCD_QUEUE_CTX_REG1_CREDIT_MSK (0x00FFFF00) | 193 | #define SCD_QUEUE_CTX_REG1_CREDIT_MSK (0x00FFFF00) |
@@ -224,6 +224,7 @@ | |||
224 | #define SCD_TXFACT (SCD_BASE + 0x10) | 224 | #define SCD_TXFACT (SCD_BASE + 0x10) |
225 | #define SCD_ACTIVE (SCD_BASE + 0x14) | 225 | #define SCD_ACTIVE (SCD_BASE + 0x14) |
226 | #define SCD_QUEUECHAIN_SEL (SCD_BASE + 0xe8) | 226 | #define SCD_QUEUECHAIN_SEL (SCD_BASE + 0xe8) |
227 | #define SCD_CHAINEXT_EN (SCD_BASE + 0x244) | ||
227 | #define SCD_AGGR_SEL (SCD_BASE + 0x248) | 228 | #define SCD_AGGR_SEL (SCD_BASE + 0x248) |
228 | #define SCD_INTERRUPT_MASK (SCD_BASE + 0x108) | 229 | #define SCD_INTERRUPT_MASK (SCD_BASE + 0x108) |
229 | 230 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-test.c b/drivers/net/wireless/iwlwifi/iwl-test.c new file mode 100644 index 00000000000..81e8c7126d7 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-test.c | |||
@@ -0,0 +1,856 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2010 - 2012 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2010 - 2012 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | * | ||
62 | *****************************************************************************/ | ||
63 | |||
64 | #include <linux/export.h> | ||
65 | #include <net/netlink.h> | ||
66 | |||
67 | #include "iwl-io.h" | ||
68 | #include "iwl-fh.h" | ||
69 | #include "iwl-prph.h" | ||
70 | #include "iwl-trans.h" | ||
71 | #include "iwl-test.h" | ||
72 | #include "iwl-csr.h" | ||
73 | #include "iwl-testmode.h" | ||
74 | |||
75 | /* | ||
76 | * Periphery registers absolute lower bound. This is used in order to | ||
77 | * differentiate registery access through HBUS_TARG_PRPH_* and | ||
78 | * HBUS_TARG_MEM_* accesses. | ||
79 | */ | ||
80 | #define IWL_ABS_PRPH_START (0xA00000) | ||
81 | |||
82 | /* | ||
83 | * The TLVs used in the gnl message policy between the kernel module and | ||
84 | * user space application. iwl_testmode_gnl_msg_policy is to be carried | ||
85 | * through the NL80211_CMD_TESTMODE channel regulated by nl80211. | ||
86 | * See iwl-testmode.h | ||
87 | */ | ||
88 | static | ||
89 | struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = { | ||
90 | [IWL_TM_ATTR_COMMAND] = { .type = NLA_U32, }, | ||
91 | |||
92 | [IWL_TM_ATTR_UCODE_CMD_ID] = { .type = NLA_U8, }, | ||
93 | [IWL_TM_ATTR_UCODE_CMD_DATA] = { .type = NLA_UNSPEC, }, | ||
94 | |||
95 | [IWL_TM_ATTR_REG_OFFSET] = { .type = NLA_U32, }, | ||
96 | [IWL_TM_ATTR_REG_VALUE8] = { .type = NLA_U8, }, | ||
97 | [IWL_TM_ATTR_REG_VALUE32] = { .type = NLA_U32, }, | ||
98 | |||
99 | [IWL_TM_ATTR_SYNC_RSP] = { .type = NLA_UNSPEC, }, | ||
100 | [IWL_TM_ATTR_UCODE_RX_PKT] = { .type = NLA_UNSPEC, }, | ||
101 | |||
102 | [IWL_TM_ATTR_EEPROM] = { .type = NLA_UNSPEC, }, | ||
103 | |||
104 | [IWL_TM_ATTR_TRACE_ADDR] = { .type = NLA_UNSPEC, }, | ||
105 | [IWL_TM_ATTR_TRACE_DUMP] = { .type = NLA_UNSPEC, }, | ||
106 | [IWL_TM_ATTR_TRACE_SIZE] = { .type = NLA_U32, }, | ||
107 | |||
108 | [IWL_TM_ATTR_FIXRATE] = { .type = NLA_U32, }, | ||
109 | |||
110 | [IWL_TM_ATTR_UCODE_OWNER] = { .type = NLA_U8, }, | ||
111 | |||
112 | [IWL_TM_ATTR_MEM_ADDR] = { .type = NLA_U32, }, | ||
113 | [IWL_TM_ATTR_BUFFER_SIZE] = { .type = NLA_U32, }, | ||
114 | [IWL_TM_ATTR_BUFFER_DUMP] = { .type = NLA_UNSPEC, }, | ||
115 | |||
116 | [IWL_TM_ATTR_FW_VERSION] = { .type = NLA_U32, }, | ||
117 | [IWL_TM_ATTR_DEVICE_ID] = { .type = NLA_U32, }, | ||
118 | [IWL_TM_ATTR_FW_TYPE] = { .type = NLA_U32, }, | ||
119 | [IWL_TM_ATTR_FW_INST_SIZE] = { .type = NLA_U32, }, | ||
120 | [IWL_TM_ATTR_FW_DATA_SIZE] = { .type = NLA_U32, }, | ||
121 | |||
122 | [IWL_TM_ATTR_ENABLE_NOTIFICATION] = {.type = NLA_FLAG, }, | ||
123 | }; | ||
124 | |||
125 | static inline void iwl_test_trace_clear(struct iwl_test *tst) | ||
126 | { | ||
127 | memset(&tst->trace, 0, sizeof(struct iwl_test_trace)); | ||
128 | } | ||
129 | |||
130 | static void iwl_test_trace_stop(struct iwl_test *tst) | ||
131 | { | ||
132 | if (!tst->trace.enabled) | ||
133 | return; | ||
134 | |||
135 | if (tst->trace.cpu_addr && tst->trace.dma_addr) | ||
136 | dma_free_coherent(tst->trans->dev, | ||
137 | tst->trace.tsize, | ||
138 | tst->trace.cpu_addr, | ||
139 | tst->trace.dma_addr); | ||
140 | |||
141 | iwl_test_trace_clear(tst); | ||
142 | } | ||
143 | |||
144 | static inline void iwl_test_mem_clear(struct iwl_test *tst) | ||
145 | { | ||
146 | memset(&tst->mem, 0, sizeof(struct iwl_test_mem)); | ||
147 | } | ||
148 | |||
149 | static inline void iwl_test_mem_stop(struct iwl_test *tst) | ||
150 | { | ||
151 | if (!tst->mem.in_read) | ||
152 | return; | ||
153 | |||
154 | iwl_test_mem_clear(tst); | ||
155 | } | ||
156 | |||
157 | /* | ||
158 | * Initializes the test object | ||
159 | * During the lifetime of the test object it is assumed that the transport is | ||
160 | * started. The test object should be stopped before the transport is stopped. | ||
161 | */ | ||
162 | void iwl_test_init(struct iwl_test *tst, struct iwl_trans *trans, | ||
163 | struct iwl_test_ops *ops) | ||
164 | { | ||
165 | tst->trans = trans; | ||
166 | tst->ops = ops; | ||
167 | |||
168 | iwl_test_trace_clear(tst); | ||
169 | iwl_test_mem_clear(tst); | ||
170 | } | ||
171 | EXPORT_SYMBOL_GPL(iwl_test_init); | ||
172 | |||
173 | /* | ||
174 | * Stop the test object | ||
175 | */ | ||
176 | void iwl_test_free(struct iwl_test *tst) | ||
177 | { | ||
178 | iwl_test_mem_stop(tst); | ||
179 | iwl_test_trace_stop(tst); | ||
180 | } | ||
181 | EXPORT_SYMBOL_GPL(iwl_test_free); | ||
182 | |||
183 | static inline int iwl_test_send_cmd(struct iwl_test *tst, | ||
184 | struct iwl_host_cmd *cmd) | ||
185 | { | ||
186 | return tst->ops->send_cmd(tst->trans->op_mode, cmd); | ||
187 | } | ||
188 | |||
189 | static inline bool iwl_test_valid_hw_addr(struct iwl_test *tst, u32 addr) | ||
190 | { | ||
191 | return tst->ops->valid_hw_addr(addr); | ||
192 | } | ||
193 | |||
194 | static inline u32 iwl_test_fw_ver(struct iwl_test *tst) | ||
195 | { | ||
196 | return tst->ops->get_fw_ver(tst->trans->op_mode); | ||
197 | } | ||
198 | |||
199 | static inline struct sk_buff* | ||
200 | iwl_test_alloc_reply(struct iwl_test *tst, int len) | ||
201 | { | ||
202 | return tst->ops->alloc_reply(tst->trans->op_mode, len); | ||
203 | } | ||
204 | |||
205 | static inline int iwl_test_reply(struct iwl_test *tst, struct sk_buff *skb) | ||
206 | { | ||
207 | return tst->ops->reply(tst->trans->op_mode, skb); | ||
208 | } | ||
209 | |||
210 | static inline struct sk_buff* | ||
211 | iwl_test_alloc_event(struct iwl_test *tst, int len) | ||
212 | { | ||
213 | return tst->ops->alloc_event(tst->trans->op_mode, len); | ||
214 | } | ||
215 | |||
216 | static inline void | ||
217 | iwl_test_event(struct iwl_test *tst, struct sk_buff *skb) | ||
218 | { | ||
219 | return tst->ops->event(tst->trans->op_mode, skb); | ||
220 | } | ||
221 | |||
222 | /* | ||
223 | * This function handles the user application commands to the fw. The fw | ||
224 | * commands are sent in a synchronuous manner. In case that the user requested | ||
225 | * to get commands response, it is send to the user. | ||
226 | */ | ||
227 | static int iwl_test_fw_cmd(struct iwl_test *tst, struct nlattr **tb) | ||
228 | { | ||
229 | struct iwl_host_cmd cmd; | ||
230 | struct iwl_rx_packet *pkt; | ||
231 | struct sk_buff *skb; | ||
232 | void *reply_buf; | ||
233 | u32 reply_len; | ||
234 | int ret; | ||
235 | bool cmd_want_skb; | ||
236 | |||
237 | memset(&cmd, 0, sizeof(struct iwl_host_cmd)); | ||
238 | |||
239 | if (!tb[IWL_TM_ATTR_UCODE_CMD_ID] || | ||
240 | !tb[IWL_TM_ATTR_UCODE_CMD_DATA]) { | ||
241 | IWL_ERR(tst->trans, "Missing fw command mandatory fields\n"); | ||
242 | return -ENOMSG; | ||
243 | } | ||
244 | |||
245 | cmd.flags = CMD_ON_DEMAND | CMD_SYNC; | ||
246 | cmd_want_skb = nla_get_flag(tb[IWL_TM_ATTR_UCODE_CMD_SKB]); | ||
247 | if (cmd_want_skb) | ||
248 | cmd.flags |= CMD_WANT_SKB; | ||
249 | |||
250 | cmd.id = nla_get_u8(tb[IWL_TM_ATTR_UCODE_CMD_ID]); | ||
251 | cmd.data[0] = nla_data(tb[IWL_TM_ATTR_UCODE_CMD_DATA]); | ||
252 | cmd.len[0] = nla_len(tb[IWL_TM_ATTR_UCODE_CMD_DATA]); | ||
253 | cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; | ||
254 | IWL_DEBUG_INFO(tst->trans, "test fw cmd=0x%x, flags 0x%x, len %d\n", | ||
255 | cmd.id, cmd.flags, cmd.len[0]); | ||
256 | |||
257 | ret = iwl_test_send_cmd(tst, &cmd); | ||
258 | if (ret) { | ||
259 | IWL_ERR(tst->trans, "Failed to send hcmd\n"); | ||
260 | return ret; | ||
261 | } | ||
262 | if (!cmd_want_skb) | ||
263 | return ret; | ||
264 | |||
265 | /* Handling return of SKB to the user */ | ||
266 | pkt = cmd.resp_pkt; | ||
267 | if (!pkt) { | ||
268 | IWL_ERR(tst->trans, "HCMD received a null response packet\n"); | ||
269 | return ret; | ||
270 | } | ||
271 | |||
272 | reply_len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | ||
273 | skb = iwl_test_alloc_reply(tst, reply_len + 20); | ||
274 | reply_buf = kmalloc(reply_len, GFP_KERNEL); | ||
275 | if (!skb || !reply_buf) { | ||
276 | kfree_skb(skb); | ||
277 | kfree(reply_buf); | ||
278 | return -ENOMEM; | ||
279 | } | ||
280 | |||
281 | /* The reply is in a page, that we cannot send to user space. */ | ||
282 | memcpy(reply_buf, &(pkt->hdr), reply_len); | ||
283 | iwl_free_resp(&cmd); | ||
284 | |||
285 | if (nla_put_u32(skb, IWL_TM_ATTR_COMMAND, | ||
286 | IWL_TM_CMD_DEV2APP_UCODE_RX_PKT) || | ||
287 | nla_put(skb, IWL_TM_ATTR_UCODE_RX_PKT, reply_len, reply_buf)) | ||
288 | goto nla_put_failure; | ||
289 | return iwl_test_reply(tst, skb); | ||
290 | |||
291 | nla_put_failure: | ||
292 | IWL_DEBUG_INFO(tst->trans, "Failed creating NL attributes\n"); | ||
293 | kfree(reply_buf); | ||
294 | kfree_skb(skb); | ||
295 | return -ENOMSG; | ||
296 | } | ||
297 | |||
298 | /* | ||
299 | * Handles the user application commands for register access. | ||
300 | */ | ||
301 | static int iwl_test_reg(struct iwl_test *tst, struct nlattr **tb) | ||
302 | { | ||
303 | u32 ofs, val32, cmd; | ||
304 | u8 val8; | ||
305 | struct sk_buff *skb; | ||
306 | int status = 0; | ||
307 | struct iwl_trans *trans = tst->trans; | ||
308 | |||
309 | if (!tb[IWL_TM_ATTR_REG_OFFSET]) { | ||
310 | IWL_ERR(trans, "Missing reg offset\n"); | ||
311 | return -ENOMSG; | ||
312 | } | ||
313 | |||
314 | ofs = nla_get_u32(tb[IWL_TM_ATTR_REG_OFFSET]); | ||
315 | IWL_DEBUG_INFO(trans, "test reg access cmd offset=0x%x\n", ofs); | ||
316 | |||
317 | cmd = nla_get_u32(tb[IWL_TM_ATTR_COMMAND]); | ||
318 | |||
319 | /* | ||
320 | * Allow access only to FH/CSR/HBUS in direct mode. | ||
321 | * Since we don't have the upper bounds for the CSR and HBUS segments, | ||
322 | * we will use only the upper bound of FH for sanity check. | ||
323 | */ | ||
324 | if (ofs >= FH_MEM_UPPER_BOUND) { | ||
325 | IWL_ERR(trans, "offset out of segment (0x0 - 0x%x)\n", | ||
326 | FH_MEM_UPPER_BOUND); | ||
327 | return -EINVAL; | ||
328 | } | ||
329 | |||
330 | switch (cmd) { | ||
331 | case IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32: | ||
332 | val32 = iwl_read_direct32(tst->trans, ofs); | ||
333 | IWL_DEBUG_INFO(trans, "32 value to read 0x%x\n", val32); | ||
334 | |||
335 | skb = iwl_test_alloc_reply(tst, 20); | ||
336 | if (!skb) { | ||
337 | IWL_ERR(trans, "Memory allocation fail\n"); | ||
338 | return -ENOMEM; | ||
339 | } | ||
340 | if (nla_put_u32(skb, IWL_TM_ATTR_REG_VALUE32, val32)) | ||
341 | goto nla_put_failure; | ||
342 | status = iwl_test_reply(tst, skb); | ||
343 | if (status < 0) | ||
344 | IWL_ERR(trans, "Error sending msg : %d\n", status); | ||
345 | break; | ||
346 | |||
347 | case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32: | ||
348 | if (!tb[IWL_TM_ATTR_REG_VALUE32]) { | ||
349 | IWL_ERR(trans, "Missing value to write\n"); | ||
350 | return -ENOMSG; | ||
351 | } else { | ||
352 | val32 = nla_get_u32(tb[IWL_TM_ATTR_REG_VALUE32]); | ||
353 | IWL_DEBUG_INFO(trans, "32b write val=0x%x\n", val32); | ||
354 | iwl_write_direct32(tst->trans, ofs, val32); | ||
355 | } | ||
356 | break; | ||
357 | |||
358 | case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8: | ||
359 | if (!tb[IWL_TM_ATTR_REG_VALUE8]) { | ||
360 | IWL_ERR(trans, "Missing value to write\n"); | ||
361 | return -ENOMSG; | ||
362 | } else { | ||
363 | val8 = nla_get_u8(tb[IWL_TM_ATTR_REG_VALUE8]); | ||
364 | IWL_DEBUG_INFO(trans, "8b write val=0x%x\n", val8); | ||
365 | iwl_write8(tst->trans, ofs, val8); | ||
366 | } | ||
367 | break; | ||
368 | |||
369 | default: | ||
370 | IWL_ERR(trans, "Unknown test register cmd ID\n"); | ||
371 | return -ENOMSG; | ||
372 | } | ||
373 | |||
374 | return status; | ||
375 | |||
376 | nla_put_failure: | ||
377 | kfree_skb(skb); | ||
378 | return -EMSGSIZE; | ||
379 | } | ||
380 | |||
381 | /* | ||
382 | * Handles the request to start FW tracing. Allocates of the trace buffer | ||
383 | * and sends a reply to user space with the address of the allocated buffer. | ||
384 | */ | ||
385 | static int iwl_test_trace_begin(struct iwl_test *tst, struct nlattr **tb) | ||
386 | { | ||
387 | struct sk_buff *skb; | ||
388 | int status = 0; | ||
389 | |||
390 | if (tst->trace.enabled) | ||
391 | return -EBUSY; | ||
392 | |||
393 | if (!tb[IWL_TM_ATTR_TRACE_SIZE]) | ||
394 | tst->trace.size = TRACE_BUFF_SIZE_DEF; | ||
395 | else | ||
396 | tst->trace.size = | ||
397 | nla_get_u32(tb[IWL_TM_ATTR_TRACE_SIZE]); | ||
398 | |||
399 | if (!tst->trace.size) | ||
400 | return -EINVAL; | ||
401 | |||
402 | if (tst->trace.size < TRACE_BUFF_SIZE_MIN || | ||
403 | tst->trace.size > TRACE_BUFF_SIZE_MAX) | ||
404 | return -EINVAL; | ||
405 | |||
406 | tst->trace.tsize = tst->trace.size + TRACE_BUFF_PADD; | ||
407 | tst->trace.cpu_addr = dma_alloc_coherent(tst->trans->dev, | ||
408 | tst->trace.tsize, | ||
409 | &tst->trace.dma_addr, | ||
410 | GFP_KERNEL); | ||
411 | if (!tst->trace.cpu_addr) | ||
412 | return -ENOMEM; | ||
413 | |||
414 | tst->trace.enabled = true; | ||
415 | tst->trace.trace_addr = (u8 *)PTR_ALIGN(tst->trace.cpu_addr, 0x100); | ||
416 | |||
417 | memset(tst->trace.trace_addr, 0x03B, tst->trace.size); | ||
418 | |||
419 | skb = iwl_test_alloc_reply(tst, sizeof(tst->trace.dma_addr) + 20); | ||
420 | if (!skb) { | ||
421 | IWL_ERR(tst->trans, "Memory allocation fail\n"); | ||
422 | iwl_test_trace_stop(tst); | ||
423 | return -ENOMEM; | ||
424 | } | ||
425 | |||
426 | if (nla_put(skb, IWL_TM_ATTR_TRACE_ADDR, | ||
427 | sizeof(tst->trace.dma_addr), | ||
428 | (u64 *)&tst->trace.dma_addr)) | ||
429 | goto nla_put_failure; | ||
430 | |||
431 | status = iwl_test_reply(tst, skb); | ||
432 | if (status < 0) | ||
433 | IWL_ERR(tst->trans, "Error sending msg : %d\n", status); | ||
434 | |||
435 | tst->trace.nchunks = DIV_ROUND_UP(tst->trace.size, | ||
436 | DUMP_CHUNK_SIZE); | ||
437 | |||
438 | return status; | ||
439 | |||
440 | nla_put_failure: | ||
441 | kfree_skb(skb); | ||
442 | if (nla_get_u32(tb[IWL_TM_ATTR_COMMAND]) == | ||
443 | IWL_TM_CMD_APP2DEV_BEGIN_TRACE) | ||
444 | iwl_test_trace_stop(tst); | ||
445 | return -EMSGSIZE; | ||
446 | } | ||
447 | |||
448 | /* | ||
449 | * Handles indirect read from the periphery or the SRAM. The read is performed | ||
450 | * to a temporary buffer. The user space application should later issue a dump | ||
451 | */ | ||
452 | static int iwl_test_indirect_read(struct iwl_test *tst, u32 addr, u32 size) | ||
453 | { | ||
454 | struct iwl_trans *trans = tst->trans; | ||
455 | unsigned long flags; | ||
456 | int i; | ||
457 | |||
458 | if (size & 0x3) | ||
459 | return -EINVAL; | ||
460 | |||
461 | tst->mem.size = size; | ||
462 | tst->mem.addr = kmalloc(tst->mem.size, GFP_KERNEL); | ||
463 | if (tst->mem.addr == NULL) | ||
464 | return -ENOMEM; | ||
465 | |||
466 | /* Hard-coded periphery absolute address */ | ||
467 | if (IWL_ABS_PRPH_START <= addr && | ||
468 | addr < IWL_ABS_PRPH_START + PRPH_END) { | ||
469 | spin_lock_irqsave(&trans->reg_lock, flags); | ||
470 | iwl_grab_nic_access(trans); | ||
471 | iwl_write32(trans, HBUS_TARG_PRPH_RADDR, | ||
472 | addr | (3 << 24)); | ||
473 | for (i = 0; i < size; i += 4) | ||
474 | *(u32 *)(tst->mem.addr + i) = | ||
475 | iwl_read32(trans, HBUS_TARG_PRPH_RDAT); | ||
476 | iwl_release_nic_access(trans); | ||
477 | spin_unlock_irqrestore(&trans->reg_lock, flags); | ||
478 | } else { /* target memory (SRAM) */ | ||
479 | _iwl_read_targ_mem_dwords(trans, addr, | ||
480 | tst->mem.addr, | ||
481 | tst->mem.size / 4); | ||
482 | } | ||
483 | |||
484 | tst->mem.nchunks = | ||
485 | DIV_ROUND_UP(tst->mem.size, DUMP_CHUNK_SIZE); | ||
486 | tst->mem.in_read = true; | ||
487 | return 0; | ||
488 | |||
489 | } | ||
490 | |||
491 | /* | ||
492 | * Handles indirect write to the periphery or SRAM. The is performed to a | ||
493 | * temporary buffer. | ||
494 | */ | ||
495 | static int iwl_test_indirect_write(struct iwl_test *tst, u32 addr, | ||
496 | u32 size, unsigned char *buf) | ||
497 | { | ||
498 | struct iwl_trans *trans = tst->trans; | ||
499 | u32 val, i; | ||
500 | unsigned long flags; | ||
501 | |||
502 | if (IWL_ABS_PRPH_START <= addr && | ||
503 | addr < IWL_ABS_PRPH_START + PRPH_END) { | ||
504 | /* Periphery writes can be 1-3 bytes long, or DWORDs */ | ||
505 | if (size < 4) { | ||
506 | memcpy(&val, buf, size); | ||
507 | spin_lock_irqsave(&trans->reg_lock, flags); | ||
508 | iwl_grab_nic_access(trans); | ||
509 | iwl_write32(trans, HBUS_TARG_PRPH_WADDR, | ||
510 | (addr & 0x0000FFFF) | | ||
511 | ((size - 1) << 24)); | ||
512 | iwl_write32(trans, HBUS_TARG_PRPH_WDAT, val); | ||
513 | iwl_release_nic_access(trans); | ||
514 | /* needed after consecutive writes w/o read */ | ||
515 | mmiowb(); | ||
516 | spin_unlock_irqrestore(&trans->reg_lock, flags); | ||
517 | } else { | ||
518 | if (size % 4) | ||
519 | return -EINVAL; | ||
520 | for (i = 0; i < size; i += 4) | ||
521 | iwl_write_prph(trans, addr+i, | ||
522 | *(u32 *)(buf+i)); | ||
523 | } | ||
524 | } else if (iwl_test_valid_hw_addr(tst, addr)) { | ||
525 | _iwl_write_targ_mem_dwords(trans, addr, buf, size / 4); | ||
526 | } else { | ||
527 | return -EINVAL; | ||
528 | } | ||
529 | return 0; | ||
530 | } | ||
531 | |||
532 | /* | ||
533 | * Handles the user application commands for indirect read/write | ||
534 | * to/from the periphery or the SRAM. | ||
535 | */ | ||
536 | static int iwl_test_indirect_mem(struct iwl_test *tst, struct nlattr **tb) | ||
537 | { | ||
538 | u32 addr, size, cmd; | ||
539 | unsigned char *buf; | ||
540 | |||
541 | /* Both read and write should be blocked, for atomicity */ | ||
542 | if (tst->mem.in_read) | ||
543 | return -EBUSY; | ||
544 | |||
545 | cmd = nla_get_u32(tb[IWL_TM_ATTR_COMMAND]); | ||
546 | if (!tb[IWL_TM_ATTR_MEM_ADDR]) { | ||
547 | IWL_ERR(tst->trans, "Error finding memory offset address\n"); | ||
548 | return -ENOMSG; | ||
549 | } | ||
550 | addr = nla_get_u32(tb[IWL_TM_ATTR_MEM_ADDR]); | ||
551 | if (!tb[IWL_TM_ATTR_BUFFER_SIZE]) { | ||
552 | IWL_ERR(tst->trans, "Error finding size for memory reading\n"); | ||
553 | return -ENOMSG; | ||
554 | } | ||
555 | size = nla_get_u32(tb[IWL_TM_ATTR_BUFFER_SIZE]); | ||
556 | |||
557 | if (cmd == IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_READ) { | ||
558 | return iwl_test_indirect_read(tst, addr, size); | ||
559 | } else { | ||
560 | if (!tb[IWL_TM_ATTR_BUFFER_DUMP]) | ||
561 | return -EINVAL; | ||
562 | buf = (unsigned char *)nla_data(tb[IWL_TM_ATTR_BUFFER_DUMP]); | ||
563 | return iwl_test_indirect_write(tst, addr, size, buf); | ||
564 | } | ||
565 | } | ||
566 | |||
567 | /* | ||
568 | * Enable notifications to user space | ||
569 | */ | ||
570 | static int iwl_test_notifications(struct iwl_test *tst, | ||
571 | struct nlattr **tb) | ||
572 | { | ||
573 | tst->notify = nla_get_flag(tb[IWL_TM_ATTR_ENABLE_NOTIFICATION]); | ||
574 | return 0; | ||
575 | } | ||
576 | |||
577 | /* | ||
578 | * Handles the request to get the device id | ||
579 | */ | ||
580 | static int iwl_test_get_dev_id(struct iwl_test *tst, struct nlattr **tb) | ||
581 | { | ||
582 | u32 devid = tst->trans->hw_id; | ||
583 | struct sk_buff *skb; | ||
584 | int status; | ||
585 | |||
586 | IWL_DEBUG_INFO(tst->trans, "hw version: 0x%x\n", devid); | ||
587 | |||
588 | skb = iwl_test_alloc_reply(tst, 20); | ||
589 | if (!skb) { | ||
590 | IWL_ERR(tst->trans, "Memory allocation fail\n"); | ||
591 | return -ENOMEM; | ||
592 | } | ||
593 | |||
594 | if (nla_put_u32(skb, IWL_TM_ATTR_DEVICE_ID, devid)) | ||
595 | goto nla_put_failure; | ||
596 | status = iwl_test_reply(tst, skb); | ||
597 | if (status < 0) | ||
598 | IWL_ERR(tst->trans, "Error sending msg : %d\n", status); | ||
599 | |||
600 | return 0; | ||
601 | |||
602 | nla_put_failure: | ||
603 | kfree_skb(skb); | ||
604 | return -EMSGSIZE; | ||
605 | } | ||
606 | |||
607 | /* | ||
608 | * Handles the request to get the FW version | ||
609 | */ | ||
610 | static int iwl_test_get_fw_ver(struct iwl_test *tst, struct nlattr **tb) | ||
611 | { | ||
612 | struct sk_buff *skb; | ||
613 | int status; | ||
614 | u32 ver = iwl_test_fw_ver(tst); | ||
615 | |||
616 | IWL_DEBUG_INFO(tst->trans, "uCode version raw: 0x%x\n", ver); | ||
617 | |||
618 | skb = iwl_test_alloc_reply(tst, 20); | ||
619 | if (!skb) { | ||
620 | IWL_ERR(tst->trans, "Memory allocation fail\n"); | ||
621 | return -ENOMEM; | ||
622 | } | ||
623 | |||
624 | if (nla_put_u32(skb, IWL_TM_ATTR_FW_VERSION, ver)) | ||
625 | goto nla_put_failure; | ||
626 | |||
627 | status = iwl_test_reply(tst, skb); | ||
628 | if (status < 0) | ||
629 | IWL_ERR(tst->trans, "Error sending msg : %d\n", status); | ||
630 | |||
631 | return 0; | ||
632 | |||
633 | nla_put_failure: | ||
634 | kfree_skb(skb); | ||
635 | return -EMSGSIZE; | ||
636 | } | ||
637 | |||
638 | /* | ||
639 | * Parse the netlink message and validate that the IWL_TM_ATTR_CMD exists | ||
640 | */ | ||
641 | int iwl_test_parse(struct iwl_test *tst, struct nlattr **tb, | ||
642 | void *data, int len) | ||
643 | { | ||
644 | int result; | ||
645 | |||
646 | result = nla_parse(tb, IWL_TM_ATTR_MAX - 1, data, len, | ||
647 | iwl_testmode_gnl_msg_policy); | ||
648 | if (result) { | ||
649 | IWL_ERR(tst->trans, "Fail parse gnl msg: %d\n", result); | ||
650 | return result; | ||
651 | } | ||
652 | |||
653 | /* IWL_TM_ATTR_COMMAND is absolutely mandatory */ | ||
654 | if (!tb[IWL_TM_ATTR_COMMAND]) { | ||
655 | IWL_ERR(tst->trans, "Missing testmode command type\n"); | ||
656 | return -ENOMSG; | ||
657 | } | ||
658 | return 0; | ||
659 | } | ||
660 | EXPORT_SYMBOL_GPL(iwl_test_parse); | ||
661 | |||
662 | /* | ||
663 | * Handle test commands. | ||
664 | * Returns 1 for unknown commands (not handled by the test object); negative | ||
665 | * value in case of error. | ||
666 | */ | ||
667 | int iwl_test_handle_cmd(struct iwl_test *tst, struct nlattr **tb) | ||
668 | { | ||
669 | int result; | ||
670 | |||
671 | switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { | ||
672 | case IWL_TM_CMD_APP2DEV_UCODE: | ||
673 | IWL_DEBUG_INFO(tst->trans, "test cmd to uCode\n"); | ||
674 | result = iwl_test_fw_cmd(tst, tb); | ||
675 | break; | ||
676 | |||
677 | case IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32: | ||
678 | case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32: | ||
679 | case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8: | ||
680 | IWL_DEBUG_INFO(tst->trans, "test cmd to register\n"); | ||
681 | result = iwl_test_reg(tst, tb); | ||
682 | break; | ||
683 | |||
684 | case IWL_TM_CMD_APP2DEV_BEGIN_TRACE: | ||
685 | IWL_DEBUG_INFO(tst->trans, "test uCode trace cmd to driver\n"); | ||
686 | result = iwl_test_trace_begin(tst, tb); | ||
687 | break; | ||
688 | |||
689 | case IWL_TM_CMD_APP2DEV_END_TRACE: | ||
690 | iwl_test_trace_stop(tst); | ||
691 | result = 0; | ||
692 | break; | ||
693 | |||
694 | case IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_READ: | ||
695 | case IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_WRITE: | ||
696 | IWL_DEBUG_INFO(tst->trans, "test indirect memory cmd\n"); | ||
697 | result = iwl_test_indirect_mem(tst, tb); | ||
698 | break; | ||
699 | |||
700 | case IWL_TM_CMD_APP2DEV_NOTIFICATIONS: | ||
701 | IWL_DEBUG_INFO(tst->trans, "test notifications cmd\n"); | ||
702 | result = iwl_test_notifications(tst, tb); | ||
703 | break; | ||
704 | |||
705 | case IWL_TM_CMD_APP2DEV_GET_FW_VERSION: | ||
706 | IWL_DEBUG_INFO(tst->trans, "test get FW ver cmd\n"); | ||
707 | result = iwl_test_get_fw_ver(tst, tb); | ||
708 | break; | ||
709 | |||
710 | case IWL_TM_CMD_APP2DEV_GET_DEVICE_ID: | ||
711 | IWL_DEBUG_INFO(tst->trans, "test Get device ID cmd\n"); | ||
712 | result = iwl_test_get_dev_id(tst, tb); | ||
713 | break; | ||
714 | |||
715 | default: | ||
716 | IWL_DEBUG_INFO(tst->trans, "Unknown test command\n"); | ||
717 | result = 1; | ||
718 | break; | ||
719 | } | ||
720 | return result; | ||
721 | } | ||
722 | EXPORT_SYMBOL_GPL(iwl_test_handle_cmd); | ||
723 | |||
724 | static int iwl_test_trace_dump(struct iwl_test *tst, struct sk_buff *skb, | ||
725 | struct netlink_callback *cb) | ||
726 | { | ||
727 | int idx, length; | ||
728 | |||
729 | if (!tst->trace.enabled || !tst->trace.trace_addr) | ||
730 | return -EFAULT; | ||
731 | |||
732 | idx = cb->args[4]; | ||
733 | if (idx >= tst->trace.nchunks) | ||
734 | return -ENOENT; | ||
735 | |||
736 | length = DUMP_CHUNK_SIZE; | ||
737 | if (((idx + 1) == tst->trace.nchunks) && | ||
738 | (tst->trace.size % DUMP_CHUNK_SIZE)) | ||
739 | length = tst->trace.size % | ||
740 | DUMP_CHUNK_SIZE; | ||
741 | |||
742 | if (nla_put(skb, IWL_TM_ATTR_TRACE_DUMP, length, | ||
743 | tst->trace.trace_addr + (DUMP_CHUNK_SIZE * idx))) | ||
744 | goto nla_put_failure; | ||
745 | |||
746 | cb->args[4] = ++idx; | ||
747 | return 0; | ||
748 | |||
749 | nla_put_failure: | ||
750 | return -ENOBUFS; | ||
751 | } | ||
752 | |||
753 | static int iwl_test_buffer_dump(struct iwl_test *tst, struct sk_buff *skb, | ||
754 | struct netlink_callback *cb) | ||
755 | { | ||
756 | int idx, length; | ||
757 | |||
758 | if (!tst->mem.in_read) | ||
759 | return -EFAULT; | ||
760 | |||
761 | idx = cb->args[4]; | ||
762 | if (idx >= tst->mem.nchunks) { | ||
763 | iwl_test_mem_stop(tst); | ||
764 | return -ENOENT; | ||
765 | } | ||
766 | |||
767 | length = DUMP_CHUNK_SIZE; | ||
768 | if (((idx + 1) == tst->mem.nchunks) && | ||
769 | (tst->mem.size % DUMP_CHUNK_SIZE)) | ||
770 | length = tst->mem.size % DUMP_CHUNK_SIZE; | ||
771 | |||
772 | if (nla_put(skb, IWL_TM_ATTR_BUFFER_DUMP, length, | ||
773 | tst->mem.addr + (DUMP_CHUNK_SIZE * idx))) | ||
774 | goto nla_put_failure; | ||
775 | |||
776 | cb->args[4] = ++idx; | ||
777 | return 0; | ||
778 | |||
779 | nla_put_failure: | ||
780 | return -ENOBUFS; | ||
781 | } | ||
782 | |||
783 | /* | ||
784 | * Handle dump commands. | ||
785 | * Returns 1 for unknown commands (not handled by the test object); negative | ||
786 | * value in case of error. | ||
787 | */ | ||
788 | int iwl_test_dump(struct iwl_test *tst, u32 cmd, struct sk_buff *skb, | ||
789 | struct netlink_callback *cb) | ||
790 | { | ||
791 | int result; | ||
792 | |||
793 | switch (cmd) { | ||
794 | case IWL_TM_CMD_APP2DEV_READ_TRACE: | ||
795 | IWL_DEBUG_INFO(tst->trans, "uCode trace cmd\n"); | ||
796 | result = iwl_test_trace_dump(tst, skb, cb); | ||
797 | break; | ||
798 | |||
799 | case IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_DUMP: | ||
800 | IWL_DEBUG_INFO(tst->trans, "testmode sram dump cmd\n"); | ||
801 | result = iwl_test_buffer_dump(tst, skb, cb); | ||
802 | break; | ||
803 | |||
804 | default: | ||
805 | result = 1; | ||
806 | break; | ||
807 | } | ||
808 | return result; | ||
809 | } | ||
810 | EXPORT_SYMBOL_GPL(iwl_test_dump); | ||
811 | |||
812 | /* | ||
813 | * Multicast a spontaneous messages from the device to the user space. | ||
814 | */ | ||
815 | static void iwl_test_send_rx(struct iwl_test *tst, | ||
816 | struct iwl_rx_cmd_buffer *rxb) | ||
817 | { | ||
818 | struct sk_buff *skb; | ||
819 | struct iwl_rx_packet *data; | ||
820 | int length; | ||
821 | |||
822 | data = rxb_addr(rxb); | ||
823 | length = le32_to_cpu(data->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | ||
824 | |||
825 | /* the length doesn't include len_n_flags field, so add it manually */ | ||
826 | length += sizeof(__le32); | ||
827 | |||
828 | skb = iwl_test_alloc_event(tst, length + 20); | ||
829 | if (skb == NULL) { | ||
830 | IWL_ERR(tst->trans, "Out of memory for message to user\n"); | ||
831 | return; | ||
832 | } | ||
833 | |||
834 | if (nla_put_u32(skb, IWL_TM_ATTR_COMMAND, | ||
835 | IWL_TM_CMD_DEV2APP_UCODE_RX_PKT) || | ||
836 | nla_put(skb, IWL_TM_ATTR_UCODE_RX_PKT, length, data)) | ||
837 | goto nla_put_failure; | ||
838 | |||
839 | iwl_test_event(tst, skb); | ||
840 | return; | ||
841 | |||
842 | nla_put_failure: | ||
843 | kfree_skb(skb); | ||
844 | IWL_ERR(tst->trans, "Ouch, overran buffer, check allocation!\n"); | ||
845 | } | ||
846 | |||
847 | /* | ||
848 | * Called whenever a Rx frames is recevied from the device. If notifications to | ||
849 | * the user space are requested, sends the frames to the user. | ||
850 | */ | ||
851 | void iwl_test_rx(struct iwl_test *tst, struct iwl_rx_cmd_buffer *rxb) | ||
852 | { | ||
853 | if (tst->notify) | ||
854 | iwl_test_send_rx(tst, rxb); | ||
855 | } | ||
856 | EXPORT_SYMBOL_GPL(iwl_test_rx); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-test.h b/drivers/net/wireless/iwlwifi/iwl-test.h new file mode 100644 index 00000000000..e13ffa8acc0 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-test.h | |||
@@ -0,0 +1,161 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2010 - 2012 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2010 - 2012 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | * | ||
62 | *****************************************************************************/ | ||
63 | |||
64 | #ifndef __IWL_TEST_H__ | ||
65 | #define __IWL_TEST_H__ | ||
66 | |||
67 | #include <linux/types.h> | ||
68 | #include "iwl-trans.h" | ||
69 | |||
70 | struct iwl_test_trace { | ||
71 | u32 size; | ||
72 | u32 tsize; | ||
73 | u32 nchunks; | ||
74 | u8 *cpu_addr; | ||
75 | u8 *trace_addr; | ||
76 | dma_addr_t dma_addr; | ||
77 | bool enabled; | ||
78 | }; | ||
79 | |||
80 | struct iwl_test_mem { | ||
81 | u32 size; | ||
82 | u32 nchunks; | ||
83 | u8 *addr; | ||
84 | bool in_read; | ||
85 | }; | ||
86 | |||
87 | /* | ||
88 | * struct iwl_test_ops: callback to the op mode | ||
89 | * | ||
90 | * The structure defines the callbacks that the op_mode should handle, | ||
91 | * inorder to handle logic that is out of the scope of iwl_test. The | ||
92 | * op_mode must set all the callbacks. | ||
93 | |||
94 | * @send_cmd: handler that is used by the test object to request the | ||
95 | * op_mode to send a command to the fw. | ||
96 | * | ||
97 | * @valid_hw_addr: handler that is used by the test object to request the | ||
98 | * op_mode to check if the given address is a valid address. | ||
99 | * | ||
100 | * @get_fw_ver: handler used to get the FW version. | ||
101 | * | ||
102 | * @alloc_reply: handler used by the test object to request the op_mode | ||
103 | * to allocate an skb for sending a reply to the user, and initialize | ||
104 | * the skb. It is assumed that the test object only fills the required | ||
105 | * attributes. | ||
106 | * | ||
107 | * @reply: handler used by the test object to request the op_mode to reply | ||
108 | * to a request. The skb is an skb previously allocated by the the | ||
109 | * alloc_reply callback. | ||
110 | I | ||
111 | * @alloc_event: handler used by the test object to request the op_mode | ||
112 | * to allocate an skb for sending an event, and initialize | ||
113 | * the skb. It is assumed that the test object only fills the required | ||
114 | * attributes. | ||
115 | * | ||
116 | * @reply: handler used by the test object to request the op_mode to send | ||
117 | * an event. The skb is an skb previously allocated by the the | ||
118 | * alloc_event callback. | ||
119 | */ | ||
120 | struct iwl_test_ops { | ||
121 | int (*send_cmd)(struct iwl_op_mode *op_modes, | ||
122 | struct iwl_host_cmd *cmd); | ||
123 | bool (*valid_hw_addr)(u32 addr); | ||
124 | u32 (*get_fw_ver)(struct iwl_op_mode *op_mode); | ||
125 | |||
126 | struct sk_buff *(*alloc_reply)(struct iwl_op_mode *op_mode, int len); | ||
127 | int (*reply)(struct iwl_op_mode *op_mode, struct sk_buff *skb); | ||
128 | struct sk_buff* (*alloc_event)(struct iwl_op_mode *op_mode, int len); | ||
129 | void (*event)(struct iwl_op_mode *op_mode, struct sk_buff *skb); | ||
130 | }; | ||
131 | |||
132 | struct iwl_test { | ||
133 | struct iwl_trans *trans; | ||
134 | struct iwl_test_ops *ops; | ||
135 | struct iwl_test_trace trace; | ||
136 | struct iwl_test_mem mem; | ||
137 | bool notify; | ||
138 | }; | ||
139 | |||
140 | void iwl_test_init(struct iwl_test *tst, struct iwl_trans *trans, | ||
141 | struct iwl_test_ops *ops); | ||
142 | |||
143 | void iwl_test_free(struct iwl_test *tst); | ||
144 | |||
145 | int iwl_test_parse(struct iwl_test *tst, struct nlattr **tb, | ||
146 | void *data, int len); | ||
147 | |||
148 | int iwl_test_handle_cmd(struct iwl_test *tst, struct nlattr **tb); | ||
149 | |||
150 | int iwl_test_dump(struct iwl_test *tst, u32 cmd, struct sk_buff *skb, | ||
151 | struct netlink_callback *cb); | ||
152 | |||
153 | void iwl_test_rx(struct iwl_test *tst, struct iwl_rx_cmd_buffer *rxb); | ||
154 | |||
155 | static inline void iwl_test_enable_notifications(struct iwl_test *tst, | ||
156 | bool enable) | ||
157 | { | ||
158 | tst->notify = enable; | ||
159 | } | ||
160 | |||
161 | #endif | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c deleted file mode 100644 index 060aac3e22f..00000000000 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ /dev/null | |||
@@ -1,1114 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2010 - 2012 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2010 - 2012 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | * | ||
62 | *****************************************************************************/ | ||
63 | #include <linux/init.h> | ||
64 | #include <linux/kernel.h> | ||
65 | #include <linux/module.h> | ||
66 | #include <linux/dma-mapping.h> | ||
67 | #include <net/net_namespace.h> | ||
68 | #include <linux/netdevice.h> | ||
69 | #include <net/cfg80211.h> | ||
70 | #include <net/mac80211.h> | ||
71 | #include <net/netlink.h> | ||
72 | |||
73 | #include "iwl-dev.h" | ||
74 | #include "iwl-debug.h" | ||
75 | #include "iwl-io.h" | ||
76 | #include "iwl-agn.h" | ||
77 | #include "iwl-testmode.h" | ||
78 | #include "iwl-trans.h" | ||
79 | #include "iwl-fh.h" | ||
80 | #include "iwl-prph.h" | ||
81 | |||
82 | |||
83 | /* Periphery registers absolute lower bound. This is used in order to | ||
84 | * differentiate registery access through HBUS_TARG_PRPH_* and | ||
85 | * HBUS_TARG_MEM_* accesses. | ||
86 | */ | ||
87 | #define IWL_TM_ABS_PRPH_START (0xA00000) | ||
88 | |||
89 | /* The TLVs used in the gnl message policy between the kernel module and | ||
90 | * user space application. iwl_testmode_gnl_msg_policy is to be carried | ||
91 | * through the NL80211_CMD_TESTMODE channel regulated by nl80211. | ||
92 | * See iwl-testmode.h | ||
93 | */ | ||
94 | static | ||
95 | struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = { | ||
96 | [IWL_TM_ATTR_COMMAND] = { .type = NLA_U32, }, | ||
97 | |||
98 | [IWL_TM_ATTR_UCODE_CMD_ID] = { .type = NLA_U8, }, | ||
99 | [IWL_TM_ATTR_UCODE_CMD_DATA] = { .type = NLA_UNSPEC, }, | ||
100 | |||
101 | [IWL_TM_ATTR_REG_OFFSET] = { .type = NLA_U32, }, | ||
102 | [IWL_TM_ATTR_REG_VALUE8] = { .type = NLA_U8, }, | ||
103 | [IWL_TM_ATTR_REG_VALUE32] = { .type = NLA_U32, }, | ||
104 | |||
105 | [IWL_TM_ATTR_SYNC_RSP] = { .type = NLA_UNSPEC, }, | ||
106 | [IWL_TM_ATTR_UCODE_RX_PKT] = { .type = NLA_UNSPEC, }, | ||
107 | |||
108 | [IWL_TM_ATTR_EEPROM] = { .type = NLA_UNSPEC, }, | ||
109 | |||
110 | [IWL_TM_ATTR_TRACE_ADDR] = { .type = NLA_UNSPEC, }, | ||
111 | [IWL_TM_ATTR_TRACE_DUMP] = { .type = NLA_UNSPEC, }, | ||
112 | [IWL_TM_ATTR_TRACE_SIZE] = { .type = NLA_U32, }, | ||
113 | |||
114 | [IWL_TM_ATTR_FIXRATE] = { .type = NLA_U32, }, | ||
115 | |||
116 | [IWL_TM_ATTR_UCODE_OWNER] = { .type = NLA_U8, }, | ||
117 | |||
118 | [IWL_TM_ATTR_MEM_ADDR] = { .type = NLA_U32, }, | ||
119 | [IWL_TM_ATTR_BUFFER_SIZE] = { .type = NLA_U32, }, | ||
120 | [IWL_TM_ATTR_BUFFER_DUMP] = { .type = NLA_UNSPEC, }, | ||
121 | |||
122 | [IWL_TM_ATTR_FW_VERSION] = { .type = NLA_U32, }, | ||
123 | [IWL_TM_ATTR_DEVICE_ID] = { .type = NLA_U32, }, | ||
124 | [IWL_TM_ATTR_FW_TYPE] = { .type = NLA_U32, }, | ||
125 | [IWL_TM_ATTR_FW_INST_SIZE] = { .type = NLA_U32, }, | ||
126 | [IWL_TM_ATTR_FW_DATA_SIZE] = { .type = NLA_U32, }, | ||
127 | |||
128 | [IWL_TM_ATTR_ENABLE_NOTIFICATION] = {.type = NLA_FLAG, }, | ||
129 | }; | ||
130 | |||
131 | /* | ||
132 | * See the struct iwl_rx_packet in iwl-commands.h for the format of the | ||
133 | * received events from the device | ||
134 | */ | ||
135 | static inline int get_event_length(struct iwl_rx_cmd_buffer *rxb) | ||
136 | { | ||
137 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
138 | if (pkt) | ||
139 | return le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | ||
140 | else | ||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | |||
145 | /* | ||
146 | * This function multicasts the spontaneous messages from the device to the | ||
147 | * user space. It is invoked whenever there is a received messages | ||
148 | * from the device. This function is called within the ISR of the rx handlers | ||
149 | * in iwlagn driver. | ||
150 | * | ||
151 | * The parsing of the message content is left to the user space application, | ||
152 | * The message content is treated as unattacked raw data and is encapsulated | ||
153 | * with IWL_TM_ATTR_UCODE_RX_PKT multicasting to the user space. | ||
154 | * | ||
155 | * @priv: the instance of iwlwifi device | ||
156 | * @rxb: pointer to rx data content received by the ISR | ||
157 | * | ||
158 | * See the message policies and TLVs in iwl_testmode_gnl_msg_policy[]. | ||
159 | * For the messages multicasting to the user application, the mandatory | ||
160 | * TLV fields are : | ||
161 | * IWL_TM_ATTR_COMMAND must be IWL_TM_CMD_DEV2APP_UCODE_RX_PKT | ||
162 | * IWL_TM_ATTR_UCODE_RX_PKT for carrying the message content | ||
163 | */ | ||
164 | |||
165 | static void iwl_testmode_ucode_rx_pkt(struct iwl_priv *priv, | ||
166 | struct iwl_rx_cmd_buffer *rxb) | ||
167 | { | ||
168 | struct ieee80211_hw *hw = priv->hw; | ||
169 | struct sk_buff *skb; | ||
170 | void *data; | ||
171 | int length; | ||
172 | |||
173 | data = (void *)rxb_addr(rxb); | ||
174 | length = get_event_length(rxb); | ||
175 | |||
176 | if (!data || length == 0) | ||
177 | return; | ||
178 | |||
179 | skb = cfg80211_testmode_alloc_event_skb(hw->wiphy, 20 + length, | ||
180 | GFP_ATOMIC); | ||
181 | if (skb == NULL) { | ||
182 | IWL_ERR(priv, | ||
183 | "Run out of memory for messages to user space ?\n"); | ||
184 | return; | ||
185 | } | ||
186 | if (nla_put_u32(skb, IWL_TM_ATTR_COMMAND, IWL_TM_CMD_DEV2APP_UCODE_RX_PKT) || | ||
187 | /* the length doesn't include len_n_flags field, so add it manually */ | ||
188 | nla_put(skb, IWL_TM_ATTR_UCODE_RX_PKT, length + sizeof(__le32), data)) | ||
189 | goto nla_put_failure; | ||
190 | cfg80211_testmode_event(skb, GFP_ATOMIC); | ||
191 | return; | ||
192 | |||
193 | nla_put_failure: | ||
194 | kfree_skb(skb); | ||
195 | IWL_ERR(priv, "Ouch, overran buffer, check allocation!\n"); | ||
196 | } | ||
197 | |||
198 | void iwl_testmode_init(struct iwl_priv *priv) | ||
199 | { | ||
200 | priv->pre_rx_handler = NULL; | ||
201 | priv->testmode_trace.trace_enabled = false; | ||
202 | priv->testmode_mem.read_in_progress = false; | ||
203 | } | ||
204 | |||
205 | static void iwl_mem_cleanup(struct iwl_priv *priv) | ||
206 | { | ||
207 | if (priv->testmode_mem.read_in_progress) { | ||
208 | kfree(priv->testmode_mem.buff_addr); | ||
209 | priv->testmode_mem.buff_addr = NULL; | ||
210 | priv->testmode_mem.buff_size = 0; | ||
211 | priv->testmode_mem.num_chunks = 0; | ||
212 | priv->testmode_mem.read_in_progress = false; | ||
213 | } | ||
214 | } | ||
215 | |||
216 | static void iwl_trace_cleanup(struct iwl_priv *priv) | ||
217 | { | ||
218 | if (priv->testmode_trace.trace_enabled) { | ||
219 | if (priv->testmode_trace.cpu_addr && | ||
220 | priv->testmode_trace.dma_addr) | ||
221 | dma_free_coherent(priv->trans->dev, | ||
222 | priv->testmode_trace.total_size, | ||
223 | priv->testmode_trace.cpu_addr, | ||
224 | priv->testmode_trace.dma_addr); | ||
225 | priv->testmode_trace.trace_enabled = false; | ||
226 | priv->testmode_trace.cpu_addr = NULL; | ||
227 | priv->testmode_trace.trace_addr = NULL; | ||
228 | priv->testmode_trace.dma_addr = 0; | ||
229 | priv->testmode_trace.buff_size = 0; | ||
230 | priv->testmode_trace.total_size = 0; | ||
231 | } | ||
232 | } | ||
233 | |||
234 | |||
235 | void iwl_testmode_cleanup(struct iwl_priv *priv) | ||
236 | { | ||
237 | iwl_trace_cleanup(priv); | ||
238 | iwl_mem_cleanup(priv); | ||
239 | } | ||
240 | |||
241 | |||
242 | /* | ||
243 | * This function handles the user application commands to the ucode. | ||
244 | * | ||
245 | * It retrieves the mandatory fields IWL_TM_ATTR_UCODE_CMD_ID and | ||
246 | * IWL_TM_ATTR_UCODE_CMD_DATA and calls to the handler to send the | ||
247 | * host command to the ucode. | ||
248 | * | ||
249 | * If any mandatory field is missing, -ENOMSG is replied to the user space | ||
250 | * application; otherwise, waits for the host command to be sent and checks | ||
251 | * the return code. In case or error, it is returned, otherwise a reply is | ||
252 | * allocated and the reply RX packet | ||
253 | * is returned. | ||
254 | * | ||
255 | * @hw: ieee80211_hw object that represents the device | ||
256 | * @tb: gnl message fields from the user space | ||
257 | */ | ||
258 | static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb) | ||
259 | { | ||
260 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | ||
261 | struct iwl_host_cmd cmd; | ||
262 | struct iwl_rx_packet *pkt; | ||
263 | struct sk_buff *skb; | ||
264 | void *reply_buf; | ||
265 | u32 reply_len; | ||
266 | int ret; | ||
267 | bool cmd_want_skb; | ||
268 | |||
269 | memset(&cmd, 0, sizeof(struct iwl_host_cmd)); | ||
270 | |||
271 | if (!tb[IWL_TM_ATTR_UCODE_CMD_ID] || | ||
272 | !tb[IWL_TM_ATTR_UCODE_CMD_DATA]) { | ||
273 | IWL_ERR(priv, "Missing ucode command mandatory fields\n"); | ||
274 | return -ENOMSG; | ||
275 | } | ||
276 | |||
277 | cmd.flags = CMD_ON_DEMAND | CMD_SYNC; | ||
278 | cmd_want_skb = nla_get_flag(tb[IWL_TM_ATTR_UCODE_CMD_SKB]); | ||
279 | if (cmd_want_skb) | ||
280 | cmd.flags |= CMD_WANT_SKB; | ||
281 | |||
282 | cmd.id = nla_get_u8(tb[IWL_TM_ATTR_UCODE_CMD_ID]); | ||
283 | cmd.data[0] = nla_data(tb[IWL_TM_ATTR_UCODE_CMD_DATA]); | ||
284 | cmd.len[0] = nla_len(tb[IWL_TM_ATTR_UCODE_CMD_DATA]); | ||
285 | cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; | ||
286 | IWL_DEBUG_INFO(priv, "testmode ucode command ID 0x%x, flags 0x%x," | ||
287 | " len %d\n", cmd.id, cmd.flags, cmd.len[0]); | ||
288 | |||
289 | ret = iwl_dvm_send_cmd(priv, &cmd); | ||
290 | if (ret) { | ||
291 | IWL_ERR(priv, "Failed to send hcmd\n"); | ||
292 | return ret; | ||
293 | } | ||
294 | if (!cmd_want_skb) | ||
295 | return ret; | ||
296 | |||
297 | /* Handling return of SKB to the user */ | ||
298 | pkt = cmd.resp_pkt; | ||
299 | if (!pkt) { | ||
300 | IWL_ERR(priv, "HCMD received a null response packet\n"); | ||
301 | return ret; | ||
302 | } | ||
303 | |||
304 | reply_len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | ||
305 | skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, reply_len + 20); | ||
306 | reply_buf = kmalloc(reply_len, GFP_KERNEL); | ||
307 | if (!skb || !reply_buf) { | ||
308 | kfree_skb(skb); | ||
309 | kfree(reply_buf); | ||
310 | return -ENOMEM; | ||
311 | } | ||
312 | |||
313 | /* The reply is in a page, that we cannot send to user space. */ | ||
314 | memcpy(reply_buf, &(pkt->hdr), reply_len); | ||
315 | iwl_free_resp(&cmd); | ||
316 | |||
317 | if (nla_put_u32(skb, IWL_TM_ATTR_COMMAND, IWL_TM_CMD_DEV2APP_UCODE_RX_PKT) || | ||
318 | nla_put(skb, IWL_TM_ATTR_UCODE_RX_PKT, reply_len, reply_buf)) | ||
319 | goto nla_put_failure; | ||
320 | return cfg80211_testmode_reply(skb); | ||
321 | |||
322 | nla_put_failure: | ||
323 | IWL_DEBUG_INFO(priv, "Failed creating NL attributes\n"); | ||
324 | return -ENOMSG; | ||
325 | } | ||
326 | |||
327 | |||
328 | /* | ||
329 | * This function handles the user application commands for register access. | ||
330 | * | ||
331 | * It retrieves command ID carried with IWL_TM_ATTR_COMMAND and calls to the | ||
332 | * handlers respectively. | ||
333 | * | ||
334 | * If it's an unknown commdn ID, -ENOSYS is returned; or -ENOMSG if the | ||
335 | * mandatory fields(IWL_TM_ATTR_REG_OFFSET,IWL_TM_ATTR_REG_VALUE32, | ||
336 | * IWL_TM_ATTR_REG_VALUE8) are missing; Otherwise 0 is replied indicating | ||
337 | * the success of the command execution. | ||
338 | * | ||
339 | * If IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_REG_READ32, the register read | ||
340 | * value is returned with IWL_TM_ATTR_REG_VALUE32. | ||
341 | * | ||
342 | * @hw: ieee80211_hw object that represents the device | ||
343 | * @tb: gnl message fields from the user space | ||
344 | */ | ||
345 | static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) | ||
346 | { | ||
347 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | ||
348 | u32 ofs, val32, cmd; | ||
349 | u8 val8; | ||
350 | struct sk_buff *skb; | ||
351 | int status = 0; | ||
352 | |||
353 | if (!tb[IWL_TM_ATTR_REG_OFFSET]) { | ||
354 | IWL_ERR(priv, "Missing register offset\n"); | ||
355 | return -ENOMSG; | ||
356 | } | ||
357 | ofs = nla_get_u32(tb[IWL_TM_ATTR_REG_OFFSET]); | ||
358 | IWL_INFO(priv, "testmode register access command offset 0x%x\n", ofs); | ||
359 | |||
360 | /* Allow access only to FH/CSR/HBUS in direct mode. | ||
361 | Since we don't have the upper bounds for the CSR and HBUS segments, | ||
362 | we will use only the upper bound of FH for sanity check. */ | ||
363 | cmd = nla_get_u32(tb[IWL_TM_ATTR_COMMAND]); | ||
364 | if ((cmd == IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32 || | ||
365 | cmd == IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32 || | ||
366 | cmd == IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8) && | ||
367 | (ofs >= FH_MEM_UPPER_BOUND)) { | ||
368 | IWL_ERR(priv, "offset out of segment (0x0 - 0x%x)\n", | ||
369 | FH_MEM_UPPER_BOUND); | ||
370 | return -EINVAL; | ||
371 | } | ||
372 | |||
373 | switch (cmd) { | ||
374 | case IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32: | ||
375 | val32 = iwl_read_direct32(priv->trans, ofs); | ||
376 | IWL_INFO(priv, "32bit value to read 0x%x\n", val32); | ||
377 | |||
378 | skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); | ||
379 | if (!skb) { | ||
380 | IWL_ERR(priv, "Memory allocation fail\n"); | ||
381 | return -ENOMEM; | ||
382 | } | ||
383 | if (nla_put_u32(skb, IWL_TM_ATTR_REG_VALUE32, val32)) | ||
384 | goto nla_put_failure; | ||
385 | status = cfg80211_testmode_reply(skb); | ||
386 | if (status < 0) | ||
387 | IWL_ERR(priv, "Error sending msg : %d\n", status); | ||
388 | break; | ||
389 | case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32: | ||
390 | if (!tb[IWL_TM_ATTR_REG_VALUE32]) { | ||
391 | IWL_ERR(priv, "Missing value to write\n"); | ||
392 | return -ENOMSG; | ||
393 | } else { | ||
394 | val32 = nla_get_u32(tb[IWL_TM_ATTR_REG_VALUE32]); | ||
395 | IWL_INFO(priv, "32bit value to write 0x%x\n", val32); | ||
396 | iwl_write_direct32(priv->trans, ofs, val32); | ||
397 | } | ||
398 | break; | ||
399 | case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8: | ||
400 | if (!tb[IWL_TM_ATTR_REG_VALUE8]) { | ||
401 | IWL_ERR(priv, "Missing value to write\n"); | ||
402 | return -ENOMSG; | ||
403 | } else { | ||
404 | val8 = nla_get_u8(tb[IWL_TM_ATTR_REG_VALUE8]); | ||
405 | IWL_INFO(priv, "8bit value to write 0x%x\n", val8); | ||
406 | iwl_write8(priv->trans, ofs, val8); | ||
407 | } | ||
408 | break; | ||
409 | default: | ||
410 | IWL_ERR(priv, "Unknown testmode register command ID\n"); | ||
411 | return -ENOSYS; | ||
412 | } | ||
413 | |||
414 | return status; | ||
415 | |||
416 | nla_put_failure: | ||
417 | kfree_skb(skb); | ||
418 | return -EMSGSIZE; | ||
419 | } | ||
420 | |||
421 | |||
422 | static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv) | ||
423 | { | ||
424 | struct iwl_notification_wait calib_wait; | ||
425 | static const u8 calib_complete[] = { | ||
426 | CALIBRATION_COMPLETE_NOTIFICATION | ||
427 | }; | ||
428 | int ret; | ||
429 | |||
430 | iwl_init_notification_wait(&priv->notif_wait, &calib_wait, | ||
431 | calib_complete, ARRAY_SIZE(calib_complete), | ||
432 | NULL, NULL); | ||
433 | ret = iwl_init_alive_start(priv); | ||
434 | if (ret) { | ||
435 | IWL_ERR(priv, "Fail init calibration: %d\n", ret); | ||
436 | goto cfg_init_calib_error; | ||
437 | } | ||
438 | |||
439 | ret = iwl_wait_notification(&priv->notif_wait, &calib_wait, 2 * HZ); | ||
440 | if (ret) | ||
441 | IWL_ERR(priv, "Error detecting" | ||
442 | " CALIBRATION_COMPLETE_NOTIFICATION: %d\n", ret); | ||
443 | return ret; | ||
444 | |||
445 | cfg_init_calib_error: | ||
446 | iwl_remove_notification(&priv->notif_wait, &calib_wait); | ||
447 | return ret; | ||
448 | } | ||
449 | |||
450 | /* | ||
451 | * This function handles the user application commands for driver. | ||
452 | * | ||
453 | * It retrieves command ID carried with IWL_TM_ATTR_COMMAND and calls to the | ||
454 | * handlers respectively. | ||
455 | * | ||
456 | * If it's an unknown commdn ID, -ENOSYS is replied; otherwise, the returned | ||
457 | * value of the actual command execution is replied to the user application. | ||
458 | * | ||
459 | * If there's any message responding to the user space, IWL_TM_ATTR_SYNC_RSP | ||
460 | * is used for carry the message while IWL_TM_ATTR_COMMAND must set to | ||
461 | * IWL_TM_CMD_DEV2APP_SYNC_RSP. | ||
462 | * | ||
463 | * @hw: ieee80211_hw object that represents the device | ||
464 | * @tb: gnl message fields from the user space | ||
465 | */ | ||
466 | static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) | ||
467 | { | ||
468 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | ||
469 | struct iwl_trans *trans = priv->trans; | ||
470 | struct sk_buff *skb; | ||
471 | unsigned char *rsp_data_ptr = NULL; | ||
472 | int status = 0, rsp_data_len = 0; | ||
473 | u32 devid, inst_size = 0, data_size = 0; | ||
474 | const struct fw_img *img; | ||
475 | |||
476 | switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { | ||
477 | case IWL_TM_CMD_APP2DEV_GET_DEVICENAME: | ||
478 | rsp_data_ptr = (unsigned char *)priv->cfg->name; | ||
479 | rsp_data_len = strlen(priv->cfg->name); | ||
480 | skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, | ||
481 | rsp_data_len + 20); | ||
482 | if (!skb) { | ||
483 | IWL_ERR(priv, "Memory allocation fail\n"); | ||
484 | return -ENOMEM; | ||
485 | } | ||
486 | if (nla_put_u32(skb, IWL_TM_ATTR_COMMAND, | ||
487 | IWL_TM_CMD_DEV2APP_SYNC_RSP) || | ||
488 | nla_put(skb, IWL_TM_ATTR_SYNC_RSP, | ||
489 | rsp_data_len, rsp_data_ptr)) | ||
490 | goto nla_put_failure; | ||
491 | status = cfg80211_testmode_reply(skb); | ||
492 | if (status < 0) | ||
493 | IWL_ERR(priv, "Error sending msg : %d\n", status); | ||
494 | break; | ||
495 | |||
496 | case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW: | ||
497 | status = iwl_load_ucode_wait_alive(priv, IWL_UCODE_INIT); | ||
498 | if (status) | ||
499 | IWL_ERR(priv, "Error loading init ucode: %d\n", status); | ||
500 | break; | ||
501 | |||
502 | case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB: | ||
503 | iwl_testmode_cfg_init_calib(priv); | ||
504 | priv->ucode_loaded = false; | ||
505 | iwl_trans_stop_device(trans); | ||
506 | break; | ||
507 | |||
508 | case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW: | ||
509 | status = iwl_load_ucode_wait_alive(priv, IWL_UCODE_REGULAR); | ||
510 | if (status) { | ||
511 | IWL_ERR(priv, | ||
512 | "Error loading runtime ucode: %d\n", status); | ||
513 | break; | ||
514 | } | ||
515 | status = iwl_alive_start(priv); | ||
516 | if (status) | ||
517 | IWL_ERR(priv, | ||
518 | "Error starting the device: %d\n", status); | ||
519 | break; | ||
520 | |||
521 | case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW: | ||
522 | iwl_scan_cancel_timeout(priv, 200); | ||
523 | priv->ucode_loaded = false; | ||
524 | iwl_trans_stop_device(trans); | ||
525 | status = iwl_load_ucode_wait_alive(priv, IWL_UCODE_WOWLAN); | ||
526 | if (status) { | ||
527 | IWL_ERR(priv, | ||
528 | "Error loading WOWLAN ucode: %d\n", status); | ||
529 | break; | ||
530 | } | ||
531 | status = iwl_alive_start(priv); | ||
532 | if (status) | ||
533 | IWL_ERR(priv, | ||
534 | "Error starting the device: %d\n", status); | ||
535 | break; | ||
536 | |||
537 | case IWL_TM_CMD_APP2DEV_GET_EEPROM: | ||
538 | if (priv->eeprom) { | ||
539 | skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, | ||
540 | priv->cfg->base_params->eeprom_size + 20); | ||
541 | if (!skb) { | ||
542 | IWL_ERR(priv, "Memory allocation fail\n"); | ||
543 | return -ENOMEM; | ||
544 | } | ||
545 | if (nla_put_u32(skb, IWL_TM_ATTR_COMMAND, | ||
546 | IWL_TM_CMD_DEV2APP_EEPROM_RSP) || | ||
547 | nla_put(skb, IWL_TM_ATTR_EEPROM, | ||
548 | priv->cfg->base_params->eeprom_size, | ||
549 | priv->eeprom)) | ||
550 | goto nla_put_failure; | ||
551 | status = cfg80211_testmode_reply(skb); | ||
552 | if (status < 0) | ||
553 | IWL_ERR(priv, "Error sending msg : %d\n", | ||
554 | status); | ||
555 | } else | ||
556 | return -EFAULT; | ||
557 | break; | ||
558 | |||
559 | case IWL_TM_CMD_APP2DEV_FIXRATE_REQ: | ||
560 | if (!tb[IWL_TM_ATTR_FIXRATE]) { | ||
561 | IWL_ERR(priv, "Missing fixrate setting\n"); | ||
562 | return -ENOMSG; | ||
563 | } | ||
564 | priv->tm_fixed_rate = nla_get_u32(tb[IWL_TM_ATTR_FIXRATE]); | ||
565 | break; | ||
566 | |||
567 | case IWL_TM_CMD_APP2DEV_GET_FW_VERSION: | ||
568 | IWL_INFO(priv, "uCode version raw: 0x%x\n", | ||
569 | priv->fw->ucode_ver); | ||
570 | |||
571 | skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); | ||
572 | if (!skb) { | ||
573 | IWL_ERR(priv, "Memory allocation fail\n"); | ||
574 | return -ENOMEM; | ||
575 | } | ||
576 | if (nla_put_u32(skb, IWL_TM_ATTR_FW_VERSION, | ||
577 | priv->fw->ucode_ver)) | ||
578 | goto nla_put_failure; | ||
579 | status = cfg80211_testmode_reply(skb); | ||
580 | if (status < 0) | ||
581 | IWL_ERR(priv, "Error sending msg : %d\n", status); | ||
582 | break; | ||
583 | |||
584 | case IWL_TM_CMD_APP2DEV_GET_DEVICE_ID: | ||
585 | devid = priv->trans->hw_id; | ||
586 | IWL_INFO(priv, "hw version: 0x%x\n", devid); | ||
587 | |||
588 | skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); | ||
589 | if (!skb) { | ||
590 | IWL_ERR(priv, "Memory allocation fail\n"); | ||
591 | return -ENOMEM; | ||
592 | } | ||
593 | if (nla_put_u32(skb, IWL_TM_ATTR_DEVICE_ID, devid)) | ||
594 | goto nla_put_failure; | ||
595 | status = cfg80211_testmode_reply(skb); | ||
596 | if (status < 0) | ||
597 | IWL_ERR(priv, "Error sending msg : %d\n", status); | ||
598 | break; | ||
599 | |||
600 | case IWL_TM_CMD_APP2DEV_GET_FW_INFO: | ||
601 | skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20 + 8); | ||
602 | if (!skb) { | ||
603 | IWL_ERR(priv, "Memory allocation fail\n"); | ||
604 | return -ENOMEM; | ||
605 | } | ||
606 | if (!priv->ucode_loaded) { | ||
607 | IWL_ERR(priv, "No uCode has not been loaded\n"); | ||
608 | return -EINVAL; | ||
609 | } else { | ||
610 | img = &priv->fw->img[priv->cur_ucode]; | ||
611 | inst_size = img->sec[IWL_UCODE_SECTION_INST].len; | ||
612 | data_size = img->sec[IWL_UCODE_SECTION_DATA].len; | ||
613 | } | ||
614 | if (nla_put_u32(skb, IWL_TM_ATTR_FW_TYPE, priv->cur_ucode) || | ||
615 | nla_put_u32(skb, IWL_TM_ATTR_FW_INST_SIZE, inst_size) || | ||
616 | nla_put_u32(skb, IWL_TM_ATTR_FW_DATA_SIZE, data_size)) | ||
617 | goto nla_put_failure; | ||
618 | status = cfg80211_testmode_reply(skb); | ||
619 | if (status < 0) | ||
620 | IWL_ERR(priv, "Error sending msg : %d\n", status); | ||
621 | break; | ||
622 | |||
623 | default: | ||
624 | IWL_ERR(priv, "Unknown testmode driver command ID\n"); | ||
625 | return -ENOSYS; | ||
626 | } | ||
627 | return status; | ||
628 | |||
629 | nla_put_failure: | ||
630 | kfree_skb(skb); | ||
631 | return -EMSGSIZE; | ||
632 | } | ||
633 | |||
634 | |||
635 | /* | ||
636 | * This function handles the user application commands for uCode trace | ||
637 | * | ||
638 | * It retrieves command ID carried with IWL_TM_ATTR_COMMAND and calls to the | ||
639 | * handlers respectively. | ||
640 | * | ||
641 | * If it's an unknown commdn ID, -ENOSYS is replied; otherwise, the returned | ||
642 | * value of the actual command execution is replied to the user application. | ||
643 | * | ||
644 | * @hw: ieee80211_hw object that represents the device | ||
645 | * @tb: gnl message fields from the user space | ||
646 | */ | ||
647 | static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb) | ||
648 | { | ||
649 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | ||
650 | struct sk_buff *skb; | ||
651 | int status = 0; | ||
652 | struct device *dev = priv->trans->dev; | ||
653 | |||
654 | switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { | ||
655 | case IWL_TM_CMD_APP2DEV_BEGIN_TRACE: | ||
656 | if (priv->testmode_trace.trace_enabled) | ||
657 | return -EBUSY; | ||
658 | |||
659 | if (!tb[IWL_TM_ATTR_TRACE_SIZE]) | ||
660 | priv->testmode_trace.buff_size = TRACE_BUFF_SIZE_DEF; | ||
661 | else | ||
662 | priv->testmode_trace.buff_size = | ||
663 | nla_get_u32(tb[IWL_TM_ATTR_TRACE_SIZE]); | ||
664 | if (!priv->testmode_trace.buff_size) | ||
665 | return -EINVAL; | ||
666 | if (priv->testmode_trace.buff_size < TRACE_BUFF_SIZE_MIN || | ||
667 | priv->testmode_trace.buff_size > TRACE_BUFF_SIZE_MAX) | ||
668 | return -EINVAL; | ||
669 | |||
670 | priv->testmode_trace.total_size = | ||
671 | priv->testmode_trace.buff_size + TRACE_BUFF_PADD; | ||
672 | priv->testmode_trace.cpu_addr = | ||
673 | dma_alloc_coherent(dev, | ||
674 | priv->testmode_trace.total_size, | ||
675 | &priv->testmode_trace.dma_addr, | ||
676 | GFP_KERNEL); | ||
677 | if (!priv->testmode_trace.cpu_addr) | ||
678 | return -ENOMEM; | ||
679 | priv->testmode_trace.trace_enabled = true; | ||
680 | priv->testmode_trace.trace_addr = (u8 *)PTR_ALIGN( | ||
681 | priv->testmode_trace.cpu_addr, 0x100); | ||
682 | memset(priv->testmode_trace.trace_addr, 0x03B, | ||
683 | priv->testmode_trace.buff_size); | ||
684 | skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, | ||
685 | sizeof(priv->testmode_trace.dma_addr) + 20); | ||
686 | if (!skb) { | ||
687 | IWL_ERR(priv, "Memory allocation fail\n"); | ||
688 | iwl_trace_cleanup(priv); | ||
689 | return -ENOMEM; | ||
690 | } | ||
691 | if (nla_put(skb, IWL_TM_ATTR_TRACE_ADDR, | ||
692 | sizeof(priv->testmode_trace.dma_addr), | ||
693 | (u64 *)&priv->testmode_trace.dma_addr)) | ||
694 | goto nla_put_failure; | ||
695 | status = cfg80211_testmode_reply(skb); | ||
696 | if (status < 0) { | ||
697 | IWL_ERR(priv, "Error sending msg : %d\n", status); | ||
698 | } | ||
699 | priv->testmode_trace.num_chunks = | ||
700 | DIV_ROUND_UP(priv->testmode_trace.buff_size, | ||
701 | DUMP_CHUNK_SIZE); | ||
702 | break; | ||
703 | |||
704 | case IWL_TM_CMD_APP2DEV_END_TRACE: | ||
705 | iwl_trace_cleanup(priv); | ||
706 | break; | ||
707 | default: | ||
708 | IWL_ERR(priv, "Unknown testmode mem command ID\n"); | ||
709 | return -ENOSYS; | ||
710 | } | ||
711 | return status; | ||
712 | |||
713 | nla_put_failure: | ||
714 | kfree_skb(skb); | ||
715 | if (nla_get_u32(tb[IWL_TM_ATTR_COMMAND]) == | ||
716 | IWL_TM_CMD_APP2DEV_BEGIN_TRACE) | ||
717 | iwl_trace_cleanup(priv); | ||
718 | return -EMSGSIZE; | ||
719 | } | ||
720 | |||
721 | static int iwl_testmode_trace_dump(struct ieee80211_hw *hw, | ||
722 | struct sk_buff *skb, | ||
723 | struct netlink_callback *cb) | ||
724 | { | ||
725 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | ||
726 | int idx, length; | ||
727 | |||
728 | if (priv->testmode_trace.trace_enabled && | ||
729 | priv->testmode_trace.trace_addr) { | ||
730 | idx = cb->args[4]; | ||
731 | if (idx >= priv->testmode_trace.num_chunks) | ||
732 | return -ENOENT; | ||
733 | length = DUMP_CHUNK_SIZE; | ||
734 | if (((idx + 1) == priv->testmode_trace.num_chunks) && | ||
735 | (priv->testmode_trace.buff_size % DUMP_CHUNK_SIZE)) | ||
736 | length = priv->testmode_trace.buff_size % | ||
737 | DUMP_CHUNK_SIZE; | ||
738 | |||
739 | if (nla_put(skb, IWL_TM_ATTR_TRACE_DUMP, length, | ||
740 | priv->testmode_trace.trace_addr + | ||
741 | (DUMP_CHUNK_SIZE * idx))) | ||
742 | goto nla_put_failure; | ||
743 | idx++; | ||
744 | cb->args[4] = idx; | ||
745 | return 0; | ||
746 | } else | ||
747 | return -EFAULT; | ||
748 | |||
749 | nla_put_failure: | ||
750 | return -ENOBUFS; | ||
751 | } | ||
752 | |||
753 | /* | ||
754 | * This function handles the user application switch ucode ownership. | ||
755 | * | ||
756 | * It retrieves the mandatory fields IWL_TM_ATTR_UCODE_OWNER and | ||
757 | * decide who the current owner of the uCode | ||
758 | * | ||
759 | * If the current owner is OWNERSHIP_TM, then the only host command | ||
760 | * can deliver to uCode is from testmode, all the other host commands | ||
761 | * will dropped. | ||
762 | * | ||
763 | * default driver is the owner of uCode in normal operational mode | ||
764 | * | ||
765 | * @hw: ieee80211_hw object that represents the device | ||
766 | * @tb: gnl message fields from the user space | ||
767 | */ | ||
768 | static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb) | ||
769 | { | ||
770 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | ||
771 | u8 owner; | ||
772 | |||
773 | if (!tb[IWL_TM_ATTR_UCODE_OWNER]) { | ||
774 | IWL_ERR(priv, "Missing ucode owner\n"); | ||
775 | return -ENOMSG; | ||
776 | } | ||
777 | |||
778 | owner = nla_get_u8(tb[IWL_TM_ATTR_UCODE_OWNER]); | ||
779 | if (owner == IWL_OWNERSHIP_DRIVER) { | ||
780 | priv->ucode_owner = owner; | ||
781 | priv->pre_rx_handler = NULL; | ||
782 | } else if (owner == IWL_OWNERSHIP_TM) { | ||
783 | priv->pre_rx_handler = iwl_testmode_ucode_rx_pkt; | ||
784 | priv->ucode_owner = owner; | ||
785 | } else { | ||
786 | IWL_ERR(priv, "Invalid owner\n"); | ||
787 | return -EINVAL; | ||
788 | } | ||
789 | return 0; | ||
790 | } | ||
791 | |||
792 | static int iwl_testmode_indirect_read(struct iwl_priv *priv, u32 addr, u32 size) | ||
793 | { | ||
794 | struct iwl_trans *trans = priv->trans; | ||
795 | unsigned long flags; | ||
796 | int i; | ||
797 | |||
798 | if (size & 0x3) | ||
799 | return -EINVAL; | ||
800 | priv->testmode_mem.buff_size = size; | ||
801 | priv->testmode_mem.buff_addr = | ||
802 | kmalloc(priv->testmode_mem.buff_size, GFP_KERNEL); | ||
803 | if (priv->testmode_mem.buff_addr == NULL) | ||
804 | return -ENOMEM; | ||
805 | |||
806 | /* Hard-coded periphery absolute address */ | ||
807 | if (IWL_TM_ABS_PRPH_START <= addr && | ||
808 | addr < IWL_TM_ABS_PRPH_START + PRPH_END) { | ||
809 | spin_lock_irqsave(&trans->reg_lock, flags); | ||
810 | iwl_grab_nic_access(trans); | ||
811 | iwl_write32(trans, HBUS_TARG_PRPH_RADDR, | ||
812 | addr | (3 << 24)); | ||
813 | for (i = 0; i < size; i += 4) | ||
814 | *(u32 *)(priv->testmode_mem.buff_addr + i) = | ||
815 | iwl_read32(trans, HBUS_TARG_PRPH_RDAT); | ||
816 | iwl_release_nic_access(trans); | ||
817 | spin_unlock_irqrestore(&trans->reg_lock, flags); | ||
818 | } else { /* target memory (SRAM) */ | ||
819 | _iwl_read_targ_mem_words(trans, addr, | ||
820 | priv->testmode_mem.buff_addr, | ||
821 | priv->testmode_mem.buff_size / 4); | ||
822 | } | ||
823 | |||
824 | priv->testmode_mem.num_chunks = | ||
825 | DIV_ROUND_UP(priv->testmode_mem.buff_size, DUMP_CHUNK_SIZE); | ||
826 | priv->testmode_mem.read_in_progress = true; | ||
827 | return 0; | ||
828 | |||
829 | } | ||
830 | |||
831 | static int iwl_testmode_indirect_write(struct iwl_priv *priv, u32 addr, | ||
832 | u32 size, unsigned char *buf) | ||
833 | { | ||
834 | struct iwl_trans *trans = priv->trans; | ||
835 | u32 val, i; | ||
836 | unsigned long flags; | ||
837 | |||
838 | if (IWL_TM_ABS_PRPH_START <= addr && | ||
839 | addr < IWL_TM_ABS_PRPH_START + PRPH_END) { | ||
840 | /* Periphery writes can be 1-3 bytes long, or DWORDs */ | ||
841 | if (size < 4) { | ||
842 | memcpy(&val, buf, size); | ||
843 | spin_lock_irqsave(&trans->reg_lock, flags); | ||
844 | iwl_grab_nic_access(trans); | ||
845 | iwl_write32(trans, HBUS_TARG_PRPH_WADDR, | ||
846 | (addr & 0x0000FFFF) | | ||
847 | ((size - 1) << 24)); | ||
848 | iwl_write32(trans, HBUS_TARG_PRPH_WDAT, val); | ||
849 | iwl_release_nic_access(trans); | ||
850 | /* needed after consecutive writes w/o read */ | ||
851 | mmiowb(); | ||
852 | spin_unlock_irqrestore(&trans->reg_lock, flags); | ||
853 | } else { | ||
854 | if (size % 4) | ||
855 | return -EINVAL; | ||
856 | for (i = 0; i < size; i += 4) | ||
857 | iwl_write_prph(trans, addr+i, | ||
858 | *(u32 *)(buf+i)); | ||
859 | } | ||
860 | } else if (iwlagn_hw_valid_rtc_data_addr(addr) || | ||
861 | (IWLAGN_RTC_INST_LOWER_BOUND <= addr && | ||
862 | addr < IWLAGN_RTC_INST_UPPER_BOUND)) { | ||
863 | _iwl_write_targ_mem_words(trans, addr, buf, size/4); | ||
864 | } else | ||
865 | return -EINVAL; | ||
866 | return 0; | ||
867 | } | ||
868 | |||
869 | /* | ||
870 | * This function handles the user application commands for SRAM data dump | ||
871 | * | ||
872 | * It retrieves the mandatory fields IWL_TM_ATTR_SRAM_ADDR and | ||
873 | * IWL_TM_ATTR_SRAM_SIZE to decide the memory area for SRAM data reading | ||
874 | * | ||
875 | * Several error will be retured, -EBUSY if the SRAM data retrieved by | ||
876 | * previous command has not been delivered to userspace, or -ENOMSG if | ||
877 | * the mandatory fields (IWL_TM_ATTR_SRAM_ADDR,IWL_TM_ATTR_SRAM_SIZE) | ||
878 | * are missing, or -ENOMEM if the buffer allocation fails. | ||
879 | * | ||
880 | * Otherwise 0 is replied indicating the success of the SRAM reading. | ||
881 | * | ||
882 | * @hw: ieee80211_hw object that represents the device | ||
883 | * @tb: gnl message fields from the user space | ||
884 | */ | ||
885 | static int iwl_testmode_indirect_mem(struct ieee80211_hw *hw, | ||
886 | struct nlattr **tb) | ||
887 | { | ||
888 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | ||
889 | u32 addr, size, cmd; | ||
890 | unsigned char *buf; | ||
891 | |||
892 | /* Both read and write should be blocked, for atomicity */ | ||
893 | if (priv->testmode_mem.read_in_progress) | ||
894 | return -EBUSY; | ||
895 | |||
896 | cmd = nla_get_u32(tb[IWL_TM_ATTR_COMMAND]); | ||
897 | if (!tb[IWL_TM_ATTR_MEM_ADDR]) { | ||
898 | IWL_ERR(priv, "Error finding memory offset address\n"); | ||
899 | return -ENOMSG; | ||
900 | } | ||
901 | addr = nla_get_u32(tb[IWL_TM_ATTR_MEM_ADDR]); | ||
902 | if (!tb[IWL_TM_ATTR_BUFFER_SIZE]) { | ||
903 | IWL_ERR(priv, "Error finding size for memory reading\n"); | ||
904 | return -ENOMSG; | ||
905 | } | ||
906 | size = nla_get_u32(tb[IWL_TM_ATTR_BUFFER_SIZE]); | ||
907 | |||
908 | if (cmd == IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_READ) | ||
909 | return iwl_testmode_indirect_read(priv, addr, size); | ||
910 | else { | ||
911 | if (!tb[IWL_TM_ATTR_BUFFER_DUMP]) | ||
912 | return -EINVAL; | ||
913 | buf = (unsigned char *) nla_data(tb[IWL_TM_ATTR_BUFFER_DUMP]); | ||
914 | return iwl_testmode_indirect_write(priv, addr, size, buf); | ||
915 | } | ||
916 | } | ||
917 | |||
918 | static int iwl_testmode_buffer_dump(struct ieee80211_hw *hw, | ||
919 | struct sk_buff *skb, | ||
920 | struct netlink_callback *cb) | ||
921 | { | ||
922 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | ||
923 | int idx, length; | ||
924 | |||
925 | if (priv->testmode_mem.read_in_progress) { | ||
926 | idx = cb->args[4]; | ||
927 | if (idx >= priv->testmode_mem.num_chunks) { | ||
928 | iwl_mem_cleanup(priv); | ||
929 | return -ENOENT; | ||
930 | } | ||
931 | length = DUMP_CHUNK_SIZE; | ||
932 | if (((idx + 1) == priv->testmode_mem.num_chunks) && | ||
933 | (priv->testmode_mem.buff_size % DUMP_CHUNK_SIZE)) | ||
934 | length = priv->testmode_mem.buff_size % | ||
935 | DUMP_CHUNK_SIZE; | ||
936 | |||
937 | if (nla_put(skb, IWL_TM_ATTR_BUFFER_DUMP, length, | ||
938 | priv->testmode_mem.buff_addr + | ||
939 | (DUMP_CHUNK_SIZE * idx))) | ||
940 | goto nla_put_failure; | ||
941 | idx++; | ||
942 | cb->args[4] = idx; | ||
943 | return 0; | ||
944 | } else | ||
945 | return -EFAULT; | ||
946 | |||
947 | nla_put_failure: | ||
948 | return -ENOBUFS; | ||
949 | } | ||
950 | |||
951 | static int iwl_testmode_notifications(struct ieee80211_hw *hw, | ||
952 | struct nlattr **tb) | ||
953 | { | ||
954 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | ||
955 | bool enable; | ||
956 | |||
957 | enable = nla_get_flag(tb[IWL_TM_ATTR_ENABLE_NOTIFICATION]); | ||
958 | if (enable) | ||
959 | priv->pre_rx_handler = iwl_testmode_ucode_rx_pkt; | ||
960 | else | ||
961 | priv->pre_rx_handler = NULL; | ||
962 | return 0; | ||
963 | } | ||
964 | |||
965 | |||
966 | /* The testmode gnl message handler that takes the gnl message from the | ||
967 | * user space and parses it per the policy iwl_testmode_gnl_msg_policy, then | ||
968 | * invoke the corresponding handlers. | ||
969 | * | ||
970 | * This function is invoked when there is user space application sending | ||
971 | * gnl message through the testmode tunnel NL80211_CMD_TESTMODE regulated | ||
972 | * by nl80211. | ||
973 | * | ||
974 | * It retrieves the mandatory field, IWL_TM_ATTR_COMMAND, before | ||
975 | * dispatching it to the corresponding handler. | ||
976 | * | ||
977 | * If IWL_TM_ATTR_COMMAND is missing, -ENOMSG is replied to user application; | ||
978 | * -ENOSYS is replied to the user application if the command is unknown; | ||
979 | * Otherwise, the command is dispatched to the respective handler. | ||
980 | * | ||
981 | * @hw: ieee80211_hw object that represents the device | ||
982 | * @data: pointer to user space message | ||
983 | * @len: length in byte of @data | ||
984 | */ | ||
985 | int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) | ||
986 | { | ||
987 | struct nlattr *tb[IWL_TM_ATTR_MAX]; | ||
988 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | ||
989 | int result; | ||
990 | |||
991 | result = nla_parse(tb, IWL_TM_ATTR_MAX - 1, data, len, | ||
992 | iwl_testmode_gnl_msg_policy); | ||
993 | if (result != 0) { | ||
994 | IWL_ERR(priv, "Error parsing the gnl message : %d\n", result); | ||
995 | return result; | ||
996 | } | ||
997 | |||
998 | /* IWL_TM_ATTR_COMMAND is absolutely mandatory */ | ||
999 | if (!tb[IWL_TM_ATTR_COMMAND]) { | ||
1000 | IWL_ERR(priv, "Missing testmode command type\n"); | ||
1001 | return -ENOMSG; | ||
1002 | } | ||
1003 | /* in case multiple accesses to the device happens */ | ||
1004 | mutex_lock(&priv->mutex); | ||
1005 | |||
1006 | switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { | ||
1007 | case IWL_TM_CMD_APP2DEV_UCODE: | ||
1008 | IWL_DEBUG_INFO(priv, "testmode cmd to uCode\n"); | ||
1009 | result = iwl_testmode_ucode(hw, tb); | ||
1010 | break; | ||
1011 | case IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32: | ||
1012 | case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32: | ||
1013 | case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8: | ||
1014 | IWL_DEBUG_INFO(priv, "testmode cmd to register\n"); | ||
1015 | result = iwl_testmode_reg(hw, tb); | ||
1016 | break; | ||
1017 | case IWL_TM_CMD_APP2DEV_GET_DEVICENAME: | ||
1018 | case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW: | ||
1019 | case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB: | ||
1020 | case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW: | ||
1021 | case IWL_TM_CMD_APP2DEV_GET_EEPROM: | ||
1022 | case IWL_TM_CMD_APP2DEV_FIXRATE_REQ: | ||
1023 | case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW: | ||
1024 | case IWL_TM_CMD_APP2DEV_GET_FW_VERSION: | ||
1025 | case IWL_TM_CMD_APP2DEV_GET_DEVICE_ID: | ||
1026 | case IWL_TM_CMD_APP2DEV_GET_FW_INFO: | ||
1027 | IWL_DEBUG_INFO(priv, "testmode cmd to driver\n"); | ||
1028 | result = iwl_testmode_driver(hw, tb); | ||
1029 | break; | ||
1030 | |||
1031 | case IWL_TM_CMD_APP2DEV_BEGIN_TRACE: | ||
1032 | case IWL_TM_CMD_APP2DEV_END_TRACE: | ||
1033 | case IWL_TM_CMD_APP2DEV_READ_TRACE: | ||
1034 | IWL_DEBUG_INFO(priv, "testmode uCode trace cmd to driver\n"); | ||
1035 | result = iwl_testmode_trace(hw, tb); | ||
1036 | break; | ||
1037 | |||
1038 | case IWL_TM_CMD_APP2DEV_OWNERSHIP: | ||
1039 | IWL_DEBUG_INFO(priv, "testmode change uCode ownership\n"); | ||
1040 | result = iwl_testmode_ownership(hw, tb); | ||
1041 | break; | ||
1042 | |||
1043 | case IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_READ: | ||
1044 | case IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_WRITE: | ||
1045 | IWL_DEBUG_INFO(priv, "testmode indirect memory cmd " | ||
1046 | "to driver\n"); | ||
1047 | result = iwl_testmode_indirect_mem(hw, tb); | ||
1048 | break; | ||
1049 | |||
1050 | case IWL_TM_CMD_APP2DEV_NOTIFICATIONS: | ||
1051 | IWL_DEBUG_INFO(priv, "testmode notifications cmd " | ||
1052 | "to driver\n"); | ||
1053 | result = iwl_testmode_notifications(hw, tb); | ||
1054 | break; | ||
1055 | |||
1056 | default: | ||
1057 | IWL_ERR(priv, "Unknown testmode command\n"); | ||
1058 | result = -ENOSYS; | ||
1059 | break; | ||
1060 | } | ||
1061 | |||
1062 | mutex_unlock(&priv->mutex); | ||
1063 | return result; | ||
1064 | } | ||
1065 | |||
1066 | int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb, | ||
1067 | struct netlink_callback *cb, | ||
1068 | void *data, int len) | ||
1069 | { | ||
1070 | struct nlattr *tb[IWL_TM_ATTR_MAX]; | ||
1071 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | ||
1072 | int result; | ||
1073 | u32 cmd; | ||
1074 | |||
1075 | if (cb->args[3]) { | ||
1076 | /* offset by 1 since commands start at 0 */ | ||
1077 | cmd = cb->args[3] - 1; | ||
1078 | } else { | ||
1079 | result = nla_parse(tb, IWL_TM_ATTR_MAX - 1, data, len, | ||
1080 | iwl_testmode_gnl_msg_policy); | ||
1081 | if (result) { | ||
1082 | IWL_ERR(priv, | ||
1083 | "Error parsing the gnl message : %d\n", result); | ||
1084 | return result; | ||
1085 | } | ||
1086 | |||
1087 | /* IWL_TM_ATTR_COMMAND is absolutely mandatory */ | ||
1088 | if (!tb[IWL_TM_ATTR_COMMAND]) { | ||
1089 | IWL_ERR(priv, "Missing testmode command type\n"); | ||
1090 | return -ENOMSG; | ||
1091 | } | ||
1092 | cmd = nla_get_u32(tb[IWL_TM_ATTR_COMMAND]); | ||
1093 | cb->args[3] = cmd + 1; | ||
1094 | } | ||
1095 | |||
1096 | /* in case multiple accesses to the device happens */ | ||
1097 | mutex_lock(&priv->mutex); | ||
1098 | switch (cmd) { | ||
1099 | case IWL_TM_CMD_APP2DEV_READ_TRACE: | ||
1100 | IWL_DEBUG_INFO(priv, "uCode trace cmd to driver\n"); | ||
1101 | result = iwl_testmode_trace_dump(hw, skb, cb); | ||
1102 | break; | ||
1103 | case IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_DUMP: | ||
1104 | IWL_DEBUG_INFO(priv, "testmode sram dump cmd to driver\n"); | ||
1105 | result = iwl_testmode_buffer_dump(hw, skb, cb); | ||
1106 | break; | ||
1107 | default: | ||
1108 | result = -EINVAL; | ||
1109 | break; | ||
1110 | } | ||
1111 | |||
1112 | mutex_unlock(&priv->mutex); | ||
1113 | return result; | ||
1114 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 0aeeb7ce91c..00efde8e553 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
@@ -355,10 +355,10 @@ struct iwl_trans; | |||
355 | * Must be atomic | 355 | * Must be atomic |
356 | * @reclaim: free packet until ssn. Returns a list of freed packets. | 356 | * @reclaim: free packet until ssn. Returns a list of freed packets. |
357 | * Must be atomic | 357 | * Must be atomic |
358 | * @tx_agg_setup: setup a tx queue for AMPDU - will be called once the HW is | 358 | * @txq_enable: setup a tx queue for AMPDU - will be called once the HW is |
359 | * ready and a successful ADDBA response has been received. | 359 | * ready and a successful ADDBA response has been received. |
360 | * May sleep | 360 | * May sleep |
361 | * @tx_agg_disable: de-configure a Tx queue to send AMPDUs | 361 | * @txq_disable: de-configure a Tx queue to send AMPDUs |
362 | * Must be atomic | 362 | * Must be atomic |
363 | * @wait_tx_queue_empty: wait until all tx queues are empty | 363 | * @wait_tx_queue_empty: wait until all tx queues are empty |
364 | * May sleep | 364 | * May sleep |
@@ -391,9 +391,9 @@ struct iwl_trans_ops { | |||
391 | void (*reclaim)(struct iwl_trans *trans, int queue, int ssn, | 391 | void (*reclaim)(struct iwl_trans *trans, int queue, int ssn, |
392 | struct sk_buff_head *skbs); | 392 | struct sk_buff_head *skbs); |
393 | 393 | ||
394 | void (*tx_agg_setup)(struct iwl_trans *trans, int queue, int fifo, | 394 | void (*txq_enable)(struct iwl_trans *trans, int queue, int fifo, |
395 | int sta_id, int tid, int frame_limit, u16 ssn); | 395 | int sta_id, int tid, int frame_limit, u16 ssn); |
396 | void (*tx_agg_disable)(struct iwl_trans *trans, int queue); | 396 | void (*txq_disable)(struct iwl_trans *trans, int queue); |
397 | 397 | ||
398 | int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir); | 398 | int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir); |
399 | int (*wait_tx_queue_empty)(struct iwl_trans *trans); | 399 | int (*wait_tx_queue_empty)(struct iwl_trans *trans); |
@@ -433,6 +433,11 @@ enum iwl_trans_state { | |||
433 | * @hw_id_str: a string with info about HW ID. Set during transport allocation. | 433 | * @hw_id_str: a string with info about HW ID. Set during transport allocation. |
434 | * @pm_support: set to true in start_hw if link pm is supported | 434 | * @pm_support: set to true in start_hw if link pm is supported |
435 | * @wait_command_queue: the wait_queue for SYNC host commands | 435 | * @wait_command_queue: the wait_queue for SYNC host commands |
436 | * @dev_cmd_pool: pool for Tx cmd allocation - for internal use only. | ||
437 | * The user should use iwl_trans_{alloc,free}_tx_cmd. | ||
438 | * @dev_cmd_headroom: room needed for the transport's private use before the | ||
439 | * device_cmd for Tx - for internal use only | ||
440 | * The user should use iwl_trans_{alloc,free}_tx_cmd. | ||
436 | */ | 441 | */ |
437 | struct iwl_trans { | 442 | struct iwl_trans { |
438 | const struct iwl_trans_ops *ops; | 443 | const struct iwl_trans_ops *ops; |
@@ -450,6 +455,10 @@ struct iwl_trans { | |||
450 | 455 | ||
451 | wait_queue_head_t wait_command_queue; | 456 | wait_queue_head_t wait_command_queue; |
452 | 457 | ||
458 | /* The following fields are internal only */ | ||
459 | struct kmem_cache *dev_cmd_pool; | ||
460 | size_t dev_cmd_headroom; | ||
461 | |||
453 | /* pointer to trans specific struct */ | 462 | /* pointer to trans specific struct */ |
454 | /*Ensure that this pointer will always be aligned to sizeof pointer */ | 463 | /*Ensure that this pointer will always be aligned to sizeof pointer */ |
455 | char trans_specific[0] __aligned(sizeof(void *)); | 464 | char trans_specific[0] __aligned(sizeof(void *)); |
@@ -525,6 +534,26 @@ static inline int iwl_trans_send_cmd(struct iwl_trans *trans, | |||
525 | return trans->ops->send_cmd(trans, cmd); | 534 | return trans->ops->send_cmd(trans, cmd); |
526 | } | 535 | } |
527 | 536 | ||
537 | static inline struct iwl_device_cmd * | ||
538 | iwl_trans_alloc_tx_cmd(struct iwl_trans *trans) | ||
539 | { | ||
540 | u8 *dev_cmd_ptr = kmem_cache_alloc(trans->dev_cmd_pool, GFP_ATOMIC); | ||
541 | |||
542 | if (unlikely(dev_cmd_ptr == NULL)) | ||
543 | return NULL; | ||
544 | |||
545 | return (struct iwl_device_cmd *) | ||
546 | (dev_cmd_ptr + trans->dev_cmd_headroom); | ||
547 | } | ||
548 | |||
549 | static inline void iwl_trans_free_tx_cmd(struct iwl_trans *trans, | ||
550 | struct iwl_device_cmd *dev_cmd) | ||
551 | { | ||
552 | u8 *dev_cmd_ptr = (u8 *)dev_cmd - trans->dev_cmd_headroom; | ||
553 | |||
554 | kmem_cache_free(trans->dev_cmd_pool, dev_cmd_ptr); | ||
555 | } | ||
556 | |||
528 | static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, | 557 | static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, |
529 | struct iwl_device_cmd *dev_cmd, int queue) | 558 | struct iwl_device_cmd *dev_cmd, int queue) |
530 | { | 559 | { |
@@ -543,24 +572,24 @@ static inline void iwl_trans_reclaim(struct iwl_trans *trans, int queue, | |||
543 | trans->ops->reclaim(trans, queue, ssn, skbs); | 572 | trans->ops->reclaim(trans, queue, ssn, skbs); |
544 | } | 573 | } |
545 | 574 | ||
546 | static inline void iwl_trans_tx_agg_disable(struct iwl_trans *trans, int queue) | 575 | static inline void iwl_trans_txq_disable(struct iwl_trans *trans, int queue) |
547 | { | 576 | { |
548 | WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, | 577 | WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, |
549 | "%s bad state = %d", __func__, trans->state); | 578 | "%s bad state = %d", __func__, trans->state); |
550 | 579 | ||
551 | trans->ops->tx_agg_disable(trans, queue); | 580 | trans->ops->txq_disable(trans, queue); |
552 | } | 581 | } |
553 | 582 | ||
554 | static inline void iwl_trans_tx_agg_setup(struct iwl_trans *trans, int queue, | 583 | static inline void iwl_trans_txq_enable(struct iwl_trans *trans, int queue, |
555 | int fifo, int sta_id, int tid, | 584 | int fifo, int sta_id, int tid, |
556 | int frame_limit, u16 ssn) | 585 | int frame_limit, u16 ssn) |
557 | { | 586 | { |
558 | might_sleep(); | 587 | might_sleep(); |
559 | 588 | ||
560 | WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, | 589 | WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, |
561 | "%s bad state = %d", __func__, trans->state); | 590 | "%s bad state = %d", __func__, trans->state); |
562 | 591 | ||
563 | trans->ops->tx_agg_setup(trans, queue, fifo, sta_id, tid, | 592 | trans->ops->txq_enable(trans, queue, fifo, sta_id, tid, |
564 | frame_limit, ssn); | 593 | frame_limit, ssn); |
565 | } | 594 | } |
566 | 595 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/pcie/1000.c index 2629a6602df..81b83f484f0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/pcie/1000.c | |||
@@ -27,9 +27,9 @@ | |||
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/stringify.h> | 28 | #include <linux/stringify.h> |
29 | #include "iwl-config.h" | 29 | #include "iwl-config.h" |
30 | #include "iwl-cfg.h" | ||
31 | #include "iwl-csr.h" | 30 | #include "iwl-csr.h" |
32 | #include "iwl-agn-hw.h" | 31 | #include "iwl-agn-hw.h" |
32 | #include "cfg.h" | ||
33 | 33 | ||
34 | /* Highest firmware API version supported */ | 34 | /* Highest firmware API version supported */ |
35 | #define IWL1000_UCODE_API_MAX 5 | 35 | #define IWL1000_UCODE_API_MAX 5 |
@@ -64,13 +64,26 @@ static const struct iwl_base_params iwl1000_base_params = { | |||
64 | .support_ct_kill_exit = true, | 64 | .support_ct_kill_exit = true, |
65 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, | 65 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, |
66 | .chain_noise_scale = 1000, | 66 | .chain_noise_scale = 1000, |
67 | .wd_timeout = IWL_WATCHHDOG_DISABLED, | 67 | .wd_timeout = IWL_WATCHDOG_DISABLED, |
68 | .max_event_log_size = 128, | 68 | .max_event_log_size = 128, |
69 | }; | 69 | }; |
70 | 70 | ||
71 | static const struct iwl_ht_params iwl1000_ht_params = { | 71 | static const struct iwl_ht_params iwl1000_ht_params = { |
72 | .ht_greenfield_support = true, | 72 | .ht_greenfield_support = true, |
73 | .use_rts_for_aggregation = true, /* use rts/cts protection */ | 73 | .use_rts_for_aggregation = true, /* use rts/cts protection */ |
74 | .ht40_bands = BIT(IEEE80211_BAND_2GHZ), | ||
75 | }; | ||
76 | |||
77 | static const struct iwl_eeprom_params iwl1000_eeprom_params = { | ||
78 | .regulatory_bands = { | ||
79 | EEPROM_REG_BAND_1_CHANNELS, | ||
80 | EEPROM_REG_BAND_2_CHANNELS, | ||
81 | EEPROM_REG_BAND_3_CHANNELS, | ||
82 | EEPROM_REG_BAND_4_CHANNELS, | ||
83 | EEPROM_REG_BAND_5_CHANNELS, | ||
84 | EEPROM_REG_BAND_24_HT40_CHANNELS, | ||
85 | EEPROM_REGULATORY_BAND_NO_HT40, | ||
86 | } | ||
74 | }; | 87 | }; |
75 | 88 | ||
76 | #define IWL_DEVICE_1000 \ | 89 | #define IWL_DEVICE_1000 \ |
@@ -84,6 +97,7 @@ static const struct iwl_ht_params iwl1000_ht_params = { | |||
84 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, \ | 97 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, \ |
85 | .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, \ | 98 | .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, \ |
86 | .base_params = &iwl1000_base_params, \ | 99 | .base_params = &iwl1000_base_params, \ |
100 | .eeprom_params = &iwl1000_eeprom_params, \ | ||
87 | .led_mode = IWL_LED_BLINK | 101 | .led_mode = IWL_LED_BLINK |
88 | 102 | ||
89 | const struct iwl_cfg iwl1000_bgn_cfg = { | 103 | const struct iwl_cfg iwl1000_bgn_cfg = { |
@@ -108,6 +122,7 @@ const struct iwl_cfg iwl1000_bg_cfg = { | |||
108 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, \ | 122 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, \ |
109 | .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, \ | 123 | .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, \ |
110 | .base_params = &iwl1000_base_params, \ | 124 | .base_params = &iwl1000_base_params, \ |
125 | .eeprom_params = &iwl1000_eeprom_params, \ | ||
111 | .led_mode = IWL_LED_RF_STATE, \ | 126 | .led_mode = IWL_LED_RF_STATE, \ |
112 | .rx_with_siso_diversity = true | 127 | .rx_with_siso_diversity = true |
113 | 128 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/pcie/2000.c index 8133105ac64..fd4e78f56fa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/pcie/2000.c | |||
@@ -27,9 +27,9 @@ | |||
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/stringify.h> | 28 | #include <linux/stringify.h> |
29 | #include "iwl-config.h" | 29 | #include "iwl-config.h" |
30 | #include "iwl-cfg.h" | ||
31 | #include "iwl-agn-hw.h" | 30 | #include "iwl-agn-hw.h" |
32 | #include "iwl-commands.h" /* needed for BT for now */ | 31 | #include "cfg.h" |
32 | #include "dvm/commands.h" /* needed for BT for now */ | ||
33 | 33 | ||
34 | /* Highest firmware API version supported */ | 34 | /* Highest firmware API version supported */ |
35 | #define IWL2030_UCODE_API_MAX 6 | 35 | #define IWL2030_UCODE_API_MAX 6 |
@@ -104,6 +104,7 @@ static const struct iwl_base_params iwl2030_base_params = { | |||
104 | static const struct iwl_ht_params iwl2000_ht_params = { | 104 | static const struct iwl_ht_params iwl2000_ht_params = { |
105 | .ht_greenfield_support = true, | 105 | .ht_greenfield_support = true, |
106 | .use_rts_for_aggregation = true, /* use rts/cts protection */ | 106 | .use_rts_for_aggregation = true, /* use rts/cts protection */ |
107 | .ht40_bands = BIT(IEEE80211_BAND_2GHZ), | ||
107 | }; | 108 | }; |
108 | 109 | ||
109 | static const struct iwl_bt_params iwl2030_bt_params = { | 110 | static const struct iwl_bt_params iwl2030_bt_params = { |
@@ -116,6 +117,19 @@ static const struct iwl_bt_params iwl2030_bt_params = { | |||
116 | .bt_session_2 = true, | 117 | .bt_session_2 = true, |
117 | }; | 118 | }; |
118 | 119 | ||
120 | static const struct iwl_eeprom_params iwl20x0_eeprom_params = { | ||
121 | .regulatory_bands = { | ||
122 | EEPROM_REG_BAND_1_CHANNELS, | ||
123 | EEPROM_REG_BAND_2_CHANNELS, | ||
124 | EEPROM_REG_BAND_3_CHANNELS, | ||
125 | EEPROM_REG_BAND_4_CHANNELS, | ||
126 | EEPROM_REG_BAND_5_CHANNELS, | ||
127 | EEPROM_6000_REG_BAND_24_HT40_CHANNELS, | ||
128 | EEPROM_REGULATORY_BAND_NO_HT40, | ||
129 | }, | ||
130 | .enhanced_txpower = true, | ||
131 | }; | ||
132 | |||
119 | #define IWL_DEVICE_2000 \ | 133 | #define IWL_DEVICE_2000 \ |
120 | .fw_name_pre = IWL2000_FW_PRE, \ | 134 | .fw_name_pre = IWL2000_FW_PRE, \ |
121 | .ucode_api_max = IWL2000_UCODE_API_MAX, \ | 135 | .ucode_api_max = IWL2000_UCODE_API_MAX, \ |
@@ -127,6 +141,7 @@ static const struct iwl_bt_params iwl2030_bt_params = { | |||
127 | .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ | 141 | .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ |
128 | .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ | 142 | .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ |
129 | .base_params = &iwl2000_base_params, \ | 143 | .base_params = &iwl2000_base_params, \ |
144 | .eeprom_params = &iwl20x0_eeprom_params, \ | ||
130 | .need_temp_offset_calib = true, \ | 145 | .need_temp_offset_calib = true, \ |
131 | .temp_offset_v2 = true, \ | 146 | .temp_offset_v2 = true, \ |
132 | .led_mode = IWL_LED_RF_STATE | 147 | .led_mode = IWL_LED_RF_STATE |
@@ -155,6 +170,7 @@ const struct iwl_cfg iwl2000_2bgn_d_cfg = { | |||
155 | .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ | 170 | .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ |
156 | .base_params = &iwl2030_base_params, \ | 171 | .base_params = &iwl2030_base_params, \ |
157 | .bt_params = &iwl2030_bt_params, \ | 172 | .bt_params = &iwl2030_bt_params, \ |
173 | .eeprom_params = &iwl20x0_eeprom_params, \ | ||
158 | .need_temp_offset_calib = true, \ | 174 | .need_temp_offset_calib = true, \ |
159 | .temp_offset_v2 = true, \ | 175 | .temp_offset_v2 = true, \ |
160 | .led_mode = IWL_LED_RF_STATE, \ | 176 | .led_mode = IWL_LED_RF_STATE, \ |
@@ -177,6 +193,7 @@ const struct iwl_cfg iwl2030_2bgn_cfg = { | |||
177 | .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ | 193 | .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ |
178 | .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ | 194 | .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ |
179 | .base_params = &iwl2000_base_params, \ | 195 | .base_params = &iwl2000_base_params, \ |
196 | .eeprom_params = &iwl20x0_eeprom_params, \ | ||
180 | .need_temp_offset_calib = true, \ | 197 | .need_temp_offset_calib = true, \ |
181 | .temp_offset_v2 = true, \ | 198 | .temp_offset_v2 = true, \ |
182 | .led_mode = IWL_LED_RF_STATE, \ | 199 | .led_mode = IWL_LED_RF_STATE, \ |
@@ -207,6 +224,7 @@ const struct iwl_cfg iwl105_bgn_d_cfg = { | |||
207 | .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ | 224 | .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ |
208 | .base_params = &iwl2030_base_params, \ | 225 | .base_params = &iwl2030_base_params, \ |
209 | .bt_params = &iwl2030_bt_params, \ | 226 | .bt_params = &iwl2030_bt_params, \ |
227 | .eeprom_params = &iwl20x0_eeprom_params, \ | ||
210 | .need_temp_offset_calib = true, \ | 228 | .need_temp_offset_calib = true, \ |
211 | .temp_offset_v2 = true, \ | 229 | .temp_offset_v2 = true, \ |
212 | .led_mode = IWL_LED_RF_STATE, \ | 230 | .led_mode = IWL_LED_RF_STATE, \ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/pcie/5000.c index 8e26bc825f2..d1665fa6d15 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/pcie/5000.c | |||
@@ -27,9 +27,9 @@ | |||
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/stringify.h> | 28 | #include <linux/stringify.h> |
29 | #include "iwl-config.h" | 29 | #include "iwl-config.h" |
30 | #include "iwl-cfg.h" | ||
31 | #include "iwl-agn-hw.h" | 30 | #include "iwl-agn-hw.h" |
32 | #include "iwl-csr.h" | 31 | #include "iwl-csr.h" |
32 | #include "cfg.h" | ||
33 | 33 | ||
34 | /* Highest firmware API version supported */ | 34 | /* Highest firmware API version supported */ |
35 | #define IWL5000_UCODE_API_MAX 5 | 35 | #define IWL5000_UCODE_API_MAX 5 |
@@ -62,13 +62,26 @@ static const struct iwl_base_params iwl5000_base_params = { | |||
62 | .led_compensation = 51, | 62 | .led_compensation = 51, |
63 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | 63 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
64 | .chain_noise_scale = 1000, | 64 | .chain_noise_scale = 1000, |
65 | .wd_timeout = IWL_WATCHHDOG_DISABLED, | 65 | .wd_timeout = IWL_WATCHDOG_DISABLED, |
66 | .max_event_log_size = 512, | 66 | .max_event_log_size = 512, |
67 | .no_idle_support = true, | 67 | .no_idle_support = true, |
68 | }; | 68 | }; |
69 | 69 | ||
70 | static const struct iwl_ht_params iwl5000_ht_params = { | 70 | static const struct iwl_ht_params iwl5000_ht_params = { |
71 | .ht_greenfield_support = true, | 71 | .ht_greenfield_support = true, |
72 | .ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ), | ||
73 | }; | ||
74 | |||
75 | static const struct iwl_eeprom_params iwl5000_eeprom_params = { | ||
76 | .regulatory_bands = { | ||
77 | EEPROM_REG_BAND_1_CHANNELS, | ||
78 | EEPROM_REG_BAND_2_CHANNELS, | ||
79 | EEPROM_REG_BAND_3_CHANNELS, | ||
80 | EEPROM_REG_BAND_4_CHANNELS, | ||
81 | EEPROM_REG_BAND_5_CHANNELS, | ||
82 | EEPROM_REG_BAND_24_HT40_CHANNELS, | ||
83 | EEPROM_REG_BAND_52_HT40_CHANNELS | ||
84 | }, | ||
72 | }; | 85 | }; |
73 | 86 | ||
74 | #define IWL_DEVICE_5000 \ | 87 | #define IWL_DEVICE_5000 \ |
@@ -82,6 +95,7 @@ static const struct iwl_ht_params iwl5000_ht_params = { | |||
82 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, \ | 95 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, \ |
83 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, \ | 96 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, \ |
84 | .base_params = &iwl5000_base_params, \ | 97 | .base_params = &iwl5000_base_params, \ |
98 | .eeprom_params = &iwl5000_eeprom_params, \ | ||
85 | .led_mode = IWL_LED_BLINK | 99 | .led_mode = IWL_LED_BLINK |
86 | 100 | ||
87 | const struct iwl_cfg iwl5300_agn_cfg = { | 101 | const struct iwl_cfg iwl5300_agn_cfg = { |
@@ -128,6 +142,7 @@ const struct iwl_cfg iwl5350_agn_cfg = { | |||
128 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, | 142 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, |
129 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, | 143 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, |
130 | .base_params = &iwl5000_base_params, | 144 | .base_params = &iwl5000_base_params, |
145 | .eeprom_params = &iwl5000_eeprom_params, | ||
131 | .ht_params = &iwl5000_ht_params, | 146 | .ht_params = &iwl5000_ht_params, |
132 | .led_mode = IWL_LED_BLINK, | 147 | .led_mode = IWL_LED_BLINK, |
133 | .internal_wimax_coex = true, | 148 | .internal_wimax_coex = true, |
@@ -144,6 +159,7 @@ const struct iwl_cfg iwl5350_agn_cfg = { | |||
144 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, \ | 159 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, \ |
145 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, \ | 160 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, \ |
146 | .base_params = &iwl5000_base_params, \ | 161 | .base_params = &iwl5000_base_params, \ |
162 | .eeprom_params = &iwl5000_eeprom_params, \ | ||
147 | .no_xtal_calib = true, \ | 163 | .no_xtal_calib = true, \ |
148 | .led_mode = IWL_LED_BLINK, \ | 164 | .led_mode = IWL_LED_BLINK, \ |
149 | .internal_wimax_coex = true | 165 | .internal_wimax_coex = true |
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/pcie/6000.c index 19f7ee84ae8..4a57624afc4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/pcie/6000.c | |||
@@ -27,25 +27,28 @@ | |||
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/stringify.h> | 28 | #include <linux/stringify.h> |
29 | #include "iwl-config.h" | 29 | #include "iwl-config.h" |
30 | #include "iwl-cfg.h" | ||
31 | #include "iwl-agn-hw.h" | 30 | #include "iwl-agn-hw.h" |
32 | #include "iwl-commands.h" /* needed for BT for now */ | 31 | #include "cfg.h" |
32 | #include "dvm/commands.h" /* needed for BT for now */ | ||
33 | 33 | ||
34 | /* Highest firmware API version supported */ | 34 | /* Highest firmware API version supported */ |
35 | #define IWL6000_UCODE_API_MAX 6 | 35 | #define IWL6000_UCODE_API_MAX 6 |
36 | #define IWL6050_UCODE_API_MAX 5 | 36 | #define IWL6050_UCODE_API_MAX 5 |
37 | #define IWL6000G2_UCODE_API_MAX 6 | 37 | #define IWL6000G2_UCODE_API_MAX 6 |
38 | #define IWL6035_UCODE_API_MAX 6 | ||
38 | 39 | ||
39 | /* Oldest version we won't warn about */ | 40 | /* Oldest version we won't warn about */ |
40 | #define IWL6000_UCODE_API_OK 4 | 41 | #define IWL6000_UCODE_API_OK 4 |
41 | #define IWL6000G2_UCODE_API_OK 5 | 42 | #define IWL6000G2_UCODE_API_OK 5 |
42 | #define IWL6050_UCODE_API_OK 5 | 43 | #define IWL6050_UCODE_API_OK 5 |
43 | #define IWL6000G2B_UCODE_API_OK 6 | 44 | #define IWL6000G2B_UCODE_API_OK 6 |
45 | #define IWL6035_UCODE_API_OK 6 | ||
44 | 46 | ||
45 | /* Lowest firmware API version supported */ | 47 | /* Lowest firmware API version supported */ |
46 | #define IWL6000_UCODE_API_MIN 4 | 48 | #define IWL6000_UCODE_API_MIN 4 |
47 | #define IWL6050_UCODE_API_MIN 4 | 49 | #define IWL6050_UCODE_API_MIN 4 |
48 | #define IWL6000G2_UCODE_API_MIN 4 | 50 | #define IWL6000G2_UCODE_API_MIN 5 |
51 | #define IWL6035_UCODE_API_MIN 6 | ||
49 | 52 | ||
50 | /* EEPROM versions */ | 53 | /* EEPROM versions */ |
51 | #define EEPROM_6000_TX_POWER_VERSION (4) | 54 | #define EEPROM_6000_TX_POWER_VERSION (4) |
@@ -124,6 +127,7 @@ static const struct iwl_base_params iwl6000_g2_base_params = { | |||
124 | static const struct iwl_ht_params iwl6000_ht_params = { | 127 | static const struct iwl_ht_params iwl6000_ht_params = { |
125 | .ht_greenfield_support = true, | 128 | .ht_greenfield_support = true, |
126 | .use_rts_for_aggregation = true, /* use rts/cts protection */ | 129 | .use_rts_for_aggregation = true, /* use rts/cts protection */ |
130 | .ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ), | ||
127 | }; | 131 | }; |
128 | 132 | ||
129 | static const struct iwl_bt_params iwl6000_bt_params = { | 133 | static const struct iwl_bt_params iwl6000_bt_params = { |
@@ -135,6 +139,19 @@ static const struct iwl_bt_params iwl6000_bt_params = { | |||
135 | .bt_sco_disable = true, | 139 | .bt_sco_disable = true, |
136 | }; | 140 | }; |
137 | 141 | ||
142 | static const struct iwl_eeprom_params iwl6000_eeprom_params = { | ||
143 | .regulatory_bands = { | ||
144 | EEPROM_REG_BAND_1_CHANNELS, | ||
145 | EEPROM_REG_BAND_2_CHANNELS, | ||
146 | EEPROM_REG_BAND_3_CHANNELS, | ||
147 | EEPROM_REG_BAND_4_CHANNELS, | ||
148 | EEPROM_REG_BAND_5_CHANNELS, | ||
149 | EEPROM_6000_REG_BAND_24_HT40_CHANNELS, | ||
150 | EEPROM_REG_BAND_52_HT40_CHANNELS | ||
151 | }, | ||
152 | .enhanced_txpower = true, | ||
153 | }; | ||
154 | |||
138 | #define IWL_DEVICE_6005 \ | 155 | #define IWL_DEVICE_6005 \ |
139 | .fw_name_pre = IWL6005_FW_PRE, \ | 156 | .fw_name_pre = IWL6005_FW_PRE, \ |
140 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, \ | 157 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, \ |
@@ -146,6 +163,7 @@ static const struct iwl_bt_params iwl6000_bt_params = { | |||
146 | .eeprom_ver = EEPROM_6005_EEPROM_VERSION, \ | 163 | .eeprom_ver = EEPROM_6005_EEPROM_VERSION, \ |
147 | .eeprom_calib_ver = EEPROM_6005_TX_POWER_VERSION, \ | 164 | .eeprom_calib_ver = EEPROM_6005_TX_POWER_VERSION, \ |
148 | .base_params = &iwl6000_g2_base_params, \ | 165 | .base_params = &iwl6000_g2_base_params, \ |
166 | .eeprom_params = &iwl6000_eeprom_params, \ | ||
149 | .need_temp_offset_calib = true, \ | 167 | .need_temp_offset_calib = true, \ |
150 | .led_mode = IWL_LED_RF_STATE | 168 | .led_mode = IWL_LED_RF_STATE |
151 | 169 | ||
@@ -201,6 +219,7 @@ const struct iwl_cfg iwl6005_2agn_mow2_cfg = { | |||
201 | .eeprom_calib_ver = EEPROM_6030_TX_POWER_VERSION, \ | 219 | .eeprom_calib_ver = EEPROM_6030_TX_POWER_VERSION, \ |
202 | .base_params = &iwl6000_g2_base_params, \ | 220 | .base_params = &iwl6000_g2_base_params, \ |
203 | .bt_params = &iwl6000_bt_params, \ | 221 | .bt_params = &iwl6000_bt_params, \ |
222 | .eeprom_params = &iwl6000_eeprom_params, \ | ||
204 | .need_temp_offset_calib = true, \ | 223 | .need_temp_offset_calib = true, \ |
205 | .led_mode = IWL_LED_RF_STATE, \ | 224 | .led_mode = IWL_LED_RF_STATE, \ |
206 | .adv_pm = true \ | 225 | .adv_pm = true \ |
@@ -227,9 +246,26 @@ const struct iwl_cfg iwl6030_2bg_cfg = { | |||
227 | IWL_DEVICE_6030, | 246 | IWL_DEVICE_6030, |
228 | }; | 247 | }; |
229 | 248 | ||
249 | #define IWL_DEVICE_6035 \ | ||
250 | .fw_name_pre = IWL6030_FW_PRE, \ | ||
251 | .ucode_api_max = IWL6035_UCODE_API_MAX, \ | ||
252 | .ucode_api_ok = IWL6035_UCODE_API_OK, \ | ||
253 | .ucode_api_min = IWL6035_UCODE_API_MIN, \ | ||
254 | .device_family = IWL_DEVICE_FAMILY_6030, \ | ||
255 | .max_inst_size = IWL60_RTC_INST_SIZE, \ | ||
256 | .max_data_size = IWL60_RTC_DATA_SIZE, \ | ||
257 | .eeprom_ver = EEPROM_6030_EEPROM_VERSION, \ | ||
258 | .eeprom_calib_ver = EEPROM_6030_TX_POWER_VERSION, \ | ||
259 | .base_params = &iwl6000_g2_base_params, \ | ||
260 | .bt_params = &iwl6000_bt_params, \ | ||
261 | .eeprom_params = &iwl6000_eeprom_params, \ | ||
262 | .need_temp_offset_calib = true, \ | ||
263 | .led_mode = IWL_LED_RF_STATE, \ | ||
264 | .adv_pm = true | ||
265 | |||
230 | const struct iwl_cfg iwl6035_2agn_cfg = { | 266 | const struct iwl_cfg iwl6035_2agn_cfg = { |
231 | .name = "Intel(R) Centrino(R) Advanced-N 6235 AGN", | 267 | .name = "Intel(R) Centrino(R) Advanced-N 6235 AGN", |
232 | IWL_DEVICE_6030, | 268 | IWL_DEVICE_6035, |
233 | .ht_params = &iwl6000_ht_params, | 269 | .ht_params = &iwl6000_ht_params, |
234 | }; | 270 | }; |
235 | 271 | ||
@@ -273,6 +309,7 @@ const struct iwl_cfg iwl130_bg_cfg = { | |||
273 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, \ | 309 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, \ |
274 | .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, \ | 310 | .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, \ |
275 | .base_params = &iwl6000_base_params, \ | 311 | .base_params = &iwl6000_base_params, \ |
312 | .eeprom_params = &iwl6000_eeprom_params, \ | ||
276 | .led_mode = IWL_LED_BLINK | 313 | .led_mode = IWL_LED_BLINK |
277 | 314 | ||
278 | const struct iwl_cfg iwl6000i_2agn_cfg = { | 315 | const struct iwl_cfg iwl6000i_2agn_cfg = { |
@@ -303,6 +340,7 @@ const struct iwl_cfg iwl6000i_2bg_cfg = { | |||
303 | .eeprom_ver = EEPROM_6050_EEPROM_VERSION, \ | 340 | .eeprom_ver = EEPROM_6050_EEPROM_VERSION, \ |
304 | .eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION, \ | 341 | .eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION, \ |
305 | .base_params = &iwl6050_base_params, \ | 342 | .base_params = &iwl6050_base_params, \ |
343 | .eeprom_params = &iwl6000_eeprom_params, \ | ||
306 | .led_mode = IWL_LED_BLINK, \ | 344 | .led_mode = IWL_LED_BLINK, \ |
307 | .internal_wimax_coex = true | 345 | .internal_wimax_coex = true |
308 | 346 | ||
@@ -327,6 +365,7 @@ const struct iwl_cfg iwl6050_2abg_cfg = { | |||
327 | .eeprom_ver = EEPROM_6150_EEPROM_VERSION, \ | 365 | .eeprom_ver = EEPROM_6150_EEPROM_VERSION, \ |
328 | .eeprom_calib_ver = EEPROM_6150_TX_POWER_VERSION, \ | 366 | .eeprom_calib_ver = EEPROM_6150_TX_POWER_VERSION, \ |
329 | .base_params = &iwl6050_base_params, \ | 367 | .base_params = &iwl6050_base_params, \ |
368 | .eeprom_params = &iwl6000_eeprom_params, \ | ||
330 | .led_mode = IWL_LED_BLINK, \ | 369 | .led_mode = IWL_LED_BLINK, \ |
331 | .internal_wimax_coex = true | 370 | .internal_wimax_coex = true |
332 | 371 | ||
@@ -353,6 +392,7 @@ const struct iwl_cfg iwl6000_3agn_cfg = { | |||
353 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | 392 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, |
354 | .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, | 393 | .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, |
355 | .base_params = &iwl6000_base_params, | 394 | .base_params = &iwl6000_base_params, |
395 | .eeprom_params = &iwl6000_eeprom_params, | ||
356 | .ht_params = &iwl6000_ht_params, | 396 | .ht_params = &iwl6000_ht_params, |
357 | .led_mode = IWL_LED_BLINK, | 397 | .led_mode = IWL_LED_BLINK, |
358 | }; | 398 | }; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-cfg.h b/drivers/net/wireless/iwlwifi/pcie/cfg.h index 82152311d73..82152311d73 100644 --- a/drivers/net/wireless/iwlwifi/iwl-cfg.h +++ b/drivers/net/wireless/iwlwifi/pcie/cfg.h | |||
diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/pcie/drv.c index 0c8a1c2d884..f4c3500b68c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/drivers/net/wireless/iwlwifi/pcie/drv.c | |||
@@ -68,10 +68,11 @@ | |||
68 | #include <linux/pci-aspm.h> | 68 | #include <linux/pci-aspm.h> |
69 | 69 | ||
70 | #include "iwl-trans.h" | 70 | #include "iwl-trans.h" |
71 | #include "iwl-cfg.h" | ||
72 | #include "iwl-drv.h" | 71 | #include "iwl-drv.h" |
73 | #include "iwl-trans.h" | 72 | #include "iwl-trans.h" |
74 | #include "iwl-trans-pcie-int.h" | 73 | |
74 | #include "cfg.h" | ||
75 | #include "internal.h" | ||
75 | 76 | ||
76 | #define IWL_PCI_DEVICE(dev, subdev, cfg) \ | 77 | #define IWL_PCI_DEVICE(dev, subdev, cfg) \ |
77 | .vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \ | 78 | .vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h b/drivers/net/wireless/iwlwifi/pcie/internal.h index f027769933d..5024fb662bf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h +++ b/drivers/net/wireless/iwlwifi/pcie/internal.h | |||
@@ -339,13 +339,9 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, | |||
339 | void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans, | 339 | void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans, |
340 | struct iwl_tx_queue *txq, | 340 | struct iwl_tx_queue *txq, |
341 | u16 byte_cnt); | 341 | u16 byte_cnt); |
342 | void iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans, int queue); | 342 | void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo, |
343 | void iwl_trans_set_wr_ptrs(struct iwl_trans *trans, int txq_id, u32 index); | 343 | int sta_id, int tid, int frame_limit, u16 ssn); |
344 | void iwl_trans_tx_queue_set_status(struct iwl_trans *trans, | 344 | void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int queue); |
345 | struct iwl_tx_queue *txq, | ||
346 | int tx_fifo_id, bool active); | ||
347 | void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans, int queue, int fifo, | ||
348 | int sta_id, int tid, int frame_limit, u16 ssn); | ||
349 | void iwl_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, | 345 | void iwl_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, |
350 | enum dma_data_direction dma_dir); | 346 | enum dma_data_direction dma_dir); |
351 | int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, | 347 | int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c index 98605fc7ad3..be143eb4aa4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +++ b/drivers/net/wireless/iwlwifi/pcie/rx.c | |||
@@ -32,7 +32,7 @@ | |||
32 | 32 | ||
33 | #include "iwl-prph.h" | 33 | #include "iwl-prph.h" |
34 | #include "iwl-io.h" | 34 | #include "iwl-io.h" |
35 | #include "iwl-trans-pcie-int.h" | 35 | #include "internal.h" |
36 | #include "iwl-op-mode.h" | 36 | #include "iwl-op-mode.h" |
37 | 37 | ||
38 | #ifdef CONFIG_IWLWIFI_IDI | 38 | #ifdef CONFIG_IWLWIFI_IDI |
@@ -867,24 +867,23 @@ void iwl_disable_ict(struct iwl_trans *trans) | |||
867 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | 867 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); |
868 | } | 868 | } |
869 | 869 | ||
870 | /* legacy (non-ICT) ISR. Assumes that trans_pcie->irq_lock is held */ | ||
870 | static irqreturn_t iwl_isr(int irq, void *data) | 871 | static irqreturn_t iwl_isr(int irq, void *data) |
871 | { | 872 | { |
872 | struct iwl_trans *trans = data; | 873 | struct iwl_trans *trans = data; |
873 | struct iwl_trans_pcie *trans_pcie; | 874 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
874 | u32 inta, inta_mask; | 875 | u32 inta, inta_mask; |
875 | unsigned long flags; | ||
876 | #ifdef CONFIG_IWLWIFI_DEBUG | 876 | #ifdef CONFIG_IWLWIFI_DEBUG |
877 | u32 inta_fh; | 877 | u32 inta_fh; |
878 | #endif | 878 | #endif |
879 | |||
880 | lockdep_assert_held(&trans_pcie->irq_lock); | ||
881 | |||
879 | if (!trans) | 882 | if (!trans) |
880 | return IRQ_NONE; | 883 | return IRQ_NONE; |
881 | 884 | ||
882 | trace_iwlwifi_dev_irq(trans->dev); | 885 | trace_iwlwifi_dev_irq(trans->dev); |
883 | 886 | ||
884 | trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
885 | |||
886 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); | ||
887 | |||
888 | /* Disable (but don't clear!) interrupts here to avoid | 887 | /* Disable (but don't clear!) interrupts here to avoid |
889 | * back-to-back ISRs and sporadic interrupts from our NIC. | 888 | * back-to-back ISRs and sporadic interrupts from our NIC. |
890 | * If we have something to service, the tasklet will re-enable ints. | 889 | * If we have something to service, the tasklet will re-enable ints. |
@@ -907,7 +906,7 @@ static irqreturn_t iwl_isr(int irq, void *data) | |||
907 | /* Hardware disappeared. It might have already raised | 906 | /* Hardware disappeared. It might have already raised |
908 | * an interrupt */ | 907 | * an interrupt */ |
909 | IWL_WARN(trans, "HARDWARE GONE?? INTA == 0x%08x\n", inta); | 908 | IWL_WARN(trans, "HARDWARE GONE?? INTA == 0x%08x\n", inta); |
910 | goto unplugged; | 909 | return IRQ_HANDLED; |
911 | } | 910 | } |
912 | 911 | ||
913 | #ifdef CONFIG_IWLWIFI_DEBUG | 912 | #ifdef CONFIG_IWLWIFI_DEBUG |
@@ -926,18 +925,13 @@ static irqreturn_t iwl_isr(int irq, void *data) | |||
926 | !trans_pcie->inta) | 925 | !trans_pcie->inta) |
927 | iwl_enable_interrupts(trans); | 926 | iwl_enable_interrupts(trans); |
928 | 927 | ||
929 | unplugged: | 928 | none: |
930 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | ||
931 | return IRQ_HANDLED; | ||
932 | |||
933 | none: | ||
934 | /* re-enable interrupts here since we don't have anything to service. */ | 929 | /* re-enable interrupts here since we don't have anything to service. */ |
935 | /* only Re-enable if disabled by irq and no schedules tasklet. */ | 930 | /* only Re-enable if disabled by irq and no schedules tasklet. */ |
936 | if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) && | 931 | if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) && |
937 | !trans_pcie->inta) | 932 | !trans_pcie->inta) |
938 | iwl_enable_interrupts(trans); | 933 | iwl_enable_interrupts(trans); |
939 | 934 | ||
940 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | ||
941 | return IRQ_NONE; | 935 | return IRQ_NONE; |
942 | } | 936 | } |
943 | 937 | ||
@@ -963,15 +957,19 @@ irqreturn_t iwl_isr_ict(int irq, void *data) | |||
963 | 957 | ||
964 | trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 958 | trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
965 | 959 | ||
960 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); | ||
961 | |||
966 | /* dram interrupt table not set yet, | 962 | /* dram interrupt table not set yet, |
967 | * use legacy interrupt. | 963 | * use legacy interrupt. |
968 | */ | 964 | */ |
969 | if (!trans_pcie->use_ict) | 965 | if (unlikely(!trans_pcie->use_ict)) { |
970 | return iwl_isr(irq, data); | 966 | irqreturn_t ret = iwl_isr(irq, data); |
967 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | ||
968 | return ret; | ||
969 | } | ||
971 | 970 | ||
972 | trace_iwlwifi_dev_irq(trans->dev); | 971 | trace_iwlwifi_dev_irq(trans->dev); |
973 | 972 | ||
974 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); | ||
975 | 973 | ||
976 | /* Disable (but don't clear!) interrupts here to avoid | 974 | /* Disable (but don't clear!) interrupts here to avoid |
977 | * back-to-back ISRs and sporadic interrupts from our NIC. | 975 | * back-to-back ISRs and sporadic interrupts from our NIC. |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index 1e50401023e..42f369d15f4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c | |||
@@ -70,13 +70,12 @@ | |||
70 | 70 | ||
71 | #include "iwl-drv.h" | 71 | #include "iwl-drv.h" |
72 | #include "iwl-trans.h" | 72 | #include "iwl-trans.h" |
73 | #include "iwl-trans-pcie-int.h" | ||
74 | #include "iwl-csr.h" | 73 | #include "iwl-csr.h" |
75 | #include "iwl-prph.h" | 74 | #include "iwl-prph.h" |
76 | #include "iwl-eeprom.h" | ||
77 | #include "iwl-agn-hw.h" | 75 | #include "iwl-agn-hw.h" |
76 | #include "internal.h" | ||
78 | /* FIXME: need to abstract out TX command (once we know what it looks like) */ | 77 | /* FIXME: need to abstract out TX command (once we know what it looks like) */ |
79 | #include "iwl-commands.h" | 78 | #include "dvm/commands.h" |
80 | 79 | ||
81 | #define SCD_QUEUECHAIN_SEL_ALL(trans, trans_pcie) \ | 80 | #define SCD_QUEUECHAIN_SEL_ALL(trans, trans_pcie) \ |
82 | (((1<<trans->cfg->base_params->num_of_queues) - 1) &\ | 81 | (((1<<trans->cfg->base_params->num_of_queues) - 1) &\ |
@@ -297,8 +296,13 @@ static void iwlagn_free_dma_ptr(struct iwl_trans *trans, | |||
297 | static void iwl_trans_pcie_queue_stuck_timer(unsigned long data) | 296 | static void iwl_trans_pcie_queue_stuck_timer(unsigned long data) |
298 | { | 297 | { |
299 | struct iwl_tx_queue *txq = (void *)data; | 298 | struct iwl_tx_queue *txq = (void *)data; |
299 | struct iwl_queue *q = &txq->q; | ||
300 | struct iwl_trans_pcie *trans_pcie = txq->trans_pcie; | 300 | struct iwl_trans_pcie *trans_pcie = txq->trans_pcie; |
301 | struct iwl_trans *trans = iwl_trans_pcie_get_trans(trans_pcie); | 301 | struct iwl_trans *trans = iwl_trans_pcie_get_trans(trans_pcie); |
302 | u32 scd_sram_addr = trans_pcie->scd_base_addr + | ||
303 | SCD_TX_STTS_MEM_LOWER_BOUND + (16 * txq->q.id); | ||
304 | u8 buf[16]; | ||
305 | int i; | ||
302 | 306 | ||
303 | spin_lock(&txq->lock); | 307 | spin_lock(&txq->lock); |
304 | /* check if triggered erroneously */ | 308 | /* check if triggered erroneously */ |
@@ -308,15 +312,48 @@ static void iwl_trans_pcie_queue_stuck_timer(unsigned long data) | |||
308 | } | 312 | } |
309 | spin_unlock(&txq->lock); | 313 | spin_unlock(&txq->lock); |
310 | 314 | ||
311 | |||
312 | IWL_ERR(trans, "Queue %d stuck for %u ms.\n", txq->q.id, | 315 | IWL_ERR(trans, "Queue %d stuck for %u ms.\n", txq->q.id, |
313 | jiffies_to_msecs(trans_pcie->wd_timeout)); | 316 | jiffies_to_msecs(trans_pcie->wd_timeout)); |
314 | IWL_ERR(trans, "Current SW read_ptr %d write_ptr %d\n", | 317 | IWL_ERR(trans, "Current SW read_ptr %d write_ptr %d\n", |
315 | txq->q.read_ptr, txq->q.write_ptr); | 318 | txq->q.read_ptr, txq->q.write_ptr); |
316 | IWL_ERR(trans, "Current HW read_ptr %d write_ptr %d\n", | 319 | |
317 | iwl_read_prph(trans, SCD_QUEUE_RDPTR(txq->q.id)) | 320 | iwl_read_targ_mem_bytes(trans, scd_sram_addr, buf, sizeof(buf)); |
318 | & (TFD_QUEUE_SIZE_MAX - 1), | 321 | |
319 | iwl_read_prph(trans, SCD_QUEUE_WRPTR(txq->q.id))); | 322 | iwl_print_hex_error(trans, buf, sizeof(buf)); |
323 | |||
324 | for (i = 0; i < FH_TCSR_CHNL_NUM; i++) | ||
325 | IWL_ERR(trans, "FH TRBs(%d) = 0x%08x\n", i, | ||
326 | iwl_read_direct32(trans, FH_TX_TRB_REG(i))); | ||
327 | |||
328 | for (i = 0; i < trans->cfg->base_params->num_of_queues; i++) { | ||
329 | u32 status = iwl_read_prph(trans, SCD_QUEUE_STATUS_BITS(i)); | ||
330 | u8 fifo = (status >> SCD_QUEUE_STTS_REG_POS_TXF) & 0x7; | ||
331 | bool active = !!(status & BIT(SCD_QUEUE_STTS_REG_POS_ACTIVE)); | ||
332 | u32 tbl_dw = | ||
333 | iwl_read_targ_mem(trans, | ||
334 | trans_pcie->scd_base_addr + | ||
335 | SCD_TRANS_TBL_OFFSET_QUEUE(i)); | ||
336 | |||
337 | if (i & 0x1) | ||
338 | tbl_dw = (tbl_dw & 0xFFFF0000) >> 16; | ||
339 | else | ||
340 | tbl_dw = tbl_dw & 0x0000FFFF; | ||
341 | |||
342 | IWL_ERR(trans, | ||
343 | "Q %d is %sactive and mapped to fifo %d ra_tid 0x%04x [%d,%d]\n", | ||
344 | i, active ? "" : "in", fifo, tbl_dw, | ||
345 | iwl_read_prph(trans, | ||
346 | SCD_QUEUE_RDPTR(i)) & (txq->q.n_bd - 1), | ||
347 | iwl_read_prph(trans, SCD_QUEUE_WRPTR(i))); | ||
348 | } | ||
349 | |||
350 | for (i = q->read_ptr; i != q->write_ptr; | ||
351 | i = iwl_queue_inc_wrap(i, q->n_bd)) { | ||
352 | struct iwl_tx_cmd *tx_cmd = | ||
353 | (struct iwl_tx_cmd *)txq->entries[i].cmd->payload; | ||
354 | IWL_ERR(trans, "scratch %d = 0x%08x\n", i, | ||
355 | get_unaligned_le32(&tx_cmd->scratch)); | ||
356 | } | ||
320 | 357 | ||
321 | iwl_op_mode_nic_error(trans->op_mode); | 358 | iwl_op_mode_nic_error(trans->op_mode); |
322 | } | 359 | } |
@@ -1009,15 +1046,12 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, | |||
1009 | 1046 | ||
1010 | /* | 1047 | /* |
1011 | * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask | 1048 | * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask |
1012 | * must be called under the irq lock and with MAC access | ||
1013 | */ | 1049 | */ |
1014 | static void iwl_trans_txq_set_sched(struct iwl_trans *trans, u32 mask) | 1050 | static void iwl_trans_txq_set_sched(struct iwl_trans *trans, u32 mask) |
1015 | { | 1051 | { |
1016 | struct iwl_trans_pcie __maybe_unused *trans_pcie = | 1052 | struct iwl_trans_pcie __maybe_unused *trans_pcie = |
1017 | IWL_TRANS_GET_PCIE_TRANS(trans); | 1053 | IWL_TRANS_GET_PCIE_TRANS(trans); |
1018 | 1054 | ||
1019 | lockdep_assert_held(&trans_pcie->irq_lock); | ||
1020 | |||
1021 | iwl_write_prph(trans, SCD_TXFACT, mask); | 1055 | iwl_write_prph(trans, SCD_TXFACT, mask); |
1022 | } | 1056 | } |
1023 | 1057 | ||
@@ -1025,11 +1059,12 @@ static void iwl_tx_start(struct iwl_trans *trans) | |||
1025 | { | 1059 | { |
1026 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 1060 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
1027 | u32 a; | 1061 | u32 a; |
1028 | unsigned long flags; | ||
1029 | int i, chan; | 1062 | int i, chan; |
1030 | u32 reg_val; | 1063 | u32 reg_val; |
1031 | 1064 | ||
1032 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); | 1065 | /* make sure all queue are not stopped/used */ |
1066 | memset(trans_pcie->queue_stopped, 0, sizeof(trans_pcie->queue_stopped)); | ||
1067 | memset(trans_pcie->queue_used, 0, sizeof(trans_pcie->queue_used)); | ||
1033 | 1068 | ||
1034 | trans_pcie->scd_base_addr = | 1069 | trans_pcie->scd_base_addr = |
1035 | iwl_read_prph(trans, SCD_SRAM_BASE_ADDR); | 1070 | iwl_read_prph(trans, SCD_SRAM_BASE_ADDR); |
@@ -1051,60 +1086,31 @@ static void iwl_tx_start(struct iwl_trans *trans) | |||
1051 | iwl_write_prph(trans, SCD_DRAM_BASE_ADDR, | 1086 | iwl_write_prph(trans, SCD_DRAM_BASE_ADDR, |
1052 | trans_pcie->scd_bc_tbls.dma >> 10); | 1087 | trans_pcie->scd_bc_tbls.dma >> 10); |
1053 | 1088 | ||
1054 | /* Enable DMA channel */ | 1089 | /* The chain extension of the SCD doesn't work well. This feature is |
1055 | for (chan = 0; chan < FH_TCSR_CHNL_NUM ; chan++) | 1090 | * enabled by default by the HW, so we need to disable it manually. |
1056 | iwl_write_direct32(trans, FH_TCSR_CHNL_TX_CONFIG_REG(chan), | 1091 | */ |
1057 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | | 1092 | iwl_write_prph(trans, SCD_CHAINEXT_EN, 0); |
1058 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE); | ||
1059 | |||
1060 | /* Update FH chicken bits */ | ||
1061 | reg_val = iwl_read_direct32(trans, FH_TX_CHICKEN_BITS_REG); | ||
1062 | iwl_write_direct32(trans, FH_TX_CHICKEN_BITS_REG, | ||
1063 | reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); | ||
1064 | 1093 | ||
1065 | iwl_write_prph(trans, SCD_QUEUECHAIN_SEL, | 1094 | for (i = 0; i < trans_pcie->n_q_to_fifo; i++) { |
1066 | SCD_QUEUECHAIN_SEL_ALL(trans, trans_pcie)); | 1095 | int fifo = trans_pcie->setup_q_to_fifo[i]; |
1067 | iwl_write_prph(trans, SCD_AGGR_SEL, 0); | ||
1068 | 1096 | ||
1069 | /* initiate the queues */ | 1097 | iwl_trans_pcie_txq_enable(trans, i, fifo, IWL_INVALID_STATION, |
1070 | for (i = 0; i < trans->cfg->base_params->num_of_queues; i++) { | 1098 | IWL_TID_NON_QOS, SCD_FRAME_LIMIT, 0); |
1071 | iwl_write_prph(trans, SCD_QUEUE_RDPTR(i), 0); | ||
1072 | iwl_write_direct32(trans, HBUS_TARG_WRPTR, 0 | (i << 8)); | ||
1073 | iwl_write_targ_mem(trans, trans_pcie->scd_base_addr + | ||
1074 | SCD_CONTEXT_QUEUE_OFFSET(i), 0); | ||
1075 | iwl_write_targ_mem(trans, trans_pcie->scd_base_addr + | ||
1076 | SCD_CONTEXT_QUEUE_OFFSET(i) + | ||
1077 | sizeof(u32), | ||
1078 | ((SCD_WIN_SIZE << | ||
1079 | SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & | ||
1080 | SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | | ||
1081 | ((SCD_FRAME_LIMIT << | ||
1082 | SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & | ||
1083 | SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); | ||
1084 | } | 1099 | } |
1085 | 1100 | ||
1086 | iwl_write_prph(trans, SCD_INTERRUPT_MASK, | ||
1087 | IWL_MASK(0, trans->cfg->base_params->num_of_queues)); | ||
1088 | |||
1089 | /* Activate all Tx DMA/FIFO channels */ | 1101 | /* Activate all Tx DMA/FIFO channels */ |
1090 | iwl_trans_txq_set_sched(trans, IWL_MASK(0, 7)); | 1102 | iwl_trans_txq_set_sched(trans, IWL_MASK(0, 7)); |
1091 | 1103 | ||
1092 | iwl_trans_set_wr_ptrs(trans, trans_pcie->cmd_queue, 0); | 1104 | /* Enable DMA channel */ |
1093 | 1105 | for (chan = 0; chan < FH_TCSR_CHNL_NUM ; chan++) | |
1094 | /* make sure all queue are not stopped/used */ | 1106 | iwl_write_direct32(trans, FH_TCSR_CHNL_TX_CONFIG_REG(chan), |
1095 | memset(trans_pcie->queue_stopped, 0, sizeof(trans_pcie->queue_stopped)); | 1107 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | |
1096 | memset(trans_pcie->queue_used, 0, sizeof(trans_pcie->queue_used)); | 1108 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE); |
1097 | |||
1098 | for (i = 0; i < trans_pcie->n_q_to_fifo; i++) { | ||
1099 | int fifo = trans_pcie->setup_q_to_fifo[i]; | ||
1100 | |||
1101 | set_bit(i, trans_pcie->queue_used); | ||
1102 | |||
1103 | iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[i], | ||
1104 | fifo, true); | ||
1105 | } | ||
1106 | 1109 | ||
1107 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | 1110 | /* Update FH chicken bits */ |
1111 | reg_val = iwl_read_direct32(trans, FH_TX_CHICKEN_BITS_REG); | ||
1112 | iwl_write_direct32(trans, FH_TX_CHICKEN_BITS_REG, | ||
1113 | reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); | ||
1108 | 1114 | ||
1109 | /* Enable L1-Active */ | 1115 | /* Enable L1-Active */ |
1110 | iwl_clear_bits_prph(trans, APMG_PCIDEV_STT_REG, | 1116 | iwl_clear_bits_prph(trans, APMG_PCIDEV_STT_REG, |
@@ -1261,6 +1267,19 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, | |||
1261 | 1267 | ||
1262 | spin_lock(&txq->lock); | 1268 | spin_lock(&txq->lock); |
1263 | 1269 | ||
1270 | /* In AGG mode, the index in the ring must correspond to the WiFi | ||
1271 | * sequence number. This is a HW requirements to help the SCD to parse | ||
1272 | * the BA. | ||
1273 | * Check here that the packets are in the right place on the ring. | ||
1274 | */ | ||
1275 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1276 | wifi_seq = SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); | ||
1277 | WARN_ONCE((iwl_read_prph(trans, SCD_AGGR_SEL) & BIT(txq_id)) && | ||
1278 | ((wifi_seq & 0xff) != q->write_ptr), | ||
1279 | "Q: %d WiFi Seq %d tfdNum %d", | ||
1280 | txq_id, wifi_seq, q->write_ptr); | ||
1281 | #endif | ||
1282 | |||
1264 | /* Set up driver data for this TFD */ | 1283 | /* Set up driver data for this TFD */ |
1265 | txq->entries[q->write_ptr].skb = skb; | 1284 | txq->entries[q->write_ptr].skb = skb; |
1266 | txq->entries[q->write_ptr].cmd = dev_cmd; | 1285 | txq->entries[q->write_ptr].cmd = dev_cmd; |
@@ -1354,7 +1373,8 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, | |||
1354 | skb->data + hdr_len, secondlen); | 1373 | skb->data + hdr_len, secondlen); |
1355 | 1374 | ||
1356 | /* start timer if queue currently empty */ | 1375 | /* start timer if queue currently empty */ |
1357 | if (q->read_ptr == q->write_ptr && trans_pcie->wd_timeout) | 1376 | if (txq->need_update && q->read_ptr == q->write_ptr && |
1377 | trans_pcie->wd_timeout) | ||
1358 | mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout); | 1378 | mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout); |
1359 | 1379 | ||
1360 | /* Tell device the write index *just past* this latest filled TFD */ | 1380 | /* Tell device the write index *just past* this latest filled TFD */ |
@@ -1556,6 +1576,7 @@ void iwl_trans_pcie_free(struct iwl_trans *trans) | |||
1556 | iounmap(trans_pcie->hw_base); | 1576 | iounmap(trans_pcie->hw_base); |
1557 | pci_release_regions(trans_pcie->pci_dev); | 1577 | pci_release_regions(trans_pcie->pci_dev); |
1558 | pci_disable_device(trans_pcie->pci_dev); | 1578 | pci_disable_device(trans_pcie->pci_dev); |
1579 | kmem_cache_destroy(trans->dev_cmd_pool); | ||
1559 | 1580 | ||
1560 | kfree(trans); | 1581 | kfree(trans); |
1561 | } | 1582 | } |
@@ -1997,7 +2018,9 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct file *file, | |||
1997 | if (!trans->op_mode) | 2018 | if (!trans->op_mode) |
1998 | return -EAGAIN; | 2019 | return -EAGAIN; |
1999 | 2020 | ||
2021 | local_bh_disable(); | ||
2000 | iwl_op_mode_nic_error(trans->op_mode); | 2022 | iwl_op_mode_nic_error(trans->op_mode); |
2023 | local_bh_enable(); | ||
2001 | 2024 | ||
2002 | return count; | 2025 | return count; |
2003 | } | 2026 | } |
@@ -2046,8 +2069,8 @@ static const struct iwl_trans_ops trans_ops_pcie = { | |||
2046 | .tx = iwl_trans_pcie_tx, | 2069 | .tx = iwl_trans_pcie_tx, |
2047 | .reclaim = iwl_trans_pcie_reclaim, | 2070 | .reclaim = iwl_trans_pcie_reclaim, |
2048 | 2071 | ||
2049 | .tx_agg_disable = iwl_trans_pcie_tx_agg_disable, | 2072 | .txq_disable = iwl_trans_pcie_txq_disable, |
2050 | .tx_agg_setup = iwl_trans_pcie_tx_agg_setup, | 2073 | .txq_enable = iwl_trans_pcie_txq_enable, |
2051 | 2074 | ||
2052 | .dbgfs_register = iwl_trans_pcie_dbgfs_register, | 2075 | .dbgfs_register = iwl_trans_pcie_dbgfs_register, |
2053 | 2076 | ||
@@ -2070,6 +2093,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, | |||
2070 | { | 2093 | { |
2071 | struct iwl_trans_pcie *trans_pcie; | 2094 | struct iwl_trans_pcie *trans_pcie; |
2072 | struct iwl_trans *trans; | 2095 | struct iwl_trans *trans; |
2096 | char cmd_pool_name[100]; | ||
2073 | u16 pci_cmd; | 2097 | u16 pci_cmd; |
2074 | int err; | 2098 | int err; |
2075 | 2099 | ||
@@ -2166,8 +2190,25 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, | |||
2166 | init_waitqueue_head(&trans->wait_command_queue); | 2190 | init_waitqueue_head(&trans->wait_command_queue); |
2167 | spin_lock_init(&trans->reg_lock); | 2191 | spin_lock_init(&trans->reg_lock); |
2168 | 2192 | ||
2193 | snprintf(cmd_pool_name, sizeof(cmd_pool_name), "iwl_cmd_pool:%s", | ||
2194 | dev_name(trans->dev)); | ||
2195 | |||
2196 | trans->dev_cmd_headroom = 0; | ||
2197 | trans->dev_cmd_pool = | ||
2198 | kmem_cache_create(cmd_pool_name, | ||
2199 | sizeof(struct iwl_device_cmd) | ||
2200 | + trans->dev_cmd_headroom, | ||
2201 | sizeof(void *), | ||
2202 | SLAB_HWCACHE_ALIGN, | ||
2203 | NULL); | ||
2204 | |||
2205 | if (!trans->dev_cmd_pool) | ||
2206 | goto out_pci_disable_msi; | ||
2207 | |||
2169 | return trans; | 2208 | return trans; |
2170 | 2209 | ||
2210 | out_pci_disable_msi: | ||
2211 | pci_disable_msi(pdev); | ||
2171 | out_pci_release_regions: | 2212 | out_pci_release_regions: |
2172 | pci_release_regions(pdev); | 2213 | pci_release_regions(pdev); |
2173 | out_pci_disable_device: | 2214 | out_pci_disable_device: |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index 6f601cd05a9..6baf8deef51 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c | |||
@@ -34,11 +34,10 @@ | |||
34 | #include "iwl-csr.h" | 34 | #include "iwl-csr.h" |
35 | #include "iwl-prph.h" | 35 | #include "iwl-prph.h" |
36 | #include "iwl-io.h" | 36 | #include "iwl-io.h" |
37 | #include "iwl-agn-hw.h" | ||
38 | #include "iwl-op-mode.h" | 37 | #include "iwl-op-mode.h" |
39 | #include "iwl-trans-pcie-int.h" | 38 | #include "internal.h" |
40 | /* FIXME: need to abstract out TX command (once we know what it looks like) */ | 39 | /* FIXME: need to abstract out TX command (once we know what it looks like) */ |
41 | #include "iwl-commands.h" | 40 | #include "dvm/commands.h" |
42 | 41 | ||
43 | #define IWL_TX_CRC_SIZE 4 | 42 | #define IWL_TX_CRC_SIZE 4 |
44 | #define IWL_TX_DELIMITER_SIZE 4 | 43 | #define IWL_TX_DELIMITER_SIZE 4 |
@@ -381,8 +380,8 @@ static void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_trans *trans, | |||
381 | tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent; | 380 | tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent; |
382 | } | 381 | } |
383 | 382 | ||
384 | static int iwlagn_tx_queue_set_q2ratid(struct iwl_trans *trans, u16 ra_tid, | 383 | static int iwl_txq_set_ratid_map(struct iwl_trans *trans, u16 ra_tid, |
385 | u16 txq_id) | 384 | u16 txq_id) |
386 | { | 385 | { |
387 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 386 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
388 | u32 tbl_dw_addr; | 387 | u32 tbl_dw_addr; |
@@ -406,7 +405,7 @@ static int iwlagn_tx_queue_set_q2ratid(struct iwl_trans *trans, u16 ra_tid, | |||
406 | return 0; | 405 | return 0; |
407 | } | 406 | } |
408 | 407 | ||
409 | static void iwlagn_tx_queue_stop_scheduler(struct iwl_trans *trans, u16 txq_id) | 408 | static inline void iwl_txq_set_inactive(struct iwl_trans *trans, u16 txq_id) |
410 | { | 409 | { |
411 | /* Simply stop the queue, but don't change any configuration; | 410 | /* Simply stop the queue, but don't change any configuration; |
412 | * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */ | 411 | * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */ |
@@ -416,101 +415,87 @@ static void iwlagn_tx_queue_stop_scheduler(struct iwl_trans *trans, u16 txq_id) | |||
416 | (1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); | 415 | (1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); |
417 | } | 416 | } |
418 | 417 | ||
419 | void iwl_trans_set_wr_ptrs(struct iwl_trans *trans, int txq_id, u32 index) | 418 | void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo, |
420 | { | 419 | int sta_id, int tid, int frame_limit, u16 ssn) |
421 | IWL_DEBUG_TX_QUEUES(trans, "Q %d WrPtr: %d\n", txq_id, index & 0xff); | ||
422 | iwl_write_direct32(trans, HBUS_TARG_WRPTR, | ||
423 | (index & 0xff) | (txq_id << 8)); | ||
424 | iwl_write_prph(trans, SCD_QUEUE_RDPTR(txq_id), index); | ||
425 | } | ||
426 | |||
427 | void iwl_trans_tx_queue_set_status(struct iwl_trans *trans, | ||
428 | struct iwl_tx_queue *txq, | ||
429 | int tx_fifo_id, bool active) | ||
430 | { | ||
431 | int txq_id = txq->q.id; | ||
432 | |||
433 | iwl_write_prph(trans, SCD_QUEUE_STATUS_BITS(txq_id), | ||
434 | (active << SCD_QUEUE_STTS_REG_POS_ACTIVE) | | ||
435 | (tx_fifo_id << SCD_QUEUE_STTS_REG_POS_TXF) | | ||
436 | (1 << SCD_QUEUE_STTS_REG_POS_WSL) | | ||
437 | SCD_QUEUE_STTS_REG_MSK); | ||
438 | |||
439 | if (active) | ||
440 | IWL_DEBUG_TX_QUEUES(trans, "Activate queue %d on FIFO %d\n", | ||
441 | txq_id, tx_fifo_id); | ||
442 | else | ||
443 | IWL_DEBUG_TX_QUEUES(trans, "Deactivate queue %d\n", txq_id); | ||
444 | } | ||
445 | |||
446 | void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans, int txq_id, int fifo, | ||
447 | int sta_id, int tid, int frame_limit, u16 ssn) | ||
448 | { | 420 | { |
449 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 421 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
450 | unsigned long flags; | ||
451 | u16 ra_tid = BUILD_RAxTID(sta_id, tid); | ||
452 | 422 | ||
453 | if (test_and_set_bit(txq_id, trans_pcie->queue_used)) | 423 | if (test_and_set_bit(txq_id, trans_pcie->queue_used)) |
454 | WARN_ONCE(1, "queue %d already used - expect issues", txq_id); | 424 | WARN_ONCE(1, "queue %d already used - expect issues", txq_id); |
455 | 425 | ||
456 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); | ||
457 | |||
458 | /* Stop this Tx queue before configuring it */ | 426 | /* Stop this Tx queue before configuring it */ |
459 | iwlagn_tx_queue_stop_scheduler(trans, txq_id); | 427 | iwl_txq_set_inactive(trans, txq_id); |
428 | |||
429 | /* Set this queue as a chain-building queue unless it is CMD queue */ | ||
430 | if (txq_id != trans_pcie->cmd_queue) | ||
431 | iwl_set_bits_prph(trans, SCD_QUEUECHAIN_SEL, BIT(txq_id)); | ||
460 | 432 | ||
461 | /* Map receiver-address / traffic-ID to this queue */ | 433 | /* If this queue is mapped to a certain station: it is an AGG queue */ |
462 | iwlagn_tx_queue_set_q2ratid(trans, ra_tid, txq_id); | 434 | if (sta_id != IWL_INVALID_STATION) { |
435 | u16 ra_tid = BUILD_RAxTID(sta_id, tid); | ||
463 | 436 | ||
464 | /* Set this queue as a chain-building queue */ | 437 | /* Map receiver-address / traffic-ID to this queue */ |
465 | iwl_set_bits_prph(trans, SCD_QUEUECHAIN_SEL, BIT(txq_id)); | 438 | iwl_txq_set_ratid_map(trans, ra_tid, txq_id); |
466 | 439 | ||
467 | /* enable aggregations for the queue */ | 440 | /* enable aggregations for the queue */ |
468 | iwl_set_bits_prph(trans, SCD_AGGR_SEL, BIT(txq_id)); | 441 | iwl_set_bits_prph(trans, SCD_AGGR_SEL, BIT(txq_id)); |
442 | } else { | ||
443 | /* | ||
444 | * disable aggregations for the queue, this will also make the | ||
445 | * ra_tid mapping configuration irrelevant since it is now a | ||
446 | * non-AGG queue. | ||
447 | */ | ||
448 | iwl_clear_bits_prph(trans, SCD_AGGR_SEL, BIT(txq_id)); | ||
449 | } | ||
469 | 450 | ||
470 | /* Place first TFD at index corresponding to start sequence number. | 451 | /* Place first TFD at index corresponding to start sequence number. |
471 | * Assumes that ssn_idx is valid (!= 0xFFF) */ | 452 | * Assumes that ssn_idx is valid (!= 0xFFF) */ |
472 | trans_pcie->txq[txq_id].q.read_ptr = (ssn & 0xff); | 453 | trans_pcie->txq[txq_id].q.read_ptr = (ssn & 0xff); |
473 | trans_pcie->txq[txq_id].q.write_ptr = (ssn & 0xff); | 454 | trans_pcie->txq[txq_id].q.write_ptr = (ssn & 0xff); |
474 | iwl_trans_set_wr_ptrs(trans, txq_id, ssn); | 455 | |
456 | iwl_write_direct32(trans, HBUS_TARG_WRPTR, | ||
457 | (ssn & 0xff) | (txq_id << 8)); | ||
458 | iwl_write_prph(trans, SCD_QUEUE_RDPTR(txq_id), ssn); | ||
475 | 459 | ||
476 | /* Set up Tx window size and frame limit for this queue */ | 460 | /* Set up Tx window size and frame limit for this queue */ |
477 | iwl_write_targ_mem(trans, trans_pcie->scd_base_addr + | 461 | iwl_write_targ_mem(trans, trans_pcie->scd_base_addr + |
462 | SCD_CONTEXT_QUEUE_OFFSET(txq_id), 0); | ||
463 | iwl_write_targ_mem(trans, trans_pcie->scd_base_addr + | ||
478 | SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32), | 464 | SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32), |
479 | ((frame_limit << SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & | 465 | ((frame_limit << SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & |
480 | SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | | 466 | SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | |
481 | ((frame_limit << SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & | 467 | ((frame_limit << SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & |
482 | SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); | 468 | SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); |
483 | 469 | ||
484 | iwl_set_bits_prph(trans, SCD_INTERRUPT_MASK, (1 << txq_id)); | ||
485 | |||
486 | /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ | 470 | /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ |
487 | iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[txq_id], | 471 | iwl_write_prph(trans, SCD_QUEUE_STATUS_BITS(txq_id), |
488 | fifo, true); | 472 | (1 << SCD_QUEUE_STTS_REG_POS_ACTIVE) | |
489 | 473 | (fifo << SCD_QUEUE_STTS_REG_POS_TXF) | | |
490 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | 474 | (1 << SCD_QUEUE_STTS_REG_POS_WSL) | |
475 | SCD_QUEUE_STTS_REG_MSK); | ||
476 | IWL_DEBUG_TX_QUEUES(trans, "Activate queue %d on FIFO %d WrPtr: %d\n", | ||
477 | txq_id, fifo, ssn & 0xff); | ||
491 | } | 478 | } |
492 | 479 | ||
493 | void iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans, int txq_id) | 480 | void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id) |
494 | { | 481 | { |
495 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 482 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
483 | u16 rd_ptr, wr_ptr; | ||
484 | int n_bd = trans_pcie->txq[txq_id].q.n_bd; | ||
496 | 485 | ||
497 | if (!test_and_clear_bit(txq_id, trans_pcie->queue_used)) { | 486 | if (!test_and_clear_bit(txq_id, trans_pcie->queue_used)) { |
498 | WARN_ONCE(1, "queue %d not used", txq_id); | 487 | WARN_ONCE(1, "queue %d not used", txq_id); |
499 | return; | 488 | return; |
500 | } | 489 | } |
501 | 490 | ||
502 | iwlagn_tx_queue_stop_scheduler(trans, txq_id); | 491 | rd_ptr = iwl_read_prph(trans, SCD_QUEUE_RDPTR(txq_id)) & (n_bd - 1); |
503 | 492 | wr_ptr = iwl_read_prph(trans, SCD_QUEUE_WRPTR(txq_id)); | |
504 | iwl_clear_bits_prph(trans, SCD_AGGR_SEL, BIT(txq_id)); | ||
505 | |||
506 | trans_pcie->txq[txq_id].q.read_ptr = 0; | ||
507 | trans_pcie->txq[txq_id].q.write_ptr = 0; | ||
508 | iwl_trans_set_wr_ptrs(trans, txq_id, 0); | ||
509 | 493 | ||
510 | iwl_clear_bits_prph(trans, SCD_INTERRUPT_MASK, BIT(txq_id)); | 494 | WARN_ONCE(rd_ptr != wr_ptr, "queue %d isn't empty: [%d,%d]", |
495 | txq_id, rd_ptr, wr_ptr); | ||
511 | 496 | ||
512 | iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[txq_id], | 497 | iwl_txq_set_inactive(trans, txq_id); |
513 | 0, false); | 498 | IWL_DEBUG_TX_QUEUES(trans, "Deactivate queue %d\n", txq_id); |
514 | } | 499 | } |
515 | 500 | ||
516 | /*************** HOST COMMAND QUEUE FUNCTIONS *****/ | 501 | /*************** HOST COMMAND QUEUE FUNCTIONS *****/ |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index eacfe020d0b..5bddf53ece1 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -1553,6 +1553,7 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2, | |||
1553 | hdr = (struct ieee80211_hdr *) skb->data; | 1553 | hdr = (struct ieee80211_hdr *) skb->data; |
1554 | mac80211_hwsim_monitor_ack(data2->hw, hdr->addr2); | 1554 | mac80211_hwsim_monitor_ack(data2->hw, hdr->addr2); |
1555 | } | 1555 | } |
1556 | txi->flags |= IEEE80211_TX_STAT_ACK; | ||
1556 | } | 1557 | } |
1557 | ieee80211_tx_status_irqsafe(data2->hw, skb); | 1558 | ieee80211_tx_status_irqsafe(data2->hw, skb); |
1558 | return 0; | 1559 | return 0; |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 015fec3371a..9c2e08e4b09 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -170,7 +170,9 @@ mwifiex_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *netdev, | |||
170 | if (!priv->sec_info.wep_enabled) | 170 | if (!priv->sec_info.wep_enabled) |
171 | return 0; | 171 | return 0; |
172 | 172 | ||
173 | if (mwifiex_set_encode(priv, NULL, 0, key_index, NULL, 0)) { | 173 | if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP) { |
174 | priv->wep_key_curr_index = key_index; | ||
175 | } else if (mwifiex_set_encode(priv, NULL, 0, key_index, NULL, 0)) { | ||
174 | wiphy_err(wiphy, "set default Tx key index\n"); | 176 | wiphy_err(wiphy, "set default Tx key index\n"); |
175 | return -EFAULT; | 177 | return -EFAULT; |
176 | } | 178 | } |
@@ -187,9 +189,25 @@ mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev, | |||
187 | struct key_params *params) | 189 | struct key_params *params) |
188 | { | 190 | { |
189 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev); | 191 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev); |
192 | struct mwifiex_wep_key *wep_key; | ||
190 | const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | 193 | const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; |
191 | const u8 *peer_mac = pairwise ? mac_addr : bc_mac; | 194 | const u8 *peer_mac = pairwise ? mac_addr : bc_mac; |
192 | 195 | ||
196 | if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP && | ||
197 | (params->cipher == WLAN_CIPHER_SUITE_WEP40 || | ||
198 | params->cipher == WLAN_CIPHER_SUITE_WEP104)) { | ||
199 | if (params->key && params->key_len) { | ||
200 | wep_key = &priv->wep_key[key_index]; | ||
201 | memset(wep_key, 0, sizeof(struct mwifiex_wep_key)); | ||
202 | memcpy(wep_key->key_material, params->key, | ||
203 | params->key_len); | ||
204 | wep_key->key_index = key_index; | ||
205 | wep_key->key_length = params->key_len; | ||
206 | priv->sec_info.wep_enabled = 1; | ||
207 | } | ||
208 | return 0; | ||
209 | } | ||
210 | |||
193 | if (mwifiex_set_encode(priv, params->key, params->key_len, | 211 | if (mwifiex_set_encode(priv, params->key, params->key_len, |
194 | key_index, peer_mac, 0)) { | 212 | key_index, peer_mac, 0)) { |
195 | wiphy_err(wiphy, "crypto keys added\n"); | 213 | wiphy_err(wiphy, "crypto keys added\n"); |
@@ -384,13 +402,13 @@ mwifiex_set_rf_channel(struct mwifiex_private *priv, | |||
384 | cfp.freq = chan->center_freq; | 402 | cfp.freq = chan->center_freq; |
385 | cfp.channel = ieee80211_frequency_to_channel(chan->center_freq); | 403 | cfp.channel = ieee80211_frequency_to_channel(chan->center_freq); |
386 | 404 | ||
387 | if (mwifiex_bss_set_channel(priv, &cfp)) | 405 | if (priv->bss_type == MWIFIEX_BSS_TYPE_STA) { |
388 | return -EFAULT; | 406 | if (mwifiex_bss_set_channel(priv, &cfp)) |
389 | 407 | return -EFAULT; | |
390 | if (priv->bss_type == MWIFIEX_BSS_TYPE_STA) | ||
391 | return mwifiex_drv_change_adhoc_chan(priv, cfp.channel); | 408 | return mwifiex_drv_change_adhoc_chan(priv, cfp.channel); |
392 | else | 409 | } |
393 | return mwifiex_uap_set_channel(priv, cfp.channel); | 410 | |
411 | return 0; | ||
394 | } | 412 | } |
395 | 413 | ||
396 | /* | 414 | /* |
@@ -961,12 +979,25 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, | |||
961 | return -EINVAL; | 979 | return -EINVAL; |
962 | } | 980 | } |
963 | 981 | ||
982 | bss_cfg->channel = | ||
983 | (u8)ieee80211_frequency_to_channel(params->channel->center_freq); | ||
984 | bss_cfg->band_cfg = BAND_CONFIG_MANUAL; | ||
985 | |||
986 | if (mwifiex_set_rf_channel(priv, params->channel, | ||
987 | params->channel_type)) { | ||
988 | kfree(bss_cfg); | ||
989 | wiphy_err(wiphy, "Failed to set band config information!\n"); | ||
990 | return -1; | ||
991 | } | ||
992 | |||
964 | if (mwifiex_set_secure_params(priv, bss_cfg, params)) { | 993 | if (mwifiex_set_secure_params(priv, bss_cfg, params)) { |
965 | kfree(bss_cfg); | 994 | kfree(bss_cfg); |
966 | wiphy_err(wiphy, "Failed to parse secuirty parameters!\n"); | 995 | wiphy_err(wiphy, "Failed to parse secuirty parameters!\n"); |
967 | return -1; | 996 | return -1; |
968 | } | 997 | } |
969 | 998 | ||
999 | mwifiex_set_ht_params(priv, bss_cfg, params); | ||
1000 | |||
970 | if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_UAP_BSS_STOP, | 1001 | if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_UAP_BSS_STOP, |
971 | HostCmd_ACT_GEN_SET, 0, NULL)) { | 1002 | HostCmd_ACT_GEN_SET, 0, NULL)) { |
972 | wiphy_err(wiphy, "Failed to stop the BSS\n"); | 1003 | wiphy_err(wiphy, "Failed to stop the BSS\n"); |
@@ -990,6 +1021,16 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, | |||
990 | return -1; | 1021 | return -1; |
991 | } | 1022 | } |
992 | 1023 | ||
1024 | if (priv->sec_info.wep_enabled) | ||
1025 | priv->curr_pkt_filter |= HostCmd_ACT_MAC_WEP_ENABLE; | ||
1026 | else | ||
1027 | priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_WEP_ENABLE; | ||
1028 | |||
1029 | if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_MAC_CONTROL, | ||
1030 | HostCmd_ACT_GEN_SET, 0, | ||
1031 | &priv->curr_pkt_filter)) | ||
1032 | return -1; | ||
1033 | |||
993 | return 0; | 1034 | return 0; |
994 | } | 1035 | } |
995 | 1036 | ||
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index 51e023ec1de..ea37b887a87 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c | |||
@@ -1102,7 +1102,8 @@ int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv, | |||
1102 | &resp->params.opt_hs_cfg; | 1102 | &resp->params.opt_hs_cfg; |
1103 | uint32_t conditions = le32_to_cpu(phs_cfg->params.hs_config.conditions); | 1103 | uint32_t conditions = le32_to_cpu(phs_cfg->params.hs_config.conditions); |
1104 | 1104 | ||
1105 | if (phs_cfg->action == cpu_to_le16(HS_ACTIVATE)) { | 1105 | if (phs_cfg->action == cpu_to_le16(HS_ACTIVATE) && |
1106 | adapter->iface_type == MWIFIEX_SDIO) { | ||
1106 | mwifiex_hs_activated_event(priv, true); | 1107 | mwifiex_hs_activated_event(priv, true); |
1107 | return 0; | 1108 | return 0; |
1108 | } else { | 1109 | } else { |
@@ -1114,6 +1115,9 @@ int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv, | |||
1114 | } | 1115 | } |
1115 | if (conditions != HOST_SLEEP_CFG_CANCEL) { | 1116 | if (conditions != HOST_SLEEP_CFG_CANCEL) { |
1116 | adapter->is_hs_configured = true; | 1117 | adapter->is_hs_configured = true; |
1118 | if (adapter->iface_type == MWIFIEX_USB || | ||
1119 | adapter->iface_type == MWIFIEX_PCIE) | ||
1120 | mwifiex_hs_activated_event(priv, true); | ||
1117 | } else { | 1121 | } else { |
1118 | adapter->is_hs_configured = false; | 1122 | adapter->is_hs_configured = false; |
1119 | if (adapter->hs_activated) | 1123 | if (adapter->hs_activated) |
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 561452a5c81..1184141839a 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h | |||
@@ -124,6 +124,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
124 | #define TLV_TYPE_UAP_DTIM_PERIOD (PROPRIETARY_TLV_BASE_ID + 45) | 124 | #define TLV_TYPE_UAP_DTIM_PERIOD (PROPRIETARY_TLV_BASE_ID + 45) |
125 | #define TLV_TYPE_UAP_BCAST_SSID (PROPRIETARY_TLV_BASE_ID + 48) | 125 | #define TLV_TYPE_UAP_BCAST_SSID (PROPRIETARY_TLV_BASE_ID + 48) |
126 | #define TLV_TYPE_UAP_RTS_THRESHOLD (PROPRIETARY_TLV_BASE_ID + 51) | 126 | #define TLV_TYPE_UAP_RTS_THRESHOLD (PROPRIETARY_TLV_BASE_ID + 51) |
127 | #define TLV_TYPE_UAP_WEP_KEY (PROPRIETARY_TLV_BASE_ID + 59) | ||
127 | #define TLV_TYPE_UAP_WPA_PASSPHRASE (PROPRIETARY_TLV_BASE_ID + 60) | 128 | #define TLV_TYPE_UAP_WPA_PASSPHRASE (PROPRIETARY_TLV_BASE_ID + 60) |
128 | #define TLV_TYPE_UAP_ENCRY_PROTOCOL (PROPRIETARY_TLV_BASE_ID + 64) | 129 | #define TLV_TYPE_UAP_ENCRY_PROTOCOL (PROPRIETARY_TLV_BASE_ID + 64) |
129 | #define TLV_TYPE_UAP_AKMP (PROPRIETARY_TLV_BASE_ID + 65) | 130 | #define TLV_TYPE_UAP_AKMP (PROPRIETARY_TLV_BASE_ID + 65) |
@@ -162,6 +163,12 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
162 | 163 | ||
163 | #define ISSUPP_11NENABLED(FwCapInfo) (FwCapInfo & BIT(11)) | 164 | #define ISSUPP_11NENABLED(FwCapInfo) (FwCapInfo & BIT(11)) |
164 | 165 | ||
166 | #define MWIFIEX_DEF_HT_CAP (IEEE80211_HT_CAP_DSSSCCK40 | \ | ||
167 | (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT) | \ | ||
168 | IEEE80211_HT_CAP_SM_PS) | ||
169 | |||
170 | #define MWIFIEX_DEF_AMPDU IEEE80211_HT_AMPDU_PARM_FACTOR | ||
171 | |||
165 | /* dev_cap bitmap | 172 | /* dev_cap bitmap |
166 | * BIT | 173 | * BIT |
167 | * 0-16 reserved | 174 | * 0-16 reserved |
@@ -1195,6 +1202,13 @@ struct host_cmd_tlv_passphrase { | |||
1195 | u8 passphrase[0]; | 1202 | u8 passphrase[0]; |
1196 | } __packed; | 1203 | } __packed; |
1197 | 1204 | ||
1205 | struct host_cmd_tlv_wep_key { | ||
1206 | struct host_cmd_tlv tlv; | ||
1207 | u8 key_index; | ||
1208 | u8 is_default; | ||
1209 | u8 key[1]; | ||
1210 | }; | ||
1211 | |||
1198 | struct host_cmd_tlv_auth_type { | 1212 | struct host_cmd_tlv_auth_type { |
1199 | struct host_cmd_tlv tlv; | 1213 | struct host_cmd_tlv tlv; |
1200 | u8 auth_type; | 1214 | u8 auth_type; |
diff --git a/drivers/net/wireless/mwifiex/ie.c b/drivers/net/wireless/mwifiex/ie.c index ceb82cd749c..328fb14d9e1 100644 --- a/drivers/net/wireless/mwifiex/ie.c +++ b/drivers/net/wireless/mwifiex/ie.c | |||
@@ -224,29 +224,46 @@ int mwifiex_set_mgmt_ies(struct mwifiex_private *priv, | |||
224 | struct cfg80211_ap_settings *params) | 224 | struct cfg80211_ap_settings *params) |
225 | { | 225 | { |
226 | struct mwifiex_ie *beacon_ie = NULL, *pr_ie = NULL; | 226 | struct mwifiex_ie *beacon_ie = NULL, *pr_ie = NULL; |
227 | struct mwifiex_ie *ar_ie = NULL, *rsn_ie = NULL; | 227 | struct mwifiex_ie *ar_ie = NULL, *gen_ie = NULL; |
228 | struct ieee_types_header *ie = NULL; | 228 | struct ieee_types_header *rsn_ie = NULL, *wpa_ie = NULL; |
229 | u16 beacon_idx = MWIFIEX_AUTO_IDX_MASK, pr_idx = MWIFIEX_AUTO_IDX_MASK; | 229 | u16 beacon_idx = MWIFIEX_AUTO_IDX_MASK, pr_idx = MWIFIEX_AUTO_IDX_MASK; |
230 | u16 ar_idx = MWIFIEX_AUTO_IDX_MASK, rsn_idx = MWIFIEX_AUTO_IDX_MASK; | 230 | u16 ar_idx = MWIFIEX_AUTO_IDX_MASK, rsn_idx = MWIFIEX_AUTO_IDX_MASK; |
231 | u16 mask; | 231 | u16 mask, ie_len = 0; |
232 | const u8 *vendor_ie; | ||
232 | int ret = 0; | 233 | int ret = 0; |
233 | 234 | ||
234 | if (params->beacon.tail && params->beacon.tail_len) { | 235 | if (params->beacon.tail && params->beacon.tail_len) { |
235 | ie = (void *)cfg80211_find_ie(WLAN_EID_RSN, params->beacon.tail, | 236 | gen_ie = kzalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); |
236 | params->beacon.tail_len); | 237 | if (!gen_ie) |
237 | if (ie) { | 238 | return -ENOMEM; |
238 | rsn_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); | 239 | gen_ie->ie_index = cpu_to_le16(rsn_idx); |
239 | if (!rsn_ie) | 240 | mask = MGMT_MASK_BEACON | MGMT_MASK_PROBE_RESP | |
240 | return -ENOMEM; | 241 | MGMT_MASK_ASSOC_RESP; |
241 | 242 | gen_ie->mgmt_subtype_mask = cpu_to_le16(mask); | |
242 | rsn_ie->ie_index = cpu_to_le16(rsn_idx); | 243 | |
243 | mask = MGMT_MASK_BEACON | MGMT_MASK_PROBE_RESP | | 244 | rsn_ie = (void *)cfg80211_find_ie(WLAN_EID_RSN, |
244 | MGMT_MASK_ASSOC_RESP; | 245 | params->beacon.tail, |
245 | rsn_ie->mgmt_subtype_mask = cpu_to_le16(mask); | 246 | params->beacon.tail_len); |
246 | rsn_ie->ie_length = cpu_to_le16(ie->len + 2); | 247 | if (rsn_ie) { |
247 | memcpy(rsn_ie->ie_buffer, ie, ie->len + 2); | 248 | memcpy(gen_ie->ie_buffer, rsn_ie, rsn_ie->len + 2); |
248 | 249 | ie_len = rsn_ie->len + 2; | |
249 | if (mwifiex_update_uap_custom_ie(priv, rsn_ie, &rsn_idx, | 250 | gen_ie->ie_length = cpu_to_le16(ie_len); |
251 | } | ||
252 | |||
253 | vendor_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, | ||
254 | WLAN_OUI_TYPE_MICROSOFT_WPA, | ||
255 | params->beacon.tail, | ||
256 | params->beacon.tail_len); | ||
257 | if (vendor_ie) { | ||
258 | wpa_ie = (struct ieee_types_header *)vendor_ie; | ||
259 | memcpy(gen_ie->ie_buffer + ie_len, | ||
260 | wpa_ie, wpa_ie->len + 2); | ||
261 | ie_len += wpa_ie->len + 2; | ||
262 | gen_ie->ie_length = cpu_to_le16(ie_len); | ||
263 | } | ||
264 | |||
265 | if (rsn_ie || wpa_ie) { | ||
266 | if (mwifiex_update_uap_custom_ie(priv, gen_ie, &rsn_idx, | ||
250 | NULL, NULL, | 267 | NULL, NULL, |
251 | NULL, NULL)) { | 268 | NULL, NULL)) { |
252 | ret = -1; | 269 | ret = -1; |
@@ -319,7 +336,7 @@ done: | |||
319 | kfree(beacon_ie); | 336 | kfree(beacon_ie); |
320 | kfree(pr_ie); | 337 | kfree(pr_ie); |
321 | kfree(ar_ie); | 338 | kfree(ar_ie); |
322 | kfree(rsn_ie); | 339 | kfree(gen_ie); |
323 | 340 | ||
324 | return ret; | 341 | return ret; |
325 | } | 342 | } |
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index c1cb004db91..b543a4d82ff 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c | |||
@@ -57,6 +57,69 @@ static int mwifiex_add_bss_prio_tbl(struct mwifiex_private *priv) | |||
57 | return 0; | 57 | return 0; |
58 | } | 58 | } |
59 | 59 | ||
60 | static void scan_delay_timer_fn(unsigned long data) | ||
61 | { | ||
62 | struct mwifiex_private *priv = (struct mwifiex_private *)data; | ||
63 | struct mwifiex_adapter *adapter = priv->adapter; | ||
64 | struct cmd_ctrl_node *cmd_node, *tmp_node; | ||
65 | unsigned long flags; | ||
66 | |||
67 | if (!mwifiex_wmm_lists_empty(adapter)) { | ||
68 | if (adapter->scan_delay_cnt == MWIFIEX_MAX_SCAN_DELAY_CNT) { | ||
69 | /* | ||
70 | * Abort scan operation by cancelling all pending scan | ||
71 | * command | ||
72 | */ | ||
73 | spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); | ||
74 | list_for_each_entry_safe(cmd_node, tmp_node, | ||
75 | &adapter->scan_pending_q, | ||
76 | list) { | ||
77 | list_del(&cmd_node->list); | ||
78 | cmd_node->wait_q_enabled = false; | ||
79 | mwifiex_insert_cmd_to_free_q(adapter, cmd_node); | ||
80 | } | ||
81 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, | ||
82 | flags); | ||
83 | |||
84 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); | ||
85 | adapter->scan_processing = false; | ||
86 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, | ||
87 | flags); | ||
88 | |||
89 | if (priv->user_scan_cfg) { | ||
90 | dev_dbg(priv->adapter->dev, | ||
91 | "info: %s: scan aborted\n", __func__); | ||
92 | cfg80211_scan_done(priv->scan_request, 1); | ||
93 | priv->scan_request = NULL; | ||
94 | kfree(priv->user_scan_cfg); | ||
95 | priv->user_scan_cfg = NULL; | ||
96 | } | ||
97 | } else { | ||
98 | /* | ||
99 | * Tx data queue is still not empty, delay scan | ||
100 | * operation further by 20msec. | ||
101 | */ | ||
102 | mod_timer(&priv->scan_delay_timer, jiffies + | ||
103 | msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC)); | ||
104 | adapter->scan_delay_cnt++; | ||
105 | } | ||
106 | queue_work(priv->adapter->workqueue, &priv->adapter->main_work); | ||
107 | } else { | ||
108 | /* | ||
109 | * Tx data queue is empty. Get scan command from scan_pending_q | ||
110 | * and put to cmd_pending_q to resume scan operation | ||
111 | */ | ||
112 | adapter->scan_delay_cnt = 0; | ||
113 | spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); | ||
114 | cmd_node = list_first_entry(&adapter->scan_pending_q, | ||
115 | struct cmd_ctrl_node, list); | ||
116 | list_del(&cmd_node->list); | ||
117 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); | ||
118 | |||
119 | mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true); | ||
120 | } | ||
121 | } | ||
122 | |||
60 | /* | 123 | /* |
61 | * This function initializes the private structure and sets default | 124 | * This function initializes the private structure and sets default |
62 | * values to the members. | 125 | * values to the members. |
@@ -136,6 +199,9 @@ static int mwifiex_init_priv(struct mwifiex_private *priv) | |||
136 | 199 | ||
137 | priv->scan_block = false; | 200 | priv->scan_block = false; |
138 | 201 | ||
202 | setup_timer(&priv->scan_delay_timer, scan_delay_timer_fn, | ||
203 | (unsigned long)priv); | ||
204 | |||
139 | return mwifiex_add_bss_prio_tbl(priv); | 205 | return mwifiex_add_bss_prio_tbl(priv); |
140 | } | 206 | } |
141 | 207 | ||
diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h index e6be6ee7595..9f088fb88cb 100644 --- a/drivers/net/wireless/mwifiex/ioctl.h +++ b/drivers/net/wireless/mwifiex/ioctl.h | |||
@@ -21,6 +21,7 @@ | |||
21 | #define _MWIFIEX_IOCTL_H_ | 21 | #define _MWIFIEX_IOCTL_H_ |
22 | 22 | ||
23 | #include <net/mac80211.h> | 23 | #include <net/mac80211.h> |
24 | #include <net/lib80211.h> | ||
24 | 25 | ||
25 | enum { | 26 | enum { |
26 | MWIFIEX_SCAN_TYPE_UNCHANGED = 0, | 27 | MWIFIEX_SCAN_TYPE_UNCHANGED = 0, |
@@ -71,6 +72,13 @@ struct wpa_param { | |||
71 | u8 passphrase[MWIFIEX_WPA_PASSHPHRASE_LEN]; | 72 | u8 passphrase[MWIFIEX_WPA_PASSHPHRASE_LEN]; |
72 | }; | 73 | }; |
73 | 74 | ||
75 | struct wep_key { | ||
76 | u8 key_index; | ||
77 | u8 is_default; | ||
78 | u16 length; | ||
79 | u8 key[WLAN_KEY_LEN_WEP104]; | ||
80 | }; | ||
81 | |||
74 | #define KEY_MGMT_ON_HOST 0x03 | 82 | #define KEY_MGMT_ON_HOST 0x03 |
75 | #define MWIFIEX_AUTH_MODE_AUTO 0xFF | 83 | #define MWIFIEX_AUTH_MODE_AUTO 0xFF |
76 | #define BAND_CONFIG_MANUAL 0x00 | 84 | #define BAND_CONFIG_MANUAL 0x00 |
@@ -90,6 +98,8 @@ struct mwifiex_uap_bss_param { | |||
90 | u16 key_mgmt; | 98 | u16 key_mgmt; |
91 | u16 key_mgmt_operation; | 99 | u16 key_mgmt_operation; |
92 | struct wpa_param wpa_cfg; | 100 | struct wpa_param wpa_cfg; |
101 | struct wep_key wep_cfg[NUM_WEP_KEYS]; | ||
102 | struct ieee80211_ht_cap ht_cap; | ||
93 | }; | 103 | }; |
94 | 104 | ||
95 | enum { | 105 | enum { |
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 3192855c31c..f0219efc895 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c | |||
@@ -190,7 +190,8 @@ process_start: | |||
190 | adapter->tx_lock_flag) | 190 | adapter->tx_lock_flag) |
191 | break; | 191 | break; |
192 | 192 | ||
193 | if (adapter->scan_processing || adapter->data_sent || | 193 | if ((adapter->scan_processing && |
194 | !adapter->scan_delay_cnt) || adapter->data_sent || | ||
194 | mwifiex_wmm_lists_empty(adapter)) { | 195 | mwifiex_wmm_lists_empty(adapter)) { |
195 | if (adapter->cmd_sent || adapter->curr_cmd || | 196 | if (adapter->cmd_sent || adapter->curr_cmd || |
196 | (!is_command_pending(adapter))) | 197 | (!is_command_pending(adapter))) |
@@ -244,8 +245,8 @@ process_start: | |||
244 | } | 245 | } |
245 | } | 246 | } |
246 | 247 | ||
247 | if (!adapter->scan_processing && !adapter->data_sent && | 248 | if ((!adapter->scan_processing || adapter->scan_delay_cnt) && |
248 | !mwifiex_wmm_lists_empty(adapter)) { | 249 | !adapter->data_sent && !mwifiex_wmm_lists_empty(adapter)) { |
249 | mwifiex_wmm_process_tx(adapter); | 250 | mwifiex_wmm_process_tx(adapter); |
250 | if (adapter->hs_activated) { | 251 | if (adapter->hs_activated) { |
251 | adapter->is_hs_configured = false; | 252 | adapter->is_hs_configured = false; |
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index bd3b0bf94b9..0b3b5aa9830 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h | |||
@@ -79,14 +79,17 @@ enum { | |||
79 | 79 | ||
80 | #define SCAN_BEACON_ENTRY_PAD 6 | 80 | #define SCAN_BEACON_ENTRY_PAD 6 |
81 | 81 | ||
82 | #define MWIFIEX_PASSIVE_SCAN_CHAN_TIME 200 | 82 | #define MWIFIEX_PASSIVE_SCAN_CHAN_TIME 110 |
83 | #define MWIFIEX_ACTIVE_SCAN_CHAN_TIME 200 | 83 | #define MWIFIEX_ACTIVE_SCAN_CHAN_TIME 30 |
84 | #define MWIFIEX_SPECIFIC_SCAN_CHAN_TIME 110 | 84 | #define MWIFIEX_SPECIFIC_SCAN_CHAN_TIME 30 |
85 | 85 | ||
86 | #define SCAN_RSSI(RSSI) (0x100 - ((u8)(RSSI))) | 86 | #define SCAN_RSSI(RSSI) (0x100 - ((u8)(RSSI))) |
87 | 87 | ||
88 | #define MWIFIEX_MAX_TOTAL_SCAN_TIME (MWIFIEX_TIMER_10S - MWIFIEX_TIMER_1S) | 88 | #define MWIFIEX_MAX_TOTAL_SCAN_TIME (MWIFIEX_TIMER_10S - MWIFIEX_TIMER_1S) |
89 | 89 | ||
90 | #define MWIFIEX_MAX_SCAN_DELAY_CNT 50 | ||
91 | #define MWIFIEX_SCAN_DELAY_MSEC 20 | ||
92 | |||
90 | #define RSN_GTK_OUI_OFFSET 2 | 93 | #define RSN_GTK_OUI_OFFSET 2 |
91 | 94 | ||
92 | #define MWIFIEX_OUI_NOT_PRESENT 0 | 95 | #define MWIFIEX_OUI_NOT_PRESENT 0 |
@@ -482,6 +485,7 @@ struct mwifiex_private { | |||
482 | u16 proberesp_idx; | 485 | u16 proberesp_idx; |
483 | u16 assocresp_idx; | 486 | u16 assocresp_idx; |
484 | u16 rsn_idx; | 487 | u16 rsn_idx; |
488 | struct timer_list scan_delay_timer; | ||
485 | }; | 489 | }; |
486 | 490 | ||
487 | enum mwifiex_ba_status { | 491 | enum mwifiex_ba_status { |
@@ -686,6 +690,7 @@ struct mwifiex_adapter { | |||
686 | struct completion fw_load; | 690 | struct completion fw_load; |
687 | u8 country_code[IEEE80211_COUNTRY_STRING_LEN]; | 691 | u8 country_code[IEEE80211_COUNTRY_STRING_LEN]; |
688 | u16 max_mgmt_ie_index; | 692 | u16 max_mgmt_ie_index; |
693 | u8 scan_delay_cnt; | ||
689 | }; | 694 | }; |
690 | 695 | ||
691 | int mwifiex_init_lock_list(struct mwifiex_adapter *adapter); | 696 | int mwifiex_init_lock_list(struct mwifiex_adapter *adapter); |
@@ -835,6 +840,9 @@ void mwifiex_init_priv_params(struct mwifiex_private *priv, | |||
835 | int mwifiex_set_secure_params(struct mwifiex_private *priv, | 840 | int mwifiex_set_secure_params(struct mwifiex_private *priv, |
836 | struct mwifiex_uap_bss_param *bss_config, | 841 | struct mwifiex_uap_bss_param *bss_config, |
837 | struct cfg80211_ap_settings *params); | 842 | struct cfg80211_ap_settings *params); |
843 | void mwifiex_set_ht_params(struct mwifiex_private *priv, | ||
844 | struct mwifiex_uap_bss_param *bss_cfg, | ||
845 | struct cfg80211_ap_settings *params); | ||
838 | 846 | ||
839 | /* | 847 | /* |
840 | * This function checks if the queuing is RA based or not. | 848 | * This function checks if the queuing is RA based or not. |
@@ -985,7 +993,6 @@ int mwifiex_set_tx_power(struct mwifiex_private *priv, | |||
985 | 993 | ||
986 | int mwifiex_main_process(struct mwifiex_adapter *); | 994 | int mwifiex_main_process(struct mwifiex_adapter *); |
987 | 995 | ||
988 | int mwifiex_uap_set_channel(struct mwifiex_private *priv, int channel); | ||
989 | int mwifiex_bss_set_channel(struct mwifiex_private *, | 996 | int mwifiex_bss_set_channel(struct mwifiex_private *, |
990 | struct mwifiex_chan_freq_power *cfp); | 997 | struct mwifiex_chan_freq_power *cfp); |
991 | int mwifiex_get_bss_info(struct mwifiex_private *, | 998 | int mwifiex_get_bss_info(struct mwifiex_private *, |
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 74f04571572..efaf26ccd6b 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c | |||
@@ -28,7 +28,10 @@ | |||
28 | /* The maximum number of channels the firmware can scan per command */ | 28 | /* The maximum number of channels the firmware can scan per command */ |
29 | #define MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN 14 | 29 | #define MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN 14 |
30 | 30 | ||
31 | #define MWIFIEX_CHANNELS_PER_SCAN_CMD 4 | 31 | #define MWIFIEX_DEF_CHANNELS_PER_SCAN_CMD 4 |
32 | #define MWIFIEX_LIMIT_1_CHANNEL_PER_SCAN_CMD 15 | ||
33 | #define MWIFIEX_LIMIT_2_CHANNELS_PER_SCAN_CMD 27 | ||
34 | #define MWIFIEX_LIMIT_3_CHANNELS_PER_SCAN_CMD 35 | ||
32 | 35 | ||
33 | /* Memory needed to store a max sized Channel List TLV for a firmware scan */ | 36 | /* Memory needed to store a max sized Channel List TLV for a firmware scan */ |
34 | #define CHAN_TLV_MAX_SIZE (sizeof(struct mwifiex_ie_types_header) \ | 37 | #define CHAN_TLV_MAX_SIZE (sizeof(struct mwifiex_ie_types_header) \ |
@@ -471,7 +474,7 @@ mwifiex_is_network_compatible(struct mwifiex_private *priv, | |||
471 | * This routine is used for any scan that is not provided with a | 474 | * This routine is used for any scan that is not provided with a |
472 | * specific channel list to scan. | 475 | * specific channel list to scan. |
473 | */ | 476 | */ |
474 | static void | 477 | static int |
475 | mwifiex_scan_create_channel_list(struct mwifiex_private *priv, | 478 | mwifiex_scan_create_channel_list(struct mwifiex_private *priv, |
476 | const struct mwifiex_user_scan_cfg | 479 | const struct mwifiex_user_scan_cfg |
477 | *user_scan_in, | 480 | *user_scan_in, |
@@ -528,6 +531,7 @@ mwifiex_scan_create_channel_list(struct mwifiex_private *priv, | |||
528 | } | 531 | } |
529 | 532 | ||
530 | } | 533 | } |
534 | return chan_idx; | ||
531 | } | 535 | } |
532 | 536 | ||
533 | /* | 537 | /* |
@@ -727,6 +731,7 @@ mwifiex_config_scan(struct mwifiex_private *priv, | |||
727 | u32 num_probes; | 731 | u32 num_probes; |
728 | u32 ssid_len; | 732 | u32 ssid_len; |
729 | u32 chan_idx; | 733 | u32 chan_idx; |
734 | u32 chan_num; | ||
730 | u32 scan_type; | 735 | u32 scan_type; |
731 | u16 scan_dur; | 736 | u16 scan_dur; |
732 | u8 channel; | 737 | u8 channel; |
@@ -850,7 +855,7 @@ mwifiex_config_scan(struct mwifiex_private *priv, | |||
850 | if (*filtered_scan) | 855 | if (*filtered_scan) |
851 | *max_chan_per_scan = MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN; | 856 | *max_chan_per_scan = MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN; |
852 | else | 857 | else |
853 | *max_chan_per_scan = MWIFIEX_CHANNELS_PER_SCAN_CMD; | 858 | *max_chan_per_scan = MWIFIEX_DEF_CHANNELS_PER_SCAN_CMD; |
854 | 859 | ||
855 | /* If the input config or adapter has the number of Probes set, | 860 | /* If the input config or adapter has the number of Probes set, |
856 | add tlv */ | 861 | add tlv */ |
@@ -962,13 +967,28 @@ mwifiex_config_scan(struct mwifiex_private *priv, | |||
962 | dev_dbg(adapter->dev, | 967 | dev_dbg(adapter->dev, |
963 | "info: Scan: Scanning current channel only\n"); | 968 | "info: Scan: Scanning current channel only\n"); |
964 | } | 969 | } |
965 | 970 | chan_num = chan_idx; | |
966 | } else { | 971 | } else { |
967 | dev_dbg(adapter->dev, | 972 | dev_dbg(adapter->dev, |
968 | "info: Scan: Creating full region channel list\n"); | 973 | "info: Scan: Creating full region channel list\n"); |
969 | mwifiex_scan_create_channel_list(priv, user_scan_in, | 974 | chan_num = mwifiex_scan_create_channel_list(priv, user_scan_in, |
970 | scan_chan_list, | 975 | scan_chan_list, |
971 | *filtered_scan); | 976 | *filtered_scan); |
977 | } | ||
978 | |||
979 | /* | ||
980 | * In associated state we will reduce the number of channels scanned per | ||
981 | * scan command to avoid any traffic delay/loss. This number is decided | ||
982 | * based on total number of channels to be scanned due to constraints | ||
983 | * of command buffers. | ||
984 | */ | ||
985 | if (priv->media_connected) { | ||
986 | if (chan_num < MWIFIEX_LIMIT_1_CHANNEL_PER_SCAN_CMD) | ||
987 | *max_chan_per_scan = 1; | ||
988 | else if (chan_num < MWIFIEX_LIMIT_2_CHANNELS_PER_SCAN_CMD) | ||
989 | *max_chan_per_scan = 2; | ||
990 | else if (chan_num < MWIFIEX_LIMIT_3_CHANNELS_PER_SCAN_CMD) | ||
991 | *max_chan_per_scan = 3; | ||
972 | } | 992 | } |
973 | } | 993 | } |
974 | 994 | ||
@@ -1772,14 +1792,23 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, | |||
1772 | priv->user_scan_cfg = NULL; | 1792 | priv->user_scan_cfg = NULL; |
1773 | } | 1793 | } |
1774 | } else { | 1794 | } else { |
1775 | /* Get scan command from scan_pending_q and put to | 1795 | if (!mwifiex_wmm_lists_empty(adapter)) { |
1776 | cmd_pending_q */ | 1796 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, |
1777 | cmd_node = list_first_entry(&adapter->scan_pending_q, | 1797 | flags); |
1778 | struct cmd_ctrl_node, list); | 1798 | adapter->scan_delay_cnt = 1; |
1779 | list_del(&cmd_node->list); | 1799 | mod_timer(&priv->scan_delay_timer, jiffies + |
1780 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); | 1800 | msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC)); |
1781 | 1801 | } else { | |
1782 | mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true); | 1802 | /* Get scan command from scan_pending_q and put to |
1803 | cmd_pending_q */ | ||
1804 | cmd_node = list_first_entry(&adapter->scan_pending_q, | ||
1805 | struct cmd_ctrl_node, list); | ||
1806 | list_del(&cmd_node->list); | ||
1807 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, | ||
1808 | flags); | ||
1809 | mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, | ||
1810 | true); | ||
1811 | } | ||
1783 | } | 1812 | } |
1784 | 1813 | ||
1785 | done: | 1814 | done: |
diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c index 8173ab66066..f40e93fe894 100644 --- a/drivers/net/wireless/mwifiex/uap_cmd.c +++ b/drivers/net/wireless/mwifiex/uap_cmd.c | |||
@@ -26,6 +26,18 @@ int mwifiex_set_secure_params(struct mwifiex_private *priv, | |||
26 | struct mwifiex_uap_bss_param *bss_config, | 26 | struct mwifiex_uap_bss_param *bss_config, |
27 | struct cfg80211_ap_settings *params) { | 27 | struct cfg80211_ap_settings *params) { |
28 | int i; | 28 | int i; |
29 | struct mwifiex_wep_key wep_key; | ||
30 | |||
31 | if (!params->privacy) { | ||
32 | bss_config->protocol = PROTOCOL_NO_SECURITY; | ||
33 | bss_config->key_mgmt = KEY_MGMT_NONE; | ||
34 | bss_config->wpa_cfg.length = 0; | ||
35 | priv->sec_info.wep_enabled = 0; | ||
36 | priv->sec_info.wpa_enabled = 0; | ||
37 | priv->sec_info.wpa2_enabled = 0; | ||
38 | |||
39 | return 0; | ||
40 | } | ||
29 | 41 | ||
30 | switch (params->auth_type) { | 42 | switch (params->auth_type) { |
31 | case NL80211_AUTHTYPE_OPEN_SYSTEM: | 43 | case NL80211_AUTHTYPE_OPEN_SYSTEM: |
@@ -54,7 +66,7 @@ int mwifiex_set_secure_params(struct mwifiex_private *priv, | |||
54 | } | 66 | } |
55 | if (params->crypto.wpa_versions & | 67 | if (params->crypto.wpa_versions & |
56 | NL80211_WPA_VERSION_2) { | 68 | NL80211_WPA_VERSION_2) { |
57 | bss_config->protocol = PROTOCOL_WPA2; | 69 | bss_config->protocol |= PROTOCOL_WPA2; |
58 | bss_config->key_mgmt = KEY_MGMT_EAP; | 70 | bss_config->key_mgmt = KEY_MGMT_EAP; |
59 | } | 71 | } |
60 | break; | 72 | break; |
@@ -66,7 +78,7 @@ int mwifiex_set_secure_params(struct mwifiex_private *priv, | |||
66 | } | 78 | } |
67 | if (params->crypto.wpa_versions & | 79 | if (params->crypto.wpa_versions & |
68 | NL80211_WPA_VERSION_2) { | 80 | NL80211_WPA_VERSION_2) { |
69 | bss_config->protocol = PROTOCOL_WPA2; | 81 | bss_config->protocol |= PROTOCOL_WPA2; |
70 | bss_config->key_mgmt = KEY_MGMT_PSK; | 82 | bss_config->key_mgmt = KEY_MGMT_PSK; |
71 | } | 83 | } |
72 | break; | 84 | break; |
@@ -80,10 +92,19 @@ int mwifiex_set_secure_params(struct mwifiex_private *priv, | |||
80 | case WLAN_CIPHER_SUITE_WEP104: | 92 | case WLAN_CIPHER_SUITE_WEP104: |
81 | break; | 93 | break; |
82 | case WLAN_CIPHER_SUITE_TKIP: | 94 | case WLAN_CIPHER_SUITE_TKIP: |
83 | bss_config->wpa_cfg.pairwise_cipher_wpa = CIPHER_TKIP; | 95 | if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1) |
96 | bss_config->wpa_cfg.pairwise_cipher_wpa |= | ||
97 | CIPHER_TKIP; | ||
98 | if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2) | ||
99 | bss_config->wpa_cfg.pairwise_cipher_wpa2 |= | ||
100 | CIPHER_TKIP; | ||
84 | break; | 101 | break; |
85 | case WLAN_CIPHER_SUITE_CCMP: | 102 | case WLAN_CIPHER_SUITE_CCMP: |
86 | bss_config->wpa_cfg.pairwise_cipher_wpa2 = | 103 | if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1) |
104 | bss_config->wpa_cfg.pairwise_cipher_wpa |= | ||
105 | CIPHER_AES_CCMP; | ||
106 | if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2) | ||
107 | bss_config->wpa_cfg.pairwise_cipher_wpa2 |= | ||
87 | CIPHER_AES_CCMP; | 108 | CIPHER_AES_CCMP; |
88 | default: | 109 | default: |
89 | break; | 110 | break; |
@@ -93,6 +114,27 @@ int mwifiex_set_secure_params(struct mwifiex_private *priv, | |||
93 | switch (params->crypto.cipher_group) { | 114 | switch (params->crypto.cipher_group) { |
94 | case WLAN_CIPHER_SUITE_WEP40: | 115 | case WLAN_CIPHER_SUITE_WEP40: |
95 | case WLAN_CIPHER_SUITE_WEP104: | 116 | case WLAN_CIPHER_SUITE_WEP104: |
117 | if (priv->sec_info.wep_enabled) { | ||
118 | bss_config->protocol = PROTOCOL_STATIC_WEP; | ||
119 | bss_config->key_mgmt = KEY_MGMT_NONE; | ||
120 | bss_config->wpa_cfg.length = 0; | ||
121 | |||
122 | for (i = 0; i < NUM_WEP_KEYS; i++) { | ||
123 | wep_key = priv->wep_key[i]; | ||
124 | bss_config->wep_cfg[i].key_index = i; | ||
125 | |||
126 | if (priv->wep_key_curr_index == i) | ||
127 | bss_config->wep_cfg[i].is_default = 1; | ||
128 | else | ||
129 | bss_config->wep_cfg[i].is_default = 0; | ||
130 | |||
131 | bss_config->wep_cfg[i].length = | ||
132 | wep_key.key_length; | ||
133 | memcpy(&bss_config->wep_cfg[i].key, | ||
134 | &wep_key.key_material, | ||
135 | wep_key.key_length); | ||
136 | } | ||
137 | } | ||
96 | break; | 138 | break; |
97 | case WLAN_CIPHER_SUITE_TKIP: | 139 | case WLAN_CIPHER_SUITE_TKIP: |
98 | bss_config->wpa_cfg.group_cipher = CIPHER_TKIP; | 140 | bss_config->wpa_cfg.group_cipher = CIPHER_TKIP; |
@@ -107,6 +149,33 @@ int mwifiex_set_secure_params(struct mwifiex_private *priv, | |||
107 | return 0; | 149 | return 0; |
108 | } | 150 | } |
109 | 151 | ||
152 | /* This function updates 11n related parameters from IE and sets them into | ||
153 | * bss_config structure. | ||
154 | */ | ||
155 | void | ||
156 | mwifiex_set_ht_params(struct mwifiex_private *priv, | ||
157 | struct mwifiex_uap_bss_param *bss_cfg, | ||
158 | struct cfg80211_ap_settings *params) | ||
159 | { | ||
160 | const u8 *ht_ie; | ||
161 | |||
162 | if (!ISSUPP_11NENABLED(priv->adapter->fw_cap_info)) | ||
163 | return; | ||
164 | |||
165 | ht_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, params->beacon.tail, | ||
166 | params->beacon.tail_len); | ||
167 | if (ht_ie) { | ||
168 | memcpy(&bss_cfg->ht_cap, ht_ie + 2, | ||
169 | sizeof(struct ieee80211_ht_cap)); | ||
170 | } else { | ||
171 | memset(&bss_cfg->ht_cap , 0, sizeof(struct ieee80211_ht_cap)); | ||
172 | bss_cfg->ht_cap.cap_info = cpu_to_le16(MWIFIEX_DEF_HT_CAP); | ||
173 | bss_cfg->ht_cap.ampdu_params_info = MWIFIEX_DEF_AMPDU; | ||
174 | } | ||
175 | |||
176 | return; | ||
177 | } | ||
178 | |||
110 | /* This function initializes some of mwifiex_uap_bss_param variables. | 179 | /* This function initializes some of mwifiex_uap_bss_param variables. |
111 | * This helps FW in ignoring invalid values. These values may or may not | 180 | * This helps FW in ignoring invalid values. These values may or may not |
112 | * be get updated to valid ones at later stage. | 181 | * be get updated to valid ones at later stage. |
@@ -124,6 +193,120 @@ void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config) | |||
124 | } | 193 | } |
125 | 194 | ||
126 | /* This function parses BSS related parameters from structure | 195 | /* This function parses BSS related parameters from structure |
196 | * and prepares TLVs specific to WPA/WPA2 security. | ||
197 | * These TLVs are appended to command buffer. | ||
198 | */ | ||
199 | static void | ||
200 | mwifiex_uap_bss_wpa(u8 **tlv_buf, void *cmd_buf, u16 *param_size) | ||
201 | { | ||
202 | struct host_cmd_tlv_pwk_cipher *pwk_cipher; | ||
203 | struct host_cmd_tlv_gwk_cipher *gwk_cipher; | ||
204 | struct host_cmd_tlv_passphrase *passphrase; | ||
205 | struct host_cmd_tlv_akmp *tlv_akmp; | ||
206 | struct mwifiex_uap_bss_param *bss_cfg = cmd_buf; | ||
207 | u16 cmd_size = *param_size; | ||
208 | u8 *tlv = *tlv_buf; | ||
209 | |||
210 | tlv_akmp = (struct host_cmd_tlv_akmp *)tlv; | ||
211 | tlv_akmp->tlv.type = cpu_to_le16(TLV_TYPE_UAP_AKMP); | ||
212 | tlv_akmp->tlv.len = cpu_to_le16(sizeof(struct host_cmd_tlv_akmp) - | ||
213 | sizeof(struct host_cmd_tlv)); | ||
214 | tlv_akmp->key_mgmt_operation = cpu_to_le16(bss_cfg->key_mgmt_operation); | ||
215 | tlv_akmp->key_mgmt = cpu_to_le16(bss_cfg->key_mgmt); | ||
216 | cmd_size += sizeof(struct host_cmd_tlv_akmp); | ||
217 | tlv += sizeof(struct host_cmd_tlv_akmp); | ||
218 | |||
219 | if (bss_cfg->wpa_cfg.pairwise_cipher_wpa & VALID_CIPHER_BITMAP) { | ||
220 | pwk_cipher = (struct host_cmd_tlv_pwk_cipher *)tlv; | ||
221 | pwk_cipher->tlv.type = cpu_to_le16(TLV_TYPE_PWK_CIPHER); | ||
222 | pwk_cipher->tlv.len = | ||
223 | cpu_to_le16(sizeof(struct host_cmd_tlv_pwk_cipher) - | ||
224 | sizeof(struct host_cmd_tlv)); | ||
225 | pwk_cipher->proto = cpu_to_le16(PROTOCOL_WPA); | ||
226 | pwk_cipher->cipher = bss_cfg->wpa_cfg.pairwise_cipher_wpa; | ||
227 | cmd_size += sizeof(struct host_cmd_tlv_pwk_cipher); | ||
228 | tlv += sizeof(struct host_cmd_tlv_pwk_cipher); | ||
229 | } | ||
230 | |||
231 | if (bss_cfg->wpa_cfg.pairwise_cipher_wpa2 & VALID_CIPHER_BITMAP) { | ||
232 | pwk_cipher = (struct host_cmd_tlv_pwk_cipher *)tlv; | ||
233 | pwk_cipher->tlv.type = cpu_to_le16(TLV_TYPE_PWK_CIPHER); | ||
234 | pwk_cipher->tlv.len = | ||
235 | cpu_to_le16(sizeof(struct host_cmd_tlv_pwk_cipher) - | ||
236 | sizeof(struct host_cmd_tlv)); | ||
237 | pwk_cipher->proto = cpu_to_le16(PROTOCOL_WPA2); | ||
238 | pwk_cipher->cipher = bss_cfg->wpa_cfg.pairwise_cipher_wpa2; | ||
239 | cmd_size += sizeof(struct host_cmd_tlv_pwk_cipher); | ||
240 | tlv += sizeof(struct host_cmd_tlv_pwk_cipher); | ||
241 | } | ||
242 | |||
243 | if (bss_cfg->wpa_cfg.group_cipher & VALID_CIPHER_BITMAP) { | ||
244 | gwk_cipher = (struct host_cmd_tlv_gwk_cipher *)tlv; | ||
245 | gwk_cipher->tlv.type = cpu_to_le16(TLV_TYPE_GWK_CIPHER); | ||
246 | gwk_cipher->tlv.len = | ||
247 | cpu_to_le16(sizeof(struct host_cmd_tlv_gwk_cipher) - | ||
248 | sizeof(struct host_cmd_tlv)); | ||
249 | gwk_cipher->cipher = bss_cfg->wpa_cfg.group_cipher; | ||
250 | cmd_size += sizeof(struct host_cmd_tlv_gwk_cipher); | ||
251 | tlv += sizeof(struct host_cmd_tlv_gwk_cipher); | ||
252 | } | ||
253 | |||
254 | if (bss_cfg->wpa_cfg.length) { | ||
255 | passphrase = (struct host_cmd_tlv_passphrase *)tlv; | ||
256 | passphrase->tlv.type = cpu_to_le16(TLV_TYPE_UAP_WPA_PASSPHRASE); | ||
257 | passphrase->tlv.len = cpu_to_le16(bss_cfg->wpa_cfg.length); | ||
258 | memcpy(passphrase->passphrase, bss_cfg->wpa_cfg.passphrase, | ||
259 | bss_cfg->wpa_cfg.length); | ||
260 | cmd_size += sizeof(struct host_cmd_tlv) + | ||
261 | bss_cfg->wpa_cfg.length; | ||
262 | tlv += sizeof(struct host_cmd_tlv) + bss_cfg->wpa_cfg.length; | ||
263 | } | ||
264 | |||
265 | *param_size = cmd_size; | ||
266 | *tlv_buf = tlv; | ||
267 | |||
268 | return; | ||
269 | } | ||
270 | |||
271 | /* This function parses BSS related parameters from structure | ||
272 | * and prepares TLVs specific to WEP encryption. | ||
273 | * These TLVs are appended to command buffer. | ||
274 | */ | ||
275 | static void | ||
276 | mwifiex_uap_bss_wep(u8 **tlv_buf, void *cmd_buf, u16 *param_size) | ||
277 | { | ||
278 | struct host_cmd_tlv_wep_key *wep_key; | ||
279 | u16 cmd_size = *param_size; | ||
280 | int i; | ||
281 | u8 *tlv = *tlv_buf; | ||
282 | struct mwifiex_uap_bss_param *bss_cfg = cmd_buf; | ||
283 | |||
284 | for (i = 0; i < NUM_WEP_KEYS; i++) { | ||
285 | if (bss_cfg->wep_cfg[i].length && | ||
286 | (bss_cfg->wep_cfg[i].length == WLAN_KEY_LEN_WEP40 || | ||
287 | bss_cfg->wep_cfg[i].length == WLAN_KEY_LEN_WEP104)) { | ||
288 | wep_key = (struct host_cmd_tlv_wep_key *)tlv; | ||
289 | wep_key->tlv.type = cpu_to_le16(TLV_TYPE_UAP_WEP_KEY); | ||
290 | wep_key->tlv.len = | ||
291 | cpu_to_le16(bss_cfg->wep_cfg[i].length + 2); | ||
292 | wep_key->key_index = bss_cfg->wep_cfg[i].key_index; | ||
293 | wep_key->is_default = bss_cfg->wep_cfg[i].is_default; | ||
294 | memcpy(wep_key->key, bss_cfg->wep_cfg[i].key, | ||
295 | bss_cfg->wep_cfg[i].length); | ||
296 | cmd_size += sizeof(struct host_cmd_tlv) + 2 + | ||
297 | bss_cfg->wep_cfg[i].length; | ||
298 | tlv += sizeof(struct host_cmd_tlv) + 2 + | ||
299 | bss_cfg->wep_cfg[i].length; | ||
300 | } | ||
301 | } | ||
302 | |||
303 | *param_size = cmd_size; | ||
304 | *tlv_buf = tlv; | ||
305 | |||
306 | return; | ||
307 | } | ||
308 | |||
309 | /* This function parses BSS related parameters from structure | ||
127 | * and prepares TLVs. These TLVs are appended to command buffer. | 310 | * and prepares TLVs. These TLVs are appended to command buffer. |
128 | */ | 311 | */ |
129 | static int | 312 | static int |
@@ -137,12 +320,9 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size) | |||
137 | struct host_cmd_tlv_frag_threshold *frag_threshold; | 320 | struct host_cmd_tlv_frag_threshold *frag_threshold; |
138 | struct host_cmd_tlv_rts_threshold *rts_threshold; | 321 | struct host_cmd_tlv_rts_threshold *rts_threshold; |
139 | struct host_cmd_tlv_retry_limit *retry_limit; | 322 | struct host_cmd_tlv_retry_limit *retry_limit; |
140 | struct host_cmd_tlv_pwk_cipher *pwk_cipher; | ||
141 | struct host_cmd_tlv_gwk_cipher *gwk_cipher; | ||
142 | struct host_cmd_tlv_encrypt_protocol *encrypt_protocol; | 323 | struct host_cmd_tlv_encrypt_protocol *encrypt_protocol; |
143 | struct host_cmd_tlv_auth_type *auth_type; | 324 | struct host_cmd_tlv_auth_type *auth_type; |
144 | struct host_cmd_tlv_passphrase *passphrase; | 325 | struct mwifiex_ie_types_htcap *htcap; |
145 | struct host_cmd_tlv_akmp *tlv_akmp; | ||
146 | struct mwifiex_uap_bss_param *bss_cfg = cmd_buf; | 326 | struct mwifiex_uap_bss_param *bss_cfg = cmd_buf; |
147 | u16 cmd_size = *param_size; | 327 | u16 cmd_size = *param_size; |
148 | 328 | ||
@@ -232,70 +412,11 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size) | |||
232 | } | 412 | } |
233 | if ((bss_cfg->protocol & PROTOCOL_WPA) || | 413 | if ((bss_cfg->protocol & PROTOCOL_WPA) || |
234 | (bss_cfg->protocol & PROTOCOL_WPA2) || | 414 | (bss_cfg->protocol & PROTOCOL_WPA2) || |
235 | (bss_cfg->protocol & PROTOCOL_EAP)) { | 415 | (bss_cfg->protocol & PROTOCOL_EAP)) |
236 | tlv_akmp = (struct host_cmd_tlv_akmp *)tlv; | 416 | mwifiex_uap_bss_wpa(&tlv, cmd_buf, &cmd_size); |
237 | tlv_akmp->tlv.type = cpu_to_le16(TLV_TYPE_UAP_AKMP); | 417 | else |
238 | tlv_akmp->tlv.len = | 418 | mwifiex_uap_bss_wep(&tlv, cmd_buf, &cmd_size); |
239 | cpu_to_le16(sizeof(struct host_cmd_tlv_akmp) - | 419 | |
240 | sizeof(struct host_cmd_tlv)); | ||
241 | tlv_akmp->key_mgmt_operation = | ||
242 | cpu_to_le16(bss_cfg->key_mgmt_operation); | ||
243 | tlv_akmp->key_mgmt = cpu_to_le16(bss_cfg->key_mgmt); | ||
244 | cmd_size += sizeof(struct host_cmd_tlv_akmp); | ||
245 | tlv += sizeof(struct host_cmd_tlv_akmp); | ||
246 | |||
247 | if (bss_cfg->wpa_cfg.pairwise_cipher_wpa & | ||
248 | VALID_CIPHER_BITMAP) { | ||
249 | pwk_cipher = (struct host_cmd_tlv_pwk_cipher *)tlv; | ||
250 | pwk_cipher->tlv.type = | ||
251 | cpu_to_le16(TLV_TYPE_PWK_CIPHER); | ||
252 | pwk_cipher->tlv.len = cpu_to_le16( | ||
253 | sizeof(struct host_cmd_tlv_pwk_cipher) - | ||
254 | sizeof(struct host_cmd_tlv)); | ||
255 | pwk_cipher->proto = cpu_to_le16(PROTOCOL_WPA); | ||
256 | pwk_cipher->cipher = | ||
257 | bss_cfg->wpa_cfg.pairwise_cipher_wpa; | ||
258 | cmd_size += sizeof(struct host_cmd_tlv_pwk_cipher); | ||
259 | tlv += sizeof(struct host_cmd_tlv_pwk_cipher); | ||
260 | } | ||
261 | if (bss_cfg->wpa_cfg.pairwise_cipher_wpa2 & | ||
262 | VALID_CIPHER_BITMAP) { | ||
263 | pwk_cipher = (struct host_cmd_tlv_pwk_cipher *)tlv; | ||
264 | pwk_cipher->tlv.type = cpu_to_le16(TLV_TYPE_PWK_CIPHER); | ||
265 | pwk_cipher->tlv.len = cpu_to_le16( | ||
266 | sizeof(struct host_cmd_tlv_pwk_cipher) - | ||
267 | sizeof(struct host_cmd_tlv)); | ||
268 | pwk_cipher->proto = cpu_to_le16(PROTOCOL_WPA2); | ||
269 | pwk_cipher->cipher = | ||
270 | bss_cfg->wpa_cfg.pairwise_cipher_wpa2; | ||
271 | cmd_size += sizeof(struct host_cmd_tlv_pwk_cipher); | ||
272 | tlv += sizeof(struct host_cmd_tlv_pwk_cipher); | ||
273 | } | ||
274 | if (bss_cfg->wpa_cfg.group_cipher & VALID_CIPHER_BITMAP) { | ||
275 | gwk_cipher = (struct host_cmd_tlv_gwk_cipher *)tlv; | ||
276 | gwk_cipher->tlv.type = cpu_to_le16(TLV_TYPE_GWK_CIPHER); | ||
277 | gwk_cipher->tlv.len = cpu_to_le16( | ||
278 | sizeof(struct host_cmd_tlv_gwk_cipher) - | ||
279 | sizeof(struct host_cmd_tlv)); | ||
280 | gwk_cipher->cipher = bss_cfg->wpa_cfg.group_cipher; | ||
281 | cmd_size += sizeof(struct host_cmd_tlv_gwk_cipher); | ||
282 | tlv += sizeof(struct host_cmd_tlv_gwk_cipher); | ||
283 | } | ||
284 | if (bss_cfg->wpa_cfg.length) { | ||
285 | passphrase = (struct host_cmd_tlv_passphrase *)tlv; | ||
286 | passphrase->tlv.type = | ||
287 | cpu_to_le16(TLV_TYPE_UAP_WPA_PASSPHRASE); | ||
288 | passphrase->tlv.len = | ||
289 | cpu_to_le16(bss_cfg->wpa_cfg.length); | ||
290 | memcpy(passphrase->passphrase, | ||
291 | bss_cfg->wpa_cfg.passphrase, | ||
292 | bss_cfg->wpa_cfg.length); | ||
293 | cmd_size += sizeof(struct host_cmd_tlv) + | ||
294 | bss_cfg->wpa_cfg.length; | ||
295 | tlv += sizeof(struct host_cmd_tlv) + | ||
296 | bss_cfg->wpa_cfg.length; | ||
297 | } | ||
298 | } | ||
299 | if ((bss_cfg->auth_mode <= WLAN_AUTH_SHARED_KEY) || | 420 | if ((bss_cfg->auth_mode <= WLAN_AUTH_SHARED_KEY) || |
300 | (bss_cfg->auth_mode == MWIFIEX_AUTH_MODE_AUTO)) { | 421 | (bss_cfg->auth_mode == MWIFIEX_AUTH_MODE_AUTO)) { |
301 | auth_type = (struct host_cmd_tlv_auth_type *)tlv; | 422 | auth_type = (struct host_cmd_tlv_auth_type *)tlv; |
@@ -319,6 +440,25 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size) | |||
319 | tlv += sizeof(struct host_cmd_tlv_encrypt_protocol); | 440 | tlv += sizeof(struct host_cmd_tlv_encrypt_protocol); |
320 | } | 441 | } |
321 | 442 | ||
443 | if (bss_cfg->ht_cap.cap_info) { | ||
444 | htcap = (struct mwifiex_ie_types_htcap *)tlv; | ||
445 | htcap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY); | ||
446 | htcap->header.len = | ||
447 | cpu_to_le16(sizeof(struct ieee80211_ht_cap)); | ||
448 | htcap->ht_cap.cap_info = bss_cfg->ht_cap.cap_info; | ||
449 | htcap->ht_cap.ampdu_params_info = | ||
450 | bss_cfg->ht_cap.ampdu_params_info; | ||
451 | memcpy(&htcap->ht_cap.mcs, &bss_cfg->ht_cap.mcs, | ||
452 | sizeof(struct ieee80211_mcs_info)); | ||
453 | htcap->ht_cap.extended_ht_cap_info = | ||
454 | bss_cfg->ht_cap.extended_ht_cap_info; | ||
455 | htcap->ht_cap.tx_BF_cap_info = bss_cfg->ht_cap.tx_BF_cap_info; | ||
456 | htcap->ht_cap.antenna_selection_info = | ||
457 | bss_cfg->ht_cap.antenna_selection_info; | ||
458 | cmd_size += sizeof(struct mwifiex_ie_types_htcap); | ||
459 | tlv += sizeof(struct mwifiex_ie_types_htcap); | ||
460 | } | ||
461 | |||
322 | *param_size = cmd_size; | 462 | *param_size = cmd_size; |
323 | 463 | ||
324 | return 0; | 464 | return 0; |
@@ -410,33 +550,3 @@ int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, u16 cmd_no, | |||
410 | 550 | ||
411 | return 0; | 551 | return 0; |
412 | } | 552 | } |
413 | |||
414 | /* This function sets the RF channel for AP. | ||
415 | * | ||
416 | * This function populates channel information in AP config structure | ||
417 | * and sends command to configure channel information in AP. | ||
418 | */ | ||
419 | int mwifiex_uap_set_channel(struct mwifiex_private *priv, int channel) | ||
420 | { | ||
421 | struct mwifiex_uap_bss_param *bss_cfg; | ||
422 | struct wiphy *wiphy = priv->wdev->wiphy; | ||
423 | |||
424 | bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param), GFP_KERNEL); | ||
425 | if (!bss_cfg) | ||
426 | return -ENOMEM; | ||
427 | |||
428 | mwifiex_set_sys_config_invalid_data(bss_cfg); | ||
429 | bss_cfg->band_cfg = BAND_CONFIG_MANUAL; | ||
430 | bss_cfg->channel = channel; | ||
431 | |||
432 | if (mwifiex_send_cmd_async(priv, HostCmd_CMD_UAP_SYS_CONFIG, | ||
433 | HostCmd_ACT_GEN_SET, | ||
434 | UAP_BSS_PARAMS_I, bss_cfg)) { | ||
435 | wiphy_err(wiphy, "Failed to set the uAP channel\n"); | ||
436 | kfree(bss_cfg); | ||
437 | return -1; | ||
438 | } | ||
439 | |||
440 | kfree(bss_cfg); | ||
441 | return 0; | ||
442 | } | ||
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 2e9e6af2136..dfcd02ab6ca 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c | |||
@@ -2110,7 +2110,7 @@ resize_buf: | |||
2110 | while (check_bssid_list_item(bssid, bssid_len, buf, len)) { | 2110 | while (check_bssid_list_item(bssid, bssid_len, buf, len)) { |
2111 | if (rndis_bss_info_update(usbdev, bssid) && match_bssid && | 2111 | if (rndis_bss_info_update(usbdev, bssid) && match_bssid && |
2112 | matched) { | 2112 | matched) { |
2113 | if (!ether_addr_equal(bssid->mac, match_bssid)) | 2113 | if (ether_addr_equal(bssid->mac, match_bssid)) |
2114 | *matched = true; | 2114 | *matched = true; |
2115 | } | 2115 | } |
2116 | 2116 | ||
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index 299c3879582..c7548da6573 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig | |||
@@ -99,6 +99,14 @@ config RT2800PCI_RT53XX | |||
99 | rt2800pci driver. | 99 | rt2800pci driver. |
100 | Supported chips: RT5390 | 100 | Supported chips: RT5390 |
101 | 101 | ||
102 | config RT2800PCI_RT3290 | ||
103 | bool "rt2800pci - Include support for rt3290 devices (EXPERIMENTAL)" | ||
104 | depends on EXPERIMENTAL | ||
105 | default y | ||
106 | ---help--- | ||
107 | This adds support for rt3290 wireless chipset family to the | ||
108 | rt2800pci driver. | ||
109 | Supported chips: RT3290 | ||
102 | endif | 110 | endif |
103 | 111 | ||
104 | config RT2500USB | 112 | config RT2500USB |
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index 1ca88cdc6ec..e252e9bafd0 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h | |||
@@ -68,6 +68,7 @@ | |||
68 | #define RF3320 0x000b | 68 | #define RF3320 0x000b |
69 | #define RF3322 0x000c | 69 | #define RF3322 0x000c |
70 | #define RF3053 0x000d | 70 | #define RF3053 0x000d |
71 | #define RF3290 0x3290 | ||
71 | #define RF5360 0x5360 | 72 | #define RF5360 0x5360 |
72 | #define RF5370 0x5370 | 73 | #define RF5370 0x5370 |
73 | #define RF5372 0x5372 | 74 | #define RF5372 0x5372 |
@@ -117,6 +118,12 @@ | |||
117 | * Registers. | 118 | * Registers. |
118 | */ | 119 | */ |
119 | 120 | ||
121 | |||
122 | /* | ||
123 | * MAC_CSR0_3290: MAC_CSR0 for RT3290 to identity MAC version number. | ||
124 | */ | ||
125 | #define MAC_CSR0_3290 0x0000 | ||
126 | |||
120 | /* | 127 | /* |
121 | * E2PROM_CSR: PCI EEPROM control register. | 128 | * E2PROM_CSR: PCI EEPROM control register. |
122 | * RELOAD: Write 1 to reload eeprom content. | 129 | * RELOAD: Write 1 to reload eeprom content. |
@@ -133,6 +140,150 @@ | |||
133 | #define E2PROM_CSR_RELOAD FIELD32(0x00000080) | 140 | #define E2PROM_CSR_RELOAD FIELD32(0x00000080) |
134 | 141 | ||
135 | /* | 142 | /* |
143 | * CMB_CTRL_CFG | ||
144 | */ | ||
145 | #define CMB_CTRL 0x0020 | ||
146 | #define AUX_OPT_BIT0 FIELD32(0x00000001) | ||
147 | #define AUX_OPT_BIT1 FIELD32(0x00000002) | ||
148 | #define AUX_OPT_BIT2 FIELD32(0x00000004) | ||
149 | #define AUX_OPT_BIT3 FIELD32(0x00000008) | ||
150 | #define AUX_OPT_BIT4 FIELD32(0x00000010) | ||
151 | #define AUX_OPT_BIT5 FIELD32(0x00000020) | ||
152 | #define AUX_OPT_BIT6 FIELD32(0x00000040) | ||
153 | #define AUX_OPT_BIT7 FIELD32(0x00000080) | ||
154 | #define AUX_OPT_BIT8 FIELD32(0x00000100) | ||
155 | #define AUX_OPT_BIT9 FIELD32(0x00000200) | ||
156 | #define AUX_OPT_BIT10 FIELD32(0x00000400) | ||
157 | #define AUX_OPT_BIT11 FIELD32(0x00000800) | ||
158 | #define AUX_OPT_BIT12 FIELD32(0x00001000) | ||
159 | #define AUX_OPT_BIT13 FIELD32(0x00002000) | ||
160 | #define AUX_OPT_BIT14 FIELD32(0x00004000) | ||
161 | #define AUX_OPT_BIT15 FIELD32(0x00008000) | ||
162 | #define LDO25_LEVEL FIELD32(0x00030000) | ||
163 | #define LDO25_LARGEA FIELD32(0x00040000) | ||
164 | #define LDO25_FRC_ON FIELD32(0x00080000) | ||
165 | #define CMB_RSV FIELD32(0x00300000) | ||
166 | #define XTAL_RDY FIELD32(0x00400000) | ||
167 | #define PLL_LD FIELD32(0x00800000) | ||
168 | #define LDO_CORE_LEVEL FIELD32(0x0F000000) | ||
169 | #define LDO_BGSEL FIELD32(0x30000000) | ||
170 | #define LDO3_EN FIELD32(0x40000000) | ||
171 | #define LDO0_EN FIELD32(0x80000000) | ||
172 | |||
173 | /* | ||
174 | * EFUSE_CSR_3290: RT3290 EEPROM | ||
175 | */ | ||
176 | #define EFUSE_CTRL_3290 0x0024 | ||
177 | |||
178 | /* | ||
179 | * EFUSE_DATA3 of 3290 | ||
180 | */ | ||
181 | #define EFUSE_DATA3_3290 0x0028 | ||
182 | |||
183 | /* | ||
184 | * EFUSE_DATA2 of 3290 | ||
185 | */ | ||
186 | #define EFUSE_DATA2_3290 0x002c | ||
187 | |||
188 | /* | ||
189 | * EFUSE_DATA1 of 3290 | ||
190 | */ | ||
191 | #define EFUSE_DATA1_3290 0x0030 | ||
192 | |||
193 | /* | ||
194 | * EFUSE_DATA0 of 3290 | ||
195 | */ | ||
196 | #define EFUSE_DATA0_3290 0x0034 | ||
197 | |||
198 | /* | ||
199 | * OSC_CTRL_CFG | ||
200 | * Ring oscillator configuration | ||
201 | */ | ||
202 | #define OSC_CTRL 0x0038 | ||
203 | #define OSC_REF_CYCLE FIELD32(0x00001fff) | ||
204 | #define OSC_RSV FIELD32(0x0000e000) | ||
205 | #define OSC_CAL_CNT FIELD32(0x0fff0000) | ||
206 | #define OSC_CAL_ACK FIELD32(0x10000000) | ||
207 | #define OSC_CLK_32K_VLD FIELD32(0x20000000) | ||
208 | #define OSC_CAL_REQ FIELD32(0x40000000) | ||
209 | #define OSC_ROSC_EN FIELD32(0x80000000) | ||
210 | |||
211 | /* | ||
212 | * COEX_CFG_0 | ||
213 | */ | ||
214 | #define COEX_CFG0 0x0040 | ||
215 | #define COEX_CFG_ANT FIELD32(0xff000000) | ||
216 | /* | ||
217 | * COEX_CFG_1 | ||
218 | */ | ||
219 | #define COEX_CFG1 0x0044 | ||
220 | |||
221 | /* | ||
222 | * COEX_CFG_2 | ||
223 | */ | ||
224 | #define COEX_CFG2 0x0048 | ||
225 | #define BT_COEX_CFG1 FIELD32(0xff000000) | ||
226 | #define BT_COEX_CFG0 FIELD32(0x00ff0000) | ||
227 | #define WL_COEX_CFG1 FIELD32(0x0000ff00) | ||
228 | #define WL_COEX_CFG0 FIELD32(0x000000ff) | ||
229 | /* | ||
230 | * PLL_CTRL_CFG | ||
231 | * PLL configuration register | ||
232 | */ | ||
233 | #define PLL_CTRL 0x0050 | ||
234 | #define PLL_RESERVED_INPUT1 FIELD32(0x000000ff) | ||
235 | #define PLL_RESERVED_INPUT2 FIELD32(0x0000ff00) | ||
236 | #define PLL_CONTROL FIELD32(0x00070000) | ||
237 | #define PLL_LPF_R1 FIELD32(0x00080000) | ||
238 | #define PLL_LPF_C1_CTRL FIELD32(0x00300000) | ||
239 | #define PLL_LPF_C2_CTRL FIELD32(0x00c00000) | ||
240 | #define PLL_CP_CURRENT_CTRL FIELD32(0x03000000) | ||
241 | #define PLL_PFD_DELAY_CTRL FIELD32(0x0c000000) | ||
242 | #define PLL_LOCK_CTRL FIELD32(0x70000000) | ||
243 | #define PLL_VBGBK_EN FIELD32(0x80000000) | ||
244 | |||
245 | |||
246 | /* | ||
247 | * WLAN_CTRL_CFG | ||
248 | * RT3290 wlan configuration | ||
249 | */ | ||
250 | #define WLAN_FUN_CTRL 0x0080 | ||
251 | #define WLAN_EN FIELD32(0x00000001) | ||
252 | #define WLAN_CLK_EN FIELD32(0x00000002) | ||
253 | #define WLAN_RSV1 FIELD32(0x00000004) | ||
254 | #define WLAN_RESET FIELD32(0x00000008) | ||
255 | #define PCIE_APP0_CLK_REQ FIELD32(0x00000010) | ||
256 | #define FRC_WL_ANT_SET FIELD32(0x00000020) | ||
257 | #define INV_TR_SW0 FIELD32(0x00000040) | ||
258 | #define WLAN_GPIO_IN_BIT0 FIELD32(0x00000100) | ||
259 | #define WLAN_GPIO_IN_BIT1 FIELD32(0x00000200) | ||
260 | #define WLAN_GPIO_IN_BIT2 FIELD32(0x00000400) | ||
261 | #define WLAN_GPIO_IN_BIT3 FIELD32(0x00000800) | ||
262 | #define WLAN_GPIO_IN_BIT4 FIELD32(0x00001000) | ||
263 | #define WLAN_GPIO_IN_BIT5 FIELD32(0x00002000) | ||
264 | #define WLAN_GPIO_IN_BIT6 FIELD32(0x00004000) | ||
265 | #define WLAN_GPIO_IN_BIT7 FIELD32(0x00008000) | ||
266 | #define WLAN_GPIO_IN_BIT_ALL FIELD32(0x0000ff00) | ||
267 | #define WLAN_GPIO_OUT_BIT0 FIELD32(0x00010000) | ||
268 | #define WLAN_GPIO_OUT_BIT1 FIELD32(0x00020000) | ||
269 | #define WLAN_GPIO_OUT_BIT2 FIELD32(0x00040000) | ||
270 | #define WLAN_GPIO_OUT_BIT3 FIELD32(0x00050000) | ||
271 | #define WLAN_GPIO_OUT_BIT4 FIELD32(0x00100000) | ||
272 | #define WLAN_GPIO_OUT_BIT5 FIELD32(0x00200000) | ||
273 | #define WLAN_GPIO_OUT_BIT6 FIELD32(0x00400000) | ||
274 | #define WLAN_GPIO_OUT_BIT7 FIELD32(0x00800000) | ||
275 | #define WLAN_GPIO_OUT_BIT_ALL FIELD32(0x00ff0000) | ||
276 | #define WLAN_GPIO_OUT_OE_BIT0 FIELD32(0x01000000) | ||
277 | #define WLAN_GPIO_OUT_OE_BIT1 FIELD32(0x02000000) | ||
278 | #define WLAN_GPIO_OUT_OE_BIT2 FIELD32(0x04000000) | ||
279 | #define WLAN_GPIO_OUT_OE_BIT3 FIELD32(0x08000000) | ||
280 | #define WLAN_GPIO_OUT_OE_BIT4 FIELD32(0x10000000) | ||
281 | #define WLAN_GPIO_OUT_OE_BIT5 FIELD32(0x20000000) | ||
282 | #define WLAN_GPIO_OUT_OE_BIT6 FIELD32(0x40000000) | ||
283 | #define WLAN_GPIO_OUT_OE_BIT7 FIELD32(0x80000000) | ||
284 | #define WLAN_GPIO_OUT_OE_BIT_ALL FIELD32(0xff000000) | ||
285 | |||
286 | /* | ||
136 | * AUX_CTRL: Aux/PCI-E related configuration | 287 | * AUX_CTRL: Aux/PCI-E related configuration |
137 | */ | 288 | */ |
138 | #define AUX_CTRL 0x10c | 289 | #define AUX_CTRL 0x10c |
@@ -1763,9 +1914,11 @@ struct mac_iveiv_entry { | |||
1763 | /* | 1914 | /* |
1764 | * BBP 3: RX Antenna | 1915 | * BBP 3: RX Antenna |
1765 | */ | 1916 | */ |
1766 | #define BBP3_RX_ADC FIELD8(0x03) | 1917 | #define BBP3_RX_ADC FIELD8(0x03) |
1767 | #define BBP3_RX_ANTENNA FIELD8(0x18) | 1918 | #define BBP3_RX_ANTENNA FIELD8(0x18) |
1768 | #define BBP3_HT40_MINUS FIELD8(0x20) | 1919 | #define BBP3_HT40_MINUS FIELD8(0x20) |
1920 | #define BBP3_ADC_MODE_SWITCH FIELD8(0x40) | ||
1921 | #define BBP3_ADC_INIT_MODE FIELD8(0x80) | ||
1769 | 1922 | ||
1770 | /* | 1923 | /* |
1771 | * BBP 4: Bandwidth | 1924 | * BBP 4: Bandwidth |
@@ -1775,6 +1928,14 @@ struct mac_iveiv_entry { | |||
1775 | #define BBP4_MAC_IF_CTRL FIELD8(0x40) | 1928 | #define BBP4_MAC_IF_CTRL FIELD8(0x40) |
1776 | 1929 | ||
1777 | /* | 1930 | /* |
1931 | * BBP 47: Bandwidth | ||
1932 | */ | ||
1933 | #define BBP47_TSSI_REPORT_SEL FIELD8(0x03) | ||
1934 | #define BBP47_TSSI_UPDATE_REQ FIELD8(0x04) | ||
1935 | #define BBP47_TSSI_TSSI_MODE FIELD8(0x18) | ||
1936 | #define BBP47_TSSI_ADC6 FIELD8(0x80) | ||
1937 | |||
1938 | /* | ||
1778 | * BBP 109 | 1939 | * BBP 109 |
1779 | */ | 1940 | */ |
1780 | #define BBP109_TX0_POWER FIELD8(0x0f) | 1941 | #define BBP109_TX0_POWER FIELD8(0x0f) |
@@ -1917,6 +2078,16 @@ struct mac_iveiv_entry { | |||
1917 | #define RFCSR27_R4 FIELD8(0x40) | 2078 | #define RFCSR27_R4 FIELD8(0x40) |
1918 | 2079 | ||
1919 | /* | 2080 | /* |
2081 | * RFCSR 29: | ||
2082 | */ | ||
2083 | #define RFCSR29_ADC6_TEST FIELD8(0x01) | ||
2084 | #define RFCSR29_ADC6_INT_TEST FIELD8(0x02) | ||
2085 | #define RFCSR29_RSSI_RESET FIELD8(0x04) | ||
2086 | #define RFCSR29_RSSI_ON FIELD8(0x08) | ||
2087 | #define RFCSR29_RSSI_RIP_CTRL FIELD8(0x30) | ||
2088 | #define RFCSR29_RSSI_GAIN FIELD8(0xc0) | ||
2089 | |||
2090 | /* | ||
1920 | * RFCSR 30: | 2091 | * RFCSR 30: |
1921 | */ | 2092 | */ |
1922 | #define RFCSR30_TX_H20M FIELD8(0x02) | 2093 | #define RFCSR30_TX_H20M FIELD8(0x02) |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 4d3747c3010..068276ee8af 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
@@ -354,16 +354,15 @@ int rt2800_check_firmware(struct rt2x00_dev *rt2x00dev, | |||
354 | * of 4kb. Certain USB chipsets however require different firmware, | 354 | * of 4kb. Certain USB chipsets however require different firmware, |
355 | * which Ralink only provides attached to the original firmware | 355 | * which Ralink only provides attached to the original firmware |
356 | * file. Thus for USB devices, firmware files have a length | 356 | * file. Thus for USB devices, firmware files have a length |
357 | * which is a multiple of 4kb. | 357 | * which is a multiple of 4kb. The firmware for rt3290 chip also |
358 | * have a length which is a multiple of 4kb. | ||
358 | */ | 359 | */ |
359 | if (rt2x00_is_usb(rt2x00dev)) { | 360 | if (rt2x00_is_usb(rt2x00dev) || rt2x00_rt(rt2x00dev, RT3290)) |
360 | fw_len = 4096; | 361 | fw_len = 4096; |
361 | multiple = true; | 362 | else |
362 | } else { | ||
363 | fw_len = 8192; | 363 | fw_len = 8192; |
364 | multiple = true; | ||
365 | } | ||
366 | 364 | ||
365 | multiple = true; | ||
367 | /* | 366 | /* |
368 | * Validate the firmware length | 367 | * Validate the firmware length |
369 | */ | 368 | */ |
@@ -415,7 +414,8 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev, | |||
415 | return -EBUSY; | 414 | return -EBUSY; |
416 | 415 | ||
417 | if (rt2x00_is_pci(rt2x00dev)) { | 416 | if (rt2x00_is_pci(rt2x00dev)) { |
418 | if (rt2x00_rt(rt2x00dev, RT3572) || | 417 | if (rt2x00_rt(rt2x00dev, RT3290) || |
418 | rt2x00_rt(rt2x00dev, RT3572) || | ||
419 | rt2x00_rt(rt2x00dev, RT5390) || | 419 | rt2x00_rt(rt2x00dev, RT5390) || |
420 | rt2x00_rt(rt2x00dev, RT5392)) { | 420 | rt2x00_rt(rt2x00dev, RT5392)) { |
421 | rt2800_register_read(rt2x00dev, AUX_CTRL, ®); | 421 | rt2800_register_read(rt2x00dev, AUX_CTRL, ®); |
@@ -851,8 +851,13 @@ int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev) | |||
851 | { | 851 | { |
852 | u32 reg; | 852 | u32 reg; |
853 | 853 | ||
854 | rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); | 854 | if (rt2x00_rt(rt2x00dev, RT3290)) { |
855 | return rt2x00_get_field32(reg, GPIO_CTRL_CFG_BIT2); | 855 | rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, ®); |
856 | return rt2x00_get_field32(reg, WLAN_GPIO_IN_BIT0); | ||
857 | } else { | ||
858 | rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); | ||
859 | return rt2x00_get_field32(reg, GPIO_CTRL_CFG_BIT2); | ||
860 | } | ||
856 | } | 861 | } |
857 | EXPORT_SYMBOL_GPL(rt2800_rfkill_poll); | 862 | EXPORT_SYMBOL_GPL(rt2800_rfkill_poll); |
858 | 863 | ||
@@ -1935,9 +1940,54 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev, | |||
1935 | rt2800_rfcsr_write(rt2x00dev, 7, rfcsr); | 1940 | rt2800_rfcsr_write(rt2x00dev, 7, rfcsr); |
1936 | } | 1941 | } |
1937 | 1942 | ||
1943 | #define RT3290_POWER_BOUND 0x27 | ||
1944 | #define RT3290_FREQ_OFFSET_BOUND 0x5f | ||
1938 | #define RT5390_POWER_BOUND 0x27 | 1945 | #define RT5390_POWER_BOUND 0x27 |
1939 | #define RT5390_FREQ_OFFSET_BOUND 0x5f | 1946 | #define RT5390_FREQ_OFFSET_BOUND 0x5f |
1940 | 1947 | ||
1948 | static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev, | ||
1949 | struct ieee80211_conf *conf, | ||
1950 | struct rf_channel *rf, | ||
1951 | struct channel_info *info) | ||
1952 | { | ||
1953 | u8 rfcsr; | ||
1954 | |||
1955 | rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1); | ||
1956 | rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3); | ||
1957 | rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr); | ||
1958 | rt2x00_set_field8(&rfcsr, RFCSR11_R, rf->rf2); | ||
1959 | rt2800_rfcsr_write(rt2x00dev, 11, rfcsr); | ||
1960 | |||
1961 | rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr); | ||
1962 | if (info->default_power1 > RT3290_POWER_BOUND) | ||
1963 | rt2x00_set_field8(&rfcsr, RFCSR49_TX, RT3290_POWER_BOUND); | ||
1964 | else | ||
1965 | rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1); | ||
1966 | rt2800_rfcsr_write(rt2x00dev, 49, rfcsr); | ||
1967 | |||
1968 | rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr); | ||
1969 | if (rt2x00dev->freq_offset > RT3290_FREQ_OFFSET_BOUND) | ||
1970 | rt2x00_set_field8(&rfcsr, RFCSR17_CODE, | ||
1971 | RT3290_FREQ_OFFSET_BOUND); | ||
1972 | else | ||
1973 | rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset); | ||
1974 | rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); | ||
1975 | |||
1976 | if (rf->channel <= 14) { | ||
1977 | if (rf->channel == 6) | ||
1978 | rt2800_bbp_write(rt2x00dev, 68, 0x0c); | ||
1979 | else | ||
1980 | rt2800_bbp_write(rt2x00dev, 68, 0x0b); | ||
1981 | |||
1982 | if (rf->channel >= 1 && rf->channel <= 6) | ||
1983 | rt2800_bbp_write(rt2x00dev, 59, 0x0f); | ||
1984 | else if (rf->channel >= 7 && rf->channel <= 11) | ||
1985 | rt2800_bbp_write(rt2x00dev, 59, 0x0e); | ||
1986 | else if (rf->channel >= 12 && rf->channel <= 14) | ||
1987 | rt2800_bbp_write(rt2x00dev, 59, 0x0d); | ||
1988 | } | ||
1989 | } | ||
1990 | |||
1941 | static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev, | 1991 | static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev, |
1942 | struct ieee80211_conf *conf, | 1992 | struct ieee80211_conf *conf, |
1943 | struct rf_channel *rf, | 1993 | struct rf_channel *rf, |
@@ -2036,15 +2086,6 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev, | |||
2036 | } | 2086 | } |
2037 | } | 2087 | } |
2038 | } | 2088 | } |
2039 | |||
2040 | rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr); | ||
2041 | rt2x00_set_field8(&rfcsr, RFCSR30_TX_H20M, 0); | ||
2042 | rt2x00_set_field8(&rfcsr, RFCSR30_RX_H20M, 0); | ||
2043 | rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); | ||
2044 | |||
2045 | rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr); | ||
2046 | rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1); | ||
2047 | rt2800_rfcsr_write(rt2x00dev, 3, rfcsr); | ||
2048 | } | 2089 | } |
2049 | 2090 | ||
2050 | static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, | 2091 | static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, |
@@ -2054,7 +2095,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, | |||
2054 | { | 2095 | { |
2055 | u32 reg; | 2096 | u32 reg; |
2056 | unsigned int tx_pin; | 2097 | unsigned int tx_pin; |
2057 | u8 bbp; | 2098 | u8 bbp, rfcsr; |
2058 | 2099 | ||
2059 | if (rf->channel <= 14) { | 2100 | if (rf->channel <= 14) { |
2060 | info->default_power1 = TXPOWER_G_TO_DEV(info->default_power1); | 2101 | info->default_power1 = TXPOWER_G_TO_DEV(info->default_power1); |
@@ -2075,6 +2116,9 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, | |||
2075 | case RF3052: | 2116 | case RF3052: |
2076 | rt2800_config_channel_rf3052(rt2x00dev, conf, rf, info); | 2117 | rt2800_config_channel_rf3052(rt2x00dev, conf, rf, info); |
2077 | break; | 2118 | break; |
2119 | case RF3290: | ||
2120 | rt2800_config_channel_rf3290(rt2x00dev, conf, rf, info); | ||
2121 | break; | ||
2078 | case RF5360: | 2122 | case RF5360: |
2079 | case RF5370: | 2123 | case RF5370: |
2080 | case RF5372: | 2124 | case RF5372: |
@@ -2086,6 +2130,22 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, | |||
2086 | rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info); | 2130 | rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info); |
2087 | } | 2131 | } |
2088 | 2132 | ||
2133 | if (rt2x00_rf(rt2x00dev, RF3290) || | ||
2134 | rt2x00_rf(rt2x00dev, RF5360) || | ||
2135 | rt2x00_rf(rt2x00dev, RF5370) || | ||
2136 | rt2x00_rf(rt2x00dev, RF5372) || | ||
2137 | rt2x00_rf(rt2x00dev, RF5390) || | ||
2138 | rt2x00_rf(rt2x00dev, RF5392)) { | ||
2139 | rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr); | ||
2140 | rt2x00_set_field8(&rfcsr, RFCSR30_TX_H20M, 0); | ||
2141 | rt2x00_set_field8(&rfcsr, RFCSR30_RX_H20M, 0); | ||
2142 | rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); | ||
2143 | |||
2144 | rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr); | ||
2145 | rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1); | ||
2146 | rt2800_rfcsr_write(rt2x00dev, 3, rfcsr); | ||
2147 | } | ||
2148 | |||
2089 | /* | 2149 | /* |
2090 | * Change BBP settings | 2150 | * Change BBP settings |
2091 | */ | 2151 | */ |
@@ -2566,6 +2626,7 @@ void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev) | |||
2566 | rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1); | 2626 | rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1); |
2567 | rt2800_rfcsr_write(rt2x00dev, 7, rfcsr); | 2627 | rt2800_rfcsr_write(rt2x00dev, 7, rfcsr); |
2568 | break; | 2628 | break; |
2629 | case RF3290: | ||
2569 | case RF5360: | 2630 | case RF5360: |
2570 | case RF5370: | 2631 | case RF5370: |
2571 | case RF5372: | 2632 | case RF5372: |
@@ -2701,6 +2762,7 @@ static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev) | |||
2701 | if (rt2x00_rt(rt2x00dev, RT3070) || | 2762 | if (rt2x00_rt(rt2x00dev, RT3070) || |
2702 | rt2x00_rt(rt2x00dev, RT3071) || | 2763 | rt2x00_rt(rt2x00dev, RT3071) || |
2703 | rt2x00_rt(rt2x00dev, RT3090) || | 2764 | rt2x00_rt(rt2x00dev, RT3090) || |
2765 | rt2x00_rt(rt2x00dev, RT3290) || | ||
2704 | rt2x00_rt(rt2x00dev, RT3390) || | 2766 | rt2x00_rt(rt2x00dev, RT3390) || |
2705 | rt2x00_rt(rt2x00dev, RT5390) || | 2767 | rt2x00_rt(rt2x00dev, RT5390) || |
2706 | rt2x00_rt(rt2x00dev, RT5392)) | 2768 | rt2x00_rt(rt2x00dev, RT5392)) |
@@ -2797,10 +2859,54 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
2797 | rt2x00_set_field32(®, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2); | 2859 | rt2x00_set_field32(®, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2); |
2798 | rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg); | 2860 | rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg); |
2799 | 2861 | ||
2862 | if (rt2x00_rt(rt2x00dev, RT3290)) { | ||
2863 | rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, ®); | ||
2864 | if (rt2x00_get_field32(reg, WLAN_EN) == 1) { | ||
2865 | rt2x00_set_field32(®, PCIE_APP0_CLK_REQ, 1); | ||
2866 | rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg); | ||
2867 | } | ||
2868 | |||
2869 | rt2800_register_read(rt2x00dev, CMB_CTRL, ®); | ||
2870 | if (!(rt2x00_get_field32(reg, LDO0_EN) == 1)) { | ||
2871 | rt2x00_set_field32(®, LDO0_EN, 1); | ||
2872 | rt2x00_set_field32(®, LDO_BGSEL, 3); | ||
2873 | rt2800_register_write(rt2x00dev, CMB_CTRL, reg); | ||
2874 | } | ||
2875 | |||
2876 | rt2800_register_read(rt2x00dev, OSC_CTRL, ®); | ||
2877 | rt2x00_set_field32(®, OSC_ROSC_EN, 1); | ||
2878 | rt2x00_set_field32(®, OSC_CAL_REQ, 1); | ||
2879 | rt2x00_set_field32(®, OSC_REF_CYCLE, 0x27); | ||
2880 | rt2800_register_write(rt2x00dev, OSC_CTRL, reg); | ||
2881 | |||
2882 | rt2800_register_read(rt2x00dev, COEX_CFG0, ®); | ||
2883 | rt2x00_set_field32(®, COEX_CFG_ANT, 0x5e); | ||
2884 | rt2800_register_write(rt2x00dev, COEX_CFG0, reg); | ||
2885 | |||
2886 | rt2800_register_read(rt2x00dev, COEX_CFG2, ®); | ||
2887 | rt2x00_set_field32(®, BT_COEX_CFG1, 0x00); | ||
2888 | rt2x00_set_field32(®, BT_COEX_CFG0, 0x17); | ||
2889 | rt2x00_set_field32(®, WL_COEX_CFG1, 0x93); | ||
2890 | rt2x00_set_field32(®, WL_COEX_CFG0, 0x7f); | ||
2891 | rt2800_register_write(rt2x00dev, COEX_CFG2, reg); | ||
2892 | |||
2893 | rt2800_register_read(rt2x00dev, PLL_CTRL, ®); | ||
2894 | rt2x00_set_field32(®, PLL_CONTROL, 1); | ||
2895 | rt2800_register_write(rt2x00dev, PLL_CTRL, reg); | ||
2896 | } | ||
2897 | |||
2800 | if (rt2x00_rt(rt2x00dev, RT3071) || | 2898 | if (rt2x00_rt(rt2x00dev, RT3071) || |
2801 | rt2x00_rt(rt2x00dev, RT3090) || | 2899 | rt2x00_rt(rt2x00dev, RT3090) || |
2900 | rt2x00_rt(rt2x00dev, RT3290) || | ||
2802 | rt2x00_rt(rt2x00dev, RT3390)) { | 2901 | rt2x00_rt(rt2x00dev, RT3390)) { |
2803 | rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); | 2902 | |
2903 | if (rt2x00_rt(rt2x00dev, RT3290)) | ||
2904 | rt2800_register_write(rt2x00dev, TX_SW_CFG0, | ||
2905 | 0x00000404); | ||
2906 | else | ||
2907 | rt2800_register_write(rt2x00dev, TX_SW_CFG0, | ||
2908 | 0x00000400); | ||
2909 | |||
2804 | rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); | 2910 | rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); |
2805 | if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || | 2911 | if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || |
2806 | rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) || | 2912 | rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) || |
@@ -3209,14 +3315,16 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) | |||
3209 | rt2800_wait_bbp_ready(rt2x00dev))) | 3315 | rt2800_wait_bbp_ready(rt2x00dev))) |
3210 | return -EACCES; | 3316 | return -EACCES; |
3211 | 3317 | ||
3212 | if (rt2x00_rt(rt2x00dev, RT5390) || | 3318 | if (rt2x00_rt(rt2x00dev, RT3290) || |
3213 | rt2x00_rt(rt2x00dev, RT5392)) { | 3319 | rt2x00_rt(rt2x00dev, RT5390) || |
3320 | rt2x00_rt(rt2x00dev, RT5392)) { | ||
3214 | rt2800_bbp_read(rt2x00dev, 4, &value); | 3321 | rt2800_bbp_read(rt2x00dev, 4, &value); |
3215 | rt2x00_set_field8(&value, BBP4_MAC_IF_CTRL, 1); | 3322 | rt2x00_set_field8(&value, BBP4_MAC_IF_CTRL, 1); |
3216 | rt2800_bbp_write(rt2x00dev, 4, value); | 3323 | rt2800_bbp_write(rt2x00dev, 4, value); |
3217 | } | 3324 | } |
3218 | 3325 | ||
3219 | if (rt2800_is_305x_soc(rt2x00dev) || | 3326 | if (rt2800_is_305x_soc(rt2x00dev) || |
3327 | rt2x00_rt(rt2x00dev, RT3290) || | ||
3220 | rt2x00_rt(rt2x00dev, RT3572) || | 3328 | rt2x00_rt(rt2x00dev, RT3572) || |
3221 | rt2x00_rt(rt2x00dev, RT5390) || | 3329 | rt2x00_rt(rt2x00dev, RT5390) || |
3222 | rt2x00_rt(rt2x00dev, RT5392)) | 3330 | rt2x00_rt(rt2x00dev, RT5392)) |
@@ -3225,20 +3333,26 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) | |||
3225 | rt2800_bbp_write(rt2x00dev, 65, 0x2c); | 3333 | rt2800_bbp_write(rt2x00dev, 65, 0x2c); |
3226 | rt2800_bbp_write(rt2x00dev, 66, 0x38); | 3334 | rt2800_bbp_write(rt2x00dev, 66, 0x38); |
3227 | 3335 | ||
3228 | if (rt2x00_rt(rt2x00dev, RT5390) || | 3336 | if (rt2x00_rt(rt2x00dev, RT3290) || |
3229 | rt2x00_rt(rt2x00dev, RT5392)) | 3337 | rt2x00_rt(rt2x00dev, RT5390) || |
3338 | rt2x00_rt(rt2x00dev, RT5392)) | ||
3230 | rt2800_bbp_write(rt2x00dev, 68, 0x0b); | 3339 | rt2800_bbp_write(rt2x00dev, 68, 0x0b); |
3231 | 3340 | ||
3232 | if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) { | 3341 | if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) { |
3233 | rt2800_bbp_write(rt2x00dev, 69, 0x16); | 3342 | rt2800_bbp_write(rt2x00dev, 69, 0x16); |
3234 | rt2800_bbp_write(rt2x00dev, 73, 0x12); | 3343 | rt2800_bbp_write(rt2x00dev, 73, 0x12); |
3235 | } else if (rt2x00_rt(rt2x00dev, RT5390) || | 3344 | } else if (rt2x00_rt(rt2x00dev, RT3290) || |
3236 | rt2x00_rt(rt2x00dev, RT5392)) { | 3345 | rt2x00_rt(rt2x00dev, RT5390) || |
3346 | rt2x00_rt(rt2x00dev, RT5392)) { | ||
3237 | rt2800_bbp_write(rt2x00dev, 69, 0x12); | 3347 | rt2800_bbp_write(rt2x00dev, 69, 0x12); |
3238 | rt2800_bbp_write(rt2x00dev, 73, 0x13); | 3348 | rt2800_bbp_write(rt2x00dev, 73, 0x13); |
3239 | rt2800_bbp_write(rt2x00dev, 75, 0x46); | 3349 | rt2800_bbp_write(rt2x00dev, 75, 0x46); |
3240 | rt2800_bbp_write(rt2x00dev, 76, 0x28); | 3350 | rt2800_bbp_write(rt2x00dev, 76, 0x28); |
3241 | rt2800_bbp_write(rt2x00dev, 77, 0x59); | 3351 | |
3352 | if (rt2x00_rt(rt2x00dev, RT3290)) | ||
3353 | rt2800_bbp_write(rt2x00dev, 77, 0x58); | ||
3354 | else | ||
3355 | rt2800_bbp_write(rt2x00dev, 77, 0x59); | ||
3242 | } else { | 3356 | } else { |
3243 | rt2800_bbp_write(rt2x00dev, 69, 0x12); | 3357 | rt2800_bbp_write(rt2x00dev, 69, 0x12); |
3244 | rt2800_bbp_write(rt2x00dev, 73, 0x10); | 3358 | rt2800_bbp_write(rt2x00dev, 73, 0x10); |
@@ -3263,23 +3377,33 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) | |||
3263 | rt2800_bbp_write(rt2x00dev, 81, 0x37); | 3377 | rt2800_bbp_write(rt2x00dev, 81, 0x37); |
3264 | } | 3378 | } |
3265 | 3379 | ||
3380 | if (rt2x00_rt(rt2x00dev, RT3290)) { | ||
3381 | rt2800_bbp_write(rt2x00dev, 74, 0x0b); | ||
3382 | rt2800_bbp_write(rt2x00dev, 79, 0x18); | ||
3383 | rt2800_bbp_write(rt2x00dev, 80, 0x09); | ||
3384 | rt2800_bbp_write(rt2x00dev, 81, 0x33); | ||
3385 | } | ||
3386 | |||
3266 | rt2800_bbp_write(rt2x00dev, 82, 0x62); | 3387 | rt2800_bbp_write(rt2x00dev, 82, 0x62); |
3267 | if (rt2x00_rt(rt2x00dev, RT5390) || | 3388 | if (rt2x00_rt(rt2x00dev, RT3290) || |
3268 | rt2x00_rt(rt2x00dev, RT5392)) | 3389 | rt2x00_rt(rt2x00dev, RT5390) || |
3390 | rt2x00_rt(rt2x00dev, RT5392)) | ||
3269 | rt2800_bbp_write(rt2x00dev, 83, 0x7a); | 3391 | rt2800_bbp_write(rt2x00dev, 83, 0x7a); |
3270 | else | 3392 | else |
3271 | rt2800_bbp_write(rt2x00dev, 83, 0x6a); | 3393 | rt2800_bbp_write(rt2x00dev, 83, 0x6a); |
3272 | 3394 | ||
3273 | if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860D)) | 3395 | if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860D)) |
3274 | rt2800_bbp_write(rt2x00dev, 84, 0x19); | 3396 | rt2800_bbp_write(rt2x00dev, 84, 0x19); |
3275 | else if (rt2x00_rt(rt2x00dev, RT5390) || | 3397 | else if (rt2x00_rt(rt2x00dev, RT3290) || |
3276 | rt2x00_rt(rt2x00dev, RT5392)) | 3398 | rt2x00_rt(rt2x00dev, RT5390) || |
3399 | rt2x00_rt(rt2x00dev, RT5392)) | ||
3277 | rt2800_bbp_write(rt2x00dev, 84, 0x9a); | 3400 | rt2800_bbp_write(rt2x00dev, 84, 0x9a); |
3278 | else | 3401 | else |
3279 | rt2800_bbp_write(rt2x00dev, 84, 0x99); | 3402 | rt2800_bbp_write(rt2x00dev, 84, 0x99); |
3280 | 3403 | ||
3281 | if (rt2x00_rt(rt2x00dev, RT5390) || | 3404 | if (rt2x00_rt(rt2x00dev, RT3290) || |
3282 | rt2x00_rt(rt2x00dev, RT5392)) | 3405 | rt2x00_rt(rt2x00dev, RT5390) || |
3406 | rt2x00_rt(rt2x00dev, RT5392)) | ||
3283 | rt2800_bbp_write(rt2x00dev, 86, 0x38); | 3407 | rt2800_bbp_write(rt2x00dev, 86, 0x38); |
3284 | else | 3408 | else |
3285 | rt2800_bbp_write(rt2x00dev, 86, 0x00); | 3409 | rt2800_bbp_write(rt2x00dev, 86, 0x00); |
@@ -3289,8 +3413,9 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) | |||
3289 | 3413 | ||
3290 | rt2800_bbp_write(rt2x00dev, 91, 0x04); | 3414 | rt2800_bbp_write(rt2x00dev, 91, 0x04); |
3291 | 3415 | ||
3292 | if (rt2x00_rt(rt2x00dev, RT5390) || | 3416 | if (rt2x00_rt(rt2x00dev, RT3290) || |
3293 | rt2x00_rt(rt2x00dev, RT5392)) | 3417 | rt2x00_rt(rt2x00dev, RT5390) || |
3418 | rt2x00_rt(rt2x00dev, RT5392)) | ||
3294 | rt2800_bbp_write(rt2x00dev, 92, 0x02); | 3419 | rt2800_bbp_write(rt2x00dev, 92, 0x02); |
3295 | else | 3420 | else |
3296 | rt2800_bbp_write(rt2x00dev, 92, 0x00); | 3421 | rt2800_bbp_write(rt2x00dev, 92, 0x00); |
@@ -3304,6 +3429,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) | |||
3304 | rt2x00_rt_rev_gte(rt2x00dev, RT3071, REV_RT3071E) || | 3429 | rt2x00_rt_rev_gte(rt2x00dev, RT3071, REV_RT3071E) || |
3305 | rt2x00_rt_rev_gte(rt2x00dev, RT3090, REV_RT3090E) || | 3430 | rt2x00_rt_rev_gte(rt2x00dev, RT3090, REV_RT3090E) || |
3306 | rt2x00_rt_rev_gte(rt2x00dev, RT3390, REV_RT3390E) || | 3431 | rt2x00_rt_rev_gte(rt2x00dev, RT3390, REV_RT3390E) || |
3432 | rt2x00_rt(rt2x00dev, RT3290) || | ||
3307 | rt2x00_rt(rt2x00dev, RT3572) || | 3433 | rt2x00_rt(rt2x00dev, RT3572) || |
3308 | rt2x00_rt(rt2x00dev, RT5390) || | 3434 | rt2x00_rt(rt2x00dev, RT5390) || |
3309 | rt2x00_rt(rt2x00dev, RT5392) || | 3435 | rt2x00_rt(rt2x00dev, RT5392) || |
@@ -3312,27 +3438,32 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) | |||
3312 | else | 3438 | else |
3313 | rt2800_bbp_write(rt2x00dev, 103, 0x00); | 3439 | rt2800_bbp_write(rt2x00dev, 103, 0x00); |
3314 | 3440 | ||
3315 | if (rt2x00_rt(rt2x00dev, RT5390) || | 3441 | if (rt2x00_rt(rt2x00dev, RT3290) || |
3316 | rt2x00_rt(rt2x00dev, RT5392)) | 3442 | rt2x00_rt(rt2x00dev, RT5390) || |
3443 | rt2x00_rt(rt2x00dev, RT5392)) | ||
3317 | rt2800_bbp_write(rt2x00dev, 104, 0x92); | 3444 | rt2800_bbp_write(rt2x00dev, 104, 0x92); |
3318 | 3445 | ||
3319 | if (rt2800_is_305x_soc(rt2x00dev)) | 3446 | if (rt2800_is_305x_soc(rt2x00dev)) |
3320 | rt2800_bbp_write(rt2x00dev, 105, 0x01); | 3447 | rt2800_bbp_write(rt2x00dev, 105, 0x01); |
3448 | else if (rt2x00_rt(rt2x00dev, RT3290)) | ||
3449 | rt2800_bbp_write(rt2x00dev, 105, 0x1c); | ||
3321 | else if (rt2x00_rt(rt2x00dev, RT5390) || | 3450 | else if (rt2x00_rt(rt2x00dev, RT5390) || |
3322 | rt2x00_rt(rt2x00dev, RT5392)) | 3451 | rt2x00_rt(rt2x00dev, RT5392)) |
3323 | rt2800_bbp_write(rt2x00dev, 105, 0x3c); | 3452 | rt2800_bbp_write(rt2x00dev, 105, 0x3c); |
3324 | else | 3453 | else |
3325 | rt2800_bbp_write(rt2x00dev, 105, 0x05); | 3454 | rt2800_bbp_write(rt2x00dev, 105, 0x05); |
3326 | 3455 | ||
3327 | if (rt2x00_rt(rt2x00dev, RT5390)) | 3456 | if (rt2x00_rt(rt2x00dev, RT3290) || |
3457 | rt2x00_rt(rt2x00dev, RT5390)) | ||
3328 | rt2800_bbp_write(rt2x00dev, 106, 0x03); | 3458 | rt2800_bbp_write(rt2x00dev, 106, 0x03); |
3329 | else if (rt2x00_rt(rt2x00dev, RT5392)) | 3459 | else if (rt2x00_rt(rt2x00dev, RT5392)) |
3330 | rt2800_bbp_write(rt2x00dev, 106, 0x12); | 3460 | rt2800_bbp_write(rt2x00dev, 106, 0x12); |
3331 | else | 3461 | else |
3332 | rt2800_bbp_write(rt2x00dev, 106, 0x35); | 3462 | rt2800_bbp_write(rt2x00dev, 106, 0x35); |
3333 | 3463 | ||
3334 | if (rt2x00_rt(rt2x00dev, RT5390) || | 3464 | if (rt2x00_rt(rt2x00dev, RT3290) || |
3335 | rt2x00_rt(rt2x00dev, RT5392)) | 3465 | rt2x00_rt(rt2x00dev, RT5390) || |
3466 | rt2x00_rt(rt2x00dev, RT5392)) | ||
3336 | rt2800_bbp_write(rt2x00dev, 128, 0x12); | 3467 | rt2800_bbp_write(rt2x00dev, 128, 0x12); |
3337 | 3468 | ||
3338 | if (rt2x00_rt(rt2x00dev, RT5392)) { | 3469 | if (rt2x00_rt(rt2x00dev, RT5392)) { |
@@ -3357,6 +3488,29 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) | |||
3357 | rt2800_bbp_write(rt2x00dev, 138, value); | 3488 | rt2800_bbp_write(rt2x00dev, 138, value); |
3358 | } | 3489 | } |
3359 | 3490 | ||
3491 | if (rt2x00_rt(rt2x00dev, RT3290)) { | ||
3492 | rt2800_bbp_write(rt2x00dev, 67, 0x24); | ||
3493 | rt2800_bbp_write(rt2x00dev, 143, 0x04); | ||
3494 | rt2800_bbp_write(rt2x00dev, 142, 0x99); | ||
3495 | rt2800_bbp_write(rt2x00dev, 150, 0x30); | ||
3496 | rt2800_bbp_write(rt2x00dev, 151, 0x2e); | ||
3497 | rt2800_bbp_write(rt2x00dev, 152, 0x20); | ||
3498 | rt2800_bbp_write(rt2x00dev, 153, 0x34); | ||
3499 | rt2800_bbp_write(rt2x00dev, 154, 0x40); | ||
3500 | rt2800_bbp_write(rt2x00dev, 155, 0x3b); | ||
3501 | rt2800_bbp_write(rt2x00dev, 253, 0x04); | ||
3502 | |||
3503 | rt2800_bbp_read(rt2x00dev, 47, &value); | ||
3504 | rt2x00_set_field8(&value, BBP47_TSSI_ADC6, 1); | ||
3505 | rt2800_bbp_write(rt2x00dev, 47, value); | ||
3506 | |||
3507 | /* Use 5-bit ADC for Acquisition and 8-bit ADC for data */ | ||
3508 | rt2800_bbp_read(rt2x00dev, 3, &value); | ||
3509 | rt2x00_set_field8(&value, BBP3_ADC_MODE_SWITCH, 1); | ||
3510 | rt2x00_set_field8(&value, BBP3_ADC_INIT_MODE, 1); | ||
3511 | rt2800_bbp_write(rt2x00dev, 3, value); | ||
3512 | } | ||
3513 | |||
3360 | if (rt2x00_rt(rt2x00dev, RT5390) || | 3514 | if (rt2x00_rt(rt2x00dev, RT5390) || |
3361 | rt2x00_rt(rt2x00dev, RT5392)) { | 3515 | rt2x00_rt(rt2x00dev, RT5392)) { |
3362 | int ant, div_mode; | 3516 | int ant, div_mode; |
@@ -3489,6 +3643,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
3489 | if (!rt2x00_rt(rt2x00dev, RT3070) && | 3643 | if (!rt2x00_rt(rt2x00dev, RT3070) && |
3490 | !rt2x00_rt(rt2x00dev, RT3071) && | 3644 | !rt2x00_rt(rt2x00dev, RT3071) && |
3491 | !rt2x00_rt(rt2x00dev, RT3090) && | 3645 | !rt2x00_rt(rt2x00dev, RT3090) && |
3646 | !rt2x00_rt(rt2x00dev, RT3290) && | ||
3492 | !rt2x00_rt(rt2x00dev, RT3390) && | 3647 | !rt2x00_rt(rt2x00dev, RT3390) && |
3493 | !rt2x00_rt(rt2x00dev, RT3572) && | 3648 | !rt2x00_rt(rt2x00dev, RT3572) && |
3494 | !rt2x00_rt(rt2x00dev, RT5390) && | 3649 | !rt2x00_rt(rt2x00dev, RT5390) && |
@@ -3499,8 +3654,9 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
3499 | /* | 3654 | /* |
3500 | * Init RF calibration. | 3655 | * Init RF calibration. |
3501 | */ | 3656 | */ |
3502 | if (rt2x00_rt(rt2x00dev, RT5390) || | 3657 | if (rt2x00_rt(rt2x00dev, RT3290) || |
3503 | rt2x00_rt(rt2x00dev, RT5392)) { | 3658 | rt2x00_rt(rt2x00dev, RT5390) || |
3659 | rt2x00_rt(rt2x00dev, RT5392)) { | ||
3504 | rt2800_rfcsr_read(rt2x00dev, 2, &rfcsr); | 3660 | rt2800_rfcsr_read(rt2x00dev, 2, &rfcsr); |
3505 | rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 1); | 3661 | rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 1); |
3506 | rt2800_rfcsr_write(rt2x00dev, 2, rfcsr); | 3662 | rt2800_rfcsr_write(rt2x00dev, 2, rfcsr); |
@@ -3538,6 +3694,53 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
3538 | rt2800_rfcsr_write(rt2x00dev, 24, 0x16); | 3694 | rt2800_rfcsr_write(rt2x00dev, 24, 0x16); |
3539 | rt2800_rfcsr_write(rt2x00dev, 25, 0x01); | 3695 | rt2800_rfcsr_write(rt2x00dev, 25, 0x01); |
3540 | rt2800_rfcsr_write(rt2x00dev, 29, 0x1f); | 3696 | rt2800_rfcsr_write(rt2x00dev, 29, 0x1f); |
3697 | } else if (rt2x00_rt(rt2x00dev, RT3290)) { | ||
3698 | rt2800_rfcsr_write(rt2x00dev, 1, 0x0f); | ||
3699 | rt2800_rfcsr_write(rt2x00dev, 2, 0x80); | ||
3700 | rt2800_rfcsr_write(rt2x00dev, 3, 0x08); | ||
3701 | rt2800_rfcsr_write(rt2x00dev, 4, 0x00); | ||
3702 | rt2800_rfcsr_write(rt2x00dev, 6, 0xa0); | ||
3703 | rt2800_rfcsr_write(rt2x00dev, 8, 0xf3); | ||
3704 | rt2800_rfcsr_write(rt2x00dev, 9, 0x02); | ||
3705 | rt2800_rfcsr_write(rt2x00dev, 10, 0x53); | ||
3706 | rt2800_rfcsr_write(rt2x00dev, 11, 0x4a); | ||
3707 | rt2800_rfcsr_write(rt2x00dev, 12, 0x46); | ||
3708 | rt2800_rfcsr_write(rt2x00dev, 13, 0x9f); | ||
3709 | rt2800_rfcsr_write(rt2x00dev, 18, 0x02); | ||
3710 | rt2800_rfcsr_write(rt2x00dev, 22, 0x20); | ||
3711 | rt2800_rfcsr_write(rt2x00dev, 25, 0x83); | ||
3712 | rt2800_rfcsr_write(rt2x00dev, 26, 0x82); | ||
3713 | rt2800_rfcsr_write(rt2x00dev, 27, 0x09); | ||
3714 | rt2800_rfcsr_write(rt2x00dev, 29, 0x10); | ||
3715 | rt2800_rfcsr_write(rt2x00dev, 30, 0x10); | ||
3716 | rt2800_rfcsr_write(rt2x00dev, 31, 0x80); | ||
3717 | rt2800_rfcsr_write(rt2x00dev, 32, 0x80); | ||
3718 | rt2800_rfcsr_write(rt2x00dev, 33, 0x00); | ||
3719 | rt2800_rfcsr_write(rt2x00dev, 34, 0x05); | ||
3720 | rt2800_rfcsr_write(rt2x00dev, 35, 0x12); | ||
3721 | rt2800_rfcsr_write(rt2x00dev, 36, 0x00); | ||
3722 | rt2800_rfcsr_write(rt2x00dev, 38, 0x85); | ||
3723 | rt2800_rfcsr_write(rt2x00dev, 39, 0x1b); | ||
3724 | rt2800_rfcsr_write(rt2x00dev, 40, 0x0b); | ||
3725 | rt2800_rfcsr_write(rt2x00dev, 41, 0xbb); | ||
3726 | rt2800_rfcsr_write(rt2x00dev, 42, 0xd5); | ||
3727 | rt2800_rfcsr_write(rt2x00dev, 43, 0x7b); | ||
3728 | rt2800_rfcsr_write(rt2x00dev, 44, 0x0e); | ||
3729 | rt2800_rfcsr_write(rt2x00dev, 45, 0xa2); | ||
3730 | rt2800_rfcsr_write(rt2x00dev, 46, 0x73); | ||
3731 | rt2800_rfcsr_write(rt2x00dev, 47, 0x00); | ||
3732 | rt2800_rfcsr_write(rt2x00dev, 48, 0x10); | ||
3733 | rt2800_rfcsr_write(rt2x00dev, 49, 0x98); | ||
3734 | rt2800_rfcsr_write(rt2x00dev, 52, 0x38); | ||
3735 | rt2800_rfcsr_write(rt2x00dev, 53, 0x00); | ||
3736 | rt2800_rfcsr_write(rt2x00dev, 54, 0x78); | ||
3737 | rt2800_rfcsr_write(rt2x00dev, 55, 0x43); | ||
3738 | rt2800_rfcsr_write(rt2x00dev, 56, 0x02); | ||
3739 | rt2800_rfcsr_write(rt2x00dev, 57, 0x80); | ||
3740 | rt2800_rfcsr_write(rt2x00dev, 58, 0x7f); | ||
3741 | rt2800_rfcsr_write(rt2x00dev, 59, 0x09); | ||
3742 | rt2800_rfcsr_write(rt2x00dev, 60, 0x45); | ||
3743 | rt2800_rfcsr_write(rt2x00dev, 61, 0xc1); | ||
3541 | } else if (rt2x00_rt(rt2x00dev, RT3390)) { | 3744 | } else if (rt2x00_rt(rt2x00dev, RT3390)) { |
3542 | rt2800_rfcsr_write(rt2x00dev, 0, 0xa0); | 3745 | rt2800_rfcsr_write(rt2x00dev, 0, 0xa0); |
3543 | rt2800_rfcsr_write(rt2x00dev, 1, 0xe1); | 3746 | rt2800_rfcsr_write(rt2x00dev, 1, 0xe1); |
@@ -3946,6 +4149,12 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
3946 | rt2800_rfcsr_write(rt2x00dev, 27, rfcsr); | 4149 | rt2800_rfcsr_write(rt2x00dev, 27, rfcsr); |
3947 | } | 4150 | } |
3948 | 4151 | ||
4152 | if (rt2x00_rt(rt2x00dev, RT3290)) { | ||
4153 | rt2800_rfcsr_read(rt2x00dev, 29, &rfcsr); | ||
4154 | rt2x00_set_field8(&rfcsr, RFCSR29_RSSI_GAIN, 3); | ||
4155 | rt2800_rfcsr_write(rt2x00dev, 29, rfcsr); | ||
4156 | } | ||
4157 | |||
3949 | if (rt2x00_rt(rt2x00dev, RT5390) || | 4158 | if (rt2x00_rt(rt2x00dev, RT5390) || |
3950 | rt2x00_rt(rt2x00dev, RT5392)) { | 4159 | rt2x00_rt(rt2x00dev, RT5392)) { |
3951 | rt2800_rfcsr_read(rt2x00dev, 38, &rfcsr); | 4160 | rt2800_rfcsr_read(rt2x00dev, 38, &rfcsr); |
@@ -4052,9 +4261,14 @@ EXPORT_SYMBOL_GPL(rt2800_disable_radio); | |||
4052 | int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev) | 4261 | int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev) |
4053 | { | 4262 | { |
4054 | u32 reg; | 4263 | u32 reg; |
4264 | u16 efuse_ctrl_reg; | ||
4055 | 4265 | ||
4056 | rt2800_register_read(rt2x00dev, EFUSE_CTRL, ®); | 4266 | if (rt2x00_rt(rt2x00dev, RT3290)) |
4267 | efuse_ctrl_reg = EFUSE_CTRL_3290; | ||
4268 | else | ||
4269 | efuse_ctrl_reg = EFUSE_CTRL; | ||
4057 | 4270 | ||
4271 | rt2800_register_read(rt2x00dev, efuse_ctrl_reg, ®); | ||
4058 | return rt2x00_get_field32(reg, EFUSE_CTRL_PRESENT); | 4272 | return rt2x00_get_field32(reg, EFUSE_CTRL_PRESENT); |
4059 | } | 4273 | } |
4060 | EXPORT_SYMBOL_GPL(rt2800_efuse_detect); | 4274 | EXPORT_SYMBOL_GPL(rt2800_efuse_detect); |
@@ -4062,27 +4276,44 @@ EXPORT_SYMBOL_GPL(rt2800_efuse_detect); | |||
4062 | static void rt2800_efuse_read(struct rt2x00_dev *rt2x00dev, unsigned int i) | 4276 | static void rt2800_efuse_read(struct rt2x00_dev *rt2x00dev, unsigned int i) |
4063 | { | 4277 | { |
4064 | u32 reg; | 4278 | u32 reg; |
4065 | 4279 | u16 efuse_ctrl_reg; | |
4280 | u16 efuse_data0_reg; | ||
4281 | u16 efuse_data1_reg; | ||
4282 | u16 efuse_data2_reg; | ||
4283 | u16 efuse_data3_reg; | ||
4284 | |||
4285 | if (rt2x00_rt(rt2x00dev, RT3290)) { | ||
4286 | efuse_ctrl_reg = EFUSE_CTRL_3290; | ||
4287 | efuse_data0_reg = EFUSE_DATA0_3290; | ||
4288 | efuse_data1_reg = EFUSE_DATA1_3290; | ||
4289 | efuse_data2_reg = EFUSE_DATA2_3290; | ||
4290 | efuse_data3_reg = EFUSE_DATA3_3290; | ||
4291 | } else { | ||
4292 | efuse_ctrl_reg = EFUSE_CTRL; | ||
4293 | efuse_data0_reg = EFUSE_DATA0; | ||
4294 | efuse_data1_reg = EFUSE_DATA1; | ||
4295 | efuse_data2_reg = EFUSE_DATA2; | ||
4296 | efuse_data3_reg = EFUSE_DATA3; | ||
4297 | } | ||
4066 | mutex_lock(&rt2x00dev->csr_mutex); | 4298 | mutex_lock(&rt2x00dev->csr_mutex); |
4067 | 4299 | ||
4068 | rt2800_register_read_lock(rt2x00dev, EFUSE_CTRL, ®); | 4300 | rt2800_register_read_lock(rt2x00dev, efuse_ctrl_reg, ®); |
4069 | rt2x00_set_field32(®, EFUSE_CTRL_ADDRESS_IN, i); | 4301 | rt2x00_set_field32(®, EFUSE_CTRL_ADDRESS_IN, i); |
4070 | rt2x00_set_field32(®, EFUSE_CTRL_MODE, 0); | 4302 | rt2x00_set_field32(®, EFUSE_CTRL_MODE, 0); |
4071 | rt2x00_set_field32(®, EFUSE_CTRL_KICK, 1); | 4303 | rt2x00_set_field32(®, EFUSE_CTRL_KICK, 1); |
4072 | rt2800_register_write_lock(rt2x00dev, EFUSE_CTRL, reg); | 4304 | rt2800_register_write_lock(rt2x00dev, efuse_ctrl_reg, reg); |
4073 | 4305 | ||
4074 | /* Wait until the EEPROM has been loaded */ | 4306 | /* Wait until the EEPROM has been loaded */ |
4075 | rt2800_regbusy_read(rt2x00dev, EFUSE_CTRL, EFUSE_CTRL_KICK, ®); | 4307 | rt2800_regbusy_read(rt2x00dev, efuse_ctrl_reg, EFUSE_CTRL_KICK, ®); |
4076 | |||
4077 | /* Apparently the data is read from end to start */ | 4308 | /* Apparently the data is read from end to start */ |
4078 | rt2800_register_read_lock(rt2x00dev, EFUSE_DATA3, ®); | 4309 | rt2800_register_read_lock(rt2x00dev, efuse_data3_reg, ®); |
4079 | /* The returned value is in CPU order, but eeprom is le */ | 4310 | /* The returned value is in CPU order, but eeprom is le */ |
4080 | *(u32 *)&rt2x00dev->eeprom[i] = cpu_to_le32(reg); | 4311 | *(u32 *)&rt2x00dev->eeprom[i] = cpu_to_le32(reg); |
4081 | rt2800_register_read_lock(rt2x00dev, EFUSE_DATA2, ®); | 4312 | rt2800_register_read_lock(rt2x00dev, efuse_data2_reg, ®); |
4082 | *(u32 *)&rt2x00dev->eeprom[i + 2] = cpu_to_le32(reg); | 4313 | *(u32 *)&rt2x00dev->eeprom[i + 2] = cpu_to_le32(reg); |
4083 | rt2800_register_read_lock(rt2x00dev, EFUSE_DATA1, ®); | 4314 | rt2800_register_read_lock(rt2x00dev, efuse_data1_reg, ®); |
4084 | *(u32 *)&rt2x00dev->eeprom[i + 4] = cpu_to_le32(reg); | 4315 | *(u32 *)&rt2x00dev->eeprom[i + 4] = cpu_to_le32(reg); |
4085 | rt2800_register_read_lock(rt2x00dev, EFUSE_DATA0, ®); | 4316 | rt2800_register_read_lock(rt2x00dev, efuse_data0_reg, ®); |
4086 | *(u32 *)&rt2x00dev->eeprom[i + 6] = cpu_to_le32(reg); | 4317 | *(u32 *)&rt2x00dev->eeprom[i + 6] = cpu_to_le32(reg); |
4087 | 4318 | ||
4088 | mutex_unlock(&rt2x00dev->csr_mutex); | 4319 | mutex_unlock(&rt2x00dev->csr_mutex); |
@@ -4244,9 +4475,14 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
4244 | * RT28xx/RT30xx: defined in "EEPROM_NIC_CONF0_RF_TYPE" field | 4475 | * RT28xx/RT30xx: defined in "EEPROM_NIC_CONF0_RF_TYPE" field |
4245 | * RT53xx: defined in "EEPROM_CHIP_ID" field | 4476 | * RT53xx: defined in "EEPROM_CHIP_ID" field |
4246 | */ | 4477 | */ |
4247 | rt2800_register_read(rt2x00dev, MAC_CSR0, ®); | 4478 | if (rt2x00_rt(rt2x00dev, RT3290)) |
4248 | if (rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5390 || | 4479 | rt2800_register_read(rt2x00dev, MAC_CSR0_3290, ®); |
4249 | rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5392) | 4480 | else |
4481 | rt2800_register_read(rt2x00dev, MAC_CSR0, ®); | ||
4482 | |||
4483 | if (rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT3290 || | ||
4484 | rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5390 || | ||
4485 | rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5392) | ||
4250 | rt2x00_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &value); | 4486 | rt2x00_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &value); |
4251 | else | 4487 | else |
4252 | value = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE); | 4488 | value = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE); |
@@ -4261,6 +4497,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
4261 | case RT3070: | 4497 | case RT3070: |
4262 | case RT3071: | 4498 | case RT3071: |
4263 | case RT3090: | 4499 | case RT3090: |
4500 | case RT3290: | ||
4264 | case RT3390: | 4501 | case RT3390: |
4265 | case RT3572: | 4502 | case RT3572: |
4266 | case RT5390: | 4503 | case RT5390: |
@@ -4281,6 +4518,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
4281 | case RF3021: | 4518 | case RF3021: |
4282 | case RF3022: | 4519 | case RF3022: |
4283 | case RF3052: | 4520 | case RF3052: |
4521 | case RF3290: | ||
4284 | case RF3320: | 4522 | case RF3320: |
4285 | case RF5360: | 4523 | case RF5360: |
4286 | case RF5370: | 4524 | case RF5370: |
@@ -4597,6 +4835,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
4597 | rt2x00_rf(rt2x00dev, RF2020) || | 4835 | rt2x00_rf(rt2x00dev, RF2020) || |
4598 | rt2x00_rf(rt2x00dev, RF3021) || | 4836 | rt2x00_rf(rt2x00dev, RF3021) || |
4599 | rt2x00_rf(rt2x00dev, RF3022) || | 4837 | rt2x00_rf(rt2x00dev, RF3022) || |
4838 | rt2x00_rf(rt2x00dev, RF3290) || | ||
4600 | rt2x00_rf(rt2x00dev, RF3320) || | 4839 | rt2x00_rf(rt2x00dev, RF3320) || |
4601 | rt2x00_rf(rt2x00dev, RF5360) || | 4840 | rt2x00_rf(rt2x00dev, RF5360) || |
4602 | rt2x00_rf(rt2x00dev, RF5370) || | 4841 | rt2x00_rf(rt2x00dev, RF5370) || |
@@ -4685,6 +4924,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
4685 | case RF3022: | 4924 | case RF3022: |
4686 | case RF3320: | 4925 | case RF3320: |
4687 | case RF3052: | 4926 | case RF3052: |
4927 | case RF3290: | ||
4688 | case RF5360: | 4928 | case RF5360: |
4689 | case RF5370: | 4929 | case RF5370: |
4690 | case RF5372: | 4930 | case RF5372: |
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 206158b6742..dd436125fe3 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c | |||
@@ -280,7 +280,13 @@ static void rt2800pci_stop_queue(struct data_queue *queue) | |||
280 | */ | 280 | */ |
281 | static char *rt2800pci_get_firmware_name(struct rt2x00_dev *rt2x00dev) | 281 | static char *rt2800pci_get_firmware_name(struct rt2x00_dev *rt2x00dev) |
282 | { | 282 | { |
283 | return FIRMWARE_RT2860; | 283 | /* |
284 | * Chip rt3290 use specific 4KB firmware named rt3290.bin. | ||
285 | */ | ||
286 | if (rt2x00_rt(rt2x00dev, RT3290)) | ||
287 | return FIRMWARE_RT3290; | ||
288 | else | ||
289 | return FIRMWARE_RT2860; | ||
284 | } | 290 | } |
285 | 291 | ||
286 | static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev, | 292 | static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev, |
@@ -974,6 +980,66 @@ static int rt2800pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) | |||
974 | return rt2800_validate_eeprom(rt2x00dev); | 980 | return rt2800_validate_eeprom(rt2x00dev); |
975 | } | 981 | } |
976 | 982 | ||
983 | static int rt2800_enable_wlan_rt3290(struct rt2x00_dev *rt2x00dev) | ||
984 | { | ||
985 | u32 reg; | ||
986 | int i, count; | ||
987 | |||
988 | rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, ®); | ||
989 | if ((rt2x00_get_field32(reg, WLAN_EN) == 1)) | ||
990 | return 0; | ||
991 | |||
992 | rt2x00_set_field32(®, WLAN_GPIO_OUT_OE_BIT_ALL, 0xff); | ||
993 | rt2x00_set_field32(®, FRC_WL_ANT_SET, 1); | ||
994 | rt2x00_set_field32(®, WLAN_CLK_EN, 0); | ||
995 | rt2x00_set_field32(®, WLAN_EN, 1); | ||
996 | rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg); | ||
997 | |||
998 | udelay(REGISTER_BUSY_DELAY); | ||
999 | |||
1000 | count = 0; | ||
1001 | do { | ||
1002 | /* | ||
1003 | * Check PLL_LD & XTAL_RDY. | ||
1004 | */ | ||
1005 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | ||
1006 | rt2800_register_read(rt2x00dev, CMB_CTRL, ®); | ||
1007 | if ((rt2x00_get_field32(reg, PLL_LD) == 1) && | ||
1008 | (rt2x00_get_field32(reg, XTAL_RDY) == 1)) | ||
1009 | break; | ||
1010 | udelay(REGISTER_BUSY_DELAY); | ||
1011 | } | ||
1012 | |||
1013 | if (i >= REGISTER_BUSY_COUNT) { | ||
1014 | |||
1015 | if (count >= 10) | ||
1016 | return -EIO; | ||
1017 | |||
1018 | rt2800_register_write(rt2x00dev, 0x58, 0x018); | ||
1019 | udelay(REGISTER_BUSY_DELAY); | ||
1020 | rt2800_register_write(rt2x00dev, 0x58, 0x418); | ||
1021 | udelay(REGISTER_BUSY_DELAY); | ||
1022 | rt2800_register_write(rt2x00dev, 0x58, 0x618); | ||
1023 | udelay(REGISTER_BUSY_DELAY); | ||
1024 | count++; | ||
1025 | } else { | ||
1026 | count = 0; | ||
1027 | } | ||
1028 | |||
1029 | rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, ®); | ||
1030 | rt2x00_set_field32(®, PCIE_APP0_CLK_REQ, 0); | ||
1031 | rt2x00_set_field32(®, WLAN_CLK_EN, 1); | ||
1032 | rt2x00_set_field32(®, WLAN_RESET, 1); | ||
1033 | rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg); | ||
1034 | udelay(10); | ||
1035 | rt2x00_set_field32(®, WLAN_RESET, 0); | ||
1036 | rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg); | ||
1037 | udelay(10); | ||
1038 | rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, 0x7fffffff); | ||
1039 | } while (count != 0); | ||
1040 | |||
1041 | return 0; | ||
1042 | } | ||
977 | static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) | 1043 | static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) |
978 | { | 1044 | { |
979 | int retval; | 1045 | int retval; |
@@ -997,6 +1063,17 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
997 | return retval; | 1063 | return retval; |
998 | 1064 | ||
999 | /* | 1065 | /* |
1066 | * In probe phase call rt2800_enable_wlan_rt3290 to enable wlan | ||
1067 | * clk for rt3290. That avoid the MCU fail in start phase. | ||
1068 | */ | ||
1069 | if (rt2x00_rt(rt2x00dev, RT3290)) { | ||
1070 | retval = rt2800_enable_wlan_rt3290(rt2x00dev); | ||
1071 | |||
1072 | if (retval) | ||
1073 | return retval; | ||
1074 | } | ||
1075 | |||
1076 | /* | ||
1000 | * This device has multiple filters for control frames | 1077 | * This device has multiple filters for control frames |
1001 | * and has a separate filter for PS Poll frames. | 1078 | * and has a separate filter for PS Poll frames. |
1002 | */ | 1079 | */ |
@@ -1175,6 +1252,9 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { | |||
1175 | { PCI_DEVICE(0x1432, 0x7768) }, | 1252 | { PCI_DEVICE(0x1432, 0x7768) }, |
1176 | { PCI_DEVICE(0x1462, 0x891a) }, | 1253 | { PCI_DEVICE(0x1462, 0x891a) }, |
1177 | { PCI_DEVICE(0x1a3b, 0x1059) }, | 1254 | { PCI_DEVICE(0x1a3b, 0x1059) }, |
1255 | #ifdef CONFIG_RT2800PCI_RT3290 | ||
1256 | { PCI_DEVICE(0x1814, 0x3290) }, | ||
1257 | #endif | ||
1178 | #ifdef CONFIG_RT2800PCI_RT33XX | 1258 | #ifdef CONFIG_RT2800PCI_RT33XX |
1179 | { PCI_DEVICE(0x1814, 0x3390) }, | 1259 | { PCI_DEVICE(0x1814, 0x3390) }, |
1180 | #endif | 1260 | #endif |
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.h b/drivers/net/wireless/rt2x00/rt2800pci.h index 70e050d904c..ab22a087c50 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.h +++ b/drivers/net/wireless/rt2x00/rt2800pci.h | |||
@@ -47,6 +47,7 @@ | |||
47 | * 8051 firmware image. | 47 | * 8051 firmware image. |
48 | */ | 48 | */ |
49 | #define FIRMWARE_RT2860 "rt2860.bin" | 49 | #define FIRMWARE_RT2860 "rt2860.bin" |
50 | #define FIRMWARE_RT3290 "rt3290.bin" | ||
50 | #define FIRMWARE_IMAGE_BASE 0x2000 | 51 | #define FIRMWARE_IMAGE_BASE 0x2000 |
51 | 52 | ||
52 | /* | 53 | /* |
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 20a50407289..6cf336595e2 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c | |||
@@ -971,6 +971,7 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
971 | { USB_DEVICE(0x0411, 0x015d) }, | 971 | { USB_DEVICE(0x0411, 0x015d) }, |
972 | { USB_DEVICE(0x0411, 0x016f) }, | 972 | { USB_DEVICE(0x0411, 0x016f) }, |
973 | { USB_DEVICE(0x0411, 0x01a2) }, | 973 | { USB_DEVICE(0x0411, 0x01a2) }, |
974 | { USB_DEVICE(0x0411, 0x01ee) }, | ||
974 | /* Corega */ | 975 | /* Corega */ |
975 | { USB_DEVICE(0x07aa, 0x002f) }, | 976 | { USB_DEVICE(0x07aa, 0x002f) }, |
976 | { USB_DEVICE(0x07aa, 0x003c) }, | 977 | { USB_DEVICE(0x07aa, 0x003c) }, |
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 8f754025b06..8afb546c2b2 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -187,6 +187,7 @@ struct rt2x00_chip { | |||
187 | #define RT3070 0x3070 | 187 | #define RT3070 0x3070 |
188 | #define RT3071 0x3071 | 188 | #define RT3071 0x3071 |
189 | #define RT3090 0x3090 /* 2.4GHz PCIe */ | 189 | #define RT3090 0x3090 /* 2.4GHz PCIe */ |
190 | #define RT3290 0x3290 | ||
190 | #define RT3390 0x3390 | 191 | #define RT3390 0x3390 |
191 | #define RT3572 0x3572 | 192 | #define RT3572 0x3572 |
192 | #define RT3593 0x3593 | 193 | #define RT3593 0x3593 |
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 0a4653a92ca..a0c8caef3b0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c | |||
@@ -256,6 +256,7 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops) | |||
256 | struct ieee80211_hw *hw; | 256 | struct ieee80211_hw *hw; |
257 | struct rt2x00_dev *rt2x00dev; | 257 | struct rt2x00_dev *rt2x00dev; |
258 | int retval; | 258 | int retval; |
259 | u16 chip; | ||
259 | 260 | ||
260 | retval = pci_enable_device(pci_dev); | 261 | retval = pci_enable_device(pci_dev); |
261 | if (retval) { | 262 | if (retval) { |
@@ -305,6 +306,14 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops) | |||
305 | if (retval) | 306 | if (retval) |
306 | goto exit_free_device; | 307 | goto exit_free_device; |
307 | 308 | ||
309 | /* | ||
310 | * Because rt3290 chip use different efuse offset to read efuse data. | ||
311 | * So before read efuse it need to indicate it is the | ||
312 | * rt3290 or not. | ||
313 | */ | ||
314 | pci_read_config_word(pci_dev, PCI_DEVICE_ID, &chip); | ||
315 | rt2x00dev->chip.rt = chip; | ||
316 | |||
308 | retval = rt2x00lib_probe_dev(rt2x00dev); | 317 | retval = rt2x00lib_probe_dev(rt2x00dev); |
309 | if (retval) | 318 | if (retval) |
310 | goto exit_free_reg; | 319 | goto exit_free_reg; |
diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/rtl818x/rtl8180/dev.c index 2bebcb71a1e..3b505395d86 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180/dev.c | |||
@@ -47,6 +47,8 @@ static DEFINE_PCI_DEVICE_TABLE(rtl8180_table) = { | |||
47 | { PCI_DEVICE(0x1799, 0x6001) }, | 47 | { PCI_DEVICE(0x1799, 0x6001) }, |
48 | { PCI_DEVICE(0x1799, 0x6020) }, | 48 | { PCI_DEVICE(0x1799, 0x6020) }, |
49 | { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x3300) }, | 49 | { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x3300) }, |
50 | { PCI_DEVICE(0x1186, 0x3301) }, | ||
51 | { PCI_DEVICE(0x1432, 0x7106) }, | ||
50 | { } | 52 | { } |
51 | }; | 53 | }; |
52 | 54 | ||
diff --git a/drivers/net/wireless/rtl818x/rtl8187/leds.c b/drivers/net/wireless/rtl818x/rtl8187/leds.c index 2e0de2f5f0f..c2d5b495c17 100644 --- a/drivers/net/wireless/rtl818x/rtl8187/leds.c +++ b/drivers/net/wireless/rtl818x/rtl8187/leds.c | |||
@@ -117,7 +117,7 @@ static void rtl8187_led_brightness_set(struct led_classdev *led_dev, | |||
117 | radio_on = true; | 117 | radio_on = true; |
118 | } else if (radio_on) { | 118 | } else if (radio_on) { |
119 | radio_on = false; | 119 | radio_on = false; |
120 | cancel_delayed_work_sync(&priv->led_on); | 120 | cancel_delayed_work(&priv->led_on); |
121 | ieee80211_queue_delayed_work(hw, &priv->led_off, 0); | 121 | ieee80211_queue_delayed_work(hw, &priv->led_off, 0); |
122 | } | 122 | } |
123 | } else if (radio_on) { | 123 | } else if (radio_on) { |
diff --git a/drivers/net/wireless/rtlwifi/cam.c b/drivers/net/wireless/rtlwifi/cam.c index 3d8cc4a0c86..6a2d72beb00 100644 --- a/drivers/net/wireless/rtlwifi/cam.c +++ b/drivers/net/wireless/rtlwifi/cam.c | |||
@@ -128,7 +128,7 @@ u8 rtl_cam_add_one_entry(struct ieee80211_hw *hw, u8 *mac_addr, | |||
128 | u32 us_config; | 128 | u32 us_config; |
129 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 129 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
130 | 130 | ||
131 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, | 131 | RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, |
132 | "EntryNo:%x, ulKeyId=%x, ulEncAlg=%x, ulUseDK=%x MacAddr %pM\n", | 132 | "EntryNo:%x, ulKeyId=%x, ulEncAlg=%x, ulUseDK=%x MacAddr %pM\n", |
133 | ul_entry_idx, ul_key_id, ul_enc_alg, | 133 | ul_entry_idx, ul_key_id, ul_enc_alg, |
134 | ul_default_key, mac_addr); | 134 | ul_default_key, mac_addr); |
@@ -342,7 +342,8 @@ void rtl_cam_del_entry(struct ieee80211_hw *hw, u8 *sta_addr) | |||
342 | /* Remove from HW Security CAM */ | 342 | /* Remove from HW Security CAM */ |
343 | memset(rtlpriv->sec.hwsec_cam_sta_addr[i], 0, ETH_ALEN); | 343 | memset(rtlpriv->sec.hwsec_cam_sta_addr[i], 0, ETH_ALEN); |
344 | rtlpriv->sec.hwsec_cam_bitmap &= ~(BIT(0) << i); | 344 | rtlpriv->sec.hwsec_cam_bitmap &= ~(BIT(0) << i); |
345 | pr_info("&&&&&&&&&del entry %d\n", i); | 345 | RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, |
346 | "del CAM entry %d\n", i); | ||
346 | } | 347 | } |
347 | } | 348 | } |
348 | return; | 349 | return; |
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 2062ea1d7c8..36bffbc4519 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c | |||
@@ -1273,17 +1273,18 @@ int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw) | |||
1273 | *after reset, release previous pending packet, | 1273 | *after reset, release previous pending packet, |
1274 | *and force the tx idx to the first one | 1274 | *and force the tx idx to the first one |
1275 | */ | 1275 | */ |
1276 | spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); | ||
1277 | for (i = 0; i < RTL_PCI_MAX_TX_QUEUE_COUNT; i++) { | 1276 | for (i = 0; i < RTL_PCI_MAX_TX_QUEUE_COUNT; i++) { |
1278 | if (rtlpci->tx_ring[i].desc) { | 1277 | if (rtlpci->tx_ring[i].desc) { |
1279 | struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[i]; | 1278 | struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[i]; |
1280 | 1279 | ||
1281 | while (skb_queue_len(&ring->queue)) { | 1280 | while (skb_queue_len(&ring->queue)) { |
1282 | struct rtl_tx_desc *entry = | 1281 | struct rtl_tx_desc *entry; |
1283 | &ring->desc[ring->idx]; | 1282 | struct sk_buff *skb; |
1284 | struct sk_buff *skb = | ||
1285 | __skb_dequeue(&ring->queue); | ||
1286 | 1283 | ||
1284 | spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, | ||
1285 | flags); | ||
1286 | entry = &ring->desc[ring->idx]; | ||
1287 | skb = __skb_dequeue(&ring->queue); | ||
1287 | pci_unmap_single(rtlpci->pdev, | 1288 | pci_unmap_single(rtlpci->pdev, |
1288 | rtlpriv->cfg->ops-> | 1289 | rtlpriv->cfg->ops-> |
1289 | get_desc((u8 *) | 1290 | get_desc((u8 *) |
@@ -1291,15 +1292,15 @@ int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw) | |||
1291 | true, | 1292 | true, |
1292 | HW_DESC_TXBUFF_ADDR), | 1293 | HW_DESC_TXBUFF_ADDR), |
1293 | skb->len, PCI_DMA_TODEVICE); | 1294 | skb->len, PCI_DMA_TODEVICE); |
1294 | kfree_skb(skb); | ||
1295 | ring->idx = (ring->idx + 1) % ring->entries; | 1295 | ring->idx = (ring->idx + 1) % ring->entries; |
1296 | spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, | ||
1297 | flags); | ||
1298 | kfree_skb(skb); | ||
1296 | } | 1299 | } |
1297 | ring->idx = 0; | 1300 | ring->idx = 0; |
1298 | } | 1301 | } |
1299 | } | 1302 | } |
1300 | 1303 | ||
1301 | spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); | ||
1302 | |||
1303 | return 0; | 1304 | return 0; |
1304 | } | 1305 | } |
1305 | 1306 | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c index 8d7099bc472..b917a2a3caf 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c | |||
@@ -1247,6 +1247,9 @@ static void _rtl92s_phy_get_txpower_index(struct ieee80211_hw *hw, u8 channel, | |||
1247 | /* Read HT 40 OFDM TX power */ | 1247 | /* Read HT 40 OFDM TX power */ |
1248 | ofdmpowerLevel[0] = rtlefuse->txpwrlevel_ht40_2s[0][index]; | 1248 | ofdmpowerLevel[0] = rtlefuse->txpwrlevel_ht40_2s[0][index]; |
1249 | ofdmpowerLevel[1] = rtlefuse->txpwrlevel_ht40_2s[1][index]; | 1249 | ofdmpowerLevel[1] = rtlefuse->txpwrlevel_ht40_2s[1][index]; |
1250 | } else { | ||
1251 | ofdmpowerLevel[0] = 0; | ||
1252 | ofdmpowerLevel[1] = 0; | ||
1250 | } | 1253 | } |
1251 | } | 1254 | } |
1252 | 1255 | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c index 730bcc91952..ad4b4803482 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c | |||
@@ -29,7 +29,6 @@ | |||
29 | 29 | ||
30 | #include "../wifi.h" | 30 | #include "../wifi.h" |
31 | #include "../core.h" | 31 | #include "../core.h" |
32 | #include "../pci.h" | ||
33 | #include "../base.h" | 32 | #include "../base.h" |
34 | #include "../pci.h" | 33 | #include "../pci.h" |
35 | #include "reg.h" | 34 | #include "reg.h" |
diff --git a/drivers/net/wireless/ti/wl1251/cmd.c b/drivers/net/wireless/ti/wl1251/cmd.c index d14d69d733a..6822b845efc 100644 --- a/drivers/net/wireless/ti/wl1251/cmd.c +++ b/drivers/net/wireless/ti/wl1251/cmd.c | |||
@@ -277,15 +277,6 @@ int wl1251_cmd_join(struct wl1251 *wl, u8 bss_type, u8 channel, | |||
277 | join->rx_config_options = wl->rx_config; | 277 | join->rx_config_options = wl->rx_config; |
278 | join->rx_filter_options = wl->rx_filter; | 278 | join->rx_filter_options = wl->rx_filter; |
279 | 279 | ||
280 | /* | ||
281 | * FIXME: disable temporarily all filters because after commit | ||
282 | * 9cef8737 "mac80211: fix managed mode BSSID handling" broke | ||
283 | * association. The filter logic needs to be implemented properly | ||
284 | * and once that is done, this hack can be removed. | ||
285 | */ | ||
286 | join->rx_config_options = 0; | ||
287 | join->rx_filter_options = WL1251_DEFAULT_RX_FILTER; | ||
288 | |||
289 | join->basic_rate_set = RATE_MASK_1MBPS | RATE_MASK_2MBPS | | 280 | join->basic_rate_set = RATE_MASK_1MBPS | RATE_MASK_2MBPS | |
290 | RATE_MASK_5_5MBPS | RATE_MASK_11MBPS; | 281 | RATE_MASK_5_5MBPS | RATE_MASK_11MBPS; |
291 | 282 | ||
diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c index d1afb8e3b2e..3118c425bcf 100644 --- a/drivers/net/wireless/ti/wl1251/main.c +++ b/drivers/net/wireless/ti/wl1251/main.c | |||
@@ -334,6 +334,12 @@ static int wl1251_join(struct wl1251 *wl, u8 bss_type, u8 channel, | |||
334 | if (ret < 0) | 334 | if (ret < 0) |
335 | goto out; | 335 | goto out; |
336 | 336 | ||
337 | /* | ||
338 | * Join command applies filters, and if we are not associated, | ||
339 | * BSSID filter must be disabled for association to work. | ||
340 | */ | ||
341 | if (is_zero_ether_addr(wl->bssid)) | ||
342 | wl->rx_config &= ~CFG_BSSID_FILTER_EN; | ||
337 | 343 | ||
338 | ret = wl1251_cmd_join(wl, bss_type, channel, beacon_interval, | 344 | ret = wl1251_cmd_join(wl, bss_type, channel, beacon_interval, |
339 | dtim_period); | 345 | dtim_period); |
@@ -348,33 +354,6 @@ out: | |||
348 | return ret; | 354 | return ret; |
349 | } | 355 | } |
350 | 356 | ||
351 | static void wl1251_filter_work(struct work_struct *work) | ||
352 | { | ||
353 | struct wl1251 *wl = | ||
354 | container_of(work, struct wl1251, filter_work); | ||
355 | int ret; | ||
356 | |||
357 | mutex_lock(&wl->mutex); | ||
358 | |||
359 | if (wl->state == WL1251_STATE_OFF) | ||
360 | goto out; | ||
361 | |||
362 | ret = wl1251_ps_elp_wakeup(wl); | ||
363 | if (ret < 0) | ||
364 | goto out; | ||
365 | |||
366 | ret = wl1251_join(wl, wl->bss_type, wl->channel, wl->beacon_int, | ||
367 | wl->dtim_period); | ||
368 | if (ret < 0) | ||
369 | goto out_sleep; | ||
370 | |||
371 | out_sleep: | ||
372 | wl1251_ps_elp_sleep(wl); | ||
373 | |||
374 | out: | ||
375 | mutex_unlock(&wl->mutex); | ||
376 | } | ||
377 | |||
378 | static void wl1251_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | 357 | static void wl1251_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) |
379 | { | 358 | { |
380 | struct wl1251 *wl = hw->priv; | 359 | struct wl1251 *wl = hw->priv; |
@@ -478,7 +457,6 @@ static void wl1251_op_stop(struct ieee80211_hw *hw) | |||
478 | 457 | ||
479 | cancel_work_sync(&wl->irq_work); | 458 | cancel_work_sync(&wl->irq_work); |
480 | cancel_work_sync(&wl->tx_work); | 459 | cancel_work_sync(&wl->tx_work); |
481 | cancel_work_sync(&wl->filter_work); | ||
482 | cancel_delayed_work_sync(&wl->elp_work); | 460 | cancel_delayed_work_sync(&wl->elp_work); |
483 | 461 | ||
484 | mutex_lock(&wl->mutex); | 462 | mutex_lock(&wl->mutex); |
@@ -681,13 +659,15 @@ out: | |||
681 | FIF_FCSFAIL | \ | 659 | FIF_FCSFAIL | \ |
682 | FIF_BCN_PRBRESP_PROMISC | \ | 660 | FIF_BCN_PRBRESP_PROMISC | \ |
683 | FIF_CONTROL | \ | 661 | FIF_CONTROL | \ |
684 | FIF_OTHER_BSS) | 662 | FIF_OTHER_BSS | \ |
663 | FIF_PROBE_REQ) | ||
685 | 664 | ||
686 | static void wl1251_op_configure_filter(struct ieee80211_hw *hw, | 665 | static void wl1251_op_configure_filter(struct ieee80211_hw *hw, |
687 | unsigned int changed, | 666 | unsigned int changed, |
688 | unsigned int *total,u64 multicast) | 667 | unsigned int *total,u64 multicast) |
689 | { | 668 | { |
690 | struct wl1251 *wl = hw->priv; | 669 | struct wl1251 *wl = hw->priv; |
670 | int ret; | ||
691 | 671 | ||
692 | wl1251_debug(DEBUG_MAC80211, "mac80211 configure filter"); | 672 | wl1251_debug(DEBUG_MAC80211, "mac80211 configure filter"); |
693 | 673 | ||
@@ -698,7 +678,7 @@ static void wl1251_op_configure_filter(struct ieee80211_hw *hw, | |||
698 | /* no filters which we support changed */ | 678 | /* no filters which we support changed */ |
699 | return; | 679 | return; |
700 | 680 | ||
701 | /* FIXME: wl->rx_config and wl->rx_filter are not protected */ | 681 | mutex_lock(&wl->mutex); |
702 | 682 | ||
703 | wl->rx_config = WL1251_DEFAULT_RX_CONFIG; | 683 | wl->rx_config = WL1251_DEFAULT_RX_CONFIG; |
704 | wl->rx_filter = WL1251_DEFAULT_RX_FILTER; | 684 | wl->rx_filter = WL1251_DEFAULT_RX_FILTER; |
@@ -721,15 +701,25 @@ static void wl1251_op_configure_filter(struct ieee80211_hw *hw, | |||
721 | } | 701 | } |
722 | if (*total & FIF_CONTROL) | 702 | if (*total & FIF_CONTROL) |
723 | wl->rx_filter |= CFG_RX_CTL_EN; | 703 | wl->rx_filter |= CFG_RX_CTL_EN; |
724 | if (*total & FIF_OTHER_BSS) | 704 | if (*total & FIF_OTHER_BSS || is_zero_ether_addr(wl->bssid)) |
725 | wl->rx_filter &= ~CFG_BSSID_FILTER_EN; | 705 | wl->rx_config &= ~CFG_BSSID_FILTER_EN; |
706 | if (*total & FIF_PROBE_REQ) | ||
707 | wl->rx_filter |= CFG_RX_PREQ_EN; | ||
726 | 708 | ||
727 | /* | 709 | if (wl->state == WL1251_STATE_OFF) |
728 | * FIXME: workqueues need to be properly cancelled on stop(), for | 710 | goto out; |
729 | * now let's just disable changing the filter settings. They will | 711 | |
730 | * be updated any on config(). | 712 | ret = wl1251_ps_elp_wakeup(wl); |
731 | */ | 713 | if (ret < 0) |
732 | /* schedule_work(&wl->filter_work); */ | 714 | goto out; |
715 | |||
716 | /* send filters to firmware */ | ||
717 | wl1251_acx_rx_config(wl, wl->rx_config, wl->rx_filter); | ||
718 | |||
719 | wl1251_ps_elp_sleep(wl); | ||
720 | |||
721 | out: | ||
722 | mutex_unlock(&wl->mutex); | ||
733 | } | 723 | } |
734 | 724 | ||
735 | /* HW encryption */ | 725 | /* HW encryption */ |
@@ -1390,7 +1380,6 @@ struct ieee80211_hw *wl1251_alloc_hw(void) | |||
1390 | 1380 | ||
1391 | skb_queue_head_init(&wl->tx_queue); | 1381 | skb_queue_head_init(&wl->tx_queue); |
1392 | 1382 | ||
1393 | INIT_WORK(&wl->filter_work, wl1251_filter_work); | ||
1394 | INIT_DELAYED_WORK(&wl->elp_work, wl1251_elp_work); | 1383 | INIT_DELAYED_WORK(&wl->elp_work, wl1251_elp_work); |
1395 | wl->channel = WL1251_DEFAULT_CHANNEL; | 1384 | wl->channel = WL1251_DEFAULT_CHANNEL; |
1396 | wl->scanning = false; | 1385 | wl->scanning = false; |
diff --git a/drivers/net/wireless/ti/wl1251/wl1251.h b/drivers/net/wireless/ti/wl1251/wl1251.h index 9d8f5816c6f..fd02060038d 100644 --- a/drivers/net/wireless/ti/wl1251/wl1251.h +++ b/drivers/net/wireless/ti/wl1251/wl1251.h | |||
@@ -315,7 +315,6 @@ struct wl1251 { | |||
315 | bool tx_queue_stopped; | 315 | bool tx_queue_stopped; |
316 | 316 | ||
317 | struct work_struct tx_work; | 317 | struct work_struct tx_work; |
318 | struct work_struct filter_work; | ||
319 | 318 | ||
320 | /* Pending TX frames */ | 319 | /* Pending TX frames */ |
321 | struct sk_buff *tx_frames[16]; | 320 | struct sk_buff *tx_frames[16]; |
diff --git a/drivers/net/wireless/ti/wl12xx/cmd.c b/drivers/net/wireless/ti/wl12xx/cmd.c index 50ba7480b79..30be784a40d 100644 --- a/drivers/net/wireless/ti/wl12xx/cmd.c +++ b/drivers/net/wireless/ti/wl12xx/cmd.c | |||
@@ -174,7 +174,7 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) | |||
174 | struct wl1271_nvs_file *nvs = (struct wl1271_nvs_file *)wl->nvs; | 174 | struct wl1271_nvs_file *nvs = (struct wl1271_nvs_file *)wl->nvs; |
175 | struct wl1271_radio_parms_cmd *radio_parms; | 175 | struct wl1271_radio_parms_cmd *radio_parms; |
176 | struct wl1271_ini_general_params *gp = &nvs->general_params; | 176 | struct wl1271_ini_general_params *gp = &nvs->general_params; |
177 | int ret; | 177 | int ret, fem_idx; |
178 | 178 | ||
179 | if (!wl->nvs) | 179 | if (!wl->nvs) |
180 | return -ENODEV; | 180 | return -ENODEV; |
@@ -185,11 +185,13 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) | |||
185 | 185 | ||
186 | radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM; | 186 | radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM; |
187 | 187 | ||
188 | fem_idx = WL12XX_FEM_TO_NVS_ENTRY(gp->tx_bip_fem_manufacturer); | ||
189 | |||
188 | /* 2.4GHz parameters */ | 190 | /* 2.4GHz parameters */ |
189 | memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2, | 191 | memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2, |
190 | sizeof(struct wl1271_ini_band_params_2)); | 192 | sizeof(struct wl1271_ini_band_params_2)); |
191 | memcpy(&radio_parms->dyn_params_2, | 193 | memcpy(&radio_parms->dyn_params_2, |
192 | &nvs->dyn_radio_params_2[gp->tx_bip_fem_manufacturer].params, | 194 | &nvs->dyn_radio_params_2[fem_idx].params, |
193 | sizeof(struct wl1271_ini_fem_params_2)); | 195 | sizeof(struct wl1271_ini_fem_params_2)); |
194 | 196 | ||
195 | /* 5GHz parameters */ | 197 | /* 5GHz parameters */ |
@@ -197,7 +199,7 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) | |||
197 | &nvs->stat_radio_params_5, | 199 | &nvs->stat_radio_params_5, |
198 | sizeof(struct wl1271_ini_band_params_5)); | 200 | sizeof(struct wl1271_ini_band_params_5)); |
199 | memcpy(&radio_parms->dyn_params_5, | 201 | memcpy(&radio_parms->dyn_params_5, |
200 | &nvs->dyn_radio_params_5[gp->tx_bip_fem_manufacturer].params, | 202 | &nvs->dyn_radio_params_5[fem_idx].params, |
201 | sizeof(struct wl1271_ini_fem_params_5)); | 203 | sizeof(struct wl1271_ini_fem_params_5)); |
202 | 204 | ||
203 | wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", | 205 | wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", |
@@ -216,7 +218,7 @@ int wl128x_cmd_radio_parms(struct wl1271 *wl) | |||
216 | struct wl128x_nvs_file *nvs = (struct wl128x_nvs_file *)wl->nvs; | 218 | struct wl128x_nvs_file *nvs = (struct wl128x_nvs_file *)wl->nvs; |
217 | struct wl128x_radio_parms_cmd *radio_parms; | 219 | struct wl128x_radio_parms_cmd *radio_parms; |
218 | struct wl128x_ini_general_params *gp = &nvs->general_params; | 220 | struct wl128x_ini_general_params *gp = &nvs->general_params; |
219 | int ret; | 221 | int ret, fem_idx; |
220 | 222 | ||
221 | if (!wl->nvs) | 223 | if (!wl->nvs) |
222 | return -ENODEV; | 224 | return -ENODEV; |
@@ -227,11 +229,13 @@ int wl128x_cmd_radio_parms(struct wl1271 *wl) | |||
227 | 229 | ||
228 | radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM; | 230 | radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM; |
229 | 231 | ||
232 | fem_idx = WL12XX_FEM_TO_NVS_ENTRY(gp->tx_bip_fem_manufacturer); | ||
233 | |||
230 | /* 2.4GHz parameters */ | 234 | /* 2.4GHz parameters */ |
231 | memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2, | 235 | memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2, |
232 | sizeof(struct wl128x_ini_band_params_2)); | 236 | sizeof(struct wl128x_ini_band_params_2)); |
233 | memcpy(&radio_parms->dyn_params_2, | 237 | memcpy(&radio_parms->dyn_params_2, |
234 | &nvs->dyn_radio_params_2[gp->tx_bip_fem_manufacturer].params, | 238 | &nvs->dyn_radio_params_2[fem_idx].params, |
235 | sizeof(struct wl128x_ini_fem_params_2)); | 239 | sizeof(struct wl128x_ini_fem_params_2)); |
236 | 240 | ||
237 | /* 5GHz parameters */ | 241 | /* 5GHz parameters */ |
@@ -239,7 +243,7 @@ int wl128x_cmd_radio_parms(struct wl1271 *wl) | |||
239 | &nvs->stat_radio_params_5, | 243 | &nvs->stat_radio_params_5, |
240 | sizeof(struct wl128x_ini_band_params_5)); | 244 | sizeof(struct wl128x_ini_band_params_5)); |
241 | memcpy(&radio_parms->dyn_params_5, | 245 | memcpy(&radio_parms->dyn_params_5, |
242 | &nvs->dyn_radio_params_5[gp->tx_bip_fem_manufacturer].params, | 246 | &nvs->dyn_radio_params_5[fem_idx].params, |
243 | sizeof(struct wl128x_ini_fem_params_5)); | 247 | sizeof(struct wl128x_ini_fem_params_5)); |
244 | 248 | ||
245 | radio_parms->fem_vendor_and_options = nvs->fem_vendor_and_options; | 249 | radio_parms->fem_vendor_and_options = nvs->fem_vendor_and_options; |
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c index 85d1600ee34..47ba2e0017f 100644 --- a/drivers/net/wireless/ti/wl12xx/main.c +++ b/drivers/net/wireless/ti/wl12xx/main.c | |||
@@ -246,6 +246,7 @@ static struct wlcore_conf wl12xx_conf = { | |||
246 | .forced_ps = false, | 246 | .forced_ps = false, |
247 | .keep_alive_interval = 55000, | 247 | .keep_alive_interval = 55000, |
248 | .max_listen_interval = 20, | 248 | .max_listen_interval = 20, |
249 | .sta_sleep_auth = WL1271_PSM_ILLEGAL, | ||
249 | }, | 250 | }, |
250 | .itrim = { | 251 | .itrim = { |
251 | .enable = false, | 252 | .enable = false, |
@@ -597,8 +598,10 @@ static const int wl12xx_rtable[REG_TABLE_LEN] = { | |||
597 | #define WL128X_FW_NAME_SINGLE "ti-connectivity/wl128x-fw-4-sr.bin" | 598 | #define WL128X_FW_NAME_SINGLE "ti-connectivity/wl128x-fw-4-sr.bin" |
598 | #define WL128X_PLT_FW_NAME "ti-connectivity/wl128x-fw-4-plt.bin" | 599 | #define WL128X_PLT_FW_NAME "ti-connectivity/wl128x-fw-4-plt.bin" |
599 | 600 | ||
600 | static void wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len) | 601 | static int wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len) |
601 | { | 602 | { |
603 | int ret; | ||
604 | |||
602 | if (wl->chip.id != CHIP_ID_1283_PG20) { | 605 | if (wl->chip.id != CHIP_ID_1283_PG20) { |
603 | struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map; | 606 | struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map; |
604 | struct wl127x_rx_mem_pool_addr rx_mem_addr; | 607 | struct wl127x_rx_mem_pool_addr rx_mem_addr; |
@@ -615,9 +618,13 @@ static void wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len) | |||
615 | 618 | ||
616 | rx_mem_addr.addr_extra = rx_mem_addr.addr + 4; | 619 | rx_mem_addr.addr_extra = rx_mem_addr.addr + 4; |
617 | 620 | ||
618 | wl1271_write(wl, WL1271_SLV_REG_DATA, | 621 | ret = wlcore_write(wl, WL1271_SLV_REG_DATA, &rx_mem_addr, |
619 | &rx_mem_addr, sizeof(rx_mem_addr), false); | 622 | sizeof(rx_mem_addr), false); |
623 | if (ret < 0) | ||
624 | return ret; | ||
620 | } | 625 | } |
626 | |||
627 | return 0; | ||
621 | } | 628 | } |
622 | 629 | ||
623 | static int wl12xx_identify_chip(struct wl1271 *wl) | 630 | static int wl12xx_identify_chip(struct wl1271 *wl) |
@@ -681,64 +688,95 @@ out: | |||
681 | return ret; | 688 | return ret; |
682 | } | 689 | } |
683 | 690 | ||
684 | static void wl12xx_top_reg_write(struct wl1271 *wl, int addr, u16 val) | 691 | static int __must_check wl12xx_top_reg_write(struct wl1271 *wl, int addr, |
692 | u16 val) | ||
685 | { | 693 | { |
694 | int ret; | ||
695 | |||
686 | /* write address >> 1 + 0x30000 to OCP_POR_CTR */ | 696 | /* write address >> 1 + 0x30000 to OCP_POR_CTR */ |
687 | addr = (addr >> 1) + 0x30000; | 697 | addr = (addr >> 1) + 0x30000; |
688 | wl1271_write32(wl, WL12XX_OCP_POR_CTR, addr); | 698 | ret = wlcore_write32(wl, WL12XX_OCP_POR_CTR, addr); |
699 | if (ret < 0) | ||
700 | goto out; | ||
689 | 701 | ||
690 | /* write value to OCP_POR_WDATA */ | 702 | /* write value to OCP_POR_WDATA */ |
691 | wl1271_write32(wl, WL12XX_OCP_DATA_WRITE, val); | 703 | ret = wlcore_write32(wl, WL12XX_OCP_DATA_WRITE, val); |
704 | if (ret < 0) | ||
705 | goto out; | ||
692 | 706 | ||
693 | /* write 1 to OCP_CMD */ | 707 | /* write 1 to OCP_CMD */ |
694 | wl1271_write32(wl, WL12XX_OCP_CMD, OCP_CMD_WRITE); | 708 | ret = wlcore_write32(wl, WL12XX_OCP_CMD, OCP_CMD_WRITE); |
709 | if (ret < 0) | ||
710 | goto out; | ||
711 | |||
712 | out: | ||
713 | return ret; | ||
695 | } | 714 | } |
696 | 715 | ||
697 | static u16 wl12xx_top_reg_read(struct wl1271 *wl, int addr) | 716 | static int __must_check wl12xx_top_reg_read(struct wl1271 *wl, int addr, |
717 | u16 *out) | ||
698 | { | 718 | { |
699 | u32 val; | 719 | u32 val; |
700 | int timeout = OCP_CMD_LOOP; | 720 | int timeout = OCP_CMD_LOOP; |
721 | int ret; | ||
701 | 722 | ||
702 | /* write address >> 1 + 0x30000 to OCP_POR_CTR */ | 723 | /* write address >> 1 + 0x30000 to OCP_POR_CTR */ |
703 | addr = (addr >> 1) + 0x30000; | 724 | addr = (addr >> 1) + 0x30000; |
704 | wl1271_write32(wl, WL12XX_OCP_POR_CTR, addr); | 725 | ret = wlcore_write32(wl, WL12XX_OCP_POR_CTR, addr); |
726 | if (ret < 0) | ||
727 | return ret; | ||
705 | 728 | ||
706 | /* write 2 to OCP_CMD */ | 729 | /* write 2 to OCP_CMD */ |
707 | wl1271_write32(wl, WL12XX_OCP_CMD, OCP_CMD_READ); | 730 | ret = wlcore_write32(wl, WL12XX_OCP_CMD, OCP_CMD_READ); |
731 | if (ret < 0) | ||
732 | return ret; | ||
708 | 733 | ||
709 | /* poll for data ready */ | 734 | /* poll for data ready */ |
710 | do { | 735 | do { |
711 | val = wl1271_read32(wl, WL12XX_OCP_DATA_READ); | 736 | ret = wlcore_read32(wl, WL12XX_OCP_DATA_READ, &val); |
737 | if (ret < 0) | ||
738 | return ret; | ||
712 | } while (!(val & OCP_READY_MASK) && --timeout); | 739 | } while (!(val & OCP_READY_MASK) && --timeout); |
713 | 740 | ||
714 | if (!timeout) { | 741 | if (!timeout) { |
715 | wl1271_warning("Top register access timed out."); | 742 | wl1271_warning("Top register access timed out."); |
716 | return 0xffff; | 743 | return -ETIMEDOUT; |
717 | } | 744 | } |
718 | 745 | ||
719 | /* check data status and return if OK */ | 746 | /* check data status and return if OK */ |
720 | if ((val & OCP_STATUS_MASK) == OCP_STATUS_OK) | 747 | if ((val & OCP_STATUS_MASK) != OCP_STATUS_OK) { |
721 | return val & 0xffff; | ||
722 | else { | ||
723 | wl1271_warning("Top register access returned error."); | 748 | wl1271_warning("Top register access returned error."); |
724 | return 0xffff; | 749 | return -EIO; |
725 | } | 750 | } |
751 | |||
752 | if (out) | ||
753 | *out = val & 0xffff; | ||
754 | |||
755 | return 0; | ||
726 | } | 756 | } |
727 | 757 | ||
728 | static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl) | 758 | static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl) |
729 | { | 759 | { |
730 | u16 spare_reg; | 760 | u16 spare_reg; |
761 | int ret; | ||
731 | 762 | ||
732 | /* Mask bits [2] & [8:4] in the sys_clk_cfg register */ | 763 | /* Mask bits [2] & [8:4] in the sys_clk_cfg register */ |
733 | spare_reg = wl12xx_top_reg_read(wl, WL_SPARE_REG); | 764 | ret = wl12xx_top_reg_read(wl, WL_SPARE_REG, &spare_reg); |
765 | if (ret < 0) | ||
766 | return ret; | ||
767 | |||
734 | if (spare_reg == 0xFFFF) | 768 | if (spare_reg == 0xFFFF) |
735 | return -EFAULT; | 769 | return -EFAULT; |
736 | spare_reg |= (BIT(3) | BIT(5) | BIT(6)); | 770 | spare_reg |= (BIT(3) | BIT(5) | BIT(6)); |
737 | wl12xx_top_reg_write(wl, WL_SPARE_REG, spare_reg); | 771 | ret = wl12xx_top_reg_write(wl, WL_SPARE_REG, spare_reg); |
772 | if (ret < 0) | ||
773 | return ret; | ||
738 | 774 | ||
739 | /* Enable FREF_CLK_REQ & mux MCS and coex PLLs to FREF */ | 775 | /* Enable FREF_CLK_REQ & mux MCS and coex PLLs to FREF */ |
740 | wl12xx_top_reg_write(wl, SYS_CLK_CFG_REG, | 776 | ret = wl12xx_top_reg_write(wl, SYS_CLK_CFG_REG, |
741 | WL_CLK_REQ_TYPE_PG2 | MCS_PLL_CLK_SEL_FREF); | 777 | WL_CLK_REQ_TYPE_PG2 | MCS_PLL_CLK_SEL_FREF); |
778 | if (ret < 0) | ||
779 | return ret; | ||
742 | 780 | ||
743 | /* Delay execution for 15msec, to let the HW settle */ | 781 | /* Delay execution for 15msec, to let the HW settle */ |
744 | mdelay(15); | 782 | mdelay(15); |
@@ -749,8 +787,12 @@ static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl) | |||
749 | static bool wl128x_is_tcxo_valid(struct wl1271 *wl) | 787 | static bool wl128x_is_tcxo_valid(struct wl1271 *wl) |
750 | { | 788 | { |
751 | u16 tcxo_detection; | 789 | u16 tcxo_detection; |
790 | int ret; | ||
791 | |||
792 | ret = wl12xx_top_reg_read(wl, TCXO_CLK_DETECT_REG, &tcxo_detection); | ||
793 | if (ret < 0) | ||
794 | return false; | ||
752 | 795 | ||
753 | tcxo_detection = wl12xx_top_reg_read(wl, TCXO_CLK_DETECT_REG); | ||
754 | if (tcxo_detection & TCXO_DET_FAILED) | 796 | if (tcxo_detection & TCXO_DET_FAILED) |
755 | return false; | 797 | return false; |
756 | 798 | ||
@@ -760,8 +802,12 @@ static bool wl128x_is_tcxo_valid(struct wl1271 *wl) | |||
760 | static bool wl128x_is_fref_valid(struct wl1271 *wl) | 802 | static bool wl128x_is_fref_valid(struct wl1271 *wl) |
761 | { | 803 | { |
762 | u16 fref_detection; | 804 | u16 fref_detection; |
805 | int ret; | ||
806 | |||
807 | ret = wl12xx_top_reg_read(wl, FREF_CLK_DETECT_REG, &fref_detection); | ||
808 | if (ret < 0) | ||
809 | return false; | ||
763 | 810 | ||
764 | fref_detection = wl12xx_top_reg_read(wl, FREF_CLK_DETECT_REG); | ||
765 | if (fref_detection & FREF_CLK_DETECT_FAIL) | 811 | if (fref_detection & FREF_CLK_DETECT_FAIL) |
766 | return false; | 812 | return false; |
767 | 813 | ||
@@ -770,11 +816,21 @@ static bool wl128x_is_fref_valid(struct wl1271 *wl) | |||
770 | 816 | ||
771 | static int wl128x_manually_configure_mcs_pll(struct wl1271 *wl) | 817 | static int wl128x_manually_configure_mcs_pll(struct wl1271 *wl) |
772 | { | 818 | { |
773 | wl12xx_top_reg_write(wl, MCS_PLL_M_REG, MCS_PLL_M_REG_VAL); | 819 | int ret; |
774 | wl12xx_top_reg_write(wl, MCS_PLL_N_REG, MCS_PLL_N_REG_VAL); | ||
775 | wl12xx_top_reg_write(wl, MCS_PLL_CONFIG_REG, MCS_PLL_CONFIG_REG_VAL); | ||
776 | 820 | ||
777 | return 0; | 821 | ret = wl12xx_top_reg_write(wl, MCS_PLL_M_REG, MCS_PLL_M_REG_VAL); |
822 | if (ret < 0) | ||
823 | goto out; | ||
824 | |||
825 | ret = wl12xx_top_reg_write(wl, MCS_PLL_N_REG, MCS_PLL_N_REG_VAL); | ||
826 | if (ret < 0) | ||
827 | goto out; | ||
828 | |||
829 | ret = wl12xx_top_reg_write(wl, MCS_PLL_CONFIG_REG, | ||
830 | MCS_PLL_CONFIG_REG_VAL); | ||
831 | |||
832 | out: | ||
833 | return ret; | ||
778 | } | 834 | } |
779 | 835 | ||
780 | static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk) | 836 | static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk) |
@@ -783,13 +839,19 @@ static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk) | |||
783 | u16 pll_config; | 839 | u16 pll_config; |
784 | u8 input_freq; | 840 | u8 input_freq; |
785 | struct wl12xx_priv *priv = wl->priv; | 841 | struct wl12xx_priv *priv = wl->priv; |
842 | int ret; | ||
786 | 843 | ||
787 | /* Mask bits [3:1] in the sys_clk_cfg register */ | 844 | /* Mask bits [3:1] in the sys_clk_cfg register */ |
788 | spare_reg = wl12xx_top_reg_read(wl, WL_SPARE_REG); | 845 | ret = wl12xx_top_reg_read(wl, WL_SPARE_REG, &spare_reg); |
846 | if (ret < 0) | ||
847 | return ret; | ||
848 | |||
789 | if (spare_reg == 0xFFFF) | 849 | if (spare_reg == 0xFFFF) |
790 | return -EFAULT; | 850 | return -EFAULT; |
791 | spare_reg |= BIT(2); | 851 | spare_reg |= BIT(2); |
792 | wl12xx_top_reg_write(wl, WL_SPARE_REG, spare_reg); | 852 | ret = wl12xx_top_reg_write(wl, WL_SPARE_REG, spare_reg); |
853 | if (ret < 0) | ||
854 | return ret; | ||
793 | 855 | ||
794 | /* Handle special cases of the TCXO clock */ | 856 | /* Handle special cases of the TCXO clock */ |
795 | if (priv->tcxo_clock == WL12XX_TCXOCLOCK_16_8 || | 857 | if (priv->tcxo_clock == WL12XX_TCXOCLOCK_16_8 || |
@@ -799,14 +861,17 @@ static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk) | |||
799 | /* Set the input frequency according to the selected clock source */ | 861 | /* Set the input frequency according to the selected clock source */ |
800 | input_freq = (clk & 1) + 1; | 862 | input_freq = (clk & 1) + 1; |
801 | 863 | ||
802 | pll_config = wl12xx_top_reg_read(wl, MCS_PLL_CONFIG_REG); | 864 | ret = wl12xx_top_reg_read(wl, MCS_PLL_CONFIG_REG, &pll_config); |
865 | if (ret < 0) | ||
866 | return ret; | ||
867 | |||
803 | if (pll_config == 0xFFFF) | 868 | if (pll_config == 0xFFFF) |
804 | return -EFAULT; | 869 | return -EFAULT; |
805 | pll_config |= (input_freq << MCS_SEL_IN_FREQ_SHIFT); | 870 | pll_config |= (input_freq << MCS_SEL_IN_FREQ_SHIFT); |
806 | pll_config |= MCS_PLL_ENABLE_HP; | 871 | pll_config |= MCS_PLL_ENABLE_HP; |
807 | wl12xx_top_reg_write(wl, MCS_PLL_CONFIG_REG, pll_config); | 872 | ret = wl12xx_top_reg_write(wl, MCS_PLL_CONFIG_REG, pll_config); |
808 | 873 | ||
809 | return 0; | 874 | return ret; |
810 | } | 875 | } |
811 | 876 | ||
812 | /* | 877 | /* |
@@ -820,6 +885,7 @@ static int wl128x_boot_clk(struct wl1271 *wl, int *selected_clock) | |||
820 | { | 885 | { |
821 | struct wl12xx_priv *priv = wl->priv; | 886 | struct wl12xx_priv *priv = wl->priv; |
822 | u16 sys_clk_cfg; | 887 | u16 sys_clk_cfg; |
888 | int ret; | ||
823 | 889 | ||
824 | /* For XTAL-only modes, FREF will be used after switching from TCXO */ | 890 | /* For XTAL-only modes, FREF will be used after switching from TCXO */ |
825 | if (priv->ref_clock == WL12XX_REFCLOCK_26_XTAL || | 891 | if (priv->ref_clock == WL12XX_REFCLOCK_26_XTAL || |
@@ -830,7 +896,10 @@ static int wl128x_boot_clk(struct wl1271 *wl, int *selected_clock) | |||
830 | } | 896 | } |
831 | 897 | ||
832 | /* Query the HW, to determine which clock source we should use */ | 898 | /* Query the HW, to determine which clock source we should use */ |
833 | sys_clk_cfg = wl12xx_top_reg_read(wl, SYS_CLK_CFG_REG); | 899 | ret = wl12xx_top_reg_read(wl, SYS_CLK_CFG_REG, &sys_clk_cfg); |
900 | if (ret < 0) | ||
901 | return ret; | ||
902 | |||
834 | if (sys_clk_cfg == 0xFFFF) | 903 | if (sys_clk_cfg == 0xFFFF) |
835 | return -EINVAL; | 904 | return -EINVAL; |
836 | if (sys_clk_cfg & PRCM_CM_EN_MUX_WLAN_FREF) | 905 | if (sys_clk_cfg & PRCM_CM_EN_MUX_WLAN_FREF) |
@@ -865,6 +934,7 @@ static int wl127x_boot_clk(struct wl1271 *wl) | |||
865 | struct wl12xx_priv *priv = wl->priv; | 934 | struct wl12xx_priv *priv = wl->priv; |
866 | u32 pause; | 935 | u32 pause; |
867 | u32 clk; | 936 | u32 clk; |
937 | int ret; | ||
868 | 938 | ||
869 | if (WL127X_PG_GET_MAJOR(wl->hw_pg_ver) < 3) | 939 | if (WL127X_PG_GET_MAJOR(wl->hw_pg_ver) < 3) |
870 | wl->quirks |= WLCORE_QUIRK_END_OF_TRANSACTION; | 940 | wl->quirks |= WLCORE_QUIRK_END_OF_TRANSACTION; |
@@ -885,48 +955,74 @@ static int wl127x_boot_clk(struct wl1271 *wl) | |||
885 | if (priv->ref_clock != CONF_REF_CLK_19_2_E) { | 955 | if (priv->ref_clock != CONF_REF_CLK_19_2_E) { |
886 | u16 val; | 956 | u16 val; |
887 | /* Set clock type (open drain) */ | 957 | /* Set clock type (open drain) */ |
888 | val = wl12xx_top_reg_read(wl, OCP_REG_CLK_TYPE); | 958 | ret = wl12xx_top_reg_read(wl, OCP_REG_CLK_TYPE, &val); |
959 | if (ret < 0) | ||
960 | goto out; | ||
961 | |||
889 | val &= FREF_CLK_TYPE_BITS; | 962 | val &= FREF_CLK_TYPE_BITS; |
890 | wl12xx_top_reg_write(wl, OCP_REG_CLK_TYPE, val); | 963 | ret = wl12xx_top_reg_write(wl, OCP_REG_CLK_TYPE, val); |
964 | if (ret < 0) | ||
965 | goto out; | ||
891 | 966 | ||
892 | /* Set clock pull mode (no pull) */ | 967 | /* Set clock pull mode (no pull) */ |
893 | val = wl12xx_top_reg_read(wl, OCP_REG_CLK_PULL); | 968 | ret = wl12xx_top_reg_read(wl, OCP_REG_CLK_PULL, &val); |
969 | if (ret < 0) | ||
970 | goto out; | ||
971 | |||
894 | val |= NO_PULL; | 972 | val |= NO_PULL; |
895 | wl12xx_top_reg_write(wl, OCP_REG_CLK_PULL, val); | 973 | ret = wl12xx_top_reg_write(wl, OCP_REG_CLK_PULL, val); |
974 | if (ret < 0) | ||
975 | goto out; | ||
896 | } else { | 976 | } else { |
897 | u16 val; | 977 | u16 val; |
898 | /* Set clock polarity */ | 978 | /* Set clock polarity */ |
899 | val = wl12xx_top_reg_read(wl, OCP_REG_CLK_POLARITY); | 979 | ret = wl12xx_top_reg_read(wl, OCP_REG_CLK_POLARITY, &val); |
980 | if (ret < 0) | ||
981 | goto out; | ||
982 | |||
900 | val &= FREF_CLK_POLARITY_BITS; | 983 | val &= FREF_CLK_POLARITY_BITS; |
901 | val |= CLK_REQ_OUTN_SEL; | 984 | val |= CLK_REQ_OUTN_SEL; |
902 | wl12xx_top_reg_write(wl, OCP_REG_CLK_POLARITY, val); | 985 | ret = wl12xx_top_reg_write(wl, OCP_REG_CLK_POLARITY, val); |
986 | if (ret < 0) | ||
987 | goto out; | ||
903 | } | 988 | } |
904 | 989 | ||
905 | wl1271_write32(wl, WL12XX_PLL_PARAMETERS, clk); | 990 | ret = wlcore_write32(wl, WL12XX_PLL_PARAMETERS, clk); |
991 | if (ret < 0) | ||
992 | goto out; | ||
906 | 993 | ||
907 | pause = wl1271_read32(wl, WL12XX_PLL_PARAMETERS); | 994 | ret = wlcore_read32(wl, WL12XX_PLL_PARAMETERS, &pause); |
995 | if (ret < 0) | ||
996 | goto out; | ||
908 | 997 | ||
909 | wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause); | 998 | wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause); |
910 | 999 | ||
911 | pause &= ~(WU_COUNTER_PAUSE_VAL); | 1000 | pause &= ~(WU_COUNTER_PAUSE_VAL); |
912 | pause |= WU_COUNTER_PAUSE_VAL; | 1001 | pause |= WU_COUNTER_PAUSE_VAL; |
913 | wl1271_write32(wl, WL12XX_WU_COUNTER_PAUSE, pause); | 1002 | ret = wlcore_write32(wl, WL12XX_WU_COUNTER_PAUSE, pause); |
914 | 1003 | ||
915 | return 0; | 1004 | out: |
1005 | return ret; | ||
916 | } | 1006 | } |
917 | 1007 | ||
918 | static int wl1271_boot_soft_reset(struct wl1271 *wl) | 1008 | static int wl1271_boot_soft_reset(struct wl1271 *wl) |
919 | { | 1009 | { |
920 | unsigned long timeout; | 1010 | unsigned long timeout; |
921 | u32 boot_data; | 1011 | u32 boot_data; |
1012 | int ret = 0; | ||
922 | 1013 | ||
923 | /* perform soft reset */ | 1014 | /* perform soft reset */ |
924 | wl1271_write32(wl, WL12XX_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT); | 1015 | ret = wlcore_write32(wl, WL12XX_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT); |
1016 | if (ret < 0) | ||
1017 | goto out; | ||
925 | 1018 | ||
926 | /* SOFT_RESET is self clearing */ | 1019 | /* SOFT_RESET is self clearing */ |
927 | timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME); | 1020 | timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME); |
928 | while (1) { | 1021 | while (1) { |
929 | boot_data = wl1271_read32(wl, WL12XX_SLV_SOFT_RESET); | 1022 | ret = wlcore_read32(wl, WL12XX_SLV_SOFT_RESET, &boot_data); |
1023 | if (ret < 0) | ||
1024 | goto out; | ||
1025 | |||
930 | wl1271_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data); | 1026 | wl1271_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data); |
931 | if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0) | 1027 | if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0) |
932 | break; | 1028 | break; |
@@ -942,12 +1038,15 @@ static int wl1271_boot_soft_reset(struct wl1271 *wl) | |||
942 | } | 1038 | } |
943 | 1039 | ||
944 | /* disable Rx/Tx */ | 1040 | /* disable Rx/Tx */ |
945 | wl1271_write32(wl, WL12XX_ENABLE, 0x0); | 1041 | ret = wlcore_write32(wl, WL12XX_ENABLE, 0x0); |
1042 | if (ret < 0) | ||
1043 | goto out; | ||
946 | 1044 | ||
947 | /* disable auto calibration on start*/ | 1045 | /* disable auto calibration on start*/ |
948 | wl1271_write32(wl, WL12XX_SPARE_A2, 0xffff); | 1046 | ret = wlcore_write32(wl, WL12XX_SPARE_A2, 0xffff); |
949 | 1047 | ||
950 | return 0; | 1048 | out: |
1049 | return ret; | ||
951 | } | 1050 | } |
952 | 1051 | ||
953 | static int wl12xx_pre_boot(struct wl1271 *wl) | 1052 | static int wl12xx_pre_boot(struct wl1271 *wl) |
@@ -968,16 +1067,23 @@ static int wl12xx_pre_boot(struct wl1271 *wl) | |||
968 | } | 1067 | } |
969 | 1068 | ||
970 | /* Continue the ELP wake up sequence */ | 1069 | /* Continue the ELP wake up sequence */ |
971 | wl1271_write32(wl, WL12XX_WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); | 1070 | ret = wlcore_write32(wl, WL12XX_WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); |
1071 | if (ret < 0) | ||
1072 | goto out; | ||
1073 | |||
972 | udelay(500); | 1074 | udelay(500); |
973 | 1075 | ||
974 | wlcore_set_partition(wl, &wl->ptable[PART_DRPW]); | 1076 | ret = wlcore_set_partition(wl, &wl->ptable[PART_DRPW]); |
1077 | if (ret < 0) | ||
1078 | goto out; | ||
975 | 1079 | ||
976 | /* Read-modify-write DRPW_SCRATCH_START register (see next state) | 1080 | /* Read-modify-write DRPW_SCRATCH_START register (see next state) |
977 | to be used by DRPw FW. The RTRIM value will be added by the FW | 1081 | to be used by DRPw FW. The RTRIM value will be added by the FW |
978 | before taking DRPw out of reset */ | 1082 | before taking DRPw out of reset */ |
979 | 1083 | ||
980 | clk = wl1271_read32(wl, WL12XX_DRPW_SCRATCH_START); | 1084 | ret = wlcore_read32(wl, WL12XX_DRPW_SCRATCH_START, &clk); |
1085 | if (ret < 0) | ||
1086 | goto out; | ||
981 | 1087 | ||
982 | wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk); | 1088 | wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk); |
983 | 1089 | ||
@@ -986,12 +1092,18 @@ static int wl12xx_pre_boot(struct wl1271 *wl) | |||
986 | else | 1092 | else |
987 | clk |= (priv->ref_clock << 1) << 4; | 1093 | clk |= (priv->ref_clock << 1) << 4; |
988 | 1094 | ||
989 | wl1271_write32(wl, WL12XX_DRPW_SCRATCH_START, clk); | 1095 | ret = wlcore_write32(wl, WL12XX_DRPW_SCRATCH_START, clk); |
1096 | if (ret < 0) | ||
1097 | goto out; | ||
990 | 1098 | ||
991 | wlcore_set_partition(wl, &wl->ptable[PART_WORK]); | 1099 | ret = wlcore_set_partition(wl, &wl->ptable[PART_WORK]); |
1100 | if (ret < 0) | ||
1101 | goto out; | ||
992 | 1102 | ||
993 | /* Disable interrupts */ | 1103 | /* Disable interrupts */ |
994 | wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); | 1104 | ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); |
1105 | if (ret < 0) | ||
1106 | goto out; | ||
995 | 1107 | ||
996 | ret = wl1271_boot_soft_reset(wl); | 1108 | ret = wl1271_boot_soft_reset(wl); |
997 | if (ret < 0) | 1109 | if (ret < 0) |
@@ -1001,47 +1113,72 @@ out: | |||
1001 | return ret; | 1113 | return ret; |
1002 | } | 1114 | } |
1003 | 1115 | ||
1004 | static void wl12xx_pre_upload(struct wl1271 *wl) | 1116 | static int wl12xx_pre_upload(struct wl1271 *wl) |
1005 | { | 1117 | { |
1006 | u32 tmp, polarity; | 1118 | u32 tmp; |
1119 | u16 polarity; | ||
1120 | int ret; | ||
1007 | 1121 | ||
1008 | /* write firmware's last address (ie. it's length) to | 1122 | /* write firmware's last address (ie. it's length) to |
1009 | * ACX_EEPROMLESS_IND_REG */ | 1123 | * ACX_EEPROMLESS_IND_REG */ |
1010 | wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG"); | 1124 | wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG"); |
1011 | 1125 | ||
1012 | wl1271_write32(wl, WL12XX_EEPROMLESS_IND, WL12XX_EEPROMLESS_IND); | 1126 | ret = wlcore_write32(wl, WL12XX_EEPROMLESS_IND, WL12XX_EEPROMLESS_IND); |
1127 | if (ret < 0) | ||
1128 | goto out; | ||
1013 | 1129 | ||
1014 | tmp = wlcore_read_reg(wl, REG_CHIP_ID_B); | 1130 | ret = wlcore_read_reg(wl, REG_CHIP_ID_B, &tmp); |
1131 | if (ret < 0) | ||
1132 | goto out; | ||
1015 | 1133 | ||
1016 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp); | 1134 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp); |
1017 | 1135 | ||
1018 | /* 6. read the EEPROM parameters */ | 1136 | /* 6. read the EEPROM parameters */ |
1019 | tmp = wl1271_read32(wl, WL12XX_SCR_PAD2); | 1137 | ret = wlcore_read32(wl, WL12XX_SCR_PAD2, &tmp); |
1138 | if (ret < 0) | ||
1139 | goto out; | ||
1020 | 1140 | ||
1021 | /* WL1271: The reference driver skips steps 7 to 10 (jumps directly | 1141 | /* WL1271: The reference driver skips steps 7 to 10 (jumps directly |
1022 | * to upload_fw) */ | 1142 | * to upload_fw) */ |
1023 | 1143 | ||
1024 | if (wl->chip.id == CHIP_ID_1283_PG20) | 1144 | if (wl->chip.id == CHIP_ID_1283_PG20) { |
1025 | wl12xx_top_reg_write(wl, SDIO_IO_DS, HCI_IO_DS_6MA); | 1145 | ret = wl12xx_top_reg_write(wl, SDIO_IO_DS, HCI_IO_DS_6MA); |
1146 | if (ret < 0) | ||
1147 | goto out; | ||
1148 | } | ||
1026 | 1149 | ||
1027 | /* polarity must be set before the firmware is loaded */ | 1150 | /* polarity must be set before the firmware is loaded */ |
1028 | polarity = wl12xx_top_reg_read(wl, OCP_REG_POLARITY); | 1151 | ret = wl12xx_top_reg_read(wl, OCP_REG_POLARITY, &polarity); |
1152 | if (ret < 0) | ||
1153 | goto out; | ||
1029 | 1154 | ||
1030 | /* We use HIGH polarity, so unset the LOW bit */ | 1155 | /* We use HIGH polarity, so unset the LOW bit */ |
1031 | polarity &= ~POLARITY_LOW; | 1156 | polarity &= ~POLARITY_LOW; |
1032 | wl12xx_top_reg_write(wl, OCP_REG_POLARITY, polarity); | 1157 | ret = wl12xx_top_reg_write(wl, OCP_REG_POLARITY, polarity); |
1033 | 1158 | ||
1159 | out: | ||
1160 | return ret; | ||
1034 | } | 1161 | } |
1035 | 1162 | ||
1036 | static void wl12xx_enable_interrupts(struct wl1271 *wl) | 1163 | static int wl12xx_enable_interrupts(struct wl1271 *wl) |
1037 | { | 1164 | { |
1038 | wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL12XX_ACX_ALL_EVENTS_VECTOR); | 1165 | int ret; |
1166 | |||
1167 | ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK, | ||
1168 | WL12XX_ACX_ALL_EVENTS_VECTOR); | ||
1169 | if (ret < 0) | ||
1170 | goto out; | ||
1039 | 1171 | ||
1040 | wlcore_enable_interrupts(wl); | 1172 | wlcore_enable_interrupts(wl); |
1041 | wlcore_write_reg(wl, REG_INTERRUPT_MASK, | 1173 | ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK, |
1042 | WL1271_ACX_INTR_ALL & ~(WL12XX_INTR_MASK)); | 1174 | WL1271_ACX_INTR_ALL & ~(WL12XX_INTR_MASK)); |
1175 | if (ret < 0) | ||
1176 | goto out; | ||
1043 | 1177 | ||
1044 | wl1271_write32(wl, WL12XX_HI_CFG, HI_CFG_DEF_VAL); | 1178 | ret = wlcore_write32(wl, WL12XX_HI_CFG, HI_CFG_DEF_VAL); |
1179 | |||
1180 | out: | ||
1181 | return ret; | ||
1045 | } | 1182 | } |
1046 | 1183 | ||
1047 | static int wl12xx_boot(struct wl1271 *wl) | 1184 | static int wl12xx_boot(struct wl1271 *wl) |
@@ -1056,7 +1193,9 @@ static int wl12xx_boot(struct wl1271 *wl) | |||
1056 | if (ret < 0) | 1193 | if (ret < 0) |
1057 | goto out; | 1194 | goto out; |
1058 | 1195 | ||
1059 | wl12xx_pre_upload(wl); | 1196 | ret = wl12xx_pre_upload(wl); |
1197 | if (ret < 0) | ||
1198 | goto out; | ||
1060 | 1199 | ||
1061 | ret = wlcore_boot_upload_firmware(wl); | 1200 | ret = wlcore_boot_upload_firmware(wl); |
1062 | if (ret < 0) | 1201 | if (ret < 0) |
@@ -1066,22 +1205,30 @@ static int wl12xx_boot(struct wl1271 *wl) | |||
1066 | if (ret < 0) | 1205 | if (ret < 0) |
1067 | goto out; | 1206 | goto out; |
1068 | 1207 | ||
1069 | wl12xx_enable_interrupts(wl); | 1208 | ret = wl12xx_enable_interrupts(wl); |
1070 | 1209 | ||
1071 | out: | 1210 | out: |
1072 | return ret; | 1211 | return ret; |
1073 | } | 1212 | } |
1074 | 1213 | ||
1075 | static void wl12xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr, | 1214 | static int wl12xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr, |
1076 | void *buf, size_t len) | 1215 | void *buf, size_t len) |
1077 | { | 1216 | { |
1078 | wl1271_write(wl, cmd_box_addr, buf, len, false); | 1217 | int ret; |
1079 | wlcore_write_reg(wl, REG_INTERRUPT_TRIG, WL12XX_INTR_TRIG_CMD); | 1218 | |
1219 | ret = wlcore_write(wl, cmd_box_addr, buf, len, false); | ||
1220 | if (ret < 0) | ||
1221 | return ret; | ||
1222 | |||
1223 | ret = wlcore_write_reg(wl, REG_INTERRUPT_TRIG, WL12XX_INTR_TRIG_CMD); | ||
1224 | |||
1225 | return ret; | ||
1080 | } | 1226 | } |
1081 | 1227 | ||
1082 | static void wl12xx_ack_event(struct wl1271 *wl) | 1228 | static int wl12xx_ack_event(struct wl1271 *wl) |
1083 | { | 1229 | { |
1084 | wlcore_write_reg(wl, REG_INTERRUPT_TRIG, WL12XX_INTR_TRIG_EVENT_ACK); | 1230 | return wlcore_write_reg(wl, REG_INTERRUPT_TRIG, |
1231 | WL12XX_INTR_TRIG_EVENT_ACK); | ||
1085 | } | 1232 | } |
1086 | 1233 | ||
1087 | static u32 wl12xx_calc_tx_blocks(struct wl1271 *wl, u32 len, u32 spare_blks) | 1234 | static u32 wl12xx_calc_tx_blocks(struct wl1271 *wl, u32 len, u32 spare_blks) |
@@ -1161,13 +1308,13 @@ static u32 wl12xx_get_rx_packet_len(struct wl1271 *wl, void *rx_data, | |||
1161 | return data_len - sizeof(*desc) - desc->pad_len; | 1308 | return data_len - sizeof(*desc) - desc->pad_len; |
1162 | } | 1309 | } |
1163 | 1310 | ||
1164 | static void wl12xx_tx_delayed_compl(struct wl1271 *wl) | 1311 | static int wl12xx_tx_delayed_compl(struct wl1271 *wl) |
1165 | { | 1312 | { |
1166 | if (wl->fw_status_1->tx_results_counter == | 1313 | if (wl->fw_status_1->tx_results_counter == |
1167 | (wl->tx_results_count & 0xff)) | 1314 | (wl->tx_results_count & 0xff)) |
1168 | return; | 1315 | return 0; |
1169 | 1316 | ||
1170 | wl1271_tx_complete(wl); | 1317 | return wlcore_tx_complete(wl); |
1171 | } | 1318 | } |
1172 | 1319 | ||
1173 | static int wl12xx_hw_init(struct wl1271 *wl) | 1320 | static int wl12xx_hw_init(struct wl1271 *wl) |
@@ -1268,39 +1415,58 @@ static bool wl12xx_mac_in_fuse(struct wl1271 *wl) | |||
1268 | return supported; | 1415 | return supported; |
1269 | } | 1416 | } |
1270 | 1417 | ||
1271 | static void wl12xx_get_fuse_mac(struct wl1271 *wl) | 1418 | static int wl12xx_get_fuse_mac(struct wl1271 *wl) |
1272 | { | 1419 | { |
1273 | u32 mac1, mac2; | 1420 | u32 mac1, mac2; |
1421 | int ret; | ||
1274 | 1422 | ||
1275 | wlcore_set_partition(wl, &wl->ptable[PART_DRPW]); | 1423 | ret = wlcore_set_partition(wl, &wl->ptable[PART_DRPW]); |
1424 | if (ret < 0) | ||
1425 | goto out; | ||
1276 | 1426 | ||
1277 | mac1 = wl1271_read32(wl, WL12XX_REG_FUSE_BD_ADDR_1); | 1427 | ret = wlcore_read32(wl, WL12XX_REG_FUSE_BD_ADDR_1, &mac1); |
1278 | mac2 = wl1271_read32(wl, WL12XX_REG_FUSE_BD_ADDR_2); | 1428 | if (ret < 0) |
1429 | goto out; | ||
1430 | |||
1431 | ret = wlcore_read32(wl, WL12XX_REG_FUSE_BD_ADDR_2, &mac2); | ||
1432 | if (ret < 0) | ||
1433 | goto out; | ||
1279 | 1434 | ||
1280 | /* these are the two parts of the BD_ADDR */ | 1435 | /* these are the two parts of the BD_ADDR */ |
1281 | wl->fuse_oui_addr = ((mac2 & 0xffff) << 8) + | 1436 | wl->fuse_oui_addr = ((mac2 & 0xffff) << 8) + |
1282 | ((mac1 & 0xff000000) >> 24); | 1437 | ((mac1 & 0xff000000) >> 24); |
1283 | wl->fuse_nic_addr = mac1 & 0xffffff; | 1438 | wl->fuse_nic_addr = mac1 & 0xffffff; |
1284 | 1439 | ||
1285 | wlcore_set_partition(wl, &wl->ptable[PART_DOWN]); | 1440 | ret = wlcore_set_partition(wl, &wl->ptable[PART_DOWN]); |
1441 | |||
1442 | out: | ||
1443 | return ret; | ||
1286 | } | 1444 | } |
1287 | 1445 | ||
1288 | static s8 wl12xx_get_pg_ver(struct wl1271 *wl) | 1446 | static int wl12xx_get_pg_ver(struct wl1271 *wl, s8 *ver) |
1289 | { | 1447 | { |
1290 | u32 die_info; | 1448 | u16 die_info; |
1449 | int ret; | ||
1291 | 1450 | ||
1292 | if (wl->chip.id == CHIP_ID_1283_PG20) | 1451 | if (wl->chip.id == CHIP_ID_1283_PG20) |
1293 | die_info = wl12xx_top_reg_read(wl, WL128X_REG_FUSE_DATA_2_1); | 1452 | ret = wl12xx_top_reg_read(wl, WL128X_REG_FUSE_DATA_2_1, |
1453 | &die_info); | ||
1294 | else | 1454 | else |
1295 | die_info = wl12xx_top_reg_read(wl, WL127X_REG_FUSE_DATA_2_1); | 1455 | ret = wl12xx_top_reg_read(wl, WL127X_REG_FUSE_DATA_2_1, |
1456 | &die_info); | ||
1296 | 1457 | ||
1297 | return (s8) (die_info & PG_VER_MASK) >> PG_VER_OFFSET; | 1458 | if (ret >= 0 && ver) |
1459 | *ver = (s8)((die_info & PG_VER_MASK) >> PG_VER_OFFSET); | ||
1460 | |||
1461 | return ret; | ||
1298 | } | 1462 | } |
1299 | 1463 | ||
1300 | static void wl12xx_get_mac(struct wl1271 *wl) | 1464 | static int wl12xx_get_mac(struct wl1271 *wl) |
1301 | { | 1465 | { |
1302 | if (wl12xx_mac_in_fuse(wl)) | 1466 | if (wl12xx_mac_in_fuse(wl)) |
1303 | wl12xx_get_fuse_mac(wl); | 1467 | return wl12xx_get_fuse_mac(wl); |
1468 | |||
1469 | return 0; | ||
1304 | } | 1470 | } |
1305 | 1471 | ||
1306 | static void wl12xx_set_tx_desc_csum(struct wl1271 *wl, | 1472 | static void wl12xx_set_tx_desc_csum(struct wl1271 *wl, |
@@ -1448,10 +1614,8 @@ static int __devinit wl12xx_probe(struct platform_device *pdev) | |||
1448 | wl->hw_min_ht_rate = WL12XX_CONF_HW_RXTX_RATE_MCS0; | 1614 | wl->hw_min_ht_rate = WL12XX_CONF_HW_RXTX_RATE_MCS0; |
1449 | wl->fw_status_priv_len = 0; | 1615 | wl->fw_status_priv_len = 0; |
1450 | wl->stats.fw_stats_len = sizeof(struct wl12xx_acx_statistics); | 1616 | wl->stats.fw_stats_len = sizeof(struct wl12xx_acx_statistics); |
1451 | memcpy(&wl->ht_cap[IEEE80211_BAND_2GHZ], &wl12xx_ht_cap, | 1617 | wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ, &wl12xx_ht_cap); |
1452 | sizeof(wl12xx_ht_cap)); | 1618 | wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ, &wl12xx_ht_cap); |
1453 | memcpy(&wl->ht_cap[IEEE80211_BAND_5GHZ], &wl12xx_ht_cap, | ||
1454 | sizeof(wl12xx_ht_cap)); | ||
1455 | wl12xx_conf_init(wl); | 1619 | wl12xx_conf_init(wl); |
1456 | 1620 | ||
1457 | if (!fref_param) { | 1621 | if (!fref_param) { |
diff --git a/drivers/net/wireless/ti/wl18xx/acx.h b/drivers/net/wireless/ti/wl18xx/acx.h index ebbaf611e97..e2609a6b734 100644 --- a/drivers/net/wireless/ti/wl18xx/acx.h +++ b/drivers/net/wireless/ti/wl18xx/acx.h | |||
@@ -32,25 +32,21 @@ enum { | |||
32 | /* numbers of bits the length field takes (add 1 for the actual number) */ | 32 | /* numbers of bits the length field takes (add 1 for the actual number) */ |
33 | #define WL18XX_HOST_IF_LEN_SIZE_FIELD 15 | 33 | #define WL18XX_HOST_IF_LEN_SIZE_FIELD 15 |
34 | 34 | ||
35 | #define WL18XX_ACX_EVENTS_VECTOR_PG1 (WL1271_ACX_INTR_WATCHDOG | \ | 35 | #define WL18XX_ACX_EVENTS_VECTOR (WL1271_ACX_INTR_WATCHDOG | \ |
36 | WL1271_ACX_INTR_INIT_COMPLETE | \ | 36 | WL1271_ACX_INTR_INIT_COMPLETE | \ |
37 | WL1271_ACX_INTR_EVENT_A | \ | 37 | WL1271_ACX_INTR_EVENT_A | \ |
38 | WL1271_ACX_INTR_EVENT_B | \ | 38 | WL1271_ACX_INTR_EVENT_B | \ |
39 | WL1271_ACX_INTR_CMD_COMPLETE | \ | 39 | WL1271_ACX_INTR_CMD_COMPLETE | \ |
40 | WL1271_ACX_INTR_HW_AVAILABLE | \ | 40 | WL1271_ACX_INTR_HW_AVAILABLE | \ |
41 | WL1271_ACX_INTR_DATA) | 41 | WL1271_ACX_INTR_DATA | \ |
42 | 42 | WL1271_ACX_SW_INTR_WATCHDOG) | |
43 | #define WL18XX_ACX_EVENTS_VECTOR_PG2 (WL18XX_ACX_EVENTS_VECTOR_PG1 | \ | 43 | |
44 | WL1271_ACX_SW_INTR_WATCHDOG) | 44 | #define WL18XX_INTR_MASK (WL1271_ACX_INTR_WATCHDOG | \ |
45 | 45 | WL1271_ACX_INTR_EVENT_A | \ | |
46 | #define WL18XX_INTR_MASK_PG1 (WL1271_ACX_INTR_WATCHDOG | \ | 46 | WL1271_ACX_INTR_EVENT_B | \ |
47 | WL1271_ACX_INTR_EVENT_A | \ | 47 | WL1271_ACX_INTR_HW_AVAILABLE | \ |
48 | WL1271_ACX_INTR_EVENT_B | \ | 48 | WL1271_ACX_INTR_DATA | \ |
49 | WL1271_ACX_INTR_HW_AVAILABLE | \ | 49 | WL1271_ACX_SW_INTR_WATCHDOG) |
50 | WL1271_ACX_INTR_DATA) | ||
51 | |||
52 | #define WL18XX_INTR_MASK_PG2 (WL18XX_INTR_MASK_PG1 | \ | ||
53 | WL1271_ACX_SW_INTR_WATCHDOG) | ||
54 | 50 | ||
55 | struct wl18xx_acx_host_config_bitmap { | 51 | struct wl18xx_acx_host_config_bitmap { |
56 | struct acx_header header; | 52 | struct acx_header header; |
diff --git a/drivers/net/wireless/ti/wl18xx/io.c b/drivers/net/wireless/ti/wl18xx/io.c index 598c057e722..0c06ccfd1b8 100644 --- a/drivers/net/wireless/ti/wl18xx/io.c +++ b/drivers/net/wireless/ti/wl18xx/io.c | |||
@@ -24,37 +24,52 @@ | |||
24 | 24 | ||
25 | #include "io.h" | 25 | #include "io.h" |
26 | 26 | ||
27 | void wl18xx_top_reg_write(struct wl1271 *wl, int addr, u16 val) | 27 | int wl18xx_top_reg_write(struct wl1271 *wl, int addr, u16 val) |
28 | { | 28 | { |
29 | u32 tmp; | 29 | u32 tmp; |
30 | int ret; | ||
30 | 31 | ||
31 | if (WARN_ON(addr % 2)) | 32 | if (WARN_ON(addr % 2)) |
32 | return; | 33 | return -EINVAL; |
33 | 34 | ||
34 | if ((addr % 4) == 0) { | 35 | if ((addr % 4) == 0) { |
35 | tmp = wl1271_read32(wl, addr); | 36 | ret = wlcore_read32(wl, addr, &tmp); |
37 | if (ret < 0) | ||
38 | goto out; | ||
39 | |||
36 | tmp = (tmp & 0xffff0000) | val; | 40 | tmp = (tmp & 0xffff0000) | val; |
37 | wl1271_write32(wl, addr, tmp); | 41 | ret = wlcore_write32(wl, addr, tmp); |
38 | } else { | 42 | } else { |
39 | tmp = wl1271_read32(wl, addr - 2); | 43 | ret = wlcore_read32(wl, addr - 2, &tmp); |
44 | if (ret < 0) | ||
45 | goto out; | ||
46 | |||
40 | tmp = (tmp & 0xffff) | (val << 16); | 47 | tmp = (tmp & 0xffff) | (val << 16); |
41 | wl1271_write32(wl, addr - 2, tmp); | 48 | ret = wlcore_write32(wl, addr - 2, tmp); |
42 | } | 49 | } |
50 | |||
51 | out: | ||
52 | return ret; | ||
43 | } | 53 | } |
44 | 54 | ||
45 | u16 wl18xx_top_reg_read(struct wl1271 *wl, int addr) | 55 | int wl18xx_top_reg_read(struct wl1271 *wl, int addr, u16 *out) |
46 | { | 56 | { |
47 | u32 val; | 57 | u32 val; |
58 | int ret; | ||
48 | 59 | ||
49 | if (WARN_ON(addr % 2)) | 60 | if (WARN_ON(addr % 2)) |
50 | return 0; | 61 | return -EINVAL; |
51 | 62 | ||
52 | if ((addr % 4) == 0) { | 63 | if ((addr % 4) == 0) { |
53 | /* address is 4-bytes aligned */ | 64 | /* address is 4-bytes aligned */ |
54 | val = wl1271_read32(wl, addr); | 65 | ret = wlcore_read32(wl, addr, &val); |
55 | return val & 0xffff; | 66 | if (ret >= 0 && out) |
67 | *out = val & 0xffff; | ||
56 | } else { | 68 | } else { |
57 | val = wl1271_read32(wl, addr - 2); | 69 | ret = wlcore_read32(wl, addr - 2, &val); |
58 | return (val & 0xffff0000) >> 16; | 70 | if (ret >= 0 && out) |
71 | *out = (val & 0xffff0000) >> 16; | ||
59 | } | 72 | } |
73 | |||
74 | return ret; | ||
60 | } | 75 | } |
diff --git a/drivers/net/wireless/ti/wl18xx/io.h b/drivers/net/wireless/ti/wl18xx/io.h index be4e126ff61..c32ae30277d 100644 --- a/drivers/net/wireless/ti/wl18xx/io.h +++ b/drivers/net/wireless/ti/wl18xx/io.h | |||
@@ -22,7 +22,7 @@ | |||
22 | #ifndef __WL18XX_IO_H__ | 22 | #ifndef __WL18XX_IO_H__ |
23 | #define __WL18XX_IO_H__ | 23 | #define __WL18XX_IO_H__ |
24 | 24 | ||
25 | void wl18xx_top_reg_write(struct wl1271 *wl, int addr, u16 val); | 25 | int __must_check wl18xx_top_reg_write(struct wl1271 *wl, int addr, u16 val); |
26 | u16 wl18xx_top_reg_read(struct wl1271 *wl, int addr); | 26 | int __must_check wl18xx_top_reg_read(struct wl1271 *wl, int addr, u16 *out); |
27 | 27 | ||
28 | #endif /* __WL18XX_IO_H__ */ | 28 | #endif /* __WL18XX_IO_H__ */ |
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c index ed9c3650e08..5e583be8f67 100644 --- a/drivers/net/wireless/ti/wl18xx/main.c +++ b/drivers/net/wireless/ti/wl18xx/main.c | |||
@@ -43,10 +43,11 @@ | |||
43 | 43 | ||
44 | #define WL18XX_RX_CHECKSUM_MASK 0x40 | 44 | #define WL18XX_RX_CHECKSUM_MASK 0x40 |
45 | 45 | ||
46 | static char *ht_mode_param = "wide"; | 46 | static char *ht_mode_param = "default"; |
47 | static char *board_type_param = "hdk"; | 47 | static char *board_type_param = "hdk"; |
48 | static bool checksum_param = false; | 48 | static bool checksum_param = false; |
49 | static bool enable_11a_param = true; | 49 | static bool enable_11a_param = true; |
50 | static int num_rx_desc_param = -1; | ||
50 | 51 | ||
51 | /* phy paramters */ | 52 | /* phy paramters */ |
52 | static int dc2dc_param = -1; | 53 | static int dc2dc_param = -1; |
@@ -372,6 +373,7 @@ static struct wlcore_conf wl18xx_conf = { | |||
372 | .forced_ps = false, | 373 | .forced_ps = false, |
373 | .keep_alive_interval = 55000, | 374 | .keep_alive_interval = 55000, |
374 | .max_listen_interval = 20, | 375 | .max_listen_interval = 20, |
376 | .sta_sleep_auth = WL1271_PSM_ILLEGAL, | ||
375 | }, | 377 | }, |
376 | .itrim = { | 378 | .itrim = { |
377 | .enable = false, | 379 | .enable = false, |
@@ -606,24 +608,15 @@ static int wl18xx_identify_chip(struct wl1271 *wl) | |||
606 | wl->plt_fw_name = WL18XX_FW_NAME; | 608 | wl->plt_fw_name = WL18XX_FW_NAME; |
607 | wl->quirks |= WLCORE_QUIRK_NO_ELP | | 609 | wl->quirks |= WLCORE_QUIRK_NO_ELP | |
608 | WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN | | 610 | WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN | |
611 | WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN | | ||
609 | WLCORE_QUIRK_TX_PAD_LAST_FRAME; | 612 | WLCORE_QUIRK_TX_PAD_LAST_FRAME; |
610 | |||
611 | break; | 613 | break; |
612 | case CHIP_ID_185x_PG10: | 614 | case CHIP_ID_185x_PG10: |
613 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (185x PG10)", | 615 | wl1271_warning("chip id 0x%x (185x PG10) is deprecated", |
614 | wl->chip.id); | 616 | wl->chip.id); |
615 | wl->sr_fw_name = WL18XX_FW_NAME; | 617 | ret = -ENODEV; |
616 | /* wl18xx uses the same firmware for PLT */ | 618 | goto out; |
617 | wl->plt_fw_name = WL18XX_FW_NAME; | ||
618 | wl->quirks |= WLCORE_QUIRK_NO_ELP | | ||
619 | WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED | | ||
620 | WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN | | ||
621 | WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN; | ||
622 | |||
623 | /* PG 1.0 has some problems with MCS_13, so disable it */ | ||
624 | wl->ht_cap[IEEE80211_BAND_2GHZ].mcs.rx_mask[1] &= ~BIT(5); | ||
625 | 619 | ||
626 | break; | ||
627 | default: | 620 | default: |
628 | wl1271_warning("unsupported chip id: 0x%x", wl->chip.id); | 621 | wl1271_warning("unsupported chip id: 0x%x", wl->chip.id); |
629 | ret = -ENODEV; | 622 | ret = -ENODEV; |
@@ -634,123 +627,178 @@ out: | |||
634 | return ret; | 627 | return ret; |
635 | } | 628 | } |
636 | 629 | ||
637 | static void wl18xx_set_clk(struct wl1271 *wl) | 630 | static int wl18xx_set_clk(struct wl1271 *wl) |
638 | { | 631 | { |
639 | u32 clk_freq; | 632 | u16 clk_freq; |
633 | int ret; | ||
640 | 634 | ||
641 | wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]); | 635 | ret = wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]); |
636 | if (ret < 0) | ||
637 | goto out; | ||
642 | 638 | ||
643 | /* TODO: PG2: apparently we need to read the clk type */ | 639 | /* TODO: PG2: apparently we need to read the clk type */ |
644 | 640 | ||
645 | clk_freq = wl18xx_top_reg_read(wl, PRIMARY_CLK_DETECT); | 641 | ret = wl18xx_top_reg_read(wl, PRIMARY_CLK_DETECT, &clk_freq); |
642 | if (ret < 0) | ||
643 | goto out; | ||
644 | |||
646 | wl1271_debug(DEBUG_BOOT, "clock freq %d (%d, %d, %d, %d, %s)", clk_freq, | 645 | wl1271_debug(DEBUG_BOOT, "clock freq %d (%d, %d, %d, %d, %s)", clk_freq, |
647 | wl18xx_clk_table[clk_freq].n, wl18xx_clk_table[clk_freq].m, | 646 | wl18xx_clk_table[clk_freq].n, wl18xx_clk_table[clk_freq].m, |
648 | wl18xx_clk_table[clk_freq].p, wl18xx_clk_table[clk_freq].q, | 647 | wl18xx_clk_table[clk_freq].p, wl18xx_clk_table[clk_freq].q, |
649 | wl18xx_clk_table[clk_freq].swallow ? "swallow" : "spit"); | 648 | wl18xx_clk_table[clk_freq].swallow ? "swallow" : "spit"); |
650 | 649 | ||
651 | wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_N, wl18xx_clk_table[clk_freq].n); | 650 | ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_N, |
652 | wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_M, wl18xx_clk_table[clk_freq].m); | 651 | wl18xx_clk_table[clk_freq].n); |
652 | if (ret < 0) | ||
653 | goto out; | ||
654 | |||
655 | ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_M, | ||
656 | wl18xx_clk_table[clk_freq].m); | ||
657 | if (ret < 0) | ||
658 | goto out; | ||
653 | 659 | ||
654 | if (wl18xx_clk_table[clk_freq].swallow) { | 660 | if (wl18xx_clk_table[clk_freq].swallow) { |
655 | /* first the 16 lower bits */ | 661 | /* first the 16 lower bits */ |
656 | wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_Q_FACTOR_CFG_1, | 662 | ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_Q_FACTOR_CFG_1, |
657 | wl18xx_clk_table[clk_freq].q & | 663 | wl18xx_clk_table[clk_freq].q & |
658 | PLLSH_WCS_PLL_Q_FACTOR_CFG_1_MASK); | 664 | PLLSH_WCS_PLL_Q_FACTOR_CFG_1_MASK); |
665 | if (ret < 0) | ||
666 | goto out; | ||
667 | |||
659 | /* then the 16 higher bits, masked out */ | 668 | /* then the 16 higher bits, masked out */ |
660 | wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_Q_FACTOR_CFG_2, | 669 | ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_Q_FACTOR_CFG_2, |
661 | (wl18xx_clk_table[clk_freq].q >> 16) & | 670 | (wl18xx_clk_table[clk_freq].q >> 16) & |
662 | PLLSH_WCS_PLL_Q_FACTOR_CFG_2_MASK); | 671 | PLLSH_WCS_PLL_Q_FACTOR_CFG_2_MASK); |
672 | if (ret < 0) | ||
673 | goto out; | ||
663 | 674 | ||
664 | /* first the 16 lower bits */ | 675 | /* first the 16 lower bits */ |
665 | wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_P_FACTOR_CFG_1, | 676 | ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_P_FACTOR_CFG_1, |
666 | wl18xx_clk_table[clk_freq].p & | 677 | wl18xx_clk_table[clk_freq].p & |
667 | PLLSH_WCS_PLL_P_FACTOR_CFG_1_MASK); | 678 | PLLSH_WCS_PLL_P_FACTOR_CFG_1_MASK); |
679 | if (ret < 0) | ||
680 | goto out; | ||
681 | |||
668 | /* then the 16 higher bits, masked out */ | 682 | /* then the 16 higher bits, masked out */ |
669 | wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_P_FACTOR_CFG_2, | 683 | ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_P_FACTOR_CFG_2, |
670 | (wl18xx_clk_table[clk_freq].p >> 16) & | 684 | (wl18xx_clk_table[clk_freq].p >> 16) & |
671 | PLLSH_WCS_PLL_P_FACTOR_CFG_2_MASK); | 685 | PLLSH_WCS_PLL_P_FACTOR_CFG_2_MASK); |
672 | } else { | 686 | } else { |
673 | wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_SWALLOW_EN, | 687 | ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_SWALLOW_EN, |
674 | PLLSH_WCS_PLL_SWALLOW_EN_VAL2); | 688 | PLLSH_WCS_PLL_SWALLOW_EN_VAL2); |
675 | } | 689 | } |
690 | |||
691 | out: | ||
692 | return ret; | ||
676 | } | 693 | } |
677 | 694 | ||
678 | static void wl18xx_boot_soft_reset(struct wl1271 *wl) | 695 | static int wl18xx_boot_soft_reset(struct wl1271 *wl) |
679 | { | 696 | { |
697 | int ret; | ||
698 | |||
680 | /* disable Rx/Tx */ | 699 | /* disable Rx/Tx */ |
681 | wl1271_write32(wl, WL18XX_ENABLE, 0x0); | 700 | ret = wlcore_write32(wl, WL18XX_ENABLE, 0x0); |
701 | if (ret < 0) | ||
702 | goto out; | ||
682 | 703 | ||
683 | /* disable auto calibration on start*/ | 704 | /* disable auto calibration on start*/ |
684 | wl1271_write32(wl, WL18XX_SPARE_A2, 0xffff); | 705 | ret = wlcore_write32(wl, WL18XX_SPARE_A2, 0xffff); |
706 | |||
707 | out: | ||
708 | return ret; | ||
685 | } | 709 | } |
686 | 710 | ||
687 | static int wl18xx_pre_boot(struct wl1271 *wl) | 711 | static int wl18xx_pre_boot(struct wl1271 *wl) |
688 | { | 712 | { |
689 | wl18xx_set_clk(wl); | 713 | int ret; |
714 | |||
715 | ret = wl18xx_set_clk(wl); | ||
716 | if (ret < 0) | ||
717 | goto out; | ||
690 | 718 | ||
691 | /* Continue the ELP wake up sequence */ | 719 | /* Continue the ELP wake up sequence */ |
692 | wl1271_write32(wl, WL18XX_WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); | 720 | ret = wlcore_write32(wl, WL18XX_WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); |
721 | if (ret < 0) | ||
722 | goto out; | ||
723 | |||
693 | udelay(500); | 724 | udelay(500); |
694 | 725 | ||
695 | wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); | 726 | ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); |
727 | if (ret < 0) | ||
728 | goto out; | ||
696 | 729 | ||
697 | /* Disable interrupts */ | 730 | /* Disable interrupts */ |
698 | wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); | 731 | ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); |
732 | if (ret < 0) | ||
733 | goto out; | ||
699 | 734 | ||
700 | wl18xx_boot_soft_reset(wl); | 735 | ret = wl18xx_boot_soft_reset(wl); |
701 | 736 | ||
702 | return 0; | 737 | out: |
738 | return ret; | ||
703 | } | 739 | } |
704 | 740 | ||
705 | static void wl18xx_pre_upload(struct wl1271 *wl) | 741 | static int wl18xx_pre_upload(struct wl1271 *wl) |
706 | { | 742 | { |
707 | u32 tmp; | 743 | u32 tmp; |
744 | int ret; | ||
708 | 745 | ||
709 | wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); | 746 | ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); |
747 | if (ret < 0) | ||
748 | goto out; | ||
710 | 749 | ||
711 | /* TODO: check if this is all needed */ | 750 | /* TODO: check if this is all needed */ |
712 | wl1271_write32(wl, WL18XX_EEPROMLESS_IND, WL18XX_EEPROMLESS_IND); | 751 | ret = wlcore_write32(wl, WL18XX_EEPROMLESS_IND, WL18XX_EEPROMLESS_IND); |
752 | if (ret < 0) | ||
753 | goto out; | ||
713 | 754 | ||
714 | tmp = wlcore_read_reg(wl, REG_CHIP_ID_B); | 755 | ret = wlcore_read_reg(wl, REG_CHIP_ID_B, &tmp); |
756 | if (ret < 0) | ||
757 | goto out; | ||
715 | 758 | ||
716 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp); | 759 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp); |
717 | 760 | ||
718 | tmp = wl1271_read32(wl, WL18XX_SCR_PAD2); | 761 | ret = wlcore_read32(wl, WL18XX_SCR_PAD2, &tmp); |
762 | |||
763 | out: | ||
764 | return ret; | ||
719 | } | 765 | } |
720 | 766 | ||
721 | static void wl18xx_set_mac_and_phy(struct wl1271 *wl) | 767 | static int wl18xx_set_mac_and_phy(struct wl1271 *wl) |
722 | { | 768 | { |
723 | struct wl18xx_priv *priv = wl->priv; | 769 | struct wl18xx_priv *priv = wl->priv; |
724 | size_t len; | 770 | int ret; |
725 | 771 | ||
726 | /* the parameters struct is smaller for PG1 */ | 772 | ret = wlcore_set_partition(wl, &wl->ptable[PART_PHY_INIT]); |
727 | if (wl->chip.id == CHIP_ID_185x_PG10) | 773 | if (ret < 0) |
728 | len = offsetof(struct wl18xx_mac_and_phy_params, psat) + 1; | 774 | goto out; |
729 | else | 775 | |
730 | len = sizeof(struct wl18xx_mac_and_phy_params); | 776 | ret = wlcore_write(wl, WL18XX_PHY_INIT_MEM_ADDR, (u8 *)&priv->conf.phy, |
777 | sizeof(struct wl18xx_mac_and_phy_params), false); | ||
731 | 778 | ||
732 | wlcore_set_partition(wl, &wl->ptable[PART_PHY_INIT]); | 779 | out: |
733 | wl1271_write(wl, WL18XX_PHY_INIT_MEM_ADDR, (u8 *)&priv->conf.phy, len, | 780 | return ret; |
734 | false); | ||
735 | } | 781 | } |
736 | 782 | ||
737 | static void wl18xx_enable_interrupts(struct wl1271 *wl) | 783 | static int wl18xx_enable_interrupts(struct wl1271 *wl) |
738 | { | 784 | { |
739 | u32 event_mask, intr_mask; | 785 | u32 event_mask, intr_mask; |
786 | int ret; | ||
740 | 787 | ||
741 | if (wl->chip.id == CHIP_ID_185x_PG10) { | 788 | event_mask = WL18XX_ACX_EVENTS_VECTOR; |
742 | event_mask = WL18XX_ACX_EVENTS_VECTOR_PG1; | 789 | intr_mask = WL18XX_INTR_MASK; |
743 | intr_mask = WL18XX_INTR_MASK_PG1; | ||
744 | } else { | ||
745 | event_mask = WL18XX_ACX_EVENTS_VECTOR_PG2; | ||
746 | intr_mask = WL18XX_INTR_MASK_PG2; | ||
747 | } | ||
748 | 790 | ||
749 | wlcore_write_reg(wl, REG_INTERRUPT_MASK, event_mask); | 791 | ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK, event_mask); |
792 | if (ret < 0) | ||
793 | goto out; | ||
750 | 794 | ||
751 | wlcore_enable_interrupts(wl); | 795 | wlcore_enable_interrupts(wl); |
752 | wlcore_write_reg(wl, REG_INTERRUPT_MASK, | 796 | |
753 | WL1271_ACX_INTR_ALL & ~intr_mask); | 797 | ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK, |
798 | WL1271_ACX_INTR_ALL & ~intr_mask); | ||
799 | |||
800 | out: | ||
801 | return ret; | ||
754 | } | 802 | } |
755 | 803 | ||
756 | static int wl18xx_boot(struct wl1271 *wl) | 804 | static int wl18xx_boot(struct wl1271 *wl) |
@@ -761,25 +809,29 @@ static int wl18xx_boot(struct wl1271 *wl) | |||
761 | if (ret < 0) | 809 | if (ret < 0) |
762 | goto out; | 810 | goto out; |
763 | 811 | ||
764 | wl18xx_pre_upload(wl); | 812 | ret = wl18xx_pre_upload(wl); |
813 | if (ret < 0) | ||
814 | goto out; | ||
765 | 815 | ||
766 | ret = wlcore_boot_upload_firmware(wl); | 816 | ret = wlcore_boot_upload_firmware(wl); |
767 | if (ret < 0) | 817 | if (ret < 0) |
768 | goto out; | 818 | goto out; |
769 | 819 | ||
770 | wl18xx_set_mac_and_phy(wl); | 820 | ret = wl18xx_set_mac_and_phy(wl); |
821 | if (ret < 0) | ||
822 | goto out; | ||
771 | 823 | ||
772 | ret = wlcore_boot_run_firmware(wl); | 824 | ret = wlcore_boot_run_firmware(wl); |
773 | if (ret < 0) | 825 | if (ret < 0) |
774 | goto out; | 826 | goto out; |
775 | 827 | ||
776 | wl18xx_enable_interrupts(wl); | 828 | ret = wl18xx_enable_interrupts(wl); |
777 | 829 | ||
778 | out: | 830 | out: |
779 | return ret; | 831 | return ret; |
780 | } | 832 | } |
781 | 833 | ||
782 | static void wl18xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr, | 834 | static int wl18xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr, |
783 | void *buf, size_t len) | 835 | void *buf, size_t len) |
784 | { | 836 | { |
785 | struct wl18xx_priv *priv = wl->priv; | 837 | struct wl18xx_priv *priv = wl->priv; |
@@ -787,13 +839,14 @@ static void wl18xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr, | |||
787 | memcpy(priv->cmd_buf, buf, len); | 839 | memcpy(priv->cmd_buf, buf, len); |
788 | memset(priv->cmd_buf + len, 0, WL18XX_CMD_MAX_SIZE - len); | 840 | memset(priv->cmd_buf + len, 0, WL18XX_CMD_MAX_SIZE - len); |
789 | 841 | ||
790 | wl1271_write(wl, cmd_box_addr, priv->cmd_buf, WL18XX_CMD_MAX_SIZE, | 842 | return wlcore_write(wl, cmd_box_addr, priv->cmd_buf, |
791 | false); | 843 | WL18XX_CMD_MAX_SIZE, false); |
792 | } | 844 | } |
793 | 845 | ||
794 | static void wl18xx_ack_event(struct wl1271 *wl) | 846 | static int wl18xx_ack_event(struct wl1271 *wl) |
795 | { | 847 | { |
796 | wlcore_write_reg(wl, REG_INTERRUPT_TRIG, WL18XX_INTR_TRIG_EVENT_ACK); | 848 | return wlcore_write_reg(wl, REG_INTERRUPT_TRIG, |
849 | WL18XX_INTR_TRIG_EVENT_ACK); | ||
797 | } | 850 | } |
798 | 851 | ||
799 | static u32 wl18xx_calc_tx_blocks(struct wl1271 *wl, u32 len, u32 spare_blks) | 852 | static u32 wl18xx_calc_tx_blocks(struct wl1271 *wl, u32 len, u32 spare_blks) |
@@ -975,34 +1028,32 @@ static u32 wl18xx_ap_get_mimo_wide_rate_mask(struct wl1271 *wl, | |||
975 | } else if (!strcmp(ht_mode_param, "mimo")) { | 1028 | } else if (!strcmp(ht_mode_param, "mimo")) { |
976 | wl1271_debug(DEBUG_ACX, "using MIMO rate mask"); | 1029 | wl1271_debug(DEBUG_ACX, "using MIMO rate mask"); |
977 | 1030 | ||
978 | /* | ||
979 | * PG 1.0 has some problems with MCS_13, so disable it | ||
980 | * | ||
981 | * TODO: instead of hacking this in here, we should | ||
982 | * make it more general and change a bit in the | ||
983 | * wlvif->rate_set instead. | ||
984 | */ | ||
985 | if (wl->chip.id == CHIP_ID_185x_PG10) | ||
986 | return CONF_TX_MIMO_RATES & ~CONF_HW_BIT_RATE_MCS_13; | ||
987 | |||
988 | return CONF_TX_MIMO_RATES; | 1031 | return CONF_TX_MIMO_RATES; |
989 | } else { | 1032 | } else { |
990 | return 0; | 1033 | return 0; |
991 | } | 1034 | } |
992 | } | 1035 | } |
993 | 1036 | ||
994 | static s8 wl18xx_get_pg_ver(struct wl1271 *wl) | 1037 | static int wl18xx_get_pg_ver(struct wl1271 *wl, s8 *ver) |
995 | { | 1038 | { |
996 | u32 fuse; | 1039 | u32 fuse; |
1040 | int ret; | ||
997 | 1041 | ||
998 | wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]); | 1042 | ret = wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]); |
1043 | if (ret < 0) | ||
1044 | goto out; | ||
1045 | |||
1046 | ret = wlcore_read32(wl, WL18XX_REG_FUSE_DATA_1_3, &fuse); | ||
1047 | if (ret < 0) | ||
1048 | goto out; | ||
999 | 1049 | ||
1000 | fuse = wl1271_read32(wl, WL18XX_REG_FUSE_DATA_1_3); | 1050 | if (ver) |
1001 | fuse = (fuse & WL18XX_PG_VER_MASK) >> WL18XX_PG_VER_OFFSET; | 1051 | *ver = (fuse & WL18XX_PG_VER_MASK) >> WL18XX_PG_VER_OFFSET; |
1002 | 1052 | ||
1003 | wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); | 1053 | ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); |
1004 | 1054 | ||
1005 | return (s8)fuse; | 1055 | out: |
1056 | return ret; | ||
1006 | } | 1057 | } |
1007 | 1058 | ||
1008 | #define WL18XX_CONF_FILE_NAME "ti-connectivity/wl18xx-conf.bin" | 1059 | #define WL18XX_CONF_FILE_NAME "ti-connectivity/wl18xx-conf.bin" |
@@ -1021,8 +1072,7 @@ static int wl18xx_conf_init(struct wl1271 *wl, struct device *dev) | |||
1021 | } | 1072 | } |
1022 | 1073 | ||
1023 | if (fw->size != WL18XX_CONF_SIZE) { | 1074 | if (fw->size != WL18XX_CONF_SIZE) { |
1024 | wl1271_error("configuration binary file size is wrong, " | 1075 | wl1271_error("configuration binary file size is wrong, expected %zu got %zu", |
1025 | "expected %ld got %zd", | ||
1026 | WL18XX_CONF_SIZE, fw->size); | 1076 | WL18XX_CONF_SIZE, fw->size); |
1027 | ret = -EINVAL; | 1077 | ret = -EINVAL; |
1028 | goto out; | 1078 | goto out; |
@@ -1069,26 +1119,41 @@ out: | |||
1069 | 1119 | ||
1070 | static int wl18xx_plt_init(struct wl1271 *wl) | 1120 | static int wl18xx_plt_init(struct wl1271 *wl) |
1071 | { | 1121 | { |
1072 | wl1271_write32(wl, WL18XX_SCR_PAD8, WL18XX_SCR_PAD8_PLT); | 1122 | int ret; |
1123 | |||
1124 | ret = wlcore_write32(wl, WL18XX_SCR_PAD8, WL18XX_SCR_PAD8_PLT); | ||
1125 | if (ret < 0) | ||
1126 | return ret; | ||
1073 | 1127 | ||
1074 | return wl->ops->boot(wl); | 1128 | return wl->ops->boot(wl); |
1075 | } | 1129 | } |
1076 | 1130 | ||
1077 | static void wl18xx_get_mac(struct wl1271 *wl) | 1131 | static int wl18xx_get_mac(struct wl1271 *wl) |
1078 | { | 1132 | { |
1079 | u32 mac1, mac2; | 1133 | u32 mac1, mac2; |
1134 | int ret; | ||
1135 | |||
1136 | ret = wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]); | ||
1137 | if (ret < 0) | ||
1138 | goto out; | ||
1080 | 1139 | ||
1081 | wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]); | 1140 | ret = wlcore_read32(wl, WL18XX_REG_FUSE_BD_ADDR_1, &mac1); |
1141 | if (ret < 0) | ||
1142 | goto out; | ||
1082 | 1143 | ||
1083 | mac1 = wl1271_read32(wl, WL18XX_REG_FUSE_BD_ADDR_1); | 1144 | ret = wlcore_read32(wl, WL18XX_REG_FUSE_BD_ADDR_2, &mac2); |
1084 | mac2 = wl1271_read32(wl, WL18XX_REG_FUSE_BD_ADDR_2); | 1145 | if (ret < 0) |
1146 | goto out; | ||
1085 | 1147 | ||
1086 | /* these are the two parts of the BD_ADDR */ | 1148 | /* these are the two parts of the BD_ADDR */ |
1087 | wl->fuse_oui_addr = ((mac2 & 0xffff) << 8) + | 1149 | wl->fuse_oui_addr = ((mac2 & 0xffff) << 8) + |
1088 | ((mac1 & 0xff000000) >> 24); | 1150 | ((mac1 & 0xff000000) >> 24); |
1089 | wl->fuse_nic_addr = (mac1 & 0xffffff); | 1151 | wl->fuse_nic_addr = (mac1 & 0xffffff); |
1090 | 1152 | ||
1091 | wlcore_set_partition(wl, &wl->ptable[PART_DOWN]); | 1153 | ret = wlcore_set_partition(wl, &wl->ptable[PART_DOWN]); |
1154 | |||
1155 | out: | ||
1156 | return ret; | ||
1092 | } | 1157 | } |
1093 | 1158 | ||
1094 | static int wl18xx_handle_static_data(struct wl1271 *wl, | 1159 | static int wl18xx_handle_static_data(struct wl1271 *wl, |
@@ -1214,8 +1279,8 @@ static struct wlcore_ops wl18xx_ops = { | |||
1214 | .pre_pkt_send = wl18xx_pre_pkt_send, | 1279 | .pre_pkt_send = wl18xx_pre_pkt_send, |
1215 | }; | 1280 | }; |
1216 | 1281 | ||
1217 | /* HT cap appropriate for wide channels */ | 1282 | /* HT cap appropriate for wide channels in 2Ghz */ |
1218 | static struct ieee80211_sta_ht_cap wl18xx_siso40_ht_cap = { | 1283 | static struct ieee80211_sta_ht_cap wl18xx_siso40_ht_cap_2ghz = { |
1219 | .cap = IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 | | 1284 | .cap = IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 | |
1220 | IEEE80211_HT_CAP_SUP_WIDTH_20_40 | IEEE80211_HT_CAP_DSSSCCK40, | 1285 | IEEE80211_HT_CAP_SUP_WIDTH_20_40 | IEEE80211_HT_CAP_DSSSCCK40, |
1221 | .ht_supported = true, | 1286 | .ht_supported = true, |
@@ -1228,40 +1293,42 @@ static struct ieee80211_sta_ht_cap wl18xx_siso40_ht_cap = { | |||
1228 | }, | 1293 | }, |
1229 | }; | 1294 | }; |
1230 | 1295 | ||
1231 | /* HT cap appropriate for SISO 20 */ | 1296 | /* HT cap appropriate for wide channels in 5Ghz */ |
1232 | static struct ieee80211_sta_ht_cap wl18xx_siso20_ht_cap = { | 1297 | static struct ieee80211_sta_ht_cap wl18xx_siso40_ht_cap_5ghz = { |
1233 | .cap = IEEE80211_HT_CAP_SGI_20, | 1298 | .cap = IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 | |
1299 | IEEE80211_HT_CAP_SUP_WIDTH_20_40, | ||
1234 | .ht_supported = true, | 1300 | .ht_supported = true, |
1235 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K, | 1301 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K, |
1236 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, | 1302 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, |
1237 | .mcs = { | 1303 | .mcs = { |
1238 | .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, | 1304 | .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, |
1239 | .rx_highest = cpu_to_le16(72), | 1305 | .rx_highest = cpu_to_le16(150), |
1240 | .tx_params = IEEE80211_HT_MCS_TX_DEFINED, | 1306 | .tx_params = IEEE80211_HT_MCS_TX_DEFINED, |
1241 | }, | 1307 | }, |
1242 | }; | 1308 | }; |
1243 | 1309 | ||
1244 | /* HT cap appropriate for MIMO rates in 20mhz channel */ | 1310 | /* HT cap appropriate for SISO 20 */ |
1245 | static struct ieee80211_sta_ht_cap wl18xx_mimo_ht_cap_2ghz = { | 1311 | static struct ieee80211_sta_ht_cap wl18xx_siso20_ht_cap = { |
1246 | .cap = IEEE80211_HT_CAP_SGI_20, | 1312 | .cap = IEEE80211_HT_CAP_SGI_20, |
1247 | .ht_supported = true, | 1313 | .ht_supported = true, |
1248 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K, | 1314 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K, |
1249 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, | 1315 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, |
1250 | .mcs = { | 1316 | .mcs = { |
1251 | .rx_mask = { 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, }, | 1317 | .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, |
1252 | .rx_highest = cpu_to_le16(144), | 1318 | .rx_highest = cpu_to_le16(72), |
1253 | .tx_params = IEEE80211_HT_MCS_TX_DEFINED, | 1319 | .tx_params = IEEE80211_HT_MCS_TX_DEFINED, |
1254 | }, | 1320 | }, |
1255 | }; | 1321 | }; |
1256 | 1322 | ||
1257 | static struct ieee80211_sta_ht_cap wl18xx_mimo_ht_cap_5ghz = { | 1323 | /* HT cap appropriate for MIMO rates in 20mhz channel */ |
1324 | static struct ieee80211_sta_ht_cap wl18xx_mimo_ht_cap_2ghz = { | ||
1258 | .cap = IEEE80211_HT_CAP_SGI_20, | 1325 | .cap = IEEE80211_HT_CAP_SGI_20, |
1259 | .ht_supported = true, | 1326 | .ht_supported = true, |
1260 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K, | 1327 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K, |
1261 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, | 1328 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, |
1262 | .mcs = { | 1329 | .mcs = { |
1263 | .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, | 1330 | .rx_mask = { 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, }, |
1264 | .rx_highest = cpu_to_le16(72), | 1331 | .rx_highest = cpu_to_le16(144), |
1265 | .tx_params = IEEE80211_HT_MCS_TX_DEFINED, | 1332 | .tx_params = IEEE80211_HT_MCS_TX_DEFINED, |
1266 | }, | 1333 | }, |
1267 | }; | 1334 | }; |
@@ -1286,7 +1353,7 @@ static int __devinit wl18xx_probe(struct platform_device *pdev) | |||
1286 | wl->ptable = wl18xx_ptable; | 1353 | wl->ptable = wl18xx_ptable; |
1287 | wl->rtable = wl18xx_rtable; | 1354 | wl->rtable = wl18xx_rtable; |
1288 | wl->num_tx_desc = 32; | 1355 | wl->num_tx_desc = 32; |
1289 | wl->num_rx_desc = 16; | 1356 | wl->num_rx_desc = 32; |
1290 | wl->band_rate_to_idx = wl18xx_band_rate_to_idx; | 1357 | wl->band_rate_to_idx = wl18xx_band_rate_to_idx; |
1291 | wl->hw_tx_rate_tbl_size = WL18XX_CONF_HW_RXTX_RATE_MAX; | 1358 | wl->hw_tx_rate_tbl_size = WL18XX_CONF_HW_RXTX_RATE_MAX; |
1292 | wl->hw_min_ht_rate = WL18XX_CONF_HW_RXTX_RATE_MCS0; | 1359 | wl->hw_min_ht_rate = WL18XX_CONF_HW_RXTX_RATE_MCS0; |
@@ -1294,32 +1361,8 @@ static int __devinit wl18xx_probe(struct platform_device *pdev) | |||
1294 | wl->stats.fw_stats_len = sizeof(struct wl18xx_acx_statistics); | 1361 | wl->stats.fw_stats_len = sizeof(struct wl18xx_acx_statistics); |
1295 | wl->static_data_priv_len = sizeof(struct wl18xx_static_data_priv); | 1362 | wl->static_data_priv_len = sizeof(struct wl18xx_static_data_priv); |
1296 | 1363 | ||
1297 | if (!strcmp(ht_mode_param, "wide")) { | 1364 | if (num_rx_desc_param != -1) |
1298 | memcpy(&wl->ht_cap[IEEE80211_BAND_2GHZ], | 1365 | wl->num_rx_desc = num_rx_desc_param; |
1299 | &wl18xx_siso40_ht_cap, | ||
1300 | sizeof(wl18xx_siso40_ht_cap)); | ||
1301 | memcpy(&wl->ht_cap[IEEE80211_BAND_5GHZ], | ||
1302 | &wl18xx_siso40_ht_cap, | ||
1303 | sizeof(wl18xx_siso40_ht_cap)); | ||
1304 | } else if (!strcmp(ht_mode_param, "mimo")) { | ||
1305 | memcpy(&wl->ht_cap[IEEE80211_BAND_2GHZ], | ||
1306 | &wl18xx_mimo_ht_cap_2ghz, | ||
1307 | sizeof(wl18xx_mimo_ht_cap_2ghz)); | ||
1308 | memcpy(&wl->ht_cap[IEEE80211_BAND_5GHZ], | ||
1309 | &wl18xx_mimo_ht_cap_5ghz, | ||
1310 | sizeof(wl18xx_mimo_ht_cap_5ghz)); | ||
1311 | } else if (!strcmp(ht_mode_param, "siso20")) { | ||
1312 | memcpy(&wl->ht_cap[IEEE80211_BAND_2GHZ], | ||
1313 | &wl18xx_siso20_ht_cap, | ||
1314 | sizeof(wl18xx_siso20_ht_cap)); | ||
1315 | memcpy(&wl->ht_cap[IEEE80211_BAND_5GHZ], | ||
1316 | &wl18xx_siso20_ht_cap, | ||
1317 | sizeof(wl18xx_siso20_ht_cap)); | ||
1318 | } else { | ||
1319 | wl1271_error("invalid ht_mode '%s'", ht_mode_param); | ||
1320 | ret = -EINVAL; | ||
1321 | goto out_free; | ||
1322 | } | ||
1323 | 1366 | ||
1324 | ret = wl18xx_conf_init(wl, &pdev->dev); | 1367 | ret = wl18xx_conf_init(wl, &pdev->dev); |
1325 | if (ret < 0) | 1368 | if (ret < 0) |
@@ -1366,6 +1409,37 @@ static int __devinit wl18xx_probe(struct platform_device *pdev) | |||
1366 | if (dc2dc_param != -1) | 1409 | if (dc2dc_param != -1) |
1367 | priv->conf.phy.external_pa_dc2dc = dc2dc_param; | 1410 | priv->conf.phy.external_pa_dc2dc = dc2dc_param; |
1368 | 1411 | ||
1412 | if (!strcmp(ht_mode_param, "default")) { | ||
1413 | /* | ||
1414 | * Only support mimo with multiple antennas. Fall back to | ||
1415 | * siso20. | ||
1416 | */ | ||
1417 | if (priv->conf.phy.number_of_assembled_ant2_4 >= 2) | ||
1418 | wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ, | ||
1419 | &wl18xx_mimo_ht_cap_2ghz); | ||
1420 | else | ||
1421 | wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ, | ||
1422 | &wl18xx_siso20_ht_cap); | ||
1423 | |||
1424 | /* 5Ghz is always wide */ | ||
1425 | wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ, | ||
1426 | &wl18xx_siso40_ht_cap_5ghz); | ||
1427 | } else if (!strcmp(ht_mode_param, "wide")) { | ||
1428 | wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ, | ||
1429 | &wl18xx_siso40_ht_cap_2ghz); | ||
1430 | wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ, | ||
1431 | &wl18xx_siso40_ht_cap_5ghz); | ||
1432 | } else if (!strcmp(ht_mode_param, "siso20")) { | ||
1433 | wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ, | ||
1434 | &wl18xx_siso20_ht_cap); | ||
1435 | wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ, | ||
1436 | &wl18xx_siso20_ht_cap); | ||
1437 | } else { | ||
1438 | wl1271_error("invalid ht_mode '%s'", ht_mode_param); | ||
1439 | ret = -EINVAL; | ||
1440 | goto out_free; | ||
1441 | } | ||
1442 | |||
1369 | if (!checksum_param) { | 1443 | if (!checksum_param) { |
1370 | wl18xx_ops.set_rx_csum = NULL; | 1444 | wl18xx_ops.set_rx_csum = NULL; |
1371 | wl18xx_ops.init_vif = NULL; | 1445 | wl18xx_ops.init_vif = NULL; |
@@ -1410,7 +1484,7 @@ static void __exit wl18xx_exit(void) | |||
1410 | module_exit(wl18xx_exit); | 1484 | module_exit(wl18xx_exit); |
1411 | 1485 | ||
1412 | module_param_named(ht_mode, ht_mode_param, charp, S_IRUSR); | 1486 | module_param_named(ht_mode, ht_mode_param, charp, S_IRUSR); |
1413 | MODULE_PARM_DESC(ht_mode, "Force HT mode: wide (default), mimo or siso20"); | 1487 | MODULE_PARM_DESC(ht_mode, "Force HT mode: wide or siso20"); |
1414 | 1488 | ||
1415 | module_param_named(board_type, board_type_param, charp, S_IRUSR); | 1489 | module_param_named(board_type, board_type_param, charp, S_IRUSR); |
1416 | MODULE_PARM_DESC(board_type, "Board type: fpga, hdk (default), evb, com8 or " | 1490 | MODULE_PARM_DESC(board_type, "Board type: fpga, hdk (default), evb, com8 or " |
@@ -1458,6 +1532,11 @@ module_param_named(pwr_limit_reference_11_abg, | |||
1458 | MODULE_PARM_DESC(pwr_limit_reference_11_abg, "Power limit reference: u8 " | 1532 | MODULE_PARM_DESC(pwr_limit_reference_11_abg, "Power limit reference: u8 " |
1459 | "(default is 0xc8)"); | 1533 | "(default is 0xc8)"); |
1460 | 1534 | ||
1535 | module_param_named(num_rx_desc, | ||
1536 | num_rx_desc_param, int, S_IRUSR); | ||
1537 | MODULE_PARM_DESC(num_rx_desc_param, | ||
1538 | "Number of Rx descriptors: u8 (default is 32)"); | ||
1539 | |||
1461 | MODULE_LICENSE("GPL v2"); | 1540 | MODULE_LICENSE("GPL v2"); |
1462 | MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>"); | 1541 | MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>"); |
1463 | MODULE_FIRMWARE(WL18XX_FW_NAME); | 1542 | MODULE_FIRMWARE(WL18XX_FW_NAME); |
diff --git a/drivers/net/wireless/ti/wlcore/acx.c b/drivers/net/wireless/ti/wlcore/acx.c index b9ec42c8375..ce108a736bd 100644 --- a/drivers/net/wireless/ti/wlcore/acx.c +++ b/drivers/net/wireless/ti/wlcore/acx.c | |||
@@ -70,7 +70,7 @@ int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth) | |||
70 | struct acx_sleep_auth *auth; | 70 | struct acx_sleep_auth *auth; |
71 | int ret; | 71 | int ret; |
72 | 72 | ||
73 | wl1271_debug(DEBUG_ACX, "acx sleep auth"); | 73 | wl1271_debug(DEBUG_ACX, "acx sleep auth %d", sleep_auth); |
74 | 74 | ||
75 | auth = kzalloc(sizeof(*auth), GFP_KERNEL); | 75 | auth = kzalloc(sizeof(*auth), GFP_KERNEL); |
76 | if (!auth) { | 76 | if (!auth) { |
@@ -81,7 +81,13 @@ int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth) | |||
81 | auth->sleep_auth = sleep_auth; | 81 | auth->sleep_auth = sleep_auth; |
82 | 82 | ||
83 | ret = wl1271_cmd_configure(wl, ACX_SLEEP_AUTH, auth, sizeof(*auth)); | 83 | ret = wl1271_cmd_configure(wl, ACX_SLEEP_AUTH, auth, sizeof(*auth)); |
84 | if (ret < 0) { | ||
85 | wl1271_error("could not configure sleep_auth to %d: %d", | ||
86 | sleep_auth, ret); | ||
87 | goto out; | ||
88 | } | ||
84 | 89 | ||
90 | wl->sleep_auth = sleep_auth; | ||
85 | out: | 91 | out: |
86 | kfree(auth); | 92 | kfree(auth); |
87 | return ret; | 93 | return ret; |
diff --git a/drivers/net/wireless/ti/wlcore/acx.h b/drivers/net/wireless/ti/wlcore/acx.h index c0181258b72..d03215d6b3b 100644 --- a/drivers/net/wireless/ti/wlcore/acx.h +++ b/drivers/net/wireless/ti/wlcore/acx.h | |||
@@ -118,6 +118,11 @@ enum wl1271_psm_mode { | |||
118 | 118 | ||
119 | /* Extreme low power */ | 119 | /* Extreme low power */ |
120 | WL1271_PSM_ELP = 2, | 120 | WL1271_PSM_ELP = 2, |
121 | |||
122 | WL1271_PSM_MAX = WL1271_PSM_ELP, | ||
123 | |||
124 | /* illegal out of band value of PSM mode */ | ||
125 | WL1271_PSM_ILLEGAL = 0xff | ||
121 | }; | 126 | }; |
122 | 127 | ||
123 | struct acx_sleep_auth { | 128 | struct acx_sleep_auth { |
diff --git a/drivers/net/wireless/ti/wlcore/boot.c b/drivers/net/wireless/ti/wlcore/boot.c index 0fda500c01c..8965960b841 100644 --- a/drivers/net/wireless/ti/wlcore/boot.c +++ b/drivers/net/wireless/ti/wlcore/boot.c | |||
@@ -33,16 +33,22 @@ | |||
33 | #include "rx.h" | 33 | #include "rx.h" |
34 | #include "hw_ops.h" | 34 | #include "hw_ops.h" |
35 | 35 | ||
36 | static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag) | 36 | static int wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag) |
37 | { | 37 | { |
38 | u32 cpu_ctrl; | 38 | u32 cpu_ctrl; |
39 | int ret; | ||
39 | 40 | ||
40 | /* 10.5.0 run the firmware (I) */ | 41 | /* 10.5.0 run the firmware (I) */ |
41 | cpu_ctrl = wlcore_read_reg(wl, REG_ECPU_CONTROL); | 42 | ret = wlcore_read_reg(wl, REG_ECPU_CONTROL, &cpu_ctrl); |
43 | if (ret < 0) | ||
44 | goto out; | ||
42 | 45 | ||
43 | /* 10.5.1 run the firmware (II) */ | 46 | /* 10.5.1 run the firmware (II) */ |
44 | cpu_ctrl |= flag; | 47 | cpu_ctrl |= flag; |
45 | wlcore_write_reg(wl, REG_ECPU_CONTROL, cpu_ctrl); | 48 | ret = wlcore_write_reg(wl, REG_ECPU_CONTROL, cpu_ctrl); |
49 | |||
50 | out: | ||
51 | return ret; | ||
46 | } | 52 | } |
47 | 53 | ||
48 | static int wlcore_boot_parse_fw_ver(struct wl1271 *wl, | 54 | static int wlcore_boot_parse_fw_ver(struct wl1271 *wl, |
@@ -87,7 +93,9 @@ static int wlcore_boot_static_data(struct wl1271 *wl) | |||
87 | goto out; | 93 | goto out; |
88 | } | 94 | } |
89 | 95 | ||
90 | wl1271_read(wl, wl->cmd_box_addr, static_data, len, false); | 96 | ret = wlcore_read(wl, wl->cmd_box_addr, static_data, len, false); |
97 | if (ret < 0) | ||
98 | goto out_free; | ||
91 | 99 | ||
92 | ret = wlcore_boot_parse_fw_ver(wl, static_data); | 100 | ret = wlcore_boot_parse_fw_ver(wl, static_data); |
93 | if (ret < 0) | 101 | if (ret < 0) |
@@ -109,6 +117,7 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, | |||
109 | struct wlcore_partition_set partition; | 117 | struct wlcore_partition_set partition; |
110 | int addr, chunk_num, partition_limit; | 118 | int addr, chunk_num, partition_limit; |
111 | u8 *p, *chunk; | 119 | u8 *p, *chunk; |
120 | int ret; | ||
112 | 121 | ||
113 | /* whal_FwCtrl_LoadFwImageSm() */ | 122 | /* whal_FwCtrl_LoadFwImageSm() */ |
114 | 123 | ||
@@ -130,7 +139,9 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, | |||
130 | 139 | ||
131 | memcpy(&partition, &wl->ptable[PART_DOWN], sizeof(partition)); | 140 | memcpy(&partition, &wl->ptable[PART_DOWN], sizeof(partition)); |
132 | partition.mem.start = dest; | 141 | partition.mem.start = dest; |
133 | wlcore_set_partition(wl, &partition); | 142 | ret = wlcore_set_partition(wl, &partition); |
143 | if (ret < 0) | ||
144 | return ret; | ||
134 | 145 | ||
135 | /* 10.1 set partition limit and chunk num */ | 146 | /* 10.1 set partition limit and chunk num */ |
136 | chunk_num = 0; | 147 | chunk_num = 0; |
@@ -144,7 +155,9 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, | |||
144 | partition_limit = chunk_num * CHUNK_SIZE + | 155 | partition_limit = chunk_num * CHUNK_SIZE + |
145 | wl->ptable[PART_DOWN].mem.size; | 156 | wl->ptable[PART_DOWN].mem.size; |
146 | partition.mem.start = addr; | 157 | partition.mem.start = addr; |
147 | wlcore_set_partition(wl, &partition); | 158 | ret = wlcore_set_partition(wl, &partition); |
159 | if (ret < 0) | ||
160 | return ret; | ||
148 | } | 161 | } |
149 | 162 | ||
150 | /* 10.3 upload the chunk */ | 163 | /* 10.3 upload the chunk */ |
@@ -153,7 +166,9 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, | |||
153 | memcpy(chunk, p, CHUNK_SIZE); | 166 | memcpy(chunk, p, CHUNK_SIZE); |
154 | wl1271_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x", | 167 | wl1271_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x", |
155 | p, addr); | 168 | p, addr); |
156 | wl1271_write(wl, addr, chunk, CHUNK_SIZE, false); | 169 | ret = wlcore_write(wl, addr, chunk, CHUNK_SIZE, false); |
170 | if (ret < 0) | ||
171 | goto out; | ||
157 | 172 | ||
158 | chunk_num++; | 173 | chunk_num++; |
159 | } | 174 | } |
@@ -164,10 +179,11 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, | |||
164 | memcpy(chunk, p, fw_data_len % CHUNK_SIZE); | 179 | memcpy(chunk, p, fw_data_len % CHUNK_SIZE); |
165 | wl1271_debug(DEBUG_BOOT, "uploading fw last chunk (%zd B) 0x%p to 0x%x", | 180 | wl1271_debug(DEBUG_BOOT, "uploading fw last chunk (%zd B) 0x%p to 0x%x", |
166 | fw_data_len % CHUNK_SIZE, p, addr); | 181 | fw_data_len % CHUNK_SIZE, p, addr); |
167 | wl1271_write(wl, addr, chunk, fw_data_len % CHUNK_SIZE, false); | 182 | ret = wlcore_write(wl, addr, chunk, fw_data_len % CHUNK_SIZE, false); |
168 | 183 | ||
184 | out: | ||
169 | kfree(chunk); | 185 | kfree(chunk); |
170 | return 0; | 186 | return ret; |
171 | } | 187 | } |
172 | 188 | ||
173 | int wlcore_boot_upload_firmware(struct wl1271 *wl) | 189 | int wlcore_boot_upload_firmware(struct wl1271 *wl) |
@@ -210,6 +226,7 @@ int wlcore_boot_upload_nvs(struct wl1271 *wl) | |||
210 | int i; | 226 | int i; |
211 | u32 dest_addr, val; | 227 | u32 dest_addr, val; |
212 | u8 *nvs_ptr, *nvs_aligned; | 228 | u8 *nvs_ptr, *nvs_aligned; |
229 | int ret; | ||
213 | 230 | ||
214 | if (wl->nvs == NULL) { | 231 | if (wl->nvs == NULL) { |
215 | wl1271_error("NVS file is needed during boot"); | 232 | wl1271_error("NVS file is needed during boot"); |
@@ -307,7 +324,9 @@ int wlcore_boot_upload_nvs(struct wl1271 *wl) | |||
307 | wl1271_debug(DEBUG_BOOT, | 324 | wl1271_debug(DEBUG_BOOT, |
308 | "nvs burst write 0x%x: 0x%x", | 325 | "nvs burst write 0x%x: 0x%x", |
309 | dest_addr, val); | 326 | dest_addr, val); |
310 | wl1271_write32(wl, dest_addr, val); | 327 | ret = wlcore_write32(wl, dest_addr, val); |
328 | if (ret < 0) | ||
329 | return ret; | ||
311 | 330 | ||
312 | nvs_ptr += 4; | 331 | nvs_ptr += 4; |
313 | dest_addr += 4; | 332 | dest_addr += 4; |
@@ -333,7 +352,9 @@ int wlcore_boot_upload_nvs(struct wl1271 *wl) | |||
333 | nvs_len -= nvs_ptr - (u8 *)wl->nvs; | 352 | nvs_len -= nvs_ptr - (u8 *)wl->nvs; |
334 | 353 | ||
335 | /* Now we must set the partition correctly */ | 354 | /* Now we must set the partition correctly */ |
336 | wlcore_set_partition(wl, &wl->ptable[PART_WORK]); | 355 | ret = wlcore_set_partition(wl, &wl->ptable[PART_WORK]); |
356 | if (ret < 0) | ||
357 | return ret; | ||
337 | 358 | ||
338 | /* Copy the NVS tables to a new block to ensure alignment */ | 359 | /* Copy the NVS tables to a new block to ensure alignment */ |
339 | nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL); | 360 | nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL); |
@@ -341,11 +362,11 @@ int wlcore_boot_upload_nvs(struct wl1271 *wl) | |||
341 | return -ENOMEM; | 362 | return -ENOMEM; |
342 | 363 | ||
343 | /* And finally we upload the NVS tables */ | 364 | /* And finally we upload the NVS tables */ |
344 | wlcore_write_data(wl, REG_CMD_MBOX_ADDRESS, | 365 | ret = wlcore_write_data(wl, REG_CMD_MBOX_ADDRESS, nvs_aligned, nvs_len, |
345 | nvs_aligned, nvs_len, false); | 366 | false); |
346 | 367 | ||
347 | kfree(nvs_aligned); | 368 | kfree(nvs_aligned); |
348 | return 0; | 369 | return ret; |
349 | 370 | ||
350 | out_badnvs: | 371 | out_badnvs: |
351 | wl1271_error("nvs data is malformed"); | 372 | wl1271_error("nvs data is malformed"); |
@@ -359,11 +380,17 @@ int wlcore_boot_run_firmware(struct wl1271 *wl) | |||
359 | u32 chip_id, intr; | 380 | u32 chip_id, intr; |
360 | 381 | ||
361 | /* Make sure we have the boot partition */ | 382 | /* Make sure we have the boot partition */ |
362 | wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); | 383 | ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); |
384 | if (ret < 0) | ||
385 | return ret; | ||
363 | 386 | ||
364 | wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT); | 387 | ret = wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT); |
388 | if (ret < 0) | ||
389 | return ret; | ||
365 | 390 | ||
366 | chip_id = wlcore_read_reg(wl, REG_CHIP_ID_B); | 391 | ret = wlcore_read_reg(wl, REG_CHIP_ID_B, &chip_id); |
392 | if (ret < 0) | ||
393 | return ret; | ||
367 | 394 | ||
368 | wl1271_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id); | 395 | wl1271_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id); |
369 | 396 | ||
@@ -376,7 +403,9 @@ int wlcore_boot_run_firmware(struct wl1271 *wl) | |||
376 | loop = 0; | 403 | loop = 0; |
377 | while (loop++ < INIT_LOOP) { | 404 | while (loop++ < INIT_LOOP) { |
378 | udelay(INIT_LOOP_DELAY); | 405 | udelay(INIT_LOOP_DELAY); |
379 | intr = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR); | 406 | ret = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR, &intr); |
407 | if (ret < 0) | ||
408 | return ret; | ||
380 | 409 | ||
381 | if (intr == 0xffffffff) { | 410 | if (intr == 0xffffffff) { |
382 | wl1271_error("error reading hardware complete " | 411 | wl1271_error("error reading hardware complete " |
@@ -385,8 +414,10 @@ int wlcore_boot_run_firmware(struct wl1271 *wl) | |||
385 | } | 414 | } |
386 | /* check that ACX_INTR_INIT_COMPLETE is enabled */ | 415 | /* check that ACX_INTR_INIT_COMPLETE is enabled */ |
387 | else if (intr & WL1271_ACX_INTR_INIT_COMPLETE) { | 416 | else if (intr & WL1271_ACX_INTR_INIT_COMPLETE) { |
388 | wlcore_write_reg(wl, REG_INTERRUPT_ACK, | 417 | ret = wlcore_write_reg(wl, REG_INTERRUPT_ACK, |
389 | WL1271_ACX_INTR_INIT_COMPLETE); | 418 | WL1271_ACX_INTR_INIT_COMPLETE); |
419 | if (ret < 0) | ||
420 | return ret; | ||
390 | break; | 421 | break; |
391 | } | 422 | } |
392 | } | 423 | } |
@@ -398,12 +429,17 @@ int wlcore_boot_run_firmware(struct wl1271 *wl) | |||
398 | } | 429 | } |
399 | 430 | ||
400 | /* get hardware config command mail box */ | 431 | /* get hardware config command mail box */ |
401 | wl->cmd_box_addr = wlcore_read_reg(wl, REG_COMMAND_MAILBOX_PTR); | 432 | ret = wlcore_read_reg(wl, REG_COMMAND_MAILBOX_PTR, &wl->cmd_box_addr); |
433 | if (ret < 0) | ||
434 | return ret; | ||
402 | 435 | ||
403 | wl1271_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x", wl->cmd_box_addr); | 436 | wl1271_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x", wl->cmd_box_addr); |
404 | 437 | ||
405 | /* get hardware config event mail box */ | 438 | /* get hardware config event mail box */ |
406 | wl->mbox_ptr[0] = wlcore_read_reg(wl, REG_EVENT_MAILBOX_PTR); | 439 | ret = wlcore_read_reg(wl, REG_EVENT_MAILBOX_PTR, &wl->mbox_ptr[0]); |
440 | if (ret < 0) | ||
441 | return ret; | ||
442 | |||
407 | wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox); | 443 | wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox); |
408 | 444 | ||
409 | wl1271_debug(DEBUG_MAILBOX, "MBOX ptrs: 0x%x 0x%x", | 445 | wl1271_debug(DEBUG_MAILBOX, "MBOX ptrs: 0x%x 0x%x", |
@@ -445,9 +481,9 @@ int wlcore_boot_run_firmware(struct wl1271 *wl) | |||
445 | } | 481 | } |
446 | 482 | ||
447 | /* set the working partition to its "running" mode offset */ | 483 | /* set the working partition to its "running" mode offset */ |
448 | wlcore_set_partition(wl, &wl->ptable[PART_WORK]); | 484 | ret = wlcore_set_partition(wl, &wl->ptable[PART_WORK]); |
449 | 485 | ||
450 | /* firmware startup completed */ | 486 | /* firmware startup completed */ |
451 | return 0; | 487 | return ret; |
452 | } | 488 | } |
453 | EXPORT_SYMBOL_GPL(wlcore_boot_run_firmware); | 489 | EXPORT_SYMBOL_GPL(wlcore_boot_run_firmware); |
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c index 885364ca434..56c7a2342fd 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.c +++ b/drivers/net/wireless/ti/wlcore/cmd.c | |||
@@ -65,17 +65,24 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
65 | WARN_ON(len % 4 != 0); | 65 | WARN_ON(len % 4 != 0); |
66 | WARN_ON(test_bit(WL1271_FLAG_IN_ELP, &wl->flags)); | 66 | WARN_ON(test_bit(WL1271_FLAG_IN_ELP, &wl->flags)); |
67 | 67 | ||
68 | wl1271_write(wl, wl->cmd_box_addr, buf, len, false); | 68 | ret = wlcore_write(wl, wl->cmd_box_addr, buf, len, false); |
69 | if (ret < 0) | ||
70 | goto fail; | ||
69 | 71 | ||
70 | /* | 72 | /* |
71 | * TODO: we just need this because one bit is in a different | 73 | * TODO: we just need this because one bit is in a different |
72 | * place. Is there any better way? | 74 | * place. Is there any better way? |
73 | */ | 75 | */ |
74 | wl->ops->trigger_cmd(wl, wl->cmd_box_addr, buf, len); | 76 | ret = wl->ops->trigger_cmd(wl, wl->cmd_box_addr, buf, len); |
77 | if (ret < 0) | ||
78 | goto fail; | ||
75 | 79 | ||
76 | timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT); | 80 | timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT); |
77 | 81 | ||
78 | intr = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR); | 82 | ret = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR, &intr); |
83 | if (ret < 0) | ||
84 | goto fail; | ||
85 | |||
79 | while (!(intr & WL1271_ACX_INTR_CMD_COMPLETE)) { | 86 | while (!(intr & WL1271_ACX_INTR_CMD_COMPLETE)) { |
80 | if (time_after(jiffies, timeout)) { | 87 | if (time_after(jiffies, timeout)) { |
81 | wl1271_error("command complete timeout"); | 88 | wl1271_error("command complete timeout"); |
@@ -89,13 +96,18 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
89 | else | 96 | else |
90 | msleep(1); | 97 | msleep(1); |
91 | 98 | ||
92 | intr = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR); | 99 | ret = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR, &intr); |
100 | if (ret < 0) | ||
101 | goto fail; | ||
93 | } | 102 | } |
94 | 103 | ||
95 | /* read back the status code of the command */ | 104 | /* read back the status code of the command */ |
96 | if (res_len == 0) | 105 | if (res_len == 0) |
97 | res_len = sizeof(struct wl1271_cmd_header); | 106 | res_len = sizeof(struct wl1271_cmd_header); |
98 | wl1271_read(wl, wl->cmd_box_addr, cmd, res_len, false); | 107 | |
108 | ret = wlcore_read(wl, wl->cmd_box_addr, cmd, res_len, false); | ||
109 | if (ret < 0) | ||
110 | goto fail; | ||
99 | 111 | ||
100 | status = le16_to_cpu(cmd->status); | 112 | status = le16_to_cpu(cmd->status); |
101 | if (status != CMD_STATUS_SUCCESS) { | 113 | if (status != CMD_STATUS_SUCCESS) { |
@@ -104,11 +116,14 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
104 | goto fail; | 116 | goto fail; |
105 | } | 117 | } |
106 | 118 | ||
107 | wlcore_write_reg(wl, REG_INTERRUPT_ACK, WL1271_ACX_INTR_CMD_COMPLETE); | 119 | ret = wlcore_write_reg(wl, REG_INTERRUPT_ACK, |
120 | WL1271_ACX_INTR_CMD_COMPLETE); | ||
121 | if (ret < 0) | ||
122 | goto fail; | ||
123 | |||
108 | return 0; | 124 | return 0; |
109 | 125 | ||
110 | fail: | 126 | fail: |
111 | WARN_ON(1); | ||
112 | wl12xx_queue_recovery_work(wl); | 127 | wl12xx_queue_recovery_work(wl); |
113 | return ret; | 128 | return ret; |
114 | } | 129 | } |
@@ -117,35 +132,45 @@ fail: | |||
117 | * Poll the mailbox event field until any of the bits in the mask is set or a | 132 | * Poll the mailbox event field until any of the bits in the mask is set or a |
118 | * timeout occurs (WL1271_EVENT_TIMEOUT in msecs) | 133 | * timeout occurs (WL1271_EVENT_TIMEOUT in msecs) |
119 | */ | 134 | */ |
120 | static int wl1271_cmd_wait_for_event_or_timeout(struct wl1271 *wl, u32 mask) | 135 | static int wl1271_cmd_wait_for_event_or_timeout(struct wl1271 *wl, |
136 | u32 mask, bool *timeout) | ||
121 | { | 137 | { |
122 | u32 *events_vector; | 138 | u32 *events_vector; |
123 | u32 event; | 139 | u32 event; |
124 | unsigned long timeout; | 140 | unsigned long timeout_time; |
125 | int ret = 0; | 141 | int ret = 0; |
126 | 142 | ||
143 | *timeout = false; | ||
144 | |||
127 | events_vector = kmalloc(sizeof(*events_vector), GFP_KERNEL | GFP_DMA); | 145 | events_vector = kmalloc(sizeof(*events_vector), GFP_KERNEL | GFP_DMA); |
128 | if (!events_vector) | 146 | if (!events_vector) |
129 | return -ENOMEM; | 147 | return -ENOMEM; |
130 | 148 | ||
131 | timeout = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT); | 149 | timeout_time = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT); |
132 | 150 | ||
133 | do { | 151 | do { |
134 | if (time_after(jiffies, timeout)) { | 152 | if (time_after(jiffies, timeout_time)) { |
135 | wl1271_debug(DEBUG_CMD, "timeout waiting for event %d", | 153 | wl1271_debug(DEBUG_CMD, "timeout waiting for event %d", |
136 | (int)mask); | 154 | (int)mask); |
137 | ret = -ETIMEDOUT; | 155 | *timeout = true; |
138 | goto out; | 156 | goto out; |
139 | } | 157 | } |
140 | 158 | ||
141 | msleep(1); | 159 | msleep(1); |
142 | 160 | ||
143 | /* read from both event fields */ | 161 | /* read from both event fields */ |
144 | wl1271_read(wl, wl->mbox_ptr[0], events_vector, | 162 | ret = wlcore_read(wl, wl->mbox_ptr[0], events_vector, |
145 | sizeof(*events_vector), false); | 163 | sizeof(*events_vector), false); |
164 | if (ret < 0) | ||
165 | goto out; | ||
166 | |||
146 | event = *events_vector & mask; | 167 | event = *events_vector & mask; |
147 | wl1271_read(wl, wl->mbox_ptr[1], events_vector, | 168 | |
148 | sizeof(*events_vector), false); | 169 | ret = wlcore_read(wl, wl->mbox_ptr[1], events_vector, |
170 | sizeof(*events_vector), false); | ||
171 | if (ret < 0) | ||
172 | goto out; | ||
173 | |||
149 | event |= *events_vector & mask; | 174 | event |= *events_vector & mask; |
150 | } while (!event); | 175 | } while (!event); |
151 | 176 | ||
@@ -157,9 +182,10 @@ out: | |||
157 | static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask) | 182 | static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask) |
158 | { | 183 | { |
159 | int ret; | 184 | int ret; |
185 | bool timeout = false; | ||
160 | 186 | ||
161 | ret = wl1271_cmd_wait_for_event_or_timeout(wl, mask); | 187 | ret = wl1271_cmd_wait_for_event_or_timeout(wl, mask, &timeout); |
162 | if (ret != 0) { | 188 | if (ret != 0 || timeout) { |
163 | wl12xx_queue_recovery_work(wl); | 189 | wl12xx_queue_recovery_work(wl); |
164 | return ret; | 190 | return ret; |
165 | } | 191 | } |
@@ -1412,6 +1438,7 @@ int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid) | |||
1412 | { | 1438 | { |
1413 | struct wl12xx_cmd_remove_peer *cmd; | 1439 | struct wl12xx_cmd_remove_peer *cmd; |
1414 | int ret; | 1440 | int ret; |
1441 | bool timeout = false; | ||
1415 | 1442 | ||
1416 | wl1271_debug(DEBUG_CMD, "cmd remove peer %d", (int)hlid); | 1443 | wl1271_debug(DEBUG_CMD, "cmd remove peer %d", (int)hlid); |
1417 | 1444 | ||
@@ -1432,12 +1459,16 @@ int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid) | |||
1432 | goto out_free; | 1459 | goto out_free; |
1433 | } | 1460 | } |
1434 | 1461 | ||
1462 | ret = wl1271_cmd_wait_for_event_or_timeout(wl, | ||
1463 | PEER_REMOVE_COMPLETE_EVENT_ID, | ||
1464 | &timeout); | ||
1435 | /* | 1465 | /* |
1436 | * We are ok with a timeout here. The event is sometimes not sent | 1466 | * We are ok with a timeout here. The event is sometimes not sent |
1437 | * due to a firmware bug. | 1467 | * due to a firmware bug. In case of another error (like SDIO timeout) |
1468 | * queue a recovery. | ||
1438 | */ | 1469 | */ |
1439 | wl1271_cmd_wait_for_event_or_timeout(wl, | 1470 | if (ret) |
1440 | PEER_REMOVE_COMPLETE_EVENT_ID); | 1471 | wl12xx_queue_recovery_work(wl); |
1441 | 1472 | ||
1442 | out_free: | 1473 | out_free: |
1443 | kfree(cmd); | 1474 | kfree(cmd); |
@@ -1754,7 +1785,9 @@ int wl12xx_stop_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
1754 | return -EINVAL; | 1785 | return -EINVAL; |
1755 | 1786 | ||
1756 | /* flush all pending packets */ | 1787 | /* flush all pending packets */ |
1757 | wl1271_tx_work_locked(wl); | 1788 | ret = wlcore_tx_work_locked(wl); |
1789 | if (ret < 0) | ||
1790 | goto out; | ||
1758 | 1791 | ||
1759 | if (test_bit(wlvif->dev_role_id, wl->roc_map)) { | 1792 | if (test_bit(wlvif->dev_role_id, wl->roc_map)) { |
1760 | ret = wl12xx_croc(wl, wlvif->dev_role_id); | 1793 | ret = wl12xx_croc(wl, wlvif->dev_role_id); |
diff --git a/drivers/net/wireless/ti/wlcore/cmd.h b/drivers/net/wireless/ti/wlcore/cmd.h index 85171f2bf68..c8a6510c72c 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.h +++ b/drivers/net/wireless/ti/wlcore/cmd.h | |||
@@ -652,4 +652,25 @@ struct wl12xx_cmd_stop_channel_switch { | |||
652 | struct wl1271_cmd_header header; | 652 | struct wl1271_cmd_header header; |
653 | } __packed; | 653 | } __packed; |
654 | 654 | ||
655 | /* Used to check radio status after calibration */ | ||
656 | #define MAX_TLV_LENGTH 500 | ||
657 | #define TEST_CMD_P2G_CAL 2 /* TX BiP */ | ||
658 | |||
659 | struct wl1271_cmd_cal_p2g { | ||
660 | struct wl1271_cmd_header header; | ||
661 | |||
662 | struct wl1271_cmd_test_header test; | ||
663 | |||
664 | __le32 ver; | ||
665 | __le16 len; | ||
666 | u8 buf[MAX_TLV_LENGTH]; | ||
667 | u8 type; | ||
668 | u8 padding; | ||
669 | |||
670 | __le16 radio_status; | ||
671 | |||
672 | u8 sub_band_mask; | ||
673 | u8 padding2; | ||
674 | } __packed; | ||
675 | |||
655 | #endif /* __WL1271_CMD_H__ */ | 676 | #endif /* __WL1271_CMD_H__ */ |
diff --git a/drivers/net/wireless/ti/wlcore/conf.h b/drivers/net/wireless/ti/wlcore/conf.h index 03c63587233..d77224f2ac6 100644 --- a/drivers/net/wireless/ti/wlcore/conf.h +++ b/drivers/net/wireless/ti/wlcore/conf.h | |||
@@ -951,6 +951,12 @@ struct conf_conn_settings { | |||
951 | * Range: u16 | 951 | * Range: u16 |
952 | */ | 952 | */ |
953 | u8 max_listen_interval; | 953 | u8 max_listen_interval; |
954 | |||
955 | /* | ||
956 | * Default sleep authorization for a new STA interface. This determines | ||
957 | * whether we can go to ELP. | ||
958 | */ | ||
959 | u8 sta_sleep_auth; | ||
954 | } __packed; | 960 | } __packed; |
955 | 961 | ||
956 | enum { | 962 | enum { |
@@ -1276,7 +1282,7 @@ struct conf_hangover_settings { | |||
1276 | * version, the two LSB are the lower driver's private conf | 1282 | * version, the two LSB are the lower driver's private conf |
1277 | * version. | 1283 | * version. |
1278 | */ | 1284 | */ |
1279 | #define WLCORE_CONF_VERSION (0x0001 << 16) | 1285 | #define WLCORE_CONF_VERSION (0x0002 << 16) |
1280 | #define WLCORE_CONF_MASK 0xffff0000 | 1286 | #define WLCORE_CONF_MASK 0xffff0000 |
1281 | #define WLCORE_CONF_SIZE (sizeof(struct wlcore_conf_header) + \ | 1287 | #define WLCORE_CONF_SIZE (sizeof(struct wlcore_conf_header) + \ |
1282 | sizeof(struct wlcore_conf)) | 1288 | sizeof(struct wlcore_conf)) |
diff --git a/drivers/net/wireless/ti/wlcore/debugfs.c b/drivers/net/wireless/ti/wlcore/debugfs.c index 689a847005c..80dbc5304fa 100644 --- a/drivers/net/wireless/ti/wlcore/debugfs.c +++ b/drivers/net/wireless/ti/wlcore/debugfs.c | |||
@@ -38,6 +38,8 @@ | |||
38 | /* ms */ | 38 | /* ms */ |
39 | #define WL1271_DEBUGFS_STATS_LIFETIME 1000 | 39 | #define WL1271_DEBUGFS_STATS_LIFETIME 1000 |
40 | 40 | ||
41 | #define WLCORE_MAX_BLOCK_SIZE ((size_t)(4*PAGE_SIZE)) | ||
42 | |||
41 | /* debugfs macros idea from mac80211 */ | 43 | /* debugfs macros idea from mac80211 */ |
42 | int wl1271_format_buffer(char __user *userbuf, size_t count, | 44 | int wl1271_format_buffer(char __user *userbuf, size_t count, |
43 | loff_t *ppos, char *fmt, ...) | 45 | loff_t *ppos, char *fmt, ...) |
@@ -963,6 +965,257 @@ static const struct file_operations fw_stats_raw_ops = { | |||
963 | .llseek = default_llseek, | 965 | .llseek = default_llseek, |
964 | }; | 966 | }; |
965 | 967 | ||
968 | static ssize_t sleep_auth_read(struct file *file, char __user *user_buf, | ||
969 | size_t count, loff_t *ppos) | ||
970 | { | ||
971 | struct wl1271 *wl = file->private_data; | ||
972 | |||
973 | return wl1271_format_buffer(user_buf, count, | ||
974 | ppos, "%d\n", | ||
975 | wl->sleep_auth); | ||
976 | } | ||
977 | |||
978 | static ssize_t sleep_auth_write(struct file *file, | ||
979 | const char __user *user_buf, | ||
980 | size_t count, loff_t *ppos) | ||
981 | { | ||
982 | struct wl1271 *wl = file->private_data; | ||
983 | unsigned long value; | ||
984 | int ret; | ||
985 | |||
986 | ret = kstrtoul_from_user(user_buf, count, 0, &value); | ||
987 | if (ret < 0) { | ||
988 | wl1271_warning("illegal value in sleep_auth"); | ||
989 | return -EINVAL; | ||
990 | } | ||
991 | |||
992 | if (value < 0 || value > WL1271_PSM_MAX) { | ||
993 | wl1271_warning("sleep_auth must be between 0 and %d", | ||
994 | WL1271_PSM_MAX); | ||
995 | return -ERANGE; | ||
996 | } | ||
997 | |||
998 | mutex_lock(&wl->mutex); | ||
999 | |||
1000 | wl->conf.conn.sta_sleep_auth = value; | ||
1001 | |||
1002 | if (wl->state == WL1271_STATE_OFF) { | ||
1003 | /* this will show up on "read" in case we are off */ | ||
1004 | wl->sleep_auth = value; | ||
1005 | goto out; | ||
1006 | } | ||
1007 | |||
1008 | ret = wl1271_ps_elp_wakeup(wl); | ||
1009 | if (ret < 0) | ||
1010 | goto out; | ||
1011 | |||
1012 | ret = wl1271_acx_sleep_auth(wl, value); | ||
1013 | if (ret < 0) | ||
1014 | goto out_sleep; | ||
1015 | |||
1016 | out_sleep: | ||
1017 | wl1271_ps_elp_sleep(wl); | ||
1018 | out: | ||
1019 | mutex_unlock(&wl->mutex); | ||
1020 | return count; | ||
1021 | } | ||
1022 | |||
1023 | static const struct file_operations sleep_auth_ops = { | ||
1024 | .read = sleep_auth_read, | ||
1025 | .write = sleep_auth_write, | ||
1026 | .open = simple_open, | ||
1027 | .llseek = default_llseek, | ||
1028 | }; | ||
1029 | |||
1030 | static ssize_t dev_mem_read(struct file *file, | ||
1031 | char __user *user_buf, size_t count, | ||
1032 | loff_t *ppos) | ||
1033 | { | ||
1034 | struct wl1271 *wl = file->private_data; | ||
1035 | struct wlcore_partition_set part, old_part; | ||
1036 | size_t bytes = count; | ||
1037 | int ret; | ||
1038 | char *buf; | ||
1039 | |||
1040 | /* only requests of dword-aligned size and offset are supported */ | ||
1041 | if (bytes % 4) | ||
1042 | return -EINVAL; | ||
1043 | |||
1044 | if (*ppos % 4) | ||
1045 | return -EINVAL; | ||
1046 | |||
1047 | /* function should return in reasonable time */ | ||
1048 | bytes = min(bytes, WLCORE_MAX_BLOCK_SIZE); | ||
1049 | |||
1050 | if (bytes == 0) | ||
1051 | return -EINVAL; | ||
1052 | |||
1053 | memset(&part, 0, sizeof(part)); | ||
1054 | part.mem.start = file->f_pos; | ||
1055 | part.mem.size = bytes; | ||
1056 | |||
1057 | buf = kmalloc(bytes, GFP_KERNEL); | ||
1058 | if (!buf) | ||
1059 | return -ENOMEM; | ||
1060 | |||
1061 | mutex_lock(&wl->mutex); | ||
1062 | |||
1063 | if (wl->state == WL1271_STATE_OFF) { | ||
1064 | ret = -EFAULT; | ||
1065 | goto skip_read; | ||
1066 | } | ||
1067 | |||
1068 | ret = wl1271_ps_elp_wakeup(wl); | ||
1069 | if (ret < 0) | ||
1070 | goto skip_read; | ||
1071 | |||
1072 | /* store current partition and switch partition */ | ||
1073 | memcpy(&old_part, &wl->curr_part, sizeof(old_part)); | ||
1074 | ret = wlcore_set_partition(wl, &part); | ||
1075 | if (ret < 0) | ||
1076 | goto part_err; | ||
1077 | |||
1078 | ret = wlcore_raw_read(wl, 0, buf, bytes, false); | ||
1079 | if (ret < 0) | ||
1080 | goto read_err; | ||
1081 | |||
1082 | read_err: | ||
1083 | /* recover partition */ | ||
1084 | ret = wlcore_set_partition(wl, &old_part); | ||
1085 | if (ret < 0) | ||
1086 | goto part_err; | ||
1087 | |||
1088 | part_err: | ||
1089 | wl1271_ps_elp_sleep(wl); | ||
1090 | |||
1091 | skip_read: | ||
1092 | mutex_unlock(&wl->mutex); | ||
1093 | |||
1094 | if (ret == 0) { | ||
1095 | ret = copy_to_user(user_buf, buf, bytes); | ||
1096 | if (ret < bytes) { | ||
1097 | bytes -= ret; | ||
1098 | *ppos += bytes; | ||
1099 | ret = 0; | ||
1100 | } else { | ||
1101 | ret = -EFAULT; | ||
1102 | } | ||
1103 | } | ||
1104 | |||
1105 | kfree(buf); | ||
1106 | |||
1107 | return ((ret == 0) ? bytes : ret); | ||
1108 | } | ||
1109 | |||
1110 | static ssize_t dev_mem_write(struct file *file, const char __user *user_buf, | ||
1111 | size_t count, loff_t *ppos) | ||
1112 | { | ||
1113 | struct wl1271 *wl = file->private_data; | ||
1114 | struct wlcore_partition_set part, old_part; | ||
1115 | size_t bytes = count; | ||
1116 | int ret; | ||
1117 | char *buf; | ||
1118 | |||
1119 | /* only requests of dword-aligned size and offset are supported */ | ||
1120 | if (bytes % 4) | ||
1121 | return -EINVAL; | ||
1122 | |||
1123 | if (*ppos % 4) | ||
1124 | return -EINVAL; | ||
1125 | |||
1126 | /* function should return in reasonable time */ | ||
1127 | bytes = min(bytes, WLCORE_MAX_BLOCK_SIZE); | ||
1128 | |||
1129 | if (bytes == 0) | ||
1130 | return -EINVAL; | ||
1131 | |||
1132 | memset(&part, 0, sizeof(part)); | ||
1133 | part.mem.start = file->f_pos; | ||
1134 | part.mem.size = bytes; | ||
1135 | |||
1136 | buf = kmalloc(bytes, GFP_KERNEL); | ||
1137 | if (!buf) | ||
1138 | return -ENOMEM; | ||
1139 | |||
1140 | ret = copy_from_user(buf, user_buf, bytes); | ||
1141 | if (ret) { | ||
1142 | ret = -EFAULT; | ||
1143 | goto err_out; | ||
1144 | } | ||
1145 | |||
1146 | mutex_lock(&wl->mutex); | ||
1147 | |||
1148 | if (wl->state == WL1271_STATE_OFF) { | ||
1149 | ret = -EFAULT; | ||
1150 | goto skip_write; | ||
1151 | } | ||
1152 | |||
1153 | ret = wl1271_ps_elp_wakeup(wl); | ||
1154 | if (ret < 0) | ||
1155 | goto skip_write; | ||
1156 | |||
1157 | /* store current partition and switch partition */ | ||
1158 | memcpy(&old_part, &wl->curr_part, sizeof(old_part)); | ||
1159 | ret = wlcore_set_partition(wl, &part); | ||
1160 | if (ret < 0) | ||
1161 | goto part_err; | ||
1162 | |||
1163 | ret = wlcore_raw_write(wl, 0, buf, bytes, false); | ||
1164 | if (ret < 0) | ||
1165 | goto write_err; | ||
1166 | |||
1167 | write_err: | ||
1168 | /* recover partition */ | ||
1169 | ret = wlcore_set_partition(wl, &old_part); | ||
1170 | if (ret < 0) | ||
1171 | goto part_err; | ||
1172 | |||
1173 | part_err: | ||
1174 | wl1271_ps_elp_sleep(wl); | ||
1175 | |||
1176 | skip_write: | ||
1177 | mutex_unlock(&wl->mutex); | ||
1178 | |||
1179 | if (ret == 0) | ||
1180 | *ppos += bytes; | ||
1181 | |||
1182 | err_out: | ||
1183 | kfree(buf); | ||
1184 | |||
1185 | return ((ret == 0) ? bytes : ret); | ||
1186 | } | ||
1187 | |||
1188 | static loff_t dev_mem_seek(struct file *file, loff_t offset, int orig) | ||
1189 | { | ||
1190 | loff_t ret; | ||
1191 | |||
1192 | /* only requests of dword-aligned size and offset are supported */ | ||
1193 | if (offset % 4) | ||
1194 | return -EINVAL; | ||
1195 | |||
1196 | switch (orig) { | ||
1197 | case SEEK_SET: | ||
1198 | file->f_pos = offset; | ||
1199 | ret = file->f_pos; | ||
1200 | break; | ||
1201 | case SEEK_CUR: | ||
1202 | file->f_pos += offset; | ||
1203 | ret = file->f_pos; | ||
1204 | break; | ||
1205 | default: | ||
1206 | ret = -EINVAL; | ||
1207 | } | ||
1208 | |||
1209 | return ret; | ||
1210 | } | ||
1211 | |||
1212 | static const struct file_operations dev_mem_ops = { | ||
1213 | .open = simple_open, | ||
1214 | .read = dev_mem_read, | ||
1215 | .write = dev_mem_write, | ||
1216 | .llseek = dev_mem_seek, | ||
1217 | }; | ||
1218 | |||
966 | static int wl1271_debugfs_add_files(struct wl1271 *wl, | 1219 | static int wl1271_debugfs_add_files(struct wl1271 *wl, |
967 | struct dentry *rootdir) | 1220 | struct dentry *rootdir) |
968 | { | 1221 | { |
@@ -988,6 +1241,7 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl, | |||
988 | DEBUGFS_ADD(irq_blk_threshold, rootdir); | 1241 | DEBUGFS_ADD(irq_blk_threshold, rootdir); |
989 | DEBUGFS_ADD(irq_timeout, rootdir); | 1242 | DEBUGFS_ADD(irq_timeout, rootdir); |
990 | DEBUGFS_ADD(fw_stats_raw, rootdir); | 1243 | DEBUGFS_ADD(fw_stats_raw, rootdir); |
1244 | DEBUGFS_ADD(sleep_auth, rootdir); | ||
991 | 1245 | ||
992 | streaming = debugfs_create_dir("rx_streaming", rootdir); | 1246 | streaming = debugfs_create_dir("rx_streaming", rootdir); |
993 | if (!streaming || IS_ERR(streaming)) | 1247 | if (!streaming || IS_ERR(streaming)) |
@@ -996,6 +1250,7 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl, | |||
996 | DEBUGFS_ADD_PREFIX(rx_streaming, interval, streaming); | 1250 | DEBUGFS_ADD_PREFIX(rx_streaming, interval, streaming); |
997 | DEBUGFS_ADD_PREFIX(rx_streaming, always, streaming); | 1251 | DEBUGFS_ADD_PREFIX(rx_streaming, always, streaming); |
998 | 1252 | ||
1253 | DEBUGFS_ADD_PREFIX(dev, mem, rootdir); | ||
999 | 1254 | ||
1000 | return 0; | 1255 | return 0; |
1001 | 1256 | ||
diff --git a/drivers/net/wireless/ti/wlcore/event.c b/drivers/net/wireless/ti/wlcore/event.c index c976f040986..48907054d49 100644 --- a/drivers/net/wireless/ti/wlcore/event.c +++ b/drivers/net/wireless/ti/wlcore/event.c | |||
@@ -105,6 +105,7 @@ static int wl1271_event_process(struct wl1271 *wl) | |||
105 | u32 vector; | 105 | u32 vector; |
106 | bool disconnect_sta = false; | 106 | bool disconnect_sta = false; |
107 | unsigned long sta_bitmap = 0; | 107 | unsigned long sta_bitmap = 0; |
108 | int ret; | ||
108 | 109 | ||
109 | wl1271_event_mbox_dump(mbox); | 110 | wl1271_event_mbox_dump(mbox); |
110 | 111 | ||
@@ -228,7 +229,9 @@ static int wl1271_event_process(struct wl1271 *wl) | |||
228 | 229 | ||
229 | if ((vector & DUMMY_PACKET_EVENT_ID)) { | 230 | if ((vector & DUMMY_PACKET_EVENT_ID)) { |
230 | wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID"); | 231 | wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID"); |
231 | wl1271_tx_dummy_packet(wl); | 232 | ret = wl1271_tx_dummy_packet(wl); |
233 | if (ret < 0) | ||
234 | return ret; | ||
232 | } | 235 | } |
233 | 236 | ||
234 | /* | 237 | /* |
@@ -301,8 +304,10 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num) | |||
301 | return -EINVAL; | 304 | return -EINVAL; |
302 | 305 | ||
303 | /* first we read the mbox descriptor */ | 306 | /* first we read the mbox descriptor */ |
304 | wl1271_read(wl, wl->mbox_ptr[mbox_num], wl->mbox, | 307 | ret = wlcore_read(wl, wl->mbox_ptr[mbox_num], wl->mbox, |
305 | sizeof(*wl->mbox), false); | 308 | sizeof(*wl->mbox), false); |
309 | if (ret < 0) | ||
310 | return ret; | ||
306 | 311 | ||
307 | /* process the descriptor */ | 312 | /* process the descriptor */ |
308 | ret = wl1271_event_process(wl); | 313 | ret = wl1271_event_process(wl); |
@@ -313,7 +318,7 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num) | |||
313 | * TODO: we just need this because one bit is in a different | 318 | * TODO: we just need this because one bit is in a different |
314 | * place. Is there any better way? | 319 | * place. Is there any better way? |
315 | */ | 320 | */ |
316 | wl->ops->ack_event(wl); | 321 | ret = wl->ops->ack_event(wl); |
317 | 322 | ||
318 | return 0; | 323 | return ret; |
319 | } | 324 | } |
diff --git a/drivers/net/wireless/ti/wlcore/hw_ops.h b/drivers/net/wireless/ti/wlcore/hw_ops.h index 9e7787ba961..2673d783ec1 100644 --- a/drivers/net/wireless/ti/wlcore/hw_ops.h +++ b/drivers/net/wireless/ti/wlcore/hw_ops.h | |||
@@ -65,11 +65,13 @@ wlcore_hw_get_rx_buf_align(struct wl1271 *wl, u32 rx_desc) | |||
65 | return wl->ops->get_rx_buf_align(wl, rx_desc); | 65 | return wl->ops->get_rx_buf_align(wl, rx_desc); |
66 | } | 66 | } |
67 | 67 | ||
68 | static inline void | 68 | static inline int |
69 | wlcore_hw_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len) | 69 | wlcore_hw_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len) |
70 | { | 70 | { |
71 | if (wl->ops->prepare_read) | 71 | if (wl->ops->prepare_read) |
72 | wl->ops->prepare_read(wl, rx_desc, len); | 72 | return wl->ops->prepare_read(wl, rx_desc, len); |
73 | |||
74 | return 0; | ||
73 | } | 75 | } |
74 | 76 | ||
75 | static inline u32 | 77 | static inline u32 |
@@ -81,10 +83,12 @@ wlcore_hw_get_rx_packet_len(struct wl1271 *wl, void *rx_data, u32 data_len) | |||
81 | return wl->ops->get_rx_packet_len(wl, rx_data, data_len); | 83 | return wl->ops->get_rx_packet_len(wl, rx_data, data_len); |
82 | } | 84 | } |
83 | 85 | ||
84 | static inline void wlcore_hw_tx_delayed_compl(struct wl1271 *wl) | 86 | static inline int wlcore_hw_tx_delayed_compl(struct wl1271 *wl) |
85 | { | 87 | { |
86 | if (wl->ops->tx_delayed_compl) | 88 | if (wl->ops->tx_delayed_compl) |
87 | wl->ops->tx_delayed_compl(wl); | 89 | return wl->ops->tx_delayed_compl(wl); |
90 | |||
91 | return 0; | ||
88 | } | 92 | } |
89 | 93 | ||
90 | static inline void wlcore_hw_tx_immediate_compl(struct wl1271 *wl) | 94 | static inline void wlcore_hw_tx_immediate_compl(struct wl1271 *wl) |
diff --git a/drivers/net/wireless/ti/wlcore/ini.h b/drivers/net/wireless/ti/wlcore/ini.h index 4cf9ecc5621..d24fe3bbc67 100644 --- a/drivers/net/wireless/ti/wlcore/ini.h +++ b/drivers/net/wireless/ti/wlcore/ini.h | |||
@@ -172,7 +172,19 @@ struct wl128x_ini_fem_params_5 { | |||
172 | 172 | ||
173 | /* NVS data structure */ | 173 | /* NVS data structure */ |
174 | #define WL1271_INI_NVS_SECTION_SIZE 468 | 174 | #define WL1271_INI_NVS_SECTION_SIZE 468 |
175 | #define WL1271_INI_FEM_MODULE_COUNT 2 | 175 | |
176 | /* We have four FEM module types: 0-RFMD, 1-TQS, 2-SKW, 3-TQS_HP */ | ||
177 | #define WL1271_INI_FEM_MODULE_COUNT 4 | ||
178 | |||
179 | /* | ||
180 | * In NVS we only store two FEM module entries - | ||
181 | * FEM modules 0,2,3 are stored in entry 0 | ||
182 | * FEM module 1 is stored in entry 1 | ||
183 | */ | ||
184 | #define WL12XX_NVS_FEM_MODULE_COUNT 2 | ||
185 | |||
186 | #define WL12XX_FEM_TO_NVS_ENTRY(ini_fem_module) \ | ||
187 | ((ini_fem_module) == 1 ? 1 : 0) | ||
176 | 188 | ||
177 | #define WL1271_INI_LEGACY_NVS_FILE_SIZE 800 | 189 | #define WL1271_INI_LEGACY_NVS_FILE_SIZE 800 |
178 | 190 | ||
@@ -188,13 +200,13 @@ struct wl1271_nvs_file { | |||
188 | struct { | 200 | struct { |
189 | struct wl1271_ini_fem_params_2 params; | 201 | struct wl1271_ini_fem_params_2 params; |
190 | u8 padding; | 202 | u8 padding; |
191 | } dyn_radio_params_2[WL1271_INI_FEM_MODULE_COUNT]; | 203 | } dyn_radio_params_2[WL12XX_NVS_FEM_MODULE_COUNT]; |
192 | struct wl1271_ini_band_params_5 stat_radio_params_5; | 204 | struct wl1271_ini_band_params_5 stat_radio_params_5; |
193 | u8 padding3; | 205 | u8 padding3; |
194 | struct { | 206 | struct { |
195 | struct wl1271_ini_fem_params_5 params; | 207 | struct wl1271_ini_fem_params_5 params; |
196 | u8 padding; | 208 | u8 padding; |
197 | } dyn_radio_params_5[WL1271_INI_FEM_MODULE_COUNT]; | 209 | } dyn_radio_params_5[WL12XX_NVS_FEM_MODULE_COUNT]; |
198 | } __packed; | 210 | } __packed; |
199 | 211 | ||
200 | struct wl128x_nvs_file { | 212 | struct wl128x_nvs_file { |
@@ -209,12 +221,12 @@ struct wl128x_nvs_file { | |||
209 | struct { | 221 | struct { |
210 | struct wl128x_ini_fem_params_2 params; | 222 | struct wl128x_ini_fem_params_2 params; |
211 | u8 padding; | 223 | u8 padding; |
212 | } dyn_radio_params_2[WL1271_INI_FEM_MODULE_COUNT]; | 224 | } dyn_radio_params_2[WL12XX_NVS_FEM_MODULE_COUNT]; |
213 | struct wl128x_ini_band_params_5 stat_radio_params_5; | 225 | struct wl128x_ini_band_params_5 stat_radio_params_5; |
214 | u8 padding3; | 226 | u8 padding3; |
215 | struct { | 227 | struct { |
216 | struct wl128x_ini_fem_params_5 params; | 228 | struct wl128x_ini_fem_params_5 params; |
217 | u8 padding; | 229 | u8 padding; |
218 | } dyn_radio_params_5[WL1271_INI_FEM_MODULE_COUNT]; | 230 | } dyn_radio_params_5[WL12XX_NVS_FEM_MODULE_COUNT]; |
219 | } __packed; | 231 | } __packed; |
220 | #endif | 232 | #endif |
diff --git a/drivers/net/wireless/ti/wlcore/init.c b/drivers/net/wireless/ti/wlcore/init.c index 645abd4b660..8a8a8971bef 100644 --- a/drivers/net/wireless/ti/wlcore/init.c +++ b/drivers/net/wireless/ti/wlcore/init.c | |||
@@ -554,29 +554,28 @@ int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif) | |||
554 | bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); | 554 | bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); |
555 | int ret, i; | 555 | int ret, i; |
556 | 556 | ||
557 | /* | 557 | /* consider all existing roles before configuring psm. */ |
558 | * consider all existing roles before configuring psm. | 558 | |
559 | * TODO: reconfigure on interface removal. | 559 | if (wl->ap_count == 0 && is_ap) { /* first AP */ |
560 | */ | 560 | /* Configure for power always on */ |
561 | if (!wl->ap_count) { | 561 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); |
562 | if (is_ap) { | 562 | if (ret < 0) |
563 | /* Configure for power always on */ | 563 | return ret; |
564 | /* first STA, no APs */ | ||
565 | } else if (wl->sta_count == 0 && wl->ap_count == 0 && !is_ap) { | ||
566 | u8 sta_auth = wl->conf.conn.sta_sleep_auth; | ||
567 | /* Configure for power according to debugfs */ | ||
568 | if (sta_auth != WL1271_PSM_ILLEGAL) | ||
569 | ret = wl1271_acx_sleep_auth(wl, sta_auth); | ||
570 | /* Configure for power always on */ | ||
571 | else if (wl->quirks & WLCORE_QUIRK_NO_ELP) | ||
564 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); | 572 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); |
565 | if (ret < 0) | 573 | /* Configure for ELP power saving */ |
566 | return ret; | 574 | else |
567 | } else if (!wl->sta_count) { | 575 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP); |
568 | if (wl->quirks & WLCORE_QUIRK_NO_ELP) { | 576 | |
569 | /* Configure for power always on */ | 577 | if (ret < 0) |
570 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); | 578 | return ret; |
571 | if (ret < 0) | ||
572 | return ret; | ||
573 | } else { | ||
574 | /* Configure for ELP power saving */ | ||
575 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP); | ||
576 | if (ret < 0) | ||
577 | return ret; | ||
578 | } | ||
579 | } | ||
580 | } | 579 | } |
581 | 580 | ||
582 | /* Mode specific init */ | 581 | /* Mode specific init */ |
diff --git a/drivers/net/wireless/ti/wlcore/io.c b/drivers/net/wireless/ti/wlcore/io.c index 7cd0081aede..9976219c4e4 100644 --- a/drivers/net/wireless/ti/wlcore/io.c +++ b/drivers/net/wireless/ti/wlcore/io.c | |||
@@ -48,6 +48,12 @@ void wlcore_disable_interrupts(struct wl1271 *wl) | |||
48 | } | 48 | } |
49 | EXPORT_SYMBOL_GPL(wlcore_disable_interrupts); | 49 | EXPORT_SYMBOL_GPL(wlcore_disable_interrupts); |
50 | 50 | ||
51 | void wlcore_disable_interrupts_nosync(struct wl1271 *wl) | ||
52 | { | ||
53 | disable_irq_nosync(wl->irq); | ||
54 | } | ||
55 | EXPORT_SYMBOL_GPL(wlcore_disable_interrupts_nosync); | ||
56 | |||
51 | void wlcore_enable_interrupts(struct wl1271 *wl) | 57 | void wlcore_enable_interrupts(struct wl1271 *wl) |
52 | { | 58 | { |
53 | enable_irq(wl->irq); | 59 | enable_irq(wl->irq); |
@@ -122,9 +128,11 @@ EXPORT_SYMBOL_GPL(wlcore_translate_addr); | |||
122 | * | | | 128 | * | | |
123 | * | 129 | * |
124 | */ | 130 | */ |
125 | void wlcore_set_partition(struct wl1271 *wl, | 131 | int wlcore_set_partition(struct wl1271 *wl, |
126 | const struct wlcore_partition_set *p) | 132 | const struct wlcore_partition_set *p) |
127 | { | 133 | { |
134 | int ret; | ||
135 | |||
128 | /* copy partition info */ | 136 | /* copy partition info */ |
129 | memcpy(&wl->curr_part, p, sizeof(*p)); | 137 | memcpy(&wl->curr_part, p, sizeof(*p)); |
130 | 138 | ||
@@ -137,28 +145,41 @@ void wlcore_set_partition(struct wl1271 *wl, | |||
137 | wl1271_debug(DEBUG_IO, "mem3_start %08X mem3_size %08X", | 145 | wl1271_debug(DEBUG_IO, "mem3_start %08X mem3_size %08X", |
138 | p->mem3.start, p->mem3.size); | 146 | p->mem3.start, p->mem3.size); |
139 | 147 | ||
140 | wl1271_raw_write32(wl, HW_PART0_START_ADDR, p->mem.start); | 148 | ret = wlcore_raw_write32(wl, HW_PART0_START_ADDR, p->mem.start); |
141 | wl1271_raw_write32(wl, HW_PART0_SIZE_ADDR, p->mem.size); | 149 | if (ret < 0) |
142 | wl1271_raw_write32(wl, HW_PART1_START_ADDR, p->reg.start); | 150 | goto out; |
143 | wl1271_raw_write32(wl, HW_PART1_SIZE_ADDR, p->reg.size); | 151 | |
144 | wl1271_raw_write32(wl, HW_PART2_START_ADDR, p->mem2.start); | 152 | ret = wlcore_raw_write32(wl, HW_PART0_SIZE_ADDR, p->mem.size); |
145 | wl1271_raw_write32(wl, HW_PART2_SIZE_ADDR, p->mem2.size); | 153 | if (ret < 0) |
154 | goto out; | ||
155 | |||
156 | ret = wlcore_raw_write32(wl, HW_PART1_START_ADDR, p->reg.start); | ||
157 | if (ret < 0) | ||
158 | goto out; | ||
159 | |||
160 | ret = wlcore_raw_write32(wl, HW_PART1_SIZE_ADDR, p->reg.size); | ||
161 | if (ret < 0) | ||
162 | goto out; | ||
163 | |||
164 | ret = wlcore_raw_write32(wl, HW_PART2_START_ADDR, p->mem2.start); | ||
165 | if (ret < 0) | ||
166 | goto out; | ||
167 | |||
168 | ret = wlcore_raw_write32(wl, HW_PART2_SIZE_ADDR, p->mem2.size); | ||
169 | if (ret < 0) | ||
170 | goto out; | ||
171 | |||
146 | /* | 172 | /* |
147 | * We don't need the size of the last partition, as it is | 173 | * We don't need the size of the last partition, as it is |
148 | * automatically calculated based on the total memory size and | 174 | * automatically calculated based on the total memory size and |
149 | * the sizes of the previous partitions. | 175 | * the sizes of the previous partitions. |
150 | */ | 176 | */ |
151 | wl1271_raw_write32(wl, HW_PART3_START_ADDR, p->mem3.start); | 177 | ret = wlcore_raw_write32(wl, HW_PART3_START_ADDR, p->mem3.start); |
152 | } | ||
153 | EXPORT_SYMBOL_GPL(wlcore_set_partition); | ||
154 | 178 | ||
155 | void wlcore_select_partition(struct wl1271 *wl, u8 part) | 179 | out: |
156 | { | 180 | return ret; |
157 | wl1271_debug(DEBUG_IO, "setting partition %d", part); | ||
158 | |||
159 | wlcore_set_partition(wl, &wl->ptable[part]); | ||
160 | } | 181 | } |
161 | EXPORT_SYMBOL_GPL(wlcore_select_partition); | 182 | EXPORT_SYMBOL_GPL(wlcore_set_partition); |
162 | 183 | ||
163 | void wl1271_io_reset(struct wl1271 *wl) | 184 | void wl1271_io_reset(struct wl1271 *wl) |
164 | { | 185 | { |
diff --git a/drivers/net/wireless/ti/wlcore/io.h b/drivers/net/wireless/ti/wlcore/io.h index 8942954b56a..fef80adc8bf 100644 --- a/drivers/net/wireless/ti/wlcore/io.h +++ b/drivers/net/wireless/ti/wlcore/io.h | |||
@@ -45,6 +45,7 @@ | |||
45 | struct wl1271; | 45 | struct wl1271; |
46 | 46 | ||
47 | void wlcore_disable_interrupts(struct wl1271 *wl); | 47 | void wlcore_disable_interrupts(struct wl1271 *wl); |
48 | void wlcore_disable_interrupts_nosync(struct wl1271 *wl); | ||
48 | void wlcore_enable_interrupts(struct wl1271 *wl); | 49 | void wlcore_enable_interrupts(struct wl1271 *wl); |
49 | 50 | ||
50 | void wl1271_io_reset(struct wl1271 *wl); | 51 | void wl1271_io_reset(struct wl1271 *wl); |
@@ -52,79 +53,113 @@ void wl1271_io_init(struct wl1271 *wl); | |||
52 | int wlcore_translate_addr(struct wl1271 *wl, int addr); | 53 | int wlcore_translate_addr(struct wl1271 *wl, int addr); |
53 | 54 | ||
54 | /* Raw target IO, address is not translated */ | 55 | /* Raw target IO, address is not translated */ |
55 | static inline void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf, | 56 | static inline int __must_check wlcore_raw_write(struct wl1271 *wl, int addr, |
56 | size_t len, bool fixed) | 57 | void *buf, size_t len, |
58 | bool fixed) | ||
57 | { | 59 | { |
58 | wl->if_ops->write(wl->dev, addr, buf, len, fixed); | 60 | int ret; |
61 | |||
62 | if (test_bit(WL1271_FLAG_SDIO_FAILED, &wl->flags)) | ||
63 | return -EIO; | ||
64 | |||
65 | ret = wl->if_ops->write(wl->dev, addr, buf, len, fixed); | ||
66 | if (ret) | ||
67 | set_bit(WL1271_FLAG_SDIO_FAILED, &wl->flags); | ||
68 | |||
69 | return ret; | ||
59 | } | 70 | } |
60 | 71 | ||
61 | static inline void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf, | 72 | static inline int __must_check wlcore_raw_read(struct wl1271 *wl, int addr, |
62 | size_t len, bool fixed) | 73 | void *buf, size_t len, |
74 | bool fixed) | ||
63 | { | 75 | { |
64 | wl->if_ops->read(wl->dev, addr, buf, len, fixed); | 76 | int ret; |
77 | |||
78 | if (test_bit(WL1271_FLAG_SDIO_FAILED, &wl->flags)) | ||
79 | return -EIO; | ||
80 | |||
81 | ret = wl->if_ops->read(wl->dev, addr, buf, len, fixed); | ||
82 | if (ret) | ||
83 | set_bit(WL1271_FLAG_SDIO_FAILED, &wl->flags); | ||
84 | |||
85 | return ret; | ||
65 | } | 86 | } |
66 | 87 | ||
67 | static inline void wlcore_raw_read_data(struct wl1271 *wl, int reg, void *buf, | 88 | static inline int __must_check wlcore_raw_read_data(struct wl1271 *wl, int reg, |
68 | size_t len, bool fixed) | 89 | void *buf, size_t len, |
90 | bool fixed) | ||
69 | { | 91 | { |
70 | wl1271_raw_read(wl, wl->rtable[reg], buf, len, fixed); | 92 | return wlcore_raw_read(wl, wl->rtable[reg], buf, len, fixed); |
71 | } | 93 | } |
72 | 94 | ||
73 | static inline void wlcore_raw_write_data(struct wl1271 *wl, int reg, void *buf, | 95 | static inline int __must_check wlcore_raw_write_data(struct wl1271 *wl, int reg, |
74 | size_t len, bool fixed) | 96 | void *buf, size_t len, |
97 | bool fixed) | ||
75 | { | 98 | { |
76 | wl1271_raw_write(wl, wl->rtable[reg], buf, len, fixed); | 99 | return wlcore_raw_write(wl, wl->rtable[reg], buf, len, fixed); |
77 | } | 100 | } |
78 | 101 | ||
79 | static inline u32 wl1271_raw_read32(struct wl1271 *wl, int addr) | 102 | static inline int __must_check wlcore_raw_read32(struct wl1271 *wl, int addr, |
103 | u32 *val) | ||
80 | { | 104 | { |
81 | wl1271_raw_read(wl, addr, &wl->buffer_32, | 105 | int ret; |
82 | sizeof(wl->buffer_32), false); | 106 | |
107 | ret = wlcore_raw_read(wl, addr, &wl->buffer_32, | ||
108 | sizeof(wl->buffer_32), false); | ||
109 | if (ret < 0) | ||
110 | return ret; | ||
111 | |||
112 | if (val) | ||
113 | *val = le32_to_cpu(wl->buffer_32); | ||
83 | 114 | ||
84 | return le32_to_cpu(wl->buffer_32); | 115 | return 0; |
85 | } | 116 | } |
86 | 117 | ||
87 | static inline void wl1271_raw_write32(struct wl1271 *wl, int addr, u32 val) | 118 | static inline int __must_check wlcore_raw_write32(struct wl1271 *wl, int addr, |
119 | u32 val) | ||
88 | { | 120 | { |
89 | wl->buffer_32 = cpu_to_le32(val); | 121 | wl->buffer_32 = cpu_to_le32(val); |
90 | wl1271_raw_write(wl, addr, &wl->buffer_32, | 122 | return wlcore_raw_write(wl, addr, &wl->buffer_32, |
91 | sizeof(wl->buffer_32), false); | 123 | sizeof(wl->buffer_32), false); |
92 | } | 124 | } |
93 | 125 | ||
94 | static inline void wl1271_read(struct wl1271 *wl, int addr, void *buf, | 126 | static inline int __must_check wlcore_read(struct wl1271 *wl, int addr, |
95 | size_t len, bool fixed) | 127 | void *buf, size_t len, bool fixed) |
96 | { | 128 | { |
97 | int physical; | 129 | int physical; |
98 | 130 | ||
99 | physical = wlcore_translate_addr(wl, addr); | 131 | physical = wlcore_translate_addr(wl, addr); |
100 | 132 | ||
101 | wl1271_raw_read(wl, physical, buf, len, fixed); | 133 | return wlcore_raw_read(wl, physical, buf, len, fixed); |
102 | } | 134 | } |
103 | 135 | ||
104 | static inline void wl1271_write(struct wl1271 *wl, int addr, void *buf, | 136 | static inline int __must_check wlcore_write(struct wl1271 *wl, int addr, |
105 | size_t len, bool fixed) | 137 | void *buf, size_t len, bool fixed) |
106 | { | 138 | { |
107 | int physical; | 139 | int physical; |
108 | 140 | ||
109 | physical = wlcore_translate_addr(wl, addr); | 141 | physical = wlcore_translate_addr(wl, addr); |
110 | 142 | ||
111 | wl1271_raw_write(wl, physical, buf, len, fixed); | 143 | return wlcore_raw_write(wl, physical, buf, len, fixed); |
112 | } | 144 | } |
113 | 145 | ||
114 | static inline void wlcore_write_data(struct wl1271 *wl, int reg, void *buf, | 146 | static inline int __must_check wlcore_write_data(struct wl1271 *wl, int reg, |
115 | size_t len, bool fixed) | 147 | void *buf, size_t len, |
148 | bool fixed) | ||
116 | { | 149 | { |
117 | wl1271_write(wl, wl->rtable[reg], buf, len, fixed); | 150 | return wlcore_write(wl, wl->rtable[reg], buf, len, fixed); |
118 | } | 151 | } |
119 | 152 | ||
120 | static inline void wlcore_read_data(struct wl1271 *wl, int reg, void *buf, | 153 | static inline int __must_check wlcore_read_data(struct wl1271 *wl, int reg, |
121 | size_t len, bool fixed) | 154 | void *buf, size_t len, |
155 | bool fixed) | ||
122 | { | 156 | { |
123 | wl1271_read(wl, wl->rtable[reg], buf, len, fixed); | 157 | return wlcore_read(wl, wl->rtable[reg], buf, len, fixed); |
124 | } | 158 | } |
125 | 159 | ||
126 | static inline void wl1271_read_hwaddr(struct wl1271 *wl, int hwaddr, | 160 | static inline int __must_check wlcore_read_hwaddr(struct wl1271 *wl, int hwaddr, |
127 | void *buf, size_t len, bool fixed) | 161 | void *buf, size_t len, |
162 | bool fixed) | ||
128 | { | 163 | { |
129 | int physical; | 164 | int physical; |
130 | int addr; | 165 | int addr; |
@@ -134,34 +169,47 @@ static inline void wl1271_read_hwaddr(struct wl1271 *wl, int hwaddr, | |||
134 | 169 | ||
135 | physical = wlcore_translate_addr(wl, addr); | 170 | physical = wlcore_translate_addr(wl, addr); |
136 | 171 | ||
137 | wl1271_raw_read(wl, physical, buf, len, fixed); | 172 | return wlcore_raw_read(wl, physical, buf, len, fixed); |
138 | } | 173 | } |
139 | 174 | ||
140 | static inline u32 wl1271_read32(struct wl1271 *wl, int addr) | 175 | static inline int __must_check wlcore_read32(struct wl1271 *wl, int addr, |
176 | u32 *val) | ||
141 | { | 177 | { |
142 | return wl1271_raw_read32(wl, wlcore_translate_addr(wl, addr)); | 178 | return wlcore_raw_read32(wl, wlcore_translate_addr(wl, addr), val); |
143 | } | 179 | } |
144 | 180 | ||
145 | static inline void wl1271_write32(struct wl1271 *wl, int addr, u32 val) | 181 | static inline int __must_check wlcore_write32(struct wl1271 *wl, int addr, |
182 | u32 val) | ||
146 | { | 183 | { |
147 | wl1271_raw_write32(wl, wlcore_translate_addr(wl, addr), val); | 184 | return wlcore_raw_write32(wl, wlcore_translate_addr(wl, addr), val); |
148 | } | 185 | } |
149 | 186 | ||
150 | static inline u32 wlcore_read_reg(struct wl1271 *wl, int reg) | 187 | static inline int __must_check wlcore_read_reg(struct wl1271 *wl, int reg, |
188 | u32 *val) | ||
151 | { | 189 | { |
152 | return wl1271_raw_read32(wl, | 190 | return wlcore_raw_read32(wl, |
153 | wlcore_translate_addr(wl, wl->rtable[reg])); | 191 | wlcore_translate_addr(wl, wl->rtable[reg]), |
192 | val); | ||
154 | } | 193 | } |
155 | 194 | ||
156 | static inline void wlcore_write_reg(struct wl1271 *wl, int reg, u32 val) | 195 | static inline int __must_check wlcore_write_reg(struct wl1271 *wl, int reg, |
196 | u32 val) | ||
157 | { | 197 | { |
158 | wl1271_raw_write32(wl, wlcore_translate_addr(wl, wl->rtable[reg]), val); | 198 | return wlcore_raw_write32(wl, |
199 | wlcore_translate_addr(wl, wl->rtable[reg]), | ||
200 | val); | ||
159 | } | 201 | } |
160 | 202 | ||
161 | static inline void wl1271_power_off(struct wl1271 *wl) | 203 | static inline void wl1271_power_off(struct wl1271 *wl) |
162 | { | 204 | { |
163 | wl->if_ops->power(wl->dev, false); | 205 | int ret; |
164 | clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | 206 | |
207 | if (!test_bit(WL1271_FLAG_GPIO_POWER, &wl->flags)) | ||
208 | return; | ||
209 | |||
210 | ret = wl->if_ops->power(wl->dev, false); | ||
211 | if (!ret) | ||
212 | clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
165 | } | 213 | } |
166 | 214 | ||
167 | static inline int wl1271_power_on(struct wl1271 *wl) | 215 | static inline int wl1271_power_on(struct wl1271 *wl) |
@@ -173,8 +221,8 @@ static inline int wl1271_power_on(struct wl1271 *wl) | |||
173 | return ret; | 221 | return ret; |
174 | } | 222 | } |
175 | 223 | ||
176 | void wlcore_set_partition(struct wl1271 *wl, | 224 | int wlcore_set_partition(struct wl1271 *wl, |
177 | const struct wlcore_partition_set *p); | 225 | const struct wlcore_partition_set *p); |
178 | 226 | ||
179 | bool wl1271_set_block_size(struct wl1271 *wl); | 227 | bool wl1271_set_block_size(struct wl1271 *wl); |
180 | 228 | ||
@@ -182,6 +230,4 @@ bool wl1271_set_block_size(struct wl1271 *wl); | |||
182 | 230 | ||
183 | int wl1271_tx_dummy_packet(struct wl1271 *wl); | 231 | int wl1271_tx_dummy_packet(struct wl1271 *wl); |
184 | 232 | ||
185 | void wlcore_select_partition(struct wl1271 *wl, u8 part); | ||
186 | |||
187 | #endif | 233 | #endif |
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 747a997bc60..0cc9a024022 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c | |||
@@ -378,9 +378,9 @@ static void wl12xx_irq_update_links_status(struct wl1271 *wl, | |||
378 | } | 378 | } |
379 | } | 379 | } |
380 | 380 | ||
381 | static void wl12xx_fw_status(struct wl1271 *wl, | 381 | static int wlcore_fw_status(struct wl1271 *wl, |
382 | struct wl_fw_status_1 *status_1, | 382 | struct wl_fw_status_1 *status_1, |
383 | struct wl_fw_status_2 *status_2) | 383 | struct wl_fw_status_2 *status_2) |
384 | { | 384 | { |
385 | struct wl12xx_vif *wlvif; | 385 | struct wl12xx_vif *wlvif; |
386 | struct timespec ts; | 386 | struct timespec ts; |
@@ -388,12 +388,15 @@ static void wl12xx_fw_status(struct wl1271 *wl, | |||
388 | int avail, freed_blocks; | 388 | int avail, freed_blocks; |
389 | int i; | 389 | int i; |
390 | size_t status_len; | 390 | size_t status_len; |
391 | int ret; | ||
391 | 392 | ||
392 | status_len = WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc) + | 393 | status_len = WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc) + |
393 | sizeof(*status_2) + wl->fw_status_priv_len; | 394 | sizeof(*status_2) + wl->fw_status_priv_len; |
394 | 395 | ||
395 | wlcore_raw_read_data(wl, REG_RAW_FW_STATUS_ADDR, status_1, | 396 | ret = wlcore_raw_read_data(wl, REG_RAW_FW_STATUS_ADDR, status_1, |
396 | status_len, false); | 397 | status_len, false); |
398 | if (ret < 0) | ||
399 | return ret; | ||
397 | 400 | ||
398 | wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " | 401 | wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " |
399 | "drv_rx_counter = %d, tx_results_counter = %d)", | 402 | "drv_rx_counter = %d, tx_results_counter = %d)", |
@@ -462,6 +465,8 @@ static void wl12xx_fw_status(struct wl1271 *wl, | |||
462 | getnstimeofday(&ts); | 465 | getnstimeofday(&ts); |
463 | wl->time_offset = (timespec_to_ns(&ts) >> 10) - | 466 | wl->time_offset = (timespec_to_ns(&ts) >> 10) - |
464 | (s64)le32_to_cpu(status_2->fw_localtime); | 467 | (s64)le32_to_cpu(status_2->fw_localtime); |
468 | |||
469 | return 0; | ||
465 | } | 470 | } |
466 | 471 | ||
467 | static void wl1271_flush_deferred_work(struct wl1271 *wl) | 472 | static void wl1271_flush_deferred_work(struct wl1271 *wl) |
@@ -489,20 +494,15 @@ static void wl1271_netstack_work(struct work_struct *work) | |||
489 | 494 | ||
490 | #define WL1271_IRQ_MAX_LOOPS 256 | 495 | #define WL1271_IRQ_MAX_LOOPS 256 |
491 | 496 | ||
492 | static irqreturn_t wl1271_irq(int irq, void *cookie) | 497 | static int wlcore_irq_locked(struct wl1271 *wl) |
493 | { | 498 | { |
494 | int ret; | 499 | int ret = 0; |
495 | u32 intr; | 500 | u32 intr; |
496 | int loopcount = WL1271_IRQ_MAX_LOOPS; | 501 | int loopcount = WL1271_IRQ_MAX_LOOPS; |
497 | struct wl1271 *wl = (struct wl1271 *)cookie; | ||
498 | bool done = false; | 502 | bool done = false; |
499 | unsigned int defer_count; | 503 | unsigned int defer_count; |
500 | unsigned long flags; | 504 | unsigned long flags; |
501 | 505 | ||
502 | /* TX might be handled here, avoid redundant work */ | ||
503 | set_bit(WL1271_FLAG_TX_PENDING, &wl->flags); | ||
504 | cancel_work_sync(&wl->tx_work); | ||
505 | |||
506 | /* | 506 | /* |
507 | * In case edge triggered interrupt must be used, we cannot iterate | 507 | * In case edge triggered interrupt must be used, we cannot iterate |
508 | * more than once without introducing race conditions with the hardirq. | 508 | * more than once without introducing race conditions with the hardirq. |
@@ -510,8 +510,6 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) | |||
510 | if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) | 510 | if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) |
511 | loopcount = 1; | 511 | loopcount = 1; |
512 | 512 | ||
513 | mutex_lock(&wl->mutex); | ||
514 | |||
515 | wl1271_debug(DEBUG_IRQ, "IRQ work"); | 513 | wl1271_debug(DEBUG_IRQ, "IRQ work"); |
516 | 514 | ||
517 | if (unlikely(wl->state == WL1271_STATE_OFF)) | 515 | if (unlikely(wl->state == WL1271_STATE_OFF)) |
@@ -530,7 +528,9 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) | |||
530 | clear_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags); | 528 | clear_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags); |
531 | smp_mb__after_clear_bit(); | 529 | smp_mb__after_clear_bit(); |
532 | 530 | ||
533 | wl12xx_fw_status(wl, wl->fw_status_1, wl->fw_status_2); | 531 | ret = wlcore_fw_status(wl, wl->fw_status_1, wl->fw_status_2); |
532 | if (ret < 0) | ||
533 | goto out; | ||
534 | 534 | ||
535 | wlcore_hw_tx_immediate_compl(wl); | 535 | wlcore_hw_tx_immediate_compl(wl); |
536 | 536 | ||
@@ -544,7 +544,7 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) | |||
544 | if (unlikely(intr & WL1271_ACX_INTR_WATCHDOG)) { | 544 | if (unlikely(intr & WL1271_ACX_INTR_WATCHDOG)) { |
545 | wl1271_error("HW watchdog interrupt received! starting recovery."); | 545 | wl1271_error("HW watchdog interrupt received! starting recovery."); |
546 | wl->watchdog_recovery = true; | 546 | wl->watchdog_recovery = true; |
547 | wl12xx_queue_recovery_work(wl); | 547 | ret = -EIO; |
548 | 548 | ||
549 | /* restarting the chip. ignore any other interrupt. */ | 549 | /* restarting the chip. ignore any other interrupt. */ |
550 | goto out; | 550 | goto out; |
@@ -554,7 +554,7 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) | |||
554 | wl1271_error("SW watchdog interrupt received! " | 554 | wl1271_error("SW watchdog interrupt received! " |
555 | "starting recovery."); | 555 | "starting recovery."); |
556 | wl->watchdog_recovery = true; | 556 | wl->watchdog_recovery = true; |
557 | wl12xx_queue_recovery_work(wl); | 557 | ret = -EIO; |
558 | 558 | ||
559 | /* restarting the chip. ignore any other interrupt. */ | 559 | /* restarting the chip. ignore any other interrupt. */ |
560 | goto out; | 560 | goto out; |
@@ -563,7 +563,9 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) | |||
563 | if (likely(intr & WL1271_ACX_INTR_DATA)) { | 563 | if (likely(intr & WL1271_ACX_INTR_DATA)) { |
564 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA"); | 564 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA"); |
565 | 565 | ||
566 | wl12xx_rx(wl, wl->fw_status_1); | 566 | ret = wlcore_rx(wl, wl->fw_status_1); |
567 | if (ret < 0) | ||
568 | goto out; | ||
567 | 569 | ||
568 | /* Check if any tx blocks were freed */ | 570 | /* Check if any tx blocks were freed */ |
569 | spin_lock_irqsave(&wl->wl_lock, flags); | 571 | spin_lock_irqsave(&wl->wl_lock, flags); |
@@ -574,13 +576,17 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) | |||
574 | * In order to avoid starvation of the TX path, | 576 | * In order to avoid starvation of the TX path, |
575 | * call the work function directly. | 577 | * call the work function directly. |
576 | */ | 578 | */ |
577 | wl1271_tx_work_locked(wl); | 579 | ret = wlcore_tx_work_locked(wl); |
580 | if (ret < 0) | ||
581 | goto out; | ||
578 | } else { | 582 | } else { |
579 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 583 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
580 | } | 584 | } |
581 | 585 | ||
582 | /* check for tx results */ | 586 | /* check for tx results */ |
583 | wlcore_hw_tx_delayed_compl(wl); | 587 | ret = wlcore_hw_tx_delayed_compl(wl); |
588 | if (ret < 0) | ||
589 | goto out; | ||
584 | 590 | ||
585 | /* Make sure the deferred queues don't get too long */ | 591 | /* Make sure the deferred queues don't get too long */ |
586 | defer_count = skb_queue_len(&wl->deferred_tx_queue) + | 592 | defer_count = skb_queue_len(&wl->deferred_tx_queue) + |
@@ -591,12 +597,16 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) | |||
591 | 597 | ||
592 | if (intr & WL1271_ACX_INTR_EVENT_A) { | 598 | if (intr & WL1271_ACX_INTR_EVENT_A) { |
593 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A"); | 599 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A"); |
594 | wl1271_event_handle(wl, 0); | 600 | ret = wl1271_event_handle(wl, 0); |
601 | if (ret < 0) | ||
602 | goto out; | ||
595 | } | 603 | } |
596 | 604 | ||
597 | if (intr & WL1271_ACX_INTR_EVENT_B) { | 605 | if (intr & WL1271_ACX_INTR_EVENT_B) { |
598 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B"); | 606 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B"); |
599 | wl1271_event_handle(wl, 1); | 607 | ret = wl1271_event_handle(wl, 1); |
608 | if (ret < 0) | ||
609 | goto out; | ||
600 | } | 610 | } |
601 | 611 | ||
602 | if (intr & WL1271_ACX_INTR_INIT_COMPLETE) | 612 | if (intr & WL1271_ACX_INTR_INIT_COMPLETE) |
@@ -610,6 +620,25 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) | |||
610 | wl1271_ps_elp_sleep(wl); | 620 | wl1271_ps_elp_sleep(wl); |
611 | 621 | ||
612 | out: | 622 | out: |
623 | return ret; | ||
624 | } | ||
625 | |||
626 | static irqreturn_t wlcore_irq(int irq, void *cookie) | ||
627 | { | ||
628 | int ret; | ||
629 | unsigned long flags; | ||
630 | struct wl1271 *wl = cookie; | ||
631 | |||
632 | /* TX might be handled here, avoid redundant work */ | ||
633 | set_bit(WL1271_FLAG_TX_PENDING, &wl->flags); | ||
634 | cancel_work_sync(&wl->tx_work); | ||
635 | |||
636 | mutex_lock(&wl->mutex); | ||
637 | |||
638 | ret = wlcore_irq_locked(wl); | ||
639 | if (ret) | ||
640 | wl12xx_queue_recovery_work(wl); | ||
641 | |||
613 | spin_lock_irqsave(&wl->wl_lock, flags); | 642 | spin_lock_irqsave(&wl->wl_lock, flags); |
614 | /* In case TX was not handled here, queue TX work */ | 643 | /* In case TX was not handled here, queue TX work */ |
615 | clear_bit(WL1271_FLAG_TX_PENDING, &wl->flags); | 644 | clear_bit(WL1271_FLAG_TX_PENDING, &wl->flags); |
@@ -743,8 +772,13 @@ out: | |||
743 | 772 | ||
744 | void wl12xx_queue_recovery_work(struct wl1271 *wl) | 773 | void wl12xx_queue_recovery_work(struct wl1271 *wl) |
745 | { | 774 | { |
746 | if (!test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) | 775 | WARN_ON(!test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)); |
776 | |||
777 | /* Avoid a recursive recovery */ | ||
778 | if (!test_and_set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) { | ||
779 | wlcore_disable_interrupts_nosync(wl); | ||
747 | ieee80211_queue_work(wl->hw, &wl->recovery_work); | 780 | ieee80211_queue_work(wl->hw, &wl->recovery_work); |
781 | } | ||
748 | } | 782 | } |
749 | 783 | ||
750 | size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen) | 784 | size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen) |
@@ -770,14 +804,17 @@ size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen) | |||
770 | return len; | 804 | return len; |
771 | } | 805 | } |
772 | 806 | ||
807 | #define WLCORE_FW_LOG_END 0x2000000 | ||
808 | |||
773 | static void wl12xx_read_fwlog_panic(struct wl1271 *wl) | 809 | static void wl12xx_read_fwlog_panic(struct wl1271 *wl) |
774 | { | 810 | { |
775 | u32 addr; | 811 | u32 addr; |
776 | u32 first_addr; | 812 | u32 offset; |
813 | u32 end_of_log; | ||
777 | u8 *block; | 814 | u8 *block; |
815 | int ret; | ||
778 | 816 | ||
779 | if ((wl->quirks & WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED) || | 817 | if ((wl->quirks & WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED) || |
780 | (wl->conf.fwlog.mode != WL12XX_FWLOG_ON_DEMAND) || | ||
781 | (wl->conf.fwlog.mem_blocks == 0)) | 818 | (wl->conf.fwlog.mem_blocks == 0)) |
782 | return; | 819 | return; |
783 | 820 | ||
@@ -791,34 +828,47 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl) | |||
791 | * Make sure the chip is awake and the logger isn't active. | 828 | * Make sure the chip is awake and the logger isn't active. |
792 | * Do not send a stop fwlog command if the fw is hanged. | 829 | * Do not send a stop fwlog command if the fw is hanged. |
793 | */ | 830 | */ |
794 | if (!wl1271_ps_elp_wakeup(wl) && !wl->watchdog_recovery) | 831 | if (wl1271_ps_elp_wakeup(wl)) |
795 | wl12xx_cmd_stop_fwlog(wl); | ||
796 | else | ||
797 | goto out; | 832 | goto out; |
833 | if (!wl->watchdog_recovery) | ||
834 | wl12xx_cmd_stop_fwlog(wl); | ||
798 | 835 | ||
799 | /* Read the first memory block address */ | 836 | /* Read the first memory block address */ |
800 | wl12xx_fw_status(wl, wl->fw_status_1, wl->fw_status_2); | 837 | ret = wlcore_fw_status(wl, wl->fw_status_1, wl->fw_status_2); |
801 | first_addr = le32_to_cpu(wl->fw_status_2->log_start_addr); | 838 | if (ret < 0) |
802 | if (!first_addr) | 839 | goto out; |
840 | |||
841 | addr = le32_to_cpu(wl->fw_status_2->log_start_addr); | ||
842 | if (!addr) | ||
803 | goto out; | 843 | goto out; |
804 | 844 | ||
845 | if (wl->conf.fwlog.mode == WL12XX_FWLOG_CONTINUOUS) { | ||
846 | offset = sizeof(addr) + sizeof(struct wl1271_rx_descriptor); | ||
847 | end_of_log = WLCORE_FW_LOG_END; | ||
848 | } else { | ||
849 | offset = sizeof(addr); | ||
850 | end_of_log = addr; | ||
851 | } | ||
852 | |||
805 | /* Traverse the memory blocks linked list */ | 853 | /* Traverse the memory blocks linked list */ |
806 | addr = first_addr; | ||
807 | do { | 854 | do { |
808 | memset(block, 0, WL12XX_HW_BLOCK_SIZE); | 855 | memset(block, 0, WL12XX_HW_BLOCK_SIZE); |
809 | wl1271_read_hwaddr(wl, addr, block, WL12XX_HW_BLOCK_SIZE, | 856 | ret = wlcore_read_hwaddr(wl, addr, block, WL12XX_HW_BLOCK_SIZE, |
810 | false); | 857 | false); |
858 | if (ret < 0) | ||
859 | goto out; | ||
811 | 860 | ||
812 | /* | 861 | /* |
813 | * Memory blocks are linked to one another. The first 4 bytes | 862 | * Memory blocks are linked to one another. The first 4 bytes |
814 | * of each memory block hold the hardware address of the next | 863 | * of each memory block hold the hardware address of the next |
815 | * one. The last memory block points to the first one. | 864 | * one. The last memory block points to the first one in |
865 | * on demand mode and is equal to 0x2000000 in continuous mode. | ||
816 | */ | 866 | */ |
817 | addr = le32_to_cpup((__le32 *)block); | 867 | addr = le32_to_cpup((__le32 *)block); |
818 | if (!wl12xx_copy_fwlog(wl, block + sizeof(addr), | 868 | if (!wl12xx_copy_fwlog(wl, block + offset, |
819 | WL12XX_HW_BLOCK_SIZE - sizeof(addr))) | 869 | WL12XX_HW_BLOCK_SIZE - offset)) |
820 | break; | 870 | break; |
821 | } while (addr && (addr != first_addr)); | 871 | } while (addr && (addr != end_of_log)); |
822 | 872 | ||
823 | wake_up_interruptible(&wl->fwlog_waitq); | 873 | wake_up_interruptible(&wl->fwlog_waitq); |
824 | 874 | ||
@@ -826,6 +876,34 @@ out: | |||
826 | kfree(block); | 876 | kfree(block); |
827 | } | 877 | } |
828 | 878 | ||
879 | static void wlcore_print_recovery(struct wl1271 *wl) | ||
880 | { | ||
881 | u32 pc = 0; | ||
882 | u32 hint_sts = 0; | ||
883 | int ret; | ||
884 | |||
885 | wl1271_info("Hardware recovery in progress. FW ver: %s", | ||
886 | wl->chip.fw_ver_str); | ||
887 | |||
888 | /* change partitions momentarily so we can read the FW pc */ | ||
889 | ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); | ||
890 | if (ret < 0) | ||
891 | return; | ||
892 | |||
893 | ret = wlcore_read_reg(wl, REG_PC_ON_RECOVERY, &pc); | ||
894 | if (ret < 0) | ||
895 | return; | ||
896 | |||
897 | ret = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR, &hint_sts); | ||
898 | if (ret < 0) | ||
899 | return; | ||
900 | |||
901 | wl1271_info("pc: 0x%x, hint_sts: 0x%08x", pc, hint_sts); | ||
902 | |||
903 | wlcore_set_partition(wl, &wl->ptable[PART_WORK]); | ||
904 | } | ||
905 | |||
906 | |||
829 | static void wl1271_recovery_work(struct work_struct *work) | 907 | static void wl1271_recovery_work(struct work_struct *work) |
830 | { | 908 | { |
831 | struct wl1271 *wl = | 909 | struct wl1271 *wl = |
@@ -838,19 +916,9 @@ static void wl1271_recovery_work(struct work_struct *work) | |||
838 | if (wl->state != WL1271_STATE_ON || wl->plt) | 916 | if (wl->state != WL1271_STATE_ON || wl->plt) |
839 | goto out_unlock; | 917 | goto out_unlock; |
840 | 918 | ||
841 | /* Avoid a recursive recovery */ | ||
842 | set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags); | ||
843 | |||
844 | wl12xx_read_fwlog_panic(wl); | 919 | wl12xx_read_fwlog_panic(wl); |
845 | 920 | ||
846 | /* change partitions momentarily so we can read the FW pc */ | 921 | wlcore_print_recovery(wl); |
847 | wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); | ||
848 | wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x " | ||
849 | "hint_sts: 0x%08x", | ||
850 | wl->chip.fw_ver_str, | ||
851 | wlcore_read_reg(wl, REG_PC_ON_RECOVERY), | ||
852 | wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR)); | ||
853 | wlcore_set_partition(wl, &wl->ptable[PART_WORK]); | ||
854 | 922 | ||
855 | BUG_ON(bug_on_recovery && | 923 | BUG_ON(bug_on_recovery && |
856 | !test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)); | 924 | !test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)); |
@@ -892,8 +960,6 @@ static void wl1271_recovery_work(struct work_struct *work) | |||
892 | mutex_unlock(&wl->mutex); | 960 | mutex_unlock(&wl->mutex); |
893 | wl1271_op_stop(wl->hw); | 961 | wl1271_op_stop(wl->hw); |
894 | 962 | ||
895 | clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags); | ||
896 | |||
897 | ieee80211_restart_hw(wl->hw); | 963 | ieee80211_restart_hw(wl->hw); |
898 | 964 | ||
899 | /* | 965 | /* |
@@ -907,9 +973,9 @@ out_unlock: | |||
907 | mutex_unlock(&wl->mutex); | 973 | mutex_unlock(&wl->mutex); |
908 | } | 974 | } |
909 | 975 | ||
910 | static void wl1271_fw_wakeup(struct wl1271 *wl) | 976 | static int wlcore_fw_wakeup(struct wl1271 *wl) |
911 | { | 977 | { |
912 | wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_WAKE_UP); | 978 | return wlcore_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_WAKE_UP); |
913 | } | 979 | } |
914 | 980 | ||
915 | static int wl1271_setup(struct wl1271 *wl) | 981 | static int wl1271_setup(struct wl1271 *wl) |
@@ -945,13 +1011,21 @@ static int wl12xx_set_power_on(struct wl1271 *wl) | |||
945 | wl1271_io_reset(wl); | 1011 | wl1271_io_reset(wl); |
946 | wl1271_io_init(wl); | 1012 | wl1271_io_init(wl); |
947 | 1013 | ||
948 | wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); | 1014 | ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); |
1015 | if (ret < 0) | ||
1016 | goto fail; | ||
949 | 1017 | ||
950 | /* ELP module wake up */ | 1018 | /* ELP module wake up */ |
951 | wl1271_fw_wakeup(wl); | 1019 | ret = wlcore_fw_wakeup(wl); |
1020 | if (ret < 0) | ||
1021 | goto fail; | ||
952 | 1022 | ||
953 | out: | 1023 | out: |
954 | return ret; | 1024 | return ret; |
1025 | |||
1026 | fail: | ||
1027 | wl1271_power_off(wl); | ||
1028 | return ret; | ||
955 | } | 1029 | } |
956 | 1030 | ||
957 | static int wl12xx_chip_wakeup(struct wl1271 *wl, bool plt) | 1031 | static int wl12xx_chip_wakeup(struct wl1271 *wl, bool plt) |
@@ -1082,6 +1156,7 @@ int wl1271_plt_stop(struct wl1271 *wl) | |||
1082 | mutex_lock(&wl->mutex); | 1156 | mutex_lock(&wl->mutex); |
1083 | wl1271_power_off(wl); | 1157 | wl1271_power_off(wl); |
1084 | wl->flags = 0; | 1158 | wl->flags = 0; |
1159 | wl->sleep_auth = WL1271_PSM_ILLEGAL; | ||
1085 | wl->state = WL1271_STATE_OFF; | 1160 | wl->state = WL1271_STATE_OFF; |
1086 | wl->plt = false; | 1161 | wl->plt = false; |
1087 | wl->rx_counter = 0; | 1162 | wl->rx_counter = 0; |
@@ -1173,7 +1248,7 @@ int wl1271_tx_dummy_packet(struct wl1271 *wl) | |||
1173 | 1248 | ||
1174 | /* The FW is low on RX memory blocks, so send the dummy packet asap */ | 1249 | /* The FW is low on RX memory blocks, so send the dummy packet asap */ |
1175 | if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags)) | 1250 | if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags)) |
1176 | wl1271_tx_work_locked(wl); | 1251 | return wlcore_tx_work_locked(wl); |
1177 | 1252 | ||
1178 | /* | 1253 | /* |
1179 | * If the FW TX is busy, TX work will be scheduled by the threaded | 1254 | * If the FW TX is busy, TX work will be scheduled by the threaded |
@@ -1440,8 +1515,15 @@ static int wl1271_configure_wowlan(struct wl1271 *wl, | |||
1440 | int i, ret; | 1515 | int i, ret; |
1441 | 1516 | ||
1442 | if (!wow || wow->any || !wow->n_patterns) { | 1517 | if (!wow || wow->any || !wow->n_patterns) { |
1443 | wl1271_acx_default_rx_filter_enable(wl, 0, FILTER_SIGNAL); | 1518 | ret = wl1271_acx_default_rx_filter_enable(wl, 0, |
1444 | wl1271_rx_filter_clear_all(wl); | 1519 | FILTER_SIGNAL); |
1520 | if (ret) | ||
1521 | goto out; | ||
1522 | |||
1523 | ret = wl1271_rx_filter_clear_all(wl); | ||
1524 | if (ret) | ||
1525 | goto out; | ||
1526 | |||
1445 | return 0; | 1527 | return 0; |
1446 | } | 1528 | } |
1447 | 1529 | ||
@@ -1457,8 +1539,13 @@ static int wl1271_configure_wowlan(struct wl1271 *wl, | |||
1457 | } | 1539 | } |
1458 | } | 1540 | } |
1459 | 1541 | ||
1460 | wl1271_acx_default_rx_filter_enable(wl, 0, FILTER_SIGNAL); | 1542 | ret = wl1271_acx_default_rx_filter_enable(wl, 0, FILTER_SIGNAL); |
1461 | wl1271_rx_filter_clear_all(wl); | 1543 | if (ret) |
1544 | goto out; | ||
1545 | |||
1546 | ret = wl1271_rx_filter_clear_all(wl); | ||
1547 | if (ret) | ||
1548 | goto out; | ||
1462 | 1549 | ||
1463 | /* Translate WoWLAN patterns into filters */ | 1550 | /* Translate WoWLAN patterns into filters */ |
1464 | for (i = 0; i < wow->n_patterns; i++) { | 1551 | for (i = 0; i < wow->n_patterns; i++) { |
@@ -1500,7 +1587,10 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl, | |||
1500 | if (ret < 0) | 1587 | if (ret < 0) |
1501 | goto out; | 1588 | goto out; |
1502 | 1589 | ||
1503 | wl1271_configure_wowlan(wl, wow); | 1590 | ret = wl1271_configure_wowlan(wl, wow); |
1591 | if (ret < 0) | ||
1592 | goto out_sleep; | ||
1593 | |||
1504 | ret = wl1271_acx_wake_up_conditions(wl, wlvif, | 1594 | ret = wl1271_acx_wake_up_conditions(wl, wlvif, |
1505 | wl->conf.conn.suspend_wake_up_event, | 1595 | wl->conf.conn.suspend_wake_up_event, |
1506 | wl->conf.conn.suspend_listen_interval); | 1596 | wl->conf.conn.suspend_listen_interval); |
@@ -1508,8 +1598,8 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl, | |||
1508 | if (ret < 0) | 1598 | if (ret < 0) |
1509 | wl1271_error("suspend: set wake up conditions failed: %d", ret); | 1599 | wl1271_error("suspend: set wake up conditions failed: %d", ret); |
1510 | 1600 | ||
1601 | out_sleep: | ||
1511 | wl1271_ps_elp_sleep(wl); | 1602 | wl1271_ps_elp_sleep(wl); |
1512 | |||
1513 | out: | 1603 | out: |
1514 | return ret; | 1604 | return ret; |
1515 | 1605 | ||
@@ -1588,6 +1678,12 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw, | |||
1588 | wl1271_debug(DEBUG_MAC80211, "mac80211 suspend wow=%d", !!wow); | 1678 | wl1271_debug(DEBUG_MAC80211, "mac80211 suspend wow=%d", !!wow); |
1589 | WARN_ON(!wow); | 1679 | WARN_ON(!wow); |
1590 | 1680 | ||
1681 | /* we want to perform the recovery before suspending */ | ||
1682 | if (test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) { | ||
1683 | wl1271_warning("postponing suspend to perform recovery"); | ||
1684 | return -EBUSY; | ||
1685 | } | ||
1686 | |||
1591 | wl1271_tx_flush(wl); | 1687 | wl1271_tx_flush(wl); |
1592 | 1688 | ||
1593 | mutex_lock(&wl->mutex); | 1689 | mutex_lock(&wl->mutex); |
@@ -1628,7 +1724,8 @@ static int wl1271_op_resume(struct ieee80211_hw *hw) | |||
1628 | struct wl1271 *wl = hw->priv; | 1724 | struct wl1271 *wl = hw->priv; |
1629 | struct wl12xx_vif *wlvif; | 1725 | struct wl12xx_vif *wlvif; |
1630 | unsigned long flags; | 1726 | unsigned long flags; |
1631 | bool run_irq_work = false; | 1727 | bool run_irq_work = false, pending_recovery; |
1728 | int ret; | ||
1632 | 1729 | ||
1633 | wl1271_debug(DEBUG_MAC80211, "mac80211 resume wow=%d", | 1730 | wl1271_debug(DEBUG_MAC80211, "mac80211 resume wow=%d", |
1634 | wl->wow_enabled); | 1731 | wl->wow_enabled); |
@@ -1644,17 +1741,37 @@ static int wl1271_op_resume(struct ieee80211_hw *hw) | |||
1644 | run_irq_work = true; | 1741 | run_irq_work = true; |
1645 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 1742 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
1646 | 1743 | ||
1744 | mutex_lock(&wl->mutex); | ||
1745 | |||
1746 | /* test the recovery flag before calling any SDIO functions */ | ||
1747 | pending_recovery = test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, | ||
1748 | &wl->flags); | ||
1749 | |||
1647 | if (run_irq_work) { | 1750 | if (run_irq_work) { |
1648 | wl1271_debug(DEBUG_MAC80211, | 1751 | wl1271_debug(DEBUG_MAC80211, |
1649 | "run postponed irq_work directly"); | 1752 | "run postponed irq_work directly"); |
1650 | wl1271_irq(0, wl); | 1753 | |
1754 | /* don't talk to the HW if recovery is pending */ | ||
1755 | if (!pending_recovery) { | ||
1756 | ret = wlcore_irq_locked(wl); | ||
1757 | if (ret) | ||
1758 | wl12xx_queue_recovery_work(wl); | ||
1759 | } | ||
1760 | |||
1651 | wlcore_enable_interrupts(wl); | 1761 | wlcore_enable_interrupts(wl); |
1652 | } | 1762 | } |
1653 | 1763 | ||
1654 | mutex_lock(&wl->mutex); | 1764 | if (pending_recovery) { |
1765 | wl1271_warning("queuing forgotten recovery on resume"); | ||
1766 | ieee80211_queue_work(wl->hw, &wl->recovery_work); | ||
1767 | goto out; | ||
1768 | } | ||
1769 | |||
1655 | wl12xx_for_each_wlvif(wl, wlvif) { | 1770 | wl12xx_for_each_wlvif(wl, wlvif) { |
1656 | wl1271_configure_resume(wl, wlvif); | 1771 | wl1271_configure_resume(wl, wlvif); |
1657 | } | 1772 | } |
1773 | |||
1774 | out: | ||
1658 | wl->wow_enabled = false; | 1775 | wl->wow_enabled = false; |
1659 | mutex_unlock(&wl->mutex); | 1776 | mutex_unlock(&wl->mutex); |
1660 | 1777 | ||
@@ -1695,6 +1812,10 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
1695 | wlcore_disable_interrupts(wl); | 1812 | wlcore_disable_interrupts(wl); |
1696 | mutex_lock(&wl->mutex); | 1813 | mutex_lock(&wl->mutex); |
1697 | if (wl->state == WL1271_STATE_OFF) { | 1814 | if (wl->state == WL1271_STATE_OFF) { |
1815 | if (test_and_clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, | ||
1816 | &wl->flags)) | ||
1817 | wlcore_enable_interrupts(wl); | ||
1818 | |||
1698 | mutex_unlock(&wl->mutex); | 1819 | mutex_unlock(&wl->mutex); |
1699 | 1820 | ||
1700 | /* | 1821 | /* |
@@ -1726,6 +1847,13 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
1726 | mutex_lock(&wl->mutex); | 1847 | mutex_lock(&wl->mutex); |
1727 | 1848 | ||
1728 | wl1271_power_off(wl); | 1849 | wl1271_power_off(wl); |
1850 | /* | ||
1851 | * In case a recovery was scheduled, interrupts were disabled to avoid | ||
1852 | * an interrupt storm. Now that the power is down, it is safe to | ||
1853 | * re-enable interrupts to balance the disable depth | ||
1854 | */ | ||
1855 | if (test_and_clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) | ||
1856 | wlcore_enable_interrupts(wl); | ||
1729 | 1857 | ||
1730 | wl->band = IEEE80211_BAND_2GHZ; | 1858 | wl->band = IEEE80211_BAND_2GHZ; |
1731 | 1859 | ||
@@ -1740,6 +1868,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
1740 | wl->ap_fw_ps_map = 0; | 1868 | wl->ap_fw_ps_map = 0; |
1741 | wl->ap_ps_map = 0; | 1869 | wl->ap_ps_map = 0; |
1742 | wl->sched_scanning = false; | 1870 | wl->sched_scanning = false; |
1871 | wl->sleep_auth = WL1271_PSM_ILLEGAL; | ||
1743 | memset(wl->roles_map, 0, sizeof(wl->roles_map)); | 1872 | memset(wl->roles_map, 0, sizeof(wl->roles_map)); |
1744 | memset(wl->links_map, 0, sizeof(wl->links_map)); | 1873 | memset(wl->links_map, 0, sizeof(wl->links_map)); |
1745 | memset(wl->roc_map, 0, sizeof(wl->roc_map)); | 1874 | memset(wl->roc_map, 0, sizeof(wl->roc_map)); |
@@ -2146,6 +2275,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, | |||
2146 | { | 2275 | { |
2147 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | 2276 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); |
2148 | int i, ret; | 2277 | int i, ret; |
2278 | bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); | ||
2149 | 2279 | ||
2150 | wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); | 2280 | wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); |
2151 | 2281 | ||
@@ -2226,11 +2356,25 @@ deinit: | |||
2226 | wlvif->role_id = WL12XX_INVALID_ROLE_ID; | 2356 | wlvif->role_id = WL12XX_INVALID_ROLE_ID; |
2227 | wlvif->dev_role_id = WL12XX_INVALID_ROLE_ID; | 2357 | wlvif->dev_role_id = WL12XX_INVALID_ROLE_ID; |
2228 | 2358 | ||
2229 | if (wlvif->bss_type == BSS_TYPE_AP_BSS) | 2359 | if (is_ap) |
2230 | wl->ap_count--; | 2360 | wl->ap_count--; |
2231 | else | 2361 | else |
2232 | wl->sta_count--; | 2362 | wl->sta_count--; |
2233 | 2363 | ||
2364 | /* Last AP, have more stations. Configure according to STA. */ | ||
2365 | if (wl->ap_count == 0 && is_ap && wl->sta_count) { | ||
2366 | u8 sta_auth = wl->conf.conn.sta_sleep_auth; | ||
2367 | /* Configure for power according to debugfs */ | ||
2368 | if (sta_auth != WL1271_PSM_ILLEGAL) | ||
2369 | wl1271_acx_sleep_auth(wl, sta_auth); | ||
2370 | /* Configure for power always on */ | ||
2371 | else if (wl->quirks & WLCORE_QUIRK_NO_ELP) | ||
2372 | wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); | ||
2373 | /* Configure for ELP power saving */ | ||
2374 | else | ||
2375 | wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP); | ||
2376 | } | ||
2377 | |||
2234 | mutex_unlock(&wl->mutex); | 2378 | mutex_unlock(&wl->mutex); |
2235 | 2379 | ||
2236 | del_timer_sync(&wlvif->rx_streaming_timer); | 2380 | del_timer_sync(&wlvif->rx_streaming_timer); |
@@ -2448,12 +2592,16 @@ static int wl12xx_config_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
2448 | (wlvif->channel != channel) || | 2592 | (wlvif->channel != channel) || |
2449 | (wlvif->channel_type != conf->channel_type))) { | 2593 | (wlvif->channel_type != conf->channel_type))) { |
2450 | /* send all pending packets */ | 2594 | /* send all pending packets */ |
2451 | wl1271_tx_work_locked(wl); | 2595 | ret = wlcore_tx_work_locked(wl); |
2596 | if (ret < 0) | ||
2597 | return ret; | ||
2598 | |||
2452 | wlvif->band = conf->channel->band; | 2599 | wlvif->band = conf->channel->band; |
2453 | wlvif->channel = channel; | 2600 | wlvif->channel = channel; |
2454 | wlvif->channel_type = conf->channel_type; | 2601 | wlvif->channel_type = conf->channel_type; |
2455 | 2602 | ||
2456 | if (is_ap) { | 2603 | if (is_ap) { |
2604 | wl1271_set_band_rate(wl, wlvif); | ||
2457 | ret = wl1271_init_ap_rates(wl, wlvif); | 2605 | ret = wl1271_init_ap_rates(wl, wlvif); |
2458 | if (ret < 0) | 2606 | if (ret < 0) |
2459 | wl1271_error("AP rate policy change failed %d", | 2607 | wl1271_error("AP rate policy change failed %d", |
@@ -4090,16 +4238,13 @@ out: | |||
4090 | static int wl1271_op_get_survey(struct ieee80211_hw *hw, int idx, | 4238 | static int wl1271_op_get_survey(struct ieee80211_hw *hw, int idx, |
4091 | struct survey_info *survey) | 4239 | struct survey_info *survey) |
4092 | { | 4240 | { |
4093 | struct wl1271 *wl = hw->priv; | ||
4094 | struct ieee80211_conf *conf = &hw->conf; | 4241 | struct ieee80211_conf *conf = &hw->conf; |
4095 | 4242 | ||
4096 | if (idx != 0) | 4243 | if (idx != 0) |
4097 | return -ENOENT; | 4244 | return -ENOENT; |
4098 | 4245 | ||
4099 | survey->channel = conf->channel; | 4246 | survey->channel = conf->channel; |
4100 | survey->filled = SURVEY_INFO_NOISE_DBM; | 4247 | survey->filled = 0; |
4101 | survey->noise = wl->noise; | ||
4102 | |||
4103 | return 0; | 4248 | return 0; |
4104 | } | 4249 | } |
4105 | 4250 | ||
@@ -4365,9 +4510,14 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, | |||
4365 | 4510 | ||
4366 | case IEEE80211_AMPDU_RX_STOP: | 4511 | case IEEE80211_AMPDU_RX_STOP: |
4367 | if (!(*ba_bitmap & BIT(tid))) { | 4512 | if (!(*ba_bitmap & BIT(tid))) { |
4368 | ret = -EINVAL; | 4513 | /* |
4369 | wl1271_error("no active RX BA session on tid: %d", | 4514 | * this happens on reconfig - so only output a debug |
4515 | * message for now, and don't fail the function. | ||
4516 | */ | ||
4517 | wl1271_debug(DEBUG_MAC80211, | ||
4518 | "no active RX BA session on tid: %d", | ||
4370 | tid); | 4519 | tid); |
4520 | ret = 0; | ||
4371 | break; | 4521 | break; |
4372 | } | 4522 | } |
4373 | 4523 | ||
@@ -4904,18 +5054,22 @@ static int wl12xx_get_hw_info(struct wl1271 *wl) | |||
4904 | if (ret < 0) | 5054 | if (ret < 0) |
4905 | goto out; | 5055 | goto out; |
4906 | 5056 | ||
4907 | wl->chip.id = wlcore_read_reg(wl, REG_CHIP_ID_B); | 5057 | ret = wlcore_read_reg(wl, REG_CHIP_ID_B, &wl->chip.id); |
5058 | if (ret < 0) | ||
5059 | goto out; | ||
4908 | 5060 | ||
4909 | wl->fuse_oui_addr = 0; | 5061 | wl->fuse_oui_addr = 0; |
4910 | wl->fuse_nic_addr = 0; | 5062 | wl->fuse_nic_addr = 0; |
4911 | 5063 | ||
4912 | wl->hw_pg_ver = wl->ops->get_pg_ver(wl); | 5064 | ret = wl->ops->get_pg_ver(wl, &wl->hw_pg_ver); |
5065 | if (ret < 0) | ||
5066 | goto out; | ||
4913 | 5067 | ||
4914 | if (wl->ops->get_mac) | 5068 | if (wl->ops->get_mac) |
4915 | wl->ops->get_mac(wl); | 5069 | ret = wl->ops->get_mac(wl); |
4916 | 5070 | ||
4917 | wl1271_power_off(wl); | ||
4918 | out: | 5071 | out: |
5072 | wl1271_power_off(wl); | ||
4919 | return ret; | 5073 | return ret; |
4920 | } | 5074 | } |
4921 | 5075 | ||
@@ -4976,6 +5130,29 @@ static void wl1271_unregister_hw(struct wl1271 *wl) | |||
4976 | 5130 | ||
4977 | } | 5131 | } |
4978 | 5132 | ||
5133 | static const struct ieee80211_iface_limit wlcore_iface_limits[] = { | ||
5134 | { | ||
5135 | .max = 2, | ||
5136 | .types = BIT(NL80211_IFTYPE_STATION), | ||
5137 | }, | ||
5138 | { | ||
5139 | .max = 1, | ||
5140 | .types = BIT(NL80211_IFTYPE_AP) | | ||
5141 | BIT(NL80211_IFTYPE_P2P_GO) | | ||
5142 | BIT(NL80211_IFTYPE_P2P_CLIENT), | ||
5143 | }, | ||
5144 | }; | ||
5145 | |||
5146 | static const struct ieee80211_iface_combination | ||
5147 | wlcore_iface_combinations[] = { | ||
5148 | { | ||
5149 | .num_different_channels = 1, | ||
5150 | .max_interfaces = 2, | ||
5151 | .limits = wlcore_iface_limits, | ||
5152 | .n_limits = ARRAY_SIZE(wlcore_iface_limits), | ||
5153 | }, | ||
5154 | }; | ||
5155 | |||
4979 | static int wl1271_init_ieee80211(struct wl1271 *wl) | 5156 | static int wl1271_init_ieee80211(struct wl1271 *wl) |
4980 | { | 5157 | { |
4981 | static const u32 cipher_suites[] = { | 5158 | static const u32 cipher_suites[] = { |
@@ -5069,6 +5246,11 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) | |||
5069 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | | 5246 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | |
5070 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P; | 5247 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P; |
5071 | 5248 | ||
5249 | /* allowed interface combinations */ | ||
5250 | wl->hw->wiphy->iface_combinations = wlcore_iface_combinations; | ||
5251 | wl->hw->wiphy->n_iface_combinations = | ||
5252 | ARRAY_SIZE(wlcore_iface_combinations); | ||
5253 | |||
5072 | SET_IEEE80211_DEV(wl->hw, wl->dev); | 5254 | SET_IEEE80211_DEV(wl->hw, wl->dev); |
5073 | 5255 | ||
5074 | wl->hw->sta_data_size = sizeof(struct wl1271_station); | 5256 | wl->hw->sta_data_size = sizeof(struct wl1271_station); |
@@ -5140,6 +5322,7 @@ struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size) | |||
5140 | wl->channel_type = NL80211_CHAN_NO_HT; | 5322 | wl->channel_type = NL80211_CHAN_NO_HT; |
5141 | wl->flags = 0; | 5323 | wl->flags = 0; |
5142 | wl->sg_enabled = true; | 5324 | wl->sg_enabled = true; |
5325 | wl->sleep_auth = WL1271_PSM_ILLEGAL; | ||
5143 | wl->hw_pg_ver = -1; | 5326 | wl->hw_pg_ver = -1; |
5144 | wl->ap_ps_map = 0; | 5327 | wl->ap_ps_map = 0; |
5145 | wl->ap_fw_ps_map = 0; | 5328 | wl->ap_fw_ps_map = 0; |
@@ -5313,7 +5496,7 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev) | |||
5313 | else | 5496 | else |
5314 | irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; | 5497 | irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; |
5315 | 5498 | ||
5316 | ret = request_threaded_irq(wl->irq, wl12xx_hardirq, wl1271_irq, | 5499 | ret = request_threaded_irq(wl->irq, wl12xx_hardirq, wlcore_irq, |
5317 | irqflags, | 5500 | irqflags, |
5318 | pdev->name, wl); | 5501 | pdev->name, wl); |
5319 | if (ret < 0) { | 5502 | if (ret < 0) { |
@@ -5341,12 +5524,12 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev) | |||
5341 | ret = wl12xx_get_hw_info(wl); | 5524 | ret = wl12xx_get_hw_info(wl); |
5342 | if (ret < 0) { | 5525 | if (ret < 0) { |
5343 | wl1271_error("couldn't get hw info"); | 5526 | wl1271_error("couldn't get hw info"); |
5344 | goto out; | 5527 | goto out_irq; |
5345 | } | 5528 | } |
5346 | 5529 | ||
5347 | ret = wl->ops->identify_chip(wl); | 5530 | ret = wl->ops->identify_chip(wl); |
5348 | if (ret < 0) | 5531 | if (ret < 0) |
5349 | goto out; | 5532 | goto out_irq; |
5350 | 5533 | ||
5351 | ret = wl1271_init_ieee80211(wl); | 5534 | ret = wl1271_init_ieee80211(wl); |
5352 | if (ret) | 5535 | if (ret) |
@@ -5360,7 +5543,7 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev) | |||
5360 | ret = device_create_file(wl->dev, &dev_attr_bt_coex_state); | 5543 | ret = device_create_file(wl->dev, &dev_attr_bt_coex_state); |
5361 | if (ret < 0) { | 5544 | if (ret < 0) { |
5362 | wl1271_error("failed to create sysfs file bt_coex_state"); | 5545 | wl1271_error("failed to create sysfs file bt_coex_state"); |
5363 | goto out_irq; | 5546 | goto out_unreg; |
5364 | } | 5547 | } |
5365 | 5548 | ||
5366 | /* Create sysfs file to get HW PG version */ | 5549 | /* Create sysfs file to get HW PG version */ |
@@ -5385,6 +5568,9 @@ out_hw_pg_ver: | |||
5385 | out_bt_coex_state: | 5568 | out_bt_coex_state: |
5386 | device_remove_file(wl->dev, &dev_attr_bt_coex_state); | 5569 | device_remove_file(wl->dev, &dev_attr_bt_coex_state); |
5387 | 5570 | ||
5571 | out_unreg: | ||
5572 | wl1271_unregister_hw(wl); | ||
5573 | |||
5388 | out_irq: | 5574 | out_irq: |
5389 | free_irq(wl->irq, wl); | 5575 | free_irq(wl->irq, wl); |
5390 | 5576 | ||
diff --git a/drivers/net/wireless/ti/wlcore/ps.c b/drivers/net/wireless/ti/wlcore/ps.c index 47e81b32f7d..46d36fd30eb 100644 --- a/drivers/net/wireless/ti/wlcore/ps.c +++ b/drivers/net/wireless/ti/wlcore/ps.c | |||
@@ -35,6 +35,7 @@ void wl1271_elp_work(struct work_struct *work) | |||
35 | struct delayed_work *dwork; | 35 | struct delayed_work *dwork; |
36 | struct wl1271 *wl; | 36 | struct wl1271 *wl; |
37 | struct wl12xx_vif *wlvif; | 37 | struct wl12xx_vif *wlvif; |
38 | int ret; | ||
38 | 39 | ||
39 | dwork = container_of(work, struct delayed_work, work); | 40 | dwork = container_of(work, struct delayed_work, work); |
40 | wl = container_of(dwork, struct wl1271, elp_work); | 41 | wl = container_of(dwork, struct wl1271, elp_work); |
@@ -63,7 +64,12 @@ void wl1271_elp_work(struct work_struct *work) | |||
63 | } | 64 | } |
64 | 65 | ||
65 | wl1271_debug(DEBUG_PSM, "chip to elp"); | 66 | wl1271_debug(DEBUG_PSM, "chip to elp"); |
66 | wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_SLEEP); | 67 | ret = wlcore_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_SLEEP); |
68 | if (ret < 0) { | ||
69 | wl12xx_queue_recovery_work(wl); | ||
70 | goto out; | ||
71 | } | ||
72 | |||
67 | set_bit(WL1271_FLAG_IN_ELP, &wl->flags); | 73 | set_bit(WL1271_FLAG_IN_ELP, &wl->flags); |
68 | 74 | ||
69 | out: | 75 | out: |
@@ -76,7 +82,7 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl) | |||
76 | struct wl12xx_vif *wlvif; | 82 | struct wl12xx_vif *wlvif; |
77 | u32 timeout; | 83 | u32 timeout; |
78 | 84 | ||
79 | if (wl->quirks & WLCORE_QUIRK_NO_ELP) | 85 | if (wl->sleep_auth != WL1271_PSM_ELP) |
80 | return; | 86 | return; |
81 | 87 | ||
82 | /* we shouldn't get consecutive sleep requests */ | 88 | /* we shouldn't get consecutive sleep requests */ |
@@ -135,7 +141,11 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl) | |||
135 | wl->elp_compl = &compl; | 141 | wl->elp_compl = &compl; |
136 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 142 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
137 | 143 | ||
138 | wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_WAKE_UP); | 144 | ret = wlcore_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_WAKE_UP); |
145 | if (ret < 0) { | ||
146 | wl12xx_queue_recovery_work(wl); | ||
147 | goto err; | ||
148 | } | ||
139 | 149 | ||
140 | if (!pending) { | 150 | if (!pending) { |
141 | ret = wait_for_completion_timeout( | 151 | ret = wait_for_completion_timeout( |
diff --git a/drivers/net/wireless/ti/wlcore/rx.c b/drivers/net/wireless/ti/wlcore/rx.c index 78200dcacfc..f55e2f9e7ac 100644 --- a/drivers/net/wireless/ti/wlcore/rx.c +++ b/drivers/net/wireless/ti/wlcore/rx.c | |||
@@ -127,7 +127,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, | |||
127 | } | 127 | } |
128 | 128 | ||
129 | if (rx_align == WLCORE_RX_BUF_UNALIGNED) | 129 | if (rx_align == WLCORE_RX_BUF_UNALIGNED) |
130 | reserved = NET_IP_ALIGN; | 130 | reserved = RX_BUF_ALIGN; |
131 | 131 | ||
132 | /* the data read starts with the descriptor */ | 132 | /* the data read starts with the descriptor */ |
133 | desc = (struct wl1271_rx_descriptor *) data; | 133 | desc = (struct wl1271_rx_descriptor *) data; |
@@ -175,7 +175,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, | |||
175 | */ | 175 | */ |
176 | memcpy(buf, data + sizeof(*desc), pkt_data_len); | 176 | memcpy(buf, data + sizeof(*desc), pkt_data_len); |
177 | if (rx_align == WLCORE_RX_BUF_PADDED) | 177 | if (rx_align == WLCORE_RX_BUF_PADDED) |
178 | skb_pull(skb, NET_IP_ALIGN); | 178 | skb_pull(skb, RX_BUF_ALIGN); |
179 | 179 | ||
180 | *hlid = desc->hlid; | 180 | *hlid = desc->hlid; |
181 | 181 | ||
@@ -200,7 +200,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, | |||
200 | return is_data; | 200 | return is_data; |
201 | } | 201 | } |
202 | 202 | ||
203 | void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status_1 *status) | 203 | int wlcore_rx(struct wl1271 *wl, struct wl_fw_status_1 *status) |
204 | { | 204 | { |
205 | unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0}; | 205 | unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0}; |
206 | u32 buf_size; | 206 | u32 buf_size; |
@@ -211,6 +211,7 @@ void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status_1 *status) | |||
211 | u32 pkt_offset, des; | 211 | u32 pkt_offset, des; |
212 | u8 hlid; | 212 | u8 hlid; |
213 | enum wl_rx_buf_align rx_align; | 213 | enum wl_rx_buf_align rx_align; |
214 | int ret = 0; | ||
214 | 215 | ||
215 | while (drv_rx_counter != fw_rx_counter) { | 216 | while (drv_rx_counter != fw_rx_counter) { |
216 | buf_size = 0; | 217 | buf_size = 0; |
@@ -234,9 +235,14 @@ void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status_1 *status) | |||
234 | 235 | ||
235 | /* Read all available packets at once */ | 236 | /* Read all available packets at once */ |
236 | des = le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]); | 237 | des = le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]); |
237 | wlcore_hw_prepare_read(wl, des, buf_size); | 238 | ret = wlcore_hw_prepare_read(wl, des, buf_size); |
238 | wlcore_read_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf, | 239 | if (ret < 0) |
239 | buf_size, true); | 240 | goto out; |
241 | |||
242 | ret = wlcore_read_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf, | ||
243 | buf_size, true); | ||
244 | if (ret < 0) | ||
245 | goto out; | ||
240 | 246 | ||
241 | /* Split data into separate packets */ | 247 | /* Split data into separate packets */ |
242 | pkt_offset = 0; | 248 | pkt_offset = 0; |
@@ -273,11 +279,17 @@ void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status_1 *status) | |||
273 | * Write the driver's packet counter to the FW. This is only required | 279 | * Write the driver's packet counter to the FW. This is only required |
274 | * for older hardware revisions | 280 | * for older hardware revisions |
275 | */ | 281 | */ |
276 | if (wl->quirks & WLCORE_QUIRK_END_OF_TRANSACTION) | 282 | if (wl->quirks & WLCORE_QUIRK_END_OF_TRANSACTION) { |
277 | wl1271_write32(wl, WL12XX_REG_RX_DRIVER_COUNTER, | 283 | ret = wlcore_write32(wl, WL12XX_REG_RX_DRIVER_COUNTER, |
278 | wl->rx_counter); | 284 | wl->rx_counter); |
285 | if (ret < 0) | ||
286 | goto out; | ||
287 | } | ||
279 | 288 | ||
280 | wl12xx_rearm_rx_streaming(wl, active_hlids); | 289 | wl12xx_rearm_rx_streaming(wl, active_hlids); |
290 | |||
291 | out: | ||
292 | return ret; | ||
281 | } | 293 | } |
282 | 294 | ||
283 | #ifdef CONFIG_PM | 295 | #ifdef CONFIG_PM |
@@ -306,14 +318,19 @@ int wl1271_rx_filter_enable(struct wl1271 *wl, | |||
306 | return 0; | 318 | return 0; |
307 | } | 319 | } |
308 | 320 | ||
309 | void wl1271_rx_filter_clear_all(struct wl1271 *wl) | 321 | int wl1271_rx_filter_clear_all(struct wl1271 *wl) |
310 | { | 322 | { |
311 | int i; | 323 | int i, ret = 0; |
312 | 324 | ||
313 | for (i = 0; i < WL1271_MAX_RX_FILTERS; i++) { | 325 | for (i = 0; i < WL1271_MAX_RX_FILTERS; i++) { |
314 | if (!wl->rx_filter_enabled[i]) | 326 | if (!wl->rx_filter_enabled[i]) |
315 | continue; | 327 | continue; |
316 | wl1271_rx_filter_enable(wl, i, 0, NULL); | 328 | ret = wl1271_rx_filter_enable(wl, i, 0, NULL); |
329 | if (ret) | ||
330 | goto out; | ||
317 | } | 331 | } |
332 | |||
333 | out: | ||
334 | return ret; | ||
318 | } | 335 | } |
319 | #endif /* CONFIG_PM */ | 336 | #endif /* CONFIG_PM */ |
diff --git a/drivers/net/wireless/ti/wlcore/rx.h b/drivers/net/wireless/ti/wlcore/rx.h index 9be78017945..71eba189991 100644 --- a/drivers/net/wireless/ti/wlcore/rx.h +++ b/drivers/net/wireless/ti/wlcore/rx.h | |||
@@ -103,6 +103,12 @@ | |||
103 | /* If set, the buffer was padded by the FW to be 4 bytes aligned */ | 103 | /* If set, the buffer was padded by the FW to be 4 bytes aligned */ |
104 | #define RX_BUF_PADDED_PAYLOAD BIT(30) | 104 | #define RX_BUF_PADDED_PAYLOAD BIT(30) |
105 | 105 | ||
106 | /* | ||
107 | * Account for the padding inserted by the FW in case of RX_ALIGNMENT | ||
108 | * or for fixing alignment in case the packet wasn't aligned. | ||
109 | */ | ||
110 | #define RX_BUF_ALIGN 2 | ||
111 | |||
106 | /* Describes the alignment state of a Rx buffer */ | 112 | /* Describes the alignment state of a Rx buffer */ |
107 | enum wl_rx_buf_align { | 113 | enum wl_rx_buf_align { |
108 | WLCORE_RX_BUF_ALIGNED, | 114 | WLCORE_RX_BUF_ALIGNED, |
@@ -137,11 +143,11 @@ struct wl1271_rx_descriptor { | |||
137 | u8 reserved; | 143 | u8 reserved; |
138 | } __packed; | 144 | } __packed; |
139 | 145 | ||
140 | void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status_1 *status); | 146 | int wlcore_rx(struct wl1271 *wl, struct wl_fw_status_1 *status); |
141 | u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); | 147 | u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); |
142 | int wl1271_rx_filter_enable(struct wl1271 *wl, | 148 | int wl1271_rx_filter_enable(struct wl1271 *wl, |
143 | int index, bool enable, | 149 | int index, bool enable, |
144 | struct wl12xx_rx_filter *filter); | 150 | struct wl12xx_rx_filter *filter); |
145 | void wl1271_rx_filter_clear_all(struct wl1271 *wl); | 151 | int wl1271_rx_filter_clear_all(struct wl1271 *wl); |
146 | 152 | ||
147 | #endif | 153 | #endif |
diff --git a/drivers/net/wireless/ti/wlcore/sdio.c b/drivers/net/wireless/ti/wlcore/sdio.c index c67ec482e44..204e69fa932 100644 --- a/drivers/net/wireless/ti/wlcore/sdio.c +++ b/drivers/net/wireless/ti/wlcore/sdio.c | |||
@@ -71,8 +71,8 @@ static void wl1271_sdio_set_block_size(struct device *child, | |||
71 | sdio_release_host(func); | 71 | sdio_release_host(func); |
72 | } | 72 | } |
73 | 73 | ||
74 | static void wl12xx_sdio_raw_read(struct device *child, int addr, void *buf, | 74 | static int __must_check wl12xx_sdio_raw_read(struct device *child, int addr, |
75 | size_t len, bool fixed) | 75 | void *buf, size_t len, bool fixed) |
76 | { | 76 | { |
77 | int ret; | 77 | int ret; |
78 | struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent); | 78 | struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent); |
@@ -103,12 +103,14 @@ static void wl12xx_sdio_raw_read(struct device *child, int addr, void *buf, | |||
103 | 103 | ||
104 | sdio_release_host(func); | 104 | sdio_release_host(func); |
105 | 105 | ||
106 | if (ret) | 106 | if (WARN_ON(ret)) |
107 | dev_err(child->parent, "sdio read failed (%d)\n", ret); | 107 | dev_err(child->parent, "sdio read failed (%d)\n", ret); |
108 | |||
109 | return ret; | ||
108 | } | 110 | } |
109 | 111 | ||
110 | static void wl12xx_sdio_raw_write(struct device *child, int addr, void *buf, | 112 | static int __must_check wl12xx_sdio_raw_write(struct device *child, int addr, |
111 | size_t len, bool fixed) | 113 | void *buf, size_t len, bool fixed) |
112 | { | 114 | { |
113 | int ret; | 115 | int ret; |
114 | struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent); | 116 | struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent); |
@@ -139,25 +141,30 @@ static void wl12xx_sdio_raw_write(struct device *child, int addr, void *buf, | |||
139 | 141 | ||
140 | sdio_release_host(func); | 142 | sdio_release_host(func); |
141 | 143 | ||
142 | if (ret) | 144 | if (WARN_ON(ret)) |
143 | dev_err(child->parent, "sdio write failed (%d)\n", ret); | 145 | dev_err(child->parent, "sdio write failed (%d)\n", ret); |
146 | |||
147 | return ret; | ||
144 | } | 148 | } |
145 | 149 | ||
146 | static int wl12xx_sdio_power_on(struct wl12xx_sdio_glue *glue) | 150 | static int wl12xx_sdio_power_on(struct wl12xx_sdio_glue *glue) |
147 | { | 151 | { |
148 | int ret; | 152 | int ret; |
149 | struct sdio_func *func = dev_to_sdio_func(glue->dev); | 153 | struct sdio_func *func = dev_to_sdio_func(glue->dev); |
154 | struct mmc_card *card = func->card; | ||
150 | 155 | ||
151 | /* If enabled, tell runtime PM not to power off the card */ | 156 | ret = pm_runtime_get_sync(&card->dev); |
152 | if (pm_runtime_enabled(&func->dev)) { | 157 | if (ret) { |
153 | ret = pm_runtime_get_sync(&func->dev); | 158 | /* |
154 | if (ret < 0) | 159 | * Runtime PM might be temporarily disabled, or the device |
155 | goto out; | 160 | * might have a positive reference counter. Make sure it is |
156 | } else { | 161 | * really powered on. |
157 | /* Runtime PM is disabled: power up the card manually */ | 162 | */ |
158 | ret = mmc_power_restore_host(func->card->host); | 163 | ret = mmc_power_restore_host(card->host); |
159 | if (ret < 0) | 164 | if (ret < 0) { |
165 | pm_runtime_put_sync(&card->dev); | ||
160 | goto out; | 166 | goto out; |
167 | } | ||
161 | } | 168 | } |
162 | 169 | ||
163 | sdio_claim_host(func); | 170 | sdio_claim_host(func); |
@@ -172,20 +179,21 @@ static int wl12xx_sdio_power_off(struct wl12xx_sdio_glue *glue) | |||
172 | { | 179 | { |
173 | int ret; | 180 | int ret; |
174 | struct sdio_func *func = dev_to_sdio_func(glue->dev); | 181 | struct sdio_func *func = dev_to_sdio_func(glue->dev); |
182 | struct mmc_card *card = func->card; | ||
175 | 183 | ||
176 | sdio_claim_host(func); | 184 | sdio_claim_host(func); |
177 | sdio_disable_func(func); | 185 | sdio_disable_func(func); |
178 | sdio_release_host(func); | 186 | sdio_release_host(func); |
179 | 187 | ||
180 | /* Power off the card manually, even if runtime PM is enabled. */ | 188 | /* Power off the card manually in case it wasn't powered off above */ |
181 | ret = mmc_power_save_host(func->card->host); | 189 | ret = mmc_power_save_host(card->host); |
182 | if (ret < 0) | 190 | if (ret < 0) |
183 | return ret; | 191 | goto out; |
184 | 192 | ||
185 | /* If enabled, let runtime PM know the card is powered off */ | 193 | /* Let runtime PM know the card is powered off */ |
186 | if (pm_runtime_enabled(&func->dev)) | 194 | pm_runtime_put_sync(&card->dev); |
187 | ret = pm_runtime_put_sync(&func->dev); | ||
188 | 195 | ||
196 | out: | ||
189 | return ret; | 197 | return ret; |
190 | } | 198 | } |
191 | 199 | ||
diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c index 553cd3cbb98..6420abae40e 100644 --- a/drivers/net/wireless/ti/wlcore/spi.c +++ b/drivers/net/wireless/ti/wlcore/spi.c | |||
@@ -193,8 +193,8 @@ static int wl12xx_spi_read_busy(struct device *child) | |||
193 | return -ETIMEDOUT; | 193 | return -ETIMEDOUT; |
194 | } | 194 | } |
195 | 195 | ||
196 | static void wl12xx_spi_raw_read(struct device *child, int addr, void *buf, | 196 | static int __must_check wl12xx_spi_raw_read(struct device *child, int addr, |
197 | size_t len, bool fixed) | 197 | void *buf, size_t len, bool fixed) |
198 | { | 198 | { |
199 | struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent); | 199 | struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent); |
200 | struct wl1271 *wl = dev_get_drvdata(child); | 200 | struct wl1271 *wl = dev_get_drvdata(child); |
@@ -238,7 +238,7 @@ static void wl12xx_spi_raw_read(struct device *child, int addr, void *buf, | |||
238 | if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1) && | 238 | if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1) && |
239 | wl12xx_spi_read_busy(child)) { | 239 | wl12xx_spi_read_busy(child)) { |
240 | memset(buf, 0, chunk_len); | 240 | memset(buf, 0, chunk_len); |
241 | return; | 241 | return 0; |
242 | } | 242 | } |
243 | 243 | ||
244 | spi_message_init(&m); | 244 | spi_message_init(&m); |
@@ -256,10 +256,12 @@ static void wl12xx_spi_raw_read(struct device *child, int addr, void *buf, | |||
256 | buf += chunk_len; | 256 | buf += chunk_len; |
257 | len -= chunk_len; | 257 | len -= chunk_len; |
258 | } | 258 | } |
259 | |||
260 | return 0; | ||
259 | } | 261 | } |
260 | 262 | ||
261 | static void wl12xx_spi_raw_write(struct device *child, int addr, void *buf, | 263 | static int __must_check wl12xx_spi_raw_write(struct device *child, int addr, |
262 | size_t len, bool fixed) | 264 | void *buf, size_t len, bool fixed) |
263 | { | 265 | { |
264 | struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent); | 266 | struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent); |
265 | struct spi_transfer t[2 * WSPI_MAX_NUM_OF_CHUNKS]; | 267 | struct spi_transfer t[2 * WSPI_MAX_NUM_OF_CHUNKS]; |
@@ -304,6 +306,8 @@ static void wl12xx_spi_raw_write(struct device *child, int addr, void *buf, | |||
304 | } | 306 | } |
305 | 307 | ||
306 | spi_sync(to_spi_device(glue->dev), &m); | 308 | spi_sync(to_spi_device(glue->dev), &m); |
309 | |||
310 | return 0; | ||
307 | } | 311 | } |
308 | 312 | ||
309 | static struct wl1271_if_operations spi_ops = { | 313 | static struct wl1271_if_operations spi_ops = { |
diff --git a/drivers/net/wireless/ti/wlcore/testmode.c b/drivers/net/wireless/ti/wlcore/testmode.c index 0e59ea2cdd3..eeb339d61d1 100644 --- a/drivers/net/wireless/ti/wlcore/testmode.c +++ b/drivers/net/wireless/ti/wlcore/testmode.c | |||
@@ -108,6 +108,20 @@ static int wl1271_tm_cmd_test(struct wl1271 *wl, struct nlattr *tb[]) | |||
108 | } | 108 | } |
109 | 109 | ||
110 | if (answer) { | 110 | if (answer) { |
111 | /* If we got bip calibration answer print radio status */ | ||
112 | struct wl1271_cmd_cal_p2g *params = | ||
113 | (struct wl1271_cmd_cal_p2g *) buf; | ||
114 | |||
115 | s16 radio_status = (s16) le16_to_cpu(params->radio_status); | ||
116 | |||
117 | if (params->test.id == TEST_CMD_P2G_CAL && | ||
118 | radio_status < 0) | ||
119 | wl1271_warning("testmode cmd: radio status=%d", | ||
120 | radio_status); | ||
121 | else | ||
122 | wl1271_info("testmode cmd: radio status=%d", | ||
123 | radio_status); | ||
124 | |||
111 | len = nla_total_size(buf_len); | 125 | len = nla_total_size(buf_len); |
112 | skb = cfg80211_testmode_alloc_reply_skb(wl->hw->wiphy, len); | 126 | skb = cfg80211_testmode_alloc_reply_skb(wl->hw->wiphy, len); |
113 | if (!skb) { | 127 | if (!skb) { |
diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c index 6983e7a829d..6a28aeecf00 100644 --- a/drivers/net/wireless/ti/wlcore/tx.c +++ b/drivers/net/wireless/ti/wlcore/tx.c | |||
@@ -305,11 +305,15 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
305 | if (is_dummy || !wlvif) | 305 | if (is_dummy || !wlvif) |
306 | rate_idx = 0; | 306 | rate_idx = 0; |
307 | else if (wlvif->bss_type != BSS_TYPE_AP_BSS) { | 307 | else if (wlvif->bss_type != BSS_TYPE_AP_BSS) { |
308 | /* if the packets are destined for AP (have a STA entry) | 308 | /* |
309 | send them with AP rate policies, otherwise use default | 309 | * if the packets are destined for AP (have a STA entry) |
310 | basic rates */ | 310 | * send them with AP rate policies (EAPOLs are an exception), |
311 | * otherwise use default basic rates | ||
312 | */ | ||
311 | if (control->flags & IEEE80211_TX_CTL_NO_CCK_RATE) | 313 | if (control->flags & IEEE80211_TX_CTL_NO_CCK_RATE) |
312 | rate_idx = wlvif->sta.p2p_rate_idx; | 314 | rate_idx = wlvif->sta.p2p_rate_idx; |
315 | else if (skb->protocol == cpu_to_be16(ETH_P_PAE)) | ||
316 | rate_idx = wlvif->sta.basic_rate_idx; | ||
313 | else if (control->control.sta) | 317 | else if (control->control.sta) |
314 | rate_idx = wlvif->sta.ap_rate_idx; | 318 | rate_idx = wlvif->sta.ap_rate_idx; |
315 | else | 319 | else |
@@ -348,8 +352,10 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
348 | bool is_dummy; | 352 | bool is_dummy; |
349 | bool is_gem = false; | 353 | bool is_gem = false; |
350 | 354 | ||
351 | if (!skb) | 355 | if (!skb) { |
356 | wl1271_error("discarding null skb"); | ||
352 | return -EINVAL; | 357 | return -EINVAL; |
358 | } | ||
353 | 359 | ||
354 | info = IEEE80211_SKB_CB(skb); | 360 | info = IEEE80211_SKB_CB(skb); |
355 | 361 | ||
@@ -658,7 +664,17 @@ void wl12xx_rearm_rx_streaming(struct wl1271 *wl, unsigned long *active_hlids) | |||
658 | } | 664 | } |
659 | } | 665 | } |
660 | 666 | ||
661 | void wl1271_tx_work_locked(struct wl1271 *wl) | 667 | /* |
668 | * Returns failure values only in case of failed bus ops within this function. | ||
669 | * wl1271_prepare_tx_frame retvals won't be returned in order to avoid | ||
670 | * triggering recovery by higher layers when not necessary. | ||
671 | * In case a FW command fails within wl1271_prepare_tx_frame fails a recovery | ||
672 | * will be queued in wl1271_cmd_send. -EAGAIN/-EBUSY from prepare_tx_frame | ||
673 | * can occur and are legitimate so don't propagate. -EINVAL will emit a WARNING | ||
674 | * within prepare_tx_frame code but there's nothing we should do about those | ||
675 | * as well. | ||
676 | */ | ||
677 | int wlcore_tx_work_locked(struct wl1271 *wl) | ||
662 | { | 678 | { |
663 | struct wl12xx_vif *wlvif; | 679 | struct wl12xx_vif *wlvif; |
664 | struct sk_buff *skb; | 680 | struct sk_buff *skb; |
@@ -666,10 +682,11 @@ void wl1271_tx_work_locked(struct wl1271 *wl) | |||
666 | u32 buf_offset = 0, last_len = 0; | 682 | u32 buf_offset = 0, last_len = 0; |
667 | bool sent_packets = false; | 683 | bool sent_packets = false; |
668 | unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0}; | 684 | unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0}; |
669 | int ret; | 685 | int ret = 0; |
686 | int bus_ret = 0; | ||
670 | 687 | ||
671 | if (unlikely(wl->state == WL1271_STATE_OFF)) | 688 | if (unlikely(wl->state == WL1271_STATE_OFF)) |
672 | return; | 689 | return 0; |
673 | 690 | ||
674 | while ((skb = wl1271_skb_dequeue(wl))) { | 691 | while ((skb = wl1271_skb_dequeue(wl))) { |
675 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 692 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
@@ -690,8 +707,11 @@ void wl1271_tx_work_locked(struct wl1271 *wl) | |||
690 | 707 | ||
691 | buf_offset = wlcore_hw_pre_pkt_send(wl, buf_offset, | 708 | buf_offset = wlcore_hw_pre_pkt_send(wl, buf_offset, |
692 | last_len); | 709 | last_len); |
693 | wlcore_write_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf, | 710 | bus_ret = wlcore_write_data(wl, REG_SLV_MEM_DATA, |
694 | buf_offset, true); | 711 | wl->aggr_buf, buf_offset, true); |
712 | if (bus_ret < 0) | ||
713 | goto out; | ||
714 | |||
695 | sent_packets = true; | 715 | sent_packets = true; |
696 | buf_offset = 0; | 716 | buf_offset = 0; |
697 | continue; | 717 | continue; |
@@ -727,8 +747,11 @@ void wl1271_tx_work_locked(struct wl1271 *wl) | |||
727 | out_ack: | 747 | out_ack: |
728 | if (buf_offset) { | 748 | if (buf_offset) { |
729 | buf_offset = wlcore_hw_pre_pkt_send(wl, buf_offset, last_len); | 749 | buf_offset = wlcore_hw_pre_pkt_send(wl, buf_offset, last_len); |
730 | wlcore_write_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf, | 750 | bus_ret = wlcore_write_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf, |
731 | buf_offset, true); | 751 | buf_offset, true); |
752 | if (bus_ret < 0) | ||
753 | goto out; | ||
754 | |||
732 | sent_packets = true; | 755 | sent_packets = true; |
733 | } | 756 | } |
734 | if (sent_packets) { | 757 | if (sent_packets) { |
@@ -736,13 +759,19 @@ out_ack: | |||
736 | * Interrupt the firmware with the new packets. This is only | 759 | * Interrupt the firmware with the new packets. This is only |
737 | * required for older hardware revisions | 760 | * required for older hardware revisions |
738 | */ | 761 | */ |
739 | if (wl->quirks & WLCORE_QUIRK_END_OF_TRANSACTION) | 762 | if (wl->quirks & WLCORE_QUIRK_END_OF_TRANSACTION) { |
740 | wl1271_write32(wl, WL12XX_HOST_WR_ACCESS, | 763 | bus_ret = wlcore_write32(wl, WL12XX_HOST_WR_ACCESS, |
741 | wl->tx_packets_count); | 764 | wl->tx_packets_count); |
765 | if (bus_ret < 0) | ||
766 | goto out; | ||
767 | } | ||
742 | 768 | ||
743 | wl1271_handle_tx_low_watermark(wl); | 769 | wl1271_handle_tx_low_watermark(wl); |
744 | } | 770 | } |
745 | wl12xx_rearm_rx_streaming(wl, active_hlids); | 771 | wl12xx_rearm_rx_streaming(wl, active_hlids); |
772 | |||
773 | out: | ||
774 | return bus_ret; | ||
746 | } | 775 | } |
747 | 776 | ||
748 | void wl1271_tx_work(struct work_struct *work) | 777 | void wl1271_tx_work(struct work_struct *work) |
@@ -755,7 +784,11 @@ void wl1271_tx_work(struct work_struct *work) | |||
755 | if (ret < 0) | 784 | if (ret < 0) |
756 | goto out; | 785 | goto out; |
757 | 786 | ||
758 | wl1271_tx_work_locked(wl); | 787 | ret = wlcore_tx_work_locked(wl); |
788 | if (ret < 0) { | ||
789 | wl12xx_queue_recovery_work(wl); | ||
790 | goto out; | ||
791 | } | ||
759 | 792 | ||
760 | wl1271_ps_elp_sleep(wl); | 793 | wl1271_ps_elp_sleep(wl); |
761 | out: | 794 | out: |
@@ -877,22 +910,28 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, | |||
877 | } | 910 | } |
878 | 911 | ||
879 | /* Called upon reception of a TX complete interrupt */ | 912 | /* Called upon reception of a TX complete interrupt */ |
880 | void wl1271_tx_complete(struct wl1271 *wl) | 913 | int wlcore_tx_complete(struct wl1271 *wl) |
881 | { | 914 | { |
882 | struct wl1271_acx_mem_map *memmap = | 915 | struct wl1271_acx_mem_map *memmap = |
883 | (struct wl1271_acx_mem_map *)wl->target_mem_map; | 916 | (struct wl1271_acx_mem_map *)wl->target_mem_map; |
884 | u32 count, fw_counter; | 917 | u32 count, fw_counter; |
885 | u32 i; | 918 | u32 i; |
919 | int ret; | ||
886 | 920 | ||
887 | /* read the tx results from the chipset */ | 921 | /* read the tx results from the chipset */ |
888 | wl1271_read(wl, le32_to_cpu(memmap->tx_result), | 922 | ret = wlcore_read(wl, le32_to_cpu(memmap->tx_result), |
889 | wl->tx_res_if, sizeof(*wl->tx_res_if), false); | 923 | wl->tx_res_if, sizeof(*wl->tx_res_if), false); |
924 | if (ret < 0) | ||
925 | goto out; | ||
926 | |||
890 | fw_counter = le32_to_cpu(wl->tx_res_if->tx_result_fw_counter); | 927 | fw_counter = le32_to_cpu(wl->tx_res_if->tx_result_fw_counter); |
891 | 928 | ||
892 | /* write host counter to chipset (to ack) */ | 929 | /* write host counter to chipset (to ack) */ |
893 | wl1271_write32(wl, le32_to_cpu(memmap->tx_result) + | 930 | ret = wlcore_write32(wl, le32_to_cpu(memmap->tx_result) + |
894 | offsetof(struct wl1271_tx_hw_res_if, | 931 | offsetof(struct wl1271_tx_hw_res_if, |
895 | tx_result_host_counter), fw_counter); | 932 | tx_result_host_counter), fw_counter); |
933 | if (ret < 0) | ||
934 | goto out; | ||
896 | 935 | ||
897 | count = fw_counter - wl->tx_results_count; | 936 | count = fw_counter - wl->tx_results_count; |
898 | wl1271_debug(DEBUG_TX, "tx_complete received, packets: %d", count); | 937 | wl1271_debug(DEBUG_TX, "tx_complete received, packets: %d", count); |
@@ -912,8 +951,11 @@ void wl1271_tx_complete(struct wl1271 *wl) | |||
912 | 951 | ||
913 | wl->tx_results_count++; | 952 | wl->tx_results_count++; |
914 | } | 953 | } |
954 | |||
955 | out: | ||
956 | return ret; | ||
915 | } | 957 | } |
916 | EXPORT_SYMBOL(wl1271_tx_complete); | 958 | EXPORT_SYMBOL(wlcore_tx_complete); |
917 | 959 | ||
918 | void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid) | 960 | void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid) |
919 | { | 961 | { |
diff --git a/drivers/net/wireless/ti/wlcore/tx.h b/drivers/net/wireless/ti/wlcore/tx.h index fa4be1b9113..1e939b01615 100644 --- a/drivers/net/wireless/ti/wlcore/tx.h +++ b/drivers/net/wireless/ti/wlcore/tx.h | |||
@@ -234,8 +234,8 @@ static inline int wl1271_tx_total_queue_count(struct wl1271 *wl) | |||
234 | } | 234 | } |
235 | 235 | ||
236 | void wl1271_tx_work(struct work_struct *work); | 236 | void wl1271_tx_work(struct work_struct *work); |
237 | void wl1271_tx_work_locked(struct wl1271 *wl); | 237 | int wlcore_tx_work_locked(struct wl1271 *wl); |
238 | void wl1271_tx_complete(struct wl1271 *wl); | 238 | int wlcore_tx_complete(struct wl1271 *wl); |
239 | void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif); | 239 | void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif); |
240 | void wl12xx_tx_reset(struct wl1271 *wl); | 240 | void wl12xx_tx_reset(struct wl1271 *wl); |
241 | void wl1271_tx_flush(struct wl1271 *wl); | 241 | void wl1271_tx_flush(struct wl1271 *wl); |
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h index 761a72f4b8d..e796974df59 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/drivers/net/wireless/ti/wlcore/wlcore.h | |||
@@ -41,9 +41,9 @@ struct wlcore_ops { | |||
41 | int (*identify_fw)(struct wl1271 *wl); | 41 | int (*identify_fw)(struct wl1271 *wl); |
42 | int (*boot)(struct wl1271 *wl); | 42 | int (*boot)(struct wl1271 *wl); |
43 | int (*plt_init)(struct wl1271 *wl); | 43 | int (*plt_init)(struct wl1271 *wl); |
44 | void (*trigger_cmd)(struct wl1271 *wl, int cmd_box_addr, | 44 | int (*trigger_cmd)(struct wl1271 *wl, int cmd_box_addr, |
45 | void *buf, size_t len); | 45 | void *buf, size_t len); |
46 | void (*ack_event)(struct wl1271 *wl); | 46 | int (*ack_event)(struct wl1271 *wl); |
47 | u32 (*calc_tx_blocks)(struct wl1271 *wl, u32 len, u32 spare_blks); | 47 | u32 (*calc_tx_blocks)(struct wl1271 *wl, u32 len, u32 spare_blks); |
48 | void (*set_tx_desc_blocks)(struct wl1271 *wl, | 48 | void (*set_tx_desc_blocks)(struct wl1271 *wl, |
49 | struct wl1271_tx_hw_descr *desc, | 49 | struct wl1271_tx_hw_descr *desc, |
@@ -53,17 +53,17 @@ struct wlcore_ops { | |||
53 | struct sk_buff *skb); | 53 | struct sk_buff *skb); |
54 | enum wl_rx_buf_align (*get_rx_buf_align)(struct wl1271 *wl, | 54 | enum wl_rx_buf_align (*get_rx_buf_align)(struct wl1271 *wl, |
55 | u32 rx_desc); | 55 | u32 rx_desc); |
56 | void (*prepare_read)(struct wl1271 *wl, u32 rx_desc, u32 len); | 56 | int (*prepare_read)(struct wl1271 *wl, u32 rx_desc, u32 len); |
57 | u32 (*get_rx_packet_len)(struct wl1271 *wl, void *rx_data, | 57 | u32 (*get_rx_packet_len)(struct wl1271 *wl, void *rx_data, |
58 | u32 data_len); | 58 | u32 data_len); |
59 | void (*tx_delayed_compl)(struct wl1271 *wl); | 59 | int (*tx_delayed_compl)(struct wl1271 *wl); |
60 | void (*tx_immediate_compl)(struct wl1271 *wl); | 60 | void (*tx_immediate_compl)(struct wl1271 *wl); |
61 | int (*hw_init)(struct wl1271 *wl); | 61 | int (*hw_init)(struct wl1271 *wl); |
62 | int (*init_vif)(struct wl1271 *wl, struct wl12xx_vif *wlvif); | 62 | int (*init_vif)(struct wl1271 *wl, struct wl12xx_vif *wlvif); |
63 | u32 (*sta_get_ap_rate_mask)(struct wl1271 *wl, | 63 | u32 (*sta_get_ap_rate_mask)(struct wl1271 *wl, |
64 | struct wl12xx_vif *wlvif); | 64 | struct wl12xx_vif *wlvif); |
65 | s8 (*get_pg_ver)(struct wl1271 *wl); | 65 | int (*get_pg_ver)(struct wl1271 *wl, s8 *ver); |
66 | void (*get_mac)(struct wl1271 *wl); | 66 | int (*get_mac)(struct wl1271 *wl); |
67 | void (*set_tx_desc_csum)(struct wl1271 *wl, | 67 | void (*set_tx_desc_csum)(struct wl1271 *wl, |
68 | struct wl1271_tx_hw_descr *desc, | 68 | struct wl1271_tx_hw_descr *desc, |
69 | struct sk_buff *skb); | 69 | struct sk_buff *skb); |
@@ -387,6 +387,9 @@ struct wl1271 { | |||
387 | 387 | ||
388 | /* mutex for protecting the tx_flush function */ | 388 | /* mutex for protecting the tx_flush function */ |
389 | struct mutex flush_mutex; | 389 | struct mutex flush_mutex; |
390 | |||
391 | /* sleep auth value currently configured to FW */ | ||
392 | int sleep_auth; | ||
390 | }; | 393 | }; |
391 | 394 | ||
392 | int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev); | 395 | int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev); |
@@ -398,6 +401,13 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, | |||
398 | struct ieee80211_sta *sta, | 401 | struct ieee80211_sta *sta, |
399 | struct ieee80211_key_conf *key_conf); | 402 | struct ieee80211_key_conf *key_conf); |
400 | 403 | ||
404 | static inline void | ||
405 | wlcore_set_ht_cap(struct wl1271 *wl, enum ieee80211_band band, | ||
406 | struct ieee80211_sta_ht_cap *ht_cap) | ||
407 | { | ||
408 | memcpy(&wl->ht_cap[band], ht_cap, sizeof(*ht_cap)); | ||
409 | } | ||
410 | |||
401 | /* Firmware image load chunk size */ | 411 | /* Firmware image load chunk size */ |
402 | #define CHUNK_SIZE 16384 | 412 | #define CHUNK_SIZE 16384 |
403 | 413 | ||
diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h index 8260b1e9288..4273a21cdde 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore_i.h +++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h | |||
@@ -209,10 +209,10 @@ struct wl1271_scan { | |||
209 | }; | 209 | }; |
210 | 210 | ||
211 | struct wl1271_if_operations { | 211 | struct wl1271_if_operations { |
212 | void (*read)(struct device *child, int addr, void *buf, size_t len, | 212 | int __must_check (*read)(struct device *child, int addr, void *buf, |
213 | bool fixed); | 213 | size_t len, bool fixed); |
214 | void (*write)(struct device *child, int addr, void *buf, size_t len, | 214 | int __must_check (*write)(struct device *child, int addr, void *buf, |
215 | bool fixed); | 215 | size_t len, bool fixed); |
216 | void (*reset)(struct device *child); | 216 | void (*reset)(struct device *child); |
217 | void (*init)(struct device *child); | 217 | void (*init)(struct device *child); |
218 | int (*power)(struct device *child, bool enable); | 218 | int (*power)(struct device *child, bool enable); |
@@ -247,6 +247,7 @@ enum wl12xx_flags { | |||
247 | WL1271_FLAG_RECOVERY_IN_PROGRESS, | 247 | WL1271_FLAG_RECOVERY_IN_PROGRESS, |
248 | WL1271_FLAG_VIF_CHANGE_IN_PROGRESS, | 248 | WL1271_FLAG_VIF_CHANGE_IN_PROGRESS, |
249 | WL1271_FLAG_INTENDED_FW_RECOVERY, | 249 | WL1271_FLAG_INTENDED_FW_RECOVERY, |
250 | WL1271_FLAG_SDIO_FAILED, | ||
250 | }; | 251 | }; |
251 | 252 | ||
252 | enum wl12xx_vif_flags { | 253 | enum wl12xx_vif_flags { |
diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index 19110f0eb15..9ac829e22e7 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c | |||
@@ -45,6 +45,9 @@ static const struct usb_device_id pn533_table[] = { | |||
45 | }; | 45 | }; |
46 | MODULE_DEVICE_TABLE(usb, pn533_table); | 46 | MODULE_DEVICE_TABLE(usb, pn533_table); |
47 | 47 | ||
48 | /* How much time we spend listening for initiators */ | ||
49 | #define PN533_LISTEN_TIME 2 | ||
50 | |||
48 | /* frame definitions */ | 51 | /* frame definitions */ |
49 | #define PN533_FRAME_TAIL_SIZE 2 | 52 | #define PN533_FRAME_TAIL_SIZE 2 |
50 | #define PN533_FRAME_SIZE(f) (sizeof(struct pn533_frame) + f->datalen + \ | 53 | #define PN533_FRAME_SIZE(f) (sizeof(struct pn533_frame) + f->datalen + \ |
@@ -74,6 +77,10 @@ MODULE_DEVICE_TABLE(usb, pn533_table); | |||
74 | #define PN533_CMD_IN_RELEASE 0x52 | 77 | #define PN533_CMD_IN_RELEASE 0x52 |
75 | #define PN533_CMD_IN_JUMP_FOR_DEP 0x56 | 78 | #define PN533_CMD_IN_JUMP_FOR_DEP 0x56 |
76 | 79 | ||
80 | #define PN533_CMD_TG_INIT_AS_TARGET 0x8c | ||
81 | #define PN533_CMD_TG_GET_DATA 0x86 | ||
82 | #define PN533_CMD_TG_SET_DATA 0x8e | ||
83 | |||
77 | #define PN533_CMD_RESPONSE(cmd) (cmd + 1) | 84 | #define PN533_CMD_RESPONSE(cmd) (cmd + 1) |
78 | 85 | ||
79 | /* PN533 Return codes */ | 86 | /* PN533 Return codes */ |
@@ -81,6 +88,9 @@ MODULE_DEVICE_TABLE(usb, pn533_table); | |||
81 | #define PN533_CMD_MI_MASK 0x40 | 88 | #define PN533_CMD_MI_MASK 0x40 |
82 | #define PN533_CMD_RET_SUCCESS 0x00 | 89 | #define PN533_CMD_RET_SUCCESS 0x00 |
83 | 90 | ||
91 | /* PN533 status codes */ | ||
92 | #define PN533_STATUS_TARGET_RELEASED 0x29 | ||
93 | |||
84 | struct pn533; | 94 | struct pn533; |
85 | 95 | ||
86 | typedef int (*pn533_cmd_complete_t) (struct pn533 *dev, void *arg, | 96 | typedef int (*pn533_cmd_complete_t) (struct pn533 *dev, void *arg, |
@@ -97,8 +107,14 @@ struct pn533_fw_version { | |||
97 | }; | 107 | }; |
98 | 108 | ||
99 | /* PN533_CMD_RF_CONFIGURATION */ | 109 | /* PN533_CMD_RF_CONFIGURATION */ |
110 | #define PN533_CFGITEM_TIMING 0x02 | ||
100 | #define PN533_CFGITEM_MAX_RETRIES 0x05 | 111 | #define PN533_CFGITEM_MAX_RETRIES 0x05 |
101 | 112 | ||
113 | #define PN533_CONFIG_TIMING_102 0xb | ||
114 | #define PN533_CONFIG_TIMING_204 0xc | ||
115 | #define PN533_CONFIG_TIMING_409 0xd | ||
116 | #define PN533_CONFIG_TIMING_819 0xe | ||
117 | |||
102 | #define PN533_CONFIG_MAX_RETRIES_NO_RETRY 0x00 | 118 | #define PN533_CONFIG_MAX_RETRIES_NO_RETRY 0x00 |
103 | #define PN533_CONFIG_MAX_RETRIES_ENDLESS 0xFF | 119 | #define PN533_CONFIG_MAX_RETRIES_ENDLESS 0xFF |
104 | 120 | ||
@@ -108,6 +124,12 @@ struct pn533_config_max_retries { | |||
108 | u8 mx_rty_passive_act; | 124 | u8 mx_rty_passive_act; |
109 | } __packed; | 125 | } __packed; |
110 | 126 | ||
127 | struct pn533_config_timing { | ||
128 | u8 rfu; | ||
129 | u8 atr_res_timeout; | ||
130 | u8 dep_timeout; | ||
131 | } __packed; | ||
132 | |||
111 | /* PN533_CMD_IN_LIST_PASSIVE_TARGET */ | 133 | /* PN533_CMD_IN_LIST_PASSIVE_TARGET */ |
112 | 134 | ||
113 | /* felica commands opcode */ | 135 | /* felica commands opcode */ |
@@ -144,6 +166,7 @@ enum { | |||
144 | PN533_POLL_MOD_424KBPS_FELICA, | 166 | PN533_POLL_MOD_424KBPS_FELICA, |
145 | PN533_POLL_MOD_106KBPS_JEWEL, | 167 | PN533_POLL_MOD_106KBPS_JEWEL, |
146 | PN533_POLL_MOD_847KBPS_B, | 168 | PN533_POLL_MOD_847KBPS_B, |
169 | PN533_LISTEN_MOD, | ||
147 | 170 | ||
148 | __PN533_POLL_MOD_AFTER_LAST, | 171 | __PN533_POLL_MOD_AFTER_LAST, |
149 | }; | 172 | }; |
@@ -211,6 +234,9 @@ const struct pn533_poll_modulations poll_mod[] = { | |||
211 | }, | 234 | }, |
212 | .len = 3, | 235 | .len = 3, |
213 | }, | 236 | }, |
237 | [PN533_LISTEN_MOD] = { | ||
238 | .len = 0, | ||
239 | }, | ||
214 | }; | 240 | }; |
215 | 241 | ||
216 | /* PN533_CMD_IN_ATR */ | 242 | /* PN533_CMD_IN_ATR */ |
@@ -237,7 +263,7 @@ struct pn533_cmd_jump_dep { | |||
237 | u8 active; | 263 | u8 active; |
238 | u8 baud; | 264 | u8 baud; |
239 | u8 next; | 265 | u8 next; |
240 | u8 gt[]; | 266 | u8 data[]; |
241 | } __packed; | 267 | } __packed; |
242 | 268 | ||
243 | struct pn533_cmd_jump_dep_response { | 269 | struct pn533_cmd_jump_dep_response { |
@@ -253,6 +279,29 @@ struct pn533_cmd_jump_dep_response { | |||
253 | u8 gt[]; | 279 | u8 gt[]; |
254 | } __packed; | 280 | } __packed; |
255 | 281 | ||
282 | |||
283 | /* PN533_TG_INIT_AS_TARGET */ | ||
284 | #define PN533_INIT_TARGET_PASSIVE 0x1 | ||
285 | #define PN533_INIT_TARGET_DEP 0x2 | ||
286 | |||
287 | #define PN533_INIT_TARGET_RESP_FRAME_MASK 0x3 | ||
288 | #define PN533_INIT_TARGET_RESP_ACTIVE 0x1 | ||
289 | #define PN533_INIT_TARGET_RESP_DEP 0x4 | ||
290 | |||
291 | struct pn533_cmd_init_target { | ||
292 | u8 mode; | ||
293 | u8 mifare[6]; | ||
294 | u8 felica[18]; | ||
295 | u8 nfcid3[10]; | ||
296 | u8 gb_len; | ||
297 | u8 gb[]; | ||
298 | } __packed; | ||
299 | |||
300 | struct pn533_cmd_init_target_response { | ||
301 | u8 mode; | ||
302 | u8 cmd[]; | ||
303 | } __packed; | ||
304 | |||
256 | struct pn533 { | 305 | struct pn533 { |
257 | struct usb_device *udev; | 306 | struct usb_device *udev; |
258 | struct usb_interface *interface; | 307 | struct usb_interface *interface; |
@@ -270,22 +319,31 @@ struct pn533 { | |||
270 | 319 | ||
271 | struct workqueue_struct *wq; | 320 | struct workqueue_struct *wq; |
272 | struct work_struct cmd_work; | 321 | struct work_struct cmd_work; |
322 | struct work_struct poll_work; | ||
273 | struct work_struct mi_work; | 323 | struct work_struct mi_work; |
324 | struct work_struct tg_work; | ||
325 | struct timer_list listen_timer; | ||
274 | struct pn533_frame *wq_in_frame; | 326 | struct pn533_frame *wq_in_frame; |
275 | int wq_in_error; | 327 | int wq_in_error; |
328 | int cancel_listen; | ||
276 | 329 | ||
277 | pn533_cmd_complete_t cmd_complete; | 330 | pn533_cmd_complete_t cmd_complete; |
278 | void *cmd_complete_arg; | 331 | void *cmd_complete_arg; |
279 | struct semaphore cmd_lock; | 332 | struct mutex cmd_lock; |
280 | u8 cmd; | 333 | u8 cmd; |
281 | 334 | ||
282 | struct pn533_poll_modulations *poll_mod_active[PN533_POLL_MOD_MAX + 1]; | 335 | struct pn533_poll_modulations *poll_mod_active[PN533_POLL_MOD_MAX + 1]; |
283 | u8 poll_mod_count; | 336 | u8 poll_mod_count; |
284 | u8 poll_mod_curr; | 337 | u8 poll_mod_curr; |
285 | u32 poll_protocols; | 338 | u32 poll_protocols; |
339 | u32 listen_protocols; | ||
340 | |||
341 | u8 *gb; | ||
342 | size_t gb_len; | ||
286 | 343 | ||
287 | u8 tgt_available_prots; | 344 | u8 tgt_available_prots; |
288 | u8 tgt_active_prot; | 345 | u8 tgt_active_prot; |
346 | u8 tgt_mode; | ||
289 | }; | 347 | }; |
290 | 348 | ||
291 | struct pn533_frame { | 349 | struct pn533_frame { |
@@ -405,7 +463,7 @@ static void pn533_wq_cmd_complete(struct work_struct *work) | |||
405 | PN533_FRAME_CMD_PARAMS_LEN(in_frame)); | 463 | PN533_FRAME_CMD_PARAMS_LEN(in_frame)); |
406 | 464 | ||
407 | if (rc != -EINPROGRESS) | 465 | if (rc != -EINPROGRESS) |
408 | up(&dev->cmd_lock); | 466 | mutex_unlock(&dev->cmd_lock); |
409 | } | 467 | } |
410 | 468 | ||
411 | static void pn533_recv_response(struct urb *urb) | 469 | static void pn533_recv_response(struct urb *urb) |
@@ -583,7 +641,7 @@ static int pn533_send_cmd_frame_async(struct pn533 *dev, | |||
583 | 641 | ||
584 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 642 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); |
585 | 643 | ||
586 | if (down_trylock(&dev->cmd_lock)) | 644 | if (!mutex_trylock(&dev->cmd_lock)) |
587 | return -EBUSY; | 645 | return -EBUSY; |
588 | 646 | ||
589 | rc = __pn533_send_cmd_frame_async(dev, out_frame, in_frame, | 647 | rc = __pn533_send_cmd_frame_async(dev, out_frame, in_frame, |
@@ -593,7 +651,7 @@ static int pn533_send_cmd_frame_async(struct pn533 *dev, | |||
593 | 651 | ||
594 | return 0; | 652 | return 0; |
595 | error: | 653 | error: |
596 | up(&dev->cmd_lock); | 654 | mutex_unlock(&dev->cmd_lock); |
597 | return rc; | 655 | return rc; |
598 | } | 656 | } |
599 | 657 | ||
@@ -963,6 +1021,11 @@ static int pn533_target_found(struct pn533 *dev, | |||
963 | return 0; | 1021 | return 0; |
964 | } | 1022 | } |
965 | 1023 | ||
1024 | static inline void pn533_poll_next_mod(struct pn533 *dev) | ||
1025 | { | ||
1026 | dev->poll_mod_curr = (dev->poll_mod_curr + 1) % dev->poll_mod_count; | ||
1027 | } | ||
1028 | |||
966 | static void pn533_poll_reset_mod_list(struct pn533 *dev) | 1029 | static void pn533_poll_reset_mod_list(struct pn533 *dev) |
967 | { | 1030 | { |
968 | dev->poll_mod_count = 0; | 1031 | dev->poll_mod_count = 0; |
@@ -975,102 +1038,283 @@ static void pn533_poll_add_mod(struct pn533 *dev, u8 mod_index) | |||
975 | dev->poll_mod_count++; | 1038 | dev->poll_mod_count++; |
976 | } | 1039 | } |
977 | 1040 | ||
978 | static void pn533_poll_create_mod_list(struct pn533 *dev, u32 protocols) | 1041 | static void pn533_poll_create_mod_list(struct pn533 *dev, |
1042 | u32 im_protocols, u32 tm_protocols) | ||
979 | { | 1043 | { |
980 | pn533_poll_reset_mod_list(dev); | 1044 | pn533_poll_reset_mod_list(dev); |
981 | 1045 | ||
982 | if (protocols & NFC_PROTO_MIFARE_MASK | 1046 | if (im_protocols & NFC_PROTO_MIFARE_MASK |
983 | || protocols & NFC_PROTO_ISO14443_MASK | 1047 | || im_protocols & NFC_PROTO_ISO14443_MASK |
984 | || protocols & NFC_PROTO_NFC_DEP_MASK) | 1048 | || im_protocols & NFC_PROTO_NFC_DEP_MASK) |
985 | pn533_poll_add_mod(dev, PN533_POLL_MOD_106KBPS_A); | 1049 | pn533_poll_add_mod(dev, PN533_POLL_MOD_106KBPS_A); |
986 | 1050 | ||
987 | if (protocols & NFC_PROTO_FELICA_MASK | 1051 | if (im_protocols & NFC_PROTO_FELICA_MASK |
988 | || protocols & NFC_PROTO_NFC_DEP_MASK) { | 1052 | || im_protocols & NFC_PROTO_NFC_DEP_MASK) { |
989 | pn533_poll_add_mod(dev, PN533_POLL_MOD_212KBPS_FELICA); | 1053 | pn533_poll_add_mod(dev, PN533_POLL_MOD_212KBPS_FELICA); |
990 | pn533_poll_add_mod(dev, PN533_POLL_MOD_424KBPS_FELICA); | 1054 | pn533_poll_add_mod(dev, PN533_POLL_MOD_424KBPS_FELICA); |
991 | } | 1055 | } |
992 | 1056 | ||
993 | if (protocols & NFC_PROTO_JEWEL_MASK) | 1057 | if (im_protocols & NFC_PROTO_JEWEL_MASK) |
994 | pn533_poll_add_mod(dev, PN533_POLL_MOD_106KBPS_JEWEL); | 1058 | pn533_poll_add_mod(dev, PN533_POLL_MOD_106KBPS_JEWEL); |
995 | 1059 | ||
996 | if (protocols & NFC_PROTO_ISO14443_MASK) | 1060 | if (im_protocols & NFC_PROTO_ISO14443_MASK) |
997 | pn533_poll_add_mod(dev, PN533_POLL_MOD_847KBPS_B); | 1061 | pn533_poll_add_mod(dev, PN533_POLL_MOD_847KBPS_B); |
1062 | |||
1063 | if (tm_protocols) | ||
1064 | pn533_poll_add_mod(dev, PN533_LISTEN_MOD); | ||
1065 | } | ||
1066 | |||
1067 | static int pn533_start_poll_complete(struct pn533 *dev, void *arg, | ||
1068 | u8 *params, int params_len) | ||
1069 | { | ||
1070 | struct pn533_poll_response *resp; | ||
1071 | int rc; | ||
1072 | |||
1073 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | ||
1074 | |||
1075 | resp = (struct pn533_poll_response *) params; | ||
1076 | if (resp->nbtg) { | ||
1077 | rc = pn533_target_found(dev, resp, params_len); | ||
1078 | |||
1079 | /* We must stop the poll after a valid target found */ | ||
1080 | if (rc == 0) { | ||
1081 | pn533_poll_reset_mod_list(dev); | ||
1082 | return 0; | ||
1083 | } | ||
1084 | } | ||
1085 | |||
1086 | return -EAGAIN; | ||
998 | } | 1087 | } |
999 | 1088 | ||
1000 | static void pn533_start_poll_frame(struct pn533_frame *frame, | 1089 | static int pn533_init_target_frame(struct pn533_frame *frame, |
1001 | struct pn533_poll_modulations *mod) | 1090 | u8 *gb, size_t gb_len) |
1002 | { | 1091 | { |
1092 | struct pn533_cmd_init_target *cmd; | ||
1093 | size_t cmd_len; | ||
1094 | u8 felica_params[18] = {0x1, 0xfe, /* DEP */ | ||
1095 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, /* random */ | ||
1096 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, | ||
1097 | 0xff, 0xff}; /* System code */ | ||
1098 | u8 mifare_params[6] = {0x1, 0x1, /* SENS_RES */ | ||
1099 | 0x0, 0x0, 0x0, | ||
1100 | 0x40}; /* SEL_RES for DEP */ | ||
1101 | |||
1102 | cmd_len = sizeof(struct pn533_cmd_init_target) + gb_len + 1; | ||
1103 | cmd = kzalloc(cmd_len, GFP_KERNEL); | ||
1104 | if (cmd == NULL) | ||
1105 | return -ENOMEM; | ||
1106 | |||
1107 | pn533_tx_frame_init(frame, PN533_CMD_TG_INIT_AS_TARGET); | ||
1108 | |||
1109 | /* DEP support only */ | ||
1110 | cmd->mode |= PN533_INIT_TARGET_DEP; | ||
1111 | |||
1112 | /* Felica params */ | ||
1113 | memcpy(cmd->felica, felica_params, 18); | ||
1114 | get_random_bytes(cmd->felica + 2, 6); | ||
1115 | |||
1116 | /* NFCID3 */ | ||
1117 | memset(cmd->nfcid3, 0, 10); | ||
1118 | memcpy(cmd->nfcid3, cmd->felica, 8); | ||
1003 | 1119 | ||
1004 | pn533_tx_frame_init(frame, PN533_CMD_IN_LIST_PASSIVE_TARGET); | 1120 | /* MIFARE params */ |
1121 | memcpy(cmd->mifare, mifare_params, 6); | ||
1005 | 1122 | ||
1006 | memcpy(PN533_FRAME_CMD_PARAMS_PTR(frame), &mod->data, mod->len); | 1123 | /* General bytes */ |
1007 | frame->datalen += mod->len; | 1124 | cmd->gb_len = gb_len; |
1125 | memcpy(cmd->gb, gb, gb_len); | ||
1126 | |||
1127 | /* Len Tk */ | ||
1128 | cmd->gb[gb_len] = 0; | ||
1129 | |||
1130 | memcpy(PN533_FRAME_CMD_PARAMS_PTR(frame), cmd, cmd_len); | ||
1131 | |||
1132 | frame->datalen += cmd_len; | ||
1008 | 1133 | ||
1009 | pn533_tx_frame_finish(frame); | 1134 | pn533_tx_frame_finish(frame); |
1135 | |||
1136 | kfree(cmd); | ||
1137 | |||
1138 | return 0; | ||
1010 | } | 1139 | } |
1011 | 1140 | ||
1012 | static int pn533_start_poll_complete(struct pn533 *dev, void *arg, | 1141 | #define PN533_CMD_DATAEXCH_HEAD_LEN (sizeof(struct pn533_frame) + 3) |
1013 | u8 *params, int params_len) | 1142 | #define PN533_CMD_DATAEXCH_DATA_MAXLEN 262 |
1143 | static int pn533_tm_get_data_complete(struct pn533 *dev, void *arg, | ||
1144 | u8 *params, int params_len) | ||
1014 | { | 1145 | { |
1015 | struct pn533_poll_response *resp; | 1146 | struct sk_buff *skb_resp = arg; |
1016 | struct pn533_poll_modulations *next_mod; | 1147 | struct pn533_frame *in_frame = (struct pn533_frame *) skb_resp->data; |
1017 | int rc; | ||
1018 | 1148 | ||
1019 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 1149 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); |
1020 | 1150 | ||
1021 | if (params_len == -ENOENT) { | 1151 | if (params_len < 0) { |
1022 | nfc_dev_dbg(&dev->interface->dev, "Polling operation has been" | 1152 | nfc_dev_err(&dev->interface->dev, |
1023 | " stopped"); | 1153 | "Error %d when starting as a target", |
1024 | goto stop_poll; | 1154 | params_len); |
1155 | |||
1156 | return params_len; | ||
1025 | } | 1157 | } |
1026 | 1158 | ||
1159 | if (params_len > 0 && params[0] != 0) { | ||
1160 | nfc_tm_deactivated(dev->nfc_dev); | ||
1161 | |||
1162 | dev->tgt_mode = 0; | ||
1163 | |||
1164 | kfree_skb(skb_resp); | ||
1165 | return 0; | ||
1166 | } | ||
1167 | |||
1168 | skb_put(skb_resp, PN533_FRAME_SIZE(in_frame)); | ||
1169 | skb_pull(skb_resp, PN533_CMD_DATAEXCH_HEAD_LEN); | ||
1170 | skb_trim(skb_resp, skb_resp->len - PN533_FRAME_TAIL_SIZE); | ||
1171 | |||
1172 | return nfc_tm_data_received(dev->nfc_dev, skb_resp); | ||
1173 | } | ||
1174 | |||
1175 | static void pn533_wq_tg_get_data(struct work_struct *work) | ||
1176 | { | ||
1177 | struct pn533 *dev = container_of(work, struct pn533, tg_work); | ||
1178 | struct pn533_frame *in_frame; | ||
1179 | struct sk_buff *skb_resp; | ||
1180 | size_t skb_resp_len; | ||
1181 | |||
1182 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | ||
1183 | |||
1184 | skb_resp_len = PN533_CMD_DATAEXCH_HEAD_LEN + | ||
1185 | PN533_CMD_DATAEXCH_DATA_MAXLEN + | ||
1186 | PN533_FRAME_TAIL_SIZE; | ||
1187 | |||
1188 | skb_resp = nfc_alloc_recv_skb(skb_resp_len, GFP_KERNEL); | ||
1189 | if (!skb_resp) | ||
1190 | return; | ||
1191 | |||
1192 | in_frame = (struct pn533_frame *)skb_resp->data; | ||
1193 | |||
1194 | pn533_tx_frame_init(dev->out_frame, PN533_CMD_TG_GET_DATA); | ||
1195 | pn533_tx_frame_finish(dev->out_frame); | ||
1196 | |||
1197 | pn533_send_cmd_frame_async(dev, dev->out_frame, in_frame, | ||
1198 | skb_resp_len, | ||
1199 | pn533_tm_get_data_complete, | ||
1200 | skb_resp, GFP_KERNEL); | ||
1201 | |||
1202 | return; | ||
1203 | } | ||
1204 | |||
1205 | #define ATR_REQ_GB_OFFSET 17 | ||
1206 | static int pn533_init_target_complete(struct pn533 *dev, void *arg, | ||
1207 | u8 *params, int params_len) | ||
1208 | { | ||
1209 | struct pn533_cmd_init_target_response *resp; | ||
1210 | u8 frame, comm_mode = NFC_COMM_PASSIVE, *gb; | ||
1211 | size_t gb_len; | ||
1212 | int rc; | ||
1213 | |||
1214 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | ||
1215 | |||
1027 | if (params_len < 0) { | 1216 | if (params_len < 0) { |
1028 | nfc_dev_err(&dev->interface->dev, "Error %d when running poll", | 1217 | nfc_dev_err(&dev->interface->dev, |
1029 | params_len); | 1218 | "Error %d when starting as a target", |
1030 | goto stop_poll; | 1219 | params_len); |
1220 | |||
1221 | return params_len; | ||
1031 | } | 1222 | } |
1032 | 1223 | ||
1033 | resp = (struct pn533_poll_response *) params; | 1224 | if (params_len < ATR_REQ_GB_OFFSET + 1) |
1034 | if (resp->nbtg) { | 1225 | return -EINVAL; |
1035 | rc = pn533_target_found(dev, resp, params_len); | ||
1036 | 1226 | ||
1037 | /* We must stop the poll after a valid target found */ | 1227 | resp = (struct pn533_cmd_init_target_response *) params; |
1038 | if (rc == 0) | 1228 | |
1039 | goto stop_poll; | 1229 | nfc_dev_dbg(&dev->interface->dev, "Target mode 0x%x param len %d\n", |
1230 | resp->mode, params_len); | ||
1231 | |||
1232 | frame = resp->mode & PN533_INIT_TARGET_RESP_FRAME_MASK; | ||
1233 | if (frame == PN533_INIT_TARGET_RESP_ACTIVE) | ||
1234 | comm_mode = NFC_COMM_ACTIVE; | ||
1040 | 1235 | ||
1041 | if (rc != -EAGAIN) | 1236 | /* Again, only DEP */ |
1042 | nfc_dev_err(&dev->interface->dev, "The target found is" | 1237 | if ((resp->mode & PN533_INIT_TARGET_RESP_DEP) == 0) |
1043 | " not valid - continuing to poll"); | 1238 | return -EOPNOTSUPP; |
1239 | |||
1240 | gb = resp->cmd + ATR_REQ_GB_OFFSET; | ||
1241 | gb_len = params_len - (ATR_REQ_GB_OFFSET + 1); | ||
1242 | |||
1243 | rc = nfc_tm_activated(dev->nfc_dev, NFC_PROTO_NFC_DEP_MASK, | ||
1244 | comm_mode, gb, gb_len); | ||
1245 | if (rc < 0) { | ||
1246 | nfc_dev_err(&dev->interface->dev, | ||
1247 | "Error when signaling target activation"); | ||
1248 | return rc; | ||
1044 | } | 1249 | } |
1045 | 1250 | ||
1046 | dev->poll_mod_curr = (dev->poll_mod_curr + 1) % dev->poll_mod_count; | 1251 | dev->tgt_mode = 1; |
1047 | 1252 | ||
1048 | next_mod = dev->poll_mod_active[dev->poll_mod_curr]; | 1253 | queue_work(dev->wq, &dev->tg_work); |
1049 | 1254 | ||
1050 | nfc_dev_dbg(&dev->interface->dev, "Polling next modulation (0x%x)", | 1255 | return 0; |
1051 | dev->poll_mod_curr); | 1256 | } |
1257 | |||
1258 | static void pn533_listen_mode_timer(unsigned long data) | ||
1259 | { | ||
1260 | struct pn533 *dev = (struct pn533 *) data; | ||
1261 | |||
1262 | nfc_dev_dbg(&dev->interface->dev, "Listen mode timeout"); | ||
1263 | |||
1264 | /* An ack will cancel the last issued command (poll) */ | ||
1265 | pn533_send_ack(dev, GFP_ATOMIC); | ||
1266 | |||
1267 | dev->cancel_listen = 1; | ||
1268 | |||
1269 | mutex_unlock(&dev->cmd_lock); | ||
1270 | |||
1271 | pn533_poll_next_mod(dev); | ||
1272 | |||
1273 | queue_work(dev->wq, &dev->poll_work); | ||
1274 | } | ||
1052 | 1275 | ||
1053 | pn533_start_poll_frame(dev->out_frame, next_mod); | 1276 | static int pn533_poll_complete(struct pn533 *dev, void *arg, |
1277 | u8 *params, int params_len) | ||
1278 | { | ||
1279 | struct pn533_poll_modulations *cur_mod; | ||
1280 | int rc; | ||
1054 | 1281 | ||
1055 | /* Don't need to down the semaphore again */ | 1282 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); |
1056 | rc = __pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame, | 1283 | |
1057 | dev->in_maxlen, pn533_start_poll_complete, | 1284 | if (params_len == -ENOENT) { |
1058 | NULL, GFP_ATOMIC); | 1285 | if (dev->poll_mod_count != 0) |
1286 | return 0; | ||
1287 | |||
1288 | nfc_dev_err(&dev->interface->dev, | ||
1289 | "Polling operation has been stopped"); | ||
1059 | 1290 | ||
1060 | if (rc == -EPERM) { | ||
1061 | nfc_dev_dbg(&dev->interface->dev, "Cannot poll next modulation" | ||
1062 | " because poll has been stopped"); | ||
1063 | goto stop_poll; | 1291 | goto stop_poll; |
1064 | } | 1292 | } |
1065 | 1293 | ||
1066 | if (rc) { | 1294 | if (params_len < 0) { |
1067 | nfc_dev_err(&dev->interface->dev, "Error %d when trying to poll" | 1295 | nfc_dev_err(&dev->interface->dev, |
1068 | " next modulation", rc); | 1296 | "Error %d when running poll", params_len); |
1297 | |||
1069 | goto stop_poll; | 1298 | goto stop_poll; |
1070 | } | 1299 | } |
1071 | 1300 | ||
1072 | /* Inform caller function to do not up the semaphore */ | 1301 | cur_mod = dev->poll_mod_active[dev->poll_mod_curr]; |
1073 | return -EINPROGRESS; | 1302 | |
1303 | if (cur_mod->len == 0) { | ||
1304 | del_timer(&dev->listen_timer); | ||
1305 | |||
1306 | return pn533_init_target_complete(dev, arg, params, params_len); | ||
1307 | } else { | ||
1308 | rc = pn533_start_poll_complete(dev, arg, params, params_len); | ||
1309 | if (!rc) | ||
1310 | return rc; | ||
1311 | } | ||
1312 | |||
1313 | pn533_poll_next_mod(dev); | ||
1314 | |||
1315 | queue_work(dev->wq, &dev->poll_work); | ||
1316 | |||
1317 | return 0; | ||
1074 | 1318 | ||
1075 | stop_poll: | 1319 | stop_poll: |
1076 | pn533_poll_reset_mod_list(dev); | 1320 | pn533_poll_reset_mod_list(dev); |
@@ -1078,61 +1322,104 @@ stop_poll: | |||
1078 | return 0; | 1322 | return 0; |
1079 | } | 1323 | } |
1080 | 1324 | ||
1081 | static int pn533_start_poll(struct nfc_dev *nfc_dev, u32 protocols) | 1325 | static void pn533_build_poll_frame(struct pn533 *dev, |
1326 | struct pn533_frame *frame, | ||
1327 | struct pn533_poll_modulations *mod) | ||
1082 | { | 1328 | { |
1083 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); | 1329 | nfc_dev_dbg(&dev->interface->dev, "mod len %d\n", mod->len); |
1084 | struct pn533_poll_modulations *start_mod; | ||
1085 | int rc; | ||
1086 | 1330 | ||
1087 | nfc_dev_dbg(&dev->interface->dev, "%s - protocols=0x%x", __func__, | 1331 | if (mod->len == 0) { |
1088 | protocols); | 1332 | /* Listen mode */ |
1333 | pn533_init_target_frame(frame, dev->gb, dev->gb_len); | ||
1334 | } else { | ||
1335 | /* Polling mode */ | ||
1336 | pn533_tx_frame_init(frame, PN533_CMD_IN_LIST_PASSIVE_TARGET); | ||
1089 | 1337 | ||
1090 | if (dev->poll_mod_count) { | 1338 | memcpy(PN533_FRAME_CMD_PARAMS_PTR(frame), &mod->data, mod->len); |
1091 | nfc_dev_err(&dev->interface->dev, "Polling operation already" | 1339 | frame->datalen += mod->len; |
1092 | " active"); | ||
1093 | return -EBUSY; | ||
1094 | } | ||
1095 | 1340 | ||
1096 | if (dev->tgt_active_prot) { | 1341 | pn533_tx_frame_finish(frame); |
1097 | nfc_dev_err(&dev->interface->dev, "Cannot poll with a target" | ||
1098 | " already activated"); | ||
1099 | return -EBUSY; | ||
1100 | } | 1342 | } |
1343 | } | ||
1101 | 1344 | ||
1102 | pn533_poll_create_mod_list(dev, protocols); | 1345 | static int pn533_send_poll_frame(struct pn533 *dev) |
1346 | { | ||
1347 | struct pn533_poll_modulations *cur_mod; | ||
1348 | int rc; | ||
1103 | 1349 | ||
1104 | if (!dev->poll_mod_count) { | 1350 | cur_mod = dev->poll_mod_active[dev->poll_mod_curr]; |
1105 | nfc_dev_err(&dev->interface->dev, "No valid protocols" | 1351 | |
1106 | " specified"); | 1352 | pn533_build_poll_frame(dev, dev->out_frame, cur_mod); |
1107 | rc = -EINVAL; | 1353 | |
1108 | goto error; | 1354 | rc = pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame, |
1355 | dev->in_maxlen, pn533_poll_complete, | ||
1356 | NULL, GFP_KERNEL); | ||
1357 | if (rc) | ||
1358 | nfc_dev_err(&dev->interface->dev, "Polling loop error %d", rc); | ||
1359 | |||
1360 | return rc; | ||
1361 | } | ||
1362 | |||
1363 | static void pn533_wq_poll(struct work_struct *work) | ||
1364 | { | ||
1365 | struct pn533 *dev = container_of(work, struct pn533, poll_work); | ||
1366 | struct pn533_poll_modulations *cur_mod; | ||
1367 | int rc; | ||
1368 | |||
1369 | cur_mod = dev->poll_mod_active[dev->poll_mod_curr]; | ||
1370 | |||
1371 | nfc_dev_dbg(&dev->interface->dev, | ||
1372 | "%s cancel_listen %d modulation len %d", | ||
1373 | __func__, dev->cancel_listen, cur_mod->len); | ||
1374 | |||
1375 | if (dev->cancel_listen == 1) { | ||
1376 | dev->cancel_listen = 0; | ||
1377 | usb_kill_urb(dev->in_urb); | ||
1109 | } | 1378 | } |
1110 | 1379 | ||
1111 | nfc_dev_dbg(&dev->interface->dev, "It will poll %d modulations types", | 1380 | rc = pn533_send_poll_frame(dev); |
1112 | dev->poll_mod_count); | 1381 | if (rc) |
1382 | return; | ||
1113 | 1383 | ||
1114 | dev->poll_mod_curr = 0; | 1384 | if (cur_mod->len == 0 && dev->poll_mod_count > 1) |
1115 | start_mod = dev->poll_mod_active[dev->poll_mod_curr]; | 1385 | mod_timer(&dev->listen_timer, jiffies + PN533_LISTEN_TIME * HZ); |
1116 | 1386 | ||
1117 | pn533_start_poll_frame(dev->out_frame, start_mod); | 1387 | return; |
1388 | } | ||
1118 | 1389 | ||
1119 | rc = pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame, | 1390 | static int pn533_start_poll(struct nfc_dev *nfc_dev, |
1120 | dev->in_maxlen, pn533_start_poll_complete, | 1391 | u32 im_protocols, u32 tm_protocols) |
1121 | NULL, GFP_KERNEL); | 1392 | { |
1393 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); | ||
1122 | 1394 | ||
1123 | if (rc) { | 1395 | nfc_dev_dbg(&dev->interface->dev, |
1124 | nfc_dev_err(&dev->interface->dev, "Error %d when trying to" | 1396 | "%s: im protocols 0x%x tm protocols 0x%x", |
1125 | " start poll", rc); | 1397 | __func__, im_protocols, tm_protocols); |
1126 | goto error; | 1398 | |
1399 | if (dev->tgt_active_prot) { | ||
1400 | nfc_dev_err(&dev->interface->dev, | ||
1401 | "Cannot poll with a target already activated"); | ||
1402 | return -EBUSY; | ||
1127 | } | 1403 | } |
1128 | 1404 | ||
1129 | dev->poll_protocols = protocols; | 1405 | if (dev->tgt_mode) { |
1406 | nfc_dev_err(&dev->interface->dev, | ||
1407 | "Cannot poll while already being activated"); | ||
1408 | return -EBUSY; | ||
1409 | } | ||
1130 | 1410 | ||
1131 | return 0; | 1411 | if (tm_protocols) { |
1412 | dev->gb = nfc_get_local_general_bytes(nfc_dev, &dev->gb_len); | ||
1413 | if (dev->gb == NULL) | ||
1414 | tm_protocols = 0; | ||
1415 | } | ||
1132 | 1416 | ||
1133 | error: | 1417 | dev->poll_mod_curr = 0; |
1134 | pn533_poll_reset_mod_list(dev); | 1418 | pn533_poll_create_mod_list(dev, im_protocols, tm_protocols); |
1135 | return rc; | 1419 | dev->poll_protocols = im_protocols; |
1420 | dev->listen_protocols = tm_protocols; | ||
1421 | |||
1422 | return pn533_send_poll_frame(dev); | ||
1136 | } | 1423 | } |
1137 | 1424 | ||
1138 | static void pn533_stop_poll(struct nfc_dev *nfc_dev) | 1425 | static void pn533_stop_poll(struct nfc_dev *nfc_dev) |
@@ -1141,6 +1428,8 @@ static void pn533_stop_poll(struct nfc_dev *nfc_dev) | |||
1141 | 1428 | ||
1142 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 1429 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); |
1143 | 1430 | ||
1431 | del_timer(&dev->listen_timer); | ||
1432 | |||
1144 | if (!dev->poll_mod_count) { | 1433 | if (!dev->poll_mod_count) { |
1145 | nfc_dev_dbg(&dev->interface->dev, "Polling operation was not" | 1434 | nfc_dev_dbg(&dev->interface->dev, "Polling operation was not" |
1146 | " running"); | 1435 | " running"); |
@@ -1152,6 +1441,8 @@ static void pn533_stop_poll(struct nfc_dev *nfc_dev) | |||
1152 | 1441 | ||
1153 | /* prevent pn533_start_poll_complete to issue a new poll meanwhile */ | 1442 | /* prevent pn533_start_poll_complete to issue a new poll meanwhile */ |
1154 | usb_kill_urb(dev->in_urb); | 1443 | usb_kill_urb(dev->in_urb); |
1444 | |||
1445 | pn533_poll_reset_mod_list(dev); | ||
1155 | } | 1446 | } |
1156 | 1447 | ||
1157 | static int pn533_activate_target_nfcdep(struct pn533 *dev) | 1448 | static int pn533_activate_target_nfcdep(struct pn533 *dev) |
@@ -1349,13 +1640,29 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, | |||
1349 | return 0; | 1640 | return 0; |
1350 | } | 1641 | } |
1351 | 1642 | ||
1643 | static int pn533_mod_to_baud(struct pn533 *dev) | ||
1644 | { | ||
1645 | switch (dev->poll_mod_curr) { | ||
1646 | case PN533_POLL_MOD_106KBPS_A: | ||
1647 | return 0; | ||
1648 | case PN533_POLL_MOD_212KBPS_FELICA: | ||
1649 | return 1; | ||
1650 | case PN533_POLL_MOD_424KBPS_FELICA: | ||
1651 | return 2; | ||
1652 | default: | ||
1653 | return -EINVAL; | ||
1654 | } | ||
1655 | } | ||
1656 | |||
1657 | #define PASSIVE_DATA_LEN 5 | ||
1352 | static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, | 1658 | static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, |
1353 | u8 comm_mode, u8* gb, size_t gb_len) | 1659 | u8 comm_mode, u8* gb, size_t gb_len) |
1354 | { | 1660 | { |
1355 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); | 1661 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); |
1356 | struct pn533_cmd_jump_dep *cmd; | 1662 | struct pn533_cmd_jump_dep *cmd; |
1357 | u8 cmd_len; | 1663 | u8 cmd_len, *data_ptr; |
1358 | int rc; | 1664 | u8 passive_data[PASSIVE_DATA_LEN] = {0x00, 0xff, 0xff, 0x00, 0x3}; |
1665 | int rc, baud; | ||
1359 | 1666 | ||
1360 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 1667 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); |
1361 | 1668 | ||
@@ -1371,7 +1678,17 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, | |||
1371 | return -EBUSY; | 1678 | return -EBUSY; |
1372 | } | 1679 | } |
1373 | 1680 | ||
1681 | baud = pn533_mod_to_baud(dev); | ||
1682 | if (baud < 0) { | ||
1683 | nfc_dev_err(&dev->interface->dev, | ||
1684 | "Invalid curr modulation %d", dev->poll_mod_curr); | ||
1685 | return baud; | ||
1686 | } | ||
1687 | |||
1374 | cmd_len = sizeof(struct pn533_cmd_jump_dep) + gb_len; | 1688 | cmd_len = sizeof(struct pn533_cmd_jump_dep) + gb_len; |
1689 | if (comm_mode == NFC_COMM_PASSIVE) | ||
1690 | cmd_len += PASSIVE_DATA_LEN; | ||
1691 | |||
1375 | cmd = kzalloc(cmd_len, GFP_KERNEL); | 1692 | cmd = kzalloc(cmd_len, GFP_KERNEL); |
1376 | if (cmd == NULL) | 1693 | if (cmd == NULL) |
1377 | return -ENOMEM; | 1694 | return -ENOMEM; |
@@ -1379,10 +1696,18 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, | |||
1379 | pn533_tx_frame_init(dev->out_frame, PN533_CMD_IN_JUMP_FOR_DEP); | 1696 | pn533_tx_frame_init(dev->out_frame, PN533_CMD_IN_JUMP_FOR_DEP); |
1380 | 1697 | ||
1381 | cmd->active = !comm_mode; | 1698 | cmd->active = !comm_mode; |
1382 | cmd->baud = 0; | 1699 | cmd->next = 0; |
1700 | cmd->baud = baud; | ||
1701 | data_ptr = cmd->data; | ||
1702 | if (comm_mode == NFC_COMM_PASSIVE && cmd->baud > 0) { | ||
1703 | memcpy(data_ptr, passive_data, PASSIVE_DATA_LEN); | ||
1704 | cmd->next |= 1; | ||
1705 | data_ptr += PASSIVE_DATA_LEN; | ||
1706 | } | ||
1707 | |||
1383 | if (gb != NULL && gb_len > 0) { | 1708 | if (gb != NULL && gb_len > 0) { |
1384 | cmd->next = 4; /* We have some Gi */ | 1709 | cmd->next |= 4; /* We have some Gi */ |
1385 | memcpy(cmd->gt, gb, gb_len); | 1710 | memcpy(data_ptr, gb, gb_len); |
1386 | } else { | 1711 | } else { |
1387 | cmd->next = 0; | 1712 | cmd->next = 0; |
1388 | } | 1713 | } |
@@ -1407,15 +1732,25 @@ out: | |||
1407 | 1732 | ||
1408 | static int pn533_dep_link_down(struct nfc_dev *nfc_dev) | 1733 | static int pn533_dep_link_down(struct nfc_dev *nfc_dev) |
1409 | { | 1734 | { |
1410 | pn533_deactivate_target(nfc_dev, 0); | 1735 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); |
1736 | |||
1737 | pn533_poll_reset_mod_list(dev); | ||
1738 | |||
1739 | if (dev->tgt_mode || dev->tgt_active_prot) { | ||
1740 | pn533_send_ack(dev, GFP_KERNEL); | ||
1741 | usb_kill_urb(dev->in_urb); | ||
1742 | } | ||
1743 | |||
1744 | dev->tgt_active_prot = 0; | ||
1745 | dev->tgt_mode = 0; | ||
1746 | |||
1747 | skb_queue_purge(&dev->resp_q); | ||
1411 | 1748 | ||
1412 | return 0; | 1749 | return 0; |
1413 | } | 1750 | } |
1414 | 1751 | ||
1415 | #define PN533_CMD_DATAEXCH_HEAD_LEN (sizeof(struct pn533_frame) + 3) | 1752 | static int pn533_build_tx_frame(struct pn533 *dev, struct sk_buff *skb, |
1416 | #define PN533_CMD_DATAEXCH_DATA_MAXLEN 262 | 1753 | bool target) |
1417 | |||
1418 | static int pn533_data_exchange_tx_frame(struct pn533 *dev, struct sk_buff *skb) | ||
1419 | { | 1754 | { |
1420 | int payload_len = skb->len; | 1755 | int payload_len = skb->len; |
1421 | struct pn533_frame *out_frame; | 1756 | struct pn533_frame *out_frame; |
@@ -1432,14 +1767,20 @@ static int pn533_data_exchange_tx_frame(struct pn533 *dev, struct sk_buff *skb) | |||
1432 | return -ENOSYS; | 1767 | return -ENOSYS; |
1433 | } | 1768 | } |
1434 | 1769 | ||
1435 | skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN); | 1770 | if (target == true) { |
1436 | out_frame = (struct pn533_frame *) skb->data; | 1771 | skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN); |
1772 | out_frame = (struct pn533_frame *) skb->data; | ||
1437 | 1773 | ||
1438 | pn533_tx_frame_init(out_frame, PN533_CMD_IN_DATA_EXCHANGE); | 1774 | pn533_tx_frame_init(out_frame, PN533_CMD_IN_DATA_EXCHANGE); |
1775 | tg = 1; | ||
1776 | memcpy(PN533_FRAME_CMD_PARAMS_PTR(out_frame), &tg, sizeof(u8)); | ||
1777 | out_frame->datalen += sizeof(u8); | ||
1778 | } else { | ||
1779 | skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN - 1); | ||
1780 | out_frame = (struct pn533_frame *) skb->data; | ||
1781 | pn533_tx_frame_init(out_frame, PN533_CMD_TG_SET_DATA); | ||
1782 | } | ||
1439 | 1783 | ||
1440 | tg = 1; | ||
1441 | memcpy(PN533_FRAME_CMD_PARAMS_PTR(out_frame), &tg, sizeof(u8)); | ||
1442 | out_frame->datalen += sizeof(u8); | ||
1443 | 1784 | ||
1444 | /* The data is already in the out_frame, just update the datalen */ | 1785 | /* The data is already in the out_frame, just update the datalen */ |
1445 | out_frame->datalen += payload_len; | 1786 | out_frame->datalen += payload_len; |
@@ -1550,9 +1891,9 @@ error: | |||
1550 | return 0; | 1891 | return 0; |
1551 | } | 1892 | } |
1552 | 1893 | ||
1553 | static int pn533_data_exchange(struct nfc_dev *nfc_dev, | 1894 | static int pn533_transceive(struct nfc_dev *nfc_dev, |
1554 | struct nfc_target *target, struct sk_buff *skb, | 1895 | struct nfc_target *target, struct sk_buff *skb, |
1555 | data_exchange_cb_t cb, void *cb_context) | 1896 | data_exchange_cb_t cb, void *cb_context) |
1556 | { | 1897 | { |
1557 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); | 1898 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); |
1558 | struct pn533_frame *out_frame, *in_frame; | 1899 | struct pn533_frame *out_frame, *in_frame; |
@@ -1570,7 +1911,7 @@ static int pn533_data_exchange(struct nfc_dev *nfc_dev, | |||
1570 | goto error; | 1911 | goto error; |
1571 | } | 1912 | } |
1572 | 1913 | ||
1573 | rc = pn533_data_exchange_tx_frame(dev, skb); | 1914 | rc = pn533_build_tx_frame(dev, skb, true); |
1574 | if (rc) | 1915 | if (rc) |
1575 | goto error; | 1916 | goto error; |
1576 | 1917 | ||
@@ -1618,6 +1959,63 @@ error: | |||
1618 | return rc; | 1959 | return rc; |
1619 | } | 1960 | } |
1620 | 1961 | ||
1962 | static int pn533_tm_send_complete(struct pn533 *dev, void *arg, | ||
1963 | u8 *params, int params_len) | ||
1964 | { | ||
1965 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | ||
1966 | |||
1967 | if (params_len < 0) { | ||
1968 | nfc_dev_err(&dev->interface->dev, | ||
1969 | "Error %d when sending data", | ||
1970 | params_len); | ||
1971 | |||
1972 | return params_len; | ||
1973 | } | ||
1974 | |||
1975 | if (params_len > 0 && params[0] != 0) { | ||
1976 | nfc_tm_deactivated(dev->nfc_dev); | ||
1977 | |||
1978 | dev->tgt_mode = 0; | ||
1979 | |||
1980 | return 0; | ||
1981 | } | ||
1982 | |||
1983 | queue_work(dev->wq, &dev->tg_work); | ||
1984 | |||
1985 | return 0; | ||
1986 | } | ||
1987 | |||
1988 | static int pn533_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb) | ||
1989 | { | ||
1990 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); | ||
1991 | struct pn533_frame *out_frame; | ||
1992 | int rc; | ||
1993 | |||
1994 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | ||
1995 | |||
1996 | rc = pn533_build_tx_frame(dev, skb, false); | ||
1997 | if (rc) | ||
1998 | goto error; | ||
1999 | |||
2000 | out_frame = (struct pn533_frame *) skb->data; | ||
2001 | |||
2002 | rc = pn533_send_cmd_frame_async(dev, out_frame, dev->in_frame, | ||
2003 | dev->in_maxlen, pn533_tm_send_complete, | ||
2004 | NULL, GFP_KERNEL); | ||
2005 | if (rc) { | ||
2006 | nfc_dev_err(&dev->interface->dev, | ||
2007 | "Error %d when trying to send data", rc); | ||
2008 | goto error; | ||
2009 | } | ||
2010 | |||
2011 | return 0; | ||
2012 | |||
2013 | error: | ||
2014 | kfree_skb(skb); | ||
2015 | |||
2016 | return rc; | ||
2017 | } | ||
2018 | |||
1621 | static void pn533_wq_mi_recv(struct work_struct *work) | 2019 | static void pn533_wq_mi_recv(struct work_struct *work) |
1622 | { | 2020 | { |
1623 | struct pn533 *dev = container_of(work, struct pn533, mi_work); | 2021 | struct pn533 *dev = container_of(work, struct pn533, mi_work); |
@@ -1638,7 +2036,7 @@ static void pn533_wq_mi_recv(struct work_struct *work) | |||
1638 | 2036 | ||
1639 | skb_reserve(skb_cmd, PN533_CMD_DATAEXCH_HEAD_LEN); | 2037 | skb_reserve(skb_cmd, PN533_CMD_DATAEXCH_HEAD_LEN); |
1640 | 2038 | ||
1641 | rc = pn533_data_exchange_tx_frame(dev, skb_cmd); | 2039 | rc = pn533_build_tx_frame(dev, skb_cmd, true); |
1642 | if (rc) | 2040 | if (rc) |
1643 | goto error_frame; | 2041 | goto error_frame; |
1644 | 2042 | ||
@@ -1677,7 +2075,7 @@ error_cmd: | |||
1677 | 2075 | ||
1678 | kfree(arg); | 2076 | kfree(arg); |
1679 | 2077 | ||
1680 | up(&dev->cmd_lock); | 2078 | mutex_unlock(&dev->cmd_lock); |
1681 | } | 2079 | } |
1682 | 2080 | ||
1683 | static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata, | 2081 | static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata, |
@@ -1712,7 +2110,8 @@ struct nfc_ops pn533_nfc_ops = { | |||
1712 | .stop_poll = pn533_stop_poll, | 2110 | .stop_poll = pn533_stop_poll, |
1713 | .activate_target = pn533_activate_target, | 2111 | .activate_target = pn533_activate_target, |
1714 | .deactivate_target = pn533_deactivate_target, | 2112 | .deactivate_target = pn533_deactivate_target, |
1715 | .data_exchange = pn533_data_exchange, | 2113 | .im_transceive = pn533_transceive, |
2114 | .tm_send = pn533_tm_send, | ||
1716 | }; | 2115 | }; |
1717 | 2116 | ||
1718 | static int pn533_probe(struct usb_interface *interface, | 2117 | static int pn533_probe(struct usb_interface *interface, |
@@ -1723,6 +2122,7 @@ static int pn533_probe(struct usb_interface *interface, | |||
1723 | struct usb_host_interface *iface_desc; | 2122 | struct usb_host_interface *iface_desc; |
1724 | struct usb_endpoint_descriptor *endpoint; | 2123 | struct usb_endpoint_descriptor *endpoint; |
1725 | struct pn533_config_max_retries max_retries; | 2124 | struct pn533_config_max_retries max_retries; |
2125 | struct pn533_config_timing timing; | ||
1726 | int in_endpoint = 0; | 2126 | int in_endpoint = 0; |
1727 | int out_endpoint = 0; | 2127 | int out_endpoint = 0; |
1728 | int rc = -ENOMEM; | 2128 | int rc = -ENOMEM; |
@@ -1735,7 +2135,7 @@ static int pn533_probe(struct usb_interface *interface, | |||
1735 | 2135 | ||
1736 | dev->udev = usb_get_dev(interface_to_usbdev(interface)); | 2136 | dev->udev = usb_get_dev(interface_to_usbdev(interface)); |
1737 | dev->interface = interface; | 2137 | dev->interface = interface; |
1738 | sema_init(&dev->cmd_lock, 1); | 2138 | mutex_init(&dev->cmd_lock); |
1739 | 2139 | ||
1740 | iface_desc = interface->cur_altsetting; | 2140 | iface_desc = interface->cur_altsetting; |
1741 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { | 2141 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { |
@@ -1779,12 +2179,18 @@ static int pn533_probe(struct usb_interface *interface, | |||
1779 | 2179 | ||
1780 | INIT_WORK(&dev->cmd_work, pn533_wq_cmd_complete); | 2180 | INIT_WORK(&dev->cmd_work, pn533_wq_cmd_complete); |
1781 | INIT_WORK(&dev->mi_work, pn533_wq_mi_recv); | 2181 | INIT_WORK(&dev->mi_work, pn533_wq_mi_recv); |
2182 | INIT_WORK(&dev->tg_work, pn533_wq_tg_get_data); | ||
2183 | INIT_WORK(&dev->poll_work, pn533_wq_poll); | ||
1782 | dev->wq = alloc_workqueue("pn533", | 2184 | dev->wq = alloc_workqueue("pn533", |
1783 | WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM, | 2185 | WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM, |
1784 | 1); | 2186 | 1); |
1785 | if (dev->wq == NULL) | 2187 | if (dev->wq == NULL) |
1786 | goto error; | 2188 | goto error; |
1787 | 2189 | ||
2190 | init_timer(&dev->listen_timer); | ||
2191 | dev->listen_timer.data = (unsigned long) dev; | ||
2192 | dev->listen_timer.function = pn533_listen_mode_timer; | ||
2193 | |||
1788 | skb_queue_head_init(&dev->resp_q); | 2194 | skb_queue_head_init(&dev->resp_q); |
1789 | 2195 | ||
1790 | usb_set_intfdata(interface, dev); | 2196 | usb_set_intfdata(interface, dev); |
@@ -1830,13 +2236,29 @@ static int pn533_probe(struct usb_interface *interface, | |||
1830 | if (rc) { | 2236 | if (rc) { |
1831 | nfc_dev_err(&dev->interface->dev, "Error on setting MAX_RETRIES" | 2237 | nfc_dev_err(&dev->interface->dev, "Error on setting MAX_RETRIES" |
1832 | " config"); | 2238 | " config"); |
1833 | goto free_nfc_dev; | 2239 | goto unregister_nfc_dev; |
2240 | } | ||
2241 | |||
2242 | timing.rfu = PN533_CONFIG_TIMING_102; | ||
2243 | timing.atr_res_timeout = PN533_CONFIG_TIMING_204; | ||
2244 | timing.dep_timeout = PN533_CONFIG_TIMING_409; | ||
2245 | |||
2246 | rc = pn533_set_configuration(dev, PN533_CFGITEM_TIMING, | ||
2247 | (u8 *) &timing, sizeof(timing)); | ||
2248 | if (rc) { | ||
2249 | nfc_dev_err(&dev->interface->dev, | ||
2250 | "Error on setting RF timings"); | ||
2251 | goto unregister_nfc_dev; | ||
1834 | } | 2252 | } |
1835 | 2253 | ||
1836 | return 0; | 2254 | return 0; |
1837 | 2255 | ||
2256 | unregister_nfc_dev: | ||
2257 | nfc_unregister_device(dev->nfc_dev); | ||
2258 | |||
1838 | free_nfc_dev: | 2259 | free_nfc_dev: |
1839 | nfc_free_device(dev->nfc_dev); | 2260 | nfc_free_device(dev->nfc_dev); |
2261 | |||
1840 | destroy_wq: | 2262 | destroy_wq: |
1841 | destroy_workqueue(dev->wq); | 2263 | destroy_workqueue(dev->wq); |
1842 | error: | 2264 | error: |
@@ -1865,6 +2287,8 @@ static void pn533_disconnect(struct usb_interface *interface) | |||
1865 | 2287 | ||
1866 | skb_queue_purge(&dev->resp_q); | 2288 | skb_queue_purge(&dev->resp_q); |
1867 | 2289 | ||
2290 | del_timer(&dev->listen_timer); | ||
2291 | |||
1868 | kfree(dev->in_frame); | 2292 | kfree(dev->in_frame); |
1869 | usb_free_urb(dev->in_urb); | 2293 | usb_free_urb(dev->in_urb); |
1870 | kfree(dev->out_frame); | 2294 | kfree(dev->out_frame); |
diff --git a/drivers/nfc/pn544_hci.c b/drivers/nfc/pn544_hci.c index 281f18c2fb8..457eac35dc7 100644 --- a/drivers/nfc/pn544_hci.c +++ b/drivers/nfc/pn544_hci.c | |||
@@ -576,7 +576,8 @@ static int pn544_hci_xmit(struct nfc_shdlc *shdlc, struct sk_buff *skb) | |||
576 | return pn544_hci_i2c_write(client, skb->data, skb->len); | 576 | return pn544_hci_i2c_write(client, skb->data, skb->len); |
577 | } | 577 | } |
578 | 578 | ||
579 | static int pn544_hci_start_poll(struct nfc_shdlc *shdlc, u32 protocols) | 579 | static int pn544_hci_start_poll(struct nfc_shdlc *shdlc, |
580 | u32 im_protocols, u32 tm_protocols) | ||
580 | { | 581 | { |
581 | struct nfc_hci_dev *hdev = nfc_shdlc_get_hci_dev(shdlc); | 582 | struct nfc_hci_dev *hdev = nfc_shdlc_get_hci_dev(shdlc); |
582 | u8 phases = 0; | 583 | u8 phases = 0; |
@@ -584,7 +585,8 @@ static int pn544_hci_start_poll(struct nfc_shdlc *shdlc, u32 protocols) | |||
584 | u8 duration[2]; | 585 | u8 duration[2]; |
585 | u8 activated; | 586 | u8 activated; |
586 | 587 | ||
587 | pr_info(DRIVER_DESC ": %s protocols = %d\n", __func__, protocols); | 588 | pr_info(DRIVER_DESC ": %s protocols 0x%x 0x%x\n", |
589 | __func__, im_protocols, tm_protocols); | ||
588 | 590 | ||
589 | r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, | 591 | r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, |
590 | NFC_HCI_EVT_END_OPERATION, NULL, 0); | 592 | NFC_HCI_EVT_END_OPERATION, NULL, 0); |
@@ -604,10 +606,10 @@ static int pn544_hci_start_poll(struct nfc_shdlc *shdlc, u32 protocols) | |||
604 | if (r < 0) | 606 | if (r < 0) |
605 | return r; | 607 | return r; |
606 | 608 | ||
607 | if (protocols & (NFC_PROTO_ISO14443_MASK | NFC_PROTO_MIFARE_MASK | | 609 | if (im_protocols & (NFC_PROTO_ISO14443_MASK | NFC_PROTO_MIFARE_MASK | |
608 | NFC_PROTO_JEWEL_MASK)) | 610 | NFC_PROTO_JEWEL_MASK)) |
609 | phases |= 1; /* Type A */ | 611 | phases |= 1; /* Type A */ |
610 | if (protocols & NFC_PROTO_FELICA_MASK) { | 612 | if (im_protocols & NFC_PROTO_FELICA_MASK) { |
611 | phases |= (1 << 2); /* Type F 212 */ | 613 | phases |= (1 << 2); /* Type F 212 */ |
612 | phases |= (1 << 3); /* Type F 424 */ | 614 | phases |= (1 << 3); /* Type F 424 */ |
613 | } | 615 | } |
diff --git a/drivers/ssb/b43_pci_bridge.c b/drivers/ssb/b43_pci_bridge.c index f551e537614..266aa1648a0 100644 --- a/drivers/ssb/b43_pci_bridge.c +++ b/drivers/ssb/b43_pci_bridge.c | |||
@@ -36,6 +36,7 @@ static const struct pci_device_id b43_pci_bridge_tbl[] = { | |||
36 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4328) }, | 36 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4328) }, |
37 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4329) }, | 37 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4329) }, |
38 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x432b) }, | 38 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x432b) }, |
39 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x432c) }, | ||
39 | { 0, }, | 40 | { 0, }, |
40 | }; | 41 | }; |
41 | MODULE_DEVICE_TABLE(pci, b43_pci_bridge_tbl); | 42 | MODULE_DEVICE_TABLE(pci, b43_pci_bridge_tbl); |
diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h index 8deaf6d050c..12334f9190c 100644 --- a/include/linux/bcma/bcma.h +++ b/include/linux/bcma/bcma.h | |||
@@ -70,6 +70,13 @@ struct bcma_host_ops { | |||
70 | 70 | ||
71 | /* Core-ID values. */ | 71 | /* Core-ID values. */ |
72 | #define BCMA_CORE_OOB_ROUTER 0x367 /* Out of band */ | 72 | #define BCMA_CORE_OOB_ROUTER 0x367 /* Out of band */ |
73 | #define BCMA_CORE_4706_CHIPCOMMON 0x500 | ||
74 | #define BCMA_CORE_4706_SOC_RAM 0x50E | ||
75 | #define BCMA_CORE_4706_MAC_GBIT 0x52D | ||
76 | #define BCMA_CORE_AMEMC 0x52E /* DDR1/2 memory controller core */ | ||
77 | #define BCMA_CORE_ALTA 0x534 /* I2S core */ | ||
78 | #define BCMA_CORE_4706_MAC_GBIT_COMMON 0x5DC | ||
79 | #define BCMA_CORE_DDR23_PHY 0x5DD | ||
73 | #define BCMA_CORE_INVALID 0x700 | 80 | #define BCMA_CORE_INVALID 0x700 |
74 | #define BCMA_CORE_CHIPCOMMON 0x800 | 81 | #define BCMA_CORE_CHIPCOMMON 0x800 |
75 | #define BCMA_CORE_ILINE20 0x801 | 82 | #define BCMA_CORE_ILINE20 0x801 |
diff --git a/include/linux/nfc.h b/include/linux/nfc.h index 0ae9b5857c8..f4e6dd915b1 100644 --- a/include/linux/nfc.h +++ b/include/linux/nfc.h | |||
@@ -56,6 +56,10 @@ | |||
56 | * %NFC_ATTR_PROTOCOLS) | 56 | * %NFC_ATTR_PROTOCOLS) |
57 | * @NFC_EVENT_DEVICE_REMOVED: event emitted when a device is removed | 57 | * @NFC_EVENT_DEVICE_REMOVED: event emitted when a device is removed |
58 | * (it sends %NFC_ATTR_DEVICE_INDEX) | 58 | * (it sends %NFC_ATTR_DEVICE_INDEX) |
59 | * @NFC_EVENT_TM_ACTIVATED: event emitted when the adapter is activated in | ||
60 | * target mode. | ||
61 | * @NFC_EVENT_DEVICE_DEACTIVATED: event emitted when the adapter is deactivated | ||
62 | * from target mode. | ||
59 | */ | 63 | */ |
60 | enum nfc_commands { | 64 | enum nfc_commands { |
61 | NFC_CMD_UNSPEC, | 65 | NFC_CMD_UNSPEC, |
@@ -71,6 +75,8 @@ enum nfc_commands { | |||
71 | NFC_EVENT_DEVICE_ADDED, | 75 | NFC_EVENT_DEVICE_ADDED, |
72 | NFC_EVENT_DEVICE_REMOVED, | 76 | NFC_EVENT_DEVICE_REMOVED, |
73 | NFC_EVENT_TARGET_LOST, | 77 | NFC_EVENT_TARGET_LOST, |
78 | NFC_EVENT_TM_ACTIVATED, | ||
79 | NFC_EVENT_TM_DEACTIVATED, | ||
74 | /* private: internal use only */ | 80 | /* private: internal use only */ |
75 | __NFC_CMD_AFTER_LAST | 81 | __NFC_CMD_AFTER_LAST |
76 | }; | 82 | }; |
@@ -94,6 +100,8 @@ enum nfc_commands { | |||
94 | * @NFC_ATTR_TARGET_SENSF_RES: NFC-F targets extra information, max 18 bytes | 100 | * @NFC_ATTR_TARGET_SENSF_RES: NFC-F targets extra information, max 18 bytes |
95 | * @NFC_ATTR_COMM_MODE: Passive or active mode | 101 | * @NFC_ATTR_COMM_MODE: Passive or active mode |
96 | * @NFC_ATTR_RF_MODE: Initiator or target | 102 | * @NFC_ATTR_RF_MODE: Initiator or target |
103 | * @NFC_ATTR_IM_PROTOCOLS: Initiator mode protocols to poll for | ||
104 | * @NFC_ATTR_TM_PROTOCOLS: Target mode protocols to listen for | ||
97 | */ | 105 | */ |
98 | enum nfc_attrs { | 106 | enum nfc_attrs { |
99 | NFC_ATTR_UNSPEC, | 107 | NFC_ATTR_UNSPEC, |
@@ -109,6 +117,8 @@ enum nfc_attrs { | |||
109 | NFC_ATTR_COMM_MODE, | 117 | NFC_ATTR_COMM_MODE, |
110 | NFC_ATTR_RF_MODE, | 118 | NFC_ATTR_RF_MODE, |
111 | NFC_ATTR_DEVICE_POWERED, | 119 | NFC_ATTR_DEVICE_POWERED, |
120 | NFC_ATTR_IM_PROTOCOLS, | ||
121 | NFC_ATTR_TM_PROTOCOLS, | ||
112 | /* private: internal use only */ | 122 | /* private: internal use only */ |
113 | __NFC_ATTR_AFTER_LAST | 123 | __NFC_ATTR_AFTER_LAST |
114 | }; | 124 | }; |
@@ -118,6 +128,7 @@ enum nfc_attrs { | |||
118 | #define NFC_NFCID1_MAXSIZE 10 | 128 | #define NFC_NFCID1_MAXSIZE 10 |
119 | #define NFC_SENSB_RES_MAXSIZE 12 | 129 | #define NFC_SENSB_RES_MAXSIZE 12 |
120 | #define NFC_SENSF_RES_MAXSIZE 18 | 130 | #define NFC_SENSF_RES_MAXSIZE 18 |
131 | #define NFC_GB_MAXSIZE 48 | ||
121 | 132 | ||
122 | /* NFC protocols */ | 133 | /* NFC protocols */ |
123 | #define NFC_PROTO_JEWEL 1 | 134 | #define NFC_PROTO_JEWEL 1 |
@@ -135,6 +146,7 @@ enum nfc_attrs { | |||
135 | /* NFC RF modes */ | 146 | /* NFC RF modes */ |
136 | #define NFC_RF_INITIATOR 0 | 147 | #define NFC_RF_INITIATOR 0 |
137 | #define NFC_RF_TARGET 1 | 148 | #define NFC_RF_TARGET 1 |
149 | #define NFC_RF_NONE 2 | ||
138 | 150 | ||
139 | /* NFC protocols masks used in bitsets */ | 151 | /* NFC protocols masks used in bitsets */ |
140 | #define NFC_PROTO_JEWEL_MASK (1 << NFC_PROTO_JEWEL) | 152 | #define NFC_PROTO_JEWEL_MASK (1 << NFC_PROTO_JEWEL) |
diff --git a/include/net/bluetooth/a2mp.h b/include/net/bluetooth/a2mp.h new file mode 100644 index 00000000000..6a76e0a0705 --- /dev/null +++ b/include/net/bluetooth/a2mp.h | |||
@@ -0,0 +1,126 @@ | |||
1 | /* | ||
2 | Copyright (c) 2010,2011 Code Aurora Forum. All rights reserved. | ||
3 | Copyright (c) 2011,2012 Intel Corp. | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License version 2 and | ||
7 | only version 2 as published by the Free Software Foundation. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | */ | ||
14 | |||
15 | #ifndef __A2MP_H | ||
16 | #define __A2MP_H | ||
17 | |||
18 | #include <net/bluetooth/l2cap.h> | ||
19 | |||
20 | #define A2MP_FEAT_EXT 0x8000 | ||
21 | |||
22 | struct amp_mgr { | ||
23 | struct l2cap_conn *l2cap_conn; | ||
24 | struct l2cap_chan *a2mp_chan; | ||
25 | struct kref kref; | ||
26 | __u8 ident; | ||
27 | __u8 handle; | ||
28 | unsigned long flags; | ||
29 | }; | ||
30 | |||
31 | struct a2mp_cmd { | ||
32 | __u8 code; | ||
33 | __u8 ident; | ||
34 | __le16 len; | ||
35 | __u8 data[0]; | ||
36 | } __packed; | ||
37 | |||
38 | /* A2MP command codes */ | ||
39 | #define A2MP_COMMAND_REJ 0x01 | ||
40 | struct a2mp_cmd_rej { | ||
41 | __le16 reason; | ||
42 | __u8 data[0]; | ||
43 | } __packed; | ||
44 | |||
45 | #define A2MP_DISCOVER_REQ 0x02 | ||
46 | struct a2mp_discov_req { | ||
47 | __le16 mtu; | ||
48 | __le16 ext_feat; | ||
49 | } __packed; | ||
50 | |||
51 | struct a2mp_cl { | ||
52 | __u8 id; | ||
53 | __u8 type; | ||
54 | __u8 status; | ||
55 | } __packed; | ||
56 | |||
57 | #define A2MP_DISCOVER_RSP 0x03 | ||
58 | struct a2mp_discov_rsp { | ||
59 | __le16 mtu; | ||
60 | __le16 ext_feat; | ||
61 | struct a2mp_cl cl[0]; | ||
62 | } __packed; | ||
63 | |||
64 | #define A2MP_CHANGE_NOTIFY 0x04 | ||
65 | #define A2MP_CHANGE_RSP 0x05 | ||
66 | |||
67 | #define A2MP_GETINFO_REQ 0x06 | ||
68 | struct a2mp_info_req { | ||
69 | __u8 id; | ||
70 | } __packed; | ||
71 | |||
72 | #define A2MP_GETINFO_RSP 0x07 | ||
73 | struct a2mp_info_rsp { | ||
74 | __u8 id; | ||
75 | __u8 status; | ||
76 | __le32 total_bw; | ||
77 | __le32 max_bw; | ||
78 | __le32 min_latency; | ||
79 | __le16 pal_cap; | ||
80 | __le16 assoc_size; | ||
81 | } __packed; | ||
82 | |||
83 | #define A2MP_GETAMPASSOC_REQ 0x08 | ||
84 | struct a2mp_amp_assoc_req { | ||
85 | __u8 id; | ||
86 | } __packed; | ||
87 | |||
88 | #define A2MP_GETAMPASSOC_RSP 0x09 | ||
89 | struct a2mp_amp_assoc_rsp { | ||
90 | __u8 id; | ||
91 | __u8 status; | ||
92 | __u8 amp_assoc[0]; | ||
93 | } __packed; | ||
94 | |||
95 | #define A2MP_CREATEPHYSLINK_REQ 0x0A | ||
96 | #define A2MP_DISCONNPHYSLINK_REQ 0x0C | ||
97 | struct a2mp_physlink_req { | ||
98 | __u8 local_id; | ||
99 | __u8 remote_id; | ||
100 | __u8 amp_assoc[0]; | ||
101 | } __packed; | ||
102 | |||
103 | #define A2MP_CREATEPHYSLINK_RSP 0x0B | ||
104 | #define A2MP_DISCONNPHYSLINK_RSP 0x0D | ||
105 | struct a2mp_physlink_rsp { | ||
106 | __u8 local_id; | ||
107 | __u8 remote_id; | ||
108 | __u8 status; | ||
109 | } __packed; | ||
110 | |||
111 | /* A2MP response status */ | ||
112 | #define A2MP_STATUS_SUCCESS 0x00 | ||
113 | #define A2MP_STATUS_INVALID_CTRL_ID 0x01 | ||
114 | #define A2MP_STATUS_UNABLE_START_LINK_CREATION 0x02 | ||
115 | #define A2MP_STATUS_NO_PHYSICAL_LINK_EXISTS 0x02 | ||
116 | #define A2MP_STATUS_COLLISION_OCCURED 0x03 | ||
117 | #define A2MP_STATUS_DISCONN_REQ_RECVD 0x04 | ||
118 | #define A2MP_STATUS_PHYS_LINK_EXISTS 0x05 | ||
119 | #define A2MP_STATUS_SECURITY_VIOLATION 0x06 | ||
120 | |||
121 | void amp_mgr_get(struct amp_mgr *mgr); | ||
122 | int amp_mgr_put(struct amp_mgr *mgr); | ||
123 | struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn, | ||
124 | struct sk_buff *skb); | ||
125 | |||
126 | #endif /* __A2MP_H */ | ||
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 961669b648f..565d4bee1e4 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | BlueZ - Bluetooth protocol stack for Linux | 2 | BlueZ - Bluetooth protocol stack for Linux |
3 | Copyright (C) 2000-2001 Qualcomm Incorporated | 3 | Copyright (C) 2000-2001 Qualcomm Incorporated |
4 | 4 | ||
@@ -12,22 +12,19 @@ | |||
12 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 12 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
13 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. | 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 | 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 | 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 | 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 | 17 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
18 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 18 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
19 | 19 | ||
20 | ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, | 20 | ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, |
21 | COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS | 21 | COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS |
22 | SOFTWARE IS DISCLAIMED. | 22 | SOFTWARE IS DISCLAIMED. |
23 | */ | 23 | */ |
24 | 24 | ||
25 | #ifndef __BLUETOOTH_H | 25 | #ifndef __BLUETOOTH_H |
26 | #define __BLUETOOTH_H | 26 | #define __BLUETOOTH_H |
27 | 27 | ||
28 | #include <asm/types.h> | ||
29 | #include <asm/byteorder.h> | ||
30 | #include <linux/list.h> | ||
31 | #include <linux/poll.h> | 28 | #include <linux/poll.h> |
32 | #include <net/sock.h> | 29 | #include <net/sock.h> |
33 | 30 | ||
@@ -168,8 +165,8 @@ typedef struct { | |||
168 | #define BDADDR_LE_PUBLIC 0x01 | 165 | #define BDADDR_LE_PUBLIC 0x01 |
169 | #define BDADDR_LE_RANDOM 0x02 | 166 | #define BDADDR_LE_RANDOM 0x02 |
170 | 167 | ||
171 | #define BDADDR_ANY (&(bdaddr_t) {{0, 0, 0, 0, 0, 0}}) | 168 | #define BDADDR_ANY (&(bdaddr_t) {{0, 0, 0, 0, 0, 0} }) |
172 | #define BDADDR_LOCAL (&(bdaddr_t) {{0, 0, 0, 0xff, 0xff, 0xff}}) | 169 | #define BDADDR_LOCAL (&(bdaddr_t) {{0, 0, 0, 0xff, 0xff, 0xff} }) |
173 | 170 | ||
174 | /* Copy, swap, convert BD Address */ | 171 | /* Copy, swap, convert BD Address */ |
175 | static inline int bacmp(bdaddr_t *ba1, bdaddr_t *ba2) | 172 | static inline int bacmp(bdaddr_t *ba1, bdaddr_t *ba2) |
@@ -215,7 +212,7 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
215 | struct msghdr *msg, size_t len, int flags); | 212 | struct msghdr *msg, size_t len, int flags); |
216 | int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | 213 | int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock, |
217 | struct msghdr *msg, size_t len, int flags); | 214 | struct msghdr *msg, size_t len, int flags); |
218 | uint bt_sock_poll(struct file * file, struct socket *sock, poll_table *wait); | 215 | uint bt_sock_poll(struct file *file, struct socket *sock, poll_table *wait); |
219 | int bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg); | 216 | int bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg); |
220 | int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo); | 217 | int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo); |
221 | 218 | ||
@@ -225,12 +222,12 @@ struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock); | |||
225 | 222 | ||
226 | /* Skb helpers */ | 223 | /* Skb helpers */ |
227 | struct l2cap_ctrl { | 224 | struct l2cap_ctrl { |
228 | unsigned int sframe : 1, | 225 | unsigned int sframe:1, |
229 | poll : 1, | 226 | poll:1, |
230 | final : 1, | 227 | final:1, |
231 | fcs : 1, | 228 | fcs:1, |
232 | sar : 2, | 229 | sar:2, |
233 | super : 2; | 230 | super:2; |
234 | __u16 reqseq; | 231 | __u16 reqseq; |
235 | __u16 txseq; | 232 | __u16 txseq; |
236 | __u8 retries; | 233 | __u8 retries; |
@@ -249,7 +246,8 @@ static inline struct sk_buff *bt_skb_alloc(unsigned int len, gfp_t how) | |||
249 | { | 246 | { |
250 | struct sk_buff *skb; | 247 | struct sk_buff *skb; |
251 | 248 | ||
252 | if ((skb = alloc_skb(len + BT_SKB_RESERVE, how))) { | 249 | skb = alloc_skb(len + BT_SKB_RESERVE, how); |
250 | if (skb) { | ||
253 | skb_reserve(skb, BT_SKB_RESERVE); | 251 | skb_reserve(skb, BT_SKB_RESERVE); |
254 | bt_cb(skb)->incoming = 0; | 252 | bt_cb(skb)->incoming = 0; |
255 | } | 253 | } |
@@ -261,7 +259,8 @@ static inline struct sk_buff *bt_skb_send_alloc(struct sock *sk, | |||
261 | { | 259 | { |
262 | struct sk_buff *skb; | 260 | struct sk_buff *skb; |
263 | 261 | ||
264 | if ((skb = sock_alloc_send_skb(sk, len + BT_SKB_RESERVE, nb, err))) { | 262 | skb = sock_alloc_send_skb(sk, len + BT_SKB_RESERVE, nb, err); |
263 | if (skb) { | ||
265 | skb_reserve(skb, BT_SKB_RESERVE); | 264 | skb_reserve(skb, BT_SKB_RESERVE); |
266 | bt_cb(skb)->incoming = 0; | 265 | bt_cb(skb)->incoming = 0; |
267 | } | 266 | } |
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 66a7b579e31..2a6b0b8b712 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h | |||
@@ -30,6 +30,9 @@ | |||
30 | #define HCI_MAX_EVENT_SIZE 260 | 30 | #define HCI_MAX_EVENT_SIZE 260 |
31 | #define HCI_MAX_FRAME_SIZE (HCI_MAX_ACL_SIZE + 4) | 31 | #define HCI_MAX_FRAME_SIZE (HCI_MAX_ACL_SIZE + 4) |
32 | 32 | ||
33 | #define HCI_LINK_KEY_SIZE 16 | ||
34 | #define HCI_AMP_LINK_KEY_SIZE (2 * HCI_LINK_KEY_SIZE) | ||
35 | |||
33 | /* HCI dev events */ | 36 | /* HCI dev events */ |
34 | #define HCI_DEV_REG 1 | 37 | #define HCI_DEV_REG 1 |
35 | #define HCI_DEV_UNREG 2 | 38 | #define HCI_DEV_UNREG 2 |
@@ -56,9 +59,12 @@ | |||
56 | #define HCI_BREDR 0x00 | 59 | #define HCI_BREDR 0x00 |
57 | #define HCI_AMP 0x01 | 60 | #define HCI_AMP 0x01 |
58 | 61 | ||
62 | /* First BR/EDR Controller shall have ID = 0 */ | ||
63 | #define HCI_BREDR_ID 0 | ||
64 | |||
59 | /* HCI device quirks */ | 65 | /* HCI device quirks */ |
60 | enum { | 66 | enum { |
61 | HCI_QUIRK_NO_RESET, | 67 | HCI_QUIRK_RESET_ON_CLOSE, |
62 | HCI_QUIRK_RAW_DEVICE, | 68 | HCI_QUIRK_RAW_DEVICE, |
63 | HCI_QUIRK_FIXUP_BUFFER_SIZE | 69 | HCI_QUIRK_FIXUP_BUFFER_SIZE |
64 | }; | 70 | }; |
@@ -133,10 +139,8 @@ enum { | |||
133 | #define HCIINQUIRY _IOR('H', 240, int) | 139 | #define HCIINQUIRY _IOR('H', 240, int) |
134 | 140 | ||
135 | /* HCI timeouts */ | 141 | /* HCI timeouts */ |
136 | #define HCI_CONNECT_TIMEOUT (40000) /* 40 seconds */ | ||
137 | #define HCI_DISCONN_TIMEOUT (2000) /* 2 seconds */ | 142 | #define HCI_DISCONN_TIMEOUT (2000) /* 2 seconds */ |
138 | #define HCI_PAIRING_TIMEOUT (60000) /* 60 seconds */ | 143 | #define HCI_PAIRING_TIMEOUT (60000) /* 60 seconds */ |
139 | #define HCI_IDLE_TIMEOUT (6000) /* 6 seconds */ | ||
140 | #define HCI_INIT_TIMEOUT (10000) /* 10 seconds */ | 144 | #define HCI_INIT_TIMEOUT (10000) /* 10 seconds */ |
141 | #define HCI_CMD_TIMEOUT (1000) /* 1 seconds */ | 145 | #define HCI_CMD_TIMEOUT (1000) /* 1 seconds */ |
142 | #define HCI_ACL_TX_TIMEOUT (45000) /* 45 seconds */ | 146 | #define HCI_ACL_TX_TIMEOUT (45000) /* 45 seconds */ |
@@ -371,7 +375,7 @@ struct hci_cp_reject_conn_req { | |||
371 | #define HCI_OP_LINK_KEY_REPLY 0x040b | 375 | #define HCI_OP_LINK_KEY_REPLY 0x040b |
372 | struct hci_cp_link_key_reply { | 376 | struct hci_cp_link_key_reply { |
373 | bdaddr_t bdaddr; | 377 | bdaddr_t bdaddr; |
374 | __u8 link_key[16]; | 378 | __u8 link_key[HCI_LINK_KEY_SIZE]; |
375 | } __packed; | 379 | } __packed; |
376 | 380 | ||
377 | #define HCI_OP_LINK_KEY_NEG_REPLY 0x040c | 381 | #define HCI_OP_LINK_KEY_NEG_REPLY 0x040c |
@@ -523,6 +527,28 @@ struct hci_cp_io_capability_neg_reply { | |||
523 | __u8 reason; | 527 | __u8 reason; |
524 | } __packed; | 528 | } __packed; |
525 | 529 | ||
530 | #define HCI_OP_CREATE_PHY_LINK 0x0435 | ||
531 | struct hci_cp_create_phy_link { | ||
532 | __u8 phy_handle; | ||
533 | __u8 key_len; | ||
534 | __u8 key_type; | ||
535 | __u8 key[HCI_AMP_LINK_KEY_SIZE]; | ||
536 | } __packed; | ||
537 | |||
538 | #define HCI_OP_ACCEPT_PHY_LINK 0x0436 | ||
539 | struct hci_cp_accept_phy_link { | ||
540 | __u8 phy_handle; | ||
541 | __u8 key_len; | ||
542 | __u8 key_type; | ||
543 | __u8 key[HCI_AMP_LINK_KEY_SIZE]; | ||
544 | } __packed; | ||
545 | |||
546 | #define HCI_OP_DISCONN_PHY_LINK 0x0437 | ||
547 | struct hci_cp_disconn_phy_link { | ||
548 | __u8 phy_handle; | ||
549 | __u8 reason; | ||
550 | } __packed; | ||
551 | |||
526 | #define HCI_OP_SNIFF_MODE 0x0803 | 552 | #define HCI_OP_SNIFF_MODE 0x0803 |
527 | struct hci_cp_sniff_mode { | 553 | struct hci_cp_sniff_mode { |
528 | __le16 handle; | 554 | __le16 handle; |
@@ -818,6 +844,31 @@ struct hci_rp_read_local_amp_info { | |||
818 | __le32 be_flush_to; | 844 | __le32 be_flush_to; |
819 | } __packed; | 845 | } __packed; |
820 | 846 | ||
847 | #define HCI_OP_READ_LOCAL_AMP_ASSOC 0x140a | ||
848 | struct hci_cp_read_local_amp_assoc { | ||
849 | __u8 phy_handle; | ||
850 | __le16 len_so_far; | ||
851 | __le16 max_len; | ||
852 | } __packed; | ||
853 | struct hci_rp_read_local_amp_assoc { | ||
854 | __u8 status; | ||
855 | __u8 phy_handle; | ||
856 | __le16 rem_len; | ||
857 | __u8 frag[0]; | ||
858 | } __packed; | ||
859 | |||
860 | #define HCI_OP_WRITE_REMOTE_AMP_ASSOC 0x140b | ||
861 | struct hci_cp_write_remote_amp_assoc { | ||
862 | __u8 phy_handle; | ||
863 | __le16 len_so_far; | ||
864 | __le16 rem_len; | ||
865 | __u8 frag[0]; | ||
866 | } __packed; | ||
867 | struct hci_rp_write_remote_amp_assoc { | ||
868 | __u8 status; | ||
869 | __u8 phy_handle; | ||
870 | } __packed; | ||
871 | |||
821 | #define HCI_OP_LE_SET_EVENT_MASK 0x2001 | 872 | #define HCI_OP_LE_SET_EVENT_MASK 0x2001 |
822 | struct hci_cp_le_set_event_mask { | 873 | struct hci_cp_le_set_event_mask { |
823 | __u8 mask[8]; | 874 | __u8 mask[8]; |
@@ -1048,7 +1099,7 @@ struct hci_ev_link_key_req { | |||
1048 | #define HCI_EV_LINK_KEY_NOTIFY 0x18 | 1099 | #define HCI_EV_LINK_KEY_NOTIFY 0x18 |
1049 | struct hci_ev_link_key_notify { | 1100 | struct hci_ev_link_key_notify { |
1050 | bdaddr_t bdaddr; | 1101 | bdaddr_t bdaddr; |
1051 | __u8 link_key[16]; | 1102 | __u8 link_key[HCI_LINK_KEY_SIZE]; |
1052 | __u8 key_type; | 1103 | __u8 key_type; |
1053 | } __packed; | 1104 | } __packed; |
1054 | 1105 | ||
@@ -1144,6 +1195,12 @@ struct extended_inquiry_info { | |||
1144 | __u8 data[240]; | 1195 | __u8 data[240]; |
1145 | } __packed; | 1196 | } __packed; |
1146 | 1197 | ||
1198 | #define HCI_EV_KEY_REFRESH_COMPLETE 0x30 | ||
1199 | struct hci_ev_key_refresh_complete { | ||
1200 | __u8 status; | ||
1201 | __le16 handle; | ||
1202 | } __packed; | ||
1203 | |||
1147 | #define HCI_EV_IO_CAPA_REQUEST 0x31 | 1204 | #define HCI_EV_IO_CAPA_REQUEST 0x31 |
1148 | struct hci_ev_io_capa_request { | 1205 | struct hci_ev_io_capa_request { |
1149 | bdaddr_t bdaddr; | 1206 | bdaddr_t bdaddr; |
@@ -1190,6 +1247,39 @@ struct hci_ev_le_meta { | |||
1190 | __u8 subevent; | 1247 | __u8 subevent; |
1191 | } __packed; | 1248 | } __packed; |
1192 | 1249 | ||
1250 | #define HCI_EV_PHY_LINK_COMPLETE 0x40 | ||
1251 | struct hci_ev_phy_link_complete { | ||
1252 | __u8 status; | ||
1253 | __u8 phy_handle; | ||
1254 | } __packed; | ||
1255 | |||
1256 | #define HCI_EV_CHANNEL_SELECTED 0x41 | ||
1257 | struct hci_ev_channel_selected { | ||
1258 | __u8 phy_handle; | ||
1259 | } __packed; | ||
1260 | |||
1261 | #define HCI_EV_DISCONN_PHY_LINK_COMPLETE 0x42 | ||
1262 | struct hci_ev_disconn_phy_link_complete { | ||
1263 | __u8 status; | ||
1264 | __u8 phy_handle; | ||
1265 | __u8 reason; | ||
1266 | } __packed; | ||
1267 | |||
1268 | #define HCI_EV_LOGICAL_LINK_COMPLETE 0x45 | ||
1269 | struct hci_ev_logical_link_complete { | ||
1270 | __u8 status; | ||
1271 | __le16 handle; | ||
1272 | __u8 phy_handle; | ||
1273 | __u8 flow_spec_id; | ||
1274 | } __packed; | ||
1275 | |||
1276 | #define HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE 0x46 | ||
1277 | struct hci_ev_disconn_logical_link_complete { | ||
1278 | __u8 status; | ||
1279 | __le16 handle; | ||
1280 | __u8 reason; | ||
1281 | } __packed; | ||
1282 | |||
1193 | #define HCI_EV_NUM_COMP_BLOCKS 0x48 | 1283 | #define HCI_EV_NUM_COMP_BLOCKS 0x48 |
1194 | struct hci_comp_blocks_info { | 1284 | struct hci_comp_blocks_info { |
1195 | __le16 handle; | 1285 | __le16 handle; |
@@ -1290,7 +1380,6 @@ struct hci_sco_hdr { | |||
1290 | __u8 dlen; | 1380 | __u8 dlen; |
1291 | } __packed; | 1381 | } __packed; |
1292 | 1382 | ||
1293 | #include <linux/skbuff.h> | ||
1294 | static inline struct hci_event_hdr *hci_event_hdr(const struct sk_buff *skb) | 1383 | static inline struct hci_event_hdr *hci_event_hdr(const struct sk_buff *skb) |
1295 | { | 1384 | { |
1296 | return (struct hci_event_hdr *) skb->data; | 1385 | return (struct hci_event_hdr *) skb->data; |
@@ -1307,12 +1396,12 @@ static inline struct hci_sco_hdr *hci_sco_hdr(const struct sk_buff *skb) | |||
1307 | } | 1396 | } |
1308 | 1397 | ||
1309 | /* Command opcode pack/unpack */ | 1398 | /* Command opcode pack/unpack */ |
1310 | #define hci_opcode_pack(ogf, ocf) (__u16) ((ocf & 0x03ff)|(ogf << 10)) | 1399 | #define hci_opcode_pack(ogf, ocf) ((__u16) ((ocf & 0x03ff)|(ogf << 10))) |
1311 | #define hci_opcode_ogf(op) (op >> 10) | 1400 | #define hci_opcode_ogf(op) (op >> 10) |
1312 | #define hci_opcode_ocf(op) (op & 0x03ff) | 1401 | #define hci_opcode_ocf(op) (op & 0x03ff) |
1313 | 1402 | ||
1314 | /* ACL handle and flags pack/unpack */ | 1403 | /* ACL handle and flags pack/unpack */ |
1315 | #define hci_handle_pack(h, f) (__u16) ((h & 0x0fff)|(f << 12)) | 1404 | #define hci_handle_pack(h, f) ((__u16) ((h & 0x0fff)|(f << 12))) |
1316 | #define hci_handle(h) (h & 0x0fff) | 1405 | #define hci_handle(h) (h & 0x0fff) |
1317 | #define hci_flags(h) (h >> 12) | 1406 | #define hci_flags(h) (h >> 12) |
1318 | 1407 | ||
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 9fc7728f94e..20fd57367dd 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
@@ -25,7 +25,6 @@ | |||
25 | #ifndef __HCI_CORE_H | 25 | #ifndef __HCI_CORE_H |
26 | #define __HCI_CORE_H | 26 | #define __HCI_CORE_H |
27 | 27 | ||
28 | #include <linux/interrupt.h> | ||
29 | #include <net/bluetooth/hci.h> | 28 | #include <net/bluetooth/hci.h> |
30 | 29 | ||
31 | /* HCI priority */ | 30 | /* HCI priority */ |
@@ -65,7 +64,7 @@ struct discovery_state { | |||
65 | DISCOVERY_RESOLVING, | 64 | DISCOVERY_RESOLVING, |
66 | DISCOVERY_STOPPING, | 65 | DISCOVERY_STOPPING, |
67 | } state; | 66 | } state; |
68 | struct list_head all; /* All devices found during inquiry */ | 67 | struct list_head all; /* All devices found during inquiry */ |
69 | struct list_head unknown; /* Name state not known */ | 68 | struct list_head unknown; /* Name state not known */ |
70 | struct list_head resolve; /* Name needs to be resolved */ | 69 | struct list_head resolve; /* Name needs to be resolved */ |
71 | __u32 timestamp; | 70 | __u32 timestamp; |
@@ -105,7 +104,7 @@ struct link_key { | |||
105 | struct list_head list; | 104 | struct list_head list; |
106 | bdaddr_t bdaddr; | 105 | bdaddr_t bdaddr; |
107 | u8 type; | 106 | u8 type; |
108 | u8 val[16]; | 107 | u8 val[HCI_LINK_KEY_SIZE]; |
109 | u8 pin_len; | 108 | u8 pin_len; |
110 | }; | 109 | }; |
111 | 110 | ||
@@ -333,6 +332,7 @@ struct hci_conn { | |||
333 | void *l2cap_data; | 332 | void *l2cap_data; |
334 | void *sco_data; | 333 | void *sco_data; |
335 | void *smp_conn; | 334 | void *smp_conn; |
335 | struct amp_mgr *amp_mgr; | ||
336 | 336 | ||
337 | struct hci_conn *link; | 337 | struct hci_conn *link; |
338 | 338 | ||
@@ -360,7 +360,8 @@ extern int l2cap_connect_cfm(struct hci_conn *hcon, u8 status); | |||
360 | extern int l2cap_disconn_ind(struct hci_conn *hcon); | 360 | extern int l2cap_disconn_ind(struct hci_conn *hcon); |
361 | extern int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason); | 361 | extern int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason); |
362 | extern int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt); | 362 | extern int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt); |
363 | extern int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags); | 363 | extern int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, |
364 | u16 flags); | ||
364 | 365 | ||
365 | extern int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr); | 366 | extern int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr); |
366 | extern int sco_connect_cfm(struct hci_conn *hcon, __u8 status); | 367 | extern int sco_connect_cfm(struct hci_conn *hcon, __u8 status); |
@@ -429,8 +430,8 @@ enum { | |||
429 | static inline bool hci_conn_ssp_enabled(struct hci_conn *conn) | 430 | static inline bool hci_conn_ssp_enabled(struct hci_conn *conn) |
430 | { | 431 | { |
431 | struct hci_dev *hdev = conn->hdev; | 432 | struct hci_dev *hdev = conn->hdev; |
432 | return (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) && | 433 | return test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) && |
433 | test_bit(HCI_CONN_SSP_ENABLED, &conn->flags)); | 434 | test_bit(HCI_CONN_SSP_ENABLED, &conn->flags); |
434 | } | 435 | } |
435 | 436 | ||
436 | static inline void hci_conn_hash_init(struct hci_dev *hdev) | 437 | static inline void hci_conn_hash_init(struct hci_dev *hdev) |
@@ -640,6 +641,19 @@ static inline void hci_set_drvdata(struct hci_dev *hdev, void *data) | |||
640 | dev_set_drvdata(&hdev->dev, data); | 641 | dev_set_drvdata(&hdev->dev, data); |
641 | } | 642 | } |
642 | 643 | ||
644 | /* hci_dev_list shall be locked */ | ||
645 | static inline uint8_t __hci_num_ctrl(void) | ||
646 | { | ||
647 | uint8_t count = 0; | ||
648 | struct list_head *p; | ||
649 | |||
650 | list_for_each(p, &hci_dev_list) { | ||
651 | count++; | ||
652 | } | ||
653 | |||
654 | return count; | ||
655 | } | ||
656 | |||
643 | struct hci_dev *hci_dev_get(int index); | 657 | struct hci_dev *hci_dev_get(int index); |
644 | struct hci_dev *hci_get_route(bdaddr_t *src, bdaddr_t *dst); | 658 | struct hci_dev *hci_get_route(bdaddr_t *src, bdaddr_t *dst); |
645 | 659 | ||
@@ -661,7 +675,8 @@ int hci_get_conn_info(struct hci_dev *hdev, void __user *arg); | |||
661 | int hci_get_auth_info(struct hci_dev *hdev, void __user *arg); | 675 | int hci_get_auth_info(struct hci_dev *hdev, void __user *arg); |
662 | int hci_inquiry(void __user *arg); | 676 | int hci_inquiry(void __user *arg); |
663 | 677 | ||
664 | struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr); | 678 | struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, |
679 | bdaddr_t *bdaddr); | ||
665 | int hci_blacklist_clear(struct hci_dev *hdev); | 680 | int hci_blacklist_clear(struct hci_dev *hdev); |
666 | int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); | 681 | int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); |
667 | int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); | 682 | int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); |
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 1c7d1cd5e67..d80e3f0691b 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h | |||
@@ -40,11 +40,11 @@ | |||
40 | #define L2CAP_DEFAULT_MONITOR_TO 12000 /* 12 seconds */ | 40 | #define L2CAP_DEFAULT_MONITOR_TO 12000 /* 12 seconds */ |
41 | #define L2CAP_DEFAULT_MAX_PDU_SIZE 1009 /* Sized for 3-DH5 packet */ | 41 | #define L2CAP_DEFAULT_MAX_PDU_SIZE 1009 /* Sized for 3-DH5 packet */ |
42 | #define L2CAP_DEFAULT_ACK_TO 200 | 42 | #define L2CAP_DEFAULT_ACK_TO 200 |
43 | #define L2CAP_LE_DEFAULT_MTU 23 | ||
44 | #define L2CAP_DEFAULT_MAX_SDU_SIZE 0xFFFF | 43 | #define L2CAP_DEFAULT_MAX_SDU_SIZE 0xFFFF |
45 | #define L2CAP_DEFAULT_SDU_ITIME 0xFFFFFFFF | 44 | #define L2CAP_DEFAULT_SDU_ITIME 0xFFFFFFFF |
46 | #define L2CAP_DEFAULT_ACC_LAT 0xFFFFFFFF | 45 | #define L2CAP_DEFAULT_ACC_LAT 0xFFFFFFFF |
47 | #define L2CAP_BREDR_MAX_PAYLOAD 1019 /* 3-DH5 packet */ | 46 | #define L2CAP_BREDR_MAX_PAYLOAD 1019 /* 3-DH5 packet */ |
47 | #define L2CAP_LE_MIN_MTU 23 | ||
48 | 48 | ||
49 | #define L2CAP_DISC_TIMEOUT msecs_to_jiffies(100) | 49 | #define L2CAP_DISC_TIMEOUT msecs_to_jiffies(100) |
50 | #define L2CAP_DISC_REJ_TIMEOUT msecs_to_jiffies(5000) | 50 | #define L2CAP_DISC_REJ_TIMEOUT msecs_to_jiffies(5000) |
@@ -52,6 +52,8 @@ | |||
52 | #define L2CAP_CONN_TIMEOUT msecs_to_jiffies(40000) | 52 | #define L2CAP_CONN_TIMEOUT msecs_to_jiffies(40000) |
53 | #define L2CAP_INFO_TIMEOUT msecs_to_jiffies(4000) | 53 | #define L2CAP_INFO_TIMEOUT msecs_to_jiffies(4000) |
54 | 54 | ||
55 | #define L2CAP_A2MP_DEFAULT_MTU 670 | ||
56 | |||
55 | /* L2CAP socket address */ | 57 | /* L2CAP socket address */ |
56 | struct sockaddr_l2 { | 58 | struct sockaddr_l2 { |
57 | sa_family_t l2_family; | 59 | sa_family_t l2_family; |
@@ -229,9 +231,14 @@ struct l2cap_conn_rsp { | |||
229 | __le16 status; | 231 | __le16 status; |
230 | } __packed; | 232 | } __packed; |
231 | 233 | ||
234 | /* protocol/service multiplexer (PSM) */ | ||
235 | #define L2CAP_PSM_SDP 0x0001 | ||
236 | #define L2CAP_PSM_RFCOMM 0x0003 | ||
237 | |||
232 | /* channel indentifier */ | 238 | /* channel indentifier */ |
233 | #define L2CAP_CID_SIGNALING 0x0001 | 239 | #define L2CAP_CID_SIGNALING 0x0001 |
234 | #define L2CAP_CID_CONN_LESS 0x0002 | 240 | #define L2CAP_CID_CONN_LESS 0x0002 |
241 | #define L2CAP_CID_A2MP 0x0003 | ||
235 | #define L2CAP_CID_LE_DATA 0x0004 | 242 | #define L2CAP_CID_LE_DATA 0x0004 |
236 | #define L2CAP_CID_LE_SIGNALING 0x0005 | 243 | #define L2CAP_CID_LE_SIGNALING 0x0005 |
237 | #define L2CAP_CID_SMP 0x0006 | 244 | #define L2CAP_CID_SMP 0x0006 |
@@ -271,6 +278,9 @@ struct l2cap_conf_rsp { | |||
271 | #define L2CAP_CONF_PENDING 0x0004 | 278 | #define L2CAP_CONF_PENDING 0x0004 |
272 | #define L2CAP_CONF_EFS_REJECT 0x0005 | 279 | #define L2CAP_CONF_EFS_REJECT 0x0005 |
273 | 280 | ||
281 | /* configuration req/rsp continuation flag */ | ||
282 | #define L2CAP_CONF_FLAG_CONTINUATION 0x0001 | ||
283 | |||
274 | struct l2cap_conf_opt { | 284 | struct l2cap_conf_opt { |
275 | __u8 type; | 285 | __u8 type; |
276 | __u8 len; | 286 | __u8 len; |
@@ -419,11 +429,6 @@ struct l2cap_seq_list { | |||
419 | #define L2CAP_SEQ_LIST_CLEAR 0xFFFF | 429 | #define L2CAP_SEQ_LIST_CLEAR 0xFFFF |
420 | #define L2CAP_SEQ_LIST_TAIL 0x8000 | 430 | #define L2CAP_SEQ_LIST_TAIL 0x8000 |
421 | 431 | ||
422 | struct srej_list { | ||
423 | __u16 tx_seq; | ||
424 | struct list_head list; | ||
425 | }; | ||
426 | |||
427 | struct l2cap_chan { | 432 | struct l2cap_chan { |
428 | struct sock *sk; | 433 | struct sock *sk; |
429 | 434 | ||
@@ -475,14 +480,12 @@ struct l2cap_chan { | |||
475 | __u16 expected_ack_seq; | 480 | __u16 expected_ack_seq; |
476 | __u16 expected_tx_seq; | 481 | __u16 expected_tx_seq; |
477 | __u16 buffer_seq; | 482 | __u16 buffer_seq; |
478 | __u16 buffer_seq_srej; | ||
479 | __u16 srej_save_reqseq; | 483 | __u16 srej_save_reqseq; |
480 | __u16 last_acked_seq; | 484 | __u16 last_acked_seq; |
481 | __u16 frames_sent; | 485 | __u16 frames_sent; |
482 | __u16 unacked_frames; | 486 | __u16 unacked_frames; |
483 | __u8 retry_count; | 487 | __u8 retry_count; |
484 | __u16 srej_queue_next; | 488 | __u16 srej_queue_next; |
485 | __u8 num_acked; | ||
486 | __u16 sdu_len; | 489 | __u16 sdu_len; |
487 | struct sk_buff *sdu; | 490 | struct sk_buff *sdu; |
488 | struct sk_buff *sdu_last_frag; | 491 | struct sk_buff *sdu_last_frag; |
@@ -515,7 +518,6 @@ struct l2cap_chan { | |||
515 | struct sk_buff_head srej_q; | 518 | struct sk_buff_head srej_q; |
516 | struct l2cap_seq_list srej_list; | 519 | struct l2cap_seq_list srej_list; |
517 | struct l2cap_seq_list retrans_list; | 520 | struct l2cap_seq_list retrans_list; |
518 | struct list_head srej_l; | ||
519 | 521 | ||
520 | struct list_head list; | 522 | struct list_head list; |
521 | struct list_head global_l; | 523 | struct list_head global_l; |
@@ -528,10 +530,14 @@ struct l2cap_chan { | |||
528 | struct l2cap_ops { | 530 | struct l2cap_ops { |
529 | char *name; | 531 | char *name; |
530 | 532 | ||
531 | struct l2cap_chan *(*new_connection) (void *data); | 533 | struct l2cap_chan *(*new_connection) (struct l2cap_chan *chan); |
532 | int (*recv) (void *data, struct sk_buff *skb); | 534 | int (*recv) (struct l2cap_chan * chan, |
533 | void (*close) (void *data); | 535 | struct sk_buff *skb); |
534 | void (*state_change) (void *data, int state); | 536 | void (*teardown) (struct l2cap_chan *chan, int err); |
537 | void (*close) (struct l2cap_chan *chan); | ||
538 | void (*state_change) (struct l2cap_chan *chan, | ||
539 | int state); | ||
540 | void (*ready) (struct l2cap_chan *chan); | ||
535 | struct sk_buff *(*alloc_skb) (struct l2cap_chan *chan, | 541 | struct sk_buff *(*alloc_skb) (struct l2cap_chan *chan, |
536 | unsigned long len, int nb); | 542 | unsigned long len, int nb); |
537 | }; | 543 | }; |
@@ -575,6 +581,7 @@ struct l2cap_conn { | |||
575 | #define L2CAP_CHAN_RAW 1 | 581 | #define L2CAP_CHAN_RAW 1 |
576 | #define L2CAP_CHAN_CONN_LESS 2 | 582 | #define L2CAP_CHAN_CONN_LESS 2 |
577 | #define L2CAP_CHAN_CONN_ORIENTED 3 | 583 | #define L2CAP_CHAN_CONN_ORIENTED 3 |
584 | #define L2CAP_CHAN_CONN_FIX_A2MP 4 | ||
578 | 585 | ||
579 | /* ----- L2CAP socket info ----- */ | 586 | /* ----- L2CAP socket info ----- */ |
580 | #define l2cap_pi(sk) ((struct l2cap_pinfo *) sk) | 587 | #define l2cap_pi(sk) ((struct l2cap_pinfo *) sk) |
@@ -597,6 +604,7 @@ enum { | |||
597 | CONF_EWS_RECV, | 604 | CONF_EWS_RECV, |
598 | CONF_LOC_CONF_PEND, | 605 | CONF_LOC_CONF_PEND, |
599 | CONF_REM_CONF_PEND, | 606 | CONF_REM_CONF_PEND, |
607 | CONF_NOT_COMPLETE, | ||
600 | }; | 608 | }; |
601 | 609 | ||
602 | #define L2CAP_CONF_MAX_CONF_REQ 2 | 610 | #define L2CAP_CONF_MAX_CONF_REQ 2 |
@@ -713,11 +721,7 @@ static inline bool l2cap_clear_timer(struct l2cap_chan *chan, | |||
713 | 721 | ||
714 | #define __set_chan_timer(c, t) l2cap_set_timer(c, &c->chan_timer, (t)) | 722 | #define __set_chan_timer(c, t) l2cap_set_timer(c, &c->chan_timer, (t)) |
715 | #define __clear_chan_timer(c) l2cap_clear_timer(c, &c->chan_timer) | 723 | #define __clear_chan_timer(c) l2cap_clear_timer(c, &c->chan_timer) |
716 | #define __set_retrans_timer(c) l2cap_set_timer(c, &c->retrans_timer, \ | ||
717 | msecs_to_jiffies(L2CAP_DEFAULT_RETRANS_TO)); | ||
718 | #define __clear_retrans_timer(c) l2cap_clear_timer(c, &c->retrans_timer) | 724 | #define __clear_retrans_timer(c) l2cap_clear_timer(c, &c->retrans_timer) |
719 | #define __set_monitor_timer(c) l2cap_set_timer(c, &c->monitor_timer, \ | ||
720 | msecs_to_jiffies(L2CAP_DEFAULT_MONITOR_TO)); | ||
721 | #define __clear_monitor_timer(c) l2cap_clear_timer(c, &c->monitor_timer) | 725 | #define __clear_monitor_timer(c) l2cap_clear_timer(c, &c->monitor_timer) |
722 | #define __set_ack_timer(c) l2cap_set_timer(c, &chan->ack_timer, \ | 726 | #define __set_ack_timer(c) l2cap_set_timer(c, &chan->ack_timer, \ |
723 | msecs_to_jiffies(L2CAP_DEFAULT_ACK_TO)); | 727 | msecs_to_jiffies(L2CAP_DEFAULT_ACK_TO)); |
@@ -736,173 +740,17 @@ static inline __u16 __next_seq(struct l2cap_chan *chan, __u16 seq) | |||
736 | return (seq + 1) % (chan->tx_win_max + 1); | 740 | return (seq + 1) % (chan->tx_win_max + 1); |
737 | } | 741 | } |
738 | 742 | ||
739 | static inline int l2cap_tx_window_full(struct l2cap_chan *ch) | 743 | static inline struct l2cap_chan *l2cap_chan_no_new_connection(struct l2cap_chan *chan) |
740 | { | ||
741 | int sub; | ||
742 | |||
743 | sub = (ch->next_tx_seq - ch->expected_ack_seq) % 64; | ||
744 | |||
745 | if (sub < 0) | ||
746 | sub += 64; | ||
747 | |||
748 | return sub == ch->remote_tx_win; | ||
749 | } | ||
750 | |||
751 | static inline __u16 __get_reqseq(struct l2cap_chan *chan, __u32 ctrl) | ||
752 | { | ||
753 | if (test_bit(FLAG_EXT_CTRL, &chan->flags)) | ||
754 | return (ctrl & L2CAP_EXT_CTRL_REQSEQ) >> | ||
755 | L2CAP_EXT_CTRL_REQSEQ_SHIFT; | ||
756 | else | ||
757 | return (ctrl & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT; | ||
758 | } | ||
759 | |||
760 | static inline __u32 __set_reqseq(struct l2cap_chan *chan, __u32 reqseq) | ||
761 | { | 744 | { |
762 | if (test_bit(FLAG_EXT_CTRL, &chan->flags)) | 745 | return NULL; |
763 | return (reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT) & | ||
764 | L2CAP_EXT_CTRL_REQSEQ; | ||
765 | else | ||
766 | return (reqseq << L2CAP_CTRL_REQSEQ_SHIFT) & L2CAP_CTRL_REQSEQ; | ||
767 | } | 746 | } |
768 | 747 | ||
769 | static inline __u16 __get_txseq(struct l2cap_chan *chan, __u32 ctrl) | 748 | static inline void l2cap_chan_no_teardown(struct l2cap_chan *chan, int err) |
770 | { | 749 | { |
771 | if (test_bit(FLAG_EXT_CTRL, &chan->flags)) | ||
772 | return (ctrl & L2CAP_EXT_CTRL_TXSEQ) >> | ||
773 | L2CAP_EXT_CTRL_TXSEQ_SHIFT; | ||
774 | else | ||
775 | return (ctrl & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT; | ||
776 | } | 750 | } |
777 | 751 | ||
778 | static inline __u32 __set_txseq(struct l2cap_chan *chan, __u32 txseq) | 752 | static inline void l2cap_chan_no_ready(struct l2cap_chan *chan) |
779 | { | 753 | { |
780 | if (test_bit(FLAG_EXT_CTRL, &chan->flags)) | ||
781 | return (txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT) & | ||
782 | L2CAP_EXT_CTRL_TXSEQ; | ||
783 | else | ||
784 | return (txseq << L2CAP_CTRL_TXSEQ_SHIFT) & L2CAP_CTRL_TXSEQ; | ||
785 | } | ||
786 | |||
787 | static inline bool __is_sframe(struct l2cap_chan *chan, __u32 ctrl) | ||
788 | { | ||
789 | if (test_bit(FLAG_EXT_CTRL, &chan->flags)) | ||
790 | return ctrl & L2CAP_EXT_CTRL_FRAME_TYPE; | ||
791 | else | ||
792 | return ctrl & L2CAP_CTRL_FRAME_TYPE; | ||
793 | } | ||
794 | |||
795 | static inline __u32 __set_sframe(struct l2cap_chan *chan) | ||
796 | { | ||
797 | if (test_bit(FLAG_EXT_CTRL, &chan->flags)) | ||
798 | return L2CAP_EXT_CTRL_FRAME_TYPE; | ||
799 | else | ||
800 | return L2CAP_CTRL_FRAME_TYPE; | ||
801 | } | ||
802 | |||
803 | static inline __u8 __get_ctrl_sar(struct l2cap_chan *chan, __u32 ctrl) | ||
804 | { | ||
805 | if (test_bit(FLAG_EXT_CTRL, &chan->flags)) | ||
806 | return (ctrl & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT; | ||
807 | else | ||
808 | return (ctrl & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT; | ||
809 | } | ||
810 | |||
811 | static inline __u32 __set_ctrl_sar(struct l2cap_chan *chan, __u32 sar) | ||
812 | { | ||
813 | if (test_bit(FLAG_EXT_CTRL, &chan->flags)) | ||
814 | return (sar << L2CAP_EXT_CTRL_SAR_SHIFT) & L2CAP_EXT_CTRL_SAR; | ||
815 | else | ||
816 | return (sar << L2CAP_CTRL_SAR_SHIFT) & L2CAP_CTRL_SAR; | ||
817 | } | ||
818 | |||
819 | static inline bool __is_sar_start(struct l2cap_chan *chan, __u32 ctrl) | ||
820 | { | ||
821 | return __get_ctrl_sar(chan, ctrl) == L2CAP_SAR_START; | ||
822 | } | ||
823 | |||
824 | static inline __u32 __get_sar_mask(struct l2cap_chan *chan) | ||
825 | { | ||
826 | if (test_bit(FLAG_EXT_CTRL, &chan->flags)) | ||
827 | return L2CAP_EXT_CTRL_SAR; | ||
828 | else | ||
829 | return L2CAP_CTRL_SAR; | ||
830 | } | ||
831 | |||
832 | static inline __u8 __get_ctrl_super(struct l2cap_chan *chan, __u32 ctrl) | ||
833 | { | ||
834 | if (test_bit(FLAG_EXT_CTRL, &chan->flags)) | ||
835 | return (ctrl & L2CAP_EXT_CTRL_SUPERVISE) >> | ||
836 | L2CAP_EXT_CTRL_SUPER_SHIFT; | ||
837 | else | ||
838 | return (ctrl & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT; | ||
839 | } | ||
840 | |||
841 | static inline __u32 __set_ctrl_super(struct l2cap_chan *chan, __u32 super) | ||
842 | { | ||
843 | if (test_bit(FLAG_EXT_CTRL, &chan->flags)) | ||
844 | return (super << L2CAP_EXT_CTRL_SUPER_SHIFT) & | ||
845 | L2CAP_EXT_CTRL_SUPERVISE; | ||
846 | else | ||
847 | return (super << L2CAP_CTRL_SUPER_SHIFT) & | ||
848 | L2CAP_CTRL_SUPERVISE; | ||
849 | } | ||
850 | |||
851 | static inline __u32 __set_ctrl_final(struct l2cap_chan *chan) | ||
852 | { | ||
853 | if (test_bit(FLAG_EXT_CTRL, &chan->flags)) | ||
854 | return L2CAP_EXT_CTRL_FINAL; | ||
855 | else | ||
856 | return L2CAP_CTRL_FINAL; | ||
857 | } | ||
858 | |||
859 | static inline bool __is_ctrl_final(struct l2cap_chan *chan, __u32 ctrl) | ||
860 | { | ||
861 | if (test_bit(FLAG_EXT_CTRL, &chan->flags)) | ||
862 | return ctrl & L2CAP_EXT_CTRL_FINAL; | ||
863 | else | ||
864 | return ctrl & L2CAP_CTRL_FINAL; | ||
865 | } | ||
866 | |||
867 | static inline __u32 __set_ctrl_poll(struct l2cap_chan *chan) | ||
868 | { | ||
869 | if (test_bit(FLAG_EXT_CTRL, &chan->flags)) | ||
870 | return L2CAP_EXT_CTRL_POLL; | ||
871 | else | ||
872 | return L2CAP_CTRL_POLL; | ||
873 | } | ||
874 | |||
875 | static inline bool __is_ctrl_poll(struct l2cap_chan *chan, __u32 ctrl) | ||
876 | { | ||
877 | if (test_bit(FLAG_EXT_CTRL, &chan->flags)) | ||
878 | return ctrl & L2CAP_EXT_CTRL_POLL; | ||
879 | else | ||
880 | return ctrl & L2CAP_CTRL_POLL; | ||
881 | } | ||
882 | |||
883 | static inline __u32 __get_control(struct l2cap_chan *chan, void *p) | ||
884 | { | ||
885 | if (test_bit(FLAG_EXT_CTRL, &chan->flags)) | ||
886 | return get_unaligned_le32(p); | ||
887 | else | ||
888 | return get_unaligned_le16(p); | ||
889 | } | ||
890 | |||
891 | static inline void __put_control(struct l2cap_chan *chan, __u32 control, | ||
892 | void *p) | ||
893 | { | ||
894 | if (test_bit(FLAG_EXT_CTRL, &chan->flags)) | ||
895 | return put_unaligned_le32(control, p); | ||
896 | else | ||
897 | return put_unaligned_le16(control, p); | ||
898 | } | ||
899 | |||
900 | static inline __u8 __ctrl_size(struct l2cap_chan *chan) | ||
901 | { | ||
902 | if (test_bit(FLAG_EXT_CTRL, &chan->flags)) | ||
903 | return L2CAP_EXT_HDR_SIZE - L2CAP_HDR_SIZE; | ||
904 | else | ||
905 | return L2CAP_ENH_HDR_SIZE - L2CAP_HDR_SIZE; | ||
906 | } | 754 | } |
907 | 755 | ||
908 | extern bool disable_ertm; | 756 | extern bool disable_ertm; |
@@ -926,5 +774,8 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, | |||
926 | void l2cap_chan_busy(struct l2cap_chan *chan, int busy); | 774 | void l2cap_chan_busy(struct l2cap_chan *chan, int busy); |
927 | int l2cap_chan_check_security(struct l2cap_chan *chan); | 775 | int l2cap_chan_check_security(struct l2cap_chan *chan); |
928 | void l2cap_chan_set_defaults(struct l2cap_chan *chan); | 776 | void l2cap_chan_set_defaults(struct l2cap_chan *chan); |
777 | int l2cap_ertm_init(struct l2cap_chan *chan); | ||
778 | void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan); | ||
779 | void l2cap_chan_del(struct l2cap_chan *chan, int err); | ||
929 | 780 | ||
930 | #endif /* __L2CAP_H */ | 781 | #endif /* __L2CAP_H */ |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 5e67020b170..b5da094468f 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -1945,6 +1945,11 @@ enum ieee80211_rate_control_changed { | |||
1945 | * to also unregister the device. If it returns 1, then mac80211 | 1945 | * to also unregister the device. If it returns 1, then mac80211 |
1946 | * will also go through the regular complete restart on resume. | 1946 | * will also go through the regular complete restart on resume. |
1947 | * | 1947 | * |
1948 | * @set_wakeup: Enable or disable wakeup when WoWLAN configuration is | ||
1949 | * modified. The reason is that device_set_wakeup_enable() is | ||
1950 | * supposed to be called when the configuration changes, not only | ||
1951 | * in suspend(). | ||
1952 | * | ||
1948 | * @add_interface: Called when a netdevice attached to the hardware is | 1953 | * @add_interface: Called when a netdevice attached to the hardware is |
1949 | * enabled. Because it is not called for monitor mode devices, @start | 1954 | * enabled. Because it is not called for monitor mode devices, @start |
1950 | * and @stop must be implemented. | 1955 | * and @stop must be implemented. |
@@ -2979,6 +2984,7 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, | |||
2979 | * ieee80211_generic_frame_duration - Calculate the duration field for a frame | 2984 | * ieee80211_generic_frame_duration - Calculate the duration field for a frame |
2980 | * @hw: pointer obtained from ieee80211_alloc_hw(). | 2985 | * @hw: pointer obtained from ieee80211_alloc_hw(). |
2981 | * @vif: &struct ieee80211_vif pointer from the add_interface callback. | 2986 | * @vif: &struct ieee80211_vif pointer from the add_interface callback. |
2987 | * @band: the band to calculate the frame duration on | ||
2982 | * @frame_len: the length of the frame. | 2988 | * @frame_len: the length of the frame. |
2983 | * @rate: the rate at which the frame is going to be transmitted. | 2989 | * @rate: the rate at which the frame is going to be transmitted. |
2984 | * | 2990 | * |
diff --git a/include/net/nfc/hci.h b/include/net/nfc/hci.h index 4467c946085..e30e6a86971 100644 --- a/include/net/nfc/hci.h +++ b/include/net/nfc/hci.h | |||
@@ -31,7 +31,8 @@ struct nfc_hci_ops { | |||
31 | void (*close) (struct nfc_hci_dev *hdev); | 31 | void (*close) (struct nfc_hci_dev *hdev); |
32 | int (*hci_ready) (struct nfc_hci_dev *hdev); | 32 | int (*hci_ready) (struct nfc_hci_dev *hdev); |
33 | int (*xmit) (struct nfc_hci_dev *hdev, struct sk_buff *skb); | 33 | int (*xmit) (struct nfc_hci_dev *hdev, struct sk_buff *skb); |
34 | int (*start_poll) (struct nfc_hci_dev *hdev, u32 protocols); | 34 | int (*start_poll) (struct nfc_hci_dev *hdev, |
35 | u32 im_protocols, u32 tm_protocols); | ||
35 | int (*target_from_gate) (struct nfc_hci_dev *hdev, u8 gate, | 36 | int (*target_from_gate) (struct nfc_hci_dev *hdev, u8 gate, |
36 | struct nfc_target *target); | 37 | struct nfc_target *target); |
37 | int (*complete_target_discovered) (struct nfc_hci_dev *hdev, u8 gate, | 38 | int (*complete_target_discovered) (struct nfc_hci_dev *hdev, u8 gate, |
diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h index b7ca4a2a1d7..180964b954a 100644 --- a/include/net/nfc/nfc.h +++ b/include/net/nfc/nfc.h | |||
@@ -53,7 +53,8 @@ struct nfc_target; | |||
53 | struct nfc_ops { | 53 | struct nfc_ops { |
54 | int (*dev_up)(struct nfc_dev *dev); | 54 | int (*dev_up)(struct nfc_dev *dev); |
55 | int (*dev_down)(struct nfc_dev *dev); | 55 | int (*dev_down)(struct nfc_dev *dev); |
56 | int (*start_poll)(struct nfc_dev *dev, u32 protocols); | 56 | int (*start_poll)(struct nfc_dev *dev, |
57 | u32 im_protocols, u32 tm_protocols); | ||
57 | void (*stop_poll)(struct nfc_dev *dev); | 58 | void (*stop_poll)(struct nfc_dev *dev); |
58 | int (*dep_link_up)(struct nfc_dev *dev, struct nfc_target *target, | 59 | int (*dep_link_up)(struct nfc_dev *dev, struct nfc_target *target, |
59 | u8 comm_mode, u8 *gb, size_t gb_len); | 60 | u8 comm_mode, u8 *gb, size_t gb_len); |
@@ -62,9 +63,10 @@ struct nfc_ops { | |||
62 | u32 protocol); | 63 | u32 protocol); |
63 | void (*deactivate_target)(struct nfc_dev *dev, | 64 | void (*deactivate_target)(struct nfc_dev *dev, |
64 | struct nfc_target *target); | 65 | struct nfc_target *target); |
65 | int (*data_exchange)(struct nfc_dev *dev, struct nfc_target *target, | 66 | int (*im_transceive)(struct nfc_dev *dev, struct nfc_target *target, |
66 | struct sk_buff *skb, data_exchange_cb_t cb, | 67 | struct sk_buff *skb, data_exchange_cb_t cb, |
67 | void *cb_context); | 68 | void *cb_context); |
69 | int (*tm_send)(struct nfc_dev *dev, struct sk_buff *skb); | ||
68 | int (*check_presence)(struct nfc_dev *dev, struct nfc_target *target); | 70 | int (*check_presence)(struct nfc_dev *dev, struct nfc_target *target); |
69 | }; | 71 | }; |
70 | 72 | ||
@@ -99,10 +101,10 @@ struct nfc_dev { | |||
99 | int targets_generation; | 101 | int targets_generation; |
100 | struct device dev; | 102 | struct device dev; |
101 | bool dev_up; | 103 | bool dev_up; |
104 | u8 rf_mode; | ||
102 | bool polling; | 105 | bool polling; |
103 | struct nfc_target *active_target; | 106 | struct nfc_target *active_target; |
104 | bool dep_link_up; | 107 | bool dep_link_up; |
105 | u32 dep_rf_mode; | ||
106 | struct nfc_genl_data genl_data; | 108 | struct nfc_genl_data genl_data; |
107 | u32 supported_protocols; | 109 | u32 supported_protocols; |
108 | 110 | ||
@@ -188,6 +190,7 @@ struct sk_buff *nfc_alloc_recv_skb(unsigned int size, gfp_t gfp); | |||
188 | 190 | ||
189 | int nfc_set_remote_general_bytes(struct nfc_dev *dev, | 191 | int nfc_set_remote_general_bytes(struct nfc_dev *dev, |
190 | u8 *gt, u8 gt_len); | 192 | u8 *gt, u8 gt_len); |
193 | u8 *nfc_get_local_general_bytes(struct nfc_dev *dev, size_t *gb_len); | ||
191 | 194 | ||
192 | int nfc_targets_found(struct nfc_dev *dev, | 195 | int nfc_targets_found(struct nfc_dev *dev, |
193 | struct nfc_target *targets, int ntargets); | 196 | struct nfc_target *targets, int ntargets); |
@@ -196,4 +199,9 @@ int nfc_target_lost(struct nfc_dev *dev, u32 target_idx); | |||
196 | int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx, | 199 | int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx, |
197 | u8 comm_mode, u8 rf_mode); | 200 | u8 comm_mode, u8 rf_mode); |
198 | 201 | ||
202 | int nfc_tm_activated(struct nfc_dev *dev, u32 protocol, u8 comm_mode, | ||
203 | u8 *gb, size_t gb_len); | ||
204 | int nfc_tm_deactivated(struct nfc_dev *dev); | ||
205 | int nfc_tm_data_received(struct nfc_dev *dev, struct sk_buff *skb); | ||
206 | |||
199 | #endif /* __NET_NFC_H */ | 207 | #endif /* __NET_NFC_H */ |
diff --git a/include/net/nfc/shdlc.h b/include/net/nfc/shdlc.h index ab06afd462d..35e930d2f63 100644 --- a/include/net/nfc/shdlc.h +++ b/include/net/nfc/shdlc.h | |||
@@ -27,7 +27,8 @@ struct nfc_shdlc_ops { | |||
27 | void (*close) (struct nfc_shdlc *shdlc); | 27 | void (*close) (struct nfc_shdlc *shdlc); |
28 | int (*hci_ready) (struct nfc_shdlc *shdlc); | 28 | int (*hci_ready) (struct nfc_shdlc *shdlc); |
29 | int (*xmit) (struct nfc_shdlc *shdlc, struct sk_buff *skb); | 29 | int (*xmit) (struct nfc_shdlc *shdlc, struct sk_buff *skb); |
30 | int (*start_poll) (struct nfc_shdlc *shdlc, u32 protocols); | 30 | int (*start_poll) (struct nfc_shdlc *shdlc, |
31 | u32 im_protocols, u32 tm_protocols); | ||
31 | int (*target_from_gate) (struct nfc_shdlc *shdlc, u8 gate, | 32 | int (*target_from_gate) (struct nfc_shdlc *shdlc, u8 gate, |
32 | struct nfc_target *target); | 33 | struct nfc_target *target); |
33 | int (*complete_target_discovered) (struct nfc_shdlc *shdlc, u8 gate, | 34 | int (*complete_target_discovered) (struct nfc_shdlc *shdlc, u8 gate, |
diff --git a/net/bluetooth/Makefile b/net/bluetooth/Makefile index 2dc5a5700f5..fa6d94a4602 100644 --- a/net/bluetooth/Makefile +++ b/net/bluetooth/Makefile | |||
@@ -9,4 +9,5 @@ obj-$(CONFIG_BT_CMTP) += cmtp/ | |||
9 | obj-$(CONFIG_BT_HIDP) += hidp/ | 9 | obj-$(CONFIG_BT_HIDP) += hidp/ |
10 | 10 | ||
11 | bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \ | 11 | bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \ |
12 | hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o sco.o lib.o | 12 | hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o sco.o lib.o \ |
13 | a2mp.o | ||
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c new file mode 100644 index 00000000000..fb93250b393 --- /dev/null +++ b/net/bluetooth/a2mp.c | |||
@@ -0,0 +1,568 @@ | |||
1 | /* | ||
2 | Copyright (c) 2010,2011 Code Aurora Forum. All rights reserved. | ||
3 | Copyright (c) 2011,2012 Intel Corp. | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License version 2 and | ||
7 | only version 2 as published by the Free Software Foundation. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | */ | ||
14 | |||
15 | #include <net/bluetooth/bluetooth.h> | ||
16 | #include <net/bluetooth/hci_core.h> | ||
17 | #include <net/bluetooth/l2cap.h> | ||
18 | #include <net/bluetooth/a2mp.h> | ||
19 | |||
20 | /* A2MP build & send command helper functions */ | ||
21 | static struct a2mp_cmd *__a2mp_build(u8 code, u8 ident, u16 len, void *data) | ||
22 | { | ||
23 | struct a2mp_cmd *cmd; | ||
24 | int plen; | ||
25 | |||
26 | plen = sizeof(*cmd) + len; | ||
27 | cmd = kzalloc(plen, GFP_KERNEL); | ||
28 | if (!cmd) | ||
29 | return NULL; | ||
30 | |||
31 | cmd->code = code; | ||
32 | cmd->ident = ident; | ||
33 | cmd->len = cpu_to_le16(len); | ||
34 | |||
35 | memcpy(cmd->data, data, len); | ||
36 | |||
37 | return cmd; | ||
38 | } | ||
39 | |||
40 | static void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, | ||
41 | void *data) | ||
42 | { | ||
43 | struct l2cap_chan *chan = mgr->a2mp_chan; | ||
44 | struct a2mp_cmd *cmd; | ||
45 | u16 total_len = len + sizeof(*cmd); | ||
46 | struct kvec iv; | ||
47 | struct msghdr msg; | ||
48 | |||
49 | cmd = __a2mp_build(code, ident, len, data); | ||
50 | if (!cmd) | ||
51 | return; | ||
52 | |||
53 | iv.iov_base = cmd; | ||
54 | iv.iov_len = total_len; | ||
55 | |||
56 | memset(&msg, 0, sizeof(msg)); | ||
57 | |||
58 | msg.msg_iov = (struct iovec *) &iv; | ||
59 | msg.msg_iovlen = 1; | ||
60 | |||
61 | l2cap_chan_send(chan, &msg, total_len, 0); | ||
62 | |||
63 | kfree(cmd); | ||
64 | } | ||
65 | |||
66 | static inline void __a2mp_cl_bredr(struct a2mp_cl *cl) | ||
67 | { | ||
68 | cl->id = 0; | ||
69 | cl->type = 0; | ||
70 | cl->status = 1; | ||
71 | } | ||
72 | |||
73 | /* hci_dev_list shall be locked */ | ||
74 | static void __a2mp_add_cl(struct amp_mgr *mgr, struct a2mp_cl *cl, u8 num_ctrl) | ||
75 | { | ||
76 | int i = 0; | ||
77 | struct hci_dev *hdev; | ||
78 | |||
79 | __a2mp_cl_bredr(cl); | ||
80 | |||
81 | list_for_each_entry(hdev, &hci_dev_list, list) { | ||
82 | /* Iterate through AMP controllers */ | ||
83 | if (hdev->id == HCI_BREDR_ID) | ||
84 | continue; | ||
85 | |||
86 | /* Starting from second entry */ | ||
87 | if (++i >= num_ctrl) | ||
88 | return; | ||
89 | |||
90 | cl[i].id = hdev->id; | ||
91 | cl[i].type = hdev->amp_type; | ||
92 | cl[i].status = hdev->amp_status; | ||
93 | } | ||
94 | } | ||
95 | |||
96 | /* Processing A2MP messages */ | ||
97 | static int a2mp_command_rej(struct amp_mgr *mgr, struct sk_buff *skb, | ||
98 | struct a2mp_cmd *hdr) | ||
99 | { | ||
100 | struct a2mp_cmd_rej *rej = (void *) skb->data; | ||
101 | |||
102 | if (le16_to_cpu(hdr->len) < sizeof(*rej)) | ||
103 | return -EINVAL; | ||
104 | |||
105 | BT_DBG("ident %d reason %d", hdr->ident, le16_to_cpu(rej->reason)); | ||
106 | |||
107 | skb_pull(skb, sizeof(*rej)); | ||
108 | |||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | static int a2mp_discover_req(struct amp_mgr *mgr, struct sk_buff *skb, | ||
113 | struct a2mp_cmd *hdr) | ||
114 | { | ||
115 | struct a2mp_discov_req *req = (void *) skb->data; | ||
116 | u16 len = le16_to_cpu(hdr->len); | ||
117 | struct a2mp_discov_rsp *rsp; | ||
118 | u16 ext_feat; | ||
119 | u8 num_ctrl; | ||
120 | |||
121 | if (len < sizeof(*req)) | ||
122 | return -EINVAL; | ||
123 | |||
124 | skb_pull(skb, sizeof(*req)); | ||
125 | |||
126 | ext_feat = le16_to_cpu(req->ext_feat); | ||
127 | |||
128 | BT_DBG("mtu %d efm 0x%4.4x", le16_to_cpu(req->mtu), ext_feat); | ||
129 | |||
130 | /* check that packet is not broken for now */ | ||
131 | while (ext_feat & A2MP_FEAT_EXT) { | ||
132 | if (len < sizeof(ext_feat)) | ||
133 | return -EINVAL; | ||
134 | |||
135 | ext_feat = get_unaligned_le16(skb->data); | ||
136 | BT_DBG("efm 0x%4.4x", ext_feat); | ||
137 | len -= sizeof(ext_feat); | ||
138 | skb_pull(skb, sizeof(ext_feat)); | ||
139 | } | ||
140 | |||
141 | read_lock(&hci_dev_list_lock); | ||
142 | |||
143 | num_ctrl = __hci_num_ctrl(); | ||
144 | len = num_ctrl * sizeof(struct a2mp_cl) + sizeof(*rsp); | ||
145 | rsp = kmalloc(len, GFP_ATOMIC); | ||
146 | if (!rsp) { | ||
147 | read_unlock(&hci_dev_list_lock); | ||
148 | return -ENOMEM; | ||
149 | } | ||
150 | |||
151 | rsp->mtu = __constant_cpu_to_le16(L2CAP_A2MP_DEFAULT_MTU); | ||
152 | rsp->ext_feat = 0; | ||
153 | |||
154 | __a2mp_add_cl(mgr, rsp->cl, num_ctrl); | ||
155 | |||
156 | read_unlock(&hci_dev_list_lock); | ||
157 | |||
158 | a2mp_send(mgr, A2MP_DISCOVER_RSP, hdr->ident, len, rsp); | ||
159 | |||
160 | kfree(rsp); | ||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | static int a2mp_change_notify(struct amp_mgr *mgr, struct sk_buff *skb, | ||
165 | struct a2mp_cmd *hdr) | ||
166 | { | ||
167 | struct a2mp_cl *cl = (void *) skb->data; | ||
168 | |||
169 | while (skb->len >= sizeof(*cl)) { | ||
170 | BT_DBG("Controller id %d type %d status %d", cl->id, cl->type, | ||
171 | cl->status); | ||
172 | cl = (struct a2mp_cl *) skb_pull(skb, sizeof(*cl)); | ||
173 | } | ||
174 | |||
175 | /* TODO send A2MP_CHANGE_RSP */ | ||
176 | |||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | static int a2mp_getinfo_req(struct amp_mgr *mgr, struct sk_buff *skb, | ||
181 | struct a2mp_cmd *hdr) | ||
182 | { | ||
183 | struct a2mp_info_req *req = (void *) skb->data; | ||
184 | struct a2mp_info_rsp rsp; | ||
185 | struct hci_dev *hdev; | ||
186 | |||
187 | if (le16_to_cpu(hdr->len) < sizeof(*req)) | ||
188 | return -EINVAL; | ||
189 | |||
190 | BT_DBG("id %d", req->id); | ||
191 | |||
192 | rsp.id = req->id; | ||
193 | rsp.status = A2MP_STATUS_INVALID_CTRL_ID; | ||
194 | |||
195 | hdev = hci_dev_get(req->id); | ||
196 | if (hdev && hdev->amp_type != HCI_BREDR) { | ||
197 | rsp.status = 0; | ||
198 | rsp.total_bw = cpu_to_le32(hdev->amp_total_bw); | ||
199 | rsp.max_bw = cpu_to_le32(hdev->amp_max_bw); | ||
200 | rsp.min_latency = cpu_to_le32(hdev->amp_min_latency); | ||
201 | rsp.pal_cap = cpu_to_le16(hdev->amp_pal_cap); | ||
202 | rsp.assoc_size = cpu_to_le16(hdev->amp_assoc_size); | ||
203 | } | ||
204 | |||
205 | if (hdev) | ||
206 | hci_dev_put(hdev); | ||
207 | |||
208 | a2mp_send(mgr, A2MP_GETINFO_RSP, hdr->ident, sizeof(rsp), &rsp); | ||
209 | |||
210 | skb_pull(skb, sizeof(*req)); | ||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | static int a2mp_getampassoc_req(struct amp_mgr *mgr, struct sk_buff *skb, | ||
215 | struct a2mp_cmd *hdr) | ||
216 | { | ||
217 | struct a2mp_amp_assoc_req *req = (void *) skb->data; | ||
218 | struct hci_dev *hdev; | ||
219 | |||
220 | if (le16_to_cpu(hdr->len) < sizeof(*req)) | ||
221 | return -EINVAL; | ||
222 | |||
223 | BT_DBG("id %d", req->id); | ||
224 | |||
225 | hdev = hci_dev_get(req->id); | ||
226 | if (!hdev || hdev->amp_type == HCI_BREDR) { | ||
227 | struct a2mp_amp_assoc_rsp rsp; | ||
228 | rsp.id = req->id; | ||
229 | rsp.status = A2MP_STATUS_INVALID_CTRL_ID; | ||
230 | |||
231 | a2mp_send(mgr, A2MP_GETAMPASSOC_RSP, hdr->ident, sizeof(rsp), | ||
232 | &rsp); | ||
233 | goto clean; | ||
234 | } | ||
235 | |||
236 | /* Placeholder for HCI Read AMP Assoc */ | ||
237 | |||
238 | clean: | ||
239 | if (hdev) | ||
240 | hci_dev_put(hdev); | ||
241 | |||
242 | skb_pull(skb, sizeof(*req)); | ||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb, | ||
247 | struct a2mp_cmd *hdr) | ||
248 | { | ||
249 | struct a2mp_physlink_req *req = (void *) skb->data; | ||
250 | |||
251 | struct a2mp_physlink_rsp rsp; | ||
252 | struct hci_dev *hdev; | ||
253 | |||
254 | if (le16_to_cpu(hdr->len) < sizeof(*req)) | ||
255 | return -EINVAL; | ||
256 | |||
257 | BT_DBG("local_id %d, remote_id %d", req->local_id, req->remote_id); | ||
258 | |||
259 | rsp.local_id = req->remote_id; | ||
260 | rsp.remote_id = req->local_id; | ||
261 | |||
262 | hdev = hci_dev_get(req->remote_id); | ||
263 | if (!hdev || hdev->amp_type != HCI_AMP) { | ||
264 | rsp.status = A2MP_STATUS_INVALID_CTRL_ID; | ||
265 | goto send_rsp; | ||
266 | } | ||
267 | |||
268 | /* TODO process physlink create */ | ||
269 | |||
270 | rsp.status = A2MP_STATUS_SUCCESS; | ||
271 | |||
272 | send_rsp: | ||
273 | if (hdev) | ||
274 | hci_dev_put(hdev); | ||
275 | |||
276 | a2mp_send(mgr, A2MP_CREATEPHYSLINK_RSP, hdr->ident, sizeof(rsp), | ||
277 | &rsp); | ||
278 | |||
279 | skb_pull(skb, le16_to_cpu(hdr->len)); | ||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | static int a2mp_discphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb, | ||
284 | struct a2mp_cmd *hdr) | ||
285 | { | ||
286 | struct a2mp_physlink_req *req = (void *) skb->data; | ||
287 | struct a2mp_physlink_rsp rsp; | ||
288 | struct hci_dev *hdev; | ||
289 | |||
290 | if (le16_to_cpu(hdr->len) < sizeof(*req)) | ||
291 | return -EINVAL; | ||
292 | |||
293 | BT_DBG("local_id %d remote_id %d", req->local_id, req->remote_id); | ||
294 | |||
295 | rsp.local_id = req->remote_id; | ||
296 | rsp.remote_id = req->local_id; | ||
297 | rsp.status = A2MP_STATUS_SUCCESS; | ||
298 | |||
299 | hdev = hci_dev_get(req->local_id); | ||
300 | if (!hdev) { | ||
301 | rsp.status = A2MP_STATUS_INVALID_CTRL_ID; | ||
302 | goto send_rsp; | ||
303 | } | ||
304 | |||
305 | /* TODO Disconnect Phys Link here */ | ||
306 | |||
307 | hci_dev_put(hdev); | ||
308 | |||
309 | send_rsp: | ||
310 | a2mp_send(mgr, A2MP_DISCONNPHYSLINK_RSP, hdr->ident, sizeof(rsp), &rsp); | ||
311 | |||
312 | skb_pull(skb, sizeof(*req)); | ||
313 | return 0; | ||
314 | } | ||
315 | |||
316 | static inline int a2mp_cmd_rsp(struct amp_mgr *mgr, struct sk_buff *skb, | ||
317 | struct a2mp_cmd *hdr) | ||
318 | { | ||
319 | BT_DBG("ident %d code %d", hdr->ident, hdr->code); | ||
320 | |||
321 | skb_pull(skb, le16_to_cpu(hdr->len)); | ||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | /* Handle A2MP signalling */ | ||
326 | static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) | ||
327 | { | ||
328 | struct a2mp_cmd *hdr = (void *) skb->data; | ||
329 | struct amp_mgr *mgr = chan->data; | ||
330 | int err = 0; | ||
331 | |||
332 | amp_mgr_get(mgr); | ||
333 | |||
334 | while (skb->len >= sizeof(*hdr)) { | ||
335 | struct a2mp_cmd *hdr = (void *) skb->data; | ||
336 | u16 len = le16_to_cpu(hdr->len); | ||
337 | |||
338 | BT_DBG("code 0x%02x id %d len %d", hdr->code, hdr->ident, len); | ||
339 | |||
340 | skb_pull(skb, sizeof(*hdr)); | ||
341 | |||
342 | if (len > skb->len || !hdr->ident) { | ||
343 | err = -EINVAL; | ||
344 | break; | ||
345 | } | ||
346 | |||
347 | mgr->ident = hdr->ident; | ||
348 | |||
349 | switch (hdr->code) { | ||
350 | case A2MP_COMMAND_REJ: | ||
351 | a2mp_command_rej(mgr, skb, hdr); | ||
352 | break; | ||
353 | |||
354 | case A2MP_DISCOVER_REQ: | ||
355 | err = a2mp_discover_req(mgr, skb, hdr); | ||
356 | break; | ||
357 | |||
358 | case A2MP_CHANGE_NOTIFY: | ||
359 | err = a2mp_change_notify(mgr, skb, hdr); | ||
360 | break; | ||
361 | |||
362 | case A2MP_GETINFO_REQ: | ||
363 | err = a2mp_getinfo_req(mgr, skb, hdr); | ||
364 | break; | ||
365 | |||
366 | case A2MP_GETAMPASSOC_REQ: | ||
367 | err = a2mp_getampassoc_req(mgr, skb, hdr); | ||
368 | break; | ||
369 | |||
370 | case A2MP_CREATEPHYSLINK_REQ: | ||
371 | err = a2mp_createphyslink_req(mgr, skb, hdr); | ||
372 | break; | ||
373 | |||
374 | case A2MP_DISCONNPHYSLINK_REQ: | ||
375 | err = a2mp_discphyslink_req(mgr, skb, hdr); | ||
376 | break; | ||
377 | |||
378 | case A2MP_CHANGE_RSP: | ||
379 | case A2MP_DISCOVER_RSP: | ||
380 | case A2MP_GETINFO_RSP: | ||
381 | case A2MP_GETAMPASSOC_RSP: | ||
382 | case A2MP_CREATEPHYSLINK_RSP: | ||
383 | case A2MP_DISCONNPHYSLINK_RSP: | ||
384 | err = a2mp_cmd_rsp(mgr, skb, hdr); | ||
385 | break; | ||
386 | |||
387 | default: | ||
388 | BT_ERR("Unknown A2MP sig cmd 0x%2.2x", hdr->code); | ||
389 | err = -EINVAL; | ||
390 | break; | ||
391 | } | ||
392 | } | ||
393 | |||
394 | if (err) { | ||
395 | struct a2mp_cmd_rej rej; | ||
396 | rej.reason = __constant_cpu_to_le16(0); | ||
397 | |||
398 | BT_DBG("Send A2MP Rej: cmd 0x%2.2x err %d", hdr->code, err); | ||
399 | |||
400 | a2mp_send(mgr, A2MP_COMMAND_REJ, hdr->ident, sizeof(rej), | ||
401 | &rej); | ||
402 | } | ||
403 | |||
404 | /* Always free skb and return success error code to prevent | ||
405 | from sending L2CAP Disconnect over A2MP channel */ | ||
406 | kfree_skb(skb); | ||
407 | |||
408 | amp_mgr_put(mgr); | ||
409 | |||
410 | return 0; | ||
411 | } | ||
412 | |||
413 | static void a2mp_chan_close_cb(struct l2cap_chan *chan) | ||
414 | { | ||
415 | l2cap_chan_destroy(chan); | ||
416 | } | ||
417 | |||
418 | static void a2mp_chan_state_change_cb(struct l2cap_chan *chan, int state) | ||
419 | { | ||
420 | struct amp_mgr *mgr = chan->data; | ||
421 | |||
422 | if (!mgr) | ||
423 | return; | ||
424 | |||
425 | BT_DBG("chan %p state %s", chan, state_to_string(state)); | ||
426 | |||
427 | chan->state = state; | ||
428 | |||
429 | switch (state) { | ||
430 | case BT_CLOSED: | ||
431 | if (mgr) | ||
432 | amp_mgr_put(mgr); | ||
433 | break; | ||
434 | } | ||
435 | } | ||
436 | |||
437 | static struct sk_buff *a2mp_chan_alloc_skb_cb(struct l2cap_chan *chan, | ||
438 | unsigned long len, int nb) | ||
439 | { | ||
440 | return bt_skb_alloc(len, GFP_KERNEL); | ||
441 | } | ||
442 | |||
443 | static struct l2cap_ops a2mp_chan_ops = { | ||
444 | .name = "L2CAP A2MP channel", | ||
445 | .recv = a2mp_chan_recv_cb, | ||
446 | .close = a2mp_chan_close_cb, | ||
447 | .state_change = a2mp_chan_state_change_cb, | ||
448 | .alloc_skb = a2mp_chan_alloc_skb_cb, | ||
449 | |||
450 | /* Not implemented for A2MP */ | ||
451 | .new_connection = l2cap_chan_no_new_connection, | ||
452 | .teardown = l2cap_chan_no_teardown, | ||
453 | .ready = l2cap_chan_no_ready, | ||
454 | }; | ||
455 | |||
456 | static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn) | ||
457 | { | ||
458 | struct l2cap_chan *chan; | ||
459 | int err; | ||
460 | |||
461 | chan = l2cap_chan_create(); | ||
462 | if (!chan) | ||
463 | return NULL; | ||
464 | |||
465 | BT_DBG("chan %p", chan); | ||
466 | |||
467 | chan->chan_type = L2CAP_CHAN_CONN_FIX_A2MP; | ||
468 | chan->flush_to = L2CAP_DEFAULT_FLUSH_TO; | ||
469 | |||
470 | chan->ops = &a2mp_chan_ops; | ||
471 | |||
472 | l2cap_chan_set_defaults(chan); | ||
473 | chan->remote_max_tx = chan->max_tx; | ||
474 | chan->remote_tx_win = chan->tx_win; | ||
475 | |||
476 | chan->retrans_timeout = L2CAP_DEFAULT_RETRANS_TO; | ||
477 | chan->monitor_timeout = L2CAP_DEFAULT_MONITOR_TO; | ||
478 | |||
479 | skb_queue_head_init(&chan->tx_q); | ||
480 | |||
481 | chan->mode = L2CAP_MODE_ERTM; | ||
482 | |||
483 | err = l2cap_ertm_init(chan); | ||
484 | if (err < 0) { | ||
485 | l2cap_chan_del(chan, 0); | ||
486 | return NULL; | ||
487 | } | ||
488 | |||
489 | chan->conf_state = 0; | ||
490 | |||
491 | l2cap_chan_add(conn, chan); | ||
492 | |||
493 | chan->remote_mps = chan->omtu; | ||
494 | chan->mps = chan->omtu; | ||
495 | |||
496 | chan->state = BT_CONNECTED; | ||
497 | |||
498 | return chan; | ||
499 | } | ||
500 | |||
501 | /* AMP Manager functions */ | ||
502 | void amp_mgr_get(struct amp_mgr *mgr) | ||
503 | { | ||
504 | BT_DBG("mgr %p", mgr); | ||
505 | |||
506 | kref_get(&mgr->kref); | ||
507 | } | ||
508 | |||
509 | static void amp_mgr_destroy(struct kref *kref) | ||
510 | { | ||
511 | struct amp_mgr *mgr = container_of(kref, struct amp_mgr, kref); | ||
512 | |||
513 | BT_DBG("mgr %p", mgr); | ||
514 | |||
515 | kfree(mgr); | ||
516 | } | ||
517 | |||
518 | int amp_mgr_put(struct amp_mgr *mgr) | ||
519 | { | ||
520 | BT_DBG("mgr %p", mgr); | ||
521 | |||
522 | return kref_put(&mgr->kref, &_mgr_destroy); | ||
523 | } | ||
524 | |||
525 | static struct amp_mgr *amp_mgr_create(struct l2cap_conn *conn) | ||
526 | { | ||
527 | struct amp_mgr *mgr; | ||
528 | struct l2cap_chan *chan; | ||
529 | |||
530 | mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); | ||
531 | if (!mgr) | ||
532 | return NULL; | ||
533 | |||
534 | BT_DBG("conn %p mgr %p", conn, mgr); | ||
535 | |||
536 | mgr->l2cap_conn = conn; | ||
537 | |||
538 | chan = a2mp_chan_open(conn); | ||
539 | if (!chan) { | ||
540 | kfree(mgr); | ||
541 | return NULL; | ||
542 | } | ||
543 | |||
544 | mgr->a2mp_chan = chan; | ||
545 | chan->data = mgr; | ||
546 | |||
547 | conn->hcon->amp_mgr = mgr; | ||
548 | |||
549 | kref_init(&mgr->kref); | ||
550 | |||
551 | return mgr; | ||
552 | } | ||
553 | |||
554 | struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn, | ||
555 | struct sk_buff *skb) | ||
556 | { | ||
557 | struct amp_mgr *mgr; | ||
558 | |||
559 | mgr = amp_mgr_create(conn); | ||
560 | if (!mgr) { | ||
561 | BT_ERR("Could not create AMP manager"); | ||
562 | return NULL; | ||
563 | } | ||
564 | |||
565 | BT_DBG("mgr: %p chan %p", mgr, mgr->a2mp_chan); | ||
566 | |||
567 | return mgr->a2mp_chan; | ||
568 | } | ||
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 3e18af4dadc..f7db5792ec6 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c | |||
@@ -25,18 +25,7 @@ | |||
25 | /* Bluetooth address family and sockets. */ | 25 | /* Bluetooth address family and sockets. */ |
26 | 26 | ||
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | |||
29 | #include <linux/types.h> | ||
30 | #include <linux/list.h> | ||
31 | #include <linux/errno.h> | ||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/sched.h> | ||
34 | #include <linux/skbuff.h> | ||
35 | #include <linux/init.h> | ||
36 | #include <linux/poll.h> | ||
37 | #include <net/sock.h> | ||
38 | #include <asm/ioctls.h> | 28 | #include <asm/ioctls.h> |
39 | #include <linux/kmod.h> | ||
40 | 29 | ||
41 | #include <net/bluetooth/bluetooth.h> | 30 | #include <net/bluetooth/bluetooth.h> |
42 | 31 | ||
@@ -418,7 +407,8 @@ static inline unsigned int bt_accept_poll(struct sock *parent) | |||
418 | return 0; | 407 | return 0; |
419 | } | 408 | } |
420 | 409 | ||
421 | unsigned int bt_sock_poll(struct file *file, struct socket *sock, poll_table *wait) | 410 | unsigned int bt_sock_poll(struct file *file, struct socket *sock, |
411 | poll_table *wait) | ||
422 | { | 412 | { |
423 | struct sock *sk = sock->sk; | 413 | struct sock *sk = sock->sk; |
424 | unsigned int mask = 0; | 414 | unsigned int mask = 0; |
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index 031d7d65675..4a6620bc157 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c | |||
@@ -26,26 +26,9 @@ | |||
26 | */ | 26 | */ |
27 | 27 | ||
28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
29 | |||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/sched.h> | ||
32 | #include <linux/signal.h> | ||
33 | #include <linux/init.h> | ||
34 | #include <linux/wait.h> | ||
35 | #include <linux/freezer.h> | ||
36 | #include <linux/errno.h> | ||
37 | #include <linux/net.h> | ||
38 | #include <linux/slab.h> | ||
39 | #include <linux/kthread.h> | 29 | #include <linux/kthread.h> |
40 | #include <net/sock.h> | ||
41 | |||
42 | #include <linux/socket.h> | ||
43 | #include <linux/file.h> | 30 | #include <linux/file.h> |
44 | |||
45 | #include <linux/netdevice.h> | ||
46 | #include <linux/etherdevice.h> | 31 | #include <linux/etherdevice.h> |
47 | #include <linux/skbuff.h> | ||
48 | |||
49 | #include <asm/unaligned.h> | 32 | #include <asm/unaligned.h> |
50 | 33 | ||
51 | #include <net/bluetooth/bluetooth.h> | 34 | #include <net/bluetooth/bluetooth.h> |
@@ -306,7 +289,7 @@ static u8 __bnep_rx_hlen[] = { | |||
306 | ETH_ALEN + 2 /* BNEP_COMPRESSED_DST_ONLY */ | 289 | ETH_ALEN + 2 /* BNEP_COMPRESSED_DST_ONLY */ |
307 | }; | 290 | }; |
308 | 291 | ||
309 | static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb) | 292 | static int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb) |
310 | { | 293 | { |
311 | struct net_device *dev = s->dev; | 294 | struct net_device *dev = s->dev; |
312 | struct sk_buff *nskb; | 295 | struct sk_buff *nskb; |
@@ -404,7 +387,7 @@ static u8 __bnep_tx_types[] = { | |||
404 | BNEP_COMPRESSED | 387 | BNEP_COMPRESSED |
405 | }; | 388 | }; |
406 | 389 | ||
407 | static inline int bnep_tx_frame(struct bnep_session *s, struct sk_buff *skb) | 390 | static int bnep_tx_frame(struct bnep_session *s, struct sk_buff *skb) |
408 | { | 391 | { |
409 | struct ethhdr *eh = (void *) skb->data; | 392 | struct ethhdr *eh = (void *) skb->data; |
410 | struct socket *sock = s->sock; | 393 | struct socket *sock = s->sock; |
diff --git a/net/bluetooth/bnep/netdev.c b/net/bluetooth/bnep/netdev.c index bc4086480d9..98f86f91d47 100644 --- a/net/bluetooth/bnep/netdev.c +++ b/net/bluetooth/bnep/netdev.c | |||
@@ -25,16 +25,8 @@ | |||
25 | SOFTWARE IS DISCLAIMED. | 25 | SOFTWARE IS DISCLAIMED. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | #include <linux/module.h> | 28 | #include <linux/export.h> |
29 | #include <linux/slab.h> | ||
30 | |||
31 | #include <linux/socket.h> | ||
32 | #include <linux/netdevice.h> | ||
33 | #include <linux/etherdevice.h> | 29 | #include <linux/etherdevice.h> |
34 | #include <linux/skbuff.h> | ||
35 | #include <linux/wait.h> | ||
36 | |||
37 | #include <asm/unaligned.h> | ||
38 | 30 | ||
39 | #include <net/bluetooth/bluetooth.h> | 31 | #include <net/bluetooth/bluetooth.h> |
40 | #include <net/bluetooth/hci_core.h> | 32 | #include <net/bluetooth/hci_core.h> |
@@ -128,7 +120,7 @@ static void bnep_net_timeout(struct net_device *dev) | |||
128 | } | 120 | } |
129 | 121 | ||
130 | #ifdef CONFIG_BT_BNEP_MC_FILTER | 122 | #ifdef CONFIG_BT_BNEP_MC_FILTER |
131 | static inline int bnep_net_mc_filter(struct sk_buff *skb, struct bnep_session *s) | 123 | static int bnep_net_mc_filter(struct sk_buff *skb, struct bnep_session *s) |
132 | { | 124 | { |
133 | struct ethhdr *eh = (void *) skb->data; | 125 | struct ethhdr *eh = (void *) skb->data; |
134 | 126 | ||
@@ -140,7 +132,7 @@ static inline int bnep_net_mc_filter(struct sk_buff *skb, struct bnep_session *s | |||
140 | 132 | ||
141 | #ifdef CONFIG_BT_BNEP_PROTO_FILTER | 133 | #ifdef CONFIG_BT_BNEP_PROTO_FILTER |
142 | /* Determine ether protocol. Based on eth_type_trans. */ | 134 | /* Determine ether protocol. Based on eth_type_trans. */ |
143 | static inline u16 bnep_net_eth_proto(struct sk_buff *skb) | 135 | static u16 bnep_net_eth_proto(struct sk_buff *skb) |
144 | { | 136 | { |
145 | struct ethhdr *eh = (void *) skb->data; | 137 | struct ethhdr *eh = (void *) skb->data; |
146 | u16 proto = ntohs(eh->h_proto); | 138 | u16 proto = ntohs(eh->h_proto); |
@@ -154,7 +146,7 @@ static inline u16 bnep_net_eth_proto(struct sk_buff *skb) | |||
154 | return ETH_P_802_2; | 146 | return ETH_P_802_2; |
155 | } | 147 | } |
156 | 148 | ||
157 | static inline int bnep_net_proto_filter(struct sk_buff *skb, struct bnep_session *s) | 149 | static int bnep_net_proto_filter(struct sk_buff *skb, struct bnep_session *s) |
158 | { | 150 | { |
159 | u16 proto = bnep_net_eth_proto(skb); | 151 | u16 proto = bnep_net_eth_proto(skb); |
160 | struct bnep_proto_filter *f = s->proto_filter; | 152 | struct bnep_proto_filter *f = s->proto_filter; |
diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c index 180bfc45810..5e5f5b410e0 100644 --- a/net/bluetooth/bnep/sock.c +++ b/net/bluetooth/bnep/sock.c | |||
@@ -24,24 +24,8 @@ | |||
24 | SOFTWARE IS DISCLAIMED. | 24 | SOFTWARE IS DISCLAIMED. |
25 | */ | 25 | */ |
26 | 26 | ||
27 | #include <linux/module.h> | 27 | #include <linux/export.h> |
28 | |||
29 | #include <linux/types.h> | ||
30 | #include <linux/capability.h> | ||
31 | #include <linux/errno.h> | ||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/poll.h> | ||
34 | #include <linux/fcntl.h> | ||
35 | #include <linux/skbuff.h> | ||
36 | #include <linux/socket.h> | ||
37 | #include <linux/ioctl.h> | ||
38 | #include <linux/file.h> | 28 | #include <linux/file.h> |
39 | #include <linux/init.h> | ||
40 | #include <linux/compat.h> | ||
41 | #include <linux/gfp.h> | ||
42 | #include <linux/uaccess.h> | ||
43 | #include <net/sock.h> | ||
44 | |||
45 | 29 | ||
46 | #include "bnep.h" | 30 | #include "bnep.h" |
47 | 31 | ||
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 3f18a6ed973..2fcced377e5 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -24,24 +24,11 @@ | |||
24 | 24 | ||
25 | /* Bluetooth HCI connection handling. */ | 25 | /* Bluetooth HCI connection handling. */ |
26 | 26 | ||
27 | #include <linux/module.h> | 27 | #include <linux/export.h> |
28 | |||
29 | #include <linux/types.h> | ||
30 | #include <linux/errno.h> | ||
31 | #include <linux/kernel.h> | ||
32 | #include <linux/slab.h> | ||
33 | #include <linux/poll.h> | ||
34 | #include <linux/fcntl.h> | ||
35 | #include <linux/init.h> | ||
36 | #include <linux/skbuff.h> | ||
37 | #include <linux/interrupt.h> | ||
38 | #include <net/sock.h> | ||
39 | |||
40 | #include <linux/uaccess.h> | ||
41 | #include <asm/unaligned.h> | ||
42 | 28 | ||
43 | #include <net/bluetooth/bluetooth.h> | 29 | #include <net/bluetooth/bluetooth.h> |
44 | #include <net/bluetooth/hci_core.h> | 30 | #include <net/bluetooth/hci_core.h> |
31 | #include <net/bluetooth/a2mp.h> | ||
45 | 32 | ||
46 | static void hci_le_connect(struct hci_conn *conn) | 33 | static void hci_le_connect(struct hci_conn *conn) |
47 | { | 34 | { |
@@ -54,15 +41,15 @@ static void hci_le_connect(struct hci_conn *conn) | |||
54 | conn->sec_level = BT_SECURITY_LOW; | 41 | conn->sec_level = BT_SECURITY_LOW; |
55 | 42 | ||
56 | memset(&cp, 0, sizeof(cp)); | 43 | memset(&cp, 0, sizeof(cp)); |
57 | cp.scan_interval = cpu_to_le16(0x0060); | 44 | cp.scan_interval = __constant_cpu_to_le16(0x0060); |
58 | cp.scan_window = cpu_to_le16(0x0030); | 45 | cp.scan_window = __constant_cpu_to_le16(0x0030); |
59 | bacpy(&cp.peer_addr, &conn->dst); | 46 | bacpy(&cp.peer_addr, &conn->dst); |
60 | cp.peer_addr_type = conn->dst_type; | 47 | cp.peer_addr_type = conn->dst_type; |
61 | cp.conn_interval_min = cpu_to_le16(0x0028); | 48 | cp.conn_interval_min = __constant_cpu_to_le16(0x0028); |
62 | cp.conn_interval_max = cpu_to_le16(0x0038); | 49 | cp.conn_interval_max = __constant_cpu_to_le16(0x0038); |
63 | cp.supervision_timeout = cpu_to_le16(0x002a); | 50 | cp.supervision_timeout = __constant_cpu_to_le16(0x002a); |
64 | cp.min_ce_len = cpu_to_le16(0x0000); | 51 | cp.min_ce_len = __constant_cpu_to_le16(0x0000); |
65 | cp.max_ce_len = cpu_to_le16(0x0000); | 52 | cp.max_ce_len = __constant_cpu_to_le16(0x0000); |
66 | 53 | ||
67 | hci_send_cmd(hdev, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp); | 54 | hci_send_cmd(hdev, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp); |
68 | } | 55 | } |
@@ -99,7 +86,7 @@ void hci_acl_connect(struct hci_conn *conn) | |||
99 | cp.pscan_rep_mode = ie->data.pscan_rep_mode; | 86 | cp.pscan_rep_mode = ie->data.pscan_rep_mode; |
100 | cp.pscan_mode = ie->data.pscan_mode; | 87 | cp.pscan_mode = ie->data.pscan_mode; |
101 | cp.clock_offset = ie->data.clock_offset | | 88 | cp.clock_offset = ie->data.clock_offset | |
102 | cpu_to_le16(0x8000); | 89 | __constant_cpu_to_le16(0x8000); |
103 | } | 90 | } |
104 | 91 | ||
105 | memcpy(conn->dev_class, ie->data.dev_class, 3); | 92 | memcpy(conn->dev_class, ie->data.dev_class, 3); |
@@ -175,9 +162,9 @@ void hci_setup_sync(struct hci_conn *conn, __u16 handle) | |||
175 | cp.handle = cpu_to_le16(handle); | 162 | cp.handle = cpu_to_le16(handle); |
176 | cp.pkt_type = cpu_to_le16(conn->pkt_type); | 163 | cp.pkt_type = cpu_to_le16(conn->pkt_type); |
177 | 164 | ||
178 | cp.tx_bandwidth = cpu_to_le32(0x00001f40); | 165 | cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40); |
179 | cp.rx_bandwidth = cpu_to_le32(0x00001f40); | 166 | cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40); |
180 | cp.max_latency = cpu_to_le16(0xffff); | 167 | cp.max_latency = __constant_cpu_to_le16(0xffff); |
181 | cp.voice_setting = cpu_to_le16(hdev->voice_setting); | 168 | cp.voice_setting = cpu_to_le16(hdev->voice_setting); |
182 | cp.retrans_effort = 0xff; | 169 | cp.retrans_effort = 0xff; |
183 | 170 | ||
@@ -185,7 +172,7 @@ void hci_setup_sync(struct hci_conn *conn, __u16 handle) | |||
185 | } | 172 | } |
186 | 173 | ||
187 | void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, | 174 | void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, |
188 | u16 latency, u16 to_multiplier) | 175 | u16 latency, u16 to_multiplier) |
189 | { | 176 | { |
190 | struct hci_cp_le_conn_update cp; | 177 | struct hci_cp_le_conn_update cp; |
191 | struct hci_dev *hdev = conn->hdev; | 178 | struct hci_dev *hdev = conn->hdev; |
@@ -197,15 +184,14 @@ void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, | |||
197 | cp.conn_interval_max = cpu_to_le16(max); | 184 | cp.conn_interval_max = cpu_to_le16(max); |
198 | cp.conn_latency = cpu_to_le16(latency); | 185 | cp.conn_latency = cpu_to_le16(latency); |
199 | cp.supervision_timeout = cpu_to_le16(to_multiplier); | 186 | cp.supervision_timeout = cpu_to_le16(to_multiplier); |
200 | cp.min_ce_len = cpu_to_le16(0x0001); | 187 | cp.min_ce_len = __constant_cpu_to_le16(0x0001); |
201 | cp.max_ce_len = cpu_to_le16(0x0001); | 188 | cp.max_ce_len = __constant_cpu_to_le16(0x0001); |
202 | 189 | ||
203 | hci_send_cmd(hdev, HCI_OP_LE_CONN_UPDATE, sizeof(cp), &cp); | 190 | hci_send_cmd(hdev, HCI_OP_LE_CONN_UPDATE, sizeof(cp), &cp); |
204 | } | 191 | } |
205 | EXPORT_SYMBOL(hci_le_conn_update); | ||
206 | 192 | ||
207 | void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8], | 193 | void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8], |
208 | __u8 ltk[16]) | 194 | __u8 ltk[16]) |
209 | { | 195 | { |
210 | struct hci_dev *hdev = conn->hdev; | 196 | struct hci_dev *hdev = conn->hdev; |
211 | struct hci_cp_le_start_enc cp; | 197 | struct hci_cp_le_start_enc cp; |
@@ -221,7 +207,6 @@ void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8], | |||
221 | 207 | ||
222 | hci_send_cmd(hdev, HCI_OP_LE_START_ENC, sizeof(cp), &cp); | 208 | hci_send_cmd(hdev, HCI_OP_LE_START_ENC, sizeof(cp), &cp); |
223 | } | 209 | } |
224 | EXPORT_SYMBOL(hci_le_start_enc); | ||
225 | 210 | ||
226 | /* Device _must_ be locked */ | 211 | /* Device _must_ be locked */ |
227 | void hci_sco_setup(struct hci_conn *conn, __u8 status) | 212 | void hci_sco_setup(struct hci_conn *conn, __u8 status) |
@@ -247,7 +232,7 @@ void hci_sco_setup(struct hci_conn *conn, __u8 status) | |||
247 | static void hci_conn_timeout(struct work_struct *work) | 232 | static void hci_conn_timeout(struct work_struct *work) |
248 | { | 233 | { |
249 | struct hci_conn *conn = container_of(work, struct hci_conn, | 234 | struct hci_conn *conn = container_of(work, struct hci_conn, |
250 | disc_work.work); | 235 | disc_work.work); |
251 | __u8 reason; | 236 | __u8 reason; |
252 | 237 | ||
253 | BT_DBG("conn %p state %s", conn, state_to_string(conn->state)); | 238 | BT_DBG("conn %p state %s", conn, state_to_string(conn->state)); |
@@ -295,9 +280,9 @@ static void hci_conn_enter_sniff_mode(struct hci_conn *conn) | |||
295 | if (lmp_sniffsubr_capable(hdev) && lmp_sniffsubr_capable(conn)) { | 280 | if (lmp_sniffsubr_capable(hdev) && lmp_sniffsubr_capable(conn)) { |
296 | struct hci_cp_sniff_subrate cp; | 281 | struct hci_cp_sniff_subrate cp; |
297 | cp.handle = cpu_to_le16(conn->handle); | 282 | cp.handle = cpu_to_le16(conn->handle); |
298 | cp.max_latency = cpu_to_le16(0); | 283 | cp.max_latency = __constant_cpu_to_le16(0); |
299 | cp.min_remote_timeout = cpu_to_le16(0); | 284 | cp.min_remote_timeout = __constant_cpu_to_le16(0); |
300 | cp.min_local_timeout = cpu_to_le16(0); | 285 | cp.min_local_timeout = __constant_cpu_to_le16(0); |
301 | hci_send_cmd(hdev, HCI_OP_SNIFF_SUBRATE, sizeof(cp), &cp); | 286 | hci_send_cmd(hdev, HCI_OP_SNIFF_SUBRATE, sizeof(cp), &cp); |
302 | } | 287 | } |
303 | 288 | ||
@@ -306,8 +291,8 @@ static void hci_conn_enter_sniff_mode(struct hci_conn *conn) | |||
306 | cp.handle = cpu_to_le16(conn->handle); | 291 | cp.handle = cpu_to_le16(conn->handle); |
307 | cp.max_interval = cpu_to_le16(hdev->sniff_max_interval); | 292 | cp.max_interval = cpu_to_le16(hdev->sniff_max_interval); |
308 | cp.min_interval = cpu_to_le16(hdev->sniff_min_interval); | 293 | cp.min_interval = cpu_to_le16(hdev->sniff_min_interval); |
309 | cp.attempt = cpu_to_le16(4); | 294 | cp.attempt = __constant_cpu_to_le16(4); |
310 | cp.timeout = cpu_to_le16(1); | 295 | cp.timeout = __constant_cpu_to_le16(1); |
311 | hci_send_cmd(hdev, HCI_OP_SNIFF_MODE, sizeof(cp), &cp); | 296 | hci_send_cmd(hdev, HCI_OP_SNIFF_MODE, sizeof(cp), &cp); |
312 | } | 297 | } |
313 | } | 298 | } |
@@ -327,7 +312,7 @@ static void hci_conn_auto_accept(unsigned long arg) | |||
327 | struct hci_dev *hdev = conn->hdev; | 312 | struct hci_dev *hdev = conn->hdev; |
328 | 313 | ||
329 | hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, sizeof(conn->dst), | 314 | hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, sizeof(conn->dst), |
330 | &conn->dst); | 315 | &conn->dst); |
331 | } | 316 | } |
332 | 317 | ||
333 | struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) | 318 | struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) |
@@ -376,7 +361,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) | |||
376 | INIT_DELAYED_WORK(&conn->disc_work, hci_conn_timeout); | 361 | INIT_DELAYED_WORK(&conn->disc_work, hci_conn_timeout); |
377 | setup_timer(&conn->idle_timer, hci_conn_idle, (unsigned long)conn); | 362 | setup_timer(&conn->idle_timer, hci_conn_idle, (unsigned long)conn); |
378 | setup_timer(&conn->auto_accept_timer, hci_conn_auto_accept, | 363 | setup_timer(&conn->auto_accept_timer, hci_conn_auto_accept, |
379 | (unsigned long) conn); | 364 | (unsigned long) conn); |
380 | 365 | ||
381 | atomic_set(&conn->refcnt, 0); | 366 | atomic_set(&conn->refcnt, 0); |
382 | 367 | ||
@@ -425,9 +410,11 @@ int hci_conn_del(struct hci_conn *conn) | |||
425 | } | 410 | } |
426 | } | 411 | } |
427 | 412 | ||
428 | |||
429 | hci_chan_list_flush(conn); | 413 | hci_chan_list_flush(conn); |
430 | 414 | ||
415 | if (conn->amp_mgr) | ||
416 | amp_mgr_put(conn->amp_mgr); | ||
417 | |||
431 | hci_conn_hash_del(hdev, conn); | 418 | hci_conn_hash_del(hdev, conn); |
432 | if (hdev->notify) | 419 | if (hdev->notify) |
433 | hdev->notify(hdev, HCI_NOTIFY_CONN_DEL); | 420 | hdev->notify(hdev, HCI_NOTIFY_CONN_DEL); |
@@ -454,7 +441,8 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src) | |||
454 | read_lock(&hci_dev_list_lock); | 441 | read_lock(&hci_dev_list_lock); |
455 | 442 | ||
456 | list_for_each_entry(d, &hci_dev_list, list) { | 443 | list_for_each_entry(d, &hci_dev_list, list) { |
457 | if (!test_bit(HCI_UP, &d->flags) || test_bit(HCI_RAW, &d->flags)) | 444 | if (!test_bit(HCI_UP, &d->flags) || |
445 | test_bit(HCI_RAW, &d->flags)) | ||
458 | continue; | 446 | continue; |
459 | 447 | ||
460 | /* Simple routing: | 448 | /* Simple routing: |
@@ -495,6 +483,11 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, | |||
495 | if (type == LE_LINK) { | 483 | if (type == LE_LINK) { |
496 | le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst); | 484 | le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst); |
497 | if (!le) { | 485 | if (!le) { |
486 | le = hci_conn_hash_lookup_state(hdev, LE_LINK, | ||
487 | BT_CONNECT); | ||
488 | if (le) | ||
489 | return ERR_PTR(-EBUSY); | ||
490 | |||
498 | le = hci_conn_add(hdev, LE_LINK, dst); | 491 | le = hci_conn_add(hdev, LE_LINK, dst); |
499 | if (!le) | 492 | if (!le) |
500 | return ERR_PTR(-ENOMEM); | 493 | return ERR_PTR(-ENOMEM); |
@@ -545,7 +538,7 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, | |||
545 | hci_conn_hold(sco); | 538 | hci_conn_hold(sco); |
546 | 539 | ||
547 | if (acl->state == BT_CONNECTED && | 540 | if (acl->state == BT_CONNECTED && |
548 | (sco->state == BT_OPEN || sco->state == BT_CLOSED)) { | 541 | (sco->state == BT_OPEN || sco->state == BT_CLOSED)) { |
549 | set_bit(HCI_CONN_POWER_SAVE, &acl->flags); | 542 | set_bit(HCI_CONN_POWER_SAVE, &acl->flags); |
550 | hci_conn_enter_active_mode(acl, BT_POWER_FORCE_ACTIVE_ON); | 543 | hci_conn_enter_active_mode(acl, BT_POWER_FORCE_ACTIVE_ON); |
551 | 544 | ||
@@ -560,7 +553,6 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, | |||
560 | 553 | ||
561 | return sco; | 554 | return sco; |
562 | } | 555 | } |
563 | EXPORT_SYMBOL(hci_connect); | ||
564 | 556 | ||
565 | /* Check link security requirement */ | 557 | /* Check link security requirement */ |
566 | int hci_conn_check_link_mode(struct hci_conn *conn) | 558 | int hci_conn_check_link_mode(struct hci_conn *conn) |
@@ -572,7 +564,6 @@ int hci_conn_check_link_mode(struct hci_conn *conn) | |||
572 | 564 | ||
573 | return 1; | 565 | return 1; |
574 | } | 566 | } |
575 | EXPORT_SYMBOL(hci_conn_check_link_mode); | ||
576 | 567 | ||
577 | /* Authenticate remote device */ | 568 | /* Authenticate remote device */ |
578 | static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) | 569 | static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) |
@@ -600,7 +591,7 @@ static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) | |||
600 | 591 | ||
601 | cp.handle = cpu_to_le16(conn->handle); | 592 | cp.handle = cpu_to_le16(conn->handle); |
602 | hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED, | 593 | hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED, |
603 | sizeof(cp), &cp); | 594 | sizeof(cp), &cp); |
604 | if (conn->key_type != 0xff) | 595 | if (conn->key_type != 0xff) |
605 | set_bit(HCI_CONN_REAUTH_PEND, &conn->flags); | 596 | set_bit(HCI_CONN_REAUTH_PEND, &conn->flags); |
606 | } | 597 | } |
@@ -618,7 +609,7 @@ static void hci_conn_encrypt(struct hci_conn *conn) | |||
618 | cp.handle = cpu_to_le16(conn->handle); | 609 | cp.handle = cpu_to_le16(conn->handle); |
619 | cp.encrypt = 0x01; | 610 | cp.encrypt = 0x01; |
620 | hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), | 611 | hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), |
621 | &cp); | 612 | &cp); |
622 | } | 613 | } |
623 | } | 614 | } |
624 | 615 | ||
@@ -648,8 +639,7 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) | |||
648 | /* An unauthenticated combination key has sufficient security for | 639 | /* An unauthenticated combination key has sufficient security for |
649 | security level 1 and 2. */ | 640 | security level 1 and 2. */ |
650 | if (conn->key_type == HCI_LK_UNAUTH_COMBINATION && | 641 | if (conn->key_type == HCI_LK_UNAUTH_COMBINATION && |
651 | (sec_level == BT_SECURITY_MEDIUM || | 642 | (sec_level == BT_SECURITY_MEDIUM || sec_level == BT_SECURITY_LOW)) |
652 | sec_level == BT_SECURITY_LOW)) | ||
653 | goto encrypt; | 643 | goto encrypt; |
654 | 644 | ||
655 | /* A combination key has always sufficient security for the security | 645 | /* A combination key has always sufficient security for the security |
@@ -657,8 +647,7 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) | |||
657 | is generated using maximum PIN code length (16). | 647 | is generated using maximum PIN code length (16). |
658 | For pre 2.1 units. */ | 648 | For pre 2.1 units. */ |
659 | if (conn->key_type == HCI_LK_COMBINATION && | 649 | if (conn->key_type == HCI_LK_COMBINATION && |
660 | (sec_level != BT_SECURITY_HIGH || | 650 | (sec_level != BT_SECURITY_HIGH || conn->pin_length == 16)) |
661 | conn->pin_length == 16)) | ||
662 | goto encrypt; | 651 | goto encrypt; |
663 | 652 | ||
664 | auth: | 653 | auth: |
@@ -701,12 +690,11 @@ int hci_conn_change_link_key(struct hci_conn *conn) | |||
701 | struct hci_cp_change_conn_link_key cp; | 690 | struct hci_cp_change_conn_link_key cp; |
702 | cp.handle = cpu_to_le16(conn->handle); | 691 | cp.handle = cpu_to_le16(conn->handle); |
703 | hci_send_cmd(conn->hdev, HCI_OP_CHANGE_CONN_LINK_KEY, | 692 | hci_send_cmd(conn->hdev, HCI_OP_CHANGE_CONN_LINK_KEY, |
704 | sizeof(cp), &cp); | 693 | sizeof(cp), &cp); |
705 | } | 694 | } |
706 | 695 | ||
707 | return 0; | 696 | return 0; |
708 | } | 697 | } |
709 | EXPORT_SYMBOL(hci_conn_change_link_key); | ||
710 | 698 | ||
711 | /* Switch role */ | 699 | /* Switch role */ |
712 | int hci_conn_switch_role(struct hci_conn *conn, __u8 role) | 700 | int hci_conn_switch_role(struct hci_conn *conn, __u8 role) |
@@ -752,7 +740,7 @@ void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active) | |||
752 | timer: | 740 | timer: |
753 | if (hdev->idle_timeout > 0) | 741 | if (hdev->idle_timeout > 0) |
754 | mod_timer(&conn->idle_timer, | 742 | mod_timer(&conn->idle_timer, |
755 | jiffies + msecs_to_jiffies(hdev->idle_timeout)); | 743 | jiffies + msecs_to_jiffies(hdev->idle_timeout)); |
756 | } | 744 | } |
757 | 745 | ||
758 | /* Drop all connection on the device */ | 746 | /* Drop all connection on the device */ |
@@ -802,7 +790,7 @@ EXPORT_SYMBOL(hci_conn_put_device); | |||
802 | 790 | ||
803 | int hci_get_conn_list(void __user *arg) | 791 | int hci_get_conn_list(void __user *arg) |
804 | { | 792 | { |
805 | register struct hci_conn *c; | 793 | struct hci_conn *c; |
806 | struct hci_conn_list_req req, *cl; | 794 | struct hci_conn_list_req req, *cl; |
807 | struct hci_conn_info *ci; | 795 | struct hci_conn_info *ci; |
808 | struct hci_dev *hdev; | 796 | struct hci_dev *hdev; |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 411ace8e647..08994ecc3b6 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -25,28 +25,10 @@ | |||
25 | 25 | ||
26 | /* Bluetooth HCI core. */ | 26 | /* Bluetooth HCI core. */ |
27 | 27 | ||
28 | #include <linux/jiffies.h> | 28 | #include <linux/export.h> |
29 | #include <linux/module.h> | 29 | #include <linux/idr.h> |
30 | #include <linux/kmod.h> | ||
31 | |||
32 | #include <linux/types.h> | ||
33 | #include <linux/errno.h> | ||
34 | #include <linux/kernel.h> | ||
35 | #include <linux/sched.h> | ||
36 | #include <linux/slab.h> | ||
37 | #include <linux/poll.h> | ||
38 | #include <linux/fcntl.h> | ||
39 | #include <linux/init.h> | ||
40 | #include <linux/skbuff.h> | ||
41 | #include <linux/workqueue.h> | ||
42 | #include <linux/interrupt.h> | ||
43 | #include <linux/rfkill.h> | ||
44 | #include <linux/timer.h> | ||
45 | #include <linux/crypto.h> | ||
46 | #include <net/sock.h> | ||
47 | 30 | ||
48 | #include <linux/uaccess.h> | 31 | #include <linux/rfkill.h> |
49 | #include <asm/unaligned.h> | ||
50 | 32 | ||
51 | #include <net/bluetooth/bluetooth.h> | 33 | #include <net/bluetooth/bluetooth.h> |
52 | #include <net/bluetooth/hci_core.h> | 34 | #include <net/bluetooth/hci_core.h> |
@@ -65,6 +47,9 @@ DEFINE_RWLOCK(hci_dev_list_lock); | |||
65 | LIST_HEAD(hci_cb_list); | 47 | LIST_HEAD(hci_cb_list); |
66 | DEFINE_RWLOCK(hci_cb_list_lock); | 48 | DEFINE_RWLOCK(hci_cb_list_lock); |
67 | 49 | ||
50 | /* HCI ID Numbering */ | ||
51 | static DEFINE_IDA(hci_index_ida); | ||
52 | |||
68 | /* ---- HCI notifications ---- */ | 53 | /* ---- HCI notifications ---- */ |
69 | 54 | ||
70 | static void hci_notify(struct hci_dev *hdev, int event) | 55 | static void hci_notify(struct hci_dev *hdev, int event) |
@@ -124,8 +109,9 @@ static void hci_req_cancel(struct hci_dev *hdev, int err) | |||
124 | } | 109 | } |
125 | 110 | ||
126 | /* Execute request and wait for completion. */ | 111 | /* Execute request and wait for completion. */ |
127 | static int __hci_request(struct hci_dev *hdev, void (*req)(struct hci_dev *hdev, unsigned long opt), | 112 | static int __hci_request(struct hci_dev *hdev, |
128 | unsigned long opt, __u32 timeout) | 113 | void (*req)(struct hci_dev *hdev, unsigned long opt), |
114 | unsigned long opt, __u32 timeout) | ||
129 | { | 115 | { |
130 | DECLARE_WAITQUEUE(wait, current); | 116 | DECLARE_WAITQUEUE(wait, current); |
131 | int err = 0; | 117 | int err = 0; |
@@ -166,8 +152,9 @@ static int __hci_request(struct hci_dev *hdev, void (*req)(struct hci_dev *hdev, | |||
166 | return err; | 152 | return err; |
167 | } | 153 | } |
168 | 154 | ||
169 | static inline int hci_request(struct hci_dev *hdev, void (*req)(struct hci_dev *hdev, unsigned long opt), | 155 | static int hci_request(struct hci_dev *hdev, |
170 | unsigned long opt, __u32 timeout) | 156 | void (*req)(struct hci_dev *hdev, unsigned long opt), |
157 | unsigned long opt, __u32 timeout) | ||
171 | { | 158 | { |
172 | int ret; | 159 | int ret; |
173 | 160 | ||
@@ -202,7 +189,7 @@ static void bredr_init(struct hci_dev *hdev) | |||
202 | /* Mandatory initialization */ | 189 | /* Mandatory initialization */ |
203 | 190 | ||
204 | /* Reset */ | 191 | /* Reset */ |
205 | if (!test_bit(HCI_QUIRK_NO_RESET, &hdev->quirks)) { | 192 | if (!test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks)) { |
206 | set_bit(HCI_RESET, &hdev->flags); | 193 | set_bit(HCI_RESET, &hdev->flags); |
207 | hci_send_cmd(hdev, HCI_OP_RESET, 0, NULL); | 194 | hci_send_cmd(hdev, HCI_OP_RESET, 0, NULL); |
208 | } | 195 | } |
@@ -235,7 +222,7 @@ static void bredr_init(struct hci_dev *hdev) | |||
235 | hci_send_cmd(hdev, HCI_OP_SET_EVENT_FLT, 1, &flt_type); | 222 | hci_send_cmd(hdev, HCI_OP_SET_EVENT_FLT, 1, &flt_type); |
236 | 223 | ||
237 | /* Connection accept timeout ~20 secs */ | 224 | /* Connection accept timeout ~20 secs */ |
238 | param = cpu_to_le16(0x7d00); | 225 | param = __constant_cpu_to_le16(0x7d00); |
239 | hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, ¶m); | 226 | hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, ¶m); |
240 | 227 | ||
241 | bacpy(&cp.bdaddr, BDADDR_ANY); | 228 | bacpy(&cp.bdaddr, BDADDR_ANY); |
@@ -417,7 +404,8 @@ static void inquiry_cache_flush(struct hci_dev *hdev) | |||
417 | INIT_LIST_HEAD(&cache->resolve); | 404 | INIT_LIST_HEAD(&cache->resolve); |
418 | } | 405 | } |
419 | 406 | ||
420 | struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr) | 407 | struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev, |
408 | bdaddr_t *bdaddr) | ||
421 | { | 409 | { |
422 | struct discovery_state *cache = &hdev->discovery; | 410 | struct discovery_state *cache = &hdev->discovery; |
423 | struct inquiry_entry *e; | 411 | struct inquiry_entry *e; |
@@ -478,7 +466,7 @@ void hci_inquiry_cache_update_resolve(struct hci_dev *hdev, | |||
478 | 466 | ||
479 | list_for_each_entry(p, &cache->resolve, list) { | 467 | list_for_each_entry(p, &cache->resolve, list) { |
480 | if (p->name_state != NAME_PENDING && | 468 | if (p->name_state != NAME_PENDING && |
481 | abs(p->data.rssi) >= abs(ie->data.rssi)) | 469 | abs(p->data.rssi) >= abs(ie->data.rssi)) |
482 | break; | 470 | break; |
483 | pos = &p->list; | 471 | pos = &p->list; |
484 | } | 472 | } |
@@ -503,7 +491,7 @@ bool hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data, | |||
503 | *ssp = true; | 491 | *ssp = true; |
504 | 492 | ||
505 | if (ie->name_state == NAME_NEEDED && | 493 | if (ie->name_state == NAME_NEEDED && |
506 | data->rssi != ie->data.rssi) { | 494 | data->rssi != ie->data.rssi) { |
507 | ie->data.rssi = data->rssi; | 495 | ie->data.rssi = data->rssi; |
508 | hci_inquiry_cache_update_resolve(hdev, ie); | 496 | hci_inquiry_cache_update_resolve(hdev, ie); |
509 | } | 497 | } |
@@ -527,7 +515,7 @@ bool hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data, | |||
527 | 515 | ||
528 | update: | 516 | update: |
529 | if (name_known && ie->name_state != NAME_KNOWN && | 517 | if (name_known && ie->name_state != NAME_KNOWN && |
530 | ie->name_state != NAME_PENDING) { | 518 | ie->name_state != NAME_PENDING) { |
531 | ie->name_state = NAME_KNOWN; | 519 | ie->name_state = NAME_KNOWN; |
532 | list_del(&ie->list); | 520 | list_del(&ie->list); |
533 | } | 521 | } |
@@ -605,8 +593,7 @@ int hci_inquiry(void __user *arg) | |||
605 | 593 | ||
606 | hci_dev_lock(hdev); | 594 | hci_dev_lock(hdev); |
607 | if (inquiry_cache_age(hdev) > INQUIRY_CACHE_AGE_MAX || | 595 | if (inquiry_cache_age(hdev) > INQUIRY_CACHE_AGE_MAX || |
608 | inquiry_cache_empty(hdev) || | 596 | inquiry_cache_empty(hdev) || ir.flags & IREQ_CACHE_FLUSH) { |
609 | ir.flags & IREQ_CACHE_FLUSH) { | ||
610 | inquiry_cache_flush(hdev); | 597 | inquiry_cache_flush(hdev); |
611 | do_inquiry = 1; | 598 | do_inquiry = 1; |
612 | } | 599 | } |
@@ -620,7 +607,9 @@ int hci_inquiry(void __user *arg) | |||
620 | goto done; | 607 | goto done; |
621 | } | 608 | } |
622 | 609 | ||
623 | /* for unlimited number of responses we will use buffer with 255 entries */ | 610 | /* for unlimited number of responses we will use buffer with |
611 | * 255 entries | ||
612 | */ | ||
624 | max_rsp = (ir.num_rsp == 0) ? 255 : ir.num_rsp; | 613 | max_rsp = (ir.num_rsp == 0) ? 255 : ir.num_rsp; |
625 | 614 | ||
626 | /* cache_dump can't sleep. Therefore we allocate temp buffer and then | 615 | /* cache_dump can't sleep. Therefore we allocate temp buffer and then |
@@ -641,7 +630,7 @@ int hci_inquiry(void __user *arg) | |||
641 | if (!copy_to_user(ptr, &ir, sizeof(ir))) { | 630 | if (!copy_to_user(ptr, &ir, sizeof(ir))) { |
642 | ptr += sizeof(ir); | 631 | ptr += sizeof(ir); |
643 | if (copy_to_user(ptr, buf, sizeof(struct inquiry_info) * | 632 | if (copy_to_user(ptr, buf, sizeof(struct inquiry_info) * |
644 | ir.num_rsp)) | 633 | ir.num_rsp)) |
645 | err = -EFAULT; | 634 | err = -EFAULT; |
646 | } else | 635 | } else |
647 | err = -EFAULT; | 636 | err = -EFAULT; |
@@ -702,11 +691,11 @@ int hci_dev_open(__u16 dev) | |||
702 | hdev->init_last_cmd = 0; | 691 | hdev->init_last_cmd = 0; |
703 | 692 | ||
704 | ret = __hci_request(hdev, hci_init_req, 0, | 693 | ret = __hci_request(hdev, hci_init_req, 0, |
705 | msecs_to_jiffies(HCI_INIT_TIMEOUT)); | 694 | msecs_to_jiffies(HCI_INIT_TIMEOUT)); |
706 | 695 | ||
707 | if (lmp_host_le_capable(hdev)) | 696 | if (lmp_host_le_capable(hdev)) |
708 | ret = __hci_request(hdev, hci_le_init_req, 0, | 697 | ret = __hci_request(hdev, hci_le_init_req, 0, |
709 | msecs_to_jiffies(HCI_INIT_TIMEOUT)); | 698 | msecs_to_jiffies(HCI_INIT_TIMEOUT)); |
710 | 699 | ||
711 | clear_bit(HCI_INIT, &hdev->flags); | 700 | clear_bit(HCI_INIT, &hdev->flags); |
712 | } | 701 | } |
@@ -791,10 +780,10 @@ static int hci_dev_do_close(struct hci_dev *hdev) | |||
791 | skb_queue_purge(&hdev->cmd_q); | 780 | skb_queue_purge(&hdev->cmd_q); |
792 | atomic_set(&hdev->cmd_cnt, 1); | 781 | atomic_set(&hdev->cmd_cnt, 1); |
793 | if (!test_bit(HCI_RAW, &hdev->flags) && | 782 | if (!test_bit(HCI_RAW, &hdev->flags) && |
794 | test_bit(HCI_QUIRK_NO_RESET, &hdev->quirks)) { | 783 | test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks)) { |
795 | set_bit(HCI_INIT, &hdev->flags); | 784 | set_bit(HCI_INIT, &hdev->flags); |
796 | __hci_request(hdev, hci_reset_req, 0, | 785 | __hci_request(hdev, hci_reset_req, 0, |
797 | msecs_to_jiffies(250)); | 786 | msecs_to_jiffies(250)); |
798 | clear_bit(HCI_INIT, &hdev->flags); | 787 | clear_bit(HCI_INIT, &hdev->flags); |
799 | } | 788 | } |
800 | 789 | ||
@@ -884,7 +873,7 @@ int hci_dev_reset(__u16 dev) | |||
884 | 873 | ||
885 | if (!test_bit(HCI_RAW, &hdev->flags)) | 874 | if (!test_bit(HCI_RAW, &hdev->flags)) |
886 | ret = __hci_request(hdev, hci_reset_req, 0, | 875 | ret = __hci_request(hdev, hci_reset_req, 0, |
887 | msecs_to_jiffies(HCI_INIT_TIMEOUT)); | 876 | msecs_to_jiffies(HCI_INIT_TIMEOUT)); |
888 | 877 | ||
889 | done: | 878 | done: |
890 | hci_req_unlock(hdev); | 879 | hci_req_unlock(hdev); |
@@ -924,7 +913,7 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg) | |||
924 | switch (cmd) { | 913 | switch (cmd) { |
925 | case HCISETAUTH: | 914 | case HCISETAUTH: |
926 | err = hci_request(hdev, hci_auth_req, dr.dev_opt, | 915 | err = hci_request(hdev, hci_auth_req, dr.dev_opt, |
927 | msecs_to_jiffies(HCI_INIT_TIMEOUT)); | 916 | msecs_to_jiffies(HCI_INIT_TIMEOUT)); |
928 | break; | 917 | break; |
929 | 918 | ||
930 | case HCISETENCRYPT: | 919 | case HCISETENCRYPT: |
@@ -936,23 +925,23 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg) | |||
936 | if (!test_bit(HCI_AUTH, &hdev->flags)) { | 925 | if (!test_bit(HCI_AUTH, &hdev->flags)) { |
937 | /* Auth must be enabled first */ | 926 | /* Auth must be enabled first */ |
938 | err = hci_request(hdev, hci_auth_req, dr.dev_opt, | 927 | err = hci_request(hdev, hci_auth_req, dr.dev_opt, |
939 | msecs_to_jiffies(HCI_INIT_TIMEOUT)); | 928 | msecs_to_jiffies(HCI_INIT_TIMEOUT)); |
940 | if (err) | 929 | if (err) |
941 | break; | 930 | break; |
942 | } | 931 | } |
943 | 932 | ||
944 | err = hci_request(hdev, hci_encrypt_req, dr.dev_opt, | 933 | err = hci_request(hdev, hci_encrypt_req, dr.dev_opt, |
945 | msecs_to_jiffies(HCI_INIT_TIMEOUT)); | 934 | msecs_to_jiffies(HCI_INIT_TIMEOUT)); |
946 | break; | 935 | break; |
947 | 936 | ||
948 | case HCISETSCAN: | 937 | case HCISETSCAN: |
949 | err = hci_request(hdev, hci_scan_req, dr.dev_opt, | 938 | err = hci_request(hdev, hci_scan_req, dr.dev_opt, |
950 | msecs_to_jiffies(HCI_INIT_TIMEOUT)); | 939 | msecs_to_jiffies(HCI_INIT_TIMEOUT)); |
951 | break; | 940 | break; |
952 | 941 | ||
953 | case HCISETLINKPOL: | 942 | case HCISETLINKPOL: |
954 | err = hci_request(hdev, hci_linkpol_req, dr.dev_opt, | 943 | err = hci_request(hdev, hci_linkpol_req, dr.dev_opt, |
955 | msecs_to_jiffies(HCI_INIT_TIMEOUT)); | 944 | msecs_to_jiffies(HCI_INIT_TIMEOUT)); |
956 | break; | 945 | break; |
957 | 946 | ||
958 | case HCISETLINKMODE: | 947 | case HCISETLINKMODE: |
@@ -1103,7 +1092,7 @@ static void hci_power_on(struct work_struct *work) | |||
1103 | 1092 | ||
1104 | if (test_bit(HCI_AUTO_OFF, &hdev->dev_flags)) | 1093 | if (test_bit(HCI_AUTO_OFF, &hdev->dev_flags)) |
1105 | schedule_delayed_work(&hdev->power_off, | 1094 | schedule_delayed_work(&hdev->power_off, |
1106 | msecs_to_jiffies(AUTO_OFF_TIMEOUT)); | 1095 | msecs_to_jiffies(AUTO_OFF_TIMEOUT)); |
1107 | 1096 | ||
1108 | if (test_and_clear_bit(HCI_SETUP, &hdev->dev_flags)) | 1097 | if (test_and_clear_bit(HCI_SETUP, &hdev->dev_flags)) |
1109 | mgmt_index_added(hdev); | 1098 | mgmt_index_added(hdev); |
@@ -1112,7 +1101,7 @@ static void hci_power_on(struct work_struct *work) | |||
1112 | static void hci_power_off(struct work_struct *work) | 1101 | static void hci_power_off(struct work_struct *work) |
1113 | { | 1102 | { |
1114 | struct hci_dev *hdev = container_of(work, struct hci_dev, | 1103 | struct hci_dev *hdev = container_of(work, struct hci_dev, |
1115 | power_off.work); | 1104 | power_off.work); |
1116 | 1105 | ||
1117 | BT_DBG("%s", hdev->name); | 1106 | BT_DBG("%s", hdev->name); |
1118 | 1107 | ||
@@ -1193,7 +1182,7 @@ struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr) | |||
1193 | } | 1182 | } |
1194 | 1183 | ||
1195 | static bool hci_persistent_key(struct hci_dev *hdev, struct hci_conn *conn, | 1184 | static bool hci_persistent_key(struct hci_dev *hdev, struct hci_conn *conn, |
1196 | u8 key_type, u8 old_key_type) | 1185 | u8 key_type, u8 old_key_type) |
1197 | { | 1186 | { |
1198 | /* Legacy key */ | 1187 | /* Legacy key */ |
1199 | if (key_type < 0x03) | 1188 | if (key_type < 0x03) |
@@ -1234,7 +1223,7 @@ struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8]) | |||
1234 | 1223 | ||
1235 | list_for_each_entry(k, &hdev->long_term_keys, list) { | 1224 | list_for_each_entry(k, &hdev->long_term_keys, list) { |
1236 | if (k->ediv != ediv || | 1225 | if (k->ediv != ediv || |
1237 | memcmp(rand, k->rand, sizeof(k->rand))) | 1226 | memcmp(rand, k->rand, sizeof(k->rand))) |
1238 | continue; | 1227 | continue; |
1239 | 1228 | ||
1240 | return k; | 1229 | return k; |
@@ -1242,7 +1231,6 @@ struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8]) | |||
1242 | 1231 | ||
1243 | return NULL; | 1232 | return NULL; |
1244 | } | 1233 | } |
1245 | EXPORT_SYMBOL(hci_find_ltk); | ||
1246 | 1234 | ||
1247 | struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr, | 1235 | struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr, |
1248 | u8 addr_type) | 1236 | u8 addr_type) |
@@ -1251,12 +1239,11 @@ struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr, | |||
1251 | 1239 | ||
1252 | list_for_each_entry(k, &hdev->long_term_keys, list) | 1240 | list_for_each_entry(k, &hdev->long_term_keys, list) |
1253 | if (addr_type == k->bdaddr_type && | 1241 | if (addr_type == k->bdaddr_type && |
1254 | bacmp(bdaddr, &k->bdaddr) == 0) | 1242 | bacmp(bdaddr, &k->bdaddr) == 0) |
1255 | return k; | 1243 | return k; |
1256 | 1244 | ||
1257 | return NULL; | 1245 | return NULL; |
1258 | } | 1246 | } |
1259 | EXPORT_SYMBOL(hci_find_ltk_by_addr); | ||
1260 | 1247 | ||
1261 | int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, | 1248 | int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, |
1262 | bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len) | 1249 | bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len) |
@@ -1283,15 +1270,14 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, | |||
1283 | * combination key for legacy pairing even when there's no | 1270 | * combination key for legacy pairing even when there's no |
1284 | * previous key */ | 1271 | * previous key */ |
1285 | if (type == HCI_LK_CHANGED_COMBINATION && | 1272 | if (type == HCI_LK_CHANGED_COMBINATION && |
1286 | (!conn || conn->remote_auth == 0xff) && | 1273 | (!conn || conn->remote_auth == 0xff) && old_key_type == 0xff) { |
1287 | old_key_type == 0xff) { | ||
1288 | type = HCI_LK_COMBINATION; | 1274 | type = HCI_LK_COMBINATION; |
1289 | if (conn) | 1275 | if (conn) |
1290 | conn->key_type = type; | 1276 | conn->key_type = type; |
1291 | } | 1277 | } |
1292 | 1278 | ||
1293 | bacpy(&key->bdaddr, bdaddr); | 1279 | bacpy(&key->bdaddr, bdaddr); |
1294 | memcpy(key->val, val, 16); | 1280 | memcpy(key->val, val, HCI_LINK_KEY_SIZE); |
1295 | key->pin_len = pin_len; | 1281 | key->pin_len = pin_len; |
1296 | 1282 | ||
1297 | if (type == HCI_LK_CHANGED_COMBINATION) | 1283 | if (type == HCI_LK_CHANGED_COMBINATION) |
@@ -1540,6 +1526,7 @@ static void le_scan_enable_req(struct hci_dev *hdev, unsigned long opt) | |||
1540 | 1526 | ||
1541 | memset(&cp, 0, sizeof(cp)); | 1527 | memset(&cp, 0, sizeof(cp)); |
1542 | cp.enable = 1; | 1528 | cp.enable = 1; |
1529 | cp.filter_dup = 1; | ||
1543 | 1530 | ||
1544 | hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp); | 1531 | hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp); |
1545 | } | 1532 | } |
@@ -1707,41 +1694,39 @@ EXPORT_SYMBOL(hci_free_dev); | |||
1707 | /* Register HCI device */ | 1694 | /* Register HCI device */ |
1708 | int hci_register_dev(struct hci_dev *hdev) | 1695 | int hci_register_dev(struct hci_dev *hdev) |
1709 | { | 1696 | { |
1710 | struct list_head *head, *p; | ||
1711 | int id, error; | 1697 | int id, error; |
1712 | 1698 | ||
1713 | if (!hdev->open || !hdev->close) | 1699 | if (!hdev->open || !hdev->close) |
1714 | return -EINVAL; | 1700 | return -EINVAL; |
1715 | 1701 | ||
1716 | write_lock(&hci_dev_list_lock); | ||
1717 | |||
1718 | /* Do not allow HCI_AMP devices to register at index 0, | 1702 | /* Do not allow HCI_AMP devices to register at index 0, |
1719 | * so the index can be used as the AMP controller ID. | 1703 | * so the index can be used as the AMP controller ID. |
1720 | */ | 1704 | */ |
1721 | id = (hdev->dev_type == HCI_BREDR) ? 0 : 1; | 1705 | switch (hdev->dev_type) { |
1722 | head = &hci_dev_list; | 1706 | case HCI_BREDR: |
1723 | 1707 | id = ida_simple_get(&hci_index_ida, 0, 0, GFP_KERNEL); | |
1724 | /* Find first available device id */ | 1708 | break; |
1725 | list_for_each(p, &hci_dev_list) { | 1709 | case HCI_AMP: |
1726 | int nid = list_entry(p, struct hci_dev, list)->id; | 1710 | id = ida_simple_get(&hci_index_ida, 1, 0, GFP_KERNEL); |
1727 | if (nid > id) | 1711 | break; |
1728 | break; | 1712 | default: |
1729 | if (nid == id) | 1713 | return -EINVAL; |
1730 | id++; | ||
1731 | head = p; | ||
1732 | } | 1714 | } |
1733 | 1715 | ||
1716 | if (id < 0) | ||
1717 | return id; | ||
1718 | |||
1734 | sprintf(hdev->name, "hci%d", id); | 1719 | sprintf(hdev->name, "hci%d", id); |
1735 | hdev->id = id; | 1720 | hdev->id = id; |
1736 | 1721 | ||
1737 | BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus); | 1722 | BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus); |
1738 | 1723 | ||
1739 | list_add(&hdev->list, head); | 1724 | write_lock(&hci_dev_list_lock); |
1740 | 1725 | list_add(&hdev->list, &hci_dev_list); | |
1741 | write_unlock(&hci_dev_list_lock); | 1726 | write_unlock(&hci_dev_list_lock); |
1742 | 1727 | ||
1743 | hdev->workqueue = alloc_workqueue(hdev->name, WQ_HIGHPRI | WQ_UNBOUND | | 1728 | hdev->workqueue = alloc_workqueue(hdev->name, WQ_HIGHPRI | WQ_UNBOUND | |
1744 | WQ_MEM_RECLAIM, 1); | 1729 | WQ_MEM_RECLAIM, 1); |
1745 | if (!hdev->workqueue) { | 1730 | if (!hdev->workqueue) { |
1746 | error = -ENOMEM; | 1731 | error = -ENOMEM; |
1747 | goto err; | 1732 | goto err; |
@@ -1752,7 +1737,8 @@ int hci_register_dev(struct hci_dev *hdev) | |||
1752 | goto err_wqueue; | 1737 | goto err_wqueue; |
1753 | 1738 | ||
1754 | hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev, | 1739 | hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev, |
1755 | RFKILL_TYPE_BLUETOOTH, &hci_rfkill_ops, hdev); | 1740 | RFKILL_TYPE_BLUETOOTH, &hci_rfkill_ops, |
1741 | hdev); | ||
1756 | if (hdev->rfkill) { | 1742 | if (hdev->rfkill) { |
1757 | if (rfkill_register(hdev->rfkill) < 0) { | 1743 | if (rfkill_register(hdev->rfkill) < 0) { |
1758 | rfkill_destroy(hdev->rfkill); | 1744 | rfkill_destroy(hdev->rfkill); |
@@ -1772,6 +1758,7 @@ int hci_register_dev(struct hci_dev *hdev) | |||
1772 | err_wqueue: | 1758 | err_wqueue: |
1773 | destroy_workqueue(hdev->workqueue); | 1759 | destroy_workqueue(hdev->workqueue); |
1774 | err: | 1760 | err: |
1761 | ida_simple_remove(&hci_index_ida, hdev->id); | ||
1775 | write_lock(&hci_dev_list_lock); | 1762 | write_lock(&hci_dev_list_lock); |
1776 | list_del(&hdev->list); | 1763 | list_del(&hdev->list); |
1777 | write_unlock(&hci_dev_list_lock); | 1764 | write_unlock(&hci_dev_list_lock); |
@@ -1783,12 +1770,14 @@ EXPORT_SYMBOL(hci_register_dev); | |||
1783 | /* Unregister HCI device */ | 1770 | /* Unregister HCI device */ |
1784 | void hci_unregister_dev(struct hci_dev *hdev) | 1771 | void hci_unregister_dev(struct hci_dev *hdev) |
1785 | { | 1772 | { |
1786 | int i; | 1773 | int i, id; |
1787 | 1774 | ||
1788 | BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus); | 1775 | BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus); |
1789 | 1776 | ||
1790 | set_bit(HCI_UNREGISTER, &hdev->dev_flags); | 1777 | set_bit(HCI_UNREGISTER, &hdev->dev_flags); |
1791 | 1778 | ||
1779 | id = hdev->id; | ||
1780 | |||
1792 | write_lock(&hci_dev_list_lock); | 1781 | write_lock(&hci_dev_list_lock); |
1793 | list_del(&hdev->list); | 1782 | list_del(&hdev->list); |
1794 | write_unlock(&hci_dev_list_lock); | 1783 | write_unlock(&hci_dev_list_lock); |
@@ -1799,7 +1788,7 @@ void hci_unregister_dev(struct hci_dev *hdev) | |||
1799 | kfree_skb(hdev->reassembly[i]); | 1788 | kfree_skb(hdev->reassembly[i]); |
1800 | 1789 | ||
1801 | if (!test_bit(HCI_INIT, &hdev->flags) && | 1790 | if (!test_bit(HCI_INIT, &hdev->flags) && |
1802 | !test_bit(HCI_SETUP, &hdev->dev_flags)) { | 1791 | !test_bit(HCI_SETUP, &hdev->dev_flags)) { |
1803 | hci_dev_lock(hdev); | 1792 | hci_dev_lock(hdev); |
1804 | mgmt_index_removed(hdev); | 1793 | mgmt_index_removed(hdev); |
1805 | hci_dev_unlock(hdev); | 1794 | hci_dev_unlock(hdev); |
@@ -1829,6 +1818,8 @@ void hci_unregister_dev(struct hci_dev *hdev) | |||
1829 | hci_dev_unlock(hdev); | 1818 | hci_dev_unlock(hdev); |
1830 | 1819 | ||
1831 | hci_dev_put(hdev); | 1820 | hci_dev_put(hdev); |
1821 | |||
1822 | ida_simple_remove(&hci_index_ida, id); | ||
1832 | } | 1823 | } |
1833 | EXPORT_SYMBOL(hci_unregister_dev); | 1824 | EXPORT_SYMBOL(hci_unregister_dev); |
1834 | 1825 | ||
@@ -1853,7 +1844,7 @@ int hci_recv_frame(struct sk_buff *skb) | |||
1853 | { | 1844 | { |
1854 | struct hci_dev *hdev = (struct hci_dev *) skb->dev; | 1845 | struct hci_dev *hdev = (struct hci_dev *) skb->dev; |
1855 | if (!hdev || (!test_bit(HCI_UP, &hdev->flags) | 1846 | if (!hdev || (!test_bit(HCI_UP, &hdev->flags) |
1856 | && !test_bit(HCI_INIT, &hdev->flags))) { | 1847 | && !test_bit(HCI_INIT, &hdev->flags))) { |
1857 | kfree_skb(skb); | 1848 | kfree_skb(skb); |
1858 | return -ENXIO; | 1849 | return -ENXIO; |
1859 | } | 1850 | } |
@@ -1872,7 +1863,7 @@ int hci_recv_frame(struct sk_buff *skb) | |||
1872 | EXPORT_SYMBOL(hci_recv_frame); | 1863 | EXPORT_SYMBOL(hci_recv_frame); |
1873 | 1864 | ||
1874 | static int hci_reassembly(struct hci_dev *hdev, int type, void *data, | 1865 | static int hci_reassembly(struct hci_dev *hdev, int type, void *data, |
1875 | int count, __u8 index) | 1866 | int count, __u8 index) |
1876 | { | 1867 | { |
1877 | int len = 0; | 1868 | int len = 0; |
1878 | int hlen = 0; | 1869 | int hlen = 0; |
@@ -1881,7 +1872,7 @@ static int hci_reassembly(struct hci_dev *hdev, int type, void *data, | |||
1881 | struct bt_skb_cb *scb; | 1872 | struct bt_skb_cb *scb; |
1882 | 1873 | ||
1883 | if ((type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT) || | 1874 | if ((type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT) || |
1884 | index >= NUM_REASSEMBLY) | 1875 | index >= NUM_REASSEMBLY) |
1885 | return -EILSEQ; | 1876 | return -EILSEQ; |
1886 | 1877 | ||
1887 | skb = hdev->reassembly[index]; | 1878 | skb = hdev->reassembly[index]; |
@@ -2023,7 +2014,7 @@ int hci_recv_stream_fragment(struct hci_dev *hdev, void *data, int count) | |||
2023 | type = bt_cb(skb)->pkt_type; | 2014 | type = bt_cb(skb)->pkt_type; |
2024 | 2015 | ||
2025 | rem = hci_reassembly(hdev, type, data, count, | 2016 | rem = hci_reassembly(hdev, type, data, count, |
2026 | STREAM_REASSEMBLY); | 2017 | STREAM_REASSEMBLY); |
2027 | if (rem < 0) | 2018 | if (rem < 0) |
2028 | return rem; | 2019 | return rem; |
2029 | 2020 | ||
@@ -2157,7 +2148,7 @@ static void hci_add_acl_hdr(struct sk_buff *skb, __u16 handle, __u16 flags) | |||
2157 | } | 2148 | } |
2158 | 2149 | ||
2159 | static void hci_queue_acl(struct hci_conn *conn, struct sk_buff_head *queue, | 2150 | static void hci_queue_acl(struct hci_conn *conn, struct sk_buff_head *queue, |
2160 | struct sk_buff *skb, __u16 flags) | 2151 | struct sk_buff *skb, __u16 flags) |
2161 | { | 2152 | { |
2162 | struct hci_dev *hdev = conn->hdev; | 2153 | struct hci_dev *hdev = conn->hdev; |
2163 | struct sk_buff *list; | 2154 | struct sk_buff *list; |
@@ -2216,7 +2207,6 @@ void hci_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags) | |||
2216 | 2207 | ||
2217 | queue_work(hdev->workqueue, &hdev->tx_work); | 2208 | queue_work(hdev->workqueue, &hdev->tx_work); |
2218 | } | 2209 | } |
2219 | EXPORT_SYMBOL(hci_send_acl); | ||
2220 | 2210 | ||
2221 | /* Send SCO data */ | 2211 | /* Send SCO data */ |
2222 | void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb) | 2212 | void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb) |
@@ -2239,12 +2229,12 @@ void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb) | |||
2239 | skb_queue_tail(&conn->data_q, skb); | 2229 | skb_queue_tail(&conn->data_q, skb); |
2240 | queue_work(hdev->workqueue, &hdev->tx_work); | 2230 | queue_work(hdev->workqueue, &hdev->tx_work); |
2241 | } | 2231 | } |
2242 | EXPORT_SYMBOL(hci_send_sco); | ||
2243 | 2232 | ||
2244 | /* ---- HCI TX task (outgoing data) ---- */ | 2233 | /* ---- HCI TX task (outgoing data) ---- */ |
2245 | 2234 | ||
2246 | /* HCI Connection scheduler */ | 2235 | /* HCI Connection scheduler */ |
2247 | static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int *quote) | 2236 | static struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, |
2237 | int *quote) | ||
2248 | { | 2238 | { |
2249 | struct hci_conn_hash *h = &hdev->conn_hash; | 2239 | struct hci_conn_hash *h = &hdev->conn_hash; |
2250 | struct hci_conn *conn = NULL, *c; | 2240 | struct hci_conn *conn = NULL, *c; |
@@ -2303,7 +2293,7 @@ static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int | |||
2303 | return conn; | 2293 | return conn; |
2304 | } | 2294 | } |
2305 | 2295 | ||
2306 | static inline void hci_link_tx_to(struct hci_dev *hdev, __u8 type) | 2296 | static void hci_link_tx_to(struct hci_dev *hdev, __u8 type) |
2307 | { | 2297 | { |
2308 | struct hci_conn_hash *h = &hdev->conn_hash; | 2298 | struct hci_conn_hash *h = &hdev->conn_hash; |
2309 | struct hci_conn *c; | 2299 | struct hci_conn *c; |
@@ -2316,16 +2306,16 @@ static inline void hci_link_tx_to(struct hci_dev *hdev, __u8 type) | |||
2316 | list_for_each_entry_rcu(c, &h->list, list) { | 2306 | list_for_each_entry_rcu(c, &h->list, list) { |
2317 | if (c->type == type && c->sent) { | 2307 | if (c->type == type && c->sent) { |
2318 | BT_ERR("%s killing stalled connection %s", | 2308 | BT_ERR("%s killing stalled connection %s", |
2319 | hdev->name, batostr(&c->dst)); | 2309 | hdev->name, batostr(&c->dst)); |
2320 | hci_acl_disconn(c, 0x13); | 2310 | hci_acl_disconn(c, HCI_ERROR_REMOTE_USER_TERM); |
2321 | } | 2311 | } |
2322 | } | 2312 | } |
2323 | 2313 | ||
2324 | rcu_read_unlock(); | 2314 | rcu_read_unlock(); |
2325 | } | 2315 | } |
2326 | 2316 | ||
2327 | static inline struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type, | 2317 | static struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type, |
2328 | int *quote) | 2318 | int *quote) |
2329 | { | 2319 | { |
2330 | struct hci_conn_hash *h = &hdev->conn_hash; | 2320 | struct hci_conn_hash *h = &hdev->conn_hash; |
2331 | struct hci_chan *chan = NULL; | 2321 | struct hci_chan *chan = NULL; |
@@ -2442,7 +2432,7 @@ static void hci_prio_recalculate(struct hci_dev *hdev, __u8 type) | |||
2442 | skb->priority = HCI_PRIO_MAX - 1; | 2432 | skb->priority = HCI_PRIO_MAX - 1; |
2443 | 2433 | ||
2444 | BT_DBG("chan %p skb %p promoted to %d", chan, skb, | 2434 | BT_DBG("chan %p skb %p promoted to %d", chan, skb, |
2445 | skb->priority); | 2435 | skb->priority); |
2446 | } | 2436 | } |
2447 | 2437 | ||
2448 | if (hci_conn_num(hdev, type) == num) | 2438 | if (hci_conn_num(hdev, type) == num) |
@@ -2459,18 +2449,18 @@ static inline int __get_blocks(struct hci_dev *hdev, struct sk_buff *skb) | |||
2459 | return DIV_ROUND_UP(skb->len - HCI_ACL_HDR_SIZE, hdev->block_len); | 2449 | return DIV_ROUND_UP(skb->len - HCI_ACL_HDR_SIZE, hdev->block_len); |
2460 | } | 2450 | } |
2461 | 2451 | ||
2462 | static inline void __check_timeout(struct hci_dev *hdev, unsigned int cnt) | 2452 | static void __check_timeout(struct hci_dev *hdev, unsigned int cnt) |
2463 | { | 2453 | { |
2464 | if (!test_bit(HCI_RAW, &hdev->flags)) { | 2454 | if (!test_bit(HCI_RAW, &hdev->flags)) { |
2465 | /* ACL tx timeout must be longer than maximum | 2455 | /* ACL tx timeout must be longer than maximum |
2466 | * link supervision timeout (40.9 seconds) */ | 2456 | * link supervision timeout (40.9 seconds) */ |
2467 | if (!cnt && time_after(jiffies, hdev->acl_last_tx + | 2457 | if (!cnt && time_after(jiffies, hdev->acl_last_tx + |
2468 | msecs_to_jiffies(HCI_ACL_TX_TIMEOUT))) | 2458 | msecs_to_jiffies(HCI_ACL_TX_TIMEOUT))) |
2469 | hci_link_tx_to(hdev, ACL_LINK); | 2459 | hci_link_tx_to(hdev, ACL_LINK); |
2470 | } | 2460 | } |
2471 | } | 2461 | } |
2472 | 2462 | ||
2473 | static inline void hci_sched_acl_pkt(struct hci_dev *hdev) | 2463 | static void hci_sched_acl_pkt(struct hci_dev *hdev) |
2474 | { | 2464 | { |
2475 | unsigned int cnt = hdev->acl_cnt; | 2465 | unsigned int cnt = hdev->acl_cnt; |
2476 | struct hci_chan *chan; | 2466 | struct hci_chan *chan; |
@@ -2480,11 +2470,11 @@ static inline void hci_sched_acl_pkt(struct hci_dev *hdev) | |||
2480 | __check_timeout(hdev, cnt); | 2470 | __check_timeout(hdev, cnt); |
2481 | 2471 | ||
2482 | while (hdev->acl_cnt && | 2472 | while (hdev->acl_cnt && |
2483 | (chan = hci_chan_sent(hdev, ACL_LINK, "e))) { | 2473 | (chan = hci_chan_sent(hdev, ACL_LINK, "e))) { |
2484 | u32 priority = (skb_peek(&chan->data_q))->priority; | 2474 | u32 priority = (skb_peek(&chan->data_q))->priority; |
2485 | while (quote-- && (skb = skb_peek(&chan->data_q))) { | 2475 | while (quote-- && (skb = skb_peek(&chan->data_q))) { |
2486 | BT_DBG("chan %p skb %p len %d priority %u", chan, skb, | 2476 | BT_DBG("chan %p skb %p len %d priority %u", chan, skb, |
2487 | skb->len, skb->priority); | 2477 | skb->len, skb->priority); |
2488 | 2478 | ||
2489 | /* Stop if priority has changed */ | 2479 | /* Stop if priority has changed */ |
2490 | if (skb->priority < priority) | 2480 | if (skb->priority < priority) |
@@ -2508,7 +2498,7 @@ static inline void hci_sched_acl_pkt(struct hci_dev *hdev) | |||
2508 | hci_prio_recalculate(hdev, ACL_LINK); | 2498 | hci_prio_recalculate(hdev, ACL_LINK); |
2509 | } | 2499 | } |
2510 | 2500 | ||
2511 | static inline void hci_sched_acl_blk(struct hci_dev *hdev) | 2501 | static void hci_sched_acl_blk(struct hci_dev *hdev) |
2512 | { | 2502 | { |
2513 | unsigned int cnt = hdev->block_cnt; | 2503 | unsigned int cnt = hdev->block_cnt; |
2514 | struct hci_chan *chan; | 2504 | struct hci_chan *chan; |
@@ -2518,13 +2508,13 @@ static inline void hci_sched_acl_blk(struct hci_dev *hdev) | |||
2518 | __check_timeout(hdev, cnt); | 2508 | __check_timeout(hdev, cnt); |
2519 | 2509 | ||
2520 | while (hdev->block_cnt > 0 && | 2510 | while (hdev->block_cnt > 0 && |
2521 | (chan = hci_chan_sent(hdev, ACL_LINK, "e))) { | 2511 | (chan = hci_chan_sent(hdev, ACL_LINK, "e))) { |
2522 | u32 priority = (skb_peek(&chan->data_q))->priority; | 2512 | u32 priority = (skb_peek(&chan->data_q))->priority; |
2523 | while (quote > 0 && (skb = skb_peek(&chan->data_q))) { | 2513 | while (quote > 0 && (skb = skb_peek(&chan->data_q))) { |
2524 | int blocks; | 2514 | int blocks; |
2525 | 2515 | ||
2526 | BT_DBG("chan %p skb %p len %d priority %u", chan, skb, | 2516 | BT_DBG("chan %p skb %p len %d priority %u", chan, skb, |
2527 | skb->len, skb->priority); | 2517 | skb->len, skb->priority); |
2528 | 2518 | ||
2529 | /* Stop if priority has changed */ | 2519 | /* Stop if priority has changed */ |
2530 | if (skb->priority < priority) | 2520 | if (skb->priority < priority) |
@@ -2537,7 +2527,7 @@ static inline void hci_sched_acl_blk(struct hci_dev *hdev) | |||
2537 | return; | 2527 | return; |
2538 | 2528 | ||
2539 | hci_conn_enter_active_mode(chan->conn, | 2529 | hci_conn_enter_active_mode(chan->conn, |
2540 | bt_cb(skb)->force_active); | 2530 | bt_cb(skb)->force_active); |
2541 | 2531 | ||
2542 | hci_send_frame(skb); | 2532 | hci_send_frame(skb); |
2543 | hdev->acl_last_tx = jiffies; | 2533 | hdev->acl_last_tx = jiffies; |
@@ -2554,7 +2544,7 @@ static inline void hci_sched_acl_blk(struct hci_dev *hdev) | |||
2554 | hci_prio_recalculate(hdev, ACL_LINK); | 2544 | hci_prio_recalculate(hdev, ACL_LINK); |
2555 | } | 2545 | } |
2556 | 2546 | ||
2557 | static inline void hci_sched_acl(struct hci_dev *hdev) | 2547 | static void hci_sched_acl(struct hci_dev *hdev) |
2558 | { | 2548 | { |
2559 | BT_DBG("%s", hdev->name); | 2549 | BT_DBG("%s", hdev->name); |
2560 | 2550 | ||
@@ -2573,7 +2563,7 @@ static inline void hci_sched_acl(struct hci_dev *hdev) | |||
2573 | } | 2563 | } |
2574 | 2564 | ||
2575 | /* Schedule SCO */ | 2565 | /* Schedule SCO */ |
2576 | static inline void hci_sched_sco(struct hci_dev *hdev) | 2566 | static void hci_sched_sco(struct hci_dev *hdev) |
2577 | { | 2567 | { |
2578 | struct hci_conn *conn; | 2568 | struct hci_conn *conn; |
2579 | struct sk_buff *skb; | 2569 | struct sk_buff *skb; |
@@ -2596,7 +2586,7 @@ static inline void hci_sched_sco(struct hci_dev *hdev) | |||
2596 | } | 2586 | } |
2597 | } | 2587 | } |
2598 | 2588 | ||
2599 | static inline void hci_sched_esco(struct hci_dev *hdev) | 2589 | static void hci_sched_esco(struct hci_dev *hdev) |
2600 | { | 2590 | { |
2601 | struct hci_conn *conn; | 2591 | struct hci_conn *conn; |
2602 | struct sk_buff *skb; | 2592 | struct sk_buff *skb; |
@@ -2607,7 +2597,8 @@ static inline void hci_sched_esco(struct hci_dev *hdev) | |||
2607 | if (!hci_conn_num(hdev, ESCO_LINK)) | 2597 | if (!hci_conn_num(hdev, ESCO_LINK)) |
2608 | return; | 2598 | return; |
2609 | 2599 | ||
2610 | while (hdev->sco_cnt && (conn = hci_low_sent(hdev, ESCO_LINK, "e))) { | 2600 | while (hdev->sco_cnt && (conn = hci_low_sent(hdev, ESCO_LINK, |
2601 | "e))) { | ||
2611 | while (quote-- && (skb = skb_dequeue(&conn->data_q))) { | 2602 | while (quote-- && (skb = skb_dequeue(&conn->data_q))) { |
2612 | BT_DBG("skb %p len %d", skb, skb->len); | 2603 | BT_DBG("skb %p len %d", skb, skb->len); |
2613 | hci_send_frame(skb); | 2604 | hci_send_frame(skb); |
@@ -2619,7 +2610,7 @@ static inline void hci_sched_esco(struct hci_dev *hdev) | |||
2619 | } | 2610 | } |
2620 | } | 2611 | } |
2621 | 2612 | ||
2622 | static inline void hci_sched_le(struct hci_dev *hdev) | 2613 | static void hci_sched_le(struct hci_dev *hdev) |
2623 | { | 2614 | { |
2624 | struct hci_chan *chan; | 2615 | struct hci_chan *chan; |
2625 | struct sk_buff *skb; | 2616 | struct sk_buff *skb; |
@@ -2634,7 +2625,7 @@ static inline void hci_sched_le(struct hci_dev *hdev) | |||
2634 | /* LE tx timeout must be longer than maximum | 2625 | /* LE tx timeout must be longer than maximum |
2635 | * link supervision timeout (40.9 seconds) */ | 2626 | * link supervision timeout (40.9 seconds) */ |
2636 | if (!hdev->le_cnt && hdev->le_pkts && | 2627 | if (!hdev->le_cnt && hdev->le_pkts && |
2637 | time_after(jiffies, hdev->le_last_tx + HZ * 45)) | 2628 | time_after(jiffies, hdev->le_last_tx + HZ * 45)) |
2638 | hci_link_tx_to(hdev, LE_LINK); | 2629 | hci_link_tx_to(hdev, LE_LINK); |
2639 | } | 2630 | } |
2640 | 2631 | ||
@@ -2644,7 +2635,7 @@ static inline void hci_sched_le(struct hci_dev *hdev) | |||
2644 | u32 priority = (skb_peek(&chan->data_q))->priority; | 2635 | u32 priority = (skb_peek(&chan->data_q))->priority; |
2645 | while (quote-- && (skb = skb_peek(&chan->data_q))) { | 2636 | while (quote-- && (skb = skb_peek(&chan->data_q))) { |
2646 | BT_DBG("chan %p skb %p len %d priority %u", chan, skb, | 2637 | BT_DBG("chan %p skb %p len %d priority %u", chan, skb, |
2647 | skb->len, skb->priority); | 2638 | skb->len, skb->priority); |
2648 | 2639 | ||
2649 | /* Stop if priority has changed */ | 2640 | /* Stop if priority has changed */ |
2650 | if (skb->priority < priority) | 2641 | if (skb->priority < priority) |
@@ -2676,7 +2667,7 @@ static void hci_tx_work(struct work_struct *work) | |||
2676 | struct sk_buff *skb; | 2667 | struct sk_buff *skb; |
2677 | 2668 | ||
2678 | BT_DBG("%s acl %d sco %d le %d", hdev->name, hdev->acl_cnt, | 2669 | BT_DBG("%s acl %d sco %d le %d", hdev->name, hdev->acl_cnt, |
2679 | hdev->sco_cnt, hdev->le_cnt); | 2670 | hdev->sco_cnt, hdev->le_cnt); |
2680 | 2671 | ||
2681 | /* Schedule queues and send stuff to HCI driver */ | 2672 | /* Schedule queues and send stuff to HCI driver */ |
2682 | 2673 | ||
@@ -2696,7 +2687,7 @@ static void hci_tx_work(struct work_struct *work) | |||
2696 | /* ----- HCI RX task (incoming data processing) ----- */ | 2687 | /* ----- HCI RX task (incoming data processing) ----- */ |
2697 | 2688 | ||
2698 | /* ACL data packet */ | 2689 | /* ACL data packet */ |
2699 | static inline void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb) | 2690 | static void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb) |
2700 | { | 2691 | { |
2701 | struct hci_acl_hdr *hdr = (void *) skb->data; | 2692 | struct hci_acl_hdr *hdr = (void *) skb->data; |
2702 | struct hci_conn *conn; | 2693 | struct hci_conn *conn; |
@@ -2708,7 +2699,8 @@ static inline void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb) | |||
2708 | flags = hci_flags(handle); | 2699 | flags = hci_flags(handle); |
2709 | handle = hci_handle(handle); | 2700 | handle = hci_handle(handle); |
2710 | 2701 | ||
2711 | BT_DBG("%s len %d handle 0x%x flags 0x%x", hdev->name, skb->len, handle, flags); | 2702 | BT_DBG("%s len %d handle 0x%x flags 0x%x", hdev->name, skb->len, |
2703 | handle, flags); | ||
2712 | 2704 | ||
2713 | hdev->stat.acl_rx++; | 2705 | hdev->stat.acl_rx++; |
2714 | 2706 | ||
@@ -2732,14 +2724,14 @@ static inline void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb) | |||
2732 | return; | 2724 | return; |
2733 | } else { | 2725 | } else { |
2734 | BT_ERR("%s ACL packet for unknown connection handle %d", | 2726 | BT_ERR("%s ACL packet for unknown connection handle %d", |
2735 | hdev->name, handle); | 2727 | hdev->name, handle); |
2736 | } | 2728 | } |
2737 | 2729 | ||
2738 | kfree_skb(skb); | 2730 | kfree_skb(skb); |
2739 | } | 2731 | } |
2740 | 2732 | ||
2741 | /* SCO data packet */ | 2733 | /* SCO data packet */ |
2742 | static inline void hci_scodata_packet(struct hci_dev *hdev, struct sk_buff *skb) | 2734 | static void hci_scodata_packet(struct hci_dev *hdev, struct sk_buff *skb) |
2743 | { | 2735 | { |
2744 | struct hci_sco_hdr *hdr = (void *) skb->data; | 2736 | struct hci_sco_hdr *hdr = (void *) skb->data; |
2745 | struct hci_conn *conn; | 2737 | struct hci_conn *conn; |
@@ -2763,7 +2755,7 @@ static inline void hci_scodata_packet(struct hci_dev *hdev, struct sk_buff *skb) | |||
2763 | return; | 2755 | return; |
2764 | } else { | 2756 | } else { |
2765 | BT_ERR("%s SCO packet for unknown connection handle %d", | 2757 | BT_ERR("%s SCO packet for unknown connection handle %d", |
2766 | hdev->name, handle); | 2758 | hdev->name, handle); |
2767 | } | 2759 | } |
2768 | 2760 | ||
2769 | kfree_skb(skb); | 2761 | kfree_skb(skb); |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 4eefb7f65cf..1ba929c05d0 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -24,20 +24,7 @@ | |||
24 | 24 | ||
25 | /* Bluetooth HCI event handling. */ | 25 | /* Bluetooth HCI event handling. */ |
26 | 26 | ||
27 | #include <linux/module.h> | 27 | #include <linux/export.h> |
28 | |||
29 | #include <linux/types.h> | ||
30 | #include <linux/errno.h> | ||
31 | #include <linux/kernel.h> | ||
32 | #include <linux/slab.h> | ||
33 | #include <linux/poll.h> | ||
34 | #include <linux/fcntl.h> | ||
35 | #include <linux/init.h> | ||
36 | #include <linux/skbuff.h> | ||
37 | #include <linux/interrupt.h> | ||
38 | #include <net/sock.h> | ||
39 | |||
40 | #include <linux/uaccess.h> | ||
41 | #include <asm/unaligned.h> | 28 | #include <asm/unaligned.h> |
42 | 29 | ||
43 | #include <net/bluetooth/bluetooth.h> | 30 | #include <net/bluetooth/bluetooth.h> |
@@ -95,7 +82,8 @@ static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) | |||
95 | hci_conn_check_pending(hdev); | 82 | hci_conn_check_pending(hdev); |
96 | } | 83 | } |
97 | 84 | ||
98 | static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, struct sk_buff *skb) | 85 | static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, |
86 | struct sk_buff *skb) | ||
99 | { | 87 | { |
100 | BT_DBG("%s", hdev->name); | 88 | BT_DBG("%s", hdev->name); |
101 | } | 89 | } |
@@ -166,7 +154,8 @@ static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb) | |||
166 | hci_dev_unlock(hdev); | 154 | hci_dev_unlock(hdev); |
167 | } | 155 | } |
168 | 156 | ||
169 | static void hci_cc_read_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb) | 157 | static void hci_cc_read_def_link_policy(struct hci_dev *hdev, |
158 | struct sk_buff *skb) | ||
170 | { | 159 | { |
171 | struct hci_rp_read_def_link_policy *rp = (void *) skb->data; | 160 | struct hci_rp_read_def_link_policy *rp = (void *) skb->data; |
172 | 161 | ||
@@ -178,7 +167,8 @@ static void hci_cc_read_def_link_policy(struct hci_dev *hdev, struct sk_buff *sk | |||
178 | hdev->link_policy = __le16_to_cpu(rp->policy); | 167 | hdev->link_policy = __le16_to_cpu(rp->policy); |
179 | } | 168 | } |
180 | 169 | ||
181 | static void hci_cc_write_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb) | 170 | static void hci_cc_write_def_link_policy(struct hci_dev *hdev, |
171 | struct sk_buff *skb) | ||
182 | { | 172 | { |
183 | __u8 status = *((__u8 *) skb->data); | 173 | __u8 status = *((__u8 *) skb->data); |
184 | void *sent; | 174 | void *sent; |
@@ -329,7 +319,7 @@ static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) | |||
329 | if (hdev->discov_timeout > 0) { | 319 | if (hdev->discov_timeout > 0) { |
330 | int to = msecs_to_jiffies(hdev->discov_timeout * 1000); | 320 | int to = msecs_to_jiffies(hdev->discov_timeout * 1000); |
331 | queue_delayed_work(hdev->workqueue, &hdev->discov_off, | 321 | queue_delayed_work(hdev->workqueue, &hdev->discov_off, |
332 | to); | 322 | to); |
333 | } | 323 | } |
334 | } else if (old_iscan) | 324 | } else if (old_iscan) |
335 | mgmt_discoverable(hdev, 0); | 325 | mgmt_discoverable(hdev, 0); |
@@ -358,7 +348,7 @@ static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) | |||
358 | memcpy(hdev->dev_class, rp->dev_class, 3); | 348 | memcpy(hdev->dev_class, rp->dev_class, 3); |
359 | 349 | ||
360 | BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name, | 350 | BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name, |
361 | hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]); | 351 | hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]); |
362 | } | 352 | } |
363 | 353 | ||
364 | static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) | 354 | static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -406,7 +396,8 @@ static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) | |||
406 | hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); | 396 | hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); |
407 | } | 397 | } |
408 | 398 | ||
409 | static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) | 399 | static void hci_cc_write_voice_setting(struct hci_dev *hdev, |
400 | struct sk_buff *skb) | ||
410 | { | 401 | { |
411 | __u8 status = *((__u8 *) skb->data); | 402 | __u8 status = *((__u8 *) skb->data); |
412 | __u16 setting; | 403 | __u16 setting; |
@@ -473,7 +464,7 @@ static u8 hci_get_inquiry_mode(struct hci_dev *hdev) | |||
473 | return 1; | 464 | return 1; |
474 | 465 | ||
475 | if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 && | 466 | if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 && |
476 | hdev->lmp_subver == 0x0757) | 467 | hdev->lmp_subver == 0x0757) |
477 | return 1; | 468 | return 1; |
478 | 469 | ||
479 | if (hdev->manufacturer == 15) { | 470 | if (hdev->manufacturer == 15) { |
@@ -486,7 +477,7 @@ static u8 hci_get_inquiry_mode(struct hci_dev *hdev) | |||
486 | } | 477 | } |
487 | 478 | ||
488 | if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 && | 479 | if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 && |
489 | hdev->lmp_subver == 0x1805) | 480 | hdev->lmp_subver == 0x1805) |
490 | return 1; | 481 | return 1; |
491 | 482 | ||
492 | return 0; | 483 | return 0; |
@@ -566,7 +557,7 @@ static void hci_setup(struct hci_dev *hdev) | |||
566 | if (hdev->hci_ver > BLUETOOTH_VER_1_1) | 557 | if (hdev->hci_ver > BLUETOOTH_VER_1_1) |
567 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL); | 558 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL); |
568 | 559 | ||
569 | if (hdev->features[6] & LMP_SIMPLE_PAIR) { | 560 | if (lmp_ssp_capable(hdev)) { |
570 | if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) { | 561 | if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) { |
571 | u8 mode = 0x01; | 562 | u8 mode = 0x01; |
572 | hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, | 563 | hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, |
@@ -618,8 +609,7 @@ static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) | |||
618 | hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver); | 609 | hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver); |
619 | 610 | ||
620 | BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name, | 611 | BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name, |
621 | hdev->manufacturer, | 612 | hdev->manufacturer, hdev->hci_ver, hdev->hci_rev); |
622 | hdev->hci_ver, hdev->hci_rev); | ||
623 | 613 | ||
624 | if (test_bit(HCI_INIT, &hdev->flags)) | 614 | if (test_bit(HCI_INIT, &hdev->flags)) |
625 | hci_setup(hdev); | 615 | hci_setup(hdev); |
@@ -646,7 +636,8 @@ static void hci_setup_link_policy(struct hci_dev *hdev) | |||
646 | hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp); | 636 | hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp); |
647 | } | 637 | } |
648 | 638 | ||
649 | static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb) | 639 | static void hci_cc_read_local_commands(struct hci_dev *hdev, |
640 | struct sk_buff *skb) | ||
650 | { | 641 | { |
651 | struct hci_rp_read_local_commands *rp = (void *) skb->data; | 642 | struct hci_rp_read_local_commands *rp = (void *) skb->data; |
652 | 643 | ||
@@ -664,7 +655,8 @@ done: | |||
664 | hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status); | 655 | hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status); |
665 | } | 656 | } |
666 | 657 | ||
667 | static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb) | 658 | static void hci_cc_read_local_features(struct hci_dev *hdev, |
659 | struct sk_buff *skb) | ||
668 | { | 660 | { |
669 | struct hci_rp_read_local_features *rp = (void *) skb->data; | 661 | struct hci_rp_read_local_features *rp = (void *) skb->data; |
670 | 662 | ||
@@ -713,10 +705,10 @@ static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb | |||
713 | hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5); | 705 | hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5); |
714 | 706 | ||
715 | BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name, | 707 | BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name, |
716 | hdev->features[0], hdev->features[1], | 708 | hdev->features[0], hdev->features[1], |
717 | hdev->features[2], hdev->features[3], | 709 | hdev->features[2], hdev->features[3], |
718 | hdev->features[4], hdev->features[5], | 710 | hdev->features[4], hdev->features[5], |
719 | hdev->features[6], hdev->features[7]); | 711 | hdev->features[6], hdev->features[7]); |
720 | } | 712 | } |
721 | 713 | ||
722 | static void hci_set_le_support(struct hci_dev *hdev) | 714 | static void hci_set_le_support(struct hci_dev *hdev) |
@@ -736,7 +728,7 @@ static void hci_set_le_support(struct hci_dev *hdev) | |||
736 | } | 728 | } |
737 | 729 | ||
738 | static void hci_cc_read_local_ext_features(struct hci_dev *hdev, | 730 | static void hci_cc_read_local_ext_features(struct hci_dev *hdev, |
739 | struct sk_buff *skb) | 731 | struct sk_buff *skb) |
740 | { | 732 | { |
741 | struct hci_rp_read_local_ext_features *rp = (void *) skb->data; | 733 | struct hci_rp_read_local_ext_features *rp = (void *) skb->data; |
742 | 734 | ||
@@ -762,7 +754,7 @@ done: | |||
762 | } | 754 | } |
763 | 755 | ||
764 | static void hci_cc_read_flow_control_mode(struct hci_dev *hdev, | 756 | static void hci_cc_read_flow_control_mode(struct hci_dev *hdev, |
765 | struct sk_buff *skb) | 757 | struct sk_buff *skb) |
766 | { | 758 | { |
767 | struct hci_rp_read_flow_control_mode *rp = (void *) skb->data; | 759 | struct hci_rp_read_flow_control_mode *rp = (void *) skb->data; |
768 | 760 | ||
@@ -798,9 +790,8 @@ static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) | |||
798 | hdev->acl_cnt = hdev->acl_pkts; | 790 | hdev->acl_cnt = hdev->acl_pkts; |
799 | hdev->sco_cnt = hdev->sco_pkts; | 791 | hdev->sco_cnt = hdev->sco_pkts; |
800 | 792 | ||
801 | BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, | 793 | BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu, |
802 | hdev->acl_mtu, hdev->acl_pkts, | 794 | hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts); |
803 | hdev->sco_mtu, hdev->sco_pkts); | ||
804 | } | 795 | } |
805 | 796 | ||
806 | static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) | 797 | static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -816,7 +807,7 @@ static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) | |||
816 | } | 807 | } |
817 | 808 | ||
818 | static void hci_cc_read_data_block_size(struct hci_dev *hdev, | 809 | static void hci_cc_read_data_block_size(struct hci_dev *hdev, |
819 | struct sk_buff *skb) | 810 | struct sk_buff *skb) |
820 | { | 811 | { |
821 | struct hci_rp_read_data_block_size *rp = (void *) skb->data; | 812 | struct hci_rp_read_data_block_size *rp = (void *) skb->data; |
822 | 813 | ||
@@ -832,7 +823,7 @@ static void hci_cc_read_data_block_size(struct hci_dev *hdev, | |||
832 | hdev->block_cnt = hdev->num_blocks; | 823 | hdev->block_cnt = hdev->num_blocks; |
833 | 824 | ||
834 | BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu, | 825 | BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu, |
835 | hdev->block_cnt, hdev->block_len); | 826 | hdev->block_cnt, hdev->block_len); |
836 | 827 | ||
837 | hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status); | 828 | hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status); |
838 | } | 829 | } |
@@ -847,7 +838,7 @@ static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb) | |||
847 | } | 838 | } |
848 | 839 | ||
849 | static void hci_cc_read_local_amp_info(struct hci_dev *hdev, | 840 | static void hci_cc_read_local_amp_info(struct hci_dev *hdev, |
850 | struct sk_buff *skb) | 841 | struct sk_buff *skb) |
851 | { | 842 | { |
852 | struct hci_rp_read_local_amp_info *rp = (void *) skb->data; | 843 | struct hci_rp_read_local_amp_info *rp = (void *) skb->data; |
853 | 844 | ||
@@ -871,7 +862,7 @@ static void hci_cc_read_local_amp_info(struct hci_dev *hdev, | |||
871 | } | 862 | } |
872 | 863 | ||
873 | static void hci_cc_delete_stored_link_key(struct hci_dev *hdev, | 864 | static void hci_cc_delete_stored_link_key(struct hci_dev *hdev, |
874 | struct sk_buff *skb) | 865 | struct sk_buff *skb) |
875 | { | 866 | { |
876 | __u8 status = *((__u8 *) skb->data); | 867 | __u8 status = *((__u8 *) skb->data); |
877 | 868 | ||
@@ -890,7 +881,7 @@ static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb) | |||
890 | } | 881 | } |
891 | 882 | ||
892 | static void hci_cc_write_inquiry_mode(struct hci_dev *hdev, | 883 | static void hci_cc_write_inquiry_mode(struct hci_dev *hdev, |
893 | struct sk_buff *skb) | 884 | struct sk_buff *skb) |
894 | { | 885 | { |
895 | __u8 status = *((__u8 *) skb->data); | 886 | __u8 status = *((__u8 *) skb->data); |
896 | 887 | ||
@@ -900,7 +891,7 @@ static void hci_cc_write_inquiry_mode(struct hci_dev *hdev, | |||
900 | } | 891 | } |
901 | 892 | ||
902 | static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, | 893 | static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, |
903 | struct sk_buff *skb) | 894 | struct sk_buff *skb) |
904 | { | 895 | { |
905 | struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data; | 896 | struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data; |
906 | 897 | ||
@@ -959,7 +950,7 @@ static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) | |||
959 | 950 | ||
960 | if (test_bit(HCI_MGMT, &hdev->dev_flags)) | 951 | if (test_bit(HCI_MGMT, &hdev->dev_flags)) |
961 | mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr, | 952 | mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr, |
962 | rp->status); | 953 | rp->status); |
963 | 954 | ||
964 | hci_dev_unlock(hdev); | 955 | hci_dev_unlock(hdev); |
965 | } | 956 | } |
@@ -1000,7 +991,7 @@ static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) | |||
1000 | } | 991 | } |
1001 | 992 | ||
1002 | static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, | 993 | static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, |
1003 | struct sk_buff *skb) | 994 | struct sk_buff *skb) |
1004 | { | 995 | { |
1005 | struct hci_rp_user_confirm_reply *rp = (void *) skb->data; | 996 | struct hci_rp_user_confirm_reply *rp = (void *) skb->data; |
1006 | 997 | ||
@@ -1031,7 +1022,7 @@ static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb) | |||
1031 | } | 1022 | } |
1032 | 1023 | ||
1033 | static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev, | 1024 | static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev, |
1034 | struct sk_buff *skb) | 1025 | struct sk_buff *skb) |
1035 | { | 1026 | { |
1036 | struct hci_rp_user_confirm_reply *rp = (void *) skb->data; | 1027 | struct hci_rp_user_confirm_reply *rp = (void *) skb->data; |
1037 | 1028 | ||
@@ -1047,7 +1038,7 @@ static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev, | |||
1047 | } | 1038 | } |
1048 | 1039 | ||
1049 | static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, | 1040 | static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, |
1050 | struct sk_buff *skb) | 1041 | struct sk_buff *skb) |
1051 | { | 1042 | { |
1052 | struct hci_rp_read_local_oob_data *rp = (void *) skb->data; | 1043 | struct hci_rp_read_local_oob_data *rp = (void *) skb->data; |
1053 | 1044 | ||
@@ -1076,7 +1067,7 @@ static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) | |||
1076 | } | 1067 | } |
1077 | 1068 | ||
1078 | static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, | 1069 | static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, |
1079 | struct sk_buff *skb) | 1070 | struct sk_buff *skb) |
1080 | { | 1071 | { |
1081 | struct hci_cp_le_set_scan_enable *cp; | 1072 | struct hci_cp_le_set_scan_enable *cp; |
1082 | __u8 status = *((__u8 *) skb->data); | 1073 | __u8 status = *((__u8 *) skb->data); |
@@ -1156,8 +1147,8 @@ static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) | |||
1156 | hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status); | 1147 | hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status); |
1157 | } | 1148 | } |
1158 | 1149 | ||
1159 | static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev, | 1150 | static void hci_cc_write_le_host_supported(struct hci_dev *hdev, |
1160 | struct sk_buff *skb) | 1151 | struct sk_buff *skb) |
1161 | { | 1152 | { |
1162 | struct hci_cp_write_le_host_supported *sent; | 1153 | struct hci_cp_write_le_host_supported *sent; |
1163 | __u8 status = *((__u8 *) skb->data); | 1154 | __u8 status = *((__u8 *) skb->data); |
@@ -1176,13 +1167,13 @@ static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev, | |||
1176 | } | 1167 | } |
1177 | 1168 | ||
1178 | if (test_bit(HCI_MGMT, &hdev->dev_flags) && | 1169 | if (test_bit(HCI_MGMT, &hdev->dev_flags) && |
1179 | !test_bit(HCI_INIT, &hdev->flags)) | 1170 | !test_bit(HCI_INIT, &hdev->flags)) |
1180 | mgmt_le_enable_complete(hdev, sent->le, status); | 1171 | mgmt_le_enable_complete(hdev, sent->le, status); |
1181 | 1172 | ||
1182 | hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status); | 1173 | hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status); |
1183 | } | 1174 | } |
1184 | 1175 | ||
1185 | static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) | 1176 | static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) |
1186 | { | 1177 | { |
1187 | BT_DBG("%s status 0x%x", hdev->name, status); | 1178 | BT_DBG("%s status 0x%x", hdev->name, status); |
1188 | 1179 | ||
@@ -1203,7 +1194,7 @@ static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) | |||
1203 | hci_dev_unlock(hdev); | 1194 | hci_dev_unlock(hdev); |
1204 | } | 1195 | } |
1205 | 1196 | ||
1206 | static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) | 1197 | static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) |
1207 | { | 1198 | { |
1208 | struct hci_cp_create_conn *cp; | 1199 | struct hci_cp_create_conn *cp; |
1209 | struct hci_conn *conn; | 1200 | struct hci_conn *conn; |
@@ -1333,7 +1324,7 @@ static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status) | |||
1333 | } | 1324 | } |
1334 | 1325 | ||
1335 | static int hci_outgoing_auth_needed(struct hci_dev *hdev, | 1326 | static int hci_outgoing_auth_needed(struct hci_dev *hdev, |
1336 | struct hci_conn *conn) | 1327 | struct hci_conn *conn) |
1337 | { | 1328 | { |
1338 | if (conn->state != BT_CONFIG || !conn->out) | 1329 | if (conn->state != BT_CONFIG || !conn->out) |
1339 | return 0; | 1330 | return 0; |
@@ -1343,15 +1334,14 @@ static int hci_outgoing_auth_needed(struct hci_dev *hdev, | |||
1343 | 1334 | ||
1344 | /* Only request authentication for SSP connections or non-SSP | 1335 | /* Only request authentication for SSP connections or non-SSP |
1345 | * devices with sec_level HIGH or if MITM protection is requested */ | 1336 | * devices with sec_level HIGH or if MITM protection is requested */ |
1346 | if (!hci_conn_ssp_enabled(conn) && | 1337 | if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) && |
1347 | conn->pending_sec_level != BT_SECURITY_HIGH && | 1338 | conn->pending_sec_level != BT_SECURITY_HIGH) |
1348 | !(conn->auth_type & 0x01)) | ||
1349 | return 0; | 1339 | return 0; |
1350 | 1340 | ||
1351 | return 1; | 1341 | return 1; |
1352 | } | 1342 | } |
1353 | 1343 | ||
1354 | static inline int hci_resolve_name(struct hci_dev *hdev, | 1344 | static int hci_resolve_name(struct hci_dev *hdev, |
1355 | struct inquiry_entry *e) | 1345 | struct inquiry_entry *e) |
1356 | { | 1346 | { |
1357 | struct hci_cp_remote_name_req cp; | 1347 | struct hci_cp_remote_name_req cp; |
@@ -1638,7 +1628,7 @@ static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) | |||
1638 | conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr); | 1628 | conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr); |
1639 | 1629 | ||
1640 | BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr), | 1630 | BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr), |
1641 | conn); | 1631 | conn); |
1642 | 1632 | ||
1643 | if (status) { | 1633 | if (status) { |
1644 | if (conn && conn->state == BT_CONNECT) { | 1634 | if (conn && conn->state == BT_CONNECT) { |
@@ -1668,7 +1658,7 @@ static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) | |||
1668 | BT_DBG("%s status 0x%x", hdev->name, status); | 1658 | BT_DBG("%s status 0x%x", hdev->name, status); |
1669 | } | 1659 | } |
1670 | 1660 | ||
1671 | static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | 1661 | static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) |
1672 | { | 1662 | { |
1673 | __u8 status = *((__u8 *) skb->data); | 1663 | __u8 status = *((__u8 *) skb->data); |
1674 | struct discovery_state *discov = &hdev->discovery; | 1664 | struct discovery_state *discov = &hdev->discovery; |
@@ -1708,7 +1698,7 @@ unlock: | |||
1708 | hci_dev_unlock(hdev); | 1698 | hci_dev_unlock(hdev); |
1709 | } | 1699 | } |
1710 | 1700 | ||
1711 | static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) | 1701 | static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) |
1712 | { | 1702 | { |
1713 | struct inquiry_data data; | 1703 | struct inquiry_data data; |
1714 | struct inquiry_info *info = (void *) (skb->data + 1); | 1704 | struct inquiry_info *info = (void *) (skb->data + 1); |
@@ -1745,7 +1735,7 @@ static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff * | |||
1745 | hci_dev_unlock(hdev); | 1735 | hci_dev_unlock(hdev); |
1746 | } | 1736 | } |
1747 | 1737 | ||
1748 | static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | 1738 | static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) |
1749 | { | 1739 | { |
1750 | struct hci_ev_conn_complete *ev = (void *) skb->data; | 1740 | struct hci_ev_conn_complete *ev = (void *) skb->data; |
1751 | struct hci_conn *conn; | 1741 | struct hci_conn *conn; |
@@ -1823,18 +1813,18 @@ unlock: | |||
1823 | hci_conn_check_pending(hdev); | 1813 | hci_conn_check_pending(hdev); |
1824 | } | 1814 | } |
1825 | 1815 | ||
1826 | static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | 1816 | static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) |
1827 | { | 1817 | { |
1828 | struct hci_ev_conn_request *ev = (void *) skb->data; | 1818 | struct hci_ev_conn_request *ev = (void *) skb->data; |
1829 | int mask = hdev->link_mode; | 1819 | int mask = hdev->link_mode; |
1830 | 1820 | ||
1831 | BT_DBG("%s bdaddr %s type 0x%x", hdev->name, | 1821 | BT_DBG("%s bdaddr %s type 0x%x", hdev->name, batostr(&ev->bdaddr), |
1832 | batostr(&ev->bdaddr), ev->link_type); | 1822 | ev->link_type); |
1833 | 1823 | ||
1834 | mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type); | 1824 | mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type); |
1835 | 1825 | ||
1836 | if ((mask & HCI_LM_ACCEPT) && | 1826 | if ((mask & HCI_LM_ACCEPT) && |
1837 | !hci_blacklist_lookup(hdev, &ev->bdaddr)) { | 1827 | !hci_blacklist_lookup(hdev, &ev->bdaddr)) { |
1838 | /* Connection accepted */ | 1828 | /* Connection accepted */ |
1839 | struct inquiry_entry *ie; | 1829 | struct inquiry_entry *ie; |
1840 | struct hci_conn *conn; | 1830 | struct hci_conn *conn; |
@@ -1845,7 +1835,8 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk | |||
1845 | if (ie) | 1835 | if (ie) |
1846 | memcpy(ie->data.dev_class, ev->dev_class, 3); | 1836 | memcpy(ie->data.dev_class, ev->dev_class, 3); |
1847 | 1837 | ||
1848 | conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); | 1838 | conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, |
1839 | &ev->bdaddr); | ||
1849 | if (!conn) { | 1840 | if (!conn) { |
1850 | conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr); | 1841 | conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr); |
1851 | if (!conn) { | 1842 | if (!conn) { |
@@ -1878,9 +1869,9 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk | |||
1878 | bacpy(&cp.bdaddr, &ev->bdaddr); | 1869 | bacpy(&cp.bdaddr, &ev->bdaddr); |
1879 | cp.pkt_type = cpu_to_le16(conn->pkt_type); | 1870 | cp.pkt_type = cpu_to_le16(conn->pkt_type); |
1880 | 1871 | ||
1881 | cp.tx_bandwidth = cpu_to_le32(0x00001f40); | 1872 | cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40); |
1882 | cp.rx_bandwidth = cpu_to_le32(0x00001f40); | 1873 | cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40); |
1883 | cp.max_latency = cpu_to_le16(0xffff); | 1874 | cp.max_latency = __constant_cpu_to_le16(0xffff); |
1884 | cp.content_format = cpu_to_le16(hdev->voice_setting); | 1875 | cp.content_format = cpu_to_le16(hdev->voice_setting); |
1885 | cp.retrans_effort = 0xff; | 1876 | cp.retrans_effort = 0xff; |
1886 | 1877 | ||
@@ -1897,7 +1888,7 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk | |||
1897 | } | 1888 | } |
1898 | } | 1889 | } |
1899 | 1890 | ||
1900 | static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | 1891 | static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) |
1901 | { | 1892 | { |
1902 | struct hci_ev_disconn_complete *ev = (void *) skb->data; | 1893 | struct hci_ev_disconn_complete *ev = (void *) skb->data; |
1903 | struct hci_conn *conn; | 1894 | struct hci_conn *conn; |
@@ -1914,10 +1905,10 @@ static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff | |||
1914 | conn->state = BT_CLOSED; | 1905 | conn->state = BT_CLOSED; |
1915 | 1906 | ||
1916 | if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) && | 1907 | if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) && |
1917 | (conn->type == ACL_LINK || conn->type == LE_LINK)) { | 1908 | (conn->type == ACL_LINK || conn->type == LE_LINK)) { |
1918 | if (ev->status != 0) | 1909 | if (ev->status != 0) |
1919 | mgmt_disconnect_failed(hdev, &conn->dst, conn->type, | 1910 | mgmt_disconnect_failed(hdev, &conn->dst, conn->type, |
1920 | conn->dst_type, ev->status); | 1911 | conn->dst_type, ev->status); |
1921 | else | 1912 | else |
1922 | mgmt_device_disconnected(hdev, &conn->dst, conn->type, | 1913 | mgmt_device_disconnected(hdev, &conn->dst, conn->type, |
1923 | conn->dst_type); | 1914 | conn->dst_type); |
@@ -1934,7 +1925,7 @@ unlock: | |||
1934 | hci_dev_unlock(hdev); | 1925 | hci_dev_unlock(hdev); |
1935 | } | 1926 | } |
1936 | 1927 | ||
1937 | static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | 1928 | static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) |
1938 | { | 1929 | { |
1939 | struct hci_ev_auth_complete *ev = (void *) skb->data; | 1930 | struct hci_ev_auth_complete *ev = (void *) skb->data; |
1940 | struct hci_conn *conn; | 1931 | struct hci_conn *conn; |
@@ -1949,7 +1940,7 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s | |||
1949 | 1940 | ||
1950 | if (!ev->status) { | 1941 | if (!ev->status) { |
1951 | if (!hci_conn_ssp_enabled(conn) && | 1942 | if (!hci_conn_ssp_enabled(conn) && |
1952 | test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) { | 1943 | test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) { |
1953 | BT_INFO("re-auth of legacy device is not possible."); | 1944 | BT_INFO("re-auth of legacy device is not possible."); |
1954 | } else { | 1945 | } else { |
1955 | conn->link_mode |= HCI_LM_AUTH; | 1946 | conn->link_mode |= HCI_LM_AUTH; |
@@ -1969,7 +1960,7 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s | |||
1969 | cp.handle = ev->handle; | 1960 | cp.handle = ev->handle; |
1970 | cp.encrypt = 0x01; | 1961 | cp.encrypt = 0x01; |
1971 | hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), | 1962 | hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), |
1972 | &cp); | 1963 | &cp); |
1973 | } else { | 1964 | } else { |
1974 | conn->state = BT_CONNECTED; | 1965 | conn->state = BT_CONNECTED; |
1975 | hci_proto_connect_cfm(conn, ev->status); | 1966 | hci_proto_connect_cfm(conn, ev->status); |
@@ -1989,7 +1980,7 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s | |||
1989 | cp.handle = ev->handle; | 1980 | cp.handle = ev->handle; |
1990 | cp.encrypt = 0x01; | 1981 | cp.encrypt = 0x01; |
1991 | hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), | 1982 | hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), |
1992 | &cp); | 1983 | &cp); |
1993 | } else { | 1984 | } else { |
1994 | clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); | 1985 | clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); |
1995 | hci_encrypt_cfm(conn, ev->status, 0x00); | 1986 | hci_encrypt_cfm(conn, ev->status, 0x00); |
@@ -2000,7 +1991,7 @@ unlock: | |||
2000 | hci_dev_unlock(hdev); | 1991 | hci_dev_unlock(hdev); |
2001 | } | 1992 | } |
2002 | 1993 | ||
2003 | static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) | 1994 | static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) |
2004 | { | 1995 | { |
2005 | struct hci_ev_remote_name *ev = (void *) skb->data; | 1996 | struct hci_ev_remote_name *ev = (void *) skb->data; |
2006 | struct hci_conn *conn; | 1997 | struct hci_conn *conn; |
@@ -2039,7 +2030,7 @@ unlock: | |||
2039 | hci_dev_unlock(hdev); | 2030 | hci_dev_unlock(hdev); |
2040 | } | 2031 | } |
2041 | 2032 | ||
2042 | static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) | 2033 | static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) |
2043 | { | 2034 | { |
2044 | struct hci_ev_encrypt_change *ev = (void *) skb->data; | 2035 | struct hci_ev_encrypt_change *ev = (void *) skb->data; |
2045 | struct hci_conn *conn; | 2036 | struct hci_conn *conn; |
@@ -2082,7 +2073,8 @@ unlock: | |||
2082 | hci_dev_unlock(hdev); | 2073 | hci_dev_unlock(hdev); |
2083 | } | 2074 | } |
2084 | 2075 | ||
2085 | static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | 2076 | static void hci_change_link_key_complete_evt(struct hci_dev *hdev, |
2077 | struct sk_buff *skb) | ||
2086 | { | 2078 | { |
2087 | struct hci_ev_change_link_key_complete *ev = (void *) skb->data; | 2079 | struct hci_ev_change_link_key_complete *ev = (void *) skb->data; |
2088 | struct hci_conn *conn; | 2080 | struct hci_conn *conn; |
@@ -2104,7 +2096,8 @@ static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct | |||
2104 | hci_dev_unlock(hdev); | 2096 | hci_dev_unlock(hdev); |
2105 | } | 2097 | } |
2106 | 2098 | ||
2107 | static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb) | 2099 | static void hci_remote_features_evt(struct hci_dev *hdev, |
2100 | struct sk_buff *skb) | ||
2108 | { | 2101 | { |
2109 | struct hci_ev_remote_features *ev = (void *) skb->data; | 2102 | struct hci_ev_remote_features *ev = (void *) skb->data; |
2110 | struct hci_conn *conn; | 2103 | struct hci_conn *conn; |
@@ -2128,7 +2121,7 @@ static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff | |||
2128 | cp.handle = ev->handle; | 2121 | cp.handle = ev->handle; |
2129 | cp.page = 0x01; | 2122 | cp.page = 0x01; |
2130 | hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, | 2123 | hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, |
2131 | sizeof(cp), &cp); | 2124 | sizeof(cp), &cp); |
2132 | goto unlock; | 2125 | goto unlock; |
2133 | } | 2126 | } |
2134 | 2127 | ||
@@ -2153,17 +2146,18 @@ unlock: | |||
2153 | hci_dev_unlock(hdev); | 2146 | hci_dev_unlock(hdev); |
2154 | } | 2147 | } |
2155 | 2148 | ||
2156 | static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb) | 2149 | static void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb) |
2157 | { | 2150 | { |
2158 | BT_DBG("%s", hdev->name); | 2151 | BT_DBG("%s", hdev->name); |
2159 | } | 2152 | } |
2160 | 2153 | ||
2161 | static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | 2154 | static void hci_qos_setup_complete_evt(struct hci_dev *hdev, |
2155 | struct sk_buff *skb) | ||
2162 | { | 2156 | { |
2163 | BT_DBG("%s", hdev->name); | 2157 | BT_DBG("%s", hdev->name); |
2164 | } | 2158 | } |
2165 | 2159 | ||
2166 | static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | 2160 | static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) |
2167 | { | 2161 | { |
2168 | struct hci_ev_cmd_complete *ev = (void *) skb->data; | 2162 | struct hci_ev_cmd_complete *ev = (void *) skb->data; |
2169 | __u16 opcode; | 2163 | __u16 opcode; |
@@ -2384,7 +2378,7 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk | |||
2384 | } | 2378 | } |
2385 | } | 2379 | } |
2386 | 2380 | ||
2387 | static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) | 2381 | static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) |
2388 | { | 2382 | { |
2389 | struct hci_ev_cmd_status *ev = (void *) skb->data; | 2383 | struct hci_ev_cmd_status *ev = (void *) skb->data; |
2390 | __u16 opcode; | 2384 | __u16 opcode; |
@@ -2465,7 +2459,7 @@ static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2465 | } | 2459 | } |
2466 | } | 2460 | } |
2467 | 2461 | ||
2468 | static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) | 2462 | static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) |
2469 | { | 2463 | { |
2470 | struct hci_ev_role_change *ev = (void *) skb->data; | 2464 | struct hci_ev_role_change *ev = (void *) skb->data; |
2471 | struct hci_conn *conn; | 2465 | struct hci_conn *conn; |
@@ -2491,7 +2485,7 @@ static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb | |||
2491 | hci_dev_unlock(hdev); | 2485 | hci_dev_unlock(hdev); |
2492 | } | 2486 | } |
2493 | 2487 | ||
2494 | static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) | 2488 | static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) |
2495 | { | 2489 | { |
2496 | struct hci_ev_num_comp_pkts *ev = (void *) skb->data; | 2490 | struct hci_ev_num_comp_pkts *ev = (void *) skb->data; |
2497 | int i; | 2491 | int i; |
@@ -2502,7 +2496,7 @@ static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *s | |||
2502 | } | 2496 | } |
2503 | 2497 | ||
2504 | if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + | 2498 | if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + |
2505 | ev->num_hndl * sizeof(struct hci_comp_pkts_info)) { | 2499 | ev->num_hndl * sizeof(struct hci_comp_pkts_info)) { |
2506 | BT_DBG("%s bad parameters", hdev->name); | 2500 | BT_DBG("%s bad parameters", hdev->name); |
2507 | return; | 2501 | return; |
2508 | } | 2502 | } |
@@ -2557,8 +2551,7 @@ static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *s | |||
2557 | queue_work(hdev->workqueue, &hdev->tx_work); | 2551 | queue_work(hdev->workqueue, &hdev->tx_work); |
2558 | } | 2552 | } |
2559 | 2553 | ||
2560 | static inline void hci_num_comp_blocks_evt(struct hci_dev *hdev, | 2554 | static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb) |
2561 | struct sk_buff *skb) | ||
2562 | { | 2555 | { |
2563 | struct hci_ev_num_comp_blocks *ev = (void *) skb->data; | 2556 | struct hci_ev_num_comp_blocks *ev = (void *) skb->data; |
2564 | int i; | 2557 | int i; |
@@ -2569,13 +2562,13 @@ static inline void hci_num_comp_blocks_evt(struct hci_dev *hdev, | |||
2569 | } | 2562 | } |
2570 | 2563 | ||
2571 | if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + | 2564 | if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + |
2572 | ev->num_hndl * sizeof(struct hci_comp_blocks_info)) { | 2565 | ev->num_hndl * sizeof(struct hci_comp_blocks_info)) { |
2573 | BT_DBG("%s bad parameters", hdev->name); | 2566 | BT_DBG("%s bad parameters", hdev->name); |
2574 | return; | 2567 | return; |
2575 | } | 2568 | } |
2576 | 2569 | ||
2577 | BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks, | 2570 | BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks, |
2578 | ev->num_hndl); | 2571 | ev->num_hndl); |
2579 | 2572 | ||
2580 | for (i = 0; i < ev->num_hndl; i++) { | 2573 | for (i = 0; i < ev->num_hndl; i++) { |
2581 | struct hci_comp_blocks_info *info = &ev->handles[i]; | 2574 | struct hci_comp_blocks_info *info = &ev->handles[i]; |
@@ -2607,7 +2600,7 @@ static inline void hci_num_comp_blocks_evt(struct hci_dev *hdev, | |||
2607 | queue_work(hdev->workqueue, &hdev->tx_work); | 2600 | queue_work(hdev->workqueue, &hdev->tx_work); |
2608 | } | 2601 | } |
2609 | 2602 | ||
2610 | static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) | 2603 | static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) |
2611 | { | 2604 | { |
2612 | struct hci_ev_mode_change *ev = (void *) skb->data; | 2605 | struct hci_ev_mode_change *ev = (void *) skb->data; |
2613 | struct hci_conn *conn; | 2606 | struct hci_conn *conn; |
@@ -2621,7 +2614,8 @@ static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb | |||
2621 | conn->mode = ev->mode; | 2614 | conn->mode = ev->mode; |
2622 | conn->interval = __le16_to_cpu(ev->interval); | 2615 | conn->interval = __le16_to_cpu(ev->interval); |
2623 | 2616 | ||
2624 | if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags)) { | 2617 | if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, |
2618 | &conn->flags)) { | ||
2625 | if (conn->mode == HCI_CM_ACTIVE) | 2619 | if (conn->mode == HCI_CM_ACTIVE) |
2626 | set_bit(HCI_CONN_POWER_SAVE, &conn->flags); | 2620 | set_bit(HCI_CONN_POWER_SAVE, &conn->flags); |
2627 | else | 2621 | else |
@@ -2635,7 +2629,7 @@ static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb | |||
2635 | hci_dev_unlock(hdev); | 2629 | hci_dev_unlock(hdev); |
2636 | } | 2630 | } |
2637 | 2631 | ||
2638 | static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | 2632 | static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) |
2639 | { | 2633 | { |
2640 | struct hci_ev_pin_code_req *ev = (void *) skb->data; | 2634 | struct hci_ev_pin_code_req *ev = (void *) skb->data; |
2641 | struct hci_conn *conn; | 2635 | struct hci_conn *conn; |
@@ -2656,7 +2650,7 @@ static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff | |||
2656 | 2650 | ||
2657 | if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags)) | 2651 | if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags)) |
2658 | hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, | 2652 | hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, |
2659 | sizeof(ev->bdaddr), &ev->bdaddr); | 2653 | sizeof(ev->bdaddr), &ev->bdaddr); |
2660 | else if (test_bit(HCI_MGMT, &hdev->dev_flags)) { | 2654 | else if (test_bit(HCI_MGMT, &hdev->dev_flags)) { |
2661 | u8 secure; | 2655 | u8 secure; |
2662 | 2656 | ||
@@ -2672,7 +2666,7 @@ unlock: | |||
2672 | hci_dev_unlock(hdev); | 2666 | hci_dev_unlock(hdev); |
2673 | } | 2667 | } |
2674 | 2668 | ||
2675 | static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | 2669 | static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) |
2676 | { | 2670 | { |
2677 | struct hci_ev_link_key_req *ev = (void *) skb->data; | 2671 | struct hci_ev_link_key_req *ev = (void *) skb->data; |
2678 | struct hci_cp_link_key_reply cp; | 2672 | struct hci_cp_link_key_reply cp; |
@@ -2689,15 +2683,15 @@ static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff | |||
2689 | key = hci_find_link_key(hdev, &ev->bdaddr); | 2683 | key = hci_find_link_key(hdev, &ev->bdaddr); |
2690 | if (!key) { | 2684 | if (!key) { |
2691 | BT_DBG("%s link key not found for %s", hdev->name, | 2685 | BT_DBG("%s link key not found for %s", hdev->name, |
2692 | batostr(&ev->bdaddr)); | 2686 | batostr(&ev->bdaddr)); |
2693 | goto not_found; | 2687 | goto not_found; |
2694 | } | 2688 | } |
2695 | 2689 | ||
2696 | BT_DBG("%s found key type %u for %s", hdev->name, key->type, | 2690 | BT_DBG("%s found key type %u for %s", hdev->name, key->type, |
2697 | batostr(&ev->bdaddr)); | 2691 | batostr(&ev->bdaddr)); |
2698 | 2692 | ||
2699 | if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) && | 2693 | if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) && |
2700 | key->type == HCI_LK_DEBUG_COMBINATION) { | 2694 | key->type == HCI_LK_DEBUG_COMBINATION) { |
2701 | BT_DBG("%s ignoring debug key", hdev->name); | 2695 | BT_DBG("%s ignoring debug key", hdev->name); |
2702 | goto not_found; | 2696 | goto not_found; |
2703 | } | 2697 | } |
@@ -2705,16 +2699,15 @@ static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff | |||
2705 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); | 2699 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); |
2706 | if (conn) { | 2700 | if (conn) { |
2707 | if (key->type == HCI_LK_UNAUTH_COMBINATION && | 2701 | if (key->type == HCI_LK_UNAUTH_COMBINATION && |
2708 | conn->auth_type != 0xff && | 2702 | conn->auth_type != 0xff && (conn->auth_type & 0x01)) { |
2709 | (conn->auth_type & 0x01)) { | ||
2710 | BT_DBG("%s ignoring unauthenticated key", hdev->name); | 2703 | BT_DBG("%s ignoring unauthenticated key", hdev->name); |
2711 | goto not_found; | 2704 | goto not_found; |
2712 | } | 2705 | } |
2713 | 2706 | ||
2714 | if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 && | 2707 | if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 && |
2715 | conn->pending_sec_level == BT_SECURITY_HIGH) { | 2708 | conn->pending_sec_level == BT_SECURITY_HIGH) { |
2716 | BT_DBG("%s ignoring key unauthenticated for high \ | 2709 | BT_DBG("%s ignoring key unauthenticated for high security", |
2717 | security", hdev->name); | 2710 | hdev->name); |
2718 | goto not_found; | 2711 | goto not_found; |
2719 | } | 2712 | } |
2720 | 2713 | ||
@@ -2723,7 +2716,7 @@ static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff | |||
2723 | } | 2716 | } |
2724 | 2717 | ||
2725 | bacpy(&cp.bdaddr, &ev->bdaddr); | 2718 | bacpy(&cp.bdaddr, &ev->bdaddr); |
2726 | memcpy(cp.link_key, key->val, 16); | 2719 | memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE); |
2727 | 2720 | ||
2728 | hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp); | 2721 | hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp); |
2729 | 2722 | ||
@@ -2736,7 +2729,7 @@ not_found: | |||
2736 | hci_dev_unlock(hdev); | 2729 | hci_dev_unlock(hdev); |
2737 | } | 2730 | } |
2738 | 2731 | ||
2739 | static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) | 2732 | static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) |
2740 | { | 2733 | { |
2741 | struct hci_ev_link_key_notify *ev = (void *) skb->data; | 2734 | struct hci_ev_link_key_notify *ev = (void *) skb->data; |
2742 | struct hci_conn *conn; | 2735 | struct hci_conn *conn; |
@@ -2760,12 +2753,12 @@ static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff | |||
2760 | 2753 | ||
2761 | if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags)) | 2754 | if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags)) |
2762 | hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key, | 2755 | hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key, |
2763 | ev->key_type, pin_len); | 2756 | ev->key_type, pin_len); |
2764 | 2757 | ||
2765 | hci_dev_unlock(hdev); | 2758 | hci_dev_unlock(hdev); |
2766 | } | 2759 | } |
2767 | 2760 | ||
2768 | static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) | 2761 | static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) |
2769 | { | 2762 | { |
2770 | struct hci_ev_clock_offset *ev = (void *) skb->data; | 2763 | struct hci_ev_clock_offset *ev = (void *) skb->data; |
2771 | struct hci_conn *conn; | 2764 | struct hci_conn *conn; |
@@ -2788,7 +2781,7 @@ static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *sk | |||
2788 | hci_dev_unlock(hdev); | 2781 | hci_dev_unlock(hdev); |
2789 | } | 2782 | } |
2790 | 2783 | ||
2791 | static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) | 2784 | static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) |
2792 | { | 2785 | { |
2793 | struct hci_ev_pkt_type_change *ev = (void *) skb->data; | 2786 | struct hci_ev_pkt_type_change *ev = (void *) skb->data; |
2794 | struct hci_conn *conn; | 2787 | struct hci_conn *conn; |
@@ -2804,7 +2797,7 @@ static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff | |||
2804 | hci_dev_unlock(hdev); | 2797 | hci_dev_unlock(hdev); |
2805 | } | 2798 | } |
2806 | 2799 | ||
2807 | static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) | 2800 | static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) |
2808 | { | 2801 | { |
2809 | struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; | 2802 | struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; |
2810 | struct inquiry_entry *ie; | 2803 | struct inquiry_entry *ie; |
@@ -2822,7 +2815,8 @@ static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff * | |||
2822 | hci_dev_unlock(hdev); | 2815 | hci_dev_unlock(hdev); |
2823 | } | 2816 | } |
2824 | 2817 | ||
2825 | static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb) | 2818 | static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, |
2819 | struct sk_buff *skb) | ||
2826 | { | 2820 | { |
2827 | struct inquiry_data data; | 2821 | struct inquiry_data data; |
2828 | int num_rsp = *((__u8 *) skb->data); | 2822 | int num_rsp = *((__u8 *) skb->data); |
@@ -2881,7 +2875,8 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct | |||
2881 | hci_dev_unlock(hdev); | 2875 | hci_dev_unlock(hdev); |
2882 | } | 2876 | } |
2883 | 2877 | ||
2884 | static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb) | 2878 | static void hci_remote_ext_features_evt(struct hci_dev *hdev, |
2879 | struct sk_buff *skb) | ||
2885 | { | 2880 | { |
2886 | struct hci_ev_remote_ext_features *ev = (void *) skb->data; | 2881 | struct hci_ev_remote_ext_features *ev = (void *) skb->data; |
2887 | struct hci_conn *conn; | 2882 | struct hci_conn *conn; |
@@ -2929,7 +2924,8 @@ unlock: | |||
2929 | hci_dev_unlock(hdev); | 2924 | hci_dev_unlock(hdev); |
2930 | } | 2925 | } |
2931 | 2926 | ||
2932 | static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | 2927 | static void hci_sync_conn_complete_evt(struct hci_dev *hdev, |
2928 | struct sk_buff *skb) | ||
2933 | { | 2929 | { |
2934 | struct hci_ev_sync_conn_complete *ev = (void *) skb->data; | 2930 | struct hci_ev_sync_conn_complete *ev = (void *) skb->data; |
2935 | struct hci_conn *conn; | 2931 | struct hci_conn *conn; |
@@ -2984,19 +2980,20 @@ unlock: | |||
2984 | hci_dev_unlock(hdev); | 2980 | hci_dev_unlock(hdev); |
2985 | } | 2981 | } |
2986 | 2982 | ||
2987 | static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb) | 2983 | static void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb) |
2988 | { | 2984 | { |
2989 | BT_DBG("%s", hdev->name); | 2985 | BT_DBG("%s", hdev->name); |
2990 | } | 2986 | } |
2991 | 2987 | ||
2992 | static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb) | 2988 | static void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb) |
2993 | { | 2989 | { |
2994 | struct hci_ev_sniff_subrate *ev = (void *) skb->data; | 2990 | struct hci_ev_sniff_subrate *ev = (void *) skb->data; |
2995 | 2991 | ||
2996 | BT_DBG("%s status %d", hdev->name, ev->status); | 2992 | BT_DBG("%s status %d", hdev->name, ev->status); |
2997 | } | 2993 | } |
2998 | 2994 | ||
2999 | static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) | 2995 | static void hci_extended_inquiry_result_evt(struct hci_dev *hdev, |
2996 | struct sk_buff *skb) | ||
3000 | { | 2997 | { |
3001 | struct inquiry_data data; | 2998 | struct inquiry_data data; |
3002 | struct extended_inquiry_info *info = (void *) (skb->data + 1); | 2999 | struct extended_inquiry_info *info = (void *) (skb->data + 1); |
@@ -3043,7 +3040,51 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct | |||
3043 | hci_dev_unlock(hdev); | 3040 | hci_dev_unlock(hdev); |
3044 | } | 3041 | } |
3045 | 3042 | ||
3046 | static inline u8 hci_get_auth_req(struct hci_conn *conn) | 3043 | static void hci_key_refresh_complete_evt(struct hci_dev *hdev, |
3044 | struct sk_buff *skb) | ||
3045 | { | ||
3046 | struct hci_ev_key_refresh_complete *ev = (void *) skb->data; | ||
3047 | struct hci_conn *conn; | ||
3048 | |||
3049 | BT_DBG("%s status %u handle %u", hdev->name, ev->status, | ||
3050 | __le16_to_cpu(ev->handle)); | ||
3051 | |||
3052 | hci_dev_lock(hdev); | ||
3053 | |||
3054 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); | ||
3055 | if (!conn) | ||
3056 | goto unlock; | ||
3057 | |||
3058 | if (!ev->status) | ||
3059 | conn->sec_level = conn->pending_sec_level; | ||
3060 | |||
3061 | clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); | ||
3062 | |||
3063 | if (ev->status && conn->state == BT_CONNECTED) { | ||
3064 | hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE); | ||
3065 | hci_conn_put(conn); | ||
3066 | goto unlock; | ||
3067 | } | ||
3068 | |||
3069 | if (conn->state == BT_CONFIG) { | ||
3070 | if (!ev->status) | ||
3071 | conn->state = BT_CONNECTED; | ||
3072 | |||
3073 | hci_proto_connect_cfm(conn, ev->status); | ||
3074 | hci_conn_put(conn); | ||
3075 | } else { | ||
3076 | hci_auth_cfm(conn, ev->status); | ||
3077 | |||
3078 | hci_conn_hold(conn); | ||
3079 | conn->disc_timeout = HCI_DISCONN_TIMEOUT; | ||
3080 | hci_conn_put(conn); | ||
3081 | } | ||
3082 | |||
3083 | unlock: | ||
3084 | hci_dev_unlock(hdev); | ||
3085 | } | ||
3086 | |||
3087 | static u8 hci_get_auth_req(struct hci_conn *conn) | ||
3047 | { | 3088 | { |
3048 | /* If remote requests dedicated bonding follow that lead */ | 3089 | /* If remote requests dedicated bonding follow that lead */ |
3049 | if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) { | 3090 | if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) { |
@@ -3062,7 +3103,7 @@ static inline u8 hci_get_auth_req(struct hci_conn *conn) | |||
3062 | return conn->auth_type; | 3103 | return conn->auth_type; |
3063 | } | 3104 | } |
3064 | 3105 | ||
3065 | static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | 3106 | static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) |
3066 | { | 3107 | { |
3067 | struct hci_ev_io_capa_request *ev = (void *) skb->data; | 3108 | struct hci_ev_io_capa_request *ev = (void *) skb->data; |
3068 | struct hci_conn *conn; | 3109 | struct hci_conn *conn; |
@@ -3081,7 +3122,7 @@ static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff | |||
3081 | goto unlock; | 3122 | goto unlock; |
3082 | 3123 | ||
3083 | if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) || | 3124 | if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) || |
3084 | (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { | 3125 | (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { |
3085 | struct hci_cp_io_capability_reply cp; | 3126 | struct hci_cp_io_capability_reply cp; |
3086 | 3127 | ||
3087 | bacpy(&cp.bdaddr, &ev->bdaddr); | 3128 | bacpy(&cp.bdaddr, &ev->bdaddr); |
@@ -3092,14 +3133,14 @@ static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff | |||
3092 | conn->auth_type = hci_get_auth_req(conn); | 3133 | conn->auth_type = hci_get_auth_req(conn); |
3093 | cp.authentication = conn->auth_type; | 3134 | cp.authentication = conn->auth_type; |
3094 | 3135 | ||
3095 | if ((conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)) && | 3136 | if (hci_find_remote_oob_data(hdev, &conn->dst) && |
3096 | hci_find_remote_oob_data(hdev, &conn->dst)) | 3137 | (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags))) |
3097 | cp.oob_data = 0x01; | 3138 | cp.oob_data = 0x01; |
3098 | else | 3139 | else |
3099 | cp.oob_data = 0x00; | 3140 | cp.oob_data = 0x00; |
3100 | 3141 | ||
3101 | hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY, | 3142 | hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY, |
3102 | sizeof(cp), &cp); | 3143 | sizeof(cp), &cp); |
3103 | } else { | 3144 | } else { |
3104 | struct hci_cp_io_capability_neg_reply cp; | 3145 | struct hci_cp_io_capability_neg_reply cp; |
3105 | 3146 | ||
@@ -3107,14 +3148,14 @@ static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff | |||
3107 | cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED; | 3148 | cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED; |
3108 | 3149 | ||
3109 | hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY, | 3150 | hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY, |
3110 | sizeof(cp), &cp); | 3151 | sizeof(cp), &cp); |
3111 | } | 3152 | } |
3112 | 3153 | ||
3113 | unlock: | 3154 | unlock: |
3114 | hci_dev_unlock(hdev); | 3155 | hci_dev_unlock(hdev); |
3115 | } | 3156 | } |
3116 | 3157 | ||
3117 | static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb) | 3158 | static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb) |
3118 | { | 3159 | { |
3119 | struct hci_ev_io_capa_reply *ev = (void *) skb->data; | 3160 | struct hci_ev_io_capa_reply *ev = (void *) skb->data; |
3120 | struct hci_conn *conn; | 3161 | struct hci_conn *conn; |
@@ -3136,8 +3177,8 @@ unlock: | |||
3136 | hci_dev_unlock(hdev); | 3177 | hci_dev_unlock(hdev); |
3137 | } | 3178 | } |
3138 | 3179 | ||
3139 | static inline void hci_user_confirm_request_evt(struct hci_dev *hdev, | 3180 | static void hci_user_confirm_request_evt(struct hci_dev *hdev, |
3140 | struct sk_buff *skb) | 3181 | struct sk_buff *skb) |
3141 | { | 3182 | { |
3142 | struct hci_ev_user_confirm_req *ev = (void *) skb->data; | 3183 | struct hci_ev_user_confirm_req *ev = (void *) skb->data; |
3143 | int loc_mitm, rem_mitm, confirm_hint = 0; | 3184 | int loc_mitm, rem_mitm, confirm_hint = 0; |
@@ -3165,13 +3206,13 @@ static inline void hci_user_confirm_request_evt(struct hci_dev *hdev, | |||
3165 | if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) { | 3206 | if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) { |
3166 | BT_DBG("Rejecting request: remote device can't provide MITM"); | 3207 | BT_DBG("Rejecting request: remote device can't provide MITM"); |
3167 | hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY, | 3208 | hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY, |
3168 | sizeof(ev->bdaddr), &ev->bdaddr); | 3209 | sizeof(ev->bdaddr), &ev->bdaddr); |
3169 | goto unlock; | 3210 | goto unlock; |
3170 | } | 3211 | } |
3171 | 3212 | ||
3172 | /* If no side requires MITM protection; auto-accept */ | 3213 | /* If no side requires MITM protection; auto-accept */ |
3173 | if ((!loc_mitm || conn->remote_cap == 0x03) && | 3214 | if ((!loc_mitm || conn->remote_cap == 0x03) && |
3174 | (!rem_mitm || conn->io_capability == 0x03)) { | 3215 | (!rem_mitm || conn->io_capability == 0x03)) { |
3175 | 3216 | ||
3176 | /* If we're not the initiators request authorization to | 3217 | /* If we're not the initiators request authorization to |
3177 | * proceed from user space (mgmt_user_confirm with | 3218 | * proceed from user space (mgmt_user_confirm with |
@@ -3183,7 +3224,7 @@ static inline void hci_user_confirm_request_evt(struct hci_dev *hdev, | |||
3183 | } | 3224 | } |
3184 | 3225 | ||
3185 | BT_DBG("Auto-accept of user confirmation with %ums delay", | 3226 | BT_DBG("Auto-accept of user confirmation with %ums delay", |
3186 | hdev->auto_accept_delay); | 3227 | hdev->auto_accept_delay); |
3187 | 3228 | ||
3188 | if (hdev->auto_accept_delay > 0) { | 3229 | if (hdev->auto_accept_delay > 0) { |
3189 | int delay = msecs_to_jiffies(hdev->auto_accept_delay); | 3230 | int delay = msecs_to_jiffies(hdev->auto_accept_delay); |
@@ -3192,7 +3233,7 @@ static inline void hci_user_confirm_request_evt(struct hci_dev *hdev, | |||
3192 | } | 3233 | } |
3193 | 3234 | ||
3194 | hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, | 3235 | hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, |
3195 | sizeof(ev->bdaddr), &ev->bdaddr); | 3236 | sizeof(ev->bdaddr), &ev->bdaddr); |
3196 | goto unlock; | 3237 | goto unlock; |
3197 | } | 3238 | } |
3198 | 3239 | ||
@@ -3204,8 +3245,8 @@ unlock: | |||
3204 | hci_dev_unlock(hdev); | 3245 | hci_dev_unlock(hdev); |
3205 | } | 3246 | } |
3206 | 3247 | ||
3207 | static inline void hci_user_passkey_request_evt(struct hci_dev *hdev, | 3248 | static void hci_user_passkey_request_evt(struct hci_dev *hdev, |
3208 | struct sk_buff *skb) | 3249 | struct sk_buff *skb) |
3209 | { | 3250 | { |
3210 | struct hci_ev_user_passkey_req *ev = (void *) skb->data; | 3251 | struct hci_ev_user_passkey_req *ev = (void *) skb->data; |
3211 | 3252 | ||
@@ -3219,7 +3260,8 @@ static inline void hci_user_passkey_request_evt(struct hci_dev *hdev, | |||
3219 | hci_dev_unlock(hdev); | 3260 | hci_dev_unlock(hdev); |
3220 | } | 3261 | } |
3221 | 3262 | ||
3222 | static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | 3263 | static void hci_simple_pair_complete_evt(struct hci_dev *hdev, |
3264 | struct sk_buff *skb) | ||
3223 | { | 3265 | { |
3224 | struct hci_ev_simple_pair_complete *ev = (void *) skb->data; | 3266 | struct hci_ev_simple_pair_complete *ev = (void *) skb->data; |
3225 | struct hci_conn *conn; | 3267 | struct hci_conn *conn; |
@@ -3247,7 +3289,8 @@ unlock: | |||
3247 | hci_dev_unlock(hdev); | 3289 | hci_dev_unlock(hdev); |
3248 | } | 3290 | } |
3249 | 3291 | ||
3250 | static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb) | 3292 | static void hci_remote_host_features_evt(struct hci_dev *hdev, |
3293 | struct sk_buff *skb) | ||
3251 | { | 3294 | { |
3252 | struct hci_ev_remote_host_features *ev = (void *) skb->data; | 3295 | struct hci_ev_remote_host_features *ev = (void *) skb->data; |
3253 | struct inquiry_entry *ie; | 3296 | struct inquiry_entry *ie; |
@@ -3263,8 +3306,8 @@ static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_ | |||
3263 | hci_dev_unlock(hdev); | 3306 | hci_dev_unlock(hdev); |
3264 | } | 3307 | } |
3265 | 3308 | ||
3266 | static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev, | 3309 | static void hci_remote_oob_data_request_evt(struct hci_dev *hdev, |
3267 | struct sk_buff *skb) | 3310 | struct sk_buff *skb) |
3268 | { | 3311 | { |
3269 | struct hci_ev_remote_oob_data_request *ev = (void *) skb->data; | 3312 | struct hci_ev_remote_oob_data_request *ev = (void *) skb->data; |
3270 | struct oob_data *data; | 3313 | struct oob_data *data; |
@@ -3285,20 +3328,20 @@ static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev, | |||
3285 | memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer)); | 3328 | memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer)); |
3286 | 3329 | ||
3287 | hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp), | 3330 | hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp), |
3288 | &cp); | 3331 | &cp); |
3289 | } else { | 3332 | } else { |
3290 | struct hci_cp_remote_oob_data_neg_reply cp; | 3333 | struct hci_cp_remote_oob_data_neg_reply cp; |
3291 | 3334 | ||
3292 | bacpy(&cp.bdaddr, &ev->bdaddr); | 3335 | bacpy(&cp.bdaddr, &ev->bdaddr); |
3293 | hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp), | 3336 | hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp), |
3294 | &cp); | 3337 | &cp); |
3295 | } | 3338 | } |
3296 | 3339 | ||
3297 | unlock: | 3340 | unlock: |
3298 | hci_dev_unlock(hdev); | 3341 | hci_dev_unlock(hdev); |
3299 | } | 3342 | } |
3300 | 3343 | ||
3301 | static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | 3344 | static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) |
3302 | { | 3345 | { |
3303 | struct hci_ev_le_conn_complete *ev = (void *) skb->data; | 3346 | struct hci_ev_le_conn_complete *ev = (void *) skb->data; |
3304 | struct hci_conn *conn; | 3347 | struct hci_conn *conn; |
@@ -3307,6 +3350,19 @@ static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff | |||
3307 | 3350 | ||
3308 | hci_dev_lock(hdev); | 3351 | hci_dev_lock(hdev); |
3309 | 3352 | ||
3353 | if (ev->status) { | ||
3354 | conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); | ||
3355 | if (!conn) | ||
3356 | goto unlock; | ||
3357 | |||
3358 | mgmt_connect_failed(hdev, &conn->dst, conn->type, | ||
3359 | conn->dst_type, ev->status); | ||
3360 | hci_proto_connect_cfm(conn, ev->status); | ||
3361 | conn->state = BT_CLOSED; | ||
3362 | hci_conn_del(conn); | ||
3363 | goto unlock; | ||
3364 | } | ||
3365 | |||
3310 | conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr); | 3366 | conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr); |
3311 | if (!conn) { | 3367 | if (!conn) { |
3312 | conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); | 3368 | conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); |
@@ -3319,15 +3375,6 @@ static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff | |||
3319 | conn->dst_type = ev->bdaddr_type; | 3375 | conn->dst_type = ev->bdaddr_type; |
3320 | } | 3376 | } |
3321 | 3377 | ||
3322 | if (ev->status) { | ||
3323 | mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, | ||
3324 | conn->dst_type, ev->status); | ||
3325 | hci_proto_connect_cfm(conn, ev->status); | ||
3326 | conn->state = BT_CLOSED; | ||
3327 | hci_conn_del(conn); | ||
3328 | goto unlock; | ||
3329 | } | ||
3330 | |||
3331 | if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) | 3378 | if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) |
3332 | mgmt_device_connected(hdev, &ev->bdaddr, conn->type, | 3379 | mgmt_device_connected(hdev, &ev->bdaddr, conn->type, |
3333 | conn->dst_type, 0, NULL, 0, NULL); | 3380 | conn->dst_type, 0, NULL, 0, NULL); |
@@ -3345,8 +3392,7 @@ unlock: | |||
3345 | hci_dev_unlock(hdev); | 3392 | hci_dev_unlock(hdev); |
3346 | } | 3393 | } |
3347 | 3394 | ||
3348 | static inline void hci_le_adv_report_evt(struct hci_dev *hdev, | 3395 | static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb) |
3349 | struct sk_buff *skb) | ||
3350 | { | 3396 | { |
3351 | u8 num_reports = skb->data[0]; | 3397 | u8 num_reports = skb->data[0]; |
3352 | void *ptr = &skb->data[1]; | 3398 | void *ptr = &skb->data[1]; |
@@ -3367,8 +3413,7 @@ static inline void hci_le_adv_report_evt(struct hci_dev *hdev, | |||
3367 | hci_dev_unlock(hdev); | 3413 | hci_dev_unlock(hdev); |
3368 | } | 3414 | } |
3369 | 3415 | ||
3370 | static inline void hci_le_ltk_request_evt(struct hci_dev *hdev, | 3416 | static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb) |
3371 | struct sk_buff *skb) | ||
3372 | { | 3417 | { |
3373 | struct hci_ev_le_ltk_req *ev = (void *) skb->data; | 3418 | struct hci_ev_le_ltk_req *ev = (void *) skb->data; |
3374 | struct hci_cp_le_ltk_reply cp; | 3419 | struct hci_cp_le_ltk_reply cp; |
@@ -3411,7 +3456,7 @@ not_found: | |||
3411 | hci_dev_unlock(hdev); | 3456 | hci_dev_unlock(hdev); |
3412 | } | 3457 | } |
3413 | 3458 | ||
3414 | static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) | 3459 | static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) |
3415 | { | 3460 | { |
3416 | struct hci_ev_le_meta *le_ev = (void *) skb->data; | 3461 | struct hci_ev_le_meta *le_ev = (void *) skb->data; |
3417 | 3462 | ||
@@ -3559,6 +3604,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) | |||
3559 | hci_extended_inquiry_result_evt(hdev, skb); | 3604 | hci_extended_inquiry_result_evt(hdev, skb); |
3560 | break; | 3605 | break; |
3561 | 3606 | ||
3607 | case HCI_EV_KEY_REFRESH_COMPLETE: | ||
3608 | hci_key_refresh_complete_evt(hdev, skb); | ||
3609 | break; | ||
3610 | |||
3562 | case HCI_EV_IO_CAPA_REQUEST: | 3611 | case HCI_EV_IO_CAPA_REQUEST: |
3563 | hci_io_capa_request_evt(hdev, skb); | 3612 | hci_io_capa_request_evt(hdev, skb); |
3564 | break; | 3613 | break; |
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 5914623f426..a7f04de03d7 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c | |||
@@ -24,25 +24,7 @@ | |||
24 | 24 | ||
25 | /* Bluetooth HCI sockets. */ | 25 | /* Bluetooth HCI sockets. */ |
26 | 26 | ||
27 | #include <linux/module.h> | 27 | #include <linux/export.h> |
28 | |||
29 | #include <linux/types.h> | ||
30 | #include <linux/capability.h> | ||
31 | #include <linux/errno.h> | ||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/slab.h> | ||
34 | #include <linux/poll.h> | ||
35 | #include <linux/fcntl.h> | ||
36 | #include <linux/init.h> | ||
37 | #include <linux/skbuff.h> | ||
38 | #include <linux/workqueue.h> | ||
39 | #include <linux/interrupt.h> | ||
40 | #include <linux/compat.h> | ||
41 | #include <linux/socket.h> | ||
42 | #include <linux/ioctl.h> | ||
43 | #include <net/sock.h> | ||
44 | |||
45 | #include <linux/uaccess.h> | ||
46 | #include <asm/unaligned.h> | 28 | #include <asm/unaligned.h> |
47 | 29 | ||
48 | #include <net/bluetooth/bluetooth.h> | 30 | #include <net/bluetooth/bluetooth.h> |
@@ -113,11 +95,12 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb) | |||
113 | flt = &hci_pi(sk)->filter; | 95 | flt = &hci_pi(sk)->filter; |
114 | 96 | ||
115 | if (!test_bit((bt_cb(skb)->pkt_type == HCI_VENDOR_PKT) ? | 97 | if (!test_bit((bt_cb(skb)->pkt_type == HCI_VENDOR_PKT) ? |
116 | 0 : (bt_cb(skb)->pkt_type & HCI_FLT_TYPE_BITS), &flt->type_mask)) | 98 | 0 : (bt_cb(skb)->pkt_type & HCI_FLT_TYPE_BITS), |
99 | &flt->type_mask)) | ||
117 | continue; | 100 | continue; |
118 | 101 | ||
119 | if (bt_cb(skb)->pkt_type == HCI_EVENT_PKT) { | 102 | if (bt_cb(skb)->pkt_type == HCI_EVENT_PKT) { |
120 | register int evt = (*(__u8 *)skb->data & HCI_FLT_EVENT_BITS); | 103 | int evt = (*(__u8 *)skb->data & HCI_FLT_EVENT_BITS); |
121 | 104 | ||
122 | if (!hci_test_bit(evt, &flt->event_mask)) | 105 | if (!hci_test_bit(evt, &flt->event_mask)) |
123 | continue; | 106 | continue; |
@@ -240,7 +223,8 @@ void hci_send_to_monitor(struct hci_dev *hdev, struct sk_buff *skb) | |||
240 | struct hci_mon_hdr *hdr; | 223 | struct hci_mon_hdr *hdr; |
241 | 224 | ||
242 | /* Create a private copy with headroom */ | 225 | /* Create a private copy with headroom */ |
243 | skb_copy = __pskb_copy(skb, HCI_MON_HDR_SIZE, GFP_ATOMIC); | 226 | skb_copy = __pskb_copy(skb, HCI_MON_HDR_SIZE, |
227 | GFP_ATOMIC); | ||
244 | if (!skb_copy) | 228 | if (!skb_copy) |
245 | continue; | 229 | continue; |
246 | 230 | ||
@@ -495,7 +479,8 @@ static int hci_sock_blacklist_del(struct hci_dev *hdev, void __user *arg) | |||
495 | } | 479 | } |
496 | 480 | ||
497 | /* Ioctls that require bound socket */ | 481 | /* Ioctls that require bound socket */ |
498 | static inline int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, unsigned long arg) | 482 | static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, |
483 | unsigned long arg) | ||
499 | { | 484 | { |
500 | struct hci_dev *hdev = hci_pi(sk)->hdev; | 485 | struct hci_dev *hdev = hci_pi(sk)->hdev; |
501 | 486 | ||
@@ -540,7 +525,8 @@ static inline int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, unsign | |||
540 | } | 525 | } |
541 | } | 526 | } |
542 | 527 | ||
543 | static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | 528 | static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, |
529 | unsigned long arg) | ||
544 | { | 530 | { |
545 | struct sock *sk = sock->sk; | 531 | struct sock *sk = sock->sk; |
546 | void __user *argp = (void __user *) arg; | 532 | void __user *argp = (void __user *) arg; |
@@ -601,7 +587,8 @@ static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long a | |||
601 | } | 587 | } |
602 | } | 588 | } |
603 | 589 | ||
604 | static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_len) | 590 | static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, |
591 | int addr_len) | ||
605 | { | 592 | { |
606 | struct sockaddr_hci haddr; | 593 | struct sockaddr_hci haddr; |
607 | struct sock *sk = sock->sk; | 594 | struct sock *sk = sock->sk; |
@@ -690,7 +677,8 @@ done: | |||
690 | return err; | 677 | return err; |
691 | } | 678 | } |
692 | 679 | ||
693 | static int hci_sock_getname(struct socket *sock, struct sockaddr *addr, int *addr_len, int peer) | 680 | static int hci_sock_getname(struct socket *sock, struct sockaddr *addr, |
681 | int *addr_len, int peer) | ||
694 | { | 682 | { |
695 | struct sockaddr_hci *haddr = (struct sockaddr_hci *) addr; | 683 | struct sockaddr_hci *haddr = (struct sockaddr_hci *) addr; |
696 | struct sock *sk = sock->sk; | 684 | struct sock *sk = sock->sk; |
@@ -711,13 +699,15 @@ static int hci_sock_getname(struct socket *sock, struct sockaddr *addr, int *add | |||
711 | return 0; | 699 | return 0; |
712 | } | 700 | } |
713 | 701 | ||
714 | static inline void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, struct sk_buff *skb) | 702 | static void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, |
703 | struct sk_buff *skb) | ||
715 | { | 704 | { |
716 | __u32 mask = hci_pi(sk)->cmsg_mask; | 705 | __u32 mask = hci_pi(sk)->cmsg_mask; |
717 | 706 | ||
718 | if (mask & HCI_CMSG_DIR) { | 707 | if (mask & HCI_CMSG_DIR) { |
719 | int incoming = bt_cb(skb)->incoming; | 708 | int incoming = bt_cb(skb)->incoming; |
720 | put_cmsg(msg, SOL_HCI, HCI_CMSG_DIR, sizeof(incoming), &incoming); | 709 | put_cmsg(msg, SOL_HCI, HCI_CMSG_DIR, sizeof(incoming), |
710 | &incoming); | ||
721 | } | 711 | } |
722 | 712 | ||
723 | if (mask & HCI_CMSG_TSTAMP) { | 713 | if (mask & HCI_CMSG_TSTAMP) { |
@@ -747,7 +737,7 @@ static inline void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, struct sk_ | |||
747 | } | 737 | } |
748 | 738 | ||
749 | static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock, | 739 | static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock, |
750 | struct msghdr *msg, size_t len, int flags) | 740 | struct msghdr *msg, size_t len, int flags) |
751 | { | 741 | { |
752 | int noblock = flags & MSG_DONTWAIT; | 742 | int noblock = flags & MSG_DONTWAIT; |
753 | struct sock *sk = sock->sk; | 743 | struct sock *sk = sock->sk; |
@@ -857,8 +847,9 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
857 | u16 ocf = hci_opcode_ocf(opcode); | 847 | u16 ocf = hci_opcode_ocf(opcode); |
858 | 848 | ||
859 | if (((ogf > HCI_SFLT_MAX_OGF) || | 849 | if (((ogf > HCI_SFLT_MAX_OGF) || |
860 | !hci_test_bit(ocf & HCI_FLT_OCF_BITS, &hci_sec_filter.ocf_mask[ogf])) && | 850 | !hci_test_bit(ocf & HCI_FLT_OCF_BITS, |
861 | !capable(CAP_NET_RAW)) { | 851 | &hci_sec_filter.ocf_mask[ogf])) && |
852 | !capable(CAP_NET_RAW)) { | ||
862 | err = -EPERM; | 853 | err = -EPERM; |
863 | goto drop; | 854 | goto drop; |
864 | } | 855 | } |
@@ -891,7 +882,8 @@ drop: | |||
891 | goto done; | 882 | goto done; |
892 | } | 883 | } |
893 | 884 | ||
894 | static int hci_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int len) | 885 | static int hci_sock_setsockopt(struct socket *sock, int level, int optname, |
886 | char __user *optval, unsigned int len) | ||
895 | { | 887 | { |
896 | struct hci_ufilter uf = { .opcode = 0 }; | 888 | struct hci_ufilter uf = { .opcode = 0 }; |
897 | struct sock *sk = sock->sk; | 889 | struct sock *sk = sock->sk; |
@@ -973,7 +965,8 @@ done: | |||
973 | return err; | 965 | return err; |
974 | } | 966 | } |
975 | 967 | ||
976 | static int hci_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) | 968 | static int hci_sock_getsockopt(struct socket *sock, int level, int optname, |
969 | char __user *optval, int __user *optlen) | ||
977 | { | 970 | { |
978 | struct hci_ufilter uf; | 971 | struct hci_ufilter uf; |
979 | struct sock *sk = sock->sk; | 972 | struct sock *sk = sock->sk; |
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index 937f3187eaf..a20e61c3653 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c | |||
@@ -1,10 +1,6 @@ | |||
1 | /* Bluetooth HCI driver model support. */ | 1 | /* Bluetooth HCI driver model support. */ |
2 | 2 | ||
3 | #include <linux/kernel.h> | ||
4 | #include <linux/slab.h> | ||
5 | #include <linux/init.h> | ||
6 | #include <linux/debugfs.h> | 3 | #include <linux/debugfs.h> |
7 | #include <linux/seq_file.h> | ||
8 | #include <linux/module.h> | 4 | #include <linux/module.h> |
9 | 5 | ||
10 | #include <net/bluetooth/bluetooth.h> | 6 | #include <net/bluetooth/bluetooth.h> |
@@ -31,27 +27,30 @@ static inline char *link_typetostr(int type) | |||
31 | } | 27 | } |
32 | } | 28 | } |
33 | 29 | ||
34 | static ssize_t show_link_type(struct device *dev, struct device_attribute *attr, char *buf) | 30 | static ssize_t show_link_type(struct device *dev, |
31 | struct device_attribute *attr, char *buf) | ||
35 | { | 32 | { |
36 | struct hci_conn *conn = to_hci_conn(dev); | 33 | struct hci_conn *conn = to_hci_conn(dev); |
37 | return sprintf(buf, "%s\n", link_typetostr(conn->type)); | 34 | return sprintf(buf, "%s\n", link_typetostr(conn->type)); |
38 | } | 35 | } |
39 | 36 | ||
40 | static ssize_t show_link_address(struct device *dev, struct device_attribute *attr, char *buf) | 37 | static ssize_t show_link_address(struct device *dev, |
38 | struct device_attribute *attr, char *buf) | ||
41 | { | 39 | { |
42 | struct hci_conn *conn = to_hci_conn(dev); | 40 | struct hci_conn *conn = to_hci_conn(dev); |
43 | return sprintf(buf, "%s\n", batostr(&conn->dst)); | 41 | return sprintf(buf, "%s\n", batostr(&conn->dst)); |
44 | } | 42 | } |
45 | 43 | ||
46 | static ssize_t show_link_features(struct device *dev, struct device_attribute *attr, char *buf) | 44 | static ssize_t show_link_features(struct device *dev, |
45 | struct device_attribute *attr, char *buf) | ||
47 | { | 46 | { |
48 | struct hci_conn *conn = to_hci_conn(dev); | 47 | struct hci_conn *conn = to_hci_conn(dev); |
49 | 48 | ||
50 | return sprintf(buf, "0x%02x%02x%02x%02x%02x%02x%02x%02x\n", | 49 | return sprintf(buf, "0x%02x%02x%02x%02x%02x%02x%02x%02x\n", |
51 | conn->features[0], conn->features[1], | 50 | conn->features[0], conn->features[1], |
52 | conn->features[2], conn->features[3], | 51 | conn->features[2], conn->features[3], |
53 | conn->features[4], conn->features[5], | 52 | conn->features[4], conn->features[5], |
54 | conn->features[6], conn->features[7]); | 53 | conn->features[6], conn->features[7]); |
55 | } | 54 | } |
56 | 55 | ||
57 | #define LINK_ATTR(_name, _mode, _show, _store) \ | 56 | #define LINK_ATTR(_name, _mode, _show, _store) \ |
@@ -185,19 +184,22 @@ static inline char *host_typetostr(int type) | |||
185 | } | 184 | } |
186 | } | 185 | } |
187 | 186 | ||
188 | static ssize_t show_bus(struct device *dev, struct device_attribute *attr, char *buf) | 187 | static ssize_t show_bus(struct device *dev, |
188 | struct device_attribute *attr, char *buf) | ||
189 | { | 189 | { |
190 | struct hci_dev *hdev = to_hci_dev(dev); | 190 | struct hci_dev *hdev = to_hci_dev(dev); |
191 | return sprintf(buf, "%s\n", host_bustostr(hdev->bus)); | 191 | return sprintf(buf, "%s\n", host_bustostr(hdev->bus)); |
192 | } | 192 | } |
193 | 193 | ||
194 | static ssize_t show_type(struct device *dev, struct device_attribute *attr, char *buf) | 194 | static ssize_t show_type(struct device *dev, |
195 | struct device_attribute *attr, char *buf) | ||
195 | { | 196 | { |
196 | struct hci_dev *hdev = to_hci_dev(dev); | 197 | struct hci_dev *hdev = to_hci_dev(dev); |
197 | return sprintf(buf, "%s\n", host_typetostr(hdev->dev_type)); | 198 | return sprintf(buf, "%s\n", host_typetostr(hdev->dev_type)); |
198 | } | 199 | } |
199 | 200 | ||
200 | static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf) | 201 | static ssize_t show_name(struct device *dev, |
202 | struct device_attribute *attr, char *buf) | ||
201 | { | 203 | { |
202 | struct hci_dev *hdev = to_hci_dev(dev); | 204 | struct hci_dev *hdev = to_hci_dev(dev); |
203 | char name[HCI_MAX_NAME_LENGTH + 1]; | 205 | char name[HCI_MAX_NAME_LENGTH + 1]; |
@@ -210,55 +212,64 @@ static ssize_t show_name(struct device *dev, struct device_attribute *attr, char | |||
210 | return sprintf(buf, "%s\n", name); | 212 | return sprintf(buf, "%s\n", name); |
211 | } | 213 | } |
212 | 214 | ||
213 | static ssize_t show_class(struct device *dev, struct device_attribute *attr, char *buf) | 215 | static ssize_t show_class(struct device *dev, |
216 | struct device_attribute *attr, char *buf) | ||
214 | { | 217 | { |
215 | struct hci_dev *hdev = to_hci_dev(dev); | 218 | struct hci_dev *hdev = to_hci_dev(dev); |
216 | return sprintf(buf, "0x%.2x%.2x%.2x\n", | 219 | return sprintf(buf, "0x%.2x%.2x%.2x\n", hdev->dev_class[2], |
217 | hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]); | 220 | hdev->dev_class[1], hdev->dev_class[0]); |
218 | } | 221 | } |
219 | 222 | ||
220 | static ssize_t show_address(struct device *dev, struct device_attribute *attr, char *buf) | 223 | static ssize_t show_address(struct device *dev, |
224 | struct device_attribute *attr, char *buf) | ||
221 | { | 225 | { |
222 | struct hci_dev *hdev = to_hci_dev(dev); | 226 | struct hci_dev *hdev = to_hci_dev(dev); |
223 | return sprintf(buf, "%s\n", batostr(&hdev->bdaddr)); | 227 | return sprintf(buf, "%s\n", batostr(&hdev->bdaddr)); |
224 | } | 228 | } |
225 | 229 | ||
226 | static ssize_t show_features(struct device *dev, struct device_attribute *attr, char *buf) | 230 | static ssize_t show_features(struct device *dev, |
231 | struct device_attribute *attr, char *buf) | ||
227 | { | 232 | { |
228 | struct hci_dev *hdev = to_hci_dev(dev); | 233 | struct hci_dev *hdev = to_hci_dev(dev); |
229 | 234 | ||
230 | return sprintf(buf, "0x%02x%02x%02x%02x%02x%02x%02x%02x\n", | 235 | return sprintf(buf, "0x%02x%02x%02x%02x%02x%02x%02x%02x\n", |
231 | hdev->features[0], hdev->features[1], | 236 | hdev->features[0], hdev->features[1], |
232 | hdev->features[2], hdev->features[3], | 237 | hdev->features[2], hdev->features[3], |
233 | hdev->features[4], hdev->features[5], | 238 | hdev->features[4], hdev->features[5], |
234 | hdev->features[6], hdev->features[7]); | 239 | hdev->features[6], hdev->features[7]); |
235 | } | 240 | } |
236 | 241 | ||
237 | static ssize_t show_manufacturer(struct device *dev, struct device_attribute *attr, char *buf) | 242 | static ssize_t show_manufacturer(struct device *dev, |
243 | struct device_attribute *attr, char *buf) | ||
238 | { | 244 | { |
239 | struct hci_dev *hdev = to_hci_dev(dev); | 245 | struct hci_dev *hdev = to_hci_dev(dev); |
240 | return sprintf(buf, "%d\n", hdev->manufacturer); | 246 | return sprintf(buf, "%d\n", hdev->manufacturer); |
241 | } | 247 | } |
242 | 248 | ||
243 | static ssize_t show_hci_version(struct device *dev, struct device_attribute *attr, char *buf) | 249 | static ssize_t show_hci_version(struct device *dev, |
250 | struct device_attribute *attr, char *buf) | ||
244 | { | 251 | { |
245 | struct hci_dev *hdev = to_hci_dev(dev); | 252 | struct hci_dev *hdev = to_hci_dev(dev); |
246 | return sprintf(buf, "%d\n", hdev->hci_ver); | 253 | return sprintf(buf, "%d\n", hdev->hci_ver); |
247 | } | 254 | } |
248 | 255 | ||
249 | static ssize_t show_hci_revision(struct device *dev, struct device_attribute *attr, char *buf) | 256 | static ssize_t show_hci_revision(struct device *dev, |
257 | struct device_attribute *attr, char *buf) | ||
250 | { | 258 | { |
251 | struct hci_dev *hdev = to_hci_dev(dev); | 259 | struct hci_dev *hdev = to_hci_dev(dev); |
252 | return sprintf(buf, "%d\n", hdev->hci_rev); | 260 | return sprintf(buf, "%d\n", hdev->hci_rev); |
253 | } | 261 | } |
254 | 262 | ||
255 | static ssize_t show_idle_timeout(struct device *dev, struct device_attribute *attr, char *buf) | 263 | static ssize_t show_idle_timeout(struct device *dev, |
264 | struct device_attribute *attr, char *buf) | ||
256 | { | 265 | { |
257 | struct hci_dev *hdev = to_hci_dev(dev); | 266 | struct hci_dev *hdev = to_hci_dev(dev); |
258 | return sprintf(buf, "%d\n", hdev->idle_timeout); | 267 | return sprintf(buf, "%d\n", hdev->idle_timeout); |
259 | } | 268 | } |
260 | 269 | ||
261 | static ssize_t store_idle_timeout(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 270 | static ssize_t store_idle_timeout(struct device *dev, |
271 | struct device_attribute *attr, | ||
272 | const char *buf, size_t count) | ||
262 | { | 273 | { |
263 | struct hci_dev *hdev = to_hci_dev(dev); | 274 | struct hci_dev *hdev = to_hci_dev(dev); |
264 | unsigned int val; | 275 | unsigned int val; |
@@ -276,13 +287,16 @@ static ssize_t store_idle_timeout(struct device *dev, struct device_attribute *a | |||
276 | return count; | 287 | return count; |
277 | } | 288 | } |
278 | 289 | ||
279 | static ssize_t show_sniff_max_interval(struct device *dev, struct device_attribute *attr, char *buf) | 290 | static ssize_t show_sniff_max_interval(struct device *dev, |
291 | struct device_attribute *attr, char *buf) | ||
280 | { | 292 | { |
281 | struct hci_dev *hdev = to_hci_dev(dev); | 293 | struct hci_dev *hdev = to_hci_dev(dev); |
282 | return sprintf(buf, "%d\n", hdev->sniff_max_interval); | 294 | return sprintf(buf, "%d\n", hdev->sniff_max_interval); |
283 | } | 295 | } |
284 | 296 | ||
285 | static ssize_t store_sniff_max_interval(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 297 | static ssize_t store_sniff_max_interval(struct device *dev, |
298 | struct device_attribute *attr, | ||
299 | const char *buf, size_t count) | ||
286 | { | 300 | { |
287 | struct hci_dev *hdev = to_hci_dev(dev); | 301 | struct hci_dev *hdev = to_hci_dev(dev); |
288 | u16 val; | 302 | u16 val; |
@@ -300,13 +314,16 @@ static ssize_t store_sniff_max_interval(struct device *dev, struct device_attrib | |||
300 | return count; | 314 | return count; |
301 | } | 315 | } |
302 | 316 | ||
303 | static ssize_t show_sniff_min_interval(struct device *dev, struct device_attribute *attr, char *buf) | 317 | static ssize_t show_sniff_min_interval(struct device *dev, |
318 | struct device_attribute *attr, char *buf) | ||
304 | { | 319 | { |
305 | struct hci_dev *hdev = to_hci_dev(dev); | 320 | struct hci_dev *hdev = to_hci_dev(dev); |
306 | return sprintf(buf, "%d\n", hdev->sniff_min_interval); | 321 | return sprintf(buf, "%d\n", hdev->sniff_min_interval); |
307 | } | 322 | } |
308 | 323 | ||
309 | static ssize_t store_sniff_min_interval(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 324 | static ssize_t store_sniff_min_interval(struct device *dev, |
325 | struct device_attribute *attr, | ||
326 | const char *buf, size_t count) | ||
310 | { | 327 | { |
311 | struct hci_dev *hdev = to_hci_dev(dev); | 328 | struct hci_dev *hdev = to_hci_dev(dev); |
312 | u16 val; | 329 | u16 val; |
@@ -335,11 +352,11 @@ static DEVICE_ATTR(hci_version, S_IRUGO, show_hci_version, NULL); | |||
335 | static DEVICE_ATTR(hci_revision, S_IRUGO, show_hci_revision, NULL); | 352 | static DEVICE_ATTR(hci_revision, S_IRUGO, show_hci_revision, NULL); |
336 | 353 | ||
337 | static DEVICE_ATTR(idle_timeout, S_IRUGO | S_IWUSR, | 354 | static DEVICE_ATTR(idle_timeout, S_IRUGO | S_IWUSR, |
338 | show_idle_timeout, store_idle_timeout); | 355 | show_idle_timeout, store_idle_timeout); |
339 | static DEVICE_ATTR(sniff_max_interval, S_IRUGO | S_IWUSR, | 356 | static DEVICE_ATTR(sniff_max_interval, S_IRUGO | S_IWUSR, |
340 | show_sniff_max_interval, store_sniff_max_interval); | 357 | show_sniff_max_interval, store_sniff_max_interval); |
341 | static DEVICE_ATTR(sniff_min_interval, S_IRUGO | S_IWUSR, | 358 | static DEVICE_ATTR(sniff_min_interval, S_IRUGO | S_IWUSR, |
342 | show_sniff_min_interval, store_sniff_min_interval); | 359 | show_sniff_min_interval, store_sniff_min_interval); |
343 | 360 | ||
344 | static struct attribute *bt_host_attrs[] = { | 361 | static struct attribute *bt_host_attrs[] = { |
345 | &dev_attr_bus.attr, | 362 | &dev_attr_bus.attr, |
@@ -455,8 +472,8 @@ static void print_bt_uuid(struct seq_file *f, u8 *uuid) | |||
455 | memcpy(&data5, &uuid[14], 2); | 472 | memcpy(&data5, &uuid[14], 2); |
456 | 473 | ||
457 | seq_printf(f, "%.8x-%.4x-%.4x-%.4x-%.8x%.4x\n", | 474 | seq_printf(f, "%.8x-%.4x-%.4x-%.4x-%.8x%.4x\n", |
458 | ntohl(data0), ntohs(data1), ntohs(data2), | 475 | ntohl(data0), ntohs(data1), ntohs(data2), ntohs(data3), |
459 | ntohs(data3), ntohl(data4), ntohs(data5)); | 476 | ntohl(data4), ntohs(data5)); |
460 | } | 477 | } |
461 | 478 | ||
462 | static int uuids_show(struct seq_file *f, void *p) | 479 | static int uuids_show(struct seq_file *f, void *p) |
@@ -513,7 +530,7 @@ static int auto_accept_delay_get(void *data, u64 *val) | |||
513 | } | 530 | } |
514 | 531 | ||
515 | DEFINE_SIMPLE_ATTRIBUTE(auto_accept_delay_fops, auto_accept_delay_get, | 532 | DEFINE_SIMPLE_ATTRIBUTE(auto_accept_delay_fops, auto_accept_delay_get, |
516 | auto_accept_delay_set, "%llu\n"); | 533 | auto_accept_delay_set, "%llu\n"); |
517 | 534 | ||
518 | void hci_init_sysfs(struct hci_dev *hdev) | 535 | void hci_init_sysfs(struct hci_dev *hdev) |
519 | { | 536 | { |
@@ -547,15 +564,15 @@ int hci_add_sysfs(struct hci_dev *hdev) | |||
547 | return 0; | 564 | return 0; |
548 | 565 | ||
549 | debugfs_create_file("inquiry_cache", 0444, hdev->debugfs, | 566 | debugfs_create_file("inquiry_cache", 0444, hdev->debugfs, |
550 | hdev, &inquiry_cache_fops); | 567 | hdev, &inquiry_cache_fops); |
551 | 568 | ||
552 | debugfs_create_file("blacklist", 0444, hdev->debugfs, | 569 | debugfs_create_file("blacklist", 0444, hdev->debugfs, |
553 | hdev, &blacklist_fops); | 570 | hdev, &blacklist_fops); |
554 | 571 | ||
555 | debugfs_create_file("uuids", 0444, hdev->debugfs, hdev, &uuids_fops); | 572 | debugfs_create_file("uuids", 0444, hdev->debugfs, hdev, &uuids_fops); |
556 | 573 | ||
557 | debugfs_create_file("auto_accept_delay", 0444, hdev->debugfs, hdev, | 574 | debugfs_create_file("auto_accept_delay", 0444, hdev->debugfs, hdev, |
558 | &auto_accept_delay_fops); | 575 | &auto_accept_delay_fops); |
559 | return 0; | 576 | return 0; |
560 | } | 577 | } |
561 | 578 | ||
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index 2c20d765b39..ccd985da651 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c | |||
@@ -21,27 +21,8 @@ | |||
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | |||
25 | #include <linux/types.h> | ||
26 | #include <linux/errno.h> | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/sched.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/poll.h> | ||
31 | #include <linux/freezer.h> | ||
32 | #include <linux/fcntl.h> | ||
33 | #include <linux/skbuff.h> | ||
34 | #include <linux/socket.h> | ||
35 | #include <linux/ioctl.h> | ||
36 | #include <linux/file.h> | 24 | #include <linux/file.h> |
37 | #include <linux/init.h> | ||
38 | #include <linux/wait.h> | ||
39 | #include <linux/mutex.h> | ||
40 | #include <linux/kthread.h> | 25 | #include <linux/kthread.h> |
41 | #include <net/sock.h> | ||
42 | |||
43 | #include <linux/input.h> | ||
44 | #include <linux/hid.h> | ||
45 | #include <linux/hidraw.h> | 26 | #include <linux/hidraw.h> |
46 | 27 | ||
47 | #include <net/bluetooth/bluetooth.h> | 28 | #include <net/bluetooth/bluetooth.h> |
@@ -244,7 +225,8 @@ static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb) | |||
244 | } | 225 | } |
245 | 226 | ||
246 | static int __hidp_send_ctrl_message(struct hidp_session *session, | 227 | static int __hidp_send_ctrl_message(struct hidp_session *session, |
247 | unsigned char hdr, unsigned char *data, int size) | 228 | unsigned char hdr, unsigned char *data, |
229 | int size) | ||
248 | { | 230 | { |
249 | struct sk_buff *skb; | 231 | struct sk_buff *skb; |
250 | 232 | ||
@@ -268,7 +250,7 @@ static int __hidp_send_ctrl_message(struct hidp_session *session, | |||
268 | return 0; | 250 | return 0; |
269 | } | 251 | } |
270 | 252 | ||
271 | static inline int hidp_send_ctrl_message(struct hidp_session *session, | 253 | static int hidp_send_ctrl_message(struct hidp_session *session, |
272 | unsigned char hdr, unsigned char *data, int size) | 254 | unsigned char hdr, unsigned char *data, int size) |
273 | { | 255 | { |
274 | int err; | 256 | int err; |
@@ -471,7 +453,7 @@ static void hidp_set_timer(struct hidp_session *session) | |||
471 | mod_timer(&session->timer, jiffies + HZ * session->idle_to); | 453 | mod_timer(&session->timer, jiffies + HZ * session->idle_to); |
472 | } | 454 | } |
473 | 455 | ||
474 | static inline void hidp_del_timer(struct hidp_session *session) | 456 | static void hidp_del_timer(struct hidp_session *session) |
475 | { | 457 | { |
476 | if (session->idle_to > 0) | 458 | if (session->idle_to > 0) |
477 | del_timer(&session->timer); | 459 | del_timer(&session->timer); |
diff --git a/net/bluetooth/hidp/sock.c b/net/bluetooth/hidp/sock.c index 73a32d705c1..18b3f6892a3 100644 --- a/net/bluetooth/hidp/sock.c +++ b/net/bluetooth/hidp/sock.c | |||
@@ -20,22 +20,8 @@ | |||
20 | SOFTWARE IS DISCLAIMED. | 20 | SOFTWARE IS DISCLAIMED. |
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <linux/module.h> | 23 | #include <linux/export.h> |
24 | |||
25 | #include <linux/types.h> | ||
26 | #include <linux/capability.h> | ||
27 | #include <linux/errno.h> | ||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/poll.h> | ||
30 | #include <linux/fcntl.h> | ||
31 | #include <linux/skbuff.h> | ||
32 | #include <linux/socket.h> | ||
33 | #include <linux/ioctl.h> | ||
34 | #include <linux/file.h> | 24 | #include <linux/file.h> |
35 | #include <linux/init.h> | ||
36 | #include <linux/compat.h> | ||
37 | #include <linux/gfp.h> | ||
38 | #include <net/sock.h> | ||
39 | 25 | ||
40 | #include "hidp.h" | 26 | #include "hidp.h" |
41 | 27 | ||
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 24f144b72a9..4ca88247b7c 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -30,32 +30,14 @@ | |||
30 | 30 | ||
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | 32 | ||
33 | #include <linux/types.h> | ||
34 | #include <linux/capability.h> | ||
35 | #include <linux/errno.h> | ||
36 | #include <linux/kernel.h> | ||
37 | #include <linux/sched.h> | ||
38 | #include <linux/slab.h> | ||
39 | #include <linux/poll.h> | ||
40 | #include <linux/fcntl.h> | ||
41 | #include <linux/init.h> | ||
42 | #include <linux/interrupt.h> | ||
43 | #include <linux/socket.h> | ||
44 | #include <linux/skbuff.h> | ||
45 | #include <linux/list.h> | ||
46 | #include <linux/device.h> | ||
47 | #include <linux/debugfs.h> | 33 | #include <linux/debugfs.h> |
48 | #include <linux/seq_file.h> | ||
49 | #include <linux/uaccess.h> | ||
50 | #include <linux/crc16.h> | 34 | #include <linux/crc16.h> |
51 | #include <net/sock.h> | ||
52 | |||
53 | #include <asm/unaligned.h> | ||
54 | 35 | ||
55 | #include <net/bluetooth/bluetooth.h> | 36 | #include <net/bluetooth/bluetooth.h> |
56 | #include <net/bluetooth/hci_core.h> | 37 | #include <net/bluetooth/hci_core.h> |
57 | #include <net/bluetooth/l2cap.h> | 38 | #include <net/bluetooth/l2cap.h> |
58 | #include <net/bluetooth/smp.h> | 39 | #include <net/bluetooth/smp.h> |
40 | #include <net/bluetooth/a2mp.h> | ||
59 | 41 | ||
60 | bool disable_ertm; | 42 | bool disable_ertm; |
61 | 43 | ||
@@ -73,6 +55,9 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data); | |||
73 | static void l2cap_send_disconn_req(struct l2cap_conn *conn, | 55 | static void l2cap_send_disconn_req(struct l2cap_conn *conn, |
74 | struct l2cap_chan *chan, int err); | 56 | struct l2cap_chan *chan, int err); |
75 | 57 | ||
58 | static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, | ||
59 | struct sk_buff_head *skbs, u8 event); | ||
60 | |||
76 | /* ---- L2CAP channels ---- */ | 61 | /* ---- L2CAP channels ---- */ |
77 | 62 | ||
78 | static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid) | 63 | static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid) |
@@ -196,7 +181,7 @@ static void __l2cap_state_change(struct l2cap_chan *chan, int state) | |||
196 | state_to_string(state)); | 181 | state_to_string(state)); |
197 | 182 | ||
198 | chan->state = state; | 183 | chan->state = state; |
199 | chan->ops->state_change(chan->data, state); | 184 | chan->ops->state_change(chan, state); |
200 | } | 185 | } |
201 | 186 | ||
202 | static void l2cap_state_change(struct l2cap_chan *chan, int state) | 187 | static void l2cap_state_change(struct l2cap_chan *chan, int state) |
@@ -224,6 +209,37 @@ static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err) | |||
224 | release_sock(sk); | 209 | release_sock(sk); |
225 | } | 210 | } |
226 | 211 | ||
212 | static void __set_retrans_timer(struct l2cap_chan *chan) | ||
213 | { | ||
214 | if (!delayed_work_pending(&chan->monitor_timer) && | ||
215 | chan->retrans_timeout) { | ||
216 | l2cap_set_timer(chan, &chan->retrans_timer, | ||
217 | msecs_to_jiffies(chan->retrans_timeout)); | ||
218 | } | ||
219 | } | ||
220 | |||
221 | static void __set_monitor_timer(struct l2cap_chan *chan) | ||
222 | { | ||
223 | __clear_retrans_timer(chan); | ||
224 | if (chan->monitor_timeout) { | ||
225 | l2cap_set_timer(chan, &chan->monitor_timer, | ||
226 | msecs_to_jiffies(chan->monitor_timeout)); | ||
227 | } | ||
228 | } | ||
229 | |||
230 | static struct sk_buff *l2cap_ertm_seq_in_queue(struct sk_buff_head *head, | ||
231 | u16 seq) | ||
232 | { | ||
233 | struct sk_buff *skb; | ||
234 | |||
235 | skb_queue_walk(head, skb) { | ||
236 | if (bt_cb(skb)->control.txseq == seq) | ||
237 | return skb; | ||
238 | } | ||
239 | |||
240 | return NULL; | ||
241 | } | ||
242 | |||
227 | /* ---- L2CAP sequence number lists ---- */ | 243 | /* ---- L2CAP sequence number lists ---- */ |
228 | 244 | ||
229 | /* For ERTM, ordered lists of sequence numbers must be tracked for | 245 | /* For ERTM, ordered lists of sequence numbers must be tracked for |
@@ -366,7 +382,7 @@ static void l2cap_chan_timeout(struct work_struct *work) | |||
366 | 382 | ||
367 | l2cap_chan_unlock(chan); | 383 | l2cap_chan_unlock(chan); |
368 | 384 | ||
369 | chan->ops->close(chan->data); | 385 | chan->ops->close(chan); |
370 | mutex_unlock(&conn->chan_lock); | 386 | mutex_unlock(&conn->chan_lock); |
371 | 387 | ||
372 | l2cap_chan_put(chan); | 388 | l2cap_chan_put(chan); |
@@ -392,6 +408,9 @@ struct l2cap_chan *l2cap_chan_create(void) | |||
392 | 408 | ||
393 | atomic_set(&chan->refcnt, 1); | 409 | atomic_set(&chan->refcnt, 1); |
394 | 410 | ||
411 | /* This flag is cleared in l2cap_chan_ready() */ | ||
412 | set_bit(CONF_NOT_COMPLETE, &chan->conf_state); | ||
413 | |||
395 | BT_DBG("chan %p", chan); | 414 | BT_DBG("chan %p", chan); |
396 | 415 | ||
397 | return chan; | 416 | return chan; |
@@ -430,7 +449,7 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) | |||
430 | case L2CAP_CHAN_CONN_ORIENTED: | 449 | case L2CAP_CHAN_CONN_ORIENTED: |
431 | if (conn->hcon->type == LE_LINK) { | 450 | if (conn->hcon->type == LE_LINK) { |
432 | /* LE connection */ | 451 | /* LE connection */ |
433 | chan->omtu = L2CAP_LE_DEFAULT_MTU; | 452 | chan->omtu = L2CAP_DEFAULT_MTU; |
434 | chan->scid = L2CAP_CID_LE_DATA; | 453 | chan->scid = L2CAP_CID_LE_DATA; |
435 | chan->dcid = L2CAP_CID_LE_DATA; | 454 | chan->dcid = L2CAP_CID_LE_DATA; |
436 | } else { | 455 | } else { |
@@ -447,6 +466,13 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) | |||
447 | chan->omtu = L2CAP_DEFAULT_MTU; | 466 | chan->omtu = L2CAP_DEFAULT_MTU; |
448 | break; | 467 | break; |
449 | 468 | ||
469 | case L2CAP_CHAN_CONN_FIX_A2MP: | ||
470 | chan->scid = L2CAP_CID_A2MP; | ||
471 | chan->dcid = L2CAP_CID_A2MP; | ||
472 | chan->omtu = L2CAP_A2MP_DEFAULT_MTU; | ||
473 | chan->imtu = L2CAP_A2MP_DEFAULT_MTU; | ||
474 | break; | ||
475 | |||
450 | default: | 476 | default: |
451 | /* Raw socket can send/recv signalling messages only */ | 477 | /* Raw socket can send/recv signalling messages only */ |
452 | chan->scid = L2CAP_CID_SIGNALING; | 478 | chan->scid = L2CAP_CID_SIGNALING; |
@@ -466,18 +492,16 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) | |||
466 | list_add(&chan->list, &conn->chan_l); | 492 | list_add(&chan->list, &conn->chan_l); |
467 | } | 493 | } |
468 | 494 | ||
469 | static void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) | 495 | void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) |
470 | { | 496 | { |
471 | mutex_lock(&conn->chan_lock); | 497 | mutex_lock(&conn->chan_lock); |
472 | __l2cap_chan_add(conn, chan); | 498 | __l2cap_chan_add(conn, chan); |
473 | mutex_unlock(&conn->chan_lock); | 499 | mutex_unlock(&conn->chan_lock); |
474 | } | 500 | } |
475 | 501 | ||
476 | static void l2cap_chan_del(struct l2cap_chan *chan, int err) | 502 | void l2cap_chan_del(struct l2cap_chan *chan, int err) |
477 | { | 503 | { |
478 | struct sock *sk = chan->sk; | ||
479 | struct l2cap_conn *conn = chan->conn; | 504 | struct l2cap_conn *conn = chan->conn; |
480 | struct sock *parent = bt_sk(sk)->parent; | ||
481 | 505 | ||
482 | __clear_chan_timer(chan); | 506 | __clear_chan_timer(chan); |
483 | 507 | ||
@@ -490,34 +514,22 @@ static void l2cap_chan_del(struct l2cap_chan *chan, int err) | |||
490 | l2cap_chan_put(chan); | 514 | l2cap_chan_put(chan); |
491 | 515 | ||
492 | chan->conn = NULL; | 516 | chan->conn = NULL; |
493 | hci_conn_put(conn->hcon); | ||
494 | } | ||
495 | |||
496 | lock_sock(sk); | ||
497 | |||
498 | __l2cap_state_change(chan, BT_CLOSED); | ||
499 | sock_set_flag(sk, SOCK_ZAPPED); | ||
500 | 517 | ||
501 | if (err) | 518 | if (chan->chan_type != L2CAP_CHAN_CONN_FIX_A2MP) |
502 | __l2cap_chan_set_err(chan, err); | 519 | hci_conn_put(conn->hcon); |
520 | } | ||
503 | 521 | ||
504 | if (parent) { | 522 | if (chan->ops->teardown) |
505 | bt_accept_unlink(sk); | 523 | chan->ops->teardown(chan, err); |
506 | parent->sk_data_ready(parent, 0); | ||
507 | } else | ||
508 | sk->sk_state_change(sk); | ||
509 | 524 | ||
510 | release_sock(sk); | 525 | if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state)) |
511 | |||
512 | if (!(test_bit(CONF_OUTPUT_DONE, &chan->conf_state) && | ||
513 | test_bit(CONF_INPUT_DONE, &chan->conf_state))) | ||
514 | return; | 526 | return; |
515 | 527 | ||
516 | skb_queue_purge(&chan->tx_q); | 528 | switch(chan->mode) { |
517 | 529 | case L2CAP_MODE_BASIC: | |
518 | if (chan->mode == L2CAP_MODE_ERTM) { | 530 | break; |
519 | struct srej_list *l, *tmp; | ||
520 | 531 | ||
532 | case L2CAP_MODE_ERTM: | ||
521 | __clear_retrans_timer(chan); | 533 | __clear_retrans_timer(chan); |
522 | __clear_monitor_timer(chan); | 534 | __clear_monitor_timer(chan); |
523 | __clear_ack_timer(chan); | 535 | __clear_ack_timer(chan); |
@@ -526,30 +538,15 @@ static void l2cap_chan_del(struct l2cap_chan *chan, int err) | |||
526 | 538 | ||
527 | l2cap_seq_list_free(&chan->srej_list); | 539 | l2cap_seq_list_free(&chan->srej_list); |
528 | l2cap_seq_list_free(&chan->retrans_list); | 540 | l2cap_seq_list_free(&chan->retrans_list); |
529 | list_for_each_entry_safe(l, tmp, &chan->srej_l, list) { | ||
530 | list_del(&l->list); | ||
531 | kfree(l); | ||
532 | } | ||
533 | } | ||
534 | } | ||
535 | |||
536 | static void l2cap_chan_cleanup_listen(struct sock *parent) | ||
537 | { | ||
538 | struct sock *sk; | ||
539 | |||
540 | BT_DBG("parent %p", parent); | ||
541 | 541 | ||
542 | /* Close not yet accepted channels */ | 542 | /* fall through */ |
543 | while ((sk = bt_accept_dequeue(parent, NULL))) { | ||
544 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; | ||
545 | |||
546 | l2cap_chan_lock(chan); | ||
547 | __clear_chan_timer(chan); | ||
548 | l2cap_chan_close(chan, ECONNRESET); | ||
549 | l2cap_chan_unlock(chan); | ||
550 | 543 | ||
551 | chan->ops->close(chan->data); | 544 | case L2CAP_MODE_STREAMING: |
545 | skb_queue_purge(&chan->tx_q); | ||
546 | break; | ||
552 | } | 547 | } |
548 | |||
549 | return; | ||
553 | } | 550 | } |
554 | 551 | ||
555 | void l2cap_chan_close(struct l2cap_chan *chan, int reason) | 552 | void l2cap_chan_close(struct l2cap_chan *chan, int reason) |
@@ -562,12 +559,8 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason) | |||
562 | 559 | ||
563 | switch (chan->state) { | 560 | switch (chan->state) { |
564 | case BT_LISTEN: | 561 | case BT_LISTEN: |
565 | lock_sock(sk); | 562 | if (chan->ops->teardown) |
566 | l2cap_chan_cleanup_listen(sk); | 563 | chan->ops->teardown(chan, 0); |
567 | |||
568 | __l2cap_state_change(chan, BT_CLOSED); | ||
569 | sock_set_flag(sk, SOCK_ZAPPED); | ||
570 | release_sock(sk); | ||
571 | break; | 564 | break; |
572 | 565 | ||
573 | case BT_CONNECTED: | 566 | case BT_CONNECTED: |
@@ -595,7 +588,7 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason) | |||
595 | rsp.scid = cpu_to_le16(chan->dcid); | 588 | rsp.scid = cpu_to_le16(chan->dcid); |
596 | rsp.dcid = cpu_to_le16(chan->scid); | 589 | rsp.dcid = cpu_to_le16(chan->scid); |
597 | rsp.result = cpu_to_le16(result); | 590 | rsp.result = cpu_to_le16(result); |
598 | rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); | 591 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); |
599 | l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, | 592 | l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, |
600 | sizeof(rsp), &rsp); | 593 | sizeof(rsp), &rsp); |
601 | } | 594 | } |
@@ -609,9 +602,8 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason) | |||
609 | break; | 602 | break; |
610 | 603 | ||
611 | default: | 604 | default: |
612 | lock_sock(sk); | 605 | if (chan->ops->teardown) |
613 | sock_set_flag(sk, SOCK_ZAPPED); | 606 | chan->ops->teardown(chan, 0); |
614 | release_sock(sk); | ||
615 | break; | 607 | break; |
616 | } | 608 | } |
617 | } | 609 | } |
@@ -627,7 +619,7 @@ static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) | |||
627 | default: | 619 | default: |
628 | return HCI_AT_NO_BONDING; | 620 | return HCI_AT_NO_BONDING; |
629 | } | 621 | } |
630 | } else if (chan->psm == cpu_to_le16(0x0001)) { | 622 | } else if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_SDP)) { |
631 | if (chan->sec_level == BT_SECURITY_LOW) | 623 | if (chan->sec_level == BT_SECURITY_LOW) |
632 | chan->sec_level = BT_SECURITY_SDP; | 624 | chan->sec_level = BT_SECURITY_SDP; |
633 | 625 | ||
@@ -773,9 +765,11 @@ static inline void __unpack_control(struct l2cap_chan *chan, | |||
773 | if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { | 765 | if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { |
774 | __unpack_extended_control(get_unaligned_le32(skb->data), | 766 | __unpack_extended_control(get_unaligned_le32(skb->data), |
775 | &bt_cb(skb)->control); | 767 | &bt_cb(skb)->control); |
768 | skb_pull(skb, L2CAP_EXT_CTRL_SIZE); | ||
776 | } else { | 769 | } else { |
777 | __unpack_enhanced_control(get_unaligned_le16(skb->data), | 770 | __unpack_enhanced_control(get_unaligned_le16(skb->data), |
778 | &bt_cb(skb)->control); | 771 | &bt_cb(skb)->control); |
772 | skb_pull(skb, L2CAP_ENH_CTRL_SIZE); | ||
779 | } | 773 | } |
780 | } | 774 | } |
781 | 775 | ||
@@ -830,66 +824,102 @@ static inline void __pack_control(struct l2cap_chan *chan, | |||
830 | } | 824 | } |
831 | } | 825 | } |
832 | 826 | ||
833 | static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control) | 827 | static inline unsigned int __ertm_hdr_size(struct l2cap_chan *chan) |
834 | { | 828 | { |
835 | struct sk_buff *skb; | ||
836 | struct l2cap_hdr *lh; | ||
837 | struct l2cap_conn *conn = chan->conn; | ||
838 | int count, hlen; | ||
839 | |||
840 | if (chan->state != BT_CONNECTED) | ||
841 | return; | ||
842 | |||
843 | if (test_bit(FLAG_EXT_CTRL, &chan->flags)) | 829 | if (test_bit(FLAG_EXT_CTRL, &chan->flags)) |
844 | hlen = L2CAP_EXT_HDR_SIZE; | 830 | return L2CAP_EXT_HDR_SIZE; |
845 | else | 831 | else |
846 | hlen = L2CAP_ENH_HDR_SIZE; | 832 | return L2CAP_ENH_HDR_SIZE; |
833 | } | ||
834 | |||
835 | static struct sk_buff *l2cap_create_sframe_pdu(struct l2cap_chan *chan, | ||
836 | u32 control) | ||
837 | { | ||
838 | struct sk_buff *skb; | ||
839 | struct l2cap_hdr *lh; | ||
840 | int hlen = __ertm_hdr_size(chan); | ||
847 | 841 | ||
848 | if (chan->fcs == L2CAP_FCS_CRC16) | 842 | if (chan->fcs == L2CAP_FCS_CRC16) |
849 | hlen += L2CAP_FCS_SIZE; | 843 | hlen += L2CAP_FCS_SIZE; |
850 | 844 | ||
851 | BT_DBG("chan %p, control 0x%8.8x", chan, control); | 845 | skb = bt_skb_alloc(hlen, GFP_KERNEL); |
852 | |||
853 | count = min_t(unsigned int, conn->mtu, hlen); | ||
854 | |||
855 | control |= __set_sframe(chan); | ||
856 | 846 | ||
857 | if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) | ||
858 | control |= __set_ctrl_final(chan); | ||
859 | |||
860 | if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state)) | ||
861 | control |= __set_ctrl_poll(chan); | ||
862 | |||
863 | skb = bt_skb_alloc(count, GFP_ATOMIC); | ||
864 | if (!skb) | 847 | if (!skb) |
865 | return; | 848 | return ERR_PTR(-ENOMEM); |
866 | 849 | ||
867 | lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); | 850 | lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); |
868 | lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE); | 851 | lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE); |
869 | lh->cid = cpu_to_le16(chan->dcid); | 852 | lh->cid = cpu_to_le16(chan->dcid); |
870 | 853 | ||
871 | __put_control(chan, control, skb_put(skb, __ctrl_size(chan))); | 854 | if (test_bit(FLAG_EXT_CTRL, &chan->flags)) |
855 | put_unaligned_le32(control, skb_put(skb, L2CAP_EXT_CTRL_SIZE)); | ||
856 | else | ||
857 | put_unaligned_le16(control, skb_put(skb, L2CAP_ENH_CTRL_SIZE)); | ||
872 | 858 | ||
873 | if (chan->fcs == L2CAP_FCS_CRC16) { | 859 | if (chan->fcs == L2CAP_FCS_CRC16) { |
874 | u16 fcs = crc16(0, (u8 *)lh, count - L2CAP_FCS_SIZE); | 860 | u16 fcs = crc16(0, (u8 *)skb->data, skb->len); |
875 | put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); | 861 | put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); |
876 | } | 862 | } |
877 | 863 | ||
878 | skb->priority = HCI_PRIO_MAX; | 864 | skb->priority = HCI_PRIO_MAX; |
879 | l2cap_do_send(chan, skb); | 865 | return skb; |
880 | } | 866 | } |
881 | 867 | ||
882 | static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control) | 868 | static void l2cap_send_sframe(struct l2cap_chan *chan, |
869 | struct l2cap_ctrl *control) | ||
883 | { | 870 | { |
884 | if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { | 871 | struct sk_buff *skb; |
885 | control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR); | 872 | u32 control_field; |
873 | |||
874 | BT_DBG("chan %p, control %p", chan, control); | ||
875 | |||
876 | if (!control->sframe) | ||
877 | return; | ||
878 | |||
879 | if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) && | ||
880 | !control->poll) | ||
881 | control->final = 1; | ||
882 | |||
883 | if (control->super == L2CAP_SUPER_RR) | ||
884 | clear_bit(CONN_RNR_SENT, &chan->conn_state); | ||
885 | else if (control->super == L2CAP_SUPER_RNR) | ||
886 | set_bit(CONN_RNR_SENT, &chan->conn_state); | 886 | set_bit(CONN_RNR_SENT, &chan->conn_state); |
887 | } else | ||
888 | control |= __set_ctrl_super(chan, L2CAP_SUPER_RR); | ||
889 | 887 | ||
890 | control |= __set_reqseq(chan, chan->buffer_seq); | 888 | if (control->super != L2CAP_SUPER_SREJ) { |
889 | chan->last_acked_seq = control->reqseq; | ||
890 | __clear_ack_timer(chan); | ||
891 | } | ||
892 | |||
893 | BT_DBG("reqseq %d, final %d, poll %d, super %d", control->reqseq, | ||
894 | control->final, control->poll, control->super); | ||
895 | |||
896 | if (test_bit(FLAG_EXT_CTRL, &chan->flags)) | ||
897 | control_field = __pack_extended_control(control); | ||
898 | else | ||
899 | control_field = __pack_enhanced_control(control); | ||
900 | |||
901 | skb = l2cap_create_sframe_pdu(chan, control_field); | ||
902 | if (!IS_ERR(skb)) | ||
903 | l2cap_do_send(chan, skb); | ||
904 | } | ||
905 | |||
906 | static void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, bool poll) | ||
907 | { | ||
908 | struct l2cap_ctrl control; | ||
909 | |||
910 | BT_DBG("chan %p, poll %d", chan, poll); | ||
911 | |||
912 | memset(&control, 0, sizeof(control)); | ||
913 | control.sframe = 1; | ||
914 | control.poll = poll; | ||
891 | 915 | ||
892 | l2cap_send_sframe(chan, control); | 916 | if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) |
917 | control.super = L2CAP_SUPER_RNR; | ||
918 | else | ||
919 | control.super = L2CAP_SUPER_RR; | ||
920 | |||
921 | control.reqseq = chan->buffer_seq; | ||
922 | l2cap_send_sframe(chan, &control); | ||
893 | } | 923 | } |
894 | 924 | ||
895 | static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan) | 925 | static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan) |
@@ -914,25 +944,13 @@ static void l2cap_send_conn_req(struct l2cap_chan *chan) | |||
914 | 944 | ||
915 | static void l2cap_chan_ready(struct l2cap_chan *chan) | 945 | static void l2cap_chan_ready(struct l2cap_chan *chan) |
916 | { | 946 | { |
917 | struct sock *sk = chan->sk; | 947 | /* This clears all conf flags, including CONF_NOT_COMPLETE */ |
918 | struct sock *parent; | ||
919 | |||
920 | lock_sock(sk); | ||
921 | |||
922 | parent = bt_sk(sk)->parent; | ||
923 | |||
924 | BT_DBG("sk %p, parent %p", sk, parent); | ||
925 | |||
926 | chan->conf_state = 0; | 948 | chan->conf_state = 0; |
927 | __clear_chan_timer(chan); | 949 | __clear_chan_timer(chan); |
928 | 950 | ||
929 | __l2cap_state_change(chan, BT_CONNECTED); | 951 | chan->state = BT_CONNECTED; |
930 | sk->sk_state_change(sk); | ||
931 | |||
932 | if (parent) | ||
933 | parent->sk_data_ready(parent, 0); | ||
934 | 952 | ||
935 | release_sock(sk); | 953 | chan->ops->ready(chan); |
936 | } | 954 | } |
937 | 955 | ||
938 | static void l2cap_do_start(struct l2cap_chan *chan) | 956 | static void l2cap_do_start(struct l2cap_chan *chan) |
@@ -953,7 +971,7 @@ static void l2cap_do_start(struct l2cap_chan *chan) | |||
953 | l2cap_send_conn_req(chan); | 971 | l2cap_send_conn_req(chan); |
954 | } else { | 972 | } else { |
955 | struct l2cap_info_req req; | 973 | struct l2cap_info_req req; |
956 | req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK); | 974 | req.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK); |
957 | 975 | ||
958 | conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; | 976 | conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; |
959 | conn->info_ident = l2cap_get_ident(conn); | 977 | conn->info_ident = l2cap_get_ident(conn); |
@@ -995,6 +1013,11 @@ static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *c | |||
995 | __clear_ack_timer(chan); | 1013 | __clear_ack_timer(chan); |
996 | } | 1014 | } |
997 | 1015 | ||
1016 | if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) { | ||
1017 | __l2cap_state_change(chan, BT_DISCONN); | ||
1018 | return; | ||
1019 | } | ||
1020 | |||
998 | req.dcid = cpu_to_le16(chan->dcid); | 1021 | req.dcid = cpu_to_le16(chan->dcid); |
999 | req.scid = cpu_to_le16(chan->scid); | 1022 | req.scid = cpu_to_le16(chan->scid); |
1000 | l2cap_send_cmd(conn, l2cap_get_ident(conn), | 1023 | l2cap_send_cmd(conn, l2cap_get_ident(conn), |
@@ -1053,20 +1076,20 @@ static void l2cap_conn_start(struct l2cap_conn *conn) | |||
1053 | if (test_bit(BT_SK_DEFER_SETUP, | 1076 | if (test_bit(BT_SK_DEFER_SETUP, |
1054 | &bt_sk(sk)->flags)) { | 1077 | &bt_sk(sk)->flags)) { |
1055 | struct sock *parent = bt_sk(sk)->parent; | 1078 | struct sock *parent = bt_sk(sk)->parent; |
1056 | rsp.result = cpu_to_le16(L2CAP_CR_PEND); | 1079 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND); |
1057 | rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND); | 1080 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHOR_PEND); |
1058 | if (parent) | 1081 | if (parent) |
1059 | parent->sk_data_ready(parent, 0); | 1082 | parent->sk_data_ready(parent, 0); |
1060 | 1083 | ||
1061 | } else { | 1084 | } else { |
1062 | __l2cap_state_change(chan, BT_CONFIG); | 1085 | __l2cap_state_change(chan, BT_CONFIG); |
1063 | rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); | 1086 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); |
1064 | rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); | 1087 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); |
1065 | } | 1088 | } |
1066 | release_sock(sk); | 1089 | release_sock(sk); |
1067 | } else { | 1090 | } else { |
1068 | rsp.result = cpu_to_le16(L2CAP_CR_PEND); | 1091 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND); |
1069 | rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND); | 1092 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHEN_PEND); |
1070 | } | 1093 | } |
1071 | 1094 | ||
1072 | l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, | 1095 | l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, |
@@ -1150,13 +1173,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) | |||
1150 | 1173 | ||
1151 | lock_sock(parent); | 1174 | lock_sock(parent); |
1152 | 1175 | ||
1153 | /* Check for backlog size */ | 1176 | chan = pchan->ops->new_connection(pchan); |
1154 | if (sk_acceptq_is_full(parent)) { | ||
1155 | BT_DBG("backlog full %d", parent->sk_ack_backlog); | ||
1156 | goto clean; | ||
1157 | } | ||
1158 | |||
1159 | chan = pchan->ops->new_connection(pchan->data); | ||
1160 | if (!chan) | 1177 | if (!chan) |
1161 | goto clean; | 1178 | goto clean; |
1162 | 1179 | ||
@@ -1171,10 +1188,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) | |||
1171 | 1188 | ||
1172 | l2cap_chan_add(conn, chan); | 1189 | l2cap_chan_add(conn, chan); |
1173 | 1190 | ||
1174 | __set_chan_timer(chan, sk->sk_sndtimeo); | 1191 | l2cap_chan_ready(chan); |
1175 | |||
1176 | __l2cap_state_change(chan, BT_CONNECTED); | ||
1177 | parent->sk_data_ready(parent, 0); | ||
1178 | 1192 | ||
1179 | clean: | 1193 | clean: |
1180 | release_sock(parent); | 1194 | release_sock(parent); |
@@ -1198,6 +1212,11 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) | |||
1198 | 1212 | ||
1199 | l2cap_chan_lock(chan); | 1213 | l2cap_chan_lock(chan); |
1200 | 1214 | ||
1215 | if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) { | ||
1216 | l2cap_chan_unlock(chan); | ||
1217 | continue; | ||
1218 | } | ||
1219 | |||
1201 | if (conn->hcon->type == LE_LINK) { | 1220 | if (conn->hcon->type == LE_LINK) { |
1202 | if (smp_conn_security(conn, chan->sec_level)) | 1221 | if (smp_conn_security(conn, chan->sec_level)) |
1203 | l2cap_chan_ready(chan); | 1222 | l2cap_chan_ready(chan); |
@@ -1270,7 +1289,7 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) | |||
1270 | 1289 | ||
1271 | l2cap_chan_unlock(chan); | 1290 | l2cap_chan_unlock(chan); |
1272 | 1291 | ||
1273 | chan->ops->close(chan->data); | 1292 | chan->ops->close(chan); |
1274 | l2cap_chan_put(chan); | 1293 | l2cap_chan_put(chan); |
1275 | } | 1294 | } |
1276 | 1295 | ||
@@ -1295,7 +1314,12 @@ static void security_timeout(struct work_struct *work) | |||
1295 | struct l2cap_conn *conn = container_of(work, struct l2cap_conn, | 1314 | struct l2cap_conn *conn = container_of(work, struct l2cap_conn, |
1296 | security_timer.work); | 1315 | security_timer.work); |
1297 | 1316 | ||
1298 | l2cap_conn_del(conn->hcon, ETIMEDOUT); | 1317 | BT_DBG("conn %p", conn); |
1318 | |||
1319 | if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) { | ||
1320 | smp_chan_destroy(conn); | ||
1321 | l2cap_conn_del(conn->hcon, ETIMEDOUT); | ||
1322 | } | ||
1299 | } | 1323 | } |
1300 | 1324 | ||
1301 | static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status) | 1325 | static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status) |
@@ -1439,21 +1463,17 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, | |||
1439 | goto done; | 1463 | goto done; |
1440 | } | 1464 | } |
1441 | 1465 | ||
1442 | lock_sock(sk); | 1466 | switch (chan->state) { |
1443 | |||
1444 | switch (sk->sk_state) { | ||
1445 | case BT_CONNECT: | 1467 | case BT_CONNECT: |
1446 | case BT_CONNECT2: | 1468 | case BT_CONNECT2: |
1447 | case BT_CONFIG: | 1469 | case BT_CONFIG: |
1448 | /* Already connecting */ | 1470 | /* Already connecting */ |
1449 | err = 0; | 1471 | err = 0; |
1450 | release_sock(sk); | ||
1451 | goto done; | 1472 | goto done; |
1452 | 1473 | ||
1453 | case BT_CONNECTED: | 1474 | case BT_CONNECTED: |
1454 | /* Already connected */ | 1475 | /* Already connected */ |
1455 | err = -EISCONN; | 1476 | err = -EISCONN; |
1456 | release_sock(sk); | ||
1457 | goto done; | 1477 | goto done; |
1458 | 1478 | ||
1459 | case BT_OPEN: | 1479 | case BT_OPEN: |
@@ -1463,13 +1483,12 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, | |||
1463 | 1483 | ||
1464 | default: | 1484 | default: |
1465 | err = -EBADFD; | 1485 | err = -EBADFD; |
1466 | release_sock(sk); | ||
1467 | goto done; | 1486 | goto done; |
1468 | } | 1487 | } |
1469 | 1488 | ||
1470 | /* Set destination address and psm */ | 1489 | /* Set destination address and psm */ |
1490 | lock_sock(sk); | ||
1471 | bacpy(&bt_sk(sk)->dst, dst); | 1491 | bacpy(&bt_sk(sk)->dst, dst); |
1472 | |||
1473 | release_sock(sk); | 1492 | release_sock(sk); |
1474 | 1493 | ||
1475 | chan->psm = psm; | 1494 | chan->psm = psm; |
@@ -1571,23 +1590,20 @@ int __l2cap_wait_ack(struct sock *sk) | |||
1571 | static void l2cap_monitor_timeout(struct work_struct *work) | 1590 | static void l2cap_monitor_timeout(struct work_struct *work) |
1572 | { | 1591 | { |
1573 | struct l2cap_chan *chan = container_of(work, struct l2cap_chan, | 1592 | struct l2cap_chan *chan = container_of(work, struct l2cap_chan, |
1574 | monitor_timer.work); | 1593 | monitor_timer.work); |
1575 | 1594 | ||
1576 | BT_DBG("chan %p", chan); | 1595 | BT_DBG("chan %p", chan); |
1577 | 1596 | ||
1578 | l2cap_chan_lock(chan); | 1597 | l2cap_chan_lock(chan); |
1579 | 1598 | ||
1580 | if (chan->retry_count >= chan->remote_max_tx) { | 1599 | if (!chan->conn) { |
1581 | l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED); | ||
1582 | l2cap_chan_unlock(chan); | 1600 | l2cap_chan_unlock(chan); |
1583 | l2cap_chan_put(chan); | 1601 | l2cap_chan_put(chan); |
1584 | return; | 1602 | return; |
1585 | } | 1603 | } |
1586 | 1604 | ||
1587 | chan->retry_count++; | 1605 | l2cap_tx(chan, NULL, NULL, L2CAP_EV_MONITOR_TO); |
1588 | __set_monitor_timer(chan); | ||
1589 | 1606 | ||
1590 | l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL); | ||
1591 | l2cap_chan_unlock(chan); | 1607 | l2cap_chan_unlock(chan); |
1592 | l2cap_chan_put(chan); | 1608 | l2cap_chan_put(chan); |
1593 | } | 1609 | } |
@@ -1595,234 +1611,293 @@ static void l2cap_monitor_timeout(struct work_struct *work) | |||
1595 | static void l2cap_retrans_timeout(struct work_struct *work) | 1611 | static void l2cap_retrans_timeout(struct work_struct *work) |
1596 | { | 1612 | { |
1597 | struct l2cap_chan *chan = container_of(work, struct l2cap_chan, | 1613 | struct l2cap_chan *chan = container_of(work, struct l2cap_chan, |
1598 | retrans_timer.work); | 1614 | retrans_timer.work); |
1599 | 1615 | ||
1600 | BT_DBG("chan %p", chan); | 1616 | BT_DBG("chan %p", chan); |
1601 | 1617 | ||
1602 | l2cap_chan_lock(chan); | 1618 | l2cap_chan_lock(chan); |
1603 | 1619 | ||
1604 | chan->retry_count = 1; | 1620 | if (!chan->conn) { |
1605 | __set_monitor_timer(chan); | 1621 | l2cap_chan_unlock(chan); |
1606 | 1622 | l2cap_chan_put(chan); | |
1607 | set_bit(CONN_WAIT_F, &chan->conn_state); | 1623 | return; |
1608 | 1624 | } | |
1609 | l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL); | ||
1610 | 1625 | ||
1626 | l2cap_tx(chan, NULL, NULL, L2CAP_EV_RETRANS_TO); | ||
1611 | l2cap_chan_unlock(chan); | 1627 | l2cap_chan_unlock(chan); |
1612 | l2cap_chan_put(chan); | 1628 | l2cap_chan_put(chan); |
1613 | } | 1629 | } |
1614 | 1630 | ||
1615 | static void l2cap_drop_acked_frames(struct l2cap_chan *chan) | 1631 | static void l2cap_streaming_send(struct l2cap_chan *chan, |
1632 | struct sk_buff_head *skbs) | ||
1616 | { | 1633 | { |
1617 | struct sk_buff *skb; | 1634 | struct sk_buff *skb; |
1635 | struct l2cap_ctrl *control; | ||
1618 | 1636 | ||
1619 | while ((skb = skb_peek(&chan->tx_q)) && | 1637 | BT_DBG("chan %p, skbs %p", chan, skbs); |
1620 | chan->unacked_frames) { | ||
1621 | if (bt_cb(skb)->control.txseq == chan->expected_ack_seq) | ||
1622 | break; | ||
1623 | 1638 | ||
1624 | skb = skb_dequeue(&chan->tx_q); | 1639 | skb_queue_splice_tail_init(skbs, &chan->tx_q); |
1625 | kfree_skb(skb); | ||
1626 | 1640 | ||
1627 | chan->unacked_frames--; | 1641 | while (!skb_queue_empty(&chan->tx_q)) { |
1628 | } | ||
1629 | 1642 | ||
1630 | if (!chan->unacked_frames) | 1643 | skb = skb_dequeue(&chan->tx_q); |
1631 | __clear_retrans_timer(chan); | ||
1632 | } | ||
1633 | 1644 | ||
1634 | static void l2cap_streaming_send(struct l2cap_chan *chan) | 1645 | bt_cb(skb)->control.retries = 1; |
1635 | { | 1646 | control = &bt_cb(skb)->control; |
1636 | struct sk_buff *skb; | 1647 | |
1637 | u32 control; | 1648 | control->reqseq = 0; |
1638 | u16 fcs; | 1649 | control->txseq = chan->next_tx_seq; |
1639 | 1650 | ||
1640 | while ((skb = skb_dequeue(&chan->tx_q))) { | 1651 | __pack_control(chan, control, skb); |
1641 | control = __get_control(chan, skb->data + L2CAP_HDR_SIZE); | ||
1642 | control |= __set_txseq(chan, chan->next_tx_seq); | ||
1643 | control |= __set_ctrl_sar(chan, bt_cb(skb)->control.sar); | ||
1644 | __put_control(chan, control, skb->data + L2CAP_HDR_SIZE); | ||
1645 | 1652 | ||
1646 | if (chan->fcs == L2CAP_FCS_CRC16) { | 1653 | if (chan->fcs == L2CAP_FCS_CRC16) { |
1647 | fcs = crc16(0, (u8 *)skb->data, | 1654 | u16 fcs = crc16(0, (u8 *) skb->data, skb->len); |
1648 | skb->len - L2CAP_FCS_SIZE); | 1655 | put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); |
1649 | put_unaligned_le16(fcs, | ||
1650 | skb->data + skb->len - L2CAP_FCS_SIZE); | ||
1651 | } | 1656 | } |
1652 | 1657 | ||
1653 | l2cap_do_send(chan, skb); | 1658 | l2cap_do_send(chan, skb); |
1654 | 1659 | ||
1660 | BT_DBG("Sent txseq %d", (int)control->txseq); | ||
1661 | |||
1655 | chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); | 1662 | chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); |
1663 | chan->frames_sent++; | ||
1656 | } | 1664 | } |
1657 | } | 1665 | } |
1658 | 1666 | ||
1659 | static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq) | 1667 | static int l2cap_ertm_send(struct l2cap_chan *chan) |
1660 | { | 1668 | { |
1661 | struct sk_buff *skb, *tx_skb; | 1669 | struct sk_buff *skb, *tx_skb; |
1662 | u16 fcs; | 1670 | struct l2cap_ctrl *control; |
1663 | u32 control; | 1671 | int sent = 0; |
1664 | 1672 | ||
1665 | skb = skb_peek(&chan->tx_q); | 1673 | BT_DBG("chan %p", chan); |
1666 | if (!skb) | ||
1667 | return; | ||
1668 | 1674 | ||
1669 | while (bt_cb(skb)->control.txseq != tx_seq) { | 1675 | if (chan->state != BT_CONNECTED) |
1670 | if (skb_queue_is_last(&chan->tx_q, skb)) | 1676 | return -ENOTCONN; |
1671 | return; | ||
1672 | 1677 | ||
1673 | skb = skb_queue_next(&chan->tx_q, skb); | 1678 | if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) |
1674 | } | 1679 | return 0; |
1675 | 1680 | ||
1676 | if (bt_cb(skb)->control.retries == chan->remote_max_tx && | 1681 | while (chan->tx_send_head && |
1677 | chan->remote_max_tx) { | 1682 | chan->unacked_frames < chan->remote_tx_win && |
1678 | l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED); | 1683 | chan->tx_state == L2CAP_TX_STATE_XMIT) { |
1679 | return; | ||
1680 | } | ||
1681 | 1684 | ||
1682 | tx_skb = skb_clone(skb, GFP_ATOMIC); | 1685 | skb = chan->tx_send_head; |
1683 | bt_cb(skb)->control.retries++; | ||
1684 | 1686 | ||
1685 | control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE); | 1687 | bt_cb(skb)->control.retries = 1; |
1686 | control &= __get_sar_mask(chan); | 1688 | control = &bt_cb(skb)->control; |
1687 | 1689 | ||
1688 | if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) | 1690 | if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) |
1689 | control |= __set_ctrl_final(chan); | 1691 | control->final = 1; |
1690 | 1692 | ||
1691 | control |= __set_reqseq(chan, chan->buffer_seq); | 1693 | control->reqseq = chan->buffer_seq; |
1692 | control |= __set_txseq(chan, tx_seq); | 1694 | chan->last_acked_seq = chan->buffer_seq; |
1695 | control->txseq = chan->next_tx_seq; | ||
1693 | 1696 | ||
1694 | __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE); | 1697 | __pack_control(chan, control, skb); |
1695 | 1698 | ||
1696 | if (chan->fcs == L2CAP_FCS_CRC16) { | 1699 | if (chan->fcs == L2CAP_FCS_CRC16) { |
1697 | fcs = crc16(0, (u8 *)tx_skb->data, | 1700 | u16 fcs = crc16(0, (u8 *) skb->data, skb->len); |
1698 | tx_skb->len - L2CAP_FCS_SIZE); | 1701 | put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); |
1699 | put_unaligned_le16(fcs, | 1702 | } |
1700 | tx_skb->data + tx_skb->len - L2CAP_FCS_SIZE); | 1703 | |
1704 | /* Clone after data has been modified. Data is assumed to be | ||
1705 | read-only (for locking purposes) on cloned sk_buffs. | ||
1706 | */ | ||
1707 | tx_skb = skb_clone(skb, GFP_KERNEL); | ||
1708 | |||
1709 | if (!tx_skb) | ||
1710 | break; | ||
1711 | |||
1712 | __set_retrans_timer(chan); | ||
1713 | |||
1714 | chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); | ||
1715 | chan->unacked_frames++; | ||
1716 | chan->frames_sent++; | ||
1717 | sent++; | ||
1718 | |||
1719 | if (skb_queue_is_last(&chan->tx_q, skb)) | ||
1720 | chan->tx_send_head = NULL; | ||
1721 | else | ||
1722 | chan->tx_send_head = skb_queue_next(&chan->tx_q, skb); | ||
1723 | |||
1724 | l2cap_do_send(chan, tx_skb); | ||
1725 | BT_DBG("Sent txseq %d", (int)control->txseq); | ||
1701 | } | 1726 | } |
1702 | 1727 | ||
1703 | l2cap_do_send(chan, tx_skb); | 1728 | BT_DBG("Sent %d, %d unacked, %d in ERTM queue", sent, |
1729 | (int) chan->unacked_frames, skb_queue_len(&chan->tx_q)); | ||
1730 | |||
1731 | return sent; | ||
1704 | } | 1732 | } |
1705 | 1733 | ||
1706 | static int l2cap_ertm_send(struct l2cap_chan *chan) | 1734 | static void l2cap_ertm_resend(struct l2cap_chan *chan) |
1707 | { | 1735 | { |
1708 | struct sk_buff *skb, *tx_skb; | 1736 | struct l2cap_ctrl control; |
1709 | u16 fcs; | 1737 | struct sk_buff *skb; |
1710 | u32 control; | 1738 | struct sk_buff *tx_skb; |
1711 | int nsent = 0; | 1739 | u16 seq; |
1712 | 1740 | ||
1713 | if (chan->state != BT_CONNECTED) | 1741 | BT_DBG("chan %p", chan); |
1714 | return -ENOTCONN; | ||
1715 | 1742 | ||
1716 | if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) | 1743 | if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) |
1717 | return 0; | 1744 | return; |
1718 | 1745 | ||
1719 | while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) { | 1746 | while (chan->retrans_list.head != L2CAP_SEQ_LIST_CLEAR) { |
1747 | seq = l2cap_seq_list_pop(&chan->retrans_list); | ||
1720 | 1748 | ||
1721 | if (bt_cb(skb)->control.retries == chan->remote_max_tx && | 1749 | skb = l2cap_ertm_seq_in_queue(&chan->tx_q, seq); |
1722 | chan->remote_max_tx) { | 1750 | if (!skb) { |
1723 | l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED); | 1751 | BT_DBG("Error: Can't retransmit seq %d, frame missing", |
1724 | break; | 1752 | seq); |
1753 | continue; | ||
1725 | } | 1754 | } |
1726 | 1755 | ||
1727 | tx_skb = skb_clone(skb, GFP_ATOMIC); | ||
1728 | |||
1729 | bt_cb(skb)->control.retries++; | 1756 | bt_cb(skb)->control.retries++; |
1757 | control = bt_cb(skb)->control; | ||
1730 | 1758 | ||
1731 | control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE); | 1759 | if (chan->max_tx != 0 && |
1732 | control &= __get_sar_mask(chan); | 1760 | bt_cb(skb)->control.retries > chan->max_tx) { |
1761 | BT_DBG("Retry limit exceeded (%d)", chan->max_tx); | ||
1762 | l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); | ||
1763 | l2cap_seq_list_clear(&chan->retrans_list); | ||
1764 | break; | ||
1765 | } | ||
1733 | 1766 | ||
1767 | control.reqseq = chan->buffer_seq; | ||
1734 | if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) | 1768 | if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state)) |
1735 | control |= __set_ctrl_final(chan); | 1769 | control.final = 1; |
1770 | else | ||
1771 | control.final = 0; | ||
1736 | 1772 | ||
1737 | control |= __set_reqseq(chan, chan->buffer_seq); | 1773 | if (skb_cloned(skb)) { |
1738 | control |= __set_txseq(chan, chan->next_tx_seq); | 1774 | /* Cloned sk_buffs are read-only, so we need a |
1739 | control |= __set_ctrl_sar(chan, bt_cb(skb)->control.sar); | 1775 | * writeable copy |
1776 | */ | ||
1777 | tx_skb = skb_copy(skb, GFP_ATOMIC); | ||
1778 | } else { | ||
1779 | tx_skb = skb_clone(skb, GFP_ATOMIC); | ||
1780 | } | ||
1740 | 1781 | ||
1741 | __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE); | 1782 | if (!tx_skb) { |
1783 | l2cap_seq_list_clear(&chan->retrans_list); | ||
1784 | break; | ||
1785 | } | ||
1786 | |||
1787 | /* Update skb contents */ | ||
1788 | if (test_bit(FLAG_EXT_CTRL, &chan->flags)) { | ||
1789 | put_unaligned_le32(__pack_extended_control(&control), | ||
1790 | tx_skb->data + L2CAP_HDR_SIZE); | ||
1791 | } else { | ||
1792 | put_unaligned_le16(__pack_enhanced_control(&control), | ||
1793 | tx_skb->data + L2CAP_HDR_SIZE); | ||
1794 | } | ||
1742 | 1795 | ||
1743 | if (chan->fcs == L2CAP_FCS_CRC16) { | 1796 | if (chan->fcs == L2CAP_FCS_CRC16) { |
1744 | fcs = crc16(0, (u8 *)skb->data, | 1797 | u16 fcs = crc16(0, (u8 *) tx_skb->data, tx_skb->len); |
1745 | tx_skb->len - L2CAP_FCS_SIZE); | 1798 | put_unaligned_le16(fcs, skb_put(tx_skb, |
1746 | put_unaligned_le16(fcs, skb->data + | 1799 | L2CAP_FCS_SIZE)); |
1747 | tx_skb->len - L2CAP_FCS_SIZE); | ||
1748 | } | 1800 | } |
1749 | 1801 | ||
1750 | l2cap_do_send(chan, tx_skb); | 1802 | l2cap_do_send(chan, tx_skb); |
1751 | 1803 | ||
1752 | __set_retrans_timer(chan); | 1804 | BT_DBG("Resent txseq %d", control.txseq); |
1753 | |||
1754 | bt_cb(skb)->control.txseq = chan->next_tx_seq; | ||
1755 | |||
1756 | chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); | ||
1757 | |||
1758 | if (bt_cb(skb)->control.retries == 1) { | ||
1759 | chan->unacked_frames++; | ||
1760 | |||
1761 | if (!nsent++) | ||
1762 | __clear_ack_timer(chan); | ||
1763 | } | ||
1764 | |||
1765 | chan->frames_sent++; | ||
1766 | 1805 | ||
1767 | if (skb_queue_is_last(&chan->tx_q, skb)) | 1806 | chan->last_acked_seq = chan->buffer_seq; |
1768 | chan->tx_send_head = NULL; | ||
1769 | else | ||
1770 | chan->tx_send_head = skb_queue_next(&chan->tx_q, skb); | ||
1771 | } | 1807 | } |
1772 | |||
1773 | return nsent; | ||
1774 | } | 1808 | } |
1775 | 1809 | ||
1776 | static int l2cap_retransmit_frames(struct l2cap_chan *chan) | 1810 | static void l2cap_retransmit(struct l2cap_chan *chan, |
1811 | struct l2cap_ctrl *control) | ||
1777 | { | 1812 | { |
1778 | int ret; | 1813 | BT_DBG("chan %p, control %p", chan, control); |
1779 | |||
1780 | if (!skb_queue_empty(&chan->tx_q)) | ||
1781 | chan->tx_send_head = chan->tx_q.next; | ||
1782 | 1814 | ||
1783 | chan->next_tx_seq = chan->expected_ack_seq; | 1815 | l2cap_seq_list_append(&chan->retrans_list, control->reqseq); |
1784 | ret = l2cap_ertm_send(chan); | 1816 | l2cap_ertm_resend(chan); |
1785 | return ret; | ||
1786 | } | 1817 | } |
1787 | 1818 | ||
1788 | static void __l2cap_send_ack(struct l2cap_chan *chan) | 1819 | static void l2cap_retransmit_all(struct l2cap_chan *chan, |
1820 | struct l2cap_ctrl *control) | ||
1789 | { | 1821 | { |
1790 | u32 control = 0; | 1822 | struct sk_buff *skb; |
1791 | 1823 | ||
1792 | control |= __set_reqseq(chan, chan->buffer_seq); | 1824 | BT_DBG("chan %p, control %p", chan, control); |
1793 | 1825 | ||
1794 | if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { | 1826 | if (control->poll) |
1795 | control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR); | 1827 | set_bit(CONN_SEND_FBIT, &chan->conn_state); |
1796 | set_bit(CONN_RNR_SENT, &chan->conn_state); | ||
1797 | l2cap_send_sframe(chan, control); | ||
1798 | return; | ||
1799 | } | ||
1800 | 1828 | ||
1801 | if (l2cap_ertm_send(chan) > 0) | 1829 | l2cap_seq_list_clear(&chan->retrans_list); |
1830 | |||
1831 | if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) | ||
1802 | return; | 1832 | return; |
1803 | 1833 | ||
1804 | control |= __set_ctrl_super(chan, L2CAP_SUPER_RR); | 1834 | if (chan->unacked_frames) { |
1805 | l2cap_send_sframe(chan, control); | 1835 | skb_queue_walk(&chan->tx_q, skb) { |
1836 | if (bt_cb(skb)->control.txseq == control->reqseq || | ||
1837 | skb == chan->tx_send_head) | ||
1838 | break; | ||
1839 | } | ||
1840 | |||
1841 | skb_queue_walk_from(&chan->tx_q, skb) { | ||
1842 | if (skb == chan->tx_send_head) | ||
1843 | break; | ||
1844 | |||
1845 | l2cap_seq_list_append(&chan->retrans_list, | ||
1846 | bt_cb(skb)->control.txseq); | ||
1847 | } | ||
1848 | |||
1849 | l2cap_ertm_resend(chan); | ||
1850 | } | ||
1806 | } | 1851 | } |
1807 | 1852 | ||
1808 | static void l2cap_send_ack(struct l2cap_chan *chan) | 1853 | static void l2cap_send_ack(struct l2cap_chan *chan) |
1809 | { | 1854 | { |
1810 | __clear_ack_timer(chan); | 1855 | struct l2cap_ctrl control; |
1811 | __l2cap_send_ack(chan); | 1856 | u16 frames_to_ack = __seq_offset(chan, chan->buffer_seq, |
1812 | } | 1857 | chan->last_acked_seq); |
1858 | int threshold; | ||
1813 | 1859 | ||
1814 | static void l2cap_send_srejtail(struct l2cap_chan *chan) | 1860 | BT_DBG("chan %p last_acked_seq %d buffer_seq %d", |
1815 | { | 1861 | chan, chan->last_acked_seq, chan->buffer_seq); |
1816 | struct srej_list *tail; | ||
1817 | u32 control; | ||
1818 | 1862 | ||
1819 | control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ); | 1863 | memset(&control, 0, sizeof(control)); |
1820 | control |= __set_ctrl_final(chan); | 1864 | control.sframe = 1; |
1821 | 1865 | ||
1822 | tail = list_entry((&chan->srej_l)->prev, struct srej_list, list); | 1866 | if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && |
1823 | control |= __set_reqseq(chan, tail->tx_seq); | 1867 | chan->rx_state == L2CAP_RX_STATE_RECV) { |
1868 | __clear_ack_timer(chan); | ||
1869 | control.super = L2CAP_SUPER_RNR; | ||
1870 | control.reqseq = chan->buffer_seq; | ||
1871 | l2cap_send_sframe(chan, &control); | ||
1872 | } else { | ||
1873 | if (!test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) { | ||
1874 | l2cap_ertm_send(chan); | ||
1875 | /* If any i-frames were sent, they included an ack */ | ||
1876 | if (chan->buffer_seq == chan->last_acked_seq) | ||
1877 | frames_to_ack = 0; | ||
1878 | } | ||
1824 | 1879 | ||
1825 | l2cap_send_sframe(chan, control); | 1880 | /* Ack now if the tx window is 3/4ths full. |
1881 | * Calculate without mul or div | ||
1882 | */ | ||
1883 | threshold = chan->tx_win; | ||
1884 | threshold += threshold << 1; | ||
1885 | threshold >>= 2; | ||
1886 | |||
1887 | BT_DBG("frames_to_ack %d, threshold %d", (int)frames_to_ack, | ||
1888 | threshold); | ||
1889 | |||
1890 | if (frames_to_ack >= threshold) { | ||
1891 | __clear_ack_timer(chan); | ||
1892 | control.super = L2CAP_SUPER_RR; | ||
1893 | control.reqseq = chan->buffer_seq; | ||
1894 | l2cap_send_sframe(chan, &control); | ||
1895 | frames_to_ack = 0; | ||
1896 | } | ||
1897 | |||
1898 | if (frames_to_ack) | ||
1899 | __set_ack_timer(chan); | ||
1900 | } | ||
1826 | } | 1901 | } |
1827 | 1902 | ||
1828 | static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan, | 1903 | static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan, |
@@ -1951,10 +2026,7 @@ static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, | |||
1951 | if (!conn) | 2026 | if (!conn) |
1952 | return ERR_PTR(-ENOTCONN); | 2027 | return ERR_PTR(-ENOTCONN); |
1953 | 2028 | ||
1954 | if (test_bit(FLAG_EXT_CTRL, &chan->flags)) | 2029 | hlen = __ertm_hdr_size(chan); |
1955 | hlen = L2CAP_EXT_HDR_SIZE; | ||
1956 | else | ||
1957 | hlen = L2CAP_ENH_HDR_SIZE; | ||
1958 | 2030 | ||
1959 | if (sdulen) | 2031 | if (sdulen) |
1960 | hlen += L2CAP_SDULEN_SIZE; | 2032 | hlen += L2CAP_SDULEN_SIZE; |
@@ -1974,7 +2046,11 @@ static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, | |||
1974 | lh->cid = cpu_to_le16(chan->dcid); | 2046 | lh->cid = cpu_to_le16(chan->dcid); |
1975 | lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); | 2047 | lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); |
1976 | 2048 | ||
1977 | __put_control(chan, 0, skb_put(skb, __ctrl_size(chan))); | 2049 | /* Control header is populated later */ |
2050 | if (test_bit(FLAG_EXT_CTRL, &chan->flags)) | ||
2051 | put_unaligned_le32(0, skb_put(skb, L2CAP_EXT_CTRL_SIZE)); | ||
2052 | else | ||
2053 | put_unaligned_le16(0, skb_put(skb, L2CAP_ENH_CTRL_SIZE)); | ||
1978 | 2054 | ||
1979 | if (sdulen) | 2055 | if (sdulen) |
1980 | put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE)); | 2056 | put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE)); |
@@ -1985,9 +2061,7 @@ static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, | |||
1985 | return ERR_PTR(err); | 2061 | return ERR_PTR(err); |
1986 | } | 2062 | } |
1987 | 2063 | ||
1988 | if (chan->fcs == L2CAP_FCS_CRC16) | 2064 | bt_cb(skb)->control.fcs = chan->fcs; |
1989 | put_unaligned_le16(0, skb_put(skb, L2CAP_FCS_SIZE)); | ||
1990 | |||
1991 | bt_cb(skb)->control.retries = 0; | 2065 | bt_cb(skb)->control.retries = 0; |
1992 | return skb; | 2066 | return skb; |
1993 | } | 2067 | } |
@@ -1999,7 +2073,6 @@ static int l2cap_segment_sdu(struct l2cap_chan *chan, | |||
1999 | struct sk_buff *skb; | 2073 | struct sk_buff *skb; |
2000 | u16 sdu_len; | 2074 | u16 sdu_len; |
2001 | size_t pdu_len; | 2075 | size_t pdu_len; |
2002 | int err = 0; | ||
2003 | u8 sar; | 2076 | u8 sar; |
2004 | 2077 | ||
2005 | BT_DBG("chan %p, msg %p, len %d", chan, msg, (int)len); | 2078 | BT_DBG("chan %p, msg %p, len %d", chan, msg, (int)len); |
@@ -2015,7 +2088,10 @@ static int l2cap_segment_sdu(struct l2cap_chan *chan, | |||
2015 | pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD); | 2088 | pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD); |
2016 | 2089 | ||
2017 | /* Adjust for largest possible L2CAP overhead. */ | 2090 | /* Adjust for largest possible L2CAP overhead. */ |
2018 | pdu_len -= L2CAP_EXT_HDR_SIZE + L2CAP_FCS_SIZE; | 2091 | if (chan->fcs) |
2092 | pdu_len -= L2CAP_FCS_SIZE; | ||
2093 | |||
2094 | pdu_len -= __ertm_hdr_size(chan); | ||
2019 | 2095 | ||
2020 | /* Remote device may have requested smaller PDUs */ | 2096 | /* Remote device may have requested smaller PDUs */ |
2021 | pdu_len = min_t(size_t, pdu_len, chan->remote_mps); | 2097 | pdu_len = min_t(size_t, pdu_len, chan->remote_mps); |
@@ -2055,7 +2131,7 @@ static int l2cap_segment_sdu(struct l2cap_chan *chan, | |||
2055 | } | 2131 | } |
2056 | } | 2132 | } |
2057 | 2133 | ||
2058 | return err; | 2134 | return 0; |
2059 | } | 2135 | } |
2060 | 2136 | ||
2061 | int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, | 2137 | int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, |
@@ -2117,17 +2193,12 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, | |||
2117 | if (err) | 2193 | if (err) |
2118 | break; | 2194 | break; |
2119 | 2195 | ||
2120 | if (chan->mode == L2CAP_MODE_ERTM && chan->tx_send_head == NULL) | ||
2121 | chan->tx_send_head = seg_queue.next; | ||
2122 | skb_queue_splice_tail_init(&seg_queue, &chan->tx_q); | ||
2123 | |||
2124 | if (chan->mode == L2CAP_MODE_ERTM) | 2196 | if (chan->mode == L2CAP_MODE_ERTM) |
2125 | err = l2cap_ertm_send(chan); | 2197 | l2cap_tx(chan, NULL, &seg_queue, L2CAP_EV_DATA_REQUEST); |
2126 | else | 2198 | else |
2127 | l2cap_streaming_send(chan); | 2199 | l2cap_streaming_send(chan, &seg_queue); |
2128 | 2200 | ||
2129 | if (err >= 0) | 2201 | err = len; |
2130 | err = len; | ||
2131 | 2202 | ||
2132 | /* If the skbs were not queued for sending, they'll still be in | 2203 | /* If the skbs were not queued for sending, they'll still be in |
2133 | * seg_queue and need to be purged. | 2204 | * seg_queue and need to be purged. |
@@ -2143,6 +2214,296 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, | |||
2143 | return err; | 2214 | return err; |
2144 | } | 2215 | } |
2145 | 2216 | ||
2217 | static void l2cap_send_srej(struct l2cap_chan *chan, u16 txseq) | ||
2218 | { | ||
2219 | struct l2cap_ctrl control; | ||
2220 | u16 seq; | ||
2221 | |||
2222 | BT_DBG("chan %p, txseq %d", chan, txseq); | ||
2223 | |||
2224 | memset(&control, 0, sizeof(control)); | ||
2225 | control.sframe = 1; | ||
2226 | control.super = L2CAP_SUPER_SREJ; | ||
2227 | |||
2228 | for (seq = chan->expected_tx_seq; seq != txseq; | ||
2229 | seq = __next_seq(chan, seq)) { | ||
2230 | if (!l2cap_ertm_seq_in_queue(&chan->srej_q, seq)) { | ||
2231 | control.reqseq = seq; | ||
2232 | l2cap_send_sframe(chan, &control); | ||
2233 | l2cap_seq_list_append(&chan->srej_list, seq); | ||
2234 | } | ||
2235 | } | ||
2236 | |||
2237 | chan->expected_tx_seq = __next_seq(chan, txseq); | ||
2238 | } | ||
2239 | |||
2240 | static void l2cap_send_srej_tail(struct l2cap_chan *chan) | ||
2241 | { | ||
2242 | struct l2cap_ctrl control; | ||
2243 | |||
2244 | BT_DBG("chan %p", chan); | ||
2245 | |||
2246 | if (chan->srej_list.tail == L2CAP_SEQ_LIST_CLEAR) | ||
2247 | return; | ||
2248 | |||
2249 | memset(&control, 0, sizeof(control)); | ||
2250 | control.sframe = 1; | ||
2251 | control.super = L2CAP_SUPER_SREJ; | ||
2252 | control.reqseq = chan->srej_list.tail; | ||
2253 | l2cap_send_sframe(chan, &control); | ||
2254 | } | ||
2255 | |||
2256 | static void l2cap_send_srej_list(struct l2cap_chan *chan, u16 txseq) | ||
2257 | { | ||
2258 | struct l2cap_ctrl control; | ||
2259 | u16 initial_head; | ||
2260 | u16 seq; | ||
2261 | |||
2262 | BT_DBG("chan %p, txseq %d", chan, txseq); | ||
2263 | |||
2264 | memset(&control, 0, sizeof(control)); | ||
2265 | control.sframe = 1; | ||
2266 | control.super = L2CAP_SUPER_SREJ; | ||
2267 | |||
2268 | /* Capture initial list head to allow only one pass through the list. */ | ||
2269 | initial_head = chan->srej_list.head; | ||
2270 | |||
2271 | do { | ||
2272 | seq = l2cap_seq_list_pop(&chan->srej_list); | ||
2273 | if (seq == txseq || seq == L2CAP_SEQ_LIST_CLEAR) | ||
2274 | break; | ||
2275 | |||
2276 | control.reqseq = seq; | ||
2277 | l2cap_send_sframe(chan, &control); | ||
2278 | l2cap_seq_list_append(&chan->srej_list, seq); | ||
2279 | } while (chan->srej_list.head != initial_head); | ||
2280 | } | ||
2281 | |||
2282 | static void l2cap_process_reqseq(struct l2cap_chan *chan, u16 reqseq) | ||
2283 | { | ||
2284 | struct sk_buff *acked_skb; | ||
2285 | u16 ackseq; | ||
2286 | |||
2287 | BT_DBG("chan %p, reqseq %d", chan, reqseq); | ||
2288 | |||
2289 | if (chan->unacked_frames == 0 || reqseq == chan->expected_ack_seq) | ||
2290 | return; | ||
2291 | |||
2292 | BT_DBG("expected_ack_seq %d, unacked_frames %d", | ||
2293 | chan->expected_ack_seq, chan->unacked_frames); | ||
2294 | |||
2295 | for (ackseq = chan->expected_ack_seq; ackseq != reqseq; | ||
2296 | ackseq = __next_seq(chan, ackseq)) { | ||
2297 | |||
2298 | acked_skb = l2cap_ertm_seq_in_queue(&chan->tx_q, ackseq); | ||
2299 | if (acked_skb) { | ||
2300 | skb_unlink(acked_skb, &chan->tx_q); | ||
2301 | kfree_skb(acked_skb); | ||
2302 | chan->unacked_frames--; | ||
2303 | } | ||
2304 | } | ||
2305 | |||
2306 | chan->expected_ack_seq = reqseq; | ||
2307 | |||
2308 | if (chan->unacked_frames == 0) | ||
2309 | __clear_retrans_timer(chan); | ||
2310 | |||
2311 | BT_DBG("unacked_frames %d", (int) chan->unacked_frames); | ||
2312 | } | ||
2313 | |||
2314 | static void l2cap_abort_rx_srej_sent(struct l2cap_chan *chan) | ||
2315 | { | ||
2316 | BT_DBG("chan %p", chan); | ||
2317 | |||
2318 | chan->expected_tx_seq = chan->buffer_seq; | ||
2319 | l2cap_seq_list_clear(&chan->srej_list); | ||
2320 | skb_queue_purge(&chan->srej_q); | ||
2321 | chan->rx_state = L2CAP_RX_STATE_RECV; | ||
2322 | } | ||
2323 | |||
2324 | static void l2cap_tx_state_xmit(struct l2cap_chan *chan, | ||
2325 | struct l2cap_ctrl *control, | ||
2326 | struct sk_buff_head *skbs, u8 event) | ||
2327 | { | ||
2328 | BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs, | ||
2329 | event); | ||
2330 | |||
2331 | switch (event) { | ||
2332 | case L2CAP_EV_DATA_REQUEST: | ||
2333 | if (chan->tx_send_head == NULL) | ||
2334 | chan->tx_send_head = skb_peek(skbs); | ||
2335 | |||
2336 | skb_queue_splice_tail_init(skbs, &chan->tx_q); | ||
2337 | l2cap_ertm_send(chan); | ||
2338 | break; | ||
2339 | case L2CAP_EV_LOCAL_BUSY_DETECTED: | ||
2340 | BT_DBG("Enter LOCAL_BUSY"); | ||
2341 | set_bit(CONN_LOCAL_BUSY, &chan->conn_state); | ||
2342 | |||
2343 | if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { | ||
2344 | /* The SREJ_SENT state must be aborted if we are to | ||
2345 | * enter the LOCAL_BUSY state. | ||
2346 | */ | ||
2347 | l2cap_abort_rx_srej_sent(chan); | ||
2348 | } | ||
2349 | |||
2350 | l2cap_send_ack(chan); | ||
2351 | |||
2352 | break; | ||
2353 | case L2CAP_EV_LOCAL_BUSY_CLEAR: | ||
2354 | BT_DBG("Exit LOCAL_BUSY"); | ||
2355 | clear_bit(CONN_LOCAL_BUSY, &chan->conn_state); | ||
2356 | |||
2357 | if (test_bit(CONN_RNR_SENT, &chan->conn_state)) { | ||
2358 | struct l2cap_ctrl local_control; | ||
2359 | |||
2360 | memset(&local_control, 0, sizeof(local_control)); | ||
2361 | local_control.sframe = 1; | ||
2362 | local_control.super = L2CAP_SUPER_RR; | ||
2363 | local_control.poll = 1; | ||
2364 | local_control.reqseq = chan->buffer_seq; | ||
2365 | l2cap_send_sframe(chan, &local_control); | ||
2366 | |||
2367 | chan->retry_count = 1; | ||
2368 | __set_monitor_timer(chan); | ||
2369 | chan->tx_state = L2CAP_TX_STATE_WAIT_F; | ||
2370 | } | ||
2371 | break; | ||
2372 | case L2CAP_EV_RECV_REQSEQ_AND_FBIT: | ||
2373 | l2cap_process_reqseq(chan, control->reqseq); | ||
2374 | break; | ||
2375 | case L2CAP_EV_EXPLICIT_POLL: | ||
2376 | l2cap_send_rr_or_rnr(chan, 1); | ||
2377 | chan->retry_count = 1; | ||
2378 | __set_monitor_timer(chan); | ||
2379 | __clear_ack_timer(chan); | ||
2380 | chan->tx_state = L2CAP_TX_STATE_WAIT_F; | ||
2381 | break; | ||
2382 | case L2CAP_EV_RETRANS_TO: | ||
2383 | l2cap_send_rr_or_rnr(chan, 1); | ||
2384 | chan->retry_count = 1; | ||
2385 | __set_monitor_timer(chan); | ||
2386 | chan->tx_state = L2CAP_TX_STATE_WAIT_F; | ||
2387 | break; | ||
2388 | case L2CAP_EV_RECV_FBIT: | ||
2389 | /* Nothing to process */ | ||
2390 | break; | ||
2391 | default: | ||
2392 | break; | ||
2393 | } | ||
2394 | } | ||
2395 | |||
2396 | static void l2cap_tx_state_wait_f(struct l2cap_chan *chan, | ||
2397 | struct l2cap_ctrl *control, | ||
2398 | struct sk_buff_head *skbs, u8 event) | ||
2399 | { | ||
2400 | BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs, | ||
2401 | event); | ||
2402 | |||
2403 | switch (event) { | ||
2404 | case L2CAP_EV_DATA_REQUEST: | ||
2405 | if (chan->tx_send_head == NULL) | ||
2406 | chan->tx_send_head = skb_peek(skbs); | ||
2407 | /* Queue data, but don't send. */ | ||
2408 | skb_queue_splice_tail_init(skbs, &chan->tx_q); | ||
2409 | break; | ||
2410 | case L2CAP_EV_LOCAL_BUSY_DETECTED: | ||
2411 | BT_DBG("Enter LOCAL_BUSY"); | ||
2412 | set_bit(CONN_LOCAL_BUSY, &chan->conn_state); | ||
2413 | |||
2414 | if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { | ||
2415 | /* The SREJ_SENT state must be aborted if we are to | ||
2416 | * enter the LOCAL_BUSY state. | ||
2417 | */ | ||
2418 | l2cap_abort_rx_srej_sent(chan); | ||
2419 | } | ||
2420 | |||
2421 | l2cap_send_ack(chan); | ||
2422 | |||
2423 | break; | ||
2424 | case L2CAP_EV_LOCAL_BUSY_CLEAR: | ||
2425 | BT_DBG("Exit LOCAL_BUSY"); | ||
2426 | clear_bit(CONN_LOCAL_BUSY, &chan->conn_state); | ||
2427 | |||
2428 | if (test_bit(CONN_RNR_SENT, &chan->conn_state)) { | ||
2429 | struct l2cap_ctrl local_control; | ||
2430 | memset(&local_control, 0, sizeof(local_control)); | ||
2431 | local_control.sframe = 1; | ||
2432 | local_control.super = L2CAP_SUPER_RR; | ||
2433 | local_control.poll = 1; | ||
2434 | local_control.reqseq = chan->buffer_seq; | ||
2435 | l2cap_send_sframe(chan, &local_control); | ||
2436 | |||
2437 | chan->retry_count = 1; | ||
2438 | __set_monitor_timer(chan); | ||
2439 | chan->tx_state = L2CAP_TX_STATE_WAIT_F; | ||
2440 | } | ||
2441 | break; | ||
2442 | case L2CAP_EV_RECV_REQSEQ_AND_FBIT: | ||
2443 | l2cap_process_reqseq(chan, control->reqseq); | ||
2444 | |||
2445 | /* Fall through */ | ||
2446 | |||
2447 | case L2CAP_EV_RECV_FBIT: | ||
2448 | if (control && control->final) { | ||
2449 | __clear_monitor_timer(chan); | ||
2450 | if (chan->unacked_frames > 0) | ||
2451 | __set_retrans_timer(chan); | ||
2452 | chan->retry_count = 0; | ||
2453 | chan->tx_state = L2CAP_TX_STATE_XMIT; | ||
2454 | BT_DBG("recv fbit tx_state 0x2.2%x", chan->tx_state); | ||
2455 | } | ||
2456 | break; | ||
2457 | case L2CAP_EV_EXPLICIT_POLL: | ||
2458 | /* Ignore */ | ||
2459 | break; | ||
2460 | case L2CAP_EV_MONITOR_TO: | ||
2461 | if (chan->max_tx == 0 || chan->retry_count < chan->max_tx) { | ||
2462 | l2cap_send_rr_or_rnr(chan, 1); | ||
2463 | __set_monitor_timer(chan); | ||
2464 | chan->retry_count++; | ||
2465 | } else { | ||
2466 | l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED); | ||
2467 | } | ||
2468 | break; | ||
2469 | default: | ||
2470 | break; | ||
2471 | } | ||
2472 | } | ||
2473 | |||
2474 | static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, | ||
2475 | struct sk_buff_head *skbs, u8 event) | ||
2476 | { | ||
2477 | BT_DBG("chan %p, control %p, skbs %p, event %d, state %d", | ||
2478 | chan, control, skbs, event, chan->tx_state); | ||
2479 | |||
2480 | switch (chan->tx_state) { | ||
2481 | case L2CAP_TX_STATE_XMIT: | ||
2482 | l2cap_tx_state_xmit(chan, control, skbs, event); | ||
2483 | break; | ||
2484 | case L2CAP_TX_STATE_WAIT_F: | ||
2485 | l2cap_tx_state_wait_f(chan, control, skbs, event); | ||
2486 | break; | ||
2487 | default: | ||
2488 | /* Ignore event */ | ||
2489 | break; | ||
2490 | } | ||
2491 | } | ||
2492 | |||
2493 | static void l2cap_pass_to_tx(struct l2cap_chan *chan, | ||
2494 | struct l2cap_ctrl *control) | ||
2495 | { | ||
2496 | BT_DBG("chan %p, control %p", chan, control); | ||
2497 | l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_REQSEQ_AND_FBIT); | ||
2498 | } | ||
2499 | |||
2500 | static void l2cap_pass_to_tx_fbit(struct l2cap_chan *chan, | ||
2501 | struct l2cap_ctrl *control) | ||
2502 | { | ||
2503 | BT_DBG("chan %p, control %p", chan, control); | ||
2504 | l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_FBIT); | ||
2505 | } | ||
2506 | |||
2146 | /* Copy frame to all raw sockets on that connection */ | 2507 | /* Copy frame to all raw sockets on that connection */ |
2147 | static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) | 2508 | static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) |
2148 | { | 2509 | { |
@@ -2165,7 +2526,7 @@ static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) | |||
2165 | if (!nskb) | 2526 | if (!nskb) |
2166 | continue; | 2527 | continue; |
2167 | 2528 | ||
2168 | if (chan->ops->recv(chan->data, nskb)) | 2529 | if (chan->ops->recv(chan, nskb)) |
2169 | kfree_skb(nskb); | 2530 | kfree_skb(nskb); |
2170 | } | 2531 | } |
2171 | 2532 | ||
@@ -2195,9 +2556,9 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, | |||
2195 | lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen); | 2556 | lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen); |
2196 | 2557 | ||
2197 | if (conn->hcon->type == LE_LINK) | 2558 | if (conn->hcon->type == LE_LINK) |
2198 | lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING); | 2559 | lh->cid = __constant_cpu_to_le16(L2CAP_CID_LE_SIGNALING); |
2199 | else | 2560 | else |
2200 | lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING); | 2561 | lh->cid = __constant_cpu_to_le16(L2CAP_CID_SIGNALING); |
2201 | 2562 | ||
2202 | cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE); | 2563 | cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE); |
2203 | cmd->code = code; | 2564 | cmd->code = code; |
@@ -2309,8 +2670,8 @@ static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan) | |||
2309 | efs.stype = chan->local_stype; | 2670 | efs.stype = chan->local_stype; |
2310 | efs.msdu = cpu_to_le16(chan->local_msdu); | 2671 | efs.msdu = cpu_to_le16(chan->local_msdu); |
2311 | efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); | 2672 | efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); |
2312 | efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT); | 2673 | efs.acc_lat = __constant_cpu_to_le32(L2CAP_DEFAULT_ACC_LAT); |
2313 | efs.flush_to = cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO); | 2674 | efs.flush_to = __constant_cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO); |
2314 | break; | 2675 | break; |
2315 | 2676 | ||
2316 | case L2CAP_MODE_STREAMING: | 2677 | case L2CAP_MODE_STREAMING: |
@@ -2333,20 +2694,24 @@ static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan) | |||
2333 | static void l2cap_ack_timeout(struct work_struct *work) | 2694 | static void l2cap_ack_timeout(struct work_struct *work) |
2334 | { | 2695 | { |
2335 | struct l2cap_chan *chan = container_of(work, struct l2cap_chan, | 2696 | struct l2cap_chan *chan = container_of(work, struct l2cap_chan, |
2336 | ack_timer.work); | 2697 | ack_timer.work); |
2698 | u16 frames_to_ack; | ||
2337 | 2699 | ||
2338 | BT_DBG("chan %p", chan); | 2700 | BT_DBG("chan %p", chan); |
2339 | 2701 | ||
2340 | l2cap_chan_lock(chan); | 2702 | l2cap_chan_lock(chan); |
2341 | 2703 | ||
2342 | __l2cap_send_ack(chan); | 2704 | frames_to_ack = __seq_offset(chan, chan->buffer_seq, |
2705 | chan->last_acked_seq); | ||
2343 | 2706 | ||
2344 | l2cap_chan_unlock(chan); | 2707 | if (frames_to_ack) |
2708 | l2cap_send_rr_or_rnr(chan, 0); | ||
2345 | 2709 | ||
2710 | l2cap_chan_unlock(chan); | ||
2346 | l2cap_chan_put(chan); | 2711 | l2cap_chan_put(chan); |
2347 | } | 2712 | } |
2348 | 2713 | ||
2349 | static inline int l2cap_ertm_init(struct l2cap_chan *chan) | 2714 | int l2cap_ertm_init(struct l2cap_chan *chan) |
2350 | { | 2715 | { |
2351 | int err; | 2716 | int err; |
2352 | 2717 | ||
@@ -2355,7 +2720,6 @@ static inline int l2cap_ertm_init(struct l2cap_chan *chan) | |||
2355 | chan->expected_ack_seq = 0; | 2720 | chan->expected_ack_seq = 0; |
2356 | chan->unacked_frames = 0; | 2721 | chan->unacked_frames = 0; |
2357 | chan->buffer_seq = 0; | 2722 | chan->buffer_seq = 0; |
2358 | chan->num_acked = 0; | ||
2359 | chan->frames_sent = 0; | 2723 | chan->frames_sent = 0; |
2360 | chan->last_acked_seq = 0; | 2724 | chan->last_acked_seq = 0; |
2361 | chan->sdu = NULL; | 2725 | chan->sdu = NULL; |
@@ -2376,12 +2740,15 @@ static inline int l2cap_ertm_init(struct l2cap_chan *chan) | |||
2376 | 2740 | ||
2377 | skb_queue_head_init(&chan->srej_q); | 2741 | skb_queue_head_init(&chan->srej_q); |
2378 | 2742 | ||
2379 | INIT_LIST_HEAD(&chan->srej_l); | ||
2380 | err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win); | 2743 | err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win); |
2381 | if (err < 0) | 2744 | if (err < 0) |
2382 | return err; | 2745 | return err; |
2383 | 2746 | ||
2384 | return l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win); | 2747 | err = l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win); |
2748 | if (err < 0) | ||
2749 | l2cap_seq_list_free(&chan->srej_list); | ||
2750 | |||
2751 | return err; | ||
2385 | } | 2752 | } |
2386 | 2753 | ||
2387 | static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask) | 2754 | static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask) |
@@ -2507,6 +2874,7 @@ done: | |||
2507 | break; | 2874 | break; |
2508 | 2875 | ||
2509 | case L2CAP_MODE_STREAMING: | 2876 | case L2CAP_MODE_STREAMING: |
2877 | l2cap_txwin_setup(chan); | ||
2510 | rfc.mode = L2CAP_MODE_STREAMING; | 2878 | rfc.mode = L2CAP_MODE_STREAMING; |
2511 | rfc.txwin_size = 0; | 2879 | rfc.txwin_size = 0; |
2512 | rfc.max_transmit = 0; | 2880 | rfc.max_transmit = 0; |
@@ -2537,7 +2905,7 @@ done: | |||
2537 | } | 2905 | } |
2538 | 2906 | ||
2539 | req->dcid = cpu_to_le16(chan->dcid); | 2907 | req->dcid = cpu_to_le16(chan->dcid); |
2540 | req->flags = cpu_to_le16(0); | 2908 | req->flags = __constant_cpu_to_le16(0); |
2541 | 2909 | ||
2542 | return ptr - data; | 2910 | return ptr - data; |
2543 | } | 2911 | } |
@@ -2757,7 +3125,7 @@ done: | |||
2757 | } | 3125 | } |
2758 | rsp->scid = cpu_to_le16(chan->dcid); | 3126 | rsp->scid = cpu_to_le16(chan->dcid); |
2759 | rsp->result = cpu_to_le16(result); | 3127 | rsp->result = cpu_to_le16(result); |
2760 | rsp->flags = cpu_to_le16(0x0000); | 3128 | rsp->flags = __constant_cpu_to_le16(0); |
2761 | 3129 | ||
2762 | return ptr - data; | 3130 | return ptr - data; |
2763 | } | 3131 | } |
@@ -2856,7 +3224,7 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi | |||
2856 | } | 3224 | } |
2857 | 3225 | ||
2858 | req->dcid = cpu_to_le16(chan->dcid); | 3226 | req->dcid = cpu_to_le16(chan->dcid); |
2859 | req->flags = cpu_to_le16(0x0000); | 3227 | req->flags = __constant_cpu_to_le16(0); |
2860 | 3228 | ||
2861 | return ptr - data; | 3229 | return ptr - data; |
2862 | } | 3230 | } |
@@ -2883,8 +3251,8 @@ void __l2cap_connect_rsp_defer(struct l2cap_chan *chan) | |||
2883 | 3251 | ||
2884 | rsp.scid = cpu_to_le16(chan->dcid); | 3252 | rsp.scid = cpu_to_le16(chan->dcid); |
2885 | rsp.dcid = cpu_to_le16(chan->scid); | 3253 | rsp.dcid = cpu_to_le16(chan->scid); |
2886 | rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); | 3254 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); |
2887 | rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); | 3255 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); |
2888 | l2cap_send_cmd(conn, chan->ident, | 3256 | l2cap_send_cmd(conn, chan->ident, |
2889 | L2CAP_CONN_RSP, sizeof(rsp), &rsp); | 3257 | L2CAP_CONN_RSP, sizeof(rsp), &rsp); |
2890 | 3258 | ||
@@ -2922,8 +3290,8 @@ static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len) | |||
2922 | * did not send an RFC option. | 3290 | * did not send an RFC option. |
2923 | */ | 3291 | */ |
2924 | rfc.mode = chan->mode; | 3292 | rfc.mode = chan->mode; |
2925 | rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO); | 3293 | rfc.retrans_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO); |
2926 | rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO); | 3294 | rfc.monitor_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO); |
2927 | rfc.max_pdu_size = cpu_to_le16(chan->imtu); | 3295 | rfc.max_pdu_size = cpu_to_le16(chan->imtu); |
2928 | 3296 | ||
2929 | BT_ERR("Expected RFC option was not found, using defaults"); | 3297 | BT_ERR("Expected RFC option was not found, using defaults"); |
@@ -2986,7 +3354,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
2986 | lock_sock(parent); | 3354 | lock_sock(parent); |
2987 | 3355 | ||
2988 | /* Check if the ACL is secure enough (if not SDP) */ | 3356 | /* Check if the ACL is secure enough (if not SDP) */ |
2989 | if (psm != cpu_to_le16(0x0001) && | 3357 | if (psm != __constant_cpu_to_le16(L2CAP_PSM_SDP) && |
2990 | !hci_conn_check_link_mode(conn->hcon)) { | 3358 | !hci_conn_check_link_mode(conn->hcon)) { |
2991 | conn->disc_reason = HCI_ERROR_AUTH_FAILURE; | 3359 | conn->disc_reason = HCI_ERROR_AUTH_FAILURE; |
2992 | result = L2CAP_CR_SEC_BLOCK; | 3360 | result = L2CAP_CR_SEC_BLOCK; |
@@ -2995,25 +3363,16 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
2995 | 3363 | ||
2996 | result = L2CAP_CR_NO_MEM; | 3364 | result = L2CAP_CR_NO_MEM; |
2997 | 3365 | ||
2998 | /* Check for backlog size */ | 3366 | /* Check if we already have channel with that dcid */ |
2999 | if (sk_acceptq_is_full(parent)) { | 3367 | if (__l2cap_get_chan_by_dcid(conn, scid)) |
3000 | BT_DBG("backlog full %d", parent->sk_ack_backlog); | ||
3001 | goto response; | 3368 | goto response; |
3002 | } | ||
3003 | 3369 | ||
3004 | chan = pchan->ops->new_connection(pchan->data); | 3370 | chan = pchan->ops->new_connection(pchan); |
3005 | if (!chan) | 3371 | if (!chan) |
3006 | goto response; | 3372 | goto response; |
3007 | 3373 | ||
3008 | sk = chan->sk; | 3374 | sk = chan->sk; |
3009 | 3375 | ||
3010 | /* Check if we already have channel with that dcid */ | ||
3011 | if (__l2cap_get_chan_by_dcid(conn, scid)) { | ||
3012 | sock_set_flag(sk, SOCK_ZAPPED); | ||
3013 | chan->ops->close(chan->data); | ||
3014 | goto response; | ||
3015 | } | ||
3016 | |||
3017 | hci_conn_hold(conn->hcon); | 3376 | hci_conn_hold(conn->hcon); |
3018 | 3377 | ||
3019 | bacpy(&bt_sk(sk)->src, conn->src); | 3378 | bacpy(&bt_sk(sk)->src, conn->src); |
@@ -3067,7 +3426,7 @@ sendresp: | |||
3067 | 3426 | ||
3068 | if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) { | 3427 | if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) { |
3069 | struct l2cap_info_req info; | 3428 | struct l2cap_info_req info; |
3070 | info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK); | 3429 | info.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK); |
3071 | 3430 | ||
3072 | conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; | 3431 | conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; |
3073 | conn->info_ident = l2cap_get_ident(conn); | 3432 | conn->info_ident = l2cap_get_ident(conn); |
@@ -3189,7 +3548,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
3189 | if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) { | 3548 | if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) { |
3190 | struct l2cap_cmd_rej_cid rej; | 3549 | struct l2cap_cmd_rej_cid rej; |
3191 | 3550 | ||
3192 | rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID); | 3551 | rej.reason = __constant_cpu_to_le16(L2CAP_REJ_INVALID_CID); |
3193 | rej.scid = cpu_to_le16(chan->scid); | 3552 | rej.scid = cpu_to_le16(chan->scid); |
3194 | rej.dcid = cpu_to_le16(chan->dcid); | 3553 | rej.dcid = cpu_to_le16(chan->dcid); |
3195 | 3554 | ||
@@ -3211,11 +3570,11 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
3211 | memcpy(chan->conf_req + chan->conf_len, req->data, len); | 3570 | memcpy(chan->conf_req + chan->conf_len, req->data, len); |
3212 | chan->conf_len += len; | 3571 | chan->conf_len += len; |
3213 | 3572 | ||
3214 | if (flags & 0x0001) { | 3573 | if (flags & L2CAP_CONF_FLAG_CONTINUATION) { |
3215 | /* Incomplete config. Send empty response. */ | 3574 | /* Incomplete config. Send empty response. */ |
3216 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, | 3575 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, |
3217 | l2cap_build_conf_rsp(chan, rsp, | 3576 | l2cap_build_conf_rsp(chan, rsp, |
3218 | L2CAP_CONF_SUCCESS, 0x0001), rsp); | 3577 | L2CAP_CONF_SUCCESS, flags), rsp); |
3219 | goto unlock; | 3578 | goto unlock; |
3220 | } | 3579 | } |
3221 | 3580 | ||
@@ -3238,8 +3597,6 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
3238 | if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { | 3597 | if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { |
3239 | set_default_fcs(chan); | 3598 | set_default_fcs(chan); |
3240 | 3599 | ||
3241 | l2cap_state_change(chan, BT_CONNECTED); | ||
3242 | |||
3243 | if (chan->mode == L2CAP_MODE_ERTM || | 3600 | if (chan->mode == L2CAP_MODE_ERTM || |
3244 | chan->mode == L2CAP_MODE_STREAMING) | 3601 | chan->mode == L2CAP_MODE_STREAMING) |
3245 | err = l2cap_ertm_init(chan); | 3602 | err = l2cap_ertm_init(chan); |
@@ -3271,7 +3628,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
3271 | 3628 | ||
3272 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, | 3629 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, |
3273 | l2cap_build_conf_rsp(chan, rsp, | 3630 | l2cap_build_conf_rsp(chan, rsp, |
3274 | L2CAP_CONF_SUCCESS, 0x0000), rsp); | 3631 | L2CAP_CONF_SUCCESS, flags), rsp); |
3275 | } | 3632 | } |
3276 | 3633 | ||
3277 | unlock: | 3634 | unlock: |
@@ -3362,7 +3719,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
3362 | goto done; | 3719 | goto done; |
3363 | } | 3720 | } |
3364 | 3721 | ||
3365 | if (flags & 0x01) | 3722 | if (flags & L2CAP_CONF_FLAG_CONTINUATION) |
3366 | goto done; | 3723 | goto done; |
3367 | 3724 | ||
3368 | set_bit(CONF_INPUT_DONE, &chan->conf_state); | 3725 | set_bit(CONF_INPUT_DONE, &chan->conf_state); |
@@ -3370,7 +3727,6 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
3370 | if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) { | 3727 | if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) { |
3371 | set_default_fcs(chan); | 3728 | set_default_fcs(chan); |
3372 | 3729 | ||
3373 | l2cap_state_change(chan, BT_CONNECTED); | ||
3374 | if (chan->mode == L2CAP_MODE_ERTM || | 3730 | if (chan->mode == L2CAP_MODE_ERTM || |
3375 | chan->mode == L2CAP_MODE_STREAMING) | 3731 | chan->mode == L2CAP_MODE_STREAMING) |
3376 | err = l2cap_ertm_init(chan); | 3732 | err = l2cap_ertm_init(chan); |
@@ -3424,7 +3780,7 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd | |||
3424 | 3780 | ||
3425 | l2cap_chan_unlock(chan); | 3781 | l2cap_chan_unlock(chan); |
3426 | 3782 | ||
3427 | chan->ops->close(chan->data); | 3783 | chan->ops->close(chan); |
3428 | l2cap_chan_put(chan); | 3784 | l2cap_chan_put(chan); |
3429 | 3785 | ||
3430 | mutex_unlock(&conn->chan_lock); | 3786 | mutex_unlock(&conn->chan_lock); |
@@ -3458,7 +3814,7 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd | |||
3458 | 3814 | ||
3459 | l2cap_chan_unlock(chan); | 3815 | l2cap_chan_unlock(chan); |
3460 | 3816 | ||
3461 | chan->ops->close(chan->data); | 3817 | chan->ops->close(chan); |
3462 | l2cap_chan_put(chan); | 3818 | l2cap_chan_put(chan); |
3463 | 3819 | ||
3464 | mutex_unlock(&conn->chan_lock); | 3820 | mutex_unlock(&conn->chan_lock); |
@@ -3479,8 +3835,8 @@ static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cm | |||
3479 | u8 buf[8]; | 3835 | u8 buf[8]; |
3480 | u32 feat_mask = l2cap_feat_mask; | 3836 | u32 feat_mask = l2cap_feat_mask; |
3481 | struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; | 3837 | struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; |
3482 | rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK); | 3838 | rsp->type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK); |
3483 | rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS); | 3839 | rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS); |
3484 | if (!disable_ertm) | 3840 | if (!disable_ertm) |
3485 | feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING | 3841 | feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING |
3486 | | L2CAP_FEAT_FCS; | 3842 | | L2CAP_FEAT_FCS; |
@@ -3500,15 +3856,15 @@ static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cm | |||
3500 | else | 3856 | else |
3501 | l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP; | 3857 | l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP; |
3502 | 3858 | ||
3503 | rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN); | 3859 | rsp->type = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN); |
3504 | rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS); | 3860 | rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS); |
3505 | memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan)); | 3861 | memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan)); |
3506 | l2cap_send_cmd(conn, cmd->ident, | 3862 | l2cap_send_cmd(conn, cmd->ident, |
3507 | L2CAP_INFO_RSP, sizeof(buf), buf); | 3863 | L2CAP_INFO_RSP, sizeof(buf), buf); |
3508 | } else { | 3864 | } else { |
3509 | struct l2cap_info_rsp rsp; | 3865 | struct l2cap_info_rsp rsp; |
3510 | rsp.type = cpu_to_le16(type); | 3866 | rsp.type = cpu_to_le16(type); |
3511 | rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP); | 3867 | rsp.result = __constant_cpu_to_le16(L2CAP_IR_NOTSUPP); |
3512 | l2cap_send_cmd(conn, cmd->ident, | 3868 | l2cap_send_cmd(conn, cmd->ident, |
3513 | L2CAP_INFO_RSP, sizeof(rsp), &rsp); | 3869 | L2CAP_INFO_RSP, sizeof(rsp), &rsp); |
3514 | } | 3870 | } |
@@ -3548,7 +3904,7 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cm | |||
3548 | 3904 | ||
3549 | if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) { | 3905 | if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) { |
3550 | struct l2cap_info_req req; | 3906 | struct l2cap_info_req req; |
3551 | req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN); | 3907 | req.type = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN); |
3552 | 3908 | ||
3553 | conn->info_ident = l2cap_get_ident(conn); | 3909 | conn->info_ident = l2cap_get_ident(conn); |
3554 | 3910 | ||
@@ -3783,9 +4139,9 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, | |||
3783 | 4139 | ||
3784 | err = l2cap_check_conn_param(min, max, latency, to_multiplier); | 4140 | err = l2cap_check_conn_param(min, max, latency, to_multiplier); |
3785 | if (err) | 4141 | if (err) |
3786 | rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED); | 4142 | rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_REJECTED); |
3787 | else | 4143 | else |
3788 | rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED); | 4144 | rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED); |
3789 | 4145 | ||
3790 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP, | 4146 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP, |
3791 | sizeof(rsp), &rsp); | 4147 | sizeof(rsp), &rsp); |
@@ -3933,7 +4289,7 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn, | |||
3933 | BT_ERR("Wrong link type (%d)", err); | 4289 | BT_ERR("Wrong link type (%d)", err); |
3934 | 4290 | ||
3935 | /* FIXME: Map err to a valid reason */ | 4291 | /* FIXME: Map err to a valid reason */ |
3936 | rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); | 4292 | rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); |
3937 | l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej); | 4293 | l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej); |
3938 | } | 4294 | } |
3939 | 4295 | ||
@@ -3965,65 +4321,38 @@ static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb) | |||
3965 | return 0; | 4321 | return 0; |
3966 | } | 4322 | } |
3967 | 4323 | ||
3968 | static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan) | 4324 | static void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan) |
3969 | { | 4325 | { |
3970 | u32 control = 0; | 4326 | struct l2cap_ctrl control; |
3971 | 4327 | ||
3972 | chan->frames_sent = 0; | 4328 | BT_DBG("chan %p", chan); |
3973 | 4329 | ||
3974 | control |= __set_reqseq(chan, chan->buffer_seq); | 4330 | memset(&control, 0, sizeof(control)); |
4331 | control.sframe = 1; | ||
4332 | control.final = 1; | ||
4333 | control.reqseq = chan->buffer_seq; | ||
4334 | set_bit(CONN_SEND_FBIT, &chan->conn_state); | ||
3975 | 4335 | ||
3976 | if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { | 4336 | if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { |
3977 | control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR); | 4337 | control.super = L2CAP_SUPER_RNR; |
3978 | l2cap_send_sframe(chan, control); | 4338 | l2cap_send_sframe(chan, &control); |
3979 | set_bit(CONN_RNR_SENT, &chan->conn_state); | ||
3980 | } | 4339 | } |
3981 | 4340 | ||
3982 | if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) | 4341 | if (test_and_clear_bit(CONN_REMOTE_BUSY, &chan->conn_state) && |
3983 | l2cap_retransmit_frames(chan); | 4342 | chan->unacked_frames > 0) |
4343 | __set_retrans_timer(chan); | ||
3984 | 4344 | ||
4345 | /* Send pending iframes */ | ||
3985 | l2cap_ertm_send(chan); | 4346 | l2cap_ertm_send(chan); |
3986 | 4347 | ||
3987 | if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && | 4348 | if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && |
3988 | chan->frames_sent == 0) { | 4349 | test_bit(CONN_SEND_FBIT, &chan->conn_state)) { |
3989 | control |= __set_ctrl_super(chan, L2CAP_SUPER_RR); | 4350 | /* F-bit wasn't sent in an s-frame or i-frame yet, so |
3990 | l2cap_send_sframe(chan, control); | 4351 | * send it now. |
3991 | } | 4352 | */ |
3992 | } | 4353 | control.super = L2CAP_SUPER_RR; |
3993 | 4354 | l2cap_send_sframe(chan, &control); | |
3994 | static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, u16 tx_seq, u8 sar) | ||
3995 | { | ||
3996 | struct sk_buff *next_skb; | ||
3997 | int tx_seq_offset, next_tx_seq_offset; | ||
3998 | |||
3999 | bt_cb(skb)->control.txseq = tx_seq; | ||
4000 | bt_cb(skb)->control.sar = sar; | ||
4001 | |||
4002 | next_skb = skb_peek(&chan->srej_q); | ||
4003 | |||
4004 | tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq); | ||
4005 | |||
4006 | while (next_skb) { | ||
4007 | if (bt_cb(next_skb)->control.txseq == tx_seq) | ||
4008 | return -EINVAL; | ||
4009 | |||
4010 | next_tx_seq_offset = __seq_offset(chan, | ||
4011 | bt_cb(next_skb)->control.txseq, chan->buffer_seq); | ||
4012 | |||
4013 | if (next_tx_seq_offset > tx_seq_offset) { | ||
4014 | __skb_queue_before(&chan->srej_q, next_skb, skb); | ||
4015 | return 0; | ||
4016 | } | ||
4017 | |||
4018 | if (skb_queue_is_last(&chan->srej_q, next_skb)) | ||
4019 | next_skb = NULL; | ||
4020 | else | ||
4021 | next_skb = skb_queue_next(&chan->srej_q, next_skb); | ||
4022 | } | 4355 | } |
4023 | |||
4024 | __skb_queue_tail(&chan->srej_q, skb); | ||
4025 | |||
4026 | return 0; | ||
4027 | } | 4356 | } |
4028 | 4357 | ||
4029 | static void append_skb_frag(struct sk_buff *skb, | 4358 | static void append_skb_frag(struct sk_buff *skb, |
@@ -4045,16 +4374,17 @@ static void append_skb_frag(struct sk_buff *skb, | |||
4045 | skb->truesize += new_frag->truesize; | 4374 | skb->truesize += new_frag->truesize; |
4046 | } | 4375 | } |
4047 | 4376 | ||
4048 | static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u32 control) | 4377 | static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, |
4378 | struct l2cap_ctrl *control) | ||
4049 | { | 4379 | { |
4050 | int err = -EINVAL; | 4380 | int err = -EINVAL; |
4051 | 4381 | ||
4052 | switch (__get_ctrl_sar(chan, control)) { | 4382 | switch (control->sar) { |
4053 | case L2CAP_SAR_UNSEGMENTED: | 4383 | case L2CAP_SAR_UNSEGMENTED: |
4054 | if (chan->sdu) | 4384 | if (chan->sdu) |
4055 | break; | 4385 | break; |
4056 | 4386 | ||
4057 | err = chan->ops->recv(chan->data, skb); | 4387 | err = chan->ops->recv(chan, skb); |
4058 | break; | 4388 | break; |
4059 | 4389 | ||
4060 | case L2CAP_SAR_START: | 4390 | case L2CAP_SAR_START: |
@@ -4104,7 +4434,7 @@ static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u3 | |||
4104 | if (chan->sdu->len != chan->sdu_len) | 4434 | if (chan->sdu->len != chan->sdu_len) |
4105 | break; | 4435 | break; |
4106 | 4436 | ||
4107 | err = chan->ops->recv(chan->data, chan->sdu); | 4437 | err = chan->ops->recv(chan, chan->sdu); |
4108 | 4438 | ||
4109 | if (!err) { | 4439 | if (!err) { |
4110 | /* Reassembly complete */ | 4440 | /* Reassembly complete */ |
@@ -4126,448 +4456,609 @@ static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u3 | |||
4126 | return err; | 4456 | return err; |
4127 | } | 4457 | } |
4128 | 4458 | ||
4129 | static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan) | 4459 | void l2cap_chan_busy(struct l2cap_chan *chan, int busy) |
4130 | { | 4460 | { |
4131 | BT_DBG("chan %p, Enter local busy", chan); | 4461 | u8 event; |
4132 | 4462 | ||
4133 | set_bit(CONN_LOCAL_BUSY, &chan->conn_state); | 4463 | if (chan->mode != L2CAP_MODE_ERTM) |
4134 | l2cap_seq_list_clear(&chan->srej_list); | 4464 | return; |
4135 | 4465 | ||
4136 | __set_ack_timer(chan); | 4466 | event = busy ? L2CAP_EV_LOCAL_BUSY_DETECTED : L2CAP_EV_LOCAL_BUSY_CLEAR; |
4467 | l2cap_tx(chan, NULL, NULL, event); | ||
4137 | } | 4468 | } |
4138 | 4469 | ||
4139 | static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan) | 4470 | static int l2cap_rx_queued_iframes(struct l2cap_chan *chan) |
4140 | { | 4471 | { |
4141 | u32 control; | 4472 | int err = 0; |
4142 | 4473 | /* Pass sequential frames to l2cap_reassemble_sdu() | |
4143 | if (!test_bit(CONN_RNR_SENT, &chan->conn_state)) | 4474 | * until a gap is encountered. |
4144 | goto done; | 4475 | */ |
4145 | 4476 | ||
4146 | control = __set_reqseq(chan, chan->buffer_seq); | 4477 | BT_DBG("chan %p", chan); |
4147 | control |= __set_ctrl_poll(chan); | ||
4148 | control |= __set_ctrl_super(chan, L2CAP_SUPER_RR); | ||
4149 | l2cap_send_sframe(chan, control); | ||
4150 | chan->retry_count = 1; | ||
4151 | 4478 | ||
4152 | __clear_retrans_timer(chan); | 4479 | while (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { |
4153 | __set_monitor_timer(chan); | 4480 | struct sk_buff *skb; |
4481 | BT_DBG("Searching for skb with txseq %d (queue len %d)", | ||
4482 | chan->buffer_seq, skb_queue_len(&chan->srej_q)); | ||
4154 | 4483 | ||
4155 | set_bit(CONN_WAIT_F, &chan->conn_state); | 4484 | skb = l2cap_ertm_seq_in_queue(&chan->srej_q, chan->buffer_seq); |
4156 | 4485 | ||
4157 | done: | 4486 | if (!skb) |
4158 | clear_bit(CONN_LOCAL_BUSY, &chan->conn_state); | 4487 | break; |
4159 | clear_bit(CONN_RNR_SENT, &chan->conn_state); | ||
4160 | 4488 | ||
4161 | BT_DBG("chan %p, Exit local busy", chan); | 4489 | skb_unlink(skb, &chan->srej_q); |
4162 | } | 4490 | chan->buffer_seq = __next_seq(chan, chan->buffer_seq); |
4491 | err = l2cap_reassemble_sdu(chan, skb, &bt_cb(skb)->control); | ||
4492 | if (err) | ||
4493 | break; | ||
4494 | } | ||
4163 | 4495 | ||
4164 | void l2cap_chan_busy(struct l2cap_chan *chan, int busy) | 4496 | if (skb_queue_empty(&chan->srej_q)) { |
4165 | { | 4497 | chan->rx_state = L2CAP_RX_STATE_RECV; |
4166 | if (chan->mode == L2CAP_MODE_ERTM) { | 4498 | l2cap_send_ack(chan); |
4167 | if (busy) | ||
4168 | l2cap_ertm_enter_local_busy(chan); | ||
4169 | else | ||
4170 | l2cap_ertm_exit_local_busy(chan); | ||
4171 | } | 4499 | } |
4500 | |||
4501 | return err; | ||
4172 | } | 4502 | } |
4173 | 4503 | ||
4174 | static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq) | 4504 | static void l2cap_handle_srej(struct l2cap_chan *chan, |
4505 | struct l2cap_ctrl *control) | ||
4175 | { | 4506 | { |
4176 | struct sk_buff *skb; | 4507 | struct sk_buff *skb; |
4177 | u32 control; | ||
4178 | 4508 | ||
4179 | while ((skb = skb_peek(&chan->srej_q)) && | 4509 | BT_DBG("chan %p, control %p", chan, control); |
4180 | !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { | ||
4181 | int err; | ||
4182 | 4510 | ||
4183 | if (bt_cb(skb)->control.txseq != tx_seq) | 4511 | if (control->reqseq == chan->next_tx_seq) { |
4184 | break; | 4512 | BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq); |
4513 | l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); | ||
4514 | return; | ||
4515 | } | ||
4185 | 4516 | ||
4186 | skb = skb_dequeue(&chan->srej_q); | 4517 | skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq); |
4187 | control = __set_ctrl_sar(chan, bt_cb(skb)->control.sar); | ||
4188 | err = l2cap_reassemble_sdu(chan, skb, control); | ||
4189 | 4518 | ||
4190 | if (err < 0) { | 4519 | if (skb == NULL) { |
4191 | l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); | 4520 | BT_DBG("Seq %d not available for retransmission", |
4192 | break; | 4521 | control->reqseq); |
4193 | } | 4522 | return; |
4523 | } | ||
4194 | 4524 | ||
4195 | chan->buffer_seq_srej = __next_seq(chan, chan->buffer_seq_srej); | 4525 | if (chan->max_tx != 0 && bt_cb(skb)->control.retries >= chan->max_tx) { |
4196 | tx_seq = __next_seq(chan, tx_seq); | 4526 | BT_DBG("Retry limit exceeded (%d)", chan->max_tx); |
4527 | l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); | ||
4528 | return; | ||
4197 | } | 4529 | } |
4198 | } | ||
4199 | 4530 | ||
4200 | static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq) | 4531 | clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); |
4201 | { | ||
4202 | struct srej_list *l, *tmp; | ||
4203 | u32 control; | ||
4204 | 4532 | ||
4205 | list_for_each_entry_safe(l, tmp, &chan->srej_l, list) { | 4533 | if (control->poll) { |
4206 | if (l->tx_seq == tx_seq) { | 4534 | l2cap_pass_to_tx(chan, control); |
4207 | list_del(&l->list); | 4535 | |
4208 | kfree(l); | 4536 | set_bit(CONN_SEND_FBIT, &chan->conn_state); |
4209 | return; | 4537 | l2cap_retransmit(chan, control); |
4538 | l2cap_ertm_send(chan); | ||
4539 | |||
4540 | if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) { | ||
4541 | set_bit(CONN_SREJ_ACT, &chan->conn_state); | ||
4542 | chan->srej_save_reqseq = control->reqseq; | ||
4543 | } | ||
4544 | } else { | ||
4545 | l2cap_pass_to_tx_fbit(chan, control); | ||
4546 | |||
4547 | if (control->final) { | ||
4548 | if (chan->srej_save_reqseq != control->reqseq || | ||
4549 | !test_and_clear_bit(CONN_SREJ_ACT, | ||
4550 | &chan->conn_state)) | ||
4551 | l2cap_retransmit(chan, control); | ||
4552 | } else { | ||
4553 | l2cap_retransmit(chan, control); | ||
4554 | if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) { | ||
4555 | set_bit(CONN_SREJ_ACT, &chan->conn_state); | ||
4556 | chan->srej_save_reqseq = control->reqseq; | ||
4557 | } | ||
4210 | } | 4558 | } |
4211 | control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ); | ||
4212 | control |= __set_reqseq(chan, l->tx_seq); | ||
4213 | l2cap_send_sframe(chan, control); | ||
4214 | list_del(&l->list); | ||
4215 | list_add_tail(&l->list, &chan->srej_l); | ||
4216 | } | 4559 | } |
4217 | } | 4560 | } |
4218 | 4561 | ||
4219 | static int l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq) | 4562 | static void l2cap_handle_rej(struct l2cap_chan *chan, |
4563 | struct l2cap_ctrl *control) | ||
4220 | { | 4564 | { |
4221 | struct srej_list *new; | 4565 | struct sk_buff *skb; |
4222 | u32 control; | ||
4223 | |||
4224 | while (tx_seq != chan->expected_tx_seq) { | ||
4225 | control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ); | ||
4226 | control |= __set_reqseq(chan, chan->expected_tx_seq); | ||
4227 | l2cap_seq_list_append(&chan->srej_list, chan->expected_tx_seq); | ||
4228 | l2cap_send_sframe(chan, control); | ||
4229 | 4566 | ||
4230 | new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC); | 4567 | BT_DBG("chan %p, control %p", chan, control); |
4231 | if (!new) | ||
4232 | return -ENOMEM; | ||
4233 | 4568 | ||
4234 | new->tx_seq = chan->expected_tx_seq; | 4569 | if (control->reqseq == chan->next_tx_seq) { |
4570 | BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq); | ||
4571 | l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); | ||
4572 | return; | ||
4573 | } | ||
4235 | 4574 | ||
4236 | chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq); | 4575 | skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq); |
4237 | 4576 | ||
4238 | list_add_tail(&new->list, &chan->srej_l); | 4577 | if (chan->max_tx && skb && |
4578 | bt_cb(skb)->control.retries >= chan->max_tx) { | ||
4579 | BT_DBG("Retry limit exceeded (%d)", chan->max_tx); | ||
4580 | l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); | ||
4581 | return; | ||
4239 | } | 4582 | } |
4240 | 4583 | ||
4241 | chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq); | 4584 | clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); |
4242 | 4585 | ||
4243 | return 0; | 4586 | l2cap_pass_to_tx(chan, control); |
4587 | |||
4588 | if (control->final) { | ||
4589 | if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state)) | ||
4590 | l2cap_retransmit_all(chan, control); | ||
4591 | } else { | ||
4592 | l2cap_retransmit_all(chan, control); | ||
4593 | l2cap_ertm_send(chan); | ||
4594 | if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) | ||
4595 | set_bit(CONN_REJ_ACT, &chan->conn_state); | ||
4596 | } | ||
4244 | } | 4597 | } |
4245 | 4598 | ||
4246 | static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb) | 4599 | static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq) |
4247 | { | 4600 | { |
4248 | u16 tx_seq = __get_txseq(chan, rx_control); | 4601 | BT_DBG("chan %p, txseq %d", chan, txseq); |
4249 | u16 req_seq = __get_reqseq(chan, rx_control); | ||
4250 | u8 sar = __get_ctrl_sar(chan, rx_control); | ||
4251 | int tx_seq_offset, expected_tx_seq_offset; | ||
4252 | int num_to_ack = (chan->tx_win/6) + 1; | ||
4253 | int err = 0; | ||
4254 | 4602 | ||
4255 | BT_DBG("chan %p len %d tx_seq %d rx_control 0x%8.8x", chan, skb->len, | 4603 | BT_DBG("last_acked_seq %d, expected_tx_seq %d", chan->last_acked_seq, |
4256 | tx_seq, rx_control); | 4604 | chan->expected_tx_seq); |
4257 | 4605 | ||
4258 | if (__is_ctrl_final(chan, rx_control) && | 4606 | if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { |
4259 | test_bit(CONN_WAIT_F, &chan->conn_state)) { | 4607 | if (__seq_offset(chan, txseq, chan->last_acked_seq) >= |
4260 | __clear_monitor_timer(chan); | 4608 | chan->tx_win) { |
4261 | if (chan->unacked_frames > 0) | 4609 | /* See notes below regarding "double poll" and |
4262 | __set_retrans_timer(chan); | 4610 | * invalid packets. |
4263 | clear_bit(CONN_WAIT_F, &chan->conn_state); | 4611 | */ |
4264 | } | 4612 | if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) { |
4613 | BT_DBG("Invalid/Ignore - after SREJ"); | ||
4614 | return L2CAP_TXSEQ_INVALID_IGNORE; | ||
4615 | } else { | ||
4616 | BT_DBG("Invalid - in window after SREJ sent"); | ||
4617 | return L2CAP_TXSEQ_INVALID; | ||
4618 | } | ||
4619 | } | ||
4265 | 4620 | ||
4266 | chan->expected_ack_seq = req_seq; | 4621 | if (chan->srej_list.head == txseq) { |
4267 | l2cap_drop_acked_frames(chan); | 4622 | BT_DBG("Expected SREJ"); |
4623 | return L2CAP_TXSEQ_EXPECTED_SREJ; | ||
4624 | } | ||
4268 | 4625 | ||
4269 | tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq); | 4626 | if (l2cap_ertm_seq_in_queue(&chan->srej_q, txseq)) { |
4627 | BT_DBG("Duplicate SREJ - txseq already stored"); | ||
4628 | return L2CAP_TXSEQ_DUPLICATE_SREJ; | ||
4629 | } | ||
4270 | 4630 | ||
4271 | /* invalid tx_seq */ | 4631 | if (l2cap_seq_list_contains(&chan->srej_list, txseq)) { |
4272 | if (tx_seq_offset >= chan->tx_win) { | 4632 | BT_DBG("Unexpected SREJ - not requested"); |
4273 | l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); | 4633 | return L2CAP_TXSEQ_UNEXPECTED_SREJ; |
4274 | goto drop; | 4634 | } |
4275 | } | 4635 | } |
4276 | 4636 | ||
4277 | if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { | 4637 | if (chan->expected_tx_seq == txseq) { |
4278 | if (!test_bit(CONN_RNR_SENT, &chan->conn_state)) | 4638 | if (__seq_offset(chan, txseq, chan->last_acked_seq) >= |
4279 | l2cap_send_ack(chan); | 4639 | chan->tx_win) { |
4280 | goto drop; | 4640 | BT_DBG("Invalid - txseq outside tx window"); |
4641 | return L2CAP_TXSEQ_INVALID; | ||
4642 | } else { | ||
4643 | BT_DBG("Expected"); | ||
4644 | return L2CAP_TXSEQ_EXPECTED; | ||
4645 | } | ||
4281 | } | 4646 | } |
4282 | 4647 | ||
4283 | if (tx_seq == chan->expected_tx_seq) | 4648 | if (__seq_offset(chan, txseq, chan->last_acked_seq) < |
4284 | goto expected; | 4649 | __seq_offset(chan, chan->expected_tx_seq, |
4650 | chan->last_acked_seq)){ | ||
4651 | BT_DBG("Duplicate - expected_tx_seq later than txseq"); | ||
4652 | return L2CAP_TXSEQ_DUPLICATE; | ||
4653 | } | ||
4654 | |||
4655 | if (__seq_offset(chan, txseq, chan->last_acked_seq) >= chan->tx_win) { | ||
4656 | /* A source of invalid packets is a "double poll" condition, | ||
4657 | * where delays cause us to send multiple poll packets. If | ||
4658 | * the remote stack receives and processes both polls, | ||
4659 | * sequence numbers can wrap around in such a way that a | ||
4660 | * resent frame has a sequence number that looks like new data | ||
4661 | * with a sequence gap. This would trigger an erroneous SREJ | ||
4662 | * request. | ||
4663 | * | ||
4664 | * Fortunately, this is impossible with a tx window that's | ||
4665 | * less than half of the maximum sequence number, which allows | ||
4666 | * invalid frames to be safely ignored. | ||
4667 | * | ||
4668 | * With tx window sizes greater than half of the tx window | ||
4669 | * maximum, the frame is invalid and cannot be ignored. This | ||
4670 | * causes a disconnect. | ||
4671 | */ | ||
4672 | |||
4673 | if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) { | ||
4674 | BT_DBG("Invalid/Ignore - txseq outside tx window"); | ||
4675 | return L2CAP_TXSEQ_INVALID_IGNORE; | ||
4676 | } else { | ||
4677 | BT_DBG("Invalid - txseq outside tx window"); | ||
4678 | return L2CAP_TXSEQ_INVALID; | ||
4679 | } | ||
4680 | } else { | ||
4681 | BT_DBG("Unexpected - txseq indicates missing frames"); | ||
4682 | return L2CAP_TXSEQ_UNEXPECTED; | ||
4683 | } | ||
4684 | } | ||
4285 | 4685 | ||
4286 | if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) { | 4686 | static int l2cap_rx_state_recv(struct l2cap_chan *chan, |
4287 | struct srej_list *first; | 4687 | struct l2cap_ctrl *control, |
4688 | struct sk_buff *skb, u8 event) | ||
4689 | { | ||
4690 | int err = 0; | ||
4691 | bool skb_in_use = 0; | ||
4288 | 4692 | ||
4289 | first = list_first_entry(&chan->srej_l, | 4693 | BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, |
4290 | struct srej_list, list); | 4694 | event); |
4291 | if (tx_seq == first->tx_seq) { | ||
4292 | l2cap_add_to_srej_queue(chan, skb, tx_seq, sar); | ||
4293 | l2cap_check_srej_gap(chan, tx_seq); | ||
4294 | 4695 | ||
4295 | list_del(&first->list); | 4696 | switch (event) { |
4296 | kfree(first); | 4697 | case L2CAP_EV_RECV_IFRAME: |
4698 | switch (l2cap_classify_txseq(chan, control->txseq)) { | ||
4699 | case L2CAP_TXSEQ_EXPECTED: | ||
4700 | l2cap_pass_to_tx(chan, control); | ||
4297 | 4701 | ||
4298 | if (list_empty(&chan->srej_l)) { | 4702 | if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { |
4299 | chan->buffer_seq = chan->buffer_seq_srej; | 4703 | BT_DBG("Busy, discarding expected seq %d", |
4300 | clear_bit(CONN_SREJ_SENT, &chan->conn_state); | 4704 | control->txseq); |
4301 | l2cap_send_ack(chan); | 4705 | break; |
4302 | BT_DBG("chan %p, Exit SREJ_SENT", chan); | ||
4303 | } | 4706 | } |
4304 | } else { | ||
4305 | struct srej_list *l; | ||
4306 | 4707 | ||
4307 | /* duplicated tx_seq */ | 4708 | chan->expected_tx_seq = __next_seq(chan, |
4308 | if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0) | 4709 | control->txseq); |
4309 | goto drop; | 4710 | |
4711 | chan->buffer_seq = chan->expected_tx_seq; | ||
4712 | skb_in_use = 1; | ||
4310 | 4713 | ||
4311 | list_for_each_entry(l, &chan->srej_l, list) { | 4714 | err = l2cap_reassemble_sdu(chan, skb, control); |
4312 | if (l->tx_seq == tx_seq) { | 4715 | if (err) |
4313 | l2cap_resend_srejframe(chan, tx_seq); | 4716 | break; |
4314 | return 0; | 4717 | |
4718 | if (control->final) { | ||
4719 | if (!test_and_clear_bit(CONN_REJ_ACT, | ||
4720 | &chan->conn_state)) { | ||
4721 | control->final = 0; | ||
4722 | l2cap_retransmit_all(chan, control); | ||
4723 | l2cap_ertm_send(chan); | ||
4315 | } | 4724 | } |
4316 | } | 4725 | } |
4317 | 4726 | ||
4318 | err = l2cap_send_srejframe(chan, tx_seq); | 4727 | if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) |
4319 | if (err < 0) { | 4728 | l2cap_send_ack(chan); |
4320 | l2cap_send_disconn_req(chan->conn, chan, -err); | 4729 | break; |
4321 | return err; | 4730 | case L2CAP_TXSEQ_UNEXPECTED: |
4731 | l2cap_pass_to_tx(chan, control); | ||
4732 | |||
4733 | /* Can't issue SREJ frames in the local busy state. | ||
4734 | * Drop this frame, it will be seen as missing | ||
4735 | * when local busy is exited. | ||
4736 | */ | ||
4737 | if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { | ||
4738 | BT_DBG("Busy, discarding unexpected seq %d", | ||
4739 | control->txseq); | ||
4740 | break; | ||
4322 | } | 4741 | } |
4323 | } | ||
4324 | } else { | ||
4325 | expected_tx_seq_offset = __seq_offset(chan, | ||
4326 | chan->expected_tx_seq, chan->buffer_seq); | ||
4327 | 4742 | ||
4328 | /* duplicated tx_seq */ | 4743 | /* There was a gap in the sequence, so an SREJ |
4329 | if (tx_seq_offset < expected_tx_seq_offset) | 4744 | * must be sent for each missing frame. The |
4330 | goto drop; | 4745 | * current frame is stored for later use. |
4331 | 4746 | */ | |
4332 | set_bit(CONN_SREJ_SENT, &chan->conn_state); | 4747 | skb_queue_tail(&chan->srej_q, skb); |
4748 | skb_in_use = 1; | ||
4749 | BT_DBG("Queued %p (queue len %d)", skb, | ||
4750 | skb_queue_len(&chan->srej_q)); | ||
4333 | 4751 | ||
4334 | BT_DBG("chan %p, Enter SREJ", chan); | 4752 | clear_bit(CONN_SREJ_ACT, &chan->conn_state); |
4753 | l2cap_seq_list_clear(&chan->srej_list); | ||
4754 | l2cap_send_srej(chan, control->txseq); | ||
4335 | 4755 | ||
4336 | INIT_LIST_HEAD(&chan->srej_l); | 4756 | chan->rx_state = L2CAP_RX_STATE_SREJ_SENT; |
4337 | chan->buffer_seq_srej = chan->buffer_seq; | 4757 | break; |
4758 | case L2CAP_TXSEQ_DUPLICATE: | ||
4759 | l2cap_pass_to_tx(chan, control); | ||
4760 | break; | ||
4761 | case L2CAP_TXSEQ_INVALID_IGNORE: | ||
4762 | break; | ||
4763 | case L2CAP_TXSEQ_INVALID: | ||
4764 | default: | ||
4765 | l2cap_send_disconn_req(chan->conn, chan, | ||
4766 | ECONNRESET); | ||
4767 | break; | ||
4768 | } | ||
4769 | break; | ||
4770 | case L2CAP_EV_RECV_RR: | ||
4771 | l2cap_pass_to_tx(chan, control); | ||
4772 | if (control->final) { | ||
4773 | clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); | ||
4338 | 4774 | ||
4339 | __skb_queue_head_init(&chan->srej_q); | 4775 | if (!test_and_clear_bit(CONN_REJ_ACT, |
4340 | l2cap_add_to_srej_queue(chan, skb, tx_seq, sar); | 4776 | &chan->conn_state)) { |
4777 | control->final = 0; | ||
4778 | l2cap_retransmit_all(chan, control); | ||
4779 | } | ||
4341 | 4780 | ||
4342 | /* Set P-bit only if there are some I-frames to ack. */ | 4781 | l2cap_ertm_send(chan); |
4343 | if (__clear_ack_timer(chan)) | 4782 | } else if (control->poll) { |
4344 | set_bit(CONN_SEND_PBIT, &chan->conn_state); | 4783 | l2cap_send_i_or_rr_or_rnr(chan); |
4784 | } else { | ||
4785 | if (test_and_clear_bit(CONN_REMOTE_BUSY, | ||
4786 | &chan->conn_state) && | ||
4787 | chan->unacked_frames) | ||
4788 | __set_retrans_timer(chan); | ||
4345 | 4789 | ||
4346 | err = l2cap_send_srejframe(chan, tx_seq); | 4790 | l2cap_ertm_send(chan); |
4347 | if (err < 0) { | ||
4348 | l2cap_send_disconn_req(chan->conn, chan, -err); | ||
4349 | return err; | ||
4350 | } | 4791 | } |
4792 | break; | ||
4793 | case L2CAP_EV_RECV_RNR: | ||
4794 | set_bit(CONN_REMOTE_BUSY, &chan->conn_state); | ||
4795 | l2cap_pass_to_tx(chan, control); | ||
4796 | if (control && control->poll) { | ||
4797 | set_bit(CONN_SEND_FBIT, &chan->conn_state); | ||
4798 | l2cap_send_rr_or_rnr(chan, 0); | ||
4799 | } | ||
4800 | __clear_retrans_timer(chan); | ||
4801 | l2cap_seq_list_clear(&chan->retrans_list); | ||
4802 | break; | ||
4803 | case L2CAP_EV_RECV_REJ: | ||
4804 | l2cap_handle_rej(chan, control); | ||
4805 | break; | ||
4806 | case L2CAP_EV_RECV_SREJ: | ||
4807 | l2cap_handle_srej(chan, control); | ||
4808 | break; | ||
4809 | default: | ||
4810 | break; | ||
4351 | } | 4811 | } |
4352 | return 0; | ||
4353 | |||
4354 | expected: | ||
4355 | chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq); | ||
4356 | |||
4357 | if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) { | ||
4358 | bt_cb(skb)->control.txseq = tx_seq; | ||
4359 | bt_cb(skb)->control.sar = sar; | ||
4360 | __skb_queue_tail(&chan->srej_q, skb); | ||
4361 | return 0; | ||
4362 | } | ||
4363 | |||
4364 | err = l2cap_reassemble_sdu(chan, skb, rx_control); | ||
4365 | chan->buffer_seq = __next_seq(chan, chan->buffer_seq); | ||
4366 | 4812 | ||
4367 | if (err < 0) { | 4813 | if (skb && !skb_in_use) { |
4368 | l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); | 4814 | BT_DBG("Freeing %p", skb); |
4369 | return err; | 4815 | kfree_skb(skb); |
4370 | } | 4816 | } |
4371 | 4817 | ||
4372 | if (__is_ctrl_final(chan, rx_control)) { | 4818 | return err; |
4373 | if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state)) | 4819 | } |
4374 | l2cap_retransmit_frames(chan); | ||
4375 | } | ||
4376 | 4820 | ||
4821 | static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan, | ||
4822 | struct l2cap_ctrl *control, | ||
4823 | struct sk_buff *skb, u8 event) | ||
4824 | { | ||
4825 | int err = 0; | ||
4826 | u16 txseq = control->txseq; | ||
4827 | bool skb_in_use = 0; | ||
4828 | |||
4829 | BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, | ||
4830 | event); | ||
4831 | |||
4832 | switch (event) { | ||
4833 | case L2CAP_EV_RECV_IFRAME: | ||
4834 | switch (l2cap_classify_txseq(chan, txseq)) { | ||
4835 | case L2CAP_TXSEQ_EXPECTED: | ||
4836 | /* Keep frame for reassembly later */ | ||
4837 | l2cap_pass_to_tx(chan, control); | ||
4838 | skb_queue_tail(&chan->srej_q, skb); | ||
4839 | skb_in_use = 1; | ||
4840 | BT_DBG("Queued %p (queue len %d)", skb, | ||
4841 | skb_queue_len(&chan->srej_q)); | ||
4842 | |||
4843 | chan->expected_tx_seq = __next_seq(chan, txseq); | ||
4844 | break; | ||
4845 | case L2CAP_TXSEQ_EXPECTED_SREJ: | ||
4846 | l2cap_seq_list_pop(&chan->srej_list); | ||
4377 | 4847 | ||
4378 | chan->num_acked = (chan->num_acked + 1) % num_to_ack; | 4848 | l2cap_pass_to_tx(chan, control); |
4379 | if (chan->num_acked == num_to_ack - 1) | 4849 | skb_queue_tail(&chan->srej_q, skb); |
4380 | l2cap_send_ack(chan); | 4850 | skb_in_use = 1; |
4381 | else | 4851 | BT_DBG("Queued %p (queue len %d)", skb, |
4382 | __set_ack_timer(chan); | 4852 | skb_queue_len(&chan->srej_q)); |
4383 | 4853 | ||
4384 | return 0; | 4854 | err = l2cap_rx_queued_iframes(chan); |
4855 | if (err) | ||
4856 | break; | ||
4385 | 4857 | ||
4386 | drop: | 4858 | break; |
4387 | kfree_skb(skb); | 4859 | case L2CAP_TXSEQ_UNEXPECTED: |
4388 | return 0; | 4860 | /* Got a frame that can't be reassembled yet. |
4389 | } | 4861 | * Save it for later, and send SREJs to cover |
4862 | * the missing frames. | ||
4863 | */ | ||
4864 | skb_queue_tail(&chan->srej_q, skb); | ||
4865 | skb_in_use = 1; | ||
4866 | BT_DBG("Queued %p (queue len %d)", skb, | ||
4867 | skb_queue_len(&chan->srej_q)); | ||
4868 | |||
4869 | l2cap_pass_to_tx(chan, control); | ||
4870 | l2cap_send_srej(chan, control->txseq); | ||
4871 | break; | ||
4872 | case L2CAP_TXSEQ_UNEXPECTED_SREJ: | ||
4873 | /* This frame was requested with an SREJ, but | ||
4874 | * some expected retransmitted frames are | ||
4875 | * missing. Request retransmission of missing | ||
4876 | * SREJ'd frames. | ||
4877 | */ | ||
4878 | skb_queue_tail(&chan->srej_q, skb); | ||
4879 | skb_in_use = 1; | ||
4880 | BT_DBG("Queued %p (queue len %d)", skb, | ||
4881 | skb_queue_len(&chan->srej_q)); | ||
4882 | |||
4883 | l2cap_pass_to_tx(chan, control); | ||
4884 | l2cap_send_srej_list(chan, control->txseq); | ||
4885 | break; | ||
4886 | case L2CAP_TXSEQ_DUPLICATE_SREJ: | ||
4887 | /* We've already queued this frame. Drop this copy. */ | ||
4888 | l2cap_pass_to_tx(chan, control); | ||
4889 | break; | ||
4890 | case L2CAP_TXSEQ_DUPLICATE: | ||
4891 | /* Expecting a later sequence number, so this frame | ||
4892 | * was already received. Ignore it completely. | ||
4893 | */ | ||
4894 | break; | ||
4895 | case L2CAP_TXSEQ_INVALID_IGNORE: | ||
4896 | break; | ||
4897 | case L2CAP_TXSEQ_INVALID: | ||
4898 | default: | ||
4899 | l2cap_send_disconn_req(chan->conn, chan, | ||
4900 | ECONNRESET); | ||
4901 | break; | ||
4902 | } | ||
4903 | break; | ||
4904 | case L2CAP_EV_RECV_RR: | ||
4905 | l2cap_pass_to_tx(chan, control); | ||
4906 | if (control->final) { | ||
4907 | clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); | ||
4390 | 4908 | ||
4391 | static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u32 rx_control) | 4909 | if (!test_and_clear_bit(CONN_REJ_ACT, |
4392 | { | 4910 | &chan->conn_state)) { |
4393 | BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, | 4911 | control->final = 0; |
4394 | __get_reqseq(chan, rx_control), rx_control); | 4912 | l2cap_retransmit_all(chan, control); |
4913 | } | ||
4395 | 4914 | ||
4396 | chan->expected_ack_seq = __get_reqseq(chan, rx_control); | 4915 | l2cap_ertm_send(chan); |
4397 | l2cap_drop_acked_frames(chan); | 4916 | } else if (control->poll) { |
4917 | if (test_and_clear_bit(CONN_REMOTE_BUSY, | ||
4918 | &chan->conn_state) && | ||
4919 | chan->unacked_frames) { | ||
4920 | __set_retrans_timer(chan); | ||
4921 | } | ||
4398 | 4922 | ||
4399 | if (__is_ctrl_poll(chan, rx_control)) { | 4923 | set_bit(CONN_SEND_FBIT, &chan->conn_state); |
4400 | set_bit(CONN_SEND_FBIT, &chan->conn_state); | 4924 | l2cap_send_srej_tail(chan); |
4401 | if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) { | 4925 | } else { |
4402 | if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) && | 4926 | if (test_and_clear_bit(CONN_REMOTE_BUSY, |
4403 | (chan->unacked_frames > 0)) | 4927 | &chan->conn_state) && |
4928 | chan->unacked_frames) | ||
4404 | __set_retrans_timer(chan); | 4929 | __set_retrans_timer(chan); |
4405 | 4930 | ||
4406 | clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); | 4931 | l2cap_send_ack(chan); |
4407 | l2cap_send_srejtail(chan); | 4932 | } |
4933 | break; | ||
4934 | case L2CAP_EV_RECV_RNR: | ||
4935 | set_bit(CONN_REMOTE_BUSY, &chan->conn_state); | ||
4936 | l2cap_pass_to_tx(chan, control); | ||
4937 | if (control->poll) { | ||
4938 | l2cap_send_srej_tail(chan); | ||
4408 | } else { | 4939 | } else { |
4409 | l2cap_send_i_or_rr_or_rnr(chan); | 4940 | struct l2cap_ctrl rr_control; |
4941 | memset(&rr_control, 0, sizeof(rr_control)); | ||
4942 | rr_control.sframe = 1; | ||
4943 | rr_control.super = L2CAP_SUPER_RR; | ||
4944 | rr_control.reqseq = chan->buffer_seq; | ||
4945 | l2cap_send_sframe(chan, &rr_control); | ||
4410 | } | 4946 | } |
4411 | 4947 | ||
4412 | } else if (__is_ctrl_final(chan, rx_control)) { | 4948 | break; |
4413 | clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); | 4949 | case L2CAP_EV_RECV_REJ: |
4414 | 4950 | l2cap_handle_rej(chan, control); | |
4415 | if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state)) | 4951 | break; |
4416 | l2cap_retransmit_frames(chan); | 4952 | case L2CAP_EV_RECV_SREJ: |
4417 | 4953 | l2cap_handle_srej(chan, control); | |
4418 | } else { | 4954 | break; |
4419 | if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) && | 4955 | } |
4420 | (chan->unacked_frames > 0)) | ||
4421 | __set_retrans_timer(chan); | ||
4422 | 4956 | ||
4423 | clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); | 4957 | if (skb && !skb_in_use) { |
4424 | if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) | 4958 | BT_DBG("Freeing %p", skb); |
4425 | l2cap_send_ack(chan); | 4959 | kfree_skb(skb); |
4426 | else | ||
4427 | l2cap_ertm_send(chan); | ||
4428 | } | 4960 | } |
4961 | |||
4962 | return err; | ||
4429 | } | 4963 | } |
4430 | 4964 | ||
4431 | static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u32 rx_control) | 4965 | static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq) |
4432 | { | 4966 | { |
4433 | u16 tx_seq = __get_reqseq(chan, rx_control); | 4967 | /* Make sure reqseq is for a packet that has been sent but not acked */ |
4434 | 4968 | u16 unacked; | |
4435 | BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control); | ||
4436 | |||
4437 | clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); | ||
4438 | |||
4439 | chan->expected_ack_seq = tx_seq; | ||
4440 | l2cap_drop_acked_frames(chan); | ||
4441 | |||
4442 | if (__is_ctrl_final(chan, rx_control)) { | ||
4443 | if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state)) | ||
4444 | l2cap_retransmit_frames(chan); | ||
4445 | } else { | ||
4446 | l2cap_retransmit_frames(chan); | ||
4447 | 4969 | ||
4448 | if (test_bit(CONN_WAIT_F, &chan->conn_state)) | 4970 | unacked = __seq_offset(chan, chan->next_tx_seq, chan->expected_ack_seq); |
4449 | set_bit(CONN_REJ_ACT, &chan->conn_state); | 4971 | return __seq_offset(chan, chan->next_tx_seq, reqseq) <= unacked; |
4450 | } | ||
4451 | } | 4972 | } |
4452 | static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u32 rx_control) | ||
4453 | { | ||
4454 | u16 tx_seq = __get_reqseq(chan, rx_control); | ||
4455 | |||
4456 | BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control); | ||
4457 | |||
4458 | clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); | ||
4459 | 4973 | ||
4460 | if (__is_ctrl_poll(chan, rx_control)) { | 4974 | static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, |
4461 | chan->expected_ack_seq = tx_seq; | 4975 | struct sk_buff *skb, u8 event) |
4462 | l2cap_drop_acked_frames(chan); | 4976 | { |
4463 | 4977 | int err = 0; | |
4464 | set_bit(CONN_SEND_FBIT, &chan->conn_state); | ||
4465 | l2cap_retransmit_one_frame(chan, tx_seq); | ||
4466 | 4978 | ||
4467 | l2cap_ertm_send(chan); | 4979 | BT_DBG("chan %p, control %p, skb %p, event %d, state %d", chan, |
4980 | control, skb, event, chan->rx_state); | ||
4468 | 4981 | ||
4469 | if (test_bit(CONN_WAIT_F, &chan->conn_state)) { | 4982 | if (__valid_reqseq(chan, control->reqseq)) { |
4470 | chan->srej_save_reqseq = tx_seq; | 4983 | switch (chan->rx_state) { |
4471 | set_bit(CONN_SREJ_ACT, &chan->conn_state); | 4984 | case L2CAP_RX_STATE_RECV: |
4985 | err = l2cap_rx_state_recv(chan, control, skb, event); | ||
4986 | break; | ||
4987 | case L2CAP_RX_STATE_SREJ_SENT: | ||
4988 | err = l2cap_rx_state_srej_sent(chan, control, skb, | ||
4989 | event); | ||
4990 | break; | ||
4991 | default: | ||
4992 | /* shut it down */ | ||
4993 | break; | ||
4472 | } | 4994 | } |
4473 | } else if (__is_ctrl_final(chan, rx_control)) { | ||
4474 | if (test_bit(CONN_SREJ_ACT, &chan->conn_state) && | ||
4475 | chan->srej_save_reqseq == tx_seq) | ||
4476 | clear_bit(CONN_SREJ_ACT, &chan->conn_state); | ||
4477 | else | ||
4478 | l2cap_retransmit_one_frame(chan, tx_seq); | ||
4479 | } else { | 4995 | } else { |
4480 | l2cap_retransmit_one_frame(chan, tx_seq); | 4996 | BT_DBG("Invalid reqseq %d (next_tx_seq %d, expected_ack_seq %d", |
4481 | if (test_bit(CONN_WAIT_F, &chan->conn_state)) { | 4997 | control->reqseq, chan->next_tx_seq, |
4482 | chan->srej_save_reqseq = tx_seq; | 4998 | chan->expected_ack_seq); |
4483 | set_bit(CONN_SREJ_ACT, &chan->conn_state); | 4999 | l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); |
4484 | } | ||
4485 | } | 5000 | } |
5001 | |||
5002 | return err; | ||
4486 | } | 5003 | } |
4487 | 5004 | ||
4488 | static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u32 rx_control) | 5005 | static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, |
5006 | struct sk_buff *skb) | ||
4489 | { | 5007 | { |
4490 | u16 tx_seq = __get_reqseq(chan, rx_control); | 5008 | int err = 0; |
4491 | 5009 | ||
4492 | BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control); | 5010 | BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb, |
5011 | chan->rx_state); | ||
4493 | 5012 | ||
4494 | set_bit(CONN_REMOTE_BUSY, &chan->conn_state); | 5013 | if (l2cap_classify_txseq(chan, control->txseq) == |
4495 | chan->expected_ack_seq = tx_seq; | 5014 | L2CAP_TXSEQ_EXPECTED) { |
4496 | l2cap_drop_acked_frames(chan); | 5015 | l2cap_pass_to_tx(chan, control); |
4497 | 5016 | ||
4498 | if (__is_ctrl_poll(chan, rx_control)) | 5017 | BT_DBG("buffer_seq %d->%d", chan->buffer_seq, |
4499 | set_bit(CONN_SEND_FBIT, &chan->conn_state); | 5018 | __next_seq(chan, chan->buffer_seq)); |
4500 | 5019 | ||
4501 | if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) { | 5020 | chan->buffer_seq = __next_seq(chan, chan->buffer_seq); |
4502 | __clear_retrans_timer(chan); | ||
4503 | if (__is_ctrl_poll(chan, rx_control)) | ||
4504 | l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL); | ||
4505 | return; | ||
4506 | } | ||
4507 | 5021 | ||
4508 | if (__is_ctrl_poll(chan, rx_control)) { | 5022 | l2cap_reassemble_sdu(chan, skb, control); |
4509 | l2cap_send_srejtail(chan); | ||
4510 | } else { | 5023 | } else { |
4511 | rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR); | 5024 | if (chan->sdu) { |
4512 | l2cap_send_sframe(chan, rx_control); | 5025 | kfree_skb(chan->sdu); |
4513 | } | 5026 | chan->sdu = NULL; |
4514 | } | 5027 | } |
4515 | 5028 | chan->sdu_last_frag = NULL; | |
4516 | static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb) | 5029 | chan->sdu_len = 0; |
4517 | { | ||
4518 | BT_DBG("chan %p rx_control 0x%8.8x len %d", chan, rx_control, skb->len); | ||
4519 | 5030 | ||
4520 | if (__is_ctrl_final(chan, rx_control) && | 5031 | if (skb) { |
4521 | test_bit(CONN_WAIT_F, &chan->conn_state)) { | 5032 | BT_DBG("Freeing %p", skb); |
4522 | __clear_monitor_timer(chan); | 5033 | kfree_skb(skb); |
4523 | if (chan->unacked_frames > 0) | 5034 | } |
4524 | __set_retrans_timer(chan); | ||
4525 | clear_bit(CONN_WAIT_F, &chan->conn_state); | ||
4526 | } | 5035 | } |
4527 | 5036 | ||
4528 | switch (__get_ctrl_super(chan, rx_control)) { | 5037 | chan->last_acked_seq = control->txseq; |
4529 | case L2CAP_SUPER_RR: | 5038 | chan->expected_tx_seq = __next_seq(chan, control->txseq); |
4530 | l2cap_data_channel_rrframe(chan, rx_control); | ||
4531 | break; | ||
4532 | 5039 | ||
4533 | case L2CAP_SUPER_REJ: | 5040 | return err; |
4534 | l2cap_data_channel_rejframe(chan, rx_control); | ||
4535 | break; | ||
4536 | |||
4537 | case L2CAP_SUPER_SREJ: | ||
4538 | l2cap_data_channel_srejframe(chan, rx_control); | ||
4539 | break; | ||
4540 | |||
4541 | case L2CAP_SUPER_RNR: | ||
4542 | l2cap_data_channel_rnrframe(chan, rx_control); | ||
4543 | break; | ||
4544 | } | ||
4545 | |||
4546 | kfree_skb(skb); | ||
4547 | return 0; | ||
4548 | } | 5041 | } |
4549 | 5042 | ||
4550 | static int l2cap_ertm_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) | 5043 | static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) |
4551 | { | 5044 | { |
4552 | u32 control; | 5045 | struct l2cap_ctrl *control = &bt_cb(skb)->control; |
4553 | u16 req_seq; | 5046 | u16 len; |
4554 | int len, next_tx_seq_offset, req_seq_offset; | 5047 | u8 event; |
4555 | 5048 | ||
4556 | __unpack_control(chan, skb); | 5049 | __unpack_control(chan, skb); |
4557 | 5050 | ||
4558 | control = __get_control(chan, skb->data); | ||
4559 | skb_pull(skb, __ctrl_size(chan)); | ||
4560 | len = skb->len; | 5051 | len = skb->len; |
4561 | 5052 | ||
4562 | /* | 5053 | /* |
4563 | * We can just drop the corrupted I-frame here. | 5054 | * We can just drop the corrupted I-frame here. |
4564 | * Receiver will miss it and start proper recovery | 5055 | * Receiver will miss it and start proper recovery |
4565 | * procedures and ask retransmission. | 5056 | * procedures and ask for retransmission. |
4566 | */ | 5057 | */ |
4567 | if (l2cap_check_fcs(chan, skb)) | 5058 | if (l2cap_check_fcs(chan, skb)) |
4568 | goto drop; | 5059 | goto drop; |
4569 | 5060 | ||
4570 | if (__is_sar_start(chan, control) && !__is_sframe(chan, control)) | 5061 | if (!control->sframe && control->sar == L2CAP_SAR_START) |
4571 | len -= L2CAP_SDULEN_SIZE; | 5062 | len -= L2CAP_SDULEN_SIZE; |
4572 | 5063 | ||
4573 | if (chan->fcs == L2CAP_FCS_CRC16) | 5064 | if (chan->fcs == L2CAP_FCS_CRC16) |
@@ -4578,34 +5069,57 @@ static int l2cap_ertm_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) | |||
4578 | goto drop; | 5069 | goto drop; |
4579 | } | 5070 | } |
4580 | 5071 | ||
4581 | req_seq = __get_reqseq(chan, control); | 5072 | if (!control->sframe) { |
4582 | 5073 | int err; | |
4583 | req_seq_offset = __seq_offset(chan, req_seq, chan->expected_ack_seq); | ||
4584 | |||
4585 | next_tx_seq_offset = __seq_offset(chan, chan->next_tx_seq, | ||
4586 | chan->expected_ack_seq); | ||
4587 | 5074 | ||
4588 | /* check for invalid req-seq */ | 5075 | BT_DBG("iframe sar %d, reqseq %d, final %d, txseq %d", |
4589 | if (req_seq_offset > next_tx_seq_offset) { | 5076 | control->sar, control->reqseq, control->final, |
4590 | l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); | 5077 | control->txseq); |
4591 | goto drop; | ||
4592 | } | ||
4593 | 5078 | ||
4594 | if (!__is_sframe(chan, control)) { | 5079 | /* Validate F-bit - F=0 always valid, F=1 only |
4595 | if (len < 0) { | 5080 | * valid in TX WAIT_F |
4596 | l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); | 5081 | */ |
5082 | if (control->final && chan->tx_state != L2CAP_TX_STATE_WAIT_F) | ||
4597 | goto drop; | 5083 | goto drop; |
5084 | |||
5085 | if (chan->mode != L2CAP_MODE_STREAMING) { | ||
5086 | event = L2CAP_EV_RECV_IFRAME; | ||
5087 | err = l2cap_rx(chan, control, skb, event); | ||
5088 | } else { | ||
5089 | err = l2cap_stream_rx(chan, control, skb); | ||
4598 | } | 5090 | } |
4599 | 5091 | ||
4600 | l2cap_data_channel_iframe(chan, control, skb); | 5092 | if (err) |
5093 | l2cap_send_disconn_req(chan->conn, chan, | ||
5094 | ECONNRESET); | ||
4601 | } else { | 5095 | } else { |
5096 | const u8 rx_func_to_event[4] = { | ||
5097 | L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ, | ||
5098 | L2CAP_EV_RECV_RNR, L2CAP_EV_RECV_SREJ | ||
5099 | }; | ||
5100 | |||
5101 | /* Only I-frames are expected in streaming mode */ | ||
5102 | if (chan->mode == L2CAP_MODE_STREAMING) | ||
5103 | goto drop; | ||
5104 | |||
5105 | BT_DBG("sframe reqseq %d, final %d, poll %d, super %d", | ||
5106 | control->reqseq, control->final, control->poll, | ||
5107 | control->super); | ||
5108 | |||
4602 | if (len != 0) { | 5109 | if (len != 0) { |
4603 | BT_ERR("%d", len); | 5110 | BT_ERR("%d", len); |
4604 | l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); | 5111 | l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); |
4605 | goto drop; | 5112 | goto drop; |
4606 | } | 5113 | } |
4607 | 5114 | ||
4608 | l2cap_data_channel_sframe(chan, control, skb); | 5115 | /* Validate F and P bits */ |
5116 | if (control->final && (control->poll || | ||
5117 | chan->tx_state != L2CAP_TX_STATE_WAIT_F)) | ||
5118 | goto drop; | ||
5119 | |||
5120 | event = rx_func_to_event[control->super]; | ||
5121 | if (l2cap_rx(chan, control, skb, event)) | ||
5122 | l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); | ||
4609 | } | 5123 | } |
4610 | 5124 | ||
4611 | return 0; | 5125 | return 0; |
@@ -4615,19 +5129,27 @@ drop: | |||
4615 | return 0; | 5129 | return 0; |
4616 | } | 5130 | } |
4617 | 5131 | ||
4618 | static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb) | 5132 | static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid, |
5133 | struct sk_buff *skb) | ||
4619 | { | 5134 | { |
4620 | struct l2cap_chan *chan; | 5135 | struct l2cap_chan *chan; |
4621 | u32 control; | ||
4622 | u16 tx_seq; | ||
4623 | int len; | ||
4624 | 5136 | ||
4625 | chan = l2cap_get_chan_by_scid(conn, cid); | 5137 | chan = l2cap_get_chan_by_scid(conn, cid); |
4626 | if (!chan) { | 5138 | if (!chan) { |
4627 | BT_DBG("unknown cid 0x%4.4x", cid); | 5139 | if (cid == L2CAP_CID_A2MP) { |
4628 | /* Drop packet and return */ | 5140 | chan = a2mp_channel_create(conn, skb); |
4629 | kfree_skb(skb); | 5141 | if (!chan) { |
4630 | return 0; | 5142 | kfree_skb(skb); |
5143 | return; | ||
5144 | } | ||
5145 | |||
5146 | l2cap_chan_lock(chan); | ||
5147 | } else { | ||
5148 | BT_DBG("unknown cid 0x%4.4x", cid); | ||
5149 | /* Drop packet and return */ | ||
5150 | kfree_skb(skb); | ||
5151 | return; | ||
5152 | } | ||
4631 | } | 5153 | } |
4632 | 5154 | ||
4633 | BT_DBG("chan %p, len %d", chan, skb->len); | 5155 | BT_DBG("chan %p, len %d", chan, skb->len); |
@@ -4645,49 +5167,13 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk | |||
4645 | if (chan->imtu < skb->len) | 5167 | if (chan->imtu < skb->len) |
4646 | goto drop; | 5168 | goto drop; |
4647 | 5169 | ||
4648 | if (!chan->ops->recv(chan->data, skb)) | 5170 | if (!chan->ops->recv(chan, skb)) |
4649 | goto done; | 5171 | goto done; |
4650 | break; | 5172 | break; |
4651 | 5173 | ||
4652 | case L2CAP_MODE_ERTM: | 5174 | case L2CAP_MODE_ERTM: |
4653 | l2cap_ertm_data_rcv(chan, skb); | ||
4654 | |||
4655 | goto done; | ||
4656 | |||
4657 | case L2CAP_MODE_STREAMING: | 5175 | case L2CAP_MODE_STREAMING: |
4658 | control = __get_control(chan, skb->data); | 5176 | l2cap_data_rcv(chan, skb); |
4659 | skb_pull(skb, __ctrl_size(chan)); | ||
4660 | len = skb->len; | ||
4661 | |||
4662 | if (l2cap_check_fcs(chan, skb)) | ||
4663 | goto drop; | ||
4664 | |||
4665 | if (__is_sar_start(chan, control)) | ||
4666 | len -= L2CAP_SDULEN_SIZE; | ||
4667 | |||
4668 | if (chan->fcs == L2CAP_FCS_CRC16) | ||
4669 | len -= L2CAP_FCS_SIZE; | ||
4670 | |||
4671 | if (len > chan->mps || len < 0 || __is_sframe(chan, control)) | ||
4672 | goto drop; | ||
4673 | |||
4674 | tx_seq = __get_txseq(chan, control); | ||
4675 | |||
4676 | if (chan->expected_tx_seq != tx_seq) { | ||
4677 | /* Frame(s) missing - must discard partial SDU */ | ||
4678 | kfree_skb(chan->sdu); | ||
4679 | chan->sdu = NULL; | ||
4680 | chan->sdu_last_frag = NULL; | ||
4681 | chan->sdu_len = 0; | ||
4682 | |||
4683 | /* TODO: Notify userland of missing data */ | ||
4684 | } | ||
4685 | |||
4686 | chan->expected_tx_seq = __next_seq(chan, tx_seq); | ||
4687 | |||
4688 | if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE) | ||
4689 | l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); | ||
4690 | |||
4691 | goto done; | 5177 | goto done; |
4692 | 5178 | ||
4693 | default: | 5179 | default: |
@@ -4700,11 +5186,10 @@ drop: | |||
4700 | 5186 | ||
4701 | done: | 5187 | done: |
4702 | l2cap_chan_unlock(chan); | 5188 | l2cap_chan_unlock(chan); |
4703 | |||
4704 | return 0; | ||
4705 | } | 5189 | } |
4706 | 5190 | ||
4707 | static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb) | 5191 | static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, |
5192 | struct sk_buff *skb) | ||
4708 | { | 5193 | { |
4709 | struct l2cap_chan *chan; | 5194 | struct l2cap_chan *chan; |
4710 | 5195 | ||
@@ -4720,17 +5205,15 @@ static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, str | |||
4720 | if (chan->imtu < skb->len) | 5205 | if (chan->imtu < skb->len) |
4721 | goto drop; | 5206 | goto drop; |
4722 | 5207 | ||
4723 | if (!chan->ops->recv(chan->data, skb)) | 5208 | if (!chan->ops->recv(chan, skb)) |
4724 | return 0; | 5209 | return; |
4725 | 5210 | ||
4726 | drop: | 5211 | drop: |
4727 | kfree_skb(skb); | 5212 | kfree_skb(skb); |
4728 | |||
4729 | return 0; | ||
4730 | } | 5213 | } |
4731 | 5214 | ||
4732 | static inline int l2cap_att_channel(struct l2cap_conn *conn, u16 cid, | 5215 | static void l2cap_att_channel(struct l2cap_conn *conn, u16 cid, |
4733 | struct sk_buff *skb) | 5216 | struct sk_buff *skb) |
4734 | { | 5217 | { |
4735 | struct l2cap_chan *chan; | 5218 | struct l2cap_chan *chan; |
4736 | 5219 | ||
@@ -4746,13 +5229,11 @@ static inline int l2cap_att_channel(struct l2cap_conn *conn, u16 cid, | |||
4746 | if (chan->imtu < skb->len) | 5229 | if (chan->imtu < skb->len) |
4747 | goto drop; | 5230 | goto drop; |
4748 | 5231 | ||
4749 | if (!chan->ops->recv(chan->data, skb)) | 5232 | if (!chan->ops->recv(chan, skb)) |
4750 | return 0; | 5233 | return; |
4751 | 5234 | ||
4752 | drop: | 5235 | drop: |
4753 | kfree_skb(skb); | 5236 | kfree_skb(skb); |
4754 | |||
4755 | return 0; | ||
4756 | } | 5237 | } |
4757 | 5238 | ||
4758 | static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) | 5239 | static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) |
@@ -4780,7 +5261,7 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) | |||
4780 | 5261 | ||
4781 | case L2CAP_CID_CONN_LESS: | 5262 | case L2CAP_CID_CONN_LESS: |
4782 | psm = get_unaligned((__le16 *) skb->data); | 5263 | psm = get_unaligned((__le16 *) skb->data); |
4783 | skb_pull(skb, 2); | 5264 | skb_pull(skb, L2CAP_PSMLEN_SIZE); |
4784 | l2cap_conless_channel(conn, psm, skb); | 5265 | l2cap_conless_channel(conn, psm, skb); |
4785 | break; | 5266 | break; |
4786 | 5267 | ||
@@ -4974,6 +5455,17 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) | |||
4974 | rsp.status = cpu_to_le16(stat); | 5455 | rsp.status = cpu_to_le16(stat); |
4975 | l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, | 5456 | l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, |
4976 | sizeof(rsp), &rsp); | 5457 | sizeof(rsp), &rsp); |
5458 | |||
5459 | if (!test_bit(CONF_REQ_SENT, &chan->conf_state) && | ||
5460 | res == L2CAP_CR_SUCCESS) { | ||
5461 | char buf[128]; | ||
5462 | set_bit(CONF_REQ_SENT, &chan->conf_state); | ||
5463 | l2cap_send_cmd(conn, l2cap_get_ident(conn), | ||
5464 | L2CAP_CONF_REQ, | ||
5465 | l2cap_build_conf_req(chan, buf), | ||
5466 | buf); | ||
5467 | chan->num_conf_req++; | ||
5468 | } | ||
4977 | } | 5469 | } |
4978 | 5470 | ||
4979 | l2cap_chan_unlock(chan); | 5471 | l2cap_chan_unlock(chan); |
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 3bb1611b9d4..a4bb27e8427 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -27,7 +27,6 @@ | |||
27 | 27 | ||
28 | /* Bluetooth L2CAP sockets. */ | 28 | /* Bluetooth L2CAP sockets. */ |
29 | 29 | ||
30 | #include <linux/security.h> | ||
31 | #include <linux/export.h> | 30 | #include <linux/export.h> |
32 | 31 | ||
33 | #include <net/bluetooth/bluetooth.h> | 32 | #include <net/bluetooth/bluetooth.h> |
@@ -89,8 +88,8 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) | |||
89 | if (err < 0) | 88 | if (err < 0) |
90 | goto done; | 89 | goto done; |
91 | 90 | ||
92 | if (__le16_to_cpu(la.l2_psm) == 0x0001 || | 91 | if (__le16_to_cpu(la.l2_psm) == L2CAP_PSM_SDP || |
93 | __le16_to_cpu(la.l2_psm) == 0x0003) | 92 | __le16_to_cpu(la.l2_psm) == L2CAP_PSM_RFCOMM) |
94 | chan->sec_level = BT_SECURITY_SDP; | 93 | chan->sec_level = BT_SECURITY_SDP; |
95 | 94 | ||
96 | bacpy(&bt_sk(sk)->src, &la.l2_bdaddr); | 95 | bacpy(&bt_sk(sk)->src, &la.l2_bdaddr); |
@@ -446,6 +445,22 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch | |||
446 | return err; | 445 | return err; |
447 | } | 446 | } |
448 | 447 | ||
448 | static bool l2cap_valid_mtu(struct l2cap_chan *chan, u16 mtu) | ||
449 | { | ||
450 | switch (chan->scid) { | ||
451 | case L2CAP_CID_LE_DATA: | ||
452 | if (mtu < L2CAP_LE_MIN_MTU) | ||
453 | return false; | ||
454 | break; | ||
455 | |||
456 | default: | ||
457 | if (mtu < L2CAP_DEFAULT_MIN_MTU) | ||
458 | return false; | ||
459 | } | ||
460 | |||
461 | return true; | ||
462 | } | ||
463 | |||
449 | static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen) | 464 | static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen) |
450 | { | 465 | { |
451 | struct sock *sk = sock->sk; | 466 | struct sock *sk = sock->sk; |
@@ -484,6 +499,11 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us | |||
484 | break; | 499 | break; |
485 | } | 500 | } |
486 | 501 | ||
502 | if (!l2cap_valid_mtu(chan, opts.imtu)) { | ||
503 | err = -EINVAL; | ||
504 | break; | ||
505 | } | ||
506 | |||
487 | chan->mode = opts.mode; | 507 | chan->mode = opts.mode; |
488 | switch (chan->mode) { | 508 | switch (chan->mode) { |
489 | case L2CAP_MODE_BASIC: | 509 | case L2CAP_MODE_BASIC: |
@@ -873,9 +893,34 @@ static int l2cap_sock_release(struct socket *sock) | |||
873 | return err; | 893 | return err; |
874 | } | 894 | } |
875 | 895 | ||
876 | static struct l2cap_chan *l2cap_sock_new_connection_cb(void *data) | 896 | static void l2cap_sock_cleanup_listen(struct sock *parent) |
877 | { | 897 | { |
878 | struct sock *sk, *parent = data; | 898 | struct sock *sk; |
899 | |||
900 | BT_DBG("parent %p", parent); | ||
901 | |||
902 | /* Close not yet accepted channels */ | ||
903 | while ((sk = bt_accept_dequeue(parent, NULL))) { | ||
904 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; | ||
905 | |||
906 | l2cap_chan_lock(chan); | ||
907 | __clear_chan_timer(chan); | ||
908 | l2cap_chan_close(chan, ECONNRESET); | ||
909 | l2cap_chan_unlock(chan); | ||
910 | |||
911 | l2cap_sock_kill(sk); | ||
912 | } | ||
913 | } | ||
914 | |||
915 | static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan) | ||
916 | { | ||
917 | struct sock *sk, *parent = chan->data; | ||
918 | |||
919 | /* Check for backlog size */ | ||
920 | if (sk_acceptq_is_full(parent)) { | ||
921 | BT_DBG("backlog full %d", parent->sk_ack_backlog); | ||
922 | return NULL; | ||
923 | } | ||
879 | 924 | ||
880 | sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, | 925 | sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, |
881 | GFP_ATOMIC); | 926 | GFP_ATOMIC); |
@@ -889,10 +934,10 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(void *data) | |||
889 | return l2cap_pi(sk)->chan; | 934 | return l2cap_pi(sk)->chan; |
890 | } | 935 | } |
891 | 936 | ||
892 | static int l2cap_sock_recv_cb(void *data, struct sk_buff *skb) | 937 | static int l2cap_sock_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) |
893 | { | 938 | { |
894 | int err; | 939 | int err; |
895 | struct sock *sk = data; | 940 | struct sock *sk = chan->data; |
896 | struct l2cap_pinfo *pi = l2cap_pi(sk); | 941 | struct l2cap_pinfo *pi = l2cap_pi(sk); |
897 | 942 | ||
898 | lock_sock(sk); | 943 | lock_sock(sk); |
@@ -925,16 +970,57 @@ done: | |||
925 | return err; | 970 | return err; |
926 | } | 971 | } |
927 | 972 | ||
928 | static void l2cap_sock_close_cb(void *data) | 973 | static void l2cap_sock_close_cb(struct l2cap_chan *chan) |
929 | { | 974 | { |
930 | struct sock *sk = data; | 975 | struct sock *sk = chan->data; |
931 | 976 | ||
932 | l2cap_sock_kill(sk); | 977 | l2cap_sock_kill(sk); |
933 | } | 978 | } |
934 | 979 | ||
935 | static void l2cap_sock_state_change_cb(void *data, int state) | 980 | static void l2cap_sock_teardown_cb(struct l2cap_chan *chan, int err) |
936 | { | 981 | { |
937 | struct sock *sk = data; | 982 | struct sock *sk = chan->data; |
983 | struct sock *parent; | ||
984 | |||
985 | lock_sock(sk); | ||
986 | |||
987 | parent = bt_sk(sk)->parent; | ||
988 | |||
989 | sock_set_flag(sk, SOCK_ZAPPED); | ||
990 | |||
991 | switch (chan->state) { | ||
992 | case BT_OPEN: | ||
993 | case BT_BOUND: | ||
994 | case BT_CLOSED: | ||
995 | break; | ||
996 | case BT_LISTEN: | ||
997 | l2cap_sock_cleanup_listen(sk); | ||
998 | sk->sk_state = BT_CLOSED; | ||
999 | chan->state = BT_CLOSED; | ||
1000 | |||
1001 | break; | ||
1002 | default: | ||
1003 | sk->sk_state = BT_CLOSED; | ||
1004 | chan->state = BT_CLOSED; | ||
1005 | |||
1006 | sk->sk_err = err; | ||
1007 | |||
1008 | if (parent) { | ||
1009 | bt_accept_unlink(sk); | ||
1010 | parent->sk_data_ready(parent, 0); | ||
1011 | } else { | ||
1012 | sk->sk_state_change(sk); | ||
1013 | } | ||
1014 | |||
1015 | break; | ||
1016 | } | ||
1017 | |||
1018 | release_sock(sk); | ||
1019 | } | ||
1020 | |||
1021 | static void l2cap_sock_state_change_cb(struct l2cap_chan *chan, int state) | ||
1022 | { | ||
1023 | struct sock *sk = chan->data; | ||
938 | 1024 | ||
939 | sk->sk_state = state; | 1025 | sk->sk_state = state; |
940 | } | 1026 | } |
@@ -955,12 +1041,34 @@ static struct sk_buff *l2cap_sock_alloc_skb_cb(struct l2cap_chan *chan, | |||
955 | return skb; | 1041 | return skb; |
956 | } | 1042 | } |
957 | 1043 | ||
1044 | static void l2cap_sock_ready_cb(struct l2cap_chan *chan) | ||
1045 | { | ||
1046 | struct sock *sk = chan->data; | ||
1047 | struct sock *parent; | ||
1048 | |||
1049 | lock_sock(sk); | ||
1050 | |||
1051 | parent = bt_sk(sk)->parent; | ||
1052 | |||
1053 | BT_DBG("sk %p, parent %p", sk, parent); | ||
1054 | |||
1055 | sk->sk_state = BT_CONNECTED; | ||
1056 | sk->sk_state_change(sk); | ||
1057 | |||
1058 | if (parent) | ||
1059 | parent->sk_data_ready(parent, 0); | ||
1060 | |||
1061 | release_sock(sk); | ||
1062 | } | ||
1063 | |||
958 | static struct l2cap_ops l2cap_chan_ops = { | 1064 | static struct l2cap_ops l2cap_chan_ops = { |
959 | .name = "L2CAP Socket Interface", | 1065 | .name = "L2CAP Socket Interface", |
960 | .new_connection = l2cap_sock_new_connection_cb, | 1066 | .new_connection = l2cap_sock_new_connection_cb, |
961 | .recv = l2cap_sock_recv_cb, | 1067 | .recv = l2cap_sock_recv_cb, |
962 | .close = l2cap_sock_close_cb, | 1068 | .close = l2cap_sock_close_cb, |
1069 | .teardown = l2cap_sock_teardown_cb, | ||
963 | .state_change = l2cap_sock_state_change_cb, | 1070 | .state_change = l2cap_sock_state_change_cb, |
1071 | .ready = l2cap_sock_ready_cb, | ||
964 | .alloc_skb = l2cap_sock_alloc_skb_cb, | 1072 | .alloc_skb = l2cap_sock_alloc_skb_cb, |
965 | }; | 1073 | }; |
966 | 1074 | ||
diff --git a/net/bluetooth/lib.c b/net/bluetooth/lib.c index 506628876f3..e1c97527e16 100644 --- a/net/bluetooth/lib.c +++ b/net/bluetooth/lib.c | |||
@@ -26,12 +26,7 @@ | |||
26 | 26 | ||
27 | #define pr_fmt(fmt) "Bluetooth: " fmt | 27 | #define pr_fmt(fmt) "Bluetooth: " fmt |
28 | 28 | ||
29 | #include <linux/module.h> | 29 | #include <linux/export.h> |
30 | |||
31 | #include <linux/kernel.h> | ||
32 | #include <linux/stddef.h> | ||
33 | #include <linux/string.h> | ||
34 | #include <asm/errno.h> | ||
35 | 30 | ||
36 | #include <net/bluetooth/bluetooth.h> | 31 | #include <net/bluetooth/bluetooth.h> |
37 | 32 | ||
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 25d22077607..c72307cc25f 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -24,8 +24,6 @@ | |||
24 | 24 | ||
25 | /* Bluetooth HCI Management interface */ | 25 | /* Bluetooth HCI Management interface */ |
26 | 26 | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/uaccess.h> | ||
29 | #include <linux/module.h> | 27 | #include <linux/module.h> |
30 | #include <asm/unaligned.h> | 28 | #include <asm/unaligned.h> |
31 | 29 | ||
@@ -714,7 +712,8 @@ static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode, | |||
714 | } | 712 | } |
715 | 713 | ||
716 | static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev, | 714 | static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev, |
717 | void (*cb)(struct pending_cmd *cmd, void *data), | 715 | void (*cb)(struct pending_cmd *cmd, |
716 | void *data), | ||
718 | void *data) | 717 | void *data) |
719 | { | 718 | { |
720 | struct list_head *p, *n; | 719 | struct list_head *p, *n; |
@@ -871,7 +870,7 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
871 | } | 870 | } |
872 | 871 | ||
873 | if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) || | 872 | if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) || |
874 | mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) { | 873 | mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) { |
875 | err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE, | 874 | err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE, |
876 | MGMT_STATUS_BUSY); | 875 | MGMT_STATUS_BUSY); |
877 | goto failed; | 876 | goto failed; |
@@ -978,7 +977,7 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
978 | } | 977 | } |
979 | 978 | ||
980 | if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) || | 979 | if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) || |
981 | mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) { | 980 | mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) { |
982 | err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE, | 981 | err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE, |
983 | MGMT_STATUS_BUSY); | 982 | MGMT_STATUS_BUSY); |
984 | goto failed; | 983 | goto failed; |
@@ -1001,7 +1000,7 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1001 | scan = 0; | 1000 | scan = 0; |
1002 | 1001 | ||
1003 | if (test_bit(HCI_ISCAN, &hdev->flags) && | 1002 | if (test_bit(HCI_ISCAN, &hdev->flags) && |
1004 | hdev->discov_timeout > 0) | 1003 | hdev->discov_timeout > 0) |
1005 | cancel_delayed_work(&hdev->discov_off); | 1004 | cancel_delayed_work(&hdev->discov_off); |
1006 | } | 1005 | } |
1007 | 1006 | ||
@@ -1056,7 +1055,7 @@ static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1056 | bool changed = false; | 1055 | bool changed = false; |
1057 | 1056 | ||
1058 | if (!!cp->val != test_bit(HCI_LINK_SECURITY, | 1057 | if (!!cp->val != test_bit(HCI_LINK_SECURITY, |
1059 | &hdev->dev_flags)) { | 1058 | &hdev->dev_flags)) { |
1060 | change_bit(HCI_LINK_SECURITY, &hdev->dev_flags); | 1059 | change_bit(HCI_LINK_SECURITY, &hdev->dev_flags); |
1061 | changed = true; | 1060 | changed = true; |
1062 | } | 1061 | } |
@@ -1317,7 +1316,7 @@ static bool enable_service_cache(struct hci_dev *hdev) | |||
1317 | } | 1316 | } |
1318 | 1317 | ||
1319 | static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data, | 1318 | static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data, |
1320 | u16 len) | 1319 | u16 len) |
1321 | { | 1320 | { |
1322 | struct mgmt_cp_remove_uuid *cp = data; | 1321 | struct mgmt_cp_remove_uuid *cp = data; |
1323 | struct pending_cmd *cmd; | 1322 | struct pending_cmd *cmd; |
@@ -1442,7 +1441,7 @@ unlock: | |||
1442 | } | 1441 | } |
1443 | 1442 | ||
1444 | static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data, | 1443 | static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data, |
1445 | u16 len) | 1444 | u16 len) |
1446 | { | 1445 | { |
1447 | struct mgmt_cp_load_link_keys *cp = data; | 1446 | struct mgmt_cp_load_link_keys *cp = data; |
1448 | u16 key_count, expected_len; | 1447 | u16 key_count, expected_len; |
@@ -1454,13 +1453,13 @@ static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1454 | sizeof(struct mgmt_link_key_info); | 1453 | sizeof(struct mgmt_link_key_info); |
1455 | if (expected_len != len) { | 1454 | if (expected_len != len) { |
1456 | BT_ERR("load_link_keys: expected %u bytes, got %u bytes", | 1455 | BT_ERR("load_link_keys: expected %u bytes, got %u bytes", |
1457 | len, expected_len); | 1456 | len, expected_len); |
1458 | return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, | 1457 | return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, |
1459 | MGMT_STATUS_INVALID_PARAMS); | 1458 | MGMT_STATUS_INVALID_PARAMS); |
1460 | } | 1459 | } |
1461 | 1460 | ||
1462 | BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys, | 1461 | BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys, |
1463 | key_count); | 1462 | key_count); |
1464 | 1463 | ||
1465 | hci_dev_lock(hdev); | 1464 | hci_dev_lock(hdev); |
1466 | 1465 | ||
@@ -1535,10 +1534,10 @@ static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1535 | if (cp->disconnect) { | 1534 | if (cp->disconnect) { |
1536 | if (cp->addr.type == BDADDR_BREDR) | 1535 | if (cp->addr.type == BDADDR_BREDR) |
1537 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, | 1536 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, |
1538 | &cp->addr.bdaddr); | 1537 | &cp->addr.bdaddr); |
1539 | else | 1538 | else |
1540 | conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, | 1539 | conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, |
1541 | &cp->addr.bdaddr); | 1540 | &cp->addr.bdaddr); |
1542 | } else { | 1541 | } else { |
1543 | conn = NULL; | 1542 | conn = NULL; |
1544 | } | 1543 | } |
@@ -1594,7 +1593,8 @@ static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1594 | } | 1593 | } |
1595 | 1594 | ||
1596 | if (cp->addr.type == BDADDR_BREDR) | 1595 | if (cp->addr.type == BDADDR_BREDR) |
1597 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr); | 1596 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, |
1597 | &cp->addr.bdaddr); | ||
1598 | else | 1598 | else |
1599 | conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr); | 1599 | conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr); |
1600 | 1600 | ||
@@ -1813,7 +1813,7 @@ static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1813 | hdev->io_capability = cp->io_capability; | 1813 | hdev->io_capability = cp->io_capability; |
1814 | 1814 | ||
1815 | BT_DBG("%s IO capability set to 0x%02x", hdev->name, | 1815 | BT_DBG("%s IO capability set to 0x%02x", hdev->name, |
1816 | hdev->io_capability); | 1816 | hdev->io_capability); |
1817 | 1817 | ||
1818 | hci_dev_unlock(hdev); | 1818 | hci_dev_unlock(hdev); |
1819 | 1819 | ||
@@ -1821,7 +1821,7 @@ static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1821 | 0); | 1821 | 0); |
1822 | } | 1822 | } |
1823 | 1823 | ||
1824 | static inline struct pending_cmd *find_pairing(struct hci_conn *conn) | 1824 | static struct pending_cmd *find_pairing(struct hci_conn *conn) |
1825 | { | 1825 | { |
1826 | struct hci_dev *hdev = conn->hdev; | 1826 | struct hci_dev *hdev = conn->hdev; |
1827 | struct pending_cmd *cmd; | 1827 | struct pending_cmd *cmd; |
@@ -1873,6 +1873,22 @@ static void pairing_complete_cb(struct hci_conn *conn, u8 status) | |||
1873 | pairing_complete(cmd, mgmt_status(status)); | 1873 | pairing_complete(cmd, mgmt_status(status)); |
1874 | } | 1874 | } |
1875 | 1875 | ||
1876 | static void le_connect_complete_cb(struct hci_conn *conn, u8 status) | ||
1877 | { | ||
1878 | struct pending_cmd *cmd; | ||
1879 | |||
1880 | BT_DBG("status %u", status); | ||
1881 | |||
1882 | if (!status) | ||
1883 | return; | ||
1884 | |||
1885 | cmd = find_pairing(conn); | ||
1886 | if (!cmd) | ||
1887 | BT_DBG("Unable to find a pending command"); | ||
1888 | else | ||
1889 | pairing_complete(cmd, mgmt_status(status)); | ||
1890 | } | ||
1891 | |||
1876 | static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data, | 1892 | static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data, |
1877 | u16 len) | 1893 | u16 len) |
1878 | { | 1894 | { |
@@ -1911,8 +1927,15 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1911 | rp.addr.type = cp->addr.type; | 1927 | rp.addr.type = cp->addr.type; |
1912 | 1928 | ||
1913 | if (IS_ERR(conn)) { | 1929 | if (IS_ERR(conn)) { |
1930 | int status; | ||
1931 | |||
1932 | if (PTR_ERR(conn) == -EBUSY) | ||
1933 | status = MGMT_STATUS_BUSY; | ||
1934 | else | ||
1935 | status = MGMT_STATUS_CONNECT_FAILED; | ||
1936 | |||
1914 | err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE, | 1937 | err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE, |
1915 | MGMT_STATUS_CONNECT_FAILED, &rp, | 1938 | status, &rp, |
1916 | sizeof(rp)); | 1939 | sizeof(rp)); |
1917 | goto unlock; | 1940 | goto unlock; |
1918 | } | 1941 | } |
@@ -1934,6 +1957,8 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1934 | /* For LE, just connecting isn't a proof that the pairing finished */ | 1957 | /* For LE, just connecting isn't a proof that the pairing finished */ |
1935 | if (cp->addr.type == BDADDR_BREDR) | 1958 | if (cp->addr.type == BDADDR_BREDR) |
1936 | conn->connect_cfm_cb = pairing_complete_cb; | 1959 | conn->connect_cfm_cb = pairing_complete_cb; |
1960 | else | ||
1961 | conn->connect_cfm_cb = le_connect_complete_cb; | ||
1937 | 1962 | ||
1938 | conn->security_cfm_cb = pairing_complete_cb; | 1963 | conn->security_cfm_cb = pairing_complete_cb; |
1939 | conn->disconn_cfm_cb = pairing_complete_cb; | 1964 | conn->disconn_cfm_cb = pairing_complete_cb; |
@@ -1941,7 +1966,7 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1941 | cmd->user_data = conn; | 1966 | cmd->user_data = conn; |
1942 | 1967 | ||
1943 | if (conn->state == BT_CONNECTED && | 1968 | if (conn->state == BT_CONNECTED && |
1944 | hci_conn_security(conn, sec_level, auth_type)) | 1969 | hci_conn_security(conn, sec_level, auth_type)) |
1945 | pairing_complete(cmd, 0); | 1970 | pairing_complete(cmd, 0); |
1946 | 1971 | ||
1947 | err = 0; | 1972 | err = 0; |
@@ -2238,7 +2263,7 @@ unlock: | |||
2238 | } | 2263 | } |
2239 | 2264 | ||
2240 | static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev, | 2265 | static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev, |
2241 | void *data, u16 len) | 2266 | void *data, u16 len) |
2242 | { | 2267 | { |
2243 | struct mgmt_cp_remove_remote_oob_data *cp = data; | 2268 | struct mgmt_cp_remove_remote_oob_data *cp = data; |
2244 | u8 status; | 2269 | u8 status; |
@@ -2407,7 +2432,7 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2407 | 2432 | ||
2408 | case DISCOVERY_RESOLVING: | 2433 | case DISCOVERY_RESOLVING: |
2409 | e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, | 2434 | e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, |
2410 | NAME_PENDING); | 2435 | NAME_PENDING); |
2411 | if (!e) { | 2436 | if (!e) { |
2412 | mgmt_pending_remove(cmd); | 2437 | mgmt_pending_remove(cmd); |
2413 | err = cmd_complete(sk, hdev->id, | 2438 | err = cmd_complete(sk, hdev->id, |
@@ -2629,7 +2654,7 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev, | |||
2629 | sizeof(struct mgmt_ltk_info); | 2654 | sizeof(struct mgmt_ltk_info); |
2630 | if (expected_len != len) { | 2655 | if (expected_len != len) { |
2631 | BT_ERR("load_keys: expected %u bytes, got %u bytes", | 2656 | BT_ERR("load_keys: expected %u bytes, got %u bytes", |
2632 | len, expected_len); | 2657 | len, expected_len); |
2633 | return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, | 2658 | return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, |
2634 | EINVAL); | 2659 | EINVAL); |
2635 | } | 2660 | } |
@@ -2754,7 +2779,7 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) | |||
2754 | } | 2779 | } |
2755 | 2780 | ||
2756 | if (opcode >= ARRAY_SIZE(mgmt_handlers) || | 2781 | if (opcode >= ARRAY_SIZE(mgmt_handlers) || |
2757 | mgmt_handlers[opcode].func == NULL) { | 2782 | mgmt_handlers[opcode].func == NULL) { |
2758 | BT_DBG("Unknown op %u", opcode); | 2783 | BT_DBG("Unknown op %u", opcode); |
2759 | err = cmd_status(sk, index, opcode, | 2784 | err = cmd_status(sk, index, opcode, |
2760 | MGMT_STATUS_UNKNOWN_COMMAND); | 2785 | MGMT_STATUS_UNKNOWN_COMMAND); |
@@ -2762,7 +2787,7 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) | |||
2762 | } | 2787 | } |
2763 | 2788 | ||
2764 | if ((hdev && opcode < MGMT_OP_READ_INFO) || | 2789 | if ((hdev && opcode < MGMT_OP_READ_INFO) || |
2765 | (!hdev && opcode >= MGMT_OP_READ_INFO)) { | 2790 | (!hdev && opcode >= MGMT_OP_READ_INFO)) { |
2766 | err = cmd_status(sk, index, opcode, | 2791 | err = cmd_status(sk, index, opcode, |
2767 | MGMT_STATUS_INVALID_INDEX); | 2792 | MGMT_STATUS_INVALID_INDEX); |
2768 | goto done; | 2793 | goto done; |
@@ -2771,7 +2796,7 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) | |||
2771 | handler = &mgmt_handlers[opcode]; | 2796 | handler = &mgmt_handlers[opcode]; |
2772 | 2797 | ||
2773 | if ((handler->var_len && len < handler->data_len) || | 2798 | if ((handler->var_len && len < handler->data_len) || |
2774 | (!handler->var_len && len != handler->data_len)) { | 2799 | (!handler->var_len && len != handler->data_len)) { |
2775 | err = cmd_status(sk, index, opcode, | 2800 | err = cmd_status(sk, index, opcode, |
2776 | MGMT_STATUS_INVALID_PARAMS); | 2801 | MGMT_STATUS_INVALID_PARAMS); |
2777 | goto done; | 2802 | goto done; |
@@ -2955,7 +2980,7 @@ int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, | |||
2955 | bacpy(&ev.key.addr.bdaddr, &key->bdaddr); | 2980 | bacpy(&ev.key.addr.bdaddr, &key->bdaddr); |
2956 | ev.key.addr.type = BDADDR_BREDR; | 2981 | ev.key.addr.type = BDADDR_BREDR; |
2957 | ev.key.type = key->type; | 2982 | ev.key.type = key->type; |
2958 | memcpy(ev.key.val, key->val, 16); | 2983 | memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE); |
2959 | ev.key.pin_len = key->pin_len; | 2984 | ev.key.pin_len = key->pin_len; |
2960 | 2985 | ||
2961 | return mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL); | 2986 | return mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL); |
@@ -3090,7 +3115,7 @@ int mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, | |||
3090 | mgmt_pending_remove(cmd); | 3115 | mgmt_pending_remove(cmd); |
3091 | 3116 | ||
3092 | mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp, | 3117 | mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp, |
3093 | hdev); | 3118 | hdev); |
3094 | return err; | 3119 | return err; |
3095 | } | 3120 | } |
3096 | 3121 | ||
@@ -3180,7 +3205,7 @@ int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr, | |||
3180 | } | 3205 | } |
3181 | 3206 | ||
3182 | int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr, | 3207 | int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr, |
3183 | u8 link_type, u8 addr_type) | 3208 | u8 link_type, u8 addr_type) |
3184 | { | 3209 | { |
3185 | struct mgmt_ev_user_passkey_request ev; | 3210 | struct mgmt_ev_user_passkey_request ev; |
3186 | 3211 | ||
@@ -3194,8 +3219,8 @@ int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr, | |||
3194 | } | 3219 | } |
3195 | 3220 | ||
3196 | static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, | 3221 | static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, |
3197 | u8 link_type, u8 addr_type, u8 status, | 3222 | u8 link_type, u8 addr_type, u8 status, |
3198 | u8 opcode) | 3223 | u8 opcode) |
3199 | { | 3224 | { |
3200 | struct pending_cmd *cmd; | 3225 | struct pending_cmd *cmd; |
3201 | struct mgmt_rp_user_confirm_reply rp; | 3226 | struct mgmt_rp_user_confirm_reply rp; |
@@ -3226,7 +3251,8 @@ int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, | |||
3226 | u8 link_type, u8 addr_type, u8 status) | 3251 | u8 link_type, u8 addr_type, u8 status) |
3227 | { | 3252 | { |
3228 | return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type, | 3253 | return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type, |
3229 | status, MGMT_OP_USER_CONFIRM_NEG_REPLY); | 3254 | status, |
3255 | MGMT_OP_USER_CONFIRM_NEG_REPLY); | ||
3230 | } | 3256 | } |
3231 | 3257 | ||
3232 | int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, | 3258 | int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, |
@@ -3240,7 +3266,8 @@ int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, | |||
3240 | u8 link_type, u8 addr_type, u8 status) | 3266 | u8 link_type, u8 addr_type, u8 status) |
3241 | { | 3267 | { |
3242 | return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type, | 3268 | return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type, |
3243 | status, MGMT_OP_USER_PASSKEY_NEG_REPLY); | 3269 | status, |
3270 | MGMT_OP_USER_PASSKEY_NEG_REPLY); | ||
3244 | } | 3271 | } |
3245 | 3272 | ||
3246 | int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | 3273 | int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, |
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 8a602388f1e..c75107ef892 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c | |||
@@ -26,22 +26,8 @@ | |||
26 | */ | 26 | */ |
27 | 27 | ||
28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
29 | #include <linux/errno.h> | ||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/sched.h> | ||
32 | #include <linux/signal.h> | ||
33 | #include <linux/init.h> | ||
34 | #include <linux/wait.h> | ||
35 | #include <linux/device.h> | ||
36 | #include <linux/debugfs.h> | 29 | #include <linux/debugfs.h> |
37 | #include <linux/seq_file.h> | ||
38 | #include <linux/net.h> | ||
39 | #include <linux/mutex.h> | ||
40 | #include <linux/kthread.h> | 30 | #include <linux/kthread.h> |
41 | #include <linux/slab.h> | ||
42 | |||
43 | #include <net/sock.h> | ||
44 | #include <linux/uaccess.h> | ||
45 | #include <asm/unaligned.h> | 31 | #include <asm/unaligned.h> |
46 | 32 | ||
47 | #include <net/bluetooth/bluetooth.h> | 33 | #include <net/bluetooth/bluetooth.h> |
@@ -115,14 +101,14 @@ static void rfcomm_session_del(struct rfcomm_session *s); | |||
115 | #define __get_rpn_stop_bits(line) (((line) >> 2) & 0x1) | 101 | #define __get_rpn_stop_bits(line) (((line) >> 2) & 0x1) |
116 | #define __get_rpn_parity(line) (((line) >> 3) & 0x7) | 102 | #define __get_rpn_parity(line) (((line) >> 3) & 0x7) |
117 | 103 | ||
118 | static inline void rfcomm_schedule(void) | 104 | static void rfcomm_schedule(void) |
119 | { | 105 | { |
120 | if (!rfcomm_thread) | 106 | if (!rfcomm_thread) |
121 | return; | 107 | return; |
122 | wake_up_process(rfcomm_thread); | 108 | wake_up_process(rfcomm_thread); |
123 | } | 109 | } |
124 | 110 | ||
125 | static inline void rfcomm_session_put(struct rfcomm_session *s) | 111 | static void rfcomm_session_put(struct rfcomm_session *s) |
126 | { | 112 | { |
127 | if (atomic_dec_and_test(&s->refcnt)) | 113 | if (atomic_dec_and_test(&s->refcnt)) |
128 | rfcomm_session_del(s); | 114 | rfcomm_session_del(s); |
@@ -227,7 +213,7 @@ static int rfcomm_l2sock_create(struct socket **sock) | |||
227 | return err; | 213 | return err; |
228 | } | 214 | } |
229 | 215 | ||
230 | static inline int rfcomm_check_security(struct rfcomm_dlc *d) | 216 | static int rfcomm_check_security(struct rfcomm_dlc *d) |
231 | { | 217 | { |
232 | struct sock *sk = d->session->sock->sk; | 218 | struct sock *sk = d->session->sock->sk; |
233 | struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn; | 219 | struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn; |
@@ -1750,7 +1736,7 @@ static void rfcomm_process_connect(struct rfcomm_session *s) | |||
1750 | /* Send data queued for the DLC. | 1736 | /* Send data queued for the DLC. |
1751 | * Return number of frames left in the queue. | 1737 | * Return number of frames left in the queue. |
1752 | */ | 1738 | */ |
1753 | static inline int rfcomm_process_tx(struct rfcomm_dlc *d) | 1739 | static int rfcomm_process_tx(struct rfcomm_dlc *d) |
1754 | { | 1740 | { |
1755 | struct sk_buff *skb; | 1741 | struct sk_buff *skb; |
1756 | int err; | 1742 | int err; |
@@ -1798,7 +1784,7 @@ static inline int rfcomm_process_tx(struct rfcomm_dlc *d) | |||
1798 | return skb_queue_len(&d->tx_queue); | 1784 | return skb_queue_len(&d->tx_queue); |
1799 | } | 1785 | } |
1800 | 1786 | ||
1801 | static inline void rfcomm_process_dlcs(struct rfcomm_session *s) | 1787 | static void rfcomm_process_dlcs(struct rfcomm_session *s) |
1802 | { | 1788 | { |
1803 | struct rfcomm_dlc *d; | 1789 | struct rfcomm_dlc *d; |
1804 | struct list_head *p, *n; | 1790 | struct list_head *p, *n; |
@@ -1858,7 +1844,7 @@ static inline void rfcomm_process_dlcs(struct rfcomm_session *s) | |||
1858 | } | 1844 | } |
1859 | } | 1845 | } |
1860 | 1846 | ||
1861 | static inline void rfcomm_process_rx(struct rfcomm_session *s) | 1847 | static void rfcomm_process_rx(struct rfcomm_session *s) |
1862 | { | 1848 | { |
1863 | struct socket *sock = s->sock; | 1849 | struct socket *sock = s->sock; |
1864 | struct sock *sk = sock->sk; | 1850 | struct sock *sk = sock->sk; |
@@ -1883,7 +1869,7 @@ static inline void rfcomm_process_rx(struct rfcomm_session *s) | |||
1883 | } | 1869 | } |
1884 | } | 1870 | } |
1885 | 1871 | ||
1886 | static inline void rfcomm_accept_connection(struct rfcomm_session *s) | 1872 | static void rfcomm_accept_connection(struct rfcomm_session *s) |
1887 | { | 1873 | { |
1888 | struct socket *sock = s->sock, *nsock; | 1874 | struct socket *sock = s->sock, *nsock; |
1889 | int err; | 1875 | int err; |
@@ -1917,7 +1903,7 @@ static inline void rfcomm_accept_connection(struct rfcomm_session *s) | |||
1917 | sock_release(nsock); | 1903 | sock_release(nsock); |
1918 | } | 1904 | } |
1919 | 1905 | ||
1920 | static inline void rfcomm_check_connection(struct rfcomm_session *s) | 1906 | static void rfcomm_check_connection(struct rfcomm_session *s) |
1921 | { | 1907 | { |
1922 | struct sock *sk = s->sock->sk; | 1908 | struct sock *sk = s->sock->sk; |
1923 | 1909 | ||
@@ -1941,7 +1927,7 @@ static inline void rfcomm_check_connection(struct rfcomm_session *s) | |||
1941 | } | 1927 | } |
1942 | } | 1928 | } |
1943 | 1929 | ||
1944 | static inline void rfcomm_process_sessions(void) | 1930 | static void rfcomm_process_sessions(void) |
1945 | { | 1931 | { |
1946 | struct list_head *p, *n; | 1932 | struct list_head *p, *n; |
1947 | 1933 | ||
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index e8707debb86..7e1e59645c0 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c | |||
@@ -25,27 +25,8 @@ | |||
25 | * RFCOMM sockets. | 25 | * RFCOMM sockets. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | #include <linux/module.h> | 28 | #include <linux/export.h> |
29 | |||
30 | #include <linux/types.h> | ||
31 | #include <linux/errno.h> | ||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/sched.h> | ||
34 | #include <linux/slab.h> | ||
35 | #include <linux/poll.h> | ||
36 | #include <linux/fcntl.h> | ||
37 | #include <linux/init.h> | ||
38 | #include <linux/interrupt.h> | ||
39 | #include <linux/socket.h> | ||
40 | #include <linux/skbuff.h> | ||
41 | #include <linux/list.h> | ||
42 | #include <linux/device.h> | ||
43 | #include <linux/debugfs.h> | 29 | #include <linux/debugfs.h> |
44 | #include <linux/seq_file.h> | ||
45 | #include <linux/security.h> | ||
46 | #include <net/sock.h> | ||
47 | |||
48 | #include <linux/uaccess.h> | ||
49 | 30 | ||
50 | #include <net/bluetooth/bluetooth.h> | 31 | #include <net/bluetooth/bluetooth.h> |
51 | #include <net/bluetooth/hci_core.h> | 32 | #include <net/bluetooth/hci_core.h> |
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index d1820ff14ae..cb960773c00 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c | |||
@@ -31,11 +31,6 @@ | |||
31 | #include <linux/tty_driver.h> | 31 | #include <linux/tty_driver.h> |
32 | #include <linux/tty_flip.h> | 32 | #include <linux/tty_flip.h> |
33 | 33 | ||
34 | #include <linux/capability.h> | ||
35 | #include <linux/slab.h> | ||
36 | #include <linux/skbuff.h> | ||
37 | #include <linux/workqueue.h> | ||
38 | |||
39 | #include <net/bluetooth/bluetooth.h> | 34 | #include <net/bluetooth/bluetooth.h> |
40 | #include <net/bluetooth/hci_core.h> | 35 | #include <net/bluetooth/hci_core.h> |
41 | #include <net/bluetooth/rfcomm.h> | 36 | #include <net/bluetooth/rfcomm.h> |
@@ -132,7 +127,7 @@ static struct rfcomm_dev *__rfcomm_dev_get(int id) | |||
132 | return NULL; | 127 | return NULL; |
133 | } | 128 | } |
134 | 129 | ||
135 | static inline struct rfcomm_dev *rfcomm_dev_get(int id) | 130 | static struct rfcomm_dev *rfcomm_dev_get(int id) |
136 | { | 131 | { |
137 | struct rfcomm_dev *dev; | 132 | struct rfcomm_dev *dev; |
138 | 133 | ||
@@ -345,7 +340,7 @@ static void rfcomm_wfree(struct sk_buff *skb) | |||
345 | tty_port_put(&dev->port); | 340 | tty_port_put(&dev->port); |
346 | } | 341 | } |
347 | 342 | ||
348 | static inline void rfcomm_set_owner_w(struct sk_buff *skb, struct rfcomm_dev *dev) | 343 | static void rfcomm_set_owner_w(struct sk_buff *skb, struct rfcomm_dev *dev) |
349 | { | 344 | { |
350 | tty_port_get(&dev->port); | 345 | tty_port_get(&dev->port); |
351 | atomic_add(skb->truesize, &dev->wmem_alloc); | 346 | atomic_add(skb->truesize, &dev->wmem_alloc); |
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index cbdd313659a..40bbe25dcff 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c | |||
@@ -25,26 +25,8 @@ | |||
25 | /* Bluetooth SCO sockets. */ | 25 | /* Bluetooth SCO sockets. */ |
26 | 26 | ||
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | |||
29 | #include <linux/types.h> | ||
30 | #include <linux/errno.h> | ||
31 | #include <linux/kernel.h> | ||
32 | #include <linux/sched.h> | ||
33 | #include <linux/slab.h> | ||
34 | #include <linux/poll.h> | ||
35 | #include <linux/fcntl.h> | ||
36 | #include <linux/init.h> | ||
37 | #include <linux/interrupt.h> | ||
38 | #include <linux/socket.h> | ||
39 | #include <linux/skbuff.h> | ||
40 | #include <linux/device.h> | ||
41 | #include <linux/debugfs.h> | 28 | #include <linux/debugfs.h> |
42 | #include <linux/seq_file.h> | 29 | #include <linux/seq_file.h> |
43 | #include <linux/list.h> | ||
44 | #include <linux/security.h> | ||
45 | #include <net/sock.h> | ||
46 | |||
47 | #include <linux/uaccess.h> | ||
48 | 30 | ||
49 | #include <net/bluetooth/bluetooth.h> | 31 | #include <net/bluetooth/bluetooth.h> |
50 | #include <net/bluetooth/hci_core.h> | 32 | #include <net/bluetooth/hci_core.h> |
@@ -123,7 +105,7 @@ static struct sco_conn *sco_conn_add(struct hci_conn *hcon) | |||
123 | return conn; | 105 | return conn; |
124 | } | 106 | } |
125 | 107 | ||
126 | static inline struct sock *sco_chan_get(struct sco_conn *conn) | 108 | static struct sock *sco_chan_get(struct sco_conn *conn) |
127 | { | 109 | { |
128 | struct sock *sk = NULL; | 110 | struct sock *sk = NULL; |
129 | sco_conn_lock(conn); | 111 | sco_conn_lock(conn); |
@@ -157,7 +139,8 @@ static int sco_conn_del(struct hci_conn *hcon, int err) | |||
157 | return 0; | 139 | return 0; |
158 | } | 140 | } |
159 | 141 | ||
160 | static inline int sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent) | 142 | static int sco_chan_add(struct sco_conn *conn, struct sock *sk, |
143 | struct sock *parent) | ||
161 | { | 144 | { |
162 | int err = 0; | 145 | int err = 0; |
163 | 146 | ||
@@ -228,7 +211,7 @@ done: | |||
228 | return err; | 211 | return err; |
229 | } | 212 | } |
230 | 213 | ||
231 | static inline int sco_send_frame(struct sock *sk, struct msghdr *msg, int len) | 214 | static int sco_send_frame(struct sock *sk, struct msghdr *msg, int len) |
232 | { | 215 | { |
233 | struct sco_conn *conn = sco_pi(sk)->conn; | 216 | struct sco_conn *conn = sco_pi(sk)->conn; |
234 | struct sk_buff *skb; | 217 | struct sk_buff *skb; |
@@ -254,7 +237,7 @@ static inline int sco_send_frame(struct sock *sk, struct msghdr *msg, int len) | |||
254 | return len; | 237 | return len; |
255 | } | 238 | } |
256 | 239 | ||
257 | static inline void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb) | 240 | static void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb) |
258 | { | 241 | { |
259 | struct sock *sk = sco_chan_get(conn); | 242 | struct sock *sk = sco_chan_get(conn); |
260 | 243 | ||
@@ -523,7 +506,7 @@ static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen | |||
523 | goto done; | 506 | goto done; |
524 | 507 | ||
525 | err = bt_sock_wait_state(sk, BT_CONNECTED, | 508 | err = bt_sock_wait_state(sk, BT_CONNECTED, |
526 | sock_sndtimeo(sk, flags & O_NONBLOCK)); | 509 | sock_sndtimeo(sk, flags & O_NONBLOCK)); |
527 | 510 | ||
528 | done: | 511 | done: |
529 | release_sock(sk); | 512 | release_sock(sk); |
@@ -788,7 +771,7 @@ static int sco_sock_shutdown(struct socket *sock, int how) | |||
788 | 771 | ||
789 | if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) | 772 | if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) |
790 | err = bt_sock_wait_state(sk, BT_CLOSED, | 773 | err = bt_sock_wait_state(sk, BT_CLOSED, |
791 | sk->sk_lingertime); | 774 | sk->sk_lingertime); |
792 | } | 775 | } |
793 | release_sock(sk); | 776 | release_sock(sk); |
794 | return err; | 777 | return err; |
@@ -878,7 +861,7 @@ static void sco_conn_ready(struct sco_conn *conn) | |||
878 | bh_lock_sock(parent); | 861 | bh_lock_sock(parent); |
879 | 862 | ||
880 | sk = sco_sock_alloc(sock_net(parent), NULL, | 863 | sk = sco_sock_alloc(sock_net(parent), NULL, |
881 | BTPROTO_SCO, GFP_ATOMIC); | 864 | BTPROTO_SCO, GFP_ATOMIC); |
882 | if (!sk) { | 865 | if (!sk) { |
883 | bh_unlock_sock(parent); | 866 | bh_unlock_sock(parent); |
884 | goto done; | 867 | goto done; |
@@ -907,7 +890,7 @@ done: | |||
907 | /* ----- SCO interface with lower layer (HCI) ----- */ | 890 | /* ----- SCO interface with lower layer (HCI) ----- */ |
908 | int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) | 891 | int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) |
909 | { | 892 | { |
910 | register struct sock *sk; | 893 | struct sock *sk; |
911 | struct hlist_node *node; | 894 | struct hlist_node *node; |
912 | int lm = 0; | 895 | int lm = 0; |
913 | 896 | ||
@@ -920,7 +903,7 @@ int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) | |||
920 | continue; | 903 | continue; |
921 | 904 | ||
922 | if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr) || | 905 | if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr) || |
923 | !bacmp(&bt_sk(sk)->src, BDADDR_ANY)) { | 906 | !bacmp(&bt_sk(sk)->src, BDADDR_ANY)) { |
924 | lm |= HCI_LM_ACCEPT; | 907 | lm |= HCI_LM_ACCEPT; |
925 | break; | 908 | break; |
926 | } | 909 | } |
@@ -981,7 +964,7 @@ static int sco_debugfs_show(struct seq_file *f, void *p) | |||
981 | 964 | ||
982 | sk_for_each(sk, node, &sco_sk_list.head) { | 965 | sk_for_each(sk, node, &sco_sk_list.head) { |
983 | seq_printf(f, "%s %s %d\n", batostr(&bt_sk(sk)->src), | 966 | seq_printf(f, "%s %s %d\n", batostr(&bt_sk(sk)->src), |
984 | batostr(&bt_sk(sk)->dst), sk->sk_state); | 967 | batostr(&bt_sk(sk)->dst), sk->sk_state); |
985 | } | 968 | } |
986 | 969 | ||
987 | read_unlock(&sco_sk_list.lock); | 970 | read_unlock(&sco_sk_list.lock); |
@@ -1044,8 +1027,8 @@ int __init sco_init(void) | |||
1044 | } | 1027 | } |
1045 | 1028 | ||
1046 | if (bt_debugfs) { | 1029 | if (bt_debugfs) { |
1047 | sco_debugfs = debugfs_create_file("sco", 0444, | 1030 | sco_debugfs = debugfs_create_file("sco", 0444, bt_debugfs, |
1048 | bt_debugfs, NULL, &sco_debugfs_fops); | 1031 | NULL, &sco_debugfs_fops); |
1049 | if (!sco_debugfs) | 1032 | if (!sco_debugfs) |
1050 | BT_ERR("Failed to create SCO debug file"); | 1033 | BT_ERR("Failed to create SCO debug file"); |
1051 | } | 1034 | } |
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 6fc7c4708f3..16ef0dc85a0 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c | |||
@@ -20,14 +20,15 @@ | |||
20 | SOFTWARE IS DISCLAIMED. | 20 | SOFTWARE IS DISCLAIMED. |
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <linux/crypto.h> | ||
24 | #include <linux/scatterlist.h> | ||
25 | #include <crypto/b128ops.h> | ||
26 | |||
23 | #include <net/bluetooth/bluetooth.h> | 27 | #include <net/bluetooth/bluetooth.h> |
24 | #include <net/bluetooth/hci_core.h> | 28 | #include <net/bluetooth/hci_core.h> |
25 | #include <net/bluetooth/l2cap.h> | 29 | #include <net/bluetooth/l2cap.h> |
26 | #include <net/bluetooth/mgmt.h> | 30 | #include <net/bluetooth/mgmt.h> |
27 | #include <net/bluetooth/smp.h> | 31 | #include <net/bluetooth/smp.h> |
28 | #include <linux/crypto.h> | ||
29 | #include <linux/scatterlist.h> | ||
30 | #include <crypto/b128ops.h> | ||
31 | 32 | ||
32 | #define SMP_TIMEOUT msecs_to_jiffies(30000) | 33 | #define SMP_TIMEOUT msecs_to_jiffies(30000) |
33 | 34 | ||
@@ -648,7 +649,7 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb) | |||
648 | 649 | ||
649 | auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM; | 650 | auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM; |
650 | 651 | ||
651 | ret = tk_request(conn, 0, auth, rsp->io_capability, req->io_capability); | 652 | ret = tk_request(conn, 0, auth, req->io_capability, rsp->io_capability); |
652 | if (ret) | 653 | if (ret) |
653 | return SMP_UNSPECIFIED; | 654 | return SMP_UNSPECIFIED; |
654 | 655 | ||
@@ -703,7 +704,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) | |||
703 | return 0; | 704 | return 0; |
704 | } | 705 | } |
705 | 706 | ||
706 | static u8 smp_ltk_encrypt(struct l2cap_conn *conn) | 707 | static u8 smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level) |
707 | { | 708 | { |
708 | struct smp_ltk *key; | 709 | struct smp_ltk *key; |
709 | struct hci_conn *hcon = conn->hcon; | 710 | struct hci_conn *hcon = conn->hcon; |
@@ -712,6 +713,9 @@ static u8 smp_ltk_encrypt(struct l2cap_conn *conn) | |||
712 | if (!key) | 713 | if (!key) |
713 | return 0; | 714 | return 0; |
714 | 715 | ||
716 | if (sec_level > BT_SECURITY_MEDIUM && !key->authenticated) | ||
717 | return 0; | ||
718 | |||
715 | if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags)) | 719 | if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags)) |
716 | return 1; | 720 | return 1; |
717 | 721 | ||
@@ -732,7 +736,7 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
732 | 736 | ||
733 | hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req); | 737 | hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req); |
734 | 738 | ||
735 | if (smp_ltk_encrypt(conn)) | 739 | if (smp_ltk_encrypt(conn, hcon->pending_sec_level)) |
736 | return 0; | 740 | return 0; |
737 | 741 | ||
738 | if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) | 742 | if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) |
@@ -771,7 +775,7 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level) | |||
771 | return 1; | 775 | return 1; |
772 | 776 | ||
773 | if (hcon->link_mode & HCI_LM_MASTER) | 777 | if (hcon->link_mode & HCI_LM_MASTER) |
774 | if (smp_ltk_encrypt(conn)) | 778 | if (smp_ltk_encrypt(conn, sec_level)) |
775 | goto done; | 779 | goto done; |
776 | 780 | ||
777 | if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) | 781 | if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index ebc353ef690..0f02c8b77e1 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -2111,6 +2111,9 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, | |||
2111 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 2111 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
2112 | int i, ret; | 2112 | int i, ret; |
2113 | 2113 | ||
2114 | if (!ieee80211_sdata_running(sdata)) | ||
2115 | return -ENETDOWN; | ||
2116 | |||
2114 | if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) { | 2117 | if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) { |
2115 | ret = drv_set_bitrate_mask(local, sdata, mask); | 2118 | ret = drv_set_bitrate_mask(local, sdata, mask); |
2116 | if (ret) | 2119 | if (ret) |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 398acc4f649..398ce8e9c4d 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -1331,6 +1331,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1331 | if (WARN_ON(!ifmgd->associated)) | 1331 | if (WARN_ON(!ifmgd->associated)) |
1332 | return; | 1332 | return; |
1333 | 1333 | ||
1334 | ieee80211_stop_poll(sdata); | ||
1335 | |||
1334 | memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); | 1336 | memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); |
1335 | 1337 | ||
1336 | ifmgd->associated = NULL; | 1338 | ifmgd->associated = NULL; |
@@ -2589,8 +2591,6 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, | |||
2589 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 2591 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
2590 | u8 frame_buf[DEAUTH_DISASSOC_LEN]; | 2592 | u8 frame_buf[DEAUTH_DISASSOC_LEN]; |
2591 | 2593 | ||
2592 | ieee80211_stop_poll(sdata); | ||
2593 | |||
2594 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, reason, | 2594 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, reason, |
2595 | false, frame_buf); | 2595 | false, frame_buf); |
2596 | mutex_unlock(&ifmgd->mtx); | 2596 | mutex_unlock(&ifmgd->mtx); |
@@ -3081,7 +3081,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
3081 | } | 3081 | } |
3082 | 3082 | ||
3083 | local->oper_channel = cbss->channel; | 3083 | local->oper_channel = cbss->channel; |
3084 | ieee80211_hw_config(local, 0); | 3084 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); |
3085 | 3085 | ||
3086 | if (sta) { | 3086 | if (sta) { |
3087 | u32 rates = 0, basic_rates = 0; | 3087 | u32 rates = 0, basic_rates = 0; |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 3bb24a121c9..a470e1123a5 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -271,6 +271,9 @@ struct sta_ampdu_mlme { | |||
271 | * @plink_timer: peer link watch timer | 271 | * @plink_timer: peer link watch timer |
272 | * @plink_timer_was_running: used by suspend/resume to restore timers | 272 | * @plink_timer_was_running: used by suspend/resume to restore timers |
273 | * @t_offset: timing offset relative to this host | 273 | * @t_offset: timing offset relative to this host |
274 | * @t_offset_setpoint: reference timing offset of this sta to be used when | ||
275 | * calculating clockdrift | ||
276 | * @ch_type: peer's channel type | ||
274 | * @debugfs: debug filesystem info | 277 | * @debugfs: debug filesystem info |
275 | * @dead: set to true when sta is unlinked | 278 | * @dead: set to true when sta is unlinked |
276 | * @uploaded: set to true when sta is uploaded to the driver | 279 | * @uploaded: set to true when sta is uploaded to the driver |
@@ -278,6 +281,8 @@ struct sta_ampdu_mlme { | |||
278 | * @sta: station information we share with the driver | 281 | * @sta: station information we share with the driver |
279 | * @sta_state: duplicates information about station state (for debug) | 282 | * @sta_state: duplicates information about station state (for debug) |
280 | * @beacon_loss_count: number of times beacon loss has triggered | 283 | * @beacon_loss_count: number of times beacon loss has triggered |
284 | * @supports_40mhz: tracks whether the station advertised 40 MHz support | ||
285 | * as we overwrite its HT parameters with the currently used value | ||
281 | */ | 286 | */ |
282 | struct sta_info { | 287 | struct sta_info { |
283 | /* General information, mostly static */ | 288 | /* General information, mostly static */ |
diff --git a/net/nfc/core.c b/net/nfc/core.c index 9f6ce011d35..4177bb5104b 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c | |||
@@ -121,14 +121,14 @@ error: | |||
121 | * The device remains polling for targets until a target is found or | 121 | * The device remains polling for targets until a target is found or |
122 | * the nfc_stop_poll function is called. | 122 | * the nfc_stop_poll function is called. |
123 | */ | 123 | */ |
124 | int nfc_start_poll(struct nfc_dev *dev, u32 protocols) | 124 | int nfc_start_poll(struct nfc_dev *dev, u32 im_protocols, u32 tm_protocols) |
125 | { | 125 | { |
126 | int rc; | 126 | int rc; |
127 | 127 | ||
128 | pr_debug("dev_name=%s protocols=0x%x\n", | 128 | pr_debug("dev_name %s initiator protocols 0x%x target protocols 0x%x\n", |
129 | dev_name(&dev->dev), protocols); | 129 | dev_name(&dev->dev), im_protocols, tm_protocols); |
130 | 130 | ||
131 | if (!protocols) | 131 | if (!im_protocols && !tm_protocols) |
132 | return -EINVAL; | 132 | return -EINVAL; |
133 | 133 | ||
134 | device_lock(&dev->dev); | 134 | device_lock(&dev->dev); |
@@ -143,9 +143,11 @@ int nfc_start_poll(struct nfc_dev *dev, u32 protocols) | |||
143 | goto error; | 143 | goto error; |
144 | } | 144 | } |
145 | 145 | ||
146 | rc = dev->ops->start_poll(dev, protocols); | 146 | rc = dev->ops->start_poll(dev, im_protocols, tm_protocols); |
147 | if (!rc) | 147 | if (!rc) { |
148 | dev->polling = true; | 148 | dev->polling = true; |
149 | dev->rf_mode = NFC_RF_NONE; | ||
150 | } | ||
149 | 151 | ||
150 | error: | 152 | error: |
151 | device_unlock(&dev->dev); | 153 | device_unlock(&dev->dev); |
@@ -235,8 +237,10 @@ int nfc_dep_link_up(struct nfc_dev *dev, int target_index, u8 comm_mode) | |||
235 | } | 237 | } |
236 | 238 | ||
237 | rc = dev->ops->dep_link_up(dev, target, comm_mode, gb, gb_len); | 239 | rc = dev->ops->dep_link_up(dev, target, comm_mode, gb, gb_len); |
238 | if (!rc) | 240 | if (!rc) { |
239 | dev->active_target = target; | 241 | dev->active_target = target; |
242 | dev->rf_mode = NFC_RF_INITIATOR; | ||
243 | } | ||
240 | 244 | ||
241 | error: | 245 | error: |
242 | device_unlock(&dev->dev); | 246 | device_unlock(&dev->dev); |
@@ -264,11 +268,6 @@ int nfc_dep_link_down(struct nfc_dev *dev) | |||
264 | goto error; | 268 | goto error; |
265 | } | 269 | } |
266 | 270 | ||
267 | if (dev->dep_rf_mode == NFC_RF_TARGET) { | ||
268 | rc = -EOPNOTSUPP; | ||
269 | goto error; | ||
270 | } | ||
271 | |||
272 | rc = dev->ops->dep_link_down(dev); | 271 | rc = dev->ops->dep_link_down(dev); |
273 | if (!rc) { | 272 | if (!rc) { |
274 | dev->dep_link_up = false; | 273 | dev->dep_link_up = false; |
@@ -286,7 +285,6 @@ int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx, | |||
286 | u8 comm_mode, u8 rf_mode) | 285 | u8 comm_mode, u8 rf_mode) |
287 | { | 286 | { |
288 | dev->dep_link_up = true; | 287 | dev->dep_link_up = true; |
289 | dev->dep_rf_mode = rf_mode; | ||
290 | 288 | ||
291 | nfc_llcp_mac_is_up(dev, target_idx, comm_mode, rf_mode); | 289 | nfc_llcp_mac_is_up(dev, target_idx, comm_mode, rf_mode); |
292 | 290 | ||
@@ -330,6 +328,7 @@ int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol) | |||
330 | rc = dev->ops->activate_target(dev, target, protocol); | 328 | rc = dev->ops->activate_target(dev, target, protocol); |
331 | if (!rc) { | 329 | if (!rc) { |
332 | dev->active_target = target; | 330 | dev->active_target = target; |
331 | dev->rf_mode = NFC_RF_INITIATOR; | ||
333 | 332 | ||
334 | if (dev->ops->check_presence) | 333 | if (dev->ops->check_presence) |
335 | mod_timer(&dev->check_pres_timer, jiffies + | 334 | mod_timer(&dev->check_pres_timer, jiffies + |
@@ -409,27 +408,30 @@ int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx, struct sk_buff *skb, | |||
409 | goto error; | 408 | goto error; |
410 | } | 409 | } |
411 | 410 | ||
412 | if (dev->active_target == NULL) { | 411 | if (dev->rf_mode == NFC_RF_INITIATOR && dev->active_target != NULL) { |
413 | rc = -ENOTCONN; | 412 | if (dev->active_target->idx != target_idx) { |
414 | kfree_skb(skb); | 413 | rc = -EADDRNOTAVAIL; |
415 | goto error; | 414 | kfree_skb(skb); |
416 | } | 415 | goto error; |
416 | } | ||
417 | 417 | ||
418 | if (dev->active_target->idx != target_idx) { | 418 | if (dev->ops->check_presence) |
419 | rc = -EADDRNOTAVAIL; | 419 | del_timer_sync(&dev->check_pres_timer); |
420 | |||
421 | rc = dev->ops->im_transceive(dev, dev->active_target, skb, cb, | ||
422 | cb_context); | ||
423 | |||
424 | if (!rc && dev->ops->check_presence) | ||
425 | mod_timer(&dev->check_pres_timer, jiffies + | ||
426 | msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS)); | ||
427 | } else if (dev->rf_mode == NFC_RF_TARGET && dev->ops->tm_send != NULL) { | ||
428 | rc = dev->ops->tm_send(dev, skb); | ||
429 | } else { | ||
430 | rc = -ENOTCONN; | ||
420 | kfree_skb(skb); | 431 | kfree_skb(skb); |
421 | goto error; | 432 | goto error; |
422 | } | 433 | } |
423 | 434 | ||
424 | if (dev->ops->check_presence) | ||
425 | del_timer_sync(&dev->check_pres_timer); | ||
426 | |||
427 | rc = dev->ops->data_exchange(dev, dev->active_target, skb, cb, | ||
428 | cb_context); | ||
429 | |||
430 | if (!rc && dev->ops->check_presence) | ||
431 | mod_timer(&dev->check_pres_timer, jiffies + | ||
432 | msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS)); | ||
433 | 435 | ||
434 | error: | 436 | error: |
435 | device_unlock(&dev->dev); | 437 | device_unlock(&dev->dev); |
@@ -447,6 +449,63 @@ int nfc_set_remote_general_bytes(struct nfc_dev *dev, u8 *gb, u8 gb_len) | |||
447 | } | 449 | } |
448 | EXPORT_SYMBOL(nfc_set_remote_general_bytes); | 450 | EXPORT_SYMBOL(nfc_set_remote_general_bytes); |
449 | 451 | ||
452 | u8 *nfc_get_local_general_bytes(struct nfc_dev *dev, size_t *gb_len) | ||
453 | { | ||
454 | pr_debug("dev_name=%s\n", dev_name(&dev->dev)); | ||
455 | |||
456 | return nfc_llcp_general_bytes(dev, gb_len); | ||
457 | } | ||
458 | EXPORT_SYMBOL(nfc_get_local_general_bytes); | ||
459 | |||
460 | int nfc_tm_data_received(struct nfc_dev *dev, struct sk_buff *skb) | ||
461 | { | ||
462 | /* Only LLCP target mode for now */ | ||
463 | if (dev->dep_link_up == false) { | ||
464 | kfree_skb(skb); | ||
465 | return -ENOLINK; | ||
466 | } | ||
467 | |||
468 | return nfc_llcp_data_received(dev, skb); | ||
469 | } | ||
470 | EXPORT_SYMBOL(nfc_tm_data_received); | ||
471 | |||
472 | int nfc_tm_activated(struct nfc_dev *dev, u32 protocol, u8 comm_mode, | ||
473 | u8 *gb, size_t gb_len) | ||
474 | { | ||
475 | int rc; | ||
476 | |||
477 | device_lock(&dev->dev); | ||
478 | |||
479 | dev->polling = false; | ||
480 | |||
481 | if (gb != NULL) { | ||
482 | rc = nfc_set_remote_general_bytes(dev, gb, gb_len); | ||
483 | if (rc < 0) | ||
484 | goto out; | ||
485 | } | ||
486 | |||
487 | dev->rf_mode = NFC_RF_TARGET; | ||
488 | |||
489 | if (protocol == NFC_PROTO_NFC_DEP_MASK) | ||
490 | nfc_dep_link_is_up(dev, 0, comm_mode, NFC_RF_TARGET); | ||
491 | |||
492 | rc = nfc_genl_tm_activated(dev, protocol); | ||
493 | |||
494 | out: | ||
495 | device_unlock(&dev->dev); | ||
496 | |||
497 | return rc; | ||
498 | } | ||
499 | EXPORT_SYMBOL(nfc_tm_activated); | ||
500 | |||
501 | int nfc_tm_deactivated(struct nfc_dev *dev) | ||
502 | { | ||
503 | dev->dep_link_up = false; | ||
504 | |||
505 | return nfc_genl_tm_deactivated(dev); | ||
506 | } | ||
507 | EXPORT_SYMBOL(nfc_tm_deactivated); | ||
508 | |||
450 | /** | 509 | /** |
451 | * nfc_alloc_send_skb - allocate a skb for data exchange responses | 510 | * nfc_alloc_send_skb - allocate a skb for data exchange responses |
452 | * | 511 | * |
@@ -678,7 +737,7 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, | |||
678 | struct nfc_dev *dev; | 737 | struct nfc_dev *dev; |
679 | 738 | ||
680 | if (!ops->start_poll || !ops->stop_poll || !ops->activate_target || | 739 | if (!ops->start_poll || !ops->stop_poll || !ops->activate_target || |
681 | !ops->deactivate_target || !ops->data_exchange) | 740 | !ops->deactivate_target || !ops->im_transceive) |
682 | return NULL; | 741 | return NULL; |
683 | 742 | ||
684 | if (!supported_protocols) | 743 | if (!supported_protocols) |
diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index e1a640d2b58..a8b0b71e8f8 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c | |||
@@ -481,12 +481,13 @@ static int hci_dev_down(struct nfc_dev *nfc_dev) | |||
481 | return 0; | 481 | return 0; |
482 | } | 482 | } |
483 | 483 | ||
484 | static int hci_start_poll(struct nfc_dev *nfc_dev, u32 protocols) | 484 | static int hci_start_poll(struct nfc_dev *nfc_dev, |
485 | u32 im_protocols, u32 tm_protocols) | ||
485 | { | 486 | { |
486 | struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); | 487 | struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); |
487 | 488 | ||
488 | if (hdev->ops->start_poll) | 489 | if (hdev->ops->start_poll) |
489 | return hdev->ops->start_poll(hdev, protocols); | 490 | return hdev->ops->start_poll(hdev, im_protocols, tm_protocols); |
490 | else | 491 | else |
491 | return nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, | 492 | return nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, |
492 | NFC_HCI_EVT_READER_REQUESTED, NULL, 0); | 493 | NFC_HCI_EVT_READER_REQUESTED, NULL, 0); |
@@ -511,9 +512,9 @@ static void hci_deactivate_target(struct nfc_dev *nfc_dev, | |||
511 | { | 512 | { |
512 | } | 513 | } |
513 | 514 | ||
514 | static int hci_data_exchange(struct nfc_dev *nfc_dev, struct nfc_target *target, | 515 | static int hci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target, |
515 | struct sk_buff *skb, data_exchange_cb_t cb, | 516 | struct sk_buff *skb, data_exchange_cb_t cb, |
516 | void *cb_context) | 517 | void *cb_context) |
517 | { | 518 | { |
518 | struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); | 519 | struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); |
519 | int r; | 520 | int r; |
@@ -579,7 +580,7 @@ static struct nfc_ops hci_nfc_ops = { | |||
579 | .stop_poll = hci_stop_poll, | 580 | .stop_poll = hci_stop_poll, |
580 | .activate_target = hci_activate_target, | 581 | .activate_target = hci_activate_target, |
581 | .deactivate_target = hci_deactivate_target, | 582 | .deactivate_target = hci_deactivate_target, |
582 | .data_exchange = hci_data_exchange, | 583 | .im_transceive = hci_transceive, |
583 | .check_presence = hci_check_presence, | 584 | .check_presence = hci_check_presence, |
584 | }; | 585 | }; |
585 | 586 | ||
diff --git a/net/nfc/hci/shdlc.c b/net/nfc/hci/shdlc.c index 5665dc6d893..6b836e6242b 100644 --- a/net/nfc/hci/shdlc.c +++ b/net/nfc/hci/shdlc.c | |||
@@ -765,14 +765,16 @@ static int nfc_shdlc_xmit(struct nfc_hci_dev *hdev, struct sk_buff *skb) | |||
765 | return 0; | 765 | return 0; |
766 | } | 766 | } |
767 | 767 | ||
768 | static int nfc_shdlc_start_poll(struct nfc_hci_dev *hdev, u32 protocols) | 768 | static int nfc_shdlc_start_poll(struct nfc_hci_dev *hdev, |
769 | u32 im_protocols, u32 tm_protocols) | ||
769 | { | 770 | { |
770 | struct nfc_shdlc *shdlc = nfc_hci_get_clientdata(hdev); | 771 | struct nfc_shdlc *shdlc = nfc_hci_get_clientdata(hdev); |
771 | 772 | ||
772 | pr_debug("\n"); | 773 | pr_debug("\n"); |
773 | 774 | ||
774 | if (shdlc->ops->start_poll) | 775 | if (shdlc->ops->start_poll) |
775 | return shdlc->ops->start_poll(shdlc, protocols); | 776 | return shdlc->ops->start_poll(shdlc, |
777 | im_protocols, tm_protocols); | ||
776 | 778 | ||
777 | return 0; | 779 | return 0; |
778 | } | 780 | } |
diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c index bf8ae4f0b90..b982b5b890d 100644 --- a/net/nfc/llcp/commands.c +++ b/net/nfc/llcp/commands.c | |||
@@ -51,7 +51,7 @@ static u8 llcp_tlv8(u8 *tlv, u8 type) | |||
51 | return tlv[2]; | 51 | return tlv[2]; |
52 | } | 52 | } |
53 | 53 | ||
54 | static u8 llcp_tlv16(u8 *tlv, u8 type) | 54 | static u16 llcp_tlv16(u8 *tlv, u8 type) |
55 | { | 55 | { |
56 | if (tlv[0] != type || tlv[1] != llcp_tlv_length[tlv[0]]) | 56 | if (tlv[0] != type || tlv[1] != llcp_tlv_length[tlv[0]]) |
57 | return 0; | 57 | return 0; |
@@ -67,7 +67,7 @@ static u8 llcp_tlv_version(u8 *tlv) | |||
67 | 67 | ||
68 | static u16 llcp_tlv_miux(u8 *tlv) | 68 | static u16 llcp_tlv_miux(u8 *tlv) |
69 | { | 69 | { |
70 | return llcp_tlv16(tlv, LLCP_TLV_MIUX) & 0x7f; | 70 | return llcp_tlv16(tlv, LLCP_TLV_MIUX) & 0x7ff; |
71 | } | 71 | } |
72 | 72 | ||
73 | static u16 llcp_tlv_wks(u8 *tlv) | 73 | static u16 llcp_tlv_wks(u8 *tlv) |
@@ -117,8 +117,8 @@ u8 *nfc_llcp_build_tlv(u8 type, u8 *value, u8 value_length, u8 *tlv_length) | |||
117 | return tlv; | 117 | return tlv; |
118 | } | 118 | } |
119 | 119 | ||
120 | int nfc_llcp_parse_tlv(struct nfc_llcp_local *local, | 120 | int nfc_llcp_parse_gb_tlv(struct nfc_llcp_local *local, |
121 | u8 *tlv_array, u16 tlv_array_len) | 121 | u8 *tlv_array, u16 tlv_array_len) |
122 | { | 122 | { |
123 | u8 *tlv = tlv_array, type, length, offset = 0; | 123 | u8 *tlv = tlv_array, type, length, offset = 0; |
124 | 124 | ||
@@ -149,8 +149,45 @@ int nfc_llcp_parse_tlv(struct nfc_llcp_local *local, | |||
149 | case LLCP_TLV_OPT: | 149 | case LLCP_TLV_OPT: |
150 | local->remote_opt = llcp_tlv_opt(tlv); | 150 | local->remote_opt = llcp_tlv_opt(tlv); |
151 | break; | 151 | break; |
152 | default: | ||
153 | pr_err("Invalid gt tlv value 0x%x\n", type); | ||
154 | break; | ||
155 | } | ||
156 | |||
157 | offset += length + 2; | ||
158 | tlv += length + 2; | ||
159 | } | ||
160 | |||
161 | pr_debug("version 0x%x miu %d lto %d opt 0x%x wks 0x%x\n", | ||
162 | local->remote_version, local->remote_miu, | ||
163 | local->remote_lto, local->remote_opt, | ||
164 | local->remote_wks); | ||
165 | |||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | int nfc_llcp_parse_connection_tlv(struct nfc_llcp_sock *sock, | ||
170 | u8 *tlv_array, u16 tlv_array_len) | ||
171 | { | ||
172 | u8 *tlv = tlv_array, type, length, offset = 0; | ||
173 | |||
174 | pr_debug("TLV array length %d\n", tlv_array_len); | ||
175 | |||
176 | if (sock == NULL) | ||
177 | return -ENOTCONN; | ||
178 | |||
179 | while (offset < tlv_array_len) { | ||
180 | type = tlv[0]; | ||
181 | length = tlv[1]; | ||
182 | |||
183 | pr_debug("type 0x%x length %d\n", type, length); | ||
184 | |||
185 | switch (type) { | ||
186 | case LLCP_TLV_MIUX: | ||
187 | sock->miu = llcp_tlv_miux(tlv) + 128; | ||
188 | break; | ||
152 | case LLCP_TLV_RW: | 189 | case LLCP_TLV_RW: |
153 | local->remote_rw = llcp_tlv_rw(tlv); | 190 | sock->rw = llcp_tlv_rw(tlv); |
154 | break; | 191 | break; |
155 | case LLCP_TLV_SN: | 192 | case LLCP_TLV_SN: |
156 | break; | 193 | break; |
@@ -163,10 +200,7 @@ int nfc_llcp_parse_tlv(struct nfc_llcp_local *local, | |||
163 | tlv += length + 2; | 200 | tlv += length + 2; |
164 | } | 201 | } |
165 | 202 | ||
166 | pr_debug("version 0x%x miu %d lto %d opt 0x%x wks 0x%x rw %d\n", | 203 | pr_debug("sock %p rw %d miu %d\n", sock, sock->rw, sock->miu); |
167 | local->remote_version, local->remote_miu, | ||
168 | local->remote_lto, local->remote_opt, | ||
169 | local->remote_wks, local->remote_rw); | ||
170 | 204 | ||
171 | return 0; | 205 | return 0; |
172 | } | 206 | } |
@@ -474,7 +508,7 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock, | |||
474 | 508 | ||
475 | while (remaining_len > 0) { | 509 | while (remaining_len > 0) { |
476 | 510 | ||
477 | frag_len = min_t(size_t, local->remote_miu, remaining_len); | 511 | frag_len = min_t(size_t, sock->miu, remaining_len); |
478 | 512 | ||
479 | pr_debug("Fragment %zd bytes remaining %zd", | 513 | pr_debug("Fragment %zd bytes remaining %zd", |
480 | frag_len, remaining_len); | 514 | frag_len, remaining_len); |
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c index 42994fac26d..5d503eeb15a 100644 --- a/net/nfc/llcp/llcp.c +++ b/net/nfc/llcp/llcp.c | |||
@@ -31,47 +31,41 @@ static u8 llcp_magic[3] = {0x46, 0x66, 0x6d}; | |||
31 | 31 | ||
32 | static struct list_head llcp_devices; | 32 | static struct list_head llcp_devices; |
33 | 33 | ||
34 | static void nfc_llcp_socket_release(struct nfc_llcp_local *local) | 34 | void nfc_llcp_sock_link(struct llcp_sock_list *l, struct sock *sk) |
35 | { | 35 | { |
36 | struct nfc_llcp_sock *parent, *s, *n; | 36 | write_lock(&l->lock); |
37 | struct sock *sk, *parent_sk; | 37 | sk_add_node(sk, &l->head); |
38 | int i; | 38 | write_unlock(&l->lock); |
39 | 39 | } | |
40 | mutex_lock(&local->socket_lock); | ||
41 | |||
42 | for (i = 0; i < LLCP_MAX_SAP; i++) { | ||
43 | parent = local->sockets[i]; | ||
44 | if (parent == NULL) | ||
45 | continue; | ||
46 | |||
47 | /* Release all child sockets */ | ||
48 | list_for_each_entry_safe(s, n, &parent->list, list) { | ||
49 | list_del_init(&s->list); | ||
50 | sk = &s->sk; | ||
51 | |||
52 | lock_sock(sk); | ||
53 | |||
54 | if (sk->sk_state == LLCP_CONNECTED) | ||
55 | nfc_put_device(s->dev); | ||
56 | 40 | ||
57 | sk->sk_state = LLCP_CLOSED; | 41 | void nfc_llcp_sock_unlink(struct llcp_sock_list *l, struct sock *sk) |
42 | { | ||
43 | write_lock(&l->lock); | ||
44 | sk_del_node_init(sk); | ||
45 | write_unlock(&l->lock); | ||
46 | } | ||
58 | 47 | ||
59 | release_sock(sk); | 48 | static void nfc_llcp_socket_release(struct nfc_llcp_local *local) |
49 | { | ||
50 | struct sock *sk; | ||
51 | struct hlist_node *node, *tmp; | ||
52 | struct nfc_llcp_sock *llcp_sock; | ||
60 | 53 | ||
61 | sock_orphan(sk); | 54 | write_lock(&local->sockets.lock); |
62 | 55 | ||
63 | s->local = NULL; | 56 | sk_for_each_safe(sk, node, tmp, &local->sockets.head) { |
64 | } | 57 | llcp_sock = nfc_llcp_sock(sk); |
65 | 58 | ||
66 | parent_sk = &parent->sk; | 59 | lock_sock(sk); |
67 | 60 | ||
68 | lock_sock(parent_sk); | 61 | if (sk->sk_state == LLCP_CONNECTED) |
62 | nfc_put_device(llcp_sock->dev); | ||
69 | 63 | ||
70 | if (parent_sk->sk_state == LLCP_LISTEN) { | 64 | if (sk->sk_state == LLCP_LISTEN) { |
71 | struct nfc_llcp_sock *lsk, *n; | 65 | struct nfc_llcp_sock *lsk, *n; |
72 | struct sock *accept_sk; | 66 | struct sock *accept_sk; |
73 | 67 | ||
74 | list_for_each_entry_safe(lsk, n, &parent->accept_queue, | 68 | list_for_each_entry_safe(lsk, n, &llcp_sock->accept_queue, |
75 | accept_queue) { | 69 | accept_queue) { |
76 | accept_sk = &lsk->sk; | 70 | accept_sk = &lsk->sk; |
77 | lock_sock(accept_sk); | 71 | lock_sock(accept_sk); |
@@ -83,24 +77,53 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local) | |||
83 | release_sock(accept_sk); | 77 | release_sock(accept_sk); |
84 | 78 | ||
85 | sock_orphan(accept_sk); | 79 | sock_orphan(accept_sk); |
86 | |||
87 | lsk->local = NULL; | ||
88 | } | 80 | } |
89 | } | 81 | } |
90 | 82 | ||
91 | if (parent_sk->sk_state == LLCP_CONNECTED) | 83 | sk->sk_state = LLCP_CLOSED; |
92 | nfc_put_device(parent->dev); | ||
93 | |||
94 | parent_sk->sk_state = LLCP_CLOSED; | ||
95 | 84 | ||
96 | release_sock(parent_sk); | 85 | release_sock(sk); |
97 | 86 | ||
98 | sock_orphan(parent_sk); | 87 | sock_orphan(sk); |
99 | 88 | ||
100 | parent->local = NULL; | 89 | sk_del_node_init(sk); |
101 | } | 90 | } |
102 | 91 | ||
103 | mutex_unlock(&local->socket_lock); | 92 | write_unlock(&local->sockets.lock); |
93 | } | ||
94 | |||
95 | struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local) | ||
96 | { | ||
97 | kref_get(&local->ref); | ||
98 | |||
99 | return local; | ||
100 | } | ||
101 | |||
102 | static void local_release(struct kref *ref) | ||
103 | { | ||
104 | struct nfc_llcp_local *local; | ||
105 | |||
106 | local = container_of(ref, struct nfc_llcp_local, ref); | ||
107 | |||
108 | list_del(&local->list); | ||
109 | nfc_llcp_socket_release(local); | ||
110 | del_timer_sync(&local->link_timer); | ||
111 | skb_queue_purge(&local->tx_queue); | ||
112 | destroy_workqueue(local->tx_wq); | ||
113 | destroy_workqueue(local->rx_wq); | ||
114 | destroy_workqueue(local->timeout_wq); | ||
115 | kfree_skb(local->rx_pending); | ||
116 | kfree(local); | ||
117 | } | ||
118 | |||
119 | int nfc_llcp_local_put(struct nfc_llcp_local *local) | ||
120 | { | ||
121 | WARN_ON(local == NULL); | ||
122 | |||
123 | if (local == NULL) | ||
124 | return 0; | ||
125 | |||
126 | return kref_put(&local->ref, local_release); | ||
104 | } | 127 | } |
105 | 128 | ||
106 | static void nfc_llcp_clear_sdp(struct nfc_llcp_local *local) | 129 | static void nfc_llcp_clear_sdp(struct nfc_llcp_local *local) |
@@ -384,31 +407,9 @@ int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len) | |||
384 | return -EINVAL; | 407 | return -EINVAL; |
385 | } | 408 | } |
386 | 409 | ||
387 | return nfc_llcp_parse_tlv(local, | 410 | return nfc_llcp_parse_gb_tlv(local, |
388 | &local->remote_gb[3], | 411 | &local->remote_gb[3], |
389 | local->remote_gb_len - 3); | 412 | local->remote_gb_len - 3); |
390 | } | ||
391 | |||
392 | static void nfc_llcp_tx_work(struct work_struct *work) | ||
393 | { | ||
394 | struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, | ||
395 | tx_work); | ||
396 | struct sk_buff *skb; | ||
397 | |||
398 | skb = skb_dequeue(&local->tx_queue); | ||
399 | if (skb != NULL) { | ||
400 | pr_debug("Sending pending skb\n"); | ||
401 | print_hex_dump(KERN_DEBUG, "LLCP Tx: ", DUMP_PREFIX_OFFSET, | ||
402 | 16, 1, skb->data, skb->len, true); | ||
403 | |||
404 | nfc_data_exchange(local->dev, local->target_idx, | ||
405 | skb, nfc_llcp_recv, local); | ||
406 | } else { | ||
407 | nfc_llcp_send_symm(local->dev); | ||
408 | } | ||
409 | |||
410 | mod_timer(&local->link_timer, | ||
411 | jiffies + msecs_to_jiffies(local->remote_lto)); | ||
412 | } | 413 | } |
413 | 414 | ||
414 | static u8 nfc_llcp_dsap(struct sk_buff *pdu) | 415 | static u8 nfc_llcp_dsap(struct sk_buff *pdu) |
@@ -443,46 +444,146 @@ static void nfc_llcp_set_nrns(struct nfc_llcp_sock *sock, struct sk_buff *pdu) | |||
443 | sock->recv_ack_n = (sock->recv_n - 1) % 16; | 444 | sock->recv_ack_n = (sock->recv_n - 1) % 16; |
444 | } | 445 | } |
445 | 446 | ||
447 | static void nfc_llcp_tx_work(struct work_struct *work) | ||
448 | { | ||
449 | struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, | ||
450 | tx_work); | ||
451 | struct sk_buff *skb; | ||
452 | struct sock *sk; | ||
453 | struct nfc_llcp_sock *llcp_sock; | ||
454 | |||
455 | skb = skb_dequeue(&local->tx_queue); | ||
456 | if (skb != NULL) { | ||
457 | sk = skb->sk; | ||
458 | llcp_sock = nfc_llcp_sock(sk); | ||
459 | if (llcp_sock != NULL) { | ||
460 | int ret; | ||
461 | |||
462 | pr_debug("Sending pending skb\n"); | ||
463 | print_hex_dump(KERN_DEBUG, "LLCP Tx: ", | ||
464 | DUMP_PREFIX_OFFSET, 16, 1, | ||
465 | skb->data, skb->len, true); | ||
466 | |||
467 | ret = nfc_data_exchange(local->dev, local->target_idx, | ||
468 | skb, nfc_llcp_recv, local); | ||
469 | |||
470 | if (!ret && nfc_llcp_ptype(skb) == LLCP_PDU_I) { | ||
471 | skb = skb_get(skb); | ||
472 | skb_queue_tail(&llcp_sock->tx_pending_queue, | ||
473 | skb); | ||
474 | } | ||
475 | } else { | ||
476 | nfc_llcp_send_symm(local->dev); | ||
477 | } | ||
478 | } else { | ||
479 | nfc_llcp_send_symm(local->dev); | ||
480 | } | ||
481 | |||
482 | mod_timer(&local->link_timer, | ||
483 | jiffies + msecs_to_jiffies(2 * local->remote_lto)); | ||
484 | } | ||
485 | |||
486 | static struct nfc_llcp_sock *nfc_llcp_connecting_sock_get(struct nfc_llcp_local *local, | ||
487 | u8 ssap) | ||
488 | { | ||
489 | struct sock *sk; | ||
490 | struct nfc_llcp_sock *llcp_sock; | ||
491 | struct hlist_node *node; | ||
492 | |||
493 | read_lock(&local->connecting_sockets.lock); | ||
494 | |||
495 | sk_for_each(sk, node, &local->connecting_sockets.head) { | ||
496 | llcp_sock = nfc_llcp_sock(sk); | ||
497 | |||
498 | if (llcp_sock->ssap == ssap) { | ||
499 | sock_hold(&llcp_sock->sk); | ||
500 | goto out; | ||
501 | } | ||
502 | } | ||
503 | |||
504 | llcp_sock = NULL; | ||
505 | |||
506 | out: | ||
507 | read_unlock(&local->connecting_sockets.lock); | ||
508 | |||
509 | return llcp_sock; | ||
510 | } | ||
511 | |||
446 | static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local, | 512 | static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local, |
447 | u8 ssap, u8 dsap) | 513 | u8 ssap, u8 dsap) |
448 | { | 514 | { |
449 | struct nfc_llcp_sock *sock, *llcp_sock, *n; | 515 | struct sock *sk; |
516 | struct hlist_node *node; | ||
517 | struct nfc_llcp_sock *llcp_sock; | ||
450 | 518 | ||
451 | pr_debug("ssap dsap %d %d\n", ssap, dsap); | 519 | pr_debug("ssap dsap %d %d\n", ssap, dsap); |
452 | 520 | ||
453 | if (ssap == 0 && dsap == 0) | 521 | if (ssap == 0 && dsap == 0) |
454 | return NULL; | 522 | return NULL; |
455 | 523 | ||
456 | mutex_lock(&local->socket_lock); | 524 | read_lock(&local->sockets.lock); |
457 | sock = local->sockets[ssap]; | ||
458 | if (sock == NULL) { | ||
459 | mutex_unlock(&local->socket_lock); | ||
460 | return NULL; | ||
461 | } | ||
462 | 525 | ||
463 | pr_debug("root dsap %d (%d)\n", sock->dsap, dsap); | 526 | llcp_sock = NULL; |
464 | 527 | ||
465 | if (sock->dsap == dsap) { | 528 | sk_for_each(sk, node, &local->sockets.head) { |
466 | sock_hold(&sock->sk); | 529 | llcp_sock = nfc_llcp_sock(sk); |
467 | mutex_unlock(&local->socket_lock); | 530 | |
468 | return sock; | 531 | if (llcp_sock->ssap == ssap && |
532 | llcp_sock->dsap == dsap) | ||
533 | break; | ||
469 | } | 534 | } |
470 | 535 | ||
471 | list_for_each_entry_safe(llcp_sock, n, &sock->list, list) { | 536 | read_unlock(&local->sockets.lock); |
472 | pr_debug("llcp_sock %p sk %p dsap %d\n", llcp_sock, | 537 | |
473 | &llcp_sock->sk, llcp_sock->dsap); | 538 | if (llcp_sock == NULL) |
474 | if (llcp_sock->dsap == dsap) { | 539 | return NULL; |
475 | sock_hold(&llcp_sock->sk); | 540 | |
476 | mutex_unlock(&local->socket_lock); | 541 | sock_hold(&llcp_sock->sk); |
477 | return llcp_sock; | 542 | |
478 | } | 543 | return llcp_sock; |
544 | } | ||
545 | |||
546 | static struct nfc_llcp_sock *nfc_llcp_sock_get_sn(struct nfc_llcp_local *local, | ||
547 | u8 *sn, size_t sn_len) | ||
548 | { | ||
549 | struct sock *sk; | ||
550 | struct hlist_node *node; | ||
551 | struct nfc_llcp_sock *llcp_sock; | ||
552 | |||
553 | pr_debug("sn %zd\n", sn_len); | ||
554 | |||
555 | if (sn == NULL || sn_len == 0) | ||
556 | return NULL; | ||
557 | |||
558 | read_lock(&local->sockets.lock); | ||
559 | |||
560 | llcp_sock = NULL; | ||
561 | |||
562 | sk_for_each(sk, node, &local->sockets.head) { | ||
563 | llcp_sock = nfc_llcp_sock(sk); | ||
564 | |||
565 | if (llcp_sock->sk.sk_state != LLCP_LISTEN) | ||
566 | continue; | ||
567 | |||
568 | if (llcp_sock->service_name == NULL || | ||
569 | llcp_sock->service_name_len == 0) | ||
570 | continue; | ||
571 | |||
572 | if (llcp_sock->service_name_len != sn_len) | ||
573 | continue; | ||
574 | |||
575 | if (memcmp(sn, llcp_sock->service_name, sn_len) == 0) | ||
576 | break; | ||
479 | } | 577 | } |
480 | 578 | ||
481 | pr_err("Could not find socket for %d %d\n", ssap, dsap); | 579 | read_unlock(&local->sockets.lock); |
482 | 580 | ||
483 | mutex_unlock(&local->socket_lock); | 581 | if (llcp_sock == NULL) |
582 | return NULL; | ||
484 | 583 | ||
485 | return NULL; | 584 | sock_hold(&llcp_sock->sk); |
585 | |||
586 | return llcp_sock; | ||
486 | } | 587 | } |
487 | 588 | ||
488 | static void nfc_llcp_sock_put(struct nfc_llcp_sock *sock) | 589 | static void nfc_llcp_sock_put(struct nfc_llcp_sock *sock) |
@@ -518,35 +619,19 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, | |||
518 | { | 619 | { |
519 | struct sock *new_sk, *parent; | 620 | struct sock *new_sk, *parent; |
520 | struct nfc_llcp_sock *sock, *new_sock; | 621 | struct nfc_llcp_sock *sock, *new_sock; |
521 | u8 dsap, ssap, bound_sap, reason; | 622 | u8 dsap, ssap, reason; |
522 | 623 | ||
523 | dsap = nfc_llcp_dsap(skb); | 624 | dsap = nfc_llcp_dsap(skb); |
524 | ssap = nfc_llcp_ssap(skb); | 625 | ssap = nfc_llcp_ssap(skb); |
525 | 626 | ||
526 | pr_debug("%d %d\n", dsap, ssap); | 627 | pr_debug("%d %d\n", dsap, ssap); |
527 | 628 | ||
528 | nfc_llcp_parse_tlv(local, &skb->data[LLCP_HEADER_SIZE], | ||
529 | skb->len - LLCP_HEADER_SIZE); | ||
530 | |||
531 | if (dsap != LLCP_SAP_SDP) { | 629 | if (dsap != LLCP_SAP_SDP) { |
532 | bound_sap = dsap; | 630 | sock = nfc_llcp_sock_get(local, dsap, LLCP_SAP_SDP); |
533 | 631 | if (sock == NULL || sock->sk.sk_state != LLCP_LISTEN) { | |
534 | mutex_lock(&local->socket_lock); | ||
535 | sock = local->sockets[dsap]; | ||
536 | if (sock == NULL) { | ||
537 | mutex_unlock(&local->socket_lock); | ||
538 | reason = LLCP_DM_NOBOUND; | 632 | reason = LLCP_DM_NOBOUND; |
539 | goto fail; | 633 | goto fail; |
540 | } | 634 | } |
541 | |||
542 | sock_hold(&sock->sk); | ||
543 | mutex_unlock(&local->socket_lock); | ||
544 | |||
545 | lock_sock(&sock->sk); | ||
546 | |||
547 | if (sock->dsap == LLCP_SAP_SDP && | ||
548 | sock->sk.sk_state == LLCP_LISTEN) | ||
549 | goto enqueue; | ||
550 | } else { | 635 | } else { |
551 | u8 *sn; | 636 | u8 *sn; |
552 | size_t sn_len; | 637 | size_t sn_len; |
@@ -559,40 +644,15 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, | |||
559 | 644 | ||
560 | pr_debug("Service name length %zu\n", sn_len); | 645 | pr_debug("Service name length %zu\n", sn_len); |
561 | 646 | ||
562 | mutex_lock(&local->socket_lock); | 647 | sock = nfc_llcp_sock_get_sn(local, sn, sn_len); |
563 | for (bound_sap = 0; bound_sap < LLCP_LOCAL_SAP_OFFSET; | 648 | if (sock == NULL) { |
564 | bound_sap++) { | 649 | reason = LLCP_DM_NOBOUND; |
565 | sock = local->sockets[bound_sap]; | 650 | goto fail; |
566 | if (sock == NULL) | ||
567 | continue; | ||
568 | |||
569 | if (sock->service_name == NULL || | ||
570 | sock->service_name_len == 0) | ||
571 | continue; | ||
572 | |||
573 | if (sock->service_name_len != sn_len) | ||
574 | continue; | ||
575 | |||
576 | if (sock->dsap == LLCP_SAP_SDP && | ||
577 | sock->sk.sk_state == LLCP_LISTEN && | ||
578 | !memcmp(sn, sock->service_name, sn_len)) { | ||
579 | pr_debug("Found service name at SAP %d\n", | ||
580 | bound_sap); | ||
581 | sock_hold(&sock->sk); | ||
582 | mutex_unlock(&local->socket_lock); | ||
583 | |||
584 | lock_sock(&sock->sk); | ||
585 | |||
586 | goto enqueue; | ||
587 | } | ||
588 | } | 651 | } |
589 | mutex_unlock(&local->socket_lock); | ||
590 | } | 652 | } |
591 | 653 | ||
592 | reason = LLCP_DM_NOBOUND; | 654 | lock_sock(&sock->sk); |
593 | goto fail; | ||
594 | 655 | ||
595 | enqueue: | ||
596 | parent = &sock->sk; | 656 | parent = &sock->sk; |
597 | 657 | ||
598 | if (sk_acceptq_is_full(parent)) { | 658 | if (sk_acceptq_is_full(parent)) { |
@@ -612,15 +672,19 @@ enqueue: | |||
612 | 672 | ||
613 | new_sock = nfc_llcp_sock(new_sk); | 673 | new_sock = nfc_llcp_sock(new_sk); |
614 | new_sock->dev = local->dev; | 674 | new_sock->dev = local->dev; |
615 | new_sock->local = local; | 675 | new_sock->local = nfc_llcp_local_get(local); |
676 | new_sock->miu = local->remote_miu; | ||
616 | new_sock->nfc_protocol = sock->nfc_protocol; | 677 | new_sock->nfc_protocol = sock->nfc_protocol; |
617 | new_sock->ssap = bound_sap; | 678 | new_sock->ssap = sock->ssap; |
618 | new_sock->dsap = ssap; | 679 | new_sock->dsap = ssap; |
619 | new_sock->parent = parent; | 680 | new_sock->parent = parent; |
620 | 681 | ||
682 | nfc_llcp_parse_connection_tlv(new_sock, &skb->data[LLCP_HEADER_SIZE], | ||
683 | skb->len - LLCP_HEADER_SIZE); | ||
684 | |||
621 | pr_debug("new sock %p sk %p\n", new_sock, &new_sock->sk); | 685 | pr_debug("new sock %p sk %p\n", new_sock, &new_sock->sk); |
622 | 686 | ||
623 | list_add_tail(&new_sock->list, &sock->list); | 687 | nfc_llcp_sock_link(&local->sockets, new_sk); |
624 | 688 | ||
625 | nfc_llcp_accept_enqueue(&sock->sk, new_sk); | 689 | nfc_llcp_accept_enqueue(&sock->sk, new_sk); |
626 | 690 | ||
@@ -654,12 +718,12 @@ int nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock) | |||
654 | 718 | ||
655 | pr_debug("Remote ready %d tx queue len %d remote rw %d", | 719 | pr_debug("Remote ready %d tx queue len %d remote rw %d", |
656 | sock->remote_ready, skb_queue_len(&sock->tx_pending_queue), | 720 | sock->remote_ready, skb_queue_len(&sock->tx_pending_queue), |
657 | local->remote_rw); | 721 | sock->rw); |
658 | 722 | ||
659 | /* Try to queue some I frames for transmission */ | 723 | /* Try to queue some I frames for transmission */ |
660 | while (sock->remote_ready && | 724 | while (sock->remote_ready && |
661 | skb_queue_len(&sock->tx_pending_queue) < local->remote_rw) { | 725 | skb_queue_len(&sock->tx_pending_queue) < sock->rw) { |
662 | struct sk_buff *pdu, *pending_pdu; | 726 | struct sk_buff *pdu; |
663 | 727 | ||
664 | pdu = skb_dequeue(&sock->tx_queue); | 728 | pdu = skb_dequeue(&sock->tx_queue); |
665 | if (pdu == NULL) | 729 | if (pdu == NULL) |
@@ -668,10 +732,7 @@ int nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock) | |||
668 | /* Update N(S)/N(R) */ | 732 | /* Update N(S)/N(R) */ |
669 | nfc_llcp_set_nrns(sock, pdu); | 733 | nfc_llcp_set_nrns(sock, pdu); |
670 | 734 | ||
671 | pending_pdu = skb_clone(pdu, GFP_KERNEL); | ||
672 | |||
673 | skb_queue_tail(&local->tx_queue, pdu); | 735 | skb_queue_tail(&local->tx_queue, pdu); |
674 | skb_queue_tail(&sock->tx_pending_queue, pending_pdu); | ||
675 | nr_frames++; | 736 | nr_frames++; |
676 | } | 737 | } |
677 | 738 | ||
@@ -728,11 +789,21 @@ static void nfc_llcp_recv_hdlc(struct nfc_llcp_local *local, | |||
728 | 789 | ||
729 | llcp_sock->send_ack_n = nr; | 790 | llcp_sock->send_ack_n = nr; |
730 | 791 | ||
731 | skb_queue_walk_safe(&llcp_sock->tx_pending_queue, s, tmp) | 792 | /* Remove and free all skbs until ns == nr */ |
732 | if (nfc_llcp_ns(s) <= nr) { | 793 | skb_queue_walk_safe(&llcp_sock->tx_pending_queue, s, tmp) { |
733 | skb_unlink(s, &llcp_sock->tx_pending_queue); | 794 | skb_unlink(s, &llcp_sock->tx_pending_queue); |
734 | kfree_skb(s); | 795 | kfree_skb(s); |
735 | } | 796 | |
797 | if (nfc_llcp_ns(s) == nr) | ||
798 | break; | ||
799 | } | ||
800 | |||
801 | /* Re-queue the remaining skbs for transmission */ | ||
802 | skb_queue_reverse_walk_safe(&llcp_sock->tx_pending_queue, | ||
803 | s, tmp) { | ||
804 | skb_unlink(s, &llcp_sock->tx_pending_queue); | ||
805 | skb_queue_head(&local->tx_queue, s); | ||
806 | } | ||
736 | } | 807 | } |
737 | 808 | ||
738 | if (ptype == LLCP_PDU_RR) | 809 | if (ptype == LLCP_PDU_RR) |
@@ -740,7 +811,7 @@ static void nfc_llcp_recv_hdlc(struct nfc_llcp_local *local, | |||
740 | else if (ptype == LLCP_PDU_RNR) | 811 | else if (ptype == LLCP_PDU_RNR) |
741 | llcp_sock->remote_ready = false; | 812 | llcp_sock->remote_ready = false; |
742 | 813 | ||
743 | if (nfc_llcp_queue_i_frames(llcp_sock) == 0) | 814 | if (nfc_llcp_queue_i_frames(llcp_sock) == 0 && ptype == LLCP_PDU_I) |
744 | nfc_llcp_send_rr(llcp_sock); | 815 | nfc_llcp_send_rr(llcp_sock); |
745 | 816 | ||
746 | release_sock(sk); | 817 | release_sock(sk); |
@@ -791,11 +862,7 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, struct sk_buff *skb) | |||
791 | dsap = nfc_llcp_dsap(skb); | 862 | dsap = nfc_llcp_dsap(skb); |
792 | ssap = nfc_llcp_ssap(skb); | 863 | ssap = nfc_llcp_ssap(skb); |
793 | 864 | ||
794 | llcp_sock = nfc_llcp_sock_get(local, dsap, ssap); | 865 | llcp_sock = nfc_llcp_connecting_sock_get(local, dsap); |
795 | |||
796 | if (llcp_sock == NULL) | ||
797 | llcp_sock = nfc_llcp_sock_get(local, dsap, LLCP_SAP_SDP); | ||
798 | |||
799 | if (llcp_sock == NULL) { | 866 | if (llcp_sock == NULL) { |
800 | pr_err("Invalid CC\n"); | 867 | pr_err("Invalid CC\n"); |
801 | nfc_llcp_send_dm(local, dsap, ssap, LLCP_DM_NOCONN); | 868 | nfc_llcp_send_dm(local, dsap, ssap, LLCP_DM_NOCONN); |
@@ -803,11 +870,15 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, struct sk_buff *skb) | |||
803 | return; | 870 | return; |
804 | } | 871 | } |
805 | 872 | ||
806 | llcp_sock->dsap = ssap; | ||
807 | sk = &llcp_sock->sk; | 873 | sk = &llcp_sock->sk; |
808 | 874 | ||
809 | nfc_llcp_parse_tlv(local, &skb->data[LLCP_HEADER_SIZE], | 875 | /* Unlink from connecting and link to the client array */ |
810 | skb->len - LLCP_HEADER_SIZE); | 876 | nfc_llcp_sock_unlink(&local->connecting_sockets, sk); |
877 | nfc_llcp_sock_link(&local->sockets, sk); | ||
878 | llcp_sock->dsap = ssap; | ||
879 | |||
880 | nfc_llcp_parse_connection_tlv(llcp_sock, &skb->data[LLCP_HEADER_SIZE], | ||
881 | skb->len - LLCP_HEADER_SIZE); | ||
811 | 882 | ||
812 | sk->sk_state = LLCP_CONNECTED; | 883 | sk->sk_state = LLCP_CONNECTED; |
813 | sk->sk_state_change(sk); | 884 | sk->sk_state_change(sk); |
@@ -891,6 +962,21 @@ void nfc_llcp_recv(void *data, struct sk_buff *skb, int err) | |||
891 | return; | 962 | return; |
892 | } | 963 | } |
893 | 964 | ||
965 | int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb) | ||
966 | { | ||
967 | struct nfc_llcp_local *local; | ||
968 | |||
969 | local = nfc_llcp_find_local(dev); | ||
970 | if (local == NULL) | ||
971 | return -ENODEV; | ||
972 | |||
973 | local->rx_pending = skb_get(skb); | ||
974 | del_timer(&local->link_timer); | ||
975 | queue_work(local->rx_wq, &local->rx_work); | ||
976 | |||
977 | return 0; | ||
978 | } | ||
979 | |||
894 | void nfc_llcp_mac_is_down(struct nfc_dev *dev) | 980 | void nfc_llcp_mac_is_down(struct nfc_dev *dev) |
895 | { | 981 | { |
896 | struct nfc_llcp_local *local; | 982 | struct nfc_llcp_local *local; |
@@ -943,8 +1029,8 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) | |||
943 | 1029 | ||
944 | local->dev = ndev; | 1030 | local->dev = ndev; |
945 | INIT_LIST_HEAD(&local->list); | 1031 | INIT_LIST_HEAD(&local->list); |
1032 | kref_init(&local->ref); | ||
946 | mutex_init(&local->sdp_lock); | 1033 | mutex_init(&local->sdp_lock); |
947 | mutex_init(&local->socket_lock); | ||
948 | init_timer(&local->link_timer); | 1034 | init_timer(&local->link_timer); |
949 | local->link_timer.data = (unsigned long) local; | 1035 | local->link_timer.data = (unsigned long) local; |
950 | local->link_timer.function = nfc_llcp_symm_timer; | 1036 | local->link_timer.function = nfc_llcp_symm_timer; |
@@ -984,11 +1070,13 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) | |||
984 | goto err_rx_wq; | 1070 | goto err_rx_wq; |
985 | } | 1071 | } |
986 | 1072 | ||
1073 | local->sockets.lock = __RW_LOCK_UNLOCKED(local->sockets.lock); | ||
1074 | local->connecting_sockets.lock = __RW_LOCK_UNLOCKED(local->connecting_sockets.lock); | ||
1075 | |||
987 | nfc_llcp_build_gb(local); | 1076 | nfc_llcp_build_gb(local); |
988 | 1077 | ||
989 | local->remote_miu = LLCP_DEFAULT_MIU; | 1078 | local->remote_miu = LLCP_DEFAULT_MIU; |
990 | local->remote_lto = LLCP_DEFAULT_LTO; | 1079 | local->remote_lto = LLCP_DEFAULT_LTO; |
991 | local->remote_rw = LLCP_DEFAULT_RW; | ||
992 | 1080 | ||
993 | list_add(&llcp_devices, &local->list); | 1081 | list_add(&llcp_devices, &local->list); |
994 | 1082 | ||
@@ -1015,14 +1103,7 @@ void nfc_llcp_unregister_device(struct nfc_dev *dev) | |||
1015 | return; | 1103 | return; |
1016 | } | 1104 | } |
1017 | 1105 | ||
1018 | list_del(&local->list); | 1106 | nfc_llcp_local_put(local); |
1019 | nfc_llcp_socket_release(local); | ||
1020 | del_timer_sync(&local->link_timer); | ||
1021 | skb_queue_purge(&local->tx_queue); | ||
1022 | destroy_workqueue(local->tx_wq); | ||
1023 | destroy_workqueue(local->rx_wq); | ||
1024 | kfree_skb(local->rx_pending); | ||
1025 | kfree(local); | ||
1026 | } | 1107 | } |
1027 | 1108 | ||
1028 | int __init nfc_llcp_init(void) | 1109 | int __init nfc_llcp_init(void) |
diff --git a/net/nfc/llcp/llcp.h b/net/nfc/llcp/llcp.h index 50680ce5ae4..7286c86982f 100644 --- a/net/nfc/llcp/llcp.h +++ b/net/nfc/llcp/llcp.h | |||
@@ -40,12 +40,18 @@ enum llcp_state { | |||
40 | 40 | ||
41 | struct nfc_llcp_sock; | 41 | struct nfc_llcp_sock; |
42 | 42 | ||
43 | struct llcp_sock_list { | ||
44 | struct hlist_head head; | ||
45 | rwlock_t lock; | ||
46 | }; | ||
47 | |||
43 | struct nfc_llcp_local { | 48 | struct nfc_llcp_local { |
44 | struct list_head list; | 49 | struct list_head list; |
45 | struct nfc_dev *dev; | 50 | struct nfc_dev *dev; |
46 | 51 | ||
52 | struct kref ref; | ||
53 | |||
47 | struct mutex sdp_lock; | 54 | struct mutex sdp_lock; |
48 | struct mutex socket_lock; | ||
49 | 55 | ||
50 | struct timer_list link_timer; | 56 | struct timer_list link_timer; |
51 | struct sk_buff_head tx_queue; | 57 | struct sk_buff_head tx_queue; |
@@ -77,24 +83,26 @@ struct nfc_llcp_local { | |||
77 | u16 remote_lto; | 83 | u16 remote_lto; |
78 | u8 remote_opt; | 84 | u8 remote_opt; |
79 | u16 remote_wks; | 85 | u16 remote_wks; |
80 | u8 remote_rw; | ||
81 | 86 | ||
82 | /* sockets array */ | 87 | /* sockets array */ |
83 | struct nfc_llcp_sock *sockets[LLCP_MAX_SAP]; | 88 | struct llcp_sock_list sockets; |
89 | struct llcp_sock_list connecting_sockets; | ||
84 | }; | 90 | }; |
85 | 91 | ||
86 | struct nfc_llcp_sock { | 92 | struct nfc_llcp_sock { |
87 | struct sock sk; | 93 | struct sock sk; |
88 | struct list_head list; | ||
89 | struct nfc_dev *dev; | 94 | struct nfc_dev *dev; |
90 | struct nfc_llcp_local *local; | 95 | struct nfc_llcp_local *local; |
91 | u32 target_idx; | 96 | u32 target_idx; |
92 | u32 nfc_protocol; | 97 | u32 nfc_protocol; |
93 | 98 | ||
99 | /* Link parameters */ | ||
94 | u8 ssap; | 100 | u8 ssap; |
95 | u8 dsap; | 101 | u8 dsap; |
96 | char *service_name; | 102 | char *service_name; |
97 | size_t service_name_len; | 103 | size_t service_name_len; |
104 | u8 rw; | ||
105 | u16 miu; | ||
98 | 106 | ||
99 | /* Link variables */ | 107 | /* Link variables */ |
100 | u8 send_n; | 108 | u8 send_n; |
@@ -164,7 +172,11 @@ struct nfc_llcp_sock { | |||
164 | #define LLCP_DM_REJ 0x03 | 172 | #define LLCP_DM_REJ 0x03 |
165 | 173 | ||
166 | 174 | ||
175 | void nfc_llcp_sock_link(struct llcp_sock_list *l, struct sock *s); | ||
176 | void nfc_llcp_sock_unlink(struct llcp_sock_list *l, struct sock *s); | ||
167 | struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev); | 177 | struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev); |
178 | struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local); | ||
179 | int nfc_llcp_local_put(struct nfc_llcp_local *local); | ||
168 | u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local, | 180 | u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local, |
169 | struct nfc_llcp_sock *sock); | 181 | struct nfc_llcp_sock *sock); |
170 | u8 nfc_llcp_get_local_ssap(struct nfc_llcp_local *local); | 182 | u8 nfc_llcp_get_local_ssap(struct nfc_llcp_local *local); |
@@ -179,8 +191,10 @@ void nfc_llcp_accept_enqueue(struct sock *parent, struct sock *sk); | |||
179 | struct sock *nfc_llcp_accept_dequeue(struct sock *sk, struct socket *newsock); | 191 | struct sock *nfc_llcp_accept_dequeue(struct sock *sk, struct socket *newsock); |
180 | 192 | ||
181 | /* TLV API */ | 193 | /* TLV API */ |
182 | int nfc_llcp_parse_tlv(struct nfc_llcp_local *local, | 194 | int nfc_llcp_parse_gb_tlv(struct nfc_llcp_local *local, |
183 | u8 *tlv_array, u16 tlv_array_len); | 195 | u8 *tlv_array, u16 tlv_array_len); |
196 | int nfc_llcp_parse_connection_tlv(struct nfc_llcp_sock *sock, | ||
197 | u8 *tlv_array, u16 tlv_array_len); | ||
184 | 198 | ||
185 | /* Commands API */ | 199 | /* Commands API */ |
186 | void nfc_llcp_recv(void *data, struct sk_buff *skb, int err); | 200 | void nfc_llcp_recv(void *data, struct sk_buff *skb, int err); |
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c index 3f339b19d14..2c0b317344b 100644 --- a/net/nfc/llcp/sock.c +++ b/net/nfc/llcp/sock.c | |||
@@ -111,7 +111,7 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) | |||
111 | } | 111 | } |
112 | 112 | ||
113 | llcp_sock->dev = dev; | 113 | llcp_sock->dev = dev; |
114 | llcp_sock->local = local; | 114 | llcp_sock->local = nfc_llcp_local_get(local); |
115 | llcp_sock->nfc_protocol = llcp_addr.nfc_protocol; | 115 | llcp_sock->nfc_protocol = llcp_addr.nfc_protocol; |
116 | llcp_sock->service_name_len = min_t(unsigned int, | 116 | llcp_sock->service_name_len = min_t(unsigned int, |
117 | llcp_addr.service_name_len, | 117 | llcp_addr.service_name_len, |
@@ -124,7 +124,7 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) | |||
124 | if (llcp_sock->ssap == LLCP_MAX_SAP) | 124 | if (llcp_sock->ssap == LLCP_MAX_SAP) |
125 | goto put_dev; | 125 | goto put_dev; |
126 | 126 | ||
127 | local->sockets[llcp_sock->ssap] = llcp_sock; | 127 | nfc_llcp_sock_link(&local->sockets, sk); |
128 | 128 | ||
129 | pr_debug("Socket bound to SAP %d\n", llcp_sock->ssap); | 129 | pr_debug("Socket bound to SAP %d\n", llcp_sock->ssap); |
130 | 130 | ||
@@ -292,6 +292,9 @@ static int llcp_sock_getname(struct socket *sock, struct sockaddr *addr, | |||
292 | 292 | ||
293 | pr_debug("%p\n", sk); | 293 | pr_debug("%p\n", sk); |
294 | 294 | ||
295 | if (llcp_sock == NULL) | ||
296 | return -EBADFD; | ||
297 | |||
295 | addr->sa_family = AF_NFC; | 298 | addr->sa_family = AF_NFC; |
296 | *len = sizeof(struct sockaddr_nfc_llcp); | 299 | *len = sizeof(struct sockaddr_nfc_llcp); |
297 | 300 | ||
@@ -379,15 +382,6 @@ static int llcp_sock_release(struct socket *sock) | |||
379 | goto out; | 382 | goto out; |
380 | } | 383 | } |
381 | 384 | ||
382 | mutex_lock(&local->socket_lock); | ||
383 | |||
384 | if (llcp_sock == local->sockets[llcp_sock->ssap]) | ||
385 | local->sockets[llcp_sock->ssap] = NULL; | ||
386 | else | ||
387 | list_del_init(&llcp_sock->list); | ||
388 | |||
389 | mutex_unlock(&local->socket_lock); | ||
390 | |||
391 | lock_sock(sk); | 385 | lock_sock(sk); |
392 | 386 | ||
393 | /* Send a DISC */ | 387 | /* Send a DISC */ |
@@ -412,14 +406,12 @@ static int llcp_sock_release(struct socket *sock) | |||
412 | } | 406 | } |
413 | } | 407 | } |
414 | 408 | ||
415 | /* Freeing the SAP */ | 409 | nfc_llcp_put_ssap(llcp_sock->local, llcp_sock->ssap); |
416 | if ((sk->sk_state == LLCP_CONNECTED | ||
417 | && llcp_sock->ssap > LLCP_LOCAL_SAP_OFFSET) || | ||
418 | sk->sk_state == LLCP_BOUND || sk->sk_state == LLCP_LISTEN) | ||
419 | nfc_llcp_put_ssap(llcp_sock->local, llcp_sock->ssap); | ||
420 | 410 | ||
421 | release_sock(sk); | 411 | release_sock(sk); |
422 | 412 | ||
413 | nfc_llcp_sock_unlink(&local->sockets, sk); | ||
414 | |||
423 | out: | 415 | out: |
424 | sock_orphan(sk); | 416 | sock_orphan(sk); |
425 | sock_put(sk); | 417 | sock_put(sk); |
@@ -487,7 +479,8 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, | |||
487 | } | 479 | } |
488 | 480 | ||
489 | llcp_sock->dev = dev; | 481 | llcp_sock->dev = dev; |
490 | llcp_sock->local = local; | 482 | llcp_sock->local = nfc_llcp_local_get(local); |
483 | llcp_sock->miu = llcp_sock->local->remote_miu; | ||
491 | llcp_sock->ssap = nfc_llcp_get_local_ssap(local); | 484 | llcp_sock->ssap = nfc_llcp_get_local_ssap(local); |
492 | if (llcp_sock->ssap == LLCP_SAP_MAX) { | 485 | if (llcp_sock->ssap == LLCP_SAP_MAX) { |
493 | ret = -ENOMEM; | 486 | ret = -ENOMEM; |
@@ -505,21 +498,26 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, | |||
505 | llcp_sock->service_name_len, | 498 | llcp_sock->service_name_len, |
506 | GFP_KERNEL); | 499 | GFP_KERNEL); |
507 | 500 | ||
508 | local->sockets[llcp_sock->ssap] = llcp_sock; | 501 | nfc_llcp_sock_link(&local->connecting_sockets, sk); |
509 | 502 | ||
510 | ret = nfc_llcp_send_connect(llcp_sock); | 503 | ret = nfc_llcp_send_connect(llcp_sock); |
511 | if (ret) | 504 | if (ret) |
512 | goto put_dev; | 505 | goto sock_unlink; |
513 | 506 | ||
514 | ret = sock_wait_state(sk, LLCP_CONNECTED, | 507 | ret = sock_wait_state(sk, LLCP_CONNECTED, |
515 | sock_sndtimeo(sk, flags & O_NONBLOCK)); | 508 | sock_sndtimeo(sk, flags & O_NONBLOCK)); |
516 | if (ret) | 509 | if (ret) |
517 | goto put_dev; | 510 | goto sock_unlink; |
518 | 511 | ||
519 | release_sock(sk); | 512 | release_sock(sk); |
520 | 513 | ||
521 | return 0; | 514 | return 0; |
522 | 515 | ||
516 | sock_unlink: | ||
517 | nfc_llcp_put_ssap(local, llcp_sock->ssap); | ||
518 | |||
519 | nfc_llcp_sock_unlink(&local->connecting_sockets, sk); | ||
520 | |||
523 | put_dev: | 521 | put_dev: |
524 | nfc_put_device(dev); | 522 | nfc_put_device(dev); |
525 | 523 | ||
@@ -684,13 +682,14 @@ struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp) | |||
684 | 682 | ||
685 | llcp_sock->ssap = 0; | 683 | llcp_sock->ssap = 0; |
686 | llcp_sock->dsap = LLCP_SAP_SDP; | 684 | llcp_sock->dsap = LLCP_SAP_SDP; |
685 | llcp_sock->rw = LLCP_DEFAULT_RW; | ||
686 | llcp_sock->miu = LLCP_DEFAULT_MIU; | ||
687 | llcp_sock->send_n = llcp_sock->send_ack_n = 0; | 687 | llcp_sock->send_n = llcp_sock->send_ack_n = 0; |
688 | llcp_sock->recv_n = llcp_sock->recv_ack_n = 0; | 688 | llcp_sock->recv_n = llcp_sock->recv_ack_n = 0; |
689 | llcp_sock->remote_ready = 1; | 689 | llcp_sock->remote_ready = 1; |
690 | skb_queue_head_init(&llcp_sock->tx_queue); | 690 | skb_queue_head_init(&llcp_sock->tx_queue); |
691 | skb_queue_head_init(&llcp_sock->tx_pending_queue); | 691 | skb_queue_head_init(&llcp_sock->tx_pending_queue); |
692 | skb_queue_head_init(&llcp_sock->tx_backlog_queue); | 692 | skb_queue_head_init(&llcp_sock->tx_backlog_queue); |
693 | INIT_LIST_HEAD(&llcp_sock->list); | ||
694 | INIT_LIST_HEAD(&llcp_sock->accept_queue); | 693 | INIT_LIST_HEAD(&llcp_sock->accept_queue); |
695 | 694 | ||
696 | if (sock != NULL) | 695 | if (sock != NULL) |
@@ -701,8 +700,6 @@ struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp) | |||
701 | 700 | ||
702 | void nfc_llcp_sock_free(struct nfc_llcp_sock *sock) | 701 | void nfc_llcp_sock_free(struct nfc_llcp_sock *sock) |
703 | { | 702 | { |
704 | struct nfc_llcp_local *local = sock->local; | ||
705 | |||
706 | kfree(sock->service_name); | 703 | kfree(sock->service_name); |
707 | 704 | ||
708 | skb_queue_purge(&sock->tx_queue); | 705 | skb_queue_purge(&sock->tx_queue); |
@@ -711,12 +708,9 @@ void nfc_llcp_sock_free(struct nfc_llcp_sock *sock) | |||
711 | 708 | ||
712 | list_del_init(&sock->accept_queue); | 709 | list_del_init(&sock->accept_queue); |
713 | 710 | ||
714 | if (local != NULL && sock == local->sockets[sock->ssap]) | ||
715 | local->sockets[sock->ssap] = NULL; | ||
716 | else | ||
717 | list_del_init(&sock->list); | ||
718 | |||
719 | sock->parent = NULL; | 711 | sock->parent = NULL; |
712 | |||
713 | nfc_llcp_local_put(sock->local); | ||
720 | } | 714 | } |
721 | 715 | ||
722 | static int llcp_sock_create(struct net *net, struct socket *sock, | 716 | static int llcp_sock_create(struct net *net, struct socket *sock, |
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c index d560e6f1307..766a02b1dfa 100644 --- a/net/nfc/nci/core.c +++ b/net/nfc/nci/core.c | |||
@@ -387,7 +387,8 @@ static int nci_dev_down(struct nfc_dev *nfc_dev) | |||
387 | return nci_close_device(ndev); | 387 | return nci_close_device(ndev); |
388 | } | 388 | } |
389 | 389 | ||
390 | static int nci_start_poll(struct nfc_dev *nfc_dev, __u32 protocols) | 390 | static int nci_start_poll(struct nfc_dev *nfc_dev, |
391 | __u32 im_protocols, __u32 tm_protocols) | ||
391 | { | 392 | { |
392 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); | 393 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); |
393 | int rc; | 394 | int rc; |
@@ -413,11 +414,11 @@ static int nci_start_poll(struct nfc_dev *nfc_dev, __u32 protocols) | |||
413 | return -EBUSY; | 414 | return -EBUSY; |
414 | } | 415 | } |
415 | 416 | ||
416 | rc = nci_request(ndev, nci_rf_discover_req, protocols, | 417 | rc = nci_request(ndev, nci_rf_discover_req, im_protocols, |
417 | msecs_to_jiffies(NCI_RF_DISC_TIMEOUT)); | 418 | msecs_to_jiffies(NCI_RF_DISC_TIMEOUT)); |
418 | 419 | ||
419 | if (!rc) | 420 | if (!rc) |
420 | ndev->poll_prots = protocols; | 421 | ndev->poll_prots = im_protocols; |
421 | 422 | ||
422 | return rc; | 423 | return rc; |
423 | } | 424 | } |
@@ -521,9 +522,9 @@ static void nci_deactivate_target(struct nfc_dev *nfc_dev, | |||
521 | } | 522 | } |
522 | } | 523 | } |
523 | 524 | ||
524 | static int nci_data_exchange(struct nfc_dev *nfc_dev, struct nfc_target *target, | 525 | static int nci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target, |
525 | struct sk_buff *skb, | 526 | struct sk_buff *skb, |
526 | data_exchange_cb_t cb, void *cb_context) | 527 | data_exchange_cb_t cb, void *cb_context) |
527 | { | 528 | { |
528 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); | 529 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); |
529 | int rc; | 530 | int rc; |
@@ -556,7 +557,7 @@ static struct nfc_ops nci_nfc_ops = { | |||
556 | .stop_poll = nci_stop_poll, | 557 | .stop_poll = nci_stop_poll, |
557 | .activate_target = nci_activate_target, | 558 | .activate_target = nci_activate_target, |
558 | .deactivate_target = nci_deactivate_target, | 559 | .deactivate_target = nci_deactivate_target, |
559 | .data_exchange = nci_data_exchange, | 560 | .im_transceive = nci_transceive, |
560 | }; | 561 | }; |
561 | 562 | ||
562 | /* ---- Interface to NCI drivers ---- */ | 563 | /* ---- Interface to NCI drivers ---- */ |
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index 581d419083a..03c31db38f1 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c | |||
@@ -49,6 +49,8 @@ static const struct nla_policy nfc_genl_policy[NFC_ATTR_MAX + 1] = { | |||
49 | [NFC_ATTR_COMM_MODE] = { .type = NLA_U8 }, | 49 | [NFC_ATTR_COMM_MODE] = { .type = NLA_U8 }, |
50 | [NFC_ATTR_RF_MODE] = { .type = NLA_U8 }, | 50 | [NFC_ATTR_RF_MODE] = { .type = NLA_U8 }, |
51 | [NFC_ATTR_DEVICE_POWERED] = { .type = NLA_U8 }, | 51 | [NFC_ATTR_DEVICE_POWERED] = { .type = NLA_U8 }, |
52 | [NFC_ATTR_IM_PROTOCOLS] = { .type = NLA_U32 }, | ||
53 | [NFC_ATTR_TM_PROTOCOLS] = { .type = NLA_U32 }, | ||
52 | }; | 54 | }; |
53 | 55 | ||
54 | static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target, | 56 | static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target, |
@@ -219,6 +221,68 @@ free_msg: | |||
219 | return -EMSGSIZE; | 221 | return -EMSGSIZE; |
220 | } | 222 | } |
221 | 223 | ||
224 | int nfc_genl_tm_activated(struct nfc_dev *dev, u32 protocol) | ||
225 | { | ||
226 | struct sk_buff *msg; | ||
227 | void *hdr; | ||
228 | |||
229 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | ||
230 | if (!msg) | ||
231 | return -ENOMEM; | ||
232 | |||
233 | hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, | ||
234 | NFC_EVENT_TM_ACTIVATED); | ||
235 | if (!hdr) | ||
236 | goto free_msg; | ||
237 | |||
238 | if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx)) | ||
239 | goto nla_put_failure; | ||
240 | if (nla_put_u32(msg, NFC_ATTR_TM_PROTOCOLS, protocol)) | ||
241 | goto nla_put_failure; | ||
242 | |||
243 | genlmsg_end(msg, hdr); | ||
244 | |||
245 | genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL); | ||
246 | |||
247 | return 0; | ||
248 | |||
249 | nla_put_failure: | ||
250 | genlmsg_cancel(msg, hdr); | ||
251 | free_msg: | ||
252 | nlmsg_free(msg); | ||
253 | return -EMSGSIZE; | ||
254 | } | ||
255 | |||
256 | int nfc_genl_tm_deactivated(struct nfc_dev *dev) | ||
257 | { | ||
258 | struct sk_buff *msg; | ||
259 | void *hdr; | ||
260 | |||
261 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | ||
262 | if (!msg) | ||
263 | return -ENOMEM; | ||
264 | |||
265 | hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, | ||
266 | NFC_EVENT_TM_DEACTIVATED); | ||
267 | if (!hdr) | ||
268 | goto free_msg; | ||
269 | |||
270 | if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx)) | ||
271 | goto nla_put_failure; | ||
272 | |||
273 | genlmsg_end(msg, hdr); | ||
274 | |||
275 | genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL); | ||
276 | |||
277 | return 0; | ||
278 | |||
279 | nla_put_failure: | ||
280 | genlmsg_cancel(msg, hdr); | ||
281 | free_msg: | ||
282 | nlmsg_free(msg); | ||
283 | return -EMSGSIZE; | ||
284 | } | ||
285 | |||
222 | int nfc_genl_device_added(struct nfc_dev *dev) | 286 | int nfc_genl_device_added(struct nfc_dev *dev) |
223 | { | 287 | { |
224 | struct sk_buff *msg; | 288 | struct sk_buff *msg; |
@@ -519,16 +583,25 @@ static int nfc_genl_start_poll(struct sk_buff *skb, struct genl_info *info) | |||
519 | struct nfc_dev *dev; | 583 | struct nfc_dev *dev; |
520 | int rc; | 584 | int rc; |
521 | u32 idx; | 585 | u32 idx; |
522 | u32 protocols; | 586 | u32 im_protocols = 0, tm_protocols = 0; |
523 | 587 | ||
524 | pr_debug("Poll start\n"); | 588 | pr_debug("Poll start\n"); |
525 | 589 | ||
526 | if (!info->attrs[NFC_ATTR_DEVICE_INDEX] || | 590 | if (!info->attrs[NFC_ATTR_DEVICE_INDEX] || |
527 | !info->attrs[NFC_ATTR_PROTOCOLS]) | 591 | ((!info->attrs[NFC_ATTR_IM_PROTOCOLS] && |
592 | !info->attrs[NFC_ATTR_PROTOCOLS]) && | ||
593 | !info->attrs[NFC_ATTR_TM_PROTOCOLS])) | ||
528 | return -EINVAL; | 594 | return -EINVAL; |
529 | 595 | ||
530 | idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); | 596 | idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); |
531 | protocols = nla_get_u32(info->attrs[NFC_ATTR_PROTOCOLS]); | 597 | |
598 | if (info->attrs[NFC_ATTR_TM_PROTOCOLS]) | ||
599 | tm_protocols = nla_get_u32(info->attrs[NFC_ATTR_TM_PROTOCOLS]); | ||
600 | |||
601 | if (info->attrs[NFC_ATTR_IM_PROTOCOLS]) | ||
602 | im_protocols = nla_get_u32(info->attrs[NFC_ATTR_IM_PROTOCOLS]); | ||
603 | else if (info->attrs[NFC_ATTR_PROTOCOLS]) | ||
604 | im_protocols = nla_get_u32(info->attrs[NFC_ATTR_PROTOCOLS]); | ||
532 | 605 | ||
533 | dev = nfc_get_device(idx); | 606 | dev = nfc_get_device(idx); |
534 | if (!dev) | 607 | if (!dev) |
@@ -536,7 +609,7 @@ static int nfc_genl_start_poll(struct sk_buff *skb, struct genl_info *info) | |||
536 | 609 | ||
537 | mutex_lock(&dev->genl_data.genl_data_mutex); | 610 | mutex_lock(&dev->genl_data.genl_data_mutex); |
538 | 611 | ||
539 | rc = nfc_start_poll(dev, protocols); | 612 | rc = nfc_start_poll(dev, im_protocols, tm_protocols); |
540 | if (!rc) | 613 | if (!rc) |
541 | dev->genl_data.poll_req_pid = info->snd_pid; | 614 | dev->genl_data.poll_req_pid = info->snd_pid; |
542 | 615 | ||
diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h index 3dd4232ae66..c5e42b79a41 100644 --- a/net/nfc/nfc.h +++ b/net/nfc/nfc.h | |||
@@ -55,6 +55,7 @@ int nfc_llcp_register_device(struct nfc_dev *dev); | |||
55 | void nfc_llcp_unregister_device(struct nfc_dev *dev); | 55 | void nfc_llcp_unregister_device(struct nfc_dev *dev); |
56 | int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len); | 56 | int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len); |
57 | u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len); | 57 | u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len); |
58 | int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb); | ||
58 | int __init nfc_llcp_init(void); | 59 | int __init nfc_llcp_init(void); |
59 | void nfc_llcp_exit(void); | 60 | void nfc_llcp_exit(void); |
60 | 61 | ||
@@ -90,6 +91,12 @@ static inline u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *gb_len) | |||
90 | return NULL; | 91 | return NULL; |
91 | } | 92 | } |
92 | 93 | ||
94 | static inline int nfc_llcp_data_received(struct nfc_dev *dev, | ||
95 | struct sk_buff *skb) | ||
96 | { | ||
97 | return 0; | ||
98 | } | ||
99 | |||
93 | static inline int nfc_llcp_init(void) | 100 | static inline int nfc_llcp_init(void) |
94 | { | 101 | { |
95 | return 0; | 102 | return 0; |
@@ -128,6 +135,9 @@ int nfc_genl_dep_link_up_event(struct nfc_dev *dev, u32 target_idx, | |||
128 | u8 comm_mode, u8 rf_mode); | 135 | u8 comm_mode, u8 rf_mode); |
129 | int nfc_genl_dep_link_down_event(struct nfc_dev *dev); | 136 | int nfc_genl_dep_link_down_event(struct nfc_dev *dev); |
130 | 137 | ||
138 | int nfc_genl_tm_activated(struct nfc_dev *dev, u32 protocol); | ||
139 | int nfc_genl_tm_deactivated(struct nfc_dev *dev); | ||
140 | |||
131 | struct nfc_dev *nfc_get_device(unsigned int idx); | 141 | struct nfc_dev *nfc_get_device(unsigned int idx); |
132 | 142 | ||
133 | static inline void nfc_put_device(struct nfc_dev *dev) | 143 | static inline void nfc_put_device(struct nfc_dev *dev) |
@@ -158,7 +168,7 @@ int nfc_dev_up(struct nfc_dev *dev); | |||
158 | 168 | ||
159 | int nfc_dev_down(struct nfc_dev *dev); | 169 | int nfc_dev_down(struct nfc_dev *dev); |
160 | 170 | ||
161 | int nfc_start_poll(struct nfc_dev *dev, u32 protocols); | 171 | int nfc_start_poll(struct nfc_dev *dev, u32 im_protocols, u32 tm_protocols); |
162 | 172 | ||
163 | int nfc_stop_poll(struct nfc_dev *dev); | 173 | int nfc_stop_poll(struct nfc_dev *dev); |
164 | 174 | ||
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 15f347477a9..baf5704740e 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -1389,7 +1389,7 @@ static void reg_set_request_processed(void) | |||
1389 | spin_unlock(®_requests_lock); | 1389 | spin_unlock(®_requests_lock); |
1390 | 1390 | ||
1391 | if (last_request->initiator == NL80211_REGDOM_SET_BY_USER) | 1391 | if (last_request->initiator == NL80211_REGDOM_SET_BY_USER) |
1392 | cancel_delayed_work_sync(®_timeout); | 1392 | cancel_delayed_work(®_timeout); |
1393 | 1393 | ||
1394 | if (need_more_processing) | 1394 | if (need_more_processing) |
1395 | schedule_work(®_work); | 1395 | schedule_work(®_work); |
diff --git a/net/wireless/util.c b/net/wireless/util.c index 8f2d68fc3a4..316cfd00914 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -804,7 +804,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, | |||
804 | ntype == NL80211_IFTYPE_P2P_CLIENT)) | 804 | ntype == NL80211_IFTYPE_P2P_CLIENT)) |
805 | return -EBUSY; | 805 | return -EBUSY; |
806 | 806 | ||
807 | if (ntype != otype) { | 807 | if (ntype != otype && netif_running(dev)) { |
808 | err = cfg80211_can_change_interface(rdev, dev->ieee80211_ptr, | 808 | err = cfg80211_can_change_interface(rdev, dev->ieee80211_ptr, |
809 | ntype); | 809 | ntype); |
810 | if (err) | 810 | if (err) |