diff options
author | John W. Linville <linville@tuxdriver.com> | 2014-03-21 14:02:04 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-03-21 14:02:04 -0400 |
commit | 49c0ca17ee8dd3530f688052d4eb2ae6d3e55119 (patch) | |
tree | 251a4c566723b60505234a18ed864763ad0d0506 | |
parent | a85ae0e97879f51bccd8511668b07d346d98b3eb (diff) | |
parent | 67b3bd4e65f0854aca70e0134d59b1daede49504 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
215 files changed, 13523 insertions, 2758 deletions
diff --git a/Documentation/devicetree/bindings/net/nfc/trf7970a.txt b/Documentation/devicetree/bindings/net/nfc/trf7970a.txt new file mode 100644 index 000000000000..8dd3ef7bc56b --- /dev/null +++ b/Documentation/devicetree/bindings/net/nfc/trf7970a.txt | |||
@@ -0,0 +1,34 @@ | |||
1 | * Texas Instruments TRF7970A RFID/NFC/15693 Transceiver | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: Should be "ti,trf7970a". | ||
5 | - spi-max-frequency: Maximum SPI frequency (<= 2000000). | ||
6 | - interrupt-parent: phandle of parent interrupt handler. | ||
7 | - interrupts: A single interrupt specifier. | ||
8 | - ti,enable-gpios: Two GPIO entries used for 'EN' and 'EN2' pins on the | ||
9 | TRF7970A. | ||
10 | - vin-supply: Regulator for supply voltage to VIN pin | ||
11 | |||
12 | Optional SoC Specific Properties: | ||
13 | - pinctrl-names: Contains only one value - "default". | ||
14 | - pintctrl-0: Specifies the pin control groups used for this controller. | ||
15 | |||
16 | Example (for ARM-based BeagleBone with TRF7970A on SPI1): | ||
17 | |||
18 | &spi1 { | ||
19 | status = "okay"; | ||
20 | |||
21 | nfc@0 { | ||
22 | compatible = "ti,trf7970a"; | ||
23 | reg = <0>; | ||
24 | pinctrl-names = "default"; | ||
25 | pinctrl-0 = <&trf7970a_default>; | ||
26 | spi-max-frequency = <2000000>; | ||
27 | interrupt-parent = <&gpio2>; | ||
28 | interrupts = <14 0>; | ||
29 | ti,enable-gpios = <&gpio2 2 GPIO_ACTIVE_LOW>, | ||
30 | <&gpio2 5 GPIO_ACTIVE_LOW>; | ||
31 | vin-supply = <&ldo3_reg>; | ||
32 | status = "okay"; | ||
33 | }; | ||
34 | }; | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 9109eab722f5..71663f8178ea 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -6117,6 +6117,7 @@ F: include/net/nfc/ | |||
6117 | F: include/uapi/linux/nfc.h | 6117 | F: include/uapi/linux/nfc.h |
6118 | F: drivers/nfc/ | 6118 | F: drivers/nfc/ |
6119 | F: include/linux/platform_data/pn544.h | 6119 | F: include/linux/platform_data/pn544.h |
6120 | F: Documentation/devicetree/bindings/net/nfc/ | ||
6120 | 6121 | ||
6121 | NFS, SUNRPC, AND LOCKD CLIENTS | 6122 | NFS, SUNRPC, AND LOCKD CLIENTS |
6122 | M: Trond Myklebust <trond.myklebust@primarydata.com> | 6123 | M: Trond Myklebust <trond.myklebust@primarydata.com> |
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 4f78a9d39dc8..be571fef185d 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c | |||
@@ -89,6 +89,7 @@ static const struct usb_device_id ath3k_table[] = { | |||
89 | { USB_DEVICE(0x0b05, 0x17d0) }, | 89 | { USB_DEVICE(0x0b05, 0x17d0) }, |
90 | { USB_DEVICE(0x0CF3, 0x0036) }, | 90 | { USB_DEVICE(0x0CF3, 0x0036) }, |
91 | { USB_DEVICE(0x0CF3, 0x3004) }, | 91 | { USB_DEVICE(0x0CF3, 0x3004) }, |
92 | { USB_DEVICE(0x0CF3, 0x3005) }, | ||
92 | { USB_DEVICE(0x0CF3, 0x3008) }, | 93 | { USB_DEVICE(0x0CF3, 0x3008) }, |
93 | { USB_DEVICE(0x0CF3, 0x311D) }, | 94 | { USB_DEVICE(0x0CF3, 0x311D) }, |
94 | { USB_DEVICE(0x0CF3, 0x311E) }, | 95 | { USB_DEVICE(0x0CF3, 0x311E) }, |
@@ -137,6 +138,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = { | |||
137 | { USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 }, | 138 | { USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 }, |
138 | { USB_DEVICE(0x0CF3, 0x0036), .driver_info = BTUSB_ATH3012 }, | 139 | { USB_DEVICE(0x0CF3, 0x0036), .driver_info = BTUSB_ATH3012 }, |
139 | { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, | 140 | { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, |
141 | { USB_DEVICE(0x0cf3, 0x3005), .driver_info = BTUSB_ATH3012 }, | ||
140 | { USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 }, | 142 | { USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 }, |
141 | { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 }, | 143 | { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 }, |
142 | { USB_DEVICE(0x0cf3, 0x311E), .driver_info = BTUSB_ATH3012 }, | 144 | { USB_DEVICE(0x0cf3, 0x311E), .driver_info = BTUSB_ATH3012 }, |
@@ -180,10 +182,9 @@ static int ath3k_load_firmware(struct usb_device *udev, | |||
180 | } | 182 | } |
181 | 183 | ||
182 | memcpy(send_buf, firmware->data, 20); | 184 | memcpy(send_buf, firmware->data, 20); |
183 | if ((err = usb_control_msg(udev, pipe, | 185 | err = usb_control_msg(udev, pipe, USB_REQ_DFU_DNLOAD, USB_TYPE_VENDOR, |
184 | USB_REQ_DFU_DNLOAD, | 186 | 0, 0, send_buf, 20, USB_CTRL_SET_TIMEOUT); |
185 | USB_TYPE_VENDOR, 0, 0, | 187 | if (err < 0) { |
186 | send_buf, 20, USB_CTRL_SET_TIMEOUT)) < 0) { | ||
187 | BT_ERR("Can't change to loading configuration err"); | 188 | BT_ERR("Can't change to loading configuration err"); |
188 | goto error; | 189 | goto error; |
189 | } | 190 | } |
@@ -366,7 +367,7 @@ static int ath3k_load_patch(struct usb_device *udev) | |||
366 | } | 367 | } |
367 | 368 | ||
368 | snprintf(filename, ATH3K_NAME_LEN, "ar3k/AthrBT_0x%08x.dfu", | 369 | snprintf(filename, ATH3K_NAME_LEN, "ar3k/AthrBT_0x%08x.dfu", |
369 | fw_version.rom_version); | 370 | le32_to_cpu(fw_version.rom_version)); |
370 | 371 | ||
371 | ret = request_firmware(&firmware, filename, &udev->dev); | 372 | ret = request_firmware(&firmware, filename, &udev->dev); |
372 | if (ret < 0) { | 373 | if (ret < 0) { |
@@ -428,7 +429,7 @@ static int ath3k_load_syscfg(struct usb_device *udev) | |||
428 | } | 429 | } |
429 | 430 | ||
430 | snprintf(filename, ATH3K_NAME_LEN, "ar3k/ramps_0x%08x_%d%s", | 431 | snprintf(filename, ATH3K_NAME_LEN, "ar3k/ramps_0x%08x_%d%s", |
431 | fw_version.rom_version, clk_value, ".dfu"); | 432 | le32_to_cpu(fw_version.rom_version), clk_value, ".dfu"); |
432 | 433 | ||
433 | ret = request_firmware(&firmware, filename, &udev->dev); | 434 | ret = request_firmware(&firmware, filename, &udev->dev); |
434 | if (ret < 0) { | 435 | if (ret < 0) { |
diff --git a/drivers/bluetooth/bfusb.c b/drivers/bluetooth/bfusb.c index 31386998c9a7..b2e7e94a6771 100644 --- a/drivers/bluetooth/bfusb.c +++ b/drivers/bluetooth/bfusb.c | |||
@@ -131,8 +131,11 @@ static int bfusb_send_bulk(struct bfusb_data *data, struct sk_buff *skb) | |||
131 | 131 | ||
132 | BT_DBG("bfusb %p skb %p len %d", data, skb, skb->len); | 132 | BT_DBG("bfusb %p skb %p len %d", data, skb, skb->len); |
133 | 133 | ||
134 | if (!urb && !(urb = usb_alloc_urb(0, GFP_ATOMIC))) | 134 | if (!urb) { |
135 | return -ENOMEM; | 135 | urb = usb_alloc_urb(0, GFP_ATOMIC); |
136 | if (!urb) | ||
137 | return -ENOMEM; | ||
138 | } | ||
136 | 139 | ||
137 | pipe = usb_sndbulkpipe(data->udev, data->bulk_out_ep); | 140 | pipe = usb_sndbulkpipe(data->udev, data->bulk_out_ep); |
138 | 141 | ||
@@ -218,8 +221,11 @@ static int bfusb_rx_submit(struct bfusb_data *data, struct urb *urb) | |||
218 | 221 | ||
219 | BT_DBG("bfusb %p urb %p", data, urb); | 222 | BT_DBG("bfusb %p urb %p", data, urb); |
220 | 223 | ||
221 | if (!urb && !(urb = usb_alloc_urb(0, GFP_ATOMIC))) | 224 | if (!urb) { |
222 | return -ENOMEM; | 225 | urb = usb_alloc_urb(0, GFP_ATOMIC); |
226 | if (!urb) | ||
227 | return -ENOMEM; | ||
228 | } | ||
223 | 229 | ||
224 | skb = bt_skb_alloc(size, GFP_ATOMIC); | 230 | skb = bt_skb_alloc(size, GFP_ATOMIC); |
225 | if (!skb) { | 231 | if (!skb) { |
diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index 57427de864a6..a9a989e5ee88 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c | |||
@@ -257,7 +257,8 @@ static void bluecard_write_wakeup(bluecard_info_t *info) | |||
257 | ready_bit = XMIT_BUF_ONE_READY; | 257 | ready_bit = XMIT_BUF_ONE_READY; |
258 | } | 258 | } |
259 | 259 | ||
260 | if (!(skb = skb_dequeue(&(info->txq)))) | 260 | skb = skb_dequeue(&(info->txq)); |
261 | if (!skb) | ||
261 | break; | 262 | break; |
262 | 263 | ||
263 | if (bt_cb(skb)->pkt_type & 0x80) { | 264 | if (bt_cb(skb)->pkt_type & 0x80) { |
@@ -391,7 +392,8 @@ static void bluecard_receive(bluecard_info_t *info, unsigned int offset) | |||
391 | if (info->rx_skb == NULL) { | 392 | if (info->rx_skb == NULL) { |
392 | info->rx_state = RECV_WAIT_PACKET_TYPE; | 393 | info->rx_state = RECV_WAIT_PACKET_TYPE; |
393 | info->rx_count = 0; | 394 | info->rx_count = 0; |
394 | if (!(info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) { | 395 | info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC); |
396 | if (!info->rx_skb) { | ||
395 | BT_ERR("Can't allocate mem for new packet"); | 397 | BT_ERR("Can't allocate mem for new packet"); |
396 | return; | 398 | return; |
397 | } | 399 | } |
@@ -566,7 +568,8 @@ static int bluecard_hci_set_baud_rate(struct hci_dev *hdev, int baud) | |||
566 | /* Ericsson baud rate command */ | 568 | /* Ericsson baud rate command */ |
567 | unsigned char cmd[] = { HCI_COMMAND_PKT, 0x09, 0xfc, 0x01, 0x03 }; | 569 | unsigned char cmd[] = { HCI_COMMAND_PKT, 0x09, 0xfc, 0x01, 0x03 }; |
568 | 570 | ||
569 | if (!(skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) { | 571 | skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC); |
572 | if (!skb) { | ||
570 | BT_ERR("Can't allocate mem for new packet"); | 573 | BT_ERR("Can't allocate mem for new packet"); |
571 | return -1; | 574 | return -1; |
572 | } | 575 | } |
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index 73d87994d028..1d82721cf9c6 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c | |||
@@ -193,8 +193,8 @@ static void bt3c_write_wakeup(bt3c_info_t *info) | |||
193 | if (!pcmcia_dev_present(info->p_dev)) | 193 | if (!pcmcia_dev_present(info->p_dev)) |
194 | break; | 194 | break; |
195 | 195 | ||
196 | 196 | skb = skb_dequeue(&(info->txq)); | |
197 | if (!(skb = skb_dequeue(&(info->txq)))) { | 197 | if (!skb) { |
198 | clear_bit(XMIT_SENDING, &(info->tx_state)); | 198 | clear_bit(XMIT_SENDING, &(info->tx_state)); |
199 | break; | 199 | break; |
200 | } | 200 | } |
@@ -238,7 +238,8 @@ static void bt3c_receive(bt3c_info_t *info) | |||
238 | if (info->rx_skb == NULL) { | 238 | if (info->rx_skb == NULL) { |
239 | info->rx_state = RECV_WAIT_PACKET_TYPE; | 239 | info->rx_state = RECV_WAIT_PACKET_TYPE; |
240 | info->rx_count = 0; | 240 | info->rx_count = 0; |
241 | if (!(info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) { | 241 | info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC); |
242 | if (!info->rx_skb) { | ||
242 | BT_ERR("Can't allocate mem for new packet"); | 243 | BT_ERR("Can't allocate mem for new packet"); |
243 | return; | 244 | return; |
244 | } | 245 | } |
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c index a03ecc22a561..fb948f02eda5 100644 --- a/drivers/bluetooth/btuart_cs.c +++ b/drivers/bluetooth/btuart_cs.c | |||
@@ -149,7 +149,8 @@ static void btuart_write_wakeup(btuart_info_t *info) | |||
149 | if (!pcmcia_dev_present(info->p_dev)) | 149 | if (!pcmcia_dev_present(info->p_dev)) |
150 | return; | 150 | return; |
151 | 151 | ||
152 | if (!(skb = skb_dequeue(&(info->txq)))) | 152 | skb = skb_dequeue(&(info->txq)); |
153 | if (!skb) | ||
153 | break; | 154 | break; |
154 | 155 | ||
155 | /* Send frame */ | 156 | /* Send frame */ |
@@ -190,7 +191,8 @@ static void btuart_receive(btuart_info_t *info) | |||
190 | if (info->rx_skb == NULL) { | 191 | if (info->rx_skb == NULL) { |
191 | info->rx_state = RECV_WAIT_PACKET_TYPE; | 192 | info->rx_state = RECV_WAIT_PACKET_TYPE; |
192 | info->rx_count = 0; | 193 | info->rx_count = 0; |
193 | if (!(info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) { | 194 | info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC); |
195 | if (!info->rx_skb) { | ||
194 | BT_ERR("Can't allocate mem for new packet"); | 196 | BT_ERR("Can't allocate mem for new packet"); |
195 | return; | 197 | return; |
196 | } | 198 | } |
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 199b9d42489c..f338b0c5a8de 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c | |||
@@ -159,6 +159,7 @@ static const struct usb_device_id blacklist_table[] = { | |||
159 | { USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 }, | 159 | { USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 }, |
160 | { USB_DEVICE(0x0cf3, 0x0036), .driver_info = BTUSB_ATH3012 }, | 160 | { USB_DEVICE(0x0cf3, 0x0036), .driver_info = BTUSB_ATH3012 }, |
161 | { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, | 161 | { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, |
162 | { USB_DEVICE(0x0cf3, 0x3005), .driver_info = BTUSB_ATH3012 }, | ||
162 | { USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 }, | 163 | { USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 }, |
163 | { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 }, | 164 | { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 }, |
164 | { USB_DEVICE(0x0cf3, 0x311e), .driver_info = BTUSB_ATH3012 }, | 165 | { USB_DEVICE(0x0cf3, 0x311e), .driver_info = BTUSB_ATH3012 }, |
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index 52eed1f3565d..2bd8fad17206 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c | |||
@@ -153,7 +153,8 @@ static void dtl1_write_wakeup(dtl1_info_t *info) | |||
153 | if (!pcmcia_dev_present(info->p_dev)) | 153 | if (!pcmcia_dev_present(info->p_dev)) |
154 | return; | 154 | return; |
155 | 155 | ||
156 | if (!(skb = skb_dequeue(&(info->txq)))) | 156 | skb = skb_dequeue(&(info->txq)); |
157 | if (!skb) | ||
157 | break; | 158 | break; |
158 | 159 | ||
159 | /* Send frame */ | 160 | /* Send frame */ |
@@ -215,13 +216,15 @@ static void dtl1_receive(dtl1_info_t *info) | |||
215 | info->hdev->stat.byte_rx++; | 216 | info->hdev->stat.byte_rx++; |
216 | 217 | ||
217 | /* Allocate packet */ | 218 | /* Allocate packet */ |
218 | if (info->rx_skb == NULL) | 219 | if (info->rx_skb == NULL) { |
219 | if (!(info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) { | 220 | info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC); |
221 | if (!info->rx_skb) { | ||
220 | BT_ERR("Can't allocate mem for new packet"); | 222 | BT_ERR("Can't allocate mem for new packet"); |
221 | info->rx_state = RECV_WAIT_NSH; | 223 | info->rx_state = RECV_WAIT_NSH; |
222 | info->rx_count = NSHL; | 224 | info->rx_count = NSHL; |
223 | return; | 225 | return; |
224 | } | 226 | } |
227 | } | ||
225 | 228 | ||
226 | *skb_put(info->rx_skb, 1) = inb(iobase + UART_RX); | 229 | *skb_put(info->rx_skb, 1) = inb(iobase + UART_RX); |
227 | nsh = (nsh_t *)info->rx_skb->data; | 230 | nsh = (nsh_t *)info->rx_skb->data; |
diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c index 0bc87f7abd95..21cc45b34f13 100644 --- a/drivers/bluetooth/hci_bcsp.c +++ b/drivers/bluetooth/hci_bcsp.c | |||
@@ -291,7 +291,8 @@ static struct sk_buff *bcsp_dequeue(struct hci_uart *hu) | |||
291 | /* First of all, check for unreliable messages in the queue, | 291 | /* First of all, check for unreliable messages in the queue, |
292 | since they have priority */ | 292 | since they have priority */ |
293 | 293 | ||
294 | if ((skb = skb_dequeue(&bcsp->unrel)) != NULL) { | 294 | skb = skb_dequeue(&bcsp->unrel); |
295 | if (skb != NULL) { | ||
295 | struct sk_buff *nskb = bcsp_prepare_pkt(bcsp, skb->data, skb->len, bt_cb(skb)->pkt_type); | 296 | struct sk_buff *nskb = bcsp_prepare_pkt(bcsp, skb->data, skb->len, bt_cb(skb)->pkt_type); |
296 | if (nskb) { | 297 | if (nskb) { |
297 | kfree_skb(skb); | 298 | kfree_skb(skb); |
@@ -308,16 +309,20 @@ static struct sk_buff *bcsp_dequeue(struct hci_uart *hu) | |||
308 | 309 | ||
309 | spin_lock_irqsave_nested(&bcsp->unack.lock, flags, SINGLE_DEPTH_NESTING); | 310 | spin_lock_irqsave_nested(&bcsp->unack.lock, flags, SINGLE_DEPTH_NESTING); |
310 | 311 | ||
311 | if (bcsp->unack.qlen < BCSP_TXWINSIZE && (skb = skb_dequeue(&bcsp->rel)) != NULL) { | 312 | if (bcsp->unack.qlen < BCSP_TXWINSIZE) { |
312 | struct sk_buff *nskb = bcsp_prepare_pkt(bcsp, skb->data, skb->len, bt_cb(skb)->pkt_type); | 313 | skb = skb_dequeue(&bcsp->rel); |
313 | if (nskb) { | 314 | if (skb != NULL) { |
314 | __skb_queue_tail(&bcsp->unack, skb); | 315 | struct sk_buff *nskb = bcsp_prepare_pkt(bcsp, skb->data, skb->len, |
315 | mod_timer(&bcsp->tbcsp, jiffies + HZ / 4); | 316 | bt_cb(skb)->pkt_type); |
316 | spin_unlock_irqrestore(&bcsp->unack.lock, flags); | 317 | if (nskb) { |
317 | return nskb; | 318 | __skb_queue_tail(&bcsp->unack, skb); |
318 | } else { | 319 | mod_timer(&bcsp->tbcsp, jiffies + HZ / 4); |
319 | skb_queue_head(&bcsp->rel, skb); | 320 | spin_unlock_irqrestore(&bcsp->unack.lock, flags); |
320 | BT_ERR("Could not dequeue pkt because alloc_skb failed"); | 321 | return nskb; |
322 | } else { | ||
323 | skb_queue_head(&bcsp->rel, skb); | ||
324 | BT_ERR("Could not dequeue pkt because alloc_skb failed"); | ||
325 | } | ||
321 | } | 326 | } |
322 | } | 327 | } |
323 | 328 | ||
@@ -715,6 +720,9 @@ static int bcsp_open(struct hci_uart *hu) | |||
715 | static int bcsp_close(struct hci_uart *hu) | 720 | static int bcsp_close(struct hci_uart *hu) |
716 | { | 721 | { |
717 | struct bcsp_struct *bcsp = hu->priv; | 722 | struct bcsp_struct *bcsp = hu->priv; |
723 | |||
724 | del_timer_sync(&bcsp->tbcsp); | ||
725 | |||
718 | hu->priv = NULL; | 726 | hu->priv = NULL; |
719 | 727 | ||
720 | BT_DBG("hu %p", hu); | 728 | BT_DBG("hu %p", hu); |
@@ -722,7 +730,6 @@ static int bcsp_close(struct hci_uart *hu) | |||
722 | skb_queue_purge(&bcsp->unack); | 730 | skb_queue_purge(&bcsp->unack); |
723 | skb_queue_purge(&bcsp->rel); | 731 | skb_queue_purge(&bcsp->rel); |
724 | skb_queue_purge(&bcsp->unrel); | 732 | skb_queue_purge(&bcsp->unrel); |
725 | del_timer(&bcsp->tbcsp); | ||
726 | 733 | ||
727 | kfree(bcsp); | 734 | kfree(bcsp); |
728 | return 0; | 735 | return 0; |
diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c index f6f497450560..04680ead9275 100644 --- a/drivers/bluetooth/hci_h5.c +++ b/drivers/bluetooth/hci_h5.c | |||
@@ -206,12 +206,12 @@ static int h5_close(struct hci_uart *hu) | |||
206 | { | 206 | { |
207 | struct h5 *h5 = hu->priv; | 207 | struct h5 *h5 = hu->priv; |
208 | 208 | ||
209 | del_timer_sync(&h5->timer); | ||
210 | |||
209 | skb_queue_purge(&h5->unack); | 211 | skb_queue_purge(&h5->unack); |
210 | skb_queue_purge(&h5->rel); | 212 | skb_queue_purge(&h5->rel); |
211 | skb_queue_purge(&h5->unrel); | 213 | skb_queue_purge(&h5->unrel); |
212 | 214 | ||
213 | del_timer(&h5->timer); | ||
214 | |||
215 | kfree(h5); | 215 | kfree(h5); |
216 | 216 | ||
217 | return 0; | 217 | return 0; |
@@ -673,7 +673,8 @@ static struct sk_buff *h5_dequeue(struct hci_uart *hu) | |||
673 | return h5_prepare_pkt(hu, HCI_3WIRE_LINK_PKT, wakeup_req, 2); | 673 | return h5_prepare_pkt(hu, HCI_3WIRE_LINK_PKT, wakeup_req, 2); |
674 | } | 674 | } |
675 | 675 | ||
676 | if ((skb = skb_dequeue(&h5->unrel)) != NULL) { | 676 | skb = skb_dequeue(&h5->unrel); |
677 | if (skb != NULL) { | ||
677 | nskb = h5_prepare_pkt(hu, bt_cb(skb)->pkt_type, | 678 | nskb = h5_prepare_pkt(hu, bt_cb(skb)->pkt_type, |
678 | skb->data, skb->len); | 679 | skb->data, skb->len); |
679 | if (nskb) { | 680 | if (nskb) { |
@@ -690,7 +691,8 @@ static struct sk_buff *h5_dequeue(struct hci_uart *hu) | |||
690 | if (h5->unack.qlen >= h5->tx_win) | 691 | if (h5->unack.qlen >= h5->tx_win) |
691 | goto unlock; | 692 | goto unlock; |
692 | 693 | ||
693 | if ((skb = skb_dequeue(&h5->rel)) != NULL) { | 694 | skb = skb_dequeue(&h5->rel); |
695 | if (skb != NULL) { | ||
694 | nskb = h5_prepare_pkt(hu, bt_cb(skb)->pkt_type, | 696 | nskb = h5_prepare_pkt(hu, bt_cb(skb)->pkt_type, |
695 | skb->data, skb->len); | 697 | skb->data, skb->len); |
696 | if (nskb) { | 698 | if (nskb) { |
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index 6e06f6f69152..f1fbf4f1e5be 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c | |||
@@ -271,7 +271,8 @@ static int hci_uart_tty_open(struct tty_struct *tty) | |||
271 | if (tty->ops->write == NULL) | 271 | if (tty->ops->write == NULL) |
272 | return -EOPNOTSUPP; | 272 | return -EOPNOTSUPP; |
273 | 273 | ||
274 | if (!(hu = kzalloc(sizeof(struct hci_uart), GFP_KERNEL))) { | 274 | hu = kzalloc(sizeof(struct hci_uart), GFP_KERNEL); |
275 | if (!hu) { | ||
275 | BT_ERR("Can't allocate control structure"); | 276 | BT_ERR("Can't allocate control structure"); |
276 | return -ENFILE; | 277 | return -ENFILE; |
277 | } | 278 | } |
@@ -569,7 +570,8 @@ static int __init hci_uart_init(void) | |||
569 | hci_uart_ldisc.write_wakeup = hci_uart_tty_wakeup; | 570 | hci_uart_ldisc.write_wakeup = hci_uart_tty_wakeup; |
570 | hci_uart_ldisc.owner = THIS_MODULE; | 571 | hci_uart_ldisc.owner = THIS_MODULE; |
571 | 572 | ||
572 | if ((err = tty_register_ldisc(N_HCI, &hci_uart_ldisc))) { | 573 | err = tty_register_ldisc(N_HCI, &hci_uart_ldisc); |
574 | if (err) { | ||
573 | BT_ERR("HCI line discipline registration failed. (%d)", err); | 575 | BT_ERR("HCI line discipline registration failed. (%d)", err); |
574 | return err; | 576 | return err; |
575 | } | 577 | } |
@@ -614,7 +616,8 @@ static void __exit hci_uart_exit(void) | |||
614 | #endif | 616 | #endif |
615 | 617 | ||
616 | /* Release tty registration of line discipline */ | 618 | /* Release tty registration of line discipline */ |
617 | if ((err = tty_unregister_ldisc(N_HCI))) | 619 | err = tty_unregister_ldisc(N_HCI); |
620 | if (err) | ||
618 | BT_ERR("Can't unregister HCI line discipline (%d)", err); | 621 | BT_ERR("Can't unregister HCI line discipline (%d)", err); |
619 | } | 622 | } |
620 | 623 | ||
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index d1fab435f5a3..b2137e8f7ca6 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig | |||
@@ -116,7 +116,7 @@ config AT76C50X_USB | |||
116 | 116 | ||
117 | config AIRO_CS | 117 | config AIRO_CS |
118 | tristate "Cisco/Aironet 34X/35X/4500/4800 PCMCIA cards" | 118 | tristate "Cisco/Aironet 34X/35X/4500/4800 PCMCIA cards" |
119 | depends on PCMCIA && (BROKEN || !M32R) | 119 | depends on CFG80211 && PCMCIA && (BROKEN || !M32R) |
120 | select WIRELESS_EXT | 120 | select WIRELESS_EXT |
121 | select WEXT_SPY | 121 | select WEXT_SPY |
122 | select WEXT_PRIV | 122 | select WEXT_PRIV |
@@ -281,5 +281,6 @@ source "drivers/net/wireless/ti/Kconfig" | |||
281 | source "drivers/net/wireless/zd1211rw/Kconfig" | 281 | source "drivers/net/wireless/zd1211rw/Kconfig" |
282 | source "drivers/net/wireless/mwifiex/Kconfig" | 282 | source "drivers/net/wireless/mwifiex/Kconfig" |
283 | source "drivers/net/wireless/cw1200/Kconfig" | 283 | source "drivers/net/wireless/cw1200/Kconfig" |
284 | source "drivers/net/wireless/rsi/Kconfig" | ||
284 | 285 | ||
285 | endif # WLAN | 286 | endif # WLAN |
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index 0fab227025be..0c8891686718 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile | |||
@@ -59,3 +59,4 @@ obj-$(CONFIG_BRCMFMAC) += brcm80211/ | |||
59 | obj-$(CONFIG_BRCMSMAC) += brcm80211/ | 59 | obj-$(CONFIG_BRCMSMAC) += brcm80211/ |
60 | 60 | ||
61 | obj-$(CONFIG_CW1200) += cw1200/ | 61 | obj-$(CONFIG_CW1200) += cw1200/ |
62 | obj-$(CONFIG_RSI_91X) += rsi/ | ||
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index d239acc26125..a889fd66fc63 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h | |||
@@ -56,6 +56,15 @@ enum ath_device_state { | |||
56 | ATH_HW_INITIALIZED, | 56 | ATH_HW_INITIALIZED, |
57 | }; | 57 | }; |
58 | 58 | ||
59 | enum ath_op_flags { | ||
60 | ATH_OP_INVALID, | ||
61 | ATH_OP_BEACONS, | ||
62 | ATH_OP_ANI_RUN, | ||
63 | ATH_OP_PRIM_STA_VIF, | ||
64 | ATH_OP_HW_RESET, | ||
65 | ATH_OP_SCANNING, | ||
66 | }; | ||
67 | |||
59 | enum ath_bus_type { | 68 | enum ath_bus_type { |
60 | ATH_PCI, | 69 | ATH_PCI, |
61 | ATH_AHB, | 70 | ATH_AHB, |
@@ -130,6 +139,7 @@ struct ath_common { | |||
130 | struct ieee80211_hw *hw; | 139 | struct ieee80211_hw *hw; |
131 | int debug_mask; | 140 | int debug_mask; |
132 | enum ath_device_state state; | 141 | enum ath_device_state state; |
142 | unsigned long op_flags; | ||
133 | 143 | ||
134 | struct ath_ani ani; | 144 | struct ath_ani ani; |
135 | 145 | ||
diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index d44d618b05f9..a79499c82350 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c | |||
@@ -266,12 +266,12 @@ static inline void ath10k_ce_engine_int_status_clear(struct ath10k *ar, | |||
266 | * ath10k_ce_sendlist_send. | 266 | * ath10k_ce_sendlist_send. |
267 | * The caller takes responsibility for any needed locking. | 267 | * The caller takes responsibility for any needed locking. |
268 | */ | 268 | */ |
269 | static int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state, | 269 | int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state, |
270 | void *per_transfer_context, | 270 | void *per_transfer_context, |
271 | u32 buffer, | 271 | u32 buffer, |
272 | unsigned int nbytes, | 272 | unsigned int nbytes, |
273 | unsigned int transfer_id, | 273 | unsigned int transfer_id, |
274 | unsigned int flags) | 274 | unsigned int flags) |
275 | { | 275 | { |
276 | struct ath10k *ar = ce_state->ar; | 276 | struct ath10k *ar = ce_state->ar; |
277 | struct ath10k_ce_ring *src_ring = ce_state->src_ring; | 277 | struct ath10k_ce_ring *src_ring = ce_state->src_ring; |
@@ -1067,9 +1067,9 @@ struct ath10k_ce_pipe *ath10k_ce_init(struct ath10k *ar, | |||
1067 | * | 1067 | * |
1068 | * For the lack of a better place do the check here. | 1068 | * For the lack of a better place do the check here. |
1069 | */ | 1069 | */ |
1070 | BUILD_BUG_ON(TARGET_NUM_MSDU_DESC > | 1070 | BUILD_BUG_ON(2*TARGET_NUM_MSDU_DESC > |
1071 | (CE_HTT_H2T_MSG_SRC_NENTRIES - 1)); | 1071 | (CE_HTT_H2T_MSG_SRC_NENTRIES - 1)); |
1072 | BUILD_BUG_ON(TARGET_10X_NUM_MSDU_DESC > | 1072 | BUILD_BUG_ON(2*TARGET_10X_NUM_MSDU_DESC > |
1073 | (CE_HTT_H2T_MSG_SRC_NENTRIES - 1)); | 1073 | (CE_HTT_H2T_MSG_SRC_NENTRIES - 1)); |
1074 | 1074 | ||
1075 | ret = ath10k_pci_wake(ar); | 1075 | ret = ath10k_pci_wake(ar); |
diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h index 67dbde6a5c74..8eb7f99ed992 100644 --- a/drivers/net/wireless/ath/ath10k/ce.h +++ b/drivers/net/wireless/ath/ath10k/ce.h | |||
@@ -23,7 +23,7 @@ | |||
23 | 23 | ||
24 | /* Maximum number of Copy Engine's supported */ | 24 | /* Maximum number of Copy Engine's supported */ |
25 | #define CE_COUNT_MAX 8 | 25 | #define CE_COUNT_MAX 8 |
26 | #define CE_HTT_H2T_MSG_SRC_NENTRIES 2048 | 26 | #define CE_HTT_H2T_MSG_SRC_NENTRIES 4096 |
27 | 27 | ||
28 | /* Descriptor rings must be aligned to this boundary */ | 28 | /* Descriptor rings must be aligned to this boundary */ |
29 | #define CE_DESC_RING_ALIGN 8 | 29 | #define CE_DESC_RING_ALIGN 8 |
@@ -152,6 +152,13 @@ int ath10k_ce_send(struct ath10k_ce_pipe *ce_state, | |||
152 | unsigned int transfer_id, | 152 | unsigned int transfer_id, |
153 | unsigned int flags); | 153 | unsigned int flags); |
154 | 154 | ||
155 | int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state, | ||
156 | void *per_transfer_context, | ||
157 | u32 buffer, | ||
158 | unsigned int nbytes, | ||
159 | unsigned int transfer_id, | ||
160 | unsigned int flags); | ||
161 | |||
155 | void ath10k_ce_send_cb_register(struct ath10k_ce_pipe *ce_state, | 162 | void ath10k_ce_send_cb_register(struct ath10k_ce_pipe *ce_state, |
156 | void (*send_cb)(struct ath10k_ce_pipe *), | 163 | void (*send_cb)(struct ath10k_ce_pipe *), |
157 | int disable_interrupts); | 164 | int disable_interrupts); |
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 1fc26fe057e8..0e71979d837c 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h | |||
@@ -62,16 +62,13 @@ struct ath10k; | |||
62 | 62 | ||
63 | struct ath10k_skb_cb { | 63 | struct ath10k_skb_cb { |
64 | dma_addr_t paddr; | 64 | dma_addr_t paddr; |
65 | bool is_mapped; | ||
66 | bool is_aborted; | ||
67 | u8 vdev_id; | 65 | u8 vdev_id; |
68 | 66 | ||
69 | struct { | 67 | struct { |
70 | u8 tid; | 68 | u8 tid; |
71 | bool is_offchan; | 69 | bool is_offchan; |
72 | 70 | struct ath10k_htt_txbuf *txbuf; | |
73 | u8 frag_len; | 71 | u32 txbuf_paddr; |
74 | u8 pad_len; | ||
75 | } __packed htt; | 72 | } __packed htt; |
76 | 73 | ||
77 | struct { | 74 | struct { |
@@ -87,32 +84,6 @@ static inline struct ath10k_skb_cb *ATH10K_SKB_CB(struct sk_buff *skb) | |||
87 | return (struct ath10k_skb_cb *)&IEEE80211_SKB_CB(skb)->driver_data; | 84 | return (struct ath10k_skb_cb *)&IEEE80211_SKB_CB(skb)->driver_data; |
88 | } | 85 | } |
89 | 86 | ||
90 | static inline int ath10k_skb_map(struct device *dev, struct sk_buff *skb) | ||
91 | { | ||
92 | if (ATH10K_SKB_CB(skb)->is_mapped) | ||
93 | return -EINVAL; | ||
94 | |||
95 | ATH10K_SKB_CB(skb)->paddr = dma_map_single(dev, skb->data, skb->len, | ||
96 | DMA_TO_DEVICE); | ||
97 | |||
98 | if (unlikely(dma_mapping_error(dev, ATH10K_SKB_CB(skb)->paddr))) | ||
99 | return -EIO; | ||
100 | |||
101 | ATH10K_SKB_CB(skb)->is_mapped = true; | ||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | static inline int ath10k_skb_unmap(struct device *dev, struct sk_buff *skb) | ||
106 | { | ||
107 | if (!ATH10K_SKB_CB(skb)->is_mapped) | ||
108 | return -EINVAL; | ||
109 | |||
110 | dma_unmap_single(dev, ATH10K_SKB_CB(skb)->paddr, skb->len, | ||
111 | DMA_TO_DEVICE); | ||
112 | ATH10K_SKB_CB(skb)->is_mapped = false; | ||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | static inline u32 host_interest_item_address(u32 item_offset) | 87 | static inline u32 host_interest_item_address(u32 item_offset) |
117 | { | 88 | { |
118 | return QCA988X_HOST_INTEREST_ADDRESS + item_offset; | 89 | return QCA988X_HOST_INTEREST_ADDRESS + item_offset; |
@@ -288,6 +259,7 @@ struct ath10k_vif { | |||
288 | 259 | ||
289 | u8 fixed_rate; | 260 | u8 fixed_rate; |
290 | u8 fixed_nss; | 261 | u8 fixed_nss; |
262 | u8 force_sgi; | ||
291 | }; | 263 | }; |
292 | 264 | ||
293 | struct ath10k_vif_iter { | 265 | struct ath10k_vif_iter { |
diff --git a/drivers/net/wireless/ath/ath10k/hif.h b/drivers/net/wireless/ath/ath10k/hif.h index dcdea68bcc0a..2ac7beacddca 100644 --- a/drivers/net/wireless/ath/ath10k/hif.h +++ b/drivers/net/wireless/ath/ath10k/hif.h | |||
@@ -21,6 +21,14 @@ | |||
21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
22 | #include "core.h" | 22 | #include "core.h" |
23 | 23 | ||
24 | struct ath10k_hif_sg_item { | ||
25 | u16 transfer_id; | ||
26 | void *transfer_context; /* NULL = tx completion callback not called */ | ||
27 | void *vaddr; /* for debugging mostly */ | ||
28 | u32 paddr; | ||
29 | u16 len; | ||
30 | }; | ||
31 | |||
24 | struct ath10k_hif_cb { | 32 | struct ath10k_hif_cb { |
25 | int (*tx_completion)(struct ath10k *ar, | 33 | int (*tx_completion)(struct ath10k *ar, |
26 | struct sk_buff *wbuf, | 34 | struct sk_buff *wbuf, |
@@ -31,11 +39,9 @@ struct ath10k_hif_cb { | |||
31 | }; | 39 | }; |
32 | 40 | ||
33 | struct ath10k_hif_ops { | 41 | struct ath10k_hif_ops { |
34 | /* Send the head of a buffer to HIF for transmission to the target. */ | 42 | /* send a scatter-gather list to the target */ |
35 | int (*send_head)(struct ath10k *ar, u8 pipe_id, | 43 | int (*tx_sg)(struct ath10k *ar, u8 pipe_id, |
36 | unsigned int transfer_id, | 44 | struct ath10k_hif_sg_item *items, int n_items); |
37 | unsigned int nbytes, | ||
38 | struct sk_buff *buf); | ||
39 | 45 | ||
40 | /* | 46 | /* |
41 | * API to handle HIF-specific BMI message exchanges, this API is | 47 | * API to handle HIF-specific BMI message exchanges, this API is |
@@ -86,12 +92,11 @@ struct ath10k_hif_ops { | |||
86 | }; | 92 | }; |
87 | 93 | ||
88 | 94 | ||
89 | static inline int ath10k_hif_send_head(struct ath10k *ar, u8 pipe_id, | 95 | static inline int ath10k_hif_tx_sg(struct ath10k *ar, u8 pipe_id, |
90 | unsigned int transfer_id, | 96 | struct ath10k_hif_sg_item *items, |
91 | unsigned int nbytes, | 97 | int n_items) |
92 | struct sk_buff *buf) | ||
93 | { | 98 | { |
94 | return ar->hif.ops->send_head(ar, pipe_id, transfer_id, nbytes, buf); | 99 | return ar->hif.ops->tx_sg(ar, pipe_id, items, n_items); |
95 | } | 100 | } |
96 | 101 | ||
97 | static inline int ath10k_hif_exchange_bmi_msg(struct ath10k *ar, | 102 | static inline int ath10k_hif_exchange_bmi_msg(struct ath10k *ar, |
diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c index edc57ab505c8..7f1bccd3597f 100644 --- a/drivers/net/wireless/ath/ath10k/htc.c +++ b/drivers/net/wireless/ath/ath10k/htc.c | |||
@@ -63,7 +63,9 @@ static struct sk_buff *ath10k_htc_build_tx_ctrl_skb(void *ar) | |||
63 | static inline void ath10k_htc_restore_tx_skb(struct ath10k_htc *htc, | 63 | static inline void ath10k_htc_restore_tx_skb(struct ath10k_htc *htc, |
64 | struct sk_buff *skb) | 64 | struct sk_buff *skb) |
65 | { | 65 | { |
66 | ath10k_skb_unmap(htc->ar->dev, skb); | 66 | struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb); |
67 | |||
68 | dma_unmap_single(htc->ar->dev, skb_cb->paddr, skb->len, DMA_TO_DEVICE); | ||
67 | skb_pull(skb, sizeof(struct ath10k_htc_hdr)); | 69 | skb_pull(skb, sizeof(struct ath10k_htc_hdr)); |
68 | } | 70 | } |
69 | 71 | ||
@@ -122,6 +124,9 @@ int ath10k_htc_send(struct ath10k_htc *htc, | |||
122 | struct sk_buff *skb) | 124 | struct sk_buff *skb) |
123 | { | 125 | { |
124 | struct ath10k_htc_ep *ep = &htc->endpoint[eid]; | 126 | struct ath10k_htc_ep *ep = &htc->endpoint[eid]; |
127 | struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb); | ||
128 | struct ath10k_hif_sg_item sg_item; | ||
129 | struct device *dev = htc->ar->dev; | ||
125 | int credits = 0; | 130 | int credits = 0; |
126 | int ret; | 131 | int ret; |
127 | 132 | ||
@@ -157,19 +162,25 @@ int ath10k_htc_send(struct ath10k_htc *htc, | |||
157 | 162 | ||
158 | ath10k_htc_prepare_tx_skb(ep, skb); | 163 | ath10k_htc_prepare_tx_skb(ep, skb); |
159 | 164 | ||
160 | ret = ath10k_skb_map(htc->ar->dev, skb); | 165 | skb_cb->paddr = dma_map_single(dev, skb->data, skb->len, DMA_TO_DEVICE); |
166 | ret = dma_mapping_error(dev, skb_cb->paddr); | ||
161 | if (ret) | 167 | if (ret) |
162 | goto err_credits; | 168 | goto err_credits; |
163 | 169 | ||
164 | ret = ath10k_hif_send_head(htc->ar, ep->ul_pipe_id, ep->eid, | 170 | sg_item.transfer_id = ep->eid; |
165 | skb->len, skb); | 171 | sg_item.transfer_context = skb; |
172 | sg_item.vaddr = skb->data; | ||
173 | sg_item.paddr = skb_cb->paddr; | ||
174 | sg_item.len = skb->len; | ||
175 | |||
176 | ret = ath10k_hif_tx_sg(htc->ar, ep->ul_pipe_id, &sg_item, 1); | ||
166 | if (ret) | 177 | if (ret) |
167 | goto err_unmap; | 178 | goto err_unmap; |
168 | 179 | ||
169 | return 0; | 180 | return 0; |
170 | 181 | ||
171 | err_unmap: | 182 | err_unmap: |
172 | ath10k_skb_unmap(htc->ar->dev, skb); | 183 | dma_unmap_single(dev, skb_cb->paddr, skb->len, DMA_TO_DEVICE); |
173 | err_credits: | 184 | err_credits: |
174 | if (ep->tx_credit_flow_enabled) { | 185 | if (ep->tx_credit_flow_enabled) { |
175 | spin_lock_bh(&htc->tx_lock); | 186 | spin_lock_bh(&htc->tx_lock); |
@@ -191,10 +202,8 @@ static int ath10k_htc_tx_completion_handler(struct ath10k *ar, | |||
191 | struct ath10k_htc *htc = &ar->htc; | 202 | struct ath10k_htc *htc = &ar->htc; |
192 | struct ath10k_htc_ep *ep = &htc->endpoint[eid]; | 203 | struct ath10k_htc_ep *ep = &htc->endpoint[eid]; |
193 | 204 | ||
194 | if (!skb) { | 205 | if (WARN_ON_ONCE(!skb)) |
195 | ath10k_warn("invalid sk_buff completion - NULL pointer. firmware crashed?\n"); | ||
196 | return 0; | 206 | return 0; |
197 | } | ||
198 | 207 | ||
199 | ath10k_htc_notify_tx_completion(ep, skb); | 208 | ath10k_htc_notify_tx_completion(ep, skb); |
200 | /* the skb now belongs to the completion handler */ | 209 | /* the skb now belongs to the completion handler */ |
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index b93ae355bc08..654867fc1ae7 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h | |||
@@ -20,6 +20,7 @@ | |||
20 | 20 | ||
21 | #include <linux/bug.h> | 21 | #include <linux/bug.h> |
22 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
23 | #include <linux/dmapool.h> | ||
23 | 24 | ||
24 | #include "htc.h" | 25 | #include "htc.h" |
25 | #include "rx_desc.h" | 26 | #include "rx_desc.h" |
@@ -1181,11 +1182,20 @@ struct htt_rx_info { | |||
1181 | u32 info1; | 1182 | u32 info1; |
1182 | u32 info2; | 1183 | u32 info2; |
1183 | } rate; | 1184 | } rate; |
1185 | |||
1186 | u32 tsf; | ||
1184 | bool fcs_err; | 1187 | bool fcs_err; |
1185 | bool amsdu_more; | 1188 | bool amsdu_more; |
1186 | bool mic_err; | 1189 | bool mic_err; |
1187 | }; | 1190 | }; |
1188 | 1191 | ||
1192 | struct ath10k_htt_txbuf { | ||
1193 | struct htt_data_tx_desc_frag frags[2]; | ||
1194 | struct ath10k_htc_hdr htc_hdr; | ||
1195 | struct htt_cmd_hdr cmd_hdr; | ||
1196 | struct htt_data_tx_desc cmd_tx; | ||
1197 | } __packed; | ||
1198 | |||
1189 | struct ath10k_htt { | 1199 | struct ath10k_htt { |
1190 | struct ath10k *ar; | 1200 | struct ath10k *ar; |
1191 | enum ath10k_htc_ep_id eid; | 1201 | enum ath10k_htc_ep_id eid; |
@@ -1267,11 +1277,18 @@ struct ath10k_htt { | |||
1267 | struct sk_buff **pending_tx; | 1277 | struct sk_buff **pending_tx; |
1268 | unsigned long *used_msdu_ids; /* bitmap */ | 1278 | unsigned long *used_msdu_ids; /* bitmap */ |
1269 | wait_queue_head_t empty_tx_wq; | 1279 | wait_queue_head_t empty_tx_wq; |
1280 | struct dma_pool *tx_pool; | ||
1270 | 1281 | ||
1271 | /* set if host-fw communication goes haywire | 1282 | /* set if host-fw communication goes haywire |
1272 | * used to avoid further failures */ | 1283 | * used to avoid further failures */ |
1273 | bool rx_confused; | 1284 | bool rx_confused; |
1274 | struct tasklet_struct rx_replenish_task; | 1285 | struct tasklet_struct rx_replenish_task; |
1286 | |||
1287 | /* This is used to group tx/rx completions separately and process them | ||
1288 | * in batches to reduce cache stalls */ | ||
1289 | struct tasklet_struct txrx_compl_task; | ||
1290 | struct sk_buff_head tx_compl_q; | ||
1291 | struct sk_buff_head rx_compl_q; | ||
1275 | }; | 1292 | }; |
1276 | 1293 | ||
1277 | #define RX_HTT_HDR_STATUS_LEN 64 | 1294 | #define RX_HTT_HDR_STATUS_LEN 64 |
@@ -1343,4 +1360,5 @@ int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt); | |||
1343 | void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id); | 1360 | void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id); |
1344 | int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *); | 1361 | int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *); |
1345 | int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *); | 1362 | int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *); |
1363 | |||
1346 | #endif | 1364 | #endif |
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 4767c24bf819..cdcbe2de95f9 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c | |||
@@ -43,7 +43,7 @@ | |||
43 | 43 | ||
44 | 44 | ||
45 | static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb); | 45 | static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb); |
46 | 46 | static void ath10k_htt_txrx_compl_task(unsigned long ptr); | |
47 | 47 | ||
48 | static int ath10k_htt_rx_ring_size(struct ath10k_htt *htt) | 48 | static int ath10k_htt_rx_ring_size(struct ath10k_htt *htt) |
49 | { | 49 | { |
@@ -225,18 +225,16 @@ static void ath10k_htt_rx_ring_refill_retry(unsigned long arg) | |||
225 | ath10k_htt_rx_msdu_buff_replenish(htt); | 225 | ath10k_htt_rx_msdu_buff_replenish(htt); |
226 | } | 226 | } |
227 | 227 | ||
228 | static unsigned ath10k_htt_rx_ring_elems(struct ath10k_htt *htt) | ||
229 | { | ||
230 | return (__le32_to_cpu(*htt->rx_ring.alloc_idx.vaddr) - | ||
231 | htt->rx_ring.sw_rd_idx.msdu_payld) & htt->rx_ring.size_mask; | ||
232 | } | ||
233 | |||
234 | void ath10k_htt_rx_detach(struct ath10k_htt *htt) | 228 | void ath10k_htt_rx_detach(struct ath10k_htt *htt) |
235 | { | 229 | { |
236 | int sw_rd_idx = htt->rx_ring.sw_rd_idx.msdu_payld; | 230 | int sw_rd_idx = htt->rx_ring.sw_rd_idx.msdu_payld; |
237 | 231 | ||
238 | del_timer_sync(&htt->rx_ring.refill_retry_timer); | 232 | del_timer_sync(&htt->rx_ring.refill_retry_timer); |
239 | tasklet_kill(&htt->rx_replenish_task); | 233 | tasklet_kill(&htt->rx_replenish_task); |
234 | tasklet_kill(&htt->txrx_compl_task); | ||
235 | |||
236 | skb_queue_purge(&htt->tx_compl_q); | ||
237 | skb_queue_purge(&htt->rx_compl_q); | ||
240 | 238 | ||
241 | while (sw_rd_idx != __le32_to_cpu(*(htt->rx_ring.alloc_idx.vaddr))) { | 239 | while (sw_rd_idx != __le32_to_cpu(*(htt->rx_ring.alloc_idx.vaddr))) { |
242 | struct sk_buff *skb = | 240 | struct sk_buff *skb = |
@@ -270,10 +268,12 @@ static inline struct sk_buff *ath10k_htt_rx_netbuf_pop(struct ath10k_htt *htt) | |||
270 | int idx; | 268 | int idx; |
271 | struct sk_buff *msdu; | 269 | struct sk_buff *msdu; |
272 | 270 | ||
273 | spin_lock_bh(&htt->rx_ring.lock); | 271 | lockdep_assert_held(&htt->rx_ring.lock); |
274 | 272 | ||
275 | if (ath10k_htt_rx_ring_elems(htt) == 0) | 273 | if (htt->rx_ring.fill_cnt == 0) { |
276 | ath10k_warn("htt rx ring is empty!\n"); | 274 | ath10k_warn("tried to pop sk_buff from an empty rx ring\n"); |
275 | return NULL; | ||
276 | } | ||
277 | 277 | ||
278 | idx = htt->rx_ring.sw_rd_idx.msdu_payld; | 278 | idx = htt->rx_ring.sw_rd_idx.msdu_payld; |
279 | msdu = htt->rx_ring.netbufs_ring[idx]; | 279 | msdu = htt->rx_ring.netbufs_ring[idx]; |
@@ -283,7 +283,6 @@ static inline struct sk_buff *ath10k_htt_rx_netbuf_pop(struct ath10k_htt *htt) | |||
283 | htt->rx_ring.sw_rd_idx.msdu_payld = idx; | 283 | htt->rx_ring.sw_rd_idx.msdu_payld = idx; |
284 | htt->rx_ring.fill_cnt--; | 284 | htt->rx_ring.fill_cnt--; |
285 | 285 | ||
286 | spin_unlock_bh(&htt->rx_ring.lock); | ||
287 | return msdu; | 286 | return msdu; |
288 | } | 287 | } |
289 | 288 | ||
@@ -307,8 +306,7 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, | |||
307 | struct sk_buff *msdu; | 306 | struct sk_buff *msdu; |
308 | struct htt_rx_desc *rx_desc; | 307 | struct htt_rx_desc *rx_desc; |
309 | 308 | ||
310 | if (ath10k_htt_rx_ring_elems(htt) == 0) | 309 | lockdep_assert_held(&htt->rx_ring.lock); |
311 | ath10k_warn("htt rx ring is empty!\n"); | ||
312 | 310 | ||
313 | if (htt->rx_confused) { | 311 | if (htt->rx_confused) { |
314 | ath10k_warn("htt is confused. refusing rx\n"); | 312 | ath10k_warn("htt is confused. refusing rx\n"); |
@@ -400,6 +398,7 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, | |||
400 | msdu_len = MS(__le32_to_cpu(rx_desc->msdu_start.info0), | 398 | msdu_len = MS(__le32_to_cpu(rx_desc->msdu_start.info0), |
401 | RX_MSDU_START_INFO0_MSDU_LENGTH); | 399 | RX_MSDU_START_INFO0_MSDU_LENGTH); |
402 | msdu_chained = rx_desc->frag_info.ring2_more_count; | 400 | msdu_chained = rx_desc->frag_info.ring2_more_count; |
401 | msdu_chaining = msdu_chained; | ||
403 | 402 | ||
404 | if (msdu_len_invalid) | 403 | if (msdu_len_invalid) |
405 | msdu_len = 0; | 404 | msdu_len = 0; |
@@ -427,7 +426,6 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, | |||
427 | 426 | ||
428 | msdu->next = next; | 427 | msdu->next = next; |
429 | msdu = next; | 428 | msdu = next; |
430 | msdu_chaining = 1; | ||
431 | } | 429 | } |
432 | 430 | ||
433 | last_msdu = __le32_to_cpu(rx_desc->msdu_end.info0) & | 431 | last_msdu = __le32_to_cpu(rx_desc->msdu_end.info0) & |
@@ -529,6 +527,12 @@ int ath10k_htt_rx_attach(struct ath10k_htt *htt) | |||
529 | tasklet_init(&htt->rx_replenish_task, ath10k_htt_rx_replenish_task, | 527 | tasklet_init(&htt->rx_replenish_task, ath10k_htt_rx_replenish_task, |
530 | (unsigned long)htt); | 528 | (unsigned long)htt); |
531 | 529 | ||
530 | skb_queue_head_init(&htt->tx_compl_q); | ||
531 | skb_queue_head_init(&htt->rx_compl_q); | ||
532 | |||
533 | tasklet_init(&htt->txrx_compl_task, ath10k_htt_txrx_compl_task, | ||
534 | (unsigned long)htt); | ||
535 | |||
532 | ath10k_dbg(ATH10K_DBG_BOOT, "htt rx ring size %d fill_level %d\n", | 536 | ath10k_dbg(ATH10K_DBG_BOOT, "htt rx ring size %d fill_level %d\n", |
533 | htt->rx_ring.size, htt->rx_ring.fill_level); | 537 | htt->rx_ring.size, htt->rx_ring.fill_level); |
534 | return 0; | 538 | return 0; |
@@ -632,6 +636,12 @@ struct amsdu_subframe_hdr { | |||
632 | __be16 len; | 636 | __be16 len; |
633 | } __packed; | 637 | } __packed; |
634 | 638 | ||
639 | static int ath10k_htt_rx_nwifi_hdrlen(struct ieee80211_hdr *hdr) | ||
640 | { | ||
641 | /* nwifi header is padded to 4 bytes. this fixes 4addr rx */ | ||
642 | return round_up(ieee80211_hdrlen(hdr->frame_control), 4); | ||
643 | } | ||
644 | |||
635 | static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt, | 645 | static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt, |
636 | struct htt_rx_info *info) | 646 | struct htt_rx_info *info) |
637 | { | 647 | { |
@@ -681,7 +691,7 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt, | |||
681 | case RX_MSDU_DECAP_NATIVE_WIFI: | 691 | case RX_MSDU_DECAP_NATIVE_WIFI: |
682 | /* pull decapped header and copy DA */ | 692 | /* pull decapped header and copy DA */ |
683 | hdr = (struct ieee80211_hdr *)skb->data; | 693 | hdr = (struct ieee80211_hdr *)skb->data; |
684 | hdr_len = ieee80211_hdrlen(hdr->frame_control); | 694 | hdr_len = ath10k_htt_rx_nwifi_hdrlen(hdr); |
685 | memcpy(addr, ieee80211_get_DA(hdr), ETH_ALEN); | 695 | memcpy(addr, ieee80211_get_DA(hdr), ETH_ALEN); |
686 | skb_pull(skb, hdr_len); | 696 | skb_pull(skb, hdr_len); |
687 | 697 | ||
@@ -768,7 +778,7 @@ static void ath10k_htt_rx_msdu(struct ath10k_htt *htt, struct htt_rx_info *info) | |||
768 | case RX_MSDU_DECAP_NATIVE_WIFI: | 778 | case RX_MSDU_DECAP_NATIVE_WIFI: |
769 | /* Pull decapped header */ | 779 | /* Pull decapped header */ |
770 | hdr = (struct ieee80211_hdr *)skb->data; | 780 | hdr = (struct ieee80211_hdr *)skb->data; |
771 | hdr_len = ieee80211_hdrlen(hdr->frame_control); | 781 | hdr_len = ath10k_htt_rx_nwifi_hdrlen(hdr); |
772 | skb_pull(skb, hdr_len); | 782 | skb_pull(skb, hdr_len); |
773 | 783 | ||
774 | /* Push original header */ | 784 | /* Push original header */ |
@@ -846,6 +856,20 @@ static bool ath10k_htt_rx_has_mic_err(struct sk_buff *skb) | |||
846 | return false; | 856 | return false; |
847 | } | 857 | } |
848 | 858 | ||
859 | static bool ath10k_htt_rx_is_mgmt(struct sk_buff *skb) | ||
860 | { | ||
861 | struct htt_rx_desc *rxd; | ||
862 | u32 flags; | ||
863 | |||
864 | rxd = (void *)skb->data - sizeof(*rxd); | ||
865 | flags = __le32_to_cpu(rxd->attention.flags); | ||
866 | |||
867 | if (flags & RX_ATTENTION_FLAGS_MGMT_TYPE) | ||
868 | return true; | ||
869 | |||
870 | return false; | ||
871 | } | ||
872 | |||
849 | static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb) | 873 | static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb) |
850 | { | 874 | { |
851 | struct htt_rx_desc *rxd; | 875 | struct htt_rx_desc *rxd; |
@@ -877,6 +901,57 @@ static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb) | |||
877 | return CHECKSUM_UNNECESSARY; | 901 | return CHECKSUM_UNNECESSARY; |
878 | } | 902 | } |
879 | 903 | ||
904 | static int ath10k_unchain_msdu(struct sk_buff *msdu_head) | ||
905 | { | ||
906 | struct sk_buff *next = msdu_head->next; | ||
907 | struct sk_buff *to_free = next; | ||
908 | int space; | ||
909 | int total_len = 0; | ||
910 | |||
911 | /* TODO: Might could optimize this by using | ||
912 | * skb_try_coalesce or similar method to | ||
913 | * decrease copying, or maybe get mac80211 to | ||
914 | * provide a way to just receive a list of | ||
915 | * skb? | ||
916 | */ | ||
917 | |||
918 | msdu_head->next = NULL; | ||
919 | |||
920 | /* Allocate total length all at once. */ | ||
921 | while (next) { | ||
922 | total_len += next->len; | ||
923 | next = next->next; | ||
924 | } | ||
925 | |||
926 | space = total_len - skb_tailroom(msdu_head); | ||
927 | if ((space > 0) && | ||
928 | (pskb_expand_head(msdu_head, 0, space, GFP_ATOMIC) < 0)) { | ||
929 | /* TODO: bump some rx-oom error stat */ | ||
930 | /* put it back together so we can free the | ||
931 | * whole list at once. | ||
932 | */ | ||
933 | msdu_head->next = to_free; | ||
934 | return -1; | ||
935 | } | ||
936 | |||
937 | /* Walk list again, copying contents into | ||
938 | * msdu_head | ||
939 | */ | ||
940 | next = to_free; | ||
941 | while (next) { | ||
942 | skb_copy_from_linear_data(next, skb_put(msdu_head, next->len), | ||
943 | next->len); | ||
944 | next = next->next; | ||
945 | } | ||
946 | |||
947 | /* If here, we have consolidated skb. Free the | ||
948 | * fragments and pass the main skb on up the | ||
949 | * stack. | ||
950 | */ | ||
951 | ath10k_htt_rx_free_msdu_chain(to_free); | ||
952 | return 0; | ||
953 | } | ||
954 | |||
880 | static void ath10k_htt_rx_handler(struct ath10k_htt *htt, | 955 | static void ath10k_htt_rx_handler(struct ath10k_htt *htt, |
881 | struct htt_rx_indication *rx) | 956 | struct htt_rx_indication *rx) |
882 | { | 957 | { |
@@ -888,6 +963,8 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, | |||
888 | u8 *fw_desc; | 963 | u8 *fw_desc; |
889 | int i, j; | 964 | int i, j; |
890 | 965 | ||
966 | lockdep_assert_held(&htt->rx_ring.lock); | ||
967 | |||
891 | memset(&info, 0, sizeof(info)); | 968 | memset(&info, 0, sizeof(info)); |
892 | 969 | ||
893 | fw_desc_len = __le16_to_cpu(rx->prefix.fw_rx_desc_bytes); | 970 | fw_desc_len = __le16_to_cpu(rx->prefix.fw_rx_desc_bytes); |
@@ -940,7 +1017,8 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, | |||
940 | status = info.status; | 1017 | status = info.status; |
941 | 1018 | ||
942 | /* Skip mgmt frames while we handle this in WMI */ | 1019 | /* Skip mgmt frames while we handle this in WMI */ |
943 | if (status == HTT_RX_IND_MPDU_STATUS_MGMT_CTRL) { | 1020 | if (status == HTT_RX_IND_MPDU_STATUS_MGMT_CTRL || |
1021 | ath10k_htt_rx_is_mgmt(msdu_head)) { | ||
944 | ath10k_dbg(ATH10K_DBG_HTT, "htt rx mgmt ctrl\n"); | 1022 | ath10k_dbg(ATH10K_DBG_HTT, "htt rx mgmt ctrl\n"); |
945 | ath10k_htt_rx_free_msdu_chain(msdu_head); | 1023 | ath10k_htt_rx_free_msdu_chain(msdu_head); |
946 | continue; | 1024 | continue; |
@@ -964,10 +1042,8 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, | |||
964 | continue; | 1042 | continue; |
965 | } | 1043 | } |
966 | 1044 | ||
967 | /* FIXME: we do not support chaining yet. | 1045 | if (msdu_chaining && |
968 | * this needs investigation */ | 1046 | (ath10k_unchain_msdu(msdu_head) < 0)) { |
969 | if (msdu_chaining) { | ||
970 | ath10k_warn("htt rx msdu_chaining is true\n"); | ||
971 | ath10k_htt_rx_free_msdu_chain(msdu_head); | 1047 | ath10k_htt_rx_free_msdu_chain(msdu_head); |
972 | continue; | 1048 | continue; |
973 | } | 1049 | } |
@@ -990,6 +1066,7 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, | |||
990 | info.rate.info0 = rx->ppdu.info0; | 1066 | info.rate.info0 = rx->ppdu.info0; |
991 | info.rate.info1 = __le32_to_cpu(rx->ppdu.info1); | 1067 | info.rate.info1 = __le32_to_cpu(rx->ppdu.info1); |
992 | info.rate.info2 = __le32_to_cpu(rx->ppdu.info2); | 1068 | info.rate.info2 = __le32_to_cpu(rx->ppdu.info2); |
1069 | info.tsf = __le32_to_cpu(rx->ppdu.tsf); | ||
993 | 1070 | ||
994 | hdr = ath10k_htt_rx_skb_get_hdr(msdu_head); | 1071 | hdr = ath10k_htt_rx_skb_get_hdr(msdu_head); |
995 | 1072 | ||
@@ -1023,8 +1100,11 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt, | |||
1023 | 1100 | ||
1024 | msdu_head = NULL; | 1101 | msdu_head = NULL; |
1025 | msdu_tail = NULL; | 1102 | msdu_tail = NULL; |
1103 | |||
1104 | spin_lock_bh(&htt->rx_ring.lock); | ||
1026 | msdu_chaining = ath10k_htt_rx_amsdu_pop(htt, &fw_desc, &fw_desc_len, | 1105 | msdu_chaining = ath10k_htt_rx_amsdu_pop(htt, &fw_desc, &fw_desc_len, |
1027 | &msdu_head, &msdu_tail); | 1106 | &msdu_head, &msdu_tail); |
1107 | spin_unlock_bh(&htt->rx_ring.lock); | ||
1028 | 1108 | ||
1029 | ath10k_dbg(ATH10K_DBG_HTT_DUMP, "htt rx frag ahead\n"); | 1109 | ath10k_dbg(ATH10K_DBG_HTT_DUMP, "htt rx frag ahead\n"); |
1030 | 1110 | ||
@@ -1116,6 +1196,45 @@ end: | |||
1116 | } | 1196 | } |
1117 | } | 1197 | } |
1118 | 1198 | ||
1199 | static void ath10k_htt_rx_frm_tx_compl(struct ath10k *ar, | ||
1200 | struct sk_buff *skb) | ||
1201 | { | ||
1202 | struct ath10k_htt *htt = &ar->htt; | ||
1203 | struct htt_resp *resp = (struct htt_resp *)skb->data; | ||
1204 | struct htt_tx_done tx_done = {}; | ||
1205 | int status = MS(resp->data_tx_completion.flags, HTT_DATA_TX_STATUS); | ||
1206 | __le16 msdu_id; | ||
1207 | int i; | ||
1208 | |||
1209 | lockdep_assert_held(&htt->tx_lock); | ||
1210 | |||
1211 | switch (status) { | ||
1212 | case HTT_DATA_TX_STATUS_NO_ACK: | ||
1213 | tx_done.no_ack = true; | ||
1214 | break; | ||
1215 | case HTT_DATA_TX_STATUS_OK: | ||
1216 | break; | ||
1217 | case HTT_DATA_TX_STATUS_DISCARD: | ||
1218 | case HTT_DATA_TX_STATUS_POSTPONE: | ||
1219 | case HTT_DATA_TX_STATUS_DOWNLOAD_FAIL: | ||
1220 | tx_done.discard = true; | ||
1221 | break; | ||
1222 | default: | ||
1223 | ath10k_warn("unhandled tx completion status %d\n", status); | ||
1224 | tx_done.discard = true; | ||
1225 | break; | ||
1226 | } | ||
1227 | |||
1228 | ath10k_dbg(ATH10K_DBG_HTT, "htt tx completion num_msdus %d\n", | ||
1229 | resp->data_tx_completion.num_msdus); | ||
1230 | |||
1231 | for (i = 0; i < resp->data_tx_completion.num_msdus; i++) { | ||
1232 | msdu_id = resp->data_tx_completion.msdus[i]; | ||
1233 | tx_done.msdu_id = __le16_to_cpu(msdu_id); | ||
1234 | ath10k_txrx_tx_unref(htt, &tx_done); | ||
1235 | } | ||
1236 | } | ||
1237 | |||
1119 | void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) | 1238 | void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) |
1120 | { | 1239 | { |
1121 | struct ath10k_htt *htt = &ar->htt; | 1240 | struct ath10k_htt *htt = &ar->htt; |
@@ -1134,10 +1253,12 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) | |||
1134 | complete(&htt->target_version_received); | 1253 | complete(&htt->target_version_received); |
1135 | break; | 1254 | break; |
1136 | } | 1255 | } |
1137 | case HTT_T2H_MSG_TYPE_RX_IND: { | 1256 | case HTT_T2H_MSG_TYPE_RX_IND: |
1138 | ath10k_htt_rx_handler(htt, &resp->rx_ind); | 1257 | spin_lock_bh(&htt->rx_ring.lock); |
1139 | break; | 1258 | __skb_queue_tail(&htt->rx_compl_q, skb); |
1140 | } | 1259 | spin_unlock_bh(&htt->rx_ring.lock); |
1260 | tasklet_schedule(&htt->txrx_compl_task); | ||
1261 | return; | ||
1141 | case HTT_T2H_MSG_TYPE_PEER_MAP: { | 1262 | case HTT_T2H_MSG_TYPE_PEER_MAP: { |
1142 | struct htt_peer_map_event ev = { | 1263 | struct htt_peer_map_event ev = { |
1143 | .vdev_id = resp->peer_map.vdev_id, | 1264 | .vdev_id = resp->peer_map.vdev_id, |
@@ -1172,44 +1293,17 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) | |||
1172 | break; | 1293 | break; |
1173 | } | 1294 | } |
1174 | 1295 | ||
1296 | spin_lock_bh(&htt->tx_lock); | ||
1175 | ath10k_txrx_tx_unref(htt, &tx_done); | 1297 | ath10k_txrx_tx_unref(htt, &tx_done); |
1298 | spin_unlock_bh(&htt->tx_lock); | ||
1176 | break; | 1299 | break; |
1177 | } | 1300 | } |
1178 | case HTT_T2H_MSG_TYPE_TX_COMPL_IND: { | 1301 | case HTT_T2H_MSG_TYPE_TX_COMPL_IND: |
1179 | struct htt_tx_done tx_done = {}; | 1302 | spin_lock_bh(&htt->tx_lock); |
1180 | int status = MS(resp->data_tx_completion.flags, | 1303 | __skb_queue_tail(&htt->tx_compl_q, skb); |
1181 | HTT_DATA_TX_STATUS); | 1304 | spin_unlock_bh(&htt->tx_lock); |
1182 | __le16 msdu_id; | 1305 | tasklet_schedule(&htt->txrx_compl_task); |
1183 | int i; | 1306 | return; |
1184 | |||
1185 | switch (status) { | ||
1186 | case HTT_DATA_TX_STATUS_NO_ACK: | ||
1187 | tx_done.no_ack = true; | ||
1188 | break; | ||
1189 | case HTT_DATA_TX_STATUS_OK: | ||
1190 | break; | ||
1191 | case HTT_DATA_TX_STATUS_DISCARD: | ||
1192 | case HTT_DATA_TX_STATUS_POSTPONE: | ||
1193 | case HTT_DATA_TX_STATUS_DOWNLOAD_FAIL: | ||
1194 | tx_done.discard = true; | ||
1195 | break; | ||
1196 | default: | ||
1197 | ath10k_warn("unhandled tx completion status %d\n", | ||
1198 | status); | ||
1199 | tx_done.discard = true; | ||
1200 | break; | ||
1201 | } | ||
1202 | |||
1203 | ath10k_dbg(ATH10K_DBG_HTT, "htt tx completion num_msdus %d\n", | ||
1204 | resp->data_tx_completion.num_msdus); | ||
1205 | |||
1206 | for (i = 0; i < resp->data_tx_completion.num_msdus; i++) { | ||
1207 | msdu_id = resp->data_tx_completion.msdus[i]; | ||
1208 | tx_done.msdu_id = __le16_to_cpu(msdu_id); | ||
1209 | ath10k_txrx_tx_unref(htt, &tx_done); | ||
1210 | } | ||
1211 | break; | ||
1212 | } | ||
1213 | case HTT_T2H_MSG_TYPE_SEC_IND: { | 1307 | case HTT_T2H_MSG_TYPE_SEC_IND: { |
1214 | struct ath10k *ar = htt->ar; | 1308 | struct ath10k *ar = htt->ar; |
1215 | struct htt_security_indication *ev = &resp->security_indication; | 1309 | struct htt_security_indication *ev = &resp->security_indication; |
@@ -1249,3 +1343,25 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) | |||
1249 | /* Free the indication buffer */ | 1343 | /* Free the indication buffer */ |
1250 | dev_kfree_skb_any(skb); | 1344 | dev_kfree_skb_any(skb); |
1251 | } | 1345 | } |
1346 | |||
1347 | static void ath10k_htt_txrx_compl_task(unsigned long ptr) | ||
1348 | { | ||
1349 | struct ath10k_htt *htt = (struct ath10k_htt *)ptr; | ||
1350 | struct htt_resp *resp; | ||
1351 | struct sk_buff *skb; | ||
1352 | |||
1353 | spin_lock_bh(&htt->tx_lock); | ||
1354 | while ((skb = __skb_dequeue(&htt->tx_compl_q))) { | ||
1355 | ath10k_htt_rx_frm_tx_compl(htt->ar, skb); | ||
1356 | dev_kfree_skb_any(skb); | ||
1357 | } | ||
1358 | spin_unlock_bh(&htt->tx_lock); | ||
1359 | |||
1360 | spin_lock_bh(&htt->rx_ring.lock); | ||
1361 | while ((skb = __skb_dequeue(&htt->rx_compl_q))) { | ||
1362 | resp = (struct htt_resp *)skb->data; | ||
1363 | ath10k_htt_rx_handler(htt, &resp->rx_ind); | ||
1364 | dev_kfree_skb_any(skb); | ||
1365 | } | ||
1366 | spin_unlock_bh(&htt->rx_ring.lock); | ||
1367 | } | ||
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index acaa046dc93b..7a3e2e40dd5c 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c | |||
@@ -109,6 +109,14 @@ int ath10k_htt_tx_attach(struct ath10k_htt *htt) | |||
109 | return -ENOMEM; | 109 | return -ENOMEM; |
110 | } | 110 | } |
111 | 111 | ||
112 | htt->tx_pool = dma_pool_create("ath10k htt tx pool", htt->ar->dev, | ||
113 | sizeof(struct ath10k_htt_txbuf), 4, 0); | ||
114 | if (!htt->tx_pool) { | ||
115 | kfree(htt->used_msdu_ids); | ||
116 | kfree(htt->pending_tx); | ||
117 | return -ENOMEM; | ||
118 | } | ||
119 | |||
112 | return 0; | 120 | return 0; |
113 | } | 121 | } |
114 | 122 | ||
@@ -117,9 +125,7 @@ static void ath10k_htt_tx_cleanup_pending(struct ath10k_htt *htt) | |||
117 | struct htt_tx_done tx_done = {0}; | 125 | struct htt_tx_done tx_done = {0}; |
118 | int msdu_id; | 126 | int msdu_id; |
119 | 127 | ||
120 | /* No locks needed. Called after communication with the device has | 128 | spin_lock_bh(&htt->tx_lock); |
121 | * been stopped. */ | ||
122 | |||
123 | for (msdu_id = 0; msdu_id < htt->max_num_pending_tx; msdu_id++) { | 129 | for (msdu_id = 0; msdu_id < htt->max_num_pending_tx; msdu_id++) { |
124 | if (!test_bit(msdu_id, htt->used_msdu_ids)) | 130 | if (!test_bit(msdu_id, htt->used_msdu_ids)) |
125 | continue; | 131 | continue; |
@@ -132,6 +138,7 @@ static void ath10k_htt_tx_cleanup_pending(struct ath10k_htt *htt) | |||
132 | 138 | ||
133 | ath10k_txrx_tx_unref(htt, &tx_done); | 139 | ath10k_txrx_tx_unref(htt, &tx_done); |
134 | } | 140 | } |
141 | spin_unlock_bh(&htt->tx_lock); | ||
135 | } | 142 | } |
136 | 143 | ||
137 | void ath10k_htt_tx_detach(struct ath10k_htt *htt) | 144 | void ath10k_htt_tx_detach(struct ath10k_htt *htt) |
@@ -139,6 +146,7 @@ void ath10k_htt_tx_detach(struct ath10k_htt *htt) | |||
139 | ath10k_htt_tx_cleanup_pending(htt); | 146 | ath10k_htt_tx_cleanup_pending(htt); |
140 | kfree(htt->pending_tx); | 147 | kfree(htt->pending_tx); |
141 | kfree(htt->used_msdu_ids); | 148 | kfree(htt->used_msdu_ids); |
149 | dma_pool_destroy(htt->tx_pool); | ||
142 | return; | 150 | return; |
143 | } | 151 | } |
144 | 152 | ||
@@ -334,7 +342,9 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) | |||
334 | goto err_free_msdu_id; | 342 | goto err_free_msdu_id; |
335 | } | 343 | } |
336 | 344 | ||
337 | res = ath10k_skb_map(dev, msdu); | 345 | skb_cb->paddr = dma_map_single(dev, msdu->data, msdu->len, |
346 | DMA_TO_DEVICE); | ||
347 | res = dma_mapping_error(dev, skb_cb->paddr); | ||
338 | if (res) | 348 | if (res) |
339 | goto err_free_txdesc; | 349 | goto err_free_txdesc; |
340 | 350 | ||
@@ -348,8 +358,7 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) | |||
348 | memcpy(cmd->mgmt_tx.hdr, msdu->data, | 358 | memcpy(cmd->mgmt_tx.hdr, msdu->data, |
349 | min_t(int, msdu->len, HTT_MGMT_FRM_HDR_DOWNLOAD_LEN)); | 359 | min_t(int, msdu->len, HTT_MGMT_FRM_HDR_DOWNLOAD_LEN)); |
350 | 360 | ||
351 | skb_cb->htt.frag_len = 0; | 361 | skb_cb->htt.txbuf = NULL; |
352 | skb_cb->htt.pad_len = 0; | ||
353 | 362 | ||
354 | res = ath10k_htc_send(&htt->ar->htc, htt->eid, txdesc); | 363 | res = ath10k_htc_send(&htt->ar->htc, htt->eid, txdesc); |
355 | if (res) | 364 | if (res) |
@@ -358,7 +367,7 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) | |||
358 | return 0; | 367 | return 0; |
359 | 368 | ||
360 | err_unmap_msdu: | 369 | err_unmap_msdu: |
361 | ath10k_skb_unmap(dev, msdu); | 370 | dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); |
362 | err_free_txdesc: | 371 | err_free_txdesc: |
363 | dev_kfree_skb_any(txdesc); | 372 | dev_kfree_skb_any(txdesc); |
364 | err_free_msdu_id: | 373 | err_free_msdu_id: |
@@ -375,19 +384,19 @@ err: | |||
375 | int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) | 384 | int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) |
376 | { | 385 | { |
377 | struct device *dev = htt->ar->dev; | 386 | struct device *dev = htt->ar->dev; |
378 | struct htt_cmd *cmd; | ||
379 | struct htt_data_tx_desc_frag *tx_frags; | ||
380 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data; | 387 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data; |
381 | struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu); | 388 | struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu); |
382 | struct sk_buff *txdesc = NULL; | 389 | struct ath10k_hif_sg_item sg_items[2]; |
383 | bool use_frags; | 390 | struct htt_data_tx_desc_frag *frags; |
384 | u8 vdev_id = ATH10K_SKB_CB(msdu)->vdev_id; | 391 | u8 vdev_id = skb_cb->vdev_id; |
385 | u8 tid; | 392 | u8 tid = skb_cb->htt.tid; |
386 | int prefetch_len, desc_len; | 393 | int prefetch_len; |
387 | int msdu_id = -1; | ||
388 | int res; | 394 | int res; |
389 | u8 flags0; | 395 | u8 flags0 = 0; |
390 | u16 flags1; | 396 | u16 msdu_id, flags1 = 0; |
397 | dma_addr_t paddr; | ||
398 | u32 frags_paddr; | ||
399 | bool use_frags; | ||
391 | 400 | ||
392 | res = ath10k_htt_tx_inc_pending(htt); | 401 | res = ath10k_htt_tx_inc_pending(htt); |
393 | if (res) | 402 | if (res) |
@@ -406,114 +415,120 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) | |||
406 | prefetch_len = min(htt->prefetch_len, msdu->len); | 415 | prefetch_len = min(htt->prefetch_len, msdu->len); |
407 | prefetch_len = roundup(prefetch_len, 4); | 416 | prefetch_len = roundup(prefetch_len, 4); |
408 | 417 | ||
409 | desc_len = sizeof(cmd->hdr) + sizeof(cmd->data_tx) + prefetch_len; | ||
410 | |||
411 | txdesc = ath10k_htc_alloc_skb(desc_len); | ||
412 | if (!txdesc) { | ||
413 | res = -ENOMEM; | ||
414 | goto err_free_msdu_id; | ||
415 | } | ||
416 | |||
417 | /* Since HTT 3.0 there is no separate mgmt tx command. However in case | 418 | /* Since HTT 3.0 there is no separate mgmt tx command. However in case |
418 | * of mgmt tx using TX_FRM there is not tx fragment list. Instead of tx | 419 | * of mgmt tx using TX_FRM there is not tx fragment list. Instead of tx |
419 | * fragment list host driver specifies directly frame pointer. */ | 420 | * fragment list host driver specifies directly frame pointer. */ |
420 | use_frags = htt->target_version_major < 3 || | 421 | use_frags = htt->target_version_major < 3 || |
421 | !ieee80211_is_mgmt(hdr->frame_control); | 422 | !ieee80211_is_mgmt(hdr->frame_control); |
422 | 423 | ||
423 | if (!IS_ALIGNED((unsigned long)txdesc->data, 4)) { | 424 | skb_cb->htt.txbuf = dma_pool_alloc(htt->tx_pool, GFP_ATOMIC, |
424 | ath10k_warn("htt alignment check failed. dropping packet.\n"); | 425 | &paddr); |
425 | res = -EIO; | 426 | if (!skb_cb->htt.txbuf) |
426 | goto err_free_txdesc; | 427 | goto err_free_msdu_id; |
427 | } | 428 | skb_cb->htt.txbuf_paddr = paddr; |
428 | 429 | ||
429 | if (use_frags) { | 430 | skb_cb->paddr = dma_map_single(dev, msdu->data, msdu->len, |
430 | skb_cb->htt.frag_len = sizeof(*tx_frags) * 2; | 431 | DMA_TO_DEVICE); |
431 | skb_cb->htt.pad_len = (unsigned long)msdu->data - | 432 | res = dma_mapping_error(dev, skb_cb->paddr); |
432 | round_down((unsigned long)msdu->data, 4); | 433 | if (res) |
434 | goto err_free_txbuf; | ||
433 | 435 | ||
434 | skb_push(msdu, skb_cb->htt.frag_len + skb_cb->htt.pad_len); | 436 | if (likely(use_frags)) { |
435 | } else { | 437 | frags = skb_cb->htt.txbuf->frags; |
436 | skb_cb->htt.frag_len = 0; | ||
437 | skb_cb->htt.pad_len = 0; | ||
438 | } | ||
439 | 438 | ||
440 | res = ath10k_skb_map(dev, msdu); | 439 | frags[0].paddr = __cpu_to_le32(skb_cb->paddr); |
441 | if (res) | 440 | frags[0].len = __cpu_to_le32(msdu->len); |
442 | goto err_pull_txfrag; | 441 | frags[1].paddr = 0; |
443 | 442 | frags[1].len = 0; | |
444 | if (use_frags) { | ||
445 | dma_sync_single_for_cpu(dev, skb_cb->paddr, msdu->len, | ||
446 | DMA_TO_DEVICE); | ||
447 | |||
448 | /* tx fragment list must be terminated with zero-entry */ | ||
449 | tx_frags = (struct htt_data_tx_desc_frag *)msdu->data; | ||
450 | tx_frags[0].paddr = __cpu_to_le32(skb_cb->paddr + | ||
451 | skb_cb->htt.frag_len + | ||
452 | skb_cb->htt.pad_len); | ||
453 | tx_frags[0].len = __cpu_to_le32(msdu->len - | ||
454 | skb_cb->htt.frag_len - | ||
455 | skb_cb->htt.pad_len); | ||
456 | tx_frags[1].paddr = __cpu_to_le32(0); | ||
457 | tx_frags[1].len = __cpu_to_le32(0); | ||
458 | |||
459 | dma_sync_single_for_device(dev, skb_cb->paddr, msdu->len, | ||
460 | DMA_TO_DEVICE); | ||
461 | } | ||
462 | 443 | ||
463 | ath10k_dbg(ATH10K_DBG_HTT, "tx-msdu 0x%llx\n", | 444 | flags0 |= SM(ATH10K_HW_TXRX_NATIVE_WIFI, |
464 | (unsigned long long) ATH10K_SKB_CB(msdu)->paddr); | 445 | HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE); |
465 | ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "tx-msdu: ", | ||
466 | msdu->data, msdu->len); | ||
467 | 446 | ||
468 | skb_put(txdesc, desc_len); | 447 | frags_paddr = skb_cb->htt.txbuf_paddr; |
469 | cmd = (struct htt_cmd *)txdesc->data; | 448 | } else { |
449 | flags0 |= SM(ATH10K_HW_TXRX_MGMT, | ||
450 | HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE); | ||
470 | 451 | ||
471 | tid = ATH10K_SKB_CB(msdu)->htt.tid; | 452 | frags_paddr = skb_cb->paddr; |
453 | } | ||
472 | 454 | ||
473 | ath10k_dbg(ATH10K_DBG_HTT, "htt data tx using tid %hhu\n", tid); | 455 | /* Normally all commands go through HTC which manages tx credits for |
456 | * each endpoint and notifies when tx is completed. | ||
457 | * | ||
458 | * HTT endpoint is creditless so there's no need to care about HTC | ||
459 | * flags. In that case it is trivial to fill the HTC header here. | ||
460 | * | ||
461 | * MSDU transmission is considered completed upon HTT event. This | ||
462 | * implies no relevant resources can be freed until after the event is | ||
463 | * received. That's why HTC tx completion handler itself is ignored by | ||
464 | * setting NULL to transfer_context for all sg items. | ||
465 | * | ||
466 | * There is simply no point in pushing HTT TX_FRM through HTC tx path | ||
467 | * as it's a waste of resources. By bypassing HTC it is possible to | ||
468 | * avoid extra memory allocations, compress data structures and thus | ||
469 | * improve performance. */ | ||
470 | |||
471 | skb_cb->htt.txbuf->htc_hdr.eid = htt->eid; | ||
472 | skb_cb->htt.txbuf->htc_hdr.len = __cpu_to_le16( | ||
473 | sizeof(skb_cb->htt.txbuf->cmd_hdr) + | ||
474 | sizeof(skb_cb->htt.txbuf->cmd_tx) + | ||
475 | prefetch_len); | ||
476 | skb_cb->htt.txbuf->htc_hdr.flags = 0; | ||
474 | 477 | ||
475 | flags0 = 0; | ||
476 | if (!ieee80211_has_protected(hdr->frame_control)) | 478 | if (!ieee80211_has_protected(hdr->frame_control)) |
477 | flags0 |= HTT_DATA_TX_DESC_FLAGS0_NO_ENCRYPT; | 479 | flags0 |= HTT_DATA_TX_DESC_FLAGS0_NO_ENCRYPT; |
478 | flags0 |= HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT; | ||
479 | 480 | ||
480 | if (use_frags) | 481 | flags0 |= HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT; |
481 | flags0 |= SM(ATH10K_HW_TXRX_NATIVE_WIFI, | ||
482 | HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE); | ||
483 | else | ||
484 | flags0 |= SM(ATH10K_HW_TXRX_MGMT, | ||
485 | HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE); | ||
486 | 482 | ||
487 | flags1 = 0; | ||
488 | flags1 |= SM((u16)vdev_id, HTT_DATA_TX_DESC_FLAGS1_VDEV_ID); | 483 | flags1 |= SM((u16)vdev_id, HTT_DATA_TX_DESC_FLAGS1_VDEV_ID); |
489 | flags1 |= SM((u16)tid, HTT_DATA_TX_DESC_FLAGS1_EXT_TID); | 484 | flags1 |= SM((u16)tid, HTT_DATA_TX_DESC_FLAGS1_EXT_TID); |
490 | flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L3_OFFLOAD; | 485 | flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L3_OFFLOAD; |
491 | flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L4_OFFLOAD; | 486 | flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L4_OFFLOAD; |
492 | 487 | ||
493 | cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_TX_FRM; | 488 | skb_cb->htt.txbuf->cmd_hdr.msg_type = HTT_H2T_MSG_TYPE_TX_FRM; |
494 | cmd->data_tx.flags0 = flags0; | 489 | skb_cb->htt.txbuf->cmd_tx.flags0 = flags0; |
495 | cmd->data_tx.flags1 = __cpu_to_le16(flags1); | 490 | skb_cb->htt.txbuf->cmd_tx.flags1 = __cpu_to_le16(flags1); |
496 | cmd->data_tx.len = __cpu_to_le16(msdu->len - | 491 | skb_cb->htt.txbuf->cmd_tx.len = __cpu_to_le16(msdu->len); |
497 | skb_cb->htt.frag_len - | 492 | skb_cb->htt.txbuf->cmd_tx.id = __cpu_to_le16(msdu_id); |
498 | skb_cb->htt.pad_len); | 493 | skb_cb->htt.txbuf->cmd_tx.frags_paddr = __cpu_to_le32(frags_paddr); |
499 | cmd->data_tx.id = __cpu_to_le16(msdu_id); | 494 | skb_cb->htt.txbuf->cmd_tx.peerid = __cpu_to_le32(HTT_INVALID_PEERID); |
500 | cmd->data_tx.frags_paddr = __cpu_to_le32(skb_cb->paddr); | 495 | |
501 | cmd->data_tx.peerid = __cpu_to_le32(HTT_INVALID_PEERID); | 496 | ath10k_dbg(ATH10K_DBG_HTT, |
502 | 497 | "htt tx flags0 %hhu flags1 %hu len %d id %hu frags_paddr %08x, msdu_paddr %08x vdev %hhu tid %hhu\n", | |
503 | memcpy(cmd->data_tx.prefetch, hdr, prefetch_len); | 498 | flags0, flags1, msdu->len, msdu_id, frags_paddr, |
499 | (u32)skb_cb->paddr, vdev_id, tid); | ||
500 | ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "htt tx msdu: ", | ||
501 | msdu->data, msdu->len); | ||
504 | 502 | ||
505 | res = ath10k_htc_send(&htt->ar->htc, htt->eid, txdesc); | 503 | sg_items[0].transfer_id = 0; |
504 | sg_items[0].transfer_context = NULL; | ||
505 | sg_items[0].vaddr = &skb_cb->htt.txbuf->htc_hdr; | ||
506 | sg_items[0].paddr = skb_cb->htt.txbuf_paddr + | ||
507 | sizeof(skb_cb->htt.txbuf->frags); | ||
508 | sg_items[0].len = sizeof(skb_cb->htt.txbuf->htc_hdr) + | ||
509 | sizeof(skb_cb->htt.txbuf->cmd_hdr) + | ||
510 | sizeof(skb_cb->htt.txbuf->cmd_tx); | ||
511 | |||
512 | sg_items[1].transfer_id = 0; | ||
513 | sg_items[1].transfer_context = NULL; | ||
514 | sg_items[1].vaddr = msdu->data; | ||
515 | sg_items[1].paddr = skb_cb->paddr; | ||
516 | sg_items[1].len = prefetch_len; | ||
517 | |||
518 | res = ath10k_hif_tx_sg(htt->ar, | ||
519 | htt->ar->htc.endpoint[htt->eid].ul_pipe_id, | ||
520 | sg_items, ARRAY_SIZE(sg_items)); | ||
506 | if (res) | 521 | if (res) |
507 | goto err_unmap_msdu; | 522 | goto err_unmap_msdu; |
508 | 523 | ||
509 | return 0; | 524 | return 0; |
510 | 525 | ||
511 | err_unmap_msdu: | 526 | err_unmap_msdu: |
512 | ath10k_skb_unmap(dev, msdu); | 527 | dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); |
513 | err_pull_txfrag: | 528 | err_free_txbuf: |
514 | skb_pull(msdu, skb_cb->htt.frag_len + skb_cb->htt.pad_len); | 529 | dma_pool_free(htt->tx_pool, |
515 | err_free_txdesc: | 530 | skb_cb->htt.txbuf, |
516 | dev_kfree_skb_any(txdesc); | 531 | skb_cb->htt.txbuf_paddr); |
517 | err_free_msdu_id: | 532 | err_free_msdu_id: |
518 | spin_lock_bh(&htt->tx_lock); | 533 | spin_lock_bh(&htt->tx_lock); |
519 | htt->pending_tx[msdu_id] = NULL; | 534 | htt->pending_tx[msdu_id] = NULL; |
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index e17f5d732b5a..511a2f81e7af 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c | |||
@@ -323,13 +323,15 @@ static int ath10k_peer_create(struct ath10k *ar, u32 vdev_id, const u8 *addr) | |||
323 | 323 | ||
324 | ret = ath10k_wmi_peer_create(ar, vdev_id, addr); | 324 | ret = ath10k_wmi_peer_create(ar, vdev_id, addr); |
325 | if (ret) { | 325 | if (ret) { |
326 | ath10k_warn("Failed to create wmi peer: %i\n", ret); | 326 | ath10k_warn("Failed to create wmi peer %pM on vdev %i: %i\n", |
327 | addr, vdev_id, ret); | ||
327 | return ret; | 328 | return ret; |
328 | } | 329 | } |
329 | 330 | ||
330 | ret = ath10k_wait_for_peer_created(ar, vdev_id, addr); | 331 | ret = ath10k_wait_for_peer_created(ar, vdev_id, addr); |
331 | if (ret) { | 332 | if (ret) { |
332 | ath10k_warn("Failed to wait for created wmi peer: %i\n", ret); | 333 | ath10k_warn("Failed to wait for created wmi peer %pM on vdev %i: %i\n", |
334 | addr, vdev_id, ret); | ||
333 | return ret; | 335 | return ret; |
334 | } | 336 | } |
335 | spin_lock_bh(&ar->data_lock); | 337 | spin_lock_bh(&ar->data_lock); |
@@ -349,7 +351,8 @@ static int ath10k_mac_set_kickout(struct ath10k_vif *arvif) | |||
349 | ret = ath10k_wmi_pdev_set_param(ar, param, | 351 | ret = ath10k_wmi_pdev_set_param(ar, param, |
350 | ATH10K_KICKOUT_THRESHOLD); | 352 | ATH10K_KICKOUT_THRESHOLD); |
351 | if (ret) { | 353 | if (ret) { |
352 | ath10k_warn("Failed to set kickout threshold: %d\n", ret); | 354 | ath10k_warn("Failed to set kickout threshold on vdev %i: %d\n", |
355 | arvif->vdev_id, ret); | ||
353 | return ret; | 356 | return ret; |
354 | } | 357 | } |
355 | 358 | ||
@@ -357,8 +360,8 @@ static int ath10k_mac_set_kickout(struct ath10k_vif *arvif) | |||
357 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, param, | 360 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, param, |
358 | ATH10K_KEEPALIVE_MIN_IDLE); | 361 | ATH10K_KEEPALIVE_MIN_IDLE); |
359 | if (ret) { | 362 | if (ret) { |
360 | ath10k_warn("Failed to set keepalive minimum idle time : %d\n", | 363 | ath10k_warn("Failed to set keepalive minimum idle time on vdev %i : %d\n", |
361 | ret); | 364 | arvif->vdev_id, ret); |
362 | return ret; | 365 | return ret; |
363 | } | 366 | } |
364 | 367 | ||
@@ -366,8 +369,8 @@ static int ath10k_mac_set_kickout(struct ath10k_vif *arvif) | |||
366 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, param, | 369 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, param, |
367 | ATH10K_KEEPALIVE_MAX_IDLE); | 370 | ATH10K_KEEPALIVE_MAX_IDLE); |
368 | if (ret) { | 371 | if (ret) { |
369 | ath10k_warn("Failed to set keepalive maximum idle time: %d\n", | 372 | ath10k_warn("Failed to set keepalive maximum idle time on vdev %i: %d\n", |
370 | ret); | 373 | arvif->vdev_id, ret); |
371 | return ret; | 374 | return ret; |
372 | } | 375 | } |
373 | 376 | ||
@@ -375,8 +378,8 @@ static int ath10k_mac_set_kickout(struct ath10k_vif *arvif) | |||
375 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, param, | 378 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, param, |
376 | ATH10K_KEEPALIVE_MAX_UNRESPONSIVE); | 379 | ATH10K_KEEPALIVE_MAX_UNRESPONSIVE); |
377 | if (ret) { | 380 | if (ret) { |
378 | ath10k_warn("Failed to set keepalive maximum unresponsive time: %d\n", | 381 | ath10k_warn("Failed to set keepalive maximum unresponsive time on vdev %i: %d\n", |
379 | ret); | 382 | arvif->vdev_id, ret); |
380 | return ret; | 383 | return ret; |
381 | } | 384 | } |
382 | 385 | ||
@@ -529,13 +532,15 @@ static int ath10k_vdev_start(struct ath10k_vif *arvif) | |||
529 | 532 | ||
530 | ret = ath10k_wmi_vdev_start(ar, &arg); | 533 | ret = ath10k_wmi_vdev_start(ar, &arg); |
531 | if (ret) { | 534 | if (ret) { |
532 | ath10k_warn("WMI vdev start failed: ret %d\n", ret); | 535 | ath10k_warn("WMI vdev %i start failed: ret %d\n", |
536 | arg.vdev_id, ret); | ||
533 | return ret; | 537 | return ret; |
534 | } | 538 | } |
535 | 539 | ||
536 | ret = ath10k_vdev_setup_sync(ar); | 540 | ret = ath10k_vdev_setup_sync(ar); |
537 | if (ret) { | 541 | if (ret) { |
538 | ath10k_warn("vdev setup failed %d\n", ret); | 542 | ath10k_warn("vdev %i setup failed %d\n", |
543 | arg.vdev_id, ret); | ||
539 | return ret; | 544 | return ret; |
540 | } | 545 | } |
541 | 546 | ||
@@ -553,13 +558,15 @@ static int ath10k_vdev_stop(struct ath10k_vif *arvif) | |||
553 | 558 | ||
554 | ret = ath10k_wmi_vdev_stop(ar, arvif->vdev_id); | 559 | ret = ath10k_wmi_vdev_stop(ar, arvif->vdev_id); |
555 | if (ret) { | 560 | if (ret) { |
556 | ath10k_warn("WMI vdev stop failed: ret %d\n", ret); | 561 | ath10k_warn("WMI vdev %i stop failed: ret %d\n", |
562 | arvif->vdev_id, ret); | ||
557 | return ret; | 563 | return ret; |
558 | } | 564 | } |
559 | 565 | ||
560 | ret = ath10k_vdev_setup_sync(ar); | 566 | ret = ath10k_vdev_setup_sync(ar); |
561 | if (ret) { | 567 | if (ret) { |
562 | ath10k_warn("vdev setup failed %d\n", ret); | 568 | ath10k_warn("vdev %i setup sync failed %d\n", |
569 | arvif->vdev_id, ret); | ||
563 | return ret; | 570 | return ret; |
564 | } | 571 | } |
565 | 572 | ||
@@ -597,19 +604,22 @@ static int ath10k_monitor_start(struct ath10k *ar, int vdev_id) | |||
597 | 604 | ||
598 | ret = ath10k_wmi_vdev_start(ar, &arg); | 605 | ret = ath10k_wmi_vdev_start(ar, &arg); |
599 | if (ret) { | 606 | if (ret) { |
600 | ath10k_warn("Monitor vdev start failed: ret %d\n", ret); | 607 | ath10k_warn("Monitor vdev %i start failed: ret %d\n", |
608 | vdev_id, ret); | ||
601 | return ret; | 609 | return ret; |
602 | } | 610 | } |
603 | 611 | ||
604 | ret = ath10k_vdev_setup_sync(ar); | 612 | ret = ath10k_vdev_setup_sync(ar); |
605 | if (ret) { | 613 | if (ret) { |
606 | ath10k_warn("Monitor vdev setup failed %d\n", ret); | 614 | ath10k_warn("Monitor vdev %i setup failed %d\n", |
615 | vdev_id, ret); | ||
607 | return ret; | 616 | return ret; |
608 | } | 617 | } |
609 | 618 | ||
610 | ret = ath10k_wmi_vdev_up(ar, vdev_id, 0, ar->mac_addr); | 619 | ret = ath10k_wmi_vdev_up(ar, vdev_id, 0, ar->mac_addr); |
611 | if (ret) { | 620 | if (ret) { |
612 | ath10k_warn("Monitor vdev up failed: %d\n", ret); | 621 | ath10k_warn("Monitor vdev %i up failed: %d\n", |
622 | vdev_id, ret); | ||
613 | goto vdev_stop; | 623 | goto vdev_stop; |
614 | } | 624 | } |
615 | 625 | ||
@@ -621,7 +631,8 @@ static int ath10k_monitor_start(struct ath10k *ar, int vdev_id) | |||
621 | vdev_stop: | 631 | vdev_stop: |
622 | ret = ath10k_wmi_vdev_stop(ar, ar->monitor_vdev_id); | 632 | ret = ath10k_wmi_vdev_stop(ar, ar->monitor_vdev_id); |
623 | if (ret) | 633 | if (ret) |
624 | ath10k_warn("Monitor vdev stop failed: %d\n", ret); | 634 | ath10k_warn("Monitor vdev %i stop failed: %d\n", |
635 | ar->monitor_vdev_id, ret); | ||
625 | 636 | ||
626 | return ret; | 637 | return ret; |
627 | } | 638 | } |
@@ -644,15 +655,18 @@ static int ath10k_monitor_stop(struct ath10k *ar) | |||
644 | 655 | ||
645 | ret = ath10k_wmi_vdev_down(ar, ar->monitor_vdev_id); | 656 | ret = ath10k_wmi_vdev_down(ar, ar->monitor_vdev_id); |
646 | if (ret) | 657 | if (ret) |
647 | ath10k_warn("Monitor vdev down failed: %d\n", ret); | 658 | ath10k_warn("Monitor vdev %i down failed: %d\n", |
659 | ar->monitor_vdev_id, ret); | ||
648 | 660 | ||
649 | ret = ath10k_wmi_vdev_stop(ar, ar->monitor_vdev_id); | 661 | ret = ath10k_wmi_vdev_stop(ar, ar->monitor_vdev_id); |
650 | if (ret) | 662 | if (ret) |
651 | ath10k_warn("Monitor vdev stop failed: %d\n", ret); | 663 | ath10k_warn("Monitor vdev %i stop failed: %d\n", |
664 | ar->monitor_vdev_id, ret); | ||
652 | 665 | ||
653 | ret = ath10k_vdev_setup_sync(ar); | 666 | ret = ath10k_vdev_setup_sync(ar); |
654 | if (ret) | 667 | if (ret) |
655 | ath10k_warn("Monitor_down sync failed: %d\n", ret); | 668 | ath10k_warn("Monitor_down sync failed, vdev %i: %d\n", |
669 | ar->monitor_vdev_id, ret); | ||
656 | 670 | ||
657 | ar->monitor_enabled = false; | 671 | ar->monitor_enabled = false; |
658 | return ret; | 672 | return ret; |
@@ -682,7 +696,8 @@ static int ath10k_monitor_create(struct ath10k *ar) | |||
682 | WMI_VDEV_TYPE_MONITOR, | 696 | WMI_VDEV_TYPE_MONITOR, |
683 | 0, ar->mac_addr); | 697 | 0, ar->mac_addr); |
684 | if (ret) { | 698 | if (ret) { |
685 | ath10k_warn("WMI vdev monitor create failed: ret %d\n", ret); | 699 | ath10k_warn("WMI vdev %i monitor create failed: ret %d\n", |
700 | ar->monitor_vdev_id, ret); | ||
686 | goto vdev_fail; | 701 | goto vdev_fail; |
687 | } | 702 | } |
688 | 703 | ||
@@ -711,7 +726,8 @@ static int ath10k_monitor_destroy(struct ath10k *ar) | |||
711 | 726 | ||
712 | ret = ath10k_wmi_vdev_delete(ar, ar->monitor_vdev_id); | 727 | ret = ath10k_wmi_vdev_delete(ar, ar->monitor_vdev_id); |
713 | if (ret) { | 728 | if (ret) { |
714 | ath10k_warn("WMI vdev monitor delete failed: %d\n", ret); | 729 | ath10k_warn("WMI vdev %i monitor delete failed: %d\n", |
730 | ar->monitor_vdev_id, ret); | ||
715 | return ret; | 731 | return ret; |
716 | } | 732 | } |
717 | 733 | ||
@@ -839,7 +855,9 @@ static void ath10k_control_beaconing(struct ath10k_vif *arvif, | |||
839 | 855 | ||
840 | spin_lock_bh(&arvif->ar->data_lock); | 856 | spin_lock_bh(&arvif->ar->data_lock); |
841 | if (arvif->beacon) { | 857 | if (arvif->beacon) { |
842 | ath10k_skb_unmap(arvif->ar->dev, arvif->beacon); | 858 | dma_unmap_single(arvif->ar->dev, |
859 | ATH10K_SKB_CB(arvif->beacon)->paddr, | ||
860 | arvif->beacon->len, DMA_TO_DEVICE); | ||
843 | dev_kfree_skb_any(arvif->beacon); | 861 | dev_kfree_skb_any(arvif->beacon); |
844 | 862 | ||
845 | arvif->beacon = NULL; | 863 | arvif->beacon = NULL; |
@@ -862,8 +880,8 @@ static void ath10k_control_beaconing(struct ath10k_vif *arvif, | |||
862 | ret = ath10k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid, | 880 | ret = ath10k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid, |
863 | arvif->bssid); | 881 | arvif->bssid); |
864 | if (ret) { | 882 | if (ret) { |
865 | ath10k_warn("Failed to bring up VDEV: %d\n", | 883 | ath10k_warn("Failed to bring up vdev %d: %i\n", |
866 | arvif->vdev_id); | 884 | arvif->vdev_id, ret); |
867 | ath10k_vdev_stop(arvif); | 885 | ath10k_vdev_stop(arvif); |
868 | return; | 886 | return; |
869 | } | 887 | } |
@@ -943,8 +961,8 @@ static int ath10k_mac_vif_setup_ps(struct ath10k_vif *arvif) | |||
943 | ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, param, | 961 | ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, param, |
944 | conf->dynamic_ps_timeout); | 962 | conf->dynamic_ps_timeout); |
945 | if (ret) { | 963 | if (ret) { |
946 | ath10k_warn("Failed to set inactivity time for VDEV: %d\n", | 964 | ath10k_warn("Failed to set inactivity time for vdev %d: %i\n", |
947 | arvif->vdev_id); | 965 | arvif->vdev_id, ret); |
948 | return ret; | 966 | return ret; |
949 | } | 967 | } |
950 | } else { | 968 | } else { |
@@ -1196,8 +1214,8 @@ static int ath10k_peer_assoc_qos_ap(struct ath10k *ar, | |||
1196 | WMI_AP_PS_PEER_PARAM_UAPSD, | 1214 | WMI_AP_PS_PEER_PARAM_UAPSD, |
1197 | uapsd); | 1215 | uapsd); |
1198 | if (ret) { | 1216 | if (ret) { |
1199 | ath10k_warn("failed to set ap ps peer param uapsd: %d\n", | 1217 | ath10k_warn("failed to set ap ps peer param uapsd for vdev %i: %d\n", |
1200 | ret); | 1218 | arvif->vdev_id, ret); |
1201 | return ret; | 1219 | return ret; |
1202 | } | 1220 | } |
1203 | 1221 | ||
@@ -1206,8 +1224,8 @@ static int ath10k_peer_assoc_qos_ap(struct ath10k *ar, | |||
1206 | WMI_AP_PS_PEER_PARAM_MAX_SP, | 1224 | WMI_AP_PS_PEER_PARAM_MAX_SP, |
1207 | max_sp); | 1225 | max_sp); |
1208 | if (ret) { | 1226 | if (ret) { |
1209 | ath10k_warn("failed to set ap ps peer param max sp: %d\n", | 1227 | ath10k_warn("failed to set ap ps peer param max sp for vdev %i: %d\n", |
1210 | ret); | 1228 | arvif->vdev_id, ret); |
1211 | return ret; | 1229 | return ret; |
1212 | } | 1230 | } |
1213 | 1231 | ||
@@ -1218,8 +1236,8 @@ static int ath10k_peer_assoc_qos_ap(struct ath10k *ar, | |||
1218 | ret = ath10k_wmi_set_ap_ps_param(ar, arvif->vdev_id, sta->addr, | 1236 | ret = ath10k_wmi_set_ap_ps_param(ar, arvif->vdev_id, sta->addr, |
1219 | WMI_AP_PS_PEER_PARAM_AGEOUT_TIME, 10); | 1237 | WMI_AP_PS_PEER_PARAM_AGEOUT_TIME, 10); |
1220 | if (ret) { | 1238 | if (ret) { |
1221 | ath10k_warn("failed to set ap ps peer param ageout time: %d\n", | 1239 | ath10k_warn("failed to set ap ps peer param ageout time for vdev %i: %d\n", |
1222 | ret); | 1240 | arvif->vdev_id, ret); |
1223 | return ret; | 1241 | return ret; |
1224 | } | 1242 | } |
1225 | } | 1243 | } |
@@ -1411,8 +1429,8 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw, | |||
1411 | 1429 | ||
1412 | ap_sta = ieee80211_find_sta(vif, bss_conf->bssid); | 1430 | ap_sta = ieee80211_find_sta(vif, bss_conf->bssid); |
1413 | if (!ap_sta) { | 1431 | if (!ap_sta) { |
1414 | ath10k_warn("Failed to find station entry for %pM\n", | 1432 | ath10k_warn("Failed to find station entry for %pM, vdev %i\n", |
1415 | bss_conf->bssid); | 1433 | bss_conf->bssid, arvif->vdev_id); |
1416 | rcu_read_unlock(); | 1434 | rcu_read_unlock(); |
1417 | return; | 1435 | return; |
1418 | } | 1436 | } |
@@ -1424,8 +1442,8 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw, | |||
1424 | ret = ath10k_peer_assoc_prepare(ar, arvif, ap_sta, | 1442 | ret = ath10k_peer_assoc_prepare(ar, arvif, ap_sta, |
1425 | bss_conf, &peer_arg); | 1443 | bss_conf, &peer_arg); |
1426 | if (ret) { | 1444 | if (ret) { |
1427 | ath10k_warn("Peer assoc prepare failed for %pM\n: %d", | 1445 | ath10k_warn("Peer assoc prepare failed for %pM vdev %i\n: %d", |
1428 | bss_conf->bssid, ret); | 1446 | bss_conf->bssid, arvif->vdev_id, ret); |
1429 | rcu_read_unlock(); | 1447 | rcu_read_unlock(); |
1430 | return; | 1448 | return; |
1431 | } | 1449 | } |
@@ -1434,14 +1452,15 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw, | |||
1434 | 1452 | ||
1435 | ret = ath10k_wmi_peer_assoc(ar, &peer_arg); | 1453 | ret = ath10k_wmi_peer_assoc(ar, &peer_arg); |
1436 | if (ret) { | 1454 | if (ret) { |
1437 | ath10k_warn("Peer assoc failed for %pM\n: %d", | 1455 | ath10k_warn("Peer assoc failed for %pM vdev %i\n: %d", |
1438 | bss_conf->bssid, ret); | 1456 | bss_conf->bssid, arvif->vdev_id, ret); |
1439 | return; | 1457 | return; |
1440 | } | 1458 | } |
1441 | 1459 | ||
1442 | ret = ath10k_setup_peer_smps(ar, arvif, bss_conf->bssid, &ht_cap); | 1460 | ret = ath10k_setup_peer_smps(ar, arvif, bss_conf->bssid, &ht_cap); |
1443 | if (ret) { | 1461 | if (ret) { |
1444 | ath10k_warn("failed to setup peer SMPS: %d\n", ret); | 1462 | ath10k_warn("failed to setup peer SMPS for vdev %i: %d\n", |
1463 | arvif->vdev_id, ret); | ||
1445 | return; | 1464 | return; |
1446 | } | 1465 | } |
1447 | 1466 | ||
@@ -1514,34 +1533,35 @@ static int ath10k_station_assoc(struct ath10k *ar, struct ath10k_vif *arvif, | |||
1514 | 1533 | ||
1515 | ret = ath10k_peer_assoc_prepare(ar, arvif, sta, NULL, &peer_arg); | 1534 | ret = ath10k_peer_assoc_prepare(ar, arvif, sta, NULL, &peer_arg); |
1516 | if (ret) { | 1535 | if (ret) { |
1517 | ath10k_warn("WMI peer assoc prepare failed for %pM\n", | 1536 | ath10k_warn("WMI peer assoc prepare failed for %pM vdev %i: %i\n", |
1518 | sta->addr); | 1537 | sta->addr, arvif->vdev_id, ret); |
1519 | return ret; | 1538 | return ret; |
1520 | } | 1539 | } |
1521 | 1540 | ||
1522 | ret = ath10k_wmi_peer_assoc(ar, &peer_arg); | 1541 | ret = ath10k_wmi_peer_assoc(ar, &peer_arg); |
1523 | if (ret) { | 1542 | if (ret) { |
1524 | ath10k_warn("Peer assoc failed for STA %pM\n: %d", | 1543 | ath10k_warn("Peer assoc failed for STA %pM vdev %i: %d\n", |
1525 | sta->addr, ret); | 1544 | sta->addr, arvif->vdev_id, ret); |
1526 | return ret; | 1545 | return ret; |
1527 | } | 1546 | } |
1528 | 1547 | ||
1529 | ret = ath10k_setup_peer_smps(ar, arvif, sta->addr, &sta->ht_cap); | 1548 | ret = ath10k_setup_peer_smps(ar, arvif, sta->addr, &sta->ht_cap); |
1530 | if (ret) { | 1549 | if (ret) { |
1531 | ath10k_warn("failed to setup peer SMPS: %d\n", ret); | 1550 | ath10k_warn("failed to setup peer SMPS for vdev: %d\n", ret); |
1532 | return ret; | 1551 | return ret; |
1533 | } | 1552 | } |
1534 | 1553 | ||
1535 | ret = ath10k_install_peer_wep_keys(arvif, sta->addr); | 1554 | ret = ath10k_install_peer_wep_keys(arvif, sta->addr); |
1536 | if (ret) { | 1555 | if (ret) { |
1537 | ath10k_warn("could not install peer wep keys (%d)\n", ret); | 1556 | ath10k_warn("could not install peer wep keys for vdev %i: %d\n", |
1557 | arvif->vdev_id, ret); | ||
1538 | return ret; | 1558 | return ret; |
1539 | } | 1559 | } |
1540 | 1560 | ||
1541 | ret = ath10k_peer_assoc_qos_ap(ar, arvif, sta); | 1561 | ret = ath10k_peer_assoc_qos_ap(ar, arvif, sta); |
1542 | if (ret) { | 1562 | if (ret) { |
1543 | ath10k_warn("could not set qos params for STA %pM, %d\n", | 1563 | ath10k_warn("could not set qos params for STA %pM for vdev %i: %d\n", |
1544 | sta->addr, ret); | 1564 | sta->addr, arvif->vdev_id, ret); |
1545 | return ret; | 1565 | return ret; |
1546 | } | 1566 | } |
1547 | 1567 | ||
@@ -1557,7 +1577,8 @@ static int ath10k_station_disassoc(struct ath10k *ar, struct ath10k_vif *arvif, | |||
1557 | 1577 | ||
1558 | ret = ath10k_clear_peer_keys(arvif, sta->addr); | 1578 | ret = ath10k_clear_peer_keys(arvif, sta->addr); |
1559 | if (ret) { | 1579 | if (ret) { |
1560 | ath10k_warn("could not clear all peer wep keys (%d)\n", ret); | 1580 | ath10k_warn("could not clear all peer wep keys for vdev %i: %d\n", |
1581 | arvif->vdev_id, ret); | ||
1561 | return ret; | 1582 | return ret; |
1562 | } | 1583 | } |
1563 | 1584 | ||
@@ -2524,7 +2545,8 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, | |||
2524 | ret = ath10k_wmi_vdev_create(ar, arvif->vdev_id, arvif->vdev_type, | 2545 | ret = ath10k_wmi_vdev_create(ar, arvif->vdev_id, arvif->vdev_type, |
2525 | arvif->vdev_subtype, vif->addr); | 2546 | arvif->vdev_subtype, vif->addr); |
2526 | if (ret) { | 2547 | if (ret) { |
2527 | ath10k_warn("WMI vdev create failed: ret %d\n", ret); | 2548 | ath10k_warn("WMI vdev %i create failed: ret %d\n", |
2549 | arvif->vdev_id, ret); | ||
2528 | goto err; | 2550 | goto err; |
2529 | } | 2551 | } |
2530 | 2552 | ||
@@ -2535,7 +2557,8 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, | |||
2535 | ret = ath10k_wmi_vdev_set_param(ar, 0, vdev_param, | 2557 | ret = ath10k_wmi_vdev_set_param(ar, 0, vdev_param, |
2536 | arvif->def_wep_key_idx); | 2558 | arvif->def_wep_key_idx); |
2537 | if (ret) { | 2559 | if (ret) { |
2538 | ath10k_warn("Failed to set default keyid: %d\n", ret); | 2560 | ath10k_warn("Failed to set vdev %i default keyid: %d\n", |
2561 | arvif->vdev_id, ret); | ||
2539 | goto err_vdev_delete; | 2562 | goto err_vdev_delete; |
2540 | } | 2563 | } |
2541 | 2564 | ||
@@ -2544,21 +2567,23 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, | |||
2544 | ATH10K_HW_TXRX_NATIVE_WIFI); | 2567 | ATH10K_HW_TXRX_NATIVE_WIFI); |
2545 | /* 10.X firmware does not support this VDEV parameter. Do not warn */ | 2568 | /* 10.X firmware does not support this VDEV parameter. Do not warn */ |
2546 | if (ret && ret != -EOPNOTSUPP) { | 2569 | if (ret && ret != -EOPNOTSUPP) { |
2547 | ath10k_warn("Failed to set TX encap: %d\n", ret); | 2570 | ath10k_warn("Failed to set vdev %i TX encap: %d\n", |
2571 | arvif->vdev_id, ret); | ||
2548 | goto err_vdev_delete; | 2572 | goto err_vdev_delete; |
2549 | } | 2573 | } |
2550 | 2574 | ||
2551 | if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { | 2575 | if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { |
2552 | ret = ath10k_peer_create(ar, arvif->vdev_id, vif->addr); | 2576 | ret = ath10k_peer_create(ar, arvif->vdev_id, vif->addr); |
2553 | if (ret) { | 2577 | if (ret) { |
2554 | ath10k_warn("Failed to create peer for AP: %d\n", ret); | 2578 | ath10k_warn("Failed to create vdev %i peer for AP: %d\n", |
2579 | arvif->vdev_id, ret); | ||
2555 | goto err_vdev_delete; | 2580 | goto err_vdev_delete; |
2556 | } | 2581 | } |
2557 | 2582 | ||
2558 | ret = ath10k_mac_set_kickout(arvif); | 2583 | ret = ath10k_mac_set_kickout(arvif); |
2559 | if (ret) { | 2584 | if (ret) { |
2560 | ath10k_warn("Failed to set kickout parameters: %d\n", | 2585 | ath10k_warn("Failed to set vdev %i kickout parameters: %d\n", |
2561 | ret); | 2586 | arvif->vdev_id, ret); |
2562 | goto err_peer_delete; | 2587 | goto err_peer_delete; |
2563 | } | 2588 | } |
2564 | } | 2589 | } |
@@ -2569,7 +2594,8 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, | |||
2569 | ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, | 2594 | ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, |
2570 | param, value); | 2595 | param, value); |
2571 | if (ret) { | 2596 | if (ret) { |
2572 | ath10k_warn("Failed to set RX wake policy: %d\n", ret); | 2597 | ath10k_warn("Failed to set vdev %i RX wake policy: %d\n", |
2598 | arvif->vdev_id, ret); | ||
2573 | goto err_peer_delete; | 2599 | goto err_peer_delete; |
2574 | } | 2600 | } |
2575 | 2601 | ||
@@ -2578,7 +2604,8 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, | |||
2578 | ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, | 2604 | ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, |
2579 | param, value); | 2605 | param, value); |
2580 | if (ret) { | 2606 | if (ret) { |
2581 | ath10k_warn("Failed to set TX wake thresh: %d\n", ret); | 2607 | ath10k_warn("Failed to set vdev %i TX wake thresh: %d\n", |
2608 | arvif->vdev_id, ret); | ||
2582 | goto err_peer_delete; | 2609 | goto err_peer_delete; |
2583 | } | 2610 | } |
2584 | 2611 | ||
@@ -2587,7 +2614,8 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, | |||
2587 | ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, | 2614 | ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, |
2588 | param, value); | 2615 | param, value); |
2589 | if (ret) { | 2616 | if (ret) { |
2590 | ath10k_warn("Failed to set PSPOLL count: %d\n", ret); | 2617 | ath10k_warn("Failed to set vdev %i PSPOLL count: %d\n", |
2618 | arvif->vdev_id, ret); | ||
2591 | goto err_peer_delete; | 2619 | goto err_peer_delete; |
2592 | } | 2620 | } |
2593 | } | 2621 | } |
@@ -2651,17 +2679,19 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw, | |||
2651 | if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { | 2679 | if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { |
2652 | ret = ath10k_peer_delete(arvif->ar, arvif->vdev_id, vif->addr); | 2680 | ret = ath10k_peer_delete(arvif->ar, arvif->vdev_id, vif->addr); |
2653 | if (ret) | 2681 | if (ret) |
2654 | ath10k_warn("Failed to remove peer for AP: %d\n", ret); | 2682 | ath10k_warn("Failed to remove peer for AP vdev %i: %d\n", |
2683 | arvif->vdev_id, ret); | ||
2655 | 2684 | ||
2656 | kfree(arvif->u.ap.noa_data); | 2685 | kfree(arvif->u.ap.noa_data); |
2657 | } | 2686 | } |
2658 | 2687 | ||
2659 | ath10k_dbg(ATH10K_DBG_MAC, "mac vdev delete %d (remove interface)\n", | 2688 | ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %i delete (remove interface)\n", |
2660 | arvif->vdev_id); | 2689 | arvif->vdev_id); |
2661 | 2690 | ||
2662 | ret = ath10k_wmi_vdev_delete(ar, arvif->vdev_id); | 2691 | ret = ath10k_wmi_vdev_delete(ar, arvif->vdev_id); |
2663 | if (ret) | 2692 | if (ret) |
2664 | ath10k_warn("WMI vdev delete failed: %d\n", ret); | 2693 | ath10k_warn("WMI vdev %i delete failed: %d\n", |
2694 | arvif->vdev_id, ret); | ||
2665 | 2695 | ||
2666 | if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) | 2696 | if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) |
2667 | ar->monitor_present = false; | 2697 | ar->monitor_present = false; |
@@ -2750,8 +2780,8 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, | |||
2750 | arvif->vdev_id, arvif->beacon_interval); | 2780 | arvif->vdev_id, arvif->beacon_interval); |
2751 | 2781 | ||
2752 | if (ret) | 2782 | if (ret) |
2753 | ath10k_warn("Failed to set beacon interval for VDEV: %d\n", | 2783 | ath10k_warn("Failed to set beacon interval for vdev %d: %i\n", |
2754 | arvif->vdev_id); | 2784 | arvif->vdev_id, ret); |
2755 | } | 2785 | } |
2756 | 2786 | ||
2757 | if (changed & BSS_CHANGED_BEACON) { | 2787 | if (changed & BSS_CHANGED_BEACON) { |
@@ -2763,8 +2793,8 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, | |||
2763 | ret = ath10k_wmi_pdev_set_param(ar, pdev_param, | 2793 | ret = ath10k_wmi_pdev_set_param(ar, pdev_param, |
2764 | WMI_BEACON_STAGGERED_MODE); | 2794 | WMI_BEACON_STAGGERED_MODE); |
2765 | if (ret) | 2795 | if (ret) |
2766 | ath10k_warn("Failed to set beacon mode for VDEV: %d\n", | 2796 | ath10k_warn("Failed to set beacon mode for vdev %d: %i\n", |
2767 | arvif->vdev_id); | 2797 | arvif->vdev_id, ret); |
2768 | } | 2798 | } |
2769 | 2799 | ||
2770 | if (changed & BSS_CHANGED_BEACON_INFO) { | 2800 | if (changed & BSS_CHANGED_BEACON_INFO) { |
@@ -2778,8 +2808,8 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, | |||
2778 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, | 2808 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, |
2779 | arvif->dtim_period); | 2809 | arvif->dtim_period); |
2780 | if (ret) | 2810 | if (ret) |
2781 | ath10k_warn("Failed to set dtim period for VDEV: %d\n", | 2811 | ath10k_warn("Failed to set dtim period for vdev %d: %i\n", |
2782 | arvif->vdev_id); | 2812 | arvif->vdev_id, ret); |
2783 | } | 2813 | } |
2784 | 2814 | ||
2785 | if (changed & BSS_CHANGED_SSID && | 2815 | if (changed & BSS_CHANGED_SSID && |
@@ -2799,7 +2829,7 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, | |||
2799 | ret = ath10k_peer_create(ar, arvif->vdev_id, | 2829 | ret = ath10k_peer_create(ar, arvif->vdev_id, |
2800 | info->bssid); | 2830 | info->bssid); |
2801 | if (ret) | 2831 | if (ret) |
2802 | ath10k_warn("Failed to add peer %pM for vdev %d when changin bssid: %i\n", | 2832 | ath10k_warn("Failed to add peer %pM for vdev %d when changing bssid: %i\n", |
2803 | info->bssid, arvif->vdev_id, ret); | 2833 | info->bssid, arvif->vdev_id, ret); |
2804 | 2834 | ||
2805 | if (vif->type == NL80211_IFTYPE_STATION) { | 2835 | if (vif->type == NL80211_IFTYPE_STATION) { |
@@ -2815,8 +2845,8 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, | |||
2815 | 2845 | ||
2816 | ret = ath10k_vdev_start(arvif); | 2846 | ret = ath10k_vdev_start(arvif); |
2817 | if (ret) { | 2847 | if (ret) { |
2818 | ath10k_warn("failed to start vdev: %d\n", | 2848 | ath10k_warn("failed to start vdev %i: %d\n", |
2819 | ret); | 2849 | arvif->vdev_id, ret); |
2820 | goto exit; | 2850 | goto exit; |
2821 | } | 2851 | } |
2822 | 2852 | ||
@@ -2851,8 +2881,8 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, | |||
2851 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, | 2881 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, |
2852 | cts_prot); | 2882 | cts_prot); |
2853 | if (ret) | 2883 | if (ret) |
2854 | ath10k_warn("Failed to set CTS prot for VDEV: %d\n", | 2884 | ath10k_warn("Failed to set CTS prot for vdev %d: %d\n", |
2855 | arvif->vdev_id); | 2885 | arvif->vdev_id, ret); |
2856 | } | 2886 | } |
2857 | 2887 | ||
2858 | if (changed & BSS_CHANGED_ERP_SLOT) { | 2888 | if (changed & BSS_CHANGED_ERP_SLOT) { |
@@ -2870,8 +2900,8 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, | |||
2870 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, | 2900 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, |
2871 | slottime); | 2901 | slottime); |
2872 | if (ret) | 2902 | if (ret) |
2873 | ath10k_warn("Failed to set erp slot for VDEV: %d\n", | 2903 | ath10k_warn("Failed to set erp slot for vdev %d: %i\n", |
2874 | arvif->vdev_id); | 2904 | arvif->vdev_id, ret); |
2875 | } | 2905 | } |
2876 | 2906 | ||
2877 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { | 2907 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { |
@@ -2889,8 +2919,8 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, | |||
2889 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, | 2919 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, |
2890 | preamble); | 2920 | preamble); |
2891 | if (ret) | 2921 | if (ret) |
2892 | ath10k_warn("Failed to set preamble for VDEV: %d\n", | 2922 | ath10k_warn("Failed to set preamble for vdev %d: %i\n", |
2893 | arvif->vdev_id); | 2923 | arvif->vdev_id, ret); |
2894 | } | 2924 | } |
2895 | 2925 | ||
2896 | if (changed & BSS_CHANGED_ASSOC) { | 2926 | if (changed & BSS_CHANGED_ASSOC) { |
@@ -3021,8 +3051,8 @@ static void ath10k_set_key_h_def_keyidx(struct ath10k *ar, | |||
3021 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, | 3051 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, |
3022 | key->keyidx); | 3052 | key->keyidx); |
3023 | if (ret) | 3053 | if (ret) |
3024 | ath10k_warn("failed to set group key as default key: %d\n", | 3054 | ath10k_warn("failed to set vdev %i group key as default key: %d\n", |
3025 | ret); | 3055 | arvif->vdev_id, ret); |
3026 | } | 3056 | } |
3027 | 3057 | ||
3028 | static int ath10k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | 3058 | static int ath10k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, |
@@ -3082,7 +3112,8 @@ static int ath10k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3082 | 3112 | ||
3083 | ret = ath10k_install_key(arvif, key, cmd, peer_addr); | 3113 | ret = ath10k_install_key(arvif, key, cmd, peer_addr); |
3084 | if (ret) { | 3114 | if (ret) { |
3085 | ath10k_warn("ath10k_install_key failed (%d)\n", ret); | 3115 | ath10k_warn("key installation failed for vdev %i peer %pM: %d\n", |
3116 | arvif->vdev_id, peer_addr, ret); | ||
3086 | goto exit; | 3117 | goto exit; |
3087 | } | 3118 | } |
3088 | 3119 | ||
@@ -3179,6 +3210,13 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, | |||
3179 | int max_num_peers; | 3210 | int max_num_peers; |
3180 | int ret = 0; | 3211 | int ret = 0; |
3181 | 3212 | ||
3213 | if (old_state == IEEE80211_STA_NOTEXIST && | ||
3214 | new_state == IEEE80211_STA_NONE) { | ||
3215 | memset(arsta, 0, sizeof(*arsta)); | ||
3216 | arsta->arvif = arvif; | ||
3217 | INIT_WORK(&arsta->update_wk, ath10k_sta_rc_update_wk); | ||
3218 | } | ||
3219 | |||
3182 | /* cancel must be done outside the mutex to avoid deadlock */ | 3220 | /* cancel must be done outside the mutex to avoid deadlock */ |
3183 | if ((old_state == IEEE80211_STA_NONE && | 3221 | if ((old_state == IEEE80211_STA_NONE && |
3184 | new_state == IEEE80211_STA_NOTEXIST)) | 3222 | new_state == IEEE80211_STA_NOTEXIST)) |
@@ -3208,10 +3246,6 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, | |||
3208 | "mac vdev %d peer create %pM (new sta) num_peers %d\n", | 3246 | "mac vdev %d peer create %pM (new sta) num_peers %d\n", |
3209 | arvif->vdev_id, sta->addr, ar->num_peers); | 3247 | arvif->vdev_id, sta->addr, ar->num_peers); |
3210 | 3248 | ||
3211 | memset(arsta, 0, sizeof(*arsta)); | ||
3212 | arsta->arvif = arvif; | ||
3213 | INIT_WORK(&arsta->update_wk, ath10k_sta_rc_update_wk); | ||
3214 | |||
3215 | ret = ath10k_peer_create(ar, arvif->vdev_id, sta->addr); | 3249 | ret = ath10k_peer_create(ar, arvif->vdev_id, sta->addr); |
3216 | if (ret) | 3250 | if (ret) |
3217 | ath10k_warn("Failed to add peer %pM for vdev %d when adding a new sta: %i\n", | 3251 | ath10k_warn("Failed to add peer %pM for vdev %d when adding a new sta: %i\n", |
@@ -3226,8 +3260,8 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, | |||
3226 | arvif->vdev_id, sta->addr); | 3260 | arvif->vdev_id, sta->addr); |
3227 | ret = ath10k_peer_delete(ar, arvif->vdev_id, sta->addr); | 3261 | ret = ath10k_peer_delete(ar, arvif->vdev_id, sta->addr); |
3228 | if (ret) | 3262 | if (ret) |
3229 | ath10k_warn("Failed to delete peer: %pM for VDEV: %d\n", | 3263 | ath10k_warn("Failed to delete peer %pM for vdev %d: %i\n", |
3230 | sta->addr, arvif->vdev_id); | 3264 | sta->addr, arvif->vdev_id, ret); |
3231 | 3265 | ||
3232 | if (vif->type == NL80211_IFTYPE_STATION) | 3266 | if (vif->type == NL80211_IFTYPE_STATION) |
3233 | ath10k_bss_disassoc(hw, vif); | 3267 | ath10k_bss_disassoc(hw, vif); |
@@ -3243,8 +3277,8 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, | |||
3243 | 3277 | ||
3244 | ret = ath10k_station_assoc(ar, arvif, sta); | 3278 | ret = ath10k_station_assoc(ar, arvif, sta); |
3245 | if (ret) | 3279 | if (ret) |
3246 | ath10k_warn("Failed to associate station: %pM\n", | 3280 | ath10k_warn("Failed to associate station %pM for vdev %i: %i\n", |
3247 | sta->addr); | 3281 | sta->addr, arvif->vdev_id, ret); |
3248 | } else if (old_state == IEEE80211_STA_ASSOC && | 3282 | } else if (old_state == IEEE80211_STA_ASSOC && |
3249 | new_state == IEEE80211_STA_AUTH && | 3283 | new_state == IEEE80211_STA_AUTH && |
3250 | (vif->type == NL80211_IFTYPE_AP || | 3284 | (vif->type == NL80211_IFTYPE_AP || |
@@ -3257,8 +3291,8 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, | |||
3257 | 3291 | ||
3258 | ret = ath10k_station_disassoc(ar, arvif, sta); | 3292 | ret = ath10k_station_disassoc(ar, arvif, sta); |
3259 | if (ret) | 3293 | if (ret) |
3260 | ath10k_warn("Failed to disassociate station: %pM\n", | 3294 | ath10k_warn("Failed to disassociate station: %pM vdev %i ret %i\n", |
3261 | sta->addr); | 3295 | sta->addr, arvif->vdev_id, ret); |
3262 | } | 3296 | } |
3263 | exit: | 3297 | exit: |
3264 | mutex_unlock(&ar->conf_mutex); | 3298 | mutex_unlock(&ar->conf_mutex); |
@@ -3539,7 +3573,8 @@ static void ath10k_flush(struct ieee80211_hw *hw, u32 queues, bool drop) | |||
3539 | }), ATH10K_FLUSH_TIMEOUT_HZ); | 3573 | }), ATH10K_FLUSH_TIMEOUT_HZ); |
3540 | 3574 | ||
3541 | if (ret <= 0 || skip) | 3575 | if (ret <= 0 || skip) |
3542 | ath10k_warn("tx not flushed\n"); | 3576 | ath10k_warn("tx not flushed (skip %i ar-state %i): %i\n", |
3577 | skip, ar->state, ret); | ||
3543 | 3578 | ||
3544 | skip: | 3579 | skip: |
3545 | mutex_unlock(&ar->conf_mutex); | 3580 | mutex_unlock(&ar->conf_mutex); |
@@ -3905,7 +3940,8 @@ static bool ath10k_get_fixed_rate_nss(const struct cfg80211_bitrate_mask *mask, | |||
3905 | 3940 | ||
3906 | static int ath10k_set_fixed_rate_param(struct ath10k_vif *arvif, | 3941 | static int ath10k_set_fixed_rate_param(struct ath10k_vif *arvif, |
3907 | u8 fixed_rate, | 3942 | u8 fixed_rate, |
3908 | u8 fixed_nss) | 3943 | u8 fixed_nss, |
3944 | u8 force_sgi) | ||
3909 | { | 3945 | { |
3910 | struct ath10k *ar = arvif->ar; | 3946 | struct ath10k *ar = arvif->ar; |
3911 | u32 vdev_param; | 3947 | u32 vdev_param; |
@@ -3914,12 +3950,16 @@ static int ath10k_set_fixed_rate_param(struct ath10k_vif *arvif, | |||
3914 | mutex_lock(&ar->conf_mutex); | 3950 | mutex_lock(&ar->conf_mutex); |
3915 | 3951 | ||
3916 | if (arvif->fixed_rate == fixed_rate && | 3952 | if (arvif->fixed_rate == fixed_rate && |
3917 | arvif->fixed_nss == fixed_nss) | 3953 | arvif->fixed_nss == fixed_nss && |
3954 | arvif->force_sgi == force_sgi) | ||
3918 | goto exit; | 3955 | goto exit; |
3919 | 3956 | ||
3920 | if (fixed_rate == WMI_FIXED_RATE_NONE) | 3957 | if (fixed_rate == WMI_FIXED_RATE_NONE) |
3921 | ath10k_dbg(ATH10K_DBG_MAC, "mac disable fixed bitrate mask\n"); | 3958 | ath10k_dbg(ATH10K_DBG_MAC, "mac disable fixed bitrate mask\n"); |
3922 | 3959 | ||
3960 | if (force_sgi) | ||
3961 | ath10k_dbg(ATH10K_DBG_MAC, "mac force sgi\n"); | ||
3962 | |||
3923 | vdev_param = ar->wmi.vdev_param->fixed_rate; | 3963 | vdev_param = ar->wmi.vdev_param->fixed_rate; |
3924 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, | 3964 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, |
3925 | vdev_param, fixed_rate); | 3965 | vdev_param, fixed_rate); |
@@ -3945,6 +3985,19 @@ static int ath10k_set_fixed_rate_param(struct ath10k_vif *arvif, | |||
3945 | 3985 | ||
3946 | arvif->fixed_nss = fixed_nss; | 3986 | arvif->fixed_nss = fixed_nss; |
3947 | 3987 | ||
3988 | vdev_param = ar->wmi.vdev_param->sgi; | ||
3989 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, | ||
3990 | force_sgi); | ||
3991 | |||
3992 | if (ret) { | ||
3993 | ath10k_warn("Could not set sgi param %d: %d\n", | ||
3994 | force_sgi, ret); | ||
3995 | ret = -EINVAL; | ||
3996 | goto exit; | ||
3997 | } | ||
3998 | |||
3999 | arvif->force_sgi = force_sgi; | ||
4000 | |||
3948 | exit: | 4001 | exit: |
3949 | mutex_unlock(&ar->conf_mutex); | 4002 | mutex_unlock(&ar->conf_mutex); |
3950 | return ret; | 4003 | return ret; |
@@ -3959,6 +4012,11 @@ static int ath10k_set_bitrate_mask(struct ieee80211_hw *hw, | |||
3959 | enum ieee80211_band band = ar->hw->conf.chandef.chan->band; | 4012 | enum ieee80211_band band = ar->hw->conf.chandef.chan->band; |
3960 | u8 fixed_rate = WMI_FIXED_RATE_NONE; | 4013 | u8 fixed_rate = WMI_FIXED_RATE_NONE; |
3961 | u8 fixed_nss = ar->num_rf_chains; | 4014 | u8 fixed_nss = ar->num_rf_chains; |
4015 | u8 force_sgi; | ||
4016 | |||
4017 | force_sgi = mask->control[band].gi; | ||
4018 | if (force_sgi == NL80211_TXRATE_FORCE_LGI) | ||
4019 | return -EINVAL; | ||
3962 | 4020 | ||
3963 | if (!ath10k_default_bitrate_mask(ar, band, mask)) { | 4021 | if (!ath10k_default_bitrate_mask(ar, band, mask)) { |
3964 | if (!ath10k_get_fixed_rate_nss(mask, band, | 4022 | if (!ath10k_get_fixed_rate_nss(mask, band, |
@@ -3967,7 +4025,13 @@ static int ath10k_set_bitrate_mask(struct ieee80211_hw *hw, | |||
3967 | return -EINVAL; | 4025 | return -EINVAL; |
3968 | } | 4026 | } |
3969 | 4027 | ||
3970 | return ath10k_set_fixed_rate_param(arvif, fixed_rate, fixed_nss); | 4028 | if (fixed_rate == WMI_FIXED_RATE_NONE && force_sgi) { |
4029 | ath10k_warn("Could not force SGI usage for default rate settings\n"); | ||
4030 | return -EINVAL; | ||
4031 | } | ||
4032 | |||
4033 | return ath10k_set_fixed_rate_param(arvif, fixed_rate, | ||
4034 | fixed_nss, force_sgi); | ||
3971 | } | 4035 | } |
3972 | 4036 | ||
3973 | static void ath10k_channel_switch_beacon(struct ieee80211_hw *hw, | 4037 | static void ath10k_channel_switch_beacon(struct ieee80211_hw *hw, |
@@ -4060,6 +4124,16 @@ static void ath10k_sta_rc_update(struct ieee80211_hw *hw, | |||
4060 | ieee80211_queue_work(hw, &arsta->update_wk); | 4124 | ieee80211_queue_work(hw, &arsta->update_wk); |
4061 | } | 4125 | } |
4062 | 4126 | ||
4127 | static u64 ath10k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | ||
4128 | { | ||
4129 | /* | ||
4130 | * FIXME: Return 0 for time being. Need to figure out whether FW | ||
4131 | * has the API to fetch 64-bit local TSF | ||
4132 | */ | ||
4133 | |||
4134 | return 0; | ||
4135 | } | ||
4136 | |||
4063 | static const struct ieee80211_ops ath10k_ops = { | 4137 | static const struct ieee80211_ops ath10k_ops = { |
4064 | .tx = ath10k_tx, | 4138 | .tx = ath10k_tx, |
4065 | .start = ath10k_start, | 4139 | .start = ath10k_start, |
@@ -4085,6 +4159,7 @@ static const struct ieee80211_ops ath10k_ops = { | |||
4085 | .set_bitrate_mask = ath10k_set_bitrate_mask, | 4159 | .set_bitrate_mask = ath10k_set_bitrate_mask, |
4086 | .channel_switch_beacon = ath10k_channel_switch_beacon, | 4160 | .channel_switch_beacon = ath10k_channel_switch_beacon, |
4087 | .sta_rc_update = ath10k_sta_rc_update, | 4161 | .sta_rc_update = ath10k_sta_rc_update, |
4162 | .get_tsf = ath10k_get_tsf, | ||
4088 | #ifdef CONFIG_PM | 4163 | #ifdef CONFIG_PM |
4089 | .suspend = ath10k_suspend, | 4164 | .suspend = ath10k_suspend, |
4090 | .resume = ath10k_resume, | 4165 | .resume = ath10k_resume, |
@@ -4361,7 +4436,7 @@ struct ath10k_vif *ath10k_get_arvif(struct ath10k *ar, u32 vdev_id) | |||
4361 | ath10k_get_arvif_iter, | 4436 | ath10k_get_arvif_iter, |
4362 | &arvif_iter); | 4437 | &arvif_iter); |
4363 | if (!arvif_iter.arvif) { | 4438 | if (!arvif_iter.arvif) { |
4364 | ath10k_warn("No VIF found for VDEV: %d\n", vdev_id); | 4439 | ath10k_warn("No VIF found for vdev %d\n", vdev_id); |
4365 | return NULL; | 4440 | return NULL; |
4366 | } | 4441 | } |
4367 | 4442 | ||
@@ -4442,7 +4517,8 @@ int ath10k_mac_register(struct ath10k *ar) | |||
4442 | IEEE80211_HW_HAS_RATE_CONTROL | | 4517 | IEEE80211_HW_HAS_RATE_CONTROL | |
4443 | IEEE80211_HW_SUPPORTS_STATIC_SMPS | | 4518 | IEEE80211_HW_SUPPORTS_STATIC_SMPS | |
4444 | IEEE80211_HW_WANT_MONITOR_VIF | | 4519 | IEEE80211_HW_WANT_MONITOR_VIF | |
4445 | IEEE80211_HW_AP_LINK_PS; | 4520 | IEEE80211_HW_AP_LINK_PS | |
4521 | IEEE80211_HW_SPECTRUM_MGMT; | ||
4446 | 4522 | ||
4447 | /* MSDU can have HTT TX fragment pushed in front. The additional 4 | 4523 | /* MSDU can have HTT TX fragment pushed in front. The additional 4 |
4448 | * bytes is used for padding/alignment if necessary. */ | 4524 | * bytes is used for padding/alignment if necessary. */ |
@@ -4500,7 +4576,7 @@ int ath10k_mac_register(struct ath10k *ar) | |||
4500 | ret = ath_regd_init(&ar->ath_common.regulatory, ar->hw->wiphy, | 4576 | ret = ath_regd_init(&ar->ath_common.regulatory, ar->hw->wiphy, |
4501 | ath10k_reg_notifier); | 4577 | ath10k_reg_notifier); |
4502 | if (ret) { | 4578 | if (ret) { |
4503 | ath10k_err("Regulatory initialization failed\n"); | 4579 | ath10k_err("Regulatory initialization failed: %i\n", ret); |
4504 | goto err_free; | 4580 | goto err_free; |
4505 | } | 4581 | } |
4506 | 4582 | ||
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 34f09106f423..9d242d801d9d 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c | |||
@@ -58,12 +58,10 @@ static DEFINE_PCI_DEVICE_TABLE(ath10k_pci_id_table) = { | |||
58 | static int ath10k_pci_diag_read_access(struct ath10k *ar, u32 address, | 58 | static int ath10k_pci_diag_read_access(struct ath10k *ar, u32 address, |
59 | u32 *data); | 59 | u32 *data); |
60 | 60 | ||
61 | static void ath10k_pci_process_ce(struct ath10k *ar); | ||
62 | static int ath10k_pci_post_rx(struct ath10k *ar); | 61 | static int ath10k_pci_post_rx(struct ath10k *ar); |
63 | static int ath10k_pci_post_rx_pipe(struct ath10k_pci_pipe *pipe_info, | 62 | static int ath10k_pci_post_rx_pipe(struct ath10k_pci_pipe *pipe_info, |
64 | int num); | 63 | int num); |
65 | static void ath10k_pci_rx_pipe_cleanup(struct ath10k_pci_pipe *pipe_info); | 64 | static void ath10k_pci_rx_pipe_cleanup(struct ath10k_pci_pipe *pipe_info); |
66 | static void ath10k_pci_stop_ce(struct ath10k *ar); | ||
67 | static int ath10k_pci_cold_reset(struct ath10k *ar); | 65 | static int ath10k_pci_cold_reset(struct ath10k *ar); |
68 | static int ath10k_pci_warm_reset(struct ath10k *ar); | 66 | static int ath10k_pci_warm_reset(struct ath10k *ar); |
69 | static int ath10k_pci_wait_for_target_init(struct ath10k *ar); | 67 | static int ath10k_pci_wait_for_target_init(struct ath10k *ar); |
@@ -74,7 +72,6 @@ static void ath10k_pci_free_irq(struct ath10k *ar); | |||
74 | static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe, | 72 | static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe, |
75 | struct ath10k_ce_pipe *rx_pipe, | 73 | struct ath10k_ce_pipe *rx_pipe, |
76 | struct bmi_xfer *xfer); | 74 | struct bmi_xfer *xfer); |
77 | static void ath10k_pci_cleanup_ce(struct ath10k *ar); | ||
78 | 75 | ||
79 | static const struct ce_attr host_ce_config_wlan[] = { | 76 | static const struct ce_attr host_ce_config_wlan[] = { |
80 | /* CE0: host->target HTC control and raw streams */ | 77 | /* CE0: host->target HTC control and raw streams */ |
@@ -679,34 +676,12 @@ void ath10k_do_pci_sleep(struct ath10k *ar) | |||
679 | } | 676 | } |
680 | } | 677 | } |
681 | 678 | ||
682 | /* | ||
683 | * FIXME: Handle OOM properly. | ||
684 | */ | ||
685 | static inline | ||
686 | struct ath10k_pci_compl *get_free_compl(struct ath10k_pci_pipe *pipe_info) | ||
687 | { | ||
688 | struct ath10k_pci_compl *compl = NULL; | ||
689 | |||
690 | spin_lock_bh(&pipe_info->pipe_lock); | ||
691 | if (list_empty(&pipe_info->compl_free)) { | ||
692 | ath10k_warn("Completion buffers are full\n"); | ||
693 | goto exit; | ||
694 | } | ||
695 | compl = list_first_entry(&pipe_info->compl_free, | ||
696 | struct ath10k_pci_compl, list); | ||
697 | list_del(&compl->list); | ||
698 | exit: | ||
699 | spin_unlock_bh(&pipe_info->pipe_lock); | ||
700 | return compl; | ||
701 | } | ||
702 | |||
703 | /* Called by lower (CE) layer when a send to Target completes. */ | 679 | /* Called by lower (CE) layer when a send to Target completes. */ |
704 | static void ath10k_pci_ce_send_done(struct ath10k_ce_pipe *ce_state) | 680 | static void ath10k_pci_ce_send_done(struct ath10k_ce_pipe *ce_state) |
705 | { | 681 | { |
706 | struct ath10k *ar = ce_state->ar; | 682 | struct ath10k *ar = ce_state->ar; |
707 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 683 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
708 | struct ath10k_pci_pipe *pipe_info = &ar_pci->pipe_info[ce_state->id]; | 684 | struct ath10k_hif_cb *cb = &ar_pci->msg_callbacks_current; |
709 | struct ath10k_pci_compl *compl; | ||
710 | void *transfer_context; | 685 | void *transfer_context; |
711 | u32 ce_data; | 686 | u32 ce_data; |
712 | unsigned int nbytes; | 687 | unsigned int nbytes; |
@@ -715,27 +690,12 @@ static void ath10k_pci_ce_send_done(struct ath10k_ce_pipe *ce_state) | |||
715 | while (ath10k_ce_completed_send_next(ce_state, &transfer_context, | 690 | while (ath10k_ce_completed_send_next(ce_state, &transfer_context, |
716 | &ce_data, &nbytes, | 691 | &ce_data, &nbytes, |
717 | &transfer_id) == 0) { | 692 | &transfer_id) == 0) { |
718 | compl = get_free_compl(pipe_info); | 693 | /* no need to call tx completion for NULL pointers */ |
719 | if (!compl) | 694 | if (transfer_context == NULL) |
720 | break; | 695 | continue; |
721 | |||
722 | compl->state = ATH10K_PCI_COMPL_SEND; | ||
723 | compl->ce_state = ce_state; | ||
724 | compl->pipe_info = pipe_info; | ||
725 | compl->skb = transfer_context; | ||
726 | compl->nbytes = nbytes; | ||
727 | compl->transfer_id = transfer_id; | ||
728 | compl->flags = 0; | ||
729 | 696 | ||
730 | /* | 697 | cb->tx_completion(ar, transfer_context, transfer_id); |
731 | * Add the completion to the processing queue. | ||
732 | */ | ||
733 | spin_lock_bh(&ar_pci->compl_lock); | ||
734 | list_add_tail(&compl->list, &ar_pci->compl_process); | ||
735 | spin_unlock_bh(&ar_pci->compl_lock); | ||
736 | } | 698 | } |
737 | |||
738 | ath10k_pci_process_ce(ar); | ||
739 | } | 699 | } |
740 | 700 | ||
741 | /* Called by lower (CE) layer when data is received from the Target. */ | 701 | /* Called by lower (CE) layer when data is received from the Target. */ |
@@ -744,77 +704,100 @@ static void ath10k_pci_ce_recv_data(struct ath10k_ce_pipe *ce_state) | |||
744 | struct ath10k *ar = ce_state->ar; | 704 | struct ath10k *ar = ce_state->ar; |
745 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 705 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
746 | struct ath10k_pci_pipe *pipe_info = &ar_pci->pipe_info[ce_state->id]; | 706 | struct ath10k_pci_pipe *pipe_info = &ar_pci->pipe_info[ce_state->id]; |
747 | struct ath10k_pci_compl *compl; | 707 | struct ath10k_hif_cb *cb = &ar_pci->msg_callbacks_current; |
748 | struct sk_buff *skb; | 708 | struct sk_buff *skb; |
749 | void *transfer_context; | 709 | void *transfer_context; |
750 | u32 ce_data; | 710 | u32 ce_data; |
751 | unsigned int nbytes; | 711 | unsigned int nbytes, max_nbytes; |
752 | unsigned int transfer_id; | 712 | unsigned int transfer_id; |
753 | unsigned int flags; | 713 | unsigned int flags; |
714 | int err; | ||
754 | 715 | ||
755 | while (ath10k_ce_completed_recv_next(ce_state, &transfer_context, | 716 | while (ath10k_ce_completed_recv_next(ce_state, &transfer_context, |
756 | &ce_data, &nbytes, &transfer_id, | 717 | &ce_data, &nbytes, &transfer_id, |
757 | &flags) == 0) { | 718 | &flags) == 0) { |
758 | compl = get_free_compl(pipe_info); | 719 | err = ath10k_pci_post_rx_pipe(pipe_info, 1); |
759 | if (!compl) | 720 | if (unlikely(err)) { |
760 | break; | 721 | /* FIXME: retry */ |
761 | 722 | ath10k_warn("failed to replenish CE rx ring %d: %d\n", | |
762 | compl->state = ATH10K_PCI_COMPL_RECV; | 723 | pipe_info->pipe_num, err); |
763 | compl->ce_state = ce_state; | 724 | } |
764 | compl->pipe_info = pipe_info; | ||
765 | compl->skb = transfer_context; | ||
766 | compl->nbytes = nbytes; | ||
767 | compl->transfer_id = transfer_id; | ||
768 | compl->flags = flags; | ||
769 | 725 | ||
770 | skb = transfer_context; | 726 | skb = transfer_context; |
727 | max_nbytes = skb->len + skb_tailroom(skb); | ||
771 | dma_unmap_single(ar->dev, ATH10K_SKB_CB(skb)->paddr, | 728 | dma_unmap_single(ar->dev, ATH10K_SKB_CB(skb)->paddr, |
772 | skb->len + skb_tailroom(skb), | 729 | max_nbytes, DMA_FROM_DEVICE); |
773 | DMA_FROM_DEVICE); | ||
774 | /* | ||
775 | * Add the completion to the processing queue. | ||
776 | */ | ||
777 | spin_lock_bh(&ar_pci->compl_lock); | ||
778 | list_add_tail(&compl->list, &ar_pci->compl_process); | ||
779 | spin_unlock_bh(&ar_pci->compl_lock); | ||
780 | } | ||
781 | 730 | ||
782 | ath10k_pci_process_ce(ar); | 731 | if (unlikely(max_nbytes < nbytes)) { |
732 | ath10k_warn("rxed more than expected (nbytes %d, max %d)", | ||
733 | nbytes, max_nbytes); | ||
734 | dev_kfree_skb_any(skb); | ||
735 | continue; | ||
736 | } | ||
737 | |||
738 | skb_put(skb, nbytes); | ||
739 | cb->rx_completion(ar, skb, pipe_info->pipe_num); | ||
740 | } | ||
783 | } | 741 | } |
784 | 742 | ||
785 | /* Send the first nbytes bytes of the buffer */ | 743 | static int ath10k_pci_hif_tx_sg(struct ath10k *ar, u8 pipe_id, |
786 | static int ath10k_pci_hif_send_head(struct ath10k *ar, u8 pipe_id, | 744 | struct ath10k_hif_sg_item *items, int n_items) |
787 | unsigned int transfer_id, | ||
788 | unsigned int bytes, struct sk_buff *nbuf) | ||
789 | { | 745 | { |
790 | struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(nbuf); | ||
791 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 746 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
792 | struct ath10k_pci_pipe *pipe_info = &(ar_pci->pipe_info[pipe_id]); | 747 | struct ath10k_pci_pipe *pci_pipe = &ar_pci->pipe_info[pipe_id]; |
793 | struct ath10k_ce_pipe *ce_hdl = pipe_info->ce_hdl; | 748 | struct ath10k_ce_pipe *ce_pipe = pci_pipe->ce_hdl; |
794 | unsigned int len; | 749 | struct ath10k_ce_ring *src_ring = ce_pipe->src_ring; |
795 | u32 flags = 0; | 750 | unsigned int nentries_mask = src_ring->nentries_mask; |
796 | int ret; | 751 | unsigned int sw_index = src_ring->sw_index; |
752 | unsigned int write_index = src_ring->write_index; | ||
753 | int err, i; | ||
797 | 754 | ||
798 | len = min(bytes, nbuf->len); | 755 | spin_lock_bh(&ar_pci->ce_lock); |
799 | bytes -= len; | ||
800 | 756 | ||
801 | if (len & 3) | 757 | if (unlikely(CE_RING_DELTA(nentries_mask, |
802 | ath10k_warn("skb not aligned to 4-byte boundary (%d)\n", len); | 758 | write_index, sw_index - 1) < n_items)) { |
759 | err = -ENOBUFS; | ||
760 | goto unlock; | ||
761 | } | ||
803 | 762 | ||
804 | ath10k_dbg(ATH10K_DBG_PCI, | 763 | for (i = 0; i < n_items - 1; i++) { |
805 | "pci send data vaddr %p paddr 0x%llx len %d as %d bytes\n", | 764 | ath10k_dbg(ATH10K_DBG_PCI, |
806 | nbuf->data, (unsigned long long) skb_cb->paddr, | 765 | "pci tx item %d paddr 0x%08x len %d n_items %d\n", |
807 | nbuf->len, len); | 766 | i, items[i].paddr, items[i].len, n_items); |
808 | ath10k_dbg_dump(ATH10K_DBG_PCI_DUMP, NULL, | 767 | ath10k_dbg_dump(ATH10K_DBG_PCI_DUMP, NULL, "item data: ", |
809 | "ath10k tx: data: ", | 768 | items[i].vaddr, items[i].len); |
810 | nbuf->data, nbuf->len); | ||
811 | |||
812 | ret = ath10k_ce_send(ce_hdl, nbuf, skb_cb->paddr, len, transfer_id, | ||
813 | flags); | ||
814 | if (ret) | ||
815 | ath10k_warn("failed to send sk_buff to CE: %p\n", nbuf); | ||
816 | 769 | ||
817 | return ret; | 770 | err = ath10k_ce_send_nolock(ce_pipe, |
771 | items[i].transfer_context, | ||
772 | items[i].paddr, | ||
773 | items[i].len, | ||
774 | items[i].transfer_id, | ||
775 | CE_SEND_FLAG_GATHER); | ||
776 | if (err) | ||
777 | goto unlock; | ||
778 | } | ||
779 | |||
780 | /* `i` is equal to `n_items -1` after for() */ | ||
781 | |||
782 | ath10k_dbg(ATH10K_DBG_PCI, | ||
783 | "pci tx item %d paddr 0x%08x len %d n_items %d\n", | ||
784 | i, items[i].paddr, items[i].len, n_items); | ||
785 | ath10k_dbg_dump(ATH10K_DBG_PCI_DUMP, NULL, "item data: ", | ||
786 | items[i].vaddr, items[i].len); | ||
787 | |||
788 | err = ath10k_ce_send_nolock(ce_pipe, | ||
789 | items[i].transfer_context, | ||
790 | items[i].paddr, | ||
791 | items[i].len, | ||
792 | items[i].transfer_id, | ||
793 | 0); | ||
794 | if (err) | ||
795 | goto unlock; | ||
796 | |||
797 | err = 0; | ||
798 | unlock: | ||
799 | spin_unlock_bh(&ar_pci->ce_lock); | ||
800 | return err; | ||
818 | } | 801 | } |
819 | 802 | ||
820 | static u16 ath10k_pci_hif_get_free_queue_number(struct ath10k *ar, u8 pipe) | 803 | static u16 ath10k_pci_hif_get_free_queue_number(struct ath10k *ar, u8 pipe) |
@@ -903,52 +886,6 @@ static void ath10k_pci_hif_set_callbacks(struct ath10k *ar, | |||
903 | sizeof(ar_pci->msg_callbacks_current)); | 886 | sizeof(ar_pci->msg_callbacks_current)); |
904 | } | 887 | } |
905 | 888 | ||
906 | static int ath10k_pci_alloc_compl(struct ath10k *ar) | ||
907 | { | ||
908 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | ||
909 | const struct ce_attr *attr; | ||
910 | struct ath10k_pci_pipe *pipe_info; | ||
911 | struct ath10k_pci_compl *compl; | ||
912 | int i, pipe_num, completions; | ||
913 | |||
914 | spin_lock_init(&ar_pci->compl_lock); | ||
915 | INIT_LIST_HEAD(&ar_pci->compl_process); | ||
916 | |||
917 | for (pipe_num = 0; pipe_num < CE_COUNT; pipe_num++) { | ||
918 | pipe_info = &ar_pci->pipe_info[pipe_num]; | ||
919 | |||
920 | spin_lock_init(&pipe_info->pipe_lock); | ||
921 | INIT_LIST_HEAD(&pipe_info->compl_free); | ||
922 | |||
923 | /* Handle Diagnostic CE specially */ | ||
924 | if (pipe_info->ce_hdl == ar_pci->ce_diag) | ||
925 | continue; | ||
926 | |||
927 | attr = &host_ce_config_wlan[pipe_num]; | ||
928 | completions = 0; | ||
929 | |||
930 | if (attr->src_nentries) | ||
931 | completions += attr->src_nentries; | ||
932 | |||
933 | if (attr->dest_nentries) | ||
934 | completions += attr->dest_nentries; | ||
935 | |||
936 | for (i = 0; i < completions; i++) { | ||
937 | compl = kmalloc(sizeof(*compl), GFP_KERNEL); | ||
938 | if (!compl) { | ||
939 | ath10k_warn("No memory for completion state\n"); | ||
940 | ath10k_pci_cleanup_ce(ar); | ||
941 | return -ENOMEM; | ||
942 | } | ||
943 | |||
944 | compl->state = ATH10K_PCI_COMPL_FREE; | ||
945 | list_add_tail(&compl->list, &pipe_info->compl_free); | ||
946 | } | ||
947 | } | ||
948 | |||
949 | return 0; | ||
950 | } | ||
951 | |||
952 | static int ath10k_pci_setup_ce_irq(struct ath10k *ar) | 889 | static int ath10k_pci_setup_ce_irq(struct ath10k *ar) |
953 | { | 890 | { |
954 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 891 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
@@ -993,147 +930,6 @@ static void ath10k_pci_kill_tasklet(struct ath10k *ar) | |||
993 | tasklet_kill(&ar_pci->pipe_info[i].intr); | 930 | tasklet_kill(&ar_pci->pipe_info[i].intr); |
994 | } | 931 | } |
995 | 932 | ||
996 | static void ath10k_pci_stop_ce(struct ath10k *ar) | ||
997 | { | ||
998 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | ||
999 | struct ath10k_pci_compl *compl; | ||
1000 | struct sk_buff *skb; | ||
1001 | |||
1002 | /* Mark pending completions as aborted, so that upper layers free up | ||
1003 | * their associated resources */ | ||
1004 | spin_lock_bh(&ar_pci->compl_lock); | ||
1005 | list_for_each_entry(compl, &ar_pci->compl_process, list) { | ||
1006 | skb = compl->skb; | ||
1007 | ATH10K_SKB_CB(skb)->is_aborted = true; | ||
1008 | } | ||
1009 | spin_unlock_bh(&ar_pci->compl_lock); | ||
1010 | } | ||
1011 | |||
1012 | static void ath10k_pci_cleanup_ce(struct ath10k *ar) | ||
1013 | { | ||
1014 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | ||
1015 | struct ath10k_pci_compl *compl, *tmp; | ||
1016 | struct ath10k_pci_pipe *pipe_info; | ||
1017 | struct sk_buff *netbuf; | ||
1018 | int pipe_num; | ||
1019 | |||
1020 | /* Free pending completions. */ | ||
1021 | spin_lock_bh(&ar_pci->compl_lock); | ||
1022 | if (!list_empty(&ar_pci->compl_process)) | ||
1023 | ath10k_warn("pending completions still present! possible memory leaks.\n"); | ||
1024 | |||
1025 | list_for_each_entry_safe(compl, tmp, &ar_pci->compl_process, list) { | ||
1026 | list_del(&compl->list); | ||
1027 | netbuf = compl->skb; | ||
1028 | dev_kfree_skb_any(netbuf); | ||
1029 | kfree(compl); | ||
1030 | } | ||
1031 | spin_unlock_bh(&ar_pci->compl_lock); | ||
1032 | |||
1033 | /* Free unused completions for each pipe. */ | ||
1034 | for (pipe_num = 0; pipe_num < CE_COUNT; pipe_num++) { | ||
1035 | pipe_info = &ar_pci->pipe_info[pipe_num]; | ||
1036 | |||
1037 | spin_lock_bh(&pipe_info->pipe_lock); | ||
1038 | list_for_each_entry_safe(compl, tmp, | ||
1039 | &pipe_info->compl_free, list) { | ||
1040 | list_del(&compl->list); | ||
1041 | kfree(compl); | ||
1042 | } | ||
1043 | spin_unlock_bh(&pipe_info->pipe_lock); | ||
1044 | } | ||
1045 | } | ||
1046 | |||
1047 | static void ath10k_pci_process_ce(struct ath10k *ar) | ||
1048 | { | ||
1049 | struct ath10k_pci *ar_pci = ar->hif.priv; | ||
1050 | struct ath10k_hif_cb *cb = &ar_pci->msg_callbacks_current; | ||
1051 | struct ath10k_pci_compl *compl; | ||
1052 | struct sk_buff *skb; | ||
1053 | unsigned int nbytes; | ||
1054 | int ret, send_done = 0; | ||
1055 | |||
1056 | /* Upper layers aren't ready to handle tx/rx completions in parallel so | ||
1057 | * we must serialize all completion processing. */ | ||
1058 | |||
1059 | spin_lock_bh(&ar_pci->compl_lock); | ||
1060 | if (ar_pci->compl_processing) { | ||
1061 | spin_unlock_bh(&ar_pci->compl_lock); | ||
1062 | return; | ||
1063 | } | ||
1064 | ar_pci->compl_processing = true; | ||
1065 | spin_unlock_bh(&ar_pci->compl_lock); | ||
1066 | |||
1067 | for (;;) { | ||
1068 | spin_lock_bh(&ar_pci->compl_lock); | ||
1069 | if (list_empty(&ar_pci->compl_process)) { | ||
1070 | spin_unlock_bh(&ar_pci->compl_lock); | ||
1071 | break; | ||
1072 | } | ||
1073 | compl = list_first_entry(&ar_pci->compl_process, | ||
1074 | struct ath10k_pci_compl, list); | ||
1075 | list_del(&compl->list); | ||
1076 | spin_unlock_bh(&ar_pci->compl_lock); | ||
1077 | |||
1078 | switch (compl->state) { | ||
1079 | case ATH10K_PCI_COMPL_SEND: | ||
1080 | cb->tx_completion(ar, | ||
1081 | compl->skb, | ||
1082 | compl->transfer_id); | ||
1083 | send_done = 1; | ||
1084 | break; | ||
1085 | case ATH10K_PCI_COMPL_RECV: | ||
1086 | ret = ath10k_pci_post_rx_pipe(compl->pipe_info, 1); | ||
1087 | if (ret) { | ||
1088 | ath10k_warn("failed to post RX buffer for pipe %d: %d\n", | ||
1089 | compl->pipe_info->pipe_num, ret); | ||
1090 | break; | ||
1091 | } | ||
1092 | |||
1093 | skb = compl->skb; | ||
1094 | nbytes = compl->nbytes; | ||
1095 | |||
1096 | ath10k_dbg(ATH10K_DBG_PCI, | ||
1097 | "ath10k_pci_ce_recv_data netbuf=%p nbytes=%d\n", | ||
1098 | skb, nbytes); | ||
1099 | ath10k_dbg_dump(ATH10K_DBG_PCI_DUMP, NULL, | ||
1100 | "ath10k rx: ", skb->data, nbytes); | ||
1101 | |||
1102 | if (skb->len + skb_tailroom(skb) >= nbytes) { | ||
1103 | skb_trim(skb, 0); | ||
1104 | skb_put(skb, nbytes); | ||
1105 | cb->rx_completion(ar, skb, | ||
1106 | compl->pipe_info->pipe_num); | ||
1107 | } else { | ||
1108 | ath10k_warn("rxed more than expected (nbytes %d, max %d)", | ||
1109 | nbytes, | ||
1110 | skb->len + skb_tailroom(skb)); | ||
1111 | } | ||
1112 | break; | ||
1113 | case ATH10K_PCI_COMPL_FREE: | ||
1114 | ath10k_warn("free completion cannot be processed\n"); | ||
1115 | break; | ||
1116 | default: | ||
1117 | ath10k_warn("invalid completion state (%d)\n", | ||
1118 | compl->state); | ||
1119 | break; | ||
1120 | } | ||
1121 | |||
1122 | compl->state = ATH10K_PCI_COMPL_FREE; | ||
1123 | |||
1124 | /* | ||
1125 | * Add completion back to the pipe's free list. | ||
1126 | */ | ||
1127 | spin_lock_bh(&compl->pipe_info->pipe_lock); | ||
1128 | list_add_tail(&compl->list, &compl->pipe_info->compl_free); | ||
1129 | spin_unlock_bh(&compl->pipe_info->pipe_lock); | ||
1130 | } | ||
1131 | |||
1132 | spin_lock_bh(&ar_pci->compl_lock); | ||
1133 | ar_pci->compl_processing = false; | ||
1134 | spin_unlock_bh(&ar_pci->compl_lock); | ||
1135 | } | ||
1136 | |||
1137 | /* TODO - temporary mapping while we have too few CE's */ | 933 | /* TODO - temporary mapping while we have too few CE's */ |
1138 | static int ath10k_pci_hif_map_service_to_pipe(struct ath10k *ar, | 934 | static int ath10k_pci_hif_map_service_to_pipe(struct ath10k *ar, |
1139 | u16 service_id, u8 *ul_pipe, | 935 | u16 service_id, u8 *ul_pipe, |
@@ -1305,17 +1101,11 @@ static int ath10k_pci_hif_start(struct ath10k *ar) | |||
1305 | ath10k_pci_free_early_irq(ar); | 1101 | ath10k_pci_free_early_irq(ar); |
1306 | ath10k_pci_kill_tasklet(ar); | 1102 | ath10k_pci_kill_tasklet(ar); |
1307 | 1103 | ||
1308 | ret = ath10k_pci_alloc_compl(ar); | ||
1309 | if (ret) { | ||
1310 | ath10k_warn("failed to allocate CE completions: %d\n", ret); | ||
1311 | goto err_early_irq; | ||
1312 | } | ||
1313 | |||
1314 | ret = ath10k_pci_request_irq(ar); | 1104 | ret = ath10k_pci_request_irq(ar); |
1315 | if (ret) { | 1105 | if (ret) { |
1316 | ath10k_warn("failed to post RX buffers for all pipes: %d\n", | 1106 | ath10k_warn("failed to post RX buffers for all pipes: %d\n", |
1317 | ret); | 1107 | ret); |
1318 | goto err_free_compl; | 1108 | goto err_early_irq; |
1319 | } | 1109 | } |
1320 | 1110 | ||
1321 | ret = ath10k_pci_setup_ce_irq(ar); | 1111 | ret = ath10k_pci_setup_ce_irq(ar); |
@@ -1339,10 +1129,6 @@ err_stop: | |||
1339 | ath10k_ce_disable_interrupts(ar); | 1129 | ath10k_ce_disable_interrupts(ar); |
1340 | ath10k_pci_free_irq(ar); | 1130 | ath10k_pci_free_irq(ar); |
1341 | ath10k_pci_kill_tasklet(ar); | 1131 | ath10k_pci_kill_tasklet(ar); |
1342 | ath10k_pci_stop_ce(ar); | ||
1343 | ath10k_pci_process_ce(ar); | ||
1344 | err_free_compl: | ||
1345 | ath10k_pci_cleanup_ce(ar); | ||
1346 | err_early_irq: | 1132 | err_early_irq: |
1347 | /* Though there should be no interrupts (device was reset) | 1133 | /* Though there should be no interrupts (device was reset) |
1348 | * power_down() expects the early IRQ to be installed as per the | 1134 | * power_down() expects the early IRQ to be installed as per the |
@@ -1413,18 +1199,10 @@ static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pipe_info) | |||
1413 | 1199 | ||
1414 | while (ath10k_ce_cancel_send_next(ce_hdl, (void **)&netbuf, | 1200 | while (ath10k_ce_cancel_send_next(ce_hdl, (void **)&netbuf, |
1415 | &ce_data, &nbytes, &id) == 0) { | 1201 | &ce_data, &nbytes, &id) == 0) { |
1416 | /* | 1202 | /* no need to call tx completion for NULL pointers */ |
1417 | * Indicate the completion to higer layer to free | 1203 | if (!netbuf) |
1418 | * the buffer | ||
1419 | */ | ||
1420 | |||
1421 | if (!netbuf) { | ||
1422 | ath10k_warn("invalid sk_buff on CE %d - NULL pointer. firmware crashed?\n", | ||
1423 | ce_hdl->id); | ||
1424 | continue; | 1204 | continue; |
1425 | } | ||
1426 | 1205 | ||
1427 | ATH10K_SKB_CB(netbuf)->is_aborted = true; | ||
1428 | ar_pci->msg_callbacks_current.tx_completion(ar, | 1206 | ar_pci->msg_callbacks_current.tx_completion(ar, |
1429 | netbuf, | 1207 | netbuf, |
1430 | id); | 1208 | id); |
@@ -1482,7 +1260,6 @@ static void ath10k_pci_hif_stop(struct ath10k *ar) | |||
1482 | 1260 | ||
1483 | ath10k_pci_free_irq(ar); | 1261 | ath10k_pci_free_irq(ar); |
1484 | ath10k_pci_kill_tasklet(ar); | 1262 | ath10k_pci_kill_tasklet(ar); |
1485 | ath10k_pci_stop_ce(ar); | ||
1486 | 1263 | ||
1487 | ret = ath10k_pci_request_early_irq(ar); | 1264 | ret = ath10k_pci_request_early_irq(ar); |
1488 | if (ret) | 1265 | if (ret) |
@@ -1492,8 +1269,6 @@ static void ath10k_pci_hif_stop(struct ath10k *ar) | |||
1492 | * not DMA nor interrupt. We process the leftovers and then free | 1269 | * not DMA nor interrupt. We process the leftovers and then free |
1493 | * everything else up. */ | 1270 | * everything else up. */ |
1494 | 1271 | ||
1495 | ath10k_pci_process_ce(ar); | ||
1496 | ath10k_pci_cleanup_ce(ar); | ||
1497 | ath10k_pci_buffer_cleanup(ar); | 1272 | ath10k_pci_buffer_cleanup(ar); |
1498 | 1273 | ||
1499 | /* Make the sure the device won't access any structures on the host by | 1274 | /* Make the sure the device won't access any structures on the host by |
@@ -2269,7 +2044,7 @@ static int ath10k_pci_hif_resume(struct ath10k *ar) | |||
2269 | #endif | 2044 | #endif |
2270 | 2045 | ||
2271 | static const struct ath10k_hif_ops ath10k_pci_hif_ops = { | 2046 | static const struct ath10k_hif_ops ath10k_pci_hif_ops = { |
2272 | .send_head = ath10k_pci_hif_send_head, | 2047 | .tx_sg = ath10k_pci_hif_tx_sg, |
2273 | .exchange_bmi_msg = ath10k_pci_hif_exchange_bmi_msg, | 2048 | .exchange_bmi_msg = ath10k_pci_hif_exchange_bmi_msg, |
2274 | .start = ath10k_pci_hif_start, | 2049 | .start = ath10k_pci_hif_start, |
2275 | .stop = ath10k_pci_hif_stop, | 2050 | .stop = ath10k_pci_hif_stop, |
diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index a4f32038c440..b43fdb4f7319 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h | |||
@@ -43,23 +43,6 @@ struct bmi_xfer { | |||
43 | u32 resp_len; | 43 | u32 resp_len; |
44 | }; | 44 | }; |
45 | 45 | ||
46 | enum ath10k_pci_compl_state { | ||
47 | ATH10K_PCI_COMPL_FREE = 0, | ||
48 | ATH10K_PCI_COMPL_SEND, | ||
49 | ATH10K_PCI_COMPL_RECV, | ||
50 | }; | ||
51 | |||
52 | struct ath10k_pci_compl { | ||
53 | struct list_head list; | ||
54 | enum ath10k_pci_compl_state state; | ||
55 | struct ath10k_ce_pipe *ce_state; | ||
56 | struct ath10k_pci_pipe *pipe_info; | ||
57 | struct sk_buff *skb; | ||
58 | unsigned int nbytes; | ||
59 | unsigned int transfer_id; | ||
60 | unsigned int flags; | ||
61 | }; | ||
62 | |||
63 | /* | 46 | /* |
64 | * PCI-specific Target state | 47 | * PCI-specific Target state |
65 | * | 48 | * |
@@ -175,9 +158,6 @@ struct ath10k_pci_pipe { | |||
175 | /* protects compl_free and num_send_allowed */ | 158 | /* protects compl_free and num_send_allowed */ |
176 | spinlock_t pipe_lock; | 159 | spinlock_t pipe_lock; |
177 | 160 | ||
178 | /* List of free CE completion slots */ | ||
179 | struct list_head compl_free; | ||
180 | |||
181 | struct ath10k_pci *ar_pci; | 161 | struct ath10k_pci *ar_pci; |
182 | struct tasklet_struct intr; | 162 | struct tasklet_struct intr; |
183 | }; | 163 | }; |
@@ -205,14 +185,6 @@ struct ath10k_pci { | |||
205 | atomic_t keep_awake_count; | 185 | atomic_t keep_awake_count; |
206 | bool verified_awake; | 186 | bool verified_awake; |
207 | 187 | ||
208 | /* List of CE completions to be processed */ | ||
209 | struct list_head compl_process; | ||
210 | |||
211 | /* protects compl_processing and compl_process */ | ||
212 | spinlock_t compl_lock; | ||
213 | |||
214 | bool compl_processing; | ||
215 | |||
216 | struct ath10k_pci_pipe pipe_info[CE_COUNT_MAX]; | 188 | struct ath10k_pci_pipe pipe_info[CE_COUNT_MAX]; |
217 | 189 | ||
218 | struct ath10k_hif_cb msg_callbacks_current; | 190 | struct ath10k_hif_cb msg_callbacks_current; |
diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index ec6f82521b0e..0541dd939ce9 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c | |||
@@ -51,7 +51,8 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt, | |||
51 | struct ieee80211_tx_info *info; | 51 | struct ieee80211_tx_info *info; |
52 | struct ath10k_skb_cb *skb_cb; | 52 | struct ath10k_skb_cb *skb_cb; |
53 | struct sk_buff *msdu; | 53 | struct sk_buff *msdu; |
54 | int ret; | 54 | |
55 | lockdep_assert_held(&htt->tx_lock); | ||
55 | 56 | ||
56 | ath10k_dbg(ATH10K_DBG_HTT, "htt tx completion msdu_id %u discard %d no_ack %d\n", | 57 | ath10k_dbg(ATH10K_DBG_HTT, "htt tx completion msdu_id %u discard %d no_ack %d\n", |
57 | tx_done->msdu_id, !!tx_done->discard, !!tx_done->no_ack); | 58 | tx_done->msdu_id, !!tx_done->discard, !!tx_done->no_ack); |
@@ -65,12 +66,12 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt, | |||
65 | msdu = htt->pending_tx[tx_done->msdu_id]; | 66 | msdu = htt->pending_tx[tx_done->msdu_id]; |
66 | skb_cb = ATH10K_SKB_CB(msdu); | 67 | skb_cb = ATH10K_SKB_CB(msdu); |
67 | 68 | ||
68 | ret = ath10k_skb_unmap(dev, msdu); | 69 | dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); |
69 | if (ret) | ||
70 | ath10k_warn("data skb unmap failed (%d)\n", ret); | ||
71 | 70 | ||
72 | if (skb_cb->htt.frag_len) | 71 | if (skb_cb->htt.txbuf) |
73 | skb_pull(msdu, skb_cb->htt.frag_len + skb_cb->htt.pad_len); | 72 | dma_pool_free(htt->tx_pool, |
73 | skb_cb->htt.txbuf, | ||
74 | skb_cb->htt.txbuf_paddr); | ||
74 | 75 | ||
75 | ath10k_report_offchan_tx(htt->ar, msdu); | 76 | ath10k_report_offchan_tx(htt->ar, msdu); |
76 | 77 | ||
@@ -92,13 +93,11 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt, | |||
92 | /* we do not own the msdu anymore */ | 93 | /* we do not own the msdu anymore */ |
93 | 94 | ||
94 | exit: | 95 | exit: |
95 | spin_lock_bh(&htt->tx_lock); | ||
96 | htt->pending_tx[tx_done->msdu_id] = NULL; | 96 | htt->pending_tx[tx_done->msdu_id] = NULL; |
97 | ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id); | 97 | ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id); |
98 | __ath10k_htt_tx_dec_pending(htt); | 98 | __ath10k_htt_tx_dec_pending(htt); |
99 | if (htt->num_pending_tx == 0) | 99 | if (htt->num_pending_tx == 0) |
100 | wake_up(&htt->empty_tx_wq); | 100 | wake_up(&htt->empty_tx_wq); |
101 | spin_unlock_bh(&htt->tx_lock); | ||
102 | } | 101 | } |
103 | 102 | ||
104 | static const u8 rx_legacy_rate_idx[] = { | 103 | static const u8 rx_legacy_rate_idx[] = { |
@@ -258,6 +257,12 @@ void ath10k_process_rx(struct ath10k *ar, struct htt_rx_info *info) | |||
258 | status->band = ch->band; | 257 | status->band = ch->band; |
259 | status->freq = ch->center_freq; | 258 | status->freq = ch->center_freq; |
260 | 259 | ||
260 | if (info->rate.info0 & HTT_RX_INDICATION_INFO0_END_VALID) { | ||
261 | /* TSF available only in 32-bit */ | ||
262 | status->mactime = info->tsf & 0xffffffff; | ||
263 | status->flag |= RX_FLAG_MACTIME_END; | ||
264 | } | ||
265 | |||
261 | ath10k_dbg(ATH10K_DBG_DATA, | 266 | ath10k_dbg(ATH10K_DBG_DATA, |
262 | "rx skb %p len %u %s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i\n", | 267 | "rx skb %p len %u %s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i\n", |
263 | info->skb, | 268 | info->skb, |
@@ -378,7 +383,8 @@ void ath10k_peer_unmap_event(struct ath10k_htt *htt, | |||
378 | spin_lock_bh(&ar->data_lock); | 383 | spin_lock_bh(&ar->data_lock); |
379 | peer = ath10k_peer_find_by_id(ar, ev->peer_id); | 384 | peer = ath10k_peer_find_by_id(ar, ev->peer_id); |
380 | if (!peer) { | 385 | if (!peer) { |
381 | ath10k_warn("unknown peer id %d\n", ev->peer_id); | 386 | ath10k_warn("peer-unmap-event: unknown peer id %d\n", |
387 | ev->peer_id); | ||
382 | goto exit; | 388 | goto exit; |
383 | } | 389 | } |
384 | 390 | ||
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 91e501b5499e..cb1f7b5bcf4c 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c | |||
@@ -1360,7 +1360,7 @@ static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb) | |||
1360 | struct wmi_bcn_info *bcn_info; | 1360 | struct wmi_bcn_info *bcn_info; |
1361 | struct ath10k_vif *arvif; | 1361 | struct ath10k_vif *arvif; |
1362 | struct sk_buff *bcn; | 1362 | struct sk_buff *bcn; |
1363 | int vdev_id = 0; | 1363 | int ret, vdev_id = 0; |
1364 | 1364 | ||
1365 | ath10k_dbg(ATH10K_DBG_MGMT, "WMI_HOST_SWBA_EVENTID\n"); | 1365 | ath10k_dbg(ATH10K_DBG_MGMT, "WMI_HOST_SWBA_EVENTID\n"); |
1366 | 1366 | ||
@@ -1435,16 +1435,27 @@ static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb) | |||
1435 | ath10k_warn("SWBA overrun on vdev %d\n", | 1435 | ath10k_warn("SWBA overrun on vdev %d\n", |
1436 | arvif->vdev_id); | 1436 | arvif->vdev_id); |
1437 | 1437 | ||
1438 | ath10k_skb_unmap(ar->dev, arvif->beacon); | 1438 | dma_unmap_single(arvif->ar->dev, |
1439 | ATH10K_SKB_CB(arvif->beacon)->paddr, | ||
1440 | arvif->beacon->len, DMA_TO_DEVICE); | ||
1439 | dev_kfree_skb_any(arvif->beacon); | 1441 | dev_kfree_skb_any(arvif->beacon); |
1440 | } | 1442 | } |
1441 | 1443 | ||
1442 | ath10k_skb_map(ar->dev, bcn); | 1444 | ATH10K_SKB_CB(bcn)->paddr = dma_map_single(arvif->ar->dev, |
1445 | bcn->data, bcn->len, | ||
1446 | DMA_TO_DEVICE); | ||
1447 | ret = dma_mapping_error(arvif->ar->dev, | ||
1448 | ATH10K_SKB_CB(bcn)->paddr); | ||
1449 | if (ret) { | ||
1450 | ath10k_warn("failed to map beacon: %d\n", ret); | ||
1451 | goto skip; | ||
1452 | } | ||
1443 | 1453 | ||
1444 | arvif->beacon = bcn; | 1454 | arvif->beacon = bcn; |
1445 | arvif->beacon_sent = false; | 1455 | arvif->beacon_sent = false; |
1446 | 1456 | ||
1447 | ath10k_wmi_tx_beacon_nowait(arvif); | 1457 | ath10k_wmi_tx_beacon_nowait(arvif); |
1458 | skip: | ||
1448 | spin_unlock_bh(&ar->data_lock); | 1459 | spin_unlock_bh(&ar->data_lock); |
1449 | } | 1460 | } |
1450 | } | 1461 | } |
@@ -3382,7 +3393,6 @@ int ath10k_wmi_scan_chan_list(struct ath10k *ar, | |||
3382 | ci->max_power = ch->max_power; | 3393 | ci->max_power = ch->max_power; |
3383 | ci->reg_power = ch->max_reg_power; | 3394 | ci->reg_power = ch->max_reg_power; |
3384 | ci->antenna_max = ch->max_antenna_gain; | 3395 | ci->antenna_max = ch->max_antenna_gain; |
3385 | ci->antenna_max = 0; | ||
3386 | 3396 | ||
3387 | /* mode & flags share storage */ | 3397 | /* mode & flags share storage */ |
3388 | ci->mode = ch->mode; | 3398 | ci->mode = ch->mode; |
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index ef35da84f63b..4b18434ba697 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -751,6 +751,9 @@ ath5k_txbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf, | |||
751 | bf->skbaddr = dma_map_single(ah->dev, skb->data, skb->len, | 751 | bf->skbaddr = dma_map_single(ah->dev, skb->data, skb->len, |
752 | DMA_TO_DEVICE); | 752 | DMA_TO_DEVICE); |
753 | 753 | ||
754 | if (dma_mapping_error(ah->dev, bf->skbaddr)) | ||
755 | return -ENOSPC; | ||
756 | |||
754 | ieee80211_get_tx_rates(info->control.vif, (control) ? control->sta : NULL, skb, bf->rates, | 757 | ieee80211_get_tx_rates(info->control.vif, (control) ? control->sta : NULL, skb, bf->rates, |
755 | ARRAY_SIZE(bf->rates)); | 758 | ARRAY_SIZE(bf->rates)); |
756 | 759 | ||
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index b58fe99ef745..8e1c7b0fe76c 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile | |||
@@ -52,7 +52,8 @@ obj-$(CONFIG_ATH9K_HW) += ath9k_hw.o | |||
52 | 52 | ||
53 | obj-$(CONFIG_ATH9K_COMMON) += ath9k_common.o | 53 | obj-$(CONFIG_ATH9K_COMMON) += ath9k_common.o |
54 | ath9k_common-y:= common.o \ | 54 | ath9k_common-y:= common.o \ |
55 | common-init.o | 55 | common-init.o \ |
56 | common-beacon.o | ||
56 | 57 | ||
57 | ath9k_htc-y += htc_hst.o \ | 58 | ath9k_htc-y += htc_hst.o \ |
58 | hif_usb.o \ | 59 | hif_usb.o \ |
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index 2dff2765769b..a0398fe3eb28 100644 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c | |||
@@ -39,6 +39,10 @@ static const struct platform_device_id ath9k_platform_id_table[] = { | |||
39 | .name = "qca955x_wmac", | 39 | .name = "qca955x_wmac", |
40 | .driver_data = AR9300_DEVID_QCA955X, | 40 | .driver_data = AR9300_DEVID_QCA955X, |
41 | }, | 41 | }, |
42 | { | ||
43 | .name = "qca953x_wmac", | ||
44 | .driver_data = AR9300_DEVID_AR953X, | ||
45 | }, | ||
42 | {}, | 46 | {}, |
43 | }; | 47 | }; |
44 | 48 | ||
@@ -82,6 +86,7 @@ static int ath_ahb_probe(struct platform_device *pdev) | |||
82 | int irq; | 86 | int irq; |
83 | int ret = 0; | 87 | int ret = 0; |
84 | struct ath_hw *ah; | 88 | struct ath_hw *ah; |
89 | struct ath_common *common; | ||
85 | char hw_name[64]; | 90 | char hw_name[64]; |
86 | 91 | ||
87 | if (!dev_get_platdata(&pdev->dev)) { | 92 | if (!dev_get_platdata(&pdev->dev)) { |
@@ -124,9 +129,6 @@ static int ath_ahb_probe(struct platform_device *pdev) | |||
124 | sc->mem = mem; | 129 | sc->mem = mem; |
125 | sc->irq = irq; | 130 | sc->irq = irq; |
126 | 131 | ||
127 | /* Will be cleared in ath9k_start() */ | ||
128 | set_bit(SC_OP_INVALID, &sc->sc_flags); | ||
129 | |||
130 | ret = request_irq(irq, ath_isr, IRQF_SHARED, "ath9k", sc); | 132 | ret = request_irq(irq, ath_isr, IRQF_SHARED, "ath9k", sc); |
131 | if (ret) { | 133 | if (ret) { |
132 | dev_err(&pdev->dev, "request_irq failed\n"); | 134 | dev_err(&pdev->dev, "request_irq failed\n"); |
@@ -144,6 +146,9 @@ static int ath_ahb_probe(struct platform_device *pdev) | |||
144 | wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n", | 146 | wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n", |
145 | hw_name, (unsigned long)mem, irq); | 147 | hw_name, (unsigned long)mem, irq); |
146 | 148 | ||
149 | common = ath9k_hw_common(sc->sc_ah); | ||
150 | /* Will be cleared in ath9k_start() */ | ||
151 | set_bit(ATH_OP_INVALID, &common->op_flags); | ||
147 | return 0; | 152 | return 0; |
148 | 153 | ||
149 | err_irq: | 154 | err_irq: |
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index 2ce5079007b6..6d47783f2e5b 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c | |||
@@ -318,17 +318,6 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning) | |||
318 | BUG_ON(aniState == NULL); | 318 | BUG_ON(aniState == NULL); |
319 | ah->stats.ast_ani_reset++; | 319 | ah->stats.ast_ani_reset++; |
320 | 320 | ||
321 | /* only allow a subset of functions in AP mode */ | ||
322 | if (ah->opmode == NL80211_IFTYPE_AP) { | ||
323 | if (IS_CHAN_2GHZ(chan)) { | ||
324 | ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL | | ||
325 | ATH9K_ANI_FIRSTEP_LEVEL); | ||
326 | if (AR_SREV_9300_20_OR_LATER(ah)) | ||
327 | ah->ani_function |= ATH9K_ANI_MRC_CCK; | ||
328 | } else | ||
329 | ah->ani_function = 0; | ||
330 | } | ||
331 | |||
332 | ofdm_nil = max_t(int, ATH9K_ANI_OFDM_DEF_LEVEL, | 321 | ofdm_nil = max_t(int, ATH9K_ANI_OFDM_DEF_LEVEL, |
333 | aniState->ofdmNoiseImmunityLevel); | 322 | aniState->ofdmNoiseImmunityLevel); |
334 | cck_nil = max_t(int, ATH9K_ANI_CCK_DEF_LEVEL, | 323 | cck_nil = max_t(int, ATH9K_ANI_CCK_DEF_LEVEL, |
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c index ff415e863ee9..3b3e91057a4c 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c | |||
@@ -26,10 +26,6 @@ static const int firstep_table[] = | |||
26 | /* level: 0 1 2 3 4 5 6 7 8 */ | 26 | /* level: 0 1 2 3 4 5 6 7 8 */ |
27 | { -4, -2, 0, 2, 4, 6, 8, 10, 12 }; /* lvl 0-8, default 2 */ | 27 | { -4, -2, 0, 2, 4, 6, 8, 10, 12 }; /* lvl 0-8, default 2 */ |
28 | 28 | ||
29 | static const int cycpwrThr1_table[] = | ||
30 | /* level: 0 1 2 3 4 5 6 7 8 */ | ||
31 | { -6, -4, -2, 0, 2, 4, 6, 8 }; /* lvl 0-7, default 3 */ | ||
32 | |||
33 | /* | 29 | /* |
34 | * register values to turn OFDM weak signal detection OFF | 30 | * register values to turn OFDM weak signal detection OFF |
35 | */ | 31 | */ |
@@ -921,7 +917,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, | |||
921 | struct ath_common *common = ath9k_hw_common(ah); | 917 | struct ath_common *common = ath9k_hw_common(ah); |
922 | struct ath9k_channel *chan = ah->curchan; | 918 | struct ath9k_channel *chan = ah->curchan; |
923 | struct ar5416AniState *aniState = &ah->ani; | 919 | struct ar5416AniState *aniState = &ah->ani; |
924 | s32 value, value2; | 920 | s32 value; |
925 | 921 | ||
926 | switch (cmd & ah->ani_function) { | 922 | switch (cmd & ah->ani_function) { |
927 | case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{ | 923 | case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{ |
@@ -1008,42 +1004,11 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, | |||
1008 | case ATH9K_ANI_FIRSTEP_LEVEL:{ | 1004 | case ATH9K_ANI_FIRSTEP_LEVEL:{ |
1009 | u32 level = param; | 1005 | u32 level = param; |
1010 | 1006 | ||
1011 | if (level >= ARRAY_SIZE(firstep_table)) { | 1007 | value = level * 2; |
1012 | ath_dbg(common, ANI, | ||
1013 | "ATH9K_ANI_FIRSTEP_LEVEL: level out of range (%u > %zu)\n", | ||
1014 | level, ARRAY_SIZE(firstep_table)); | ||
1015 | return false; | ||
1016 | } | ||
1017 | |||
1018 | /* | ||
1019 | * make register setting relative to default | ||
1020 | * from INI file & cap value | ||
1021 | */ | ||
1022 | value = firstep_table[level] - | ||
1023 | firstep_table[ATH9K_ANI_FIRSTEP_LVL] + | ||
1024 | aniState->iniDef.firstep; | ||
1025 | if (value < ATH9K_SIG_FIRSTEP_SETTING_MIN) | ||
1026 | value = ATH9K_SIG_FIRSTEP_SETTING_MIN; | ||
1027 | if (value > ATH9K_SIG_FIRSTEP_SETTING_MAX) | ||
1028 | value = ATH9K_SIG_FIRSTEP_SETTING_MAX; | ||
1029 | REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, | 1008 | REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, |
1030 | AR_PHY_FIND_SIG_FIRSTEP, | 1009 | AR_PHY_FIND_SIG_FIRSTEP, value); |
1031 | value); | ||
1032 | /* | ||
1033 | * we need to set first step low register too | ||
1034 | * make register setting relative to default | ||
1035 | * from INI file & cap value | ||
1036 | */ | ||
1037 | value2 = firstep_table[level] - | ||
1038 | firstep_table[ATH9K_ANI_FIRSTEP_LVL] + | ||
1039 | aniState->iniDef.firstepLow; | ||
1040 | if (value2 < ATH9K_SIG_FIRSTEP_SETTING_MIN) | ||
1041 | value2 = ATH9K_SIG_FIRSTEP_SETTING_MIN; | ||
1042 | if (value2 > ATH9K_SIG_FIRSTEP_SETTING_MAX) | ||
1043 | value2 = ATH9K_SIG_FIRSTEP_SETTING_MAX; | ||
1044 | |||
1045 | REG_RMW_FIELD(ah, AR_PHY_FIND_SIG_LOW, | 1010 | REG_RMW_FIELD(ah, AR_PHY_FIND_SIG_LOW, |
1046 | AR_PHY_FIND_SIG_FIRSTEP_LOW, value2); | 1011 | AR_PHY_FIND_SIG_FIRSTEP_LOW, value); |
1047 | 1012 | ||
1048 | if (level != aniState->firstepLevel) { | 1013 | if (level != aniState->firstepLevel) { |
1049 | ath_dbg(common, ANI, | 1014 | ath_dbg(common, ANI, |
@@ -1060,7 +1025,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, | |||
1060 | aniState->firstepLevel, | 1025 | aniState->firstepLevel, |
1061 | level, | 1026 | level, |
1062 | ATH9K_ANI_FIRSTEP_LVL, | 1027 | ATH9K_ANI_FIRSTEP_LVL, |
1063 | value2, | 1028 | value, |
1064 | aniState->iniDef.firstepLow); | 1029 | aniState->iniDef.firstepLow); |
1065 | if (level > aniState->firstepLevel) | 1030 | if (level > aniState->firstepLevel) |
1066 | ah->stats.ast_ani_stepup++; | 1031 | ah->stats.ast_ani_stepup++; |
@@ -1073,41 +1038,13 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, | |||
1073 | case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{ | 1038 | case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{ |
1074 | u32 level = param; | 1039 | u32 level = param; |
1075 | 1040 | ||
1076 | if (level >= ARRAY_SIZE(cycpwrThr1_table)) { | 1041 | value = (level + 1) * 2; |
1077 | ath_dbg(common, ANI, | ||
1078 | "ATH9K_ANI_SPUR_IMMUNITY_LEVEL: level out of range (%u > %zu)\n", | ||
1079 | level, ARRAY_SIZE(cycpwrThr1_table)); | ||
1080 | return false; | ||
1081 | } | ||
1082 | /* | ||
1083 | * make register setting relative to default | ||
1084 | * from INI file & cap value | ||
1085 | */ | ||
1086 | value = cycpwrThr1_table[level] - | ||
1087 | cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL] + | ||
1088 | aniState->iniDef.cycpwrThr1; | ||
1089 | if (value < ATH9K_SIG_SPUR_IMM_SETTING_MIN) | ||
1090 | value = ATH9K_SIG_SPUR_IMM_SETTING_MIN; | ||
1091 | if (value > ATH9K_SIG_SPUR_IMM_SETTING_MAX) | ||
1092 | value = ATH9K_SIG_SPUR_IMM_SETTING_MAX; | ||
1093 | REG_RMW_FIELD(ah, AR_PHY_TIMING5, | 1042 | REG_RMW_FIELD(ah, AR_PHY_TIMING5, |
1094 | AR_PHY_TIMING5_CYCPWR_THR1, | 1043 | AR_PHY_TIMING5_CYCPWR_THR1, value); |
1095 | value); | ||
1096 | 1044 | ||
1097 | /* | 1045 | if (IS_CHAN_HT40(ah->curchan)) |
1098 | * set AR_PHY_EXT_CCA for extension channel | 1046 | REG_RMW_FIELD(ah, AR_PHY_EXT_CCA, |
1099 | * make register setting relative to default | 1047 | AR_PHY_EXT_TIMING5_CYCPWR_THR1, value); |
1100 | * from INI file & cap value | ||
1101 | */ | ||
1102 | value2 = cycpwrThr1_table[level] - | ||
1103 | cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL] + | ||
1104 | aniState->iniDef.cycpwrThr1Ext; | ||
1105 | if (value2 < ATH9K_SIG_SPUR_IMM_SETTING_MIN) | ||
1106 | value2 = ATH9K_SIG_SPUR_IMM_SETTING_MIN; | ||
1107 | if (value2 > ATH9K_SIG_SPUR_IMM_SETTING_MAX) | ||
1108 | value2 = ATH9K_SIG_SPUR_IMM_SETTING_MAX; | ||
1109 | REG_RMW_FIELD(ah, AR_PHY_EXT_CCA, | ||
1110 | AR_PHY_EXT_TIMING5_CYCPWR_THR1, value2); | ||
1111 | 1048 | ||
1112 | if (level != aniState->spurImmunityLevel) { | 1049 | if (level != aniState->spurImmunityLevel) { |
1113 | ath_dbg(common, ANI, | 1050 | ath_dbg(common, ANI, |
@@ -1124,7 +1061,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, | |||
1124 | aniState->spurImmunityLevel, | 1061 | aniState->spurImmunityLevel, |
1125 | level, | 1062 | level, |
1126 | ATH9K_ANI_SPUR_IMMUNE_LVL, | 1063 | ATH9K_ANI_SPUR_IMMUNE_LVL, |
1127 | value2, | 1064 | value, |
1128 | aniState->iniDef.cycpwrThr1Ext); | 1065 | aniState->iniDef.cycpwrThr1Ext); |
1129 | if (level > aniState->spurImmunityLevel) | 1066 | if (level > aniState->spurImmunityLevel) |
1130 | ah->stats.ast_ani_spurup++; | 1067 | ah->stats.ast_ani_spurup++; |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index b8daff78b9d1..235053ba7737 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | |||
@@ -23,8 +23,8 @@ | |||
23 | #define COMP_HDR_LEN 4 | 23 | #define COMP_HDR_LEN 4 |
24 | #define COMP_CKSUM_LEN 2 | 24 | #define COMP_CKSUM_LEN 2 |
25 | 25 | ||
26 | #define LE16(x) __constant_cpu_to_le16(x) | 26 | #define LE16(x) cpu_to_le16(x) |
27 | #define LE32(x) __constant_cpu_to_le32(x) | 27 | #define LE32(x) cpu_to_le32(x) |
28 | 28 | ||
29 | /* Local defines to distinguish between extension and control CTL's */ | 29 | /* Local defines to distinguish between extension and control CTL's */ |
30 | #define EXT_ADDITIVE (0x8000) | 30 | #define EXT_ADDITIVE (0x8000) |
@@ -4792,43 +4792,54 @@ static void ar9003_hw_power_control_override(struct ath_hw *ah, | |||
4792 | 4792 | ||
4793 | tempslope: | 4793 | tempslope: |
4794 | if (AR_SREV_9550(ah) || AR_SREV_9531(ah)) { | 4794 | if (AR_SREV_9550(ah) || AR_SREV_9531(ah)) { |
4795 | u8 txmask = (eep->baseEepHeader.txrxMask & 0xf0) >> 4; | ||
4796 | |||
4795 | /* | 4797 | /* |
4796 | * AR955x has tempSlope register for each chain. | 4798 | * AR955x has tempSlope register for each chain. |
4797 | * Check whether temp_compensation feature is enabled or not. | 4799 | * Check whether temp_compensation feature is enabled or not. |
4798 | */ | 4800 | */ |
4799 | if (eep->baseEepHeader.featureEnable & 0x1) { | 4801 | if (eep->baseEepHeader.featureEnable & 0x1) { |
4800 | if (frequency < 4000) { | 4802 | if (frequency < 4000) { |
4801 | REG_RMW_FIELD(ah, AR_PHY_TPC_19, | 4803 | if (txmask & BIT(0)) |
4802 | AR_PHY_TPC_19_ALPHA_THERM, | 4804 | REG_RMW_FIELD(ah, AR_PHY_TPC_19, |
4803 | eep->base_ext2.tempSlopeLow); | 4805 | AR_PHY_TPC_19_ALPHA_THERM, |
4804 | REG_RMW_FIELD(ah, AR_PHY_TPC_19_B1, | 4806 | eep->base_ext2.tempSlopeLow); |
4805 | AR_PHY_TPC_19_ALPHA_THERM, | 4807 | if (txmask & BIT(1)) |
4806 | temp_slope); | 4808 | REG_RMW_FIELD(ah, AR_PHY_TPC_19_B1, |
4807 | REG_RMW_FIELD(ah, AR_PHY_TPC_19_B2, | 4809 | AR_PHY_TPC_19_ALPHA_THERM, |
4808 | AR_PHY_TPC_19_ALPHA_THERM, | 4810 | temp_slope); |
4809 | eep->base_ext2.tempSlopeHigh); | 4811 | if (txmask & BIT(2)) |
4812 | REG_RMW_FIELD(ah, AR_PHY_TPC_19_B2, | ||
4813 | AR_PHY_TPC_19_ALPHA_THERM, | ||
4814 | eep->base_ext2.tempSlopeHigh); | ||
4810 | } else { | 4815 | } else { |
4811 | REG_RMW_FIELD(ah, AR_PHY_TPC_19, | 4816 | if (txmask & BIT(0)) |
4812 | AR_PHY_TPC_19_ALPHA_THERM, | 4817 | REG_RMW_FIELD(ah, AR_PHY_TPC_19, |
4813 | temp_slope); | 4818 | AR_PHY_TPC_19_ALPHA_THERM, |
4814 | REG_RMW_FIELD(ah, AR_PHY_TPC_19_B1, | 4819 | temp_slope); |
4815 | AR_PHY_TPC_19_ALPHA_THERM, | 4820 | if (txmask & BIT(1)) |
4816 | temp_slope1); | 4821 | REG_RMW_FIELD(ah, AR_PHY_TPC_19_B1, |
4817 | REG_RMW_FIELD(ah, AR_PHY_TPC_19_B2, | 4822 | AR_PHY_TPC_19_ALPHA_THERM, |
4818 | AR_PHY_TPC_19_ALPHA_THERM, | 4823 | temp_slope1); |
4819 | temp_slope2); | 4824 | if (txmask & BIT(2)) |
4825 | REG_RMW_FIELD(ah, AR_PHY_TPC_19_B2, | ||
4826 | AR_PHY_TPC_19_ALPHA_THERM, | ||
4827 | temp_slope2); | ||
4820 | } | 4828 | } |
4821 | } else { | 4829 | } else { |
4822 | /* | 4830 | /* |
4823 | * If temp compensation is not enabled, | 4831 | * If temp compensation is not enabled, |
4824 | * set all registers to 0. | 4832 | * set all registers to 0. |
4825 | */ | 4833 | */ |
4826 | REG_RMW_FIELD(ah, AR_PHY_TPC_19, | 4834 | if (txmask & BIT(0)) |
4827 | AR_PHY_TPC_19_ALPHA_THERM, 0); | 4835 | REG_RMW_FIELD(ah, AR_PHY_TPC_19, |
4828 | REG_RMW_FIELD(ah, AR_PHY_TPC_19_B1, | 4836 | AR_PHY_TPC_19_ALPHA_THERM, 0); |
4829 | AR_PHY_TPC_19_ALPHA_THERM, 0); | 4837 | if (txmask & BIT(1)) |
4830 | REG_RMW_FIELD(ah, AR_PHY_TPC_19_B2, | 4838 | REG_RMW_FIELD(ah, AR_PHY_TPC_19_B1, |
4831 | AR_PHY_TPC_19_ALPHA_THERM, 0); | 4839 | AR_PHY_TPC_19_ALPHA_THERM, 0); |
4840 | if (txmask & BIT(2)) | ||
4841 | REG_RMW_FIELD(ah, AR_PHY_TPC_19_B2, | ||
4842 | AR_PHY_TPC_19_ALPHA_THERM, 0); | ||
4832 | } | 4843 | } |
4833 | } else { | 4844 | } else { |
4834 | REG_RMW_FIELD(ah, AR_PHY_TPC_19, | 4845 | REG_RMW_FIELD(ah, AR_PHY_TPC_19, |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index f995c374a9b4..44d74495c4de 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -403,20 +403,10 @@ void ath9k_calculate_iter_data(struct ieee80211_hw *hw, | |||
403 | #define ATH_BCBUF 8 | 403 | #define ATH_BCBUF 8 |
404 | #define ATH_DEFAULT_BINTVAL 100 /* TU */ | 404 | #define ATH_DEFAULT_BINTVAL 100 /* TU */ |
405 | #define ATH_DEFAULT_BMISS_LIMIT 10 | 405 | #define ATH_DEFAULT_BMISS_LIMIT 10 |
406 | #define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024) | ||
407 | 406 | ||
408 | #define TSF_TO_TU(_h,_l) \ | 407 | #define TSF_TO_TU(_h,_l) \ |
409 | ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10)) | 408 | ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10)) |
410 | 409 | ||
411 | struct ath_beacon_config { | ||
412 | int beacon_interval; | ||
413 | u16 dtim_period; | ||
414 | u16 bmiss_timeout; | ||
415 | u8 dtim_count; | ||
416 | bool enable_beacon; | ||
417 | bool ibss_creator; | ||
418 | }; | ||
419 | |||
420 | struct ath_beacon { | 410 | struct ath_beacon { |
421 | enum { | 411 | enum { |
422 | OK, /* no change needed */ | 412 | OK, /* no change needed */ |
@@ -426,11 +416,9 @@ struct ath_beacon { | |||
426 | 416 | ||
427 | u32 beaconq; | 417 | u32 beaconq; |
428 | u32 bmisscnt; | 418 | u32 bmisscnt; |
429 | u32 bc_tstamp; | ||
430 | struct ieee80211_vif *bslot[ATH_BCBUF]; | 419 | struct ieee80211_vif *bslot[ATH_BCBUF]; |
431 | int slottime; | 420 | int slottime; |
432 | int slotupdate; | 421 | int slotupdate; |
433 | struct ath9k_tx_queue_info beacon_qi; | ||
434 | struct ath_descdma bdma; | 422 | struct ath_descdma bdma; |
435 | struct ath_txq *cabq; | 423 | struct ath_txq *cabq; |
436 | struct list_head bbuf; | 424 | struct list_head bbuf; |
@@ -697,15 +685,6 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs); | |||
697 | #define ATH_TXPOWER_MAX 100 /* .5 dBm units */ | 685 | #define ATH_TXPOWER_MAX 100 /* .5 dBm units */ |
698 | #define MAX_GTT_CNT 5 | 686 | #define MAX_GTT_CNT 5 |
699 | 687 | ||
700 | enum sc_op_flags { | ||
701 | SC_OP_INVALID, | ||
702 | SC_OP_BEACONS, | ||
703 | SC_OP_ANI_RUN, | ||
704 | SC_OP_PRIM_STA_VIF, | ||
705 | SC_OP_HW_RESET, | ||
706 | SC_OP_SCANNING, | ||
707 | }; | ||
708 | |||
709 | /* Powersave flags */ | 688 | /* Powersave flags */ |
710 | #define PS_WAIT_FOR_BEACON BIT(0) | 689 | #define PS_WAIT_FOR_BEACON BIT(0) |
711 | #define PS_WAIT_FOR_CAB BIT(1) | 690 | #define PS_WAIT_FOR_CAB BIT(1) |
@@ -735,7 +714,6 @@ struct ath_softc { | |||
735 | struct completion paprd_complete; | 714 | struct completion paprd_complete; |
736 | wait_queue_head_t tx_wait; | 715 | wait_queue_head_t tx_wait; |
737 | 716 | ||
738 | unsigned long sc_flags; | ||
739 | unsigned long driver_data; | 717 | unsigned long driver_data; |
740 | 718 | ||
741 | u8 gtt_cnt; | 719 | u8 gtt_cnt; |
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 02eb4f10332b..471e0f624e81 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c | |||
@@ -328,7 +328,7 @@ void ath9k_beacon_tasklet(unsigned long data) | |||
328 | bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA); | 328 | bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA); |
329 | int slot; | 329 | int slot; |
330 | 330 | ||
331 | if (test_bit(SC_OP_HW_RESET, &sc->sc_flags)) { | 331 | if (test_bit(ATH_OP_HW_RESET, &common->op_flags)) { |
332 | ath_dbg(common, RESET, | 332 | ath_dbg(common, RESET, |
333 | "reset work is pending, skip beaconing now\n"); | 333 | "reset work is pending, skip beaconing now\n"); |
334 | return; | 334 | return; |
@@ -447,33 +447,6 @@ static void ath9k_beacon_init(struct ath_softc *sc, u32 nexttbtt, | |||
447 | ath9k_hw_enable_interrupts(ah); | 447 | ath9k_hw_enable_interrupts(ah); |
448 | } | 448 | } |
449 | 449 | ||
450 | /* Calculate the modulo of a 64 bit TSF snapshot with a TU divisor */ | ||
451 | static u32 ath9k_mod_tsf64_tu(u64 tsf, u32 div_tu) | ||
452 | { | ||
453 | u32 tsf_mod, tsf_hi, tsf_lo, mod_hi, mod_lo; | ||
454 | |||
455 | tsf_mod = tsf & (BIT(10) - 1); | ||
456 | tsf_hi = tsf >> 32; | ||
457 | tsf_lo = ((u32) tsf) >> 10; | ||
458 | |||
459 | mod_hi = tsf_hi % div_tu; | ||
460 | mod_lo = ((mod_hi << 22) + tsf_lo) % div_tu; | ||
461 | |||
462 | return (mod_lo << 10) | tsf_mod; | ||
463 | } | ||
464 | |||
465 | static u32 ath9k_get_next_tbtt(struct ath_softc *sc, u64 tsf, | ||
466 | unsigned int interval) | ||
467 | { | ||
468 | struct ath_hw *ah = sc->sc_ah; | ||
469 | unsigned int offset; | ||
470 | |||
471 | tsf += TU_TO_USEC(FUDGE + ah->config.sw_beacon_response_time); | ||
472 | offset = ath9k_mod_tsf64_tu(tsf, interval); | ||
473 | |||
474 | return (u32) tsf + TU_TO_USEC(interval) - offset; | ||
475 | } | ||
476 | |||
477 | /* | 450 | /* |
478 | * For multi-bss ap support beacons are either staggered evenly over N slots or | 451 | * For multi-bss ap support beacons are either staggered evenly over N slots or |
479 | * burst together. For the former arrange for the SWBA to be delivered for each | 452 | * burst together. For the former arrange for the SWBA to be delivered for each |
@@ -483,109 +456,18 @@ static void ath9k_beacon_config_ap(struct ath_softc *sc, | |||
483 | struct ath_beacon_config *conf) | 456 | struct ath_beacon_config *conf) |
484 | { | 457 | { |
485 | struct ath_hw *ah = sc->sc_ah; | 458 | struct ath_hw *ah = sc->sc_ah; |
486 | struct ath_common *common = ath9k_hw_common(ah); | ||
487 | u32 nexttbtt, intval; | ||
488 | |||
489 | /* NB: the beacon interval is kept internally in TU's */ | ||
490 | intval = TU_TO_USEC(conf->beacon_interval); | ||
491 | intval /= ATH_BCBUF; | ||
492 | nexttbtt = ath9k_get_next_tbtt(sc, ath9k_hw_gettsf64(ah), | ||
493 | conf->beacon_interval); | ||
494 | |||
495 | if (conf->enable_beacon) | ||
496 | ah->imask |= ATH9K_INT_SWBA; | ||
497 | else | ||
498 | ah->imask &= ~ATH9K_INT_SWBA; | ||
499 | 459 | ||
500 | ath_dbg(common, BEACON, | 460 | ath9k_cmn_beacon_config_ap(ah, conf, ATH_BCBUF); |
501 | "AP (%s) nexttbtt: %u intval: %u conf_intval: %u\n", | 461 | ath9k_beacon_init(sc, conf->nexttbtt, conf->intval, false); |
502 | (conf->enable_beacon) ? "Enable" : "Disable", | ||
503 | nexttbtt, intval, conf->beacon_interval); | ||
504 | |||
505 | ath9k_beacon_init(sc, nexttbtt, intval, false); | ||
506 | } | 462 | } |
507 | 463 | ||
508 | /* | 464 | static void ath9k_beacon_config_sta(struct ath_hw *ah, |
509 | * This sets up the beacon timers according to the timestamp of the last | ||
510 | * received beacon and the current TSF, configures PCF and DTIM | ||
511 | * handling, programs the sleep registers so the hardware will wakeup in | ||
512 | * time to receive beacons, and configures the beacon miss handling so | ||
513 | * we'll receive a BMISS interrupt when we stop seeing beacons from the AP | ||
514 | * we've associated with. | ||
515 | */ | ||
516 | static void ath9k_beacon_config_sta(struct ath_softc *sc, | ||
517 | struct ath_beacon_config *conf) | 465 | struct ath_beacon_config *conf) |
518 | { | 466 | { |
519 | struct ath_hw *ah = sc->sc_ah; | ||
520 | struct ath_common *common = ath9k_hw_common(ah); | ||
521 | struct ath9k_beacon_state bs; | 467 | struct ath9k_beacon_state bs; |
522 | int dtim_intval; | ||
523 | u32 nexttbtt = 0, intval; | ||
524 | u64 tsf; | ||
525 | 468 | ||
526 | /* No need to configure beacon if we are not associated */ | 469 | if (ath9k_cmn_beacon_config_sta(ah, conf, &bs) == -EPERM) |
527 | if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) { | ||
528 | ath_dbg(common, BEACON, | ||
529 | "STA is not yet associated..skipping beacon config\n"); | ||
530 | return; | 470 | return; |
531 | } | ||
532 | |||
533 | memset(&bs, 0, sizeof(bs)); | ||
534 | intval = conf->beacon_interval; | ||
535 | |||
536 | /* | ||
537 | * Setup dtim parameters according to | ||
538 | * last beacon we received (which may be none). | ||
539 | */ | ||
540 | dtim_intval = intval * conf->dtim_period; | ||
541 | |||
542 | /* | ||
543 | * Pull nexttbtt forward to reflect the current | ||
544 | * TSF and calculate dtim state for the result. | ||
545 | */ | ||
546 | tsf = ath9k_hw_gettsf64(ah); | ||
547 | nexttbtt = ath9k_get_next_tbtt(sc, tsf, intval); | ||
548 | |||
549 | bs.bs_intval = TU_TO_USEC(intval); | ||
550 | bs.bs_dtimperiod = conf->dtim_period * bs.bs_intval; | ||
551 | bs.bs_nexttbtt = nexttbtt; | ||
552 | bs.bs_nextdtim = nexttbtt; | ||
553 | if (conf->dtim_period > 1) | ||
554 | bs.bs_nextdtim = ath9k_get_next_tbtt(sc, tsf, dtim_intval); | ||
555 | |||
556 | /* | ||
557 | * Calculate the number of consecutive beacons to miss* before taking | ||
558 | * a BMISS interrupt. The configuration is specified in TU so we only | ||
559 | * need calculate based on the beacon interval. Note that we clamp the | ||
560 | * result to at most 15 beacons. | ||
561 | */ | ||
562 | bs.bs_bmissthreshold = DIV_ROUND_UP(conf->bmiss_timeout, intval); | ||
563 | if (bs.bs_bmissthreshold > 15) | ||
564 | bs.bs_bmissthreshold = 15; | ||
565 | else if (bs.bs_bmissthreshold <= 0) | ||
566 | bs.bs_bmissthreshold = 1; | ||
567 | |||
568 | /* | ||
569 | * Calculate sleep duration. The configuration is given in ms. | ||
570 | * We ensure a multiple of the beacon period is used. Also, if the sleep | ||
571 | * duration is greater than the DTIM period then it makes senses | ||
572 | * to make it a multiple of that. | ||
573 | * | ||
574 | * XXX fixed at 100ms | ||
575 | */ | ||
576 | |||
577 | bs.bs_sleepduration = TU_TO_USEC(roundup(IEEE80211_MS_TO_TU(100), | ||
578 | intval)); | ||
579 | if (bs.bs_sleepduration > bs.bs_dtimperiod) | ||
580 | bs.bs_sleepduration = bs.bs_dtimperiod; | ||
581 | |||
582 | /* TSF out of range threshold fixed at 1 second */ | ||
583 | bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD; | ||
584 | |||
585 | ath_dbg(common, BEACON, "bmiss: %u sleep: %u\n", | ||
586 | bs.bs_bmissthreshold, bs.bs_sleepduration); | ||
587 | |||
588 | /* Set the computed STA beacon timers */ | ||
589 | 471 | ||
590 | ath9k_hw_disable_interrupts(ah); | 472 | ath9k_hw_disable_interrupts(ah); |
591 | ath9k_hw_set_sta_beacon_timers(ah, &bs); | 473 | ath9k_hw_set_sta_beacon_timers(ah, &bs); |
@@ -600,36 +482,19 @@ static void ath9k_beacon_config_adhoc(struct ath_softc *sc, | |||
600 | { | 482 | { |
601 | struct ath_hw *ah = sc->sc_ah; | 483 | struct ath_hw *ah = sc->sc_ah; |
602 | struct ath_common *common = ath9k_hw_common(ah); | 484 | struct ath_common *common = ath9k_hw_common(ah); |
603 | u32 intval, nexttbtt; | ||
604 | 485 | ||
605 | ath9k_reset_beacon_status(sc); | 486 | ath9k_reset_beacon_status(sc); |
606 | 487 | ||
607 | intval = TU_TO_USEC(conf->beacon_interval); | 488 | ath9k_cmn_beacon_config_adhoc(ah, conf); |
608 | |||
609 | if (conf->ibss_creator) | ||
610 | nexttbtt = intval; | ||
611 | else | ||
612 | nexttbtt = ath9k_get_next_tbtt(sc, ath9k_hw_gettsf64(ah), | ||
613 | conf->beacon_interval); | ||
614 | |||
615 | if (conf->enable_beacon) | ||
616 | ah->imask |= ATH9K_INT_SWBA; | ||
617 | else | ||
618 | ah->imask &= ~ATH9K_INT_SWBA; | ||
619 | |||
620 | ath_dbg(common, BEACON, | ||
621 | "IBSS (%s) nexttbtt: %u intval: %u conf_intval: %u\n", | ||
622 | (conf->enable_beacon) ? "Enable" : "Disable", | ||
623 | nexttbtt, intval, conf->beacon_interval); | ||
624 | 489 | ||
625 | ath9k_beacon_init(sc, nexttbtt, intval, conf->ibss_creator); | 490 | ath9k_beacon_init(sc, conf->nexttbtt, conf->intval, conf->ibss_creator); |
626 | 491 | ||
627 | /* | 492 | /* |
628 | * Set the global 'beacon has been configured' flag for the | 493 | * Set the global 'beacon has been configured' flag for the |
629 | * joiner case in IBSS mode. | 494 | * joiner case in IBSS mode. |
630 | */ | 495 | */ |
631 | if (!conf->ibss_creator && conf->enable_beacon) | 496 | if (!conf->ibss_creator && conf->enable_beacon) |
632 | set_bit(SC_OP_BEACONS, &sc->sc_flags); | 497 | set_bit(ATH_OP_BEACONS, &common->op_flags); |
633 | } | 498 | } |
634 | 499 | ||
635 | static bool ath9k_allow_beacon_config(struct ath_softc *sc, | 500 | static bool ath9k_allow_beacon_config(struct ath_softc *sc, |
@@ -649,7 +514,7 @@ static bool ath9k_allow_beacon_config(struct ath_softc *sc, | |||
649 | 514 | ||
650 | if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION) { | 515 | if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION) { |
651 | if ((vif->type == NL80211_IFTYPE_STATION) && | 516 | if ((vif->type == NL80211_IFTYPE_STATION) && |
652 | test_bit(SC_OP_BEACONS, &sc->sc_flags) && | 517 | test_bit(ATH_OP_BEACONS, &common->op_flags) && |
653 | !avp->primary_sta_vif) { | 518 | !avp->primary_sta_vif) { |
654 | ath_dbg(common, CONFIG, | 519 | ath_dbg(common, CONFIG, |
655 | "Beacon already configured for a station interface\n"); | 520 | "Beacon already configured for a station interface\n"); |
@@ -700,6 +565,8 @@ void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif, | |||
700 | { | 565 | { |
701 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | 566 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; |
702 | struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; | 567 | struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; |
568 | struct ath_hw *ah = sc->sc_ah; | ||
569 | struct ath_common *common = ath9k_hw_common(ah); | ||
703 | unsigned long flags; | 570 | unsigned long flags; |
704 | bool skip_beacon = false; | 571 | bool skip_beacon = false; |
705 | 572 | ||
@@ -712,7 +579,7 @@ void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif, | |||
712 | if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION) { | 579 | if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION) { |
713 | ath9k_cache_beacon_config(sc, bss_conf); | 580 | ath9k_cache_beacon_config(sc, bss_conf); |
714 | ath9k_set_beacon(sc); | 581 | ath9k_set_beacon(sc); |
715 | set_bit(SC_OP_BEACONS, &sc->sc_flags); | 582 | set_bit(ATH_OP_BEACONS, &common->op_flags); |
716 | return; | 583 | return; |
717 | } | 584 | } |
718 | 585 | ||
@@ -751,13 +618,13 @@ void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif, | |||
751 | } | 618 | } |
752 | 619 | ||
753 | /* | 620 | /* |
754 | * Do not set the SC_OP_BEACONS flag for IBSS joiner mode | 621 | * Do not set the ATH_OP_BEACONS flag for IBSS joiner mode |
755 | * here, it is done in ath9k_beacon_config_adhoc(). | 622 | * here, it is done in ath9k_beacon_config_adhoc(). |
756 | */ | 623 | */ |
757 | if (cur_conf->enable_beacon && !skip_beacon) | 624 | if (cur_conf->enable_beacon && !skip_beacon) |
758 | set_bit(SC_OP_BEACONS, &sc->sc_flags); | 625 | set_bit(ATH_OP_BEACONS, &common->op_flags); |
759 | else | 626 | else |
760 | clear_bit(SC_OP_BEACONS, &sc->sc_flags); | 627 | clear_bit(ATH_OP_BEACONS, &common->op_flags); |
761 | } | 628 | } |
762 | } | 629 | } |
763 | 630 | ||
@@ -775,7 +642,7 @@ void ath9k_set_beacon(struct ath_softc *sc) | |||
775 | ath9k_beacon_config_adhoc(sc, cur_conf); | 642 | ath9k_beacon_config_adhoc(sc, cur_conf); |
776 | break; | 643 | break; |
777 | case NL80211_IFTYPE_STATION: | 644 | case NL80211_IFTYPE_STATION: |
778 | ath9k_beacon_config_sta(sc, cur_conf); | 645 | ath9k_beacon_config_sta(sc->sc_ah, cur_conf); |
779 | break; | 646 | break; |
780 | default: | 647 | default: |
781 | ath_dbg(common, CONFIG, "Unsupported beaconing mode\n"); | 648 | ath_dbg(common, CONFIG, "Unsupported beaconing mode\n"); |
diff --git a/drivers/net/wireless/ath/ath9k/common-beacon.c b/drivers/net/wireless/ath/ath9k/common-beacon.c new file mode 100644 index 000000000000..775d1d20ce0b --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/common-beacon.c | |||
@@ -0,0 +1,180 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-2011 Atheros Communications Inc. | ||
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 | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include "common.h" | ||
18 | |||
19 | #define FUDGE 2 | ||
20 | |||
21 | /* Calculate the modulo of a 64 bit TSF snapshot with a TU divisor */ | ||
22 | static u32 ath9k_mod_tsf64_tu(u64 tsf, u32 div_tu) | ||
23 | { | ||
24 | u32 tsf_mod, tsf_hi, tsf_lo, mod_hi, mod_lo; | ||
25 | |||
26 | tsf_mod = tsf & (BIT(10) - 1); | ||
27 | tsf_hi = tsf >> 32; | ||
28 | tsf_lo = ((u32) tsf) >> 10; | ||
29 | |||
30 | mod_hi = tsf_hi % div_tu; | ||
31 | mod_lo = ((mod_hi << 22) + tsf_lo) % div_tu; | ||
32 | |||
33 | return (mod_lo << 10) | tsf_mod; | ||
34 | } | ||
35 | |||
36 | static u32 ath9k_get_next_tbtt(struct ath_hw *ah, u64 tsf, | ||
37 | unsigned int interval) | ||
38 | { | ||
39 | unsigned int offset; | ||
40 | |||
41 | tsf += TU_TO_USEC(FUDGE + ah->config.sw_beacon_response_time); | ||
42 | offset = ath9k_mod_tsf64_tu(tsf, interval); | ||
43 | |||
44 | return (u32) tsf + TU_TO_USEC(interval) - offset; | ||
45 | } | ||
46 | |||
47 | /* | ||
48 | * This sets up the beacon timers according to the timestamp of the last | ||
49 | * received beacon and the current TSF, configures PCF and DTIM | ||
50 | * handling, programs the sleep registers so the hardware will wakeup in | ||
51 | * time to receive beacons, and configures the beacon miss handling so | ||
52 | * we'll receive a BMISS interrupt when we stop seeing beacons from the AP | ||
53 | * we've associated with. | ||
54 | */ | ||
55 | int ath9k_cmn_beacon_config_sta(struct ath_hw *ah, | ||
56 | struct ath_beacon_config *conf, | ||
57 | struct ath9k_beacon_state *bs) | ||
58 | { | ||
59 | struct ath_common *common = ath9k_hw_common(ah); | ||
60 | int dtim_intval; | ||
61 | u64 tsf; | ||
62 | |||
63 | /* No need to configure beacon if we are not associated */ | ||
64 | if (!test_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags)) { | ||
65 | ath_dbg(common, BEACON, | ||
66 | "STA is not yet associated..skipping beacon config\n"); | ||
67 | return -EPERM; | ||
68 | } | ||
69 | |||
70 | memset(bs, 0, sizeof(*bs)); | ||
71 | conf->intval = conf->beacon_interval; | ||
72 | |||
73 | /* | ||
74 | * Setup dtim parameters according to | ||
75 | * last beacon we received (which may be none). | ||
76 | */ | ||
77 | dtim_intval = conf->intval * conf->dtim_period; | ||
78 | |||
79 | /* | ||
80 | * Pull nexttbtt forward to reflect the current | ||
81 | * TSF and calculate dtim state for the result. | ||
82 | */ | ||
83 | tsf = ath9k_hw_gettsf64(ah); | ||
84 | conf->nexttbtt = ath9k_get_next_tbtt(ah, tsf, conf->intval); | ||
85 | |||
86 | bs->bs_intval = TU_TO_USEC(conf->intval); | ||
87 | bs->bs_dtimperiod = conf->dtim_period * bs->bs_intval; | ||
88 | bs->bs_nexttbtt = conf->nexttbtt; | ||
89 | bs->bs_nextdtim = conf->nexttbtt; | ||
90 | if (conf->dtim_period > 1) | ||
91 | bs->bs_nextdtim = ath9k_get_next_tbtt(ah, tsf, dtim_intval); | ||
92 | |||
93 | /* | ||
94 | * Calculate the number of consecutive beacons to miss* before taking | ||
95 | * a BMISS interrupt. The configuration is specified in TU so we only | ||
96 | * need calculate based on the beacon interval. Note that we clamp the | ||
97 | * result to at most 15 beacons. | ||
98 | */ | ||
99 | bs->bs_bmissthreshold = DIV_ROUND_UP(conf->bmiss_timeout, conf->intval); | ||
100 | if (bs->bs_bmissthreshold > 15) | ||
101 | bs->bs_bmissthreshold = 15; | ||
102 | else if (bs->bs_bmissthreshold <= 0) | ||
103 | bs->bs_bmissthreshold = 1; | ||
104 | |||
105 | /* | ||
106 | * Calculate sleep duration. The configuration is given in ms. | ||
107 | * We ensure a multiple of the beacon period is used. Also, if the sleep | ||
108 | * duration is greater than the DTIM period then it makes senses | ||
109 | * to make it a multiple of that. | ||
110 | * | ||
111 | * XXX fixed at 100ms | ||
112 | */ | ||
113 | |||
114 | bs->bs_sleepduration = TU_TO_USEC(roundup(IEEE80211_MS_TO_TU(100), | ||
115 | conf->intval)); | ||
116 | if (bs->bs_sleepduration > bs->bs_dtimperiod) | ||
117 | bs->bs_sleepduration = bs->bs_dtimperiod; | ||
118 | |||
119 | /* TSF out of range threshold fixed at 1 second */ | ||
120 | bs->bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD; | ||
121 | |||
122 | ath_dbg(common, BEACON, "bmiss: %u sleep: %u\n", | ||
123 | bs->bs_bmissthreshold, bs->bs_sleepduration); | ||
124 | return 0; | ||
125 | } | ||
126 | EXPORT_SYMBOL(ath9k_cmn_beacon_config_sta); | ||
127 | |||
128 | void ath9k_cmn_beacon_config_adhoc(struct ath_hw *ah, | ||
129 | struct ath_beacon_config *conf) | ||
130 | { | ||
131 | struct ath_common *common = ath9k_hw_common(ah); | ||
132 | |||
133 | conf->intval = TU_TO_USEC(conf->beacon_interval); | ||
134 | |||
135 | if (conf->ibss_creator) | ||
136 | conf->nexttbtt = conf->intval; | ||
137 | else | ||
138 | conf->nexttbtt = ath9k_get_next_tbtt(ah, ath9k_hw_gettsf64(ah), | ||
139 | conf->beacon_interval); | ||
140 | |||
141 | if (conf->enable_beacon) | ||
142 | ah->imask |= ATH9K_INT_SWBA; | ||
143 | else | ||
144 | ah->imask &= ~ATH9K_INT_SWBA; | ||
145 | |||
146 | ath_dbg(common, BEACON, | ||
147 | "IBSS (%s) nexttbtt: %u intval: %u conf_intval: %u\n", | ||
148 | (conf->enable_beacon) ? "Enable" : "Disable", | ||
149 | conf->nexttbtt, conf->intval, conf->beacon_interval); | ||
150 | } | ||
151 | EXPORT_SYMBOL(ath9k_cmn_beacon_config_adhoc); | ||
152 | |||
153 | /* | ||
154 | * For multi-bss ap support beacons are either staggered evenly over N slots or | ||
155 | * burst together. For the former arrange for the SWBA to be delivered for each | ||
156 | * slot. Slots that are not occupied will generate nothing. | ||
157 | */ | ||
158 | void ath9k_cmn_beacon_config_ap(struct ath_hw *ah, | ||
159 | struct ath_beacon_config *conf, | ||
160 | unsigned int bc_buf) | ||
161 | { | ||
162 | struct ath_common *common = ath9k_hw_common(ah); | ||
163 | |||
164 | /* NB: the beacon interval is kept internally in TU's */ | ||
165 | conf->intval = TU_TO_USEC(conf->beacon_interval); | ||
166 | conf->intval /= bc_buf; | ||
167 | conf->nexttbtt = ath9k_get_next_tbtt(ah, ath9k_hw_gettsf64(ah), | ||
168 | conf->beacon_interval); | ||
169 | |||
170 | if (conf->enable_beacon) | ||
171 | ah->imask |= ATH9K_INT_SWBA; | ||
172 | else | ||
173 | ah->imask &= ~ATH9K_INT_SWBA; | ||
174 | |||
175 | ath_dbg(common, BEACON, | ||
176 | "AP (%s) nexttbtt: %u intval: %u conf_intval: %u\n", | ||
177 | (conf->enable_beacon) ? "Enable" : "Disable", | ||
178 | conf->nexttbtt, conf->intval, conf->beacon_interval); | ||
179 | } | ||
180 | EXPORT_SYMBOL(ath9k_cmn_beacon_config_ap); | ||
diff --git a/drivers/net/wireless/ath/ath9k/common-beacon.h b/drivers/net/wireless/ath/ath9k/common-beacon.h new file mode 100644 index 000000000000..3665d27f0dc7 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/common-beacon.h | |||
@@ -0,0 +1,26 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2009-2011 Atheros Communications Inc. | ||
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 | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | struct ath_beacon_config; | ||
18 | |||
19 | int ath9k_cmn_beacon_config_sta(struct ath_hw *ah, | ||
20 | struct ath_beacon_config *conf, | ||
21 | struct ath9k_beacon_state *bs); | ||
22 | void ath9k_cmn_beacon_config_adhoc(struct ath_hw *ah, | ||
23 | struct ath_beacon_config *conf); | ||
24 | void ath9k_cmn_beacon_config_ap(struct ath_hw *ah, | ||
25 | struct ath_beacon_config *conf, | ||
26 | unsigned int bc_buf); | ||
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index 4c449e35bd65..ca38116838f0 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h | |||
@@ -22,6 +22,7 @@ | |||
22 | #include "hw-ops.h" | 22 | #include "hw-ops.h" |
23 | 23 | ||
24 | #include "common-init.h" | 24 | #include "common-init.h" |
25 | #include "common-beacon.h" | ||
25 | 26 | ||
26 | /* Common header for Atheros 802.11n base driver cores */ | 27 | /* Common header for Atheros 802.11n base driver cores */ |
27 | 28 | ||
@@ -44,6 +45,19 @@ | |||
44 | #define ATH_EP_RND(x, mul) \ | 45 | #define ATH_EP_RND(x, mul) \ |
45 | (((x) + ((mul)/2)) / (mul)) | 46 | (((x) + ((mul)/2)) / (mul)) |
46 | 47 | ||
48 | #define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024) | ||
49 | |||
50 | struct ath_beacon_config { | ||
51 | int beacon_interval; | ||
52 | u16 dtim_period; | ||
53 | u16 bmiss_timeout; | ||
54 | u8 dtim_count; | ||
55 | bool enable_beacon; | ||
56 | bool ibss_creator; | ||
57 | u32 nexttbtt; | ||
58 | u32 intval; | ||
59 | }; | ||
60 | |||
47 | bool ath9k_cmn_rx_accept(struct ath_common *common, | 61 | bool ath9k_cmn_rx_accept(struct ath_common *common, |
48 | struct ieee80211_hdr *hdr, | 62 | struct ieee80211_hdr *hdr, |
49 | struct ieee80211_rx_status *rxs, | 63 | struct ieee80211_rx_status *rxs, |
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index f8924efdad55..780ff1bee6f6 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -139,43 +139,41 @@ static ssize_t read_file_ani(struct file *file, char __user *user_buf, | |||
139 | const unsigned int size = 1024; | 139 | const unsigned int size = 1024; |
140 | ssize_t retval = 0; | 140 | ssize_t retval = 0; |
141 | char *buf; | 141 | char *buf; |
142 | int i; | ||
143 | struct { | ||
144 | const char *name; | ||
145 | unsigned int val; | ||
146 | } ani_info[] = { | ||
147 | { "ANI RESET", ah->stats.ast_ani_reset }, | ||
148 | { "OFDM LEVEL", ah->ani.ofdmNoiseImmunityLevel }, | ||
149 | { "CCK LEVEL", ah->ani.cckNoiseImmunityLevel }, | ||
150 | { "SPUR UP", ah->stats.ast_ani_spurup }, | ||
151 | { "SPUR DOWN", ah->stats.ast_ani_spurup }, | ||
152 | { "OFDM WS-DET ON", ah->stats.ast_ani_ofdmon }, | ||
153 | { "OFDM WS-DET OFF", ah->stats.ast_ani_ofdmoff }, | ||
154 | { "MRC-CCK ON", ah->stats.ast_ani_ccklow }, | ||
155 | { "MRC-CCK OFF", ah->stats.ast_ani_cckhigh }, | ||
156 | { "FIR-STEP UP", ah->stats.ast_ani_stepup }, | ||
157 | { "FIR-STEP DOWN", ah->stats.ast_ani_stepdown }, | ||
158 | { "INV LISTENTIME", ah->stats.ast_ani_lneg_or_lzero }, | ||
159 | { "OFDM ERRORS", ah->stats.ast_ani_ofdmerrs }, | ||
160 | { "CCK ERRORS", ah->stats.ast_ani_cckerrs }, | ||
161 | }; | ||
142 | 162 | ||
143 | buf = kzalloc(size, GFP_KERNEL); | 163 | buf = kzalloc(size, GFP_KERNEL); |
144 | if (buf == NULL) | 164 | if (buf == NULL) |
145 | return -ENOMEM; | 165 | return -ENOMEM; |
146 | 166 | ||
147 | if (common->disable_ani) { | 167 | len += scnprintf(buf + len, size - len, "%15s: %s\n", "ANI", |
148 | len += scnprintf(buf + len, size - len, "%s: %s\n", | 168 | common->disable_ani ? "DISABLED" : "ENABLED"); |
149 | "ANI", "DISABLED"); | 169 | |
170 | if (common->disable_ani) | ||
150 | goto exit; | 171 | goto exit; |
151 | } | ||
152 | 172 | ||
153 | len += scnprintf(buf + len, size - len, "%15s: %s\n", | 173 | for (i = 0; i < ARRAY_SIZE(ani_info); i++) |
154 | "ANI", "ENABLED"); | 174 | len += scnprintf(buf + len, size - len, "%15s: %u\n", |
155 | len += scnprintf(buf + len, size - len, "%15s: %u\n", | 175 | ani_info[i].name, ani_info[i].val); |
156 | "ANI RESET", ah->stats.ast_ani_reset); | 176 | |
157 | len += scnprintf(buf + len, size - len, "%15s: %u\n", | ||
158 | "SPUR UP", ah->stats.ast_ani_spurup); | ||
159 | len += scnprintf(buf + len, size - len, "%15s: %u\n", | ||
160 | "SPUR DOWN", ah->stats.ast_ani_spurup); | ||
161 | len += scnprintf(buf + len, size - len, "%15s: %u\n", | ||
162 | "OFDM WS-DET ON", ah->stats.ast_ani_ofdmon); | ||
163 | len += scnprintf(buf + len, size - len, "%15s: %u\n", | ||
164 | "OFDM WS-DET OFF", ah->stats.ast_ani_ofdmoff); | ||
165 | len += scnprintf(buf + len, size - len, "%15s: %u\n", | ||
166 | "MRC-CCK ON", ah->stats.ast_ani_ccklow); | ||
167 | len += scnprintf(buf + len, size - len, "%15s: %u\n", | ||
168 | "MRC-CCK OFF", ah->stats.ast_ani_cckhigh); | ||
169 | len += scnprintf(buf + len, size - len, "%15s: %u\n", | ||
170 | "FIR-STEP UP", ah->stats.ast_ani_stepup); | ||
171 | len += scnprintf(buf + len, size - len, "%15s: %u\n", | ||
172 | "FIR-STEP DOWN", ah->stats.ast_ani_stepdown); | ||
173 | len += scnprintf(buf + len, size - len, "%15s: %u\n", | ||
174 | "INV LISTENTIME", ah->stats.ast_ani_lneg_or_lzero); | ||
175 | len += scnprintf(buf + len, size - len, "%15s: %u\n", | ||
176 | "OFDM ERRORS", ah->stats.ast_ani_ofdmerrs); | ||
177 | len += scnprintf(buf + len, size - len, "%15s: %u\n", | ||
178 | "CCK ERRORS", ah->stats.ast_ani_cckerrs); | ||
179 | exit: | 177 | exit: |
180 | if (len > size) | 178 | if (len > size) |
181 | len = size; | 179 | len = size; |
@@ -210,7 +208,7 @@ static ssize_t write_file_ani(struct file *file, | |||
210 | common->disable_ani = !ani; | 208 | common->disable_ani = !ani; |
211 | 209 | ||
212 | if (common->disable_ani) { | 210 | if (common->disable_ani) { |
213 | clear_bit(SC_OP_ANI_RUN, &sc->sc_flags); | 211 | clear_bit(ATH_OP_ANI_RUN, &common->op_flags); |
214 | ath_stop_ani(sc); | 212 | ath_stop_ani(sc); |
215 | } else { | 213 | } else { |
216 | ath_check_ani(sc); | 214 | ath_check_ani(sc); |
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 3baf9ceae601..dab1f0cab993 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h | |||
@@ -39,7 +39,6 @@ | |||
39 | #define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ | 39 | #define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ |
40 | 40 | ||
41 | #define ATH_DEFAULT_BMISS_LIMIT 10 | 41 | #define ATH_DEFAULT_BMISS_LIMIT 10 |
42 | #define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024) | ||
43 | #define TSF_TO_TU(_h, _l) \ | 42 | #define TSF_TO_TU(_h, _l) \ |
44 | ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10)) | 43 | ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10)) |
45 | 44 | ||
@@ -406,12 +405,18 @@ static inline void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv, | |||
406 | #define DEFAULT_SWBA_RESPONSE 40 /* in TUs */ | 405 | #define DEFAULT_SWBA_RESPONSE 40 /* in TUs */ |
407 | #define MIN_SWBA_RESPONSE 10 /* in TUs */ | 406 | #define MIN_SWBA_RESPONSE 10 /* in TUs */ |
408 | 407 | ||
409 | struct htc_beacon_config { | 408 | struct htc_beacon { |
409 | enum { | ||
410 | OK, /* no change needed */ | ||
411 | UPDATE, /* update pending */ | ||
412 | COMMIT /* beacon sent, commit change */ | ||
413 | } updateslot; /* slot time update fsm */ | ||
414 | |||
410 | struct ieee80211_vif *bslot[ATH9K_HTC_MAX_BCN_VIF]; | 415 | struct ieee80211_vif *bslot[ATH9K_HTC_MAX_BCN_VIF]; |
411 | u16 beacon_interval; | 416 | u32 bmisscnt; |
412 | u16 dtim_period; | 417 | u32 beaconq; |
413 | u16 bmiss_timeout; | 418 | int slottime; |
414 | u32 bmiss_cnt; | 419 | int slotupdate; |
415 | }; | 420 | }; |
416 | 421 | ||
417 | struct ath_btcoex { | 422 | struct ath_btcoex { |
@@ -439,12 +444,8 @@ static inline void ath9k_htc_stop_btcoex(struct ath9k_htc_priv *priv) | |||
439 | } | 444 | } |
440 | #endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */ | 445 | #endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */ |
441 | 446 | ||
442 | #define OP_INVALID BIT(0) | ||
443 | #define OP_SCANNING BIT(1) | ||
444 | #define OP_ENABLE_BEACON BIT(2) | ||
445 | #define OP_BT_PRIORITY_DETECTED BIT(3) | 447 | #define OP_BT_PRIORITY_DETECTED BIT(3) |
446 | #define OP_BT_SCAN BIT(4) | 448 | #define OP_BT_SCAN BIT(4) |
447 | #define OP_ANI_RUNNING BIT(5) | ||
448 | #define OP_TSF_RESET BIT(6) | 449 | #define OP_TSF_RESET BIT(6) |
449 | 450 | ||
450 | struct ath9k_htc_priv { | 451 | struct ath9k_htc_priv { |
@@ -489,7 +490,8 @@ struct ath9k_htc_priv { | |||
489 | struct ath9k_hw_cal_data caldata; | 490 | struct ath9k_hw_cal_data caldata; |
490 | 491 | ||
491 | spinlock_t beacon_lock; | 492 | spinlock_t beacon_lock; |
492 | struct htc_beacon_config cur_beacon_conf; | 493 | struct ath_beacon_config cur_beacon_conf; |
494 | struct htc_beacon beacon; | ||
493 | 495 | ||
494 | struct ath9k_htc_rx rx; | 496 | struct ath9k_htc_rx rx; |
495 | struct ath9k_htc_tx tx; | 497 | struct ath9k_htc_tx tx; |
@@ -514,7 +516,6 @@ struct ath9k_htc_priv { | |||
514 | struct work_struct led_work; | 516 | struct work_struct led_work; |
515 | #endif | 517 | #endif |
516 | 518 | ||
517 | int beaconq; | ||
518 | int cabq; | 519 | int cabq; |
519 | int hwq_map[IEEE80211_NUM_ACS]; | 520 | int hwq_map[IEEE80211_NUM_ACS]; |
520 | 521 | ||
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index a00ddb9e737e..e8b6ec3c1dbb 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c | |||
@@ -26,7 +26,7 @@ void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv) | |||
26 | memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); | 26 | memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); |
27 | memset(&qi_be, 0, sizeof(struct ath9k_tx_queue_info)); | 27 | memset(&qi_be, 0, sizeof(struct ath9k_tx_queue_info)); |
28 | 28 | ||
29 | ath9k_hw_get_txq_props(ah, priv->beaconq, &qi); | 29 | ath9k_hw_get_txq_props(ah, priv->beacon.beaconq, &qi); |
30 | 30 | ||
31 | if (priv->ah->opmode == NL80211_IFTYPE_AP || | 31 | if (priv->ah->opmode == NL80211_IFTYPE_AP || |
32 | priv->ah->opmode == NL80211_IFTYPE_MESH_POINT) { | 32 | priv->ah->opmode == NL80211_IFTYPE_MESH_POINT) { |
@@ -54,212 +54,78 @@ void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv) | |||
54 | 54 | ||
55 | } | 55 | } |
56 | 56 | ||
57 | if (!ath9k_hw_set_txq_props(ah, priv->beaconq, &qi)) { | 57 | if (!ath9k_hw_set_txq_props(ah, priv->beacon.beaconq, &qi)) { |
58 | ath_err(ath9k_hw_common(ah), | 58 | ath_err(ath9k_hw_common(ah), |
59 | "Unable to update beacon queue %u!\n", priv->beaconq); | 59 | "Unable to update beacon queue %u!\n", priv->beacon.beaconq); |
60 | } else { | 60 | } else { |
61 | ath9k_hw_resettxqueue(ah, priv->beaconq); | 61 | ath9k_hw_resettxqueue(ah, priv->beacon.beaconq); |
62 | } | 62 | } |
63 | } | 63 | } |
64 | 64 | ||
65 | 65 | /* | |
66 | static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv, | 66 | * Both nexttbtt and intval have to be in usecs. |
67 | struct htc_beacon_config *bss_conf) | 67 | */ |
68 | static void ath9k_htc_beacon_init(struct ath9k_htc_priv *priv, | ||
69 | struct ath_beacon_config *conf, | ||
70 | bool reset_tsf) | ||
68 | { | 71 | { |
69 | struct ath_common *common = ath9k_hw_common(priv->ah); | 72 | struct ath_hw *ah = priv->ah; |
70 | struct ath9k_beacon_state bs; | ||
71 | enum ath9k_int imask = 0; | ||
72 | int dtimperiod, dtimcount; | ||
73 | int bmiss_timeout; | ||
74 | u32 nexttbtt = 0, intval, tsftu; | ||
75 | __be32 htc_imask = 0; | ||
76 | u64 tsf; | ||
77 | int num_beacons, offset, dtim_dec_count; | ||
78 | int ret __attribute__ ((unused)); | 73 | int ret __attribute__ ((unused)); |
74 | __be32 htc_imask = 0; | ||
79 | u8 cmd_rsp; | 75 | u8 cmd_rsp; |
80 | 76 | ||
81 | memset(&bs, 0, sizeof(bs)); | 77 | if (conf->intval >= TU_TO_USEC(DEFAULT_SWBA_RESPONSE)) |
82 | 78 | ah->config.sw_beacon_response_time = DEFAULT_SWBA_RESPONSE; | |
83 | intval = bss_conf->beacon_interval; | 79 | else |
84 | bmiss_timeout = (ATH_DEFAULT_BMISS_LIMIT * bss_conf->beacon_interval); | 80 | ah->config.sw_beacon_response_time = MIN_SWBA_RESPONSE; |
85 | |||
86 | /* | ||
87 | * Setup dtim parameters according to | ||
88 | * last beacon we received (which may be none). | ||
89 | */ | ||
90 | dtimperiod = bss_conf->dtim_period; | ||
91 | if (dtimperiod <= 0) /* NB: 0 if not known */ | ||
92 | dtimperiod = 1; | ||
93 | dtimcount = 1; | ||
94 | if (dtimcount >= dtimperiod) /* NB: sanity check */ | ||
95 | dtimcount = 0; | ||
96 | |||
97 | /* | ||
98 | * Pull nexttbtt forward to reflect the current | ||
99 | * TSF and calculate dtim state for the result. | ||
100 | */ | ||
101 | tsf = ath9k_hw_gettsf64(priv->ah); | ||
102 | tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE; | ||
103 | |||
104 | num_beacons = tsftu / intval + 1; | ||
105 | offset = tsftu % intval; | ||
106 | nexttbtt = tsftu - offset; | ||
107 | if (offset) | ||
108 | nexttbtt += intval; | ||
109 | |||
110 | /* DTIM Beacon every dtimperiod Beacon */ | ||
111 | dtim_dec_count = num_beacons % dtimperiod; | ||
112 | dtimcount -= dtim_dec_count; | ||
113 | if (dtimcount < 0) | ||
114 | dtimcount += dtimperiod; | ||
115 | |||
116 | bs.bs_intval = TU_TO_USEC(intval); | ||
117 | bs.bs_nexttbtt = TU_TO_USEC(nexttbtt); | ||
118 | bs.bs_dtimperiod = dtimperiod * bs.bs_intval; | ||
119 | bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount * bs.bs_intval; | ||
120 | |||
121 | /* | ||
122 | * Calculate the number of consecutive beacons to miss* before taking | ||
123 | * a BMISS interrupt. The configuration is specified in TU so we only | ||
124 | * need calculate based on the beacon interval. Note that we clamp the | ||
125 | * result to at most 15 beacons. | ||
126 | */ | ||
127 | bs.bs_bmissthreshold = DIV_ROUND_UP(bmiss_timeout, intval); | ||
128 | if (bs.bs_bmissthreshold > 15) | ||
129 | bs.bs_bmissthreshold = 15; | ||
130 | else if (bs.bs_bmissthreshold <= 0) | ||
131 | bs.bs_bmissthreshold = 1; | ||
132 | |||
133 | /* | ||
134 | * Calculate sleep duration. The configuration is given in ms. | ||
135 | * We ensure a multiple of the beacon period is used. Also, if the sleep | ||
136 | * duration is greater than the DTIM period then it makes senses | ||
137 | * to make it a multiple of that. | ||
138 | * | ||
139 | * XXX fixed at 100ms | ||
140 | */ | ||
141 | |||
142 | bs.bs_sleepduration = TU_TO_USEC(roundup(IEEE80211_MS_TO_TU(100), | ||
143 | intval)); | ||
144 | if (bs.bs_sleepduration > bs.bs_dtimperiod) | ||
145 | bs.bs_sleepduration = bs.bs_dtimperiod; | ||
146 | |||
147 | /* TSF out of range threshold fixed at 1 second */ | ||
148 | bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD; | ||
149 | |||
150 | ath_dbg(common, CONFIG, "intval: %u tsf: %llu tsftu: %u\n", | ||
151 | intval, tsf, tsftu); | ||
152 | ath_dbg(common, CONFIG, "bmiss: %u sleep: %u\n", | ||
153 | bs.bs_bmissthreshold, bs.bs_sleepduration); | ||
154 | |||
155 | /* Set the computed STA beacon timers */ | ||
156 | 81 | ||
157 | WMI_CMD(WMI_DISABLE_INTR_CMDID); | 82 | WMI_CMD(WMI_DISABLE_INTR_CMDID); |
158 | ath9k_hw_set_sta_beacon_timers(priv->ah, &bs); | 83 | if (reset_tsf) |
159 | imask |= ATH9K_INT_BMISS; | 84 | ath9k_hw_reset_tsf(ah); |
160 | htc_imask = cpu_to_be32(imask); | 85 | ath9k_htc_beaconq_config(priv); |
86 | ath9k_hw_beaconinit(ah, conf->nexttbtt, conf->intval); | ||
87 | priv->beacon.bmisscnt = 0; | ||
88 | htc_imask = cpu_to_be32(ah->imask); | ||
161 | WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); | 89 | WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); |
162 | } | 90 | } |
163 | 91 | ||
164 | static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv, | 92 | static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv, |
165 | struct htc_beacon_config *bss_conf) | 93 | struct ath_beacon_config *bss_conf) |
166 | { | 94 | { |
167 | struct ath_common *common = ath9k_hw_common(priv->ah); | 95 | struct ath9k_beacon_state bs; |
168 | enum ath9k_int imask = 0; | 96 | enum ath9k_int imask = 0; |
169 | u32 nexttbtt, intval, tsftu; | ||
170 | __be32 htc_imask = 0; | 97 | __be32 htc_imask = 0; |
171 | int ret __attribute__ ((unused)); | 98 | int ret __attribute__ ((unused)); |
172 | u8 cmd_rsp; | 99 | u8 cmd_rsp; |
173 | u64 tsf; | ||
174 | |||
175 | intval = bss_conf->beacon_interval; | ||
176 | intval /= ATH9K_HTC_MAX_BCN_VIF; | ||
177 | nexttbtt = intval; | ||
178 | 100 | ||
179 | /* | 101 | if (ath9k_cmn_beacon_config_sta(priv->ah, bss_conf, &bs) == -EPERM) |
180 | * To reduce beacon misses under heavy TX load, | 102 | return; |
181 | * set the beacon response time to a larger value. | ||
182 | */ | ||
183 | if (intval > DEFAULT_SWBA_RESPONSE) | ||
184 | priv->ah->config.sw_beacon_response_time = DEFAULT_SWBA_RESPONSE; | ||
185 | else | ||
186 | priv->ah->config.sw_beacon_response_time = MIN_SWBA_RESPONSE; | ||
187 | |||
188 | if (test_bit(OP_TSF_RESET, &priv->op_flags)) { | ||
189 | ath9k_hw_reset_tsf(priv->ah); | ||
190 | clear_bit(OP_TSF_RESET, &priv->op_flags); | ||
191 | } else { | ||
192 | /* | ||
193 | * Pull nexttbtt forward to reflect the current TSF. | ||
194 | */ | ||
195 | tsf = ath9k_hw_gettsf64(priv->ah); | ||
196 | tsftu = TSF_TO_TU(tsf >> 32, tsf) + FUDGE; | ||
197 | do { | ||
198 | nexttbtt += intval; | ||
199 | } while (nexttbtt < tsftu); | ||
200 | } | ||
201 | |||
202 | if (test_bit(OP_ENABLE_BEACON, &priv->op_flags)) | ||
203 | imask |= ATH9K_INT_SWBA; | ||
204 | |||
205 | ath_dbg(common, CONFIG, | ||
206 | "AP Beacon config, intval: %d, nexttbtt: %u, resp_time: %d imask: 0x%x\n", | ||
207 | bss_conf->beacon_interval, nexttbtt, | ||
208 | priv->ah->config.sw_beacon_response_time, imask); | ||
209 | |||
210 | ath9k_htc_beaconq_config(priv); | ||
211 | 103 | ||
212 | WMI_CMD(WMI_DISABLE_INTR_CMDID); | 104 | WMI_CMD(WMI_DISABLE_INTR_CMDID); |
213 | ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval)); | 105 | ath9k_hw_set_sta_beacon_timers(priv->ah, &bs); |
214 | priv->cur_beacon_conf.bmiss_cnt = 0; | 106 | imask |= ATH9K_INT_BMISS; |
215 | htc_imask = cpu_to_be32(imask); | 107 | htc_imask = cpu_to_be32(imask); |
216 | WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); | 108 | WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); |
217 | } | 109 | } |
218 | 110 | ||
219 | static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv, | 111 | static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv, |
220 | struct htc_beacon_config *bss_conf) | 112 | struct ath_beacon_config *conf) |
221 | { | 113 | { |
222 | struct ath_common *common = ath9k_hw_common(priv->ah); | 114 | struct ath_hw *ah = priv->ah; |
223 | enum ath9k_int imask = 0; | 115 | ah->imask = 0; |
224 | u32 nexttbtt, intval, tsftu; | ||
225 | __be32 htc_imask = 0; | ||
226 | int ret __attribute__ ((unused)); | ||
227 | u8 cmd_rsp; | ||
228 | u64 tsf; | ||
229 | |||
230 | intval = bss_conf->beacon_interval; | ||
231 | nexttbtt = intval; | ||
232 | |||
233 | /* | ||
234 | * Pull nexttbtt forward to reflect the current TSF. | ||
235 | */ | ||
236 | tsf = ath9k_hw_gettsf64(priv->ah); | ||
237 | tsftu = TSF_TO_TU(tsf >> 32, tsf) + FUDGE; | ||
238 | do { | ||
239 | nexttbtt += intval; | ||
240 | } while (nexttbtt < tsftu); | ||
241 | |||
242 | /* | ||
243 | * Only one IBSS interfce is allowed. | ||
244 | */ | ||
245 | if (intval > DEFAULT_SWBA_RESPONSE) | ||
246 | priv->ah->config.sw_beacon_response_time = DEFAULT_SWBA_RESPONSE; | ||
247 | else | ||
248 | priv->ah->config.sw_beacon_response_time = MIN_SWBA_RESPONSE; | ||
249 | 116 | ||
250 | if (test_bit(OP_ENABLE_BEACON, &priv->op_flags)) | 117 | ath9k_cmn_beacon_config_ap(ah, conf, ATH9K_HTC_MAX_BCN_VIF); |
251 | imask |= ATH9K_INT_SWBA; | 118 | ath9k_htc_beacon_init(priv, conf, false); |
119 | } | ||
252 | 120 | ||
253 | ath_dbg(common, CONFIG, | 121 | static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv, |
254 | "IBSS Beacon config, intval: %d, nexttbtt: %u, resp_time: %d, imask: 0x%x\n", | 122 | struct ath_beacon_config *conf) |
255 | bss_conf->beacon_interval, nexttbtt, | 123 | { |
256 | priv->ah->config.sw_beacon_response_time, imask); | 124 | struct ath_hw *ah = priv->ah; |
125 | ah->imask = 0; | ||
257 | 126 | ||
258 | WMI_CMD(WMI_DISABLE_INTR_CMDID); | 127 | ath9k_cmn_beacon_config_adhoc(ah, conf); |
259 | ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval)); | 128 | ath9k_htc_beacon_init(priv, conf, conf->ibss_creator); |
260 | priv->cur_beacon_conf.bmiss_cnt = 0; | ||
261 | htc_imask = cpu_to_be32(imask); | ||
262 | WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); | ||
263 | } | 129 | } |
264 | 130 | ||
265 | void ath9k_htc_beaconep(void *drv_priv, struct sk_buff *skb, | 131 | void ath9k_htc_beaconep(void *drv_priv, struct sk_buff *skb, |
@@ -279,7 +145,7 @@ static void ath9k_htc_send_buffered(struct ath9k_htc_priv *priv, | |||
279 | 145 | ||
280 | spin_lock_bh(&priv->beacon_lock); | 146 | spin_lock_bh(&priv->beacon_lock); |
281 | 147 | ||
282 | vif = priv->cur_beacon_conf.bslot[slot]; | 148 | vif = priv->beacon.bslot[slot]; |
283 | 149 | ||
284 | skb = ieee80211_get_buffered_bc(priv->hw, vif); | 150 | skb = ieee80211_get_buffered_bc(priv->hw, vif); |
285 | 151 | ||
@@ -340,10 +206,10 @@ static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv, | |||
340 | 206 | ||
341 | spin_lock_bh(&priv->beacon_lock); | 207 | spin_lock_bh(&priv->beacon_lock); |
342 | 208 | ||
343 | vif = priv->cur_beacon_conf.bslot[slot]; | 209 | vif = priv->beacon.bslot[slot]; |
344 | avp = (struct ath9k_htc_vif *)vif->drv_priv; | 210 | avp = (struct ath9k_htc_vif *)vif->drv_priv; |
345 | 211 | ||
346 | if (unlikely(test_bit(OP_SCANNING, &priv->op_flags))) { | 212 | if (unlikely(test_bit(ATH_OP_SCANNING, &common->op_flags))) { |
347 | spin_unlock_bh(&priv->beacon_lock); | 213 | spin_unlock_bh(&priv->beacon_lock); |
348 | return; | 214 | return; |
349 | } | 215 | } |
@@ -423,8 +289,8 @@ void ath9k_htc_swba(struct ath9k_htc_priv *priv, | |||
423 | int slot; | 289 | int slot; |
424 | 290 | ||
425 | if (swba->beacon_pending != 0) { | 291 | if (swba->beacon_pending != 0) { |
426 | priv->cur_beacon_conf.bmiss_cnt++; | 292 | priv->beacon.bmisscnt++; |
427 | if (priv->cur_beacon_conf.bmiss_cnt > BSTUCK_THRESHOLD) { | 293 | if (priv->beacon.bmisscnt > BSTUCK_THRESHOLD) { |
428 | ath_dbg(common, BSTUCK, "Beacon stuck, HW reset\n"); | 294 | ath_dbg(common, BSTUCK, "Beacon stuck, HW reset\n"); |
429 | ieee80211_queue_work(priv->hw, | 295 | ieee80211_queue_work(priv->hw, |
430 | &priv->fatal_work); | 296 | &priv->fatal_work); |
@@ -432,16 +298,16 @@ void ath9k_htc_swba(struct ath9k_htc_priv *priv, | |||
432 | return; | 298 | return; |
433 | } | 299 | } |
434 | 300 | ||
435 | if (priv->cur_beacon_conf.bmiss_cnt) { | 301 | if (priv->beacon.bmisscnt) { |
436 | ath_dbg(common, BSTUCK, | 302 | ath_dbg(common, BSTUCK, |
437 | "Resuming beacon xmit after %u misses\n", | 303 | "Resuming beacon xmit after %u misses\n", |
438 | priv->cur_beacon_conf.bmiss_cnt); | 304 | priv->beacon.bmisscnt); |
439 | priv->cur_beacon_conf.bmiss_cnt = 0; | 305 | priv->beacon.bmisscnt = 0; |
440 | } | 306 | } |
441 | 307 | ||
442 | slot = ath9k_htc_choose_bslot(priv, swba); | 308 | slot = ath9k_htc_choose_bslot(priv, swba); |
443 | spin_lock_bh(&priv->beacon_lock); | 309 | spin_lock_bh(&priv->beacon_lock); |
444 | if (priv->cur_beacon_conf.bslot[slot] == NULL) { | 310 | if (priv->beacon.bslot[slot] == NULL) { |
445 | spin_unlock_bh(&priv->beacon_lock); | 311 | spin_unlock_bh(&priv->beacon_lock); |
446 | return; | 312 | return; |
447 | } | 313 | } |
@@ -460,13 +326,13 @@ void ath9k_htc_assign_bslot(struct ath9k_htc_priv *priv, | |||
460 | 326 | ||
461 | spin_lock_bh(&priv->beacon_lock); | 327 | spin_lock_bh(&priv->beacon_lock); |
462 | for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++) { | 328 | for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++) { |
463 | if (priv->cur_beacon_conf.bslot[i] == NULL) { | 329 | if (priv->beacon.bslot[i] == NULL) { |
464 | avp->bslot = i; | 330 | avp->bslot = i; |
465 | break; | 331 | break; |
466 | } | 332 | } |
467 | } | 333 | } |
468 | 334 | ||
469 | priv->cur_beacon_conf.bslot[avp->bslot] = vif; | 335 | priv->beacon.bslot[avp->bslot] = vif; |
470 | spin_unlock_bh(&priv->beacon_lock); | 336 | spin_unlock_bh(&priv->beacon_lock); |
471 | 337 | ||
472 | ath_dbg(common, CONFIG, "Added interface at beacon slot: %d\n", | 338 | ath_dbg(common, CONFIG, "Added interface at beacon slot: %d\n", |
@@ -480,7 +346,7 @@ void ath9k_htc_remove_bslot(struct ath9k_htc_priv *priv, | |||
480 | struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *)vif->drv_priv; | 346 | struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *)vif->drv_priv; |
481 | 347 | ||
482 | spin_lock_bh(&priv->beacon_lock); | 348 | spin_lock_bh(&priv->beacon_lock); |
483 | priv->cur_beacon_conf.bslot[avp->bslot] = NULL; | 349 | priv->beacon.bslot[avp->bslot] = NULL; |
484 | spin_unlock_bh(&priv->beacon_lock); | 350 | spin_unlock_bh(&priv->beacon_lock); |
485 | 351 | ||
486 | ath_dbg(common, CONFIG, "Removed interface at beacon slot: %d\n", | 352 | ath_dbg(common, CONFIG, "Removed interface at beacon slot: %d\n", |
@@ -496,7 +362,7 @@ void ath9k_htc_set_tsfadjust(struct ath9k_htc_priv *priv, | |||
496 | { | 362 | { |
497 | struct ath_common *common = ath9k_hw_common(priv->ah); | 363 | struct ath_common *common = ath9k_hw_common(priv->ah); |
498 | struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *)vif->drv_priv; | 364 | struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *)vif->drv_priv; |
499 | struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; | 365 | struct ath_beacon_config *cur_conf = &priv->cur_beacon_conf; |
500 | u64 tsfadjust; | 366 | u64 tsfadjust; |
501 | 367 | ||
502 | if (avp->bslot == 0) | 368 | if (avp->bslot == 0) |
@@ -528,7 +394,7 @@ static bool ath9k_htc_check_beacon_config(struct ath9k_htc_priv *priv, | |||
528 | struct ieee80211_vif *vif) | 394 | struct ieee80211_vif *vif) |
529 | { | 395 | { |
530 | struct ath_common *common = ath9k_hw_common(priv->ah); | 396 | struct ath_common *common = ath9k_hw_common(priv->ah); |
531 | struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; | 397 | struct ath_beacon_config *cur_conf = &priv->cur_beacon_conf; |
532 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | 398 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; |
533 | bool beacon_configured; | 399 | bool beacon_configured; |
534 | 400 | ||
@@ -583,7 +449,7 @@ void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, | |||
583 | struct ieee80211_vif *vif) | 449 | struct ieee80211_vif *vif) |
584 | { | 450 | { |
585 | struct ath_common *common = ath9k_hw_common(priv->ah); | 451 | struct ath_common *common = ath9k_hw_common(priv->ah); |
586 | struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; | 452 | struct ath_beacon_config *cur_conf = &priv->cur_beacon_conf; |
587 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | 453 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; |
588 | struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv; | 454 | struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv; |
589 | 455 | ||
@@ -619,7 +485,7 @@ void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, | |||
619 | void ath9k_htc_beacon_reconfig(struct ath9k_htc_priv *priv) | 485 | void ath9k_htc_beacon_reconfig(struct ath9k_htc_priv *priv) |
620 | { | 486 | { |
621 | struct ath_common *common = ath9k_hw_common(priv->ah); | 487 | struct ath_common *common = ath9k_hw_common(priv->ah); |
622 | struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; | 488 | struct ath_beacon_config *cur_conf = &priv->cur_beacon_conf; |
623 | 489 | ||
624 | switch (priv->ah->opmode) { | 490 | switch (priv->ah->opmode) { |
625 | case NL80211_IFTYPE_STATION: | 491 | case NL80211_IFTYPE_STATION: |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index b22fb64403d9..8a3bd5fe3a54 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c | |||
@@ -405,8 +405,8 @@ static int ath9k_init_queues(struct ath9k_htc_priv *priv) | |||
405 | for (i = 0; i < ARRAY_SIZE(priv->hwq_map); i++) | 405 | for (i = 0; i < ARRAY_SIZE(priv->hwq_map); i++) |
406 | priv->hwq_map[i] = -1; | 406 | priv->hwq_map[i] = -1; |
407 | 407 | ||
408 | priv->beaconq = ath9k_hw_beaconq_setup(priv->ah); | 408 | priv->beacon.beaconq = ath9k_hw_beaconq_setup(priv->ah); |
409 | if (priv->beaconq == -1) { | 409 | if (priv->beacon.beaconq == -1) { |
410 | ath_err(common, "Unable to setup BEACON xmit queue\n"); | 410 | ath_err(common, "Unable to setup BEACON xmit queue\n"); |
411 | goto err; | 411 | goto err; |
412 | } | 412 | } |
@@ -459,8 +459,6 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, | |||
459 | struct ath_common *common; | 459 | struct ath_common *common; |
460 | int i, ret = 0, csz = 0; | 460 | int i, ret = 0, csz = 0; |
461 | 461 | ||
462 | set_bit(OP_INVALID, &priv->op_flags); | ||
463 | |||
464 | ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL); | 462 | ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL); |
465 | if (!ah) | 463 | if (!ah) |
466 | return -ENOMEM; | 464 | return -ENOMEM; |
@@ -485,6 +483,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, | |||
485 | common->priv = priv; | 483 | common->priv = priv; |
486 | common->debug_mask = ath9k_debug; | 484 | common->debug_mask = ath9k_debug; |
487 | common->btcoex_enabled = ath9k_htc_btcoex_enable == 1; | 485 | common->btcoex_enabled = ath9k_htc_btcoex_enable == 1; |
486 | set_bit(ATH_OP_INVALID, &common->op_flags); | ||
488 | 487 | ||
489 | spin_lock_init(&priv->beacon_lock); | 488 | spin_lock_init(&priv->beacon_lock); |
490 | spin_lock_init(&priv->tx.tx_lock); | 489 | spin_lock_init(&priv->tx.tx_lock); |
@@ -520,7 +519,8 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, | |||
520 | goto err_queues; | 519 | goto err_queues; |
521 | 520 | ||
522 | for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++) | 521 | for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++) |
523 | priv->cur_beacon_conf.bslot[i] = NULL; | 522 | priv->beacon.bslot[i] = NULL; |
523 | priv->beacon.slottime = ATH9K_SLOT_TIME_9; | ||
524 | 524 | ||
525 | ath9k_cmn_init_channels_rates(common); | 525 | ath9k_cmn_init_channels_rates(common); |
526 | ath9k_cmn_init_crypto(ah); | 526 | ath9k_cmn_init_crypto(ah); |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 90dad4172b0a..f46cd0250e48 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | |||
@@ -250,7 +250,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, | |||
250 | u8 cmd_rsp; | 250 | u8 cmd_rsp; |
251 | int ret; | 251 | int ret; |
252 | 252 | ||
253 | if (test_bit(OP_INVALID, &priv->op_flags)) | 253 | if (test_bit(ATH_OP_INVALID, &common->op_flags)) |
254 | return -EIO; | 254 | return -EIO; |
255 | 255 | ||
256 | fastcc = !!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL); | 256 | fastcc = !!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL); |
@@ -304,7 +304,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, | |||
304 | 304 | ||
305 | htc_start(priv->htc); | 305 | htc_start(priv->htc); |
306 | 306 | ||
307 | if (!test_bit(OP_SCANNING, &priv->op_flags) && | 307 | if (!test_bit(ATH_OP_SCANNING, &common->op_flags) && |
308 | !(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) | 308 | !(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) |
309 | ath9k_htc_vif_reconfig(priv); | 309 | ath9k_htc_vif_reconfig(priv); |
310 | 310 | ||
@@ -748,7 +748,7 @@ void ath9k_htc_start_ani(struct ath9k_htc_priv *priv) | |||
748 | common->ani.shortcal_timer = timestamp; | 748 | common->ani.shortcal_timer = timestamp; |
749 | common->ani.checkani_timer = timestamp; | 749 | common->ani.checkani_timer = timestamp; |
750 | 750 | ||
751 | set_bit(OP_ANI_RUNNING, &priv->op_flags); | 751 | set_bit(ATH_OP_ANI_RUN, &common->op_flags); |
752 | 752 | ||
753 | ieee80211_queue_delayed_work(common->hw, &priv->ani_work, | 753 | ieee80211_queue_delayed_work(common->hw, &priv->ani_work, |
754 | msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); | 754 | msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); |
@@ -756,8 +756,9 @@ void ath9k_htc_start_ani(struct ath9k_htc_priv *priv) | |||
756 | 756 | ||
757 | void ath9k_htc_stop_ani(struct ath9k_htc_priv *priv) | 757 | void ath9k_htc_stop_ani(struct ath9k_htc_priv *priv) |
758 | { | 758 | { |
759 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
759 | cancel_delayed_work_sync(&priv->ani_work); | 760 | cancel_delayed_work_sync(&priv->ani_work); |
760 | clear_bit(OP_ANI_RUNNING, &priv->op_flags); | 761 | clear_bit(ATH_OP_ANI_RUN, &common->op_flags); |
761 | } | 762 | } |
762 | 763 | ||
763 | void ath9k_htc_ani_work(struct work_struct *work) | 764 | void ath9k_htc_ani_work(struct work_struct *work) |
@@ -942,7 +943,7 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) | |||
942 | ath_dbg(common, CONFIG, | 943 | ath_dbg(common, CONFIG, |
943 | "Failed to update capability in target\n"); | 944 | "Failed to update capability in target\n"); |
944 | 945 | ||
945 | clear_bit(OP_INVALID, &priv->op_flags); | 946 | clear_bit(ATH_OP_INVALID, &common->op_flags); |
946 | htc_start(priv->htc); | 947 | htc_start(priv->htc); |
947 | 948 | ||
948 | spin_lock_bh(&priv->tx.tx_lock); | 949 | spin_lock_bh(&priv->tx.tx_lock); |
@@ -971,7 +972,7 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) | |||
971 | 972 | ||
972 | mutex_lock(&priv->mutex); | 973 | mutex_lock(&priv->mutex); |
973 | 974 | ||
974 | if (test_bit(OP_INVALID, &priv->op_flags)) { | 975 | if (test_bit(ATH_OP_INVALID, &common->op_flags)) { |
975 | ath_dbg(common, ANY, "Device not present\n"); | 976 | ath_dbg(common, ANY, "Device not present\n"); |
976 | mutex_unlock(&priv->mutex); | 977 | mutex_unlock(&priv->mutex); |
977 | return; | 978 | return; |
@@ -1013,7 +1014,7 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) | |||
1013 | ath9k_htc_ps_restore(priv); | 1014 | ath9k_htc_ps_restore(priv); |
1014 | ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP); | 1015 | ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP); |
1015 | 1016 | ||
1016 | set_bit(OP_INVALID, &priv->op_flags); | 1017 | set_bit(ATH_OP_INVALID, &common->op_flags); |
1017 | 1018 | ||
1018 | ath_dbg(common, CONFIG, "Driver halt\n"); | 1019 | ath_dbg(common, CONFIG, "Driver halt\n"); |
1019 | mutex_unlock(&priv->mutex); | 1020 | mutex_unlock(&priv->mutex); |
@@ -1087,7 +1088,7 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw, | |||
1087 | ath9k_htc_set_opmode(priv); | 1088 | ath9k_htc_set_opmode(priv); |
1088 | 1089 | ||
1089 | if ((priv->ah->opmode == NL80211_IFTYPE_AP) && | 1090 | if ((priv->ah->opmode == NL80211_IFTYPE_AP) && |
1090 | !test_bit(OP_ANI_RUNNING, &priv->op_flags)) { | 1091 | !test_bit(ATH_OP_ANI_RUN, &common->op_flags)) { |
1091 | ath9k_hw_set_tsfadjust(priv->ah, true); | 1092 | ath9k_hw_set_tsfadjust(priv->ah, true); |
1092 | ath9k_htc_start_ani(priv); | 1093 | ath9k_htc_start_ani(priv); |
1093 | } | 1094 | } |
@@ -1245,13 +1246,14 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw, | |||
1245 | u64 multicast) | 1246 | u64 multicast) |
1246 | { | 1247 | { |
1247 | struct ath9k_htc_priv *priv = hw->priv; | 1248 | struct ath9k_htc_priv *priv = hw->priv; |
1249 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
1248 | u32 rfilt; | 1250 | u32 rfilt; |
1249 | 1251 | ||
1250 | mutex_lock(&priv->mutex); | 1252 | mutex_lock(&priv->mutex); |
1251 | changed_flags &= SUPPORTED_FILTERS; | 1253 | changed_flags &= SUPPORTED_FILTERS; |
1252 | *total_flags &= SUPPORTED_FILTERS; | 1254 | *total_flags &= SUPPORTED_FILTERS; |
1253 | 1255 | ||
1254 | if (test_bit(OP_INVALID, &priv->op_flags)) { | 1256 | if (test_bit(ATH_OP_INVALID, &common->op_flags)) { |
1255 | ath_dbg(ath9k_hw_common(priv->ah), ANY, | 1257 | ath_dbg(ath9k_hw_common(priv->ah), ANY, |
1256 | "Unable to configure filter on invalid state\n"); | 1258 | "Unable to configure filter on invalid state\n"); |
1257 | mutex_unlock(&priv->mutex); | 1259 | mutex_unlock(&priv->mutex); |
@@ -1476,6 +1478,7 @@ static void ath9k_htc_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | |||
1476 | common->curaid = bss_conf->aid; | 1478 | common->curaid = bss_conf->aid; |
1477 | common->last_rssi = ATH_RSSI_DUMMY_MARKER; | 1479 | common->last_rssi = ATH_RSSI_DUMMY_MARKER; |
1478 | memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); | 1480 | memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); |
1481 | set_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags); | ||
1479 | } | 1482 | } |
1480 | } | 1483 | } |
1481 | 1484 | ||
@@ -1497,6 +1500,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, | |||
1497 | struct ath9k_htc_priv *priv = hw->priv; | 1500 | struct ath9k_htc_priv *priv = hw->priv; |
1498 | struct ath_hw *ah = priv->ah; | 1501 | struct ath_hw *ah = priv->ah; |
1499 | struct ath_common *common = ath9k_hw_common(ah); | 1502 | struct ath_common *common = ath9k_hw_common(ah); |
1503 | int slottime; | ||
1500 | 1504 | ||
1501 | mutex_lock(&priv->mutex); | 1505 | mutex_lock(&priv->mutex); |
1502 | ath9k_htc_ps_wakeup(priv); | 1506 | ath9k_htc_ps_wakeup(priv); |
@@ -1508,6 +1512,9 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, | |||
1508 | bss_conf->assoc ? | 1512 | bss_conf->assoc ? |
1509 | priv->num_sta_assoc_vif++ : priv->num_sta_assoc_vif--; | 1513 | priv->num_sta_assoc_vif++ : priv->num_sta_assoc_vif--; |
1510 | 1514 | ||
1515 | if (!bss_conf->assoc) | ||
1516 | clear_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags); | ||
1517 | |||
1511 | if (priv->ah->opmode == NL80211_IFTYPE_STATION) { | 1518 | if (priv->ah->opmode == NL80211_IFTYPE_STATION) { |
1512 | ath9k_htc_choose_set_bssid(priv); | 1519 | ath9k_htc_choose_set_bssid(priv); |
1513 | if (bss_conf->assoc && (priv->num_sta_assoc_vif == 1)) | 1520 | if (bss_conf->assoc && (priv->num_sta_assoc_vif == 1)) |
@@ -1529,7 +1536,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, | |||
1529 | ath_dbg(common, CONFIG, "Beacon enabled for BSS: %pM\n", | 1536 | ath_dbg(common, CONFIG, "Beacon enabled for BSS: %pM\n", |
1530 | bss_conf->bssid); | 1537 | bss_conf->bssid); |
1531 | ath9k_htc_set_tsfadjust(priv, vif); | 1538 | ath9k_htc_set_tsfadjust(priv, vif); |
1532 | set_bit(OP_ENABLE_BEACON, &priv->op_flags); | 1539 | priv->cur_beacon_conf.enable_beacon = 1; |
1533 | ath9k_htc_beacon_config(priv, vif); | 1540 | ath9k_htc_beacon_config(priv, vif); |
1534 | } | 1541 | } |
1535 | 1542 | ||
@@ -1543,7 +1550,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, | |||
1543 | ath_dbg(common, CONFIG, | 1550 | ath_dbg(common, CONFIG, |
1544 | "Beacon disabled for BSS: %pM\n", | 1551 | "Beacon disabled for BSS: %pM\n", |
1545 | bss_conf->bssid); | 1552 | bss_conf->bssid); |
1546 | clear_bit(OP_ENABLE_BEACON, &priv->op_flags); | 1553 | priv->cur_beacon_conf.enable_beacon = 0; |
1547 | ath9k_htc_beacon_config(priv, vif); | 1554 | ath9k_htc_beacon_config(priv, vif); |
1548 | } | 1555 | } |
1549 | } | 1556 | } |
@@ -1569,11 +1576,21 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, | |||
1569 | 1576 | ||
1570 | if (changed & BSS_CHANGED_ERP_SLOT) { | 1577 | if (changed & BSS_CHANGED_ERP_SLOT) { |
1571 | if (bss_conf->use_short_slot) | 1578 | if (bss_conf->use_short_slot) |
1572 | ah->slottime = 9; | 1579 | slottime = 9; |
1573 | else | 1580 | else |
1574 | ah->slottime = 20; | 1581 | slottime = 20; |
1575 | 1582 | if (vif->type == NL80211_IFTYPE_AP) { | |
1576 | ath9k_hw_init_global_settings(ah); | 1583 | /* |
1584 | * Defer update, so that connected stations can adjust | ||
1585 | * their settings at the same time. | ||
1586 | * See beacon.c for more details | ||
1587 | */ | ||
1588 | priv->beacon.slottime = slottime; | ||
1589 | priv->beacon.updateslot = UPDATE; | ||
1590 | } else { | ||
1591 | ah->slottime = slottime; | ||
1592 | ath9k_hw_init_global_settings(ah); | ||
1593 | } | ||
1577 | } | 1594 | } |
1578 | 1595 | ||
1579 | if (changed & BSS_CHANGED_HT) | 1596 | if (changed & BSS_CHANGED_HT) |
@@ -1670,10 +1687,11 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, | |||
1670 | static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw) | 1687 | static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw) |
1671 | { | 1688 | { |
1672 | struct ath9k_htc_priv *priv = hw->priv; | 1689 | struct ath9k_htc_priv *priv = hw->priv; |
1690 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
1673 | 1691 | ||
1674 | mutex_lock(&priv->mutex); | 1692 | mutex_lock(&priv->mutex); |
1675 | spin_lock_bh(&priv->beacon_lock); | 1693 | spin_lock_bh(&priv->beacon_lock); |
1676 | set_bit(OP_SCANNING, &priv->op_flags); | 1694 | set_bit(ATH_OP_SCANNING, &common->op_flags); |
1677 | spin_unlock_bh(&priv->beacon_lock); | 1695 | spin_unlock_bh(&priv->beacon_lock); |
1678 | cancel_work_sync(&priv->ps_work); | 1696 | cancel_work_sync(&priv->ps_work); |
1679 | ath9k_htc_stop_ani(priv); | 1697 | ath9k_htc_stop_ani(priv); |
@@ -1683,10 +1701,11 @@ static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw) | |||
1683 | static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw) | 1701 | static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw) |
1684 | { | 1702 | { |
1685 | struct ath9k_htc_priv *priv = hw->priv; | 1703 | struct ath9k_htc_priv *priv = hw->priv; |
1704 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
1686 | 1705 | ||
1687 | mutex_lock(&priv->mutex); | 1706 | mutex_lock(&priv->mutex); |
1688 | spin_lock_bh(&priv->beacon_lock); | 1707 | spin_lock_bh(&priv->beacon_lock); |
1689 | clear_bit(OP_SCANNING, &priv->op_flags); | 1708 | clear_bit(ATH_OP_SCANNING, &common->op_flags); |
1690 | spin_unlock_bh(&priv->beacon_lock); | 1709 | spin_unlock_bh(&priv->beacon_lock); |
1691 | ath9k_htc_ps_wakeup(priv); | 1710 | ath9k_htc_ps_wakeup(priv); |
1692 | ath9k_htc_vif_reconfig(priv); | 1711 | 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 47b2bfcd8223..e8149e3dbdd5 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | |||
@@ -924,9 +924,10 @@ static void ath9k_htc_opmode_init(struct ath9k_htc_priv *priv) | |||
924 | 924 | ||
925 | void ath9k_host_rx_init(struct ath9k_htc_priv *priv) | 925 | void ath9k_host_rx_init(struct ath9k_htc_priv *priv) |
926 | { | 926 | { |
927 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
927 | ath9k_hw_rxena(priv->ah); | 928 | ath9k_hw_rxena(priv->ah); |
928 | ath9k_htc_opmode_init(priv); | 929 | ath9k_htc_opmode_init(priv); |
929 | ath9k_hw_startpcureceive(priv->ah, test_bit(OP_SCANNING, &priv->op_flags)); | 930 | ath9k_hw_startpcureceive(priv->ah, test_bit(ATH_OP_SCANNING, &common->op_flags)); |
930 | } | 931 | } |
931 | 932 | ||
932 | static inline void convert_htc_flag(struct ath_rx_status *rx_stats, | 933 | static inline void convert_htc_flag(struct ath_rx_status *rx_stats, |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 2509c2ff0828..0992f7c70e1a 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -882,7 +882,7 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, | |||
882 | AR_IMR_RXORN | | 882 | AR_IMR_RXORN | |
883 | AR_IMR_BCNMISC; | 883 | AR_IMR_BCNMISC; |
884 | 884 | ||
885 | if (AR_SREV_9340(ah) || AR_SREV_9550(ah)) | 885 | if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah)) |
886 | sync_default &= ~AR_INTR_SYNC_HOST1_FATAL; | 886 | sync_default &= ~AR_INTR_SYNC_HOST1_FATAL; |
887 | 887 | ||
888 | if (AR_SREV_9300_20_OR_LATER(ah)) { | 888 | if (AR_SREV_9300_20_OR_LATER(ah)) { |
@@ -3048,6 +3048,7 @@ static struct { | |||
3048 | { AR_SREV_VERSION_9462, "9462" }, | 3048 | { AR_SREV_VERSION_9462, "9462" }, |
3049 | { AR_SREV_VERSION_9550, "9550" }, | 3049 | { AR_SREV_VERSION_9550, "9550" }, |
3050 | { AR_SREV_VERSION_9565, "9565" }, | 3050 | { AR_SREV_VERSION_9565, "9565" }, |
3051 | { AR_SREV_VERSION_9531, "9531" }, | ||
3051 | }; | 3052 | }; |
3052 | 3053 | ||
3053 | /* For devices with external radios */ | 3054 | /* For devices with external radios */ |
diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c index 30dcef5aba10..72a715fe8f24 100644 --- a/drivers/net/wireless/ath/ath9k/link.c +++ b/drivers/net/wireless/ath/ath9k/link.c | |||
@@ -115,13 +115,14 @@ void ath_hw_pll_work(struct work_struct *work) | |||
115 | u32 pll_sqsum; | 115 | u32 pll_sqsum; |
116 | struct ath_softc *sc = container_of(work, struct ath_softc, | 116 | struct ath_softc *sc = container_of(work, struct ath_softc, |
117 | hw_pll_work.work); | 117 | hw_pll_work.work); |
118 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
118 | /* | 119 | /* |
119 | * ensure that the PLL WAR is executed only | 120 | * ensure that the PLL WAR is executed only |
120 | * after the STA is associated (or) if the | 121 | * after the STA is associated (or) if the |
121 | * beaconing had started in interfaces that | 122 | * beaconing had started in interfaces that |
122 | * uses beacons. | 123 | * uses beacons. |
123 | */ | 124 | */ |
124 | if (!test_bit(SC_OP_BEACONS, &sc->sc_flags)) | 125 | if (!test_bit(ATH_OP_BEACONS, &common->op_flags)) |
125 | return; | 126 | return; |
126 | 127 | ||
127 | if (sc->tx99_state) | 128 | if (sc->tx99_state) |
@@ -414,7 +415,7 @@ void ath_start_ani(struct ath_softc *sc) | |||
414 | unsigned long timestamp = jiffies_to_msecs(jiffies); | 415 | unsigned long timestamp = jiffies_to_msecs(jiffies); |
415 | 416 | ||
416 | if (common->disable_ani || | 417 | if (common->disable_ani || |
417 | !test_bit(SC_OP_ANI_RUN, &sc->sc_flags) || | 418 | !test_bit(ATH_OP_ANI_RUN, &common->op_flags) || |
418 | (sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) | 419 | (sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) |
419 | return; | 420 | return; |
420 | 421 | ||
@@ -438,6 +439,7 @@ void ath_stop_ani(struct ath_softc *sc) | |||
438 | void ath_check_ani(struct ath_softc *sc) | 439 | void ath_check_ani(struct ath_softc *sc) |
439 | { | 440 | { |
440 | struct ath_hw *ah = sc->sc_ah; | 441 | struct ath_hw *ah = sc->sc_ah; |
442 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
441 | struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; | 443 | struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; |
442 | 444 | ||
443 | /* | 445 | /* |
@@ -453,23 +455,23 @@ void ath_check_ani(struct ath_softc *sc) | |||
453 | * Disable ANI only when there are no | 455 | * Disable ANI only when there are no |
454 | * associated stations. | 456 | * associated stations. |
455 | */ | 457 | */ |
456 | if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) | 458 | if (!test_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags)) |
457 | goto stop_ani; | 459 | goto stop_ani; |
458 | } | 460 | } |
459 | } else if (ah->opmode == NL80211_IFTYPE_STATION) { | 461 | } else if (ah->opmode == NL80211_IFTYPE_STATION) { |
460 | if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) | 462 | if (!test_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags)) |
461 | goto stop_ani; | 463 | goto stop_ani; |
462 | } | 464 | } |
463 | 465 | ||
464 | if (!test_bit(SC_OP_ANI_RUN, &sc->sc_flags)) { | 466 | if (!test_bit(ATH_OP_ANI_RUN, &common->op_flags)) { |
465 | set_bit(SC_OP_ANI_RUN, &sc->sc_flags); | 467 | set_bit(ATH_OP_ANI_RUN, &common->op_flags); |
466 | ath_start_ani(sc); | 468 | ath_start_ani(sc); |
467 | } | 469 | } |
468 | 470 | ||
469 | return; | 471 | return; |
470 | 472 | ||
471 | stop_ani: | 473 | stop_ani: |
472 | clear_bit(SC_OP_ANI_RUN, &sc->sc_flags); | 474 | clear_bit(ATH_OP_ANI_RUN, &common->op_flags); |
473 | ath_stop_ani(sc); | 475 | ath_stop_ani(sc); |
474 | } | 476 | } |
475 | 477 | ||
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 5f727588ca27..51ce36f108f9 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c | |||
@@ -827,7 +827,7 @@ void ath9k_hw_enable_interrupts(struct ath_hw *ah) | |||
827 | return; | 827 | return; |
828 | } | 828 | } |
829 | 829 | ||
830 | if (AR_SREV_9340(ah) || AR_SREV_9550(ah)) | 830 | if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah)) |
831 | sync_default &= ~AR_INTR_SYNC_HOST1_FATAL; | 831 | sync_default &= ~AR_INTR_SYNC_HOST1_FATAL; |
832 | 832 | ||
833 | async_mask = AR_INTR_MAC_IRQ; | 833 | async_mask = AR_INTR_MAC_IRQ; |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 42a18037004e..d69853b848ce 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -229,16 +229,16 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start) | |||
229 | ath9k_cmn_update_txpow(ah, sc->curtxpow, | 229 | ath9k_cmn_update_txpow(ah, sc->curtxpow, |
230 | sc->config.txpowlimit, &sc->curtxpow); | 230 | sc->config.txpowlimit, &sc->curtxpow); |
231 | 231 | ||
232 | clear_bit(SC_OP_HW_RESET, &sc->sc_flags); | 232 | clear_bit(ATH_OP_HW_RESET, &common->op_flags); |
233 | ath9k_hw_set_interrupts(ah); | 233 | ath9k_hw_set_interrupts(ah); |
234 | ath9k_hw_enable_interrupts(ah); | 234 | ath9k_hw_enable_interrupts(ah); |
235 | 235 | ||
236 | if (!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) && start) { | 236 | if (!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) && start) { |
237 | if (!test_bit(SC_OP_BEACONS, &sc->sc_flags)) | 237 | if (!test_bit(ATH_OP_BEACONS, &common->op_flags)) |
238 | goto work; | 238 | goto work; |
239 | 239 | ||
240 | if (ah->opmode == NL80211_IFTYPE_STATION && | 240 | if (ah->opmode == NL80211_IFTYPE_STATION && |
241 | test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) { | 241 | test_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags)) { |
242 | spin_lock_irqsave(&sc->sc_pm_lock, flags); | 242 | spin_lock_irqsave(&sc->sc_pm_lock, flags); |
243 | sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON; | 243 | sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON; |
244 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | 244 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); |
@@ -336,7 +336,7 @@ static int ath_set_channel(struct ath_softc *sc, struct cfg80211_chan_def *chand | |||
336 | int old_pos = -1; | 336 | int old_pos = -1; |
337 | int r; | 337 | int r; |
338 | 338 | ||
339 | if (test_bit(SC_OP_INVALID, &sc->sc_flags)) | 339 | if (test_bit(ATH_OP_INVALID, &common->op_flags)) |
340 | return -EIO; | 340 | return -EIO; |
341 | 341 | ||
342 | offchannel = !!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL); | 342 | offchannel = !!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL); |
@@ -402,7 +402,7 @@ static int ath_set_channel(struct ath_softc *sc, struct cfg80211_chan_def *chand | |||
402 | chan->center_freq); | 402 | chan->center_freq); |
403 | } else { | 403 | } else { |
404 | /* perform spectral scan if requested. */ | 404 | /* perform spectral scan if requested. */ |
405 | if (test_bit(SC_OP_SCANNING, &sc->sc_flags) && | 405 | if (test_bit(ATH_OP_SCANNING, &common->op_flags) && |
406 | sc->spectral_mode == SPECTRAL_CHANSCAN) | 406 | sc->spectral_mode == SPECTRAL_CHANSCAN) |
407 | ath9k_spectral_scan_trigger(hw); | 407 | ath9k_spectral_scan_trigger(hw); |
408 | } | 408 | } |
@@ -566,6 +566,7 @@ irqreturn_t ath_isr(int irq, void *dev) | |||
566 | 566 | ||
567 | struct ath_softc *sc = dev; | 567 | struct ath_softc *sc = dev; |
568 | struct ath_hw *ah = sc->sc_ah; | 568 | struct ath_hw *ah = sc->sc_ah; |
569 | struct ath_common *common = ath9k_hw_common(ah); | ||
569 | enum ath9k_int status; | 570 | enum ath9k_int status; |
570 | u32 sync_cause = 0; | 571 | u32 sync_cause = 0; |
571 | bool sched = false; | 572 | bool sched = false; |
@@ -575,7 +576,7 @@ irqreturn_t ath_isr(int irq, void *dev) | |||
575 | * touch anything. Note this can happen early | 576 | * touch anything. Note this can happen early |
576 | * on if the IRQ is shared. | 577 | * on if the IRQ is shared. |
577 | */ | 578 | */ |
578 | if (test_bit(SC_OP_INVALID, &sc->sc_flags)) | 579 | if (test_bit(ATH_OP_INVALID, &common->op_flags)) |
579 | return IRQ_NONE; | 580 | return IRQ_NONE; |
580 | 581 | ||
581 | /* shared irq, not for us */ | 582 | /* shared irq, not for us */ |
@@ -583,7 +584,7 @@ irqreturn_t ath_isr(int irq, void *dev) | |||
583 | if (!ath9k_hw_intrpend(ah)) | 584 | if (!ath9k_hw_intrpend(ah)) |
584 | return IRQ_NONE; | 585 | return IRQ_NONE; |
585 | 586 | ||
586 | if (test_bit(SC_OP_HW_RESET, &sc->sc_flags)) { | 587 | if (test_bit(ATH_OP_HW_RESET, &common->op_flags)) { |
587 | ath9k_hw_kill_interrupts(ah); | 588 | ath9k_hw_kill_interrupts(ah); |
588 | return IRQ_HANDLED; | 589 | return IRQ_HANDLED; |
589 | } | 590 | } |
@@ -684,10 +685,11 @@ int ath_reset(struct ath_softc *sc) | |||
684 | 685 | ||
685 | void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type) | 686 | void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type) |
686 | { | 687 | { |
688 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
687 | #ifdef CONFIG_ATH9K_DEBUGFS | 689 | #ifdef CONFIG_ATH9K_DEBUGFS |
688 | RESET_STAT_INC(sc, type); | 690 | RESET_STAT_INC(sc, type); |
689 | #endif | 691 | #endif |
690 | set_bit(SC_OP_HW_RESET, &sc->sc_flags); | 692 | set_bit(ATH_OP_HW_RESET, &common->op_flags); |
691 | ieee80211_queue_work(sc->hw, &sc->hw_reset_work); | 693 | ieee80211_queue_work(sc->hw, &sc->hw_reset_work); |
692 | } | 694 | } |
693 | 695 | ||
@@ -768,7 +770,7 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
768 | 770 | ||
769 | ath_mci_enable(sc); | 771 | ath_mci_enable(sc); |
770 | 772 | ||
771 | clear_bit(SC_OP_INVALID, &sc->sc_flags); | 773 | clear_bit(ATH_OP_INVALID, &common->op_flags); |
772 | sc->sc_ah->is_monitoring = false; | 774 | sc->sc_ah->is_monitoring = false; |
773 | 775 | ||
774 | if (!ath_complete_reset(sc, false)) | 776 | if (!ath_complete_reset(sc, false)) |
@@ -885,7 +887,7 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
885 | 887 | ||
886 | ath_cancel_work(sc); | 888 | ath_cancel_work(sc); |
887 | 889 | ||
888 | if (test_bit(SC_OP_INVALID, &sc->sc_flags)) { | 890 | if (test_bit(ATH_OP_INVALID, &common->op_flags)) { |
889 | ath_dbg(common, ANY, "Device not present\n"); | 891 | ath_dbg(common, ANY, "Device not present\n"); |
890 | mutex_unlock(&sc->mutex); | 892 | mutex_unlock(&sc->mutex); |
891 | return; | 893 | return; |
@@ -940,7 +942,7 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
940 | 942 | ||
941 | ath9k_ps_restore(sc); | 943 | ath9k_ps_restore(sc); |
942 | 944 | ||
943 | set_bit(SC_OP_INVALID, &sc->sc_flags); | 945 | set_bit(ATH_OP_INVALID, &common->op_flags); |
944 | sc->ps_idle = prev_idle; | 946 | sc->ps_idle = prev_idle; |
945 | 947 | ||
946 | mutex_unlock(&sc->mutex); | 948 | mutex_unlock(&sc->mutex); |
@@ -1081,7 +1083,7 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw, | |||
1081 | */ | 1083 | */ |
1082 | if (ah->opmode == NL80211_IFTYPE_STATION && | 1084 | if (ah->opmode == NL80211_IFTYPE_STATION && |
1083 | old_opmode == NL80211_IFTYPE_AP && | 1085 | old_opmode == NL80211_IFTYPE_AP && |
1084 | test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) { | 1086 | test_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags)) { |
1085 | ieee80211_iterate_active_interfaces_atomic( | 1087 | ieee80211_iterate_active_interfaces_atomic( |
1086 | sc->hw, IEEE80211_IFACE_ITER_RESUME_ALL, | 1088 | sc->hw, IEEE80211_IFACE_ITER_RESUME_ALL, |
1087 | ath9k_sta_vif_iter, sc); | 1089 | ath9k_sta_vif_iter, sc); |
@@ -1590,7 +1592,7 @@ static void ath9k_set_assoc_state(struct ath_softc *sc, | |||
1590 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | 1592 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; |
1591 | unsigned long flags; | 1593 | unsigned long flags; |
1592 | 1594 | ||
1593 | set_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags); | 1595 | set_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags); |
1594 | avp->primary_sta_vif = true; | 1596 | avp->primary_sta_vif = true; |
1595 | 1597 | ||
1596 | /* | 1598 | /* |
@@ -1625,8 +1627,9 @@ static void ath9k_bss_assoc_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | |||
1625 | { | 1627 | { |
1626 | struct ath_softc *sc = data; | 1628 | struct ath_softc *sc = data; |
1627 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | 1629 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; |
1630 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
1628 | 1631 | ||
1629 | if (test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) | 1632 | if (test_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags)) |
1630 | return; | 1633 | return; |
1631 | 1634 | ||
1632 | if (bss_conf->assoc) | 1635 | if (bss_conf->assoc) |
@@ -1657,18 +1660,18 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | |||
1657 | bss_conf->bssid, bss_conf->assoc); | 1660 | bss_conf->bssid, bss_conf->assoc); |
1658 | 1661 | ||
1659 | if (avp->primary_sta_vif && !bss_conf->assoc) { | 1662 | if (avp->primary_sta_vif && !bss_conf->assoc) { |
1660 | clear_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags); | 1663 | clear_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags); |
1661 | avp->primary_sta_vif = false; | 1664 | avp->primary_sta_vif = false; |
1662 | 1665 | ||
1663 | if (ah->opmode == NL80211_IFTYPE_STATION) | 1666 | if (ah->opmode == NL80211_IFTYPE_STATION) |
1664 | clear_bit(SC_OP_BEACONS, &sc->sc_flags); | 1667 | clear_bit(ATH_OP_BEACONS, &common->op_flags); |
1665 | } | 1668 | } |
1666 | 1669 | ||
1667 | ieee80211_iterate_active_interfaces_atomic( | 1670 | ieee80211_iterate_active_interfaces_atomic( |
1668 | sc->hw, IEEE80211_IFACE_ITER_RESUME_ALL, | 1671 | sc->hw, IEEE80211_IFACE_ITER_RESUME_ALL, |
1669 | ath9k_bss_assoc_iter, sc); | 1672 | ath9k_bss_assoc_iter, sc); |
1670 | 1673 | ||
1671 | if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags) && | 1674 | if (!test_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags) && |
1672 | ah->opmode == NL80211_IFTYPE_STATION) { | 1675 | ah->opmode == NL80211_IFTYPE_STATION) { |
1673 | memset(common->curbssid, 0, ETH_ALEN); | 1676 | memset(common->curbssid, 0, ETH_ALEN); |
1674 | common->curaid = 0; | 1677 | common->curaid = 0; |
@@ -1897,7 +1900,7 @@ static void ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop) | |||
1897 | return; | 1900 | return; |
1898 | } | 1901 | } |
1899 | 1902 | ||
1900 | if (test_bit(SC_OP_INVALID, &sc->sc_flags)) { | 1903 | if (test_bit(ATH_OP_INVALID, &common->op_flags)) { |
1901 | ath_dbg(common, ANY, "Device not present\n"); | 1904 | ath_dbg(common, ANY, "Device not present\n"); |
1902 | mutex_unlock(&sc->mutex); | 1905 | mutex_unlock(&sc->mutex); |
1903 | return; | 1906 | return; |
@@ -2070,13 +2073,15 @@ static int ath9k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) | |||
2070 | static void ath9k_sw_scan_start(struct ieee80211_hw *hw) | 2073 | static void ath9k_sw_scan_start(struct ieee80211_hw *hw) |
2071 | { | 2074 | { |
2072 | struct ath_softc *sc = hw->priv; | 2075 | struct ath_softc *sc = hw->priv; |
2073 | set_bit(SC_OP_SCANNING, &sc->sc_flags); | 2076 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
2077 | set_bit(ATH_OP_SCANNING, &common->op_flags); | ||
2074 | } | 2078 | } |
2075 | 2079 | ||
2076 | static void ath9k_sw_scan_complete(struct ieee80211_hw *hw) | 2080 | static void ath9k_sw_scan_complete(struct ieee80211_hw *hw) |
2077 | { | 2081 | { |
2078 | struct ath_softc *sc = hw->priv; | 2082 | struct ath_softc *sc = hw->priv; |
2079 | clear_bit(SC_OP_SCANNING, &sc->sc_flags); | 2083 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
2084 | clear_bit(ATH_OP_SCANNING, &common->op_flags); | ||
2080 | } | 2085 | } |
2081 | 2086 | ||
2082 | static void ath9k_channel_switch_beacon(struct ieee80211_hw *hw, | 2087 | static void ath9k_channel_switch_beacon(struct ieee80211_hw *hw, |
diff --git a/drivers/net/wireless/ath/ath9k/mci.c b/drivers/net/wireless/ath/ath9k/mci.c index 71799fcade54..a0dbcc412384 100644 --- a/drivers/net/wireless/ath/ath9k/mci.c +++ b/drivers/net/wireless/ath/ath9k/mci.c | |||
@@ -555,7 +555,7 @@ void ath_mci_intr(struct ath_softc *sc) | |||
555 | mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_GPM; | 555 | mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_GPM; |
556 | 556 | ||
557 | while (more_data == MCI_GPM_MORE) { | 557 | while (more_data == MCI_GPM_MORE) { |
558 | if (test_bit(SC_OP_HW_RESET, &sc->sc_flags)) | 558 | if (test_bit(ATH_OP_HW_RESET, &common->op_flags)) |
559 | return; | 559 | return; |
560 | 560 | ||
561 | pgpm = mci->gpm_buf.bf_addr; | 561 | pgpm = mci->gpm_buf.bf_addr; |
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 55724b02316b..25304adece57 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c | |||
@@ -784,6 +784,7 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
784 | { | 784 | { |
785 | struct ath_softc *sc; | 785 | struct ath_softc *sc; |
786 | struct ieee80211_hw *hw; | 786 | struct ieee80211_hw *hw; |
787 | struct ath_common *common; | ||
787 | u8 csz; | 788 | u8 csz; |
788 | u32 val; | 789 | u32 val; |
789 | int ret = 0; | 790 | int ret = 0; |
@@ -858,9 +859,6 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
858 | sc->mem = pcim_iomap_table(pdev)[0]; | 859 | sc->mem = pcim_iomap_table(pdev)[0]; |
859 | sc->driver_data = id->driver_data; | 860 | sc->driver_data = id->driver_data; |
860 | 861 | ||
861 | /* Will be cleared in ath9k_start() */ | ||
862 | set_bit(SC_OP_INVALID, &sc->sc_flags); | ||
863 | |||
864 | ret = request_irq(pdev->irq, ath_isr, IRQF_SHARED, "ath9k", sc); | 862 | ret = request_irq(pdev->irq, ath_isr, IRQF_SHARED, "ath9k", sc); |
865 | if (ret) { | 863 | if (ret) { |
866 | dev_err(&pdev->dev, "request_irq failed\n"); | 864 | dev_err(&pdev->dev, "request_irq failed\n"); |
@@ -879,6 +877,10 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
879 | wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n", | 877 | wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n", |
880 | hw_name, (unsigned long)sc->mem, pdev->irq); | 878 | hw_name, (unsigned long)sc->mem, pdev->irq); |
881 | 879 | ||
880 | /* Will be cleared in ath9k_start() */ | ||
881 | common = ath9k_hw_common(sc->sc_ah); | ||
882 | set_bit(ATH_OP_INVALID, &common->op_flags); | ||
883 | |||
882 | return 0; | 884 | return 0; |
883 | 885 | ||
884 | err_init: | 886 | err_init: |
diff --git a/drivers/net/wireless/ath/ath9k/tx99.c b/drivers/net/wireless/ath/ath9k/tx99.c index b686a7498450..a65cfb91adca 100644 --- a/drivers/net/wireless/ath/ath9k/tx99.c +++ b/drivers/net/wireless/ath/ath9k/tx99.c | |||
@@ -108,7 +108,7 @@ static int ath9k_tx99_init(struct ath_softc *sc) | |||
108 | struct ath_tx_control txctl; | 108 | struct ath_tx_control txctl; |
109 | int r; | 109 | int r; |
110 | 110 | ||
111 | if (test_bit(SC_OP_INVALID, &sc->sc_flags)) { | 111 | if (test_bit(ATH_OP_INVALID, &common->op_flags)) { |
112 | ath_err(common, | 112 | ath_err(common, |
113 | "driver is in invalid state unable to use TX99"); | 113 | "driver is in invalid state unable to use TX99"); |
114 | return -EINVAL; | 114 | return -EINVAL; |
diff --git a/drivers/net/wireless/ath/ath9k/wow.c b/drivers/net/wireless/ath/ath9k/wow.c index 1b3230fa3651..2879887f5691 100644 --- a/drivers/net/wireless/ath/ath9k/wow.c +++ b/drivers/net/wireless/ath/ath9k/wow.c | |||
@@ -198,7 +198,7 @@ int ath9k_suspend(struct ieee80211_hw *hw, | |||
198 | ath_cancel_work(sc); | 198 | ath_cancel_work(sc); |
199 | ath_stop_ani(sc); | 199 | ath_stop_ani(sc); |
200 | 200 | ||
201 | if (test_bit(SC_OP_INVALID, &sc->sc_flags)) { | 201 | if (test_bit(ATH_OP_INVALID, &common->op_flags)) { |
202 | ath_dbg(common, ANY, "Device not present\n"); | 202 | ath_dbg(common, ANY, "Device not present\n"); |
203 | ret = -EINVAL; | 203 | ret = -EINVAL; |
204 | goto fail_wow; | 204 | goto fail_wow; |
@@ -224,7 +224,7 @@ int ath9k_suspend(struct ieee80211_hw *hw, | |||
224 | * STA. | 224 | * STA. |
225 | */ | 225 | */ |
226 | 226 | ||
227 | if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) { | 227 | if (!test_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags)) { |
228 | ath_dbg(common, WOW, "None of the STA vifs are associated\n"); | 228 | ath_dbg(common, WOW, "None of the STA vifs are associated\n"); |
229 | ret = 1; | 229 | ret = 1; |
230 | goto fail_wow; | 230 | goto fail_wow; |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index fafacfed44ea..f76e6b9bb8e6 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -1699,7 +1699,7 @@ int ath_cabq_update(struct ath_softc *sc) | |||
1699 | 1699 | ||
1700 | ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi); | 1700 | ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi); |
1701 | 1701 | ||
1702 | qi.tqi_readyTime = (cur_conf->beacon_interval * | 1702 | qi.tqi_readyTime = (TU_TO_USEC(cur_conf->beacon_interval) * |
1703 | ATH_CABQ_READY_TIME) / 100; | 1703 | ATH_CABQ_READY_TIME) / 100; |
1704 | ath_txq_update(sc, qnum, &qi); | 1704 | ath_txq_update(sc, qnum, &qi); |
1705 | 1705 | ||
@@ -1769,7 +1769,7 @@ bool ath_drain_all_txq(struct ath_softc *sc) | |||
1769 | int i; | 1769 | int i; |
1770 | u32 npend = 0; | 1770 | u32 npend = 0; |
1771 | 1771 | ||
1772 | if (test_bit(SC_OP_INVALID, &sc->sc_flags)) | 1772 | if (test_bit(ATH_OP_INVALID, &common->op_flags)) |
1773 | return true; | 1773 | return true; |
1774 | 1774 | ||
1775 | ath9k_hw_abort_tx_dma(ah); | 1775 | ath9k_hw_abort_tx_dma(ah); |
@@ -1817,11 +1817,12 @@ void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq) | |||
1817 | */ | 1817 | */ |
1818 | void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) | 1818 | void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) |
1819 | { | 1819 | { |
1820 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
1820 | struct ath_atx_ac *ac, *last_ac; | 1821 | struct ath_atx_ac *ac, *last_ac; |
1821 | struct ath_atx_tid *tid, *last_tid; | 1822 | struct ath_atx_tid *tid, *last_tid; |
1822 | bool sent = false; | 1823 | bool sent = false; |
1823 | 1824 | ||
1824 | if (test_bit(SC_OP_HW_RESET, &sc->sc_flags) || | 1825 | if (test_bit(ATH_OP_HW_RESET, &common->op_flags) || |
1825 | list_empty(&txq->axq_acq)) | 1826 | list_empty(&txq->axq_acq)) |
1826 | return; | 1827 | return; |
1827 | 1828 | ||
@@ -2471,7 +2472,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
2471 | 2472 | ||
2472 | ath_txq_lock(sc, txq); | 2473 | ath_txq_lock(sc, txq); |
2473 | for (;;) { | 2474 | for (;;) { |
2474 | if (test_bit(SC_OP_HW_RESET, &sc->sc_flags)) | 2475 | if (test_bit(ATH_OP_HW_RESET, &common->op_flags)) |
2475 | break; | 2476 | break; |
2476 | 2477 | ||
2477 | if (list_empty(&txq->axq_q)) { | 2478 | if (list_empty(&txq->axq_q)) { |
@@ -2554,7 +2555,7 @@ void ath_tx_edma_tasklet(struct ath_softc *sc) | |||
2554 | int status; | 2555 | int status; |
2555 | 2556 | ||
2556 | for (;;) { | 2557 | for (;;) { |
2557 | if (test_bit(SC_OP_HW_RESET, &sc->sc_flags)) | 2558 | if (test_bit(ATH_OP_HW_RESET, &common->op_flags)) |
2558 | break; | 2559 | break; |
2559 | 2560 | ||
2560 | status = ath9k_hw_txprocdesc(ah, NULL, (void *)&ts); | 2561 | status = ath9k_hw_txprocdesc(ah, NULL, (void *)&ts); |
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 743930357061..4806a49cb61b 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c | |||
@@ -179,7 +179,7 @@ static int wil_cfg80211_get_station(struct wiphy *wiphy, | |||
179 | 179 | ||
180 | int cid = wil_find_cid(wil, mac); | 180 | int cid = wil_find_cid(wil, mac); |
181 | 181 | ||
182 | wil_info(wil, "%s(%pM) CID %d\n", __func__, mac, cid); | 182 | wil_dbg_misc(wil, "%s(%pM) CID %d\n", __func__, mac, cid); |
183 | if (cid < 0) | 183 | if (cid < 0) |
184 | return cid; | 184 | return cid; |
185 | 185 | ||
@@ -218,7 +218,7 @@ static int wil_cfg80211_dump_station(struct wiphy *wiphy, | |||
218 | return -ENOENT; | 218 | return -ENOENT; |
219 | 219 | ||
220 | memcpy(mac, wil->sta[cid].addr, ETH_ALEN); | 220 | memcpy(mac, wil->sta[cid].addr, ETH_ALEN); |
221 | wil_info(wil, "%s(%pM) CID %d\n", __func__, mac, cid); | 221 | wil_dbg_misc(wil, "%s(%pM) CID %d\n", __func__, mac, cid); |
222 | 222 | ||
223 | rc = wil_cid_fill_sinfo(wil, cid, sinfo); | 223 | rc = wil_cid_fill_sinfo(wil, cid, sinfo); |
224 | 224 | ||
@@ -265,6 +265,7 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, | |||
265 | u16 chnl[4]; | 265 | u16 chnl[4]; |
266 | } __packed cmd; | 266 | } __packed cmd; |
267 | uint i, n; | 267 | uint i, n; |
268 | int rc; | ||
268 | 269 | ||
269 | if (wil->scan_request) { | 270 | if (wil->scan_request) { |
270 | wil_err(wil, "Already scanning\n"); | 271 | wil_err(wil, "Already scanning\n"); |
@@ -282,7 +283,7 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, | |||
282 | 283 | ||
283 | /* FW don't support scan after connection attempt */ | 284 | /* FW don't support scan after connection attempt */ |
284 | if (test_bit(wil_status_dontscan, &wil->status)) { | 285 | if (test_bit(wil_status_dontscan, &wil->status)) { |
285 | wil_err(wil, "Scan after connect attempt not supported\n"); | 286 | wil_err(wil, "Can't scan now\n"); |
286 | return -EBUSY; | 287 | return -EBUSY; |
287 | } | 288 | } |
288 | 289 | ||
@@ -305,8 +306,13 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, | |||
305 | request->channels[i]->center_freq); | 306 | request->channels[i]->center_freq); |
306 | } | 307 | } |
307 | 308 | ||
308 | return wmi_send(wil, WMI_START_SCAN_CMDID, &cmd, sizeof(cmd.cmd) + | 309 | rc = wmi_send(wil, WMI_START_SCAN_CMDID, &cmd, sizeof(cmd.cmd) + |
309 | cmd.cmd.num_channels * sizeof(cmd.cmd.channel_list[0])); | 310 | cmd.cmd.num_channels * sizeof(cmd.cmd.channel_list[0])); |
311 | |||
312 | if (rc) | ||
313 | wil->scan_request = NULL; | ||
314 | |||
315 | return rc; | ||
310 | } | 316 | } |
311 | 317 | ||
312 | static int wil_cfg80211_connect(struct wiphy *wiphy, | 318 | static int wil_cfg80211_connect(struct wiphy *wiphy, |
@@ -321,6 +327,10 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, | |||
321 | int ch; | 327 | int ch; |
322 | int rc = 0; | 328 | int rc = 0; |
323 | 329 | ||
330 | if (test_bit(wil_status_fwconnecting, &wil->status) || | ||
331 | test_bit(wil_status_fwconnected, &wil->status)) | ||
332 | return -EALREADY; | ||
333 | |||
324 | bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid, | 334 | bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid, |
325 | sme->ssid, sme->ssid_len, | 335 | sme->ssid, sme->ssid_len, |
326 | WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); | 336 | WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); |
@@ -402,10 +412,7 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, | |||
402 | 412 | ||
403 | memcpy(conn.bssid, bss->bssid, ETH_ALEN); | 413 | memcpy(conn.bssid, bss->bssid, ETH_ALEN); |
404 | memcpy(conn.dst_mac, bss->bssid, ETH_ALEN); | 414 | memcpy(conn.dst_mac, bss->bssid, ETH_ALEN); |
405 | /* | 415 | |
406 | * FW don't support scan after connection attempt | ||
407 | */ | ||
408 | set_bit(wil_status_dontscan, &wil->status); | ||
409 | set_bit(wil_status_fwconnecting, &wil->status); | 416 | set_bit(wil_status_fwconnecting, &wil->status); |
410 | 417 | ||
411 | rc = wmi_send(wil, WMI_CONNECT_CMDID, &conn, sizeof(conn)); | 418 | rc = wmi_send(wil, WMI_CONNECT_CMDID, &conn, sizeof(conn)); |
@@ -414,7 +421,6 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, | |||
414 | mod_timer(&wil->connect_timer, | 421 | mod_timer(&wil->connect_timer, |
415 | jiffies + msecs_to_jiffies(2000)); | 422 | jiffies + msecs_to_jiffies(2000)); |
416 | } else { | 423 | } else { |
417 | clear_bit(wil_status_dontscan, &wil->status); | ||
418 | clear_bit(wil_status_fwconnecting, &wil->status); | 424 | clear_bit(wil_status_fwconnecting, &wil->status); |
419 | } | 425 | } |
420 | 426 | ||
@@ -603,18 +609,20 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy, | |||
603 | if (wil_fix_bcon(wil, bcon)) | 609 | if (wil_fix_bcon(wil, bcon)) |
604 | wil_dbg_misc(wil, "Fixed bcon\n"); | 610 | wil_dbg_misc(wil, "Fixed bcon\n"); |
605 | 611 | ||
612 | mutex_lock(&wil->mutex); | ||
613 | |||
606 | rc = wil_reset(wil); | 614 | rc = wil_reset(wil); |
607 | if (rc) | 615 | if (rc) |
608 | return rc; | 616 | goto out; |
609 | 617 | ||
610 | /* Rx VRING. */ | 618 | /* Rx VRING. */ |
611 | rc = wil_rx_init(wil); | 619 | rc = wil_rx_init(wil); |
612 | if (rc) | 620 | if (rc) |
613 | return rc; | 621 | goto out; |
614 | 622 | ||
615 | rc = wmi_set_ssid(wil, info->ssid_len, info->ssid); | 623 | rc = wmi_set_ssid(wil, info->ssid_len, info->ssid); |
616 | if (rc) | 624 | if (rc) |
617 | return rc; | 625 | goto out; |
618 | 626 | ||
619 | /* MAC address - pre-requisite for other commands */ | 627 | /* MAC address - pre-requisite for other commands */ |
620 | wmi_set_mac_address(wil, ndev->dev_addr); | 628 | wmi_set_mac_address(wil, ndev->dev_addr); |
@@ -638,11 +646,13 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy, | |||
638 | rc = wmi_pcp_start(wil, info->beacon_interval, wmi_nettype, | 646 | rc = wmi_pcp_start(wil, info->beacon_interval, wmi_nettype, |
639 | channel->hw_value); | 647 | channel->hw_value); |
640 | if (rc) | 648 | if (rc) |
641 | return rc; | 649 | goto out; |
642 | 650 | ||
643 | 651 | ||
644 | netif_carrier_on(ndev); | 652 | netif_carrier_on(ndev); |
645 | 653 | ||
654 | out: | ||
655 | mutex_unlock(&wil->mutex); | ||
646 | return rc; | 656 | return rc; |
647 | } | 657 | } |
648 | 658 | ||
@@ -652,8 +662,11 @@ static int wil_cfg80211_stop_ap(struct wiphy *wiphy, | |||
652 | int rc = 0; | 662 | int rc = 0; |
653 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 663 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
654 | 664 | ||
665 | mutex_lock(&wil->mutex); | ||
666 | |||
655 | rc = wmi_pcp_stop(wil); | 667 | rc = wmi_pcp_stop(wil); |
656 | 668 | ||
669 | mutex_unlock(&wil->mutex); | ||
657 | return rc; | 670 | return rc; |
658 | } | 671 | } |
659 | 672 | ||
@@ -661,7 +674,11 @@ static int wil_cfg80211_del_station(struct wiphy *wiphy, | |||
661 | struct net_device *dev, u8 *mac) | 674 | struct net_device *dev, u8 *mac) |
662 | { | 675 | { |
663 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 676 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
677 | |||
678 | mutex_lock(&wil->mutex); | ||
664 | wil6210_disconnect(wil, mac); | 679 | wil6210_disconnect(wil, mac); |
680 | mutex_unlock(&wil->mutex); | ||
681 | |||
665 | return 0; | 682 | return 0; |
666 | } | 683 | } |
667 | 684 | ||
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index 1d09a4b0a0f4..ecdabe4adec3 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c | |||
@@ -398,6 +398,44 @@ static const struct file_operations fops_reset = { | |||
398 | .open = simple_open, | 398 | .open = simple_open, |
399 | }; | 399 | }; |
400 | 400 | ||
401 | static void wil_seq_hexdump(struct seq_file *s, void *p, int len, | ||
402 | const char *prefix) | ||
403 | { | ||
404 | char printbuf[16 * 3 + 2]; | ||
405 | int i = 0; | ||
406 | while (i < len) { | ||
407 | int l = min(len - i, 16); | ||
408 | hex_dump_to_buffer(p + i, l, 16, 1, printbuf, | ||
409 | sizeof(printbuf), false); | ||
410 | seq_printf(s, "%s%s\n", prefix, printbuf); | ||
411 | i += l; | ||
412 | } | ||
413 | } | ||
414 | |||
415 | static void wil_seq_print_skb(struct seq_file *s, struct sk_buff *skb) | ||
416 | { | ||
417 | int i = 0; | ||
418 | int len = skb_headlen(skb); | ||
419 | void *p = skb->data; | ||
420 | int nr_frags = skb_shinfo(skb)->nr_frags; | ||
421 | |||
422 | seq_printf(s, " len = %d\n", len); | ||
423 | wil_seq_hexdump(s, p, len, " : "); | ||
424 | |||
425 | if (nr_frags) { | ||
426 | seq_printf(s, " nr_frags = %d\n", nr_frags); | ||
427 | for (i = 0; i < nr_frags; i++) { | ||
428 | const struct skb_frag_struct *frag = | ||
429 | &skb_shinfo(skb)->frags[i]; | ||
430 | |||
431 | len = skb_frag_size(frag); | ||
432 | p = skb_frag_address_safe(frag); | ||
433 | seq_printf(s, " [%2d] : len = %d\n", i, len); | ||
434 | wil_seq_hexdump(s, p, len, " : "); | ||
435 | } | ||
436 | } | ||
437 | } | ||
438 | |||
401 | /*---------Tx/Rx descriptor------------*/ | 439 | /*---------Tx/Rx descriptor------------*/ |
402 | static int wil_txdesc_debugfs_show(struct seq_file *s, void *data) | 440 | static int wil_txdesc_debugfs_show(struct seq_file *s, void *data) |
403 | { | 441 | { |
@@ -438,26 +476,9 @@ static int wil_txdesc_debugfs_show(struct seq_file *s, void *data) | |||
438 | seq_printf(s, " SKB = %p\n", skb); | 476 | seq_printf(s, " SKB = %p\n", skb); |
439 | 477 | ||
440 | if (skb) { | 478 | if (skb) { |
441 | char printbuf[16 * 3 + 2]; | 479 | skb_get(skb); |
442 | int i = 0; | 480 | wil_seq_print_skb(s, skb); |
443 | int len = le16_to_cpu(d->dma.length); | 481 | kfree_skb(skb); |
444 | void *p = skb->data; | ||
445 | |||
446 | if (len != skb_headlen(skb)) { | ||
447 | seq_printf(s, "!!! len: desc = %d skb = %d\n", | ||
448 | len, skb_headlen(skb)); | ||
449 | len = min_t(int, len, skb_headlen(skb)); | ||
450 | } | ||
451 | |||
452 | seq_printf(s, " len = %d\n", len); | ||
453 | |||
454 | while (i < len) { | ||
455 | int l = min(len - i, 16); | ||
456 | hex_dump_to_buffer(p + i, l, 16, 1, printbuf, | ||
457 | sizeof(printbuf), false); | ||
458 | seq_printf(s, " : %s\n", printbuf); | ||
459 | i += l; | ||
460 | } | ||
461 | } | 482 | } |
462 | seq_printf(s, "}\n"); | 483 | seq_printf(s, "}\n"); |
463 | } else { | 484 | } else { |
@@ -631,7 +652,8 @@ static int wil_sta_debugfs_show(struct seq_file *s, void *data) | |||
631 | status = "connected"; | 652 | status = "connected"; |
632 | break; | 653 | break; |
633 | } | 654 | } |
634 | seq_printf(s, "[%d] %pM %s\n", i, p->addr, status); | 655 | seq_printf(s, "[%d] %pM %s%s\n", i, p->addr, status, |
656 | (p->data_port_open ? " data_port_open" : "")); | ||
635 | 657 | ||
636 | if (p->status == wil_sta_connected) { | 658 | if (p->status == wil_sta_connected) { |
637 | for (tid = 0; tid < WIL_STA_TID_NUM; tid++) { | 659 | for (tid = 0; tid < WIL_STA_TID_NUM; tid++) { |
diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c index 10919f95a83c..5824cd41e4ba 100644 --- a/drivers/net/wireless/ath/wil6210/interrupt.c +++ b/drivers/net/wireless/ath/wil6210/interrupt.c | |||
@@ -195,8 +195,12 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie) | |||
195 | if (isr & BIT_DMA_EP_RX_ICR_RX_DONE) { | 195 | if (isr & BIT_DMA_EP_RX_ICR_RX_DONE) { |
196 | wil_dbg_irq(wil, "RX done\n"); | 196 | wil_dbg_irq(wil, "RX done\n"); |
197 | isr &= ~BIT_DMA_EP_RX_ICR_RX_DONE; | 197 | isr &= ~BIT_DMA_EP_RX_ICR_RX_DONE; |
198 | wil_dbg_txrx(wil, "NAPI schedule\n"); | 198 | if (test_bit(wil_status_reset_done, &wil->status)) { |
199 | napi_schedule(&wil->napi_rx); | 199 | wil_dbg_txrx(wil, "NAPI(Rx) schedule\n"); |
200 | napi_schedule(&wil->napi_rx); | ||
201 | } else { | ||
202 | wil_err(wil, "Got Rx interrupt while in reset\n"); | ||
203 | } | ||
200 | } | 204 | } |
201 | 205 | ||
202 | if (isr) | 206 | if (isr) |
@@ -226,10 +230,15 @@ static irqreturn_t wil6210_irq_tx(int irq, void *cookie) | |||
226 | 230 | ||
227 | if (isr & BIT_DMA_EP_TX_ICR_TX_DONE) { | 231 | if (isr & BIT_DMA_EP_TX_ICR_TX_DONE) { |
228 | wil_dbg_irq(wil, "TX done\n"); | 232 | wil_dbg_irq(wil, "TX done\n"); |
229 | napi_schedule(&wil->napi_tx); | ||
230 | isr &= ~BIT_DMA_EP_TX_ICR_TX_DONE; | 233 | isr &= ~BIT_DMA_EP_TX_ICR_TX_DONE; |
231 | /* clear also all VRING interrupts */ | 234 | /* clear also all VRING interrupts */ |
232 | isr &= ~(BIT(25) - 1UL); | 235 | isr &= ~(BIT(25) - 1UL); |
236 | if (test_bit(wil_status_reset_done, &wil->status)) { | ||
237 | wil_dbg_txrx(wil, "NAPI(Tx) schedule\n"); | ||
238 | napi_schedule(&wil->napi_tx); | ||
239 | } else { | ||
240 | wil_err(wil, "Got Tx interrupt while in reset\n"); | ||
241 | } | ||
233 | } | 242 | } |
234 | 243 | ||
235 | if (isr) | 244 | if (isr) |
@@ -319,6 +328,7 @@ static irqreturn_t wil6210_irq_misc_thread(int irq, void *cookie) | |||
319 | if (isr & ISR_MISC_FW_ERROR) { | 328 | if (isr & ISR_MISC_FW_ERROR) { |
320 | wil_notify_fw_error(wil); | 329 | wil_notify_fw_error(wil); |
321 | isr &= ~ISR_MISC_FW_ERROR; | 330 | isr &= ~ISR_MISC_FW_ERROR; |
331 | wil_fw_error_recovery(wil); | ||
322 | } | 332 | } |
323 | 333 | ||
324 | if (isr & ISR_MISC_MBOX_EVT) { | 334 | if (isr & ISR_MISC_MBOX_EVT) { |
@@ -493,6 +503,23 @@ free0: | |||
493 | 503 | ||
494 | return rc; | 504 | return rc; |
495 | } | 505 | } |
506 | /* can't use wil_ioread32_and_clear because ICC value is not ser yet */ | ||
507 | static inline void wil_clear32(void __iomem *addr) | ||
508 | { | ||
509 | u32 x = ioread32(addr); | ||
510 | |||
511 | iowrite32(x, addr); | ||
512 | } | ||
513 | |||
514 | void wil6210_clear_irq(struct wil6210_priv *wil) | ||
515 | { | ||
516 | wil_clear32(wil->csr + HOSTADDR(RGF_DMA_EP_RX_ICR) + | ||
517 | offsetof(struct RGF_ICR, ICR)); | ||
518 | wil_clear32(wil->csr + HOSTADDR(RGF_DMA_EP_TX_ICR) + | ||
519 | offsetof(struct RGF_ICR, ICR)); | ||
520 | wil_clear32(wil->csr + HOSTADDR(RGF_DMA_EP_MISC_ICR) + | ||
521 | offsetof(struct RGF_ICR, ICR)); | ||
522 | } | ||
496 | 523 | ||
497 | int wil6210_init_irq(struct wil6210_priv *wil, int irq) | 524 | int wil6210_init_irq(struct wil6210_priv *wil, int irq) |
498 | { | 525 | { |
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 41c362dee032..95f4efe9ef37 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c | |||
@@ -21,6 +21,10 @@ | |||
21 | #include "wil6210.h" | 21 | #include "wil6210.h" |
22 | #include "txrx.h" | 22 | #include "txrx.h" |
23 | 23 | ||
24 | static bool no_fw_recovery; | ||
25 | module_param(no_fw_recovery, bool, S_IRUGO | S_IWUSR); | ||
26 | MODULE_PARM_DESC(no_fw_recovery, " disable FW error recovery"); | ||
27 | |||
24 | /* | 28 | /* |
25 | * Due to a hardware issue, | 29 | * Due to a hardware issue, |
26 | * one has to read/write to/from NIC in 32-bit chunks; | 30 | * one has to read/write to/from NIC in 32-bit chunks; |
@@ -59,6 +63,7 @@ static void wil_disconnect_cid(struct wil6210_priv *wil, int cid) | |||
59 | uint i; | 63 | uint i; |
60 | struct wil_sta_info *sta = &wil->sta[cid]; | 64 | struct wil_sta_info *sta = &wil->sta[cid]; |
61 | 65 | ||
66 | sta->data_port_open = false; | ||
62 | if (sta->status != wil_sta_unused) { | 67 | if (sta->status != wil_sta_unused) { |
63 | wmi_disconnect_sta(wil, sta->addr, WLAN_REASON_DEAUTH_LEAVING); | 68 | wmi_disconnect_sta(wil, sta->addr, WLAN_REASON_DEAUTH_LEAVING); |
64 | sta->status = wil_sta_unused; | 69 | sta->status = wil_sta_unused; |
@@ -112,8 +117,6 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, void *bssid) | |||
112 | GFP_KERNEL); | 117 | GFP_KERNEL); |
113 | } | 118 | } |
114 | clear_bit(wil_status_fwconnecting, &wil->status); | 119 | clear_bit(wil_status_fwconnecting, &wil->status); |
115 | wil_dbg_misc(wil, "clear_bit(wil_status_dontscan)\n"); | ||
116 | clear_bit(wil_status_dontscan, &wil->status); | ||
117 | break; | 120 | break; |
118 | default: | 121 | default: |
119 | /* AP-like interface and monitor: | 122 | /* AP-like interface and monitor: |
@@ -130,7 +133,9 @@ static void wil_disconnect_worker(struct work_struct *work) | |||
130 | struct wil6210_priv *wil = container_of(work, | 133 | struct wil6210_priv *wil = container_of(work, |
131 | struct wil6210_priv, disconnect_worker); | 134 | struct wil6210_priv, disconnect_worker); |
132 | 135 | ||
136 | mutex_lock(&wil->mutex); | ||
133 | _wil6210_disconnect(wil, NULL); | 137 | _wil6210_disconnect(wil, NULL); |
138 | mutex_unlock(&wil->mutex); | ||
134 | } | 139 | } |
135 | 140 | ||
136 | static void wil_connect_timer_fn(ulong x) | 141 | static void wil_connect_timer_fn(ulong x) |
@@ -145,6 +150,38 @@ static void wil_connect_timer_fn(ulong x) | |||
145 | schedule_work(&wil->disconnect_worker); | 150 | schedule_work(&wil->disconnect_worker); |
146 | } | 151 | } |
147 | 152 | ||
153 | static void wil_fw_error_worker(struct work_struct *work) | ||
154 | { | ||
155 | struct wil6210_priv *wil = container_of(work, | ||
156 | struct wil6210_priv, fw_error_worker); | ||
157 | struct wireless_dev *wdev = wil->wdev; | ||
158 | |||
159 | wil_dbg_misc(wil, "fw error worker\n"); | ||
160 | |||
161 | if (no_fw_recovery) | ||
162 | return; | ||
163 | |||
164 | mutex_lock(&wil->mutex); | ||
165 | switch (wdev->iftype) { | ||
166 | case NL80211_IFTYPE_STATION: | ||
167 | case NL80211_IFTYPE_P2P_CLIENT: | ||
168 | case NL80211_IFTYPE_MONITOR: | ||
169 | wil_info(wil, "fw error recovery started...\n"); | ||
170 | wil_reset(wil); | ||
171 | |||
172 | /* need to re-allocate Rx ring after reset */ | ||
173 | wil_rx_init(wil); | ||
174 | break; | ||
175 | case NL80211_IFTYPE_AP: | ||
176 | case NL80211_IFTYPE_P2P_GO: | ||
177 | /* recovery in these modes is done by upper layers */ | ||
178 | break; | ||
179 | default: | ||
180 | break; | ||
181 | } | ||
182 | mutex_unlock(&wil->mutex); | ||
183 | } | ||
184 | |||
148 | static int wil_find_free_vring(struct wil6210_priv *wil) | 185 | static int wil_find_free_vring(struct wil6210_priv *wil) |
149 | { | 186 | { |
150 | int i; | 187 | int i; |
@@ -197,6 +234,7 @@ int wil_priv_init(struct wil6210_priv *wil) | |||
197 | INIT_WORK(&wil->connect_worker, wil_connect_worker); | 234 | INIT_WORK(&wil->connect_worker, wil_connect_worker); |
198 | INIT_WORK(&wil->disconnect_worker, wil_disconnect_worker); | 235 | INIT_WORK(&wil->disconnect_worker, wil_disconnect_worker); |
199 | INIT_WORK(&wil->wmi_event_worker, wmi_event_worker); | 236 | INIT_WORK(&wil->wmi_event_worker, wmi_event_worker); |
237 | INIT_WORK(&wil->fw_error_worker, wil_fw_error_worker); | ||
200 | 238 | ||
201 | INIT_LIST_HEAD(&wil->pending_wmi_ev); | 239 | INIT_LIST_HEAD(&wil->pending_wmi_ev); |
202 | spin_lock_init(&wil->wmi_ev_lock); | 240 | spin_lock_init(&wil->wmi_ev_lock); |
@@ -223,7 +261,10 @@ void wil6210_disconnect(struct wil6210_priv *wil, void *bssid) | |||
223 | void wil_priv_deinit(struct wil6210_priv *wil) | 261 | void wil_priv_deinit(struct wil6210_priv *wil) |
224 | { | 262 | { |
225 | cancel_work_sync(&wil->disconnect_worker); | 263 | cancel_work_sync(&wil->disconnect_worker); |
264 | cancel_work_sync(&wil->fw_error_worker); | ||
265 | mutex_lock(&wil->mutex); | ||
226 | wil6210_disconnect(wil, NULL); | 266 | wil6210_disconnect(wil, NULL); |
267 | mutex_unlock(&wil->mutex); | ||
227 | wmi_event_flush(wil); | 268 | wmi_event_flush(wil); |
228 | destroy_workqueue(wil->wmi_wq_conn); | 269 | destroy_workqueue(wil->wmi_wq_conn); |
229 | destroy_workqueue(wil->wmi_wq); | 270 | destroy_workqueue(wil->wmi_wq); |
@@ -231,40 +272,78 @@ void wil_priv_deinit(struct wil6210_priv *wil) | |||
231 | 272 | ||
232 | static void wil_target_reset(struct wil6210_priv *wil) | 273 | static void wil_target_reset(struct wil6210_priv *wil) |
233 | { | 274 | { |
275 | int delay = 0; | ||
276 | u32 hw_state; | ||
277 | u32 rev_id; | ||
278 | |||
234 | wil_dbg_misc(wil, "Resetting...\n"); | 279 | wil_dbg_misc(wil, "Resetting...\n"); |
235 | 280 | ||
281 | /* register read */ | ||
282 | #define R(a) ioread32(wil->csr + HOSTADDR(a)) | ||
236 | /* register write */ | 283 | /* register write */ |
237 | #define W(a, v) iowrite32(v, wil->csr + HOSTADDR(a)) | 284 | #define W(a, v) iowrite32(v, wil->csr + HOSTADDR(a)) |
238 | /* register set = read, OR, write */ | 285 | /* register set = read, OR, write */ |
239 | #define S(a, v) iowrite32(ioread32(wil->csr + HOSTADDR(a)) | v, \ | 286 | #define S(a, v) W(a, R(a) | v) |
240 | wil->csr + HOSTADDR(a)) | 287 | /* register clear = read, AND with inverted, write */ |
288 | #define C(a, v) W(a, R(a) & ~v) | ||
241 | 289 | ||
290 | wil->hw_version = R(RGF_USER_FW_REV_ID); | ||
291 | rev_id = wil->hw_version & 0xff; | ||
242 | /* hpal_perst_from_pad_src_n_mask */ | 292 | /* hpal_perst_from_pad_src_n_mask */ |
243 | S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT(6)); | 293 | S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT(6)); |
244 | /* car_perst_rst_src_n_mask */ | 294 | /* car_perst_rst_src_n_mask */ |
245 | S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT(7)); | 295 | S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT(7)); |
296 | wmb(); /* order is important here */ | ||
246 | 297 | ||
247 | W(RGF_USER_MAC_CPU_0, BIT(1)); /* mac_cpu_man_rst */ | 298 | W(RGF_USER_MAC_CPU_0, BIT(1)); /* mac_cpu_man_rst */ |
248 | W(RGF_USER_USER_CPU_0, BIT(1)); /* user_cpu_man_rst */ | 299 | W(RGF_USER_USER_CPU_0, BIT(1)); /* user_cpu_man_rst */ |
300 | wmb(); /* order is important here */ | ||
249 | 301 | ||
250 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0xFE000000); | 302 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0xFE000000); |
251 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0x0000003F); | 303 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0x0000003F); |
252 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000170); | 304 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000170); |
253 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xFFE7FC00); | 305 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xFFE7FC00); |
306 | wmb(); /* order is important here */ | ||
254 | 307 | ||
255 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0); | 308 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0); |
256 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0); | 309 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0); |
257 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0); | 310 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0); |
258 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0); | 311 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0); |
312 | wmb(); /* order is important here */ | ||
259 | 313 | ||
260 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000001); | 314 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000001); |
261 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00000080); | 315 | if (rev_id == 1) { |
316 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00000080); | ||
317 | } else { | ||
318 | W(RGF_PCIE_LOS_COUNTER_CTL, BIT(6) | BIT(8)); | ||
319 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00008000); | ||
320 | } | ||
262 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0); | 321 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0); |
322 | wmb(); /* order is important here */ | ||
323 | |||
324 | /* wait until device ready */ | ||
325 | do { | ||
326 | msleep(1); | ||
327 | hw_state = R(RGF_USER_HW_MACHINE_STATE); | ||
328 | if (delay++ > 100) { | ||
329 | wil_err(wil, "Reset not completed, hw_state 0x%08x\n", | ||
330 | hw_state); | ||
331 | return; | ||
332 | } | ||
333 | } while (hw_state != HW_MACHINE_BOOT_DONE); | ||
334 | |||
335 | if (rev_id == 2) | ||
336 | W(RGF_PCIE_LOS_COUNTER_CTL, BIT(8)); | ||
263 | 337 | ||
264 | wil_dbg_misc(wil, "Reset completed\n"); | 338 | C(RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_RST_PWGD); |
339 | wmb(); /* order is important here */ | ||
265 | 340 | ||
341 | wil_dbg_misc(wil, "Reset completed in %d ms\n", delay); | ||
342 | |||
343 | #undef R | ||
266 | #undef W | 344 | #undef W |
267 | #undef S | 345 | #undef S |
346 | #undef C | ||
268 | } | 347 | } |
269 | 348 | ||
270 | void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r) | 349 | void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r) |
@@ -299,11 +378,24 @@ int wil_reset(struct wil6210_priv *wil) | |||
299 | { | 378 | { |
300 | int rc; | 379 | int rc; |
301 | 380 | ||
381 | WARN_ON(!mutex_is_locked(&wil->mutex)); | ||
382 | |||
302 | cancel_work_sync(&wil->disconnect_worker); | 383 | cancel_work_sync(&wil->disconnect_worker); |
303 | wil6210_disconnect(wil, NULL); | 384 | wil6210_disconnect(wil, NULL); |
304 | 385 | ||
386 | wil->status = 0; /* prevent NAPI from being scheduled */ | ||
387 | if (test_bit(wil_status_napi_en, &wil->status)) { | ||
388 | napi_synchronize(&wil->napi_rx); | ||
389 | } | ||
390 | |||
391 | if (wil->scan_request) { | ||
392 | wil_dbg_misc(wil, "Abort scan_request 0x%p\n", | ||
393 | wil->scan_request); | ||
394 | cfg80211_scan_done(wil->scan_request, true); | ||
395 | wil->scan_request = NULL; | ||
396 | } | ||
397 | |||
305 | wil6210_disable_irq(wil); | 398 | wil6210_disable_irq(wil); |
306 | wil->status = 0; | ||
307 | 399 | ||
308 | wmi_event_flush(wil); | 400 | wmi_event_flush(wil); |
309 | 401 | ||
@@ -313,6 +405,8 @@ int wil_reset(struct wil6210_priv *wil) | |||
313 | /* TODO: put MAC in reset */ | 405 | /* TODO: put MAC in reset */ |
314 | wil_target_reset(wil); | 406 | wil_target_reset(wil); |
315 | 407 | ||
408 | wil_rx_fini(wil); | ||
409 | |||
316 | /* init after reset */ | 410 | /* init after reset */ |
317 | wil->pending_connect_cid = -1; | 411 | wil->pending_connect_cid = -1; |
318 | reinit_completion(&wil->wmi_ready); | 412 | reinit_completion(&wil->wmi_ready); |
@@ -326,6 +420,11 @@ int wil_reset(struct wil6210_priv *wil) | |||
326 | return rc; | 420 | return rc; |
327 | } | 421 | } |
328 | 422 | ||
423 | void wil_fw_error_recovery(struct wil6210_priv *wil) | ||
424 | { | ||
425 | wil_dbg_misc(wil, "starting fw error recovery\n"); | ||
426 | schedule_work(&wil->fw_error_worker); | ||
427 | } | ||
329 | 428 | ||
330 | void wil_link_on(struct wil6210_priv *wil) | 429 | void wil_link_on(struct wil6210_priv *wil) |
331 | { | 430 | { |
@@ -353,6 +452,8 @@ static int __wil_up(struct wil6210_priv *wil) | |||
353 | struct wireless_dev *wdev = wil->wdev; | 452 | struct wireless_dev *wdev = wil->wdev; |
354 | int rc; | 453 | int rc; |
355 | 454 | ||
455 | WARN_ON(!mutex_is_locked(&wil->mutex)); | ||
456 | |||
356 | rc = wil_reset(wil); | 457 | rc = wil_reset(wil); |
357 | if (rc) | 458 | if (rc) |
358 | return rc; | 459 | return rc; |
@@ -394,6 +495,7 @@ static int __wil_up(struct wil6210_priv *wil) | |||
394 | 495 | ||
395 | napi_enable(&wil->napi_rx); | 496 | napi_enable(&wil->napi_rx); |
396 | napi_enable(&wil->napi_tx); | 497 | napi_enable(&wil->napi_tx); |
498 | set_bit(wil_status_napi_en, &wil->status); | ||
397 | 499 | ||
398 | return 0; | 500 | return 0; |
399 | } | 501 | } |
@@ -411,6 +513,9 @@ int wil_up(struct wil6210_priv *wil) | |||
411 | 513 | ||
412 | static int __wil_down(struct wil6210_priv *wil) | 514 | static int __wil_down(struct wil6210_priv *wil) |
413 | { | 515 | { |
516 | WARN_ON(!mutex_is_locked(&wil->mutex)); | ||
517 | |||
518 | clear_bit(wil_status_napi_en, &wil->status); | ||
414 | napi_disable(&wil->napi_rx); | 519 | napi_disable(&wil->napi_rx); |
415 | napi_disable(&wil->napi_tx); | 520 | napi_disable(&wil->napi_tx); |
416 | 521 | ||
diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c index 717178f09aa8..fdcaeb820e75 100644 --- a/drivers/net/wireless/ath/wil6210/netdev.c +++ b/drivers/net/wireless/ath/wil6210/netdev.c | |||
@@ -127,8 +127,9 @@ void *wil_if_alloc(struct device *dev, void __iomem *csr) | |||
127 | 127 | ||
128 | ndev->netdev_ops = &wil_netdev_ops; | 128 | ndev->netdev_ops = &wil_netdev_ops; |
129 | ndev->ieee80211_ptr = wdev; | 129 | ndev->ieee80211_ptr = wdev; |
130 | ndev->hw_features = NETIF_F_HW_CSUM | NETIF_F_RXCSUM; | 130 | ndev->hw_features = NETIF_F_HW_CSUM | NETIF_F_RXCSUM | |
131 | ndev->features |= NETIF_F_HW_CSUM | NETIF_F_RXCSUM; | 131 | NETIF_F_SG | NETIF_F_GRO; |
132 | ndev->features |= ndev->hw_features; | ||
132 | SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy)); | 133 | SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy)); |
133 | wdev->netdev = ndev; | 134 | wdev->netdev = ndev; |
134 | 135 | ||
diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c index e1c8cc4a4b92..f1e1bb338d68 100644 --- a/drivers/net/wireless/ath/wil6210/pcie_bus.c +++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c | |||
@@ -68,10 +68,14 @@ static int wil_if_pcie_enable(struct wil6210_priv *wil) | |||
68 | goto stop_master; | 68 | goto stop_master; |
69 | 69 | ||
70 | /* need reset here to obtain MAC */ | 70 | /* need reset here to obtain MAC */ |
71 | mutex_lock(&wil->mutex); | ||
71 | rc = wil_reset(wil); | 72 | rc = wil_reset(wil); |
73 | mutex_unlock(&wil->mutex); | ||
72 | if (rc) | 74 | if (rc) |
73 | goto release_irq; | 75 | goto release_irq; |
74 | 76 | ||
77 | wil_info(wil, "HW version: 0x%08x\n", wil->hw_version); | ||
78 | |||
75 | return 0; | 79 | return 0; |
76 | 80 | ||
77 | release_irq: | 81 | release_irq: |
@@ -149,6 +153,7 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
149 | pci_set_drvdata(pdev, wil); | 153 | pci_set_drvdata(pdev, wil); |
150 | wil->pdev = pdev; | 154 | wil->pdev = pdev; |
151 | 155 | ||
156 | wil6210_clear_irq(wil); | ||
152 | /* FW should raise IRQ when ready */ | 157 | /* FW should raise IRQ when ready */ |
153 | rc = wil_if_pcie_enable(wil); | 158 | rc = wil_if_pcie_enable(wil); |
154 | if (rc) { | 159 | if (rc) { |
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 092081e209da..c8c547457eb4 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c | |||
@@ -104,6 +104,23 @@ static int wil_vring_alloc(struct wil6210_priv *wil, struct vring *vring) | |||
104 | return 0; | 104 | return 0; |
105 | } | 105 | } |
106 | 106 | ||
107 | static void wil_txdesc_unmap(struct device *dev, struct vring_tx_desc *d, | ||
108 | struct wil_ctx *ctx) | ||
109 | { | ||
110 | dma_addr_t pa = wil_desc_addr(&d->dma.addr); | ||
111 | u16 dmalen = le16_to_cpu(d->dma.length); | ||
112 | switch (ctx->mapped_as) { | ||
113 | case wil_mapped_as_single: | ||
114 | dma_unmap_single(dev, pa, dmalen, DMA_TO_DEVICE); | ||
115 | break; | ||
116 | case wil_mapped_as_page: | ||
117 | dma_unmap_page(dev, pa, dmalen, DMA_TO_DEVICE); | ||
118 | break; | ||
119 | default: | ||
120 | break; | ||
121 | } | ||
122 | } | ||
123 | |||
107 | static void wil_vring_free(struct wil6210_priv *wil, struct vring *vring, | 124 | static void wil_vring_free(struct wil6210_priv *wil, struct vring *vring, |
108 | int tx) | 125 | int tx) |
109 | { | 126 | { |
@@ -122,15 +139,7 @@ static void wil_vring_free(struct wil6210_priv *wil, struct vring *vring, | |||
122 | 139 | ||
123 | ctx = &vring->ctx[vring->swtail]; | 140 | ctx = &vring->ctx[vring->swtail]; |
124 | *d = *_d; | 141 | *d = *_d; |
125 | pa = wil_desc_addr(&d->dma.addr); | 142 | wil_txdesc_unmap(dev, d, ctx); |
126 | dmalen = le16_to_cpu(d->dma.length); | ||
127 | if (vring->ctx[vring->swtail].mapped_as_page) { | ||
128 | dma_unmap_page(dev, pa, dmalen, | ||
129 | DMA_TO_DEVICE); | ||
130 | } else { | ||
131 | dma_unmap_single(dev, pa, dmalen, | ||
132 | DMA_TO_DEVICE); | ||
133 | } | ||
134 | if (ctx->skb) | 143 | if (ctx->skb) |
135 | dev_kfree_skb_any(ctx->skb); | 144 | dev_kfree_skb_any(ctx->skb); |
136 | vring->swtail = wil_vring_next_tail(vring); | 145 | vring->swtail = wil_vring_next_tail(vring); |
@@ -479,7 +488,7 @@ static int wil_rx_refill(struct wil6210_priv *wil, int count) | |||
479 | */ | 488 | */ |
480 | void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev) | 489 | void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev) |
481 | { | 490 | { |
482 | int rc; | 491 | gro_result_t rc; |
483 | struct wil6210_priv *wil = ndev_to_wil(ndev); | 492 | struct wil6210_priv *wil = ndev_to_wil(ndev); |
484 | unsigned int len = skb->len; | 493 | unsigned int len = skb->len; |
485 | struct vring_rx_desc *d = wil_skb_rxdesc(skb); | 494 | struct vring_rx_desc *d = wil_skb_rxdesc(skb); |
@@ -488,17 +497,17 @@ void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev) | |||
488 | 497 | ||
489 | skb_orphan(skb); | 498 | skb_orphan(skb); |
490 | 499 | ||
491 | rc = netif_receive_skb(skb); | 500 | rc = napi_gro_receive(&wil->napi_rx, skb); |
492 | 501 | ||
493 | if (likely(rc == NET_RX_SUCCESS)) { | 502 | if (unlikely(rc == GRO_DROP)) { |
503 | ndev->stats.rx_dropped++; | ||
504 | stats->rx_dropped++; | ||
505 | wil_dbg_txrx(wil, "Rx drop %d bytes\n", len); | ||
506 | } else { | ||
494 | ndev->stats.rx_packets++; | 507 | ndev->stats.rx_packets++; |
495 | stats->rx_packets++; | 508 | stats->rx_packets++; |
496 | ndev->stats.rx_bytes += len; | 509 | ndev->stats.rx_bytes += len; |
497 | stats->rx_bytes += len; | 510 | stats->rx_bytes += len; |
498 | |||
499 | } else { | ||
500 | ndev->stats.rx_dropped++; | ||
501 | stats->rx_dropped++; | ||
502 | } | 511 | } |
503 | } | 512 | } |
504 | 513 | ||
@@ -548,6 +557,11 @@ int wil_rx_init(struct wil6210_priv *wil) | |||
548 | struct vring *vring = &wil->vring_rx; | 557 | struct vring *vring = &wil->vring_rx; |
549 | int rc; | 558 | int rc; |
550 | 559 | ||
560 | if (vring->va) { | ||
561 | wil_err(wil, "Rx ring already allocated\n"); | ||
562 | return -EINVAL; | ||
563 | } | ||
564 | |||
551 | vring->size = WIL6210_RX_RING_SIZE; | 565 | vring->size = WIL6210_RX_RING_SIZE; |
552 | rc = wil_vring_alloc(wil, vring); | 566 | rc = wil_vring_alloc(wil, vring); |
553 | if (rc) | 567 | if (rc) |
@@ -588,7 +602,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, | |||
588 | .ring_size = cpu_to_le16(size), | 602 | .ring_size = cpu_to_le16(size), |
589 | }, | 603 | }, |
590 | .ringid = id, | 604 | .ringid = id, |
591 | .cidxtid = (cid & 0xf) | ((tid & 0xf) << 4), | 605 | .cidxtid = mk_cidxtid(cid, tid), |
592 | .encap_trans_type = WMI_VRING_ENC_TYPE_802_3, | 606 | .encap_trans_type = WMI_VRING_ENC_TYPE_802_3, |
593 | .mac_ctrl = 0, | 607 | .mac_ctrl = 0, |
594 | .to_resolution = 0, | 608 | .to_resolution = 0, |
@@ -604,6 +618,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, | |||
604 | struct wmi_vring_cfg_done_event cmd; | 618 | struct wmi_vring_cfg_done_event cmd; |
605 | } __packed reply; | 619 | } __packed reply; |
606 | struct vring *vring = &wil->vring_tx[id]; | 620 | struct vring *vring = &wil->vring_tx[id]; |
621 | struct vring_tx_data *txdata = &wil->vring_tx_data[id]; | ||
607 | 622 | ||
608 | if (vring->va) { | 623 | if (vring->va) { |
609 | wil_err(wil, "Tx ring [%d] already allocated\n", id); | 624 | wil_err(wil, "Tx ring [%d] already allocated\n", id); |
@@ -611,6 +626,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, | |||
611 | goto out; | 626 | goto out; |
612 | } | 627 | } |
613 | 628 | ||
629 | memset(txdata, 0, sizeof(*txdata)); | ||
614 | vring->size = size; | 630 | vring->size = size; |
615 | rc = wil_vring_alloc(wil, vring); | 631 | rc = wil_vring_alloc(wil, vring); |
616 | if (rc) | 632 | if (rc) |
@@ -634,6 +650,8 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, | |||
634 | } | 650 | } |
635 | vring->hwtail = le32_to_cpu(reply.cmd.tx_vring_tail_ptr); | 651 | vring->hwtail = le32_to_cpu(reply.cmd.tx_vring_tail_ptr); |
636 | 652 | ||
653 | txdata->enabled = 1; | ||
654 | |||
637 | return 0; | 655 | return 0; |
638 | out_free: | 656 | out_free: |
639 | wil_vring_free(wil, vring, 1); | 657 | wil_vring_free(wil, vring, 1); |
@@ -646,9 +664,16 @@ void wil_vring_fini_tx(struct wil6210_priv *wil, int id) | |||
646 | { | 664 | { |
647 | struct vring *vring = &wil->vring_tx[id]; | 665 | struct vring *vring = &wil->vring_tx[id]; |
648 | 666 | ||
667 | WARN_ON(!mutex_is_locked(&wil->mutex)); | ||
668 | |||
649 | if (!vring->va) | 669 | if (!vring->va) |
650 | return; | 670 | return; |
651 | 671 | ||
672 | /* make sure NAPI won't touch this vring */ | ||
673 | wil->vring_tx_data[id].enabled = 0; | ||
674 | if (test_bit(wil_status_napi_en, &wil->status)) | ||
675 | napi_synchronize(&wil->napi_tx); | ||
676 | |||
652 | wil_vring_free(wil, vring, 1); | 677 | wil_vring_free(wil, vring, 1); |
653 | } | 678 | } |
654 | 679 | ||
@@ -662,6 +687,10 @@ static struct vring *wil_find_tx_vring(struct wil6210_priv *wil, | |||
662 | if (cid < 0) | 687 | if (cid < 0) |
663 | return NULL; | 688 | return NULL; |
664 | 689 | ||
690 | if (!wil->sta[cid].data_port_open && | ||
691 | (skb->protocol != cpu_to_be16(ETH_P_PAE))) | ||
692 | return NULL; | ||
693 | |||
665 | /* TODO: fix for multiple TID */ | 694 | /* TODO: fix for multiple TID */ |
666 | for (i = 0; i < ARRAY_SIZE(wil->vring2cid_tid); i++) { | 695 | for (i = 0; i < ARRAY_SIZE(wil->vring2cid_tid); i++) { |
667 | if (wil->vring2cid_tid[i][0] == cid) { | 696 | if (wil->vring2cid_tid[i][0] == cid) { |
@@ -700,12 +729,19 @@ static struct vring *wil_tx_bcast(struct wil6210_priv *wil, | |||
700 | struct vring *v, *v2; | 729 | struct vring *v, *v2; |
701 | struct sk_buff *skb2; | 730 | struct sk_buff *skb2; |
702 | int i; | 731 | int i; |
732 | u8 cid; | ||
703 | 733 | ||
704 | /* find 1-st vring */ | 734 | /* find 1-st vring eligible for data */ |
705 | for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { | 735 | for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { |
706 | v = &wil->vring_tx[i]; | 736 | v = &wil->vring_tx[i]; |
707 | if (v->va) | 737 | if (!v->va) |
708 | goto found; | 738 | continue; |
739 | |||
740 | cid = wil->vring2cid_tid[i][0]; | ||
741 | if (!wil->sta[cid].data_port_open) | ||
742 | continue; | ||
743 | |||
744 | goto found; | ||
709 | } | 745 | } |
710 | 746 | ||
711 | wil_err(wil, "Tx while no vrings active?\n"); | 747 | wil_err(wil, "Tx while no vrings active?\n"); |
@@ -721,6 +757,10 @@ found: | |||
721 | v2 = &wil->vring_tx[i]; | 757 | v2 = &wil->vring_tx[i]; |
722 | if (!v2->va) | 758 | if (!v2->va) |
723 | continue; | 759 | continue; |
760 | cid = wil->vring2cid_tid[i][0]; | ||
761 | if (!wil->sta[cid].data_port_open) | ||
762 | continue; | ||
763 | |||
724 | skb2 = skb_copy(skb, GFP_ATOMIC); | 764 | skb2 = skb_copy(skb, GFP_ATOMIC); |
725 | if (skb2) { | 765 | if (skb2) { |
726 | wil_dbg_txrx(wil, "BCAST DUP -> ring %d\n", i); | 766 | wil_dbg_txrx(wil, "BCAST DUP -> ring %d\n", i); |
@@ -759,6 +799,13 @@ static int wil_tx_desc_map(struct vring_tx_desc *d, dma_addr_t pa, u32 len, | |||
759 | return 0; | 799 | return 0; |
760 | } | 800 | } |
761 | 801 | ||
802 | static inline | ||
803 | void wil_tx_desc_set_nr_frags(struct vring_tx_desc *d, int nr_frags) | ||
804 | { | ||
805 | d->mac.d[2] |= ((nr_frags + 1) << | ||
806 | MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_POS); | ||
807 | } | ||
808 | |||
762 | static int wil_tx_desc_offload_cksum_set(struct wil6210_priv *wil, | 809 | static int wil_tx_desc_offload_cksum_set(struct wil6210_priv *wil, |
763 | struct vring_tx_desc *d, | 810 | struct vring_tx_desc *d, |
764 | struct sk_buff *skb) | 811 | struct sk_buff *skb) |
@@ -823,8 +870,6 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | |||
823 | 870 | ||
824 | wil_dbg_txrx(wil, "%s()\n", __func__); | 871 | wil_dbg_txrx(wil, "%s()\n", __func__); |
825 | 872 | ||
826 | if (avail < vring->size/8) | ||
827 | netif_tx_stop_all_queues(wil_to_ndev(wil)); | ||
828 | if (avail < 1 + nr_frags) { | 873 | if (avail < 1 + nr_frags) { |
829 | wil_err(wil, "Tx ring full. No space for %d fragments\n", | 874 | wil_err(wil, "Tx ring full. No space for %d fragments\n", |
830 | 1 + nr_frags); | 875 | 1 + nr_frags); |
@@ -842,6 +887,7 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | |||
842 | 887 | ||
843 | if (unlikely(dma_mapping_error(dev, pa))) | 888 | if (unlikely(dma_mapping_error(dev, pa))) |
844 | return -EINVAL; | 889 | return -EINVAL; |
890 | vring->ctx[i].mapped_as = wil_mapped_as_single; | ||
845 | /* 1-st segment */ | 891 | /* 1-st segment */ |
846 | wil_tx_desc_map(d, pa, skb_headlen(skb), vring_index); | 892 | wil_tx_desc_map(d, pa, skb_headlen(skb), vring_index); |
847 | /* Process TCP/UDP checksum offloading */ | 893 | /* Process TCP/UDP checksum offloading */ |
@@ -851,8 +897,8 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | |||
851 | goto dma_error; | 897 | goto dma_error; |
852 | } | 898 | } |
853 | 899 | ||
854 | d->mac.d[2] |= ((nr_frags + 1) << | 900 | vring->ctx[i].nr_frags = nr_frags; |
855 | MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_POS); | 901 | wil_tx_desc_set_nr_frags(d, nr_frags); |
856 | if (nr_frags) | 902 | if (nr_frags) |
857 | *_d = *d; | 903 | *_d = *d; |
858 | 904 | ||
@@ -867,8 +913,13 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | |||
867 | DMA_TO_DEVICE); | 913 | DMA_TO_DEVICE); |
868 | if (unlikely(dma_mapping_error(dev, pa))) | 914 | if (unlikely(dma_mapping_error(dev, pa))) |
869 | goto dma_error; | 915 | goto dma_error; |
916 | vring->ctx[i].mapped_as = wil_mapped_as_page; | ||
870 | wil_tx_desc_map(d, pa, len, vring_index); | 917 | wil_tx_desc_map(d, pa, len, vring_index); |
871 | vring->ctx[i].mapped_as_page = 1; | 918 | /* no need to check return code - |
919 | * if it succeeded for 1-st descriptor, | ||
920 | * it will succeed here too | ||
921 | */ | ||
922 | wil_tx_desc_offload_cksum_set(wil, d, skb); | ||
872 | *_d = *d; | 923 | *_d = *d; |
873 | } | 924 | } |
874 | /* for the last seg only */ | 925 | /* for the last seg only */ |
@@ -897,7 +948,6 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | |||
897 | /* unmap what we have mapped */ | 948 | /* unmap what we have mapped */ |
898 | nr_frags = f + 1; /* frags mapped + one for skb head */ | 949 | nr_frags = f + 1; /* frags mapped + one for skb head */ |
899 | for (f = 0; f < nr_frags; f++) { | 950 | for (f = 0; f < nr_frags; f++) { |
900 | u16 dmalen; | ||
901 | struct wil_ctx *ctx; | 951 | struct wil_ctx *ctx; |
902 | 952 | ||
903 | i = (swhead + f) % vring->size; | 953 | i = (swhead + f) % vring->size; |
@@ -905,12 +955,7 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | |||
905 | _d = &(vring->va[i].tx); | 955 | _d = &(vring->va[i].tx); |
906 | *d = *_d; | 956 | *d = *_d; |
907 | _d->dma.status = TX_DMA_STATUS_DU; | 957 | _d->dma.status = TX_DMA_STATUS_DU; |
908 | pa = wil_desc_addr(&d->dma.addr); | 958 | wil_txdesc_unmap(dev, d, ctx); |
909 | dmalen = le16_to_cpu(d->dma.length); | ||
910 | if (ctx->mapped_as_page) | ||
911 | dma_unmap_page(dev, pa, dmalen, DMA_TO_DEVICE); | ||
912 | else | ||
913 | dma_unmap_single(dev, pa, dmalen, DMA_TO_DEVICE); | ||
914 | 959 | ||
915 | if (ctx->skb) | 960 | if (ctx->skb) |
916 | dev_kfree_skb_any(ctx->skb); | 961 | dev_kfree_skb_any(ctx->skb); |
@@ -927,11 +972,15 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) | |||
927 | struct wil6210_priv *wil = ndev_to_wil(ndev); | 972 | struct wil6210_priv *wil = ndev_to_wil(ndev); |
928 | struct ethhdr *eth = (void *)skb->data; | 973 | struct ethhdr *eth = (void *)skb->data; |
929 | struct vring *vring; | 974 | struct vring *vring; |
975 | static bool pr_once_fw; | ||
930 | int rc; | 976 | int rc; |
931 | 977 | ||
932 | wil_dbg_txrx(wil, "%s()\n", __func__); | 978 | wil_dbg_txrx(wil, "%s()\n", __func__); |
933 | if (!test_bit(wil_status_fwready, &wil->status)) { | 979 | if (!test_bit(wil_status_fwready, &wil->status)) { |
934 | wil_err(wil, "FW not ready\n"); | 980 | if (!pr_once_fw) { |
981 | wil_err(wil, "FW not ready\n"); | ||
982 | pr_once_fw = true; | ||
983 | } | ||
935 | goto drop; | 984 | goto drop; |
936 | } | 985 | } |
937 | if (!test_bit(wil_status_fwconnected, &wil->status)) { | 986 | if (!test_bit(wil_status_fwconnected, &wil->status)) { |
@@ -942,6 +991,7 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) | |||
942 | wil_err(wil, "Xmit in monitor mode not supported\n"); | 991 | wil_err(wil, "Xmit in monitor mode not supported\n"); |
943 | goto drop; | 992 | goto drop; |
944 | } | 993 | } |
994 | pr_once_fw = false; | ||
945 | 995 | ||
946 | /* find vring */ | 996 | /* find vring */ |
947 | if (is_unicast_ether_addr(eth->h_dest)) { | 997 | if (is_unicast_ether_addr(eth->h_dest)) { |
@@ -956,6 +1006,10 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) | |||
956 | /* set up vring entry */ | 1006 | /* set up vring entry */ |
957 | rc = wil_tx_vring(wil, vring, skb); | 1007 | rc = wil_tx_vring(wil, vring, skb); |
958 | 1008 | ||
1009 | /* do we still have enough room in the vring? */ | ||
1010 | if (wil_vring_avail_tx(vring) < vring->size/8) | ||
1011 | netif_tx_stop_all_queues(wil_to_ndev(wil)); | ||
1012 | |||
959 | switch (rc) { | 1013 | switch (rc) { |
960 | case 0: | 1014 | case 0: |
961 | /* statistics will be updated on the tx_complete */ | 1015 | /* statistics will be updated on the tx_complete */ |
@@ -985,69 +1039,82 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid) | |||
985 | struct net_device *ndev = wil_to_ndev(wil); | 1039 | struct net_device *ndev = wil_to_ndev(wil); |
986 | struct device *dev = wil_to_dev(wil); | 1040 | struct device *dev = wil_to_dev(wil); |
987 | struct vring *vring = &wil->vring_tx[ringid]; | 1041 | struct vring *vring = &wil->vring_tx[ringid]; |
1042 | struct vring_tx_data *txdata = &wil->vring_tx_data[ringid]; | ||
988 | int done = 0; | 1043 | int done = 0; |
989 | int cid = wil->vring2cid_tid[ringid][0]; | 1044 | int cid = wil->vring2cid_tid[ringid][0]; |
990 | struct wil_net_stats *stats = &wil->sta[cid].stats; | 1045 | struct wil_net_stats *stats = &wil->sta[cid].stats; |
1046 | volatile struct vring_tx_desc *_d; | ||
991 | 1047 | ||
992 | if (!vring->va) { | 1048 | if (!vring->va) { |
993 | wil_err(wil, "Tx irq[%d]: vring not initialized\n", ringid); | 1049 | wil_err(wil, "Tx irq[%d]: vring not initialized\n", ringid); |
994 | return 0; | 1050 | return 0; |
995 | } | 1051 | } |
996 | 1052 | ||
1053 | if (!txdata->enabled) { | ||
1054 | wil_info(wil, "Tx irq[%d]: vring disabled\n", ringid); | ||
1055 | return 0; | ||
1056 | } | ||
1057 | |||
997 | wil_dbg_txrx(wil, "%s(%d)\n", __func__, ringid); | 1058 | wil_dbg_txrx(wil, "%s(%d)\n", __func__, ringid); |
998 | 1059 | ||
999 | while (!wil_vring_is_empty(vring)) { | 1060 | while (!wil_vring_is_empty(vring)) { |
1000 | volatile struct vring_tx_desc *_d = | 1061 | int new_swtail; |
1001 | &vring->va[vring->swtail].tx; | ||
1002 | struct vring_tx_desc dd, *d = ⅆ | ||
1003 | dma_addr_t pa; | ||
1004 | u16 dmalen; | ||
1005 | struct wil_ctx *ctx = &vring->ctx[vring->swtail]; | 1062 | struct wil_ctx *ctx = &vring->ctx[vring->swtail]; |
1006 | struct sk_buff *skb = ctx->skb; | 1063 | /** |
1007 | 1064 | * For the fragmented skb, HW will set DU bit only for the | |
1008 | *d = *_d; | 1065 | * last fragment. look for it |
1066 | */ | ||
1067 | int lf = (vring->swtail + ctx->nr_frags) % vring->size; | ||
1068 | /* TODO: check we are not past head */ | ||
1009 | 1069 | ||
1010 | if (!(d->dma.status & TX_DMA_STATUS_DU)) | 1070 | _d = &vring->va[lf].tx; |
1071 | if (!(_d->dma.status & TX_DMA_STATUS_DU)) | ||
1011 | break; | 1072 | break; |
1012 | 1073 | ||
1013 | dmalen = le16_to_cpu(d->dma.length); | 1074 | new_swtail = (lf + 1) % vring->size; |
1014 | trace_wil6210_tx_done(ringid, vring->swtail, dmalen, | 1075 | while (vring->swtail != new_swtail) { |
1015 | d->dma.error); | 1076 | struct vring_tx_desc dd, *d = ⅆ |
1016 | wil_dbg_txrx(wil, | 1077 | u16 dmalen; |
1017 | "Tx[%3d] : %d bytes, status 0x%02x err 0x%02x\n", | 1078 | struct wil_ctx *ctx = &vring->ctx[vring->swtail]; |
1018 | vring->swtail, dmalen, d->dma.status, | 1079 | struct sk_buff *skb = ctx->skb; |
1019 | d->dma.error); | 1080 | _d = &vring->va[vring->swtail].tx; |
1020 | wil_hex_dump_txrx("TxC ", DUMP_PREFIX_NONE, 32, 4, | 1081 | |
1021 | (const void *)d, sizeof(*d), false); | 1082 | *d = *_d; |
1022 | |||
1023 | pa = wil_desc_addr(&d->dma.addr); | ||
1024 | if (ctx->mapped_as_page) | ||
1025 | dma_unmap_page(dev, pa, dmalen, DMA_TO_DEVICE); | ||
1026 | else | ||
1027 | dma_unmap_single(dev, pa, dmalen, DMA_TO_DEVICE); | ||
1028 | |||
1029 | if (skb) { | ||
1030 | if (d->dma.error == 0) { | ||
1031 | ndev->stats.tx_packets++; | ||
1032 | stats->tx_packets++; | ||
1033 | ndev->stats.tx_bytes += skb->len; | ||
1034 | stats->tx_bytes += skb->len; | ||
1035 | } else { | ||
1036 | ndev->stats.tx_errors++; | ||
1037 | stats->tx_errors++; | ||
1038 | } | ||
1039 | 1083 | ||
1040 | dev_kfree_skb_any(skb); | 1084 | dmalen = le16_to_cpu(d->dma.length); |
1085 | trace_wil6210_tx_done(ringid, vring->swtail, dmalen, | ||
1086 | d->dma.error); | ||
1087 | wil_dbg_txrx(wil, | ||
1088 | "Tx[%3d] : %d bytes, status 0x%02x err 0x%02x\n", | ||
1089 | vring->swtail, dmalen, d->dma.status, | ||
1090 | d->dma.error); | ||
1091 | wil_hex_dump_txrx("TxC ", DUMP_PREFIX_NONE, 32, 4, | ||
1092 | (const void *)d, sizeof(*d), false); | ||
1093 | |||
1094 | wil_txdesc_unmap(dev, d, ctx); | ||
1095 | |||
1096 | if (skb) { | ||
1097 | if (d->dma.error == 0) { | ||
1098 | ndev->stats.tx_packets++; | ||
1099 | stats->tx_packets++; | ||
1100 | ndev->stats.tx_bytes += skb->len; | ||
1101 | stats->tx_bytes += skb->len; | ||
1102 | } else { | ||
1103 | ndev->stats.tx_errors++; | ||
1104 | stats->tx_errors++; | ||
1105 | } | ||
1106 | |||
1107 | dev_kfree_skb_any(skb); | ||
1108 | } | ||
1109 | memset(ctx, 0, sizeof(*ctx)); | ||
1110 | /* There is no need to touch HW descriptor: | ||
1111 | * - ststus bit TX_DMA_STATUS_DU is set by design, | ||
1112 | * so hardware will not try to process this desc., | ||
1113 | * - rest of descriptor will be initialized on Tx. | ||
1114 | */ | ||
1115 | vring->swtail = wil_vring_next_tail(vring); | ||
1116 | done++; | ||
1041 | } | 1117 | } |
1042 | memset(ctx, 0, sizeof(*ctx)); | ||
1043 | /* | ||
1044 | * There is no need to touch HW descriptor: | ||
1045 | * - ststus bit TX_DMA_STATUS_DU is set by design, | ||
1046 | * so hardware will not try to process this desc., | ||
1047 | * - rest of descriptor will be initialized on Tx. | ||
1048 | */ | ||
1049 | vring->swtail = wil_vring_next_tail(vring); | ||
1050 | done++; | ||
1051 | } | 1118 | } |
1052 | if (wil_vring_avail_tx(vring) > vring->size/4) | 1119 | if (wil_vring_avail_tx(vring) > vring->size/4) |
1053 | netif_tx_wake_all_queues(wil_to_ndev(wil)); | 1120 | netif_tx_wake_all_queues(wil_to_ndev(wil)); |
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 980dccc82b32..2a2dec75f026 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h | |||
@@ -74,23 +74,21 @@ struct RGF_ICR { | |||
74 | } __packed; | 74 | } __packed; |
75 | 75 | ||
76 | /* registers - FW addresses */ | 76 | /* registers - FW addresses */ |
77 | #define RGF_USER_USER_SCRATCH_PAD (0x8802bc) | 77 | #define RGF_USER_HW_MACHINE_STATE (0x8801dc) |
78 | #define RGF_USER_USER_ICR (0x880b4c) /* struct RGF_ICR */ | 78 | #define HW_MACHINE_BOOT_DONE (0x3fffffd) |
79 | #define BIT_USER_USER_ICR_SW_INT_2 BIT(18) | ||
80 | #define RGF_USER_CLKS_CTL_SW_RST_MASK_0 (0x880b14) | ||
81 | #define RGF_USER_MAC_CPU_0 (0x8801fc) | ||
82 | #define RGF_USER_USER_CPU_0 (0x8801e0) | 79 | #define RGF_USER_USER_CPU_0 (0x8801e0) |
80 | #define RGF_USER_MAC_CPU_0 (0x8801fc) | ||
81 | #define RGF_USER_USER_SCRATCH_PAD (0x8802bc) | ||
82 | #define RGF_USER_FW_REV_ID (0x880a8c) /* chip revision */ | ||
83 | #define RGF_USER_CLKS_CTL_0 (0x880abc) | ||
84 | #define BIT_USER_CLKS_RST_PWGD BIT(11) /* reset on "power good" */ | ||
83 | #define RGF_USER_CLKS_CTL_SW_RST_VEC_0 (0x880b04) | 85 | #define RGF_USER_CLKS_CTL_SW_RST_VEC_0 (0x880b04) |
84 | #define RGF_USER_CLKS_CTL_SW_RST_VEC_1 (0x880b08) | 86 | #define RGF_USER_CLKS_CTL_SW_RST_VEC_1 (0x880b08) |
85 | #define RGF_USER_CLKS_CTL_SW_RST_VEC_2 (0x880b0c) | 87 | #define RGF_USER_CLKS_CTL_SW_RST_VEC_2 (0x880b0c) |
86 | #define RGF_USER_CLKS_CTL_SW_RST_VEC_3 (0x880b10) | 88 | #define RGF_USER_CLKS_CTL_SW_RST_VEC_3 (0x880b10) |
87 | 89 | #define RGF_USER_CLKS_CTL_SW_RST_MASK_0 (0x880b14) | |
88 | #define RGF_DMA_PSEUDO_CAUSE (0x881c68) | 90 | #define RGF_USER_USER_ICR (0x880b4c) /* struct RGF_ICR */ |
89 | #define RGF_DMA_PSEUDO_CAUSE_MASK_SW (0x881c6c) | 91 | #define BIT_USER_USER_ICR_SW_INT_2 BIT(18) |
90 | #define RGF_DMA_PSEUDO_CAUSE_MASK_FW (0x881c70) | ||
91 | #define BIT_DMA_PSEUDO_CAUSE_RX BIT(0) | ||
92 | #define BIT_DMA_PSEUDO_CAUSE_TX BIT(1) | ||
93 | #define BIT_DMA_PSEUDO_CAUSE_MISC BIT(2) | ||
94 | 92 | ||
95 | #define RGF_DMA_EP_TX_ICR (0x881bb4) /* struct RGF_ICR */ | 93 | #define RGF_DMA_EP_TX_ICR (0x881bb4) /* struct RGF_ICR */ |
96 | #define BIT_DMA_EP_TX_ICR_TX_DONE BIT(0) | 94 | #define BIT_DMA_EP_TX_ICR_TX_DONE BIT(0) |
@@ -105,13 +103,22 @@ struct RGF_ICR { | |||
105 | /* Interrupt moderation control */ | 103 | /* Interrupt moderation control */ |
106 | #define RGF_DMA_ITR_CNT_TRSH (0x881c5c) | 104 | #define RGF_DMA_ITR_CNT_TRSH (0x881c5c) |
107 | #define RGF_DMA_ITR_CNT_DATA (0x881c60) | 105 | #define RGF_DMA_ITR_CNT_DATA (0x881c60) |
108 | #define RGF_DMA_ITR_CNT_CRL (0x881C64) | 106 | #define RGF_DMA_ITR_CNT_CRL (0x881c64) |
109 | #define BIT_DMA_ITR_CNT_CRL_EN BIT(0) | 107 | #define BIT_DMA_ITR_CNT_CRL_EN BIT(0) |
110 | #define BIT_DMA_ITR_CNT_CRL_EXT_TICK BIT(1) | 108 | #define BIT_DMA_ITR_CNT_CRL_EXT_TICK BIT(1) |
111 | #define BIT_DMA_ITR_CNT_CRL_FOREVER BIT(2) | 109 | #define BIT_DMA_ITR_CNT_CRL_FOREVER BIT(2) |
112 | #define BIT_DMA_ITR_CNT_CRL_CLR BIT(3) | 110 | #define BIT_DMA_ITR_CNT_CRL_CLR BIT(3) |
113 | #define BIT_DMA_ITR_CNT_CRL_REACH_TRSH BIT(4) | 111 | #define BIT_DMA_ITR_CNT_CRL_REACH_TRSH BIT(4) |
114 | 112 | ||
113 | #define RGF_DMA_PSEUDO_CAUSE (0x881c68) | ||
114 | #define RGF_DMA_PSEUDO_CAUSE_MASK_SW (0x881c6c) | ||
115 | #define RGF_DMA_PSEUDO_CAUSE_MASK_FW (0x881c70) | ||
116 | #define BIT_DMA_PSEUDO_CAUSE_RX BIT(0) | ||
117 | #define BIT_DMA_PSEUDO_CAUSE_TX BIT(1) | ||
118 | #define BIT_DMA_PSEUDO_CAUSE_MISC BIT(2) | ||
119 | |||
120 | #define RGF_PCIE_LOS_COUNTER_CTL (0x882dc4) | ||
121 | |||
115 | /* popular locations */ | 122 | /* popular locations */ |
116 | #define HOST_MBOX HOSTADDR(RGF_USER_USER_SCRATCH_PAD) | 123 | #define HOST_MBOX HOSTADDR(RGF_USER_USER_SCRATCH_PAD) |
117 | #define HOST_SW_INT (HOSTADDR(RGF_USER_USER_ICR) + \ | 124 | #define HOST_SW_INT (HOSTADDR(RGF_USER_USER_ICR) + \ |
@@ -125,6 +132,31 @@ struct RGF_ICR { | |||
125 | 132 | ||
126 | /* Hardware definitions end */ | 133 | /* Hardware definitions end */ |
127 | 134 | ||
135 | /** | ||
136 | * mk_cidxtid - construct @cidxtid field | ||
137 | * @cid: CID value | ||
138 | * @tid: TID value | ||
139 | * | ||
140 | * @cidxtid field encoded as bits 0..3 - CID; 4..7 - TID | ||
141 | */ | ||
142 | static inline u8 mk_cidxtid(u8 cid, u8 tid) | ||
143 | { | ||
144 | return ((tid & 0xf) << 4) | (cid & 0xf); | ||
145 | } | ||
146 | |||
147 | /** | ||
148 | * parse_cidxtid - parse @cidxtid field | ||
149 | * @cid: store CID value here | ||
150 | * @tid: store TID value here | ||
151 | * | ||
152 | * @cidxtid field encoded as bits 0..3 - CID; 4..7 - TID | ||
153 | */ | ||
154 | static inline void parse_cidxtid(u8 cidxtid, u8 *cid, u8 *tid) | ||
155 | { | ||
156 | *cid = cidxtid & 0xf; | ||
157 | *tid = (cidxtid >> 4) & 0xf; | ||
158 | } | ||
159 | |||
128 | struct wil6210_mbox_ring { | 160 | struct wil6210_mbox_ring { |
129 | u32 base; | 161 | u32 base; |
130 | u16 entry_size; /* max. size of mbox entry, incl. all headers */ | 162 | u16 entry_size; /* max. size of mbox entry, incl. all headers */ |
@@ -184,12 +216,19 @@ struct pending_wmi_event { | |||
184 | } __packed event; | 216 | } __packed event; |
185 | }; | 217 | }; |
186 | 218 | ||
219 | enum { /* for wil_ctx.mapped_as */ | ||
220 | wil_mapped_as_none = 0, | ||
221 | wil_mapped_as_single = 1, | ||
222 | wil_mapped_as_page = 2, | ||
223 | }; | ||
224 | |||
187 | /** | 225 | /** |
188 | * struct wil_ctx - software context for Vring descriptor | 226 | * struct wil_ctx - software context for Vring descriptor |
189 | */ | 227 | */ |
190 | struct wil_ctx { | 228 | struct wil_ctx { |
191 | struct sk_buff *skb; | 229 | struct sk_buff *skb; |
192 | u8 mapped_as_page:1; | 230 | u8 nr_frags; |
231 | u8 mapped_as; | ||
193 | }; | 232 | }; |
194 | 233 | ||
195 | union vring_desc; | 234 | union vring_desc; |
@@ -204,6 +243,14 @@ struct vring { | |||
204 | struct wil_ctx *ctx; /* ctx[size] - software context */ | 243 | struct wil_ctx *ctx; /* ctx[size] - software context */ |
205 | }; | 244 | }; |
206 | 245 | ||
246 | /** | ||
247 | * Additional data for Tx Vring | ||
248 | */ | ||
249 | struct vring_tx_data { | ||
250 | int enabled; | ||
251 | |||
252 | }; | ||
253 | |||
207 | enum { /* for wil6210_priv.status */ | 254 | enum { /* for wil6210_priv.status */ |
208 | wil_status_fwready = 0, | 255 | wil_status_fwready = 0, |
209 | wil_status_fwconnecting, | 256 | wil_status_fwconnecting, |
@@ -211,6 +258,7 @@ enum { /* for wil6210_priv.status */ | |||
211 | wil_status_dontscan, | 258 | wil_status_dontscan, |
212 | wil_status_reset_done, | 259 | wil_status_reset_done, |
213 | wil_status_irqen, /* FIXME: interrupts enabled - for debug */ | 260 | wil_status_irqen, /* FIXME: interrupts enabled - for debug */ |
261 | wil_status_napi_en, /* NAPI enabled protected by wil->mutex */ | ||
214 | }; | 262 | }; |
215 | 263 | ||
216 | struct pci_dev; | 264 | struct pci_dev; |
@@ -296,6 +344,7 @@ struct wil_sta_info { | |||
296 | u8 addr[ETH_ALEN]; | 344 | u8 addr[ETH_ALEN]; |
297 | enum wil_sta_status status; | 345 | enum wil_sta_status status; |
298 | struct wil_net_stats stats; | 346 | struct wil_net_stats stats; |
347 | bool data_port_open; /* can send any data, not only EAPOL */ | ||
299 | /* Rx BACK */ | 348 | /* Rx BACK */ |
300 | struct wil_tid_ampdu_rx *tid_rx[WIL_STA_TID_NUM]; | 349 | struct wil_tid_ampdu_rx *tid_rx[WIL_STA_TID_NUM]; |
301 | unsigned long tid_rx_timer_expired[BITS_TO_LONGS(WIL_STA_TID_NUM)]; | 350 | unsigned long tid_rx_timer_expired[BITS_TO_LONGS(WIL_STA_TID_NUM)]; |
@@ -309,6 +358,7 @@ struct wil6210_priv { | |||
309 | void __iomem *csr; | 358 | void __iomem *csr; |
310 | ulong status; | 359 | ulong status; |
311 | u32 fw_version; | 360 | u32 fw_version; |
361 | u32 hw_version; | ||
312 | u8 n_mids; /* number of additional MIDs as reported by FW */ | 362 | u8 n_mids; /* number of additional MIDs as reported by FW */ |
313 | /* profile */ | 363 | /* profile */ |
314 | u32 monitor_flags; | 364 | u32 monitor_flags; |
@@ -329,6 +379,7 @@ struct wil6210_priv { | |||
329 | struct workqueue_struct *wmi_wq_conn; /* for connect worker */ | 379 | struct workqueue_struct *wmi_wq_conn; /* for connect worker */ |
330 | struct work_struct connect_worker; | 380 | struct work_struct connect_worker; |
331 | struct work_struct disconnect_worker; | 381 | struct work_struct disconnect_worker; |
382 | struct work_struct fw_error_worker; /* for FW error recovery */ | ||
332 | struct timer_list connect_timer; | 383 | struct timer_list connect_timer; |
333 | int pending_connect_cid; | 384 | int pending_connect_cid; |
334 | struct list_head pending_wmi_ev; | 385 | struct list_head pending_wmi_ev; |
@@ -343,6 +394,7 @@ struct wil6210_priv { | |||
343 | /* DMA related */ | 394 | /* DMA related */ |
344 | struct vring vring_rx; | 395 | struct vring vring_rx; |
345 | struct vring vring_tx[WIL6210_MAX_TX_RINGS]; | 396 | struct vring vring_tx[WIL6210_MAX_TX_RINGS]; |
397 | struct vring_tx_data vring_tx_data[WIL6210_MAX_TX_RINGS]; | ||
346 | u8 vring2cid_tid[WIL6210_MAX_TX_RINGS][2]; /* [0] - CID, [1] - TID */ | 398 | u8 vring2cid_tid[WIL6210_MAX_TX_RINGS][2]; /* [0] - CID, [1] - TID */ |
347 | struct wil_sta_info sta[WIL6210_MAX_CID]; | 399 | struct wil_sta_info sta[WIL6210_MAX_CID]; |
348 | /* scan */ | 400 | /* scan */ |
@@ -406,6 +458,7 @@ void wil_if_remove(struct wil6210_priv *wil); | |||
406 | int wil_priv_init(struct wil6210_priv *wil); | 458 | int wil_priv_init(struct wil6210_priv *wil); |
407 | void wil_priv_deinit(struct wil6210_priv *wil); | 459 | void wil_priv_deinit(struct wil6210_priv *wil); |
408 | int wil_reset(struct wil6210_priv *wil); | 460 | int wil_reset(struct wil6210_priv *wil); |
461 | void wil_fw_error_recovery(struct wil6210_priv *wil); | ||
409 | void wil_link_on(struct wil6210_priv *wil); | 462 | void wil_link_on(struct wil6210_priv *wil); |
410 | void wil_link_off(struct wil6210_priv *wil); | 463 | void wil_link_off(struct wil6210_priv *wil); |
411 | int wil_up(struct wil6210_priv *wil); | 464 | int wil_up(struct wil6210_priv *wil); |
@@ -439,6 +492,7 @@ int wmi_rxon(struct wil6210_priv *wil, bool on); | |||
439 | int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_m, u32 *t_r); | 492 | int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_m, u32 *t_r); |
440 | int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason); | 493 | int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason); |
441 | 494 | ||
495 | void wil6210_clear_irq(struct wil6210_priv *wil); | ||
442 | int wil6210_init_irq(struct wil6210_priv *wil, int irq); | 496 | int wil6210_init_irq(struct wil6210_priv *wil, int irq); |
443 | void wil6210_fini_irq(struct wil6210_priv *wil, int irq); | 497 | void wil6210_fini_irq(struct wil6210_priv *wil, int irq); |
444 | void wil6210_disable_irq(struct wil6210_priv *wil); | 498 | void wil6210_disable_irq(struct wil6210_priv *wil); |
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 24eed0963581..2ba56eef0c45 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c | |||
@@ -462,7 +462,9 @@ static void wmi_evt_disconnect(struct wil6210_priv *wil, int id, | |||
462 | 462 | ||
463 | wil->sinfo_gen++; | 463 | wil->sinfo_gen++; |
464 | 464 | ||
465 | mutex_lock(&wil->mutex); | ||
465 | wil6210_disconnect(wil, evt->bssid); | 466 | wil6210_disconnect(wil, evt->bssid); |
467 | mutex_unlock(&wil->mutex); | ||
466 | } | 468 | } |
467 | 469 | ||
468 | static void wmi_evt_notify(struct wil6210_priv *wil, int id, void *d, int len) | 470 | static void wmi_evt_notify(struct wil6210_priv *wil, int id, void *d, int len) |
@@ -550,9 +552,16 @@ static void wmi_evt_linkup(struct wil6210_priv *wil, int id, void *d, int len) | |||
550 | { | 552 | { |
551 | struct net_device *ndev = wil_to_ndev(wil); | 553 | struct net_device *ndev = wil_to_ndev(wil); |
552 | struct wmi_data_port_open_event *evt = d; | 554 | struct wmi_data_port_open_event *evt = d; |
555 | u8 cid = evt->cid; | ||
553 | 556 | ||
554 | wil_dbg_wmi(wil, "Link UP for CID %d\n", evt->cid); | 557 | wil_dbg_wmi(wil, "Link UP for CID %d\n", cid); |
555 | 558 | ||
559 | if (cid >= ARRAY_SIZE(wil->sta)) { | ||
560 | wil_err(wil, "Link UP for invalid CID %d\n", cid); | ||
561 | return; | ||
562 | } | ||
563 | |||
564 | wil->sta[cid].data_port_open = true; | ||
556 | netif_carrier_on(ndev); | 565 | netif_carrier_on(ndev); |
557 | } | 566 | } |
558 | 567 | ||
@@ -560,10 +569,17 @@ static void wmi_evt_linkdown(struct wil6210_priv *wil, int id, void *d, int len) | |||
560 | { | 569 | { |
561 | struct net_device *ndev = wil_to_ndev(wil); | 570 | struct net_device *ndev = wil_to_ndev(wil); |
562 | struct wmi_wbe_link_down_event *evt = d; | 571 | struct wmi_wbe_link_down_event *evt = d; |
572 | u8 cid = evt->cid; | ||
563 | 573 | ||
564 | wil_dbg_wmi(wil, "Link DOWN for CID %d, reason %d\n", | 574 | wil_dbg_wmi(wil, "Link DOWN for CID %d, reason %d\n", |
565 | evt->cid, le32_to_cpu(evt->reason)); | 575 | cid, le32_to_cpu(evt->reason)); |
576 | |||
577 | if (cid >= ARRAY_SIZE(wil->sta)) { | ||
578 | wil_err(wil, "Link DOWN for invalid CID %d\n", cid); | ||
579 | return; | ||
580 | } | ||
566 | 581 | ||
582 | wil->sta[cid].data_port_open = false; | ||
567 | netif_carrier_off(ndev); | 583 | netif_carrier_off(ndev); |
568 | } | 584 | } |
569 | 585 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index 4a6508e7e3a1..a16e644e7c08 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | |||
@@ -269,26 +269,17 @@ static int brcmf_sdiod_request_data(struct brcmf_sdio_dev *sdiodev, u8 fn, | |||
269 | break; | 269 | break; |
270 | } | 270 | } |
271 | 271 | ||
272 | if (ret) { | 272 | if (ret) |
273 | /* | 273 | brcmf_dbg(SDIO, "failed to %s data F%d@0x%05x, err: %d\n", |
274 | * SleepCSR register access can fail when | 274 | write ? "write" : "read", fn, addr, ret); |
275 | * waking up the device so reduce this noise | 275 | |
276 | * in the logs. | ||
277 | */ | ||
278 | if (addr != SBSDIO_FUNC1_SLEEPCSR) | ||
279 | brcmf_err("failed to %s data F%d@0x%05x, err: %d\n", | ||
280 | write ? "write" : "read", fn, addr, ret); | ||
281 | else | ||
282 | brcmf_dbg(SDIO, "failed to %s data F%d@0x%05x, err: %d\n", | ||
283 | write ? "write" : "read", fn, addr, ret); | ||
284 | } | ||
285 | return ret; | 276 | return ret; |
286 | } | 277 | } |
287 | 278 | ||
288 | static int brcmf_sdiod_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, | 279 | static int brcmf_sdiod_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, |
289 | u8 regsz, void *data, bool write) | 280 | u8 regsz, void *data, bool write) |
290 | { | 281 | { |
291 | u8 func_num; | 282 | u8 func; |
292 | s32 retry = 0; | 283 | s32 retry = 0; |
293 | int ret; | 284 | int ret; |
294 | 285 | ||
@@ -302,9 +293,9 @@ static int brcmf_sdiod_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, | |||
302 | * The rest: function 1 silicon backplane core registers | 293 | * The rest: function 1 silicon backplane core registers |
303 | */ | 294 | */ |
304 | if ((addr & ~REG_F0_REG_MASK) == 0) | 295 | if ((addr & ~REG_F0_REG_MASK) == 0) |
305 | func_num = SDIO_FUNC_0; | 296 | func = SDIO_FUNC_0; |
306 | else | 297 | else |
307 | func_num = SDIO_FUNC_1; | 298 | func = SDIO_FUNC_1; |
308 | 299 | ||
309 | do { | 300 | do { |
310 | if (!write) | 301 | if (!write) |
@@ -312,16 +303,26 @@ static int brcmf_sdiod_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, | |||
312 | /* for retry wait for 1 ms till bus get settled down */ | 303 | /* for retry wait for 1 ms till bus get settled down */ |
313 | if (retry) | 304 | if (retry) |
314 | usleep_range(1000, 2000); | 305 | usleep_range(1000, 2000); |
315 | ret = brcmf_sdiod_request_data(sdiodev, func_num, addr, regsz, | 306 | ret = brcmf_sdiod_request_data(sdiodev, func, addr, regsz, |
316 | data, write); | 307 | data, write); |
317 | } while (ret != 0 && ret != -ENOMEDIUM && | 308 | } while (ret != 0 && ret != -ENOMEDIUM && |
318 | retry++ < SDIOH_API_ACCESS_RETRY_LIMIT); | 309 | retry++ < SDIOH_API_ACCESS_RETRY_LIMIT); |
319 | 310 | ||
320 | if (ret == -ENOMEDIUM) | 311 | if (ret == -ENOMEDIUM) |
321 | brcmf_bus_change_state(sdiodev->bus_if, BRCMF_BUS_NOMEDIUM); | 312 | brcmf_bus_change_state(sdiodev->bus_if, BRCMF_BUS_NOMEDIUM); |
322 | else if (ret != 0) | 313 | else if (ret != 0) { |
323 | brcmf_err("failed with %d\n", ret); | 314 | /* |
324 | 315 | * SleepCSR register access can fail when | |
316 | * waking up the device so reduce this noise | ||
317 | * in the logs. | ||
318 | */ | ||
319 | if (addr != SBSDIO_FUNC1_SLEEPCSR) | ||
320 | brcmf_err("failed to %s data F%d@0x%05x, err: %d\n", | ||
321 | write ? "write" : "read", func, addr, ret); | ||
322 | else | ||
323 | brcmf_dbg(SDIO, "failed to %s data F%d@0x%05x, err: %d\n", | ||
324 | write ? "write" : "read", func, addr, ret); | ||
325 | } | ||
325 | return ret; | 326 | return ret; |
326 | } | 327 | } |
327 | 328 | ||
@@ -988,6 +989,7 @@ static const struct sdio_device_id brcmf_sdmmc_ids[] = { | |||
988 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43362)}, | 989 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43362)}, |
989 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, | 990 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, |
990 | SDIO_DEVICE_ID_BROADCOM_4335_4339)}, | 991 | SDIO_DEVICE_ID_BROADCOM_4335_4339)}, |
992 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4354)}, | ||
991 | { /* end: all zeroes */ }, | 993 | { /* end: all zeroes */ }, |
992 | }; | 994 | }; |
993 | MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); | 995 | MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); |
@@ -1153,7 +1155,7 @@ static struct sdio_driver brcmf_sdmmc_driver = { | |||
1153 | }, | 1155 | }, |
1154 | }; | 1156 | }; |
1155 | 1157 | ||
1156 | static int brcmf_sdio_pd_probe(struct platform_device *pdev) | 1158 | static int __init brcmf_sdio_pd_probe(struct platform_device *pdev) |
1157 | { | 1159 | { |
1158 | brcmf_dbg(SDIO, "Enter\n"); | 1160 | brcmf_dbg(SDIO, "Enter\n"); |
1159 | 1161 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/brcm80211/brcmfmac/chip.c index a07b95ef9e70..df130ef53d1c 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c | |||
@@ -504,6 +504,7 @@ static void brcmf_chip_get_raminfo(struct brcmf_chip_priv *ci) | |||
504 | ci->pub.ramsize = 0x3c000; | 504 | ci->pub.ramsize = 0x3c000; |
505 | break; | 505 | break; |
506 | case BCM4339_CHIP_ID: | 506 | case BCM4339_CHIP_ID: |
507 | case BCM4354_CHIP_ID: | ||
507 | ci->pub.ramsize = 0xc0000; | 508 | ci->pub.ramsize = 0xc0000; |
508 | ci->pub.rambase = 0x180000; | 509 | ci->pub.rambase = 0x180000; |
509 | break; | 510 | break; |
@@ -1006,6 +1007,10 @@ bool brcmf_chip_sr_capable(struct brcmf_chip *pub) | |||
1006 | chip = container_of(pub, struct brcmf_chip_priv, pub); | 1007 | chip = container_of(pub, struct brcmf_chip_priv, pub); |
1007 | 1008 | ||
1008 | switch (pub->chip) { | 1009 | switch (pub->chip) { |
1010 | case BCM4354_CHIP_ID: | ||
1011 | /* explicitly check SR engine enable bit */ | ||
1012 | pmu_cc3_mask = BIT(2); | ||
1013 | /* fall-through */ | ||
1009 | case BCM43241_CHIP_ID: | 1014 | case BCM43241_CHIP_ID: |
1010 | case BCM4335_CHIP_ID: | 1015 | case BCM4335_CHIP_ID: |
1011 | case BCM4339_CHIP_ID: | 1016 | case BCM4339_CHIP_ID: |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index a111b6fbbeba..47a6f3957b7f 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | |||
@@ -175,6 +175,7 @@ struct rte_console { | |||
175 | #define SBSDIO_ALP_AVAIL 0x40 | 175 | #define SBSDIO_ALP_AVAIL 0x40 |
176 | /* Status: HT is ready */ | 176 | /* Status: HT is ready */ |
177 | #define SBSDIO_HT_AVAIL 0x80 | 177 | #define SBSDIO_HT_AVAIL 0x80 |
178 | #define SBSDIO_CSR_MASK 0x1F | ||
178 | #define SBSDIO_AVBITS (SBSDIO_HT_AVAIL | SBSDIO_ALP_AVAIL) | 179 | #define SBSDIO_AVBITS (SBSDIO_HT_AVAIL | SBSDIO_ALP_AVAIL) |
179 | #define SBSDIO_ALPAV(regval) ((regval) & SBSDIO_AVBITS) | 180 | #define SBSDIO_ALPAV(regval) ((regval) & SBSDIO_AVBITS) |
180 | #define SBSDIO_HTAV(regval) (((regval) & SBSDIO_AVBITS) == SBSDIO_AVBITS) | 181 | #define SBSDIO_HTAV(regval) (((regval) & SBSDIO_AVBITS) == SBSDIO_AVBITS) |
@@ -458,10 +459,11 @@ struct brcmf_sdio { | |||
458 | bool alp_only; /* Don't use HT clock (ALP only) */ | 459 | bool alp_only; /* Don't use HT clock (ALP only) */ |
459 | 460 | ||
460 | u8 *ctrl_frame_buf; | 461 | u8 *ctrl_frame_buf; |
461 | u32 ctrl_frame_len; | 462 | u16 ctrl_frame_len; |
462 | bool ctrl_frame_stat; | 463 | bool ctrl_frame_stat; |
463 | 464 | ||
464 | spinlock_t txqlock; | 465 | spinlock_t txq_lock; /* protect bus->txq */ |
466 | struct semaphore tx_seq_lock; /* protect bus->tx_seq */ | ||
465 | wait_queue_head_t ctrl_wait; | 467 | wait_queue_head_t ctrl_wait; |
466 | wait_queue_head_t dcmd_resp_wait; | 468 | wait_queue_head_t dcmd_resp_wait; |
467 | 469 | ||
@@ -578,6 +580,8 @@ static const struct sdiod_drive_str sdiod_drvstr_tab2_3v3[] = { | |||
578 | #define BCM43362_NVRAM_NAME "brcm/brcmfmac43362-sdio.txt" | 580 | #define BCM43362_NVRAM_NAME "brcm/brcmfmac43362-sdio.txt" |
579 | #define BCM4339_FIRMWARE_NAME "brcm/brcmfmac4339-sdio.bin" | 581 | #define BCM4339_FIRMWARE_NAME "brcm/brcmfmac4339-sdio.bin" |
580 | #define BCM4339_NVRAM_NAME "brcm/brcmfmac4339-sdio.txt" | 582 | #define BCM4339_NVRAM_NAME "brcm/brcmfmac4339-sdio.txt" |
583 | #define BCM4354_FIRMWARE_NAME "brcm/brcmfmac4354-sdio.bin" | ||
584 | #define BCM4354_NVRAM_NAME "brcm/brcmfmac4354-sdio.txt" | ||
581 | 585 | ||
582 | MODULE_FIRMWARE(BCM43143_FIRMWARE_NAME); | 586 | MODULE_FIRMWARE(BCM43143_FIRMWARE_NAME); |
583 | MODULE_FIRMWARE(BCM43143_NVRAM_NAME); | 587 | MODULE_FIRMWARE(BCM43143_NVRAM_NAME); |
@@ -597,6 +601,8 @@ MODULE_FIRMWARE(BCM43362_FIRMWARE_NAME); | |||
597 | MODULE_FIRMWARE(BCM43362_NVRAM_NAME); | 601 | MODULE_FIRMWARE(BCM43362_NVRAM_NAME); |
598 | MODULE_FIRMWARE(BCM4339_FIRMWARE_NAME); | 602 | MODULE_FIRMWARE(BCM4339_FIRMWARE_NAME); |
599 | MODULE_FIRMWARE(BCM4339_NVRAM_NAME); | 603 | MODULE_FIRMWARE(BCM4339_NVRAM_NAME); |
604 | MODULE_FIRMWARE(BCM4354_FIRMWARE_NAME); | ||
605 | MODULE_FIRMWARE(BCM4354_NVRAM_NAME); | ||
600 | 606 | ||
601 | struct brcmf_firmware_names { | 607 | struct brcmf_firmware_names { |
602 | u32 chipid; | 608 | u32 chipid; |
@@ -622,7 +628,8 @@ static const struct brcmf_firmware_names brcmf_fwname_data[] = { | |||
622 | { BCM4334_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4334) }, | 628 | { BCM4334_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4334) }, |
623 | { BCM4335_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4335) }, | 629 | { BCM4335_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4335) }, |
624 | { BCM43362_CHIP_ID, 0xFFFFFFFE, BRCMF_FIRMWARE_NVRAM(BCM43362) }, | 630 | { BCM43362_CHIP_ID, 0xFFFFFFFE, BRCMF_FIRMWARE_NVRAM(BCM43362) }, |
625 | { BCM4339_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4339) } | 631 | { BCM4339_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4339) }, |
632 | { BCM4354_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4354) } | ||
626 | }; | 633 | }; |
627 | 634 | ||
628 | 635 | ||
@@ -714,16 +721,12 @@ brcmf_sdio_kso_control(struct brcmf_sdio *bus, bool on) | |||
714 | int err = 0; | 721 | int err = 0; |
715 | int try_cnt = 0; | 722 | int try_cnt = 0; |
716 | 723 | ||
717 | brcmf_dbg(TRACE, "Enter\n"); | 724 | brcmf_dbg(TRACE, "Enter: on=%d\n", on); |
718 | 725 | ||
719 | wr_val = (on << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT); | 726 | wr_val = (on << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT); |
720 | /* 1st KSO write goes to AOS wake up core if device is asleep */ | 727 | /* 1st KSO write goes to AOS wake up core if device is asleep */ |
721 | brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, | 728 | brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, |
722 | wr_val, &err); | 729 | wr_val, &err); |
723 | if (err) { | ||
724 | brcmf_err("SDIO_AOS KSO write error: %d\n", err); | ||
725 | return err; | ||
726 | } | ||
727 | 730 | ||
728 | if (on) { | 731 | if (on) { |
729 | /* device WAKEUP through KSO: | 732 | /* device WAKEUP through KSO: |
@@ -753,13 +756,19 @@ brcmf_sdio_kso_control(struct brcmf_sdio *bus, bool on) | |||
753 | &err); | 756 | &err); |
754 | if (((rd_val & bmask) == cmp_val) && !err) | 757 | if (((rd_val & bmask) == cmp_val) && !err) |
755 | break; | 758 | break; |
756 | brcmf_dbg(SDIO, "KSO wr/rd retry:%d (max: %d) ERR:%x\n", | 759 | |
757 | try_cnt, MAX_KSO_ATTEMPTS, err); | ||
758 | udelay(KSO_WAIT_US); | 760 | udelay(KSO_WAIT_US); |
759 | brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, | 761 | brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, |
760 | wr_val, &err); | 762 | wr_val, &err); |
761 | } while (try_cnt++ < MAX_KSO_ATTEMPTS); | 763 | } while (try_cnt++ < MAX_KSO_ATTEMPTS); |
762 | 764 | ||
765 | if (try_cnt > 2) | ||
766 | brcmf_dbg(SDIO, "try_cnt=%d rd_val=0x%x err=%d\n", try_cnt, | ||
767 | rd_val, err); | ||
768 | |||
769 | if (try_cnt > MAX_KSO_ATTEMPTS) | ||
770 | brcmf_err("max tries: rd_val=0x%x err=%d\n", rd_val, err); | ||
771 | |||
763 | return err; | 772 | return err; |
764 | } | 773 | } |
765 | 774 | ||
@@ -960,6 +969,7 @@ static int | |||
960 | brcmf_sdio_bus_sleep(struct brcmf_sdio *bus, bool sleep, bool pendok) | 969 | brcmf_sdio_bus_sleep(struct brcmf_sdio *bus, bool sleep, bool pendok) |
961 | { | 970 | { |
962 | int err = 0; | 971 | int err = 0; |
972 | u8 clkcsr; | ||
963 | 973 | ||
964 | brcmf_dbg(SDIO, "Enter: request %s currently %s\n", | 974 | brcmf_dbg(SDIO, "Enter: request %s currently %s\n", |
965 | (sleep ? "SLEEP" : "WAKE"), | 975 | (sleep ? "SLEEP" : "WAKE"), |
@@ -978,8 +988,20 @@ brcmf_sdio_bus_sleep(struct brcmf_sdio *bus, bool sleep, bool pendok) | |||
978 | atomic_read(&bus->ipend) > 0 || | 988 | atomic_read(&bus->ipend) > 0 || |
979 | (!atomic_read(&bus->fcstate) && | 989 | (!atomic_read(&bus->fcstate) && |
980 | brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && | 990 | brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && |
981 | data_ok(bus))) | 991 | data_ok(bus))) { |
982 | return -EBUSY; | 992 | err = -EBUSY; |
993 | goto done; | ||
994 | } | ||
995 | |||
996 | clkcsr = brcmf_sdiod_regrb(bus->sdiodev, | ||
997 | SBSDIO_FUNC1_CHIPCLKCSR, | ||
998 | &err); | ||
999 | if ((clkcsr & SBSDIO_CSR_MASK) == 0) { | ||
1000 | brcmf_dbg(SDIO, "no clock, set ALP\n"); | ||
1001 | brcmf_sdiod_regwb(bus->sdiodev, | ||
1002 | SBSDIO_FUNC1_CHIPCLKCSR, | ||
1003 | SBSDIO_ALP_AVAIL_REQ, &err); | ||
1004 | } | ||
983 | err = brcmf_sdio_kso_control(bus, false); | 1005 | err = brcmf_sdio_kso_control(bus, false); |
984 | /* disable watchdog */ | 1006 | /* disable watchdog */ |
985 | if (!err) | 1007 | if (!err) |
@@ -996,7 +1018,7 @@ brcmf_sdio_bus_sleep(struct brcmf_sdio *bus, bool sleep, bool pendok) | |||
996 | } else { | 1018 | } else { |
997 | brcmf_err("error while changing bus sleep state %d\n", | 1019 | brcmf_err("error while changing bus sleep state %d\n", |
998 | err); | 1020 | err); |
999 | return err; | 1021 | goto done; |
1000 | } | 1022 | } |
1001 | } | 1023 | } |
1002 | 1024 | ||
@@ -1008,7 +1030,8 @@ end: | |||
1008 | } else { | 1030 | } else { |
1009 | brcmf_sdio_clkctl(bus, CLK_AVAIL, pendok); | 1031 | brcmf_sdio_clkctl(bus, CLK_AVAIL, pendok); |
1010 | } | 1032 | } |
1011 | 1033 | done: | |
1034 | brcmf_dbg(SDIO, "Exit: err=%d\n", err); | ||
1012 | return err; | 1035 | return err; |
1013 | 1036 | ||
1014 | } | 1037 | } |
@@ -2311,13 +2334,15 @@ static uint brcmf_sdio_sendfromq(struct brcmf_sdio *bus, uint maxframes) | |||
2311 | /* Send frames until the limit or some other event */ | 2334 | /* Send frames until the limit or some other event */ |
2312 | for (cnt = 0; (cnt < maxframes) && data_ok(bus);) { | 2335 | for (cnt = 0; (cnt < maxframes) && data_ok(bus);) { |
2313 | pkt_num = 1; | 2336 | pkt_num = 1; |
2314 | __skb_queue_head_init(&pktq); | 2337 | if (down_interruptible(&bus->tx_seq_lock)) |
2338 | return cnt; | ||
2315 | if (bus->txglom) | 2339 | if (bus->txglom) |
2316 | pkt_num = min_t(u8, bus->tx_max - bus->tx_seq, | 2340 | pkt_num = min_t(u8, bus->tx_max - bus->tx_seq, |
2317 | bus->sdiodev->txglomsz); | 2341 | bus->sdiodev->txglomsz); |
2318 | pkt_num = min_t(u32, pkt_num, | 2342 | pkt_num = min_t(u32, pkt_num, |
2319 | brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol)); | 2343 | brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol)); |
2320 | spin_lock_bh(&bus->txqlock); | 2344 | __skb_queue_head_init(&pktq); |
2345 | spin_lock_bh(&bus->txq_lock); | ||
2321 | for (i = 0; i < pkt_num; i++) { | 2346 | for (i = 0; i < pkt_num; i++) { |
2322 | pkt = brcmu_pktq_mdeq(&bus->txq, tx_prec_map, | 2347 | pkt = brcmu_pktq_mdeq(&bus->txq, tx_prec_map, |
2323 | &prec_out); | 2348 | &prec_out); |
@@ -2325,11 +2350,15 @@ static uint brcmf_sdio_sendfromq(struct brcmf_sdio *bus, uint maxframes) | |||
2325 | break; | 2350 | break; |
2326 | __skb_queue_tail(&pktq, pkt); | 2351 | __skb_queue_tail(&pktq, pkt); |
2327 | } | 2352 | } |
2328 | spin_unlock_bh(&bus->txqlock); | 2353 | spin_unlock_bh(&bus->txq_lock); |
2329 | if (i == 0) | 2354 | if (i == 0) { |
2355 | up(&bus->tx_seq_lock); | ||
2330 | break; | 2356 | break; |
2357 | } | ||
2331 | 2358 | ||
2332 | ret = brcmf_sdio_txpkt(bus, &pktq, SDPCM_DATA_CHANNEL); | 2359 | ret = brcmf_sdio_txpkt(bus, &pktq, SDPCM_DATA_CHANNEL); |
2360 | up(&bus->tx_seq_lock); | ||
2361 | |||
2333 | cnt += i; | 2362 | cnt += i; |
2334 | 2363 | ||
2335 | /* In poll mode, need to check for other events */ | 2364 | /* In poll mode, need to check for other events */ |
@@ -2358,6 +2387,68 @@ static uint brcmf_sdio_sendfromq(struct brcmf_sdio *bus, uint maxframes) | |||
2358 | return cnt; | 2387 | return cnt; |
2359 | } | 2388 | } |
2360 | 2389 | ||
2390 | static int brcmf_sdio_tx_ctrlframe(struct brcmf_sdio *bus, u8 *frame, u16 len) | ||
2391 | { | ||
2392 | u8 doff; | ||
2393 | u16 pad; | ||
2394 | uint retries = 0; | ||
2395 | struct brcmf_sdio_hdrinfo hd_info = {0}; | ||
2396 | int ret; | ||
2397 | |||
2398 | brcmf_dbg(TRACE, "Enter\n"); | ||
2399 | |||
2400 | /* Back the pointer to make room for bus header */ | ||
2401 | frame -= bus->tx_hdrlen; | ||
2402 | len += bus->tx_hdrlen; | ||
2403 | |||
2404 | /* Add alignment padding (optional for ctl frames) */ | ||
2405 | doff = ((unsigned long)frame % bus->head_align); | ||
2406 | if (doff) { | ||
2407 | frame -= doff; | ||
2408 | len += doff; | ||
2409 | memset(frame + bus->tx_hdrlen, 0, doff); | ||
2410 | } | ||
2411 | |||
2412 | /* Round send length to next SDIO block */ | ||
2413 | pad = 0; | ||
2414 | if (bus->roundup && bus->blocksize && (len > bus->blocksize)) { | ||
2415 | pad = bus->blocksize - (len % bus->blocksize); | ||
2416 | if ((pad > bus->roundup) || (pad >= bus->blocksize)) | ||
2417 | pad = 0; | ||
2418 | } else if (len % bus->head_align) { | ||
2419 | pad = bus->head_align - (len % bus->head_align); | ||
2420 | } | ||
2421 | len += pad; | ||
2422 | |||
2423 | hd_info.len = len - pad; | ||
2424 | hd_info.channel = SDPCM_CONTROL_CHANNEL; | ||
2425 | hd_info.dat_offset = doff + bus->tx_hdrlen; | ||
2426 | hd_info.seq_num = bus->tx_seq; | ||
2427 | hd_info.lastfrm = true; | ||
2428 | hd_info.tail_pad = pad; | ||
2429 | brcmf_sdio_hdpack(bus, frame, &hd_info); | ||
2430 | |||
2431 | if (bus->txglom) | ||
2432 | brcmf_sdio_update_hwhdr(frame, len); | ||
2433 | |||
2434 | brcmf_dbg_hex_dump(BRCMF_BYTES_ON() && BRCMF_CTL_ON(), | ||
2435 | frame, len, "Tx Frame:\n"); | ||
2436 | brcmf_dbg_hex_dump(!(BRCMF_BYTES_ON() && BRCMF_CTL_ON()) && | ||
2437 | BRCMF_HDRS_ON(), | ||
2438 | frame, min_t(u16, len, 16), "TxHdr:\n"); | ||
2439 | |||
2440 | do { | ||
2441 | ret = brcmf_sdiod_send_buf(bus->sdiodev, frame, len); | ||
2442 | |||
2443 | if (ret < 0) | ||
2444 | brcmf_sdio_txfail(bus); | ||
2445 | else | ||
2446 | bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQ_WRAP; | ||
2447 | } while (ret < 0 && retries++ < TXRETRIES); | ||
2448 | |||
2449 | return ret; | ||
2450 | } | ||
2451 | |||
2361 | static void brcmf_sdio_bus_stop(struct device *dev) | 2452 | static void brcmf_sdio_bus_stop(struct device *dev) |
2362 | { | 2453 | { |
2363 | u32 local_hostintmask; | 2454 | u32 local_hostintmask; |
@@ -2591,26 +2682,23 @@ static void brcmf_sdio_dpc(struct brcmf_sdio *bus) | |||
2591 | 2682 | ||
2592 | brcmf_sdio_clrintr(bus); | 2683 | brcmf_sdio_clrintr(bus); |
2593 | 2684 | ||
2594 | if (data_ok(bus) && bus->ctrl_frame_stat && | 2685 | if (bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL) && |
2595 | (bus->clkstate == CLK_AVAIL)) { | 2686 | (down_interruptible(&bus->tx_seq_lock) == 0)) { |
2596 | 2687 | if (data_ok(bus)) { | |
2597 | sdio_claim_host(bus->sdiodev->func[1]); | 2688 | sdio_claim_host(bus->sdiodev->func[1]); |
2598 | err = brcmf_sdiod_send_buf(bus->sdiodev, bus->ctrl_frame_buf, | 2689 | err = brcmf_sdio_tx_ctrlframe(bus, bus->ctrl_frame_buf, |
2599 | (u32)bus->ctrl_frame_len); | 2690 | bus->ctrl_frame_len); |
2600 | 2691 | sdio_release_host(bus->sdiodev->func[1]); | |
2601 | if (err < 0) | ||
2602 | brcmf_sdio_txfail(bus); | ||
2603 | else | ||
2604 | bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQ_WRAP; | ||
2605 | 2692 | ||
2606 | sdio_release_host(bus->sdiodev->func[1]); | 2693 | bus->ctrl_frame_stat = false; |
2607 | bus->ctrl_frame_stat = false; | 2694 | brcmf_sdio_wait_event_wakeup(bus); |
2608 | brcmf_sdio_wait_event_wakeup(bus); | 2695 | } |
2696 | up(&bus->tx_seq_lock); | ||
2609 | } | 2697 | } |
2610 | /* Send queued frames (limit 1 if rx may still be pending) */ | 2698 | /* Send queued frames (limit 1 if rx may still be pending) */ |
2611 | else if ((bus->clkstate == CLK_AVAIL) && !atomic_read(&bus->fcstate) && | 2699 | if ((bus->clkstate == CLK_AVAIL) && !atomic_read(&bus->fcstate) && |
2612 | brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit | 2700 | brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit && |
2613 | && data_ok(bus)) { | 2701 | data_ok(bus)) { |
2614 | framecnt = bus->rxpending ? min(txlimit, bus->txminmax) : | 2702 | framecnt = bus->rxpending ? min(txlimit, bus->txminmax) : |
2615 | txlimit; | 2703 | txlimit; |
2616 | brcmf_sdio_sendfromq(bus, framecnt); | 2704 | brcmf_sdio_sendfromq(bus, framecnt); |
@@ -2644,7 +2732,6 @@ static int brcmf_sdio_bus_txdata(struct device *dev, struct sk_buff *pkt) | |||
2644 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | 2732 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); |
2645 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | 2733 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; |
2646 | struct brcmf_sdio *bus = sdiodev->bus; | 2734 | struct brcmf_sdio *bus = sdiodev->bus; |
2647 | ulong flags; | ||
2648 | 2735 | ||
2649 | brcmf_dbg(TRACE, "Enter: pkt: data %p len %d\n", pkt->data, pkt->len); | 2736 | brcmf_dbg(TRACE, "Enter: pkt: data %p len %d\n", pkt->data, pkt->len); |
2650 | 2737 | ||
@@ -2660,7 +2747,7 @@ static int brcmf_sdio_bus_txdata(struct device *dev, struct sk_buff *pkt) | |||
2660 | bus->sdcnt.fcqueued++; | 2747 | bus->sdcnt.fcqueued++; |
2661 | 2748 | ||
2662 | /* Priority based enq */ | 2749 | /* Priority based enq */ |
2663 | spin_lock_irqsave(&bus->txqlock, flags); | 2750 | spin_lock_bh(&bus->txq_lock); |
2664 | /* reset bus_flags in packet cb */ | 2751 | /* reset bus_flags in packet cb */ |
2665 | *(u16 *)(pkt->cb) = 0; | 2752 | *(u16 *)(pkt->cb) = 0; |
2666 | if (!brcmf_c_prec_enq(bus->sdiodev->dev, &bus->txq, pkt, prec)) { | 2753 | if (!brcmf_c_prec_enq(bus->sdiodev->dev, &bus->txq, pkt, prec)) { |
@@ -2675,7 +2762,7 @@ static int brcmf_sdio_bus_txdata(struct device *dev, struct sk_buff *pkt) | |||
2675 | bus->txoff = true; | 2762 | bus->txoff = true; |
2676 | brcmf_txflowblock(bus->sdiodev->dev, true); | 2763 | brcmf_txflowblock(bus->sdiodev->dev, true); |
2677 | } | 2764 | } |
2678 | spin_unlock_irqrestore(&bus->txqlock, flags); | 2765 | spin_unlock_bh(&bus->txq_lock); |
2679 | 2766 | ||
2680 | #ifdef DEBUG | 2767 | #ifdef DEBUG |
2681 | if (pktq_plen(&bus->txq, prec) > qcount[prec]) | 2768 | if (pktq_plen(&bus->txq, prec) > qcount[prec]) |
@@ -2770,87 +2857,27 @@ break2: | |||
2770 | } | 2857 | } |
2771 | #endif /* DEBUG */ | 2858 | #endif /* DEBUG */ |
2772 | 2859 | ||
2773 | static int brcmf_sdio_tx_frame(struct brcmf_sdio *bus, u8 *frame, u16 len) | ||
2774 | { | ||
2775 | int ret; | ||
2776 | |||
2777 | bus->ctrl_frame_stat = false; | ||
2778 | ret = brcmf_sdiod_send_buf(bus->sdiodev, frame, len); | ||
2779 | |||
2780 | if (ret < 0) | ||
2781 | brcmf_sdio_txfail(bus); | ||
2782 | else | ||
2783 | bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQ_WRAP; | ||
2784 | |||
2785 | return ret; | ||
2786 | } | ||
2787 | |||
2788 | static int | 2860 | static int |
2789 | brcmf_sdio_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) | 2861 | brcmf_sdio_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) |
2790 | { | 2862 | { |
2791 | u8 *frame; | ||
2792 | u16 len, pad; | ||
2793 | uint retries = 0; | ||
2794 | u8 doff = 0; | ||
2795 | int ret = -1; | ||
2796 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | 2863 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); |
2797 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | 2864 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; |
2798 | struct brcmf_sdio *bus = sdiodev->bus; | 2865 | struct brcmf_sdio *bus = sdiodev->bus; |
2799 | struct brcmf_sdio_hdrinfo hd_info = {0}; | 2866 | int ret = -1; |
2800 | 2867 | ||
2801 | brcmf_dbg(TRACE, "Enter\n"); | 2868 | brcmf_dbg(TRACE, "Enter\n"); |
2802 | 2869 | ||
2803 | /* Back the pointer to make a room for bus header */ | 2870 | if (down_interruptible(&bus->tx_seq_lock)) |
2804 | frame = msg - bus->tx_hdrlen; | 2871 | return -EINTR; |
2805 | len = (msglen += bus->tx_hdrlen); | ||
2806 | |||
2807 | /* Add alignment padding (optional for ctl frames) */ | ||
2808 | doff = ((unsigned long)frame % bus->head_align); | ||
2809 | if (doff) { | ||
2810 | frame -= doff; | ||
2811 | len += doff; | ||
2812 | msglen += doff; | ||
2813 | memset(frame, 0, doff + bus->tx_hdrlen); | ||
2814 | } | ||
2815 | /* precondition: doff < bus->head_align */ | ||
2816 | doff += bus->tx_hdrlen; | ||
2817 | |||
2818 | /* Round send length to next SDIO block */ | ||
2819 | pad = 0; | ||
2820 | if (bus->roundup && bus->blocksize && (len > bus->blocksize)) { | ||
2821 | pad = bus->blocksize - (len % bus->blocksize); | ||
2822 | if ((pad > bus->roundup) || (pad >= bus->blocksize)) | ||
2823 | pad = 0; | ||
2824 | } else if (len % bus->head_align) { | ||
2825 | pad = bus->head_align - (len % bus->head_align); | ||
2826 | } | ||
2827 | len += pad; | ||
2828 | |||
2829 | /* precondition: IS_ALIGNED((unsigned long)frame, 2) */ | ||
2830 | |||
2831 | /* Make sure backplane clock is on */ | ||
2832 | sdio_claim_host(bus->sdiodev->func[1]); | ||
2833 | brcmf_sdio_bus_sleep(bus, false, false); | ||
2834 | sdio_release_host(bus->sdiodev->func[1]); | ||
2835 | |||
2836 | hd_info.len = (u16)msglen; | ||
2837 | hd_info.channel = SDPCM_CONTROL_CHANNEL; | ||
2838 | hd_info.dat_offset = doff; | ||
2839 | hd_info.seq_num = bus->tx_seq; | ||
2840 | hd_info.lastfrm = true; | ||
2841 | hd_info.tail_pad = pad; | ||
2842 | brcmf_sdio_hdpack(bus, frame, &hd_info); | ||
2843 | |||
2844 | if (bus->txglom) | ||
2845 | brcmf_sdio_update_hwhdr(frame, len); | ||
2846 | 2872 | ||
2847 | if (!data_ok(bus)) { | 2873 | if (!data_ok(bus)) { |
2848 | brcmf_dbg(INFO, "No bus credit bus->tx_max %d, bus->tx_seq %d\n", | 2874 | brcmf_dbg(INFO, "No bus credit bus->tx_max %d, bus->tx_seq %d\n", |
2849 | bus->tx_max, bus->tx_seq); | 2875 | bus->tx_max, bus->tx_seq); |
2850 | bus->ctrl_frame_stat = true; | 2876 | up(&bus->tx_seq_lock); |
2851 | /* Send from dpc */ | 2877 | /* Send from dpc */ |
2852 | bus->ctrl_frame_buf = frame; | 2878 | bus->ctrl_frame_buf = msg; |
2853 | bus->ctrl_frame_len = len; | 2879 | bus->ctrl_frame_len = msglen; |
2880 | bus->ctrl_frame_stat = true; | ||
2854 | 2881 | ||
2855 | wait_event_interruptible_timeout(bus->ctrl_wait, | 2882 | wait_event_interruptible_timeout(bus->ctrl_wait, |
2856 | !bus->ctrl_frame_stat, | 2883 | !bus->ctrl_frame_stat, |
@@ -2861,22 +2888,18 @@ brcmf_sdio_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) | |||
2861 | ret = 0; | 2888 | ret = 0; |
2862 | } else { | 2889 | } else { |
2863 | brcmf_dbg(SDIO, "ctrl_frame_stat == true\n"); | 2890 | brcmf_dbg(SDIO, "ctrl_frame_stat == true\n"); |
2891 | bus->ctrl_frame_stat = false; | ||
2892 | if (down_interruptible(&bus->tx_seq_lock)) | ||
2893 | return -EINTR; | ||
2864 | ret = -1; | 2894 | ret = -1; |
2865 | } | 2895 | } |
2866 | } | 2896 | } |
2867 | |||
2868 | if (ret == -1) { | 2897 | if (ret == -1) { |
2869 | brcmf_dbg_hex_dump(BRCMF_BYTES_ON() && BRCMF_CTL_ON(), | 2898 | sdio_claim_host(bus->sdiodev->func[1]); |
2870 | frame, len, "Tx Frame:\n"); | 2899 | brcmf_sdio_bus_sleep(bus, false, false); |
2871 | brcmf_dbg_hex_dump(!(BRCMF_BYTES_ON() && BRCMF_CTL_ON()) && | 2900 | ret = brcmf_sdio_tx_ctrlframe(bus, msg, msglen); |
2872 | BRCMF_HDRS_ON(), | 2901 | sdio_release_host(bus->sdiodev->func[1]); |
2873 | frame, min_t(u16, len, 16), "TxHdr:\n"); | 2902 | up(&bus->tx_seq_lock); |
2874 | |||
2875 | do { | ||
2876 | sdio_claim_host(bus->sdiodev->func[1]); | ||
2877 | ret = brcmf_sdio_tx_frame(bus, frame, len); | ||
2878 | sdio_release_host(bus->sdiodev->func[1]); | ||
2879 | } while (ret < 0 && retries++ < TXRETRIES); | ||
2880 | } | 2903 | } |
2881 | 2904 | ||
2882 | if (ret) | 2905 | if (ret) |
@@ -3971,6 +3994,7 @@ brcmf_sdio_watchdog_thread(void *data) | |||
3971 | brcmf_sdio_bus_watchdog(bus); | 3994 | brcmf_sdio_bus_watchdog(bus); |
3972 | /* Count the tick for reference */ | 3995 | /* Count the tick for reference */ |
3973 | bus->sdcnt.tickcnt++; | 3996 | bus->sdcnt.tickcnt++; |
3997 | reinit_completion(&bus->watchdog_wait); | ||
3974 | } else | 3998 | } else |
3975 | break; | 3999 | break; |
3976 | } | 4000 | } |
@@ -4047,7 +4071,8 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) | |||
4047 | } | 4071 | } |
4048 | 4072 | ||
4049 | spin_lock_init(&bus->rxctl_lock); | 4073 | spin_lock_init(&bus->rxctl_lock); |
4050 | spin_lock_init(&bus->txqlock); | 4074 | spin_lock_init(&bus->txq_lock); |
4075 | sema_init(&bus->tx_seq_lock, 1); | ||
4051 | init_waitqueue_head(&bus->ctrl_wait); | 4076 | init_waitqueue_head(&bus->ctrl_wait); |
4052 | init_waitqueue_head(&bus->dcmd_resp_wait); | 4077 | init_waitqueue_head(&bus->dcmd_resp_wait); |
4053 | 4078 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h index af17a5bc8b83..614e4888504f 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h | |||
@@ -48,6 +48,11 @@ | |||
48 | 48 | ||
49 | #define BRCMF_MAXRATES_IN_SET 16 /* max # of rates in rateset */ | 49 | #define BRCMF_MAXRATES_IN_SET 16 /* max # of rates in rateset */ |
50 | 50 | ||
51 | /* OBSS Coex Auto/On/Off */ | ||
52 | #define BRCMF_OBSS_COEX_AUTO (-1) | ||
53 | #define BRCMF_OBSS_COEX_OFF 0 | ||
54 | #define BRCMF_OBSS_COEX_ON 1 | ||
55 | |||
51 | enum brcmf_fil_p2p_if_types { | 56 | enum brcmf_fil_p2p_if_types { |
52 | BRCMF_FIL_P2P_IF_CLIENT, | 57 | BRCMF_FIL_P2P_IF_CLIENT, |
53 | BRCMF_FIL_P2P_IF_GO, | 58 | BRCMF_FIL_P2P_IF_GO, |
@@ -87,6 +92,11 @@ struct brcmf_fil_bss_enable_le { | |||
87 | __le32 enable; | 92 | __le32 enable; |
88 | }; | 93 | }; |
89 | 94 | ||
95 | struct brcmf_fil_bwcap_le { | ||
96 | __le32 band; | ||
97 | __le32 bw_cap; | ||
98 | }; | ||
99 | |||
90 | /** | 100 | /** |
91 | * struct tdls_iovar - common structure for tdls iovars. | 101 | * struct tdls_iovar - common structure for tdls iovars. |
92 | * | 102 | * |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c index fc4f98b275d7..f3445ac627e4 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c | |||
@@ -797,7 +797,8 @@ static s32 brcmf_p2p_run_escan(struct brcmf_cfg80211_info *cfg, | |||
797 | /* SOCIAL CHANNELS 1, 6, 11 */ | 797 | /* SOCIAL CHANNELS 1, 6, 11 */ |
798 | search_state = WL_P2P_DISC_ST_SEARCH; | 798 | search_state = WL_P2P_DISC_ST_SEARCH; |
799 | brcmf_dbg(INFO, "P2P SEARCH PHASE START\n"); | 799 | brcmf_dbg(INFO, "P2P SEARCH PHASE START\n"); |
800 | } else if (dev != NULL && vif->mode == WL_MODE_AP) { | 800 | } else if (dev != NULL && |
801 | vif->wdev.iftype == NL80211_IFTYPE_P2P_GO) { | ||
801 | /* If you are already a GO, then do SEARCH only */ | 802 | /* If you are already a GO, then do SEARCH only */ |
802 | brcmf_dbg(INFO, "Already a GO. Do SEARCH Only\n"); | 803 | brcmf_dbg(INFO, "Already a GO. Do SEARCH Only\n"); |
803 | search_state = WL_P2P_DISC_ST_SEARCH; | 804 | search_state = WL_P2P_DISC_ST_SEARCH; |
@@ -2256,7 +2257,6 @@ struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name, | |||
2256 | struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); | 2257 | struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); |
2257 | struct brcmf_cfg80211_vif *vif; | 2258 | struct brcmf_cfg80211_vif *vif; |
2258 | enum brcmf_fil_p2p_if_types iftype; | 2259 | enum brcmf_fil_p2p_if_types iftype; |
2259 | enum wl_mode mode; | ||
2260 | int err; | 2260 | int err; |
2261 | 2261 | ||
2262 | if (brcmf_cfg80211_vif_event_armed(cfg)) | 2262 | if (brcmf_cfg80211_vif_event_armed(cfg)) |
@@ -2267,11 +2267,9 @@ struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name, | |||
2267 | switch (type) { | 2267 | switch (type) { |
2268 | case NL80211_IFTYPE_P2P_CLIENT: | 2268 | case NL80211_IFTYPE_P2P_CLIENT: |
2269 | iftype = BRCMF_FIL_P2P_IF_CLIENT; | 2269 | iftype = BRCMF_FIL_P2P_IF_CLIENT; |
2270 | mode = WL_MODE_BSS; | ||
2271 | break; | 2270 | break; |
2272 | case NL80211_IFTYPE_P2P_GO: | 2271 | case NL80211_IFTYPE_P2P_GO: |
2273 | iftype = BRCMF_FIL_P2P_IF_GO; | 2272 | iftype = BRCMF_FIL_P2P_IF_GO; |
2274 | mode = WL_MODE_AP; | ||
2275 | break; | 2273 | break; |
2276 | case NL80211_IFTYPE_P2P_DEVICE: | 2274 | case NL80211_IFTYPE_P2P_DEVICE: |
2277 | return brcmf_p2p_create_p2pdev(&cfg->p2p, wiphy, | 2275 | return brcmf_p2p_create_p2pdev(&cfg->p2p, wiphy, |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 00bd1e16c3ce..e0e649aab8db 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | |||
@@ -191,6 +191,7 @@ static struct ieee80211_supported_band __wl_band_2ghz = { | |||
191 | .n_channels = ARRAY_SIZE(__wl_2ghz_channels), | 191 | .n_channels = ARRAY_SIZE(__wl_2ghz_channels), |
192 | .bitrates = wl_g_rates, | 192 | .bitrates = wl_g_rates, |
193 | .n_bitrates = wl_g_rates_size, | 193 | .n_bitrates = wl_g_rates_size, |
194 | .ht_cap = {IEEE80211_HT_CAP_SUP_WIDTH_20_40, true}, | ||
194 | }; | 195 | }; |
195 | 196 | ||
196 | static struct ieee80211_supported_band __wl_band_5ghz_a = { | 197 | static struct ieee80211_supported_band __wl_band_5ghz_a = { |
@@ -494,6 +495,19 @@ brcmf_configure_arp_offload(struct brcmf_if *ifp, bool enable) | |||
494 | return err; | 495 | return err; |
495 | } | 496 | } |
496 | 497 | ||
498 | static bool brcmf_is_apmode(struct brcmf_cfg80211_vif *vif) | ||
499 | { | ||
500 | enum nl80211_iftype iftype; | ||
501 | |||
502 | iftype = vif->wdev.iftype; | ||
503 | return iftype == NL80211_IFTYPE_AP || iftype == NL80211_IFTYPE_P2P_GO; | ||
504 | } | ||
505 | |||
506 | static bool brcmf_is_ibssmode(struct brcmf_cfg80211_vif *vif) | ||
507 | { | ||
508 | return vif->wdev.iftype == NL80211_IFTYPE_ADHOC; | ||
509 | } | ||
510 | |||
497 | static struct wireless_dev *brcmf_cfg80211_add_iface(struct wiphy *wiphy, | 511 | static struct wireless_dev *brcmf_cfg80211_add_iface(struct wiphy *wiphy, |
498 | const char *name, | 512 | const char *name, |
499 | enum nl80211_iftype type, | 513 | enum nl80211_iftype type, |
@@ -654,7 +668,6 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, | |||
654 | type); | 668 | type); |
655 | return -EOPNOTSUPP; | 669 | return -EOPNOTSUPP; |
656 | case NL80211_IFTYPE_ADHOC: | 670 | case NL80211_IFTYPE_ADHOC: |
657 | vif->mode = WL_MODE_IBSS; | ||
658 | infra = 0; | 671 | infra = 0; |
659 | break; | 672 | break; |
660 | case NL80211_IFTYPE_STATION: | 673 | case NL80211_IFTYPE_STATION: |
@@ -670,12 +683,10 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, | |||
670 | */ | 683 | */ |
671 | return 0; | 684 | return 0; |
672 | } | 685 | } |
673 | vif->mode = WL_MODE_BSS; | ||
674 | infra = 1; | 686 | infra = 1; |
675 | break; | 687 | break; |
676 | case NL80211_IFTYPE_AP: | 688 | case NL80211_IFTYPE_AP: |
677 | case NL80211_IFTYPE_P2P_GO: | 689 | case NL80211_IFTYPE_P2P_GO: |
678 | vif->mode = WL_MODE_AP; | ||
679 | ap = 1; | 690 | ap = 1; |
680 | break; | 691 | break; |
681 | default: | 692 | default: |
@@ -699,7 +710,7 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, | |||
699 | err = -EAGAIN; | 710 | err = -EAGAIN; |
700 | goto done; | 711 | goto done; |
701 | } | 712 | } |
702 | brcmf_dbg(INFO, "IF Type = %s\n", (vif->mode == WL_MODE_IBSS) ? | 713 | brcmf_dbg(INFO, "IF Type = %s\n", brcmf_is_ibssmode(vif) ? |
703 | "Adhoc" : "Infra"); | 714 | "Adhoc" : "Infra"); |
704 | } | 715 | } |
705 | ndev->ieee80211_ptr->iftype = type; | 716 | ndev->ieee80211_ptr->iftype = type; |
@@ -1682,22 +1693,9 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, | |||
1682 | ext_join_params->ssid_le.SSID_len = cpu_to_le32(profile->ssid.SSID_len); | 1693 | ext_join_params->ssid_le.SSID_len = cpu_to_le32(profile->ssid.SSID_len); |
1683 | memcpy(&ext_join_params->ssid_le.SSID, sme->ssid, | 1694 | memcpy(&ext_join_params->ssid_le.SSID, sme->ssid, |
1684 | profile->ssid.SSID_len); | 1695 | profile->ssid.SSID_len); |
1685 | /*increase dwell time to receive probe response or detect Beacon | 1696 | |
1686 | * from target AP at a noisy air only during connect command | ||
1687 | */ | ||
1688 | ext_join_params->scan_le.active_time = | ||
1689 | cpu_to_le32(BRCMF_SCAN_JOIN_ACTIVE_DWELL_TIME_MS); | ||
1690 | ext_join_params->scan_le.passive_time = | ||
1691 | cpu_to_le32(BRCMF_SCAN_JOIN_PASSIVE_DWELL_TIME_MS); | ||
1692 | /* Set up join scan parameters */ | 1697 | /* Set up join scan parameters */ |
1693 | ext_join_params->scan_le.scan_type = -1; | 1698 | ext_join_params->scan_le.scan_type = -1; |
1694 | /* to sync with presence period of VSDB GO. | ||
1695 | * Send probe request more frequently. Probe request will be stopped | ||
1696 | * when it gets probe response from target AP/GO. | ||
1697 | */ | ||
1698 | ext_join_params->scan_le.nprobes = | ||
1699 | cpu_to_le32(BRCMF_SCAN_JOIN_ACTIVE_DWELL_TIME_MS / | ||
1700 | BRCMF_SCAN_JOIN_PROBE_INTERVAL_MS); | ||
1701 | ext_join_params->scan_le.home_time = cpu_to_le32(-1); | 1699 | ext_join_params->scan_le.home_time = cpu_to_le32(-1); |
1702 | 1700 | ||
1703 | if (sme->bssid) | 1701 | if (sme->bssid) |
@@ -1710,6 +1708,25 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, | |||
1710 | 1708 | ||
1711 | ext_join_params->assoc_le.chanspec_list[0] = | 1709 | ext_join_params->assoc_le.chanspec_list[0] = |
1712 | cpu_to_le16(chanspec); | 1710 | cpu_to_le16(chanspec); |
1711 | /* Increase dwell time to receive probe response or detect | ||
1712 | * beacon from target AP at a noisy air only during connect | ||
1713 | * command. | ||
1714 | */ | ||
1715 | ext_join_params->scan_le.active_time = | ||
1716 | cpu_to_le32(BRCMF_SCAN_JOIN_ACTIVE_DWELL_TIME_MS); | ||
1717 | ext_join_params->scan_le.passive_time = | ||
1718 | cpu_to_le32(BRCMF_SCAN_JOIN_PASSIVE_DWELL_TIME_MS); | ||
1719 | /* To sync with presence period of VSDB GO send probe request | ||
1720 | * more frequently. Probe request will be stopped when it gets | ||
1721 | * probe response from target AP/GO. | ||
1722 | */ | ||
1723 | ext_join_params->scan_le.nprobes = | ||
1724 | cpu_to_le32(BRCMF_SCAN_JOIN_ACTIVE_DWELL_TIME_MS / | ||
1725 | BRCMF_SCAN_JOIN_PROBE_INTERVAL_MS); | ||
1726 | } else { | ||
1727 | ext_join_params->scan_le.active_time = cpu_to_le32(-1); | ||
1728 | ext_join_params->scan_le.passive_time = cpu_to_le32(-1); | ||
1729 | ext_join_params->scan_le.nprobes = cpu_to_le32(-1); | ||
1713 | } | 1730 | } |
1714 | 1731 | ||
1715 | err = brcmf_fil_bsscfg_data_set(ifp, "join", ext_join_params, | 1732 | err = brcmf_fil_bsscfg_data_set(ifp, "join", ext_join_params, |
@@ -1917,7 +1934,7 @@ brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev, | |||
1917 | brcmf_dbg(CONN, "Setting the key index %d\n", key.index); | 1934 | brcmf_dbg(CONN, "Setting the key index %d\n", key.index); |
1918 | memcpy(key.data, params->key, key.len); | 1935 | memcpy(key.data, params->key, key.len); |
1919 | 1936 | ||
1920 | if ((ifp->vif->mode != WL_MODE_AP) && | 1937 | if (!brcmf_is_apmode(ifp->vif) && |
1921 | (params->cipher == WLAN_CIPHER_SUITE_TKIP)) { | 1938 | (params->cipher == WLAN_CIPHER_SUITE_TKIP)) { |
1922 | brcmf_dbg(CONN, "Swapping RX/TX MIC key\n"); | 1939 | brcmf_dbg(CONN, "Swapping RX/TX MIC key\n"); |
1923 | memcpy(keybuf, &key.data[24], sizeof(keybuf)); | 1940 | memcpy(keybuf, &key.data[24], sizeof(keybuf)); |
@@ -2016,7 +2033,7 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, | |||
2016 | brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP104\n"); | 2033 | brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP104\n"); |
2017 | break; | 2034 | break; |
2018 | case WLAN_CIPHER_SUITE_TKIP: | 2035 | case WLAN_CIPHER_SUITE_TKIP: |
2019 | if (ifp->vif->mode != WL_MODE_AP) { | 2036 | if (!brcmf_is_apmode(ifp->vif)) { |
2020 | brcmf_dbg(CONN, "Swapping RX/TX MIC key\n"); | 2037 | brcmf_dbg(CONN, "Swapping RX/TX MIC key\n"); |
2021 | memcpy(keybuf, &key.data[24], sizeof(keybuf)); | 2038 | memcpy(keybuf, &key.data[24], sizeof(keybuf)); |
2022 | memcpy(&key.data[24], &key.data[16], sizeof(keybuf)); | 2039 | memcpy(&key.data[24], &key.data[16], sizeof(keybuf)); |
@@ -2177,7 +2194,7 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, | |||
2177 | if (!check_vif_up(ifp->vif)) | 2194 | if (!check_vif_up(ifp->vif)) |
2178 | return -EIO; | 2195 | return -EIO; |
2179 | 2196 | ||
2180 | if (ifp->vif->mode == WL_MODE_AP) { | 2197 | if (brcmf_is_apmode(ifp->vif)) { |
2181 | memcpy(&sta_info_le, mac, ETH_ALEN); | 2198 | memcpy(&sta_info_le, mac, ETH_ALEN); |
2182 | err = brcmf_fil_iovar_data_get(ifp, "sta_info", | 2199 | err = brcmf_fil_iovar_data_get(ifp, "sta_info", |
2183 | &sta_info_le, | 2200 | &sta_info_le, |
@@ -2194,7 +2211,7 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, | |||
2194 | } | 2211 | } |
2195 | brcmf_dbg(TRACE, "STA idle time : %d ms, connected time :%d sec\n", | 2212 | brcmf_dbg(TRACE, "STA idle time : %d ms, connected time :%d sec\n", |
2196 | sinfo->inactive_time, sinfo->connected_time); | 2213 | sinfo->inactive_time, sinfo->connected_time); |
2197 | } else if (ifp->vif->mode == WL_MODE_BSS) { | 2214 | } else if (ifp->vif->wdev.iftype == NL80211_IFTYPE_STATION) { |
2198 | if (memcmp(mac, bssid, ETH_ALEN)) { | 2215 | if (memcmp(mac, bssid, ETH_ALEN)) { |
2199 | brcmf_err("Wrong Mac address cfg_mac-%pM wl_bssid-%pM\n", | 2216 | brcmf_err("Wrong Mac address cfg_mac-%pM wl_bssid-%pM\n", |
2200 | mac, bssid); | 2217 | mac, bssid); |
@@ -2476,11 +2493,6 @@ CleanUp: | |||
2476 | return err; | 2493 | return err; |
2477 | } | 2494 | } |
2478 | 2495 | ||
2479 | static bool brcmf_is_ibssmode(struct brcmf_cfg80211_vif *vif) | ||
2480 | { | ||
2481 | return vif->mode == WL_MODE_IBSS; | ||
2482 | } | ||
2483 | |||
2484 | static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg, | 2496 | static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg, |
2485 | struct brcmf_if *ifp) | 2497 | struct brcmf_if *ifp) |
2486 | { | 2498 | { |
@@ -4253,32 +4265,6 @@ static struct cfg80211_ops wl_cfg80211_ops = { | |||
4253 | CFG80211_TESTMODE_CMD(brcmf_cfg80211_testmode) | 4265 | CFG80211_TESTMODE_CMD(brcmf_cfg80211_testmode) |
4254 | }; | 4266 | }; |
4255 | 4267 | ||
4256 | static s32 brcmf_nl80211_iftype_to_mode(enum nl80211_iftype type) | ||
4257 | { | ||
4258 | switch (type) { | ||
4259 | case NL80211_IFTYPE_AP_VLAN: | ||
4260 | case NL80211_IFTYPE_WDS: | ||
4261 | case NL80211_IFTYPE_MONITOR: | ||
4262 | case NL80211_IFTYPE_MESH_POINT: | ||
4263 | return -ENOTSUPP; | ||
4264 | case NL80211_IFTYPE_ADHOC: | ||
4265 | return WL_MODE_IBSS; | ||
4266 | case NL80211_IFTYPE_STATION: | ||
4267 | case NL80211_IFTYPE_P2P_CLIENT: | ||
4268 | return WL_MODE_BSS; | ||
4269 | case NL80211_IFTYPE_AP: | ||
4270 | case NL80211_IFTYPE_P2P_GO: | ||
4271 | return WL_MODE_AP; | ||
4272 | case NL80211_IFTYPE_P2P_DEVICE: | ||
4273 | return WL_MODE_P2P; | ||
4274 | case NL80211_IFTYPE_UNSPECIFIED: | ||
4275 | default: | ||
4276 | break; | ||
4277 | } | ||
4278 | |||
4279 | return -EINVAL; | ||
4280 | } | ||
4281 | |||
4282 | static void brcmf_wiphy_pno_params(struct wiphy *wiphy) | 4268 | static void brcmf_wiphy_pno_params(struct wiphy *wiphy) |
4283 | { | 4269 | { |
4284 | /* scheduled scan settings */ | 4270 | /* scheduled scan settings */ |
@@ -4403,7 +4389,6 @@ struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg, | |||
4403 | vif->wdev.wiphy = cfg->wiphy; | 4389 | vif->wdev.wiphy = cfg->wiphy; |
4404 | vif->wdev.iftype = type; | 4390 | vif->wdev.iftype = type; |
4405 | 4391 | ||
4406 | vif->mode = brcmf_nl80211_iftype_to_mode(type); | ||
4407 | vif->pm_block = pm_block; | 4392 | vif->pm_block = pm_block; |
4408 | vif->roam_off = -1; | 4393 | vif->roam_off = -1; |
4409 | 4394 | ||
@@ -4697,7 +4682,7 @@ brcmf_notify_connect_status(struct brcmf_if *ifp, | |||
4697 | s32 err = 0; | 4682 | s32 err = 0; |
4698 | u16 reason; | 4683 | u16 reason; |
4699 | 4684 | ||
4700 | if (ifp->vif->mode == WL_MODE_AP) { | 4685 | if (brcmf_is_apmode(ifp->vif)) { |
4701 | err = brcmf_notify_connect_status_ap(cfg, ndev, e, data); | 4686 | err = brcmf_notify_connect_status_ap(cfg, ndev, e, data); |
4702 | } else if (brcmf_is_linkup(e)) { | 4687 | } else if (brcmf_is_linkup(e)) { |
4703 | brcmf_dbg(CONN, "Linkup\n"); | 4688 | brcmf_dbg(CONN, "Linkup\n"); |
@@ -4945,6 +4930,30 @@ static void init_vif_event(struct brcmf_cfg80211_vif_event *event) | |||
4945 | mutex_init(&event->vif_event_lock); | 4930 | mutex_init(&event->vif_event_lock); |
4946 | } | 4931 | } |
4947 | 4932 | ||
4933 | static int brcmf_enable_bw40_2g(struct brcmf_if *ifp) | ||
4934 | { | ||
4935 | struct brcmf_fil_bwcap_le band_bwcap; | ||
4936 | u32 val; | ||
4937 | int err; | ||
4938 | |||
4939 | /* verify support for bw_cap command */ | ||
4940 | val = WLC_BAND_5G; | ||
4941 | err = brcmf_fil_iovar_int_get(ifp, "bw_cap", &val); | ||
4942 | |||
4943 | if (!err) { | ||
4944 | /* only set 2G bandwidth using bw_cap command */ | ||
4945 | band_bwcap.band = cpu_to_le32(WLC_BAND_2G); | ||
4946 | band_bwcap.bw_cap = cpu_to_le32(WLC_BW_40MHZ_BIT); | ||
4947 | err = brcmf_fil_iovar_data_set(ifp, "bw_cap", &band_bwcap, | ||
4948 | sizeof(band_bwcap)); | ||
4949 | } else { | ||
4950 | brcmf_dbg(INFO, "fallback to mimo_bw_cap\n"); | ||
4951 | val = WLC_N_BW_40ALL; | ||
4952 | err = brcmf_fil_iovar_int_set(ifp, "mimo_bw_cap", val); | ||
4953 | } | ||
4954 | return err; | ||
4955 | } | ||
4956 | |||
4948 | struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, | 4957 | struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, |
4949 | struct device *busdev) | 4958 | struct device *busdev) |
4950 | { | 4959 | { |
@@ -5002,6 +5011,17 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, | |||
5002 | goto cfg80211_p2p_attach_out; | 5011 | goto cfg80211_p2p_attach_out; |
5003 | } | 5012 | } |
5004 | 5013 | ||
5014 | /* If cfg80211 didn't disable 40MHz HT CAP in wiphy_register(), | ||
5015 | * setup 40MHz in 2GHz band and enable OBSS scanning. | ||
5016 | */ | ||
5017 | if (wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap.cap & | ||
5018 | IEEE80211_HT_CAP_SUP_WIDTH_20_40) { | ||
5019 | err = brcmf_enable_bw40_2g(ifp); | ||
5020 | if (!err) | ||
5021 | err = brcmf_fil_iovar_int_set(ifp, "obss_coex", | ||
5022 | BRCMF_OBSS_COEX_AUTO); | ||
5023 | } | ||
5024 | |||
5005 | err = brcmf_fil_iovar_int_set(ifp, "tdls_enable", 1); | 5025 | err = brcmf_fil_iovar_int_set(ifp, "tdls_enable", 1); |
5006 | if (err) { | 5026 | if (err) { |
5007 | brcmf_dbg(INFO, "TDLS not enabled (%d)\n", err); | 5027 | brcmf_dbg(INFO, "TDLS not enabled (%d)\n", err); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h index 5715bb0708cf..283c525a44f7 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h | |||
@@ -89,21 +89,6 @@ enum brcmf_scan_status { | |||
89 | BRCMF_SCAN_STATUS_SUPPRESS, | 89 | BRCMF_SCAN_STATUS_SUPPRESS, |
90 | }; | 90 | }; |
91 | 91 | ||
92 | /** | ||
93 | * enum wl_mode - driver mode of virtual interface. | ||
94 | * | ||
95 | * @WL_MODE_BSS: connects to BSS. | ||
96 | * @WL_MODE_IBSS: operate as ad-hoc. | ||
97 | * @WL_MODE_AP: operate as access-point. | ||
98 | * @WL_MODE_P2P: provide P2P discovery. | ||
99 | */ | ||
100 | enum wl_mode { | ||
101 | WL_MODE_BSS, | ||
102 | WL_MODE_IBSS, | ||
103 | WL_MODE_AP, | ||
104 | WL_MODE_P2P | ||
105 | }; | ||
106 | |||
107 | /* dongle configuration */ | 92 | /* dongle configuration */ |
108 | struct brcmf_cfg80211_conf { | 93 | struct brcmf_cfg80211_conf { |
109 | u32 frag_threshold; | 94 | u32 frag_threshold; |
@@ -193,7 +178,6 @@ struct vif_saved_ie { | |||
193 | * @ifp: lower layer interface pointer | 178 | * @ifp: lower layer interface pointer |
194 | * @wdev: wireless device. | 179 | * @wdev: wireless device. |
195 | * @profile: profile information. | 180 | * @profile: profile information. |
196 | * @mode: operating mode. | ||
197 | * @roam_off: roaming state. | 181 | * @roam_off: roaming state. |
198 | * @sme_state: SME state using enum brcmf_vif_status bits. | 182 | * @sme_state: SME state using enum brcmf_vif_status bits. |
199 | * @pm_block: power-management blocked. | 183 | * @pm_block: power-management blocked. |
@@ -204,7 +188,6 @@ struct brcmf_cfg80211_vif { | |||
204 | struct brcmf_if *ifp; | 188 | struct brcmf_if *ifp; |
205 | struct wireless_dev wdev; | 189 | struct wireless_dev wdev; |
206 | struct brcmf_cfg80211_profile profile; | 190 | struct brcmf_cfg80211_profile profile; |
207 | s32 mode; | ||
208 | s32 roam_off; | 191 | s32 roam_off; |
209 | unsigned long sme_state; | 192 | unsigned long sme_state; |
210 | bool pm_block; | 193 | bool pm_block; |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index 925034b80e9c..8c5fa4e58139 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | |||
@@ -426,6 +426,12 @@ static int brcms_ops_start(struct ieee80211_hw *hw) | |||
426 | bool blocked; | 426 | bool blocked; |
427 | int err; | 427 | int err; |
428 | 428 | ||
429 | if (!wl->ucode.bcm43xx_bomminor) { | ||
430 | err = brcms_request_fw(wl, wl->wlc->hw->d11core); | ||
431 | if (err) | ||
432 | return -ENOENT; | ||
433 | } | ||
434 | |||
429 | ieee80211_wake_queues(hw); | 435 | ieee80211_wake_queues(hw); |
430 | spin_lock_bh(&wl->lock); | 436 | spin_lock_bh(&wl->lock); |
431 | blocked = brcms_rfkill_set_hw_state(wl); | 437 | blocked = brcms_rfkill_set_hw_state(wl); |
@@ -433,14 +439,6 @@ static int brcms_ops_start(struct ieee80211_hw *hw) | |||
433 | if (!blocked) | 439 | if (!blocked) |
434 | wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy); | 440 | wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy); |
435 | 441 | ||
436 | if (!wl->ucode.bcm43xx_bomminor) { | ||
437 | err = brcms_request_fw(wl, wl->wlc->hw->d11core); | ||
438 | if (err) { | ||
439 | brcms_remove(wl->wlc->hw->d11core); | ||
440 | return -ENOENT; | ||
441 | } | ||
442 | } | ||
443 | |||
444 | spin_lock_bh(&wl->lock); | 442 | spin_lock_bh(&wl->lock); |
445 | /* avoid acknowledging frames before a non-monitor device is added */ | 443 | /* avoid acknowledging frames before a non-monitor device is added */ |
446 | wl->mute_tx = true; | 444 | wl->mute_tx = true; |
@@ -1094,12 +1092,6 @@ static int ieee_hw_init(struct ieee80211_hw *hw) | |||
1094 | * Attach to the WL device identified by vendor and device parameters. | 1092 | * Attach to the WL device identified by vendor and device parameters. |
1095 | * regs is a host accessible memory address pointing to WL device registers. | 1093 | * regs is a host accessible memory address pointing to WL device registers. |
1096 | * | 1094 | * |
1097 | * brcms_attach is not defined as static because in the case where no bus | ||
1098 | * is defined, wl_attach will never be called, and thus, gcc will issue | ||
1099 | * a warning that this function is defined but not used if we declare | ||
1100 | * it as static. | ||
1101 | * | ||
1102 | * | ||
1103 | * is called in brcms_bcma_probe() context, therefore no locking required. | 1095 | * is called in brcms_bcma_probe() context, therefore no locking required. |
1104 | */ | 1096 | */ |
1105 | static struct brcms_info *brcms_attach(struct bcma_device *pdev) | 1097 | static struct brcms_info *brcms_attach(struct bcma_device *pdev) |
diff --git a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h index 6fa5d4863782..d816270db3be 100644 --- a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h +++ b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h | |||
@@ -43,5 +43,6 @@ | |||
43 | #define BCM4335_CHIP_ID 0x4335 | 43 | #define BCM4335_CHIP_ID 0x4335 |
44 | #define BCM43362_CHIP_ID 43362 | 44 | #define BCM43362_CHIP_ID 43362 |
45 | #define BCM4339_CHIP_ID 0x4339 | 45 | #define BCM4339_CHIP_ID 0x4339 |
46 | #define BCM4354_CHIP_ID 0x4354 | ||
46 | 47 | ||
47 | #endif /* _BRCM_HW_IDS_H_ */ | 48 | #endif /* _BRCM_HW_IDS_H_ */ |
diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c index ba1b1ea54252..6a6df71af1d7 100644 --- a/drivers/net/wireless/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/iwlwifi/dvm/main.c | |||
@@ -252,13 +252,17 @@ static void iwl_bg_bt_runtime_config(struct work_struct *work) | |||
252 | struct iwl_priv *priv = | 252 | struct iwl_priv *priv = |
253 | container_of(work, struct iwl_priv, bt_runtime_config); | 253 | container_of(work, struct iwl_priv, bt_runtime_config); |
254 | 254 | ||
255 | mutex_lock(&priv->mutex); | ||
255 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 256 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
256 | return; | 257 | goto out; |
257 | 258 | ||
258 | /* dont send host command if rf-kill is on */ | 259 | /* dont send host command if rf-kill is on */ |
259 | if (!iwl_is_ready_rf(priv)) | 260 | if (!iwl_is_ready_rf(priv)) |
260 | return; | 261 | goto out; |
262 | |||
261 | iwlagn_send_advance_bt_config(priv); | 263 | iwlagn_send_advance_bt_config(priv); |
264 | out: | ||
265 | mutex_unlock(&priv->mutex); | ||
262 | } | 266 | } |
263 | 267 | ||
264 | static void iwl_bg_bt_full_concurrency(struct work_struct *work) | 268 | static void iwl_bg_bt_full_concurrency(struct work_struct *work) |
@@ -2035,7 +2039,7 @@ static void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb) | |||
2035 | ieee80211_free_txskb(priv->hw, skb); | 2039 | ieee80211_free_txskb(priv->hw, skb); |
2036 | } | 2040 | } |
2037 | 2041 | ||
2038 | static void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) | 2042 | static bool iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) |
2039 | { | 2043 | { |
2040 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | 2044 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); |
2041 | 2045 | ||
@@ -2045,6 +2049,8 @@ static void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) | |||
2045 | clear_bit(STATUS_RF_KILL_HW, &priv->status); | 2049 | clear_bit(STATUS_RF_KILL_HW, &priv->status); |
2046 | 2050 | ||
2047 | wiphy_rfkill_set_hw_state(priv->hw->wiphy, state); | 2051 | wiphy_rfkill_set_hw_state(priv->hw->wiphy, state); |
2052 | |||
2053 | return false; | ||
2048 | } | 2054 | } |
2049 | 2055 | ||
2050 | static const struct iwl_op_mode_ops iwl_dvm_ops = { | 2056 | static const struct iwl_op_mode_ops iwl_dvm_ops = { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c index fbd262ffa497..003a546571d4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-7000.c +++ b/drivers/net/wireless/iwlwifi/iwl-7000.c | |||
@@ -134,6 +134,7 @@ const struct iwl_cfg iwl7260_2ac_cfg = { | |||
134 | .nvm_ver = IWL7260_NVM_VERSION, | 134 | .nvm_ver = IWL7260_NVM_VERSION, |
135 | .nvm_calib_ver = IWL7260_TX_POWER_VERSION, | 135 | .nvm_calib_ver = IWL7260_TX_POWER_VERSION, |
136 | .host_interrupt_operation_mode = true, | 136 | .host_interrupt_operation_mode = true, |
137 | .lp_xtal_workaround = true, | ||
137 | }; | 138 | }; |
138 | 139 | ||
139 | const struct iwl_cfg iwl7260_2ac_cfg_high_temp = { | 140 | const struct iwl_cfg iwl7260_2ac_cfg_high_temp = { |
@@ -145,6 +146,7 @@ const struct iwl_cfg iwl7260_2ac_cfg_high_temp = { | |||
145 | .nvm_calib_ver = IWL7260_TX_POWER_VERSION, | 146 | .nvm_calib_ver = IWL7260_TX_POWER_VERSION, |
146 | .high_temp = true, | 147 | .high_temp = true, |
147 | .host_interrupt_operation_mode = true, | 148 | .host_interrupt_operation_mode = true, |
149 | .lp_xtal_workaround = true, | ||
148 | }; | 150 | }; |
149 | 151 | ||
150 | const struct iwl_cfg iwl7260_2n_cfg = { | 152 | const struct iwl_cfg iwl7260_2n_cfg = { |
@@ -155,6 +157,7 @@ const struct iwl_cfg iwl7260_2n_cfg = { | |||
155 | .nvm_ver = IWL7260_NVM_VERSION, | 157 | .nvm_ver = IWL7260_NVM_VERSION, |
156 | .nvm_calib_ver = IWL7260_TX_POWER_VERSION, | 158 | .nvm_calib_ver = IWL7260_TX_POWER_VERSION, |
157 | .host_interrupt_operation_mode = true, | 159 | .host_interrupt_operation_mode = true, |
160 | .lp_xtal_workaround = true, | ||
158 | }; | 161 | }; |
159 | 162 | ||
160 | const struct iwl_cfg iwl7260_n_cfg = { | 163 | const struct iwl_cfg iwl7260_n_cfg = { |
@@ -165,6 +168,7 @@ const struct iwl_cfg iwl7260_n_cfg = { | |||
165 | .nvm_ver = IWL7260_NVM_VERSION, | 168 | .nvm_ver = IWL7260_NVM_VERSION, |
166 | .nvm_calib_ver = IWL7260_TX_POWER_VERSION, | 169 | .nvm_calib_ver = IWL7260_TX_POWER_VERSION, |
167 | .host_interrupt_operation_mode = true, | 170 | .host_interrupt_operation_mode = true, |
171 | .lp_xtal_workaround = true, | ||
168 | }; | 172 | }; |
169 | 173 | ||
170 | const struct iwl_cfg iwl3160_2ac_cfg = { | 174 | const struct iwl_cfg iwl3160_2ac_cfg = { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h index 13ec56607d10..3f17dc3f2c8a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/iwlwifi/iwl-config.h | |||
@@ -262,6 +262,7 @@ struct iwl_cfg { | |||
262 | bool high_temp; | 262 | bool high_temp; |
263 | bool d0i3; | 263 | bool d0i3; |
264 | u8 nvm_hw_section_num; | 264 | u8 nvm_hw_section_num; |
265 | bool lp_xtal_workaround; | ||
265 | const struct iwl_pwr_tx_backoff *pwr_tx_backoffs; | 266 | const struct iwl_pwr_tx_backoff *pwr_tx_backoffs; |
266 | }; | 267 | }; |
267 | 268 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index f13dec9ad9c9..fe129c94ae3e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h | |||
@@ -139,6 +139,13 @@ | |||
139 | #define CSR_ANA_PLL_CFG (CSR_BASE+0x20c) | 139 | #define CSR_ANA_PLL_CFG (CSR_BASE+0x20c) |
140 | 140 | ||
141 | /* | 141 | /* |
142 | * CSR HW resources monitor registers | ||
143 | */ | ||
144 | #define CSR_MONITOR_CFG_REG (CSR_BASE+0x214) | ||
145 | #define CSR_MONITOR_STATUS_REG (CSR_BASE+0x228) | ||
146 | #define CSR_MONITOR_XTAL_RESOURCES (0x00000010) | ||
147 | |||
148 | /* | ||
142 | * CSR Hardware Revision Workaround Register. Indicates hardware rev; | 149 | * CSR Hardware Revision Workaround Register. Indicates hardware rev; |
143 | * "step" determines CCK backoff for txpower calculation. Used for 4965 only. | 150 | * "step" determines CCK backoff for txpower calculation. Used for 4965 only. |
144 | * See also CSR_HW_REV register. | 151 | * See also CSR_HW_REV register. |
@@ -173,6 +180,7 @@ | |||
173 | #define CSR_HW_IF_CONFIG_REG_BIT_NIC_READY (0x00400000) /* PCI_OWN_SEM */ | 180 | #define CSR_HW_IF_CONFIG_REG_BIT_NIC_READY (0x00400000) /* PCI_OWN_SEM */ |
174 | #define CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE (0x02000000) /* ME_OWN */ | 181 | #define CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE (0x02000000) /* ME_OWN */ |
175 | #define CSR_HW_IF_CONFIG_REG_PREPARE (0x08000000) /* WAKE_ME */ | 182 | #define CSR_HW_IF_CONFIG_REG_PREPARE (0x08000000) /* WAKE_ME */ |
183 | #define CSR_HW_IF_CONFIG_REG_PERSIST_MODE (0x40000000) /* PERSISTENCE */ | ||
176 | 184 | ||
177 | #define CSR_INT_PERIODIC_DIS (0x00) /* disable periodic int*/ | 185 | #define CSR_INT_PERIODIC_DIS (0x00) /* disable periodic int*/ |
178 | #define CSR_INT_PERIODIC_ENA (0xFF) /* 255*32 usec ~ 8 msec*/ | 186 | #define CSR_INT_PERIODIC_ENA (0xFF) /* 255*32 usec ~ 8 msec*/ |
@@ -240,6 +248,7 @@ | |||
240 | * 001 -- MAC power-down | 248 | * 001 -- MAC power-down |
241 | * 010 -- PHY (radio) power-down | 249 | * 010 -- PHY (radio) power-down |
242 | * 011 -- Error | 250 | * 011 -- Error |
251 | * 10: XTAL ON request | ||
243 | * 9-6: SYS_CONFIG | 252 | * 9-6: SYS_CONFIG |
244 | * Indicates current system configuration, reflecting pins on chip | 253 | * Indicates current system configuration, reflecting pins on chip |
245 | * as forced high/low by device circuit board. | 254 | * as forced high/low by device circuit board. |
@@ -271,6 +280,7 @@ | |||
271 | #define CSR_GP_CNTRL_REG_FLAG_INIT_DONE (0x00000004) | 280 | #define CSR_GP_CNTRL_REG_FLAG_INIT_DONE (0x00000004) |
272 | #define CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ (0x00000008) | 281 | #define CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ (0x00000008) |
273 | #define CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP (0x00000010) | 282 | #define CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP (0x00000010) |
283 | #define CSR_GP_CNTRL_REG_FLAG_XTAL_ON (0x00000400) | ||
274 | 284 | ||
275 | #define CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN (0x00000001) | 285 | #define CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN (0x00000001) |
276 | 286 | ||
@@ -396,6 +406,34 @@ | |||
396 | #define CSR_DRAM_INIT_TBL_WRAP_CHECK (1 << 27) | 406 | #define CSR_DRAM_INIT_TBL_WRAP_CHECK (1 << 27) |
397 | 407 | ||
398 | /* | 408 | /* |
409 | * SHR target access (Shared block memory space) | ||
410 | * | ||
411 | * Shared internal registers can be accessed directly from PCI bus through SHR | ||
412 | * arbiter without need for the MAC HW to be powered up. This is possible due to | ||
413 | * indirect read/write via HEEP_CTRL_WRD_PCIEX_CTRL (0xEC) and | ||
414 | * HEEP_CTRL_WRD_PCIEX_DATA (0xF4) registers. | ||
415 | * | ||
416 | * Use iwl_write32()/iwl_read32() family to access these registers. The MAC HW | ||
417 | * need not be powered up so no "grab inc access" is required. | ||
418 | */ | ||
419 | |||
420 | /* | ||
421 | * Registers for accessing shared registers (e.g. SHR_APMG_GP1, | ||
422 | * SHR_APMG_XTAL_CFG). For example, to read from SHR_APMG_GP1 register (0x1DC), | ||
423 | * first, write to the control register: | ||
424 | * HEEP_CTRL_WRD_PCIEX_CTRL[15:0] = 0x1DC (offset of the SHR_APMG_GP1 register) | ||
425 | * HEEP_CTRL_WRD_PCIEX_CTRL[29:28] = 2 (read access) | ||
426 | * second, read from the data register HEEP_CTRL_WRD_PCIEX_DATA[31:0]. | ||
427 | * | ||
428 | * To write the register, first, write to the data register | ||
429 | * HEEP_CTRL_WRD_PCIEX_DATA[31:0] and then: | ||
430 | * HEEP_CTRL_WRD_PCIEX_CTRL[15:0] = 0x1DC (offset of the SHR_APMG_GP1 register) | ||
431 | * HEEP_CTRL_WRD_PCIEX_CTRL[29:28] = 3 (write access) | ||
432 | */ | ||
433 | #define HEEP_CTRL_WRD_PCIEX_CTRL_REG (CSR_BASE+0x0ec) | ||
434 | #define HEEP_CTRL_WRD_PCIEX_DATA_REG (CSR_BASE+0x0f4) | ||
435 | |||
436 | /* | ||
399 | * HBUS (Host-side Bus) | 437 | * HBUS (Host-side Bus) |
400 | * | 438 | * |
401 | * HBUS registers are mapped directly into PCI bus space, but are used | 439 | * HBUS registers are mapped directly into PCI bus space, but are used |
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h index f04ff871dc6d..d14f19339d61 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw.h | |||
@@ -125,6 +125,22 @@ enum iwl_ucode_tlv_flag { | |||
125 | IWL_UCODE_TLV_FLAGS_GO_UAPSD = BIT(30), | 125 | IWL_UCODE_TLV_FLAGS_GO_UAPSD = BIT(30), |
126 | }; | 126 | }; |
127 | 127 | ||
128 | /** | ||
129 | * enum iwl_ucode_tlv_api - ucode api | ||
130 | * @IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID: wowlan config includes tid field. | ||
131 | */ | ||
132 | enum iwl_ucode_tlv_api { | ||
133 | IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID = BIT(0), | ||
134 | }; | ||
135 | |||
136 | /** | ||
137 | * enum iwl_ucode_tlv_capa - ucode capabilities | ||
138 | * @IWL_UCODE_TLV_CAPA_D0I3_SUPPORT: supports D0i3 | ||
139 | */ | ||
140 | enum iwl_ucode_tlv_capa { | ||
141 | IWL_UCODE_TLV_CAPA_D0I3_SUPPORT = BIT(0), | ||
142 | }; | ||
143 | |||
128 | /* The default calibrate table size if not specified by firmware file */ | 144 | /* The default calibrate table size if not specified by firmware file */ |
129 | #define IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE 18 | 145 | #define IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE 18 |
130 | #define IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE 19 | 146 | #define IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE 19 |
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c index 07372f2b0250..44cc3cf45762 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/iwlwifi/iwl-io.c | |||
@@ -93,14 +93,14 @@ int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask, | |||
93 | } | 93 | } |
94 | IWL_EXPORT_SYMBOL(iwl_poll_direct_bit); | 94 | IWL_EXPORT_SYMBOL(iwl_poll_direct_bit); |
95 | 95 | ||
96 | static inline u32 __iwl_read_prph(struct iwl_trans *trans, u32 ofs) | 96 | u32 __iwl_read_prph(struct iwl_trans *trans, u32 ofs) |
97 | { | 97 | { |
98 | u32 val = iwl_trans_read_prph(trans, ofs); | 98 | u32 val = iwl_trans_read_prph(trans, ofs); |
99 | trace_iwlwifi_dev_ioread_prph32(trans->dev, ofs, val); | 99 | trace_iwlwifi_dev_ioread_prph32(trans->dev, ofs, val); |
100 | return val; | 100 | return val; |
101 | } | 101 | } |
102 | 102 | ||
103 | static inline void __iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val) | 103 | void __iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val) |
104 | { | 104 | { |
105 | trace_iwlwifi_dev_iowrite_prph32(trans->dev, ofs, val); | 105 | trace_iwlwifi_dev_iowrite_prph32(trans->dev, ofs, val); |
106 | iwl_trans_write_prph(trans, ofs, val); | 106 | iwl_trans_write_prph(trans, ofs, val); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index 9e81b23d738b..665ddd9dbbc4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h | |||
@@ -70,7 +70,9 @@ u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg); | |||
70 | void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value); | 70 | void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value); |
71 | 71 | ||
72 | 72 | ||
73 | u32 __iwl_read_prph(struct iwl_trans *trans, u32 ofs); | ||
73 | u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs); | 74 | u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs); |
75 | void __iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val); | ||
74 | void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val); | 76 | void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val); |
75 | int iwl_poll_prph_bit(struct iwl_trans *trans, u32 addr, | 77 | int iwl_poll_prph_bit(struct iwl_trans *trans, u32 addr, |
76 | u32 bits, u32 mask, int timeout); | 78 | u32 bits, u32 mask, int timeout); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c index 2f962ec0b750..6be30c698506 100644 --- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c | |||
@@ -299,9 +299,11 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, | |||
299 | 299 | ||
300 | static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg, | 300 | static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg, |
301 | struct iwl_nvm_data *data, | 301 | struct iwl_nvm_data *data, |
302 | struct ieee80211_sta_vht_cap *vht_cap) | 302 | struct ieee80211_sta_vht_cap *vht_cap, |
303 | u8 tx_chains, u8 rx_chains) | ||
303 | { | 304 | { |
304 | int num_ants = num_of_ant(data->valid_rx_ant); | 305 | int num_rx_ants = num_of_ant(rx_chains); |
306 | int num_tx_ants = num_of_ant(tx_chains); | ||
305 | 307 | ||
306 | vht_cap->vht_supported = true; | 308 | vht_cap->vht_supported = true; |
307 | 309 | ||
@@ -311,8 +313,10 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg, | |||
311 | 3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT | | 313 | 3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT | |
312 | 7 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT; | 314 | 7 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT; |
313 | 315 | ||
314 | if (num_ants > 1) | 316 | if (num_tx_ants > 1) |
315 | vht_cap->cap |= IEEE80211_VHT_CAP_TXSTBC; | 317 | vht_cap->cap |= IEEE80211_VHT_CAP_TXSTBC; |
318 | else | ||
319 | vht_cap->cap |= IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN; | ||
316 | 320 | ||
317 | if (iwlwifi_mod_params.amsdu_size_8K) | 321 | if (iwlwifi_mod_params.amsdu_size_8K) |
318 | vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991; | 322 | vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991; |
@@ -327,10 +331,8 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg, | |||
327 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 | | 331 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 | |
328 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 14); | 332 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 14); |
329 | 333 | ||
330 | if (num_ants == 1 || | 334 | if (num_rx_ants == 1 || cfg->rx_with_siso_diversity) { |
331 | cfg->rx_with_siso_diversity) { | 335 | vht_cap->cap |= IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN; |
332 | vht_cap->cap |= IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN | | ||
333 | IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN; | ||
334 | /* this works because NOT_SUPPORTED == 3 */ | 336 | /* this works because NOT_SUPPORTED == 3 */ |
335 | vht_cap->vht_mcs.rx_mcs_map |= | 337 | vht_cap->vht_mcs.rx_mcs_map |= |
336 | cpu_to_le16(IEEE80211_VHT_MCS_NOT_SUPPORTED << 2); | 338 | cpu_to_le16(IEEE80211_VHT_MCS_NOT_SUPPORTED << 2); |
@@ -375,7 +377,8 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, | |||
375 | iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_5GHZ, | 377 | iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_5GHZ, |
376 | tx_chains, rx_chains); | 378 | tx_chains, rx_chains); |
377 | if (enable_vht) | 379 | if (enable_vht) |
378 | iwl_init_vht_hw_capab(cfg, data, &sband->vht_cap); | 380 | iwl_init_vht_hw_capab(cfg, data, &sband->vht_cap, |
381 | tx_chains, rx_chains); | ||
379 | 382 | ||
380 | if (n_channels != n_used) | 383 | if (n_channels != n_used) |
381 | IWL_ERR_DEV(dev, "NVM: used only %d of %d channels\n", | 384 | IWL_ERR_DEV(dev, "NVM: used only %d of %d channels\n", |
diff --git a/drivers/net/wireless/iwlwifi/iwl-op-mode.h b/drivers/net/wireless/iwlwifi/iwl-op-mode.h index 5d78207040b0..ea29504ac617 100644 --- a/drivers/net/wireless/iwlwifi/iwl-op-mode.h +++ b/drivers/net/wireless/iwlwifi/iwl-op-mode.h | |||
@@ -119,7 +119,8 @@ struct iwl_cfg; | |||
119 | * @queue_not_full: notifies that a HW queue is not full any more. | 119 | * @queue_not_full: notifies that a HW queue is not full any more. |
120 | * Must be atomic and called with BH disabled. | 120 | * Must be atomic and called with BH disabled. |
121 | * @hw_rf_kill:notifies of a change in the HW rf kill switch. True means that | 121 | * @hw_rf_kill:notifies of a change in the HW rf kill switch. True means that |
122 | * the radio is killed. May sleep. | 122 | * the radio is killed. Return %true if the device should be stopped by |
123 | * the transport immediately after the call. May sleep. | ||
123 | * @free_skb: allows the transport layer to free skbs that haven't been | 124 | * @free_skb: allows the transport layer to free skbs that haven't been |
124 | * reclaimed by the op_mode. This can happen when the driver is freed and | 125 | * reclaimed by the op_mode. This can happen when the driver is freed and |
125 | * there are Tx packets pending in the transport layer. | 126 | * there are Tx packets pending in the transport layer. |
@@ -144,7 +145,7 @@ struct iwl_op_mode_ops { | |||
144 | struct iwl_device_cmd *cmd); | 145 | struct iwl_device_cmd *cmd); |
145 | void (*queue_full)(struct iwl_op_mode *op_mode, int queue); | 146 | void (*queue_full)(struct iwl_op_mode *op_mode, int queue); |
146 | void (*queue_not_full)(struct iwl_op_mode *op_mode, int queue); | 147 | void (*queue_not_full)(struct iwl_op_mode *op_mode, int queue); |
147 | void (*hw_rf_kill)(struct iwl_op_mode *op_mode, bool state); | 148 | bool (*hw_rf_kill)(struct iwl_op_mode *op_mode, bool state); |
148 | void (*free_skb)(struct iwl_op_mode *op_mode, struct sk_buff *skb); | 149 | void (*free_skb)(struct iwl_op_mode *op_mode, struct sk_buff *skb); |
149 | void (*nic_error)(struct iwl_op_mode *op_mode); | 150 | void (*nic_error)(struct iwl_op_mode *op_mode); |
150 | void (*cmd_queue_full)(struct iwl_op_mode *op_mode); | 151 | void (*cmd_queue_full)(struct iwl_op_mode *op_mode); |
@@ -195,11 +196,11 @@ static inline void iwl_op_mode_queue_not_full(struct iwl_op_mode *op_mode, | |||
195 | op_mode->ops->queue_not_full(op_mode, queue); | 196 | op_mode->ops->queue_not_full(op_mode, queue); |
196 | } | 197 | } |
197 | 198 | ||
198 | static inline void iwl_op_mode_hw_rf_kill(struct iwl_op_mode *op_mode, | 199 | static inline bool __must_check |
199 | bool state) | 200 | iwl_op_mode_hw_rf_kill(struct iwl_op_mode *op_mode, bool state) |
200 | { | 201 | { |
201 | might_sleep(); | 202 | might_sleep(); |
202 | op_mode->ops->hw_rf_kill(op_mode, state); | 203 | return op_mode->ops->hw_rf_kill(op_mode, state); |
203 | } | 204 | } |
204 | 205 | ||
205 | static inline void iwl_op_mode_free_skb(struct iwl_op_mode *op_mode, | 206 | static inline void iwl_op_mode_free_skb(struct iwl_op_mode *op_mode, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index 9c90186d1744..5f657c501406 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h | |||
@@ -95,7 +95,8 @@ | |||
95 | #define APMG_SVR_VOLTAGE_CONFIG_BIT_MSK (0x000001E0) /* bit 8:5 */ | 95 | #define APMG_SVR_VOLTAGE_CONFIG_BIT_MSK (0x000001E0) /* bit 8:5 */ |
96 | #define APMG_SVR_DIGITAL_VOLTAGE_1_32 (0x00000060) | 96 | #define APMG_SVR_DIGITAL_VOLTAGE_1_32 (0x00000060) |
97 | 97 | ||
98 | #define APMG_PCIDEV_STT_VAL_L1_ACT_DIS (0x00000800) | 98 | #define APMG_PCIDEV_STT_VAL_PERSIST_DIS (0x00000200) |
99 | #define APMG_PCIDEV_STT_VAL_L1_ACT_DIS (0x00000800) | ||
99 | 100 | ||
100 | #define APMG_RTC_INT_STT_RFKILL (0x10000000) | 101 | #define APMG_RTC_INT_STT_RFKILL (0x10000000) |
101 | 102 | ||
@@ -105,6 +106,26 @@ | |||
105 | /* Device NMI register */ | 106 | /* Device NMI register */ |
106 | #define DEVICE_SET_NMI_REG 0x00a01c30 | 107 | #define DEVICE_SET_NMI_REG 0x00a01c30 |
107 | 108 | ||
109 | /* Shared registers (0x0..0x3ff, via target indirect or periphery */ | ||
110 | #define SHR_BASE 0x00a10000 | ||
111 | |||
112 | /* Shared GP1 register */ | ||
113 | #define SHR_APMG_GP1_REG 0x01dc | ||
114 | #define SHR_APMG_GP1_REG_PRPH (SHR_BASE + SHR_APMG_GP1_REG) | ||
115 | #define SHR_APMG_GP1_WF_XTAL_LP_EN 0x00000004 | ||
116 | #define SHR_APMG_GP1_CHICKEN_BIT_SELECT 0x80000000 | ||
117 | |||
118 | /* Shared DL_CFG register */ | ||
119 | #define SHR_APMG_DL_CFG_REG 0x01c4 | ||
120 | #define SHR_APMG_DL_CFG_REG_PRPH (SHR_BASE + SHR_APMG_DL_CFG_REG) | ||
121 | #define SHR_APMG_DL_CFG_RTCS_CLK_SELECTOR_MSK 0x000000c0 | ||
122 | #define SHR_APMG_DL_CFG_RTCS_CLK_INTERNAL_XTAL 0x00000080 | ||
123 | #define SHR_APMG_DL_CFG_DL_CLOCK_POWER_UP 0x00000100 | ||
124 | |||
125 | /* Shared APMG_XTAL_CFG register */ | ||
126 | #define SHR_APMG_XTAL_CFG_REG 0x1c0 | ||
127 | #define SHR_APMG_XTAL_CFG_XTAL_ON_REQ 0x80000000 | ||
128 | |||
108 | /* | 129 | /* |
109 | * Device reset for family 8000 | 130 | * Device reset for family 8000 |
110 | * write to bit 24 in order to reset the CPU | 131 | * write to bit 24 in order to reset the CPU |
diff --git a/drivers/net/wireless/iwlwifi/mvm/Makefile b/drivers/net/wireless/iwlwifi/mvm/Makefile index 41d390fd2ac8..ccdd3b7c4cce 100644 --- a/drivers/net/wireless/iwlwifi/mvm/Makefile +++ b/drivers/net/wireless/iwlwifi/mvm/Makefile | |||
@@ -2,8 +2,8 @@ obj-$(CONFIG_IWLMVM) += iwlmvm.o | |||
2 | iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o | 2 | iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o |
3 | iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o sf.o | 3 | iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o sf.o |
4 | iwlmvm-y += scan.o time-event.o rs.o | 4 | iwlmvm-y += scan.o time-event.o rs.o |
5 | iwlmvm-y += power.o bt-coex.o | 5 | iwlmvm-y += power.o coex.o |
6 | iwlmvm-y += led.o tt.o | 6 | iwlmvm-y += led.o tt.o offloading.o |
7 | iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o | 7 | iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o |
8 | iwlmvm-$(CONFIG_PM_SLEEP) += d3.o | 8 | iwlmvm-$(CONFIG_PM_SLEEP) += d3.o |
9 | 9 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c b/drivers/net/wireless/iwlwifi/mvm/coex.c index 2aa3ee93c68e..685f7e8e6943 100644 --- a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c +++ b/drivers/net/wireless/iwlwifi/mvm/coex.c | |||
@@ -61,9 +61,11 @@ | |||
61 | * | 61 | * |
62 | *****************************************************************************/ | 62 | *****************************************************************************/ |
63 | 63 | ||
64 | #include <linux/ieee80211.h> | ||
65 | #include <linux/etherdevice.h> | ||
64 | #include <net/mac80211.h> | 66 | #include <net/mac80211.h> |
65 | 67 | ||
66 | #include "fw-api-bt-coex.h" | 68 | #include "fw-api-coex.h" |
67 | #include "iwl-modparams.h" | 69 | #include "iwl-modparams.h" |
68 | #include "mvm.h" | 70 | #include "mvm.h" |
69 | #include "iwl-debug.h" | 71 | #include "iwl-debug.h" |
@@ -305,6 +307,215 @@ static const __le32 iwl_bt_mprio_lut[BT_COEX_MULTI_PRIO_LUT_SIZE] = { | |||
305 | cpu_to_le32(0x33113311), | 307 | cpu_to_le32(0x33113311), |
306 | }; | 308 | }; |
307 | 309 | ||
310 | struct corunning_block_luts { | ||
311 | u8 range; | ||
312 | __le32 lut20[BT_COEX_CORUN_LUT_SIZE]; | ||
313 | }; | ||
314 | |||
315 | /* | ||
316 | * Ranges for the antenna coupling calibration / co-running block LUT: | ||
317 | * LUT0: [ 0, 12[ | ||
318 | * LUT1: [12, 20[ | ||
319 | * LUT2: [20, 21[ | ||
320 | * LUT3: [21, 23[ | ||
321 | * LUT4: [23, 27[ | ||
322 | * LUT5: [27, 30[ | ||
323 | * LUT6: [30, 32[ | ||
324 | * LUT7: [32, 33[ | ||
325 | * LUT8: [33, - [ | ||
326 | */ | ||
327 | static const struct corunning_block_luts antenna_coupling_ranges[] = { | ||
328 | { | ||
329 | .range = 0, | ||
330 | .lut20 = { | ||
331 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
332 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
333 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
334 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
335 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
336 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
337 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
338 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
339 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
340 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
341 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
342 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
343 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
344 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
345 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
346 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
347 | }, | ||
348 | }, | ||
349 | { | ||
350 | .range = 12, | ||
351 | .lut20 = { | ||
352 | cpu_to_le32(0x00000001), cpu_to_le32(0x00000000), | ||
353 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
354 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
355 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
356 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
357 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
358 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
359 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
360 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
361 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
362 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
363 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
364 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
365 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
366 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
367 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
368 | }, | ||
369 | }, | ||
370 | { | ||
371 | .range = 20, | ||
372 | .lut20 = { | ||
373 | cpu_to_le32(0x00000002), cpu_to_le32(0x00000000), | ||
374 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
375 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
376 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
377 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
378 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
379 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
380 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
381 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
382 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
383 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
384 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
385 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
386 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
387 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
388 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
389 | }, | ||
390 | }, | ||
391 | { | ||
392 | .range = 21, | ||
393 | .lut20 = { | ||
394 | cpu_to_le32(0x00000003), cpu_to_le32(0x00000000), | ||
395 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
396 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
397 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
398 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
399 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
400 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
401 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
402 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
403 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
404 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
405 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
406 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
407 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
408 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
409 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
410 | }, | ||
411 | }, | ||
412 | { | ||
413 | .range = 23, | ||
414 | .lut20 = { | ||
415 | cpu_to_le32(0x00000004), cpu_to_le32(0x00000000), | ||
416 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
417 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
418 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
419 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
420 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
421 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
422 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
423 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
424 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
425 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
426 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
427 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
428 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
429 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
430 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
431 | }, | ||
432 | }, | ||
433 | { | ||
434 | .range = 27, | ||
435 | .lut20 = { | ||
436 | cpu_to_le32(0x00000005), cpu_to_le32(0x00000000), | ||
437 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
438 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
439 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
440 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
441 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
442 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
443 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
444 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
445 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
446 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
447 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
448 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
449 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
450 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
451 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
452 | }, | ||
453 | }, | ||
454 | { | ||
455 | .range = 30, | ||
456 | .lut20 = { | ||
457 | cpu_to_le32(0x00000006), cpu_to_le32(0x00000000), | ||
458 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
459 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
460 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
461 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
462 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
463 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
464 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
465 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
466 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
467 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
468 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
469 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
470 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
471 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
472 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
473 | }, | ||
474 | }, | ||
475 | { | ||
476 | .range = 32, | ||
477 | .lut20 = { | ||
478 | cpu_to_le32(0x00000007), cpu_to_le32(0x00000000), | ||
479 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
480 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
481 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
482 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
483 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
484 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
485 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
486 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
487 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
488 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
489 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
490 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
491 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
492 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
493 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
494 | }, | ||
495 | }, | ||
496 | { | ||
497 | .range = 33, | ||
498 | .lut20 = { | ||
499 | cpu_to_le32(0x00000008), cpu_to_le32(0x00000000), | ||
500 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
501 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
502 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
503 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
504 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
505 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
506 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
507 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
508 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
509 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
510 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
511 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
512 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
513 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
514 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | ||
515 | }, | ||
516 | }, | ||
517 | }; | ||
518 | |||
308 | static enum iwl_bt_coex_lut_type | 519 | static enum iwl_bt_coex_lut_type |
309 | iwl_get_coex_type(struct iwl_mvm *mvm, const struct ieee80211_vif *vif) | 520 | iwl_get_coex_type(struct iwl_mvm *mvm, const struct ieee80211_vif *vif) |
310 | { | 521 | { |
@@ -390,8 +601,6 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm) | |||
390 | BT_VALID_LUT | | 601 | BT_VALID_LUT | |
391 | BT_VALID_WIFI_RX_SW_PRIO_BOOST | | 602 | BT_VALID_WIFI_RX_SW_PRIO_BOOST | |
392 | BT_VALID_WIFI_TX_SW_PRIO_BOOST | | 603 | BT_VALID_WIFI_TX_SW_PRIO_BOOST | |
393 | BT_VALID_CORUN_LUT_20 | | ||
394 | BT_VALID_CORUN_LUT_40 | | ||
395 | BT_VALID_ANT_ISOLATION | | 604 | BT_VALID_ANT_ISOLATION | |
396 | BT_VALID_ANT_ISOLATION_THRS | | 605 | BT_VALID_ANT_ISOLATION_THRS | |
397 | BT_VALID_TXTX_DELTA_FREQ_THRS | | 606 | BT_VALID_TXTX_DELTA_FREQ_THRS | |
@@ -401,6 +610,17 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm) | |||
401 | if (IWL_MVM_BT_COEX_SYNC2SCO) | 610 | if (IWL_MVM_BT_COEX_SYNC2SCO) |
402 | bt_cmd->flags |= cpu_to_le32(BT_COEX_SYNC2SCO); | 611 | bt_cmd->flags |= cpu_to_le32(BT_COEX_SYNC2SCO); |
403 | 612 | ||
613 | if (IWL_MVM_BT_COEX_CORUNNING) { | ||
614 | bt_cmd->valid_bit_msk = cpu_to_le32(BT_VALID_CORUN_LUT_20 | | ||
615 | BT_VALID_CORUN_LUT_40); | ||
616 | bt_cmd->flags |= cpu_to_le32(BT_COEX_CORUNNING); | ||
617 | } | ||
618 | |||
619 | if (IWL_MVM_BT_COEX_MPLUT) { | ||
620 | bt_cmd->flags |= cpu_to_le32(BT_COEX_MPLUT); | ||
621 | bt_cmd->valid_bit_msk = cpu_to_le32(BT_VALID_MULTI_PRIO_LUT); | ||
622 | } | ||
623 | |||
404 | if (mvm->cfg->bt_shared_single_ant) | 624 | if (mvm->cfg->bt_shared_single_ant) |
405 | memcpy(&bt_cmd->decision_lut, iwl_single_shared_ant, | 625 | memcpy(&bt_cmd->decision_lut, iwl_single_shared_ant, |
406 | sizeof(iwl_single_shared_ant)); | 626 | sizeof(iwl_single_shared_ant)); |
@@ -408,6 +628,12 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm) | |||
408 | memcpy(&bt_cmd->decision_lut, iwl_combined_lookup, | 628 | memcpy(&bt_cmd->decision_lut, iwl_combined_lookup, |
409 | sizeof(iwl_combined_lookup)); | 629 | sizeof(iwl_combined_lookup)); |
410 | 630 | ||
631 | /* Take first Co-running block LUT to get started */ | ||
632 | memcpy(bt_cmd->bt4_corun_lut20, antenna_coupling_ranges[0].lut20, | ||
633 | sizeof(bt_cmd->bt4_corun_lut20)); | ||
634 | memcpy(bt_cmd->bt4_corun_lut40, antenna_coupling_ranges[0].lut20, | ||
635 | sizeof(bt_cmd->bt4_corun_lut40)); | ||
636 | |||
411 | memcpy(&bt_cmd->bt_prio_boost, iwl_bt_prio_boost, | 637 | memcpy(&bt_cmd->bt_prio_boost, iwl_bt_prio_boost, |
412 | sizeof(iwl_bt_prio_boost)); | 638 | sizeof(iwl_bt_prio_boost)); |
413 | memcpy(&bt_cmd->bt4_multiprio_lut, iwl_bt_mprio_lut, | 639 | memcpy(&bt_cmd->bt4_multiprio_lut, iwl_bt_mprio_lut, |
@@ -498,7 +724,7 @@ int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, bool enable) | |||
498 | struct iwl_host_cmd cmd = { | 724 | struct iwl_host_cmd cmd = { |
499 | .id = BT_CONFIG, | 725 | .id = BT_CONFIG, |
500 | .len = { sizeof(*bt_cmd), }, | 726 | .len = { sizeof(*bt_cmd), }, |
501 | .dataflags = { IWL_HCMD_DFL_DUP, }, | 727 | .dataflags = { IWL_HCMD_DFL_NOCOPY, }, |
502 | .flags = CMD_ASYNC, | 728 | .flags = CMD_ASYNC, |
503 | }; | 729 | }; |
504 | struct iwl_mvm_sta *mvmsta; | 730 | struct iwl_mvm_sta *mvmsta; |
@@ -952,8 +1178,8 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
952 | #define LINK_QUAL_AGG_TIME_LIMIT_DEF (4000) | 1178 | #define LINK_QUAL_AGG_TIME_LIMIT_DEF (4000) |
953 | #define LINK_QUAL_AGG_TIME_LIMIT_BT_ACT (1200) | 1179 | #define LINK_QUAL_AGG_TIME_LIMIT_BT_ACT (1200) |
954 | 1180 | ||
955 | u16 iwl_mvm_bt_coex_agg_time_limit(struct iwl_mvm *mvm, | 1181 | u16 iwl_mvm_coex_agg_time_limit(struct iwl_mvm *mvm, |
956 | struct ieee80211_sta *sta) | 1182 | struct ieee80211_sta *sta) |
957 | { | 1183 | { |
958 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); | 1184 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); |
959 | enum iwl_bt_coex_lut_type lut_type; | 1185 | enum iwl_bt_coex_lut_type lut_type; |
@@ -989,6 +1215,38 @@ bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm, | |||
989 | return iwl_get_coex_type(mvm, mvmsta->vif) == BT_COEX_TIGHT_LUT; | 1215 | return iwl_get_coex_type(mvm, mvmsta->vif) == BT_COEX_TIGHT_LUT; |
990 | } | 1216 | } |
991 | 1217 | ||
1218 | u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr, | ||
1219 | struct ieee80211_tx_info *info, u8 ac) | ||
1220 | { | ||
1221 | __le16 fc = hdr->frame_control; | ||
1222 | |||
1223 | if (info->band != IEEE80211_BAND_2GHZ) | ||
1224 | return 0; | ||
1225 | |||
1226 | if (unlikely(mvm->bt_tx_prio)) | ||
1227 | return mvm->bt_tx_prio - 1; | ||
1228 | |||
1229 | /* High prio packet (wrt. BT coex) if it is EAPOL, MCAST or MGMT */ | ||
1230 | if (info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO || | ||
1231 | is_multicast_ether_addr(hdr->addr1) || | ||
1232 | ieee80211_is_ctl(fc) || ieee80211_is_mgmt(fc) || | ||
1233 | ieee80211_is_nullfunc(fc) || ieee80211_is_qos_nullfunc(fc)) | ||
1234 | return 3; | ||
1235 | |||
1236 | switch (ac) { | ||
1237 | case IEEE80211_AC_BE: | ||
1238 | return 1; | ||
1239 | case IEEE80211_AC_VO: | ||
1240 | return 3; | ||
1241 | case IEEE80211_AC_VI: | ||
1242 | return 2; | ||
1243 | default: | ||
1244 | break; | ||
1245 | } | ||
1246 | |||
1247 | return 0; | ||
1248 | } | ||
1249 | |||
992 | void iwl_mvm_bt_coex_vif_change(struct iwl_mvm *mvm) | 1250 | void iwl_mvm_bt_coex_vif_change(struct iwl_mvm *mvm) |
993 | { | 1251 | { |
994 | if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWBT_COEX)) | 1252 | if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWBT_COEX)) |
@@ -996,3 +1254,69 @@ void iwl_mvm_bt_coex_vif_change(struct iwl_mvm *mvm) | |||
996 | 1254 | ||
997 | iwl_mvm_bt_coex_notif_handle(mvm); | 1255 | iwl_mvm_bt_coex_notif_handle(mvm); |
998 | } | 1256 | } |
1257 | |||
1258 | int iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm, | ||
1259 | struct iwl_rx_cmd_buffer *rxb, | ||
1260 | struct iwl_device_cmd *dev_cmd) | ||
1261 | { | ||
1262 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
1263 | u32 ant_isolation = le32_to_cpup((void *)pkt->data); | ||
1264 | u8 __maybe_unused lower_bound, upper_bound; | ||
1265 | u8 lut; | ||
1266 | |||
1267 | struct iwl_bt_coex_cmd *bt_cmd; | ||
1268 | struct iwl_host_cmd cmd = { | ||
1269 | .id = BT_CONFIG, | ||
1270 | .len = { sizeof(*bt_cmd), }, | ||
1271 | .dataflags = { IWL_HCMD_DFL_NOCOPY, }, | ||
1272 | .flags = CMD_SYNC, | ||
1273 | }; | ||
1274 | |||
1275 | if (!IWL_MVM_BT_COEX_CORUNNING) | ||
1276 | return 0; | ||
1277 | |||
1278 | lockdep_assert_held(&mvm->mutex); | ||
1279 | |||
1280 | if (ant_isolation == mvm->last_ant_isol) | ||
1281 | return 0; | ||
1282 | |||
1283 | for (lut = 0; lut < ARRAY_SIZE(antenna_coupling_ranges) - 1; lut++) | ||
1284 | if (ant_isolation < antenna_coupling_ranges[lut + 1].range) | ||
1285 | break; | ||
1286 | |||
1287 | lower_bound = antenna_coupling_ranges[lut].range; | ||
1288 | |||
1289 | if (lut < ARRAY_SIZE(antenna_coupling_ranges) - 1) | ||
1290 | upper_bound = antenna_coupling_ranges[lut + 1].range; | ||
1291 | else | ||
1292 | upper_bound = antenna_coupling_ranges[lut].range; | ||
1293 | |||
1294 | IWL_DEBUG_COEX(mvm, "Antenna isolation=%d in range [%d,%d[, lut=%d\n", | ||
1295 | ant_isolation, lower_bound, upper_bound, lut); | ||
1296 | |||
1297 | mvm->last_ant_isol = ant_isolation; | ||
1298 | |||
1299 | if (mvm->last_corun_lut == lut) | ||
1300 | return 0; | ||
1301 | |||
1302 | mvm->last_corun_lut = lut; | ||
1303 | |||
1304 | bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL); | ||
1305 | if (!bt_cmd) | ||
1306 | return 0; | ||
1307 | cmd.data[0] = bt_cmd; | ||
1308 | |||
1309 | bt_cmd->flags = cpu_to_le32(BT_COEX_NW); | ||
1310 | bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_ENABLE | | ||
1311 | BT_VALID_CORUN_LUT_20 | | ||
1312 | BT_VALID_CORUN_LUT_40); | ||
1313 | |||
1314 | /* For the moment, use the same LUT for 20GHz and 40GHz */ | ||
1315 | memcpy(bt_cmd->bt4_corun_lut20, antenna_coupling_ranges[lut].lut20, | ||
1316 | sizeof(bt_cmd->bt4_corun_lut20)); | ||
1317 | |||
1318 | memcpy(bt_cmd->bt4_corun_lut40, antenna_coupling_ranges[lut].lut20, | ||
1319 | sizeof(bt_cmd->bt4_corun_lut40)); | ||
1320 | |||
1321 | return 0; | ||
1322 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/constants.h b/drivers/net/wireless/iwlwifi/mvm/constants.h index 2d133b1b2dde..51685693af2e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/constants.h +++ b/drivers/net/wireless/iwlwifi/mvm/constants.h | |||
@@ -79,8 +79,8 @@ | |||
79 | #define IWL_MVM_PS_SNOOZE_WINDOW 50 | 79 | #define IWL_MVM_PS_SNOOZE_WINDOW 50 |
80 | #define IWL_MVM_WOWLAN_PS_SNOOZE_WINDOW 25 | 80 | #define IWL_MVM_WOWLAN_PS_SNOOZE_WINDOW 25 |
81 | #define IWL_MVM_LOWLAT_QUOTA_MIN_PERCENT 64 | 81 | #define IWL_MVM_LOWLAT_QUOTA_MIN_PERCENT 64 |
82 | #define IWL_MVM_LOWLAT_SINGLE_BINDING_MAXDUR 24 /* TU */ | ||
83 | #define IWL_MVM_LOWLAT_DUAL_BINDING_MAXDUR 24 /* TU */ | ||
84 | #define IWL_MVM_BT_COEX_SYNC2SCO 1 | 82 | #define IWL_MVM_BT_COEX_SYNC2SCO 1 |
83 | #define IWL_MVM_BT_COEX_CORUNNING 1 | ||
84 | #define IWL_MVM_BT_COEX_MPLUT 1 | ||
85 | 85 | ||
86 | #endif /* __MVM_CONSTANTS_H */ | 86 | #endif /* __MVM_CONSTANTS_H */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c index b956e2f0b631..e56f5a0edf85 100644 --- a/drivers/net/wireless/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/iwlwifi/mvm/d3.c | |||
@@ -376,139 +376,6 @@ static int iwl_mvm_send_patterns(struct iwl_mvm *mvm, | |||
376 | return err; | 376 | return err; |
377 | } | 377 | } |
378 | 378 | ||
379 | static int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm, | ||
380 | struct ieee80211_vif *vif) | ||
381 | { | ||
382 | union { | ||
383 | struct iwl_proto_offload_cmd_v1 v1; | ||
384 | struct iwl_proto_offload_cmd_v2 v2; | ||
385 | struct iwl_proto_offload_cmd_v3_small v3s; | ||
386 | struct iwl_proto_offload_cmd_v3_large v3l; | ||
387 | } cmd = {}; | ||
388 | struct iwl_host_cmd hcmd = { | ||
389 | .id = PROT_OFFLOAD_CONFIG_CMD, | ||
390 | .flags = CMD_SYNC, | ||
391 | .data[0] = &cmd, | ||
392 | .dataflags[0] = IWL_HCMD_DFL_DUP, | ||
393 | }; | ||
394 | struct iwl_proto_offload_cmd_common *common; | ||
395 | u32 enabled = 0, size; | ||
396 | u32 capa_flags = mvm->fw->ucode_capa.flags; | ||
397 | #if IS_ENABLED(CONFIG_IPV6) | ||
398 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
399 | int i; | ||
400 | |||
401 | if (capa_flags & IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL || | ||
402 | capa_flags & IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE) { | ||
403 | struct iwl_ns_config *nsc; | ||
404 | struct iwl_targ_addr *addrs; | ||
405 | int n_nsc, n_addrs; | ||
406 | int c; | ||
407 | |||
408 | if (capa_flags & IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL) { | ||
409 | nsc = cmd.v3s.ns_config; | ||
410 | n_nsc = IWL_PROTO_OFFLOAD_NUM_NS_CONFIG_V3S; | ||
411 | addrs = cmd.v3s.targ_addrs; | ||
412 | n_addrs = IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V3S; | ||
413 | } else { | ||
414 | nsc = cmd.v3l.ns_config; | ||
415 | n_nsc = IWL_PROTO_OFFLOAD_NUM_NS_CONFIG_V3L; | ||
416 | addrs = cmd.v3l.targ_addrs; | ||
417 | n_addrs = IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V3L; | ||
418 | } | ||
419 | |||
420 | if (mvmvif->num_target_ipv6_addrs) | ||
421 | enabled |= IWL_D3_PROTO_OFFLOAD_NS; | ||
422 | |||
423 | /* | ||
424 | * For each address we have (and that will fit) fill a target | ||
425 | * address struct and combine for NS offload structs with the | ||
426 | * solicited node addresses. | ||
427 | */ | ||
428 | for (i = 0, c = 0; | ||
429 | i < mvmvif->num_target_ipv6_addrs && | ||
430 | i < n_addrs && c < n_nsc; i++) { | ||
431 | struct in6_addr solicited_addr; | ||
432 | int j; | ||
433 | |||
434 | addrconf_addr_solict_mult(&mvmvif->target_ipv6_addrs[i], | ||
435 | &solicited_addr); | ||
436 | for (j = 0; j < c; j++) | ||
437 | if (ipv6_addr_cmp(&nsc[j].dest_ipv6_addr, | ||
438 | &solicited_addr) == 0) | ||
439 | break; | ||
440 | if (j == c) | ||
441 | c++; | ||
442 | addrs[i].addr = mvmvif->target_ipv6_addrs[i]; | ||
443 | addrs[i].config_num = cpu_to_le32(j); | ||
444 | nsc[j].dest_ipv6_addr = solicited_addr; | ||
445 | memcpy(nsc[j].target_mac_addr, vif->addr, ETH_ALEN); | ||
446 | } | ||
447 | |||
448 | if (capa_flags & IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL) | ||
449 | cmd.v3s.num_valid_ipv6_addrs = cpu_to_le32(i); | ||
450 | else | ||
451 | cmd.v3l.num_valid_ipv6_addrs = cpu_to_le32(i); | ||
452 | } else if (capa_flags & IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS) { | ||
453 | if (mvmvif->num_target_ipv6_addrs) { | ||
454 | enabled |= IWL_D3_PROTO_OFFLOAD_NS; | ||
455 | memcpy(cmd.v2.ndp_mac_addr, vif->addr, ETH_ALEN); | ||
456 | } | ||
457 | |||
458 | BUILD_BUG_ON(sizeof(cmd.v2.target_ipv6_addr[0]) != | ||
459 | sizeof(mvmvif->target_ipv6_addrs[0])); | ||
460 | |||
461 | for (i = 0; i < min(mvmvif->num_target_ipv6_addrs, | ||
462 | IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V2); i++) | ||
463 | memcpy(cmd.v2.target_ipv6_addr[i], | ||
464 | &mvmvif->target_ipv6_addrs[i], | ||
465 | sizeof(cmd.v2.target_ipv6_addr[i])); | ||
466 | } else { | ||
467 | if (mvmvif->num_target_ipv6_addrs) { | ||
468 | enabled |= IWL_D3_PROTO_OFFLOAD_NS; | ||
469 | memcpy(cmd.v1.ndp_mac_addr, vif->addr, ETH_ALEN); | ||
470 | } | ||
471 | |||
472 | BUILD_BUG_ON(sizeof(cmd.v1.target_ipv6_addr[0]) != | ||
473 | sizeof(mvmvif->target_ipv6_addrs[0])); | ||
474 | |||
475 | for (i = 0; i < min(mvmvif->num_target_ipv6_addrs, | ||
476 | IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V1); i++) | ||
477 | memcpy(cmd.v1.target_ipv6_addr[i], | ||
478 | &mvmvif->target_ipv6_addrs[i], | ||
479 | sizeof(cmd.v1.target_ipv6_addr[i])); | ||
480 | } | ||
481 | #endif | ||
482 | |||
483 | if (capa_flags & IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL) { | ||
484 | common = &cmd.v3s.common; | ||
485 | size = sizeof(cmd.v3s); | ||
486 | } else if (capa_flags & IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE) { | ||
487 | common = &cmd.v3l.common; | ||
488 | size = sizeof(cmd.v3l); | ||
489 | } else if (capa_flags & IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS) { | ||
490 | common = &cmd.v2.common; | ||
491 | size = sizeof(cmd.v2); | ||
492 | } else { | ||
493 | common = &cmd.v1.common; | ||
494 | size = sizeof(cmd.v1); | ||
495 | } | ||
496 | |||
497 | if (vif->bss_conf.arp_addr_cnt) { | ||
498 | enabled |= IWL_D3_PROTO_OFFLOAD_ARP; | ||
499 | common->host_ipv4_addr = vif->bss_conf.arp_addr_list[0]; | ||
500 | memcpy(common->arp_mac_addr, vif->addr, ETH_ALEN); | ||
501 | } | ||
502 | |||
503 | if (!enabled) | ||
504 | return 0; | ||
505 | |||
506 | common->enabled = cpu_to_le32(enabled); | ||
507 | |||
508 | hcmd.len[0] = size; | ||
509 | return iwl_mvm_send_cmd(mvm, &hcmd); | ||
510 | } | ||
511 | |||
512 | enum iwl_mvm_tcp_packet_type { | 379 | enum iwl_mvm_tcp_packet_type { |
513 | MVM_TCP_TX_SYN, | 380 | MVM_TCP_TX_SYN, |
514 | MVM_TCP_RX_SYNACK, | 381 | MVM_TCP_RX_SYNACK, |
@@ -846,8 +713,8 @@ static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
846 | quota_cmd.quotas[0].id_and_color = | 713 | quota_cmd.quotas[0].id_and_color = |
847 | cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->phy_ctxt->id, | 714 | cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->phy_ctxt->id, |
848 | mvmvif->phy_ctxt->color)); | 715 | mvmvif->phy_ctxt->color)); |
849 | quota_cmd.quotas[0].quota = cpu_to_le32(100); | 716 | quota_cmd.quotas[0].quota = cpu_to_le32(IWL_MVM_MAX_QUOTA); |
850 | quota_cmd.quotas[0].max_duration = cpu_to_le32(1000); | 717 | quota_cmd.quotas[0].max_duration = cpu_to_le32(IWL_MVM_MAX_QUOTA); |
851 | 718 | ||
852 | for (i = 1; i < MAX_BINDINGS; i++) | 719 | for (i = 1; i < MAX_BINDINGS; i++) |
853 | quota_cmd.quotas[i].id_and_color = cpu_to_le32(FW_CTXT_INVALID); | 720 | quota_cmd.quotas[i].id_and_color = cpu_to_le32(FW_CTXT_INVALID); |
@@ -927,6 +794,20 @@ void iwl_mvm_set_last_nonqos_seq(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
927 | IWL_ERR(mvm, "failed to set non-QoS seqno\n"); | 794 | IWL_ERR(mvm, "failed to set non-QoS seqno\n"); |
928 | } | 795 | } |
929 | 796 | ||
797 | static int | ||
798 | iwl_mvm_send_wowlan_config_cmd(struct iwl_mvm *mvm, | ||
799 | const struct iwl_wowlan_config_cmd_v3 *cmd) | ||
800 | { | ||
801 | /* start only with the v2 part of the command */ | ||
802 | u16 cmd_len = sizeof(cmd->common); | ||
803 | |||
804 | if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID) | ||
805 | cmd_len = sizeof(*cmd); | ||
806 | |||
807 | return iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, CMD_SYNC, | ||
808 | cmd_len, cmd); | ||
809 | } | ||
810 | |||
930 | static int __iwl_mvm_suspend(struct ieee80211_hw *hw, | 811 | static int __iwl_mvm_suspend(struct ieee80211_hw *hw, |
931 | struct cfg80211_wowlan *wowlan, | 812 | struct cfg80211_wowlan *wowlan, |
932 | bool test) | 813 | bool test) |
@@ -939,7 +820,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, | |||
939 | struct iwl_mvm_vif *mvmvif; | 820 | struct iwl_mvm_vif *mvmvif; |
940 | struct ieee80211_sta *ap_sta; | 821 | struct ieee80211_sta *ap_sta; |
941 | struct iwl_mvm_sta *mvm_ap_sta; | 822 | struct iwl_mvm_sta *mvm_ap_sta; |
942 | struct iwl_wowlan_config_cmd wowlan_config_cmd = {}; | 823 | struct iwl_wowlan_config_cmd_v3 wowlan_config_cmd = {}; |
943 | struct iwl_wowlan_kek_kck_material_cmd kek_kck_cmd = {}; | 824 | struct iwl_wowlan_kek_kck_material_cmd kek_kck_cmd = {}; |
944 | struct iwl_wowlan_tkip_params_cmd tkip_cmd = {}; | 825 | struct iwl_wowlan_tkip_params_cmd tkip_cmd = {}; |
945 | struct iwl_d3_manager_config d3_cfg_cmd_data = { | 826 | struct iwl_d3_manager_config d3_cfg_cmd_data = { |
@@ -961,7 +842,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, | |||
961 | .tkip = &tkip_cmd, | 842 | .tkip = &tkip_cmd, |
962 | .use_tkip = false, | 843 | .use_tkip = false, |
963 | }; | 844 | }; |
964 | int ret, i; | 845 | int ret; |
965 | int len __maybe_unused; | 846 | int len __maybe_unused; |
966 | 847 | ||
967 | if (!wowlan) { | 848 | if (!wowlan) { |
@@ -1002,49 +883,41 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, | |||
1002 | 883 | ||
1003 | mvm_ap_sta = (struct iwl_mvm_sta *)ap_sta->drv_priv; | 884 | mvm_ap_sta = (struct iwl_mvm_sta *)ap_sta->drv_priv; |
1004 | 885 | ||
1005 | /* TODO: wowlan_config_cmd.wowlan_ba_teardown_tids */ | 886 | /* TODO: wowlan_config_cmd.common.wowlan_ba_teardown_tids */ |
1006 | 887 | ||
1007 | wowlan_config_cmd.is_11n_connection = ap_sta->ht_cap.ht_supported; | 888 | wowlan_config_cmd.common.is_11n_connection = |
889 | ap_sta->ht_cap.ht_supported; | ||
1008 | 890 | ||
1009 | /* Query the last used seqno and set it */ | 891 | /* Query the last used seqno and set it */ |
1010 | ret = iwl_mvm_get_last_nonqos_seq(mvm, vif); | 892 | ret = iwl_mvm_get_last_nonqos_seq(mvm, vif); |
1011 | if (ret < 0) | 893 | if (ret < 0) |
1012 | goto out_noreset; | 894 | goto out_noreset; |
1013 | wowlan_config_cmd.non_qos_seq = cpu_to_le16(ret); | 895 | wowlan_config_cmd.common.non_qos_seq = cpu_to_le16(ret); |
1014 | 896 | ||
1015 | /* | 897 | iwl_mvm_set_wowlan_qos_seq(mvm_ap_sta, &wowlan_config_cmd.common); |
1016 | * For QoS counters, we store the one to use next, so subtract 0x10 | ||
1017 | * since the uCode will add 0x10 *before* using the value while we | ||
1018 | * increment after using the value (i.e. store the next value to use). | ||
1019 | */ | ||
1020 | for (i = 0; i < IWL_MAX_TID_COUNT; i++) { | ||
1021 | u16 seq = mvm_ap_sta->tid_data[i].seq_number; | ||
1022 | seq -= 0x10; | ||
1023 | wowlan_config_cmd.qos_seq[i] = cpu_to_le16(seq); | ||
1024 | } | ||
1025 | 898 | ||
1026 | if (wowlan->disconnect) | 899 | if (wowlan->disconnect) |
1027 | wowlan_config_cmd.wakeup_filter |= | 900 | wowlan_config_cmd.common.wakeup_filter |= |
1028 | cpu_to_le32(IWL_WOWLAN_WAKEUP_BEACON_MISS | | 901 | cpu_to_le32(IWL_WOWLAN_WAKEUP_BEACON_MISS | |
1029 | IWL_WOWLAN_WAKEUP_LINK_CHANGE); | 902 | IWL_WOWLAN_WAKEUP_LINK_CHANGE); |
1030 | if (wowlan->magic_pkt) | 903 | if (wowlan->magic_pkt) |
1031 | wowlan_config_cmd.wakeup_filter |= | 904 | wowlan_config_cmd.common.wakeup_filter |= |
1032 | cpu_to_le32(IWL_WOWLAN_WAKEUP_MAGIC_PACKET); | 905 | cpu_to_le32(IWL_WOWLAN_WAKEUP_MAGIC_PACKET); |
1033 | if (wowlan->gtk_rekey_failure) | 906 | if (wowlan->gtk_rekey_failure) |
1034 | wowlan_config_cmd.wakeup_filter |= | 907 | wowlan_config_cmd.common.wakeup_filter |= |
1035 | cpu_to_le32(IWL_WOWLAN_WAKEUP_GTK_REKEY_FAIL); | 908 | cpu_to_le32(IWL_WOWLAN_WAKEUP_GTK_REKEY_FAIL); |
1036 | if (wowlan->eap_identity_req) | 909 | if (wowlan->eap_identity_req) |
1037 | wowlan_config_cmd.wakeup_filter |= | 910 | wowlan_config_cmd.common.wakeup_filter |= |
1038 | cpu_to_le32(IWL_WOWLAN_WAKEUP_EAP_IDENT_REQ); | 911 | cpu_to_le32(IWL_WOWLAN_WAKEUP_EAP_IDENT_REQ); |
1039 | if (wowlan->four_way_handshake) | 912 | if (wowlan->four_way_handshake) |
1040 | wowlan_config_cmd.wakeup_filter |= | 913 | wowlan_config_cmd.common.wakeup_filter |= |
1041 | cpu_to_le32(IWL_WOWLAN_WAKEUP_4WAY_HANDSHAKE); | 914 | cpu_to_le32(IWL_WOWLAN_WAKEUP_4WAY_HANDSHAKE); |
1042 | if (wowlan->n_patterns) | 915 | if (wowlan->n_patterns) |
1043 | wowlan_config_cmd.wakeup_filter |= | 916 | wowlan_config_cmd.common.wakeup_filter |= |
1044 | cpu_to_le32(IWL_WOWLAN_WAKEUP_PATTERN_MATCH); | 917 | cpu_to_le32(IWL_WOWLAN_WAKEUP_PATTERN_MATCH); |
1045 | 918 | ||
1046 | if (wowlan->rfkill_release) | 919 | if (wowlan->rfkill_release) |
1047 | wowlan_config_cmd.wakeup_filter |= | 920 | wowlan_config_cmd.common.wakeup_filter |= |
1048 | cpu_to_le32(IWL_WOWLAN_WAKEUP_RF_KILL_DEASSERT); | 921 | cpu_to_le32(IWL_WOWLAN_WAKEUP_RF_KILL_DEASSERT); |
1049 | 922 | ||
1050 | if (wowlan->tcp) { | 923 | if (wowlan->tcp) { |
@@ -1052,7 +925,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, | |||
1052 | * Set the "link change" (really "link lost") flag as well | 925 | * Set the "link change" (really "link lost") flag as well |
1053 | * since that implies losing the TCP connection. | 926 | * since that implies losing the TCP connection. |
1054 | */ | 927 | */ |
1055 | wowlan_config_cmd.wakeup_filter |= | 928 | wowlan_config_cmd.common.wakeup_filter |= |
1056 | cpu_to_le32(IWL_WOWLAN_WAKEUP_REMOTE_LINK_LOSS | | 929 | cpu_to_le32(IWL_WOWLAN_WAKEUP_REMOTE_LINK_LOSS | |
1057 | IWL_WOWLAN_WAKEUP_REMOTE_SIGNATURE_TABLE | | 930 | IWL_WOWLAN_WAKEUP_REMOTE_SIGNATURE_TABLE | |
1058 | IWL_WOWLAN_WAKEUP_REMOTE_WAKEUP_PACKET | | 931 | IWL_WOWLAN_WAKEUP_REMOTE_WAKEUP_PACKET | |
@@ -1150,9 +1023,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, | |||
1150 | } | 1023 | } |
1151 | } | 1024 | } |
1152 | 1025 | ||
1153 | ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, | 1026 | ret = iwl_mvm_send_wowlan_config_cmd(mvm, &wowlan_config_cmd); |
1154 | CMD_SYNC, sizeof(wowlan_config_cmd), | ||
1155 | &wowlan_config_cmd); | ||
1156 | if (ret) | 1027 | if (ret) |
1157 | goto out; | 1028 | goto out; |
1158 | 1029 | ||
@@ -1160,7 +1031,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, | |||
1160 | if (ret) | 1031 | if (ret) |
1161 | goto out; | 1032 | goto out; |
1162 | 1033 | ||
1163 | ret = iwl_mvm_send_proto_offload(mvm, vif); | 1034 | ret = iwl_mvm_send_proto_offload(mvm, vif, false, CMD_SYNC); |
1164 | if (ret) | 1035 | if (ret) |
1165 | goto out; | 1036 | goto out; |
1166 | 1037 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c index f64e972191eb..9b59e1d7ae71 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c | |||
@@ -312,6 +312,11 @@ static ssize_t iwl_dbgfs_reduced_txp_write(struct ieee80211_vif *vif, | |||
312 | mutex_lock(&mvm->mutex); | 312 | mutex_lock(&mvm->mutex); |
313 | 313 | ||
314 | mvmsta = iwl_mvm_sta_from_staid_protected(mvm, mvmvif->ap_sta_id); | 314 | mvmsta = iwl_mvm_sta_from_staid_protected(mvm, mvmvif->ap_sta_id); |
315 | if (IS_ERR_OR_NULL(mvmsta)) { | ||
316 | mutex_unlock(&mvm->mutex); | ||
317 | return -ENOTCONN; | ||
318 | } | ||
319 | |||
315 | mvmsta->bt_reduced_txpower_dbg = false; | 320 | mvmsta->bt_reduced_txpower_dbg = false; |
316 | ret = iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, | 321 | ret = iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, |
317 | reduced_tx_power); | 322 | reduced_tx_power); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index e0ff43ed2482..1b52deea6081 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c | |||
@@ -60,11 +60,14 @@ | |||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
61 | * | 61 | * |
62 | *****************************************************************************/ | 62 | *****************************************************************************/ |
63 | #include <linux/vmalloc.h> | ||
64 | |||
63 | #include "mvm.h" | 65 | #include "mvm.h" |
64 | #include "sta.h" | 66 | #include "sta.h" |
65 | #include "iwl-io.h" | 67 | #include "iwl-io.h" |
66 | #include "iwl-prph.h" | 68 | #include "iwl-prph.h" |
67 | #include "debugfs.h" | 69 | #include "debugfs.h" |
70 | #include "fw-error-dump.h" | ||
68 | 71 | ||
69 | static ssize_t iwl_dbgfs_tx_flush_write(struct iwl_mvm *mvm, char *buf, | 72 | static ssize_t iwl_dbgfs_tx_flush_write(struct iwl_mvm *mvm, char *buf, |
70 | size_t count, loff_t *ppos) | 73 | size_t count, loff_t *ppos) |
@@ -117,6 +120,51 @@ static ssize_t iwl_dbgfs_sta_drain_write(struct iwl_mvm *mvm, char *buf, | |||
117 | return ret; | 120 | return ret; |
118 | } | 121 | } |
119 | 122 | ||
123 | static int iwl_dbgfs_fw_error_dump_open(struct inode *inode, struct file *file) | ||
124 | { | ||
125 | struct iwl_mvm *mvm = inode->i_private; | ||
126 | int ret; | ||
127 | |||
128 | if (!mvm) | ||
129 | return -EINVAL; | ||
130 | |||
131 | mutex_lock(&mvm->mutex); | ||
132 | if (!mvm->fw_error_dump) { | ||
133 | ret = -ENODATA; | ||
134 | goto out; | ||
135 | } | ||
136 | |||
137 | file->private_data = mvm->fw_error_dump; | ||
138 | mvm->fw_error_dump = NULL; | ||
139 | kfree(mvm->fw_error_sram); | ||
140 | mvm->fw_error_sram = NULL; | ||
141 | mvm->fw_error_sram_len = 0; | ||
142 | ret = 0; | ||
143 | |||
144 | out: | ||
145 | mutex_unlock(&mvm->mutex); | ||
146 | return ret; | ||
147 | } | ||
148 | |||
149 | static ssize_t iwl_dbgfs_fw_error_dump_read(struct file *file, | ||
150 | char __user *user_buf, | ||
151 | size_t count, loff_t *ppos) | ||
152 | { | ||
153 | struct iwl_fw_error_dump_file *dump_file = file->private_data; | ||
154 | |||
155 | return simple_read_from_buffer(user_buf, count, ppos, | ||
156 | dump_file, | ||
157 | le32_to_cpu(dump_file->file_len)); | ||
158 | } | ||
159 | |||
160 | static int iwl_dbgfs_fw_error_dump_release(struct inode *inode, | ||
161 | struct file *file) | ||
162 | { | ||
163 | vfree(file->private_data); | ||
164 | |||
165 | return 0; | ||
166 | } | ||
167 | |||
120 | static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf, | 168 | static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf, |
121 | size_t count, loff_t *ppos) | 169 | size_t count, loff_t *ppos) |
122 | { | 170 | { |
@@ -350,6 +398,9 @@ static ssize_t iwl_dbgfs_bt_notif_read(struct file *file, char __user *user_buf, | |||
350 | le32_to_cpu(notif->secondary_ch_lut)); | 398 | le32_to_cpu(notif->secondary_ch_lut)); |
351 | pos += scnprintf(buf+pos, bufsz-pos, "bt_activity_grading = %d\n", | 399 | pos += scnprintf(buf+pos, bufsz-pos, "bt_activity_grading = %d\n", |
352 | le32_to_cpu(notif->bt_activity_grading)); | 400 | le32_to_cpu(notif->bt_activity_grading)); |
401 | pos += scnprintf(buf+pos, bufsz-pos, | ||
402 | "antenna isolation = %d CORUN LUT index = %d\n", | ||
403 | mvm->last_ant_isol, mvm->last_corun_lut); | ||
353 | 404 | ||
354 | mutex_unlock(&mvm->mutex); | 405 | mutex_unlock(&mvm->mutex); |
355 | 406 | ||
@@ -392,6 +443,22 @@ static ssize_t iwl_dbgfs_bt_cmd_read(struct file *file, char __user *user_buf, | |||
392 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 443 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
393 | } | 444 | } |
394 | 445 | ||
446 | static ssize_t | ||
447 | iwl_dbgfs_bt_tx_prio_write(struct iwl_mvm *mvm, char *buf, | ||
448 | size_t count, loff_t *ppos) | ||
449 | { | ||
450 | u32 bt_tx_prio; | ||
451 | |||
452 | if (sscanf(buf, "%u", &bt_tx_prio) != 1) | ||
453 | return -EINVAL; | ||
454 | if (bt_tx_prio > 4) | ||
455 | return -EINVAL; | ||
456 | |||
457 | mvm->bt_tx_prio = bt_tx_prio; | ||
458 | |||
459 | return count; | ||
460 | } | ||
461 | |||
395 | #define PRINT_STATS_LE32(_str, _val) \ | 462 | #define PRINT_STATS_LE32(_str, _val) \ |
396 | pos += scnprintf(buf + pos, bufsz - pos, \ | 463 | pos += scnprintf(buf + pos, bufsz - pos, \ |
397 | fmt_table, _str, \ | 464 | fmt_table, _str, \ |
@@ -536,56 +603,60 @@ static ssize_t iwl_dbgfs_frame_stats_read(struct iwl_mvm *mvm, | |||
536 | loff_t *ppos, | 603 | loff_t *ppos, |
537 | struct iwl_mvm_frame_stats *stats) | 604 | struct iwl_mvm_frame_stats *stats) |
538 | { | 605 | { |
539 | char *buff; | 606 | char *buff, *pos, *endpos; |
540 | int pos = 0, idx, i; | 607 | int idx, i; |
541 | int ret; | 608 | int ret; |
542 | size_t bufsz = 1024; | 609 | static const size_t bufsz = 1024; |
543 | 610 | ||
544 | buff = kmalloc(bufsz, GFP_KERNEL); | 611 | buff = kmalloc(bufsz, GFP_KERNEL); |
545 | if (!buff) | 612 | if (!buff) |
546 | return -ENOMEM; | 613 | return -ENOMEM; |
547 | 614 | ||
548 | spin_lock_bh(&mvm->drv_stats_lock); | 615 | spin_lock_bh(&mvm->drv_stats_lock); |
549 | pos += scnprintf(buff + pos, bufsz - pos, | 616 | |
617 | pos = buff; | ||
618 | endpos = pos + bufsz; | ||
619 | |||
620 | pos += scnprintf(pos, endpos - pos, | ||
550 | "Legacy/HT/VHT\t:\t%d/%d/%d\n", | 621 | "Legacy/HT/VHT\t:\t%d/%d/%d\n", |
551 | stats->legacy_frames, | 622 | stats->legacy_frames, |
552 | stats->ht_frames, | 623 | stats->ht_frames, |
553 | stats->vht_frames); | 624 | stats->vht_frames); |
554 | pos += scnprintf(buff + pos, bufsz - pos, "20/40/80\t:\t%d/%d/%d\n", | 625 | pos += scnprintf(pos, endpos - pos, "20/40/80\t:\t%d/%d/%d\n", |
555 | stats->bw_20_frames, | 626 | stats->bw_20_frames, |
556 | stats->bw_40_frames, | 627 | stats->bw_40_frames, |
557 | stats->bw_80_frames); | 628 | stats->bw_80_frames); |
558 | pos += scnprintf(buff + pos, bufsz - pos, "NGI/SGI\t\t:\t%d/%d\n", | 629 | pos += scnprintf(pos, endpos - pos, "NGI/SGI\t\t:\t%d/%d\n", |
559 | stats->ngi_frames, | 630 | stats->ngi_frames, |
560 | stats->sgi_frames); | 631 | stats->sgi_frames); |
561 | pos += scnprintf(buff + pos, bufsz - pos, "SISO/MIMO2\t:\t%d/%d\n", | 632 | pos += scnprintf(pos, endpos - pos, "SISO/MIMO2\t:\t%d/%d\n", |
562 | stats->siso_frames, | 633 | stats->siso_frames, |
563 | stats->mimo2_frames); | 634 | stats->mimo2_frames); |
564 | pos += scnprintf(buff + pos, bufsz - pos, "FAIL/SCSS\t:\t%d/%d\n", | 635 | pos += scnprintf(pos, endpos - pos, "FAIL/SCSS\t:\t%d/%d\n", |
565 | stats->fail_frames, | 636 | stats->fail_frames, |
566 | stats->success_frames); | 637 | stats->success_frames); |
567 | pos += scnprintf(buff + pos, bufsz - pos, "MPDUs agg\t:\t%d\n", | 638 | pos += scnprintf(pos, endpos - pos, "MPDUs agg\t:\t%d\n", |
568 | stats->agg_frames); | 639 | stats->agg_frames); |
569 | pos += scnprintf(buff + pos, bufsz - pos, "A-MPDUs\t\t:\t%d\n", | 640 | pos += scnprintf(pos, endpos - pos, "A-MPDUs\t\t:\t%d\n", |
570 | stats->ampdu_count); | 641 | stats->ampdu_count); |
571 | pos += scnprintf(buff + pos, bufsz - pos, "Avg MPDUs/A-MPDU:\t%d\n", | 642 | pos += scnprintf(pos, endpos - pos, "Avg MPDUs/A-MPDU:\t%d\n", |
572 | stats->ampdu_count > 0 ? | 643 | stats->ampdu_count > 0 ? |
573 | (stats->agg_frames / stats->ampdu_count) : 0); | 644 | (stats->agg_frames / stats->ampdu_count) : 0); |
574 | 645 | ||
575 | pos += scnprintf(buff + pos, bufsz - pos, "Last Rates\n"); | 646 | pos += scnprintf(pos, endpos - pos, "Last Rates\n"); |
576 | 647 | ||
577 | idx = stats->last_frame_idx - 1; | 648 | idx = stats->last_frame_idx - 1; |
578 | for (i = 0; i < ARRAY_SIZE(stats->last_rates); i++) { | 649 | for (i = 0; i < ARRAY_SIZE(stats->last_rates); i++) { |
579 | idx = (idx + 1) % ARRAY_SIZE(stats->last_rates); | 650 | idx = (idx + 1) % ARRAY_SIZE(stats->last_rates); |
580 | if (stats->last_rates[idx] == 0) | 651 | if (stats->last_rates[idx] == 0) |
581 | continue; | 652 | continue; |
582 | pos += scnprintf(buff + pos, bufsz - pos, "Rate[%d]: ", | 653 | pos += scnprintf(pos, endpos - pos, "Rate[%d]: ", |
583 | (int)(ARRAY_SIZE(stats->last_rates) - i)); | 654 | (int)(ARRAY_SIZE(stats->last_rates) - i)); |
584 | pos += rs_pretty_print_rate(buff + pos, stats->last_rates[idx]); | 655 | pos += rs_pretty_print_rate(pos, stats->last_rates[idx]); |
585 | } | 656 | } |
586 | spin_unlock_bh(&mvm->drv_stats_lock); | 657 | spin_unlock_bh(&mvm->drv_stats_lock); |
587 | 658 | ||
588 | ret = simple_read_from_buffer(user_buf, count, ppos, buff, pos); | 659 | ret = simple_read_from_buffer(user_buf, count, ppos, buff, pos - buff); |
589 | kfree(buff); | 660 | kfree(buff); |
590 | 661 | ||
591 | return ret; | 662 | return ret; |
@@ -1032,9 +1103,16 @@ MVM_DEBUGFS_READ_FILE_OPS(fw_rx_stats); | |||
1032 | MVM_DEBUGFS_READ_FILE_OPS(drv_rx_stats); | 1103 | MVM_DEBUGFS_READ_FILE_OPS(drv_rx_stats); |
1033 | MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart, 10); | 1104 | MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart, 10); |
1034 | MVM_DEBUGFS_WRITE_FILE_OPS(fw_nmi, 10); | 1105 | MVM_DEBUGFS_WRITE_FILE_OPS(fw_nmi, 10); |
1106 | MVM_DEBUGFS_WRITE_FILE_OPS(bt_tx_prio, 10); | ||
1035 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8); | 1107 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8); |
1036 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8); | 1108 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8); |
1037 | 1109 | ||
1110 | static const struct file_operations iwl_dbgfs_fw_error_dump_ops = { | ||
1111 | .open = iwl_dbgfs_fw_error_dump_open, | ||
1112 | .read = iwl_dbgfs_fw_error_dump_read, | ||
1113 | .release = iwl_dbgfs_fw_error_dump_release, | ||
1114 | }; | ||
1115 | |||
1038 | #ifdef CONFIG_IWLWIFI_BCAST_FILTERING | 1116 | #ifdef CONFIG_IWLWIFI_BCAST_FILTERING |
1039 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256); | 1117 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256); |
1040 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters_macs, 256); | 1118 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters_macs, 256); |
@@ -1049,12 +1127,15 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) | |||
1049 | struct dentry *bcast_dir __maybe_unused; | 1127 | struct dentry *bcast_dir __maybe_unused; |
1050 | char buf[100]; | 1128 | char buf[100]; |
1051 | 1129 | ||
1130 | spin_lock_init(&mvm->drv_stats_lock); | ||
1131 | |||
1052 | mvm->debugfs_dir = dbgfs_dir; | 1132 | mvm->debugfs_dir = dbgfs_dir; |
1053 | 1133 | ||
1054 | MVM_DEBUGFS_ADD_FILE(tx_flush, mvm->debugfs_dir, S_IWUSR); | 1134 | MVM_DEBUGFS_ADD_FILE(tx_flush, mvm->debugfs_dir, S_IWUSR); |
1055 | MVM_DEBUGFS_ADD_FILE(sta_drain, mvm->debugfs_dir, S_IWUSR); | 1135 | MVM_DEBUGFS_ADD_FILE(sta_drain, mvm->debugfs_dir, S_IWUSR); |
1056 | MVM_DEBUGFS_ADD_FILE(sram, mvm->debugfs_dir, S_IWUSR | S_IRUSR); | 1136 | MVM_DEBUGFS_ADD_FILE(sram, mvm->debugfs_dir, S_IWUSR | S_IRUSR); |
1057 | MVM_DEBUGFS_ADD_FILE(stations, dbgfs_dir, S_IRUSR); | 1137 | MVM_DEBUGFS_ADD_FILE(stations, dbgfs_dir, S_IRUSR); |
1138 | MVM_DEBUGFS_ADD_FILE(fw_error_dump, dbgfs_dir, S_IRUSR); | ||
1058 | MVM_DEBUGFS_ADD_FILE(bt_notif, dbgfs_dir, S_IRUSR); | 1139 | MVM_DEBUGFS_ADD_FILE(bt_notif, dbgfs_dir, S_IRUSR); |
1059 | MVM_DEBUGFS_ADD_FILE(bt_cmd, dbgfs_dir, S_IRUSR); | 1140 | MVM_DEBUGFS_ADD_FILE(bt_cmd, dbgfs_dir, S_IRUSR); |
1060 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD) | 1141 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD) |
@@ -1064,6 +1145,7 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) | |||
1064 | MVM_DEBUGFS_ADD_FILE(drv_rx_stats, mvm->debugfs_dir, S_IRUSR); | 1145 | MVM_DEBUGFS_ADD_FILE(drv_rx_stats, mvm->debugfs_dir, S_IRUSR); |
1065 | MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR); | 1146 | MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR); |
1066 | MVM_DEBUGFS_ADD_FILE(fw_nmi, mvm->debugfs_dir, S_IWUSR); | 1147 | MVM_DEBUGFS_ADD_FILE(fw_nmi, mvm->debugfs_dir, S_IWUSR); |
1148 | MVM_DEBUGFS_ADD_FILE(bt_tx_prio, mvm->debugfs_dir, S_IWUSR); | ||
1067 | MVM_DEBUGFS_ADD_FILE(scan_ant_rxchain, mvm->debugfs_dir, | 1149 | MVM_DEBUGFS_ADD_FILE(scan_ant_rxchain, mvm->debugfs_dir, |
1068 | S_IWUSR | S_IRUSR); | 1150 | S_IWUSR | S_IRUSR); |
1069 | MVM_DEBUGFS_ADD_FILE(prph_reg, mvm->debugfs_dir, S_IWUSR | S_IRUSR); | 1151 | MVM_DEBUGFS_ADD_FILE(prph_reg, mvm->debugfs_dir, S_IWUSR | S_IRUSR); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h index 20b723d6270f..21877e5966a8 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h | |||
@@ -77,6 +77,8 @@ | |||
77 | * @BT_COEX_3W: | 77 | * @BT_COEX_3W: |
78 | * @BT_COEX_NW: | 78 | * @BT_COEX_NW: |
79 | * @BT_COEX_SYNC2SCO: | 79 | * @BT_COEX_SYNC2SCO: |
80 | * @BT_COEX_CORUNNING: | ||
81 | * @BT_COEX_MPLUT: | ||
80 | * | 82 | * |
81 | * The COEX_MODE must be set for each command. Even if it is not changed. | 83 | * The COEX_MODE must be set for each command. Even if it is not changed. |
82 | */ | 84 | */ |
@@ -88,6 +90,8 @@ enum iwl_bt_coex_flags { | |||
88 | BT_COEX_3W = 0x2 << BT_COEX_MODE_POS, | 90 | BT_COEX_3W = 0x2 << BT_COEX_MODE_POS, |
89 | BT_COEX_NW = 0x3 << BT_COEX_MODE_POS, | 91 | BT_COEX_NW = 0x3 << BT_COEX_MODE_POS, |
90 | BT_COEX_SYNC2SCO = BIT(7), | 92 | BT_COEX_SYNC2SCO = BIT(7), |
93 | BT_COEX_CORUNNING = BIT(8), | ||
94 | BT_COEX_MPLUT = BIT(9), | ||
91 | }; | 95 | }; |
92 | 96 | ||
93 | /* | 97 | /* |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h index 521997669c99..10fcc1a79ebd 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h | |||
@@ -239,7 +239,7 @@ enum iwl_wowlan_wakeup_filters { | |||
239 | IWL_WOWLAN_WAKEUP_BCN_FILTERING = BIT(16), | 239 | IWL_WOWLAN_WAKEUP_BCN_FILTERING = BIT(16), |
240 | }; /* WOWLAN_WAKEUP_FILTER_API_E_VER_4 */ | 240 | }; /* WOWLAN_WAKEUP_FILTER_API_E_VER_4 */ |
241 | 241 | ||
242 | struct iwl_wowlan_config_cmd { | 242 | struct iwl_wowlan_config_cmd_v2 { |
243 | __le32 wakeup_filter; | 243 | __le32 wakeup_filter; |
244 | __le16 non_qos_seq; | 244 | __le16 non_qos_seq; |
245 | __le16 qos_seq[8]; | 245 | __le16 qos_seq[8]; |
@@ -247,6 +247,12 @@ struct iwl_wowlan_config_cmd { | |||
247 | u8 is_11n_connection; | 247 | u8 is_11n_connection; |
248 | } __packed; /* WOWLAN_CONFIG_API_S_VER_2 */ | 248 | } __packed; /* WOWLAN_CONFIG_API_S_VER_2 */ |
249 | 249 | ||
250 | struct iwl_wowlan_config_cmd_v3 { | ||
251 | struct iwl_wowlan_config_cmd_v2 common; | ||
252 | u8 offloading_tid; | ||
253 | u8 reserved[3]; | ||
254 | } __packed; /* WOWLAN_CONFIG_API_S_VER_3 */ | ||
255 | |||
250 | /* | 256 | /* |
251 | * WOWLAN_TSC_RSC_PARAMS | 257 | * WOWLAN_TSC_RSC_PARAMS |
252 | */ | 258 | */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h index b674c2a2b51c..8e122f3a7a74 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h | |||
@@ -76,6 +76,8 @@ | |||
76 | * @TX_CMD_FLG_VHT_NDPA: mark frame is NDPA for VHT beamformer sequence | 76 | * @TX_CMD_FLG_VHT_NDPA: mark frame is NDPA for VHT beamformer sequence |
77 | * @TX_CMD_FLG_HT_NDPA: mark frame is NDPA for HT beamformer sequence | 77 | * @TX_CMD_FLG_HT_NDPA: mark frame is NDPA for HT beamformer sequence |
78 | * @TX_CMD_FLG_CSI_FDBK2HOST: mark to send feedback to host (only if good CRC) | 78 | * @TX_CMD_FLG_CSI_FDBK2HOST: mark to send feedback to host (only if good CRC) |
79 | * @TX_CMD_FLG_BT_PRIO_POS: the position of the BT priority (bit 11 is ignored | ||
80 | * on old firmwares). | ||
79 | * @TX_CMD_FLG_BT_DIS: disable BT priority for this frame | 81 | * @TX_CMD_FLG_BT_DIS: disable BT priority for this frame |
80 | * @TX_CMD_FLG_SEQ_CTL: set if FW should override the sequence control. | 82 | * @TX_CMD_FLG_SEQ_CTL: set if FW should override the sequence control. |
81 | * Should be set for mgmt, non-QOS data, mcast, bcast and in scan command | 83 | * Should be set for mgmt, non-QOS data, mcast, bcast and in scan command |
@@ -107,6 +109,7 @@ enum iwl_tx_flags { | |||
107 | TX_CMD_FLG_VHT_NDPA = BIT(8), | 109 | TX_CMD_FLG_VHT_NDPA = BIT(8), |
108 | TX_CMD_FLG_HT_NDPA = BIT(9), | 110 | TX_CMD_FLG_HT_NDPA = BIT(9), |
109 | TX_CMD_FLG_CSI_FDBK2HOST = BIT(10), | 111 | TX_CMD_FLG_CSI_FDBK2HOST = BIT(10), |
112 | TX_CMD_FLG_BT_PRIO_POS = 11, | ||
110 | TX_CMD_FLG_BT_DIS = BIT(12), | 113 | TX_CMD_FLG_BT_DIS = BIT(12), |
111 | TX_CMD_FLG_SEQ_CTL = BIT(13), | 114 | TX_CMD_FLG_SEQ_CTL = BIT(13), |
112 | TX_CMD_FLG_MORE_FRAG = BIT(14), | 115 | TX_CMD_FLG_MORE_FRAG = BIT(14), |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h index 807fa525cafe..6e75b52588de 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h | |||
@@ -70,7 +70,7 @@ | |||
70 | #include "fw-api-mac.h" | 70 | #include "fw-api-mac.h" |
71 | #include "fw-api-power.h" | 71 | #include "fw-api-power.h" |
72 | #include "fw-api-d3.h" | 72 | #include "fw-api-d3.h" |
73 | #include "fw-api-bt-coex.h" | 73 | #include "fw-api-coex.h" |
74 | 74 | ||
75 | /* maximal number of Tx queues in any platform */ | 75 | /* maximal number of Tx queues in any platform */ |
76 | #define IWL_MVM_MAX_QUEUES 20 | 76 | #define IWL_MVM_MAX_QUEUES 20 |
@@ -95,6 +95,7 @@ enum { | |||
95 | /* PHY context commands */ | 95 | /* PHY context commands */ |
96 | PHY_CONTEXT_CMD = 0x8, | 96 | PHY_CONTEXT_CMD = 0x8, |
97 | DBG_CFG = 0x9, | 97 | DBG_CFG = 0x9, |
98 | ANTENNA_COUPLING_NOTIFICATION = 0xa, | ||
98 | 99 | ||
99 | /* station table */ | 100 | /* station table */ |
100 | ADD_STA_KEY = 0x17, | 101 | ADD_STA_KEY = 0x17, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-error-dump.h b/drivers/net/wireless/iwlwifi/mvm/fw-error-dump.h new file mode 100644 index 000000000000..58c8941c0d95 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/mvm/fw-error-dump.h | |||
@@ -0,0 +1,106 @@ | |||
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) 2014 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 COPYING. | ||
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) 2014 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 __fw_error_dump_h__ | ||
64 | #define __fw_error_dump_h__ | ||
65 | |||
66 | #include <linux/types.h> | ||
67 | |||
68 | #define IWL_FW_ERROR_DUMP_BARKER 0x14789632 | ||
69 | |||
70 | /** | ||
71 | * enum iwl_fw_error_dump_type - types of data in the dump file | ||
72 | * @IWL_FW_ERROR_DUMP_SRAM: | ||
73 | * @IWL_FW_ERROR_DUMP_REG: | ||
74 | */ | ||
75 | enum iwl_fw_error_dump_type { | ||
76 | IWL_FW_ERROR_DUMP_SRAM = 0, | ||
77 | IWL_FW_ERROR_DUMP_REG = 1, | ||
78 | |||
79 | IWL_FW_ERROR_DUMP_MAX, | ||
80 | }; | ||
81 | |||
82 | /** | ||
83 | * struct iwl_fw_error_dump_data - data for one type | ||
84 | * @type: %enum iwl_fw_error_dump_type | ||
85 | * @len: the length starting from %data - must be a multiplier of 4. | ||
86 | * @data: the data itself padded to be a multiplier of 4. | ||
87 | */ | ||
88 | struct iwl_fw_error_dump_data { | ||
89 | __le32 type; | ||
90 | __le32 len; | ||
91 | __u8 data[]; | ||
92 | } __packed __aligned(4); | ||
93 | |||
94 | /** | ||
95 | * struct iwl_fw_error_dump_file - the layout of the header of the file | ||
96 | * @barker: must be %IWL_FW_ERROR_DUMP_BARKER | ||
97 | * @file_len: the length of all the file starting from %barker | ||
98 | * @data: array of %struct iwl_fw_error_dump_data | ||
99 | */ | ||
100 | struct iwl_fw_error_dump_file { | ||
101 | __le32 barker; | ||
102 | __le32 file_len; | ||
103 | u8 data[0]; | ||
104 | } __packed __aligned(4); | ||
105 | |||
106 | #endif /* __fw_error_dump_h__ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/led.c b/drivers/net/wireless/iwlwifi/mvm/led.c index 6b4ea6bf8ffe..e3b3cf4dbd77 100644 --- a/drivers/net/wireless/iwlwifi/mvm/led.c +++ b/drivers/net/wireless/iwlwifi/mvm/led.c | |||
@@ -94,6 +94,8 @@ int iwl_mvm_leds_init(struct iwl_mvm *mvm) | |||
94 | int ret; | 94 | int ret; |
95 | 95 | ||
96 | switch (mode) { | 96 | switch (mode) { |
97 | case IWL_LED_BLINK: | ||
98 | IWL_ERR(mvm, "Blink led mode not supported, used default\n"); | ||
97 | case IWL_LED_DEFAULT: | 99 | case IWL_LED_DEFAULT: |
98 | case IWL_LED_RF_STATE: | 100 | case IWL_LED_RF_STATE: |
99 | mode = IWL_LED_RF_STATE; | 101 | mode = IWL_LED_RF_STATE; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index c2ab6a3318cb..4dd9ff43b8b6 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
@@ -205,7 +205,7 @@ static const struct iwl_fw_bcast_filter iwl_mvm_default_bcast_filters[] = { | |||
205 | 205 | ||
206 | void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type) | 206 | void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type) |
207 | { | 207 | { |
208 | if (!mvm->trans->cfg->d0i3) | 208 | if (!iwl_mvm_is_d0i3_supported(mvm)) |
209 | return; | 209 | return; |
210 | 210 | ||
211 | IWL_DEBUG_RPM(mvm, "Take mvm reference - type %d\n", ref_type); | 211 | IWL_DEBUG_RPM(mvm, "Take mvm reference - type %d\n", ref_type); |
@@ -215,7 +215,7 @@ void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type) | |||
215 | 215 | ||
216 | void iwl_mvm_unref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type) | 216 | void iwl_mvm_unref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type) |
217 | { | 217 | { |
218 | if (!mvm->trans->cfg->d0i3) | 218 | if (!iwl_mvm_is_d0i3_supported(mvm)) |
219 | return; | 219 | return; |
220 | 220 | ||
221 | IWL_DEBUG_RPM(mvm, "Leave mvm reference - type %d\n", ref_type); | 221 | IWL_DEBUG_RPM(mvm, "Leave mvm reference - type %d\n", ref_type); |
@@ -228,7 +228,7 @@ iwl_mvm_unref_all_except(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref) | |||
228 | { | 228 | { |
229 | int i; | 229 | int i; |
230 | 230 | ||
231 | if (!mvm->trans->cfg->d0i3) | 231 | if (!iwl_mvm_is_d0i3_supported(mvm)) |
232 | return; | 232 | return; |
233 | 233 | ||
234 | for_each_set_bit(i, mvm->ref_bitmap, IWL_MVM_REF_COUNT) { | 234 | for_each_set_bit(i, mvm->ref_bitmap, IWL_MVM_REF_COUNT) { |
@@ -295,7 +295,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
295 | !iwlwifi_mod_params.sw_crypto) | 295 | !iwlwifi_mod_params.sw_crypto) |
296 | hw->flags |= IEEE80211_HW_MFP_CAPABLE; | 296 | hw->flags |= IEEE80211_HW_MFP_CAPABLE; |
297 | 297 | ||
298 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT) { | 298 | if (0 && mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT) { |
299 | hw->flags |= IEEE80211_HW_SUPPORTS_UAPSD; | 299 | hw->flags |= IEEE80211_HW_SUPPORTS_UAPSD; |
300 | hw->uapsd_queues = IWL_UAPSD_AC_INFO; | 300 | hw->uapsd_queues = IWL_UAPSD_AC_INFO; |
301 | hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP; | 301 | hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP; |
@@ -365,7 +365,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
365 | else | 365 | else |
366 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | 366 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; |
367 | 367 | ||
368 | if (0 && mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_SCHED_SCAN) { | 368 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_SCHED_SCAN) { |
369 | hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; | 369 | hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; |
370 | hw->wiphy->max_sched_scan_ssids = PROBE_OPTION_MAX; | 370 | hw->wiphy->max_sched_scan_ssids = PROBE_OPTION_MAX; |
371 | hw->wiphy->max_match_sets = IWL_SCAN_MAX_PROFILES; | 371 | hw->wiphy->max_match_sets = IWL_SCAN_MAX_PROFILES; |
@@ -375,8 +375,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
375 | } | 375 | } |
376 | 376 | ||
377 | hw->wiphy->features |= NL80211_FEATURE_P2P_GO_CTWIN | | 377 | hw->wiphy->features |= NL80211_FEATURE_P2P_GO_CTWIN | |
378 | NL80211_FEATURE_P2P_GO_OPPPS | | 378 | NL80211_FEATURE_P2P_GO_OPPPS; |
379 | NL80211_FEATURE_LOW_PRIORITY_SCAN; | ||
380 | 379 | ||
381 | mvm->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; | 380 | mvm->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; |
382 | 381 | ||
@@ -424,6 +423,47 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
424 | return ret; | 423 | return ret; |
425 | } | 424 | } |
426 | 425 | ||
426 | static bool iwl_mvm_defer_tx(struct iwl_mvm *mvm, | ||
427 | struct ieee80211_sta *sta, | ||
428 | struct sk_buff *skb) | ||
429 | { | ||
430 | struct iwl_mvm_sta *mvmsta; | ||
431 | bool defer = false; | ||
432 | |||
433 | /* | ||
434 | * double check the IN_D0I3 flag both before and after | ||
435 | * taking the spinlock, in order to prevent taking | ||
436 | * the spinlock when not needed. | ||
437 | */ | ||
438 | if (likely(!test_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status))) | ||
439 | return false; | ||
440 | |||
441 | spin_lock(&mvm->d0i3_tx_lock); | ||
442 | /* | ||
443 | * testing the flag again ensures the skb dequeue | ||
444 | * loop (on d0i3 exit) hasn't run yet. | ||
445 | */ | ||
446 | if (!test_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status)) | ||
447 | goto out; | ||
448 | |||
449 | mvmsta = iwl_mvm_sta_from_mac80211(sta); | ||
450 | if (mvmsta->sta_id == IWL_MVM_STATION_COUNT || | ||
451 | mvmsta->sta_id != mvm->d0i3_ap_sta_id) | ||
452 | goto out; | ||
453 | |||
454 | __skb_queue_tail(&mvm->d0i3_tx, skb); | ||
455 | ieee80211_stop_queues(mvm->hw); | ||
456 | |||
457 | /* trigger wakeup */ | ||
458 | iwl_mvm_ref(mvm, IWL_MVM_REF_TX); | ||
459 | iwl_mvm_unref(mvm, IWL_MVM_REF_TX); | ||
460 | |||
461 | defer = true; | ||
462 | out: | ||
463 | spin_unlock(&mvm->d0i3_tx_lock); | ||
464 | return defer; | ||
465 | } | ||
466 | |||
427 | static void iwl_mvm_mac_tx(struct ieee80211_hw *hw, | 467 | static void iwl_mvm_mac_tx(struct ieee80211_hw *hw, |
428 | struct ieee80211_tx_control *control, | 468 | struct ieee80211_tx_control *control, |
429 | struct sk_buff *skb) | 469 | struct sk_buff *skb) |
@@ -451,6 +491,8 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw, | |||
451 | sta = NULL; | 491 | sta = NULL; |
452 | 492 | ||
453 | if (sta) { | 493 | if (sta) { |
494 | if (iwl_mvm_defer_tx(mvm, sta, skb)) | ||
495 | return; | ||
454 | if (iwl_mvm_tx_skb(mvm, skb, sta)) | 496 | if (iwl_mvm_tx_skb(mvm, skb, sta)) |
455 | goto drop; | 497 | goto drop; |
456 | return; | 498 | return; |
@@ -489,6 +531,7 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw, | |||
489 | { | 531 | { |
490 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 532 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
491 | int ret; | 533 | int ret; |
534 | bool tx_agg_ref = false; | ||
492 | 535 | ||
493 | IWL_DEBUG_HT(mvm, "A-MPDU action on addr %pM tid %d: action %d\n", | 536 | IWL_DEBUG_HT(mvm, "A-MPDU action on addr %pM tid %d: action %d\n", |
494 | sta->addr, tid, action); | 537 | sta->addr, tid, action); |
@@ -496,6 +539,23 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw, | |||
496 | if (!(mvm->nvm_data->sku_cap_11n_enable)) | 539 | if (!(mvm->nvm_data->sku_cap_11n_enable)) |
497 | return -EACCES; | 540 | return -EACCES; |
498 | 541 | ||
542 | /* return from D0i3 before starting a new Tx aggregation */ | ||
543 | if (action == IEEE80211_AMPDU_TX_START) { | ||
544 | iwl_mvm_ref(mvm, IWL_MVM_REF_TX_AGG); | ||
545 | tx_agg_ref = true; | ||
546 | |||
547 | /* | ||
548 | * wait synchronously until D0i3 exit to get the correct | ||
549 | * sequence number for the tid | ||
550 | */ | ||
551 | if (!wait_event_timeout(mvm->d0i3_exit_waitq, | ||
552 | !test_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status), HZ)) { | ||
553 | WARN_ON_ONCE(1); | ||
554 | iwl_mvm_unref(mvm, IWL_MVM_REF_TX_AGG); | ||
555 | return -EIO; | ||
556 | } | ||
557 | } | ||
558 | |||
499 | mutex_lock(&mvm->mutex); | 559 | mutex_lock(&mvm->mutex); |
500 | 560 | ||
501 | switch (action) { | 561 | switch (action) { |
@@ -533,6 +593,13 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw, | |||
533 | } | 593 | } |
534 | mutex_unlock(&mvm->mutex); | 594 | mutex_unlock(&mvm->mutex); |
535 | 595 | ||
596 | /* | ||
597 | * If the tid is marked as started, we won't use it for offloaded | ||
598 | * traffic on the next D0i3 entry. It's safe to unref. | ||
599 | */ | ||
600 | if (tx_agg_ref) | ||
601 | iwl_mvm_unref(mvm, IWL_MVM_REF_TX_AGG); | ||
602 | |||
536 | return ret; | 603 | return ret; |
537 | } | 604 | } |
538 | 605 | ||
@@ -557,6 +624,15 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac, | |||
557 | 624 | ||
558 | static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm) | 625 | static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm) |
559 | { | 626 | { |
627 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
628 | static char *env[] = { "DRIVER=iwlwifi", "EVENT=error_dump", NULL }; | ||
629 | |||
630 | iwl_mvm_fw_error_dump(mvm); | ||
631 | |||
632 | /* notify the userspace about the error we had */ | ||
633 | kobject_uevent_env(&mvm->hw->wiphy->dev.kobj, KOBJ_CHANGE, env); | ||
634 | #endif | ||
635 | |||
560 | iwl_trans_stop_device(mvm->trans); | 636 | iwl_trans_stop_device(mvm->trans); |
561 | 637 | ||
562 | mvm->scan_status = IWL_MVM_SCAN_NONE; | 638 | mvm->scan_status = IWL_MVM_SCAN_NONE; |
@@ -610,6 +686,7 @@ static void iwl_mvm_mac_restart_complete(struct ieee80211_hw *hw) | |||
610 | mutex_lock(&mvm->mutex); | 686 | mutex_lock(&mvm->mutex); |
611 | 687 | ||
612 | clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status); | 688 | clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status); |
689 | iwl_mvm_d0i3_enable_tx(mvm, NULL); | ||
613 | ret = iwl_mvm_update_quotas(mvm, NULL); | 690 | ret = iwl_mvm_update_quotas(mvm, NULL); |
614 | if (ret) | 691 | if (ret) |
615 | IWL_ERR(mvm, "Failed to update quotas after restart (%d)\n", | 692 | IWL_ERR(mvm, "Failed to update quotas after restart (%d)\n", |
@@ -1255,6 +1332,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | |||
1255 | */ | 1332 | */ |
1256 | iwl_mvm_remove_time_event(mvm, mvmvif, | 1333 | iwl_mvm_remove_time_event(mvm, mvmvif, |
1257 | &mvmvif->time_event_data); | 1334 | &mvmvif->time_event_data); |
1335 | WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, CMD_SYNC)); | ||
1258 | } else if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS | | 1336 | } else if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS | |
1259 | BSS_CHANGED_QOS)) { | 1337 | BSS_CHANGED_QOS)) { |
1260 | ret = iwl_mvm_power_update_mac(mvm, vif); | 1338 | ret = iwl_mvm_power_update_mac(mvm, vif); |
@@ -1437,8 +1515,6 @@ static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw, | |||
1437 | struct cfg80211_scan_request *req) | 1515 | struct cfg80211_scan_request *req) |
1438 | { | 1516 | { |
1439 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 1517 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
1440 | struct iwl_notification_wait wait_scan_done; | ||
1441 | static const u8 scan_done_notif[] = { SCAN_OFFLOAD_COMPLETE, }; | ||
1442 | int ret; | 1518 | int ret; |
1443 | 1519 | ||
1444 | if (req->n_channels == 0 || req->n_channels > MAX_NUM_SCAN_CHANNELS) | 1520 | if (req->n_channels == 0 || req->n_channels > MAX_NUM_SCAN_CHANNELS) |
@@ -1448,22 +1524,11 @@ static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw, | |||
1448 | 1524 | ||
1449 | switch (mvm->scan_status) { | 1525 | switch (mvm->scan_status) { |
1450 | case IWL_MVM_SCAN_SCHED: | 1526 | case IWL_MVM_SCAN_SCHED: |
1451 | iwl_init_notification_wait(&mvm->notif_wait, &wait_scan_done, | 1527 | ret = iwl_mvm_sched_scan_stop(mvm); |
1452 | scan_done_notif, | ||
1453 | ARRAY_SIZE(scan_done_notif), | ||
1454 | NULL, NULL); | ||
1455 | iwl_mvm_sched_scan_stop(mvm); | ||
1456 | ret = iwl_wait_notification(&mvm->notif_wait, | ||
1457 | &wait_scan_done, HZ); | ||
1458 | if (ret) { | 1528 | if (ret) { |
1459 | ret = -EBUSY; | 1529 | ret = -EBUSY; |
1460 | goto out; | 1530 | goto out; |
1461 | } | 1531 | } |
1462 | /* iwl_mvm_rx_scan_offload_complete_notif() will be called | ||
1463 | * soon but will not reset the scan status as it won't be | ||
1464 | * IWL_MVM_SCAN_SCHED any more since we queue the next scan | ||
1465 | * immediately (below) | ||
1466 | */ | ||
1467 | break; | 1532 | break; |
1468 | case IWL_MVM_SCAN_NONE: | 1533 | case IWL_MVM_SCAN_NONE: |
1469 | break; | 1534 | break; |
@@ -1479,7 +1544,8 @@ static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw, | |||
1479 | iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); | 1544 | iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); |
1480 | out: | 1545 | out: |
1481 | mutex_unlock(&mvm->mutex); | 1546 | mutex_unlock(&mvm->mutex); |
1482 | 1547 | /* make sure to flush the Rx handler before the next scan arrives */ | |
1548 | iwl_mvm_wait_for_async_handlers(mvm); | ||
1483 | return ret; | 1549 | return ret; |
1484 | } | 1550 | } |
1485 | 1551 | ||
@@ -1641,7 +1707,9 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, | |||
1641 | } else if (old_state == IEEE80211_STA_ASSOC && | 1707 | } else if (old_state == IEEE80211_STA_ASSOC && |
1642 | new_state == IEEE80211_STA_AUTHORIZED) { | 1708 | new_state == IEEE80211_STA_AUTHORIZED) { |
1643 | /* enable beacon filtering */ | 1709 | /* enable beacon filtering */ |
1644 | WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, CMD_SYNC)); | 1710 | if (vif->bss_conf.dtim_period) |
1711 | WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, | ||
1712 | CMD_SYNC)); | ||
1645 | ret = 0; | 1713 | ret = 0; |
1646 | } else if (old_state == IEEE80211_STA_AUTHORIZED && | 1714 | } else if (old_state == IEEE80211_STA_AUTHORIZED && |
1647 | new_state == IEEE80211_STA_ASSOC) { | 1715 | new_state == IEEE80211_STA_ASSOC) { |
@@ -1738,9 +1806,26 @@ static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw, | |||
1738 | 1806 | ||
1739 | mutex_lock(&mvm->mutex); | 1807 | mutex_lock(&mvm->mutex); |
1740 | 1808 | ||
1741 | if (mvm->scan_status != IWL_MVM_SCAN_NONE) { | 1809 | switch (mvm->scan_status) { |
1742 | IWL_DEBUG_SCAN(mvm, | 1810 | case IWL_MVM_SCAN_OS: |
1743 | "SCHED SCAN request during internal scan - abort\n"); | 1811 | IWL_DEBUG_SCAN(mvm, "Stopping previous scan for sched_scan\n"); |
1812 | ret = iwl_mvm_cancel_scan(mvm); | ||
1813 | if (ret) { | ||
1814 | ret = -EBUSY; | ||
1815 | goto out; | ||
1816 | } | ||
1817 | |||
1818 | /* | ||
1819 | * iwl_mvm_rx_scan_complete() will be called soon but will | ||
1820 | * not reset the scan status as it won't be IWL_MVM_SCAN_OS | ||
1821 | * any more since we queue the next scan immediately (below). | ||
1822 | * We make sure it is called before the next scan starts by | ||
1823 | * flushing the async-handlers work. | ||
1824 | */ | ||
1825 | break; | ||
1826 | case IWL_MVM_SCAN_NONE: | ||
1827 | break; | ||
1828 | default: | ||
1744 | ret = -EBUSY; | 1829 | ret = -EBUSY; |
1745 | goto out; | 1830 | goto out; |
1746 | } | 1831 | } |
@@ -1762,6 +1847,8 @@ err: | |||
1762 | mvm->scan_status = IWL_MVM_SCAN_NONE; | 1847 | mvm->scan_status = IWL_MVM_SCAN_NONE; |
1763 | out: | 1848 | out: |
1764 | mutex_unlock(&mvm->mutex); | 1849 | mutex_unlock(&mvm->mutex); |
1850 | /* make sure to flush the Rx handler before the next scan arrives */ | ||
1851 | iwl_mvm_wait_for_async_handlers(mvm); | ||
1765 | return ret; | 1852 | return ret; |
1766 | } | 1853 | } |
1767 | 1854 | ||
@@ -1769,12 +1856,14 @@ static int iwl_mvm_mac_sched_scan_stop(struct ieee80211_hw *hw, | |||
1769 | struct ieee80211_vif *vif) | 1856 | struct ieee80211_vif *vif) |
1770 | { | 1857 | { |
1771 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 1858 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
1859 | int ret; | ||
1772 | 1860 | ||
1773 | mutex_lock(&mvm->mutex); | 1861 | mutex_lock(&mvm->mutex); |
1774 | iwl_mvm_sched_scan_stop(mvm); | 1862 | ret = iwl_mvm_sched_scan_stop(mvm); |
1775 | mutex_unlock(&mvm->mutex); | 1863 | mutex_unlock(&mvm->mutex); |
1864 | iwl_mvm_wait_for_async_handlers(mvm); | ||
1776 | 1865 | ||
1777 | return 0; | 1866 | return ret; |
1778 | } | 1867 | } |
1779 | 1868 | ||
1780 | static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw, | 1869 | static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 302cf779c172..d564233a65da 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h | |||
@@ -230,6 +230,8 @@ enum iwl_mvm_ref_type { | |||
230 | IWL_MVM_REF_P2P_CLIENT, | 230 | IWL_MVM_REF_P2P_CLIENT, |
231 | IWL_MVM_REF_AP_IBSS, | 231 | IWL_MVM_REF_AP_IBSS, |
232 | IWL_MVM_REF_USER, | 232 | IWL_MVM_REF_USER, |
233 | IWL_MVM_REF_TX, | ||
234 | IWL_MVM_REF_TX_AGG, | ||
233 | 235 | ||
234 | IWL_MVM_REF_COUNT, | 236 | IWL_MVM_REF_COUNT, |
235 | }; | 237 | }; |
@@ -317,13 +319,13 @@ struct iwl_mvm_vif { | |||
317 | 319 | ||
318 | bool seqno_valid; | 320 | bool seqno_valid; |
319 | u16 seqno; | 321 | u16 seqno; |
322 | #endif | ||
320 | 323 | ||
321 | #if IS_ENABLED(CONFIG_IPV6) | 324 | #if IS_ENABLED(CONFIG_IPV6) |
322 | /* IPv6 addresses for WoWLAN */ | 325 | /* IPv6 addresses for WoWLAN */ |
323 | struct in6_addr target_ipv6_addrs[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_MAX]; | 326 | struct in6_addr target_ipv6_addrs[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_MAX]; |
324 | int num_target_ipv6_addrs; | 327 | int num_target_ipv6_addrs; |
325 | #endif | 328 | #endif |
326 | #endif | ||
327 | 329 | ||
328 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 330 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
329 | struct iwl_mvm *mvm; | 331 | struct iwl_mvm *mvm; |
@@ -346,6 +348,8 @@ iwl_mvm_vif_from_mac80211(struct ieee80211_vif *vif) | |||
346 | return (void *)vif->drv_priv; | 348 | return (void *)vif->drv_priv; |
347 | } | 349 | } |
348 | 350 | ||
351 | extern const u8 tid_to_mac80211_ac[]; | ||
352 | |||
349 | enum iwl_scan_status { | 353 | enum iwl_scan_status { |
350 | IWL_MVM_SCAN_NONE, | 354 | IWL_MVM_SCAN_NONE, |
351 | IWL_MVM_SCAN_OS, | 355 | IWL_MVM_SCAN_OS, |
@@ -571,6 +575,9 @@ struct iwl_mvm { | |||
571 | 575 | ||
572 | /* -1 for always, 0 for never, >0 for that many times */ | 576 | /* -1 for always, 0 for never, >0 for that many times */ |
573 | s8 restart_fw; | 577 | s8 restart_fw; |
578 | void *fw_error_dump; | ||
579 | void *fw_error_sram; | ||
580 | u32 fw_error_sram_len; | ||
574 | 581 | ||
575 | struct led_classdev led; | 582 | struct led_classdev led; |
576 | 583 | ||
@@ -591,12 +598,20 @@ struct iwl_mvm { | |||
591 | 598 | ||
592 | /* d0i3 */ | 599 | /* d0i3 */ |
593 | u8 d0i3_ap_sta_id; | 600 | u8 d0i3_ap_sta_id; |
601 | bool d0i3_offloading; | ||
594 | struct work_struct d0i3_exit_work; | 602 | struct work_struct d0i3_exit_work; |
603 | struct sk_buff_head d0i3_tx; | ||
604 | /* sync d0i3_tx queue and IWL_MVM_STATUS_IN_D0I3 status flag */ | ||
605 | spinlock_t d0i3_tx_lock; | ||
606 | wait_queue_head_t d0i3_exit_waitq; | ||
595 | 607 | ||
596 | /* BT-Coex */ | 608 | /* BT-Coex */ |
597 | u8 bt_kill_msk; | 609 | u8 bt_kill_msk; |
598 | struct iwl_bt_coex_profile_notif last_bt_notif; | 610 | struct iwl_bt_coex_profile_notif last_bt_notif; |
599 | struct iwl_bt_coex_ci_cmd last_bt_ci_cmd; | 611 | struct iwl_bt_coex_ci_cmd last_bt_ci_cmd; |
612 | u32 last_ant_isol; | ||
613 | u8 last_corun_lut; | ||
614 | u8 bt_tx_prio; | ||
600 | 615 | ||
601 | /* Thermal Throttling and CTkill */ | 616 | /* Thermal Throttling and CTkill */ |
602 | struct iwl_mvm_tt_mgmt thermal_throttle; | 617 | struct iwl_mvm_tt_mgmt thermal_throttle; |
@@ -630,6 +645,7 @@ enum iwl_mvm_status { | |||
630 | IWL_MVM_STATUS_HW_CTKILL, | 645 | IWL_MVM_STATUS_HW_CTKILL, |
631 | IWL_MVM_STATUS_ROC_RUNNING, | 646 | IWL_MVM_STATUS_ROC_RUNNING, |
632 | IWL_MVM_STATUS_IN_HW_RESTART, | 647 | IWL_MVM_STATUS_IN_HW_RESTART, |
648 | IWL_MVM_STATUS_IN_D0I3, | ||
633 | }; | 649 | }; |
634 | 650 | ||
635 | static inline bool iwl_mvm_is_radio_killed(struct iwl_mvm *mvm) | 651 | static inline bool iwl_mvm_is_radio_killed(struct iwl_mvm *mvm) |
@@ -656,6 +672,12 @@ iwl_mvm_sta_from_staid_protected(struct iwl_mvm *mvm, u8 sta_id) | |||
656 | return iwl_mvm_sta_from_mac80211(sta); | 672 | return iwl_mvm_sta_from_mac80211(sta); |
657 | } | 673 | } |
658 | 674 | ||
675 | static inline bool iwl_mvm_is_d0i3_supported(struct iwl_mvm *mvm) | ||
676 | { | ||
677 | return mvm->trans->cfg->d0i3 && | ||
678 | (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_D0I3_SUPPORT); | ||
679 | } | ||
680 | |||
659 | extern const u8 iwl_mvm_ac_to_tx_fifo[]; | 681 | extern const u8 iwl_mvm_ac_to_tx_fifo[]; |
660 | 682 | ||
661 | struct iwl_rate_info { | 683 | struct iwl_rate_info { |
@@ -680,7 +702,10 @@ void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags, | |||
680 | struct ieee80211_tx_rate *r); | 702 | struct ieee80211_tx_rate *r); |
681 | u8 iwl_mvm_mac80211_idx_to_hwrate(int rate_idx); | 703 | u8 iwl_mvm_mac80211_idx_to_hwrate(int rate_idx); |
682 | void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm); | 704 | void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm); |
683 | void iwl_mvm_dump_sram(struct iwl_mvm *mvm); | 705 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
706 | void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm); | ||
707 | void iwl_mvm_fw_error_sram_dump(struct iwl_mvm *mvm); | ||
708 | #endif | ||
684 | u8 first_antenna(u8 mask); | 709 | u8 first_antenna(u8 mask); |
685 | u8 iwl_mvm_next_antenna(struct iwl_mvm *mvm, u8 valid, u8 last_idx); | 710 | u8 iwl_mvm_next_antenna(struct iwl_mvm *mvm, u8 valid, u8 last_idx); |
686 | 711 | ||
@@ -706,6 +731,11 @@ static inline const char *iwl_mvm_get_tx_fail_reason(u32 status) { return ""; } | |||
706 | int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, bool sync); | 731 | int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, bool sync); |
707 | void iwl_mvm_async_handlers_purge(struct iwl_mvm *mvm); | 732 | void iwl_mvm_async_handlers_purge(struct iwl_mvm *mvm); |
708 | 733 | ||
734 | static inline void iwl_mvm_wait_for_async_handlers(struct iwl_mvm *mvm) | ||
735 | { | ||
736 | flush_work(&mvm->async_handlers_wk); | ||
737 | } | ||
738 | |||
709 | /* Statistics */ | 739 | /* Statistics */ |
710 | int iwl_mvm_rx_reply_statistics(struct iwl_mvm *mvm, | 740 | int iwl_mvm_rx_reply_statistics(struct iwl_mvm *mvm, |
711 | struct iwl_rx_cmd_buffer *rxb, | 741 | struct iwl_rx_cmd_buffer *rxb, |
@@ -739,6 +769,9 @@ int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | |||
739 | struct iwl_device_cmd *cmd); | 769 | struct iwl_device_cmd *cmd); |
740 | int iwl_mvm_rx_radio_ver(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | 770 | int iwl_mvm_rx_radio_ver(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, |
741 | struct iwl_device_cmd *cmd); | 771 | struct iwl_device_cmd *cmd); |
772 | int iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm, | ||
773 | struct iwl_rx_cmd_buffer *rxb, | ||
774 | struct iwl_device_cmd *cmd); | ||
742 | int iwl_mvm_rx_fw_error(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | 775 | int iwl_mvm_rx_fw_error(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, |
743 | struct iwl_device_cmd *cmd); | 776 | struct iwl_device_cmd *cmd); |
744 | int iwl_mvm_rx_card_state_notif(struct iwl_mvm *mvm, | 777 | int iwl_mvm_rx_card_state_notif(struct iwl_mvm *mvm, |
@@ -793,7 +826,7 @@ int iwl_mvm_rx_scan_response(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | |||
793 | struct iwl_device_cmd *cmd); | 826 | struct iwl_device_cmd *cmd); |
794 | int iwl_mvm_rx_scan_complete(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | 827 | int iwl_mvm_rx_scan_complete(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, |
795 | struct iwl_device_cmd *cmd); | 828 | struct iwl_device_cmd *cmd); |
796 | void iwl_mvm_cancel_scan(struct iwl_mvm *mvm); | 829 | int iwl_mvm_cancel_scan(struct iwl_mvm *mvm); |
797 | 830 | ||
798 | /* Scheduled scan */ | 831 | /* Scheduled scan */ |
799 | int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm, | 832 | int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm, |
@@ -807,7 +840,7 @@ int iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm, | |||
807 | struct cfg80211_sched_scan_request *req); | 840 | struct cfg80211_sched_scan_request *req); |
808 | int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, | 841 | int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, |
809 | struct cfg80211_sched_scan_request *req); | 842 | struct cfg80211_sched_scan_request *req); |
810 | void iwl_mvm_sched_scan_stop(struct iwl_mvm *mvm); | 843 | int iwl_mvm_sched_scan_stop(struct iwl_mvm *mvm); |
811 | int iwl_mvm_rx_sched_scan_results(struct iwl_mvm *mvm, | 844 | int iwl_mvm_rx_sched_scan_results(struct iwl_mvm *mvm, |
812 | struct iwl_rx_cmd_buffer *rxb, | 845 | struct iwl_rx_cmd_buffer *rxb, |
813 | struct iwl_device_cmd *cmd); | 846 | struct iwl_device_cmd *cmd); |
@@ -878,10 +911,17 @@ iwl_mvm_set_last_nonqos_seq(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
878 | { | 911 | { |
879 | } | 912 | } |
880 | #endif | 913 | #endif |
914 | void iwl_mvm_set_wowlan_qos_seq(struct iwl_mvm_sta *mvm_ap_sta, | ||
915 | struct iwl_wowlan_config_cmd_v2 *cmd); | ||
916 | int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm, | ||
917 | struct ieee80211_vif *vif, | ||
918 | bool disable_offloading, | ||
919 | u32 cmd_flags); | ||
881 | 920 | ||
882 | /* D0i3 */ | 921 | /* D0i3 */ |
883 | void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type); | 922 | void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type); |
884 | void iwl_mvm_unref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type); | 923 | void iwl_mvm_unref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type); |
924 | void iwl_mvm_d0i3_enable_tx(struct iwl_mvm *mvm, __le16 *qos_seq); | ||
885 | 925 | ||
886 | /* BT Coex */ | 926 | /* BT Coex */ |
887 | int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm); | 927 | int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm); |
@@ -892,10 +932,12 @@ int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm, | |||
892 | void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 932 | void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
893 | enum ieee80211_rssi_event rssi_event); | 933 | enum ieee80211_rssi_event rssi_event); |
894 | void iwl_mvm_bt_coex_vif_change(struct iwl_mvm *mvm); | 934 | void iwl_mvm_bt_coex_vif_change(struct iwl_mvm *mvm); |
895 | u16 iwl_mvm_bt_coex_agg_time_limit(struct iwl_mvm *mvm, | 935 | u16 iwl_mvm_coex_agg_time_limit(struct iwl_mvm *mvm, |
896 | struct ieee80211_sta *sta); | 936 | struct ieee80211_sta *sta); |
897 | bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm, | 937 | bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm, |
898 | struct ieee80211_sta *sta); | 938 | struct ieee80211_sta *sta); |
939 | u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr, | ||
940 | struct ieee80211_tx_info *info, u8 ac); | ||
899 | int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, bool enable); | 941 | int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, bool enable); |
900 | 942 | ||
901 | enum iwl_bt_kill_msk { | 943 | enum iwl_bt_kill_msk { |
@@ -942,6 +984,8 @@ void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
942 | /* Low latency */ | 984 | /* Low latency */ |
943 | int iwl_mvm_update_low_latency(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 985 | int iwl_mvm_update_low_latency(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
944 | bool value); | 986 | bool value); |
987 | /* get SystemLowLatencyMode - only needed for beacon threshold? */ | ||
988 | bool iwl_mvm_low_latency(struct iwl_mvm *mvm); | ||
945 | /* get VMACLowLatencyMode */ | 989 | /* get VMACLowLatencyMode */ |
946 | static inline bool iwl_mvm_vif_low_latency(struct iwl_mvm_vif *mvmvif) | 990 | static inline bool iwl_mvm_vif_low_latency(struct iwl_mvm_vif *mvmvif) |
947 | { | 991 | { |
diff --git a/drivers/net/wireless/iwlwifi/mvm/offloading.c b/drivers/net/wireless/iwlwifi/mvm/offloading.c new file mode 100644 index 000000000000..9bfb95e89cfb --- /dev/null +++ b/drivers/net/wireless/iwlwifi/mvm/offloading.c | |||
@@ -0,0 +1,215 @@ | |||
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) 2012 - 2014 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 COPYING. | ||
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) 2012 - 2014 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 <net/ipv6.h> | ||
64 | #include <net/addrconf.h> | ||
65 | #include "mvm.h" | ||
66 | |||
67 | void iwl_mvm_set_wowlan_qos_seq(struct iwl_mvm_sta *mvm_ap_sta, | ||
68 | struct iwl_wowlan_config_cmd_v2 *cmd) | ||
69 | { | ||
70 | int i; | ||
71 | |||
72 | /* | ||
73 | * For QoS counters, we store the one to use next, so subtract 0x10 | ||
74 | * since the uCode will add 0x10 *before* using the value while we | ||
75 | * increment after using the value (i.e. store the next value to use). | ||
76 | */ | ||
77 | for (i = 0; i < IWL_MAX_TID_COUNT; i++) { | ||
78 | u16 seq = mvm_ap_sta->tid_data[i].seq_number; | ||
79 | seq -= 0x10; | ||
80 | cmd->qos_seq[i] = cpu_to_le16(seq); | ||
81 | } | ||
82 | } | ||
83 | |||
84 | int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm, | ||
85 | struct ieee80211_vif *vif, | ||
86 | bool disable_offloading, | ||
87 | u32 cmd_flags) | ||
88 | { | ||
89 | union { | ||
90 | struct iwl_proto_offload_cmd_v1 v1; | ||
91 | struct iwl_proto_offload_cmd_v2 v2; | ||
92 | struct iwl_proto_offload_cmd_v3_small v3s; | ||
93 | struct iwl_proto_offload_cmd_v3_large v3l; | ||
94 | } cmd = {}; | ||
95 | struct iwl_host_cmd hcmd = { | ||
96 | .id = PROT_OFFLOAD_CONFIG_CMD, | ||
97 | .flags = cmd_flags, | ||
98 | .data[0] = &cmd, | ||
99 | .dataflags[0] = IWL_HCMD_DFL_DUP, | ||
100 | }; | ||
101 | struct iwl_proto_offload_cmd_common *common; | ||
102 | u32 enabled = 0, size; | ||
103 | u32 capa_flags = mvm->fw->ucode_capa.flags; | ||
104 | #if IS_ENABLED(CONFIG_IPV6) | ||
105 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
106 | int i; | ||
107 | |||
108 | if (capa_flags & IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL || | ||
109 | capa_flags & IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE) { | ||
110 | struct iwl_ns_config *nsc; | ||
111 | struct iwl_targ_addr *addrs; | ||
112 | int n_nsc, n_addrs; | ||
113 | int c; | ||
114 | |||
115 | if (capa_flags & IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL) { | ||
116 | nsc = cmd.v3s.ns_config; | ||
117 | n_nsc = IWL_PROTO_OFFLOAD_NUM_NS_CONFIG_V3S; | ||
118 | addrs = cmd.v3s.targ_addrs; | ||
119 | n_addrs = IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V3S; | ||
120 | } else { | ||
121 | nsc = cmd.v3l.ns_config; | ||
122 | n_nsc = IWL_PROTO_OFFLOAD_NUM_NS_CONFIG_V3L; | ||
123 | addrs = cmd.v3l.targ_addrs; | ||
124 | n_addrs = IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V3L; | ||
125 | } | ||
126 | |||
127 | if (mvmvif->num_target_ipv6_addrs) | ||
128 | enabled |= IWL_D3_PROTO_OFFLOAD_NS; | ||
129 | |||
130 | /* | ||
131 | * For each address we have (and that will fit) fill a target | ||
132 | * address struct and combine for NS offload structs with the | ||
133 | * solicited node addresses. | ||
134 | */ | ||
135 | for (i = 0, c = 0; | ||
136 | i < mvmvif->num_target_ipv6_addrs && | ||
137 | i < n_addrs && c < n_nsc; i++) { | ||
138 | struct in6_addr solicited_addr; | ||
139 | int j; | ||
140 | |||
141 | addrconf_addr_solict_mult(&mvmvif->target_ipv6_addrs[i], | ||
142 | &solicited_addr); | ||
143 | for (j = 0; j < c; j++) | ||
144 | if (ipv6_addr_cmp(&nsc[j].dest_ipv6_addr, | ||
145 | &solicited_addr) == 0) | ||
146 | break; | ||
147 | if (j == c) | ||
148 | c++; | ||
149 | addrs[i].addr = mvmvif->target_ipv6_addrs[i]; | ||
150 | addrs[i].config_num = cpu_to_le32(j); | ||
151 | nsc[j].dest_ipv6_addr = solicited_addr; | ||
152 | memcpy(nsc[j].target_mac_addr, vif->addr, ETH_ALEN); | ||
153 | } | ||
154 | |||
155 | if (capa_flags & IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL) | ||
156 | cmd.v3s.num_valid_ipv6_addrs = cpu_to_le32(i); | ||
157 | else | ||
158 | cmd.v3l.num_valid_ipv6_addrs = cpu_to_le32(i); | ||
159 | } else if (capa_flags & IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS) { | ||
160 | if (mvmvif->num_target_ipv6_addrs) { | ||
161 | enabled |= IWL_D3_PROTO_OFFLOAD_NS; | ||
162 | memcpy(cmd.v2.ndp_mac_addr, vif->addr, ETH_ALEN); | ||
163 | } | ||
164 | |||
165 | BUILD_BUG_ON(sizeof(cmd.v2.target_ipv6_addr[0]) != | ||
166 | sizeof(mvmvif->target_ipv6_addrs[0])); | ||
167 | |||
168 | for (i = 0; i < min(mvmvif->num_target_ipv6_addrs, | ||
169 | IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V2); i++) | ||
170 | memcpy(cmd.v2.target_ipv6_addr[i], | ||
171 | &mvmvif->target_ipv6_addrs[i], | ||
172 | sizeof(cmd.v2.target_ipv6_addr[i])); | ||
173 | } else { | ||
174 | if (mvmvif->num_target_ipv6_addrs) { | ||
175 | enabled |= IWL_D3_PROTO_OFFLOAD_NS; | ||
176 | memcpy(cmd.v1.ndp_mac_addr, vif->addr, ETH_ALEN); | ||
177 | } | ||
178 | |||
179 | BUILD_BUG_ON(sizeof(cmd.v1.target_ipv6_addr[0]) != | ||
180 | sizeof(mvmvif->target_ipv6_addrs[0])); | ||
181 | |||
182 | for (i = 0; i < min(mvmvif->num_target_ipv6_addrs, | ||
183 | IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V1); i++) | ||
184 | memcpy(cmd.v1.target_ipv6_addr[i], | ||
185 | &mvmvif->target_ipv6_addrs[i], | ||
186 | sizeof(cmd.v1.target_ipv6_addr[i])); | ||
187 | } | ||
188 | #endif | ||
189 | |||
190 | if (capa_flags & IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL) { | ||
191 | common = &cmd.v3s.common; | ||
192 | size = sizeof(cmd.v3s); | ||
193 | } else if (capa_flags & IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE) { | ||
194 | common = &cmd.v3l.common; | ||
195 | size = sizeof(cmd.v3l); | ||
196 | } else if (capa_flags & IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS) { | ||
197 | common = &cmd.v2.common; | ||
198 | size = sizeof(cmd.v2); | ||
199 | } else { | ||
200 | common = &cmd.v1.common; | ||
201 | size = sizeof(cmd.v1); | ||
202 | } | ||
203 | |||
204 | if (vif->bss_conf.arp_addr_cnt) { | ||
205 | enabled |= IWL_D3_PROTO_OFFLOAD_ARP; | ||
206 | common->host_ipv4_addr = vif->bss_conf.arp_addr_list[0]; | ||
207 | memcpy(common->arp_mac_addr, vif->addr, ETH_ALEN); | ||
208 | } | ||
209 | |||
210 | if (!disable_offloading) | ||
211 | common->enabled = cpu_to_le32(enabled); | ||
212 | |||
213 | hcmd.len[0] = size; | ||
214 | return iwl_mvm_send_cmd(mvm, &hcmd); | ||
215 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index ae347fb16a5d..9545d7fdd4bf 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c | |||
@@ -61,6 +61,7 @@ | |||
61 | * | 61 | * |
62 | *****************************************************************************/ | 62 | *****************************************************************************/ |
63 | #include <linux/module.h> | 63 | #include <linux/module.h> |
64 | #include <linux/vmalloc.h> | ||
64 | #include <net/mac80211.h> | 65 | #include <net/mac80211.h> |
65 | 66 | ||
66 | #include "iwl-notif-wait.h" | 67 | #include "iwl-notif-wait.h" |
@@ -78,6 +79,7 @@ | |||
78 | #include "iwl-prph.h" | 79 | #include "iwl-prph.h" |
79 | #include "rs.h" | 80 | #include "rs.h" |
80 | #include "fw-api-scan.h" | 81 | #include "fw-api-scan.h" |
82 | #include "fw-error-dump.h" | ||
81 | #include "time-event.h" | 83 | #include "time-event.h" |
82 | 84 | ||
83 | /* | 85 | /* |
@@ -220,13 +222,15 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { | |||
220 | RX_HANDLER(BT_PROFILE_NOTIFICATION, iwl_mvm_rx_bt_coex_notif, true), | 222 | RX_HANDLER(BT_PROFILE_NOTIFICATION, iwl_mvm_rx_bt_coex_notif, true), |
221 | RX_HANDLER(BEACON_NOTIFICATION, iwl_mvm_rx_beacon_notif, false), | 223 | RX_HANDLER(BEACON_NOTIFICATION, iwl_mvm_rx_beacon_notif, false), |
222 | RX_HANDLER(STATISTICS_NOTIFICATION, iwl_mvm_rx_statistics, true), | 224 | RX_HANDLER(STATISTICS_NOTIFICATION, iwl_mvm_rx_statistics, true), |
225 | RX_HANDLER(ANTENNA_COUPLING_NOTIFICATION, | ||
226 | iwl_mvm_rx_ant_coupling_notif, true), | ||
223 | 227 | ||
224 | RX_HANDLER(TIME_EVENT_NOTIFICATION, iwl_mvm_rx_time_event_notif, false), | 228 | RX_HANDLER(TIME_EVENT_NOTIFICATION, iwl_mvm_rx_time_event_notif, false), |
225 | 229 | ||
226 | RX_HANDLER(EOSP_NOTIFICATION, iwl_mvm_rx_eosp_notif, false), | 230 | RX_HANDLER(EOSP_NOTIFICATION, iwl_mvm_rx_eosp_notif, false), |
227 | 231 | ||
228 | RX_HANDLER(SCAN_REQUEST_CMD, iwl_mvm_rx_scan_response, false), | 232 | RX_HANDLER(SCAN_REQUEST_CMD, iwl_mvm_rx_scan_response, false), |
229 | RX_HANDLER(SCAN_COMPLETE_NOTIFICATION, iwl_mvm_rx_scan_complete, false), | 233 | RX_HANDLER(SCAN_COMPLETE_NOTIFICATION, iwl_mvm_rx_scan_complete, true), |
230 | RX_HANDLER(SCAN_OFFLOAD_COMPLETE, | 234 | RX_HANDLER(SCAN_OFFLOAD_COMPLETE, |
231 | iwl_mvm_rx_scan_offload_complete_notif, true), | 235 | iwl_mvm_rx_scan_offload_complete_notif, true), |
232 | RX_HANDLER(MATCH_FOUND_NOTIFICATION, iwl_mvm_rx_sched_scan_results, | 236 | RX_HANDLER(MATCH_FOUND_NOTIFICATION, iwl_mvm_rx_sched_scan_results, |
@@ -321,6 +325,7 @@ static const char *const iwl_mvm_cmd_strings[REPLY_MAX] = { | |||
321 | CMD(MAC_PM_POWER_TABLE), | 325 | CMD(MAC_PM_POWER_TABLE), |
322 | CMD(BT_COEX_CI), | 326 | CMD(BT_COEX_CI), |
323 | CMD(PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION), | 327 | CMD(PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION), |
328 | CMD(ANTENNA_COUPLING_NOTIFICATION), | ||
324 | }; | 329 | }; |
325 | #undef CMD | 330 | #undef CMD |
326 | 331 | ||
@@ -407,6 +412,10 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
407 | INIT_WORK(&mvm->sta_drained_wk, iwl_mvm_sta_drained_wk); | 412 | INIT_WORK(&mvm->sta_drained_wk, iwl_mvm_sta_drained_wk); |
408 | INIT_WORK(&mvm->d0i3_exit_work, iwl_mvm_d0i3_exit_work); | 413 | INIT_WORK(&mvm->d0i3_exit_work, iwl_mvm_d0i3_exit_work); |
409 | 414 | ||
415 | spin_lock_init(&mvm->d0i3_tx_lock); | ||
416 | skb_queue_head_init(&mvm->d0i3_tx); | ||
417 | init_waitqueue_head(&mvm->d0i3_exit_waitq); | ||
418 | |||
410 | SET_IEEE80211_DEV(mvm->hw, mvm->trans->dev); | 419 | SET_IEEE80211_DEV(mvm->hw, mvm->trans->dev); |
411 | 420 | ||
412 | /* | 421 | /* |
@@ -527,6 +536,8 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode) | |||
527 | ieee80211_unregister_hw(mvm->hw); | 536 | ieee80211_unregister_hw(mvm->hw); |
528 | 537 | ||
529 | kfree(mvm->scan_cmd); | 538 | kfree(mvm->scan_cmd); |
539 | vfree(mvm->fw_error_dump); | ||
540 | kfree(mvm->fw_error_sram); | ||
530 | kfree(mvm->mcast_filter_cmd); | 541 | kfree(mvm->mcast_filter_cmd); |
531 | mvm->mcast_filter_cmd = NULL; | 542 | mvm->mcast_filter_cmd = NULL; |
532 | 543 | ||
@@ -690,7 +701,7 @@ void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state) | |||
690 | wiphy_rfkill_set_hw_state(mvm->hw->wiphy, iwl_mvm_is_radio_killed(mvm)); | 701 | wiphy_rfkill_set_hw_state(mvm->hw->wiphy, iwl_mvm_is_radio_killed(mvm)); |
691 | } | 702 | } |
692 | 703 | ||
693 | static void iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) | 704 | static bool iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) |
694 | { | 705 | { |
695 | struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); | 706 | struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); |
696 | 707 | ||
@@ -699,9 +710,9 @@ static void iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) | |||
699 | else | 710 | else |
700 | clear_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status); | 711 | clear_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status); |
701 | 712 | ||
702 | if (state && mvm->cur_ucode != IWL_UCODE_INIT) | ||
703 | iwl_trans_stop_device(mvm->trans); | ||
704 | wiphy_rfkill_set_hw_state(mvm->hw->wiphy, iwl_mvm_is_radio_killed(mvm)); | 713 | wiphy_rfkill_set_hw_state(mvm->hw->wiphy, iwl_mvm_is_radio_killed(mvm)); |
714 | |||
715 | return state && mvm->cur_ucode != IWL_UCODE_INIT; | ||
705 | } | 716 | } |
706 | 717 | ||
707 | static void iwl_mvm_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb) | 718 | static void iwl_mvm_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb) |
@@ -797,13 +808,52 @@ static void iwl_mvm_nic_restart(struct iwl_mvm *mvm) | |||
797 | } | 808 | } |
798 | } | 809 | } |
799 | 810 | ||
811 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
812 | void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) | ||
813 | { | ||
814 | struct iwl_fw_error_dump_file *dump_file; | ||
815 | struct iwl_fw_error_dump_data *dump_data; | ||
816 | u32 file_len; | ||
817 | |||
818 | lockdep_assert_held(&mvm->mutex); | ||
819 | |||
820 | if (mvm->fw_error_dump) | ||
821 | return; | ||
822 | |||
823 | file_len = mvm->fw_error_sram_len + | ||
824 | sizeof(*dump_file) + | ||
825 | sizeof(*dump_data); | ||
826 | |||
827 | dump_file = vmalloc(file_len); | ||
828 | if (!dump_file) | ||
829 | return; | ||
830 | |||
831 | mvm->fw_error_dump = dump_file; | ||
832 | |||
833 | dump_file->barker = cpu_to_le32(IWL_FW_ERROR_DUMP_BARKER); | ||
834 | dump_file->file_len = cpu_to_le32(file_len); | ||
835 | dump_data = (void *)dump_file->data; | ||
836 | dump_data->type = IWL_FW_ERROR_DUMP_SRAM; | ||
837 | dump_data->len = cpu_to_le32(mvm->fw_error_sram_len); | ||
838 | |||
839 | /* | ||
840 | * No need for lock since at the stage the FW isn't loaded. So it | ||
841 | * can't assert - we are the only one who can possibly be accessing | ||
842 | * mvm->fw_error_sram right now. | ||
843 | */ | ||
844 | memcpy(dump_data->data, mvm->fw_error_sram, mvm->fw_error_sram_len); | ||
845 | } | ||
846 | #endif | ||
847 | |||
800 | static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode) | 848 | static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode) |
801 | { | 849 | { |
802 | struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); | 850 | struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); |
803 | 851 | ||
804 | iwl_mvm_dump_nic_error_log(mvm); | 852 | iwl_mvm_dump_nic_error_log(mvm); |
805 | if (!mvm->restart_fw) | 853 | |
806 | iwl_mvm_dump_sram(mvm); | 854 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
855 | iwl_mvm_fw_error_sram_dump(mvm); | ||
856 | #endif | ||
807 | 857 | ||
808 | iwl_mvm_nic_restart(mvm); | 858 | iwl_mvm_nic_restart(mvm); |
809 | } | 859 | } |
@@ -820,8 +870,62 @@ struct iwl_d0i3_iter_data { | |||
820 | struct iwl_mvm *mvm; | 870 | struct iwl_mvm *mvm; |
821 | u8 ap_sta_id; | 871 | u8 ap_sta_id; |
822 | u8 vif_count; | 872 | u8 vif_count; |
873 | u8 offloading_tid; | ||
874 | bool disable_offloading; | ||
823 | }; | 875 | }; |
824 | 876 | ||
877 | static bool iwl_mvm_disallow_offloading(struct iwl_mvm *mvm, | ||
878 | struct ieee80211_vif *vif, | ||
879 | struct iwl_d0i3_iter_data *iter_data) | ||
880 | { | ||
881 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
882 | struct ieee80211_sta *ap_sta; | ||
883 | struct iwl_mvm_sta *mvmsta; | ||
884 | u32 available_tids = 0; | ||
885 | u8 tid; | ||
886 | |||
887 | if (WARN_ON(vif->type != NL80211_IFTYPE_STATION || | ||
888 | mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT)) | ||
889 | return false; | ||
890 | |||
891 | ap_sta = rcu_dereference(mvm->fw_id_to_mac_id[mvmvif->ap_sta_id]); | ||
892 | if (IS_ERR_OR_NULL(ap_sta)) | ||
893 | return false; | ||
894 | |||
895 | mvmsta = iwl_mvm_sta_from_mac80211(ap_sta); | ||
896 | spin_lock_bh(&mvmsta->lock); | ||
897 | for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) { | ||
898 | struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid]; | ||
899 | |||
900 | /* | ||
901 | * in case of pending tx packets, don't use this tid | ||
902 | * for offloading in order to prevent reuse of the same | ||
903 | * qos seq counters. | ||
904 | */ | ||
905 | if (iwl_mvm_tid_queued(tid_data)) | ||
906 | continue; | ||
907 | |||
908 | if (tid_data->state != IWL_AGG_OFF) | ||
909 | continue; | ||
910 | |||
911 | available_tids |= BIT(tid); | ||
912 | } | ||
913 | spin_unlock_bh(&mvmsta->lock); | ||
914 | |||
915 | /* | ||
916 | * disallow protocol offloading if we have no available tid | ||
917 | * (with no pending frames and no active aggregation, | ||
918 | * as we don't handle "holes" properly - the scheduler needs the | ||
919 | * frame's seq number and TFD index to match) | ||
920 | */ | ||
921 | if (!available_tids) | ||
922 | return true; | ||
923 | |||
924 | /* for simplicity, just use the first available tid */ | ||
925 | iter_data->offloading_tid = ffs(available_tids) - 1; | ||
926 | return false; | ||
927 | } | ||
928 | |||
825 | static void iwl_mvm_enter_d0i3_iterator(void *_data, u8 *mac, | 929 | static void iwl_mvm_enter_d0i3_iterator(void *_data, u8 *mac, |
826 | struct ieee80211_vif *vif) | 930 | struct ieee80211_vif *vif) |
827 | { | 931 | { |
@@ -835,7 +939,16 @@ static void iwl_mvm_enter_d0i3_iterator(void *_data, u8 *mac, | |||
835 | !vif->bss_conf.assoc) | 939 | !vif->bss_conf.assoc) |
836 | return; | 940 | return; |
837 | 941 | ||
942 | /* | ||
943 | * in case of pending tx packets or active aggregations, | ||
944 | * avoid offloading features in order to prevent reuse of | ||
945 | * the same qos seq counters. | ||
946 | */ | ||
947 | if (iwl_mvm_disallow_offloading(mvm, vif, data)) | ||
948 | data->disable_offloading = true; | ||
949 | |||
838 | iwl_mvm_update_d0i3_power_mode(mvm, vif, true, flags); | 950 | iwl_mvm_update_d0i3_power_mode(mvm, vif, true, flags); |
951 | iwl_mvm_send_proto_offload(mvm, vif, data->disable_offloading, flags); | ||
839 | 952 | ||
840 | /* | 953 | /* |
841 | * on init/association, mvm already configures POWER_TABLE_CMD | 954 | * on init/association, mvm already configures POWER_TABLE_CMD |
@@ -847,6 +960,34 @@ static void iwl_mvm_enter_d0i3_iterator(void *_data, u8 *mac, | |||
847 | data->vif_count++; | 960 | data->vif_count++; |
848 | } | 961 | } |
849 | 962 | ||
963 | static void iwl_mvm_set_wowlan_data(struct iwl_mvm *mvm, | ||
964 | struct iwl_wowlan_config_cmd_v3 *cmd, | ||
965 | struct iwl_d0i3_iter_data *iter_data) | ||
966 | { | ||
967 | struct ieee80211_sta *ap_sta; | ||
968 | struct iwl_mvm_sta *mvm_ap_sta; | ||
969 | |||
970 | if (iter_data->ap_sta_id == IWL_MVM_STATION_COUNT) | ||
971 | return; | ||
972 | |||
973 | rcu_read_lock(); | ||
974 | |||
975 | ap_sta = rcu_dereference(mvm->fw_id_to_mac_id[iter_data->ap_sta_id]); | ||
976 | if (IS_ERR_OR_NULL(ap_sta)) | ||
977 | goto out; | ||
978 | |||
979 | mvm_ap_sta = iwl_mvm_sta_from_mac80211(ap_sta); | ||
980 | cmd->common.is_11n_connection = ap_sta->ht_cap.ht_supported; | ||
981 | cmd->offloading_tid = iter_data->offloading_tid; | ||
982 | |||
983 | /* | ||
984 | * The d0i3 uCode takes care of the nonqos counters, | ||
985 | * so configure only the qos seq ones. | ||
986 | */ | ||
987 | iwl_mvm_set_wowlan_qos_seq(mvm_ap_sta, &cmd->common); | ||
988 | out: | ||
989 | rcu_read_unlock(); | ||
990 | } | ||
850 | static int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode) | 991 | static int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode) |
851 | { | 992 | { |
852 | struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); | 993 | struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); |
@@ -855,11 +996,14 @@ static int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode) | |||
855 | struct iwl_d0i3_iter_data d0i3_iter_data = { | 996 | struct iwl_d0i3_iter_data d0i3_iter_data = { |
856 | .mvm = mvm, | 997 | .mvm = mvm, |
857 | }; | 998 | }; |
858 | struct iwl_wowlan_config_cmd wowlan_config_cmd = { | 999 | struct iwl_wowlan_config_cmd_v3 wowlan_config_cmd = { |
859 | .wakeup_filter = cpu_to_le32(IWL_WOWLAN_WAKEUP_RX_FRAME | | 1000 | .common = { |
860 | IWL_WOWLAN_WAKEUP_BEACON_MISS | | 1001 | .wakeup_filter = |
861 | IWL_WOWLAN_WAKEUP_LINK_CHANGE | | 1002 | cpu_to_le32(IWL_WOWLAN_WAKEUP_RX_FRAME | |
862 | IWL_WOWLAN_WAKEUP_BCN_FILTERING), | 1003 | IWL_WOWLAN_WAKEUP_BEACON_MISS | |
1004 | IWL_WOWLAN_WAKEUP_LINK_CHANGE | | ||
1005 | IWL_WOWLAN_WAKEUP_BCN_FILTERING), | ||
1006 | }, | ||
863 | }; | 1007 | }; |
864 | struct iwl_d3_manager_config d3_cfg_cmd = { | 1008 | struct iwl_d3_manager_config d3_cfg_cmd = { |
865 | .min_sleep_time = cpu_to_le32(1000), | 1009 | .min_sleep_time = cpu_to_le32(1000), |
@@ -867,17 +1011,24 @@ static int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode) | |||
867 | 1011 | ||
868 | IWL_DEBUG_RPM(mvm, "MVM entering D0i3\n"); | 1012 | IWL_DEBUG_RPM(mvm, "MVM entering D0i3\n"); |
869 | 1013 | ||
1014 | /* make sure we have no running tx while configuring the qos */ | ||
1015 | set_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status); | ||
1016 | synchronize_net(); | ||
1017 | |||
870 | ieee80211_iterate_active_interfaces_atomic(mvm->hw, | 1018 | ieee80211_iterate_active_interfaces_atomic(mvm->hw, |
871 | IEEE80211_IFACE_ITER_NORMAL, | 1019 | IEEE80211_IFACE_ITER_NORMAL, |
872 | iwl_mvm_enter_d0i3_iterator, | 1020 | iwl_mvm_enter_d0i3_iterator, |
873 | &d0i3_iter_data); | 1021 | &d0i3_iter_data); |
874 | if (d0i3_iter_data.vif_count == 1) { | 1022 | if (d0i3_iter_data.vif_count == 1) { |
875 | mvm->d0i3_ap_sta_id = d0i3_iter_data.ap_sta_id; | 1023 | mvm->d0i3_ap_sta_id = d0i3_iter_data.ap_sta_id; |
1024 | mvm->d0i3_offloading = !d0i3_iter_data.disable_offloading; | ||
876 | } else { | 1025 | } else { |
877 | WARN_ON_ONCE(d0i3_iter_data.vif_count > 1); | 1026 | WARN_ON_ONCE(d0i3_iter_data.vif_count > 1); |
878 | mvm->d0i3_ap_sta_id = IWL_MVM_STATION_COUNT; | 1027 | mvm->d0i3_ap_sta_id = IWL_MVM_STATION_COUNT; |
1028 | mvm->d0i3_offloading = false; | ||
879 | } | 1029 | } |
880 | 1030 | ||
1031 | iwl_mvm_set_wowlan_data(mvm, &wowlan_config_cmd, &d0i3_iter_data); | ||
881 | ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, flags, | 1032 | ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, flags, |
882 | sizeof(wowlan_config_cmd), | 1033 | sizeof(wowlan_config_cmd), |
883 | &wowlan_config_cmd); | 1034 | &wowlan_config_cmd); |
@@ -914,6 +1065,62 @@ static void iwl_mvm_d0i3_disconnect_iter(void *data, u8 *mac, | |||
914 | ieee80211_connection_loss(vif); | 1065 | ieee80211_connection_loss(vif); |
915 | } | 1066 | } |
916 | 1067 | ||
1068 | void iwl_mvm_d0i3_enable_tx(struct iwl_mvm *mvm, __le16 *qos_seq) | ||
1069 | { | ||
1070 | struct ieee80211_sta *sta = NULL; | ||
1071 | struct iwl_mvm_sta *mvm_ap_sta; | ||
1072 | int i; | ||
1073 | bool wake_queues = false; | ||
1074 | |||
1075 | lockdep_assert_held(&mvm->mutex); | ||
1076 | |||
1077 | spin_lock_bh(&mvm->d0i3_tx_lock); | ||
1078 | |||
1079 | if (mvm->d0i3_ap_sta_id == IWL_MVM_STATION_COUNT) | ||
1080 | goto out; | ||
1081 | |||
1082 | IWL_DEBUG_RPM(mvm, "re-enqueue packets\n"); | ||
1083 | |||
1084 | /* get the sta in order to update seq numbers and re-enqueue skbs */ | ||
1085 | sta = rcu_dereference_protected( | ||
1086 | mvm->fw_id_to_mac_id[mvm->d0i3_ap_sta_id], | ||
1087 | lockdep_is_held(&mvm->mutex)); | ||
1088 | |||
1089 | if (IS_ERR_OR_NULL(sta)) { | ||
1090 | sta = NULL; | ||
1091 | goto out; | ||
1092 | } | ||
1093 | |||
1094 | if (mvm->d0i3_offloading && qos_seq) { | ||
1095 | /* update qos seq numbers if offloading was enabled */ | ||
1096 | mvm_ap_sta = (struct iwl_mvm_sta *)sta->drv_priv; | ||
1097 | for (i = 0; i < IWL_MAX_TID_COUNT; i++) { | ||
1098 | u16 seq = le16_to_cpu(qos_seq[i]); | ||
1099 | /* firmware stores last-used one, we store next one */ | ||
1100 | seq += 0x10; | ||
1101 | mvm_ap_sta->tid_data[i].seq_number = seq; | ||
1102 | } | ||
1103 | } | ||
1104 | out: | ||
1105 | /* re-enqueue (or drop) all packets */ | ||
1106 | while (!skb_queue_empty(&mvm->d0i3_tx)) { | ||
1107 | struct sk_buff *skb = __skb_dequeue(&mvm->d0i3_tx); | ||
1108 | |||
1109 | if (!sta || iwl_mvm_tx_skb(mvm, skb, sta)) | ||
1110 | ieee80211_free_txskb(mvm->hw, skb); | ||
1111 | |||
1112 | /* if the skb_queue is not empty, we need to wake queues */ | ||
1113 | wake_queues = true; | ||
1114 | } | ||
1115 | clear_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status); | ||
1116 | wake_up(&mvm->d0i3_exit_waitq); | ||
1117 | mvm->d0i3_ap_sta_id = IWL_MVM_STATION_COUNT; | ||
1118 | if (wake_queues) | ||
1119 | ieee80211_wake_queues(mvm->hw); | ||
1120 | |||
1121 | spin_unlock_bh(&mvm->d0i3_tx_lock); | ||
1122 | } | ||
1123 | |||
917 | static void iwl_mvm_d0i3_exit_work(struct work_struct *wk) | 1124 | static void iwl_mvm_d0i3_exit_work(struct work_struct *wk) |
918 | { | 1125 | { |
919 | struct iwl_mvm *mvm = container_of(wk, struct iwl_mvm, d0i3_exit_work); | 1126 | struct iwl_mvm *mvm = container_of(wk, struct iwl_mvm, d0i3_exit_work); |
@@ -924,6 +1131,7 @@ static void iwl_mvm_d0i3_exit_work(struct work_struct *wk) | |||
924 | struct iwl_wowlan_status_v6 *status; | 1131 | struct iwl_wowlan_status_v6 *status; |
925 | int ret; | 1132 | int ret; |
926 | u32 disconnection_reasons, wakeup_reasons; | 1133 | u32 disconnection_reasons, wakeup_reasons; |
1134 | __le16 *qos_seq = NULL; | ||
927 | 1135 | ||
928 | mutex_lock(&mvm->mutex); | 1136 | mutex_lock(&mvm->mutex); |
929 | ret = iwl_mvm_send_cmd(mvm, &get_status_cmd); | 1137 | ret = iwl_mvm_send_cmd(mvm, &get_status_cmd); |
@@ -935,6 +1143,7 @@ static void iwl_mvm_d0i3_exit_work(struct work_struct *wk) | |||
935 | 1143 | ||
936 | status = (void *)get_status_cmd.resp_pkt->data; | 1144 | status = (void *)get_status_cmd.resp_pkt->data; |
937 | wakeup_reasons = le32_to_cpu(status->wakeup_reasons); | 1145 | wakeup_reasons = le32_to_cpu(status->wakeup_reasons); |
1146 | qos_seq = status->qos_seq_ctr; | ||
938 | 1147 | ||
939 | IWL_DEBUG_RPM(mvm, "wakeup reasons: 0x%x\n", wakeup_reasons); | 1148 | IWL_DEBUG_RPM(mvm, "wakeup reasons: 0x%x\n", wakeup_reasons); |
940 | 1149 | ||
@@ -948,6 +1157,7 @@ static void iwl_mvm_d0i3_exit_work(struct work_struct *wk) | |||
948 | 1157 | ||
949 | iwl_free_resp(&get_status_cmd); | 1158 | iwl_free_resp(&get_status_cmd); |
950 | out: | 1159 | out: |
1160 | iwl_mvm_d0i3_enable_tx(mvm, qos_seq); | ||
951 | mutex_unlock(&mvm->mutex); | 1161 | mutex_unlock(&mvm->mutex); |
952 | } | 1162 | } |
953 | 1163 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c index def6ec5173b9..6b636eab3339 100644 --- a/drivers/net/wireless/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/iwlwifi/mvm/power.c | |||
@@ -511,6 +511,7 @@ int iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm, | |||
511 | struct iwl_power_constraint { | 511 | struct iwl_power_constraint { |
512 | struct ieee80211_vif *bf_vif; | 512 | struct ieee80211_vif *bf_vif; |
513 | struct ieee80211_vif *bss_vif; | 513 | struct ieee80211_vif *bss_vif; |
514 | struct ieee80211_vif *p2p_vif; | ||
514 | u16 bss_phyctx_id; | 515 | u16 bss_phyctx_id; |
515 | u16 p2p_phyctx_id; | 516 | u16 p2p_phyctx_id; |
516 | bool pm_disabled; | 517 | bool pm_disabled; |
@@ -546,6 +547,10 @@ static void iwl_mvm_power_iterator(void *_data, u8 *mac, | |||
546 | if (mvmvif->phy_ctxt) | 547 | if (mvmvif->phy_ctxt) |
547 | power_iterator->p2p_phyctx_id = mvmvif->phy_ctxt->id; | 548 | power_iterator->p2p_phyctx_id = mvmvif->phy_ctxt->id; |
548 | 549 | ||
550 | /* we should have only one P2P vif */ | ||
551 | WARN_ON(power_iterator->p2p_vif); | ||
552 | power_iterator->p2p_vif = vif; | ||
553 | |||
549 | IWL_DEBUG_POWER(mvm, "p2p: p2p_id=%d, bss_id=%d\n", | 554 | IWL_DEBUG_POWER(mvm, "p2p: p2p_id=%d, bss_id=%d\n", |
550 | power_iterator->p2p_phyctx_id, | 555 | power_iterator->p2p_phyctx_id, |
551 | power_iterator->bss_phyctx_id); | 556 | power_iterator->bss_phyctx_id); |
@@ -633,16 +638,18 @@ int iwl_mvm_power_update_mac(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
633 | return ret; | 638 | return ret; |
634 | } | 639 | } |
635 | 640 | ||
636 | ret = iwl_mvm_power_send_cmd(mvm, vif); | 641 | if (constraint.bss_vif) { |
637 | if (ret) | ||
638 | return ret; | ||
639 | |||
640 | if (constraint.bss_vif && vif != constraint.bss_vif) { | ||
641 | ret = iwl_mvm_power_send_cmd(mvm, constraint.bss_vif); | 642 | ret = iwl_mvm_power_send_cmd(mvm, constraint.bss_vif); |
642 | if (ret) | 643 | if (ret) |
643 | return ret; | 644 | return ret; |
644 | } | 645 | } |
645 | 646 | ||
647 | if (constraint.p2p_vif) { | ||
648 | ret = iwl_mvm_power_send_cmd(mvm, constraint.p2p_vif); | ||
649 | if (ret) | ||
650 | return ret; | ||
651 | } | ||
652 | |||
646 | if (!constraint.bf_vif) | 653 | if (!constraint.bf_vif) |
647 | return 0; | 654 | return 0; |
648 | 655 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/quota.c b/drivers/net/wireless/iwlwifi/mvm/quota.c index 06d8429be1fb..35e86e06dffd 100644 --- a/drivers/net/wireless/iwlwifi/mvm/quota.c +++ b/drivers/net/wireless/iwlwifi/mvm/quota.c | |||
@@ -180,7 +180,6 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif) | |||
180 | .colors = { -1, -1, -1, -1 }, | 180 | .colors = { -1, -1, -1, -1 }, |
181 | .new_vif = newvif, | 181 | .new_vif = newvif, |
182 | }; | 182 | }; |
183 | u32 ll_max_duration; | ||
184 | 183 | ||
185 | lockdep_assert_held(&mvm->mutex); | 184 | lockdep_assert_held(&mvm->mutex); |
186 | 185 | ||
@@ -199,21 +198,6 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif) | |||
199 | iwl_mvm_quota_iterator(&data, newvif->addr, newvif); | 198 | iwl_mvm_quota_iterator(&data, newvif->addr, newvif); |
200 | } | 199 | } |
201 | 200 | ||
202 | switch (data.n_low_latency_bindings) { | ||
203 | case 0: /* no low latency - use default */ | ||
204 | ll_max_duration = 0; | ||
205 | break; | ||
206 | case 1: /* SingleBindingLowLatencyMode */ | ||
207 | ll_max_duration = IWL_MVM_LOWLAT_SINGLE_BINDING_MAXDUR; | ||
208 | break; | ||
209 | case 2: /* DualBindingLowLatencyMode */ | ||
210 | ll_max_duration = IWL_MVM_LOWLAT_DUAL_BINDING_MAXDUR; | ||
211 | break; | ||
212 | default: /* MultiBindingLowLatencyMode */ | ||
213 | ll_max_duration = 0; | ||
214 | break; | ||
215 | } | ||
216 | |||
217 | /* | 201 | /* |
218 | * The FW's scheduling session consists of | 202 | * The FW's scheduling session consists of |
219 | * IWL_MVM_MAX_QUOTA fragments. Divide these fragments | 203 | * IWL_MVM_MAX_QUOTA fragments. Divide these fragments |
@@ -278,7 +262,6 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif) | |||
278 | * binding. | 262 | * binding. |
279 | */ | 263 | */ |
280 | cmd.quotas[idx].quota = cpu_to_le32(QUOTA_LOWLAT_MIN); | 264 | cmd.quotas[idx].quota = cpu_to_le32(QUOTA_LOWLAT_MIN); |
281 | |||
282 | else | 265 | else |
283 | cmd.quotas[idx].quota = | 266 | cmd.quotas[idx].quota = |
284 | cpu_to_le32(quota * data.n_interfaces[i]); | 267 | cpu_to_le32(quota * data.n_interfaces[i]); |
@@ -287,11 +270,7 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif) | |||
287 | "Binding=%d, quota=%u > max=%u\n", | 270 | "Binding=%d, quota=%u > max=%u\n", |
288 | idx, le32_to_cpu(cmd.quotas[idx].quota), QUOTA_100); | 271 | idx, le32_to_cpu(cmd.quotas[idx].quota), QUOTA_100); |
289 | 272 | ||
290 | if (data.n_interfaces[i] && !data.low_latency[i]) | 273 | cmd.quotas[idx].max_duration = cpu_to_le32(0); |
291 | cmd.quotas[idx].max_duration = | ||
292 | cpu_to_le32(ll_max_duration); | ||
293 | else | ||
294 | cmd.quotas[idx].max_duration = cpu_to_le32(0); | ||
295 | 274 | ||
296 | idx++; | 275 | idx++; |
297 | } | 276 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 399709f2be2e..568abd61b14f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c | |||
@@ -211,9 +211,9 @@ static const struct rs_tx_column rs_tx_columns[] = { | |||
211 | .next_columns = { | 211 | .next_columns = { |
212 | RS_COLUMN_LEGACY_ANT_B, | 212 | RS_COLUMN_LEGACY_ANT_B, |
213 | RS_COLUMN_SISO_ANT_A, | 213 | RS_COLUMN_SISO_ANT_A, |
214 | RS_COLUMN_SISO_ANT_B, | ||
214 | RS_COLUMN_MIMO2, | 215 | RS_COLUMN_MIMO2, |
215 | RS_COLUMN_INVALID, | 216 | RS_COLUMN_MIMO2_SGI, |
216 | RS_COLUMN_INVALID, | ||
217 | }, | 217 | }, |
218 | }, | 218 | }, |
219 | [RS_COLUMN_LEGACY_ANT_B] = { | 219 | [RS_COLUMN_LEGACY_ANT_B] = { |
@@ -221,10 +221,10 @@ static const struct rs_tx_column rs_tx_columns[] = { | |||
221 | .ant = ANT_B, | 221 | .ant = ANT_B, |
222 | .next_columns = { | 222 | .next_columns = { |
223 | RS_COLUMN_LEGACY_ANT_A, | 223 | RS_COLUMN_LEGACY_ANT_A, |
224 | RS_COLUMN_SISO_ANT_A, | ||
224 | RS_COLUMN_SISO_ANT_B, | 225 | RS_COLUMN_SISO_ANT_B, |
225 | RS_COLUMN_MIMO2, | 226 | RS_COLUMN_MIMO2, |
226 | RS_COLUMN_INVALID, | 227 | RS_COLUMN_MIMO2_SGI, |
227 | RS_COLUMN_INVALID, | ||
228 | }, | 228 | }, |
229 | }, | 229 | }, |
230 | [RS_COLUMN_SISO_ANT_A] = { | 230 | [RS_COLUMN_SISO_ANT_A] = { |
@@ -234,8 +234,8 @@ static const struct rs_tx_column rs_tx_columns[] = { | |||
234 | RS_COLUMN_SISO_ANT_B, | 234 | RS_COLUMN_SISO_ANT_B, |
235 | RS_COLUMN_MIMO2, | 235 | RS_COLUMN_MIMO2, |
236 | RS_COLUMN_SISO_ANT_A_SGI, | 236 | RS_COLUMN_SISO_ANT_A_SGI, |
237 | RS_COLUMN_INVALID, | 237 | RS_COLUMN_SISO_ANT_B_SGI, |
238 | RS_COLUMN_INVALID, | 238 | RS_COLUMN_MIMO2_SGI, |
239 | }, | 239 | }, |
240 | .checks = { | 240 | .checks = { |
241 | rs_siso_allow, | 241 | rs_siso_allow, |
@@ -248,8 +248,8 @@ static const struct rs_tx_column rs_tx_columns[] = { | |||
248 | RS_COLUMN_SISO_ANT_A, | 248 | RS_COLUMN_SISO_ANT_A, |
249 | RS_COLUMN_MIMO2, | 249 | RS_COLUMN_MIMO2, |
250 | RS_COLUMN_SISO_ANT_B_SGI, | 250 | RS_COLUMN_SISO_ANT_B_SGI, |
251 | RS_COLUMN_INVALID, | 251 | RS_COLUMN_SISO_ANT_A_SGI, |
252 | RS_COLUMN_INVALID, | 252 | RS_COLUMN_MIMO2_SGI, |
253 | }, | 253 | }, |
254 | .checks = { | 254 | .checks = { |
255 | rs_siso_allow, | 255 | rs_siso_allow, |
@@ -263,8 +263,8 @@ static const struct rs_tx_column rs_tx_columns[] = { | |||
263 | RS_COLUMN_SISO_ANT_B_SGI, | 263 | RS_COLUMN_SISO_ANT_B_SGI, |
264 | RS_COLUMN_MIMO2_SGI, | 264 | RS_COLUMN_MIMO2_SGI, |
265 | RS_COLUMN_SISO_ANT_A, | 265 | RS_COLUMN_SISO_ANT_A, |
266 | RS_COLUMN_INVALID, | 266 | RS_COLUMN_SISO_ANT_B, |
267 | RS_COLUMN_INVALID, | 267 | RS_COLUMN_MIMO2, |
268 | }, | 268 | }, |
269 | .checks = { | 269 | .checks = { |
270 | rs_siso_allow, | 270 | rs_siso_allow, |
@@ -279,8 +279,8 @@ static const struct rs_tx_column rs_tx_columns[] = { | |||
279 | RS_COLUMN_SISO_ANT_A_SGI, | 279 | RS_COLUMN_SISO_ANT_A_SGI, |
280 | RS_COLUMN_MIMO2_SGI, | 280 | RS_COLUMN_MIMO2_SGI, |
281 | RS_COLUMN_SISO_ANT_B, | 281 | RS_COLUMN_SISO_ANT_B, |
282 | RS_COLUMN_INVALID, | 282 | RS_COLUMN_SISO_ANT_A, |
283 | RS_COLUMN_INVALID, | 283 | RS_COLUMN_MIMO2, |
284 | }, | 284 | }, |
285 | .checks = { | 285 | .checks = { |
286 | rs_siso_allow, | 286 | rs_siso_allow, |
@@ -292,10 +292,10 @@ static const struct rs_tx_column rs_tx_columns[] = { | |||
292 | .ant = ANT_AB, | 292 | .ant = ANT_AB, |
293 | .next_columns = { | 293 | .next_columns = { |
294 | RS_COLUMN_SISO_ANT_A, | 294 | RS_COLUMN_SISO_ANT_A, |
295 | RS_COLUMN_SISO_ANT_B, | ||
296 | RS_COLUMN_SISO_ANT_A_SGI, | ||
297 | RS_COLUMN_SISO_ANT_B_SGI, | ||
295 | RS_COLUMN_MIMO2_SGI, | 298 | RS_COLUMN_MIMO2_SGI, |
296 | RS_COLUMN_INVALID, | ||
297 | RS_COLUMN_INVALID, | ||
298 | RS_COLUMN_INVALID, | ||
299 | }, | 299 | }, |
300 | .checks = { | 300 | .checks = { |
301 | rs_mimo_allow, | 301 | rs_mimo_allow, |
@@ -307,10 +307,10 @@ static const struct rs_tx_column rs_tx_columns[] = { | |||
307 | .sgi = true, | 307 | .sgi = true, |
308 | .next_columns = { | 308 | .next_columns = { |
309 | RS_COLUMN_SISO_ANT_A_SGI, | 309 | RS_COLUMN_SISO_ANT_A_SGI, |
310 | RS_COLUMN_SISO_ANT_B_SGI, | ||
311 | RS_COLUMN_SISO_ANT_A, | ||
312 | RS_COLUMN_SISO_ANT_B, | ||
310 | RS_COLUMN_MIMO2, | 313 | RS_COLUMN_MIMO2, |
311 | RS_COLUMN_INVALID, | ||
312 | RS_COLUMN_INVALID, | ||
313 | RS_COLUMN_INVALID, | ||
314 | }, | 314 | }, |
315 | .checks = { | 315 | .checks = { |
316 | rs_mimo_allow, | 316 | rs_mimo_allow, |
@@ -503,6 +503,14 @@ static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window) | |||
503 | window->average_tpt = IWL_INVALID_VALUE; | 503 | window->average_tpt = IWL_INVALID_VALUE; |
504 | } | 504 | } |
505 | 505 | ||
506 | static void rs_rate_scale_clear_tbl_windows(struct iwl_scale_tbl_info *tbl) | ||
507 | { | ||
508 | int i; | ||
509 | |||
510 | for (i = 0; i < IWL_RATE_COUNT; i++) | ||
511 | rs_rate_scale_clear_window(&tbl->win[i]); | ||
512 | } | ||
513 | |||
506 | static inline u8 rs_is_valid_ant(u8 valid_antenna, u8 ant_type) | 514 | static inline u8 rs_is_valid_ant(u8 valid_antenna, u8 ant_type) |
507 | { | 515 | { |
508 | return (ant_type & valid_antenna) == ant_type; | 516 | return (ant_type & valid_antenna) == ant_type; |
@@ -566,19 +574,13 @@ static s32 get_expected_tpt(struct iwl_scale_tbl_info *tbl, int rs_index) | |||
566 | * at this rate. window->data contains the bitmask of successful | 574 | * at this rate. window->data contains the bitmask of successful |
567 | * packets. | 575 | * packets. |
568 | */ | 576 | */ |
569 | static int rs_collect_tx_data(struct iwl_scale_tbl_info *tbl, | 577 | static int _rs_collect_tx_data(struct iwl_scale_tbl_info *tbl, |
570 | int scale_index, int attempts, int successes) | 578 | int scale_index, int attempts, int successes, |
579 | struct iwl_rate_scale_data *window) | ||
571 | { | 580 | { |
572 | struct iwl_rate_scale_data *window = NULL; | ||
573 | static const u64 mask = (((u64)1) << (IWL_RATE_MAX_WINDOW - 1)); | 581 | static const u64 mask = (((u64)1) << (IWL_RATE_MAX_WINDOW - 1)); |
574 | s32 fail_count, tpt; | 582 | s32 fail_count, tpt; |
575 | 583 | ||
576 | if (scale_index < 0 || scale_index >= IWL_RATE_COUNT) | ||
577 | return -EINVAL; | ||
578 | |||
579 | /* Select window for current tx bit rate */ | ||
580 | window = &(tbl->win[scale_index]); | ||
581 | |||
582 | /* Get expected throughput */ | 584 | /* Get expected throughput */ |
583 | tpt = get_expected_tpt(tbl, scale_index); | 585 | tpt = get_expected_tpt(tbl, scale_index); |
584 | 586 | ||
@@ -636,6 +638,21 @@ static int rs_collect_tx_data(struct iwl_scale_tbl_info *tbl, | |||
636 | return 0; | 638 | return 0; |
637 | } | 639 | } |
638 | 640 | ||
641 | static int rs_collect_tx_data(struct iwl_scale_tbl_info *tbl, | ||
642 | int scale_index, int attempts, int successes) | ||
643 | { | ||
644 | struct iwl_rate_scale_data *window = NULL; | ||
645 | |||
646 | if (scale_index < 0 || scale_index >= IWL_RATE_COUNT) | ||
647 | return -EINVAL; | ||
648 | |||
649 | /* Select window for current tx bit rate */ | ||
650 | window = &(tbl->win[scale_index]); | ||
651 | |||
652 | return _rs_collect_tx_data(tbl, scale_index, attempts, successes, | ||
653 | window); | ||
654 | } | ||
655 | |||
639 | /* Convert rs_rate object into ucode rate bitmask */ | 656 | /* Convert rs_rate object into ucode rate bitmask */ |
640 | static u32 ucode_rate_from_rs_rate(struct iwl_mvm *mvm, | 657 | static u32 ucode_rate_from_rs_rate(struct iwl_mvm *mvm, |
641 | struct rs_rate *rate) | 658 | struct rs_rate *rate) |
@@ -1361,7 +1378,6 @@ static u32 rs_bw_from_sta_bw(struct ieee80211_sta *sta) | |||
1361 | static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search) | 1378 | static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search) |
1362 | { | 1379 | { |
1363 | struct iwl_scale_tbl_info *tbl; | 1380 | struct iwl_scale_tbl_info *tbl; |
1364 | int i; | ||
1365 | int active_tbl; | 1381 | int active_tbl; |
1366 | int flush_interval_passed = 0; | 1382 | int flush_interval_passed = 0; |
1367 | struct iwl_mvm *mvm; | 1383 | struct iwl_mvm *mvm; |
@@ -1422,9 +1438,7 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search) | |||
1422 | 1438 | ||
1423 | IWL_DEBUG_RATE(mvm, | 1439 | IWL_DEBUG_RATE(mvm, |
1424 | "LQ: stay in table clear win\n"); | 1440 | "LQ: stay in table clear win\n"); |
1425 | for (i = 0; i < IWL_RATE_COUNT; i++) | 1441 | rs_rate_scale_clear_tbl_windows(tbl); |
1426 | rs_rate_scale_clear_window( | ||
1427 | &(tbl->win[i])); | ||
1428 | } | 1442 | } |
1429 | } | 1443 | } |
1430 | 1444 | ||
@@ -1433,8 +1447,7 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search) | |||
1433 | * "search" table). */ | 1447 | * "search" table). */ |
1434 | if (lq_sta->rs_state == RS_STATE_SEARCH_CYCLE_STARTED) { | 1448 | if (lq_sta->rs_state == RS_STATE_SEARCH_CYCLE_STARTED) { |
1435 | IWL_DEBUG_RATE(mvm, "Clearing up window stats\n"); | 1449 | IWL_DEBUG_RATE(mvm, "Clearing up window stats\n"); |
1436 | for (i = 0; i < IWL_RATE_COUNT; i++) | 1450 | rs_rate_scale_clear_tbl_windows(tbl); |
1437 | rs_rate_scale_clear_window(&(tbl->win[i])); | ||
1438 | } | 1451 | } |
1439 | } | 1452 | } |
1440 | } | 1453 | } |
@@ -1724,7 +1737,6 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, | |||
1724 | int low = IWL_RATE_INVALID; | 1737 | int low = IWL_RATE_INVALID; |
1725 | int high = IWL_RATE_INVALID; | 1738 | int high = IWL_RATE_INVALID; |
1726 | int index; | 1739 | int index; |
1727 | int i; | ||
1728 | struct iwl_rate_scale_data *window = NULL; | 1740 | struct iwl_rate_scale_data *window = NULL; |
1729 | int current_tpt = IWL_INVALID_VALUE; | 1741 | int current_tpt = IWL_INVALID_VALUE; |
1730 | int low_tpt = IWL_INVALID_VALUE; | 1742 | int low_tpt = IWL_INVALID_VALUE; |
@@ -2009,8 +2021,7 @@ lq_update: | |||
2009 | if (lq_sta->search_better_tbl) { | 2021 | if (lq_sta->search_better_tbl) { |
2010 | /* Access the "search" table, clear its history. */ | 2022 | /* Access the "search" table, clear its history. */ |
2011 | tbl = &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); | 2023 | tbl = &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); |
2012 | for (i = 0; i < IWL_RATE_COUNT; i++) | 2024 | rs_rate_scale_clear_tbl_windows(tbl); |
2013 | rs_rate_scale_clear_window(&(tbl->win[i])); | ||
2014 | 2025 | ||
2015 | /* Use new "search" start rate */ | 2026 | /* Use new "search" start rate */ |
2016 | index = tbl->rate.index; | 2027 | index = tbl->rate.index; |
@@ -2331,8 +2342,7 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
2331 | lq_sta->lq.sta_id = sta_priv->sta_id; | 2342 | lq_sta->lq.sta_id = sta_priv->sta_id; |
2332 | 2343 | ||
2333 | for (j = 0; j < LQ_SIZE; j++) | 2344 | for (j = 0; j < LQ_SIZE; j++) |
2334 | for (i = 0; i < IWL_RATE_COUNT; i++) | 2345 | rs_rate_scale_clear_tbl_windows(&lq_sta->lq_info[j]); |
2335 | rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]); | ||
2336 | 2346 | ||
2337 | lq_sta->flush_timer = 0; | 2347 | lq_sta->flush_timer = 0; |
2338 | 2348 | ||
@@ -2591,7 +2601,7 @@ static void rs_fill_lq_cmd(struct iwl_mvm *mvm, | |||
2591 | 2601 | ||
2592 | if (sta) | 2602 | if (sta) |
2593 | lq_cmd->agg_time_limit = | 2603 | lq_cmd->agg_time_limit = |
2594 | cpu_to_le16(iwl_mvm_bt_coex_agg_time_limit(mvm, sta)); | 2604 | cpu_to_le16(iwl_mvm_coex_agg_time_limit(mvm, sta)); |
2595 | } | 2605 | } |
2596 | 2606 | ||
2597 | static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) | 2607 | static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index 713efd71efe2..c91dc8498852 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c | |||
@@ -70,9 +70,16 @@ | |||
70 | 70 | ||
71 | #define IWL_PLCP_QUIET_THRESH 1 | 71 | #define IWL_PLCP_QUIET_THRESH 1 |
72 | #define IWL_ACTIVE_QUIET_TIME 10 | 72 | #define IWL_ACTIVE_QUIET_TIME 10 |
73 | #define LONG_OUT_TIME_PERIOD 600 | 73 | |
74 | #define SHORT_OUT_TIME_PERIOD 200 | 74 | struct iwl_mvm_scan_params { |
75 | #define SUSPEND_TIME_PERIOD 100 | 75 | u32 max_out_time; |
76 | u32 suspend_time; | ||
77 | bool passive_fragmented; | ||
78 | struct _dwell { | ||
79 | u16 passive; | ||
80 | u16 active; | ||
81 | } dwell[IEEE80211_NUM_BANDS]; | ||
82 | }; | ||
76 | 83 | ||
77 | static inline __le16 iwl_mvm_scan_rx_chain(struct iwl_mvm *mvm) | 84 | static inline __le16 iwl_mvm_scan_rx_chain(struct iwl_mvm *mvm) |
78 | { | 85 | { |
@@ -90,24 +97,6 @@ static inline __le16 iwl_mvm_scan_rx_chain(struct iwl_mvm *mvm) | |||
90 | return cpu_to_le16(rx_chain); | 97 | return cpu_to_le16(rx_chain); |
91 | } | 98 | } |
92 | 99 | ||
93 | static inline __le32 iwl_mvm_scan_max_out_time(struct ieee80211_vif *vif, | ||
94 | u32 flags, bool is_assoc) | ||
95 | { | ||
96 | if (!is_assoc) | ||
97 | return 0; | ||
98 | if (flags & NL80211_SCAN_FLAG_LOW_PRIORITY) | ||
99 | return cpu_to_le32(ieee80211_tu_to_usec(SHORT_OUT_TIME_PERIOD)); | ||
100 | return cpu_to_le32(ieee80211_tu_to_usec(LONG_OUT_TIME_PERIOD)); | ||
101 | } | ||
102 | |||
103 | static inline __le32 iwl_mvm_scan_suspend_time(struct ieee80211_vif *vif, | ||
104 | bool is_assoc) | ||
105 | { | ||
106 | if (!is_assoc) | ||
107 | return 0; | ||
108 | return cpu_to_le32(ieee80211_tu_to_usec(SUSPEND_TIME_PERIOD)); | ||
109 | } | ||
110 | |||
111 | static inline __le32 | 100 | static inline __le32 |
112 | iwl_mvm_scan_rxon_flags(struct cfg80211_scan_request *req) | 101 | iwl_mvm_scan_rxon_flags(struct cfg80211_scan_request *req) |
113 | { | 102 | { |
@@ -181,15 +170,14 @@ static u16 iwl_mvm_get_passive_dwell(enum ieee80211_band band) | |||
181 | 170 | ||
182 | static void iwl_mvm_scan_fill_channels(struct iwl_scan_cmd *cmd, | 171 | static void iwl_mvm_scan_fill_channels(struct iwl_scan_cmd *cmd, |
183 | struct cfg80211_scan_request *req, | 172 | struct cfg80211_scan_request *req, |
184 | bool basic_ssid) | 173 | bool basic_ssid, |
174 | struct iwl_mvm_scan_params *params) | ||
185 | { | 175 | { |
186 | u16 passive_dwell = iwl_mvm_get_passive_dwell(req->channels[0]->band); | ||
187 | u16 active_dwell = iwl_mvm_get_active_dwell(req->channels[0]->band, | ||
188 | req->n_ssids); | ||
189 | struct iwl_scan_channel *chan = (struct iwl_scan_channel *) | 176 | struct iwl_scan_channel *chan = (struct iwl_scan_channel *) |
190 | (cmd->data + le16_to_cpu(cmd->tx_cmd.len)); | 177 | (cmd->data + le16_to_cpu(cmd->tx_cmd.len)); |
191 | int i; | 178 | int i; |
192 | int type = BIT(req->n_ssids) - 1; | 179 | int type = BIT(req->n_ssids) - 1; |
180 | enum ieee80211_band band = req->channels[0]->band; | ||
193 | 181 | ||
194 | if (!basic_ssid) | 182 | if (!basic_ssid) |
195 | type |= BIT(req->n_ssids); | 183 | type |= BIT(req->n_ssids); |
@@ -199,8 +187,8 @@ static void iwl_mvm_scan_fill_channels(struct iwl_scan_cmd *cmd, | |||
199 | chan->type = cpu_to_le32(type); | 187 | chan->type = cpu_to_le32(type); |
200 | if (req->channels[i]->flags & IEEE80211_CHAN_NO_IR) | 188 | if (req->channels[i]->flags & IEEE80211_CHAN_NO_IR) |
201 | chan->type &= cpu_to_le32(~SCAN_CHANNEL_TYPE_ACTIVE); | 189 | chan->type &= cpu_to_le32(~SCAN_CHANNEL_TYPE_ACTIVE); |
202 | chan->active_dwell = cpu_to_le16(active_dwell); | 190 | chan->active_dwell = cpu_to_le16(params->dwell[band].active); |
203 | chan->passive_dwell = cpu_to_le16(passive_dwell); | 191 | chan->passive_dwell = cpu_to_le16(params->dwell[band].passive); |
204 | chan->iteration_count = cpu_to_le16(1); | 192 | chan->iteration_count = cpu_to_le16(1); |
205 | chan++; | 193 | chan++; |
206 | } | 194 | } |
@@ -267,13 +255,76 @@ static u16 iwl_mvm_fill_probe_req(struct ieee80211_mgmt *frame, const u8 *ta, | |||
267 | return (u16)len; | 255 | return (u16)len; |
268 | } | 256 | } |
269 | 257 | ||
270 | static void iwl_mvm_vif_assoc_iterator(void *data, u8 *mac, | 258 | static void iwl_mvm_scan_condition_iterator(void *data, u8 *mac, |
271 | struct ieee80211_vif *vif) | 259 | struct ieee80211_vif *vif) |
272 | { | 260 | { |
273 | bool *is_assoc = data; | 261 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
262 | bool *global_bound = data; | ||
274 | 263 | ||
275 | if (vif->bss_conf.assoc) | 264 | if (mvmvif->phy_ctxt && mvmvif->phy_ctxt->id < MAX_PHYS) |
276 | *is_assoc = true; | 265 | *global_bound = true; |
266 | } | ||
267 | |||
268 | static void iwl_mvm_scan_calc_params(struct iwl_mvm *mvm, | ||
269 | struct ieee80211_vif *vif, | ||
270 | int n_ssids, | ||
271 | struct iwl_mvm_scan_params *params) | ||
272 | { | ||
273 | bool global_bound = false; | ||
274 | enum ieee80211_band band; | ||
275 | |||
276 | ieee80211_iterate_active_interfaces_atomic(mvm->hw, | ||
277 | IEEE80211_IFACE_ITER_NORMAL, | ||
278 | iwl_mvm_scan_condition_iterator, | ||
279 | &global_bound); | ||
280 | /* | ||
281 | * Under low latency traffic passive scan is fragmented meaning | ||
282 | * that dwell on a particular channel will be fragmented. Each fragment | ||
283 | * dwell time is 20ms and fragments period is 105ms. Skipping to next | ||
284 | * channel will be delayed by the same period - 105ms. So suspend_time | ||
285 | * parameter describing both fragments and channels skipping periods is | ||
286 | * set to 105ms. This value is chosen so that overall passive scan | ||
287 | * duration will not be too long. Max_out_time in this case is set to | ||
288 | * 70ms, so for active scanning operating channel will be left for 70ms | ||
289 | * while for passive still for 20ms (fragment dwell). | ||
290 | */ | ||
291 | if (global_bound) { | ||
292 | if (!iwl_mvm_low_latency(mvm)) { | ||
293 | params->suspend_time = ieee80211_tu_to_usec(100); | ||
294 | params->max_out_time = ieee80211_tu_to_usec(600); | ||
295 | } else { | ||
296 | params->suspend_time = ieee80211_tu_to_usec(105); | ||
297 | /* P2P doesn't support fragmented passive scan, so | ||
298 | * configure max_out_time to be at least longest dwell | ||
299 | * time for passive scan. | ||
300 | */ | ||
301 | if (vif->type == NL80211_IFTYPE_STATION && !vif->p2p) { | ||
302 | params->max_out_time = ieee80211_tu_to_usec(70); | ||
303 | params->passive_fragmented = true; | ||
304 | } else { | ||
305 | u32 passive_dwell; | ||
306 | |||
307 | /* | ||
308 | * Use band G so that passive channel dwell time | ||
309 | * will be assigned with maximum value. | ||
310 | */ | ||
311 | band = IEEE80211_BAND_2GHZ; | ||
312 | passive_dwell = iwl_mvm_get_passive_dwell(band); | ||
313 | params->max_out_time = | ||
314 | ieee80211_tu_to_usec(passive_dwell); | ||
315 | } | ||
316 | } | ||
317 | } | ||
318 | |||
319 | for (band = IEEE80211_BAND_2GHZ; band < IEEE80211_NUM_BANDS; band++) { | ||
320 | if (params->passive_fragmented) | ||
321 | params->dwell[band].passive = 20; | ||
322 | else | ||
323 | params->dwell[band].passive = | ||
324 | iwl_mvm_get_passive_dwell(band); | ||
325 | params->dwell[band].active = iwl_mvm_get_active_dwell(band, | ||
326 | n_ssids); | ||
327 | } | ||
277 | } | 328 | } |
278 | 329 | ||
279 | int iwl_mvm_scan_request(struct iwl_mvm *mvm, | 330 | int iwl_mvm_scan_request(struct iwl_mvm *mvm, |
@@ -288,13 +339,13 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm, | |||
288 | .dataflags = { IWL_HCMD_DFL_NOCOPY, }, | 339 | .dataflags = { IWL_HCMD_DFL_NOCOPY, }, |
289 | }; | 340 | }; |
290 | struct iwl_scan_cmd *cmd = mvm->scan_cmd; | 341 | struct iwl_scan_cmd *cmd = mvm->scan_cmd; |
291 | bool is_assoc = false; | ||
292 | int ret; | 342 | int ret; |
293 | u32 status; | 343 | u32 status; |
294 | int ssid_len = 0; | 344 | int ssid_len = 0; |
295 | u8 *ssid = NULL; | 345 | u8 *ssid = NULL; |
296 | bool basic_ssid = !(mvm->fw->ucode_capa.flags & | 346 | bool basic_ssid = !(mvm->fw->ucode_capa.flags & |
297 | IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID); | 347 | IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID); |
348 | struct iwl_mvm_scan_params params = {}; | ||
298 | 349 | ||
299 | lockdep_assert_held(&mvm->mutex); | 350 | lockdep_assert_held(&mvm->mutex); |
300 | BUG_ON(mvm->scan_cmd == NULL); | 351 | BUG_ON(mvm->scan_cmd == NULL); |
@@ -304,17 +355,18 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm, | |||
304 | memset(cmd, 0, sizeof(struct iwl_scan_cmd) + | 355 | memset(cmd, 0, sizeof(struct iwl_scan_cmd) + |
305 | mvm->fw->ucode_capa.max_probe_length + | 356 | mvm->fw->ucode_capa.max_probe_length + |
306 | (MAX_NUM_SCAN_CHANNELS * sizeof(struct iwl_scan_channel))); | 357 | (MAX_NUM_SCAN_CHANNELS * sizeof(struct iwl_scan_channel))); |
307 | ieee80211_iterate_active_interfaces_atomic(mvm->hw, | 358 | |
308 | IEEE80211_IFACE_ITER_NORMAL, | ||
309 | iwl_mvm_vif_assoc_iterator, | ||
310 | &is_assoc); | ||
311 | cmd->channel_count = (u8)req->n_channels; | 359 | cmd->channel_count = (u8)req->n_channels; |
312 | cmd->quiet_time = cpu_to_le16(IWL_ACTIVE_QUIET_TIME); | 360 | cmd->quiet_time = cpu_to_le16(IWL_ACTIVE_QUIET_TIME); |
313 | cmd->quiet_plcp_th = cpu_to_le16(IWL_PLCP_QUIET_THRESH); | 361 | cmd->quiet_plcp_th = cpu_to_le16(IWL_PLCP_QUIET_THRESH); |
314 | cmd->rxchain_sel_flags = iwl_mvm_scan_rx_chain(mvm); | 362 | cmd->rxchain_sel_flags = iwl_mvm_scan_rx_chain(mvm); |
315 | cmd->max_out_time = iwl_mvm_scan_max_out_time(vif, req->flags, | 363 | |
316 | is_assoc); | 364 | iwl_mvm_scan_calc_params(mvm, vif, req->n_ssids, ¶ms); |
317 | cmd->suspend_time = iwl_mvm_scan_suspend_time(vif, is_assoc); | 365 | cmd->max_out_time = cpu_to_le32(params.max_out_time); |
366 | cmd->suspend_time = cpu_to_le32(params.suspend_time); | ||
367 | if (params.passive_fragmented) | ||
368 | cmd->scan_flags |= SCAN_FLAGS_FRAGMENTED_SCAN; | ||
369 | |||
318 | cmd->rxon_flags = iwl_mvm_scan_rxon_flags(req); | 370 | cmd->rxon_flags = iwl_mvm_scan_rxon_flags(req); |
319 | cmd->filter_flags = cpu_to_le32(MAC_FILTER_ACCEPT_GRP | | 371 | cmd->filter_flags = cpu_to_le32(MAC_FILTER_ACCEPT_GRP | |
320 | MAC_FILTER_IN_BEACON); | 372 | MAC_FILTER_IN_BEACON); |
@@ -360,7 +412,7 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm, | |||
360 | req->ie, req->ie_len, | 412 | req->ie, req->ie_len, |
361 | mvm->fw->ucode_capa.max_probe_length)); | 413 | mvm->fw->ucode_capa.max_probe_length)); |
362 | 414 | ||
363 | iwl_mvm_scan_fill_channels(cmd, req, basic_ssid); | 415 | iwl_mvm_scan_fill_channels(cmd, req, basic_ssid, ¶ms); |
364 | 416 | ||
365 | cmd->len = cpu_to_le16(sizeof(struct iwl_scan_cmd) + | 417 | cmd->len = cpu_to_le16(sizeof(struct iwl_scan_cmd) + |
366 | le16_to_cpu(cmd->tx_cmd.len) + | 418 | le16_to_cpu(cmd->tx_cmd.len) + |
@@ -402,10 +454,13 @@ int iwl_mvm_rx_scan_complete(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | |||
402 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 454 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
403 | struct iwl_scan_complete_notif *notif = (void *)pkt->data; | 455 | struct iwl_scan_complete_notif *notif = (void *)pkt->data; |
404 | 456 | ||
457 | lockdep_assert_held(&mvm->mutex); | ||
458 | |||
405 | IWL_DEBUG_SCAN(mvm, "Scan complete: status=0x%x scanned channels=%d\n", | 459 | IWL_DEBUG_SCAN(mvm, "Scan complete: status=0x%x scanned channels=%d\n", |
406 | notif->status, notif->scanned_channels); | 460 | notif->status, notif->scanned_channels); |
407 | 461 | ||
408 | mvm->scan_status = IWL_MVM_SCAN_NONE; | 462 | if (mvm->scan_status == IWL_MVM_SCAN_OS) |
463 | mvm->scan_status = IWL_MVM_SCAN_NONE; | ||
409 | ieee80211_scan_completed(mvm->hw, notif->status != SCAN_COMP_STATUS_OK); | 464 | ieee80211_scan_completed(mvm->hw, notif->status != SCAN_COMP_STATUS_OK); |
410 | 465 | ||
411 | iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); | 466 | iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); |
@@ -466,7 +521,7 @@ static bool iwl_mvm_scan_abort_notif(struct iwl_notif_wait_data *notif_wait, | |||
466 | }; | 521 | }; |
467 | } | 522 | } |
468 | 523 | ||
469 | void iwl_mvm_cancel_scan(struct iwl_mvm *mvm) | 524 | int iwl_mvm_cancel_scan(struct iwl_mvm *mvm) |
470 | { | 525 | { |
471 | struct iwl_notification_wait wait_scan_abort; | 526 | struct iwl_notification_wait wait_scan_abort; |
472 | static const u8 scan_abort_notif[] = { SCAN_ABORT_CMD, | 527 | static const u8 scan_abort_notif[] = { SCAN_ABORT_CMD, |
@@ -474,13 +529,13 @@ void iwl_mvm_cancel_scan(struct iwl_mvm *mvm) | |||
474 | int ret; | 529 | int ret; |
475 | 530 | ||
476 | if (mvm->scan_status == IWL_MVM_SCAN_NONE) | 531 | if (mvm->scan_status == IWL_MVM_SCAN_NONE) |
477 | return; | 532 | return 0; |
478 | 533 | ||
479 | if (iwl_mvm_is_radio_killed(mvm)) { | 534 | if (iwl_mvm_is_radio_killed(mvm)) { |
480 | ieee80211_scan_completed(mvm->hw, true); | 535 | ieee80211_scan_completed(mvm->hw, true); |
481 | iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); | 536 | iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); |
482 | mvm->scan_status = IWL_MVM_SCAN_NONE; | 537 | mvm->scan_status = IWL_MVM_SCAN_NONE; |
483 | return; | 538 | return 0; |
484 | } | 539 | } |
485 | 540 | ||
486 | iwl_init_notification_wait(&mvm->notif_wait, &wait_scan_abort, | 541 | iwl_init_notification_wait(&mvm->notif_wait, &wait_scan_abort, |
@@ -495,14 +550,11 @@ void iwl_mvm_cancel_scan(struct iwl_mvm *mvm) | |||
495 | goto out_remove_notif; | 550 | goto out_remove_notif; |
496 | } | 551 | } |
497 | 552 | ||
498 | ret = iwl_wait_notification(&mvm->notif_wait, &wait_scan_abort, 1 * HZ); | 553 | return iwl_wait_notification(&mvm->notif_wait, &wait_scan_abort, HZ); |
499 | if (ret) | ||
500 | IWL_ERR(mvm, "%s - failed on timeout\n", __func__); | ||
501 | |||
502 | return; | ||
503 | 554 | ||
504 | out_remove_notif: | 555 | out_remove_notif: |
505 | iwl_remove_notification(&mvm->notif_wait, &wait_scan_abort); | 556 | iwl_remove_notification(&mvm->notif_wait, &wait_scan_abort); |
557 | return ret; | ||
506 | } | 558 | } |
507 | 559 | ||
508 | int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm, | 560 | int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm, |
@@ -519,10 +571,11 @@ int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm, | |||
519 | scan_notif->status == IWL_SCAN_OFFLOAD_COMPLETED ? | 571 | scan_notif->status == IWL_SCAN_OFFLOAD_COMPLETED ? |
520 | "completed" : "aborted"); | 572 | "completed" : "aborted"); |
521 | 573 | ||
522 | /* might already be something else again, don't reset if so */ | 574 | /* only call mac80211 completion if the stop was initiated by FW */ |
523 | if (mvm->scan_status == IWL_MVM_SCAN_SCHED) | 575 | if (mvm->scan_status == IWL_MVM_SCAN_SCHED) { |
524 | mvm->scan_status = IWL_MVM_SCAN_NONE; | 576 | mvm->scan_status = IWL_MVM_SCAN_NONE; |
525 | ieee80211_sched_scan_stopped(mvm->hw); | 577 | ieee80211_sched_scan_stopped(mvm->hw); |
578 | } | ||
526 | 579 | ||
527 | return 0; | 580 | return 0; |
528 | } | 581 | } |
@@ -553,14 +606,9 @@ static void iwl_scan_offload_build_tx_cmd(struct iwl_mvm *mvm, | |||
553 | static void iwl_build_scan_cmd(struct iwl_mvm *mvm, | 606 | static void iwl_build_scan_cmd(struct iwl_mvm *mvm, |
554 | struct ieee80211_vif *vif, | 607 | struct ieee80211_vif *vif, |
555 | struct cfg80211_sched_scan_request *req, | 608 | struct cfg80211_sched_scan_request *req, |
556 | struct iwl_scan_offload_cmd *scan) | 609 | struct iwl_scan_offload_cmd *scan, |
610 | struct iwl_mvm_scan_params *params) | ||
557 | { | 611 | { |
558 | bool is_assoc = false; | ||
559 | |||
560 | ieee80211_iterate_active_interfaces_atomic(mvm->hw, | ||
561 | IEEE80211_IFACE_ITER_NORMAL, | ||
562 | iwl_mvm_vif_assoc_iterator, | ||
563 | &is_assoc); | ||
564 | scan->channel_count = | 612 | scan->channel_count = |
565 | mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels + | 613 | mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels + |
566 | mvm->nvm_data->bands[IEEE80211_BAND_5GHZ].n_channels; | 614 | mvm->nvm_data->bands[IEEE80211_BAND_5GHZ].n_channels; |
@@ -568,13 +616,17 @@ static void iwl_build_scan_cmd(struct iwl_mvm *mvm, | |||
568 | scan->quiet_plcp_th = cpu_to_le16(IWL_PLCP_QUIET_THRESH); | 616 | scan->quiet_plcp_th = cpu_to_le16(IWL_PLCP_QUIET_THRESH); |
569 | scan->good_CRC_th = IWL_GOOD_CRC_TH_DEFAULT; | 617 | scan->good_CRC_th = IWL_GOOD_CRC_TH_DEFAULT; |
570 | scan->rx_chain = iwl_mvm_scan_rx_chain(mvm); | 618 | scan->rx_chain = iwl_mvm_scan_rx_chain(mvm); |
571 | scan->max_out_time = iwl_mvm_scan_max_out_time(vif, req->flags, | 619 | |
572 | is_assoc); | 620 | scan->max_out_time = cpu_to_le32(params->max_out_time); |
573 | scan->suspend_time = iwl_mvm_scan_suspend_time(vif, is_assoc); | 621 | scan->suspend_time = cpu_to_le32(params->suspend_time); |
622 | |||
574 | scan->filter_flags |= cpu_to_le32(MAC_FILTER_ACCEPT_GRP | | 623 | scan->filter_flags |= cpu_to_le32(MAC_FILTER_ACCEPT_GRP | |
575 | MAC_FILTER_IN_BEACON); | 624 | MAC_FILTER_IN_BEACON); |
576 | scan->scan_type = cpu_to_le32(SCAN_TYPE_BACKGROUND); | 625 | scan->scan_type = cpu_to_le32(SCAN_TYPE_BACKGROUND); |
577 | scan->rep_count = cpu_to_le32(1); | 626 | scan->rep_count = cpu_to_le32(1); |
627 | |||
628 | if (params->passive_fragmented) | ||
629 | scan->scan_flags |= SCAN_FLAGS_FRAGMENTED_SCAN; | ||
578 | } | 630 | } |
579 | 631 | ||
580 | static int iwl_ssid_exist(u8 *ssid, u8 ssid_len, struct iwl_ssid_ie *ssid_list) | 632 | static int iwl_ssid_exist(u8 *ssid, u8 ssid_len, struct iwl_ssid_ie *ssid_list) |
@@ -639,12 +691,11 @@ static void iwl_build_channel_cfg(struct iwl_mvm *mvm, | |||
639 | struct iwl_scan_channel_cfg *channels, | 691 | struct iwl_scan_channel_cfg *channels, |
640 | enum ieee80211_band band, | 692 | enum ieee80211_band band, |
641 | int *head, int *tail, | 693 | int *head, int *tail, |
642 | u32 ssid_bitmap) | 694 | u32 ssid_bitmap, |
695 | struct iwl_mvm_scan_params *params) | ||
643 | { | 696 | { |
644 | struct ieee80211_supported_band *s_band; | 697 | struct ieee80211_supported_band *s_band; |
645 | int n_probes = req->n_ssids; | ||
646 | int n_channels = req->n_channels; | 698 | int n_channels = req->n_channels; |
647 | u8 active_dwell, passive_dwell; | ||
648 | int i, j, index = 0; | 699 | int i, j, index = 0; |
649 | bool partial; | 700 | bool partial; |
650 | 701 | ||
@@ -654,8 +705,6 @@ static void iwl_build_channel_cfg(struct iwl_mvm *mvm, | |||
654 | * to scan. So add requested channels to head of the list and others to | 705 | * to scan. So add requested channels to head of the list and others to |
655 | * the end. | 706 | * the end. |
656 | */ | 707 | */ |
657 | active_dwell = iwl_mvm_get_active_dwell(band, n_probes); | ||
658 | passive_dwell = iwl_mvm_get_passive_dwell(band); | ||
659 | s_band = &mvm->nvm_data->bands[band]; | 708 | s_band = &mvm->nvm_data->bands[band]; |
660 | 709 | ||
661 | for (i = 0; i < s_band->n_channels && *head <= *tail; i++) { | 710 | for (i = 0; i < s_band->n_channels && *head <= *tail; i++) { |
@@ -679,8 +728,8 @@ static void iwl_build_channel_cfg(struct iwl_mvm *mvm, | |||
679 | channels->channel_number[index] = | 728 | channels->channel_number[index] = |
680 | cpu_to_le16(ieee80211_frequency_to_channel( | 729 | cpu_to_le16(ieee80211_frequency_to_channel( |
681 | s_band->channels[i].center_freq)); | 730 | s_band->channels[i].center_freq)); |
682 | channels->dwell_time[index][0] = active_dwell; | 731 | channels->dwell_time[index][0] = params->dwell[band].active; |
683 | channels->dwell_time[index][1] = passive_dwell; | 732 | channels->dwell_time[index][1] = params->dwell[band].passive; |
684 | 733 | ||
685 | channels->iter_count[index] = cpu_to_le16(1); | 734 | channels->iter_count[index] = cpu_to_le16(1); |
686 | channels->iter_interval[index] = 0; | 735 | channels->iter_interval[index] = 0; |
@@ -709,7 +758,6 @@ int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm, | |||
709 | struct cfg80211_sched_scan_request *req, | 758 | struct cfg80211_sched_scan_request *req, |
710 | struct ieee80211_sched_scan_ies *ies) | 759 | struct ieee80211_sched_scan_ies *ies) |
711 | { | 760 | { |
712 | int supported_bands = 0; | ||
713 | int band_2ghz = mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels; | 761 | int band_2ghz = mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels; |
714 | int band_5ghz = mvm->nvm_data->bands[IEEE80211_BAND_5GHZ].n_channels; | 762 | int band_5ghz = mvm->nvm_data->bands[IEEE80211_BAND_5GHZ].n_channels; |
715 | int head = 0; | 763 | int head = 0; |
@@ -723,22 +771,19 @@ int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm, | |||
723 | .id = SCAN_OFFLOAD_CONFIG_CMD, | 771 | .id = SCAN_OFFLOAD_CONFIG_CMD, |
724 | .flags = CMD_SYNC, | 772 | .flags = CMD_SYNC, |
725 | }; | 773 | }; |
774 | struct iwl_mvm_scan_params params = {}; | ||
726 | 775 | ||
727 | lockdep_assert_held(&mvm->mutex); | 776 | lockdep_assert_held(&mvm->mutex); |
728 | 777 | ||
729 | if (band_2ghz) | ||
730 | supported_bands++; | ||
731 | if (band_5ghz) | ||
732 | supported_bands++; | ||
733 | |||
734 | cmd_len = sizeof(struct iwl_scan_offload_cfg) + | 778 | cmd_len = sizeof(struct iwl_scan_offload_cfg) + |
735 | supported_bands * SCAN_OFFLOAD_PROBE_REQ_SIZE; | 779 | 2 * SCAN_OFFLOAD_PROBE_REQ_SIZE; |
736 | 780 | ||
737 | scan_cfg = kzalloc(cmd_len, GFP_KERNEL); | 781 | scan_cfg = kzalloc(cmd_len, GFP_KERNEL); |
738 | if (!scan_cfg) | 782 | if (!scan_cfg) |
739 | return -ENOMEM; | 783 | return -ENOMEM; |
740 | 784 | ||
741 | iwl_build_scan_cmd(mvm, vif, req, &scan_cfg->scan_cmd); | 785 | iwl_mvm_scan_calc_params(mvm, vif, req->n_ssids, ¶ms); |
786 | iwl_build_scan_cmd(mvm, vif, req, &scan_cfg->scan_cmd, ¶ms); | ||
742 | scan_cfg->scan_cmd.len = cpu_to_le16(cmd_len); | 787 | scan_cfg->scan_cmd.len = cpu_to_le16(cmd_len); |
743 | 788 | ||
744 | iwl_scan_offload_build_ssid(req, &scan_cfg->scan_cmd, &ssid_bitmap); | 789 | iwl_scan_offload_build_ssid(req, &scan_cfg->scan_cmd, &ssid_bitmap); |
@@ -750,7 +795,7 @@ int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm, | |||
750 | scan_cfg->data); | 795 | scan_cfg->data); |
751 | iwl_build_channel_cfg(mvm, req, &scan_cfg->channel_cfg, | 796 | iwl_build_channel_cfg(mvm, req, &scan_cfg->channel_cfg, |
752 | IEEE80211_BAND_2GHZ, &head, &tail, | 797 | IEEE80211_BAND_2GHZ, &head, &tail, |
753 | ssid_bitmap); | 798 | ssid_bitmap, ¶ms); |
754 | } | 799 | } |
755 | if (band_5ghz) { | 800 | if (band_5ghz) { |
756 | iwl_scan_offload_build_tx_cmd(mvm, vif, ies, | 801 | iwl_scan_offload_build_tx_cmd(mvm, vif, ies, |
@@ -760,7 +805,7 @@ int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm, | |||
760 | SCAN_OFFLOAD_PROBE_REQ_SIZE); | 805 | SCAN_OFFLOAD_PROBE_REQ_SIZE); |
761 | iwl_build_channel_cfg(mvm, req, &scan_cfg->channel_cfg, | 806 | iwl_build_channel_cfg(mvm, req, &scan_cfg->channel_cfg, |
762 | IEEE80211_BAND_5GHZ, &head, &tail, | 807 | IEEE80211_BAND_5GHZ, &head, &tail, |
763 | ssid_bitmap); | 808 | ssid_bitmap, ¶ms); |
764 | } | 809 | } |
765 | 810 | ||
766 | cmd.data[0] = scan_cfg; | 811 | cmd.data[0] = scan_cfg; |
@@ -900,26 +945,49 @@ static int iwl_mvm_send_sched_scan_abort(struct iwl_mvm *mvm) | |||
900 | * microcode has notified us that a scan is completed. | 945 | * microcode has notified us that a scan is completed. |
901 | */ | 946 | */ |
902 | IWL_DEBUG_SCAN(mvm, "SCAN OFFLOAD ABORT ret %d.\n", status); | 947 | IWL_DEBUG_SCAN(mvm, "SCAN OFFLOAD ABORT ret %d.\n", status); |
903 | ret = -EIO; | 948 | ret = -ENOENT; |
904 | } | 949 | } |
905 | 950 | ||
906 | return ret; | 951 | return ret; |
907 | } | 952 | } |
908 | 953 | ||
909 | void iwl_mvm_sched_scan_stop(struct iwl_mvm *mvm) | 954 | int iwl_mvm_sched_scan_stop(struct iwl_mvm *mvm) |
910 | { | 955 | { |
911 | int ret; | 956 | int ret; |
957 | struct iwl_notification_wait wait_scan_done; | ||
958 | static const u8 scan_done_notif[] = { SCAN_OFFLOAD_COMPLETE, }; | ||
912 | 959 | ||
913 | lockdep_assert_held(&mvm->mutex); | 960 | lockdep_assert_held(&mvm->mutex); |
914 | 961 | ||
915 | if (mvm->scan_status != IWL_MVM_SCAN_SCHED) { | 962 | if (mvm->scan_status != IWL_MVM_SCAN_SCHED) { |
916 | IWL_DEBUG_SCAN(mvm, "No offloaded scan to stop\n"); | 963 | IWL_DEBUG_SCAN(mvm, "No offloaded scan to stop\n"); |
917 | return; | 964 | return 0; |
918 | } | 965 | } |
919 | 966 | ||
967 | iwl_init_notification_wait(&mvm->notif_wait, &wait_scan_done, | ||
968 | scan_done_notif, | ||
969 | ARRAY_SIZE(scan_done_notif), | ||
970 | NULL, NULL); | ||
971 | |||
920 | ret = iwl_mvm_send_sched_scan_abort(mvm); | 972 | ret = iwl_mvm_send_sched_scan_abort(mvm); |
921 | if (ret) | 973 | if (ret) { |
922 | IWL_DEBUG_SCAN(mvm, "Send stop offload scan failed %d\n", ret); | 974 | IWL_DEBUG_SCAN(mvm, "Send stop offload scan failed %d\n", ret); |
923 | else | 975 | iwl_remove_notification(&mvm->notif_wait, &wait_scan_done); |
924 | IWL_DEBUG_SCAN(mvm, "Successfully sent stop offload scan\n"); | 976 | return ret; |
977 | } | ||
978 | |||
979 | IWL_DEBUG_SCAN(mvm, "Successfully sent stop offload scan\n"); | ||
980 | |||
981 | ret = iwl_wait_notification(&mvm->notif_wait, &wait_scan_done, 1 * HZ); | ||
982 | if (ret) | ||
983 | return ret; | ||
984 | |||
985 | /* | ||
986 | * Clear the scan status so the next scan requests will succeed. This | ||
987 | * also ensures the Rx handler doesn't do anything, as the scan was | ||
988 | * stopped from above. | ||
989 | */ | ||
990 | mvm->scan_status = IWL_MVM_SCAN_NONE; | ||
991 | |||
992 | return 0; | ||
925 | } | 993 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index 2677d1c0e1a1..f339ef884250 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c | |||
@@ -851,7 +851,7 @@ static int iwl_mvm_sta_tx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
851 | return ret; | 851 | return ret; |
852 | } | 852 | } |
853 | 853 | ||
854 | static const u8 tid_to_mac80211_ac[] = { | 854 | const u8 tid_to_mac80211_ac[] = { |
855 | IEEE80211_AC_BE, | 855 | IEEE80211_AC_BE, |
856 | IEEE80211_AC_BK, | 856 | IEEE80211_AC_BK, |
857 | IEEE80211_AC_BK, | 857 | IEEE80211_AC_BK, |
@@ -902,10 +902,18 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
902 | return -EIO; | 902 | return -EIO; |
903 | } | 903 | } |
904 | 904 | ||
905 | spin_lock_bh(&mvmsta->lock); | ||
906 | |||
907 | /* possible race condition - we entered D0i3 while starting agg */ | ||
908 | if (test_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status)) { | ||
909 | spin_unlock_bh(&mvmsta->lock); | ||
910 | IWL_ERR(mvm, "Entered D0i3 while starting Tx agg\n"); | ||
911 | return -EIO; | ||
912 | } | ||
913 | |||
905 | /* the new tx queue is still connected to the same mac80211 queue */ | 914 | /* the new tx queue is still connected to the same mac80211 queue */ |
906 | mvm->queue_to_mac80211[txq_id] = vif->hw_queue[tid_to_mac80211_ac[tid]]; | 915 | mvm->queue_to_mac80211[txq_id] = vif->hw_queue[tid_to_mac80211_ac[tid]]; |
907 | 916 | ||
908 | spin_lock_bh(&mvmsta->lock); | ||
909 | tid_data = &mvmsta->tid_data[tid]; | 917 | tid_data = &mvmsta->tid_data[tid]; |
910 | tid_data->ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number); | 918 | tid_data->ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number); |
911 | tid_data->txq_id = txq_id; | 919 | tid_data->txq_id = txq_id; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index 0ba96654d2c3..879aeac46cc1 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c | |||
@@ -79,6 +79,7 @@ static void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
79 | __le16 fc = hdr->frame_control; | 79 | __le16 fc = hdr->frame_control; |
80 | u32 tx_flags = le32_to_cpu(tx_cmd->tx_flags); | 80 | u32 tx_flags = le32_to_cpu(tx_cmd->tx_flags); |
81 | u32 len = skb->len + FCS_LEN; | 81 | u32 len = skb->len + FCS_LEN; |
82 | u8 ac; | ||
82 | 83 | ||
83 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) | 84 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) |
84 | tx_flags |= TX_CMD_FLG_ACK; | 85 | tx_flags |= TX_CMD_FLG_ACK; |
@@ -90,13 +91,6 @@ static void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
90 | else if (ieee80211_is_back_req(fc)) | 91 | else if (ieee80211_is_back_req(fc)) |
91 | tx_flags |= TX_CMD_FLG_ACK | TX_CMD_FLG_BAR; | 92 | tx_flags |= TX_CMD_FLG_ACK | TX_CMD_FLG_BAR; |
92 | 93 | ||
93 | /* High prio packet (wrt. BT coex) if it is EAPOL, MCAST or MGMT */ | ||
94 | if (info->band == IEEE80211_BAND_2GHZ && | ||
95 | (info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO || | ||
96 | is_multicast_ether_addr(hdr->addr1) || | ||
97 | ieee80211_is_back_req(fc) || ieee80211_is_mgmt(fc))) | ||
98 | tx_flags |= TX_CMD_FLG_BT_DIS; | ||
99 | |||
100 | if (ieee80211_has_morefrags(fc)) | 94 | if (ieee80211_has_morefrags(fc)) |
101 | tx_flags |= TX_CMD_FLG_MORE_FRAG; | 95 | tx_flags |= TX_CMD_FLG_MORE_FRAG; |
102 | 96 | ||
@@ -112,6 +106,11 @@ static void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
112 | tx_flags &= ~TX_CMD_FLG_SEQ_CTL; | 106 | tx_flags &= ~TX_CMD_FLG_SEQ_CTL; |
113 | } | 107 | } |
114 | 108 | ||
109 | /* tid_tspec will default to 0 = BE when QOS isn't enabled */ | ||
110 | ac = tid_to_mac80211_ac[tx_cmd->tid_tspec]; | ||
111 | tx_flags |= iwl_mvm_bt_coex_tx_prio(mvm, hdr, info, ac) << | ||
112 | TX_CMD_FLG_BT_PRIO_POS; | ||
113 | |||
115 | if (ieee80211_is_mgmt(fc)) { | 114 | if (ieee80211_is_mgmt(fc)) { |
116 | if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc)) | 115 | if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc)) |
117 | tx_cmd->pm_frame_timeout = cpu_to_le16(3); | 116 | tx_cmd->pm_frame_timeout = cpu_to_le16(3); |
@@ -128,9 +127,6 @@ static void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
128 | tx_cmd->pm_frame_timeout = 0; | 127 | tx_cmd->pm_frame_timeout = 0; |
129 | } | 128 | } |
130 | 129 | ||
131 | if (info->flags & IEEE80211_TX_CTL_AMPDU) | ||
132 | tx_flags |= TX_CMD_FLG_PROT_REQUIRE; | ||
133 | |||
134 | if (ieee80211_is_data(fc) && len > mvm->rts_threshold && | 130 | if (ieee80211_is_data(fc) && len > mvm->rts_threshold && |
135 | !is_multicast_ether_addr(ieee80211_get_DA(hdr))) | 131 | !is_multicast_ether_addr(ieee80211_get_DA(hdr))) |
136 | tx_flags |= TX_CMD_FLG_PROT_REQUIRE; | 132 | tx_flags |= TX_CMD_FLG_PROT_REQUIRE; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c index bbfe529d7b64..d619851745a1 100644 --- a/drivers/net/wireless/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/iwlwifi/mvm/utils.c | |||
@@ -516,33 +516,26 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm) | |||
516 | iwl_mvm_dump_umac_error_log(mvm); | 516 | iwl_mvm_dump_umac_error_log(mvm); |
517 | } | 517 | } |
518 | 518 | ||
519 | void iwl_mvm_dump_sram(struct iwl_mvm *mvm) | 519 | void iwl_mvm_fw_error_sram_dump(struct iwl_mvm *mvm) |
520 | { | 520 | { |
521 | const struct fw_img *img; | 521 | const struct fw_img *img; |
522 | int ofs, len = 0; | 522 | u32 ofs, sram_len; |
523 | int i; | 523 | void *sram; |
524 | __le32 *buf; | ||
525 | 524 | ||
526 | if (!mvm->ucode_loaded) | 525 | if (!mvm->ucode_loaded || mvm->fw_error_sram) |
527 | return; | 526 | return; |
528 | 527 | ||
529 | img = &mvm->fw->img[mvm->cur_ucode]; | 528 | img = &mvm->fw->img[mvm->cur_ucode]; |
530 | ofs = img->sec[IWL_UCODE_SECTION_DATA].offset; | 529 | ofs = img->sec[IWL_UCODE_SECTION_DATA].offset; |
531 | len = img->sec[IWL_UCODE_SECTION_DATA].len; | 530 | sram_len = img->sec[IWL_UCODE_SECTION_DATA].len; |
532 | 531 | ||
533 | buf = kzalloc(len, GFP_ATOMIC); | 532 | sram = kzalloc(sram_len, GFP_ATOMIC); |
534 | if (!buf) | 533 | if (!sram) |
535 | return; | 534 | return; |
536 | 535 | ||
537 | iwl_trans_read_mem_bytes(mvm->trans, ofs, buf, len); | 536 | iwl_trans_read_mem_bytes(mvm->trans, ofs, sram, sram_len); |
538 | len = len >> 2; | 537 | mvm->fw_error_sram = sram; |
539 | for (i = 0; i < len; i++) { | 538 | mvm->fw_error_sram_len = sram_len; |
540 | IWL_ERR(mvm, "0x%08X\n", le32_to_cpu(buf[i])); | ||
541 | /* Add a small delay to let syslog catch up */ | ||
542 | udelay(10); | ||
543 | } | ||
544 | |||
545 | kfree(buf); | ||
546 | } | 539 | } |
547 | 540 | ||
548 | /** | 541 | /** |
@@ -619,6 +612,9 @@ int iwl_mvm_update_low_latency(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
619 | 612 | ||
620 | lockdep_assert_held(&mvm->mutex); | 613 | lockdep_assert_held(&mvm->mutex); |
621 | 614 | ||
615 | if (mvmvif->low_latency == value) | ||
616 | return 0; | ||
617 | |||
622 | mvmvif->low_latency = value; | 618 | mvmvif->low_latency = value; |
623 | 619 | ||
624 | res = iwl_mvm_update_quotas(mvm, NULL); | 620 | res = iwl_mvm_update_quotas(mvm, NULL); |
@@ -629,3 +625,22 @@ int iwl_mvm_update_low_latency(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
629 | 625 | ||
630 | return iwl_mvm_power_update_mac(mvm, vif); | 626 | return iwl_mvm_power_update_mac(mvm, vif); |
631 | } | 627 | } |
628 | |||
629 | static void iwl_mvm_ll_iter(void *_data, u8 *mac, struct ieee80211_vif *vif) | ||
630 | { | ||
631 | bool *result = _data; | ||
632 | |||
633 | if (iwl_mvm_vif_low_latency(iwl_mvm_vif_from_mac80211(vif))) | ||
634 | *result = true; | ||
635 | } | ||
636 | |||
637 | bool iwl_mvm_low_latency(struct iwl_mvm *mvm) | ||
638 | { | ||
639 | bool result = false; | ||
640 | |||
641 | ieee80211_iterate_active_interfaces_atomic( | ||
642 | mvm->hw, IEEE80211_IFACE_ITER_NORMAL, | ||
643 | iwl_mvm_ll_iter, &result); | ||
644 | |||
645 | return result; | ||
646 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c index 1f97631a82e4..edb015c99049 100644 --- a/drivers/net/wireless/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/iwlwifi/pcie/drv.c | |||
@@ -447,7 +447,8 @@ static void set_dflt_pwr_limit(struct iwl_trans *trans, struct pci_dev *pdev) | |||
447 | 447 | ||
448 | pxsx_handle = ACPI_HANDLE(&pdev->dev); | 448 | pxsx_handle = ACPI_HANDLE(&pdev->dev); |
449 | if (!pxsx_handle) { | 449 | if (!pxsx_handle) { |
450 | IWL_ERR(trans, "Could not retrieve root port ACPI handle"); | 450 | IWL_DEBUG_INFO(trans, |
451 | "Could not retrieve root port ACPI handle"); | ||
451 | return; | 452 | return; |
452 | } | 453 | } |
453 | 454 | ||
@@ -559,7 +560,7 @@ static int iwl_pci_resume(struct device *device) | |||
559 | iwl_enable_rfkill_int(trans); | 560 | iwl_enable_rfkill_int(trans); |
560 | 561 | ||
561 | hw_rfkill = iwl_is_rfkill_set(trans); | 562 | hw_rfkill = iwl_is_rfkill_set(trans); |
562 | iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); | 563 | iwl_trans_pcie_rf_kill(trans, hw_rfkill); |
563 | 564 | ||
564 | return 0; | 565 | return 0; |
565 | } | 566 | } |
diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h index 3120bc5bb12d..9091513ea738 100644 --- a/drivers/net/wireless/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/iwlwifi/pcie/internal.h | |||
@@ -488,4 +488,6 @@ static inline void __iwl_trans_pcie_set_bit(struct iwl_trans *trans, | |||
488 | __iwl_trans_pcie_set_bits_mask(trans, reg, mask, mask); | 488 | __iwl_trans_pcie_set_bits_mask(trans, reg, mask, mask); |
489 | } | 489 | } |
490 | 490 | ||
491 | void iwl_trans_pcie_rf_kill(struct iwl_trans *trans, bool state); | ||
492 | |||
491 | #endif /* __iwl_trans_int_pcie_h__ */ | 493 | #endif /* __iwl_trans_int_pcie_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c index cf49f6ce0ff8..fdfa3969cac9 100644 --- a/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/iwlwifi/pcie/rx.c | |||
@@ -994,7 +994,7 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id) | |||
994 | 994 | ||
995 | isr_stats->rfkill++; | 995 | isr_stats->rfkill++; |
996 | 996 | ||
997 | iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); | 997 | iwl_trans_pcie_rf_kill(trans, hw_rfkill); |
998 | if (hw_rfkill) { | 998 | if (hw_rfkill) { |
999 | set_bit(STATUS_RFKILL, &trans->status); | 999 | set_bit(STATUS_RFKILL, &trans->status); |
1000 | if (test_and_clear_bit(STATUS_SYNC_HCMD_ACTIVE, | 1000 | if (test_and_clear_bit(STATUS_SYNC_HCMD_ACTIVE, |
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index 84d471299e5a..dcfd6d866d09 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c | |||
@@ -75,6 +75,20 @@ | |||
75 | #include "iwl-agn-hw.h" | 75 | #include "iwl-agn-hw.h" |
76 | #include "internal.h" | 76 | #include "internal.h" |
77 | 77 | ||
78 | static u32 iwl_trans_pcie_read_shr(struct iwl_trans *trans, u32 reg) | ||
79 | { | ||
80 | iwl_write32(trans, HEEP_CTRL_WRD_PCIEX_CTRL_REG, | ||
81 | ((reg & 0x0000ffff) | (2 << 28))); | ||
82 | return iwl_read32(trans, HEEP_CTRL_WRD_PCIEX_DATA_REG); | ||
83 | } | ||
84 | |||
85 | static void iwl_trans_pcie_write_shr(struct iwl_trans *trans, u32 reg, u32 val) | ||
86 | { | ||
87 | iwl_write32(trans, HEEP_CTRL_WRD_PCIEX_DATA_REG, val); | ||
88 | iwl_write32(trans, HEEP_CTRL_WRD_PCIEX_CTRL_REG, | ||
89 | ((reg & 0x0000ffff) | (3 << 28))); | ||
90 | } | ||
91 | |||
78 | static void iwl_pcie_set_pwr(struct iwl_trans *trans, bool vaux) | 92 | static void iwl_pcie_set_pwr(struct iwl_trans *trans, bool vaux) |
79 | { | 93 | { |
80 | if (vaux && pci_pme_capable(to_pci_dev(trans->dev), PCI_D3cold)) | 94 | if (vaux && pci_pme_capable(to_pci_dev(trans->dev), PCI_D3cold)) |
@@ -229,6 +243,116 @@ out: | |||
229 | return ret; | 243 | return ret; |
230 | } | 244 | } |
231 | 245 | ||
246 | /* | ||
247 | * Enable LP XTAL to avoid HW bug where device may consume much power if | ||
248 | * FW is not loaded after device reset. LP XTAL is disabled by default | ||
249 | * after device HW reset. Do it only if XTAL is fed by internal source. | ||
250 | * Configure device's "persistence" mode to avoid resetting XTAL again when | ||
251 | * SHRD_HW_RST occurs in S3. | ||
252 | */ | ||
253 | static void iwl_pcie_apm_lp_xtal_enable(struct iwl_trans *trans) | ||
254 | { | ||
255 | int ret; | ||
256 | u32 apmg_gp1_reg; | ||
257 | u32 apmg_xtal_cfg_reg; | ||
258 | u32 dl_cfg_reg; | ||
259 | |||
260 | /* Force XTAL ON */ | ||
261 | __iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL, | ||
262 | CSR_GP_CNTRL_REG_FLAG_XTAL_ON); | ||
263 | |||
264 | /* Reset entire device - do controller reset (results in SHRD_HW_RST) */ | ||
265 | iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); | ||
266 | |||
267 | udelay(10); | ||
268 | |||
269 | /* | ||
270 | * Set "initialization complete" bit to move adapter from | ||
271 | * D0U* --> D0A* (powered-up active) state. | ||
272 | */ | ||
273 | iwl_set_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
274 | |||
275 | /* | ||
276 | * Wait for clock stabilization; once stabilized, access to | ||
277 | * device-internal resources is possible. | ||
278 | */ | ||
279 | ret = iwl_poll_bit(trans, CSR_GP_CNTRL, | ||
280 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||
281 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||
282 | 25000); | ||
283 | if (WARN_ON(ret < 0)) { | ||
284 | IWL_ERR(trans, "Access time out - failed to enable LP XTAL\n"); | ||
285 | /* Release XTAL ON request */ | ||
286 | __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, | ||
287 | CSR_GP_CNTRL_REG_FLAG_XTAL_ON); | ||
288 | return; | ||
289 | } | ||
290 | |||
291 | /* | ||
292 | * Clear "disable persistence" to avoid LP XTAL resetting when | ||
293 | * SHRD_HW_RST is applied in S3. | ||
294 | */ | ||
295 | iwl_clear_bits_prph(trans, APMG_PCIDEV_STT_REG, | ||
296 | APMG_PCIDEV_STT_VAL_PERSIST_DIS); | ||
297 | |||
298 | /* | ||
299 | * Force APMG XTAL to be active to prevent its disabling by HW | ||
300 | * caused by APMG idle state. | ||
301 | */ | ||
302 | apmg_xtal_cfg_reg = iwl_trans_pcie_read_shr(trans, | ||
303 | SHR_APMG_XTAL_CFG_REG); | ||
304 | iwl_trans_pcie_write_shr(trans, SHR_APMG_XTAL_CFG_REG, | ||
305 | apmg_xtal_cfg_reg | | ||
306 | SHR_APMG_XTAL_CFG_XTAL_ON_REQ); | ||
307 | |||
308 | /* | ||
309 | * Reset entire device again - do controller reset (results in | ||
310 | * SHRD_HW_RST). Turn MAC off before proceeding. | ||
311 | */ | ||
312 | iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); | ||
313 | |||
314 | udelay(10); | ||
315 | |||
316 | /* Enable LP XTAL by indirect access through CSR */ | ||
317 | apmg_gp1_reg = iwl_trans_pcie_read_shr(trans, SHR_APMG_GP1_REG); | ||
318 | iwl_trans_pcie_write_shr(trans, SHR_APMG_GP1_REG, apmg_gp1_reg | | ||
319 | SHR_APMG_GP1_WF_XTAL_LP_EN | | ||
320 | SHR_APMG_GP1_CHICKEN_BIT_SELECT); | ||
321 | |||
322 | /* Clear delay line clock power up */ | ||
323 | dl_cfg_reg = iwl_trans_pcie_read_shr(trans, SHR_APMG_DL_CFG_REG); | ||
324 | iwl_trans_pcie_write_shr(trans, SHR_APMG_DL_CFG_REG, dl_cfg_reg & | ||
325 | ~SHR_APMG_DL_CFG_DL_CLOCK_POWER_UP); | ||
326 | |||
327 | /* | ||
328 | * Enable persistence mode to avoid LP XTAL resetting when | ||
329 | * SHRD_HW_RST is applied in S3. | ||
330 | */ | ||
331 | iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, | ||
332 | CSR_HW_IF_CONFIG_REG_PERSIST_MODE); | ||
333 | |||
334 | /* | ||
335 | * Clear "initialization complete" bit to move adapter from | ||
336 | * D0A* (powered-up Active) --> D0U* (Uninitialized) state. | ||
337 | */ | ||
338 | iwl_clear_bit(trans, CSR_GP_CNTRL, | ||
339 | CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
340 | |||
341 | /* Activates XTAL resources monitor */ | ||
342 | __iwl_trans_pcie_set_bit(trans, CSR_MONITOR_CFG_REG, | ||
343 | CSR_MONITOR_XTAL_RESOURCES); | ||
344 | |||
345 | /* Release XTAL ON request */ | ||
346 | __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, | ||
347 | CSR_GP_CNTRL_REG_FLAG_XTAL_ON); | ||
348 | udelay(10); | ||
349 | |||
350 | /* Release APMG XTAL */ | ||
351 | iwl_trans_pcie_write_shr(trans, SHR_APMG_XTAL_CFG_REG, | ||
352 | apmg_xtal_cfg_reg & | ||
353 | ~SHR_APMG_XTAL_CFG_XTAL_ON_REQ); | ||
354 | } | ||
355 | |||
232 | static int iwl_pcie_apm_stop_master(struct iwl_trans *trans) | 356 | static int iwl_pcie_apm_stop_master(struct iwl_trans *trans) |
233 | { | 357 | { |
234 | int ret = 0; | 358 | int ret = 0; |
@@ -256,6 +380,11 @@ static void iwl_pcie_apm_stop(struct iwl_trans *trans) | |||
256 | /* Stop device's DMA activity */ | 380 | /* Stop device's DMA activity */ |
257 | iwl_pcie_apm_stop_master(trans); | 381 | iwl_pcie_apm_stop_master(trans); |
258 | 382 | ||
383 | if (trans->cfg->lp_xtal_workaround) { | ||
384 | iwl_pcie_apm_lp_xtal_enable(trans); | ||
385 | return; | ||
386 | } | ||
387 | |||
259 | /* Reset the entire device */ | 388 | /* Reset the entire device */ |
260 | iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); | 389 | iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); |
261 | 390 | ||
@@ -641,7 +770,7 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, | |||
641 | set_bit(STATUS_RFKILL, &trans->status); | 770 | set_bit(STATUS_RFKILL, &trans->status); |
642 | else | 771 | else |
643 | clear_bit(STATUS_RFKILL, &trans->status); | 772 | clear_bit(STATUS_RFKILL, &trans->status); |
644 | iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); | 773 | iwl_trans_pcie_rf_kill(trans, hw_rfkill); |
645 | if (hw_rfkill && !run_in_rfkill) | 774 | if (hw_rfkill && !run_in_rfkill) |
646 | return -ERFKILL; | 775 | return -ERFKILL; |
647 | 776 | ||
@@ -756,7 +885,13 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) | |||
756 | else | 885 | else |
757 | clear_bit(STATUS_RFKILL, &trans->status); | 886 | clear_bit(STATUS_RFKILL, &trans->status); |
758 | if (hw_rfkill != was_hw_rfkill) | 887 | if (hw_rfkill != was_hw_rfkill) |
759 | iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); | 888 | iwl_trans_pcie_rf_kill(trans, hw_rfkill); |
889 | } | ||
890 | |||
891 | void iwl_trans_pcie_rf_kill(struct iwl_trans *trans, bool state) | ||
892 | { | ||
893 | if (iwl_op_mode_hw_rf_kill(trans->op_mode, state)) | ||
894 | iwl_trans_pcie_stop_device(trans); | ||
760 | } | 895 | } |
761 | 896 | ||
762 | static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test) | 897 | static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test) |
@@ -865,7 +1000,7 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans) | |||
865 | set_bit(STATUS_RFKILL, &trans->status); | 1000 | set_bit(STATUS_RFKILL, &trans->status); |
866 | else | 1001 | else |
867 | clear_bit(STATUS_RFKILL, &trans->status); | 1002 | clear_bit(STATUS_RFKILL, &trans->status); |
868 | iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); | 1003 | iwl_trans_pcie_rf_kill(trans, hw_rfkill); |
869 | 1004 | ||
870 | return 0; | 1005 | return 0; |
871 | } | 1006 | } |
@@ -1208,6 +1343,7 @@ static const char *get_csr_string(int cmd) | |||
1208 | IWL_CMD(CSR_GIO_CHICKEN_BITS); | 1343 | IWL_CMD(CSR_GIO_CHICKEN_BITS); |
1209 | IWL_CMD(CSR_ANA_PLL_CFG); | 1344 | IWL_CMD(CSR_ANA_PLL_CFG); |
1210 | IWL_CMD(CSR_HW_REV_WA_REG); | 1345 | IWL_CMD(CSR_HW_REV_WA_REG); |
1346 | IWL_CMD(CSR_MONITOR_STATUS_REG); | ||
1211 | IWL_CMD(CSR_DBG_HPET_MEM_REG); | 1347 | IWL_CMD(CSR_DBG_HPET_MEM_REG); |
1212 | default: | 1348 | default: |
1213 | return "UNKNOWN"; | 1349 | return "UNKNOWN"; |
@@ -1240,6 +1376,7 @@ void iwl_pcie_dump_csr(struct iwl_trans *trans) | |||
1240 | CSR_DRAM_INT_TBL_REG, | 1376 | CSR_DRAM_INT_TBL_REG, |
1241 | CSR_GIO_CHICKEN_BITS, | 1377 | CSR_GIO_CHICKEN_BITS, |
1242 | CSR_ANA_PLL_CFG, | 1378 | CSR_ANA_PLL_CFG, |
1379 | CSR_MONITOR_STATUS_REG, | ||
1243 | CSR_HW_REV_WA_REG, | 1380 | CSR_HW_REV_WA_REG, |
1244 | CSR_DBG_HPET_MEM_REG | 1381 | CSR_DBG_HPET_MEM_REG |
1245 | }; | 1382 | }; |
diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c index d9c65b60cd72..d14ead8beca8 100644 --- a/drivers/net/wireless/mwifiex/11n.c +++ b/drivers/net/wireless/mwifiex/11n.c | |||
@@ -159,28 +159,34 @@ int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv, | |||
159 | int tid; | 159 | int tid; |
160 | struct host_cmd_ds_11n_addba_rsp *add_ba_rsp = &resp->params.add_ba_rsp; | 160 | struct host_cmd_ds_11n_addba_rsp *add_ba_rsp = &resp->params.add_ba_rsp; |
161 | struct mwifiex_tx_ba_stream_tbl *tx_ba_tbl; | 161 | struct mwifiex_tx_ba_stream_tbl *tx_ba_tbl; |
162 | u16 block_ack_param_set = le16_to_cpu(add_ba_rsp->block_ack_param_set); | ||
162 | 163 | ||
163 | add_ba_rsp->ssn = cpu_to_le16((le16_to_cpu(add_ba_rsp->ssn)) | 164 | add_ba_rsp->ssn = cpu_to_le16((le16_to_cpu(add_ba_rsp->ssn)) |
164 | & SSN_MASK); | 165 | & SSN_MASK); |
165 | 166 | ||
166 | tid = (le16_to_cpu(add_ba_rsp->block_ack_param_set) | 167 | tid = (block_ack_param_set & IEEE80211_ADDBA_PARAM_TID_MASK) |
167 | & IEEE80211_ADDBA_PARAM_TID_MASK) | 168 | >> BLOCKACKPARAM_TID_POS; |
168 | >> BLOCKACKPARAM_TID_POS; | 169 | if (le16_to_cpu(add_ba_rsp->status_code) != BA_RESULT_SUCCESS) { |
169 | if (le16_to_cpu(add_ba_rsp->status_code) == BA_RESULT_SUCCESS) { | ||
170 | tx_ba_tbl = mwifiex_get_ba_tbl(priv, tid, | ||
171 | add_ba_rsp->peer_mac_addr); | ||
172 | if (tx_ba_tbl) { | ||
173 | dev_dbg(priv->adapter->dev, "info: BA stream complete\n"); | ||
174 | tx_ba_tbl->ba_status = BA_SETUP_COMPLETE; | ||
175 | } else { | ||
176 | dev_err(priv->adapter->dev, "BA stream not created\n"); | ||
177 | } | ||
178 | } else { | ||
179 | mwifiex_del_ba_tbl(priv, tid, add_ba_rsp->peer_mac_addr, | 170 | mwifiex_del_ba_tbl(priv, tid, add_ba_rsp->peer_mac_addr, |
180 | TYPE_DELBA_SENT, true); | 171 | TYPE_DELBA_SENT, true); |
181 | if (add_ba_rsp->add_rsp_result != BA_RESULT_TIMEOUT) | 172 | if (add_ba_rsp->add_rsp_result != BA_RESULT_TIMEOUT) |
182 | priv->aggr_prio_tbl[tid].ampdu_ap = | 173 | priv->aggr_prio_tbl[tid].ampdu_ap = |
183 | BA_STREAM_NOT_ALLOWED; | 174 | BA_STREAM_NOT_ALLOWED; |
175 | return 0; | ||
176 | } | ||
177 | |||
178 | tx_ba_tbl = mwifiex_get_ba_tbl(priv, tid, add_ba_rsp->peer_mac_addr); | ||
179 | if (tx_ba_tbl) { | ||
180 | dev_dbg(priv->adapter->dev, "info: BA stream complete\n"); | ||
181 | tx_ba_tbl->ba_status = BA_SETUP_COMPLETE; | ||
182 | if ((block_ack_param_set & BLOCKACKPARAM_AMSDU_SUPP_MASK) && | ||
183 | priv->add_ba_param.tx_amsdu && | ||
184 | (priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED)) | ||
185 | tx_ba_tbl->amsdu = true; | ||
186 | else | ||
187 | tx_ba_tbl->amsdu = false; | ||
188 | } else { | ||
189 | dev_err(priv->adapter->dev, "BA stream not created\n"); | ||
184 | } | 190 | } |
185 | 191 | ||
186 | return 0; | 192 | return 0; |
@@ -540,6 +546,7 @@ int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac) | |||
540 | u32 tx_win_size = priv->add_ba_param.tx_win_size; | 546 | u32 tx_win_size = priv->add_ba_param.tx_win_size; |
541 | static u8 dialog_tok; | 547 | static u8 dialog_tok; |
542 | int ret; | 548 | int ret; |
549 | u16 block_ack_param_set; | ||
543 | 550 | ||
544 | dev_dbg(priv->adapter->dev, "cmd: %s: tid %d\n", __func__, tid); | 551 | dev_dbg(priv->adapter->dev, "cmd: %s: tid %d\n", __func__, tid); |
545 | 552 | ||
@@ -558,10 +565,16 @@ int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac) | |||
558 | tx_win_size = MWIFIEX_11AC_STA_AMPDU_DEF_TXWINSIZE; | 565 | tx_win_size = MWIFIEX_11AC_STA_AMPDU_DEF_TXWINSIZE; |
559 | } | 566 | } |
560 | 567 | ||
561 | add_ba_req.block_ack_param_set = cpu_to_le16( | 568 | block_ack_param_set = (u16)((tid << BLOCKACKPARAM_TID_POS) | |
562 | (u16) ((tid << BLOCKACKPARAM_TID_POS) | | 569 | tx_win_size << BLOCKACKPARAM_WINSIZE_POS | |
563 | tx_win_size << BLOCKACKPARAM_WINSIZE_POS | | 570 | IMMEDIATE_BLOCK_ACK); |
564 | IMMEDIATE_BLOCK_ACK)); | 571 | |
572 | /* enable AMSDU inside AMPDU */ | ||
573 | if (priv->add_ba_param.tx_amsdu && | ||
574 | (priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED)) | ||
575 | block_ack_param_set |= BLOCKACKPARAM_AMSDU_SUPP_MASK; | ||
576 | |||
577 | add_ba_req.block_ack_param_set = cpu_to_le16(block_ack_param_set); | ||
565 | add_ba_req.block_ack_tmo = cpu_to_le16((u16)priv->add_ba_param.timeout); | 578 | add_ba_req.block_ack_tmo = cpu_to_le16((u16)priv->add_ba_param.timeout); |
566 | 579 | ||
567 | ++dialog_tok; | 580 | ++dialog_tok; |
@@ -676,6 +689,7 @@ int mwifiex_get_tx_ba_stream_tbl(struct mwifiex_private *priv, | |||
676 | dev_dbg(priv->adapter->dev, "data: %s tid=%d\n", | 689 | dev_dbg(priv->adapter->dev, "data: %s tid=%d\n", |
677 | __func__, rx_reo_tbl->tid); | 690 | __func__, rx_reo_tbl->tid); |
678 | memcpy(rx_reo_tbl->ra, tx_ba_tsr_tbl->ra, ETH_ALEN); | 691 | memcpy(rx_reo_tbl->ra, tx_ba_tsr_tbl->ra, ETH_ALEN); |
692 | rx_reo_tbl->amsdu = tx_ba_tsr_tbl->amsdu; | ||
679 | rx_reo_tbl++; | 693 | rx_reo_tbl++; |
680 | count++; | 694 | count++; |
681 | if (count >= MWIFIEX_MAX_TX_BASTREAM_SUPPORTED) | 695 | if (count >= MWIFIEX_MAX_TX_BASTREAM_SUPPORTED) |
@@ -731,5 +745,8 @@ void mwifiex_set_ba_params(struct mwifiex_private *priv) | |||
731 | MWIFIEX_STA_AMPDU_DEF_RXWINSIZE; | 745 | MWIFIEX_STA_AMPDU_DEF_RXWINSIZE; |
732 | } | 746 | } |
733 | 747 | ||
748 | priv->add_ba_param.tx_amsdu = true; | ||
749 | priv->add_ba_param.rx_amsdu = true; | ||
750 | |||
734 | return; | 751 | return; |
735 | } | 752 | } |
diff --git a/drivers/net/wireless/mwifiex/11n.h b/drivers/net/wireless/mwifiex/11n.h index 12bb6acbdd58..40b007a00f4b 100644 --- a/drivers/net/wireless/mwifiex/11n.h +++ b/drivers/net/wireless/mwifiex/11n.h | |||
@@ -76,6 +76,20 @@ mwifiex_is_station_ampdu_allowed(struct mwifiex_private *priv, | |||
76 | return (node->ampdu_sta[tid] != BA_STREAM_NOT_ALLOWED) ? true : false; | 76 | return (node->ampdu_sta[tid] != BA_STREAM_NOT_ALLOWED) ? true : false; |
77 | } | 77 | } |
78 | 78 | ||
79 | /* This function checks whether AMSDU is allowed for BA stream. */ | ||
80 | static inline u8 | ||
81 | mwifiex_is_amsdu_in_ampdu_allowed(struct mwifiex_private *priv, | ||
82 | struct mwifiex_ra_list_tbl *ptr, int tid) | ||
83 | { | ||
84 | struct mwifiex_tx_ba_stream_tbl *tx_tbl; | ||
85 | |||
86 | tx_tbl = mwifiex_get_ba_tbl(priv, tid, ptr->ra); | ||
87 | if (tx_tbl) | ||
88 | return tx_tbl->amsdu; | ||
89 | |||
90 | return false; | ||
91 | } | ||
92 | |||
79 | /* This function checks whether AMPDU is allowed or not for a particular TID. */ | 93 | /* This function checks whether AMPDU is allowed or not for a particular TID. */ |
80 | static inline u8 | 94 | static inline u8 |
81 | mwifiex_is_ampdu_allowed(struct mwifiex_private *priv, | 95 | mwifiex_is_ampdu_allowed(struct mwifiex_private *priv, |
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c index c3323c492614..0c3571f830b0 100644 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.c +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c | |||
@@ -26,6 +26,56 @@ | |||
26 | #include "11n.h" | 26 | #include "11n.h" |
27 | #include "11n_rxreorder.h" | 27 | #include "11n_rxreorder.h" |
28 | 28 | ||
29 | /* This function will dispatch amsdu packet and forward it to kernel/upper | ||
30 | * layer. | ||
31 | */ | ||
32 | static int mwifiex_11n_dispatch_amsdu_pkt(struct mwifiex_private *priv, | ||
33 | struct sk_buff *skb) | ||
34 | { | ||
35 | struct rxpd *local_rx_pd = (struct rxpd *)(skb->data); | ||
36 | int ret; | ||
37 | |||
38 | if (le16_to_cpu(local_rx_pd->rx_pkt_type) == PKT_TYPE_AMSDU) { | ||
39 | struct sk_buff_head list; | ||
40 | struct sk_buff *rx_skb; | ||
41 | |||
42 | __skb_queue_head_init(&list); | ||
43 | |||
44 | skb_pull(skb, le16_to_cpu(local_rx_pd->rx_pkt_offset)); | ||
45 | skb_trim(skb, le16_to_cpu(local_rx_pd->rx_pkt_length)); | ||
46 | |||
47 | ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr, | ||
48 | priv->wdev->iftype, 0, false); | ||
49 | |||
50 | while (!skb_queue_empty(&list)) { | ||
51 | rx_skb = __skb_dequeue(&list); | ||
52 | ret = mwifiex_recv_packet(priv, rx_skb); | ||
53 | if (ret == -1) | ||
54 | dev_err(priv->adapter->dev, | ||
55 | "Rx of A-MSDU failed"); | ||
56 | } | ||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | return -1; | ||
61 | } | ||
62 | |||
63 | /* This function will process the rx packet and forward it to kernel/upper | ||
64 | * layer. | ||
65 | */ | ||
66 | static int mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv, void *payload) | ||
67 | { | ||
68 | int ret = mwifiex_11n_dispatch_amsdu_pkt(priv, payload); | ||
69 | |||
70 | if (!ret) | ||
71 | return 0; | ||
72 | |||
73 | if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) | ||
74 | return mwifiex_handle_uap_rx_forward(priv, payload); | ||
75 | |||
76 | return mwifiex_process_rx_packet(priv, payload); | ||
77 | } | ||
78 | |||
29 | /* | 79 | /* |
30 | * This function dispatches all packets in the Rx reorder table until the | 80 | * This function dispatches all packets in the Rx reorder table until the |
31 | * start window. | 81 | * start window. |
@@ -35,8 +85,9 @@ | |||
35 | * circular buffer. | 85 | * circular buffer. |
36 | */ | 86 | */ |
37 | static void | 87 | static void |
38 | mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv, | 88 | mwifiex_11n_dispatch_pkt_until_start_win(struct mwifiex_private *priv, |
39 | struct mwifiex_rx_reorder_tbl *tbl, int start_win) | 89 | struct mwifiex_rx_reorder_tbl *tbl, |
90 | int start_win) | ||
40 | { | 91 | { |
41 | int pkt_to_send, i; | 92 | int pkt_to_send, i; |
42 | void *rx_tmp_ptr; | 93 | void *rx_tmp_ptr; |
@@ -54,12 +105,8 @@ mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv, | |||
54 | tbl->rx_reorder_ptr[i] = NULL; | 105 | tbl->rx_reorder_ptr[i] = NULL; |
55 | } | 106 | } |
56 | spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); | 107 | spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); |
57 | if (rx_tmp_ptr) { | 108 | if (rx_tmp_ptr) |
58 | if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) | 109 | mwifiex_11n_dispatch_pkt(priv, rx_tmp_ptr); |
59 | mwifiex_handle_uap_rx_forward(priv, rx_tmp_ptr); | ||
60 | else | ||
61 | mwifiex_process_rx_packet(priv, rx_tmp_ptr); | ||
62 | } | ||
63 | } | 110 | } |
64 | 111 | ||
65 | spin_lock_irqsave(&priv->rx_pkt_lock, flags); | 112 | spin_lock_irqsave(&priv->rx_pkt_lock, flags); |
@@ -101,11 +148,7 @@ mwifiex_11n_scan_and_dispatch(struct mwifiex_private *priv, | |||
101 | rx_tmp_ptr = tbl->rx_reorder_ptr[i]; | 148 | rx_tmp_ptr = tbl->rx_reorder_ptr[i]; |
102 | tbl->rx_reorder_ptr[i] = NULL; | 149 | tbl->rx_reorder_ptr[i] = NULL; |
103 | spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); | 150 | spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); |
104 | 151 | mwifiex_11n_dispatch_pkt(priv, rx_tmp_ptr); | |
105 | if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) | ||
106 | mwifiex_handle_uap_rx_forward(priv, rx_tmp_ptr); | ||
107 | else | ||
108 | mwifiex_process_rx_packet(priv, rx_tmp_ptr); | ||
109 | } | 152 | } |
110 | 153 | ||
111 | spin_lock_irqsave(&priv->rx_pkt_lock, flags); | 154 | spin_lock_irqsave(&priv->rx_pkt_lock, flags); |
@@ -135,12 +178,13 @@ mwifiex_del_rx_reorder_entry(struct mwifiex_private *priv, | |||
135 | struct mwifiex_rx_reorder_tbl *tbl) | 178 | struct mwifiex_rx_reorder_tbl *tbl) |
136 | { | 179 | { |
137 | unsigned long flags; | 180 | unsigned long flags; |
181 | int start_win; | ||
138 | 182 | ||
139 | if (!tbl) | 183 | if (!tbl) |
140 | return; | 184 | return; |
141 | 185 | ||
142 | mwifiex_11n_dispatch_pkt(priv, tbl, (tbl->start_win + tbl->win_size) & | 186 | start_win = (tbl->start_win + tbl->win_size) & (MAX_TID_VALUE - 1); |
143 | (MAX_TID_VALUE - 1)); | 187 | mwifiex_11n_dispatch_pkt_until_start_win(priv, tbl, start_win); |
144 | 188 | ||
145 | del_timer_sync(&tbl->timer_context.timer); | 189 | del_timer_sync(&tbl->timer_context.timer); |
146 | 190 | ||
@@ -228,17 +272,17 @@ mwifiex_flush_data(unsigned long context) | |||
228 | { | 272 | { |
229 | struct reorder_tmr_cnxt *ctx = | 273 | struct reorder_tmr_cnxt *ctx = |
230 | (struct reorder_tmr_cnxt *) context; | 274 | (struct reorder_tmr_cnxt *) context; |
231 | int start_win; | 275 | int start_win, seq_num; |
232 | 276 | ||
233 | start_win = mwifiex_11n_find_last_seq_num(ctx->ptr); | 277 | seq_num = mwifiex_11n_find_last_seq_num(ctx->ptr); |
234 | 278 | ||
235 | if (start_win < 0) | 279 | if (seq_num < 0) |
236 | return; | 280 | return; |
237 | 281 | ||
238 | dev_dbg(ctx->priv->adapter->dev, "info: flush data %d\n", start_win); | 282 | dev_dbg(ctx->priv->adapter->dev, "info: flush data %d\n", seq_num); |
239 | mwifiex_11n_dispatch_pkt(ctx->priv, ctx->ptr, | 283 | start_win = (ctx->ptr->start_win + seq_num + 1) & (MAX_TID_VALUE - 1); |
240 | (ctx->ptr->start_win + start_win + 1) & | 284 | mwifiex_11n_dispatch_pkt_until_start_win(ctx->priv, ctx->ptr, |
241 | (MAX_TID_VALUE - 1)); | 285 | start_win); |
242 | } | 286 | } |
243 | 287 | ||
244 | /* | 288 | /* |
@@ -267,7 +311,7 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta, | |||
267 | */ | 311 | */ |
268 | tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta); | 312 | tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta); |
269 | if (tbl) { | 313 | if (tbl) { |
270 | mwifiex_11n_dispatch_pkt(priv, tbl, seq_num); | 314 | mwifiex_11n_dispatch_pkt_until_start_win(priv, tbl, seq_num); |
271 | return; | 315 | return; |
272 | } | 316 | } |
273 | /* if !tbl then create one */ | 317 | /* if !tbl then create one */ |
@@ -401,8 +445,11 @@ int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv, | |||
401 | >> BLOCKACKPARAM_TID_POS; | 445 | >> BLOCKACKPARAM_TID_POS; |
402 | add_ba_rsp->status_code = cpu_to_le16(ADDBA_RSP_STATUS_ACCEPT); | 446 | add_ba_rsp->status_code = cpu_to_le16(ADDBA_RSP_STATUS_ACCEPT); |
403 | block_ack_param_set &= ~IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK; | 447 | block_ack_param_set &= ~IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK; |
404 | /* We donot support AMSDU inside AMPDU, hence reset the bit */ | 448 | |
405 | block_ack_param_set &= ~BLOCKACKPARAM_AMSDU_SUPP_MASK; | 449 | /* If we don't support AMSDU inside AMPDU, reset the bit */ |
450 | if (!priv->add_ba_param.rx_amsdu || | ||
451 | (priv->aggr_prio_tbl[tid].amsdu == BA_STREAM_NOT_ALLOWED)) | ||
452 | block_ack_param_set &= ~BLOCKACKPARAM_AMSDU_SUPP_MASK; | ||
406 | block_ack_param_set |= rx_win_size << BLOCKACKPARAM_WINSIZE_POS; | 453 | block_ack_param_set |= rx_win_size << BLOCKACKPARAM_WINSIZE_POS; |
407 | add_ba_rsp->block_ack_param_set = cpu_to_le16(block_ack_param_set); | 454 | add_ba_rsp->block_ack_param_set = cpu_to_le16(block_ack_param_set); |
408 | win_size = (le16_to_cpu(add_ba_rsp->block_ack_param_set) | 455 | win_size = (le16_to_cpu(add_ba_rsp->block_ack_param_set) |
@@ -459,14 +506,16 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv, | |||
459 | 506 | ||
460 | tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta); | 507 | tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta); |
461 | if (!tbl) { | 508 | if (!tbl) { |
462 | if (pkt_type != PKT_TYPE_BAR) { | 509 | if (pkt_type != PKT_TYPE_BAR) |
463 | if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) | 510 | mwifiex_11n_dispatch_pkt(priv, payload); |
464 | mwifiex_handle_uap_rx_forward(priv, payload); | ||
465 | else | ||
466 | mwifiex_process_rx_packet(priv, payload); | ||
467 | } | ||
468 | return 0; | 511 | return 0; |
469 | } | 512 | } |
513 | |||
514 | if ((pkt_type == PKT_TYPE_AMSDU) && !tbl->amsdu) { | ||
515 | mwifiex_11n_dispatch_pkt(priv, payload); | ||
516 | return 0; | ||
517 | } | ||
518 | |||
470 | start_win = tbl->start_win; | 519 | start_win = tbl->start_win; |
471 | win_size = tbl->win_size; | 520 | win_size = tbl->win_size; |
472 | end_win = ((start_win + win_size) - 1) & (MAX_TID_VALUE - 1); | 521 | end_win = ((start_win + win_size) - 1) & (MAX_TID_VALUE - 1); |
@@ -520,7 +569,7 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv, | |||
520 | start_win = (end_win - win_size) + 1; | 569 | start_win = (end_win - win_size) + 1; |
521 | else | 570 | else |
522 | start_win = (MAX_TID_VALUE - (win_size - seq_num)) + 1; | 571 | start_win = (MAX_TID_VALUE - (win_size - seq_num)) + 1; |
523 | mwifiex_11n_dispatch_pkt(priv, tbl, start_win); | 572 | mwifiex_11n_dispatch_pkt_until_start_win(priv, tbl, start_win); |
524 | } | 573 | } |
525 | 574 | ||
526 | if (pkt_type != PKT_TYPE_BAR) { | 575 | if (pkt_type != PKT_TYPE_BAR) { |
@@ -611,16 +660,7 @@ int mwifiex_ret_11n_addba_resp(struct mwifiex_private *priv, | |||
611 | * Check if we had rejected the ADDBA, if yes then do not create | 660 | * Check if we had rejected the ADDBA, if yes then do not create |
612 | * the stream | 661 | * the stream |
613 | */ | 662 | */ |
614 | if (le16_to_cpu(add_ba_rsp->status_code) == BA_RESULT_SUCCESS) { | 663 | if (le16_to_cpu(add_ba_rsp->status_code) != BA_RESULT_SUCCESS) { |
615 | win_size = (block_ack_param_set & | ||
616 | IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) | ||
617 | >> BLOCKACKPARAM_WINSIZE_POS; | ||
618 | |||
619 | dev_dbg(priv->adapter->dev, | ||
620 | "cmd: ADDBA RSP: %pM tid=%d ssn=%d win_size=%d\n", | ||
621 | add_ba_rsp->peer_mac_addr, tid, | ||
622 | add_ba_rsp->ssn, win_size); | ||
623 | } else { | ||
624 | dev_err(priv->adapter->dev, "ADDBA RSP: failed %pM tid=%d)\n", | 664 | dev_err(priv->adapter->dev, "ADDBA RSP: failed %pM tid=%d)\n", |
625 | add_ba_rsp->peer_mac_addr, tid); | 665 | add_ba_rsp->peer_mac_addr, tid); |
626 | 666 | ||
@@ -628,8 +668,28 @@ int mwifiex_ret_11n_addba_resp(struct mwifiex_private *priv, | |||
628 | add_ba_rsp->peer_mac_addr); | 668 | add_ba_rsp->peer_mac_addr); |
629 | if (tbl) | 669 | if (tbl) |
630 | mwifiex_del_rx_reorder_entry(priv, tbl); | 670 | mwifiex_del_rx_reorder_entry(priv, tbl); |
671 | |||
672 | return 0; | ||
631 | } | 673 | } |
632 | 674 | ||
675 | win_size = (block_ack_param_set & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) | ||
676 | >> BLOCKACKPARAM_WINSIZE_POS; | ||
677 | |||
678 | tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, | ||
679 | add_ba_rsp->peer_mac_addr); | ||
680 | if (tbl) { | ||
681 | if ((block_ack_param_set & BLOCKACKPARAM_AMSDU_SUPP_MASK) && | ||
682 | priv->add_ba_param.rx_amsdu && | ||
683 | (priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED)) | ||
684 | tbl->amsdu = true; | ||
685 | else | ||
686 | tbl->amsdu = false; | ||
687 | } | ||
688 | |||
689 | dev_dbg(priv->adapter->dev, | ||
690 | "cmd: ADDBA RSP: %pM tid=%d ssn=%d win_size=%d\n", | ||
691 | add_ba_rsp->peer_mac_addr, tid, add_ba_rsp->ssn, win_size); | ||
692 | |||
633 | return 0; | 693 | return 0; |
634 | } | 694 | } |
635 | 695 | ||
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 51ce99cfcfb9..21ee27ab7b74 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -1158,9 +1158,10 @@ static int mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy, | |||
1158 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | 1158 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); |
1159 | u16 bitmap_rates[MAX_BITMAP_RATES_SIZE]; | 1159 | u16 bitmap_rates[MAX_BITMAP_RATES_SIZE]; |
1160 | enum ieee80211_band band; | 1160 | enum ieee80211_band band; |
1161 | struct mwifiex_adapter *adapter = priv->adapter; | ||
1161 | 1162 | ||
1162 | if (!priv->media_connected) { | 1163 | if (!priv->media_connected) { |
1163 | dev_err(priv->adapter->dev, | 1164 | dev_err(adapter->dev, |
1164 | "Can not set Tx data rate in disconnected state\n"); | 1165 | "Can not set Tx data rate in disconnected state\n"); |
1165 | return -EINVAL; | 1166 | return -EINVAL; |
1166 | } | 1167 | } |
@@ -1181,9 +1182,16 @@ static int mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy, | |||
1181 | 1182 | ||
1182 | /* Fill HT MCS rates */ | 1183 | /* Fill HT MCS rates */ |
1183 | bitmap_rates[2] = mask->control[band].ht_mcs[0]; | 1184 | bitmap_rates[2] = mask->control[band].ht_mcs[0]; |
1184 | if (priv->adapter->hw_dev_mcs_support == HT_STREAM_2X2) | 1185 | if (adapter->hw_dev_mcs_support == HT_STREAM_2X2) |
1185 | bitmap_rates[2] |= mask->control[band].ht_mcs[1] << 8; | 1186 | bitmap_rates[2] |= mask->control[band].ht_mcs[1] << 8; |
1186 | 1187 | ||
1188 | /* Fill VHT MCS rates */ | ||
1189 | if (adapter->fw_api_ver == MWIFIEX_FW_V15) { | ||
1190 | bitmap_rates[10] = mask->control[band].vht_mcs[0]; | ||
1191 | if (adapter->hw_dev_mcs_support == HT_STREAM_2X2) | ||
1192 | bitmap_rates[11] = mask->control[band].vht_mcs[1]; | ||
1193 | } | ||
1194 | |||
1187 | return mwifiex_send_cmd(priv, HostCmd_CMD_TX_RATE_CFG, | 1195 | return mwifiex_send_cmd(priv, HostCmd_CMD_TX_RATE_CFG, |
1188 | HostCmd_ACT_GEN_SET, 0, bitmap_rates, true); | 1196 | HostCmd_ACT_GEN_SET, 0, bitmap_rates, true); |
1189 | } | 1197 | } |
@@ -2092,10 +2100,10 @@ mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info, | |||
2092 | else | 2100 | else |
2093 | ht_info->cap &= ~IEEE80211_HT_CAP_SGI_40; | 2101 | ht_info->cap &= ~IEEE80211_HT_CAP_SGI_40; |
2094 | 2102 | ||
2095 | if (ISSUPP_RXSTBC(adapter->hw_dot_11n_dev_cap)) | 2103 | if (adapter->user_dev_mcs_support == HT_STREAM_2X2) |
2096 | ht_info->cap |= 1 << IEEE80211_HT_CAP_RX_STBC_SHIFT; | 2104 | ht_info->cap |= 3 << IEEE80211_HT_CAP_RX_STBC_SHIFT; |
2097 | else | 2105 | else |
2098 | ht_info->cap &= ~(3 << IEEE80211_HT_CAP_RX_STBC_SHIFT); | 2106 | ht_info->cap |= 1 << IEEE80211_HT_CAP_RX_STBC_SHIFT; |
2099 | 2107 | ||
2100 | if (ISSUPP_TXSTBC(adapter->hw_dot_11n_dev_cap)) | 2108 | if (ISSUPP_TXSTBC(adapter->hw_dot_11n_dev_cap)) |
2101 | ht_info->cap |= IEEE80211_HT_CAP_TX_STBC; | 2109 | ht_info->cap |= IEEE80211_HT_CAP_TX_STBC; |
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index 14e05c9f4663..b41155829220 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c | |||
@@ -1502,6 +1502,7 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv, | |||
1502 | } | 1502 | } |
1503 | 1503 | ||
1504 | adapter->fw_release_number = le32_to_cpu(hw_spec->fw_release_number); | 1504 | adapter->fw_release_number = le32_to_cpu(hw_spec->fw_release_number); |
1505 | adapter->fw_api_ver = (adapter->fw_release_number >> 16) & 0xff; | ||
1505 | adapter->number_of_antenna = le16_to_cpu(hw_spec->number_of_antenna); | 1506 | adapter->number_of_antenna = le16_to_cpu(hw_spec->number_of_antenna); |
1506 | 1507 | ||
1507 | if (le32_to_cpu(hw_spec->dot_11ac_dev_cap)) { | 1508 | if (le32_to_cpu(hw_spec->dot_11ac_dev_cap)) { |
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 39cb3542f79c..b485dc1ae5eb 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h | |||
@@ -202,6 +202,11 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
202 | 202 | ||
203 | #define MWIFIEX_DEF_AMPDU IEEE80211_HT_AMPDU_PARM_FACTOR | 203 | #define MWIFIEX_DEF_AMPDU IEEE80211_HT_AMPDU_PARM_FACTOR |
204 | 204 | ||
205 | #define GET_RXSTBC(x) (x & IEEE80211_HT_CAP_RX_STBC) | ||
206 | #define MWIFIEX_RX_STBC1 0x0100 | ||
207 | #define MWIFIEX_RX_STBC12 0x0200 | ||
208 | #define MWIFIEX_RX_STBC123 0x0300 | ||
209 | |||
205 | /* dev_cap bitmap | 210 | /* dev_cap bitmap |
206 | * BIT | 211 | * BIT |
207 | * 0-16 reserved | 212 | * 0-16 reserved |
@@ -515,6 +520,8 @@ enum P2P_MODES { | |||
515 | #define ACT_TDLS_CREATE 0x01 | 520 | #define ACT_TDLS_CREATE 0x01 |
516 | #define ACT_TDLS_CONFIG 0x02 | 521 | #define ACT_TDLS_CONFIG 0x02 |
517 | 522 | ||
523 | #define MWIFIEX_FW_V15 15 | ||
524 | |||
518 | struct mwifiex_ie_types_header { | 525 | struct mwifiex_ie_types_header { |
519 | __le16 type; | 526 | __le16 type; |
520 | __le16 len; | 527 | __le16 len; |
@@ -1103,6 +1110,7 @@ struct mwifiex_rate_scope { | |||
1103 | __le16 hr_dsss_rate_bitmap; | 1110 | __le16 hr_dsss_rate_bitmap; |
1104 | __le16 ofdm_rate_bitmap; | 1111 | __le16 ofdm_rate_bitmap; |
1105 | __le16 ht_mcs_rate_bitmap[8]; | 1112 | __le16 ht_mcs_rate_bitmap[8]; |
1113 | __le16 vht_mcs_rate_bitmap[8]; | ||
1106 | } __packed; | 1114 | } __packed; |
1107 | 1115 | ||
1108 | struct mwifiex_rate_drop_pattern { | 1116 | struct mwifiex_rate_drop_pattern { |
diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h index 1fb2212079ae..ee494db54060 100644 --- a/drivers/net/wireless/mwifiex/ioctl.h +++ b/drivers/net/wireless/mwifiex/ioctl.h | |||
@@ -177,6 +177,7 @@ struct mwifiex_ds_rx_reorder_tbl { | |||
177 | struct mwifiex_ds_tx_ba_stream_tbl { | 177 | struct mwifiex_ds_tx_ba_stream_tbl { |
178 | u16 tid; | 178 | u16 tid; |
179 | u8 ra[ETH_ALEN]; | 179 | u8 ra[ETH_ALEN]; |
180 | u8 amsdu; | ||
180 | }; | 181 | }; |
181 | 182 | ||
182 | #define DBG_CMD_NUM 5 | 183 | #define DBG_CMD_NUM 5 |
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index f0289c12e041..a67f7da12b30 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h | |||
@@ -116,7 +116,7 @@ enum { | |||
116 | #define MWIFIEX_TYPE_DATA 0 | 116 | #define MWIFIEX_TYPE_DATA 0 |
117 | #define MWIFIEX_TYPE_EVENT 3 | 117 | #define MWIFIEX_TYPE_EVENT 3 |
118 | 118 | ||
119 | #define MAX_BITMAP_RATES_SIZE 10 | 119 | #define MAX_BITMAP_RATES_SIZE 18 |
120 | 120 | ||
121 | #define MAX_CHANNEL_BAND_BG 14 | 121 | #define MAX_CHANNEL_BAND_BG 14 |
122 | #define MAX_CHANNEL_BAND_A 165 | 122 | #define MAX_CHANNEL_BAND_A 165 |
@@ -192,6 +192,8 @@ struct mwifiex_add_ba_param { | |||
192 | u32 tx_win_size; | 192 | u32 tx_win_size; |
193 | u32 rx_win_size; | 193 | u32 rx_win_size; |
194 | u32 timeout; | 194 | u32 timeout; |
195 | u8 tx_amsdu; | ||
196 | u8 rx_amsdu; | ||
195 | }; | 197 | }; |
196 | 198 | ||
197 | struct mwifiex_tx_aggr { | 199 | struct mwifiex_tx_aggr { |
@@ -560,6 +562,7 @@ struct mwifiex_tx_ba_stream_tbl { | |||
560 | int tid; | 562 | int tid; |
561 | u8 ra[ETH_ALEN]; | 563 | u8 ra[ETH_ALEN]; |
562 | enum mwifiex_ba_status ba_status; | 564 | enum mwifiex_ba_status ba_status; |
565 | u8 amsdu; | ||
563 | }; | 566 | }; |
564 | 567 | ||
565 | struct mwifiex_rx_reorder_tbl; | 568 | struct mwifiex_rx_reorder_tbl; |
@@ -579,6 +582,7 @@ struct mwifiex_rx_reorder_tbl { | |||
579 | int win_size; | 582 | int win_size; |
580 | void **rx_reorder_ptr; | 583 | void **rx_reorder_ptr; |
581 | struct reorder_tmr_cnxt timer_context; | 584 | struct reorder_tmr_cnxt timer_context; |
585 | u8 amsdu; | ||
582 | u8 flags; | 586 | u8 flags; |
583 | }; | 587 | }; |
584 | 588 | ||
@@ -802,6 +806,7 @@ struct mwifiex_adapter { | |||
802 | atomic_t pending_bridged_pkts; | 806 | atomic_t pending_bridged_pkts; |
803 | struct semaphore *card_sem; | 807 | struct semaphore *card_sem; |
804 | bool ext_scan; | 808 | bool ext_scan; |
809 | u8 fw_api_ver; | ||
805 | u8 fw_key_api_major_ver, fw_key_api_minor_ver; | 810 | u8 fw_key_api_major_ver, fw_key_api_minor_ver; |
806 | }; | 811 | }; |
807 | 812 | ||
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c index 9f1683b5f28f..57c353a94b29 100644 --- a/drivers/net/wireless/mwifiex/pcie.c +++ b/drivers/net/wireless/mwifiex/pcie.c | |||
@@ -327,6 +327,30 @@ static void mwifiex_pcie_dev_wakeup_delay(struct mwifiex_adapter *adapter) | |||
327 | return; | 327 | return; |
328 | } | 328 | } |
329 | 329 | ||
330 | static void mwifiex_delay_for_sleep_cookie(struct mwifiex_adapter *adapter, | ||
331 | u32 max_delay_loop_cnt) | ||
332 | { | ||
333 | struct pcie_service_card *card = adapter->card; | ||
334 | u8 *buffer; | ||
335 | u32 sleep_cookie, count; | ||
336 | |||
337 | for (count = 0; count < max_delay_loop_cnt; count++) { | ||
338 | buffer = card->cmdrsp_buf->data - INTF_HEADER_LEN; | ||
339 | sleep_cookie = *(u32 *)buffer; | ||
340 | |||
341 | if (sleep_cookie == MWIFIEX_DEF_SLEEP_COOKIE) { | ||
342 | dev_dbg(adapter->dev, | ||
343 | "sleep cookie found at count %d\n", count); | ||
344 | break; | ||
345 | } | ||
346 | usleep_range(20, 30); | ||
347 | } | ||
348 | |||
349 | if (count >= max_delay_loop_cnt) | ||
350 | dev_dbg(adapter->dev, | ||
351 | "max count reached while accessing sleep cookie\n"); | ||
352 | } | ||
353 | |||
330 | /* This function wakes up the card by reading fw_status register. */ | 354 | /* This function wakes up the card by reading fw_status register. */ |
331 | static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) | 355 | static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) |
332 | { | 356 | { |
@@ -1539,6 +1563,8 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter) | |||
1539 | "Write register failed\n"); | 1563 | "Write register failed\n"); |
1540 | return -1; | 1564 | return -1; |
1541 | } | 1565 | } |
1566 | mwifiex_delay_for_sleep_cookie(adapter, | ||
1567 | MWIFIEX_MAX_DELAY_COUNT); | ||
1542 | while (reg->sleep_cookie && (count++ < 10) && | 1568 | while (reg->sleep_cookie && (count++ < 10) && |
1543 | mwifiex_pcie_ok_to_access_hw(adapter)) | 1569 | mwifiex_pcie_ok_to_access_hw(adapter)) |
1544 | usleep_range(50, 60); | 1570 | usleep_range(50, 60); |
diff --git a/drivers/net/wireless/mwifiex/pcie.h b/drivers/net/wireless/mwifiex/pcie.h index 193af75bf582..e8ec561f8a64 100644 --- a/drivers/net/wireless/mwifiex/pcie.h +++ b/drivers/net/wireless/mwifiex/pcie.h | |||
@@ -97,6 +97,8 @@ | |||
97 | #define MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD 256 | 97 | #define MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD 256 |
98 | /* FW awake cookie after FW ready */ | 98 | /* FW awake cookie after FW ready */ |
99 | #define FW_AWAKE_COOKIE (0xAA55AA55) | 99 | #define FW_AWAKE_COOKIE (0xAA55AA55) |
100 | #define MWIFIEX_DEF_SLEEP_COOKIE 0xBEEFBEEF | ||
101 | #define MWIFIEX_MAX_DELAY_COUNT 5 | ||
100 | 102 | ||
101 | struct mwifiex_pcie_card_reg { | 103 | struct mwifiex_pcie_card_reg { |
102 | u16 cmd_addr_lo; | 104 | u16 cmd_addr_lo; |
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index 4315a3ba3b92..e3cac1495cc7 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c | |||
@@ -185,6 +185,13 @@ static int mwifiex_cmd_tx_rate_cfg(struct mwifiex_private *priv, | |||
185 | i++) | 185 | i++) |
186 | rate_scope->ht_mcs_rate_bitmap[i] = | 186 | rate_scope->ht_mcs_rate_bitmap[i] = |
187 | cpu_to_le16(pbitmap_rates[2 + i]); | 187 | cpu_to_le16(pbitmap_rates[2 + i]); |
188 | if (priv->adapter->fw_api_ver == MWIFIEX_FW_V15) { | ||
189 | for (i = 0; | ||
190 | i < ARRAY_SIZE(rate_scope->vht_mcs_rate_bitmap); | ||
191 | i++) | ||
192 | rate_scope->vht_mcs_rate_bitmap[i] = | ||
193 | cpu_to_le16(pbitmap_rates[10 + i]); | ||
194 | } | ||
188 | } else { | 195 | } else { |
189 | rate_scope->hr_dsss_rate_bitmap = | 196 | rate_scope->hr_dsss_rate_bitmap = |
190 | cpu_to_le16(priv->bitmap_rates[0]); | 197 | cpu_to_le16(priv->bitmap_rates[0]); |
@@ -195,6 +202,13 @@ static int mwifiex_cmd_tx_rate_cfg(struct mwifiex_private *priv, | |||
195 | i++) | 202 | i++) |
196 | rate_scope->ht_mcs_rate_bitmap[i] = | 203 | rate_scope->ht_mcs_rate_bitmap[i] = |
197 | cpu_to_le16(priv->bitmap_rates[2 + i]); | 204 | cpu_to_le16(priv->bitmap_rates[2 + i]); |
205 | if (priv->adapter->fw_api_ver == MWIFIEX_FW_V15) { | ||
206 | for (i = 0; | ||
207 | i < ARRAY_SIZE(rate_scope->vht_mcs_rate_bitmap); | ||
208 | i++) | ||
209 | rate_scope->vht_mcs_rate_bitmap[i] = | ||
210 | cpu_to_le16(priv->bitmap_rates[10 + i]); | ||
211 | } | ||
198 | } | 212 | } |
199 | 213 | ||
200 | rate_drop = (struct mwifiex_rate_drop_pattern *) ((u8 *) rate_scope + | 214 | rate_drop = (struct mwifiex_rate_drop_pattern *) ((u8 *) rate_scope + |
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index a8f7d545e22a..bfebb0144df5 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c | |||
@@ -304,6 +304,15 @@ static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv, | |||
304 | priv->bitmap_rates[2 + i] = | 304 | priv->bitmap_rates[2 + i] = |
305 | le16_to_cpu(rate_scope-> | 305 | le16_to_cpu(rate_scope-> |
306 | ht_mcs_rate_bitmap[i]); | 306 | ht_mcs_rate_bitmap[i]); |
307 | |||
308 | if (priv->adapter->fw_api_ver == MWIFIEX_FW_V15) { | ||
309 | for (i = 0; i < ARRAY_SIZE(rate_scope-> | ||
310 | vht_mcs_rate_bitmap); | ||
311 | i++) | ||
312 | priv->bitmap_rates[10 + i] = | ||
313 | le16_to_cpu(rate_scope-> | ||
314 | vht_mcs_rate_bitmap[i]); | ||
315 | } | ||
307 | break; | 316 | break; |
308 | /* Add RATE_DROP tlv here */ | 317 | /* Add RATE_DROP tlv here */ |
309 | } | 318 | } |
diff --git a/drivers/net/wireless/mwifiex/sta_rx.c b/drivers/net/wireless/mwifiex/sta_rx.c index b6aa958bd6e4..ed26387eccf5 100644 --- a/drivers/net/wireless/mwifiex/sta_rx.c +++ b/drivers/net/wireless/mwifiex/sta_rx.c | |||
@@ -201,26 +201,7 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_private *priv, | |||
201 | return ret; | 201 | return ret; |
202 | } | 202 | } |
203 | 203 | ||
204 | if (rx_pkt_type == PKT_TYPE_AMSDU) { | 204 | if (rx_pkt_type == PKT_TYPE_MGMT) { |
205 | struct sk_buff_head list; | ||
206 | struct sk_buff *rx_skb; | ||
207 | |||
208 | __skb_queue_head_init(&list); | ||
209 | |||
210 | skb_pull(skb, rx_pkt_offset); | ||
211 | skb_trim(skb, rx_pkt_length); | ||
212 | |||
213 | ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr, | ||
214 | priv->wdev->iftype, 0, false); | ||
215 | |||
216 | while (!skb_queue_empty(&list)) { | ||
217 | rx_skb = __skb_dequeue(&list); | ||
218 | ret = mwifiex_recv_packet(priv, rx_skb); | ||
219 | if (ret == -1) | ||
220 | dev_err(adapter->dev, "Rx of A-MSDU failed"); | ||
221 | } | ||
222 | return 0; | ||
223 | } else if (rx_pkt_type == PKT_TYPE_MGMT) { | ||
224 | ret = mwifiex_process_mgmt_packet(priv, skb); | 205 | ret = mwifiex_process_mgmt_packet(priv, skb); |
225 | if (ret) | 206 | if (ret) |
226 | dev_err(adapter->dev, "Rx of mgmt packet failed"); | 207 | dev_err(adapter->dev, "Rx of mgmt packet failed"); |
diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c index a6a6a53cda40..9be6544bdded 100644 --- a/drivers/net/wireless/mwifiex/uap_cmd.c +++ b/drivers/net/wireless/mwifiex/uap_cmd.c | |||
@@ -159,6 +159,7 @@ mwifiex_set_ht_params(struct mwifiex_private *priv, | |||
159 | struct cfg80211_ap_settings *params) | 159 | struct cfg80211_ap_settings *params) |
160 | { | 160 | { |
161 | const u8 *ht_ie; | 161 | const u8 *ht_ie; |
162 | u16 cap_info; | ||
162 | 163 | ||
163 | if (!ISSUPP_11NENABLED(priv->adapter->fw_cap_info)) | 164 | if (!ISSUPP_11NENABLED(priv->adapter->fw_cap_info)) |
164 | return; | 165 | return; |
@@ -168,6 +169,25 @@ mwifiex_set_ht_params(struct mwifiex_private *priv, | |||
168 | if (ht_ie) { | 169 | if (ht_ie) { |
169 | memcpy(&bss_cfg->ht_cap, ht_ie + 2, | 170 | memcpy(&bss_cfg->ht_cap, ht_ie + 2, |
170 | sizeof(struct ieee80211_ht_cap)); | 171 | sizeof(struct ieee80211_ht_cap)); |
172 | cap_info = le16_to_cpu(bss_cfg->ht_cap.cap_info); | ||
173 | memset(&bss_cfg->ht_cap.mcs, 0, | ||
174 | priv->adapter->number_of_antenna); | ||
175 | switch (GET_RXSTBC(cap_info)) { | ||
176 | case MWIFIEX_RX_STBC1: | ||
177 | /* HT_CAP 1X1 mode */ | ||
178 | memset(&bss_cfg->ht_cap.mcs, 0xff, 1); | ||
179 | break; | ||
180 | case MWIFIEX_RX_STBC12: /* fall through */ | ||
181 | case MWIFIEX_RX_STBC123: | ||
182 | /* HT_CAP 2X2 mode */ | ||
183 | memset(&bss_cfg->ht_cap.mcs, 0xff, 2); | ||
184 | break; | ||
185 | default: | ||
186 | dev_warn(priv->adapter->dev, | ||
187 | "Unsupported RX-STBC, default to 2x2\n"); | ||
188 | memset(&bss_cfg->ht_cap.mcs, 0xff, 2); | ||
189 | break; | ||
190 | } | ||
171 | priv->ap_11n_enabled = 1; | 191 | priv->ap_11n_enabled = 1; |
172 | } else { | 192 | } else { |
173 | memset(&bss_cfg->ht_cap , 0, sizeof(struct ieee80211_ht_cap)); | 193 | memset(&bss_cfg->ht_cap , 0, sizeof(struct ieee80211_ht_cap)); |
diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c index ae50e916d8f2..92e77a398ecf 100644 --- a/drivers/net/wireless/mwifiex/uap_event.c +++ b/drivers/net/wireless/mwifiex/uap_event.c | |||
@@ -166,6 +166,12 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv) | |||
166 | mwifiex_11n_ba_stream_timeout(priv, ba_timeout); | 166 | mwifiex_11n_ba_stream_timeout(priv, ba_timeout); |
167 | } | 167 | } |
168 | break; | 168 | break; |
169 | case EVENT_EXT_SCAN_REPORT: | ||
170 | dev_dbg(adapter->dev, "event: EXT_SCAN Report\n"); | ||
171 | if (adapter->ext_scan) | ||
172 | return mwifiex_handle_event_ext_scan_report(priv, | ||
173 | adapter->event_skb->data); | ||
174 | break; | ||
169 | default: | 175 | default: |
170 | dev_dbg(adapter->dev, "event: unknown event id: %#x\n", | 176 | dev_dbg(adapter->dev, "event: unknown event id: %#x\n", |
171 | eventcause); | 177 | eventcause); |
diff --git a/drivers/net/wireless/mwifiex/uap_txrx.c b/drivers/net/wireless/mwifiex/uap_txrx.c index 3c74eb254927..9a56bc61cb1d 100644 --- a/drivers/net/wireless/mwifiex/uap_txrx.c +++ b/drivers/net/wireless/mwifiex/uap_txrx.c | |||
@@ -284,27 +284,7 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv, | |||
284 | return 0; | 284 | return 0; |
285 | } | 285 | } |
286 | 286 | ||
287 | if (le16_to_cpu(uap_rx_pd->rx_pkt_type) == PKT_TYPE_AMSDU) { | 287 | if (rx_pkt_type == PKT_TYPE_MGMT) { |
288 | struct sk_buff_head list; | ||
289 | struct sk_buff *rx_skb; | ||
290 | |||
291 | __skb_queue_head_init(&list); | ||
292 | skb_pull(skb, le16_to_cpu(uap_rx_pd->rx_pkt_offset)); | ||
293 | skb_trim(skb, le16_to_cpu(uap_rx_pd->rx_pkt_length)); | ||
294 | |||
295 | ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr, | ||
296 | priv->wdev->iftype, 0, false); | ||
297 | |||
298 | while (!skb_queue_empty(&list)) { | ||
299 | rx_skb = __skb_dequeue(&list); | ||
300 | ret = mwifiex_recv_packet(priv, rx_skb); | ||
301 | if (ret) | ||
302 | dev_err(adapter->dev, | ||
303 | "AP:Rx A-MSDU failed"); | ||
304 | } | ||
305 | |||
306 | return 0; | ||
307 | } else if (rx_pkt_type == PKT_TYPE_MGMT) { | ||
308 | ret = mwifiex_process_mgmt_packet(priv, skb); | 288 | ret = mwifiex_process_mgmt_packet(priv, skb); |
309 | if (ret) | 289 | if (ret) |
310 | dev_err(adapter->dev, "Rx of mgmt packet failed"); | 290 | dev_err(adapter->dev, "Rx of mgmt packet failed"); |
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 1c5f2b66f057..0a7cc742aed7 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c | |||
@@ -37,8 +37,8 @@ | |||
37 | /* Offset for TOS field in the IP header */ | 37 | /* Offset for TOS field in the IP header */ |
38 | #define IPTOS_OFFSET 5 | 38 | #define IPTOS_OFFSET 5 |
39 | 39 | ||
40 | static bool enable_tx_amsdu; | 40 | static bool disable_tx_amsdu; |
41 | module_param(enable_tx_amsdu, bool, 0644); | 41 | module_param(disable_tx_amsdu, bool, 0644); |
42 | 42 | ||
43 | /* WMM information IE */ | 43 | /* WMM information IE */ |
44 | static const u8 wmm_info_ie[] = { WLAN_EID_VENDOR_SPECIFIC, 0x07, | 44 | static const u8 wmm_info_ie[] = { WLAN_EID_VENDOR_SPECIFIC, 0x07, |
@@ -413,7 +413,13 @@ mwifiex_wmm_init(struct mwifiex_adapter *adapter) | |||
413 | continue; | 413 | continue; |
414 | 414 | ||
415 | for (i = 0; i < MAX_NUM_TID; ++i) { | 415 | for (i = 0; i < MAX_NUM_TID; ++i) { |
416 | priv->aggr_prio_tbl[i].amsdu = priv->tos_to_tid_inv[i]; | 416 | if (!disable_tx_amsdu && |
417 | adapter->tx_buf_size > MWIFIEX_TX_DATA_BUF_SIZE_2K) | ||
418 | priv->aggr_prio_tbl[i].amsdu = | ||
419 | priv->tos_to_tid_inv[i]; | ||
420 | else | ||
421 | priv->aggr_prio_tbl[i].amsdu = | ||
422 | BA_STREAM_NOT_ALLOWED; | ||
417 | priv->aggr_prio_tbl[i].ampdu_ap = | 423 | priv->aggr_prio_tbl[i].ampdu_ap = |
418 | priv->tos_to_tid_inv[i]; | 424 | priv->tos_to_tid_inv[i]; |
419 | priv->aggr_prio_tbl[i].ampdu_user = | 425 | priv->aggr_prio_tbl[i].ampdu_user = |
@@ -1247,13 +1253,22 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter) | |||
1247 | 1253 | ||
1248 | if (!ptr->is_11n_enabled || | 1254 | if (!ptr->is_11n_enabled || |
1249 | mwifiex_is_ba_stream_setup(priv, ptr, tid) || | 1255 | mwifiex_is_ba_stream_setup(priv, ptr, tid) || |
1250 | priv->wps.session_enable || | 1256 | priv->wps.session_enable) { |
1251 | ((priv->sec_info.wpa_enabled || | 1257 | if (ptr->is_11n_enabled && |
1252 | priv->sec_info.wpa2_enabled) && | 1258 | mwifiex_is_ba_stream_setup(priv, ptr, tid) && |
1253 | !priv->wpa_is_gtk_set)) { | 1259 | mwifiex_is_amsdu_in_ampdu_allowed(priv, ptr, tid) && |
1254 | mwifiex_send_single_packet(priv, ptr, ptr_index, flags); | 1260 | mwifiex_is_amsdu_allowed(priv, tid) && |
1255 | /* ra_list_spinlock has been freed in | 1261 | mwifiex_is_11n_aggragation_possible(priv, ptr, |
1256 | mwifiex_send_single_packet() */ | 1262 | adapter->tx_buf_size)) |
1263 | mwifiex_11n_aggregate_pkt(priv, ptr, ptr_index, flags); | ||
1264 | /* ra_list_spinlock has been freed in | ||
1265 | * mwifiex_11n_aggregate_pkt() | ||
1266 | */ | ||
1267 | else | ||
1268 | mwifiex_send_single_packet(priv, ptr, ptr_index, flags); | ||
1269 | /* ra_list_spinlock has been freed in | ||
1270 | * mwifiex_send_single_packet() | ||
1271 | */ | ||
1257 | } else { | 1272 | } else { |
1258 | if (mwifiex_is_ampdu_allowed(priv, ptr, tid) && | 1273 | if (mwifiex_is_ampdu_allowed(priv, ptr, tid) && |
1259 | ptr->ba_pkt_count > ptr->ba_packet_thr) { | 1274 | ptr->ba_pkt_count > ptr->ba_packet_thr) { |
@@ -1268,7 +1283,7 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter) | |||
1268 | mwifiex_send_delba(priv, tid_del, ra, 1); | 1283 | mwifiex_send_delba(priv, tid_del, ra, 1); |
1269 | } | 1284 | } |
1270 | } | 1285 | } |
1271 | if (enable_tx_amsdu && mwifiex_is_amsdu_allowed(priv, tid) && | 1286 | if (mwifiex_is_amsdu_allowed(priv, tid) && |
1272 | mwifiex_is_11n_aggragation_possible(priv, ptr, | 1287 | mwifiex_is_11n_aggragation_possible(priv, ptr, |
1273 | adapter->tx_buf_size)) | 1288 | adapter->tx_buf_size)) |
1274 | mwifiex_11n_aggregate_pkt(priv, ptr, ptr_index, flags); | 1289 | mwifiex_11n_aggregate_pkt(priv, ptr, ptr_index, flags); |
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index b7ab3dfb3de8..043bd1c23c19 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c | |||
@@ -1053,6 +1053,10 @@ static int p54u_probe(struct usb_interface *intf, | |||
1053 | priv->upload_fw = p54u_upload_firmware_net2280; | 1053 | priv->upload_fw = p54u_upload_firmware_net2280; |
1054 | } | 1054 | } |
1055 | err = p54u_load_firmware(dev, intf); | 1055 | err = p54u_load_firmware(dev, intf); |
1056 | if (err) { | ||
1057 | usb_put_dev(udev); | ||
1058 | p54_free_common(dev); | ||
1059 | } | ||
1056 | return err; | 1060 | return err; |
1057 | } | 1061 | } |
1058 | 1062 | ||
diff --git a/drivers/net/wireless/rsi/Kconfig b/drivers/net/wireless/rsi/Kconfig new file mode 100644 index 000000000000..35245f994c10 --- /dev/null +++ b/drivers/net/wireless/rsi/Kconfig | |||
@@ -0,0 +1,30 @@ | |||
1 | config RSI_91X | ||
2 | tristate "Redpine Signals Inc 91x WLAN driver support" | ||
3 | depends on MAC80211 | ||
4 | ---help--- | ||
5 | This option enabes support for RSI 1x1 devices. | ||
6 | Select M (recommended), if you have a RSI 1x1 wireless module. | ||
7 | |||
8 | config RSI_DEBUGFS | ||
9 | bool "Redpine Signals Inc debug support" | ||
10 | depends on RSI_91X | ||
11 | default y | ||
12 | ---help--- | ||
13 | Say Y, if you would like to enable debug support. This option | ||
14 | creates debugfs entries | ||
15 | |||
16 | config RSI_SDIO | ||
17 | tristate "Redpine Signals SDIO bus support" | ||
18 | depends on MMC && RSI_91X | ||
19 | default m | ||
20 | ---help--- | ||
21 | This option enables the SDIO bus support in rsi drivers. | ||
22 | Select M (recommended), if you have a RSI 1x1 wireless module. | ||
23 | |||
24 | config RSI_USB | ||
25 | tristate "Redpine Signals USB bus support" | ||
26 | depends on USB && RSI_91X | ||
27 | default m | ||
28 | ---help--- | ||
29 | This option enables the USB bus support in rsi drivers. | ||
30 | Select M (recommended), if you have a RSI 1x1 wireless module. | ||
diff --git a/drivers/net/wireless/rsi/Makefile b/drivers/net/wireless/rsi/Makefile new file mode 100644 index 000000000000..25828b692756 --- /dev/null +++ b/drivers/net/wireless/rsi/Makefile | |||
@@ -0,0 +1,12 @@ | |||
1 | rsi_91x-y += rsi_91x_main.o | ||
2 | rsi_91x-y += rsi_91x_core.o | ||
3 | rsi_91x-y += rsi_91x_mac80211.o | ||
4 | rsi_91x-y += rsi_91x_mgmt.o | ||
5 | rsi_91x-y += rsi_91x_pkt.o | ||
6 | rsi_91x-$(CONFIG_RSI_DEBUGFS) += rsi_91x_debugfs.o | ||
7 | |||
8 | rsi_usb-y += rsi_91x_usb.o rsi_91x_usb_ops.o | ||
9 | rsi_sdio-y += rsi_91x_sdio.o rsi_91x_sdio_ops.o | ||
10 | obj-$(CONFIG_RSI_91X) += rsi_91x.o | ||
11 | obj-$(CONFIG_RSI_SDIO) += rsi_sdio.o | ||
12 | obj-$(CONFIG_RSI_USB) += rsi_usb.o | ||
diff --git a/drivers/net/wireless/rsi/rsi_91x_core.c b/drivers/net/wireless/rsi/rsi_91x_core.c new file mode 100644 index 000000000000..e89535e86caf --- /dev/null +++ b/drivers/net/wireless/rsi/rsi_91x_core.c | |||
@@ -0,0 +1,342 @@ | |||
1 | /** | ||
2 | * Copyright (c) 2014 Redpine Signals Inc. | ||
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 | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include "rsi_mgmt.h" | ||
18 | #include "rsi_common.h" | ||
19 | |||
20 | /** | ||
21 | * rsi_determine_min_weight_queue() - This function determines the queue with | ||
22 | * the min weight. | ||
23 | * @common: Pointer to the driver private structure. | ||
24 | * | ||
25 | * Return: q_num: Corresponding queue number. | ||
26 | */ | ||
27 | static u8 rsi_determine_min_weight_queue(struct rsi_common *common) | ||
28 | { | ||
29 | struct wmm_qinfo *tx_qinfo = common->tx_qinfo; | ||
30 | u32 q_len = 0; | ||
31 | u8 ii = 0; | ||
32 | |||
33 | for (ii = 0; ii < NUM_EDCA_QUEUES; ii++) { | ||
34 | q_len = skb_queue_len(&common->tx_queue[ii]); | ||
35 | if ((tx_qinfo[ii].pkt_contended) && q_len) { | ||
36 | common->min_weight = tx_qinfo[ii].weight; | ||
37 | break; | ||
38 | } | ||
39 | } | ||
40 | return ii; | ||
41 | } | ||
42 | |||
43 | /** | ||
44 | * rsi_recalculate_weights() - This function recalculates the weights | ||
45 | * corresponding to each queue. | ||
46 | * @common: Pointer to the driver private structure. | ||
47 | * | ||
48 | * Return: recontend_queue bool variable | ||
49 | */ | ||
50 | static bool rsi_recalculate_weights(struct rsi_common *common) | ||
51 | { | ||
52 | struct wmm_qinfo *tx_qinfo = common->tx_qinfo; | ||
53 | bool recontend_queue = false; | ||
54 | u8 ii = 0; | ||
55 | u32 q_len = 0; | ||
56 | |||
57 | for (ii = 0; ii < NUM_EDCA_QUEUES; ii++) { | ||
58 | q_len = skb_queue_len(&common->tx_queue[ii]); | ||
59 | /* Check for the need of contention */ | ||
60 | if (q_len) { | ||
61 | if (tx_qinfo[ii].pkt_contended) { | ||
62 | tx_qinfo[ii].weight = | ||
63 | ((tx_qinfo[ii].weight > common->min_weight) ? | ||
64 | tx_qinfo[ii].weight - common->min_weight : 0); | ||
65 | } else { | ||
66 | tx_qinfo[ii].pkt_contended = 1; | ||
67 | tx_qinfo[ii].weight = tx_qinfo[ii].wme_params; | ||
68 | recontend_queue = true; | ||
69 | } | ||
70 | } else { /* No packets so no contention */ | ||
71 | tx_qinfo[ii].weight = 0; | ||
72 | tx_qinfo[ii].pkt_contended = 0; | ||
73 | } | ||
74 | } | ||
75 | |||
76 | return recontend_queue; | ||
77 | } | ||
78 | |||
79 | /** | ||
80 | * rsi_core_determine_hal_queue() - This function determines the queue from | ||
81 | * which packet has to be dequeued. | ||
82 | * @common: Pointer to the driver private structure. | ||
83 | * | ||
84 | * Return: q_num: Corresponding queue number on success. | ||
85 | */ | ||
86 | static u8 rsi_core_determine_hal_queue(struct rsi_common *common) | ||
87 | { | ||
88 | bool recontend_queue = false; | ||
89 | u32 q_len = 0; | ||
90 | u8 q_num = INVALID_QUEUE; | ||
91 | u8 ii, min = 0; | ||
92 | |||
93 | if (skb_queue_len(&common->tx_queue[MGMT_SOFT_Q])) { | ||
94 | if (!common->mgmt_q_block) | ||
95 | q_num = MGMT_SOFT_Q; | ||
96 | return q_num; | ||
97 | } | ||
98 | |||
99 | if (common->pkt_cnt != 0) { | ||
100 | --common->pkt_cnt; | ||
101 | return common->selected_qnum; | ||
102 | } | ||
103 | |||
104 | get_queue_num: | ||
105 | q_num = 0; | ||
106 | recontend_queue = false; | ||
107 | |||
108 | q_num = rsi_determine_min_weight_queue(common); | ||
109 | q_len = skb_queue_len(&common->tx_queue[ii]); | ||
110 | ii = q_num; | ||
111 | |||
112 | /* Selecting the queue with least back off */ | ||
113 | for (; ii < NUM_EDCA_QUEUES; ii++) { | ||
114 | if (((common->tx_qinfo[ii].pkt_contended) && | ||
115 | (common->tx_qinfo[ii].weight < min)) && q_len) { | ||
116 | min = common->tx_qinfo[ii].weight; | ||
117 | q_num = ii; | ||
118 | } | ||
119 | } | ||
120 | |||
121 | common->tx_qinfo[q_num].pkt_contended = 0; | ||
122 | /* Adjust the back off values for all queues again */ | ||
123 | recontend_queue = rsi_recalculate_weights(common); | ||
124 | |||
125 | q_len = skb_queue_len(&common->tx_queue[q_num]); | ||
126 | if (!q_len) { | ||
127 | /* If any queues are freshly contended and the selected queue | ||
128 | * doesn't have any packets | ||
129 | * then get the queue number again with fresh values | ||
130 | */ | ||
131 | if (recontend_queue) | ||
132 | goto get_queue_num; | ||
133 | |||
134 | q_num = INVALID_QUEUE; | ||
135 | return q_num; | ||
136 | } | ||
137 | |||
138 | common->selected_qnum = q_num; | ||
139 | q_len = skb_queue_len(&common->tx_queue[q_num]); | ||
140 | |||
141 | switch (common->selected_qnum) { | ||
142 | case VO_Q: | ||
143 | if (q_len > MAX_CONTINUOUS_VO_PKTS) | ||
144 | common->pkt_cnt = (MAX_CONTINUOUS_VO_PKTS - 1); | ||
145 | else | ||
146 | common->pkt_cnt = --q_len; | ||
147 | break; | ||
148 | |||
149 | case VI_Q: | ||
150 | if (q_len > MAX_CONTINUOUS_VI_PKTS) | ||
151 | common->pkt_cnt = (MAX_CONTINUOUS_VI_PKTS - 1); | ||
152 | else | ||
153 | common->pkt_cnt = --q_len; | ||
154 | |||
155 | break; | ||
156 | |||
157 | default: | ||
158 | common->pkt_cnt = 0; | ||
159 | break; | ||
160 | } | ||
161 | |||
162 | return q_num; | ||
163 | } | ||
164 | |||
165 | /** | ||
166 | * rsi_core_queue_pkt() - This functions enqueues the packet to the queue | ||
167 | * specified by the queue number. | ||
168 | * @common: Pointer to the driver private structure. | ||
169 | * @skb: Pointer to the socket buffer structure. | ||
170 | * | ||
171 | * Return: None. | ||
172 | */ | ||
173 | static void rsi_core_queue_pkt(struct rsi_common *common, | ||
174 | struct sk_buff *skb) | ||
175 | { | ||
176 | u8 q_num = skb->priority; | ||
177 | if (q_num >= NUM_SOFT_QUEUES) { | ||
178 | rsi_dbg(ERR_ZONE, "%s: Invalid Queue Number: q_num = %d\n", | ||
179 | __func__, q_num); | ||
180 | dev_kfree_skb(skb); | ||
181 | return; | ||
182 | } | ||
183 | |||
184 | skb_queue_tail(&common->tx_queue[q_num], skb); | ||
185 | } | ||
186 | |||
187 | /** | ||
188 | * rsi_core_dequeue_pkt() - This functions dequeues the packet from the queue | ||
189 | * specified by the queue number. | ||
190 | * @common: Pointer to the driver private structure. | ||
191 | * @q_num: Queue number. | ||
192 | * | ||
193 | * Return: Pointer to sk_buff structure. | ||
194 | */ | ||
195 | static struct sk_buff *rsi_core_dequeue_pkt(struct rsi_common *common, | ||
196 | u8 q_num) | ||
197 | { | ||
198 | if (q_num >= NUM_SOFT_QUEUES) { | ||
199 | rsi_dbg(ERR_ZONE, "%s: Invalid Queue Number: q_num = %d\n", | ||
200 | __func__, q_num); | ||
201 | return NULL; | ||
202 | } | ||
203 | |||
204 | return skb_dequeue(&common->tx_queue[q_num]); | ||
205 | } | ||
206 | |||
207 | /** | ||
208 | * rsi_core_qos_processor() - This function is used to determine the wmm queue | ||
209 | * based on the backoff procedure. Data packets are | ||
210 | * dequeued from the selected hal queue and sent to | ||
211 | * the below layers. | ||
212 | * @common: Pointer to the driver private structure. | ||
213 | * | ||
214 | * Return: None. | ||
215 | */ | ||
216 | void rsi_core_qos_processor(struct rsi_common *common) | ||
217 | { | ||
218 | struct rsi_hw *adapter = common->priv; | ||
219 | struct sk_buff *skb; | ||
220 | unsigned long tstamp_1, tstamp_2; | ||
221 | u8 q_num; | ||
222 | int status; | ||
223 | |||
224 | tstamp_1 = jiffies; | ||
225 | while (1) { | ||
226 | q_num = rsi_core_determine_hal_queue(common); | ||
227 | rsi_dbg(DATA_TX_ZONE, | ||
228 | "%s: Queue number = %d\n", __func__, q_num); | ||
229 | |||
230 | if (q_num == INVALID_QUEUE) { | ||
231 | rsi_dbg(DATA_TX_ZONE, "%s: No More Pkt\n", __func__); | ||
232 | break; | ||
233 | } | ||
234 | |||
235 | mutex_lock(&common->tx_rxlock); | ||
236 | |||
237 | status = adapter->check_hw_queue_status(adapter, q_num); | ||
238 | if ((status <= 0)) { | ||
239 | mutex_unlock(&common->tx_rxlock); | ||
240 | break; | ||
241 | } | ||
242 | |||
243 | if ((q_num < MGMT_SOFT_Q) && | ||
244 | ((skb_queue_len(&common->tx_queue[q_num])) <= | ||
245 | MIN_DATA_QUEUE_WATER_MARK)) { | ||
246 | if (ieee80211_queue_stopped(adapter->hw, WME_AC(q_num))) | ||
247 | ieee80211_wake_queue(adapter->hw, | ||
248 | WME_AC(q_num)); | ||
249 | } | ||
250 | |||
251 | skb = rsi_core_dequeue_pkt(common, q_num); | ||
252 | if (skb == NULL) { | ||
253 | mutex_unlock(&common->tx_rxlock); | ||
254 | break; | ||
255 | } | ||
256 | |||
257 | if (q_num == MGMT_SOFT_Q) | ||
258 | status = rsi_send_mgmt_pkt(common, skb); | ||
259 | else | ||
260 | status = rsi_send_data_pkt(common, skb); | ||
261 | |||
262 | if (status) { | ||
263 | mutex_unlock(&common->tx_rxlock); | ||
264 | break; | ||
265 | } | ||
266 | |||
267 | common->tx_stats.total_tx_pkt_send[q_num]++; | ||
268 | |||
269 | tstamp_2 = jiffies; | ||
270 | mutex_unlock(&common->tx_rxlock); | ||
271 | |||
272 | if (tstamp_2 > tstamp_1 + (300 * HZ / 1000)) | ||
273 | schedule(); | ||
274 | } | ||
275 | } | ||
276 | |||
277 | /** | ||
278 | * rsi_core_xmit() - This function transmits the packets received from mac80211 | ||
279 | * @common: Pointer to the driver private structure. | ||
280 | * @skb: Pointer to the socket buffer structure. | ||
281 | * | ||
282 | * Return: None. | ||
283 | */ | ||
284 | void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb) | ||
285 | { | ||
286 | struct rsi_hw *adapter = common->priv; | ||
287 | struct ieee80211_tx_info *info; | ||
288 | struct skb_info *tx_params; | ||
289 | struct ieee80211_hdr *tmp_hdr = NULL; | ||
290 | u8 q_num, tid = 0; | ||
291 | |||
292 | if ((!skb) || (!skb->len)) { | ||
293 | rsi_dbg(ERR_ZONE, "%s: Null skb/zero Length packet\n", | ||
294 | __func__); | ||
295 | goto xmit_fail; | ||
296 | } | ||
297 | info = IEEE80211_SKB_CB(skb); | ||
298 | tx_params = (struct skb_info *)info->driver_data; | ||
299 | tmp_hdr = (struct ieee80211_hdr *)&skb->data[0]; | ||
300 | |||
301 | if (common->fsm_state != FSM_MAC_INIT_DONE) { | ||
302 | rsi_dbg(ERR_ZONE, "%s: FSM state not open\n", __func__); | ||
303 | goto xmit_fail; | ||
304 | } | ||
305 | |||
306 | if ((ieee80211_is_mgmt(tmp_hdr->frame_control)) || | ||
307 | (ieee80211_is_ctl(tmp_hdr->frame_control))) { | ||
308 | q_num = MGMT_SOFT_Q; | ||
309 | skb->priority = q_num; | ||
310 | } else { | ||
311 | if (ieee80211_is_data_qos(tmp_hdr->frame_control)) { | ||
312 | tid = (skb->data[24] & IEEE80211_QOS_TID); | ||
313 | skb->priority = TID_TO_WME_AC(tid); | ||
314 | } else { | ||
315 | tid = IEEE80211_NONQOS_TID; | ||
316 | skb->priority = BE_Q; | ||
317 | } | ||
318 | q_num = skb->priority; | ||
319 | tx_params->tid = tid; | ||
320 | tx_params->sta_id = 0; | ||
321 | } | ||
322 | |||
323 | if ((q_num != MGMT_SOFT_Q) && | ||
324 | ((skb_queue_len(&common->tx_queue[q_num]) + 1) >= | ||
325 | DATA_QUEUE_WATER_MARK)) { | ||
326 | if (!ieee80211_queue_stopped(adapter->hw, WME_AC(q_num))) | ||
327 | ieee80211_stop_queue(adapter->hw, WME_AC(q_num)); | ||
328 | rsi_set_event(&common->tx_thread.event); | ||
329 | goto xmit_fail; | ||
330 | } | ||
331 | |||
332 | rsi_core_queue_pkt(common, skb); | ||
333 | rsi_dbg(DATA_TX_ZONE, "%s: ===> Scheduling TX thead <===\n", __func__); | ||
334 | rsi_set_event(&common->tx_thread.event); | ||
335 | |||
336 | return; | ||
337 | |||
338 | xmit_fail: | ||
339 | rsi_dbg(ERR_ZONE, "%s: Failed to queue packet\n", __func__); | ||
340 | /* Dropping pkt here */ | ||
341 | ieee80211_free_txskb(common->priv->hw, skb); | ||
342 | } | ||
diff --git a/drivers/net/wireless/rsi/rsi_91x_debugfs.c b/drivers/net/wireless/rsi/rsi_91x_debugfs.c new file mode 100644 index 000000000000..7e4ef4554411 --- /dev/null +++ b/drivers/net/wireless/rsi/rsi_91x_debugfs.c | |||
@@ -0,0 +1,339 @@ | |||
1 | /** | ||
2 | * Copyright (c) 2014 Redpine Signals Inc. | ||
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 | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include "rsi_debugfs.h" | ||
18 | #include "rsi_sdio.h" | ||
19 | |||
20 | /** | ||
21 | * rsi_sdio_stats_read() - This function returns the sdio status of the driver. | ||
22 | * @seq: Pointer to the sequence file structure. | ||
23 | * @data: Pointer to the data. | ||
24 | * | ||
25 | * Return: 0 on success, -1 on failure. | ||
26 | */ | ||
27 | static int rsi_sdio_stats_read(struct seq_file *seq, void *data) | ||
28 | { | ||
29 | struct rsi_common *common = seq->private; | ||
30 | struct rsi_hw *adapter = common->priv; | ||
31 | struct rsi_91x_sdiodev *dev = | ||
32 | (struct rsi_91x_sdiodev *)adapter->rsi_dev; | ||
33 | |||
34 | seq_printf(seq, "total_sdio_interrupts: %d\n", | ||
35 | dev->rx_info.sdio_int_counter); | ||
36 | seq_printf(seq, "sdio_msdu_pending_intr_count: %d\n", | ||
37 | dev->rx_info.total_sdio_msdu_pending_intr); | ||
38 | seq_printf(seq, "sdio_buff_full_count : %d\n", | ||
39 | dev->rx_info.buf_full_counter); | ||
40 | seq_printf(seq, "sdio_buf_semi_full_count %d\n", | ||
41 | dev->rx_info.buf_semi_full_counter); | ||
42 | seq_printf(seq, "sdio_unknown_intr_count: %d\n", | ||
43 | dev->rx_info.total_sdio_unknown_intr); | ||
44 | /* RX Path Stats */ | ||
45 | seq_printf(seq, "BUFFER FULL STATUS : %d\n", | ||
46 | dev->rx_info.buffer_full); | ||
47 | seq_printf(seq, "SEMI BUFFER FULL STATUS : %d\n", | ||
48 | dev->rx_info.semi_buffer_full); | ||
49 | seq_printf(seq, "MGMT BUFFER FULL STATUS : %d\n", | ||
50 | dev->rx_info.mgmt_buffer_full); | ||
51 | seq_printf(seq, "BUFFER FULL COUNTER : %d\n", | ||
52 | dev->rx_info.buf_full_counter); | ||
53 | seq_printf(seq, "BUFFER SEMI FULL COUNTER : %d\n", | ||
54 | dev->rx_info.buf_semi_full_counter); | ||
55 | seq_printf(seq, "MGMT BUFFER FULL COUNTER : %d\n", | ||
56 | dev->rx_info.mgmt_buf_full_counter); | ||
57 | |||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | /** | ||
62 | * rsi_sdio_stats_open() - This funtion calls single open function of seq_file | ||
63 | * to open file and read contents from it. | ||
64 | * @inode: Pointer to the inode structure. | ||
65 | * @file: Pointer to the file structure. | ||
66 | * | ||
67 | * Return: Pointer to the opened file status: 0 on success, ENOMEM on failure. | ||
68 | */ | ||
69 | static int rsi_sdio_stats_open(struct inode *inode, | ||
70 | struct file *file) | ||
71 | { | ||
72 | return single_open(file, rsi_sdio_stats_read, inode->i_private); | ||
73 | } | ||
74 | |||
75 | /** | ||
76 | * rsi_version_read() - This function gives driver and firmware version number. | ||
77 | * @seq: Pointer to the sequence file structure. | ||
78 | * @data: Pointer to the data. | ||
79 | * | ||
80 | * Return: 0 on success, -1 on failure. | ||
81 | */ | ||
82 | static int rsi_version_read(struct seq_file *seq, void *data) | ||
83 | { | ||
84 | struct rsi_common *common = seq->private; | ||
85 | |||
86 | common->driver_ver.major = 0; | ||
87 | common->driver_ver.minor = 1; | ||
88 | common->driver_ver.release_num = 0; | ||
89 | common->driver_ver.patch_num = 0; | ||
90 | seq_printf(seq, "Driver : %x.%d.%d.%d\nLMAC : %d.%d.%d.%d\n", | ||
91 | common->driver_ver.major, | ||
92 | common->driver_ver.minor, | ||
93 | common->driver_ver.release_num, | ||
94 | common->driver_ver.patch_num, | ||
95 | common->fw_ver.major, | ||
96 | common->fw_ver.minor, | ||
97 | common->fw_ver.release_num, | ||
98 | common->fw_ver.patch_num); | ||
99 | return 0; | ||
100 | } | ||
101 | |||
102 | /** | ||
103 | * rsi_version_open() - This funtion calls single open function of seq_file to | ||
104 | * open file and read contents from it. | ||
105 | * @inode: Pointer to the inode structure. | ||
106 | * @file: Pointer to the file structure. | ||
107 | * | ||
108 | * Return: Pointer to the opened file status: 0 on success, ENOMEM on failure. | ||
109 | */ | ||
110 | static int rsi_version_open(struct inode *inode, | ||
111 | struct file *file) | ||
112 | { | ||
113 | return single_open(file, rsi_version_read, inode->i_private); | ||
114 | } | ||
115 | |||
116 | /** | ||
117 | * rsi_stats_read() - This function return the status of the driver. | ||
118 | * @seq: Pointer to the sequence file structure. | ||
119 | * @data: Pointer to the data. | ||
120 | * | ||
121 | * Return: 0 on success, -1 on failure. | ||
122 | */ | ||
123 | static int rsi_stats_read(struct seq_file *seq, void *data) | ||
124 | { | ||
125 | struct rsi_common *common = seq->private; | ||
126 | |||
127 | unsigned char fsm_state[][32] = { | ||
128 | "FSM_CARD_NOT_READY", | ||
129 | "FSM_BOOT_PARAMS_SENT", | ||
130 | "FSM_EEPROM_READ_MAC_ADDR", | ||
131 | "FSM_RESET_MAC_SENT", | ||
132 | "FSM_RADIO_CAPS_SENT", | ||
133 | "FSM_BB_RF_PROG_SENT", | ||
134 | "FSM_MAC_INIT_DONE" | ||
135 | }; | ||
136 | seq_puts(seq, "==> RSI STA DRIVER STATUS <==\n"); | ||
137 | seq_puts(seq, "DRIVER_FSM_STATE: "); | ||
138 | |||
139 | if (common->fsm_state <= FSM_MAC_INIT_DONE) | ||
140 | seq_printf(seq, "%s", fsm_state[common->fsm_state]); | ||
141 | |||
142 | seq_printf(seq, "(%d)\n\n", common->fsm_state); | ||
143 | |||
144 | /* Mgmt TX Path Stats */ | ||
145 | seq_printf(seq, "total_mgmt_pkt_send : %d\n", | ||
146 | common->tx_stats.total_tx_pkt_send[MGMT_SOFT_Q]); | ||
147 | seq_printf(seq, "total_mgmt_pkt_queued : %d\n", | ||
148 | skb_queue_len(&common->tx_queue[4])); | ||
149 | seq_printf(seq, "total_mgmt_pkt_freed : %d\n", | ||
150 | common->tx_stats.total_tx_pkt_freed[MGMT_SOFT_Q]); | ||
151 | |||
152 | /* Data TX Path Stats */ | ||
153 | seq_printf(seq, "total_data_vo_pkt_send: %8d\t", | ||
154 | common->tx_stats.total_tx_pkt_send[VO_Q]); | ||
155 | seq_printf(seq, "total_data_vo_pkt_queued: %8d\t", | ||
156 | skb_queue_len(&common->tx_queue[0])); | ||
157 | seq_printf(seq, "total_vo_pkt_freed: %8d\n", | ||
158 | common->tx_stats.total_tx_pkt_freed[VO_Q]); | ||
159 | seq_printf(seq, "total_data_vi_pkt_send: %8d\t", | ||
160 | common->tx_stats.total_tx_pkt_send[VI_Q]); | ||
161 | seq_printf(seq, "total_data_vi_pkt_queued: %8d\t", | ||
162 | skb_queue_len(&common->tx_queue[1])); | ||
163 | seq_printf(seq, "total_vi_pkt_freed: %8d\n", | ||
164 | common->tx_stats.total_tx_pkt_freed[VI_Q]); | ||
165 | seq_printf(seq, "total_data_be_pkt_send: %8d\t", | ||
166 | common->tx_stats.total_tx_pkt_send[BE_Q]); | ||
167 | seq_printf(seq, "total_data_be_pkt_queued: %8d\t", | ||
168 | skb_queue_len(&common->tx_queue[2])); | ||
169 | seq_printf(seq, "total_be_pkt_freed: %8d\n", | ||
170 | common->tx_stats.total_tx_pkt_freed[BE_Q]); | ||
171 | seq_printf(seq, "total_data_bk_pkt_send: %8d\t", | ||
172 | common->tx_stats.total_tx_pkt_send[BK_Q]); | ||
173 | seq_printf(seq, "total_data_bk_pkt_queued: %8d\t", | ||
174 | skb_queue_len(&common->tx_queue[3])); | ||
175 | seq_printf(seq, "total_bk_pkt_freed: %8d\n", | ||
176 | common->tx_stats.total_tx_pkt_freed[BK_Q]); | ||
177 | |||
178 | seq_puts(seq, "\n"); | ||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | /** | ||
183 | * rsi_stats_open() - This funtion calls single open function of seq_file to | ||
184 | * open file and read contents from it. | ||
185 | * @inode: Pointer to the inode structure. | ||
186 | * @file: Pointer to the file structure. | ||
187 | * | ||
188 | * Return: Pointer to the opened file status: 0 on success, ENOMEM on failure. | ||
189 | */ | ||
190 | static int rsi_stats_open(struct inode *inode, | ||
191 | struct file *file) | ||
192 | { | ||
193 | return single_open(file, rsi_stats_read, inode->i_private); | ||
194 | } | ||
195 | |||
196 | /** | ||
197 | * rsi_debug_zone_read() - This function display the currently enabled debug zones. | ||
198 | * @seq: Pointer to the sequence file structure. | ||
199 | * @data: Pointer to the data. | ||
200 | * | ||
201 | * Return: 0 on success, -1 on failure. | ||
202 | */ | ||
203 | static int rsi_debug_zone_read(struct seq_file *seq, void *data) | ||
204 | { | ||
205 | rsi_dbg(FSM_ZONE, "%x: rsi_enabled zone", rsi_zone_enabled); | ||
206 | seq_printf(seq, "The zones available are %#x\n", | ||
207 | rsi_zone_enabled); | ||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | /** | ||
212 | * rsi_debug_read() - This funtion calls single open function of seq_file to | ||
213 | * open file and read contents from it. | ||
214 | * @inode: Pointer to the inode structure. | ||
215 | * @file: Pointer to the file structure. | ||
216 | * | ||
217 | * Return: Pointer to the opened file status: 0 on success, ENOMEM on failure. | ||
218 | */ | ||
219 | static int rsi_debug_read(struct inode *inode, | ||
220 | struct file *file) | ||
221 | { | ||
222 | return single_open(file, rsi_debug_zone_read, inode->i_private); | ||
223 | } | ||
224 | |||
225 | /** | ||
226 | * rsi_debug_zone_write() - This function writes into hal queues as per user | ||
227 | * requirement. | ||
228 | * @filp: Pointer to the file structure. | ||
229 | * @buff: Pointer to the character buffer. | ||
230 | * @len: Length of the data to be written into buffer. | ||
231 | * @data: Pointer to the data. | ||
232 | * | ||
233 | * Return: len: Number of bytes read. | ||
234 | */ | ||
235 | static ssize_t rsi_debug_zone_write(struct file *filp, | ||
236 | const char __user *buff, | ||
237 | size_t len, | ||
238 | loff_t *data) | ||
239 | { | ||
240 | unsigned long dbg_zone; | ||
241 | int ret; | ||
242 | |||
243 | if (!len) | ||
244 | return 0; | ||
245 | |||
246 | ret = kstrtoul_from_user(buff, len, 16, &dbg_zone); | ||
247 | |||
248 | if (ret) | ||
249 | return ret; | ||
250 | |||
251 | rsi_zone_enabled = dbg_zone; | ||
252 | return len; | ||
253 | } | ||
254 | |||
255 | #define FOPS(fopen) { \ | ||
256 | .owner = THIS_MODULE, \ | ||
257 | .open = (fopen), \ | ||
258 | .read = seq_read, \ | ||
259 | .llseek = seq_lseek, \ | ||
260 | } | ||
261 | |||
262 | #define FOPS_RW(fopen, fwrite) { \ | ||
263 | .owner = THIS_MODULE, \ | ||
264 | .open = (fopen), \ | ||
265 | .read = seq_read, \ | ||
266 | .llseek = seq_lseek, \ | ||
267 | .write = (fwrite), \ | ||
268 | } | ||
269 | |||
270 | static const struct rsi_dbg_files dev_debugfs_files[] = { | ||
271 | {"version", 0644, FOPS(rsi_version_open),}, | ||
272 | {"stats", 0644, FOPS(rsi_stats_open),}, | ||
273 | {"debug_zone", 0666, FOPS_RW(rsi_debug_read, rsi_debug_zone_write),}, | ||
274 | {"sdio_stats", 0644, FOPS(rsi_sdio_stats_open),}, | ||
275 | }; | ||
276 | |||
277 | /** | ||
278 | * rsi_init_dbgfs() - This function initializes the dbgfs entry. | ||
279 | * @adapter: Pointer to the adapter structure. | ||
280 | * | ||
281 | * Return: 0 on success, -1 on failure. | ||
282 | */ | ||
283 | int rsi_init_dbgfs(struct rsi_hw *adapter) | ||
284 | { | ||
285 | struct rsi_common *common = adapter->priv; | ||
286 | struct rsi_debugfs *dev_dbgfs; | ||
287 | char devdir[6]; | ||
288 | int ii; | ||
289 | const struct rsi_dbg_files *files; | ||
290 | |||
291 | dev_dbgfs = kzalloc(sizeof(*dev_dbgfs), GFP_KERNEL); | ||
292 | adapter->dfsentry = dev_dbgfs; | ||
293 | |||
294 | snprintf(devdir, sizeof(devdir), "%s", | ||
295 | wiphy_name(adapter->hw->wiphy)); | ||
296 | dev_dbgfs->subdir = debugfs_create_dir(devdir, NULL); | ||
297 | |||
298 | if (IS_ERR(dev_dbgfs->subdir)) { | ||
299 | if (dev_dbgfs->subdir == ERR_PTR(-ENODEV)) | ||
300 | rsi_dbg(ERR_ZONE, | ||
301 | "%s:Debugfs has not been mounted\n", __func__); | ||
302 | else | ||
303 | rsi_dbg(ERR_ZONE, "debugfs:%s not created\n", devdir); | ||
304 | |||
305 | adapter->dfsentry = NULL; | ||
306 | kfree(dev_dbgfs); | ||
307 | return (int)PTR_ERR(dev_dbgfs->subdir); | ||
308 | } else { | ||
309 | for (ii = 0; ii < adapter->num_debugfs_entries; ii++) { | ||
310 | files = &dev_debugfs_files[ii]; | ||
311 | dev_dbgfs->rsi_files[ii] = | ||
312 | debugfs_create_file(files->name, | ||
313 | files->perms, | ||
314 | dev_dbgfs->subdir, | ||
315 | common, | ||
316 | &files->fops); | ||
317 | } | ||
318 | } | ||
319 | return 0; | ||
320 | } | ||
321 | EXPORT_SYMBOL_GPL(rsi_init_dbgfs); | ||
322 | |||
323 | /** | ||
324 | * rsi_remove_dbgfs() - Removes the previously created dbgfs file entries | ||
325 | * in the reverse order of creation. | ||
326 | * @adapter: Pointer to the adapter structure. | ||
327 | * | ||
328 | * Return: None. | ||
329 | */ | ||
330 | void rsi_remove_dbgfs(struct rsi_hw *adapter) | ||
331 | { | ||
332 | struct rsi_debugfs *dev_dbgfs = adapter->dfsentry; | ||
333 | |||
334 | if (!dev_dbgfs) | ||
335 | return; | ||
336 | |||
337 | debugfs_remove_recursive(dev_dbgfs->subdir); | ||
338 | } | ||
339 | EXPORT_SYMBOL_GPL(rsi_remove_dbgfs); | ||
diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c new file mode 100644 index 000000000000..84164747ace0 --- /dev/null +++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c | |||
@@ -0,0 +1,1008 @@ | |||
1 | /** | ||
2 | * Copyright (c) 2014 Redpine Signals Inc. | ||
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 | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include <linux/etherdevice.h> | ||
18 | #include "rsi_debugfs.h" | ||
19 | #include "rsi_mgmt.h" | ||
20 | #include "rsi_common.h" | ||
21 | |||
22 | static const struct ieee80211_channel rsi_2ghz_channels[] = { | ||
23 | { .band = IEEE80211_BAND_2GHZ, .center_freq = 2412, | ||
24 | .hw_value = 1 }, /* Channel 1 */ | ||
25 | { .band = IEEE80211_BAND_2GHZ, .center_freq = 2417, | ||
26 | .hw_value = 2 }, /* Channel 2 */ | ||
27 | { .band = IEEE80211_BAND_2GHZ, .center_freq = 2422, | ||
28 | .hw_value = 3 }, /* Channel 3 */ | ||
29 | { .band = IEEE80211_BAND_2GHZ, .center_freq = 2427, | ||
30 | .hw_value = 4 }, /* Channel 4 */ | ||
31 | { .band = IEEE80211_BAND_2GHZ, .center_freq = 2432, | ||
32 | .hw_value = 5 }, /* Channel 5 */ | ||
33 | { .band = IEEE80211_BAND_2GHZ, .center_freq = 2437, | ||
34 | .hw_value = 6 }, /* Channel 6 */ | ||
35 | { .band = IEEE80211_BAND_2GHZ, .center_freq = 2442, | ||
36 | .hw_value = 7 }, /* Channel 7 */ | ||
37 | { .band = IEEE80211_BAND_2GHZ, .center_freq = 2447, | ||
38 | .hw_value = 8 }, /* Channel 8 */ | ||
39 | { .band = IEEE80211_BAND_2GHZ, .center_freq = 2452, | ||
40 | .hw_value = 9 }, /* Channel 9 */ | ||
41 | { .band = IEEE80211_BAND_2GHZ, .center_freq = 2457, | ||
42 | .hw_value = 10 }, /* Channel 10 */ | ||
43 | { .band = IEEE80211_BAND_2GHZ, .center_freq = 2462, | ||
44 | .hw_value = 11 }, /* Channel 11 */ | ||
45 | { .band = IEEE80211_BAND_2GHZ, .center_freq = 2467, | ||
46 | .hw_value = 12 }, /* Channel 12 */ | ||
47 | { .band = IEEE80211_BAND_2GHZ, .center_freq = 2472, | ||
48 | .hw_value = 13 }, /* Channel 13 */ | ||
49 | { .band = IEEE80211_BAND_2GHZ, .center_freq = 2484, | ||
50 | .hw_value = 14 }, /* Channel 14 */ | ||
51 | }; | ||
52 | |||
53 | static const struct ieee80211_channel rsi_5ghz_channels[] = { | ||
54 | { .band = IEEE80211_BAND_5GHZ, .center_freq = 5180, | ||
55 | .hw_value = 36, }, /* Channel 36 */ | ||
56 | { .band = IEEE80211_BAND_5GHZ, .center_freq = 5200, | ||
57 | .hw_value = 40, }, /* Channel 40 */ | ||
58 | { .band = IEEE80211_BAND_5GHZ, .center_freq = 5220, | ||
59 | .hw_value = 44, }, /* Channel 44 */ | ||
60 | { .band = IEEE80211_BAND_5GHZ, .center_freq = 5240, | ||
61 | .hw_value = 48, }, /* Channel 48 */ | ||
62 | { .band = IEEE80211_BAND_5GHZ, .center_freq = 5260, | ||
63 | .hw_value = 52, }, /* Channel 52 */ | ||
64 | { .band = IEEE80211_BAND_5GHZ, .center_freq = 5280, | ||
65 | .hw_value = 56, }, /* Channel 56 */ | ||
66 | { .band = IEEE80211_BAND_5GHZ, .center_freq = 5300, | ||
67 | .hw_value = 60, }, /* Channel 60 */ | ||
68 | { .band = IEEE80211_BAND_5GHZ, .center_freq = 5320, | ||
69 | .hw_value = 64, }, /* Channel 64 */ | ||
70 | { .band = IEEE80211_BAND_5GHZ, .center_freq = 5500, | ||
71 | .hw_value = 100, }, /* Channel 100 */ | ||
72 | { .band = IEEE80211_BAND_5GHZ, .center_freq = 5520, | ||
73 | .hw_value = 104, }, /* Channel 104 */ | ||
74 | { .band = IEEE80211_BAND_5GHZ, .center_freq = 5540, | ||
75 | .hw_value = 108, }, /* Channel 108 */ | ||
76 | { .band = IEEE80211_BAND_5GHZ, .center_freq = 5560, | ||
77 | .hw_value = 112, }, /* Channel 112 */ | ||
78 | { .band = IEEE80211_BAND_5GHZ, .center_freq = 5580, | ||
79 | .hw_value = 116, }, /* Channel 116 */ | ||
80 | { .band = IEEE80211_BAND_5GHZ, .center_freq = 5600, | ||
81 | .hw_value = 120, }, /* Channel 120 */ | ||
82 | { .band = IEEE80211_BAND_5GHZ, .center_freq = 5620, | ||
83 | .hw_value = 124, }, /* Channel 124 */ | ||
84 | { .band = IEEE80211_BAND_5GHZ, .center_freq = 5640, | ||
85 | .hw_value = 128, }, /* Channel 128 */ | ||
86 | { .band = IEEE80211_BAND_5GHZ, .center_freq = 5660, | ||
87 | .hw_value = 132, }, /* Channel 132 */ | ||
88 | { .band = IEEE80211_BAND_5GHZ, .center_freq = 5680, | ||
89 | .hw_value = 136, }, /* Channel 136 */ | ||
90 | { .band = IEEE80211_BAND_5GHZ, .center_freq = 5700, | ||
91 | .hw_value = 140, }, /* Channel 140 */ | ||
92 | { .band = IEEE80211_BAND_5GHZ, .center_freq = 5745, | ||
93 | .hw_value = 149, }, /* Channel 149 */ | ||
94 | { .band = IEEE80211_BAND_5GHZ, .center_freq = 5765, | ||
95 | .hw_value = 153, }, /* Channel 153 */ | ||
96 | { .band = IEEE80211_BAND_5GHZ, .center_freq = 5785, | ||
97 | .hw_value = 157, }, /* Channel 157 */ | ||
98 | { .band = IEEE80211_BAND_5GHZ, .center_freq = 5805, | ||
99 | .hw_value = 161, }, /* Channel 161 */ | ||
100 | { .band = IEEE80211_BAND_5GHZ, .center_freq = 5825, | ||
101 | .hw_value = 165, }, /* Channel 165 */ | ||
102 | }; | ||
103 | |||
104 | struct ieee80211_rate rsi_rates[12] = { | ||
105 | { .bitrate = STD_RATE_01 * 5, .hw_value = RSI_RATE_1 }, | ||
106 | { .bitrate = STD_RATE_02 * 5, .hw_value = RSI_RATE_2 }, | ||
107 | { .bitrate = STD_RATE_5_5 * 5, .hw_value = RSI_RATE_5_5 }, | ||
108 | { .bitrate = STD_RATE_11 * 5, .hw_value = RSI_RATE_11 }, | ||
109 | { .bitrate = STD_RATE_06 * 5, .hw_value = RSI_RATE_6 }, | ||
110 | { .bitrate = STD_RATE_09 * 5, .hw_value = RSI_RATE_9 }, | ||
111 | { .bitrate = STD_RATE_12 * 5, .hw_value = RSI_RATE_12 }, | ||
112 | { .bitrate = STD_RATE_18 * 5, .hw_value = RSI_RATE_18 }, | ||
113 | { .bitrate = STD_RATE_24 * 5, .hw_value = RSI_RATE_24 }, | ||
114 | { .bitrate = STD_RATE_36 * 5, .hw_value = RSI_RATE_36 }, | ||
115 | { .bitrate = STD_RATE_48 * 5, .hw_value = RSI_RATE_48 }, | ||
116 | { .bitrate = STD_RATE_54 * 5, .hw_value = RSI_RATE_54 }, | ||
117 | }; | ||
118 | |||
119 | const u16 rsi_mcsrates[8] = { | ||
120 | RSI_RATE_MCS0, RSI_RATE_MCS1, RSI_RATE_MCS2, RSI_RATE_MCS3, | ||
121 | RSI_RATE_MCS4, RSI_RATE_MCS5, RSI_RATE_MCS6, RSI_RATE_MCS7 | ||
122 | }; | ||
123 | |||
124 | /** | ||
125 | * rsi_is_cipher_wep() - This function determines if the cipher is WEP or not. | ||
126 | * @common: Pointer to the driver private structure. | ||
127 | * | ||
128 | * Return: If cipher type is WEP, a value of 1 is returned, else 0. | ||
129 | */ | ||
130 | |||
131 | bool rsi_is_cipher_wep(struct rsi_common *common) | ||
132 | { | ||
133 | if (((common->secinfo.gtk_cipher == WLAN_CIPHER_SUITE_WEP104) || | ||
134 | (common->secinfo.gtk_cipher == WLAN_CIPHER_SUITE_WEP40)) && | ||
135 | (!common->secinfo.ptk_cipher)) | ||
136 | return true; | ||
137 | else | ||
138 | return false; | ||
139 | } | ||
140 | |||
141 | /** | ||
142 | * rsi_register_rates_channels() - This function registers channels and rates. | ||
143 | * @adapter: Pointer to the adapter structure. | ||
144 | * @band: Operating band to be set. | ||
145 | * | ||
146 | * Return: None. | ||
147 | */ | ||
148 | static void rsi_register_rates_channels(struct rsi_hw *adapter, int band) | ||
149 | { | ||
150 | struct ieee80211_supported_band *sbands = &adapter->sbands[band]; | ||
151 | void *channels = NULL; | ||
152 | |||
153 | if (band == IEEE80211_BAND_2GHZ) { | ||
154 | channels = kmalloc(sizeof(rsi_2ghz_channels), GFP_KERNEL); | ||
155 | memcpy(channels, | ||
156 | rsi_2ghz_channels, | ||
157 | sizeof(rsi_2ghz_channels)); | ||
158 | sbands->band = IEEE80211_BAND_2GHZ; | ||
159 | sbands->n_channels = ARRAY_SIZE(rsi_2ghz_channels); | ||
160 | sbands->bitrates = rsi_rates; | ||
161 | sbands->n_bitrates = ARRAY_SIZE(rsi_rates); | ||
162 | } else { | ||
163 | channels = kmalloc(sizeof(rsi_5ghz_channels), GFP_KERNEL); | ||
164 | memcpy(channels, | ||
165 | rsi_5ghz_channels, | ||
166 | sizeof(rsi_5ghz_channels)); | ||
167 | sbands->band = IEEE80211_BAND_5GHZ; | ||
168 | sbands->n_channels = ARRAY_SIZE(rsi_5ghz_channels); | ||
169 | sbands->bitrates = &rsi_rates[4]; | ||
170 | sbands->n_bitrates = ARRAY_SIZE(rsi_rates) - 4; | ||
171 | } | ||
172 | |||
173 | sbands->channels = channels; | ||
174 | |||
175 | memset(&sbands->ht_cap, 0, sizeof(struct ieee80211_sta_ht_cap)); | ||
176 | sbands->ht_cap.ht_supported = true; | ||
177 | sbands->ht_cap.cap = (IEEE80211_HT_CAP_SUP_WIDTH_20_40 | | ||
178 | IEEE80211_HT_CAP_SGI_20 | | ||
179 | IEEE80211_HT_CAP_SGI_40); | ||
180 | sbands->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K; | ||
181 | sbands->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE; | ||
182 | sbands->ht_cap.mcs.rx_mask[0] = 0xff; | ||
183 | sbands->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; | ||
184 | /* sbands->ht_cap.mcs.rx_highest = 0x82; */ | ||
185 | } | ||
186 | |||
187 | /** | ||
188 | * rsi_mac80211_attach() - This function is used to de-initialize the | ||
189 | * Mac80211 stack. | ||
190 | * @adapter: Pointer to the adapter structure. | ||
191 | * | ||
192 | * Return: None. | ||
193 | */ | ||
194 | void rsi_mac80211_detach(struct rsi_hw *adapter) | ||
195 | { | ||
196 | struct ieee80211_hw *hw = adapter->hw; | ||
197 | |||
198 | if (hw) { | ||
199 | ieee80211_stop_queues(hw); | ||
200 | ieee80211_unregister_hw(hw); | ||
201 | ieee80211_free_hw(hw); | ||
202 | } | ||
203 | |||
204 | rsi_remove_dbgfs(adapter); | ||
205 | } | ||
206 | EXPORT_SYMBOL_GPL(rsi_mac80211_detach); | ||
207 | |||
208 | /** | ||
209 | * rsi_indicate_tx_status() - This function indicates the transmit status. | ||
210 | * @adapter: Pointer to the adapter structure. | ||
211 | * @skb: Pointer to the socket buffer structure. | ||
212 | * @status: Status | ||
213 | * | ||
214 | * Return: None. | ||
215 | */ | ||
216 | void rsi_indicate_tx_status(struct rsi_hw *adapter, | ||
217 | struct sk_buff *skb, | ||
218 | int status) | ||
219 | { | ||
220 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
221 | |||
222 | memset(info->driver_data, 0, IEEE80211_TX_INFO_DRIVER_DATA_SIZE); | ||
223 | |||
224 | if (!status) | ||
225 | info->flags |= IEEE80211_TX_STAT_ACK; | ||
226 | |||
227 | ieee80211_tx_status_irqsafe(adapter->hw, skb); | ||
228 | } | ||
229 | |||
230 | /** | ||
231 | * rsi_mac80211_tx() - This is the handler that 802.11 module calls for each | ||
232 | * transmitted frame.SKB contains the buffer starting | ||
233 | * from the IEEE 802.11 header. | ||
234 | * @hw: Pointer to the ieee80211_hw structure. | ||
235 | * @control: Pointer to the ieee80211_tx_control structure | ||
236 | * @skb: Pointer to the socket buffer structure. | ||
237 | * | ||
238 | * Return: None | ||
239 | */ | ||
240 | static void rsi_mac80211_tx(struct ieee80211_hw *hw, | ||
241 | struct ieee80211_tx_control *control, | ||
242 | struct sk_buff *skb) | ||
243 | { | ||
244 | struct rsi_hw *adapter = hw->priv; | ||
245 | struct rsi_common *common = adapter->priv; | ||
246 | |||
247 | rsi_core_xmit(common, skb); | ||
248 | } | ||
249 | |||
250 | /** | ||
251 | * rsi_mac80211_start() - This is first handler that 802.11 module calls, since | ||
252 | * the driver init is complete by then, just | ||
253 | * returns success. | ||
254 | * @hw: Pointer to the ieee80211_hw structure. | ||
255 | * | ||
256 | * Return: 0 as success. | ||
257 | */ | ||
258 | static int rsi_mac80211_start(struct ieee80211_hw *hw) | ||
259 | { | ||
260 | struct rsi_hw *adapter = hw->priv; | ||
261 | struct rsi_common *common = adapter->priv; | ||
262 | |||
263 | mutex_lock(&common->mutex); | ||
264 | common->iface_down = false; | ||
265 | mutex_unlock(&common->mutex); | ||
266 | |||
267 | return 0; | ||
268 | } | ||
269 | |||
270 | /** | ||
271 | * rsi_mac80211_stop() - This is the last handler that 802.11 module calls. | ||
272 | * @hw: Pointer to the ieee80211_hw structure. | ||
273 | * | ||
274 | * Return: None. | ||
275 | */ | ||
276 | static void rsi_mac80211_stop(struct ieee80211_hw *hw) | ||
277 | { | ||
278 | struct rsi_hw *adapter = hw->priv; | ||
279 | struct rsi_common *common = adapter->priv; | ||
280 | |||
281 | mutex_lock(&common->mutex); | ||
282 | common->iface_down = true; | ||
283 | mutex_unlock(&common->mutex); | ||
284 | } | ||
285 | |||
286 | /** | ||
287 | * rsi_mac80211_add_interface() - This function is called when a netdevice | ||
288 | * attached to the hardware is enabled. | ||
289 | * @hw: Pointer to the ieee80211_hw structure. | ||
290 | * @vif: Pointer to the ieee80211_vif structure. | ||
291 | * | ||
292 | * Return: ret: 0 on success, negative error code on failure. | ||
293 | */ | ||
294 | static int rsi_mac80211_add_interface(struct ieee80211_hw *hw, | ||
295 | struct ieee80211_vif *vif) | ||
296 | { | ||
297 | struct rsi_hw *adapter = hw->priv; | ||
298 | struct rsi_common *common = adapter->priv; | ||
299 | int ret = -EOPNOTSUPP; | ||
300 | |||
301 | mutex_lock(&common->mutex); | ||
302 | switch (vif->type) { | ||
303 | case NL80211_IFTYPE_STATION: | ||
304 | if (!adapter->sc_nvifs) { | ||
305 | ++adapter->sc_nvifs; | ||
306 | adapter->vifs[0] = vif; | ||
307 | ret = rsi_set_vap_capabilities(common, STA_OPMODE); | ||
308 | } | ||
309 | break; | ||
310 | default: | ||
311 | rsi_dbg(ERR_ZONE, | ||
312 | "%s: Interface type %d not supported\n", __func__, | ||
313 | vif->type); | ||
314 | } | ||
315 | mutex_unlock(&common->mutex); | ||
316 | |||
317 | return ret; | ||
318 | } | ||
319 | |||
320 | /** | ||
321 | * rsi_mac80211_remove_interface() - This function notifies driver that an | ||
322 | * interface is going down. | ||
323 | * @hw: Pointer to the ieee80211_hw structure. | ||
324 | * @vif: Pointer to the ieee80211_vif structure. | ||
325 | * | ||
326 | * Return: None. | ||
327 | */ | ||
328 | static void rsi_mac80211_remove_interface(struct ieee80211_hw *hw, | ||
329 | struct ieee80211_vif *vif) | ||
330 | { | ||
331 | struct rsi_hw *adapter = hw->priv; | ||
332 | struct rsi_common *common = adapter->priv; | ||
333 | |||
334 | mutex_lock(&common->mutex); | ||
335 | if (vif->type == NL80211_IFTYPE_STATION) | ||
336 | adapter->sc_nvifs--; | ||
337 | |||
338 | if (!memcmp(adapter->vifs[0], vif, sizeof(struct ieee80211_vif))) | ||
339 | adapter->vifs[0] = NULL; | ||
340 | mutex_unlock(&common->mutex); | ||
341 | } | ||
342 | |||
343 | /** | ||
344 | * rsi_mac80211_config() - This function is a handler for configuration | ||
345 | * requests. The stack calls this function to | ||
346 | * change hardware configuration, e.g., channel. | ||
347 | * @hw: Pointer to the ieee80211_hw structure. | ||
348 | * @changed: Changed flags set. | ||
349 | * | ||
350 | * Return: 0 on success, negative error code on failure. | ||
351 | */ | ||
352 | static int rsi_mac80211_config(struct ieee80211_hw *hw, | ||
353 | u32 changed) | ||
354 | { | ||
355 | struct rsi_hw *adapter = hw->priv; | ||
356 | struct rsi_common *common = adapter->priv; | ||
357 | int status = -EOPNOTSUPP; | ||
358 | |||
359 | mutex_lock(&common->mutex); | ||
360 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { | ||
361 | struct ieee80211_channel *curchan = hw->conf.chandef.chan; | ||
362 | u16 channel = curchan->hw_value; | ||
363 | |||
364 | rsi_dbg(INFO_ZONE, | ||
365 | "%s: Set channel: %d MHz type: %d channel_no %d\n", | ||
366 | __func__, curchan->center_freq, | ||
367 | curchan->flags, channel); | ||
368 | common->band = curchan->band; | ||
369 | status = rsi_set_channel(adapter->priv, channel); | ||
370 | } | ||
371 | mutex_unlock(&common->mutex); | ||
372 | |||
373 | return status; | ||
374 | } | ||
375 | |||
376 | /** | ||
377 | * rsi_get_connected_channel() - This function is used to get the current | ||
378 | * connected channel number. | ||
379 | * @adapter: Pointer to the adapter structure. | ||
380 | * | ||
381 | * Return: Current connected AP's channel number is returned. | ||
382 | */ | ||
383 | u16 rsi_get_connected_channel(struct rsi_hw *adapter) | ||
384 | { | ||
385 | struct ieee80211_vif *vif = adapter->vifs[0]; | ||
386 | if (vif) { | ||
387 | struct ieee80211_bss_conf *bss = &vif->bss_conf; | ||
388 | struct ieee80211_channel *channel = bss->chandef.chan; | ||
389 | return channel->hw_value; | ||
390 | } | ||
391 | |||
392 | return 0; | ||
393 | } | ||
394 | |||
395 | /** | ||
396 | * rsi_mac80211_bss_info_changed() - This function is a handler for config | ||
397 | * requests related to BSS parameters that | ||
398 | * may vary during BSS's lifespan. | ||
399 | * @hw: Pointer to the ieee80211_hw structure. | ||
400 | * @vif: Pointer to the ieee80211_vif structure. | ||
401 | * @bss_conf: Pointer to the ieee80211_bss_conf structure. | ||
402 | * @changed: Changed flags set. | ||
403 | * | ||
404 | * Return: None. | ||
405 | */ | ||
406 | static void rsi_mac80211_bss_info_changed(struct ieee80211_hw *hw, | ||
407 | struct ieee80211_vif *vif, | ||
408 | struct ieee80211_bss_conf *bss_conf, | ||
409 | u32 changed) | ||
410 | { | ||
411 | struct rsi_hw *adapter = hw->priv; | ||
412 | struct rsi_common *common = adapter->priv; | ||
413 | |||
414 | mutex_lock(&common->mutex); | ||
415 | if (changed & BSS_CHANGED_ASSOC) { | ||
416 | rsi_dbg(INFO_ZONE, "%s: Changed Association status: %d\n", | ||
417 | __func__, bss_conf->assoc); | ||
418 | rsi_inform_bss_status(common, | ||
419 | bss_conf->assoc, | ||
420 | bss_conf->bssid, | ||
421 | bss_conf->qos, | ||
422 | bss_conf->aid); | ||
423 | } | ||
424 | mutex_unlock(&common->mutex); | ||
425 | } | ||
426 | |||
427 | /** | ||
428 | * rsi_mac80211_conf_filter() - This function configure the device's RX filter. | ||
429 | * @hw: Pointer to the ieee80211_hw structure. | ||
430 | * @changed: Changed flags set. | ||
431 | * @total_flags: Total initial flags set. | ||
432 | * @multicast: Multicast. | ||
433 | * | ||
434 | * Return: None. | ||
435 | */ | ||
436 | static void rsi_mac80211_conf_filter(struct ieee80211_hw *hw, | ||
437 | u32 changed_flags, | ||
438 | u32 *total_flags, | ||
439 | u64 multicast) | ||
440 | { | ||
441 | /* Not doing much here as of now */ | ||
442 | *total_flags &= RSI_SUPP_FILTERS; | ||
443 | } | ||
444 | |||
445 | /** | ||
446 | * rsi_mac80211_conf_tx() - This function configures TX queue parameters | ||
447 | * (EDCF (aifs, cw_min, cw_max), bursting) | ||
448 | * for a hardware TX queue. | ||
449 | * @hw: Pointer to the ieee80211_hw structure | ||
450 | * @vif: Pointer to the ieee80211_vif structure. | ||
451 | * @queue: Queue number. | ||
452 | * @params: Pointer to ieee80211_tx_queue_params structure. | ||
453 | * | ||
454 | * Return: 0 on success, negative error code on failure. | ||
455 | */ | ||
456 | static int rsi_mac80211_conf_tx(struct ieee80211_hw *hw, | ||
457 | struct ieee80211_vif *vif, u16 queue, | ||
458 | const struct ieee80211_tx_queue_params *params) | ||
459 | { | ||
460 | struct rsi_hw *adapter = hw->priv; | ||
461 | struct rsi_common *common = adapter->priv; | ||
462 | u8 idx = 0; | ||
463 | |||
464 | if (queue >= IEEE80211_NUM_ACS) | ||
465 | return 0; | ||
466 | |||
467 | rsi_dbg(INFO_ZONE, | ||
468 | "%s: Conf queue %d, aifs: %d, cwmin: %d cwmax: %d, txop: %d\n", | ||
469 | __func__, queue, params->aifs, | ||
470 | params->cw_min, params->cw_max, params->txop); | ||
471 | |||
472 | mutex_lock(&common->mutex); | ||
473 | /* Map into the way the f/w expects */ | ||
474 | switch (queue) { | ||
475 | case IEEE80211_AC_VO: | ||
476 | idx = VO_Q; | ||
477 | break; | ||
478 | case IEEE80211_AC_VI: | ||
479 | idx = VI_Q; | ||
480 | break; | ||
481 | case IEEE80211_AC_BE: | ||
482 | idx = BE_Q; | ||
483 | break; | ||
484 | case IEEE80211_AC_BK: | ||
485 | idx = BK_Q; | ||
486 | break; | ||
487 | default: | ||
488 | idx = BE_Q; | ||
489 | break; | ||
490 | } | ||
491 | |||
492 | memcpy(&common->edca_params[idx], | ||
493 | params, | ||
494 | sizeof(struct ieee80211_tx_queue_params)); | ||
495 | mutex_unlock(&common->mutex); | ||
496 | |||
497 | return 0; | ||
498 | } | ||
499 | |||
500 | /** | ||
501 | * rsi_hal_key_config() - This function loads the keys into the firmware. | ||
502 | * @hw: Pointer to the ieee80211_hw structure. | ||
503 | * @vif: Pointer to the ieee80211_vif structure. | ||
504 | * @key: Pointer to the ieee80211_key_conf structure. | ||
505 | * | ||
506 | * Return: status: 0 on success, -1 on failure. | ||
507 | */ | ||
508 | static int rsi_hal_key_config(struct ieee80211_hw *hw, | ||
509 | struct ieee80211_vif *vif, | ||
510 | struct ieee80211_key_conf *key) | ||
511 | { | ||
512 | struct rsi_hw *adapter = hw->priv; | ||
513 | int status; | ||
514 | u8 key_type; | ||
515 | |||
516 | if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) | ||
517 | key_type = RSI_PAIRWISE_KEY; | ||
518 | else | ||
519 | key_type = RSI_GROUP_KEY; | ||
520 | |||
521 | rsi_dbg(ERR_ZONE, "%s: Cipher 0x%x key_type: %d key_len: %d\n", | ||
522 | __func__, key->cipher, key_type, key->keylen); | ||
523 | |||
524 | if ((key->cipher == WLAN_CIPHER_SUITE_WEP104) || | ||
525 | (key->cipher == WLAN_CIPHER_SUITE_WEP40)) { | ||
526 | status = rsi_hal_load_key(adapter->priv, | ||
527 | key->key, | ||
528 | key->keylen, | ||
529 | RSI_PAIRWISE_KEY, | ||
530 | key->keyidx, | ||
531 | key->cipher); | ||
532 | if (status) | ||
533 | return status; | ||
534 | } | ||
535 | return rsi_hal_load_key(adapter->priv, | ||
536 | key->key, | ||
537 | key->keylen, | ||
538 | key_type, | ||
539 | key->keyidx, | ||
540 | key->cipher); | ||
541 | } | ||
542 | |||
543 | /** | ||
544 | * rsi_mac80211_set_key() - This function sets type of key to be loaded. | ||
545 | * @hw: Pointer to the ieee80211_hw structure. | ||
546 | * @cmd: enum set_key_cmd. | ||
547 | * @vif: Pointer to the ieee80211_vif structure. | ||
548 | * @sta: Pointer to the ieee80211_sta structure. | ||
549 | * @key: Pointer to the ieee80211_key_conf structure. | ||
550 | * | ||
551 | * Return: status: 0 on success, negative error code on failure. | ||
552 | */ | ||
553 | static int rsi_mac80211_set_key(struct ieee80211_hw *hw, | ||
554 | enum set_key_cmd cmd, | ||
555 | struct ieee80211_vif *vif, | ||
556 | struct ieee80211_sta *sta, | ||
557 | struct ieee80211_key_conf *key) | ||
558 | { | ||
559 | struct rsi_hw *adapter = hw->priv; | ||
560 | struct rsi_common *common = adapter->priv; | ||
561 | struct security_info *secinfo = &common->secinfo; | ||
562 | int status; | ||
563 | |||
564 | mutex_lock(&common->mutex); | ||
565 | switch (cmd) { | ||
566 | case SET_KEY: | ||
567 | secinfo->security_enable = true; | ||
568 | status = rsi_hal_key_config(hw, vif, key); | ||
569 | if (status) { | ||
570 | mutex_unlock(&common->mutex); | ||
571 | return status; | ||
572 | } | ||
573 | |||
574 | if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) | ||
575 | secinfo->ptk_cipher = key->cipher; | ||
576 | else | ||
577 | secinfo->gtk_cipher = key->cipher; | ||
578 | |||
579 | key->hw_key_idx = key->keyidx; | ||
580 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | ||
581 | |||
582 | rsi_dbg(ERR_ZONE, "%s: RSI set_key\n", __func__); | ||
583 | break; | ||
584 | |||
585 | case DISABLE_KEY: | ||
586 | secinfo->security_enable = false; | ||
587 | rsi_dbg(ERR_ZONE, "%s: RSI del key\n", __func__); | ||
588 | memset(key, 0, sizeof(struct ieee80211_key_conf)); | ||
589 | status = rsi_hal_key_config(hw, vif, key); | ||
590 | break; | ||
591 | |||
592 | default: | ||
593 | status = -EOPNOTSUPP; | ||
594 | break; | ||
595 | } | ||
596 | |||
597 | mutex_unlock(&common->mutex); | ||
598 | return status; | ||
599 | } | ||
600 | |||
601 | /** | ||
602 | * rsi_mac80211_ampdu_action() - This function selects the AMPDU action for | ||
603 | * the corresponding mlme_action flag and | ||
604 | * informs the f/w regarding this. | ||
605 | * @hw: Pointer to the ieee80211_hw structure. | ||
606 | * @vif: Pointer to the ieee80211_vif structure. | ||
607 | * @action: ieee80211_ampdu_mlme_action enum. | ||
608 | * @sta: Pointer to the ieee80211_sta structure. | ||
609 | * @tid: Traffic identifier. | ||
610 | * @ssn: Pointer to ssn value. | ||
611 | * @buf_size: Buffer size (for kernel version > 2.6.38). | ||
612 | * | ||
613 | * Return: status: 0 on success, negative error code on failure. | ||
614 | */ | ||
615 | static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw, | ||
616 | struct ieee80211_vif *vif, | ||
617 | enum ieee80211_ampdu_mlme_action action, | ||
618 | struct ieee80211_sta *sta, | ||
619 | unsigned short tid, | ||
620 | unsigned short *ssn, | ||
621 | unsigned char buf_size) | ||
622 | { | ||
623 | int status = -EOPNOTSUPP; | ||
624 | struct rsi_hw *adapter = hw->priv; | ||
625 | struct rsi_common *common = adapter->priv; | ||
626 | u16 seq_no = 0; | ||
627 | u8 ii = 0; | ||
628 | |||
629 | for (ii = 0; ii < RSI_MAX_VIFS; ii++) { | ||
630 | if (vif == adapter->vifs[ii]) | ||
631 | break; | ||
632 | } | ||
633 | |||
634 | mutex_lock(&common->mutex); | ||
635 | rsi_dbg(INFO_ZONE, "%s: AMPDU action %d called\n", __func__, action); | ||
636 | if (ssn != NULL) | ||
637 | seq_no = *ssn; | ||
638 | |||
639 | switch (action) { | ||
640 | case IEEE80211_AMPDU_RX_START: | ||
641 | status = rsi_send_aggregation_params_frame(common, | ||
642 | tid, | ||
643 | seq_no, | ||
644 | buf_size, | ||
645 | STA_RX_ADDBA_DONE); | ||
646 | break; | ||
647 | |||
648 | case IEEE80211_AMPDU_RX_STOP: | ||
649 | status = rsi_send_aggregation_params_frame(common, | ||
650 | tid, | ||
651 | 0, | ||
652 | buf_size, | ||
653 | STA_RX_DELBA); | ||
654 | break; | ||
655 | |||
656 | case IEEE80211_AMPDU_TX_START: | ||
657 | common->vif_info[ii].seq_start = seq_no; | ||
658 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); | ||
659 | break; | ||
660 | |||
661 | case IEEE80211_AMPDU_TX_STOP_CONT: | ||
662 | case IEEE80211_AMPDU_TX_STOP_FLUSH: | ||
663 | case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: | ||
664 | status = rsi_send_aggregation_params_frame(common, | ||
665 | tid, | ||
666 | seq_no, | ||
667 | buf_size, | ||
668 | STA_TX_DELBA); | ||
669 | if (!status) | ||
670 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); | ||
671 | break; | ||
672 | |||
673 | case IEEE80211_AMPDU_TX_OPERATIONAL: | ||
674 | status = rsi_send_aggregation_params_frame(common, | ||
675 | tid, | ||
676 | common->vif_info[ii] | ||
677 | .seq_start, | ||
678 | buf_size, | ||
679 | STA_TX_ADDBA_DONE); | ||
680 | break; | ||
681 | |||
682 | default: | ||
683 | rsi_dbg(ERR_ZONE, "%s: Uknown AMPDU action\n", __func__); | ||
684 | break; | ||
685 | } | ||
686 | |||
687 | mutex_unlock(&common->mutex); | ||
688 | return status; | ||
689 | } | ||
690 | |||
691 | /** | ||
692 | * rsi_mac80211_set_rts_threshold() - This function sets rts threshold value. | ||
693 | * @hw: Pointer to the ieee80211_hw structure. | ||
694 | * @value: Rts threshold value. | ||
695 | * | ||
696 | * Return: 0 on success. | ||
697 | */ | ||
698 | static int rsi_mac80211_set_rts_threshold(struct ieee80211_hw *hw, | ||
699 | u32 value) | ||
700 | { | ||
701 | struct rsi_hw *adapter = hw->priv; | ||
702 | struct rsi_common *common = adapter->priv; | ||
703 | |||
704 | mutex_lock(&common->mutex); | ||
705 | common->rts_threshold = value; | ||
706 | mutex_unlock(&common->mutex); | ||
707 | |||
708 | return 0; | ||
709 | } | ||
710 | |||
711 | /** | ||
712 | * rsi_mac80211_set_rate_mask() - This function sets bitrate_mask to be used. | ||
713 | * @hw: Pointer to the ieee80211_hw structure | ||
714 | * @vif: Pointer to the ieee80211_vif structure. | ||
715 | * @mask: Pointer to the cfg80211_bitrate_mask structure. | ||
716 | * | ||
717 | * Return: 0 on success. | ||
718 | */ | ||
719 | static int rsi_mac80211_set_rate_mask(struct ieee80211_hw *hw, | ||
720 | struct ieee80211_vif *vif, | ||
721 | const struct cfg80211_bitrate_mask *mask) | ||
722 | { | ||
723 | struct rsi_hw *adapter = hw->priv; | ||
724 | struct rsi_common *common = adapter->priv; | ||
725 | |||
726 | mutex_lock(&common->mutex); | ||
727 | |||
728 | common->fixedrate_mask[IEEE80211_BAND_2GHZ] = 0; | ||
729 | |||
730 | if (mask->control[IEEE80211_BAND_2GHZ].legacy == 0xfff) { | ||
731 | common->fixedrate_mask[IEEE80211_BAND_2GHZ] = | ||
732 | (mask->control[IEEE80211_BAND_2GHZ].ht_mcs[0] << 12); | ||
733 | } else { | ||
734 | common->fixedrate_mask[IEEE80211_BAND_2GHZ] = | ||
735 | mask->control[IEEE80211_BAND_2GHZ].legacy; | ||
736 | } | ||
737 | mutex_unlock(&common->mutex); | ||
738 | |||
739 | return 0; | ||
740 | } | ||
741 | |||
742 | /** | ||
743 | * rsi_fill_rx_status() - This function fills rx status in | ||
744 | * ieee80211_rx_status structure. | ||
745 | * @hw: Pointer to the ieee80211_hw structure. | ||
746 | * @skb: Pointer to the socket buffer structure. | ||
747 | * @common: Pointer to the driver private structure. | ||
748 | * @rxs: Pointer to the ieee80211_rx_status structure. | ||
749 | * | ||
750 | * Return: None. | ||
751 | */ | ||
752 | static void rsi_fill_rx_status(struct ieee80211_hw *hw, | ||
753 | struct sk_buff *skb, | ||
754 | struct rsi_common *common, | ||
755 | struct ieee80211_rx_status *rxs) | ||
756 | { | ||
757 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
758 | struct skb_info *rx_params = (struct skb_info *)info->driver_data; | ||
759 | struct ieee80211_hdr *hdr; | ||
760 | char rssi = rx_params->rssi; | ||
761 | u8 hdrlen = 0; | ||
762 | u8 channel = rx_params->channel; | ||
763 | s32 freq; | ||
764 | |||
765 | hdr = ((struct ieee80211_hdr *)(skb->data)); | ||
766 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | ||
767 | |||
768 | memset(info, 0, sizeof(struct ieee80211_tx_info)); | ||
769 | |||
770 | rxs->signal = -(rssi); | ||
771 | |||
772 | if (channel <= 14) | ||
773 | rxs->band = IEEE80211_BAND_2GHZ; | ||
774 | else | ||
775 | rxs->band = IEEE80211_BAND_5GHZ; | ||
776 | |||
777 | freq = ieee80211_channel_to_frequency(channel, rxs->band); | ||
778 | |||
779 | if (freq) | ||
780 | rxs->freq = freq; | ||
781 | |||
782 | if (ieee80211_has_protected(hdr->frame_control)) { | ||
783 | if (rsi_is_cipher_wep(common)) { | ||
784 | memmove(skb->data + 4, skb->data, hdrlen); | ||
785 | skb_pull(skb, 4); | ||
786 | } else { | ||
787 | memmove(skb->data + 8, skb->data, hdrlen); | ||
788 | skb_pull(skb, 8); | ||
789 | rxs->flag |= RX_FLAG_MMIC_STRIPPED; | ||
790 | } | ||
791 | rxs->flag |= RX_FLAG_DECRYPTED; | ||
792 | rxs->flag |= RX_FLAG_IV_STRIPPED; | ||
793 | } | ||
794 | } | ||
795 | |||
796 | /** | ||
797 | * rsi_indicate_pkt_to_os() - This function sends recieved packet to mac80211. | ||
798 | * @common: Pointer to the driver private structure. | ||
799 | * @skb: Pointer to the socket buffer structure. | ||
800 | * | ||
801 | * Return: None. | ||
802 | */ | ||
803 | void rsi_indicate_pkt_to_os(struct rsi_common *common, | ||
804 | struct sk_buff *skb) | ||
805 | { | ||
806 | struct rsi_hw *adapter = common->priv; | ||
807 | struct ieee80211_hw *hw = adapter->hw; | ||
808 | struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); | ||
809 | |||
810 | if ((common->iface_down) || (!adapter->sc_nvifs)) { | ||
811 | dev_kfree_skb(skb); | ||
812 | return; | ||
813 | } | ||
814 | |||
815 | /* filling in the ieee80211_rx_status flags */ | ||
816 | rsi_fill_rx_status(hw, skb, common, rx_status); | ||
817 | |||
818 | ieee80211_rx_irqsafe(hw, skb); | ||
819 | } | ||
820 | |||
821 | static void rsi_set_min_rate(struct ieee80211_hw *hw, | ||
822 | struct ieee80211_sta *sta, | ||
823 | struct rsi_common *common) | ||
824 | { | ||
825 | u8 band = hw->conf.chandef.chan->band; | ||
826 | u8 ii; | ||
827 | u32 rate_bitmap; | ||
828 | bool matched = false; | ||
829 | |||
830 | common->bitrate_mask[band] = sta->supp_rates[band]; | ||
831 | |||
832 | rate_bitmap = (common->fixedrate_mask[band] & sta->supp_rates[band]); | ||
833 | |||
834 | if (rate_bitmap & 0xfff) { | ||
835 | /* Find out the min rate */ | ||
836 | for (ii = 0; ii < ARRAY_SIZE(rsi_rates); ii++) { | ||
837 | if (rate_bitmap & BIT(ii)) { | ||
838 | common->min_rate = rsi_rates[ii].hw_value; | ||
839 | matched = true; | ||
840 | break; | ||
841 | } | ||
842 | } | ||
843 | } | ||
844 | |||
845 | common->vif_info[0].is_ht = sta->ht_cap.ht_supported; | ||
846 | |||
847 | if ((common->vif_info[0].is_ht) && (rate_bitmap >> 12)) { | ||
848 | for (ii = 0; ii < ARRAY_SIZE(rsi_mcsrates); ii++) { | ||
849 | if ((rate_bitmap >> 12) & BIT(ii)) { | ||
850 | common->min_rate = rsi_mcsrates[ii]; | ||
851 | matched = true; | ||
852 | break; | ||
853 | } | ||
854 | } | ||
855 | } | ||
856 | |||
857 | if (!matched) | ||
858 | common->min_rate = 0xffff; | ||
859 | } | ||
860 | |||
861 | /** | ||
862 | * rsi_mac80211_sta_add() - This function notifies driver about a peer getting | ||
863 | * connected. | ||
864 | * @hw: pointer to the ieee80211_hw structure. | ||
865 | * @vif: Pointer to the ieee80211_vif structure. | ||
866 | * @sta: Pointer to the ieee80211_sta structure. | ||
867 | * | ||
868 | * Return: 0 on success, -1 on failure. | ||
869 | */ | ||
870 | static int rsi_mac80211_sta_add(struct ieee80211_hw *hw, | ||
871 | struct ieee80211_vif *vif, | ||
872 | struct ieee80211_sta *sta) | ||
873 | { | ||
874 | struct rsi_hw *adapter = hw->priv; | ||
875 | struct rsi_common *common = adapter->priv; | ||
876 | |||
877 | mutex_lock(&common->mutex); | ||
878 | |||
879 | rsi_set_min_rate(hw, sta, common); | ||
880 | |||
881 | if ((sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) || | ||
882 | (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40)) { | ||
883 | common->vif_info[0].sgi = true; | ||
884 | } | ||
885 | |||
886 | if (sta->ht_cap.ht_supported) | ||
887 | ieee80211_start_tx_ba_session(sta, 0, 0); | ||
888 | |||
889 | mutex_unlock(&common->mutex); | ||
890 | |||
891 | return 0; | ||
892 | } | ||
893 | |||
894 | /** | ||
895 | * rsi_mac80211_sta_remove() - This function notifies driver about a peer | ||
896 | * getting disconnected. | ||
897 | * @hw: Pointer to the ieee80211_hw structure. | ||
898 | * @vif: Pointer to the ieee80211_vif structure. | ||
899 | * @sta: Pointer to the ieee80211_sta structure. | ||
900 | * | ||
901 | * Return: 0 on success, -1 on failure. | ||
902 | */ | ||
903 | static int rsi_mac80211_sta_remove(struct ieee80211_hw *hw, | ||
904 | struct ieee80211_vif *vif, | ||
905 | struct ieee80211_sta *sta) | ||
906 | { | ||
907 | struct rsi_hw *adapter = hw->priv; | ||
908 | struct rsi_common *common = adapter->priv; | ||
909 | |||
910 | mutex_lock(&common->mutex); | ||
911 | /* Resetting all the fields to default values */ | ||
912 | common->bitrate_mask[IEEE80211_BAND_2GHZ] = 0; | ||
913 | common->bitrate_mask[IEEE80211_BAND_5GHZ] = 0; | ||
914 | common->min_rate = 0xffff; | ||
915 | common->vif_info[0].is_ht = false; | ||
916 | common->vif_info[0].sgi = false; | ||
917 | common->vif_info[0].seq_start = 0; | ||
918 | common->secinfo.ptk_cipher = 0; | ||
919 | common->secinfo.gtk_cipher = 0; | ||
920 | mutex_unlock(&common->mutex); | ||
921 | |||
922 | return 0; | ||
923 | } | ||
924 | |||
925 | static struct ieee80211_ops mac80211_ops = { | ||
926 | .tx = rsi_mac80211_tx, | ||
927 | .start = rsi_mac80211_start, | ||
928 | .stop = rsi_mac80211_stop, | ||
929 | .add_interface = rsi_mac80211_add_interface, | ||
930 | .remove_interface = rsi_mac80211_remove_interface, | ||
931 | .config = rsi_mac80211_config, | ||
932 | .bss_info_changed = rsi_mac80211_bss_info_changed, | ||
933 | .conf_tx = rsi_mac80211_conf_tx, | ||
934 | .configure_filter = rsi_mac80211_conf_filter, | ||
935 | .set_key = rsi_mac80211_set_key, | ||
936 | .set_rts_threshold = rsi_mac80211_set_rts_threshold, | ||
937 | .set_bitrate_mask = rsi_mac80211_set_rate_mask, | ||
938 | .ampdu_action = rsi_mac80211_ampdu_action, | ||
939 | .sta_add = rsi_mac80211_sta_add, | ||
940 | .sta_remove = rsi_mac80211_sta_remove, | ||
941 | }; | ||
942 | |||
943 | /** | ||
944 | * rsi_mac80211_attach() - This function is used to initialize Mac80211 stack. | ||
945 | * @common: Pointer to the driver private structure. | ||
946 | * | ||
947 | * Return: 0 on success, -1 on failure. | ||
948 | */ | ||
949 | int rsi_mac80211_attach(struct rsi_common *common) | ||
950 | { | ||
951 | int status = 0; | ||
952 | struct ieee80211_hw *hw = NULL; | ||
953 | struct wiphy *wiphy = NULL; | ||
954 | struct rsi_hw *adapter = common->priv; | ||
955 | u8 addr_mask[ETH_ALEN] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x3}; | ||
956 | |||
957 | rsi_dbg(INIT_ZONE, "%s: Performing mac80211 attach\n", __func__); | ||
958 | |||
959 | hw = ieee80211_alloc_hw(sizeof(struct rsi_hw), &mac80211_ops); | ||
960 | if (!hw) { | ||
961 | rsi_dbg(ERR_ZONE, "%s: ieee80211 hw alloc failed\n", __func__); | ||
962 | return -ENOMEM; | ||
963 | } | ||
964 | |||
965 | wiphy = hw->wiphy; | ||
966 | |||
967 | SET_IEEE80211_DEV(hw, adapter->device); | ||
968 | |||
969 | hw->priv = adapter; | ||
970 | adapter->hw = hw; | ||
971 | |||
972 | hw->flags = IEEE80211_HW_SIGNAL_DBM | | ||
973 | IEEE80211_HW_HAS_RATE_CONTROL | | ||
974 | IEEE80211_HW_AMPDU_AGGREGATION | | ||
975 | 0; | ||
976 | |||
977 | hw->queues = MAX_HW_QUEUES; | ||
978 | hw->extra_tx_headroom = RSI_NEEDED_HEADROOM; | ||
979 | |||
980 | hw->max_rates = 1; | ||
981 | hw->max_rate_tries = MAX_RETRIES; | ||
982 | |||
983 | hw->max_tx_aggregation_subframes = 6; | ||
984 | rsi_register_rates_channels(adapter, IEEE80211_BAND_2GHZ); | ||
985 | hw->rate_control_algorithm = "AARF"; | ||
986 | |||
987 | SET_IEEE80211_PERM_ADDR(hw, common->mac_addr); | ||
988 | ether_addr_copy(hw->wiphy->addr_mask, addr_mask); | ||
989 | |||
990 | wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); | ||
991 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | ||
992 | wiphy->retry_short = RETRY_SHORT; | ||
993 | wiphy->retry_long = RETRY_LONG; | ||
994 | wiphy->frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD; | ||
995 | wiphy->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; | ||
996 | wiphy->flags = 0; | ||
997 | |||
998 | wiphy->available_antennas_rx = 1; | ||
999 | wiphy->available_antennas_tx = 1; | ||
1000 | wiphy->bands[IEEE80211_BAND_2GHZ] = | ||
1001 | &adapter->sbands[IEEE80211_BAND_2GHZ]; | ||
1002 | |||
1003 | status = ieee80211_register_hw(hw); | ||
1004 | if (status) | ||
1005 | return status; | ||
1006 | |||
1007 | return rsi_init_dbgfs(adapter); | ||
1008 | } | ||
diff --git a/drivers/net/wireless/rsi/rsi_91x_main.c b/drivers/net/wireless/rsi/rsi_91x_main.c new file mode 100644 index 000000000000..8810862ae826 --- /dev/null +++ b/drivers/net/wireless/rsi/rsi_91x_main.c | |||
@@ -0,0 +1,295 @@ | |||
1 | /** | ||
2 | * Copyright (c) 2014 Redpine Signals Inc. | ||
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 | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
18 | |||
19 | #include <linux/module.h> | ||
20 | #include <linux/firmware.h> | ||
21 | #include "rsi_mgmt.h" | ||
22 | #include "rsi_common.h" | ||
23 | |||
24 | u32 rsi_zone_enabled = /* INFO_ZONE | | ||
25 | INIT_ZONE | | ||
26 | MGMT_TX_ZONE | | ||
27 | MGMT_RX_ZONE | | ||
28 | DATA_TX_ZONE | | ||
29 | DATA_RX_ZONE | | ||
30 | FSM_ZONE | | ||
31 | ISR_ZONE | */ | ||
32 | ERR_ZONE | | ||
33 | 0; | ||
34 | EXPORT_SYMBOL_GPL(rsi_zone_enabled); | ||
35 | |||
36 | /** | ||
37 | * rsi_dbg() - This function outputs informational messages. | ||
38 | * @zone: Zone of interest for output message. | ||
39 | * @fmt: printf-style format for output message. | ||
40 | * | ||
41 | * Return: none | ||
42 | */ | ||
43 | void rsi_dbg(u32 zone, const char *fmt, ...) | ||
44 | { | ||
45 | struct va_format vaf; | ||
46 | va_list args; | ||
47 | |||
48 | va_start(args, fmt); | ||
49 | |||
50 | vaf.fmt = fmt; | ||
51 | vaf.va = &args; | ||
52 | |||
53 | if (zone & rsi_zone_enabled) | ||
54 | pr_info("%pV", &vaf); | ||
55 | va_end(args); | ||
56 | } | ||
57 | EXPORT_SYMBOL_GPL(rsi_dbg); | ||
58 | |||
59 | /** | ||
60 | * rsi_prepare_skb() - This function prepares the skb. | ||
61 | * @common: Pointer to the driver private structure. | ||
62 | * @buffer: Pointer to the packet data. | ||
63 | * @pkt_len: Length of the packet. | ||
64 | * @extended_desc: Extended descriptor. | ||
65 | * | ||
66 | * Return: Successfully skb. | ||
67 | */ | ||
68 | static struct sk_buff *rsi_prepare_skb(struct rsi_common *common, | ||
69 | u8 *buffer, | ||
70 | u32 pkt_len, | ||
71 | u8 extended_desc) | ||
72 | { | ||
73 | struct ieee80211_tx_info *info; | ||
74 | struct skb_info *rx_params; | ||
75 | struct sk_buff *skb = NULL; | ||
76 | u8 payload_offset; | ||
77 | |||
78 | if (WARN(!pkt_len, "%s: Dummy pkt received", __func__)) | ||
79 | return NULL; | ||
80 | |||
81 | if (pkt_len > (RSI_RCV_BUFFER_LEN * 4)) { | ||
82 | rsi_dbg(ERR_ZONE, "%s: Pkt size > max rx buf size %d\n", | ||
83 | __func__, pkt_len); | ||
84 | pkt_len = RSI_RCV_BUFFER_LEN * 4; | ||
85 | } | ||
86 | |||
87 | pkt_len -= extended_desc; | ||
88 | skb = dev_alloc_skb(pkt_len + FRAME_DESC_SZ); | ||
89 | if (skb == NULL) | ||
90 | return NULL; | ||
91 | |||
92 | payload_offset = (extended_desc + FRAME_DESC_SZ); | ||
93 | skb_put(skb, pkt_len); | ||
94 | memcpy((skb->data), (buffer + payload_offset), skb->len); | ||
95 | |||
96 | info = IEEE80211_SKB_CB(skb); | ||
97 | rx_params = (struct skb_info *)info->driver_data; | ||
98 | rx_params->rssi = rsi_get_rssi(buffer); | ||
99 | rx_params->channel = rsi_get_connected_channel(common->priv); | ||
100 | |||
101 | return skb; | ||
102 | } | ||
103 | |||
104 | /** | ||
105 | * rsi_read_pkt() - This function reads frames from the card. | ||
106 | * @common: Pointer to the driver private structure. | ||
107 | * @rcv_pkt_len: Received pkt length. In case of USB it is 0. | ||
108 | * | ||
109 | * Return: 0 on success, -1 on failure. | ||
110 | */ | ||
111 | int rsi_read_pkt(struct rsi_common *common, s32 rcv_pkt_len) | ||
112 | { | ||
113 | u8 *frame_desc = NULL, extended_desc = 0; | ||
114 | u32 index, length = 0, queueno = 0; | ||
115 | u16 actual_length = 0, offset; | ||
116 | struct sk_buff *skb = NULL; | ||
117 | |||
118 | index = 0; | ||
119 | do { | ||
120 | frame_desc = &common->rx_data_pkt[index]; | ||
121 | actual_length = *(u16 *)&frame_desc[0]; | ||
122 | offset = *(u16 *)&frame_desc[2]; | ||
123 | |||
124 | queueno = rsi_get_queueno(frame_desc, offset); | ||
125 | length = rsi_get_length(frame_desc, offset); | ||
126 | extended_desc = rsi_get_extended_desc(frame_desc, offset); | ||
127 | |||
128 | switch (queueno) { | ||
129 | case RSI_WIFI_DATA_Q: | ||
130 | skb = rsi_prepare_skb(common, | ||
131 | (frame_desc + offset), | ||
132 | length, | ||
133 | extended_desc); | ||
134 | if (skb == NULL) | ||
135 | goto fail; | ||
136 | |||
137 | rsi_indicate_pkt_to_os(common, skb); | ||
138 | break; | ||
139 | |||
140 | case RSI_WIFI_MGMT_Q: | ||
141 | rsi_mgmt_pkt_recv(common, (frame_desc + offset)); | ||
142 | break; | ||
143 | |||
144 | default: | ||
145 | rsi_dbg(ERR_ZONE, "%s: pkt from invalid queue: %d\n", | ||
146 | __func__, queueno); | ||
147 | goto fail; | ||
148 | } | ||
149 | |||
150 | index += actual_length; | ||
151 | rcv_pkt_len -= actual_length; | ||
152 | } while (rcv_pkt_len > 0); | ||
153 | |||
154 | return 0; | ||
155 | fail: | ||
156 | return -EINVAL; | ||
157 | } | ||
158 | EXPORT_SYMBOL_GPL(rsi_read_pkt); | ||
159 | |||
160 | /** | ||
161 | * rsi_tx_scheduler_thread() - This function is a kernel thread to send the | ||
162 | * packets to the device. | ||
163 | * @common: Pointer to the driver private structure. | ||
164 | * | ||
165 | * Return: None. | ||
166 | */ | ||
167 | static void rsi_tx_scheduler_thread(struct rsi_common *common) | ||
168 | { | ||
169 | struct rsi_hw *adapter = common->priv; | ||
170 | u32 timeout = EVENT_WAIT_FOREVER; | ||
171 | |||
172 | do { | ||
173 | if (adapter->determine_event_timeout) | ||
174 | timeout = adapter->determine_event_timeout(adapter); | ||
175 | rsi_wait_event(&common->tx_thread.event, timeout); | ||
176 | rsi_reset_event(&common->tx_thread.event); | ||
177 | |||
178 | if (common->init_done) | ||
179 | rsi_core_qos_processor(common); | ||
180 | } while (atomic_read(&common->tx_thread.thread_done) == 0); | ||
181 | complete_and_exit(&common->tx_thread.completion, 0); | ||
182 | } | ||
183 | |||
184 | /** | ||
185 | * rsi_91x_init() - This function initializes os interface operations. | ||
186 | * @void: Void. | ||
187 | * | ||
188 | * Return: Pointer to the adapter structure on success, NULL on failure . | ||
189 | */ | ||
190 | struct rsi_hw *rsi_91x_init(void) | ||
191 | { | ||
192 | struct rsi_hw *adapter = NULL; | ||
193 | struct rsi_common *common = NULL; | ||
194 | u8 ii = 0; | ||
195 | |||
196 | adapter = kzalloc(sizeof(*adapter), GFP_KERNEL); | ||
197 | if (!adapter) | ||
198 | return NULL; | ||
199 | |||
200 | adapter->priv = kzalloc(sizeof(*common), GFP_KERNEL); | ||
201 | if (adapter->priv == NULL) { | ||
202 | rsi_dbg(ERR_ZONE, "%s: Failed in allocation of memory\n", | ||
203 | __func__); | ||
204 | kfree(adapter); | ||
205 | return NULL; | ||
206 | } else { | ||
207 | common = adapter->priv; | ||
208 | common->priv = adapter; | ||
209 | } | ||
210 | |||
211 | for (ii = 0; ii < NUM_SOFT_QUEUES; ii++) | ||
212 | skb_queue_head_init(&common->tx_queue[ii]); | ||
213 | |||
214 | rsi_init_event(&common->tx_thread.event); | ||
215 | mutex_init(&common->mutex); | ||
216 | mutex_init(&common->tx_rxlock); | ||
217 | |||
218 | if (rsi_create_kthread(common, | ||
219 | &common->tx_thread, | ||
220 | rsi_tx_scheduler_thread, | ||
221 | "Tx-Thread")) { | ||
222 | rsi_dbg(ERR_ZONE, "%s: Unable to init tx thrd\n", __func__); | ||
223 | goto err; | ||
224 | } | ||
225 | |||
226 | common->init_done = true; | ||
227 | return adapter; | ||
228 | |||
229 | err: | ||
230 | kfree(common); | ||
231 | kfree(adapter); | ||
232 | return NULL; | ||
233 | } | ||
234 | EXPORT_SYMBOL_GPL(rsi_91x_init); | ||
235 | |||
236 | /** | ||
237 | * rsi_91x_deinit() - This function de-intializes os intf operations. | ||
238 | * @adapter: Pointer to the adapter structure. | ||
239 | * | ||
240 | * Return: None. | ||
241 | */ | ||
242 | void rsi_91x_deinit(struct rsi_hw *adapter) | ||
243 | { | ||
244 | struct rsi_common *common = adapter->priv; | ||
245 | u8 ii; | ||
246 | |||
247 | rsi_dbg(INFO_ZONE, "%s: Performing deinit os ops\n", __func__); | ||
248 | |||
249 | rsi_kill_thread(&common->tx_thread); | ||
250 | |||
251 | for (ii = 0; ii < NUM_SOFT_QUEUES; ii++) | ||
252 | skb_queue_purge(&common->tx_queue[ii]); | ||
253 | |||
254 | common->init_done = false; | ||
255 | |||
256 | kfree(common); | ||
257 | kfree(adapter->rsi_dev); | ||
258 | kfree(adapter); | ||
259 | } | ||
260 | EXPORT_SYMBOL_GPL(rsi_91x_deinit); | ||
261 | |||
262 | /** | ||
263 | * rsi_91x_hal_module_init() - This function is invoked when the module is | ||
264 | * loaded into the kernel. | ||
265 | * It registers the client driver. | ||
266 | * @void: Void. | ||
267 | * | ||
268 | * Return: 0 on success, -1 on failure. | ||
269 | */ | ||
270 | static int rsi_91x_hal_module_init(void) | ||
271 | { | ||
272 | rsi_dbg(INIT_ZONE, "%s: Module init called\n", __func__); | ||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | /** | ||
277 | * rsi_91x_hal_module_exit() - This function is called at the time of | ||
278 | * removing/unloading the module. | ||
279 | * It unregisters the client driver. | ||
280 | * @void: Void. | ||
281 | * | ||
282 | * Return: None. | ||
283 | */ | ||
284 | static void rsi_91x_hal_module_exit(void) | ||
285 | { | ||
286 | rsi_dbg(INIT_ZONE, "%s: Module exit called\n", __func__); | ||
287 | } | ||
288 | |||
289 | module_init(rsi_91x_hal_module_init); | ||
290 | module_exit(rsi_91x_hal_module_exit); | ||
291 | MODULE_AUTHOR("Redpine Signals Inc"); | ||
292 | MODULE_DESCRIPTION("Station driver for RSI 91x devices"); | ||
293 | MODULE_SUPPORTED_DEVICE("RSI-91x"); | ||
294 | MODULE_VERSION("0.1"); | ||
295 | MODULE_LICENSE("Dual BSD/GPL"); | ||
diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c new file mode 100644 index 000000000000..ef37d4b27bd4 --- /dev/null +++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c | |||
@@ -0,0 +1,1303 @@ | |||
1 | /** | ||
2 | * Copyright (c) 2014 Redpine Signals Inc. | ||
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 | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include <linux/etherdevice.h> | ||
18 | #include "rsi_mgmt.h" | ||
19 | #include "rsi_common.h" | ||
20 | |||
21 | static struct bootup_params boot_params_20 = { | ||
22 | .magic_number = cpu_to_le16(0x5aa5), | ||
23 | .crystal_good_time = 0x0, | ||
24 | .valid = cpu_to_le32(VALID_20), | ||
25 | .reserved_for_valids = 0x0, | ||
26 | .bootup_mode_info = 0x0, | ||
27 | .digital_loop_back_params = 0x0, | ||
28 | .rtls_timestamp_en = 0x0, | ||
29 | .host_spi_intr_cfg = 0x0, | ||
30 | .device_clk_info = {{ | ||
31 | .pll_config_g = { | ||
32 | .tapll_info_g = { | ||
33 | .pll_reg_1 = cpu_to_le16((TA_PLL_N_VAL_20 << 8)| | ||
34 | (TA_PLL_M_VAL_20)), | ||
35 | .pll_reg_2 = cpu_to_le16(TA_PLL_P_VAL_20), | ||
36 | }, | ||
37 | .pll960_info_g = { | ||
38 | .pll_reg_1 = cpu_to_le16((PLL960_P_VAL_20 << 8)| | ||
39 | (PLL960_N_VAL_20)), | ||
40 | .pll_reg_2 = cpu_to_le16(PLL960_M_VAL_20), | ||
41 | .pll_reg_3 = 0x0, | ||
42 | }, | ||
43 | .afepll_info_g = { | ||
44 | .pll_reg = cpu_to_le16(0x9f0), | ||
45 | } | ||
46 | }, | ||
47 | .switch_clk_g = { | ||
48 | .switch_clk_info = cpu_to_le16(BIT(3)), | ||
49 | .bbp_lmac_clk_reg_val = cpu_to_le16(0x121), | ||
50 | .umac_clock_reg_config = 0x0, | ||
51 | .qspi_uart_clock_reg_config = 0x0 | ||
52 | } | ||
53 | }, | ||
54 | { | ||
55 | .pll_config_g = { | ||
56 | .tapll_info_g = { | ||
57 | .pll_reg_1 = cpu_to_le16((TA_PLL_N_VAL_20 << 8)| | ||
58 | (TA_PLL_M_VAL_20)), | ||
59 | .pll_reg_2 = cpu_to_le16(TA_PLL_P_VAL_20), | ||
60 | }, | ||
61 | .pll960_info_g = { | ||
62 | .pll_reg_1 = cpu_to_le16((PLL960_P_VAL_20 << 8)| | ||
63 | (PLL960_N_VAL_20)), | ||
64 | .pll_reg_2 = cpu_to_le16(PLL960_M_VAL_20), | ||
65 | .pll_reg_3 = 0x0, | ||
66 | }, | ||
67 | .afepll_info_g = { | ||
68 | .pll_reg = cpu_to_le16(0x9f0), | ||
69 | } | ||
70 | }, | ||
71 | .switch_clk_g = { | ||
72 | .switch_clk_info = 0x0, | ||
73 | .bbp_lmac_clk_reg_val = 0x0, | ||
74 | .umac_clock_reg_config = 0x0, | ||
75 | .qspi_uart_clock_reg_config = 0x0 | ||
76 | } | ||
77 | }, | ||
78 | { | ||
79 | .pll_config_g = { | ||
80 | .tapll_info_g = { | ||
81 | .pll_reg_1 = cpu_to_le16((TA_PLL_N_VAL_20 << 8)| | ||
82 | (TA_PLL_M_VAL_20)), | ||
83 | .pll_reg_2 = cpu_to_le16(TA_PLL_P_VAL_20), | ||
84 | }, | ||
85 | .pll960_info_g = { | ||
86 | .pll_reg_1 = cpu_to_le16((PLL960_P_VAL_20 << 8)| | ||
87 | (PLL960_N_VAL_20)), | ||
88 | .pll_reg_2 = cpu_to_le16(PLL960_M_VAL_20), | ||
89 | .pll_reg_3 = 0x0, | ||
90 | }, | ||
91 | .afepll_info_g = { | ||
92 | .pll_reg = cpu_to_le16(0x9f0), | ||
93 | } | ||
94 | }, | ||
95 | .switch_clk_g = { | ||
96 | .switch_clk_info = 0x0, | ||
97 | .bbp_lmac_clk_reg_val = 0x0, | ||
98 | .umac_clock_reg_config = 0x0, | ||
99 | .qspi_uart_clock_reg_config = 0x0 | ||
100 | } | ||
101 | } }, | ||
102 | .buckboost_wakeup_cnt = 0x0, | ||
103 | .pmu_wakeup_wait = 0x0, | ||
104 | .shutdown_wait_time = 0x0, | ||
105 | .pmu_slp_clkout_sel = 0x0, | ||
106 | .wdt_prog_value = 0x0, | ||
107 | .wdt_soc_rst_delay = 0x0, | ||
108 | .dcdc_operation_mode = 0x0, | ||
109 | .soc_reset_wait_cnt = 0x0 | ||
110 | }; | ||
111 | |||
112 | static struct bootup_params boot_params_40 = { | ||
113 | .magic_number = cpu_to_le16(0x5aa5), | ||
114 | .crystal_good_time = 0x0, | ||
115 | .valid = cpu_to_le32(VALID_40), | ||
116 | .reserved_for_valids = 0x0, | ||
117 | .bootup_mode_info = 0x0, | ||
118 | .digital_loop_back_params = 0x0, | ||
119 | .rtls_timestamp_en = 0x0, | ||
120 | .host_spi_intr_cfg = 0x0, | ||
121 | .device_clk_info = {{ | ||
122 | .pll_config_g = { | ||
123 | .tapll_info_g = { | ||
124 | .pll_reg_1 = cpu_to_le16((TA_PLL_N_VAL_40 << 8)| | ||
125 | (TA_PLL_M_VAL_40)), | ||
126 | .pll_reg_2 = cpu_to_le16(TA_PLL_P_VAL_40), | ||
127 | }, | ||
128 | .pll960_info_g = { | ||
129 | .pll_reg_1 = cpu_to_le16((PLL960_P_VAL_40 << 8)| | ||
130 | (PLL960_N_VAL_40)), | ||
131 | .pll_reg_2 = cpu_to_le16(PLL960_M_VAL_40), | ||
132 | .pll_reg_3 = 0x0, | ||
133 | }, | ||
134 | .afepll_info_g = { | ||
135 | .pll_reg = cpu_to_le16(0x9f0), | ||
136 | } | ||
137 | }, | ||
138 | .switch_clk_g = { | ||
139 | .switch_clk_info = cpu_to_le16(0x09), | ||
140 | .bbp_lmac_clk_reg_val = cpu_to_le16(0x1121), | ||
141 | .umac_clock_reg_config = cpu_to_le16(0x48), | ||
142 | .qspi_uart_clock_reg_config = 0x0 | ||
143 | } | ||
144 | }, | ||
145 | { | ||
146 | .pll_config_g = { | ||
147 | .tapll_info_g = { | ||
148 | .pll_reg_1 = cpu_to_le16((TA_PLL_N_VAL_40 << 8)| | ||
149 | (TA_PLL_M_VAL_40)), | ||
150 | .pll_reg_2 = cpu_to_le16(TA_PLL_P_VAL_40), | ||
151 | }, | ||
152 | .pll960_info_g = { | ||
153 | .pll_reg_1 = cpu_to_le16((PLL960_P_VAL_40 << 8)| | ||
154 | (PLL960_N_VAL_40)), | ||
155 | .pll_reg_2 = cpu_to_le16(PLL960_M_VAL_40), | ||
156 | .pll_reg_3 = 0x0, | ||
157 | }, | ||
158 | .afepll_info_g = { | ||
159 | .pll_reg = cpu_to_le16(0x9f0), | ||
160 | } | ||
161 | }, | ||
162 | .switch_clk_g = { | ||
163 | .switch_clk_info = 0x0, | ||
164 | .bbp_lmac_clk_reg_val = 0x0, | ||
165 | .umac_clock_reg_config = 0x0, | ||
166 | .qspi_uart_clock_reg_config = 0x0 | ||
167 | } | ||
168 | }, | ||
169 | { | ||
170 | .pll_config_g = { | ||
171 | .tapll_info_g = { | ||
172 | .pll_reg_1 = cpu_to_le16((TA_PLL_N_VAL_40 << 8)| | ||
173 | (TA_PLL_M_VAL_40)), | ||
174 | .pll_reg_2 = cpu_to_le16(TA_PLL_P_VAL_40), | ||
175 | }, | ||
176 | .pll960_info_g = { | ||
177 | .pll_reg_1 = cpu_to_le16((PLL960_P_VAL_40 << 8)| | ||
178 | (PLL960_N_VAL_40)), | ||
179 | .pll_reg_2 = cpu_to_le16(PLL960_M_VAL_40), | ||
180 | .pll_reg_3 = 0x0, | ||
181 | }, | ||
182 | .afepll_info_g = { | ||
183 | .pll_reg = cpu_to_le16(0x9f0), | ||
184 | } | ||
185 | }, | ||
186 | .switch_clk_g = { | ||
187 | .switch_clk_info = 0x0, | ||
188 | .bbp_lmac_clk_reg_val = 0x0, | ||
189 | .umac_clock_reg_config = 0x0, | ||
190 | .qspi_uart_clock_reg_config = 0x0 | ||
191 | } | ||
192 | } }, | ||
193 | .buckboost_wakeup_cnt = 0x0, | ||
194 | .pmu_wakeup_wait = 0x0, | ||
195 | .shutdown_wait_time = 0x0, | ||
196 | .pmu_slp_clkout_sel = 0x0, | ||
197 | .wdt_prog_value = 0x0, | ||
198 | .wdt_soc_rst_delay = 0x0, | ||
199 | .dcdc_operation_mode = 0x0, | ||
200 | .soc_reset_wait_cnt = 0x0 | ||
201 | }; | ||
202 | |||
203 | static u16 mcs[] = {13, 26, 39, 52, 78, 104, 117, 130}; | ||
204 | |||
205 | /** | ||
206 | * rsi_set_default_parameters() - This function sets default parameters. | ||
207 | * @common: Pointer to the driver private structure. | ||
208 | * | ||
209 | * Return: none | ||
210 | */ | ||
211 | static void rsi_set_default_parameters(struct rsi_common *common) | ||
212 | { | ||
213 | common->band = IEEE80211_BAND_2GHZ; | ||
214 | common->channel_width = BW_20MHZ; | ||
215 | common->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; | ||
216 | common->channel = 1; | ||
217 | common->min_rate = 0xffff; | ||
218 | common->fsm_state = FSM_CARD_NOT_READY; | ||
219 | common->iface_down = true; | ||
220 | } | ||
221 | |||
222 | /** | ||
223 | * rsi_set_contention_vals() - This function sets the contention values for the | ||
224 | * backoff procedure. | ||
225 | * @common: Pointer to the driver private structure. | ||
226 | * | ||
227 | * Return: None. | ||
228 | */ | ||
229 | static void rsi_set_contention_vals(struct rsi_common *common) | ||
230 | { | ||
231 | u8 ii = 0; | ||
232 | |||
233 | for (; ii < NUM_EDCA_QUEUES; ii++) { | ||
234 | common->tx_qinfo[ii].wme_params = | ||
235 | (((common->edca_params[ii].cw_min / 2) + | ||
236 | (common->edca_params[ii].aifs)) * | ||
237 | WMM_SHORT_SLOT_TIME + SIFS_DURATION); | ||
238 | common->tx_qinfo[ii].weight = common->tx_qinfo[ii].wme_params; | ||
239 | common->tx_qinfo[ii].pkt_contended = 0; | ||
240 | } | ||
241 | } | ||
242 | |||
243 | /** | ||
244 | * rsi_send_internal_mgmt_frame() - This function sends management frames to | ||
245 | * firmware.Also schedules packet to queue | ||
246 | * for transmission. | ||
247 | * @common: Pointer to the driver private structure. | ||
248 | * @skb: Pointer to the socket buffer structure. | ||
249 | * | ||
250 | * Return: 0 on success, -1 on failure. | ||
251 | */ | ||
252 | static int rsi_send_internal_mgmt_frame(struct rsi_common *common, | ||
253 | struct sk_buff *skb) | ||
254 | { | ||
255 | struct skb_info *tx_params; | ||
256 | |||
257 | if (skb == NULL) { | ||
258 | rsi_dbg(ERR_ZONE, "%s: Unable to allocate skb\n", __func__); | ||
259 | return -ENOMEM; | ||
260 | } | ||
261 | tx_params = (struct skb_info *)&IEEE80211_SKB_CB(skb)->driver_data; | ||
262 | tx_params->flags |= INTERNAL_MGMT_PKT; | ||
263 | skb_queue_tail(&common->tx_queue[MGMT_SOFT_Q], skb); | ||
264 | rsi_set_event(&common->tx_thread.event); | ||
265 | return 0; | ||
266 | } | ||
267 | |||
268 | /** | ||
269 | * rsi_load_radio_caps() - This function is used to send radio capabilities | ||
270 | * values to firmware. | ||
271 | * @common: Pointer to the driver private structure. | ||
272 | * | ||
273 | * Return: 0 on success, corresponding negative error code on failure. | ||
274 | */ | ||
275 | static int rsi_load_radio_caps(struct rsi_common *common) | ||
276 | { | ||
277 | struct rsi_radio_caps *radio_caps; | ||
278 | struct rsi_hw *adapter = common->priv; | ||
279 | struct ieee80211_hw *hw = adapter->hw; | ||
280 | u16 inx = 0; | ||
281 | u8 ii; | ||
282 | u8 radio_id = 0; | ||
283 | u16 gc[20] = {0xf0, 0xf0, 0xf0, 0xf0, | ||
284 | 0xf0, 0xf0, 0xf0, 0xf0, | ||
285 | 0xf0, 0xf0, 0xf0, 0xf0, | ||
286 | 0xf0, 0xf0, 0xf0, 0xf0, | ||
287 | 0xf0, 0xf0, 0xf0, 0xf0}; | ||
288 | struct ieee80211_conf *conf = &hw->conf; | ||
289 | struct sk_buff *skb; | ||
290 | |||
291 | rsi_dbg(INFO_ZONE, "%s: Sending rate symbol req frame\n", __func__); | ||
292 | |||
293 | skb = dev_alloc_skb(sizeof(struct rsi_radio_caps)); | ||
294 | |||
295 | if (!skb) { | ||
296 | rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n", | ||
297 | __func__); | ||
298 | return -ENOMEM; | ||
299 | } | ||
300 | |||
301 | memset(skb->data, 0, sizeof(struct rsi_radio_caps)); | ||
302 | radio_caps = (struct rsi_radio_caps *)skb->data; | ||
303 | |||
304 | radio_caps->desc_word[1] = cpu_to_le16(RADIO_CAPABILITIES); | ||
305 | radio_caps->desc_word[4] = cpu_to_le16(RSI_RF_TYPE << 8); | ||
306 | |||
307 | if (common->channel_width == BW_40MHZ) { | ||
308 | radio_caps->desc_word[7] |= cpu_to_le16(RSI_LMAC_CLOCK_80MHZ); | ||
309 | radio_caps->desc_word[7] |= cpu_to_le16(RSI_ENABLE_40MHZ); | ||
310 | if (common->channel_width) { | ||
311 | radio_caps->desc_word[5] = | ||
312 | cpu_to_le16(common->channel_width << 12); | ||
313 | radio_caps->desc_word[5] |= cpu_to_le16(FULL40M_ENABLE); | ||
314 | } | ||
315 | |||
316 | if (conf_is_ht40_minus(conf)) { | ||
317 | radio_caps->desc_word[5] = 0; | ||
318 | radio_caps->desc_word[5] |= | ||
319 | cpu_to_le16(LOWER_20_ENABLE); | ||
320 | radio_caps->desc_word[5] |= | ||
321 | cpu_to_le16(LOWER_20_ENABLE >> 12); | ||
322 | } | ||
323 | |||
324 | if (conf_is_ht40_plus(conf)) { | ||
325 | radio_caps->desc_word[5] = 0; | ||
326 | radio_caps->desc_word[5] |= | ||
327 | cpu_to_le16(UPPER_20_ENABLE); | ||
328 | radio_caps->desc_word[5] |= | ||
329 | cpu_to_le16(UPPER_20_ENABLE >> 12); | ||
330 | } | ||
331 | } | ||
332 | |||
333 | radio_caps->desc_word[7] |= cpu_to_le16(radio_id << 8); | ||
334 | |||
335 | for (ii = 0; ii < MAX_HW_QUEUES; ii++) { | ||
336 | radio_caps->qos_params[ii].cont_win_min_q = cpu_to_le16(3); | ||
337 | radio_caps->qos_params[ii].cont_win_max_q = cpu_to_le16(0x3f); | ||
338 | radio_caps->qos_params[ii].aifsn_val_q = cpu_to_le16(2); | ||
339 | radio_caps->qos_params[ii].txop_q = 0; | ||
340 | } | ||
341 | |||
342 | for (ii = 0; ii < MAX_HW_QUEUES - 4; ii++) { | ||
343 | radio_caps->qos_params[ii].cont_win_min_q = | ||
344 | cpu_to_le16(common->edca_params[ii].cw_min); | ||
345 | radio_caps->qos_params[ii].cont_win_max_q = | ||
346 | cpu_to_le16(common->edca_params[ii].cw_max); | ||
347 | radio_caps->qos_params[ii].aifsn_val_q = | ||
348 | cpu_to_le16((common->edca_params[ii].aifs) << 8); | ||
349 | radio_caps->qos_params[ii].txop_q = | ||
350 | cpu_to_le16(common->edca_params[ii].txop); | ||
351 | } | ||
352 | |||
353 | memcpy(&common->rate_pwr[0], &gc[0], 40); | ||
354 | for (ii = 0; ii < 20; ii++) | ||
355 | radio_caps->gcpd_per_rate[inx++] = | ||
356 | cpu_to_le16(common->rate_pwr[ii] & 0x00FF); | ||
357 | |||
358 | radio_caps->desc_word[0] = cpu_to_le16((sizeof(struct rsi_radio_caps) - | ||
359 | FRAME_DESC_SZ) | | ||
360 | (RSI_WIFI_MGMT_Q << 12)); | ||
361 | |||
362 | |||
363 | skb_put(skb, (sizeof(struct rsi_radio_caps))); | ||
364 | |||
365 | return rsi_send_internal_mgmt_frame(common, skb); | ||
366 | } | ||
367 | |||
368 | /** | ||
369 | * rsi_mgmt_pkt_to_core() - This function is the entry point for Mgmt module. | ||
370 | * @common: Pointer to the driver private structure. | ||
371 | * @msg: Pointer to received packet. | ||
372 | * @msg_len: Length of the recieved packet. | ||
373 | * @type: Type of recieved packet. | ||
374 | * | ||
375 | * Return: 0 on success, -1 on failure. | ||
376 | */ | ||
377 | static int rsi_mgmt_pkt_to_core(struct rsi_common *common, | ||
378 | u8 *msg, | ||
379 | s32 msg_len, | ||
380 | u8 type) | ||
381 | { | ||
382 | struct rsi_hw *adapter = common->priv; | ||
383 | struct ieee80211_tx_info *info; | ||
384 | struct skb_info *rx_params; | ||
385 | u8 pad_bytes = msg[4]; | ||
386 | u8 pkt_recv; | ||
387 | struct sk_buff *skb; | ||
388 | char *buffer; | ||
389 | |||
390 | if (type == RX_DOT11_MGMT) { | ||
391 | if (!adapter->sc_nvifs) | ||
392 | return -ENOLINK; | ||
393 | |||
394 | msg_len -= pad_bytes; | ||
395 | if ((msg_len <= 0) || (!msg)) { | ||
396 | rsi_dbg(MGMT_RX_ZONE, | ||
397 | "%s: Invalid rx msg of len = %d\n", | ||
398 | __func__, msg_len); | ||
399 | return -EINVAL; | ||
400 | } | ||
401 | |||
402 | skb = dev_alloc_skb(msg_len); | ||
403 | if (!skb) { | ||
404 | rsi_dbg(ERR_ZONE, "%s: Failed to allocate skb\n", | ||
405 | __func__); | ||
406 | return -ENOMEM; | ||
407 | } | ||
408 | |||
409 | buffer = skb_put(skb, msg_len); | ||
410 | |||
411 | memcpy(buffer, | ||
412 | (u8 *)(msg + FRAME_DESC_SZ + pad_bytes), | ||
413 | msg_len); | ||
414 | |||
415 | pkt_recv = buffer[0]; | ||
416 | |||
417 | info = IEEE80211_SKB_CB(skb); | ||
418 | rx_params = (struct skb_info *)info->driver_data; | ||
419 | rx_params->rssi = rsi_get_rssi(msg); | ||
420 | rx_params->channel = rsi_get_channel(msg); | ||
421 | rsi_indicate_pkt_to_os(common, skb); | ||
422 | } else { | ||
423 | rsi_dbg(MGMT_TX_ZONE, "%s: Internal Packet\n", __func__); | ||
424 | } | ||
425 | |||
426 | return 0; | ||
427 | } | ||
428 | |||
429 | /** | ||
430 | * rsi_hal_send_sta_notify_frame() - This function sends the station notify | ||
431 | * frame to firmware. | ||
432 | * @common: Pointer to the driver private structure. | ||
433 | * @opmode: Operating mode of device. | ||
434 | * @notify_event: Notification about station connection. | ||
435 | * @bssid: bssid. | ||
436 | * @qos_enable: Qos is enabled. | ||
437 | * @aid: Aid (unique for all STA). | ||
438 | * | ||
439 | * Return: status: 0 on success, corresponding negative error code on failure. | ||
440 | */ | ||
441 | static int rsi_hal_send_sta_notify_frame(struct rsi_common *common, | ||
442 | u8 opmode, | ||
443 | u8 notify_event, | ||
444 | const unsigned char *bssid, | ||
445 | u8 qos_enable, | ||
446 | u16 aid) | ||
447 | { | ||
448 | struct sk_buff *skb = NULL; | ||
449 | struct rsi_peer_notify *peer_notify; | ||
450 | u16 vap_id = 0; | ||
451 | int status; | ||
452 | |||
453 | rsi_dbg(MGMT_TX_ZONE, "%s: Sending sta notify frame\n", __func__); | ||
454 | |||
455 | skb = dev_alloc_skb(sizeof(struct rsi_peer_notify)); | ||
456 | |||
457 | if (!skb) { | ||
458 | rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n", | ||
459 | __func__); | ||
460 | return -ENOMEM; | ||
461 | } | ||
462 | |||
463 | memset(skb->data, 0, sizeof(struct rsi_peer_notify)); | ||
464 | peer_notify = (struct rsi_peer_notify *)skb->data; | ||
465 | |||
466 | peer_notify->command = cpu_to_le16(opmode << 1); | ||
467 | |||
468 | switch (notify_event) { | ||
469 | case STA_CONNECTED: | ||
470 | peer_notify->command |= cpu_to_le16(RSI_ADD_PEER); | ||
471 | break; | ||
472 | case STA_DISCONNECTED: | ||
473 | peer_notify->command |= cpu_to_le16(RSI_DELETE_PEER); | ||
474 | break; | ||
475 | default: | ||
476 | break; | ||
477 | } | ||
478 | |||
479 | peer_notify->command |= cpu_to_le16((aid & 0xfff) << 4); | ||
480 | ether_addr_copy(peer_notify->mac_addr, bssid); | ||
481 | |||
482 | peer_notify->sta_flags = cpu_to_le32((qos_enable) ? 1 : 0); | ||
483 | |||
484 | peer_notify->desc_word[0] = | ||
485 | cpu_to_le16((sizeof(struct rsi_peer_notify) - FRAME_DESC_SZ) | | ||
486 | (RSI_WIFI_MGMT_Q << 12)); | ||
487 | peer_notify->desc_word[1] = cpu_to_le16(PEER_NOTIFY); | ||
488 | peer_notify->desc_word[7] |= cpu_to_le16(vap_id << 8); | ||
489 | |||
490 | skb_put(skb, sizeof(struct rsi_peer_notify)); | ||
491 | |||
492 | status = rsi_send_internal_mgmt_frame(common, skb); | ||
493 | |||
494 | if (!status && qos_enable) { | ||
495 | rsi_set_contention_vals(common); | ||
496 | status = rsi_load_radio_caps(common); | ||
497 | } | ||
498 | return status; | ||
499 | } | ||
500 | |||
501 | /** | ||
502 | * rsi_send_aggregation_params_frame() - This function sends the ampdu | ||
503 | * indication frame to firmware. | ||
504 | * @common: Pointer to the driver private structure. | ||
505 | * @tid: traffic identifier. | ||
506 | * @ssn: ssn. | ||
507 | * @buf_size: buffer size. | ||
508 | * @event: notification about station connection. | ||
509 | * | ||
510 | * Return: 0 on success, corresponding negative error code on failure. | ||
511 | */ | ||
512 | int rsi_send_aggregation_params_frame(struct rsi_common *common, | ||
513 | u16 tid, | ||
514 | u16 ssn, | ||
515 | u8 buf_size, | ||
516 | u8 event) | ||
517 | { | ||
518 | struct sk_buff *skb = NULL; | ||
519 | struct rsi_mac_frame *mgmt_frame; | ||
520 | u8 peer_id = 0; | ||
521 | |||
522 | skb = dev_alloc_skb(FRAME_DESC_SZ); | ||
523 | |||
524 | if (!skb) { | ||
525 | rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n", | ||
526 | __func__); | ||
527 | return -ENOMEM; | ||
528 | } | ||
529 | |||
530 | memset(skb->data, 0, FRAME_DESC_SZ); | ||
531 | mgmt_frame = (struct rsi_mac_frame *)skb->data; | ||
532 | |||
533 | rsi_dbg(MGMT_TX_ZONE, "%s: Sending AMPDU indication frame\n", __func__); | ||
534 | |||
535 | mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12); | ||
536 | mgmt_frame->desc_word[1] = cpu_to_le16(AMPDU_IND); | ||
537 | |||
538 | if (event == STA_TX_ADDBA_DONE) { | ||
539 | mgmt_frame->desc_word[4] = cpu_to_le16(ssn); | ||
540 | mgmt_frame->desc_word[5] = cpu_to_le16(buf_size); | ||
541 | mgmt_frame->desc_word[7] = | ||
542 | cpu_to_le16((tid | (START_AMPDU_AGGR << 4) | (peer_id << 8))); | ||
543 | } else if (event == STA_RX_ADDBA_DONE) { | ||
544 | mgmt_frame->desc_word[4] = cpu_to_le16(ssn); | ||
545 | mgmt_frame->desc_word[7] = cpu_to_le16(tid | | ||
546 | (START_AMPDU_AGGR << 4) | | ||
547 | (RX_BA_INDICATION << 5) | | ||
548 | (peer_id << 8)); | ||
549 | } else if (event == STA_TX_DELBA) { | ||
550 | mgmt_frame->desc_word[7] = cpu_to_le16(tid | | ||
551 | (STOP_AMPDU_AGGR << 4) | | ||
552 | (peer_id << 8)); | ||
553 | } else if (event == STA_RX_DELBA) { | ||
554 | mgmt_frame->desc_word[7] = cpu_to_le16(tid | | ||
555 | (STOP_AMPDU_AGGR << 4) | | ||
556 | (RX_BA_INDICATION << 5) | | ||
557 | (peer_id << 8)); | ||
558 | } | ||
559 | |||
560 | skb_put(skb, FRAME_DESC_SZ); | ||
561 | |||
562 | return rsi_send_internal_mgmt_frame(common, skb); | ||
563 | } | ||
564 | |||
565 | /** | ||
566 | * rsi_program_bb_rf() - This function starts base band and RF programming. | ||
567 | * This is called after initial configurations are done. | ||
568 | * @common: Pointer to the driver private structure. | ||
569 | * | ||
570 | * Return: 0 on success, corresponding negative error code on failure. | ||
571 | */ | ||
572 | static int rsi_program_bb_rf(struct rsi_common *common) | ||
573 | { | ||
574 | struct sk_buff *skb; | ||
575 | struct rsi_mac_frame *mgmt_frame; | ||
576 | |||
577 | rsi_dbg(MGMT_TX_ZONE, "%s: Sending program BB/RF frame\n", __func__); | ||
578 | |||
579 | skb = dev_alloc_skb(FRAME_DESC_SZ); | ||
580 | if (!skb) { | ||
581 | rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n", | ||
582 | __func__); | ||
583 | return -ENOMEM; | ||
584 | } | ||
585 | |||
586 | memset(skb->data, 0, FRAME_DESC_SZ); | ||
587 | mgmt_frame = (struct rsi_mac_frame *)skb->data; | ||
588 | |||
589 | mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12); | ||
590 | mgmt_frame->desc_word[1] = cpu_to_le16(BBP_PROG_IN_TA); | ||
591 | mgmt_frame->desc_word[4] = cpu_to_le16(common->endpoint << 8); | ||
592 | |||
593 | if (common->rf_reset) { | ||
594 | mgmt_frame->desc_word[7] = cpu_to_le16(RF_RESET_ENABLE); | ||
595 | rsi_dbg(MGMT_TX_ZONE, "%s: ===> RF RESET REQUEST SENT <===\n", | ||
596 | __func__); | ||
597 | common->rf_reset = 0; | ||
598 | } | ||
599 | common->bb_rf_prog_count = 1; | ||
600 | mgmt_frame->desc_word[7] |= cpu_to_le16(PUT_BBP_RESET | | ||
601 | BBP_REG_WRITE | (RSI_RF_TYPE << 4)); | ||
602 | skb_put(skb, FRAME_DESC_SZ); | ||
603 | |||
604 | return rsi_send_internal_mgmt_frame(common, skb); | ||
605 | } | ||
606 | |||
607 | /** | ||
608 | * rsi_set_vap_capabilities() - This function send vap capability to firmware. | ||
609 | * @common: Pointer to the driver private structure. | ||
610 | * @opmode: Operating mode of device. | ||
611 | * | ||
612 | * Return: 0 on success, corresponding negative error code on failure. | ||
613 | */ | ||
614 | int rsi_set_vap_capabilities(struct rsi_common *common, enum opmode mode) | ||
615 | { | ||
616 | struct sk_buff *skb = NULL; | ||
617 | struct rsi_vap_caps *vap_caps; | ||
618 | u16 vap_id = 0; | ||
619 | |||
620 | rsi_dbg(MGMT_TX_ZONE, "%s: Sending VAP capabilities frame\n", __func__); | ||
621 | |||
622 | skb = dev_alloc_skb(sizeof(struct rsi_vap_caps)); | ||
623 | if (!skb) { | ||
624 | rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n", | ||
625 | __func__); | ||
626 | return -ENOMEM; | ||
627 | } | ||
628 | |||
629 | memset(skb->data, 0, sizeof(struct rsi_vap_caps)); | ||
630 | vap_caps = (struct rsi_vap_caps *)skb->data; | ||
631 | |||
632 | vap_caps->desc_word[0] = cpu_to_le16((sizeof(struct rsi_vap_caps) - | ||
633 | FRAME_DESC_SZ) | | ||
634 | (RSI_WIFI_MGMT_Q << 12)); | ||
635 | vap_caps->desc_word[1] = cpu_to_le16(VAP_CAPABILITIES); | ||
636 | vap_caps->desc_word[4] = cpu_to_le16(mode | | ||
637 | (common->channel_width << 8)); | ||
638 | vap_caps->desc_word[7] = cpu_to_le16((vap_id << 8) | | ||
639 | (common->mac_id << 4) | | ||
640 | common->radio_id); | ||
641 | |||
642 | memcpy(vap_caps->mac_addr, common->mac_addr, IEEE80211_ADDR_LEN); | ||
643 | vap_caps->keep_alive_period = cpu_to_le16(90); | ||
644 | vap_caps->frag_threshold = cpu_to_le16(IEEE80211_MAX_FRAG_THRESHOLD); | ||
645 | |||
646 | vap_caps->rts_threshold = cpu_to_le16(common->rts_threshold); | ||
647 | vap_caps->default_mgmt_rate = 0; | ||
648 | if (conf_is_ht40(&common->priv->hw->conf)) { | ||
649 | vap_caps->default_ctrl_rate = | ||
650 | cpu_to_le32(RSI_RATE_6 | FULL40M_ENABLE << 16); | ||
651 | } else { | ||
652 | vap_caps->default_ctrl_rate = cpu_to_le32(RSI_RATE_6); | ||
653 | } | ||
654 | vap_caps->default_data_rate = 0; | ||
655 | vap_caps->beacon_interval = cpu_to_le16(200); | ||
656 | vap_caps->dtim_period = cpu_to_le16(4); | ||
657 | |||
658 | skb_put(skb, sizeof(*vap_caps)); | ||
659 | |||
660 | return rsi_send_internal_mgmt_frame(common, skb); | ||
661 | } | ||
662 | |||
663 | /** | ||
664 | * rsi_hal_load_key() - This function is used to load keys within the firmware. | ||
665 | * @common: Pointer to the driver private structure. | ||
666 | * @data: Pointer to the key data. | ||
667 | * @key_len: Key length to be loaded. | ||
668 | * @key_type: Type of key: GROUP/PAIRWISE. | ||
669 | * @key_id: Key index. | ||
670 | * @cipher: Type of cipher used. | ||
671 | * | ||
672 | * Return: 0 on success, -1 on failure. | ||
673 | */ | ||
674 | int rsi_hal_load_key(struct rsi_common *common, | ||
675 | u8 *data, | ||
676 | u16 key_len, | ||
677 | u8 key_type, | ||
678 | u8 key_id, | ||
679 | u32 cipher) | ||
680 | { | ||
681 | struct sk_buff *skb = NULL; | ||
682 | struct rsi_set_key *set_key; | ||
683 | u16 key_descriptor = 0; | ||
684 | |||
685 | rsi_dbg(MGMT_TX_ZONE, "%s: Sending load key frame\n", __func__); | ||
686 | |||
687 | skb = dev_alloc_skb(sizeof(struct rsi_set_key)); | ||
688 | if (!skb) { | ||
689 | rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n", | ||
690 | __func__); | ||
691 | return -ENOMEM; | ||
692 | } | ||
693 | |||
694 | memset(skb->data, 0, sizeof(struct rsi_set_key)); | ||
695 | set_key = (struct rsi_set_key *)skb->data; | ||
696 | |||
697 | if ((cipher == WLAN_CIPHER_SUITE_WEP40) || | ||
698 | (cipher == WLAN_CIPHER_SUITE_WEP104)) { | ||
699 | key_len += 1; | ||
700 | key_descriptor |= BIT(2); | ||
701 | if (key_len >= 13) | ||
702 | key_descriptor |= BIT(3); | ||
703 | } else if (cipher != KEY_TYPE_CLEAR) { | ||
704 | key_descriptor |= BIT(4); | ||
705 | if (key_type == RSI_PAIRWISE_KEY) | ||
706 | key_id = 0; | ||
707 | if (cipher == WLAN_CIPHER_SUITE_TKIP) | ||
708 | key_descriptor |= BIT(5); | ||
709 | } | ||
710 | key_descriptor |= (key_type | BIT(13) | (key_id << 14)); | ||
711 | |||
712 | set_key->desc_word[0] = cpu_to_le16((sizeof(struct rsi_set_key) - | ||
713 | FRAME_DESC_SZ) | | ||
714 | (RSI_WIFI_MGMT_Q << 12)); | ||
715 | set_key->desc_word[1] = cpu_to_le16(SET_KEY_REQ); | ||
716 | set_key->desc_word[4] = cpu_to_le16(key_descriptor); | ||
717 | |||
718 | if ((cipher == WLAN_CIPHER_SUITE_WEP40) || | ||
719 | (cipher == WLAN_CIPHER_SUITE_WEP104)) { | ||
720 | memcpy(&set_key->key[key_id][1], | ||
721 | data, | ||
722 | key_len * 2); | ||
723 | } else { | ||
724 | memcpy(&set_key->key[0][0], data, key_len); | ||
725 | } | ||
726 | |||
727 | memcpy(set_key->tx_mic_key, &data[16], 8); | ||
728 | memcpy(set_key->rx_mic_key, &data[24], 8); | ||
729 | |||
730 | skb_put(skb, sizeof(struct rsi_set_key)); | ||
731 | |||
732 | return rsi_send_internal_mgmt_frame(common, skb); | ||
733 | } | ||
734 | |||
735 | /* | ||
736 | * rsi_load_bootup_params() - This function send bootup params to the firmware. | ||
737 | * @common: Pointer to the driver private structure. | ||
738 | * | ||
739 | * Return: 0 on success, corresponding error code on failure. | ||
740 | */ | ||
741 | static u8 rsi_load_bootup_params(struct rsi_common *common) | ||
742 | { | ||
743 | struct sk_buff *skb; | ||
744 | struct rsi_boot_params *boot_params; | ||
745 | |||
746 | rsi_dbg(MGMT_TX_ZONE, "%s: Sending boot params frame\n", __func__); | ||
747 | skb = dev_alloc_skb(sizeof(struct rsi_boot_params)); | ||
748 | if (!skb) { | ||
749 | rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n", | ||
750 | __func__); | ||
751 | return -ENOMEM; | ||
752 | } | ||
753 | |||
754 | memset(skb->data, 0, sizeof(struct rsi_boot_params)); | ||
755 | boot_params = (struct rsi_boot_params *)skb->data; | ||
756 | |||
757 | rsi_dbg(MGMT_TX_ZONE, "%s:\n", __func__); | ||
758 | |||
759 | if (common->channel_width == BW_40MHZ) { | ||
760 | memcpy(&boot_params->bootup_params, | ||
761 | &boot_params_40, | ||
762 | sizeof(struct bootup_params)); | ||
763 | rsi_dbg(MGMT_TX_ZONE, "%s: Packet 40MHZ <=== %d\n", __func__, | ||
764 | UMAC_CLK_40BW); | ||
765 | boot_params->desc_word[7] = cpu_to_le16(UMAC_CLK_40BW); | ||
766 | } else { | ||
767 | memcpy(&boot_params->bootup_params, | ||
768 | &boot_params_20, | ||
769 | sizeof(struct bootup_params)); | ||
770 | if (boot_params_20.valid != cpu_to_le32(VALID_20)) { | ||
771 | boot_params->desc_word[7] = cpu_to_le16(UMAC_CLK_20BW); | ||
772 | rsi_dbg(MGMT_TX_ZONE, | ||
773 | "%s: Packet 20MHZ <=== %d\n", __func__, | ||
774 | UMAC_CLK_20BW); | ||
775 | } else { | ||
776 | boot_params->desc_word[7] = cpu_to_le16(UMAC_CLK_40MHZ); | ||
777 | rsi_dbg(MGMT_TX_ZONE, | ||
778 | "%s: Packet 20MHZ <=== %d\n", __func__, | ||
779 | UMAC_CLK_40MHZ); | ||
780 | } | ||
781 | } | ||
782 | |||
783 | /** | ||
784 | * Bit{0:11} indicates length of the Packet | ||
785 | * Bit{12:15} indicates host queue number | ||
786 | */ | ||
787 | boot_params->desc_word[0] = cpu_to_le16(sizeof(struct bootup_params) | | ||
788 | (RSI_WIFI_MGMT_Q << 12)); | ||
789 | boot_params->desc_word[1] = cpu_to_le16(BOOTUP_PARAMS_REQUEST); | ||
790 | |||
791 | skb_put(skb, sizeof(struct rsi_boot_params)); | ||
792 | |||
793 | return rsi_send_internal_mgmt_frame(common, skb); | ||
794 | } | ||
795 | |||
796 | /** | ||
797 | * rsi_send_reset_mac() - This function prepares reset MAC request and sends an | ||
798 | * internal management frame to indicate it to firmware. | ||
799 | * @common: Pointer to the driver private structure. | ||
800 | * | ||
801 | * Return: 0 on success, corresponding error code on failure. | ||
802 | */ | ||
803 | static int rsi_send_reset_mac(struct rsi_common *common) | ||
804 | { | ||
805 | struct sk_buff *skb; | ||
806 | struct rsi_mac_frame *mgmt_frame; | ||
807 | |||
808 | rsi_dbg(MGMT_TX_ZONE, "%s: Sending reset MAC frame\n", __func__); | ||
809 | |||
810 | skb = dev_alloc_skb(FRAME_DESC_SZ); | ||
811 | if (!skb) { | ||
812 | rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n", | ||
813 | __func__); | ||
814 | return -ENOMEM; | ||
815 | } | ||
816 | |||
817 | memset(skb->data, 0, FRAME_DESC_SZ); | ||
818 | mgmt_frame = (struct rsi_mac_frame *)skb->data; | ||
819 | |||
820 | mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12); | ||
821 | mgmt_frame->desc_word[1] = cpu_to_le16(RESET_MAC_REQ); | ||
822 | mgmt_frame->desc_word[4] = cpu_to_le16(RETRY_COUNT << 8); | ||
823 | |||
824 | skb_put(skb, FRAME_DESC_SZ); | ||
825 | |||
826 | return rsi_send_internal_mgmt_frame(common, skb); | ||
827 | } | ||
828 | |||
829 | /** | ||
830 | * rsi_set_channel() - This function programs the channel. | ||
831 | * @common: Pointer to the driver private structure. | ||
832 | * @channel: Channel value to be set. | ||
833 | * | ||
834 | * Return: 0 on success, corresponding error code on failure. | ||
835 | */ | ||
836 | int rsi_set_channel(struct rsi_common *common, u16 channel) | ||
837 | { | ||
838 | struct sk_buff *skb = NULL; | ||
839 | struct rsi_mac_frame *mgmt_frame; | ||
840 | |||
841 | rsi_dbg(MGMT_TX_ZONE, | ||
842 | "%s: Sending scan req frame\n", __func__); | ||
843 | |||
844 | skb = dev_alloc_skb(FRAME_DESC_SZ); | ||
845 | if (!skb) { | ||
846 | rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n", | ||
847 | __func__); | ||
848 | return -ENOMEM; | ||
849 | } | ||
850 | |||
851 | memset(skb->data, 0, FRAME_DESC_SZ); | ||
852 | mgmt_frame = (struct rsi_mac_frame *)skb->data; | ||
853 | |||
854 | if (common->band == IEEE80211_BAND_5GHZ) { | ||
855 | if ((channel >= 36) && (channel <= 64)) | ||
856 | channel = ((channel - 32) / 4); | ||
857 | else if ((channel > 64) && (channel <= 140)) | ||
858 | channel = ((channel - 102) / 4) + 8; | ||
859 | else if (channel >= 149) | ||
860 | channel = ((channel - 151) / 4) + 18; | ||
861 | else | ||
862 | return -EINVAL; | ||
863 | } else { | ||
864 | if (channel > 14) { | ||
865 | rsi_dbg(ERR_ZONE, "%s: Invalid chno %d, band = %d\n", | ||
866 | __func__, channel, common->band); | ||
867 | return -EINVAL; | ||
868 | } | ||
869 | } | ||
870 | |||
871 | mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12); | ||
872 | mgmt_frame->desc_word[1] = cpu_to_le16(SCAN_REQUEST); | ||
873 | mgmt_frame->desc_word[4] = cpu_to_le16(channel); | ||
874 | |||
875 | mgmt_frame->desc_word[7] = cpu_to_le16(PUT_BBP_RESET | | ||
876 | BBP_REG_WRITE | | ||
877 | (RSI_RF_TYPE << 4)); | ||
878 | |||
879 | mgmt_frame->desc_word[5] = cpu_to_le16(0x01); | ||
880 | |||
881 | if (common->channel_width == BW_40MHZ) | ||
882 | mgmt_frame->desc_word[5] |= cpu_to_le16(0x1 << 8); | ||
883 | |||
884 | common->channel = channel; | ||
885 | |||
886 | skb_put(skb, FRAME_DESC_SZ); | ||
887 | |||
888 | return rsi_send_internal_mgmt_frame(common, skb); | ||
889 | } | ||
890 | |||
891 | /** | ||
892 | * rsi_compare() - This function is used to compare two integers | ||
893 | * @a: pointer to the first integer | ||
894 | * @b: pointer to the second integer | ||
895 | * | ||
896 | * Return: 0 if both are equal, -1 if the first is smaller, else 1 | ||
897 | */ | ||
898 | static int rsi_compare(const void *a, const void *b) | ||
899 | { | ||
900 | u16 _a = *(const u16 *)(a); | ||
901 | u16 _b = *(const u16 *)(b); | ||
902 | |||
903 | if (_a > _b) | ||
904 | return -1; | ||
905 | |||
906 | if (_a < _b) | ||
907 | return 1; | ||
908 | |||
909 | return 0; | ||
910 | } | ||
911 | |||
912 | /** | ||
913 | * rsi_map_rates() - This function is used to map selected rates to hw rates. | ||
914 | * @rate: The standard rate to be mapped. | ||
915 | * @offset: Offset that will be returned. | ||
916 | * | ||
917 | * Return: 0 if it is a mcs rate, else 1 | ||
918 | */ | ||
919 | static bool rsi_map_rates(u16 rate, int *offset) | ||
920 | { | ||
921 | int kk; | ||
922 | for (kk = 0; kk < ARRAY_SIZE(rsi_mcsrates); kk++) { | ||
923 | if (rate == mcs[kk]) { | ||
924 | *offset = kk; | ||
925 | return false; | ||
926 | } | ||
927 | } | ||
928 | |||
929 | for (kk = 0; kk < ARRAY_SIZE(rsi_rates); kk++) { | ||
930 | if (rate == rsi_rates[kk].bitrate / 5) { | ||
931 | *offset = kk; | ||
932 | break; | ||
933 | } | ||
934 | } | ||
935 | return true; | ||
936 | } | ||
937 | |||
938 | /** | ||
939 | * rsi_send_auto_rate_request() - This function is to set rates for connection | ||
940 | * and send autorate request to firmware. | ||
941 | * @common: Pointer to the driver private structure. | ||
942 | * | ||
943 | * Return: 0 on success, corresponding error code on failure. | ||
944 | */ | ||
945 | static int rsi_send_auto_rate_request(struct rsi_common *common) | ||
946 | { | ||
947 | struct sk_buff *skb; | ||
948 | struct rsi_auto_rate *auto_rate; | ||
949 | int ii = 0, jj = 0, kk = 0; | ||
950 | struct ieee80211_hw *hw = common->priv->hw; | ||
951 | u8 band = hw->conf.chandef.chan->band; | ||
952 | u8 num_supported_rates = 0; | ||
953 | u8 rate_offset = 0; | ||
954 | u32 rate_bitmap = common->bitrate_mask[band]; | ||
955 | |||
956 | u16 *selected_rates, min_rate; | ||
957 | |||
958 | skb = dev_alloc_skb(sizeof(struct rsi_auto_rate)); | ||
959 | if (!skb) { | ||
960 | rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n", | ||
961 | __func__); | ||
962 | return -ENOMEM; | ||
963 | } | ||
964 | |||
965 | selected_rates = kmalloc(2 * RSI_TBL_SZ, GFP_KERNEL); | ||
966 | if (!selected_rates) { | ||
967 | rsi_dbg(ERR_ZONE, "%s: Failed in allocation of mem\n", | ||
968 | __func__); | ||
969 | return -ENOMEM; | ||
970 | } | ||
971 | |||
972 | memset(skb->data, 0, sizeof(struct rsi_auto_rate)); | ||
973 | memset(selected_rates, 0, 2 * RSI_TBL_SZ); | ||
974 | |||
975 | auto_rate = (struct rsi_auto_rate *)skb->data; | ||
976 | |||
977 | auto_rate->aarf_rssi = cpu_to_le16(((u16)3 << 6) | (u16)(18 & 0x3f)); | ||
978 | auto_rate->collision_tolerance = cpu_to_le16(3); | ||
979 | auto_rate->failure_limit = cpu_to_le16(3); | ||
980 | auto_rate->initial_boundary = cpu_to_le16(3); | ||
981 | auto_rate->max_threshold_limt = cpu_to_le16(27); | ||
982 | |||
983 | auto_rate->desc_word[1] = cpu_to_le16(AUTO_RATE_IND); | ||
984 | |||
985 | if (common->channel_width == BW_40MHZ) | ||
986 | auto_rate->desc_word[7] |= cpu_to_le16(1); | ||
987 | |||
988 | if (band == IEEE80211_BAND_2GHZ) | ||
989 | min_rate = STD_RATE_01; | ||
990 | else | ||
991 | min_rate = STD_RATE_06; | ||
992 | |||
993 | for (ii = 0, jj = 0; ii < ARRAY_SIZE(rsi_rates); ii++) { | ||
994 | if (rate_bitmap & BIT(ii)) { | ||
995 | selected_rates[jj++] = (rsi_rates[ii].bitrate / 5); | ||
996 | rate_offset++; | ||
997 | } | ||
998 | } | ||
999 | num_supported_rates = jj; | ||
1000 | |||
1001 | if (common->vif_info[0].is_ht) { | ||
1002 | for (ii = 0; ii < ARRAY_SIZE(mcs); ii++) | ||
1003 | selected_rates[jj++] = mcs[ii]; | ||
1004 | num_supported_rates += ARRAY_SIZE(mcs); | ||
1005 | rate_offset += ARRAY_SIZE(mcs); | ||
1006 | } | ||
1007 | |||
1008 | if (rate_offset < (RSI_TBL_SZ / 2) - 1) { | ||
1009 | for (ii = jj; ii < (RSI_TBL_SZ / 2); ii++) { | ||
1010 | selected_rates[jj++] = min_rate; | ||
1011 | rate_offset++; | ||
1012 | } | ||
1013 | } | ||
1014 | |||
1015 | sort(selected_rates, jj, sizeof(u16), &rsi_compare, NULL); | ||
1016 | |||
1017 | /* mapping the rates to RSI rates */ | ||
1018 | for (ii = 0; ii < jj; ii++) { | ||
1019 | if (rsi_map_rates(selected_rates[ii], &kk)) { | ||
1020 | auto_rate->supported_rates[ii] = | ||
1021 | cpu_to_le16(rsi_rates[kk].hw_value); | ||
1022 | } else { | ||
1023 | auto_rate->supported_rates[ii] = | ||
1024 | cpu_to_le16(rsi_mcsrates[kk]); | ||
1025 | } | ||
1026 | } | ||
1027 | |||
1028 | /* loading HT rates in the bottom half of the auto rate table */ | ||
1029 | if (common->vif_info[0].is_ht) { | ||
1030 | if (common->vif_info[0].sgi) | ||
1031 | auto_rate->supported_rates[rate_offset++] = | ||
1032 | cpu_to_le16(RSI_RATE_MCS7_SG); | ||
1033 | |||
1034 | for (ii = rate_offset, kk = ARRAY_SIZE(rsi_mcsrates) - 1; | ||
1035 | ii < rate_offset + 2 * ARRAY_SIZE(rsi_mcsrates); ii++) { | ||
1036 | if (common->vif_info[0].sgi) | ||
1037 | auto_rate->supported_rates[ii++] = | ||
1038 | cpu_to_le16(rsi_mcsrates[kk] | BIT(9)); | ||
1039 | auto_rate->supported_rates[ii] = | ||
1040 | cpu_to_le16(rsi_mcsrates[kk--]); | ||
1041 | } | ||
1042 | |||
1043 | for (; ii < RSI_TBL_SZ; ii++) { | ||
1044 | auto_rate->supported_rates[ii] = | ||
1045 | cpu_to_le16(rsi_mcsrates[0]); | ||
1046 | } | ||
1047 | } | ||
1048 | |||
1049 | auto_rate->num_supported_rates = cpu_to_le16(num_supported_rates * 2); | ||
1050 | auto_rate->moderate_rate_inx = cpu_to_le16(num_supported_rates / 2); | ||
1051 | auto_rate->desc_word[7] |= cpu_to_le16(0 << 8); | ||
1052 | num_supported_rates *= 2; | ||
1053 | |||
1054 | auto_rate->desc_word[0] = cpu_to_le16((sizeof(*auto_rate) - | ||
1055 | FRAME_DESC_SZ) | | ||
1056 | (RSI_WIFI_MGMT_Q << 12)); | ||
1057 | |||
1058 | skb_put(skb, | ||
1059 | sizeof(struct rsi_auto_rate)); | ||
1060 | kfree(selected_rates); | ||
1061 | |||
1062 | return rsi_send_internal_mgmt_frame(common, skb); | ||
1063 | } | ||
1064 | |||
1065 | /** | ||
1066 | * rsi_inform_bss_status() - This function informs about bss status with the | ||
1067 | * help of sta notify params by sending an internal | ||
1068 | * management frame to firmware. | ||
1069 | * @common: Pointer to the driver private structure. | ||
1070 | * @status: Bss status type. | ||
1071 | * @bssid: Bssid. | ||
1072 | * @qos_enable: Qos is enabled. | ||
1073 | * @aid: Aid (unique for all STAs). | ||
1074 | * | ||
1075 | * Return: None. | ||
1076 | */ | ||
1077 | void rsi_inform_bss_status(struct rsi_common *common, | ||
1078 | u8 status, | ||
1079 | const unsigned char *bssid, | ||
1080 | u8 qos_enable, | ||
1081 | u16 aid) | ||
1082 | { | ||
1083 | if (status) { | ||
1084 | rsi_hal_send_sta_notify_frame(common, | ||
1085 | NL80211_IFTYPE_STATION, | ||
1086 | STA_CONNECTED, | ||
1087 | bssid, | ||
1088 | qos_enable, | ||
1089 | aid); | ||
1090 | if (common->min_rate == 0xffff) | ||
1091 | rsi_send_auto_rate_request(common); | ||
1092 | } else { | ||
1093 | rsi_hal_send_sta_notify_frame(common, | ||
1094 | NL80211_IFTYPE_STATION, | ||
1095 | STA_DISCONNECTED, | ||
1096 | bssid, | ||
1097 | qos_enable, | ||
1098 | aid); | ||
1099 | } | ||
1100 | } | ||
1101 | |||
1102 | /** | ||
1103 | * rsi_eeprom_read() - This function sends a frame to read the mac address | ||
1104 | * from the eeprom. | ||
1105 | * @common: Pointer to the driver private structure. | ||
1106 | * | ||
1107 | * Return: 0 on success, -1 on failure. | ||
1108 | */ | ||
1109 | static int rsi_eeprom_read(struct rsi_common *common) | ||
1110 | { | ||
1111 | struct rsi_mac_frame *mgmt_frame; | ||
1112 | struct sk_buff *skb; | ||
1113 | |||
1114 | rsi_dbg(MGMT_TX_ZONE, "%s: Sending EEPROM read req frame\n", __func__); | ||
1115 | |||
1116 | skb = dev_alloc_skb(FRAME_DESC_SZ); | ||
1117 | if (!skb) { | ||
1118 | rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n", | ||
1119 | __func__); | ||
1120 | return -ENOMEM; | ||
1121 | } | ||
1122 | |||
1123 | memset(skb->data, 0, FRAME_DESC_SZ); | ||
1124 | mgmt_frame = (struct rsi_mac_frame *)skb->data; | ||
1125 | |||
1126 | /* FrameType */ | ||
1127 | mgmt_frame->desc_word[1] = cpu_to_le16(EEPROM_READ_TYPE); | ||
1128 | mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12); | ||
1129 | /* Number of bytes to read */ | ||
1130 | mgmt_frame->desc_word[3] = cpu_to_le16(ETH_ALEN + | ||
1131 | WLAN_MAC_MAGIC_WORD_LEN + | ||
1132 | WLAN_HOST_MODE_LEN + | ||
1133 | WLAN_FW_VERSION_LEN); | ||
1134 | /* Address to read */ | ||
1135 | mgmt_frame->desc_word[4] = cpu_to_le16(WLAN_MAC_EEPROM_ADDR); | ||
1136 | |||
1137 | skb_put(skb, FRAME_DESC_SZ); | ||
1138 | |||
1139 | return rsi_send_internal_mgmt_frame(common, skb); | ||
1140 | } | ||
1141 | |||
1142 | /** | ||
1143 | * rsi_handle_ta_confirm_type() - This function handles the confirm frames. | ||
1144 | * @common: Pointer to the driver private structure. | ||
1145 | * @msg: Pointer to received packet. | ||
1146 | * | ||
1147 | * Return: 0 on success, -1 on failure. | ||
1148 | */ | ||
1149 | static int rsi_handle_ta_confirm_type(struct rsi_common *common, | ||
1150 | u8 *msg) | ||
1151 | { | ||
1152 | u8 sub_type = (msg[15] & 0xff); | ||
1153 | |||
1154 | switch (sub_type) { | ||
1155 | case BOOTUP_PARAMS_REQUEST: | ||
1156 | rsi_dbg(FSM_ZONE, "%s: Boot up params confirm received\n", | ||
1157 | __func__); | ||
1158 | if (common->fsm_state == FSM_BOOT_PARAMS_SENT) { | ||
1159 | if (rsi_eeprom_read(common)) { | ||
1160 | common->fsm_state = FSM_CARD_NOT_READY; | ||
1161 | goto out; | ||
1162 | } else { | ||
1163 | common->fsm_state = FSM_EEPROM_READ_MAC_ADDR; | ||
1164 | } | ||
1165 | } else { | ||
1166 | rsi_dbg(ERR_ZONE, | ||
1167 | "%s: Received bootup params cfm in %d state\n", | ||
1168 | __func__, common->fsm_state); | ||
1169 | return 0; | ||
1170 | } | ||
1171 | break; | ||
1172 | |||
1173 | case EEPROM_READ_TYPE: | ||
1174 | if (common->fsm_state == FSM_EEPROM_READ_MAC_ADDR) { | ||
1175 | if (msg[16] == MAGIC_WORD) { | ||
1176 | u8 offset = (FRAME_DESC_SZ + WLAN_HOST_MODE_LEN | ||
1177 | + WLAN_MAC_MAGIC_WORD_LEN); | ||
1178 | memcpy(common->mac_addr, | ||
1179 | &msg[offset], | ||
1180 | ETH_ALEN); | ||
1181 | memcpy(&common->fw_ver, | ||
1182 | &msg[offset + ETH_ALEN], | ||
1183 | sizeof(struct version_info)); | ||
1184 | |||
1185 | } else { | ||
1186 | common->fsm_state = FSM_CARD_NOT_READY; | ||
1187 | break; | ||
1188 | } | ||
1189 | if (rsi_send_reset_mac(common)) | ||
1190 | goto out; | ||
1191 | else | ||
1192 | common->fsm_state = FSM_RESET_MAC_SENT; | ||
1193 | } else { | ||
1194 | rsi_dbg(ERR_ZONE, | ||
1195 | "%s: Received eeprom mac addr in %d state\n", | ||
1196 | __func__, common->fsm_state); | ||
1197 | return 0; | ||
1198 | } | ||
1199 | break; | ||
1200 | |||
1201 | case RESET_MAC_REQ: | ||
1202 | if (common->fsm_state == FSM_RESET_MAC_SENT) { | ||
1203 | rsi_dbg(FSM_ZONE, "%s: Reset MAC cfm received\n", | ||
1204 | __func__); | ||
1205 | |||
1206 | if (rsi_load_radio_caps(common)) | ||
1207 | goto out; | ||
1208 | else | ||
1209 | common->fsm_state = FSM_RADIO_CAPS_SENT; | ||
1210 | } else { | ||
1211 | rsi_dbg(ERR_ZONE, | ||
1212 | "%s: Received reset mac cfm in %d state\n", | ||
1213 | __func__, common->fsm_state); | ||
1214 | return 0; | ||
1215 | } | ||
1216 | break; | ||
1217 | |||
1218 | case RADIO_CAPABILITIES: | ||
1219 | if (common->fsm_state == FSM_RADIO_CAPS_SENT) { | ||
1220 | common->rf_reset = 1; | ||
1221 | if (rsi_program_bb_rf(common)) { | ||
1222 | goto out; | ||
1223 | } else { | ||
1224 | common->fsm_state = FSM_BB_RF_PROG_SENT; | ||
1225 | rsi_dbg(FSM_ZONE, "%s: Radio cap cfm received\n", | ||
1226 | __func__); | ||
1227 | } | ||
1228 | } else { | ||
1229 | rsi_dbg(ERR_ZONE, | ||
1230 | "%s: Received radio caps cfm in %d state\n", | ||
1231 | __func__, common->fsm_state); | ||
1232 | return 0; | ||
1233 | } | ||
1234 | break; | ||
1235 | |||
1236 | case BB_PROG_VALUES_REQUEST: | ||
1237 | case RF_PROG_VALUES_REQUEST: | ||
1238 | case BBP_PROG_IN_TA: | ||
1239 | rsi_dbg(FSM_ZONE, "%s: BB/RF cfm received\n", __func__); | ||
1240 | if (common->fsm_state == FSM_BB_RF_PROG_SENT) { | ||
1241 | common->bb_rf_prog_count--; | ||
1242 | if (!common->bb_rf_prog_count) { | ||
1243 | common->fsm_state = FSM_MAC_INIT_DONE; | ||
1244 | return rsi_mac80211_attach(common); | ||
1245 | } | ||
1246 | } else { | ||
1247 | goto out; | ||
1248 | } | ||
1249 | break; | ||
1250 | |||
1251 | default: | ||
1252 | rsi_dbg(INFO_ZONE, "%s: Invalid TA confirm pkt received\n", | ||
1253 | __func__); | ||
1254 | break; | ||
1255 | } | ||
1256 | return 0; | ||
1257 | out: | ||
1258 | rsi_dbg(ERR_ZONE, "%s: Unable to send pkt/Invalid frame received\n", | ||
1259 | __func__); | ||
1260 | return -EINVAL; | ||
1261 | } | ||
1262 | |||
1263 | /** | ||
1264 | * rsi_mgmt_pkt_recv() - This function processes the management packets | ||
1265 | * recieved from the hardware. | ||
1266 | * @common: Pointer to the driver private structure. | ||
1267 | * @msg: Pointer to the received packet. | ||
1268 | * | ||
1269 | * Return: 0 on success, -1 on failure. | ||
1270 | */ | ||
1271 | int rsi_mgmt_pkt_recv(struct rsi_common *common, u8 *msg) | ||
1272 | { | ||
1273 | s32 msg_len = (le16_to_cpu(*(__le16 *)&msg[0]) & 0x0fff); | ||
1274 | u16 msg_type = (msg[2]); | ||
1275 | |||
1276 | rsi_dbg(FSM_ZONE, "%s: Msg Len: %d, Msg Type: %4x\n", | ||
1277 | __func__, msg_len, msg_type); | ||
1278 | |||
1279 | if (msg_type == TA_CONFIRM_TYPE) { | ||
1280 | return rsi_handle_ta_confirm_type(common, msg); | ||
1281 | } else if (msg_type == CARD_READY_IND) { | ||
1282 | rsi_dbg(FSM_ZONE, "%s: Card ready indication received\n", | ||
1283 | __func__); | ||
1284 | if (common->fsm_state == FSM_CARD_NOT_READY) { | ||
1285 | rsi_set_default_parameters(common); | ||
1286 | |||
1287 | if (rsi_load_bootup_params(common)) | ||
1288 | return -ENOMEM; | ||
1289 | else | ||
1290 | common->fsm_state = FSM_BOOT_PARAMS_SENT; | ||
1291 | } else { | ||
1292 | return -EINVAL; | ||
1293 | } | ||
1294 | } else if (msg_type == TX_STATUS_IND) { | ||
1295 | if (msg[15] == PROBEREQ_CONFIRM) | ||
1296 | common->mgmt_q_block = false; | ||
1297 | rsi_dbg(FSM_ZONE, "%s: Probe confirm received\n", | ||
1298 | __func__); | ||
1299 | } else { | ||
1300 | return rsi_mgmt_pkt_to_core(common, msg, msg_len, msg_type); | ||
1301 | } | ||
1302 | return 0; | ||
1303 | } | ||
diff --git a/drivers/net/wireless/rsi/rsi_91x_pkt.c b/drivers/net/wireless/rsi/rsi_91x_pkt.c new file mode 100644 index 000000000000..8e48e72bae20 --- /dev/null +++ b/drivers/net/wireless/rsi/rsi_91x_pkt.c | |||
@@ -0,0 +1,196 @@ | |||
1 | /** | ||
2 | * Copyright (c) 2014 Redpine Signals Inc. | ||
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 | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include "rsi_mgmt.h" | ||
18 | |||
19 | /** | ||
20 | * rsi_send_data_pkt() - This function sends the recieved data packet from | ||
21 | * driver to device. | ||
22 | * @common: Pointer to the driver private structure. | ||
23 | * @skb: Pointer to the socket buffer structure. | ||
24 | * | ||
25 | * Return: status: 0 on success, -1 on failure. | ||
26 | */ | ||
27 | int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb) | ||
28 | { | ||
29 | struct rsi_hw *adapter = common->priv; | ||
30 | struct ieee80211_hdr *tmp_hdr = NULL; | ||
31 | struct ieee80211_tx_info *info; | ||
32 | struct skb_info *tx_params; | ||
33 | struct ieee80211_bss_conf *bss = NULL; | ||
34 | int status = -EINVAL; | ||
35 | u8 ieee80211_size = MIN_802_11_HDR_LEN; | ||
36 | u8 extnd_size = 0; | ||
37 | __le16 *frame_desc; | ||
38 | u16 seq_num = 0; | ||
39 | |||
40 | info = IEEE80211_SKB_CB(skb); | ||
41 | bss = &info->control.vif->bss_conf; | ||
42 | tx_params = (struct skb_info *)info->driver_data; | ||
43 | |||
44 | if (!bss->assoc) | ||
45 | goto err; | ||
46 | |||
47 | tmp_hdr = (struct ieee80211_hdr *)&skb->data[0]; | ||
48 | seq_num = (le16_to_cpu(tmp_hdr->seq_ctrl) >> 4); | ||
49 | |||
50 | extnd_size = ((uintptr_t)skb->data & 0x3); | ||
51 | |||
52 | if ((FRAME_DESC_SZ + extnd_size) > skb_headroom(skb)) { | ||
53 | rsi_dbg(ERR_ZONE, "%s: Unable to send pkt\n", __func__); | ||
54 | status = -ENOSPC; | ||
55 | goto err; | ||
56 | } | ||
57 | |||
58 | skb_push(skb, (FRAME_DESC_SZ + extnd_size)); | ||
59 | frame_desc = (__le16 *)&skb->data[0]; | ||
60 | memset((u8 *)frame_desc, 0, FRAME_DESC_SZ); | ||
61 | |||
62 | if (ieee80211_is_data_qos(tmp_hdr->frame_control)) { | ||
63 | ieee80211_size += 2; | ||
64 | frame_desc[6] |= cpu_to_le16(BIT(12)); | ||
65 | } | ||
66 | |||
67 | if ((!(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) && | ||
68 | (common->secinfo.security_enable)) { | ||
69 | if (rsi_is_cipher_wep(common)) | ||
70 | ieee80211_size += 4; | ||
71 | else | ||
72 | ieee80211_size += 8; | ||
73 | frame_desc[6] |= cpu_to_le16(BIT(15)); | ||
74 | } | ||
75 | |||
76 | frame_desc[0] = cpu_to_le16((skb->len - FRAME_DESC_SZ) | | ||
77 | (RSI_WIFI_DATA_Q << 12)); | ||
78 | frame_desc[2] = cpu_to_le16((extnd_size) | (ieee80211_size) << 8); | ||
79 | |||
80 | if (common->min_rate != 0xffff) { | ||
81 | /* Send fixed rate */ | ||
82 | frame_desc[3] = cpu_to_le16(RATE_INFO_ENABLE); | ||
83 | frame_desc[4] = cpu_to_le16(common->min_rate); | ||
84 | } | ||
85 | |||
86 | frame_desc[6] |= cpu_to_le16(seq_num & 0xfff); | ||
87 | frame_desc[7] = cpu_to_le16(((tx_params->tid & 0xf) << 4) | | ||
88 | (skb->priority & 0xf) | | ||
89 | (tx_params->sta_id << 8)); | ||
90 | |||
91 | status = adapter->host_intf_write_pkt(common->priv, | ||
92 | skb->data, | ||
93 | skb->len); | ||
94 | if (status) | ||
95 | rsi_dbg(ERR_ZONE, "%s: Failed to write pkt\n", | ||
96 | __func__); | ||
97 | |||
98 | err: | ||
99 | ++common->tx_stats.total_tx_pkt_freed[skb->priority]; | ||
100 | rsi_indicate_tx_status(common->priv, skb, status); | ||
101 | return status; | ||
102 | } | ||
103 | |||
104 | /** | ||
105 | * rsi_send_mgmt_pkt() - This functions sends the received management packet | ||
106 | * from driver to device. | ||
107 | * @common: Pointer to the driver private structure. | ||
108 | * @skb: Pointer to the socket buffer structure. | ||
109 | * | ||
110 | * Return: status: 0 on success, -1 on failure. | ||
111 | */ | ||
112 | int rsi_send_mgmt_pkt(struct rsi_common *common, | ||
113 | struct sk_buff *skb) | ||
114 | { | ||
115 | struct rsi_hw *adapter = common->priv; | ||
116 | struct ieee80211_hdr *wh = NULL; | ||
117 | struct ieee80211_tx_info *info; | ||
118 | struct ieee80211_bss_conf *bss = NULL; | ||
119 | struct skb_info *tx_params; | ||
120 | int status = -E2BIG; | ||
121 | __le16 *msg = NULL; | ||
122 | u8 extnd_size = 0; | ||
123 | u8 vap_id = 0; | ||
124 | |||
125 | info = IEEE80211_SKB_CB(skb); | ||
126 | tx_params = (struct skb_info *)info->driver_data; | ||
127 | extnd_size = ((uintptr_t)skb->data & 0x3); | ||
128 | |||
129 | if (tx_params->flags & INTERNAL_MGMT_PKT) { | ||
130 | if ((extnd_size) > skb_headroom(skb)) { | ||
131 | rsi_dbg(ERR_ZONE, "%s: Unable to send pkt\n", __func__); | ||
132 | dev_kfree_skb(skb); | ||
133 | return -ENOSPC; | ||
134 | } | ||
135 | skb_push(skb, extnd_size); | ||
136 | skb->data[extnd_size + 4] = extnd_size; | ||
137 | status = adapter->host_intf_write_pkt(common->priv, | ||
138 | (u8 *)skb->data, | ||
139 | skb->len); | ||
140 | if (status) { | ||
141 | rsi_dbg(ERR_ZONE, | ||
142 | "%s: Failed to write the packet\n", __func__); | ||
143 | } | ||
144 | dev_kfree_skb(skb); | ||
145 | return status; | ||
146 | } | ||
147 | |||
148 | bss = &info->control.vif->bss_conf; | ||
149 | wh = (struct ieee80211_hdr *)&skb->data[0]; | ||
150 | |||
151 | if (FRAME_DESC_SZ > skb_headroom(skb)) | ||
152 | goto err; | ||
153 | |||
154 | skb_push(skb, FRAME_DESC_SZ); | ||
155 | memset(skb->data, 0, FRAME_DESC_SZ); | ||
156 | msg = (__le16 *)skb->data; | ||
157 | |||
158 | if (skb->len > MAX_MGMT_PKT_SIZE) { | ||
159 | rsi_dbg(INFO_ZONE, "%s: Dropping mgmt pkt > 512\n", __func__); | ||
160 | goto err; | ||
161 | } | ||
162 | |||
163 | msg[0] = cpu_to_le16((skb->len - FRAME_DESC_SZ) | | ||
164 | (RSI_WIFI_MGMT_Q << 12)); | ||
165 | msg[1] = cpu_to_le16(TX_DOT11_MGMT); | ||
166 | msg[2] = cpu_to_le16(MIN_802_11_HDR_LEN << 8); | ||
167 | msg[3] = cpu_to_le16(RATE_INFO_ENABLE); | ||
168 | msg[6] = cpu_to_le16(le16_to_cpu(wh->seq_ctrl) >> 4); | ||
169 | |||
170 | if (wh->addr1[0] & BIT(0)) | ||
171 | msg[3] |= cpu_to_le16(RSI_BROADCAST_PKT); | ||
172 | |||
173 | if (common->band == IEEE80211_BAND_2GHZ) | ||
174 | msg[4] = cpu_to_le16(RSI_11B_MODE); | ||
175 | else | ||
176 | msg[4] = cpu_to_le16((RSI_RATE_6 & 0x0f) | RSI_11G_MODE); | ||
177 | |||
178 | /* Indicate to firmware to give cfm */ | ||
179 | if ((skb->data[16] == IEEE80211_STYPE_PROBE_REQ) && (!bss->assoc)) { | ||
180 | msg[1] |= cpu_to_le16(BIT(10)); | ||
181 | msg[7] = cpu_to_le16(PROBEREQ_CONFIRM); | ||
182 | common->mgmt_q_block = true; | ||
183 | } | ||
184 | |||
185 | msg[7] |= cpu_to_le16(vap_id << 8); | ||
186 | |||
187 | status = adapter->host_intf_write_pkt(common->priv, | ||
188 | (u8 *)msg, | ||
189 | skb->len); | ||
190 | if (status) | ||
191 | rsi_dbg(ERR_ZONE, "%s: Failed to write the packet\n", __func__); | ||
192 | |||
193 | err: | ||
194 | rsi_indicate_tx_status(common->priv, skb, status); | ||
195 | return status; | ||
196 | } | ||
diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c new file mode 100644 index 000000000000..852453f386e2 --- /dev/null +++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c | |||
@@ -0,0 +1,850 @@ | |||
1 | /** | ||
2 | * Copyright (c) 2014 Redpine Signals Inc. | ||
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 | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include "rsi_sdio.h" | ||
20 | #include "rsi_common.h" | ||
21 | |||
22 | /** | ||
23 | * rsi_sdio_set_cmd52_arg() - This function prepares cmd 52 read/write arg. | ||
24 | * @rw: Read/write | ||
25 | * @func: function number | ||
26 | * @raw: indicates whether to perform read after write | ||
27 | * @address: address to which to read/write | ||
28 | * @writedata: data to write | ||
29 | * | ||
30 | * Return: argument | ||
31 | */ | ||
32 | static u32 rsi_sdio_set_cmd52_arg(bool rw, | ||
33 | u8 func, | ||
34 | u8 raw, | ||
35 | u32 address, | ||
36 | u8 writedata) | ||
37 | { | ||
38 | return ((rw & 1) << 31) | ((func & 0x7) << 28) | | ||
39 | ((raw & 1) << 27) | (1 << 26) | | ||
40 | ((address & 0x1FFFF) << 9) | (1 << 8) | | ||
41 | (writedata & 0xFF); | ||
42 | } | ||
43 | |||
44 | /** | ||
45 | * rsi_cmd52writebyte() - This function issues cmd52 byte write onto the card. | ||
46 | * @card: Pointer to the mmc_card. | ||
47 | * @address: Address to write. | ||
48 | * @byte: Data to write. | ||
49 | * | ||
50 | * Return: Write status. | ||
51 | */ | ||
52 | static int rsi_cmd52writebyte(struct mmc_card *card, | ||
53 | u32 address, | ||
54 | u8 byte) | ||
55 | { | ||
56 | struct mmc_command io_cmd; | ||
57 | u32 arg; | ||
58 | |||
59 | memset(&io_cmd, 0, sizeof(io_cmd)); | ||
60 | arg = rsi_sdio_set_cmd52_arg(1, 0, 0, address, byte); | ||
61 | io_cmd.opcode = SD_IO_RW_DIRECT; | ||
62 | io_cmd.arg = arg; | ||
63 | io_cmd.flags = MMC_RSP_R5 | MMC_CMD_AC; | ||
64 | |||
65 | return mmc_wait_for_cmd(card->host, &io_cmd, 0); | ||
66 | } | ||
67 | |||
68 | /** | ||
69 | * rsi_cmd52readbyte() - This function issues cmd52 byte read onto the card. | ||
70 | * @card: Pointer to the mmc_card. | ||
71 | * @address: Address to read from. | ||
72 | * @byte: Variable to store read value. | ||
73 | * | ||
74 | * Return: Read status. | ||
75 | */ | ||
76 | static int rsi_cmd52readbyte(struct mmc_card *card, | ||
77 | u32 address, | ||
78 | u8 *byte) | ||
79 | { | ||
80 | struct mmc_command io_cmd; | ||
81 | u32 arg; | ||
82 | int err; | ||
83 | |||
84 | memset(&io_cmd, 0, sizeof(io_cmd)); | ||
85 | arg = rsi_sdio_set_cmd52_arg(0, 0, 0, address, 0); | ||
86 | io_cmd.opcode = SD_IO_RW_DIRECT; | ||
87 | io_cmd.arg = arg; | ||
88 | io_cmd.flags = MMC_RSP_R5 | MMC_CMD_AC; | ||
89 | |||
90 | err = mmc_wait_for_cmd(card->host, &io_cmd, 0); | ||
91 | if ((!err) && (byte)) | ||
92 | *byte = io_cmd.resp[0] & 0xFF; | ||
93 | return err; | ||
94 | } | ||
95 | |||
96 | /** | ||
97 | * rsi_issue_sdiocommand() - This function issues sdio commands. | ||
98 | * @func: Pointer to the sdio_func structure. | ||
99 | * @opcode: Opcode value. | ||
100 | * @arg: Arguments to pass. | ||
101 | * @flags: Flags which are set. | ||
102 | * @resp: Pointer to store response. | ||
103 | * | ||
104 | * Return: err: command status as 0 or -1. | ||
105 | */ | ||
106 | static int rsi_issue_sdiocommand(struct sdio_func *func, | ||
107 | u32 opcode, | ||
108 | u32 arg, | ||
109 | u32 flags, | ||
110 | u32 *resp) | ||
111 | { | ||
112 | struct mmc_command cmd; | ||
113 | struct mmc_host *host; | ||
114 | int err; | ||
115 | |||
116 | host = func->card->host; | ||
117 | |||
118 | memset(&cmd, 0, sizeof(struct mmc_command)); | ||
119 | cmd.opcode = opcode; | ||
120 | cmd.arg = arg; | ||
121 | cmd.flags = flags; | ||
122 | err = mmc_wait_for_cmd(host, &cmd, 3); | ||
123 | |||
124 | if ((!err) && (resp)) | ||
125 | *resp = cmd.resp[0]; | ||
126 | |||
127 | return err; | ||
128 | } | ||
129 | |||
130 | /** | ||
131 | * rsi_handle_interrupt() - This function is called upon the occurence | ||
132 | * of an interrupt. | ||
133 | * @function: Pointer to the sdio_func structure. | ||
134 | * | ||
135 | * Return: None. | ||
136 | */ | ||
137 | static void rsi_handle_interrupt(struct sdio_func *function) | ||
138 | { | ||
139 | struct rsi_hw *adapter = sdio_get_drvdata(function); | ||
140 | |||
141 | sdio_release_host(function); | ||
142 | rsi_interrupt_handler(adapter); | ||
143 | sdio_claim_host(function); | ||
144 | } | ||
145 | |||
146 | /** | ||
147 | * rsi_reset_card() - This function resets and re-initializes the card. | ||
148 | * @pfunction: Pointer to the sdio_func structure. | ||
149 | * | ||
150 | * Return: None. | ||
151 | */ | ||
152 | static void rsi_reset_card(struct sdio_func *pfunction) | ||
153 | { | ||
154 | int ret = 0; | ||
155 | int err; | ||
156 | struct mmc_card *card = pfunction->card; | ||
157 | struct mmc_host *host = card->host; | ||
158 | s32 bit = (fls(host->ocr_avail) - 1); | ||
159 | u8 cmd52_resp; | ||
160 | u32 clock, resp, i; | ||
161 | u16 rca; | ||
162 | |||
163 | /* Reset 9110 chip */ | ||
164 | ret = rsi_cmd52writebyte(pfunction->card, | ||
165 | SDIO_CCCR_ABORT, | ||
166 | (1 << 3)); | ||
167 | |||
168 | /* Card will not send any response as it is getting reset immediately | ||
169 | * Hence expect a timeout status from host controller | ||
170 | */ | ||
171 | if (ret != -ETIMEDOUT) | ||
172 | rsi_dbg(ERR_ZONE, "%s: Reset failed : %d\n", __func__, ret); | ||
173 | |||
174 | /* Wait for few milli seconds to get rid of residue charges if any */ | ||
175 | msleep(20); | ||
176 | |||
177 | /* Initialize the SDIO card */ | ||
178 | host->ios.vdd = bit; | ||
179 | host->ios.chip_select = MMC_CS_DONTCARE; | ||
180 | host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; | ||
181 | host->ios.power_mode = MMC_POWER_UP; | ||
182 | host->ios.bus_width = MMC_BUS_WIDTH_1; | ||
183 | host->ios.timing = MMC_TIMING_LEGACY; | ||
184 | host->ops->set_ios(host, &host->ios); | ||
185 | |||
186 | /* | ||
187 | * This delay should be sufficient to allow the power supply | ||
188 | * to reach the minimum voltage. | ||
189 | */ | ||
190 | msleep(20); | ||
191 | |||
192 | host->ios.clock = host->f_min; | ||
193 | host->ios.power_mode = MMC_POWER_ON; | ||
194 | host->ops->set_ios(host, &host->ios); | ||
195 | |||
196 | /* | ||
197 | * This delay must be at least 74 clock sizes, or 1 ms, or the | ||
198 | * time required to reach a stable voltage. | ||
199 | */ | ||
200 | msleep(20); | ||
201 | |||
202 | /* Issue CMD0. Goto idle state */ | ||
203 | host->ios.chip_select = MMC_CS_HIGH; | ||
204 | host->ops->set_ios(host, &host->ios); | ||
205 | msleep(20); | ||
206 | err = rsi_issue_sdiocommand(pfunction, | ||
207 | MMC_GO_IDLE_STATE, | ||
208 | 0, | ||
209 | (MMC_RSP_NONE | MMC_CMD_BC), | ||
210 | NULL); | ||
211 | host->ios.chip_select = MMC_CS_DONTCARE; | ||
212 | host->ops->set_ios(host, &host->ios); | ||
213 | msleep(20); | ||
214 | host->use_spi_crc = 0; | ||
215 | |||
216 | if (err) | ||
217 | rsi_dbg(ERR_ZONE, "%s: CMD0 failed : %d\n", __func__, err); | ||
218 | |||
219 | if (!host->ocr_avail) { | ||
220 | /* Issue CMD5, arg = 0 */ | ||
221 | err = rsi_issue_sdiocommand(pfunction, | ||
222 | SD_IO_SEND_OP_COND, | ||
223 | 0, | ||
224 | (MMC_RSP_R4 | MMC_CMD_BCR), | ||
225 | &resp); | ||
226 | if (err) | ||
227 | rsi_dbg(ERR_ZONE, "%s: CMD5 failed : %d\n", | ||
228 | __func__, err); | ||
229 | host->ocr_avail = resp; | ||
230 | } | ||
231 | |||
232 | /* Issue CMD5, arg = ocr. Wait till card is ready */ | ||
233 | for (i = 0; i < 100; i++) { | ||
234 | err = rsi_issue_sdiocommand(pfunction, | ||
235 | SD_IO_SEND_OP_COND, | ||
236 | host->ocr_avail, | ||
237 | (MMC_RSP_R4 | MMC_CMD_BCR), | ||
238 | &resp); | ||
239 | if (err) { | ||
240 | rsi_dbg(ERR_ZONE, "%s: CMD5 failed : %d\n", | ||
241 | __func__, err); | ||
242 | break; | ||
243 | } | ||
244 | |||
245 | if (resp & MMC_CARD_BUSY) | ||
246 | break; | ||
247 | msleep(20); | ||
248 | } | ||
249 | |||
250 | if ((i == 100) || (err)) { | ||
251 | rsi_dbg(ERR_ZONE, "%s: card in not ready : %d %d\n", | ||
252 | __func__, i, err); | ||
253 | return; | ||
254 | } | ||
255 | |||
256 | /* Issue CMD3, get RCA */ | ||
257 | err = rsi_issue_sdiocommand(pfunction, | ||
258 | SD_SEND_RELATIVE_ADDR, | ||
259 | 0, | ||
260 | (MMC_RSP_R6 | MMC_CMD_BCR), | ||
261 | &resp); | ||
262 | if (err) { | ||
263 | rsi_dbg(ERR_ZONE, "%s: CMD3 failed : %d\n", __func__, err); | ||
264 | return; | ||
265 | } | ||
266 | rca = resp >> 16; | ||
267 | host->ios.bus_mode = MMC_BUSMODE_PUSHPULL; | ||
268 | host->ops->set_ios(host, &host->ios); | ||
269 | |||
270 | /* Issue CMD7, select card */ | ||
271 | err = rsi_issue_sdiocommand(pfunction, | ||
272 | MMC_SELECT_CARD, | ||
273 | (rca << 16), | ||
274 | (MMC_RSP_R1 | MMC_CMD_AC), | ||
275 | NULL); | ||
276 | if (err) { | ||
277 | rsi_dbg(ERR_ZONE, "%s: CMD7 failed : %d\n", __func__, err); | ||
278 | return; | ||
279 | } | ||
280 | |||
281 | /* Enable high speed */ | ||
282 | if (card->host->caps & MMC_CAP_SD_HIGHSPEED) { | ||
283 | rsi_dbg(ERR_ZONE, "%s: Set high speed mode\n", __func__); | ||
284 | err = rsi_cmd52readbyte(card, SDIO_CCCR_SPEED, &cmd52_resp); | ||
285 | if (err) { | ||
286 | rsi_dbg(ERR_ZONE, "%s: CCCR speed reg read failed: %d\n", | ||
287 | __func__, err); | ||
288 | card->state &= ~MMC_STATE_HIGHSPEED; | ||
289 | } else { | ||
290 | err = rsi_cmd52writebyte(card, | ||
291 | SDIO_CCCR_SPEED, | ||
292 | (cmd52_resp | SDIO_SPEED_EHS)); | ||
293 | if (err) { | ||
294 | rsi_dbg(ERR_ZONE, | ||
295 | "%s: CCR speed regwrite failed %d\n", | ||
296 | __func__, err); | ||
297 | return; | ||
298 | } | ||
299 | mmc_card_set_highspeed(card); | ||
300 | host->ios.timing = MMC_TIMING_SD_HS; | ||
301 | host->ops->set_ios(host, &host->ios); | ||
302 | } | ||
303 | } | ||
304 | |||
305 | /* Set clock */ | ||
306 | if (mmc_card_highspeed(card)) | ||
307 | clock = 50000000; | ||
308 | else | ||
309 | clock = card->cis.max_dtr; | ||
310 | |||
311 | if (clock > host->f_max) | ||
312 | clock = host->f_max; | ||
313 | |||
314 | host->ios.clock = clock; | ||
315 | host->ops->set_ios(host, &host->ios); | ||
316 | |||
317 | if (card->host->caps & MMC_CAP_4_BIT_DATA) { | ||
318 | /* CMD52: Set bus width & disable card detect resistor */ | ||
319 | err = rsi_cmd52writebyte(card, | ||
320 | SDIO_CCCR_IF, | ||
321 | (SDIO_BUS_CD_DISABLE | | ||
322 | SDIO_BUS_WIDTH_4BIT)); | ||
323 | if (err) { | ||
324 | rsi_dbg(ERR_ZONE, "%s: Set bus mode failed : %d\n", | ||
325 | __func__, err); | ||
326 | return; | ||
327 | } | ||
328 | host->ios.bus_width = MMC_BUS_WIDTH_4; | ||
329 | host->ops->set_ios(host, &host->ios); | ||
330 | } | ||
331 | } | ||
332 | |||
333 | /** | ||
334 | * rsi_setclock() - This function sets the clock frequency. | ||
335 | * @adapter: Pointer to the adapter structure. | ||
336 | * @freq: Clock frequency. | ||
337 | * | ||
338 | * Return: None. | ||
339 | */ | ||
340 | static void rsi_setclock(struct rsi_hw *adapter, u32 freq) | ||
341 | { | ||
342 | struct rsi_91x_sdiodev *dev = | ||
343 | (struct rsi_91x_sdiodev *)adapter->rsi_dev; | ||
344 | struct mmc_host *host = dev->pfunction->card->host; | ||
345 | u32 clock; | ||
346 | |||
347 | clock = freq * 1000; | ||
348 | if (clock > host->f_max) | ||
349 | clock = host->f_max; | ||
350 | host->ios.clock = clock; | ||
351 | host->ops->set_ios(host, &host->ios); | ||
352 | } | ||
353 | |||
354 | /** | ||
355 | * rsi_setblocklength() - This function sets the host block length. | ||
356 | * @adapter: Pointer to the adapter structure. | ||
357 | * @length: Block length to be set. | ||
358 | * | ||
359 | * Return: status: 0 on success, -1 on failure. | ||
360 | */ | ||
361 | static int rsi_setblocklength(struct rsi_hw *adapter, u32 length) | ||
362 | { | ||
363 | struct rsi_91x_sdiodev *dev = | ||
364 | (struct rsi_91x_sdiodev *)adapter->rsi_dev; | ||
365 | int status; | ||
366 | rsi_dbg(INIT_ZONE, "%s: Setting the block length\n", __func__); | ||
367 | |||
368 | status = sdio_set_block_size(dev->pfunction, length); | ||
369 | dev->pfunction->max_blksize = 256; | ||
370 | |||
371 | rsi_dbg(INFO_ZONE, | ||
372 | "%s: Operational blk length is %d\n", __func__, length); | ||
373 | return status; | ||
374 | } | ||
375 | |||
376 | /** | ||
377 | * rsi_setupcard() - This function queries and sets the card's features. | ||
378 | * @adapter: Pointer to the adapter structure. | ||
379 | * | ||
380 | * Return: status: 0 on success, -1 on failure. | ||
381 | */ | ||
382 | static int rsi_setupcard(struct rsi_hw *adapter) | ||
383 | { | ||
384 | struct rsi_91x_sdiodev *dev = | ||
385 | (struct rsi_91x_sdiodev *)adapter->rsi_dev; | ||
386 | int status = 0; | ||
387 | |||
388 | rsi_setclock(adapter, 50000); | ||
389 | |||
390 | dev->tx_blk_size = 256; | ||
391 | status = rsi_setblocklength(adapter, dev->tx_blk_size); | ||
392 | if (status) | ||
393 | rsi_dbg(ERR_ZONE, | ||
394 | "%s: Unable to set block length\n", __func__); | ||
395 | return status; | ||
396 | } | ||
397 | |||
398 | /** | ||
399 | * rsi_sdio_read_register() - This function reads one byte of information | ||
400 | * from a register. | ||
401 | * @adapter: Pointer to the adapter structure. | ||
402 | * @addr: Address of the register. | ||
403 | * @data: Pointer to the data that stores the data read. | ||
404 | * | ||
405 | * Return: 0 on success, -1 on failure. | ||
406 | */ | ||
407 | int rsi_sdio_read_register(struct rsi_hw *adapter, | ||
408 | u32 addr, | ||
409 | u8 *data) | ||
410 | { | ||
411 | struct rsi_91x_sdiodev *dev = | ||
412 | (struct rsi_91x_sdiodev *)adapter->rsi_dev; | ||
413 | u8 fun_num = 0; | ||
414 | int status; | ||
415 | |||
416 | sdio_claim_host(dev->pfunction); | ||
417 | |||
418 | if (fun_num == 0) | ||
419 | *data = sdio_f0_readb(dev->pfunction, addr, &status); | ||
420 | else | ||
421 | *data = sdio_readb(dev->pfunction, addr, &status); | ||
422 | |||
423 | sdio_release_host(dev->pfunction); | ||
424 | |||
425 | return status; | ||
426 | } | ||
427 | |||
428 | /** | ||
429 | * rsi_sdio_write_register() - This function writes one byte of information | ||
430 | * into a register. | ||
431 | * @adapter: Pointer to the adapter structure. | ||
432 | * @function: Function Number. | ||
433 | * @addr: Address of the register. | ||
434 | * @data: Pointer to the data tha has to be written. | ||
435 | * | ||
436 | * Return: 0 on success, -1 on failure. | ||
437 | */ | ||
438 | int rsi_sdio_write_register(struct rsi_hw *adapter, | ||
439 | u8 function, | ||
440 | u32 addr, | ||
441 | u8 *data) | ||
442 | { | ||
443 | struct rsi_91x_sdiodev *dev = | ||
444 | (struct rsi_91x_sdiodev *)adapter->rsi_dev; | ||
445 | int status = 0; | ||
446 | |||
447 | sdio_claim_host(dev->pfunction); | ||
448 | |||
449 | if (function == 0) | ||
450 | sdio_f0_writeb(dev->pfunction, *data, addr, &status); | ||
451 | else | ||
452 | sdio_writeb(dev->pfunction, *data, addr, &status); | ||
453 | |||
454 | sdio_release_host(dev->pfunction); | ||
455 | |||
456 | return status; | ||
457 | } | ||
458 | |||
459 | /** | ||
460 | * rsi_sdio_ack_intr() - This function acks the interrupt received. | ||
461 | * @adapter: Pointer to the adapter structure. | ||
462 | * @int_bit: Interrupt bit to write into register. | ||
463 | * | ||
464 | * Return: None. | ||
465 | */ | ||
466 | void rsi_sdio_ack_intr(struct rsi_hw *adapter, u8 int_bit) | ||
467 | { | ||
468 | int status; | ||
469 | status = rsi_sdio_write_register(adapter, | ||
470 | 1, | ||
471 | (SDIO_FUN1_INTR_CLR_REG | | ||
472 | RSI_SD_REQUEST_MASTER), | ||
473 | &int_bit); | ||
474 | if (status) | ||
475 | rsi_dbg(ERR_ZONE, "%s: unable to send ack\n", __func__); | ||
476 | } | ||
477 | |||
478 | |||
479 | |||
480 | /** | ||
481 | * rsi_sdio_read_register_multiple() - This function read multiple bytes of | ||
482 | * information from the SD card. | ||
483 | * @adapter: Pointer to the adapter structure. | ||
484 | * @addr: Address of the register. | ||
485 | * @count: Number of multiple bytes to be read. | ||
486 | * @data: Pointer to the read data. | ||
487 | * | ||
488 | * Return: 0 on success, -1 on failure. | ||
489 | */ | ||
490 | static int rsi_sdio_read_register_multiple(struct rsi_hw *adapter, | ||
491 | u32 addr, | ||
492 | u32 count, | ||
493 | u8 *data) | ||
494 | { | ||
495 | struct rsi_91x_sdiodev *dev = | ||
496 | (struct rsi_91x_sdiodev *)adapter->rsi_dev; | ||
497 | u32 status; | ||
498 | |||
499 | sdio_claim_host(dev->pfunction); | ||
500 | |||
501 | status = sdio_readsb(dev->pfunction, data, addr, count); | ||
502 | |||
503 | sdio_release_host(dev->pfunction); | ||
504 | |||
505 | if (status != 0) | ||
506 | rsi_dbg(ERR_ZONE, "%s: Synch Cmd53 read failed\n", __func__); | ||
507 | return status; | ||
508 | } | ||
509 | |||
510 | /** | ||
511 | * rsi_sdio_write_register_multiple() - This function writes multiple bytes of | ||
512 | * information to the SD card. | ||
513 | * @adapter: Pointer to the adapter structure. | ||
514 | * @addr: Address of the register. | ||
515 | * @data: Pointer to the data that has to be written. | ||
516 | * @count: Number of multiple bytes to be written. | ||
517 | * | ||
518 | * Return: 0 on success, -1 on failure. | ||
519 | */ | ||
520 | int rsi_sdio_write_register_multiple(struct rsi_hw *adapter, | ||
521 | u32 addr, | ||
522 | u8 *data, | ||
523 | u32 count) | ||
524 | { | ||
525 | struct rsi_91x_sdiodev *dev = | ||
526 | (struct rsi_91x_sdiodev *)adapter->rsi_dev; | ||
527 | int status; | ||
528 | |||
529 | if (dev->write_fail > 1) { | ||
530 | rsi_dbg(ERR_ZONE, "%s: Stopping card writes\n", __func__); | ||
531 | return 0; | ||
532 | } else if (dev->write_fail == 1) { | ||
533 | /** | ||
534 | * Assuming it is a CRC failure, we want to allow another | ||
535 | * card write | ||
536 | */ | ||
537 | rsi_dbg(ERR_ZONE, "%s: Continue card writes\n", __func__); | ||
538 | dev->write_fail++; | ||
539 | } | ||
540 | |||
541 | sdio_claim_host(dev->pfunction); | ||
542 | |||
543 | status = sdio_writesb(dev->pfunction, addr, data, count); | ||
544 | |||
545 | sdio_release_host(dev->pfunction); | ||
546 | |||
547 | if (status) { | ||
548 | rsi_dbg(ERR_ZONE, "%s: Synch Cmd53 write failed %d\n", | ||
549 | __func__, status); | ||
550 | dev->write_fail = 2; | ||
551 | } else { | ||
552 | memcpy(dev->prev_desc, data, FRAME_DESC_SZ); | ||
553 | } | ||
554 | return status; | ||
555 | } | ||
556 | |||
557 | /** | ||
558 | * rsi_sdio_host_intf_write_pkt() - This function writes the packet to device. | ||
559 | * @adapter: Pointer to the adapter structure. | ||
560 | * @pkt: Pointer to the data to be written on to the device. | ||
561 | * @len: length of the data to be written on to the device. | ||
562 | * | ||
563 | * Return: 0 on success, -1 on failure. | ||
564 | */ | ||
565 | static int rsi_sdio_host_intf_write_pkt(struct rsi_hw *adapter, | ||
566 | u8 *pkt, | ||
567 | u32 len) | ||
568 | { | ||
569 | struct rsi_91x_sdiodev *dev = | ||
570 | (struct rsi_91x_sdiodev *)adapter->rsi_dev; | ||
571 | u32 block_size = dev->tx_blk_size; | ||
572 | u32 num_blocks, address, length; | ||
573 | u32 queueno; | ||
574 | int status; | ||
575 | |||
576 | queueno = ((pkt[1] >> 4) & 0xf); | ||
577 | |||
578 | num_blocks = len / block_size; | ||
579 | |||
580 | if (len % block_size) | ||
581 | num_blocks++; | ||
582 | |||
583 | address = (num_blocks * block_size | (queueno << 12)); | ||
584 | length = num_blocks * block_size; | ||
585 | |||
586 | status = rsi_sdio_write_register_multiple(adapter, | ||
587 | address, | ||
588 | (u8 *)pkt, | ||
589 | length); | ||
590 | if (status) | ||
591 | rsi_dbg(ERR_ZONE, "%s: Unable to write onto the card: %d\n", | ||
592 | __func__, status); | ||
593 | rsi_dbg(DATA_TX_ZONE, "%s: Successfully written onto card\n", __func__); | ||
594 | return status; | ||
595 | } | ||
596 | |||
597 | /** | ||
598 | * rsi_sdio_host_intf_read_pkt() - This function reads the packet | ||
599 | from the device. | ||
600 | * @adapter: Pointer to the adapter data structure. | ||
601 | * @pkt: Pointer to the packet data to be read from the the device. | ||
602 | * @length: Length of the data to be read from the device. | ||
603 | * | ||
604 | * Return: 0 on success, -1 on failure. | ||
605 | */ | ||
606 | int rsi_sdio_host_intf_read_pkt(struct rsi_hw *adapter, | ||
607 | u8 *pkt, | ||
608 | u32 length) | ||
609 | { | ||
610 | int status = -EINVAL; | ||
611 | |||
612 | if (!length) { | ||
613 | rsi_dbg(ERR_ZONE, "%s: Pkt size is zero\n", __func__); | ||
614 | return status; | ||
615 | } | ||
616 | |||
617 | status = rsi_sdio_read_register_multiple(adapter, | ||
618 | length, | ||
619 | length, /*num of bytes*/ | ||
620 | (u8 *)pkt); | ||
621 | |||
622 | if (status) | ||
623 | rsi_dbg(ERR_ZONE, "%s: Failed to read frame: %d\n", __func__, | ||
624 | status); | ||
625 | return status; | ||
626 | } | ||
627 | |||
628 | /** | ||
629 | * rsi_init_sdio_interface() - This function does init specific to SDIO. | ||
630 | * | ||
631 | * @adapter: Pointer to the adapter data structure. | ||
632 | * @pkt: Pointer to the packet data to be read from the the device. | ||
633 | * | ||
634 | * Return: 0 on success, -1 on failure. | ||
635 | */ | ||
636 | |||
637 | static int rsi_init_sdio_interface(struct rsi_hw *adapter, | ||
638 | struct sdio_func *pfunction) | ||
639 | { | ||
640 | struct rsi_91x_sdiodev *rsi_91x_dev; | ||
641 | int status = -ENOMEM; | ||
642 | |||
643 | rsi_91x_dev = kzalloc(sizeof(*rsi_91x_dev), GFP_KERNEL); | ||
644 | if (!rsi_91x_dev) | ||
645 | return status; | ||
646 | |||
647 | adapter->rsi_dev = rsi_91x_dev; | ||
648 | |||
649 | sdio_claim_host(pfunction); | ||
650 | |||
651 | pfunction->enable_timeout = 100; | ||
652 | status = sdio_enable_func(pfunction); | ||
653 | if (status) { | ||
654 | rsi_dbg(ERR_ZONE, "%s: Failed to enable interface\n", __func__); | ||
655 | sdio_release_host(pfunction); | ||
656 | return status; | ||
657 | } | ||
658 | |||
659 | rsi_dbg(INIT_ZONE, "%s: Enabled the interface\n", __func__); | ||
660 | |||
661 | rsi_91x_dev->pfunction = pfunction; | ||
662 | adapter->device = &pfunction->dev; | ||
663 | |||
664 | sdio_set_drvdata(pfunction, adapter); | ||
665 | |||
666 | status = rsi_setupcard(adapter); | ||
667 | if (status) { | ||
668 | rsi_dbg(ERR_ZONE, "%s: Failed to setup card\n", __func__); | ||
669 | goto fail; | ||
670 | } | ||
671 | |||
672 | rsi_dbg(INIT_ZONE, "%s: Setup card succesfully\n", __func__); | ||
673 | |||
674 | status = rsi_init_sdio_slave_regs(adapter); | ||
675 | if (status) { | ||
676 | rsi_dbg(ERR_ZONE, "%s: Failed to init slave regs\n", __func__); | ||
677 | goto fail; | ||
678 | } | ||
679 | sdio_release_host(pfunction); | ||
680 | |||
681 | adapter->host_intf_write_pkt = rsi_sdio_host_intf_write_pkt; | ||
682 | adapter->host_intf_read_pkt = rsi_sdio_host_intf_read_pkt; | ||
683 | adapter->determine_event_timeout = rsi_sdio_determine_event_timeout; | ||
684 | adapter->check_hw_queue_status = rsi_sdio_read_buffer_status_register; | ||
685 | |||
686 | #ifdef CONFIG_RSI_DEBUGFS | ||
687 | adapter->num_debugfs_entries = MAX_DEBUGFS_ENTRIES; | ||
688 | #endif | ||
689 | return status; | ||
690 | fail: | ||
691 | sdio_disable_func(pfunction); | ||
692 | sdio_release_host(pfunction); | ||
693 | return status; | ||
694 | } | ||
695 | |||
696 | /** | ||
697 | * rsi_probe() - This function is called by kernel when the driver provided | ||
698 | * Vendor and device IDs are matched. All the initialization | ||
699 | * work is done here. | ||
700 | * @pfunction: Pointer to the sdio_func structure. | ||
701 | * @id: Pointer to sdio_device_id structure. | ||
702 | * | ||
703 | * Return: 0 on success, 1 on failure. | ||
704 | */ | ||
705 | static int rsi_probe(struct sdio_func *pfunction, | ||
706 | const struct sdio_device_id *id) | ||
707 | { | ||
708 | struct rsi_hw *adapter; | ||
709 | |||
710 | rsi_dbg(INIT_ZONE, "%s: Init function called\n", __func__); | ||
711 | |||
712 | adapter = rsi_91x_init(); | ||
713 | if (!adapter) { | ||
714 | rsi_dbg(ERR_ZONE, "%s: Failed to init os intf ops\n", | ||
715 | __func__); | ||
716 | return 1; | ||
717 | } | ||
718 | |||
719 | if (rsi_init_sdio_interface(adapter, pfunction)) { | ||
720 | rsi_dbg(ERR_ZONE, "%s: Failed to init sdio interface\n", | ||
721 | __func__); | ||
722 | goto fail; | ||
723 | } | ||
724 | |||
725 | if (rsi_sdio_device_init(adapter->priv)) { | ||
726 | rsi_dbg(ERR_ZONE, "%s: Failed in device init\n", __func__); | ||
727 | sdio_claim_host(pfunction); | ||
728 | sdio_disable_func(pfunction); | ||
729 | sdio_release_host(pfunction); | ||
730 | goto fail; | ||
731 | } | ||
732 | |||
733 | sdio_claim_host(pfunction); | ||
734 | if (sdio_claim_irq(pfunction, rsi_handle_interrupt)) { | ||
735 | rsi_dbg(ERR_ZONE, "%s: Failed to request IRQ\n", __func__); | ||
736 | sdio_release_host(pfunction); | ||
737 | goto fail; | ||
738 | } | ||
739 | |||
740 | sdio_release_host(pfunction); | ||
741 | rsi_dbg(INIT_ZONE, "%s: Registered Interrupt handler\n", __func__); | ||
742 | |||
743 | return 0; | ||
744 | fail: | ||
745 | rsi_91x_deinit(adapter); | ||
746 | rsi_dbg(ERR_ZONE, "%s: Failed in probe...Exiting\n", __func__); | ||
747 | return 1; | ||
748 | } | ||
749 | |||
750 | /** | ||
751 | * rsi_disconnect() - This function performs the reverse of the probe function. | ||
752 | * @pfunction: Pointer to the sdio_func structure. | ||
753 | * | ||
754 | * Return: void. | ||
755 | */ | ||
756 | static void rsi_disconnect(struct sdio_func *pfunction) | ||
757 | { | ||
758 | struct rsi_hw *adapter = sdio_get_drvdata(pfunction); | ||
759 | struct rsi_91x_sdiodev *dev = | ||
760 | (struct rsi_91x_sdiodev *)adapter->rsi_dev; | ||
761 | |||
762 | if (!adapter) | ||
763 | return; | ||
764 | |||
765 | dev->write_fail = 2; | ||
766 | rsi_mac80211_detach(adapter); | ||
767 | |||
768 | sdio_claim_host(pfunction); | ||
769 | sdio_release_irq(pfunction); | ||
770 | sdio_disable_func(pfunction); | ||
771 | rsi_91x_deinit(adapter); | ||
772 | /* Resetting to take care of the case, where-in driver is re-loaded */ | ||
773 | rsi_reset_card(pfunction); | ||
774 | sdio_release_host(pfunction); | ||
775 | } | ||
776 | |||
777 | #ifdef CONFIG_PM | ||
778 | static int rsi_suspend(struct device *dev) | ||
779 | { | ||
780 | /* Not yet implemented */ | ||
781 | return -ENOSYS; | ||
782 | } | ||
783 | |||
784 | static int rsi_resume(struct device *dev) | ||
785 | { | ||
786 | /* Not yet implemented */ | ||
787 | return -ENOSYS; | ||
788 | } | ||
789 | |||
790 | static const struct dev_pm_ops rsi_pm_ops = { | ||
791 | .suspend = rsi_suspend, | ||
792 | .resume = rsi_resume, | ||
793 | }; | ||
794 | #endif | ||
795 | |||
796 | static const struct sdio_device_id rsi_dev_table[] = { | ||
797 | { SDIO_DEVICE(0x303, 0x100) }, | ||
798 | { SDIO_DEVICE(0x041B, 0x0301) }, | ||
799 | { SDIO_DEVICE(0x041B, 0x0201) }, | ||
800 | { SDIO_DEVICE(0x041B, 0x9330) }, | ||
801 | { /* Blank */}, | ||
802 | }; | ||
803 | |||
804 | static struct sdio_driver rsi_driver = { | ||
805 | .name = "RSI-SDIO WLAN", | ||
806 | .probe = rsi_probe, | ||
807 | .remove = rsi_disconnect, | ||
808 | .id_table = rsi_dev_table, | ||
809 | #ifdef CONFIG_PM | ||
810 | .drv = { | ||
811 | .pm = &rsi_pm_ops, | ||
812 | } | ||
813 | #endif | ||
814 | }; | ||
815 | |||
816 | /** | ||
817 | * rsi_module_init() - This function registers the sdio module. | ||
818 | * @void: Void. | ||
819 | * | ||
820 | * Return: 0 on success. | ||
821 | */ | ||
822 | static int rsi_module_init(void) | ||
823 | { | ||
824 | sdio_register_driver(&rsi_driver); | ||
825 | rsi_dbg(INIT_ZONE, "%s: Registering driver\n", __func__); | ||
826 | return 0; | ||
827 | } | ||
828 | |||
829 | /** | ||
830 | * rsi_module_exit() - This function unregisters the sdio module. | ||
831 | * @void: Void. | ||
832 | * | ||
833 | * Return: None. | ||
834 | */ | ||
835 | static void rsi_module_exit(void) | ||
836 | { | ||
837 | sdio_unregister_driver(&rsi_driver); | ||
838 | rsi_dbg(INFO_ZONE, "%s: Unregistering driver\n", __func__); | ||
839 | } | ||
840 | |||
841 | module_init(rsi_module_init); | ||
842 | module_exit(rsi_module_exit); | ||
843 | |||
844 | MODULE_AUTHOR("Redpine Signals Inc"); | ||
845 | MODULE_DESCRIPTION("Common SDIO layer for RSI drivers"); | ||
846 | MODULE_SUPPORTED_DEVICE("RSI-91x"); | ||
847 | MODULE_DEVICE_TABLE(sdio, rsi_dev_table); | ||
848 | MODULE_FIRMWARE(FIRMWARE_RSI9113); | ||
849 | MODULE_VERSION("0.1"); | ||
850 | MODULE_LICENSE("Dual BSD/GPL"); | ||
diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c new file mode 100644 index 000000000000..f1cb99cafed8 --- /dev/null +++ b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c | |||
@@ -0,0 +1,566 @@ | |||
1 | /** | ||
2 | * Copyright (c) 2014 Redpine Signals Inc. | ||
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 | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #include <linux/firmware.h> | ||
19 | #include "rsi_sdio.h" | ||
20 | #include "rsi_common.h" | ||
21 | |||
22 | /** | ||
23 | * rsi_sdio_master_access_msword() - This function sets the AHB master access | ||
24 | * MS word in the SDIO slave registers. | ||
25 | * @adapter: Pointer to the adapter structure. | ||
26 | * @ms_word: ms word need to be initialized. | ||
27 | * | ||
28 | * Return: status: 0 on success, -1 on failure. | ||
29 | */ | ||
30 | static int rsi_sdio_master_access_msword(struct rsi_hw *adapter, | ||
31 | u16 ms_word) | ||
32 | { | ||
33 | u8 byte; | ||
34 | u8 function = 0; | ||
35 | int status = 0; | ||
36 | |||
37 | byte = (u8)(ms_word & 0x00FF); | ||
38 | |||
39 | rsi_dbg(INIT_ZONE, | ||
40 | "%s: MASTER_ACCESS_MSBYTE:0x%x\n", __func__, byte); | ||
41 | |||
42 | status = rsi_sdio_write_register(adapter, | ||
43 | function, | ||
44 | SDIO_MASTER_ACCESS_MSBYTE, | ||
45 | &byte); | ||
46 | if (status) { | ||
47 | rsi_dbg(ERR_ZONE, | ||
48 | "%s: fail to access MASTER_ACCESS_MSBYTE\n", | ||
49 | __func__); | ||
50 | return -1; | ||
51 | } | ||
52 | |||
53 | byte = (u8)(ms_word >> 8); | ||
54 | |||
55 | rsi_dbg(INIT_ZONE, "%s:MASTER_ACCESS_LSBYTE:0x%x\n", __func__, byte); | ||
56 | status = rsi_sdio_write_register(adapter, | ||
57 | function, | ||
58 | SDIO_MASTER_ACCESS_LSBYTE, | ||
59 | &byte); | ||
60 | return status; | ||
61 | } | ||
62 | |||
63 | /** | ||
64 | * rsi_copy_to_card() - This function includes the actual funtionality of | ||
65 | * copying the TA firmware to the card.Basically this | ||
66 | * function includes opening the TA file,reading the | ||
67 | * TA file and writing their values in blocks of data. | ||
68 | * @common: Pointer to the driver private structure. | ||
69 | * @fw: Pointer to the firmware value to be written. | ||
70 | * @len: length of firmware file. | ||
71 | * @num_blocks: Number of blocks to be written to the card. | ||
72 | * | ||
73 | * Return: 0 on success and -1 on failure. | ||
74 | */ | ||
75 | static int rsi_copy_to_card(struct rsi_common *common, | ||
76 | const u8 *fw, | ||
77 | u32 len, | ||
78 | u32 num_blocks) | ||
79 | { | ||
80 | struct rsi_hw *adapter = common->priv; | ||
81 | struct rsi_91x_sdiodev *dev = | ||
82 | (struct rsi_91x_sdiodev *)adapter->rsi_dev; | ||
83 | u32 indx, ii; | ||
84 | u32 block_size = dev->tx_blk_size; | ||
85 | u32 lsb_address; | ||
86 | __le32 data[] = { TA_HOLD_THREAD_VALUE, TA_SOFT_RST_CLR, | ||
87 | TA_PC_ZERO, TA_RELEASE_THREAD_VALUE }; | ||
88 | u32 address[] = { TA_HOLD_THREAD_REG, TA_SOFT_RESET_REG, | ||
89 | TA_TH0_PC_REG, TA_RELEASE_THREAD_REG }; | ||
90 | u32 base_address; | ||
91 | u16 msb_address; | ||
92 | |||
93 | base_address = TA_LOAD_ADDRESS; | ||
94 | msb_address = base_address >> 16; | ||
95 | |||
96 | for (indx = 0, ii = 0; ii < num_blocks; ii++, indx += block_size) { | ||
97 | lsb_address = ((u16) base_address | RSI_SD_REQUEST_MASTER); | ||
98 | if (rsi_sdio_write_register_multiple(adapter, | ||
99 | lsb_address, | ||
100 | (u8 *)(fw + indx), | ||
101 | block_size)) { | ||
102 | rsi_dbg(ERR_ZONE, | ||
103 | "%s: Unable to load %s blk\n", __func__, | ||
104 | FIRMWARE_RSI9113); | ||
105 | return -1; | ||
106 | } | ||
107 | rsi_dbg(INIT_ZONE, "%s: loading block: %d\n", __func__, ii); | ||
108 | base_address += block_size; | ||
109 | if ((base_address >> 16) != msb_address) { | ||
110 | msb_address += 1; | ||
111 | if (rsi_sdio_master_access_msword(adapter, | ||
112 | msb_address)) { | ||
113 | rsi_dbg(ERR_ZONE, | ||
114 | "%s: Unable to set ms word reg\n", | ||
115 | __func__); | ||
116 | return -1; | ||
117 | } | ||
118 | } | ||
119 | } | ||
120 | |||
121 | if (len % block_size) { | ||
122 | lsb_address = ((u16) base_address | RSI_SD_REQUEST_MASTER); | ||
123 | if (rsi_sdio_write_register_multiple(adapter, | ||
124 | lsb_address, | ||
125 | (u8 *)(fw + indx), | ||
126 | len % block_size)) { | ||
127 | rsi_dbg(ERR_ZONE, | ||
128 | "%s: Unable to load f/w\n", __func__); | ||
129 | return -1; | ||
130 | } | ||
131 | } | ||
132 | rsi_dbg(INIT_ZONE, | ||
133 | "%s: Succesfully loaded TA instructions\n", __func__); | ||
134 | |||
135 | if (rsi_sdio_master_access_msword(adapter, TA_BASE_ADDR)) { | ||
136 | rsi_dbg(ERR_ZONE, | ||
137 | "%s: Unable to set ms word to common reg\n", | ||
138 | __func__); | ||
139 | return -1; | ||
140 | } | ||
141 | |||
142 | for (ii = 0; ii < ARRAY_SIZE(data); ii++) { | ||
143 | /* Bringing TA out of reset */ | ||
144 | if (rsi_sdio_write_register_multiple(adapter, | ||
145 | (address[ii] | | ||
146 | RSI_SD_REQUEST_MASTER), | ||
147 | (u8 *)&data[ii], | ||
148 | 4)) { | ||
149 | rsi_dbg(ERR_ZONE, | ||
150 | "%s: Unable to hold TA threads\n", __func__); | ||
151 | return -1; | ||
152 | } | ||
153 | } | ||
154 | |||
155 | rsi_dbg(INIT_ZONE, "%s: loaded firmware\n", __func__); | ||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | /** | ||
160 | * rsi_load_ta_instructions() - This function includes the actual funtionality | ||
161 | * of loading the TA firmware.This function also | ||
162 | * includes opening the TA file,reading the TA | ||
163 | * file and writing their value in blocks of data. | ||
164 | * @common: Pointer to the driver private structure. | ||
165 | * | ||
166 | * Return: status: 0 on success, -1 on failure. | ||
167 | */ | ||
168 | static int rsi_load_ta_instructions(struct rsi_common *common) | ||
169 | { | ||
170 | struct rsi_hw *adapter = common->priv; | ||
171 | struct rsi_91x_sdiodev *dev = | ||
172 | (struct rsi_91x_sdiodev *)adapter->rsi_dev; | ||
173 | u32 len; | ||
174 | u32 num_blocks; | ||
175 | const u8 *fw; | ||
176 | const struct firmware *fw_entry = NULL; | ||
177 | u32 block_size = dev->tx_blk_size; | ||
178 | int status = 0; | ||
179 | u32 base_address; | ||
180 | u16 msb_address; | ||
181 | |||
182 | if (rsi_sdio_master_access_msword(adapter, TA_BASE_ADDR)) { | ||
183 | rsi_dbg(ERR_ZONE, | ||
184 | "%s: Unable to set ms word to common reg\n", | ||
185 | __func__); | ||
186 | return -1; | ||
187 | } | ||
188 | base_address = TA_LOAD_ADDRESS; | ||
189 | msb_address = (base_address >> 16); | ||
190 | |||
191 | if (rsi_sdio_master_access_msword(adapter, msb_address)) { | ||
192 | rsi_dbg(ERR_ZONE, | ||
193 | "%s: Unable to set ms word reg\n", __func__); | ||
194 | return -1; | ||
195 | } | ||
196 | |||
197 | status = request_firmware(&fw_entry, FIRMWARE_RSI9113, adapter->device); | ||
198 | if (status < 0) { | ||
199 | rsi_dbg(ERR_ZONE, "%s Firmware file %s not found\n", | ||
200 | __func__, FIRMWARE_RSI9113); | ||
201 | return status; | ||
202 | } | ||
203 | |||
204 | fw = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL); | ||
205 | len = fw_entry->size; | ||
206 | |||
207 | if (len % 4) | ||
208 | len += (4 - (len % 4)); | ||
209 | |||
210 | num_blocks = (len / block_size); | ||
211 | |||
212 | rsi_dbg(INIT_ZONE, "%s: Instruction size:%d\n", __func__, len); | ||
213 | rsi_dbg(INIT_ZONE, "%s: num blocks: %d\n", __func__, num_blocks); | ||
214 | |||
215 | status = rsi_copy_to_card(common, fw, len, num_blocks); | ||
216 | release_firmware(fw_entry); | ||
217 | return status; | ||
218 | } | ||
219 | |||
220 | /** | ||
221 | * rsi_process_pkt() - This Function reads rx_blocks register and figures out | ||
222 | * the size of the rx pkt. | ||
223 | * @common: Pointer to the driver private structure. | ||
224 | * | ||
225 | * Return: 0 on success, -1 on failure. | ||
226 | */ | ||
227 | static int rsi_process_pkt(struct rsi_common *common) | ||
228 | { | ||
229 | struct rsi_hw *adapter = common->priv; | ||
230 | u8 num_blks = 0; | ||
231 | u32 rcv_pkt_len = 0; | ||
232 | int status = 0; | ||
233 | |||
234 | status = rsi_sdio_read_register(adapter, | ||
235 | SDIO_RX_NUM_BLOCKS_REG, | ||
236 | &num_blks); | ||
237 | |||
238 | if (status) { | ||
239 | rsi_dbg(ERR_ZONE, | ||
240 | "%s: Failed to read pkt length from the card:\n", | ||
241 | __func__); | ||
242 | return status; | ||
243 | } | ||
244 | rcv_pkt_len = (num_blks * 256); | ||
245 | |||
246 | common->rx_data_pkt = kmalloc(rcv_pkt_len, GFP_KERNEL); | ||
247 | if (!common->rx_data_pkt) { | ||
248 | rsi_dbg(ERR_ZONE, "%s: Failed in memory allocation\n", | ||
249 | __func__); | ||
250 | return -1; | ||
251 | } | ||
252 | |||
253 | status = rsi_sdio_host_intf_read_pkt(adapter, | ||
254 | common->rx_data_pkt, | ||
255 | rcv_pkt_len); | ||
256 | if (status) { | ||
257 | rsi_dbg(ERR_ZONE, "%s: Failed to read packet from card\n", | ||
258 | __func__); | ||
259 | goto fail; | ||
260 | } | ||
261 | |||
262 | status = rsi_read_pkt(common, rcv_pkt_len); | ||
263 | kfree(common->rx_data_pkt); | ||
264 | return status; | ||
265 | |||
266 | fail: | ||
267 | kfree(common->rx_data_pkt); | ||
268 | return -1; | ||
269 | } | ||
270 | |||
271 | /** | ||
272 | * rsi_init_sdio_slave_regs() - This function does the actual initialization | ||
273 | * of SDBUS slave registers. | ||
274 | * @adapter: Pointer to the adapter structure. | ||
275 | * | ||
276 | * Return: status: 0 on success, -1 on failure. | ||
277 | */ | ||
278 | int rsi_init_sdio_slave_regs(struct rsi_hw *adapter) | ||
279 | { | ||
280 | struct rsi_91x_sdiodev *dev = | ||
281 | (struct rsi_91x_sdiodev *)adapter->rsi_dev; | ||
282 | u8 function = 0; | ||
283 | u8 byte; | ||
284 | int status = 0; | ||
285 | |||
286 | if (dev->next_read_delay) { | ||
287 | byte = dev->next_read_delay; | ||
288 | status = rsi_sdio_write_register(adapter, | ||
289 | function, | ||
290 | SDIO_NXT_RD_DELAY2, | ||
291 | &byte); | ||
292 | if (status) { | ||
293 | rsi_dbg(ERR_ZONE, | ||
294 | "%s: Failed to write SDIO_NXT_RD_DELAY2\n", | ||
295 | __func__); | ||
296 | return -1; | ||
297 | } | ||
298 | } | ||
299 | |||
300 | if (dev->sdio_high_speed_enable) { | ||
301 | rsi_dbg(INIT_ZONE, "%s: Enabling SDIO High speed\n", __func__); | ||
302 | byte = 0x3; | ||
303 | |||
304 | status = rsi_sdio_write_register(adapter, | ||
305 | function, | ||
306 | SDIO_REG_HIGH_SPEED, | ||
307 | &byte); | ||
308 | if (status) { | ||
309 | rsi_dbg(ERR_ZONE, | ||
310 | "%s: Failed to enable SDIO high speed\n", | ||
311 | __func__); | ||
312 | return -1; | ||
313 | } | ||
314 | } | ||
315 | |||
316 | /* This tells SDIO FIFO when to start read to host */ | ||
317 | rsi_dbg(INIT_ZONE, "%s: Initialzing SDIO read start level\n", __func__); | ||
318 | byte = 0x24; | ||
319 | |||
320 | status = rsi_sdio_write_register(adapter, | ||
321 | function, | ||
322 | SDIO_READ_START_LVL, | ||
323 | &byte); | ||
324 | if (status) { | ||
325 | rsi_dbg(ERR_ZONE, | ||
326 | "%s: Failed to write SDIO_READ_START_LVL\n", __func__); | ||
327 | return -1; | ||
328 | } | ||
329 | |||
330 | rsi_dbg(INIT_ZONE, "%s: Initialzing FIFO ctrl registers\n", __func__); | ||
331 | byte = (128 - 32); | ||
332 | |||
333 | status = rsi_sdio_write_register(adapter, | ||
334 | function, | ||
335 | SDIO_READ_FIFO_CTL, | ||
336 | &byte); | ||
337 | if (status) { | ||
338 | rsi_dbg(ERR_ZONE, | ||
339 | "%s: Failed to write SDIO_READ_FIFO_CTL\n", __func__); | ||
340 | return -1; | ||
341 | } | ||
342 | |||
343 | byte = 32; | ||
344 | status = rsi_sdio_write_register(adapter, | ||
345 | function, | ||
346 | SDIO_WRITE_FIFO_CTL, | ||
347 | &byte); | ||
348 | if (status) { | ||
349 | rsi_dbg(ERR_ZONE, | ||
350 | "%s: Failed to write SDIO_WRITE_FIFO_CTL\n", __func__); | ||
351 | return -1; | ||
352 | } | ||
353 | |||
354 | return 0; | ||
355 | } | ||
356 | |||
357 | /** | ||
358 | * rsi_interrupt_handler() - This function read and process SDIO interrupts. | ||
359 | * @adapter: Pointer to the adapter structure. | ||
360 | * | ||
361 | * Return: None. | ||
362 | */ | ||
363 | void rsi_interrupt_handler(struct rsi_hw *adapter) | ||
364 | { | ||
365 | struct rsi_common *common = adapter->priv; | ||
366 | struct rsi_91x_sdiodev *dev = | ||
367 | (struct rsi_91x_sdiodev *)adapter->rsi_dev; | ||
368 | int status; | ||
369 | enum sdio_interrupt_type isr_type; | ||
370 | u8 isr_status = 0; | ||
371 | u8 fw_status = 0; | ||
372 | |||
373 | dev->rx_info.sdio_int_counter++; | ||
374 | |||
375 | do { | ||
376 | mutex_lock(&common->tx_rxlock); | ||
377 | status = rsi_sdio_read_register(common->priv, | ||
378 | RSI_FN1_INT_REGISTER, | ||
379 | &isr_status); | ||
380 | if (status) { | ||
381 | rsi_dbg(ERR_ZONE, | ||
382 | "%s: Failed to Read Intr Status Register\n", | ||
383 | __func__); | ||
384 | mutex_unlock(&common->tx_rxlock); | ||
385 | return; | ||
386 | } | ||
387 | |||
388 | if (isr_status == 0) { | ||
389 | rsi_set_event(&common->tx_thread.event); | ||
390 | dev->rx_info.sdio_intr_status_zero++; | ||
391 | mutex_unlock(&common->tx_rxlock); | ||
392 | return; | ||
393 | } | ||
394 | |||
395 | rsi_dbg(ISR_ZONE, "%s: Intr_status = %x %d %d\n", | ||
396 | __func__, isr_status, (1 << MSDU_PKT_PENDING), | ||
397 | (1 << FW_ASSERT_IND)); | ||
398 | |||
399 | do { | ||
400 | RSI_GET_SDIO_INTERRUPT_TYPE(isr_status, isr_type); | ||
401 | |||
402 | switch (isr_type) { | ||
403 | case BUFFER_AVAILABLE: | ||
404 | dev->rx_info.watch_bufferfull_count = 0; | ||
405 | dev->rx_info.buffer_full = false; | ||
406 | dev->rx_info.mgmt_buffer_full = false; | ||
407 | rsi_sdio_ack_intr(common->priv, | ||
408 | (1 << PKT_BUFF_AVAILABLE)); | ||
409 | rsi_set_event((&common->tx_thread.event)); | ||
410 | rsi_dbg(ISR_ZONE, | ||
411 | "%s: ==> BUFFER_AVILABLE <==\n", | ||
412 | __func__); | ||
413 | dev->rx_info.buf_avilable_counter++; | ||
414 | break; | ||
415 | |||
416 | case FIRMWARE_ASSERT_IND: | ||
417 | rsi_dbg(ERR_ZONE, | ||
418 | "%s: ==> FIRMWARE Assert <==\n", | ||
419 | __func__); | ||
420 | status = rsi_sdio_read_register(common->priv, | ||
421 | SDIO_FW_STATUS_REG, | ||
422 | &fw_status); | ||
423 | if (status) { | ||
424 | rsi_dbg(ERR_ZONE, | ||
425 | "%s: Failed to read f/w reg\n", | ||
426 | __func__); | ||
427 | } else { | ||
428 | rsi_dbg(ERR_ZONE, | ||
429 | "%s: Firmware Status is 0x%x\n", | ||
430 | __func__ , fw_status); | ||
431 | rsi_sdio_ack_intr(common->priv, | ||
432 | (1 << FW_ASSERT_IND)); | ||
433 | } | ||
434 | |||
435 | common->fsm_state = FSM_CARD_NOT_READY; | ||
436 | break; | ||
437 | |||
438 | case MSDU_PACKET_PENDING: | ||
439 | rsi_dbg(ISR_ZONE, "Pkt pending interrupt\n"); | ||
440 | dev->rx_info.total_sdio_msdu_pending_intr++; | ||
441 | |||
442 | status = rsi_process_pkt(common); | ||
443 | if (status) { | ||
444 | rsi_dbg(ERR_ZONE, | ||
445 | "%s: Failed to read pkt\n", | ||
446 | __func__); | ||
447 | mutex_unlock(&common->tx_rxlock); | ||
448 | return; | ||
449 | } | ||
450 | break; | ||
451 | default: | ||
452 | rsi_sdio_ack_intr(common->priv, isr_status); | ||
453 | dev->rx_info.total_sdio_unknown_intr++; | ||
454 | isr_status = 0; | ||
455 | rsi_dbg(ISR_ZONE, | ||
456 | "Unknown Interrupt %x\n", | ||
457 | isr_status); | ||
458 | break; | ||
459 | } | ||
460 | isr_status ^= BIT(isr_type - 1); | ||
461 | } while (isr_status); | ||
462 | mutex_unlock(&common->tx_rxlock); | ||
463 | } while (1); | ||
464 | } | ||
465 | |||
466 | /** | ||
467 | * rsi_device_init() - This Function Initializes The HAL. | ||
468 | * @common: Pointer to the driver private structure. | ||
469 | * | ||
470 | * Return: 0 on success, -1 on failure. | ||
471 | */ | ||
472 | int rsi_sdio_device_init(struct rsi_common *common) | ||
473 | { | ||
474 | if (rsi_load_ta_instructions(common)) | ||
475 | return -1; | ||
476 | |||
477 | if (rsi_sdio_master_access_msword(common->priv, MISC_CFG_BASE_ADDR)) { | ||
478 | rsi_dbg(ERR_ZONE, "%s: Unable to set ms word reg\n", | ||
479 | __func__); | ||
480 | return -1; | ||
481 | } | ||
482 | rsi_dbg(INIT_ZONE, | ||
483 | "%s: Setting ms word to 0x41050000\n", __func__); | ||
484 | |||
485 | return 0; | ||
486 | } | ||
487 | |||
488 | /** | ||
489 | * rsi_sdio_read_buffer_status_register() - This function is used to the read | ||
490 | * buffer status register and set | ||
491 | * relevant fields in | ||
492 | * rsi_91x_sdiodev struct. | ||
493 | * @adapter: Pointer to the driver hw structure. | ||
494 | * @q_num: The Q number whose status is to be found. | ||
495 | * | ||
496 | * Return: status: -1 on failure or else queue full/stop is indicated. | ||
497 | */ | ||
498 | int rsi_sdio_read_buffer_status_register(struct rsi_hw *adapter, u8 q_num) | ||
499 | { | ||
500 | struct rsi_common *common = adapter->priv; | ||
501 | struct rsi_91x_sdiodev *dev = | ||
502 | (struct rsi_91x_sdiodev *)adapter->rsi_dev; | ||
503 | u8 buf_status = 0; | ||
504 | int status = 0; | ||
505 | |||
506 | status = rsi_sdio_read_register(common->priv, | ||
507 | RSI_DEVICE_BUFFER_STATUS_REGISTER, | ||
508 | &buf_status); | ||
509 | |||
510 | if (status) { | ||
511 | rsi_dbg(ERR_ZONE, | ||
512 | "%s: Failed to read status register\n", __func__); | ||
513 | return -1; | ||
514 | } | ||
515 | |||
516 | if (buf_status & (BIT(PKT_MGMT_BUFF_FULL))) { | ||
517 | if (!dev->rx_info.mgmt_buffer_full) | ||
518 | dev->rx_info.mgmt_buf_full_counter++; | ||
519 | dev->rx_info.mgmt_buffer_full = true; | ||
520 | } else { | ||
521 | dev->rx_info.mgmt_buffer_full = false; | ||
522 | } | ||
523 | |||
524 | if (buf_status & (BIT(PKT_BUFF_FULL))) { | ||
525 | if (!dev->rx_info.buffer_full) | ||
526 | dev->rx_info.buf_full_counter++; | ||
527 | dev->rx_info.buffer_full = true; | ||
528 | } else { | ||
529 | dev->rx_info.buffer_full = false; | ||
530 | } | ||
531 | |||
532 | if (buf_status & (BIT(PKT_BUFF_SEMI_FULL))) { | ||
533 | if (!dev->rx_info.semi_buffer_full) | ||
534 | dev->rx_info.buf_semi_full_counter++; | ||
535 | dev->rx_info.semi_buffer_full = true; | ||
536 | } else { | ||
537 | dev->rx_info.semi_buffer_full = false; | ||
538 | } | ||
539 | |||
540 | if ((q_num == MGMT_SOFT_Q) && (dev->rx_info.mgmt_buffer_full)) | ||
541 | return QUEUE_FULL; | ||
542 | |||
543 | if (dev->rx_info.buffer_full) | ||
544 | return QUEUE_FULL; | ||
545 | |||
546 | return QUEUE_NOT_FULL; | ||
547 | } | ||
548 | |||
549 | /** | ||
550 | * rsi_sdio_determine_event_timeout() - This Function determines the event | ||
551 | * timeout duration. | ||
552 | * @adapter: Pointer to the adapter structure. | ||
553 | * | ||
554 | * Return: timeout duration is returned. | ||
555 | */ | ||
556 | int rsi_sdio_determine_event_timeout(struct rsi_hw *adapter) | ||
557 | { | ||
558 | struct rsi_91x_sdiodev *dev = | ||
559 | (struct rsi_91x_sdiodev *)adapter->rsi_dev; | ||
560 | |||
561 | /* Once buffer full is seen, event timeout to occur every 2 msecs */ | ||
562 | if (dev->rx_info.buffer_full) | ||
563 | return 2; | ||
564 | |||
565 | return EVENT_WAIT_FOREVER; | ||
566 | } | ||
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c new file mode 100644 index 000000000000..bb1bf96670eb --- /dev/null +++ b/drivers/net/wireless/rsi/rsi_91x_usb.c | |||
@@ -0,0 +1,575 @@ | |||
1 | /** | ||
2 | * Copyright (c) 2014 Redpine Signals Inc. | ||
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 | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include "rsi_usb.h" | ||
20 | |||
21 | /** | ||
22 | * rsi_usb_card_write() - This function writes to the USB Card. | ||
23 | * @adapter: Pointer to the adapter structure. | ||
24 | * @buf: Pointer to the buffer from where the data has to be taken. | ||
25 | * @len: Length to be written. | ||
26 | * @endpoint: Type of endpoint. | ||
27 | * | ||
28 | * Return: status: 0 on success, -1 on failure. | ||
29 | */ | ||
30 | static int rsi_usb_card_write(struct rsi_hw *adapter, | ||
31 | void *buf, | ||
32 | u16 len, | ||
33 | u8 endpoint) | ||
34 | { | ||
35 | struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev; | ||
36 | int status; | ||
37 | s32 transfer; | ||
38 | |||
39 | status = usb_bulk_msg(dev->usbdev, | ||
40 | usb_sndbulkpipe(dev->usbdev, | ||
41 | dev->bulkout_endpoint_addr[endpoint - 1]), | ||
42 | buf, | ||
43 | len, | ||
44 | &transfer, | ||
45 | HZ * 5); | ||
46 | |||
47 | if (status < 0) { | ||
48 | rsi_dbg(ERR_ZONE, | ||
49 | "Card write failed with error code :%10d\n", status); | ||
50 | dev->write_fail = 1; | ||
51 | } | ||
52 | return status; | ||
53 | } | ||
54 | |||
55 | /** | ||
56 | * rsi_write_multiple() - This function writes multiple bytes of information | ||
57 | * to the USB card. | ||
58 | * @adapter: Pointer to the adapter structure. | ||
59 | * @addr: Address of the register. | ||
60 | * @data: Pointer to the data that has to be written. | ||
61 | * @count: Number of multiple bytes to be written. | ||
62 | * | ||
63 | * Return: 0 on success, -1 on failure. | ||
64 | */ | ||
65 | static int rsi_write_multiple(struct rsi_hw *adapter, | ||
66 | u8 endpoint, | ||
67 | u8 *data, | ||
68 | u32 count) | ||
69 | { | ||
70 | struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev; | ||
71 | u8 *seg = dev->tx_buffer; | ||
72 | |||
73 | if (dev->write_fail) | ||
74 | return 0; | ||
75 | |||
76 | if (endpoint == MGMT_EP) { | ||
77 | memset(seg, 0, RSI_USB_TX_HEAD_ROOM); | ||
78 | memcpy(seg + RSI_USB_TX_HEAD_ROOM, data, count); | ||
79 | } else { | ||
80 | seg = ((u8 *)data - RSI_USB_TX_HEAD_ROOM); | ||
81 | } | ||
82 | |||
83 | return rsi_usb_card_write(adapter, | ||
84 | seg, | ||
85 | count + RSI_USB_TX_HEAD_ROOM, | ||
86 | endpoint); | ||
87 | } | ||
88 | |||
89 | /** | ||
90 | * rsi_find_bulk_in_and_out_endpoints() - This function initializes the bulk | ||
91 | * endpoints to the device. | ||
92 | * @interface: Pointer to the USB interface structure. | ||
93 | * @adapter: Pointer to the adapter structure. | ||
94 | * | ||
95 | * Return: ret_val: 0 on success, -ENOMEM on failure. | ||
96 | */ | ||
97 | static int rsi_find_bulk_in_and_out_endpoints(struct usb_interface *interface, | ||
98 | struct rsi_hw *adapter) | ||
99 | { | ||
100 | struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev; | ||
101 | struct usb_host_interface *iface_desc; | ||
102 | struct usb_endpoint_descriptor *endpoint; | ||
103 | __le16 buffer_size; | ||
104 | int ii, bep_found = 0; | ||
105 | |||
106 | iface_desc = &(interface->altsetting[0]); | ||
107 | |||
108 | for (ii = 0; ii < iface_desc->desc.bNumEndpoints; ++ii) { | ||
109 | endpoint = &(iface_desc->endpoint[ii].desc); | ||
110 | |||
111 | if ((!(dev->bulkin_endpoint_addr)) && | ||
112 | (endpoint->bEndpointAddress & USB_DIR_IN) && | ||
113 | ((endpoint->bmAttributes & | ||
114 | USB_ENDPOINT_XFERTYPE_MASK) == | ||
115 | USB_ENDPOINT_XFER_BULK)) { | ||
116 | buffer_size = endpoint->wMaxPacketSize; | ||
117 | dev->bulkin_size = buffer_size; | ||
118 | dev->bulkin_endpoint_addr = | ||
119 | endpoint->bEndpointAddress; | ||
120 | } | ||
121 | |||
122 | if (!dev->bulkout_endpoint_addr[bep_found] && | ||
123 | !(endpoint->bEndpointAddress & USB_DIR_IN) && | ||
124 | ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == | ||
125 | USB_ENDPOINT_XFER_BULK)) { | ||
126 | dev->bulkout_endpoint_addr[bep_found] = | ||
127 | endpoint->bEndpointAddress; | ||
128 | buffer_size = endpoint->wMaxPacketSize; | ||
129 | dev->bulkout_size[bep_found] = buffer_size; | ||
130 | bep_found++; | ||
131 | } | ||
132 | |||
133 | if (bep_found >= MAX_BULK_EP) | ||
134 | break; | ||
135 | } | ||
136 | |||
137 | if (!(dev->bulkin_endpoint_addr) && | ||
138 | (dev->bulkout_endpoint_addr[0])) | ||
139 | return -EINVAL; | ||
140 | |||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | /* rsi_usb_reg_read() - This function reads data from given register address. | ||
145 | * @usbdev: Pointer to the usb_device structure. | ||
146 | * @reg: Address of the register to be read. | ||
147 | * @value: Value to be read. | ||
148 | * @len: length of data to be read. | ||
149 | * | ||
150 | * Return: status: 0 on success, -1 on failure. | ||
151 | */ | ||
152 | static int rsi_usb_reg_read(struct usb_device *usbdev, | ||
153 | u32 reg, | ||
154 | u16 *value, | ||
155 | u16 len) | ||
156 | { | ||
157 | u8 temp_buf[4]; | ||
158 | int status = 0; | ||
159 | |||
160 | status = usb_control_msg(usbdev, | ||
161 | usb_rcvctrlpipe(usbdev, 0), | ||
162 | USB_VENDOR_REGISTER_READ, | ||
163 | USB_TYPE_VENDOR, | ||
164 | ((reg & 0xffff0000) >> 16), (reg & 0xffff), | ||
165 | (void *)temp_buf, | ||
166 | len, | ||
167 | HZ * 5); | ||
168 | |||
169 | *value = (temp_buf[0] | (temp_buf[1] << 8)); | ||
170 | if (status < 0) { | ||
171 | rsi_dbg(ERR_ZONE, | ||
172 | "%s: Reg read failed with error code :%d\n", | ||
173 | __func__, status); | ||
174 | } | ||
175 | return status; | ||
176 | } | ||
177 | |||
178 | /** | ||
179 | * rsi_usb_reg_write() - This function writes the given data into the given | ||
180 | * register address. | ||
181 | * @usbdev: Pointer to the usb_device structure. | ||
182 | * @reg: Address of the register. | ||
183 | * @value: Value to write. | ||
184 | * @len: Length of data to be written. | ||
185 | * | ||
186 | * Return: status: 0 on success, -1 on failure. | ||
187 | */ | ||
188 | static int rsi_usb_reg_write(struct usb_device *usbdev, | ||
189 | u32 reg, | ||
190 | u16 value, | ||
191 | u16 len) | ||
192 | { | ||
193 | u8 usb_reg_buf[4]; | ||
194 | int status = 0; | ||
195 | |||
196 | usb_reg_buf[0] = (value & 0x00ff); | ||
197 | usb_reg_buf[1] = (value & 0xff00) >> 8; | ||
198 | usb_reg_buf[2] = 0x0; | ||
199 | usb_reg_buf[3] = 0x0; | ||
200 | |||
201 | status = usb_control_msg(usbdev, | ||
202 | usb_sndctrlpipe(usbdev, 0), | ||
203 | USB_VENDOR_REGISTER_WRITE, | ||
204 | USB_TYPE_VENDOR, | ||
205 | ((reg & 0xffff0000) >> 16), | ||
206 | (reg & 0xffff), | ||
207 | (void *)usb_reg_buf, | ||
208 | len, | ||
209 | HZ * 5); | ||
210 | if (status < 0) { | ||
211 | rsi_dbg(ERR_ZONE, | ||
212 | "%s: Reg write failed with error code :%d\n", | ||
213 | __func__, status); | ||
214 | } | ||
215 | return status; | ||
216 | } | ||
217 | |||
218 | /** | ||
219 | * rsi_rx_done_handler() - This function is called when a packet is received | ||
220 | * from USB stack. This is callback to recieve done. | ||
221 | * @urb: Received URB. | ||
222 | * | ||
223 | * Return: None. | ||
224 | */ | ||
225 | static void rsi_rx_done_handler(struct urb *urb) | ||
226 | { | ||
227 | struct rsi_hw *adapter = urb->context; | ||
228 | struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev; | ||
229 | |||
230 | if (urb->status) | ||
231 | return; | ||
232 | |||
233 | rsi_set_event(&dev->rx_thread.event); | ||
234 | } | ||
235 | |||
236 | /** | ||
237 | * rsi_rx_urb_submit() - This function submits the given URB to the USB stack. | ||
238 | * @adapter: Pointer to the adapter structure. | ||
239 | * | ||
240 | * Return: 0 on success, -1 on failure. | ||
241 | */ | ||
242 | static int rsi_rx_urb_submit(struct rsi_hw *adapter) | ||
243 | { | ||
244 | struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev; | ||
245 | struct urb *urb = dev->rx_usb_urb[0]; | ||
246 | int status; | ||
247 | |||
248 | usb_fill_bulk_urb(urb, | ||
249 | dev->usbdev, | ||
250 | usb_rcvbulkpipe(dev->usbdev, | ||
251 | dev->bulkin_endpoint_addr), | ||
252 | urb->transfer_buffer, | ||
253 | 3000, | ||
254 | rsi_rx_done_handler, | ||
255 | adapter); | ||
256 | |||
257 | status = usb_submit_urb(urb, GFP_KERNEL); | ||
258 | if (status) | ||
259 | rsi_dbg(ERR_ZONE, "%s: Failed in urb submission\n", __func__); | ||
260 | |||
261 | return status; | ||
262 | } | ||
263 | |||
264 | /** | ||
265 | * rsi_usb_write_register_multiple() - This function writes multiple bytes of | ||
266 | * information to multiple registers. | ||
267 | * @adapter: Pointer to the adapter structure. | ||
268 | * @addr: Address of the register. | ||
269 | * @data: Pointer to the data that has to be written. | ||
270 | * @count: Number of multiple bytes to be written on to the registers. | ||
271 | * | ||
272 | * Return: status: 0 on success, -1 on failure. | ||
273 | */ | ||
274 | int rsi_usb_write_register_multiple(struct rsi_hw *adapter, | ||
275 | u32 addr, | ||
276 | u8 *data, | ||
277 | u32 count) | ||
278 | { | ||
279 | struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev; | ||
280 | u8 *buf; | ||
281 | u8 transfer; | ||
282 | int status = 0; | ||
283 | |||
284 | buf = kzalloc(4096, GFP_KERNEL); | ||
285 | if (!buf) | ||
286 | return -ENOMEM; | ||
287 | |||
288 | while (count) { | ||
289 | transfer = min_t(int, count, 4096); | ||
290 | memcpy(buf, data, transfer); | ||
291 | status = usb_control_msg(dev->usbdev, | ||
292 | usb_sndctrlpipe(dev->usbdev, 0), | ||
293 | USB_VENDOR_REGISTER_WRITE, | ||
294 | USB_TYPE_VENDOR, | ||
295 | ((addr & 0xffff0000) >> 16), | ||
296 | (addr & 0xffff), | ||
297 | (void *)buf, | ||
298 | transfer, | ||
299 | HZ * 5); | ||
300 | if (status < 0) { | ||
301 | rsi_dbg(ERR_ZONE, | ||
302 | "Reg write failed with error code :%d\n", | ||
303 | status); | ||
304 | } else { | ||
305 | count -= transfer; | ||
306 | data += transfer; | ||
307 | addr += transfer; | ||
308 | } | ||
309 | } | ||
310 | |||
311 | kfree(buf); | ||
312 | return 0; | ||
313 | } | ||
314 | |||
315 | /** | ||
316 | *rsi_usb_host_intf_write_pkt() - This function writes the packet to the | ||
317 | * USB card. | ||
318 | * @adapter: Pointer to the adapter structure. | ||
319 | * @pkt: Pointer to the data to be written on to the card. | ||
320 | * @len: Length of the data to be written on to the card. | ||
321 | * | ||
322 | * Return: 0 on success, -1 on failure. | ||
323 | */ | ||
324 | static int rsi_usb_host_intf_write_pkt(struct rsi_hw *adapter, | ||
325 | u8 *pkt, | ||
326 | u32 len) | ||
327 | { | ||
328 | u32 queueno = ((pkt[1] >> 4) & 0xf); | ||
329 | u8 endpoint; | ||
330 | |||
331 | endpoint = ((queueno == RSI_WIFI_MGMT_Q) ? MGMT_EP : DATA_EP); | ||
332 | |||
333 | return rsi_write_multiple(adapter, | ||
334 | endpoint, | ||
335 | (u8 *)pkt, | ||
336 | len); | ||
337 | } | ||
338 | |||
339 | /** | ||
340 | * rsi_deinit_usb_interface() - This function deinitializes the usb interface. | ||
341 | * @adapter: Pointer to the adapter structure. | ||
342 | * | ||
343 | * Return: None. | ||
344 | */ | ||
345 | static void rsi_deinit_usb_interface(struct rsi_hw *adapter) | ||
346 | { | ||
347 | struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev; | ||
348 | |||
349 | rsi_kill_thread(&dev->rx_thread); | ||
350 | kfree(adapter->priv->rx_data_pkt); | ||
351 | kfree(dev->tx_buffer); | ||
352 | } | ||
353 | |||
354 | /** | ||
355 | * rsi_init_usb_interface() - This function initializes the usb interface. | ||
356 | * @adapter: Pointer to the adapter structure. | ||
357 | * @pfunction: Pointer to USB interface structure. | ||
358 | * | ||
359 | * Return: 0 on success, -1 on failure. | ||
360 | */ | ||
361 | static int rsi_init_usb_interface(struct rsi_hw *adapter, | ||
362 | struct usb_interface *pfunction) | ||
363 | { | ||
364 | struct rsi_91x_usbdev *rsi_dev; | ||
365 | struct rsi_common *common = adapter->priv; | ||
366 | int status; | ||
367 | |||
368 | rsi_dev = kzalloc(sizeof(*rsi_dev), GFP_KERNEL); | ||
369 | if (!rsi_dev) | ||
370 | return -ENOMEM; | ||
371 | |||
372 | adapter->rsi_dev = rsi_dev; | ||
373 | rsi_dev->usbdev = interface_to_usbdev(pfunction); | ||
374 | |||
375 | if (rsi_find_bulk_in_and_out_endpoints(pfunction, adapter)) | ||
376 | return -EINVAL; | ||
377 | |||
378 | adapter->device = &pfunction->dev; | ||
379 | usb_set_intfdata(pfunction, adapter); | ||
380 | |||
381 | common->rx_data_pkt = kmalloc(2048, GFP_KERNEL); | ||
382 | if (!common->rx_data_pkt) { | ||
383 | rsi_dbg(ERR_ZONE, "%s: Failed to allocate memory\n", | ||
384 | __func__); | ||
385 | return -ENOMEM; | ||
386 | } | ||
387 | |||
388 | rsi_dev->tx_buffer = kmalloc(2048, GFP_ATOMIC); | ||
389 | rsi_dev->rx_usb_urb[0] = usb_alloc_urb(0, GFP_KERNEL); | ||
390 | rsi_dev->rx_usb_urb[0]->transfer_buffer = adapter->priv->rx_data_pkt; | ||
391 | rsi_dev->tx_blk_size = 252; | ||
392 | |||
393 | /* Initializing function callbacks */ | ||
394 | adapter->rx_urb_submit = rsi_rx_urb_submit; | ||
395 | adapter->host_intf_write_pkt = rsi_usb_host_intf_write_pkt; | ||
396 | adapter->check_hw_queue_status = rsi_usb_check_queue_status; | ||
397 | adapter->determine_event_timeout = rsi_usb_event_timeout; | ||
398 | |||
399 | rsi_init_event(&rsi_dev->rx_thread.event); | ||
400 | status = rsi_create_kthread(common, &rsi_dev->rx_thread, | ||
401 | rsi_usb_rx_thread, "RX-Thread"); | ||
402 | if (status) { | ||
403 | rsi_dbg(ERR_ZONE, "%s: Unable to init rx thrd\n", __func__); | ||
404 | goto fail; | ||
405 | } | ||
406 | |||
407 | #ifdef CONFIG_RSI_DEBUGFS | ||
408 | /* In USB, one less than the MAX_DEBUGFS_ENTRIES entries is required */ | ||
409 | adapter->num_debugfs_entries = (MAX_DEBUGFS_ENTRIES - 1); | ||
410 | #endif | ||
411 | |||
412 | rsi_dbg(INIT_ZONE, "%s: Enabled the interface\n", __func__); | ||
413 | return 0; | ||
414 | |||
415 | fail: | ||
416 | kfree(rsi_dev->tx_buffer); | ||
417 | kfree(common->rx_data_pkt); | ||
418 | return status; | ||
419 | } | ||
420 | |||
421 | /** | ||
422 | * rsi_probe() - This function is called by kernel when the driver provided | ||
423 | * Vendor and device IDs are matched. All the initialization | ||
424 | * work is done here. | ||
425 | * @pfunction: Pointer to the USB interface structure. | ||
426 | * @id: Pointer to the usb_device_id structure. | ||
427 | * | ||
428 | * Return: 0 on success, -1 on failure. | ||
429 | */ | ||
430 | static int rsi_probe(struct usb_interface *pfunction, | ||
431 | const struct usb_device_id *id) | ||
432 | { | ||
433 | struct rsi_hw *adapter; | ||
434 | struct rsi_91x_usbdev *dev; | ||
435 | u16 fw_status; | ||
436 | |||
437 | rsi_dbg(INIT_ZONE, "%s: Init function called\n", __func__); | ||
438 | |||
439 | adapter = rsi_91x_init(); | ||
440 | if (!adapter) { | ||
441 | rsi_dbg(ERR_ZONE, "%s: Failed to init os intf ops\n", | ||
442 | __func__); | ||
443 | return 1; | ||
444 | } | ||
445 | |||
446 | if (rsi_init_usb_interface(adapter, pfunction)) { | ||
447 | rsi_dbg(ERR_ZONE, "%s: Failed to init usb interface\n", | ||
448 | __func__); | ||
449 | goto err; | ||
450 | } | ||
451 | |||
452 | rsi_dbg(ERR_ZONE, "%s: Initialized os intf ops\n", __func__); | ||
453 | |||
454 | dev = (struct rsi_91x_usbdev *)adapter->rsi_dev; | ||
455 | |||
456 | if (rsi_usb_reg_read(dev->usbdev, FW_STATUS_REG, &fw_status, 2) < 0) | ||
457 | goto err1; | ||
458 | else | ||
459 | fw_status &= 1; | ||
460 | |||
461 | if (!fw_status) { | ||
462 | if (rsi_usb_device_init(adapter->priv)) { | ||
463 | rsi_dbg(ERR_ZONE, "%s: Failed in device init\n", | ||
464 | __func__); | ||
465 | goto err1; | ||
466 | } | ||
467 | |||
468 | if (rsi_usb_reg_write(dev->usbdev, | ||
469 | USB_INTERNAL_REG_1, | ||
470 | RSI_USB_READY_MAGIC_NUM, 1) < 0) | ||
471 | goto err1; | ||
472 | rsi_dbg(INIT_ZONE, "%s: Performed device init\n", __func__); | ||
473 | } | ||
474 | |||
475 | if (rsi_rx_urb_submit(adapter)) | ||
476 | goto err1; | ||
477 | |||
478 | return 0; | ||
479 | err1: | ||
480 | rsi_deinit_usb_interface(adapter); | ||
481 | err: | ||
482 | rsi_91x_deinit(adapter); | ||
483 | rsi_dbg(ERR_ZONE, "%s: Failed in probe...Exiting\n", __func__); | ||
484 | return 1; | ||
485 | } | ||
486 | |||
487 | /** | ||
488 | * rsi_disconnect() - This function performs the reverse of the probe function, | ||
489 | * it deintialize the driver structure. | ||
490 | * @pfunction: Pointer to the USB interface structure. | ||
491 | * | ||
492 | * Return: None. | ||
493 | */ | ||
494 | static void rsi_disconnect(struct usb_interface *pfunction) | ||
495 | { | ||
496 | struct rsi_hw *adapter = usb_get_intfdata(pfunction); | ||
497 | |||
498 | if (!adapter) | ||
499 | return; | ||
500 | |||
501 | rsi_mac80211_detach(adapter); | ||
502 | rsi_deinit_usb_interface(adapter); | ||
503 | rsi_91x_deinit(adapter); | ||
504 | |||
505 | rsi_dbg(INFO_ZONE, "%s: Deinitialization completed\n", __func__); | ||
506 | } | ||
507 | |||
508 | #ifdef CONFIG_PM | ||
509 | static int rsi_suspend(struct usb_interface *intf, pm_message_t message) | ||
510 | { | ||
511 | /* Not yet implemented */ | ||
512 | return -ENOSYS; | ||
513 | } | ||
514 | |||
515 | static int rsi_resume(struct usb_interface *intf) | ||
516 | { | ||
517 | /* Not yet implemented */ | ||
518 | return -ENOSYS; | ||
519 | } | ||
520 | #endif | ||
521 | |||
522 | static const struct usb_device_id rsi_dev_table[] = { | ||
523 | { USB_DEVICE(0x0303, 0x0100) }, | ||
524 | { USB_DEVICE(0x041B, 0x0301) }, | ||
525 | { USB_DEVICE(0x041B, 0x0201) }, | ||
526 | { USB_DEVICE(0x041B, 0x9330) }, | ||
527 | { /* Blank */}, | ||
528 | }; | ||
529 | |||
530 | static struct usb_driver rsi_driver = { | ||
531 | .name = "RSI-USB WLAN", | ||
532 | .probe = rsi_probe, | ||
533 | .disconnect = rsi_disconnect, | ||
534 | .id_table = rsi_dev_table, | ||
535 | #ifdef CONFIG_PM | ||
536 | .suspend = rsi_suspend, | ||
537 | .resume = rsi_resume, | ||
538 | #endif | ||
539 | }; | ||
540 | |||
541 | /** | ||
542 | * rsi_module_init() - This function registers the client driver. | ||
543 | * @void: Void. | ||
544 | * | ||
545 | * Return: 0 on success. | ||
546 | */ | ||
547 | static int rsi_module_init(void) | ||
548 | { | ||
549 | usb_register(&rsi_driver); | ||
550 | rsi_dbg(INIT_ZONE, "%s: Registering driver\n", __func__); | ||
551 | return 0; | ||
552 | } | ||
553 | |||
554 | /** | ||
555 | * rsi_module_exit() - This function unregisters the client driver. | ||
556 | * @void: Void. | ||
557 | * | ||
558 | * Return: None. | ||
559 | */ | ||
560 | static void rsi_module_exit(void) | ||
561 | { | ||
562 | usb_deregister(&rsi_driver); | ||
563 | rsi_dbg(INFO_ZONE, "%s: Unregistering driver\n", __func__); | ||
564 | } | ||
565 | |||
566 | module_init(rsi_module_init); | ||
567 | module_exit(rsi_module_exit); | ||
568 | |||
569 | MODULE_AUTHOR("Redpine Signals Inc"); | ||
570 | MODULE_DESCRIPTION("Common USB layer for RSI drivers"); | ||
571 | MODULE_SUPPORTED_DEVICE("RSI-91x"); | ||
572 | MODULE_DEVICE_TABLE(usb, rsi_dev_table); | ||
573 | MODULE_FIRMWARE(FIRMWARE_RSI9113); | ||
574 | MODULE_VERSION("0.1"); | ||
575 | MODULE_LICENSE("Dual BSD/GPL"); | ||
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb_ops.c b/drivers/net/wireless/rsi/rsi_91x_usb_ops.c new file mode 100644 index 000000000000..1106ce76707e --- /dev/null +++ b/drivers/net/wireless/rsi/rsi_91x_usb_ops.c | |||
@@ -0,0 +1,177 @@ | |||
1 | /** | ||
2 | * Copyright (c) 2014 Redpine Signals Inc. | ||
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 | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #include <linux/firmware.h> | ||
19 | #include "rsi_usb.h" | ||
20 | |||
21 | /** | ||
22 | * rsi_copy_to_card() - This function includes the actual funtionality of | ||
23 | * copying the TA firmware to the card.Basically this | ||
24 | * function includes opening the TA file,reading the TA | ||
25 | * file and writing their values in blocks of data. | ||
26 | * @common: Pointer to the driver private structure. | ||
27 | * @fw: Pointer to the firmware value to be written. | ||
28 | * @len: length of firmware file. | ||
29 | * @num_blocks: Number of blocks to be written to the card. | ||
30 | * | ||
31 | * Return: 0 on success and -1 on failure. | ||
32 | */ | ||
33 | static int rsi_copy_to_card(struct rsi_common *common, | ||
34 | const u8 *fw, | ||
35 | u32 len, | ||
36 | u32 num_blocks) | ||
37 | { | ||
38 | struct rsi_hw *adapter = common->priv; | ||
39 | struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev; | ||
40 | u32 indx, ii; | ||
41 | u32 block_size = dev->tx_blk_size; | ||
42 | u32 lsb_address; | ||
43 | u32 base_address; | ||
44 | |||
45 | base_address = TA_LOAD_ADDRESS; | ||
46 | |||
47 | for (indx = 0, ii = 0; ii < num_blocks; ii++, indx += block_size) { | ||
48 | lsb_address = base_address; | ||
49 | if (rsi_usb_write_register_multiple(adapter, | ||
50 | lsb_address, | ||
51 | (u8 *)(fw + indx), | ||
52 | block_size)) { | ||
53 | rsi_dbg(ERR_ZONE, | ||
54 | "%s: Unable to load %s blk\n", __func__, | ||
55 | FIRMWARE_RSI9113); | ||
56 | return -EIO; | ||
57 | } | ||
58 | rsi_dbg(INIT_ZONE, "%s: loading block: %d\n", __func__, ii); | ||
59 | base_address += block_size; | ||
60 | } | ||
61 | |||
62 | if (len % block_size) { | ||
63 | lsb_address = base_address; | ||
64 | if (rsi_usb_write_register_multiple(adapter, | ||
65 | lsb_address, | ||
66 | (u8 *)(fw + indx), | ||
67 | len % block_size)) { | ||
68 | rsi_dbg(ERR_ZONE, | ||
69 | "%s: Unable to load %s blk\n", __func__, | ||
70 | FIRMWARE_RSI9113); | ||
71 | return -EIO; | ||
72 | } | ||
73 | } | ||
74 | rsi_dbg(INIT_ZONE, | ||
75 | "%s: Succesfully loaded %s instructions\n", __func__, | ||
76 | FIRMWARE_RSI9113); | ||
77 | |||
78 | rsi_dbg(INIT_ZONE, "%s: loaded firmware\n", __func__); | ||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | /** | ||
83 | * rsi_usb_rx_thread() - This is a kernel thread to receive the packets from | ||
84 | * the USB device. | ||
85 | * @common: Pointer to the driver private structure. | ||
86 | * | ||
87 | * Return: None. | ||
88 | */ | ||
89 | void rsi_usb_rx_thread(struct rsi_common *common) | ||
90 | { | ||
91 | struct rsi_hw *adapter = common->priv; | ||
92 | struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev; | ||
93 | int status; | ||
94 | |||
95 | do { | ||
96 | rsi_wait_event(&dev->rx_thread.event, EVENT_WAIT_FOREVER); | ||
97 | |||
98 | if (atomic_read(&dev->rx_thread.thread_done)) | ||
99 | goto out; | ||
100 | |||
101 | mutex_lock(&common->tx_rxlock); | ||
102 | status = rsi_read_pkt(common, 0); | ||
103 | if (status) { | ||
104 | rsi_dbg(ERR_ZONE, "%s: Failed To read data", __func__); | ||
105 | mutex_unlock(&common->tx_rxlock); | ||
106 | return; | ||
107 | } | ||
108 | mutex_unlock(&common->tx_rxlock); | ||
109 | rsi_reset_event(&dev->rx_thread.event); | ||
110 | if (adapter->rx_urb_submit(adapter)) { | ||
111 | rsi_dbg(ERR_ZONE, | ||
112 | "%s: Failed in urb submission", __func__); | ||
113 | return; | ||
114 | } | ||
115 | } while (1); | ||
116 | |||
117 | out: | ||
118 | rsi_dbg(INFO_ZONE, "%s: Terminated thread\n", __func__); | ||
119 | complete_and_exit(&dev->rx_thread.completion, 0); | ||
120 | } | ||
121 | |||
122 | |||
123 | /** | ||
124 | * rsi_load_ta_instructions() - This function includes the actual funtionality | ||
125 | * of loading the TA firmware.This function also | ||
126 | * includes opening the TA file,reading the TA | ||
127 | * file and writing their value in blocks of data. | ||
128 | * @common: Pointer to the driver private structure. | ||
129 | * | ||
130 | * Return: status: 0 on success, -1 on failure. | ||
131 | */ | ||
132 | static int rsi_load_ta_instructions(struct rsi_common *common) | ||
133 | { | ||
134 | struct rsi_hw *adapter = common->priv; | ||
135 | struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev; | ||
136 | const struct firmware *fw_entry = NULL; | ||
137 | u32 block_size = dev->tx_blk_size; | ||
138 | const u8 *fw; | ||
139 | u32 num_blocks, len; | ||
140 | int status = 0; | ||
141 | |||
142 | status = request_firmware(&fw_entry, FIRMWARE_RSI9113, adapter->device); | ||
143 | if (status < 0) { | ||
144 | rsi_dbg(ERR_ZONE, "%s Firmware file %s not found\n", | ||
145 | __func__, FIRMWARE_RSI9113); | ||
146 | return status; | ||
147 | } | ||
148 | |||
149 | fw = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL); | ||
150 | len = fw_entry->size; | ||
151 | |||
152 | if (len % 4) | ||
153 | len += (4 - (len % 4)); | ||
154 | |||
155 | num_blocks = (len / block_size); | ||
156 | |||
157 | rsi_dbg(INIT_ZONE, "%s: Instruction size:%d\n", __func__, len); | ||
158 | rsi_dbg(INIT_ZONE, "%s: num blocks: %d\n", __func__, num_blocks); | ||
159 | |||
160 | status = rsi_copy_to_card(common, fw, len, num_blocks); | ||
161 | release_firmware(fw_entry); | ||
162 | return status; | ||
163 | } | ||
164 | |||
165 | /** | ||
166 | * rsi_device_init() - This Function Initializes The HAL. | ||
167 | * @common: Pointer to the driver private structure. | ||
168 | * | ||
169 | * Return: 0 on success, -1 on failure. | ||
170 | */ | ||
171 | int rsi_usb_device_init(struct rsi_common *common) | ||
172 | { | ||
173 | if (rsi_load_ta_instructions(common)) | ||
174 | return -EIO; | ||
175 | |||
176 | return 0; | ||
177 | } | ||
diff --git a/drivers/net/wireless/rsi/rsi_boot_params.h b/drivers/net/wireless/rsi/rsi_boot_params.h new file mode 100644 index 000000000000..5e2721f7909c --- /dev/null +++ b/drivers/net/wireless/rsi/rsi_boot_params.h | |||
@@ -0,0 +1,126 @@ | |||
1 | /** | ||
2 | * Copyright (c) 2014 Redpine Signals Inc. | ||
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 | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef __RSI_BOOTPARAMS_HEADER_H__ | ||
18 | #define __RSI_BOOTPARAMS_HEADER_H__ | ||
19 | |||
20 | #define CRYSTAL_GOOD_TIME BIT(0) | ||
21 | #define BOOTUP_MODE_INFO BIT(1) | ||
22 | #define WIFI_TAPLL_CONFIGS BIT(5) | ||
23 | #define WIFI_PLL960_CONFIGS BIT(6) | ||
24 | #define WIFI_AFEPLL_CONFIGS BIT(7) | ||
25 | #define WIFI_SWITCH_CLK_CONFIGS BIT(8) | ||
26 | |||
27 | #define TA_PLL_M_VAL_20 8 | ||
28 | #define TA_PLL_N_VAL_20 1 | ||
29 | #define TA_PLL_P_VAL_20 4 | ||
30 | |||
31 | #define PLL960_M_VAL_20 0x14 | ||
32 | #define PLL960_N_VAL_20 0 | ||
33 | #define PLL960_P_VAL_20 5 | ||
34 | |||
35 | #define UMAC_CLK_40MHZ 40 | ||
36 | |||
37 | #define TA_PLL_M_VAL_40 46 | ||
38 | #define TA_PLL_N_VAL_40 3 | ||
39 | #define TA_PLL_P_VAL_40 3 | ||
40 | |||
41 | #define PLL960_M_VAL_40 0x14 | ||
42 | #define PLL960_N_VAL_40 0 | ||
43 | #define PLL960_P_VAL_40 5 | ||
44 | |||
45 | #define UMAC_CLK_20BW \ | ||
46 | (((TA_PLL_M_VAL_20 + 1) * 40) / \ | ||
47 | ((TA_PLL_N_VAL_20 + 1) * (TA_PLL_P_VAL_20 + 1))) | ||
48 | #define VALID_20 \ | ||
49 | (WIFI_PLL960_CONFIGS | WIFI_AFEPLL_CONFIGS | WIFI_SWITCH_CLK_CONFIGS) | ||
50 | #define UMAC_CLK_40BW \ | ||
51 | (((TA_PLL_M_VAL_40 + 1) * 40) / \ | ||
52 | ((TA_PLL_N_VAL_40 + 1) * (TA_PLL_P_VAL_40 + 1))) | ||
53 | #define VALID_40 \ | ||
54 | (WIFI_PLL960_CONFIGS | WIFI_AFEPLL_CONFIGS | WIFI_SWITCH_CLK_CONFIGS | \ | ||
55 | WIFI_TAPLL_CONFIGS | CRYSTAL_GOOD_TIME | BOOTUP_MODE_INFO) | ||
56 | |||
57 | /* structure to store configs related to TAPLL programming */ | ||
58 | struct tapll_info { | ||
59 | __le16 pll_reg_1; | ||
60 | __le16 pll_reg_2; | ||
61 | } __packed; | ||
62 | |||
63 | /* structure to store configs related to PLL960 programming */ | ||
64 | struct pll960_info { | ||
65 | __le16 pll_reg_1; | ||
66 | __le16 pll_reg_2; | ||
67 | __le16 pll_reg_3; | ||
68 | } __packed; | ||
69 | |||
70 | /* structure to store configs related to AFEPLL programming */ | ||
71 | struct afepll_info { | ||
72 | __le16 pll_reg; | ||
73 | } __packed; | ||
74 | |||
75 | /* structure to store configs related to pll configs */ | ||
76 | struct pll_config { | ||
77 | struct tapll_info tapll_info_g; | ||
78 | struct pll960_info pll960_info_g; | ||
79 | struct afepll_info afepll_info_g; | ||
80 | } __packed; | ||
81 | |||
82 | /* structure to store configs related to UMAC clk programming */ | ||
83 | struct switch_clk { | ||
84 | __le16 switch_clk_info; | ||
85 | /* If switch_bbp_lmac_clk_reg is set then this value will be programmed | ||
86 | * into reg | ||
87 | */ | ||
88 | __le16 bbp_lmac_clk_reg_val; | ||
89 | /* if switch_umac_clk is set then this value will be programmed */ | ||
90 | __le16 umac_clock_reg_config; | ||
91 | /* if switch_qspi_clk is set then this value will be programmed */ | ||
92 | __le16 qspi_uart_clock_reg_config; | ||
93 | } __packed; | ||
94 | |||
95 | struct device_clk_info { | ||
96 | struct pll_config pll_config_g; | ||
97 | struct switch_clk switch_clk_g; | ||
98 | } __packed; | ||
99 | |||
100 | struct bootup_params { | ||
101 | __le16 magic_number; | ||
102 | __le16 crystal_good_time; | ||
103 | __le32 valid; | ||
104 | __le32 reserved_for_valids; | ||
105 | __le16 bootup_mode_info; | ||
106 | /* configuration used for digital loop back */ | ||
107 | __le16 digital_loop_back_params; | ||
108 | __le16 rtls_timestamp_en; | ||
109 | __le16 host_spi_intr_cfg; | ||
110 | struct device_clk_info device_clk_info[3]; | ||
111 | /* ulp buckboost wait time */ | ||
112 | __le32 buckboost_wakeup_cnt; | ||
113 | /* pmu wakeup wait time & WDT EN info */ | ||
114 | __le16 pmu_wakeup_wait; | ||
115 | u8 shutdown_wait_time; | ||
116 | /* Sleep clock source selection */ | ||
117 | u8 pmu_slp_clkout_sel; | ||
118 | /* WDT programming values */ | ||
119 | __le32 wdt_prog_value; | ||
120 | /* WDT soc reset delay */ | ||
121 | __le32 wdt_soc_rst_delay; | ||
122 | /* dcdc modes configs */ | ||
123 | __le32 dcdc_operation_mode; | ||
124 | __le32 soc_reset_wait_cnt; | ||
125 | } __packed; | ||
126 | #endif | ||
diff --git a/drivers/net/wireless/rsi/rsi_common.h b/drivers/net/wireless/rsi/rsi_common.h new file mode 100644 index 000000000000..f2f70784d4ad --- /dev/null +++ b/drivers/net/wireless/rsi/rsi_common.h | |||
@@ -0,0 +1,87 @@ | |||
1 | /** | ||
2 | * Copyright (c) 2014 Redpine Signals Inc. | ||
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 | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef __RSI_COMMON_H__ | ||
18 | #define __RSI_COMMON_H__ | ||
19 | |||
20 | #include <linux/kthread.h> | ||
21 | |||
22 | #define EVENT_WAIT_FOREVER 0 | ||
23 | #define TA_LOAD_ADDRESS 0x00 | ||
24 | #define FIRMWARE_RSI9113 "rsi_91x.fw" | ||
25 | #define QUEUE_NOT_FULL 1 | ||
26 | #define QUEUE_FULL 0 | ||
27 | |||
28 | static inline int rsi_init_event(struct rsi_event *pevent) | ||
29 | { | ||
30 | atomic_set(&pevent->event_condition, 1); | ||
31 | init_waitqueue_head(&pevent->event_queue); | ||
32 | return 0; | ||
33 | } | ||
34 | |||
35 | static inline int rsi_wait_event(struct rsi_event *event, u32 timeout) | ||
36 | { | ||
37 | int status = 0; | ||
38 | |||
39 | if (!timeout) | ||
40 | status = wait_event_interruptible(event->event_queue, | ||
41 | (atomic_read(&event->event_condition) == 0)); | ||
42 | else | ||
43 | status = wait_event_interruptible_timeout(event->event_queue, | ||
44 | (atomic_read(&event->event_condition) == 0), | ||
45 | timeout); | ||
46 | return status; | ||
47 | } | ||
48 | |||
49 | static inline void rsi_set_event(struct rsi_event *event) | ||
50 | { | ||
51 | atomic_set(&event->event_condition, 0); | ||
52 | wake_up_interruptible(&event->event_queue); | ||
53 | } | ||
54 | |||
55 | static inline void rsi_reset_event(struct rsi_event *event) | ||
56 | { | ||
57 | atomic_set(&event->event_condition, 1); | ||
58 | } | ||
59 | |||
60 | static inline int rsi_create_kthread(struct rsi_common *common, | ||
61 | struct rsi_thread *thread, | ||
62 | void *func_ptr, | ||
63 | u8 *name) | ||
64 | { | ||
65 | init_completion(&thread->completion); | ||
66 | thread->task = kthread_run(func_ptr, common, name); | ||
67 | if (IS_ERR(thread->task)) | ||
68 | return (int)PTR_ERR(thread->task); | ||
69 | |||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | static inline int rsi_kill_thread(struct rsi_thread *handle) | ||
74 | { | ||
75 | atomic_inc(&handle->thread_done); | ||
76 | rsi_set_event(&handle->event); | ||
77 | |||
78 | wait_for_completion(&handle->completion); | ||
79 | return kthread_stop(handle->task); | ||
80 | } | ||
81 | |||
82 | void rsi_mac80211_detach(struct rsi_hw *hw); | ||
83 | u16 rsi_get_connected_channel(struct rsi_hw *adapter); | ||
84 | struct rsi_hw *rsi_91x_init(void); | ||
85 | void rsi_91x_deinit(struct rsi_hw *adapter); | ||
86 | int rsi_read_pkt(struct rsi_common *common, s32 rcv_pkt_len); | ||
87 | #endif | ||
diff --git a/drivers/net/wireless/rsi/rsi_debugfs.h b/drivers/net/wireless/rsi/rsi_debugfs.h new file mode 100644 index 000000000000..580ad3b3f710 --- /dev/null +++ b/drivers/net/wireless/rsi/rsi_debugfs.h | |||
@@ -0,0 +1,48 @@ | |||
1 | /** | ||
2 | * Copyright (c) 2014 Redpine Signals Inc. | ||
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 | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef __RSI_DEBUGFS_H__ | ||
18 | #define __RSI_DEBUGFS_H__ | ||
19 | |||
20 | #include "rsi_main.h" | ||
21 | #include <linux/debugfs.h> | ||
22 | |||
23 | #ifndef CONFIG_RSI_DEBUGFS | ||
24 | static inline int rsi_init_dbgfs(struct rsi_hw *adapter) | ||
25 | { | ||
26 | return 0; | ||
27 | } | ||
28 | |||
29 | static inline void rsi_remove_dbgfs(struct rsi_hw *adapter) | ||
30 | { | ||
31 | return; | ||
32 | } | ||
33 | #else | ||
34 | struct rsi_dbg_files { | ||
35 | const char *name; | ||
36 | umode_t perms; | ||
37 | const struct file_operations fops; | ||
38 | }; | ||
39 | |||
40 | struct rsi_debugfs { | ||
41 | struct dentry *subdir; | ||
42 | struct rsi_dbg_ops *dfs_get_ops; | ||
43 | struct dentry *rsi_files[MAX_DEBUGFS_ENTRIES]; | ||
44 | }; | ||
45 | int rsi_init_dbgfs(struct rsi_hw *adapter); | ||
46 | void rsi_remove_dbgfs(struct rsi_hw *adapter); | ||
47 | #endif | ||
48 | #endif | ||
diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h new file mode 100644 index 000000000000..2cb73e7edb98 --- /dev/null +++ b/drivers/net/wireless/rsi/rsi_main.h | |||
@@ -0,0 +1,218 @@ | |||
1 | /** | ||
2 | * Copyright (c) 2014 Redpine Signals Inc. | ||
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 | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef __RSI_MAIN_H__ | ||
18 | #define __RSI_MAIN_H__ | ||
19 | |||
20 | #include <linux/string.h> | ||
21 | #include <linux/skbuff.h> | ||
22 | #include <net/mac80211.h> | ||
23 | |||
24 | #define ERR_ZONE BIT(0) /* For Error Msgs */ | ||
25 | #define INFO_ZONE BIT(1) /* For General Status Msgs */ | ||
26 | #define INIT_ZONE BIT(2) /* For Driver Init Seq Msgs */ | ||
27 | #define MGMT_TX_ZONE BIT(3) /* For TX Mgmt Path Msgs */ | ||
28 | #define MGMT_RX_ZONE BIT(4) /* For RX Mgmt Path Msgs */ | ||
29 | #define DATA_TX_ZONE BIT(5) /* For TX Data Path Msgs */ | ||
30 | #define DATA_RX_ZONE BIT(6) /* For RX Data Path Msgs */ | ||
31 | #define FSM_ZONE BIT(7) /* For State Machine Msgs */ | ||
32 | #define ISR_ZONE BIT(8) /* For Interrupt Msgs */ | ||
33 | |||
34 | #define FSM_CARD_NOT_READY 0 | ||
35 | #define FSM_BOOT_PARAMS_SENT 1 | ||
36 | #define FSM_EEPROM_READ_MAC_ADDR 2 | ||
37 | #define FSM_RESET_MAC_SENT 3 | ||
38 | #define FSM_RADIO_CAPS_SENT 4 | ||
39 | #define FSM_BB_RF_PROG_SENT 5 | ||
40 | #define FSM_MAC_INIT_DONE 6 | ||
41 | |||
42 | extern u32 rsi_zone_enabled; | ||
43 | extern __printf(2, 3) void rsi_dbg(u32 zone, const char *fmt, ...); | ||
44 | |||
45 | #define RSI_MAX_VIFS 1 | ||
46 | #define NUM_EDCA_QUEUES 4 | ||
47 | #define IEEE80211_ADDR_LEN 6 | ||
48 | #define FRAME_DESC_SZ 16 | ||
49 | #define MIN_802_11_HDR_LEN 24 | ||
50 | |||
51 | #define DATA_QUEUE_WATER_MARK 400 | ||
52 | #define MIN_DATA_QUEUE_WATER_MARK 300 | ||
53 | #define MULTICAST_WATER_MARK 200 | ||
54 | #define MAC_80211_HDR_FRAME_CONTROL 0 | ||
55 | #define WME_NUM_AC 4 | ||
56 | #define NUM_SOFT_QUEUES 5 | ||
57 | #define MAX_HW_QUEUES 8 | ||
58 | #define INVALID_QUEUE 0xff | ||
59 | #define MAX_CONTINUOUS_VO_PKTS 8 | ||
60 | #define MAX_CONTINUOUS_VI_PKTS 4 | ||
61 | |||
62 | /* Queue information */ | ||
63 | #define RSI_WIFI_MGMT_Q 0x4 | ||
64 | #define RSI_WIFI_DATA_Q 0x5 | ||
65 | #define IEEE80211_MGMT_FRAME 0x00 | ||
66 | #define IEEE80211_CTL_FRAME 0x04 | ||
67 | |||
68 | #define IEEE80211_QOS_TID 0x0f | ||
69 | #define IEEE80211_NONQOS_TID 16 | ||
70 | |||
71 | #define MAX_DEBUGFS_ENTRIES 4 | ||
72 | |||
73 | #define TID_TO_WME_AC(_tid) ( \ | ||
74 | ((_tid) == 0 || (_tid) == 3) ? BE_Q : \ | ||
75 | ((_tid) < 3) ? BK_Q : \ | ||
76 | ((_tid) < 6) ? VI_Q : \ | ||
77 | VO_Q) | ||
78 | |||
79 | #define WME_AC(_q) ( \ | ||
80 | ((_q) == BK_Q) ? IEEE80211_AC_BK : \ | ||
81 | ((_q) == BE_Q) ? IEEE80211_AC_BE : \ | ||
82 | ((_q) == VI_Q) ? IEEE80211_AC_VI : \ | ||
83 | IEEE80211_AC_VO) | ||
84 | |||
85 | struct version_info { | ||
86 | u16 major; | ||
87 | u16 minor; | ||
88 | u16 release_num; | ||
89 | u16 patch_num; | ||
90 | } __packed; | ||
91 | |||
92 | struct skb_info { | ||
93 | s8 rssi; | ||
94 | u32 flags; | ||
95 | u16 channel; | ||
96 | s8 tid; | ||
97 | s8 sta_id; | ||
98 | }; | ||
99 | |||
100 | enum edca_queue { | ||
101 | BK_Q, | ||
102 | BE_Q, | ||
103 | VI_Q, | ||
104 | VO_Q, | ||
105 | MGMT_SOFT_Q | ||
106 | }; | ||
107 | |||
108 | struct security_info { | ||
109 | bool security_enable; | ||
110 | u32 ptk_cipher; | ||
111 | u32 gtk_cipher; | ||
112 | }; | ||
113 | |||
114 | struct wmm_qinfo { | ||
115 | s32 weight; | ||
116 | s32 wme_params; | ||
117 | s32 pkt_contended; | ||
118 | }; | ||
119 | |||
120 | struct transmit_q_stats { | ||
121 | u32 total_tx_pkt_send[NUM_EDCA_QUEUES + 1]; | ||
122 | u32 total_tx_pkt_freed[NUM_EDCA_QUEUES + 1]; | ||
123 | }; | ||
124 | |||
125 | struct vif_priv { | ||
126 | bool is_ht; | ||
127 | bool sgi; | ||
128 | u16 seq_start; | ||
129 | }; | ||
130 | |||
131 | struct rsi_event { | ||
132 | atomic_t event_condition; | ||
133 | wait_queue_head_t event_queue; | ||
134 | }; | ||
135 | |||
136 | struct rsi_thread { | ||
137 | void (*thread_function)(void *); | ||
138 | struct completion completion; | ||
139 | struct task_struct *task; | ||
140 | struct rsi_event event; | ||
141 | atomic_t thread_done; | ||
142 | }; | ||
143 | |||
144 | struct rsi_hw; | ||
145 | |||
146 | struct rsi_common { | ||
147 | struct rsi_hw *priv; | ||
148 | struct vif_priv vif_info[RSI_MAX_VIFS]; | ||
149 | |||
150 | bool mgmt_q_block; | ||
151 | struct version_info driver_ver; | ||
152 | struct version_info fw_ver; | ||
153 | |||
154 | struct rsi_thread tx_thread; | ||
155 | struct sk_buff_head tx_queue[NUM_EDCA_QUEUES + 1]; | ||
156 | /* Mutex declaration */ | ||
157 | struct mutex mutex; | ||
158 | /* Mutex used between tx/rx threads */ | ||
159 | struct mutex tx_rxlock; | ||
160 | u8 endpoint; | ||
161 | |||
162 | /* Channel/band related */ | ||
163 | u8 band; | ||
164 | u8 channel_width; | ||
165 | |||
166 | u16 rts_threshold; | ||
167 | u16 bitrate_mask[2]; | ||
168 | u32 fixedrate_mask[2]; | ||
169 | |||
170 | u8 rf_reset; | ||
171 | struct transmit_q_stats tx_stats; | ||
172 | struct security_info secinfo; | ||
173 | struct wmm_qinfo tx_qinfo[NUM_EDCA_QUEUES]; | ||
174 | struct ieee80211_tx_queue_params edca_params[NUM_EDCA_QUEUES]; | ||
175 | u8 mac_addr[IEEE80211_ADDR_LEN]; | ||
176 | |||
177 | /* state related */ | ||
178 | u32 fsm_state; | ||
179 | bool init_done; | ||
180 | u8 bb_rf_prog_count; | ||
181 | bool iface_down; | ||
182 | |||
183 | /* Generic */ | ||
184 | u8 channel; | ||
185 | u8 *rx_data_pkt; | ||
186 | u8 mac_id; | ||
187 | u8 radio_id; | ||
188 | u16 rate_pwr[20]; | ||
189 | u16 min_rate; | ||
190 | |||
191 | /* WMM algo related */ | ||
192 | u8 selected_qnum; | ||
193 | u32 pkt_cnt; | ||
194 | u8 min_weight; | ||
195 | }; | ||
196 | |||
197 | struct rsi_hw { | ||
198 | struct rsi_common *priv; | ||
199 | struct ieee80211_hw *hw; | ||
200 | struct ieee80211_vif *vifs[RSI_MAX_VIFS]; | ||
201 | struct ieee80211_tx_queue_params edca_params[NUM_EDCA_QUEUES]; | ||
202 | struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; | ||
203 | |||
204 | struct device *device; | ||
205 | u8 sc_nvifs; | ||
206 | |||
207 | #ifdef CONFIG_RSI_DEBUGFS | ||
208 | struct rsi_debugfs *dfsentry; | ||
209 | u8 num_debugfs_entries; | ||
210 | #endif | ||
211 | void *rsi_dev; | ||
212 | int (*host_intf_read_pkt)(struct rsi_hw *adapter, u8 *pkt, u32 len); | ||
213 | int (*host_intf_write_pkt)(struct rsi_hw *adapter, u8 *pkt, u32 len); | ||
214 | int (*check_hw_queue_status)(struct rsi_hw *adapter, u8 q_num); | ||
215 | int (*rx_urb_submit)(struct rsi_hw *adapter); | ||
216 | int (*determine_event_timeout)(struct rsi_hw *adapter); | ||
217 | }; | ||
218 | #endif | ||
diff --git a/drivers/net/wireless/rsi/rsi_mgmt.h b/drivers/net/wireless/rsi/rsi_mgmt.h new file mode 100644 index 000000000000..ac67c4ad63c2 --- /dev/null +++ b/drivers/net/wireless/rsi/rsi_mgmt.h | |||
@@ -0,0 +1,285 @@ | |||
1 | /** | ||
2 | * Copyright (c) 2014 Redpine Signals Inc. | ||
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 | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef __RSI_MGMT_H__ | ||
18 | #define __RSI_MGMT_H__ | ||
19 | |||
20 | #include <linux/sort.h> | ||
21 | #include "rsi_boot_params.h" | ||
22 | #include "rsi_main.h" | ||
23 | |||
24 | #define MAX_MGMT_PKT_SIZE 512 | ||
25 | #define RSI_NEEDED_HEADROOM 80 | ||
26 | #define RSI_RCV_BUFFER_LEN 2000 | ||
27 | |||
28 | #define RSI_11B_MODE 0 | ||
29 | #define RSI_11G_MODE BIT(7) | ||
30 | #define RETRY_COUNT 8 | ||
31 | #define RETRY_LONG 4 | ||
32 | #define RETRY_SHORT 7 | ||
33 | #define WMM_SHORT_SLOT_TIME 9 | ||
34 | #define SIFS_DURATION 16 | ||
35 | |||
36 | #define KEY_TYPE_CLEAR 0 | ||
37 | #define RSI_PAIRWISE_KEY 1 | ||
38 | #define RSI_GROUP_KEY 2 | ||
39 | |||
40 | /* EPPROM_READ_ADDRESS */ | ||
41 | #define WLAN_MAC_EEPROM_ADDR 40 | ||
42 | #define WLAN_MAC_MAGIC_WORD_LEN 0x01 | ||
43 | #define WLAN_HOST_MODE_LEN 0x04 | ||
44 | #define WLAN_FW_VERSION_LEN 0x08 | ||
45 | #define MAGIC_WORD 0x5A | ||
46 | |||
47 | /* Receive Frame Types */ | ||
48 | #define TA_CONFIRM_TYPE 0x01 | ||
49 | #define RX_DOT11_MGMT 0x02 | ||
50 | #define TX_STATUS_IND 0x04 | ||
51 | #define PROBEREQ_CONFIRM 2 | ||
52 | #define CARD_READY_IND 0x00 | ||
53 | |||
54 | #define RSI_DELETE_PEER 0x0 | ||
55 | #define RSI_ADD_PEER 0x1 | ||
56 | #define START_AMPDU_AGGR 0x1 | ||
57 | #define STOP_AMPDU_AGGR 0x0 | ||
58 | #define INTERNAL_MGMT_PKT 0x99 | ||
59 | |||
60 | #define PUT_BBP_RESET 0 | ||
61 | #define BBP_REG_WRITE 0 | ||
62 | #define RF_RESET_ENABLE BIT(3) | ||
63 | #define RATE_INFO_ENABLE BIT(0) | ||
64 | #define RSI_BROADCAST_PKT BIT(9) | ||
65 | |||
66 | #define UPPER_20_ENABLE (0x2 << 12) | ||
67 | #define LOWER_20_ENABLE (0x4 << 12) | ||
68 | #define FULL40M_ENABLE 0x6 | ||
69 | |||
70 | #define RSI_LMAC_CLOCK_80MHZ 0x1 | ||
71 | #define RSI_ENABLE_40MHZ (0x1 << 3) | ||
72 | |||
73 | #define RX_BA_INDICATION 1 | ||
74 | #define RSI_TBL_SZ 40 | ||
75 | #define MAX_RETRIES 8 | ||
76 | |||
77 | #define STD_RATE_MCS7 0x07 | ||
78 | #define STD_RATE_MCS6 0x06 | ||
79 | #define STD_RATE_MCS5 0x05 | ||
80 | #define STD_RATE_MCS4 0x04 | ||
81 | #define STD_RATE_MCS3 0x03 | ||
82 | #define STD_RATE_MCS2 0x02 | ||
83 | #define STD_RATE_MCS1 0x01 | ||
84 | #define STD_RATE_MCS0 0x00 | ||
85 | #define STD_RATE_54 0x6c | ||
86 | #define STD_RATE_48 0x60 | ||
87 | #define STD_RATE_36 0x48 | ||
88 | #define STD_RATE_24 0x30 | ||
89 | #define STD_RATE_18 0x24 | ||
90 | #define STD_RATE_12 0x18 | ||
91 | #define STD_RATE_11 0x16 | ||
92 | #define STD_RATE_09 0x12 | ||
93 | #define STD_RATE_06 0x0C | ||
94 | #define STD_RATE_5_5 0x0B | ||
95 | #define STD_RATE_02 0x04 | ||
96 | #define STD_RATE_01 0x02 | ||
97 | |||
98 | #define RSI_RF_TYPE 1 | ||
99 | #define RSI_RATE_00 0x00 | ||
100 | #define RSI_RATE_1 0x0 | ||
101 | #define RSI_RATE_2 0x2 | ||
102 | #define RSI_RATE_5_5 0x4 | ||
103 | #define RSI_RATE_11 0x6 | ||
104 | #define RSI_RATE_6 0x8b | ||
105 | #define RSI_RATE_9 0x8f | ||
106 | #define RSI_RATE_12 0x8a | ||
107 | #define RSI_RATE_18 0x8e | ||
108 | #define RSI_RATE_24 0x89 | ||
109 | #define RSI_RATE_36 0x8d | ||
110 | #define RSI_RATE_48 0x88 | ||
111 | #define RSI_RATE_54 0x8c | ||
112 | #define RSI_RATE_MCS0 0x100 | ||
113 | #define RSI_RATE_MCS1 0x101 | ||
114 | #define RSI_RATE_MCS2 0x102 | ||
115 | #define RSI_RATE_MCS3 0x103 | ||
116 | #define RSI_RATE_MCS4 0x104 | ||
117 | #define RSI_RATE_MCS5 0x105 | ||
118 | #define RSI_RATE_MCS6 0x106 | ||
119 | #define RSI_RATE_MCS7 0x107 | ||
120 | #define RSI_RATE_MCS7_SG 0x307 | ||
121 | |||
122 | #define BW_20MHZ 0 | ||
123 | #define BW_40MHZ 1 | ||
124 | |||
125 | #define RSI_SUPP_FILTERS (FIF_ALLMULTI | FIF_PROBE_REQ |\ | ||
126 | FIF_BCN_PRBRESP_PROMISC) | ||
127 | enum opmode { | ||
128 | STA_OPMODE = 1, | ||
129 | AP_OPMODE = 2 | ||
130 | }; | ||
131 | |||
132 | extern struct ieee80211_rate rsi_rates[12]; | ||
133 | extern const u16 rsi_mcsrates[8]; | ||
134 | |||
135 | enum sta_notify_events { | ||
136 | STA_CONNECTED = 0, | ||
137 | STA_DISCONNECTED, | ||
138 | STA_TX_ADDBA_DONE, | ||
139 | STA_TX_DELBA, | ||
140 | STA_RX_ADDBA_DONE, | ||
141 | STA_RX_DELBA | ||
142 | }; | ||
143 | |||
144 | /* Send Frames Types */ | ||
145 | enum cmd_frame_type { | ||
146 | TX_DOT11_MGMT, | ||
147 | RESET_MAC_REQ, | ||
148 | RADIO_CAPABILITIES, | ||
149 | BB_PROG_VALUES_REQUEST, | ||
150 | RF_PROG_VALUES_REQUEST, | ||
151 | WAKEUP_SLEEP_REQUEST, | ||
152 | SCAN_REQUEST, | ||
153 | TSF_UPDATE, | ||
154 | PEER_NOTIFY, | ||
155 | BLOCK_UNBLOCK, | ||
156 | SET_KEY_REQ, | ||
157 | AUTO_RATE_IND, | ||
158 | BOOTUP_PARAMS_REQUEST, | ||
159 | VAP_CAPABILITIES, | ||
160 | EEPROM_READ_TYPE , | ||
161 | EEPROM_WRITE, | ||
162 | GPIO_PIN_CONFIG , | ||
163 | SET_RX_FILTER, | ||
164 | AMPDU_IND, | ||
165 | STATS_REQUEST_FRAME, | ||
166 | BB_BUF_PROG_VALUES_REQ, | ||
167 | BBP_PROG_IN_TA, | ||
168 | BG_SCAN_PARAMS, | ||
169 | BG_SCAN_PROBE_REQ, | ||
170 | CW_MODE_REQ, | ||
171 | PER_CMD_PKT | ||
172 | }; | ||
173 | |||
174 | struct rsi_mac_frame { | ||
175 | __le16 desc_word[8]; | ||
176 | } __packed; | ||
177 | |||
178 | struct rsi_boot_params { | ||
179 | __le16 desc_word[8]; | ||
180 | struct bootup_params bootup_params; | ||
181 | } __packed; | ||
182 | |||
183 | struct rsi_peer_notify { | ||
184 | __le16 desc_word[8]; | ||
185 | u8 mac_addr[6]; | ||
186 | __le16 command; | ||
187 | __le16 mpdu_density; | ||
188 | __le16 reserved; | ||
189 | __le32 sta_flags; | ||
190 | } __packed; | ||
191 | |||
192 | struct rsi_vap_caps { | ||
193 | __le16 desc_word[8]; | ||
194 | u8 mac_addr[6]; | ||
195 | __le16 keep_alive_period; | ||
196 | u8 bssid[6]; | ||
197 | __le16 reserved; | ||
198 | __le32 flags; | ||
199 | __le16 frag_threshold; | ||
200 | __le16 rts_threshold; | ||
201 | __le32 default_mgmt_rate; | ||
202 | __le32 default_ctrl_rate; | ||
203 | __le32 default_data_rate; | ||
204 | __le16 beacon_interval; | ||
205 | __le16 dtim_period; | ||
206 | } __packed; | ||
207 | |||
208 | struct rsi_set_key { | ||
209 | __le16 desc_word[8]; | ||
210 | u8 key[4][32]; | ||
211 | u8 tx_mic_key[8]; | ||
212 | u8 rx_mic_key[8]; | ||
213 | } __packed; | ||
214 | |||
215 | struct rsi_auto_rate { | ||
216 | __le16 desc_word[8]; | ||
217 | __le16 failure_limit; | ||
218 | __le16 initial_boundary; | ||
219 | __le16 max_threshold_limt; | ||
220 | __le16 num_supported_rates; | ||
221 | __le16 aarf_rssi; | ||
222 | __le16 moderate_rate_inx; | ||
223 | __le16 collision_tolerance; | ||
224 | __le16 supported_rates[40]; | ||
225 | } __packed; | ||
226 | |||
227 | struct qos_params { | ||
228 | __le16 cont_win_min_q; | ||
229 | __le16 cont_win_max_q; | ||
230 | __le16 aifsn_val_q; | ||
231 | __le16 txop_q; | ||
232 | } __packed; | ||
233 | |||
234 | struct rsi_radio_caps { | ||
235 | __le16 desc_word[8]; | ||
236 | struct qos_params qos_params[MAX_HW_QUEUES]; | ||
237 | u8 num_11n_rates; | ||
238 | u8 num_11ac_rates; | ||
239 | __le16 gcpd_per_rate[20]; | ||
240 | } __packed; | ||
241 | |||
242 | static inline u32 rsi_get_queueno(u8 *addr, u16 offset) | ||
243 | { | ||
244 | return (le16_to_cpu(*(__le16 *)&addr[offset]) & 0x7000) >> 12; | ||
245 | } | ||
246 | |||
247 | static inline u32 rsi_get_length(u8 *addr, u16 offset) | ||
248 | { | ||
249 | return (le16_to_cpu(*(__le16 *)&addr[offset])) & 0x0fff; | ||
250 | } | ||
251 | |||
252 | static inline u8 rsi_get_extended_desc(u8 *addr, u16 offset) | ||
253 | { | ||
254 | return le16_to_cpu(*((__le16 *)&addr[offset + 4])) & 0x00ff; | ||
255 | } | ||
256 | |||
257 | static inline u8 rsi_get_rssi(u8 *addr) | ||
258 | { | ||
259 | return *(u8 *)(addr + FRAME_DESC_SZ); | ||
260 | } | ||
261 | |||
262 | static inline u8 rsi_get_channel(u8 *addr) | ||
263 | { | ||
264 | return *(char *)(addr + 15); | ||
265 | } | ||
266 | |||
267 | int rsi_mgmt_pkt_recv(struct rsi_common *common, u8 *msg); | ||
268 | int rsi_set_vap_capabilities(struct rsi_common *common, enum opmode mode); | ||
269 | int rsi_send_aggregation_params_frame(struct rsi_common *common, u16 tid, | ||
270 | u16 ssn, u8 buf_size, u8 event); | ||
271 | int rsi_hal_load_key(struct rsi_common *common, u8 *data, u16 key_len, | ||
272 | u8 key_type, u8 key_id, u32 cipher); | ||
273 | int rsi_set_channel(struct rsi_common *common, u16 chno); | ||
274 | void rsi_inform_bss_status(struct rsi_common *common, u8 status, | ||
275 | const u8 *bssid, u8 qos_enable, u16 aid); | ||
276 | void rsi_indicate_pkt_to_os(struct rsi_common *common, struct sk_buff *skb); | ||
277 | int rsi_mac80211_attach(struct rsi_common *common); | ||
278 | void rsi_indicate_tx_status(struct rsi_hw *common, struct sk_buff *skb, | ||
279 | int status); | ||
280 | bool rsi_is_cipher_wep(struct rsi_common *common); | ||
281 | void rsi_core_qos_processor(struct rsi_common *common); | ||
282 | void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb); | ||
283 | int rsi_send_mgmt_pkt(struct rsi_common *common, struct sk_buff *skb); | ||
284 | int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb); | ||
285 | #endif | ||
diff --git a/drivers/net/wireless/rsi/rsi_sdio.h b/drivers/net/wireless/rsi/rsi_sdio.h new file mode 100644 index 000000000000..df4b5e20e05f --- /dev/null +++ b/drivers/net/wireless/rsi/rsi_sdio.h | |||
@@ -0,0 +1,129 @@ | |||
1 | /** | ||
2 | * @section LICENSE | ||
3 | * Copyright (c) 2014 Redpine Signals Inc. | ||
4 | * | ||
5 | * Permission to use, copy, modify, and/or distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #ifndef __RSI_SDIO_INTF__ | ||
20 | #define __RSI_SDIO_INTF__ | ||
21 | |||
22 | #include <linux/mmc/card.h> | ||
23 | #include <linux/mmc/mmc.h> | ||
24 | #include <linux/mmc/host.h> | ||
25 | #include <linux/mmc/sdio_func.h> | ||
26 | #include <linux/mmc/sdio.h> | ||
27 | #include <linux/mmc/sd.h> | ||
28 | #include <linux/mmc/sdio_ids.h> | ||
29 | #include "rsi_main.h" | ||
30 | |||
31 | enum sdio_interrupt_type { | ||
32 | BUFFER_FULL = 0x0, | ||
33 | BUFFER_AVAILABLE = 0x1, | ||
34 | FIRMWARE_ASSERT_IND = 0x3, | ||
35 | MSDU_PACKET_PENDING = 0x4, | ||
36 | UNKNOWN_INT = 0XE | ||
37 | }; | ||
38 | |||
39 | /* Buffer status register related info */ | ||
40 | #define PKT_BUFF_SEMI_FULL 0 | ||
41 | #define PKT_BUFF_FULL 1 | ||
42 | #define PKT_MGMT_BUFF_FULL 2 | ||
43 | #define MSDU_PKT_PENDING 3 | ||
44 | /* Interrupt Bit Related Macros */ | ||
45 | #define PKT_BUFF_AVAILABLE 0 | ||
46 | #define FW_ASSERT_IND 2 | ||
47 | |||
48 | #define RSI_DEVICE_BUFFER_STATUS_REGISTER 0xf3 | ||
49 | #define RSI_FN1_INT_REGISTER 0xf9 | ||
50 | #define RSI_SD_REQUEST_MASTER 0x10000 | ||
51 | |||
52 | /* FOR SD CARD ONLY */ | ||
53 | #define SDIO_RX_NUM_BLOCKS_REG 0x000F1 | ||
54 | #define SDIO_FW_STATUS_REG 0x000F2 | ||
55 | #define SDIO_NXT_RD_DELAY2 0x000F5 | ||
56 | #define SDIO_MASTER_ACCESS_MSBYTE 0x000FA | ||
57 | #define SDIO_MASTER_ACCESS_LSBYTE 0x000FB | ||
58 | #define SDIO_READ_START_LVL 0x000FC | ||
59 | #define SDIO_READ_FIFO_CTL 0x000FD | ||
60 | #define SDIO_WRITE_FIFO_CTL 0x000FE | ||
61 | #define SDIO_FUN1_INTR_CLR_REG 0x0008 | ||
62 | #define SDIO_REG_HIGH_SPEED 0x0013 | ||
63 | |||
64 | #define RSI_GET_SDIO_INTERRUPT_TYPE(_I, TYPE) \ | ||
65 | { \ | ||
66 | TYPE = \ | ||
67 | (_I & (1 << PKT_BUFF_AVAILABLE)) ? \ | ||
68 | BUFFER_AVAILABLE : \ | ||
69 | (_I & (1 << MSDU_PKT_PENDING)) ? \ | ||
70 | MSDU_PACKET_PENDING : \ | ||
71 | (_I & (1 << FW_ASSERT_IND)) ? \ | ||
72 | FIRMWARE_ASSERT_IND : UNKNOWN_INT; \ | ||
73 | } | ||
74 | |||
75 | /* common registers in SDIO function1 */ | ||
76 | #define TA_SOFT_RESET_REG 0x0004 | ||
77 | #define TA_TH0_PC_REG 0x0400 | ||
78 | #define TA_HOLD_THREAD_REG 0x0844 | ||
79 | #define TA_RELEASE_THREAD_REG 0x0848 | ||
80 | |||
81 | #define TA_SOFT_RST_CLR 0 | ||
82 | #define TA_SOFT_RST_SET BIT(0) | ||
83 | #define TA_PC_ZERO 0 | ||
84 | #define TA_HOLD_THREAD_VALUE cpu_to_le32(0xF) | ||
85 | #define TA_RELEASE_THREAD_VALUE cpu_to_le32(0xF) | ||
86 | #define TA_BASE_ADDR 0x2200 | ||
87 | #define MISC_CFG_BASE_ADDR 0x4150 | ||
88 | |||
89 | struct receive_info { | ||
90 | bool buffer_full; | ||
91 | bool semi_buffer_full; | ||
92 | bool mgmt_buffer_full; | ||
93 | u32 mgmt_buf_full_counter; | ||
94 | u32 buf_semi_full_counter; | ||
95 | u8 watch_bufferfull_count; | ||
96 | u32 sdio_intr_status_zero; | ||
97 | u32 sdio_int_counter; | ||
98 | u32 total_sdio_msdu_pending_intr; | ||
99 | u32 total_sdio_unknown_intr; | ||
100 | u32 buf_full_counter; | ||
101 | u32 buf_avilable_counter; | ||
102 | }; | ||
103 | |||
104 | struct rsi_91x_sdiodev { | ||
105 | struct sdio_func *pfunction; | ||
106 | struct task_struct *in_sdio_litefi_irq; | ||
107 | struct receive_info rx_info; | ||
108 | u32 next_read_delay; | ||
109 | u32 sdio_high_speed_enable; | ||
110 | u8 sdio_clock_speed; | ||
111 | u32 cardcapability; | ||
112 | u8 prev_desc[16]; | ||
113 | u32 tx_blk_size; | ||
114 | u8 write_fail; | ||
115 | }; | ||
116 | |||
117 | void rsi_interrupt_handler(struct rsi_hw *adapter); | ||
118 | int rsi_init_sdio_slave_regs(struct rsi_hw *adapter); | ||
119 | int rsi_sdio_device_init(struct rsi_common *common); | ||
120 | int rsi_sdio_read_register(struct rsi_hw *adapter, u32 addr, u8 *data); | ||
121 | int rsi_sdio_host_intf_read_pkt(struct rsi_hw *adapter, u8 *pkt, u32 length); | ||
122 | int rsi_sdio_write_register(struct rsi_hw *adapter, u8 function, | ||
123 | u32 addr, u8 *data); | ||
124 | int rsi_sdio_write_register_multiple(struct rsi_hw *adapter, u32 addr, | ||
125 | u8 *data, u32 count); | ||
126 | void rsi_sdio_ack_intr(struct rsi_hw *adapter, u8 int_bit); | ||
127 | int rsi_sdio_determine_event_timeout(struct rsi_hw *adapter); | ||
128 | int rsi_sdio_read_buffer_status_register(struct rsi_hw *adapter, u8 q_num); | ||
129 | #endif | ||
diff --git a/drivers/net/wireless/rsi/rsi_usb.h b/drivers/net/wireless/rsi/rsi_usb.h new file mode 100644 index 000000000000..ebea0c411ead --- /dev/null +++ b/drivers/net/wireless/rsi/rsi_usb.h | |||
@@ -0,0 +1,68 @@ | |||
1 | /** | ||
2 | * @section LICENSE | ||
3 | * Copyright (c) 2014 Redpine Signals Inc. | ||
4 | * | ||
5 | * Permission to use, copy, modify, and/or distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | #ifndef __RSI_USB_INTF__ | ||
19 | #define __RSI_USB_INTF__ | ||
20 | |||
21 | #include <linux/usb.h> | ||
22 | #include "rsi_main.h" | ||
23 | #include "rsi_common.h" | ||
24 | |||
25 | #define USB_INTERNAL_REG_1 0x25000 | ||
26 | #define RSI_USB_READY_MAGIC_NUM 0xab | ||
27 | #define FW_STATUS_REG 0x41050012 | ||
28 | |||
29 | #define USB_VENDOR_REGISTER_READ 0x15 | ||
30 | #define USB_VENDOR_REGISTER_WRITE 0x16 | ||
31 | #define RSI_USB_TX_HEAD_ROOM 128 | ||
32 | |||
33 | #define MAX_RX_URBS 1 | ||
34 | #define MAX_BULK_EP 8 | ||
35 | #define MGMT_EP 1 | ||
36 | #define DATA_EP 2 | ||
37 | |||
38 | struct rsi_91x_usbdev { | ||
39 | struct rsi_thread rx_thread; | ||
40 | u8 endpoint; | ||
41 | struct usb_device *usbdev; | ||
42 | struct usb_interface *pfunction; | ||
43 | struct urb *rx_usb_urb[MAX_RX_URBS]; | ||
44 | u8 *tx_buffer; | ||
45 | __le16 bulkin_size; | ||
46 | u8 bulkin_endpoint_addr; | ||
47 | __le16 bulkout_size[MAX_BULK_EP]; | ||
48 | u8 bulkout_endpoint_addr[MAX_BULK_EP]; | ||
49 | u32 tx_blk_size; | ||
50 | u8 write_fail; | ||
51 | }; | ||
52 | |||
53 | static inline int rsi_usb_check_queue_status(struct rsi_hw *adapter, u8 q_num) | ||
54 | { | ||
55 | /* In USB, there isn't any need to check the queue status */ | ||
56 | return QUEUE_NOT_FULL; | ||
57 | } | ||
58 | |||
59 | static inline int rsi_usb_event_timeout(struct rsi_hw *adapter) | ||
60 | { | ||
61 | return EVENT_WAIT_FOREVER; | ||
62 | } | ||
63 | |||
64 | int rsi_usb_device_init(struct rsi_common *common); | ||
65 | int rsi_usb_write_register_multiple(struct rsi_hw *adapter, u32 addr, | ||
66 | u8 *data, u32 count); | ||
67 | void rsi_usb_rx_thread(struct rsi_common *common); | ||
68 | #endif | ||
diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/rtl818x/rtl8180/dev.c index 959e699702e8..0b405b8c8d70 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180/dev.c | |||
@@ -148,7 +148,8 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev) | |||
148 | rx_status.antenna = (flags2 >> 15) & 1; | 148 | rx_status.antenna = (flags2 >> 15) & 1; |
149 | rx_status.rate_idx = (flags >> 20) & 0xF; | 149 | rx_status.rate_idx = (flags >> 20) & 0xF; |
150 | agc = (flags2 >> 17) & 0x7F; | 150 | agc = (flags2 >> 17) & 0x7F; |
151 | if (priv->r8185) { | 151 | |
152 | if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8185) { | ||
152 | if (rx_status.rate_idx > 3) | 153 | if (rx_status.rate_idx > 3) |
153 | signal = 90 - clamp_t(u8, agc, 25, 90); | 154 | signal = 90 - clamp_t(u8, agc, 25, 90); |
154 | else | 155 | else |
@@ -288,7 +289,7 @@ static void rtl8180_tx(struct ieee80211_hw *dev, | |||
288 | (ieee80211_get_tx_rate(dev, info)->hw_value << 24) | | 289 | (ieee80211_get_tx_rate(dev, info)->hw_value << 24) | |
289 | skb->len; | 290 | skb->len; |
290 | 291 | ||
291 | if (priv->r8185) | 292 | if (priv->chip_family != RTL818X_CHIP_FAMILY_RTL8180) |
292 | tx_flags |= RTL818X_TX_DESC_FLAG_DMA | | 293 | tx_flags |= RTL818X_TX_DESC_FLAG_DMA | |
293 | RTL818X_TX_DESC_FLAG_NO_ENC; | 294 | RTL818X_TX_DESC_FLAG_NO_ENC; |
294 | 295 | ||
@@ -305,7 +306,7 @@ static void rtl8180_tx(struct ieee80211_hw *dev, | |||
305 | rts_duration = ieee80211_rts_duration(dev, priv->vif, skb->len, | 306 | rts_duration = ieee80211_rts_duration(dev, priv->vif, skb->len, |
306 | info); | 307 | info); |
307 | 308 | ||
308 | if (!priv->r8185) { | 309 | if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8180) { |
309 | unsigned int remainder; | 310 | unsigned int remainder; |
310 | 311 | ||
311 | plcp_len = DIV_ROUND_UP(16 * (skb->len + 4), | 312 | plcp_len = DIV_ROUND_UP(16 * (skb->len + 4), |
@@ -370,6 +371,36 @@ void rtl8180_set_anaparam(struct rtl8180_priv *priv, u32 anaparam) | |||
370 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); | 371 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); |
371 | } | 372 | } |
372 | 373 | ||
374 | static void rtl8180_conf_basic_rates(struct ieee80211_hw *dev, | ||
375 | u32 rates_mask) | ||
376 | { | ||
377 | struct rtl8180_priv *priv = dev->priv; | ||
378 | |||
379 | u8 max, min; | ||
380 | u16 reg; | ||
381 | |||
382 | max = fls(rates_mask) - 1; | ||
383 | min = ffs(rates_mask) - 1; | ||
384 | |||
385 | switch (priv->chip_family) { | ||
386 | |||
387 | case RTL818X_CHIP_FAMILY_RTL8180: | ||
388 | /* in 8180 this is NOT a BITMAP */ | ||
389 | reg = rtl818x_ioread16(priv, &priv->map->BRSR); | ||
390 | reg &= ~3; | ||
391 | reg |= max; | ||
392 | rtl818x_iowrite16(priv, &priv->map->BRSR, reg); | ||
393 | |||
394 | break; | ||
395 | |||
396 | case RTL818X_CHIP_FAMILY_RTL8185: | ||
397 | /* in 8185 this is a BITMAP */ | ||
398 | rtl818x_iowrite16(priv, &priv->map->BRSR, rates_mask); | ||
399 | rtl818x_iowrite8(priv, &priv->map->RESP_RATE, (max << 4) | min); | ||
400 | break; | ||
401 | } | ||
402 | } | ||
403 | |||
373 | static int rtl8180_init_hw(struct ieee80211_hw *dev) | 404 | static int rtl8180_init_hw(struct ieee80211_hw *dev) |
374 | { | 405 | { |
375 | struct rtl8180_priv *priv = dev->priv; | 406 | struct rtl8180_priv *priv = dev->priv; |
@@ -412,7 +443,7 @@ static int rtl8180_init_hw(struct ieee80211_hw *dev) | |||
412 | 443 | ||
413 | rtl818x_iowrite8(priv, &priv->map->MSR, 0); | 444 | rtl818x_iowrite8(priv, &priv->map->MSR, 0); |
414 | 445 | ||
415 | if (!priv->r8185) | 446 | if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8180) |
416 | rtl8180_set_anaparam(priv, priv->anaparam); | 447 | rtl8180_set_anaparam(priv, priv->anaparam); |
417 | 448 | ||
418 | rtl818x_iowrite32(priv, &priv->map->RDSAR, priv->rx_ring_dma); | 449 | rtl818x_iowrite32(priv, &priv->map->RDSAR, priv->rx_ring_dma); |
@@ -425,7 +456,7 @@ static int rtl8180_init_hw(struct ieee80211_hw *dev) | |||
425 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); | 456 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); |
426 | reg = rtl818x_ioread8(priv, &priv->map->CONFIG2); | 457 | reg = rtl818x_ioread8(priv, &priv->map->CONFIG2); |
427 | rtl818x_iowrite8(priv, &priv->map->CONFIG2, reg & ~(1 << 3)); | 458 | rtl818x_iowrite8(priv, &priv->map->CONFIG2, reg & ~(1 << 3)); |
428 | if (priv->r8185) { | 459 | if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8185) { |
429 | reg = rtl818x_ioread8(priv, &priv->map->CONFIG2); | 460 | reg = rtl818x_ioread8(priv, &priv->map->CONFIG2); |
430 | rtl818x_iowrite8(priv, &priv->map->CONFIG2, reg | (1 << 4)); | 461 | rtl818x_iowrite8(priv, &priv->map->CONFIG2, reg | (1 << 4)); |
431 | } | 462 | } |
@@ -437,12 +468,9 @@ static int rtl8180_init_hw(struct ieee80211_hw *dev) | |||
437 | 468 | ||
438 | rtl818x_iowrite32(priv, &priv->map->INT_TIMEOUT, 0); | 469 | rtl818x_iowrite32(priv, &priv->map->INT_TIMEOUT, 0); |
439 | 470 | ||
440 | if (priv->r8185) { | 471 | if (priv->chip_family != RTL818X_CHIP_FAMILY_RTL8180) { |
441 | rtl818x_iowrite8(priv, &priv->map->WPA_CONF, 0); | 472 | rtl818x_iowrite8(priv, &priv->map->WPA_CONF, 0); |
442 | rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, 0x81); | 473 | rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, 0x81); |
443 | rtl818x_iowrite8(priv, &priv->map->RESP_RATE, (8 << 4) | 0); | ||
444 | |||
445 | rtl818x_iowrite16(priv, &priv->map->BRSR, 0x01F3); | ||
446 | 474 | ||
447 | /* TODO: set ClkRun enable? necessary? */ | 475 | /* TODO: set ClkRun enable? necessary? */ |
448 | reg = rtl818x_ioread8(priv, &priv->map->GP_ENABLE); | 476 | reg = rtl818x_ioread8(priv, &priv->map->GP_ENABLE); |
@@ -452,7 +480,6 @@ static int rtl8180_init_hw(struct ieee80211_hw *dev) | |||
452 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | (1 << 2)); | 480 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | (1 << 2)); |
453 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); | 481 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); |
454 | } else { | 482 | } else { |
455 | rtl818x_iowrite16(priv, &priv->map->BRSR, 0x1); | ||
456 | rtl818x_iowrite8(priv, &priv->map->SECURITY, 0); | 483 | rtl818x_iowrite8(priv, &priv->map->SECURITY, 0); |
457 | 484 | ||
458 | rtl818x_iowrite8(priv, &priv->map->PHY_DELAY, 0x6); | 485 | rtl818x_iowrite8(priv, &priv->map->PHY_DELAY, 0x6); |
@@ -460,8 +487,18 @@ static int rtl8180_init_hw(struct ieee80211_hw *dev) | |||
460 | } | 487 | } |
461 | 488 | ||
462 | priv->rf->init(dev); | 489 | priv->rf->init(dev); |
463 | if (priv->r8185) | 490 | |
464 | rtl818x_iowrite16(priv, &priv->map->BRSR, 0x01F3); | 491 | /* default basic rates are 1,2 Mbps for rtl8180. 1,2,6,9,12,18,24 Mbps |
492 | * otherwise. bitmask 0x3 and 0x01f3 respectively. | ||
493 | * NOTE: currenty rtl8225 RF code changes basic rates, so we need to do | ||
494 | * this after rf init. | ||
495 | * TODO: try to find out whether RF code really needs to do this.. | ||
496 | */ | ||
497 | if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8180) | ||
498 | rtl8180_conf_basic_rates(dev, 0x3); | ||
499 | else | ||
500 | rtl8180_conf_basic_rates(dev, 0x1f3); | ||
501 | |||
465 | return 0; | 502 | return 0; |
466 | } | 503 | } |
467 | 504 | ||
@@ -624,7 +661,7 @@ static int rtl8180_start(struct ieee80211_hw *dev) | |||
624 | RTL818X_RX_CONF_BROADCAST | | 661 | RTL818X_RX_CONF_BROADCAST | |
625 | RTL818X_RX_CONF_NICMAC; | 662 | RTL818X_RX_CONF_NICMAC; |
626 | 663 | ||
627 | if (priv->r8185) | 664 | if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8185) |
628 | reg |= RTL818X_RX_CONF_CSDM1 | RTL818X_RX_CONF_CSDM2; | 665 | reg |= RTL818X_RX_CONF_CSDM1 | RTL818X_RX_CONF_CSDM2; |
629 | else { | 666 | else { |
630 | reg |= (priv->rfparam & RF_PARAM_CARRIERSENSE1) | 667 | reg |= (priv->rfparam & RF_PARAM_CARRIERSENSE1) |
@@ -636,7 +673,7 @@ static int rtl8180_start(struct ieee80211_hw *dev) | |||
636 | priv->rx_conf = reg; | 673 | priv->rx_conf = reg; |
637 | rtl818x_iowrite32(priv, &priv->map->RX_CONF, reg); | 674 | rtl818x_iowrite32(priv, &priv->map->RX_CONF, reg); |
638 | 675 | ||
639 | if (priv->r8185) { | 676 | if (priv->chip_family != RTL818X_CHIP_FAMILY_RTL8180) { |
640 | reg = rtl818x_ioread8(priv, &priv->map->CW_CONF); | 677 | reg = rtl818x_ioread8(priv, &priv->map->CW_CONF); |
641 | 678 | ||
642 | /* CW is not on per-packet basis. | 679 | /* CW is not on per-packet basis. |
@@ -668,7 +705,9 @@ static int rtl8180_start(struct ieee80211_hw *dev) | |||
668 | reg |= (6 << 21 /* MAX TX DMA */) | | 705 | reg |= (6 << 21 /* MAX TX DMA */) | |
669 | RTL818X_TX_CONF_NO_ICV; | 706 | RTL818X_TX_CONF_NO_ICV; |
670 | 707 | ||
671 | if (priv->r8185) | 708 | |
709 | |||
710 | if (priv->chip_family != RTL818X_CHIP_FAMILY_RTL8180) | ||
672 | reg &= ~RTL818X_TX_CONF_PROBE_DTS; | 711 | reg &= ~RTL818X_TX_CONF_PROBE_DTS; |
673 | else | 712 | else |
674 | reg &= ~RTL818X_TX_CONF_HW_SEQNUM; | 713 | reg &= ~RTL818X_TX_CONF_HW_SEQNUM; |
@@ -827,6 +866,72 @@ static int rtl8180_config(struct ieee80211_hw *dev, u32 changed) | |||
827 | return 0; | 866 | return 0; |
828 | } | 867 | } |
829 | 868 | ||
869 | static int rtl8180_conf_tx(struct ieee80211_hw *dev, | ||
870 | struct ieee80211_vif *vif, u16 queue, | ||
871 | const struct ieee80211_tx_queue_params *params) | ||
872 | { | ||
873 | struct rtl8180_priv *priv = dev->priv; | ||
874 | u8 cw_min, cw_max; | ||
875 | |||
876 | /* nothing to do ? */ | ||
877 | if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8180) | ||
878 | return 0; | ||
879 | |||
880 | cw_min = fls(params->cw_min); | ||
881 | cw_max = fls(params->cw_max); | ||
882 | |||
883 | rtl818x_iowrite8(priv, &priv->map->CW_VAL, (cw_max << 4) | cw_min); | ||
884 | |||
885 | return 0; | ||
886 | } | ||
887 | |||
888 | static void rtl8180_conf_erp(struct ieee80211_hw *dev, | ||
889 | struct ieee80211_bss_conf *info) | ||
890 | { | ||
891 | struct rtl8180_priv *priv = dev->priv; | ||
892 | u8 sifs, difs; | ||
893 | int eifs; | ||
894 | u8 hw_eifs; | ||
895 | |||
896 | /* TODO: should we do something ? */ | ||
897 | if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8180) | ||
898 | return; | ||
899 | |||
900 | /* I _hope_ this means 10uS for the HW. | ||
901 | * In reference code it is 0x22 for | ||
902 | * both rtl8187L and rtl8187SE | ||
903 | */ | ||
904 | sifs = 0x22; | ||
905 | |||
906 | if (info->use_short_slot) | ||
907 | priv->slot_time = 9; | ||
908 | else | ||
909 | priv->slot_time = 20; | ||
910 | |||
911 | /* 10 is SIFS time in uS */ | ||
912 | difs = 10 + 2 * priv->slot_time; | ||
913 | eifs = 10 + difs + priv->ack_time; | ||
914 | |||
915 | /* HW should use 4uS units for EIFS (I'm sure for rtl8185)*/ | ||
916 | hw_eifs = DIV_ROUND_UP(eifs, 4); | ||
917 | |||
918 | |||
919 | rtl818x_iowrite8(priv, &priv->map->SLOT, priv->slot_time); | ||
920 | rtl818x_iowrite8(priv, &priv->map->SIFS, sifs); | ||
921 | rtl818x_iowrite8(priv, &priv->map->DIFS, difs); | ||
922 | |||
923 | /* from reference code. set ack timeout reg = eifs reg */ | ||
924 | rtl818x_iowrite8(priv, &priv->map->CARRIER_SENSE_COUNTER, hw_eifs); | ||
925 | |||
926 | /* rtl8187/rtl8185 HW bug. After EIFS is elapsed, | ||
927 | * the HW still wait for DIFS. | ||
928 | * HW uses 4uS units for EIFS. | ||
929 | */ | ||
930 | hw_eifs = DIV_ROUND_UP(eifs - difs, 4); | ||
931 | |||
932 | rtl818x_iowrite8(priv, &priv->map->EIFS, hw_eifs); | ||
933 | } | ||
934 | |||
830 | static void rtl8180_bss_info_changed(struct ieee80211_hw *dev, | 935 | static void rtl8180_bss_info_changed(struct ieee80211_hw *dev, |
831 | struct ieee80211_vif *vif, | 936 | struct ieee80211_vif *vif, |
832 | struct ieee80211_bss_conf *info, | 937 | struct ieee80211_bss_conf *info, |
@@ -854,8 +959,23 @@ static void rtl8180_bss_info_changed(struct ieee80211_hw *dev, | |||
854 | rtl818x_iowrite8(priv, &priv->map->MSR, reg); | 959 | rtl818x_iowrite8(priv, &priv->map->MSR, reg); |
855 | } | 960 | } |
856 | 961 | ||
857 | if (changed & BSS_CHANGED_ERP_SLOT && priv->rf->conf_erp) | 962 | if (changed & BSS_CHANGED_BASIC_RATES) |
858 | priv->rf->conf_erp(dev, info); | 963 | rtl8180_conf_basic_rates(dev, info->basic_rates); |
964 | |||
965 | if (changed & (BSS_CHANGED_ERP_SLOT | BSS_CHANGED_ERP_PREAMBLE)) { | ||
966 | |||
967 | /* when preamble changes, acktime duration changes, and erp must | ||
968 | * be recalculated. ACK time is calculated at lowest rate. | ||
969 | * Since mac80211 include SIFS time we remove it (-10) | ||
970 | */ | ||
971 | priv->ack_time = | ||
972 | le16_to_cpu(ieee80211_generic_frame_duration(dev, | ||
973 | priv->vif, | ||
974 | IEEE80211_BAND_2GHZ, 10, | ||
975 | &priv->rates[0])) - 10; | ||
976 | |||
977 | rtl8180_conf_erp(dev, info); | ||
978 | } | ||
859 | 979 | ||
860 | if (changed & BSS_CHANGED_BEACON_ENABLED) | 980 | if (changed & BSS_CHANGED_BEACON_ENABLED) |
861 | vif_priv->enable_beacon = info->enable_beacon; | 981 | vif_priv->enable_beacon = info->enable_beacon; |
@@ -913,6 +1033,7 @@ static const struct ieee80211_ops rtl8180_ops = { | |||
913 | .remove_interface = rtl8180_remove_interface, | 1033 | .remove_interface = rtl8180_remove_interface, |
914 | .config = rtl8180_config, | 1034 | .config = rtl8180_config, |
915 | .bss_info_changed = rtl8180_bss_info_changed, | 1035 | .bss_info_changed = rtl8180_bss_info_changed, |
1036 | .conf_tx = rtl8180_conf_tx, | ||
916 | .prepare_multicast = rtl8180_prepare_multicast, | 1037 | .prepare_multicast = rtl8180_prepare_multicast, |
917 | .configure_filter = rtl8180_configure_filter, | 1038 | .configure_filter = rtl8180_configure_filter, |
918 | .get_tsf = rtl8180_get_tsf, | 1039 | .get_tsf = rtl8180_get_tsf, |
@@ -920,8 +1041,7 @@ static const struct ieee80211_ops rtl8180_ops = { | |||
920 | 1041 | ||
921 | static void rtl8180_eeprom_register_read(struct eeprom_93cx6 *eeprom) | 1042 | static void rtl8180_eeprom_register_read(struct eeprom_93cx6 *eeprom) |
922 | { | 1043 | { |
923 | struct ieee80211_hw *dev = eeprom->data; | 1044 | struct rtl8180_priv *priv = eeprom->data; |
924 | struct rtl8180_priv *priv = dev->priv; | ||
925 | u8 reg = rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); | 1045 | u8 reg = rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); |
926 | 1046 | ||
927 | eeprom->reg_data_in = reg & RTL818X_EEPROM_CMD_WRITE; | 1047 | eeprom->reg_data_in = reg & RTL818X_EEPROM_CMD_WRITE; |
@@ -932,8 +1052,7 @@ static void rtl8180_eeprom_register_read(struct eeprom_93cx6 *eeprom) | |||
932 | 1052 | ||
933 | static void rtl8180_eeprom_register_write(struct eeprom_93cx6 *eeprom) | 1053 | static void rtl8180_eeprom_register_write(struct eeprom_93cx6 *eeprom) |
934 | { | 1054 | { |
935 | struct ieee80211_hw *dev = eeprom->data; | 1055 | struct rtl8180_priv *priv = eeprom->data; |
936 | struct rtl8180_priv *priv = dev->priv; | ||
937 | u8 reg = 2 << 6; | 1056 | u8 reg = 2 << 6; |
938 | 1057 | ||
939 | if (eeprom->reg_data_in) | 1058 | if (eeprom->reg_data_in) |
@@ -950,6 +1069,67 @@ static void rtl8180_eeprom_register_write(struct eeprom_93cx6 *eeprom) | |||
950 | udelay(10); | 1069 | udelay(10); |
951 | } | 1070 | } |
952 | 1071 | ||
1072 | static void rtl8180_eeprom_read(struct rtl8180_priv *priv) | ||
1073 | { | ||
1074 | struct eeprom_93cx6 eeprom; | ||
1075 | int eeprom_cck_table_adr; | ||
1076 | u16 eeprom_val; | ||
1077 | int i; | ||
1078 | |||
1079 | eeprom.data = priv; | ||
1080 | eeprom.register_read = rtl8180_eeprom_register_read; | ||
1081 | eeprom.register_write = rtl8180_eeprom_register_write; | ||
1082 | if (rtl818x_ioread32(priv, &priv->map->RX_CONF) & (1 << 6)) | ||
1083 | eeprom.width = PCI_EEPROM_WIDTH_93C66; | ||
1084 | else | ||
1085 | eeprom.width = PCI_EEPROM_WIDTH_93C46; | ||
1086 | |||
1087 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, | ||
1088 | RTL818X_EEPROM_CMD_PROGRAM); | ||
1089 | rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); | ||
1090 | udelay(10); | ||
1091 | |||
1092 | eeprom_93cx6_read(&eeprom, 0x06, &eeprom_val); | ||
1093 | eeprom_val &= 0xFF; | ||
1094 | priv->rf_type = eeprom_val; | ||
1095 | |||
1096 | eeprom_93cx6_read(&eeprom, 0x17, &eeprom_val); | ||
1097 | priv->csthreshold = eeprom_val >> 8; | ||
1098 | |||
1099 | eeprom_93cx6_multiread(&eeprom, 0x7, (__le16 *)priv->mac_addr, 3); | ||
1100 | |||
1101 | eeprom_cck_table_adr = 0x10; | ||
1102 | |||
1103 | /* CCK TX power */ | ||
1104 | for (i = 0; i < 14; i += 2) { | ||
1105 | u16 txpwr; | ||
1106 | eeprom_93cx6_read(&eeprom, eeprom_cck_table_adr + (i >> 1), | ||
1107 | &txpwr); | ||
1108 | priv->channels[i].hw_value = txpwr & 0xFF; | ||
1109 | priv->channels[i + 1].hw_value = txpwr >> 8; | ||
1110 | } | ||
1111 | |||
1112 | /* OFDM TX power */ | ||
1113 | if (priv->chip_family != RTL818X_CHIP_FAMILY_RTL8180) { | ||
1114 | for (i = 0; i < 14; i += 2) { | ||
1115 | u16 txpwr; | ||
1116 | eeprom_93cx6_read(&eeprom, 0x20 + (i >> 1), &txpwr); | ||
1117 | priv->channels[i].hw_value |= (txpwr & 0xFF) << 8; | ||
1118 | priv->channels[i + 1].hw_value |= txpwr & 0xFF00; | ||
1119 | } | ||
1120 | } | ||
1121 | |||
1122 | if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8180) { | ||
1123 | __le32 anaparam; | ||
1124 | eeprom_93cx6_multiread(&eeprom, 0xD, (__le16 *)&anaparam, 2); | ||
1125 | priv->anaparam = le32_to_cpu(anaparam); | ||
1126 | eeprom_93cx6_read(&eeprom, 0x19, &priv->rfparam); | ||
1127 | } | ||
1128 | |||
1129 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, | ||
1130 | RTL818X_EEPROM_CMD_NORMAL); | ||
1131 | } | ||
1132 | |||
953 | static int rtl8180_probe(struct pci_dev *pdev, | 1133 | static int rtl8180_probe(struct pci_dev *pdev, |
954 | const struct pci_device_id *id) | 1134 | const struct pci_device_id *id) |
955 | { | 1135 | { |
@@ -957,12 +1137,9 @@ static int rtl8180_probe(struct pci_dev *pdev, | |||
957 | struct rtl8180_priv *priv; | 1137 | struct rtl8180_priv *priv; |
958 | unsigned long mem_addr, mem_len; | 1138 | unsigned long mem_addr, mem_len; |
959 | unsigned int io_addr, io_len; | 1139 | unsigned int io_addr, io_len; |
960 | int err, i; | 1140 | int err; |
961 | struct eeprom_93cx6 eeprom; | ||
962 | const char *chip_name, *rf_name = NULL; | 1141 | const char *chip_name, *rf_name = NULL; |
963 | u32 reg; | 1142 | u32 reg; |
964 | u16 eeprom_val; | ||
965 | u8 mac_addr[ETH_ALEN]; | ||
966 | 1143 | ||
967 | err = pci_enable_device(pdev); | 1144 | err = pci_enable_device(pdev); |
968 | if (err) { | 1145 | if (err) { |
@@ -1052,15 +1229,22 @@ static int rtl8180_probe(struct pci_dev *pdev, | |||
1052 | switch (reg) { | 1229 | switch (reg) { |
1053 | case RTL818X_TX_CONF_R8180_ABCD: | 1230 | case RTL818X_TX_CONF_R8180_ABCD: |
1054 | chip_name = "RTL8180"; | 1231 | chip_name = "RTL8180"; |
1232 | priv->chip_family = RTL818X_CHIP_FAMILY_RTL8180; | ||
1055 | break; | 1233 | break; |
1234 | |||
1056 | case RTL818X_TX_CONF_R8180_F: | 1235 | case RTL818X_TX_CONF_R8180_F: |
1057 | chip_name = "RTL8180vF"; | 1236 | chip_name = "RTL8180vF"; |
1237 | priv->chip_family = RTL818X_CHIP_FAMILY_RTL8180; | ||
1058 | break; | 1238 | break; |
1239 | |||
1059 | case RTL818X_TX_CONF_R8185_ABC: | 1240 | case RTL818X_TX_CONF_R8185_ABC: |
1060 | chip_name = "RTL8185"; | 1241 | chip_name = "RTL8185"; |
1242 | priv->chip_family = RTL818X_CHIP_FAMILY_RTL8185; | ||
1061 | break; | 1243 | break; |
1244 | |||
1062 | case RTL818X_TX_CONF_R8185_D: | 1245 | case RTL818X_TX_CONF_R8185_D: |
1063 | chip_name = "RTL8185vD"; | 1246 | chip_name = "RTL8185vD"; |
1247 | priv->chip_family = RTL818X_CHIP_FAMILY_RTL8185; | ||
1064 | break; | 1248 | break; |
1065 | default: | 1249 | default: |
1066 | printk(KERN_ERR "%s (rtl8180): Unknown chip! (0x%x)\n", | 1250 | printk(KERN_ERR "%s (rtl8180): Unknown chip! (0x%x)\n", |
@@ -1068,27 +1252,14 @@ static int rtl8180_probe(struct pci_dev *pdev, | |||
1068 | goto err_iounmap; | 1252 | goto err_iounmap; |
1069 | } | 1253 | } |
1070 | 1254 | ||
1071 | priv->r8185 = reg & RTL818X_TX_CONF_R8185_ABC; | 1255 | if (priv->chip_family != RTL818X_CHIP_FAMILY_RTL8180) { |
1072 | if (priv->r8185) { | ||
1073 | priv->band.n_bitrates = ARRAY_SIZE(rtl818x_rates); | 1256 | priv->band.n_bitrates = ARRAY_SIZE(rtl818x_rates); |
1074 | pci_try_set_mwi(pdev); | 1257 | pci_try_set_mwi(pdev); |
1075 | } | 1258 | } |
1076 | 1259 | ||
1077 | eeprom.data = dev; | 1260 | rtl8180_eeprom_read(priv); |
1078 | eeprom.register_read = rtl8180_eeprom_register_read; | ||
1079 | eeprom.register_write = rtl8180_eeprom_register_write; | ||
1080 | if (rtl818x_ioread32(priv, &priv->map->RX_CONF) & (1 << 6)) | ||
1081 | eeprom.width = PCI_EEPROM_WIDTH_93C66; | ||
1082 | else | ||
1083 | eeprom.width = PCI_EEPROM_WIDTH_93C46; | ||
1084 | |||
1085 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_PROGRAM); | ||
1086 | rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); | ||
1087 | udelay(10); | ||
1088 | 1261 | ||
1089 | eeprom_93cx6_read(&eeprom, 0x06, &eeprom_val); | 1262 | switch (priv->rf_type) { |
1090 | eeprom_val &= 0xFF; | ||
1091 | switch (eeprom_val) { | ||
1092 | case 1: rf_name = "Intersil"; | 1263 | case 1: rf_name = "Intersil"; |
1093 | break; | 1264 | break; |
1094 | case 2: rf_name = "RFMD"; | 1265 | case 2: rf_name = "RFMD"; |
@@ -1106,7 +1277,7 @@ static int rtl8180_probe(struct pci_dev *pdev, | |||
1106 | break; | 1277 | break; |
1107 | default: | 1278 | default: |
1108 | printk(KERN_ERR "%s (rtl8180): Unknown RF! (0x%x)\n", | 1279 | printk(KERN_ERR "%s (rtl8180): Unknown RF! (0x%x)\n", |
1109 | pci_name(pdev), eeprom_val); | 1280 | pci_name(pdev), priv->rf_type); |
1110 | goto err_iounmap; | 1281 | goto err_iounmap; |
1111 | } | 1282 | } |
1112 | 1283 | ||
@@ -1116,42 +1287,12 @@ static int rtl8180_probe(struct pci_dev *pdev, | |||
1116 | goto err_iounmap; | 1287 | goto err_iounmap; |
1117 | } | 1288 | } |
1118 | 1289 | ||
1119 | eeprom_93cx6_read(&eeprom, 0x17, &eeprom_val); | 1290 | if (!is_valid_ether_addr(priv->mac_addr)) { |
1120 | priv->csthreshold = eeprom_val >> 8; | ||
1121 | if (!priv->r8185) { | ||
1122 | __le32 anaparam; | ||
1123 | eeprom_93cx6_multiread(&eeprom, 0xD, (__le16 *)&anaparam, 2); | ||
1124 | priv->anaparam = le32_to_cpu(anaparam); | ||
1125 | eeprom_93cx6_read(&eeprom, 0x19, &priv->rfparam); | ||
1126 | } | ||
1127 | |||
1128 | eeprom_93cx6_multiread(&eeprom, 0x7, (__le16 *)mac_addr, 3); | ||
1129 | if (!is_valid_ether_addr(mac_addr)) { | ||
1130 | printk(KERN_WARNING "%s (rtl8180): Invalid hwaddr! Using" | 1291 | printk(KERN_WARNING "%s (rtl8180): Invalid hwaddr! Using" |
1131 | " randomly generated MAC addr\n", pci_name(pdev)); | 1292 | " randomly generated MAC addr\n", pci_name(pdev)); |
1132 | eth_random_addr(mac_addr); | 1293 | eth_random_addr(priv->mac_addr); |
1133 | } | 1294 | } |
1134 | SET_IEEE80211_PERM_ADDR(dev, mac_addr); | 1295 | SET_IEEE80211_PERM_ADDR(dev, priv->mac_addr); |
1135 | |||
1136 | /* CCK TX power */ | ||
1137 | for (i = 0; i < 14; i += 2) { | ||
1138 | u16 txpwr; | ||
1139 | eeprom_93cx6_read(&eeprom, 0x10 + (i >> 1), &txpwr); | ||
1140 | priv->channels[i].hw_value = txpwr & 0xFF; | ||
1141 | priv->channels[i + 1].hw_value = txpwr >> 8; | ||
1142 | } | ||
1143 | |||
1144 | /* OFDM TX power */ | ||
1145 | if (priv->r8185) { | ||
1146 | for (i = 0; i < 14; i += 2) { | ||
1147 | u16 txpwr; | ||
1148 | eeprom_93cx6_read(&eeprom, 0x20 + (i >> 1), &txpwr); | ||
1149 | priv->channels[i].hw_value |= (txpwr & 0xFF) << 8; | ||
1150 | priv->channels[i + 1].hw_value |= txpwr & 0xFF00; | ||
1151 | } | ||
1152 | } | ||
1153 | |||
1154 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); | ||
1155 | 1296 | ||
1156 | spin_lock_init(&priv->lock); | 1297 | spin_lock_init(&priv->lock); |
1157 | 1298 | ||
@@ -1163,7 +1304,7 @@ static int rtl8180_probe(struct pci_dev *pdev, | |||
1163 | } | 1304 | } |
1164 | 1305 | ||
1165 | wiphy_info(dev->wiphy, "hwaddr %pm, %s + %s\n", | 1306 | wiphy_info(dev->wiphy, "hwaddr %pm, %s + %s\n", |
1166 | mac_addr, chip_name, priv->rf->name); | 1307 | priv->mac_addr, chip_name, priv->rf->name); |
1167 | 1308 | ||
1168 | return 0; | 1309 | return 0; |
1169 | 1310 | ||
diff --git a/drivers/net/wireless/rtl818x/rtl8180/rtl8180.h b/drivers/net/wireless/rtl818x/rtl8180/rtl8180.h index 30523314da43..26383d77fc3a 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/rtl8180.h +++ b/drivers/net/wireless/rtl818x/rtl8180/rtl8180.h | |||
@@ -81,12 +81,18 @@ struct rtl8180_priv { | |||
81 | struct ieee80211_supported_band band; | 81 | struct ieee80211_supported_band band; |
82 | struct pci_dev *pdev; | 82 | struct pci_dev *pdev; |
83 | u32 rx_conf; | 83 | u32 rx_conf; |
84 | u8 slot_time; | ||
85 | u16 ack_time; | ||
84 | 86 | ||
85 | int r8185; | 87 | enum { |
88 | RTL818X_CHIP_FAMILY_RTL8180, | ||
89 | RTL818X_CHIP_FAMILY_RTL8185, | ||
90 | } chip_family; | ||
86 | u32 anaparam; | 91 | u32 anaparam; |
87 | u16 rfparam; | 92 | u16 rfparam; |
88 | u8 csthreshold; | 93 | u8 csthreshold; |
89 | 94 | u8 mac_addr[ETH_ALEN]; | |
95 | u8 rf_type; | ||
90 | /* sequence # */ | 96 | /* sequence # */ |
91 | u16 seqno; | 97 | u16 seqno; |
92 | }; | 98 | }; |
diff --git a/drivers/net/wireless/rtl818x/rtl8180/rtl8225.c b/drivers/net/wireless/rtl818x/rtl8180/rtl8225.c index d60a5f399022..1c0fe238d995 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/rtl8225.c +++ b/drivers/net/wireless/rtl818x/rtl8180/rtl8225.c | |||
@@ -730,32 +730,11 @@ static void rtl8225_rf_set_channel(struct ieee80211_hw *dev, | |||
730 | msleep(10); | 730 | msleep(10); |
731 | } | 731 | } |
732 | 732 | ||
733 | static void rtl8225_rf_conf_erp(struct ieee80211_hw *dev, | ||
734 | struct ieee80211_bss_conf *info) | ||
735 | { | ||
736 | struct rtl8180_priv *priv = dev->priv; | ||
737 | |||
738 | if (info->use_short_slot) { | ||
739 | rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9); | ||
740 | rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22); | ||
741 | rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14); | ||
742 | rtl818x_iowrite8(priv, &priv->map->EIFS, 81); | ||
743 | rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0x73); | ||
744 | } else { | ||
745 | rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14); | ||
746 | rtl818x_iowrite8(priv, &priv->map->SIFS, 0x44); | ||
747 | rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24); | ||
748 | rtl818x_iowrite8(priv, &priv->map->EIFS, 81); | ||
749 | rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0xa5); | ||
750 | } | ||
751 | } | ||
752 | |||
753 | static const struct rtl818x_rf_ops rtl8225_ops = { | 733 | static const struct rtl818x_rf_ops rtl8225_ops = { |
754 | .name = "rtl8225", | 734 | .name = "rtl8225", |
755 | .init = rtl8225_rf_init, | 735 | .init = rtl8225_rf_init, |
756 | .stop = rtl8225_rf_stop, | 736 | .stop = rtl8225_rf_stop, |
757 | .set_chan = rtl8225_rf_set_channel, | 737 | .set_chan = rtl8225_rf_set_channel, |
758 | .conf_erp = rtl8225_rf_conf_erp, | ||
759 | }; | 738 | }; |
760 | 739 | ||
761 | static const struct rtl818x_rf_ops rtl8225z2_ops = { | 740 | static const struct rtl818x_rf_ops rtl8225z2_ops = { |
@@ -763,7 +742,6 @@ static const struct rtl818x_rf_ops rtl8225z2_ops = { | |||
763 | .init = rtl8225z2_rf_init, | 742 | .init = rtl8225z2_rf_init, |
764 | .stop = rtl8225_rf_stop, | 743 | .stop = rtl8225_rf_stop, |
765 | .set_chan = rtl8225_rf_set_channel, | 744 | .set_chan = rtl8225_rf_set_channel, |
766 | .conf_erp = rtl8225_rf_conf_erp, | ||
767 | }; | 745 | }; |
768 | 746 | ||
769 | const struct rtl818x_rf_ops * rtl8180_detect_rf(struct ieee80211_hw *dev) | 747 | const struct rtl818x_rf_ops * rtl8180_detect_rf(struct ieee80211_hw *dev) |
diff --git a/drivers/net/wireless/rtl818x/rtl818x.h b/drivers/net/wireless/rtl818x/rtl818x.h index fa7f7f61ea26..1815b15d03b1 100644 --- a/drivers/net/wireless/rtl818x/rtl818x.h +++ b/drivers/net/wireless/rtl818x/rtl818x.h | |||
@@ -192,7 +192,6 @@ struct rtl818x_rf_ops { | |||
192 | void (*init)(struct ieee80211_hw *); | 192 | void (*init)(struct ieee80211_hw *); |
193 | void (*stop)(struct ieee80211_hw *); | 193 | void (*stop)(struct ieee80211_hw *); |
194 | void (*set_chan)(struct ieee80211_hw *, struct ieee80211_conf *); | 194 | void (*set_chan)(struct ieee80211_hw *, struct ieee80211_conf *); |
195 | void (*conf_erp)(struct ieee80211_hw *, struct ieee80211_bss_conf *); | ||
196 | u8 (*calc_rssi)(u8 agc, u8 sq); | 195 | u8 (*calc_rssi)(u8 agc, u8 sq); |
197 | }; | 196 | }; |
198 | 197 | ||
diff --git a/drivers/nfc/Kconfig b/drivers/nfc/Kconfig index fe20e1cc0545..65d4ca19d132 100644 --- a/drivers/nfc/Kconfig +++ b/drivers/nfc/Kconfig | |||
@@ -26,6 +26,18 @@ config NFC_WILINK | |||
26 | Say Y here to compile support for Texas Instrument's NFC WiLink driver | 26 | Say Y here to compile support for Texas Instrument's NFC WiLink driver |
27 | into the kernel or say M to compile it as module. | 27 | into the kernel or say M to compile it as module. |
28 | 28 | ||
29 | config NFC_TRF7970A | ||
30 | tristate "Texas Instruments TRF7970a NFC driver" | ||
31 | depends on SPI && NFC_DIGITAL | ||
32 | help | ||
33 | This option enables the NFC driver for Texas Instruments' TRF7970a | ||
34 | device. Such device supports 5 different protocols: ISO14443A, | ||
35 | ISO14443B, FeLiCa, ISO15693 and ISO18000-3. | ||
36 | |||
37 | Say Y here to compile support for TRF7970a into the kernel or | ||
38 | say M to compile it as a module. The module will be called | ||
39 | trf7970a.ko. | ||
40 | |||
29 | config NFC_MEI_PHY | 41 | config NFC_MEI_PHY |
30 | tristate "MEI bus NFC device support" | 42 | tristate "MEI bus NFC device support" |
31 | depends on INTEL_MEI && NFC_HCI | 43 | depends on INTEL_MEI && NFC_HCI |
diff --git a/drivers/nfc/Makefile b/drivers/nfc/Makefile index 56ab822ba03d..ae42a3fa60c9 100644 --- a/drivers/nfc/Makefile +++ b/drivers/nfc/Makefile | |||
@@ -10,5 +10,6 @@ obj-$(CONFIG_NFC_MEI_PHY) += mei_phy.o | |||
10 | obj-$(CONFIG_NFC_SIM) += nfcsim.o | 10 | obj-$(CONFIG_NFC_SIM) += nfcsim.o |
11 | obj-$(CONFIG_NFC_PORT100) += port100.o | 11 | obj-$(CONFIG_NFC_PORT100) += port100.o |
12 | obj-$(CONFIG_NFC_MRVL) += nfcmrvl/ | 12 | obj-$(CONFIG_NFC_MRVL) += nfcmrvl/ |
13 | obj-$(CONFIG_NFC_TRF7970A) += trf7970a.o | ||
13 | 14 | ||
14 | ccflags-$(CONFIG_NFC_DEBUG) := -DDEBUG | 15 | ccflags-$(CONFIG_NFC_DEBUG) := -DDEBUG |
diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index cf1a87bb74f8..d46a700a9637 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c | |||
@@ -55,26 +55,14 @@ | |||
55 | NFC_PROTO_NFC_DEP_MASK) | 55 | NFC_PROTO_NFC_DEP_MASK) |
56 | 56 | ||
57 | static const struct usb_device_id pn533_table[] = { | 57 | static const struct usb_device_id pn533_table[] = { |
58 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE, | 58 | { USB_DEVICE(PN533_VENDOR_ID, PN533_PRODUCT_ID), |
59 | .idVendor = PN533_VENDOR_ID, | 59 | .driver_info = PN533_DEVICE_STD }, |
60 | .idProduct = PN533_PRODUCT_ID, | 60 | { USB_DEVICE(SCM_VENDOR_ID, SCL3711_PRODUCT_ID), |
61 | .driver_info = PN533_DEVICE_STD, | 61 | .driver_info = PN533_DEVICE_STD }, |
62 | }, | 62 | { USB_DEVICE(SONY_VENDOR_ID, PASORI_PRODUCT_ID), |
63 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE, | 63 | .driver_info = PN533_DEVICE_PASORI }, |
64 | .idVendor = SCM_VENDOR_ID, | 64 | { USB_DEVICE(ACS_VENDOR_ID, ACR122U_PRODUCT_ID), |
65 | .idProduct = SCL3711_PRODUCT_ID, | 65 | .driver_info = PN533_DEVICE_ACR122U }, |
66 | .driver_info = PN533_DEVICE_STD, | ||
67 | }, | ||
68 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE, | ||
69 | .idVendor = SONY_VENDOR_ID, | ||
70 | .idProduct = PASORI_PRODUCT_ID, | ||
71 | .driver_info = PN533_DEVICE_PASORI, | ||
72 | }, | ||
73 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE, | ||
74 | .idVendor = ACS_VENDOR_ID, | ||
75 | .idProduct = ACR122U_PRODUCT_ID, | ||
76 | .driver_info = PN533_DEVICE_ACR122U, | ||
77 | }, | ||
78 | { } | 66 | { } |
79 | }; | 67 | }; |
80 | MODULE_DEVICE_TABLE(usb, pn533_table); | 68 | MODULE_DEVICE_TABLE(usb, pn533_table); |
diff --git a/drivers/nfc/pn544/i2c.c b/drivers/nfc/pn544/i2c.c index d6185ff2f87b..f2acd85be86e 100644 --- a/drivers/nfc/pn544/i2c.c +++ b/drivers/nfc/pn544/i2c.c | |||
@@ -58,8 +58,19 @@ MODULE_DEVICE_TABLE(i2c, pn544_hci_i2c_id_table); | |||
58 | 58 | ||
59 | #define PN544_HCI_I2C_DRIVER_NAME "pn544_hci_i2c" | 59 | #define PN544_HCI_I2C_DRIVER_NAME "pn544_hci_i2c" |
60 | 60 | ||
61 | /* | ||
62 | * Exposed through the 4 most significant bytes | ||
63 | * from the HCI SW_VERSION first byte, a.k.a. | ||
64 | * SW RomLib. | ||
65 | */ | ||
66 | #define PN544_HW_VARIANT_C2 0xa | ||
67 | #define PN544_HW_VARIANT_C3 0xb | ||
68 | |||
69 | #define PN544_FW_CMD_RESET 0x01 | ||
61 | #define PN544_FW_CMD_WRITE 0x08 | 70 | #define PN544_FW_CMD_WRITE 0x08 |
62 | #define PN544_FW_CMD_CHECK 0x06 | 71 | #define PN544_FW_CMD_CHECK 0x06 |
72 | #define PN544_FW_CMD_SECURE_WRITE 0x0C | ||
73 | #define PN544_FW_CMD_SECURE_CHUNK_WRITE 0x0D | ||
63 | 74 | ||
64 | struct pn544_i2c_fw_frame_write { | 75 | struct pn544_i2c_fw_frame_write { |
65 | u8 cmd; | 76 | u8 cmd; |
@@ -88,13 +99,31 @@ struct pn544_i2c_fw_blob { | |||
88 | u8 data[]; | 99 | u8 data[]; |
89 | }; | 100 | }; |
90 | 101 | ||
102 | struct pn544_i2c_fw_secure_frame { | ||
103 | u8 cmd; | ||
104 | u16 be_datalen; | ||
105 | u8 data[]; | ||
106 | } __packed; | ||
107 | |||
108 | struct pn544_i2c_fw_secure_blob { | ||
109 | u64 header; | ||
110 | u8 data[]; | ||
111 | }; | ||
112 | |||
91 | #define PN544_FW_CMD_RESULT_TIMEOUT 0x01 | 113 | #define PN544_FW_CMD_RESULT_TIMEOUT 0x01 |
92 | #define PN544_FW_CMD_RESULT_BAD_CRC 0x02 | 114 | #define PN544_FW_CMD_RESULT_BAD_CRC 0x02 |
93 | #define PN544_FW_CMD_RESULT_ACCESS_DENIED 0x08 | 115 | #define PN544_FW_CMD_RESULT_ACCESS_DENIED 0x08 |
94 | #define PN544_FW_CMD_RESULT_PROTOCOL_ERROR 0x0B | 116 | #define PN544_FW_CMD_RESULT_PROTOCOL_ERROR 0x0B |
95 | #define PN544_FW_CMD_RESULT_INVALID_PARAMETER 0x11 | 117 | #define PN544_FW_CMD_RESULT_INVALID_PARAMETER 0x11 |
118 | #define PN544_FW_CMD_RESULT_UNSUPPORTED_COMMAND 0x13 | ||
96 | #define PN544_FW_CMD_RESULT_INVALID_LENGTH 0x18 | 119 | #define PN544_FW_CMD_RESULT_INVALID_LENGTH 0x18 |
120 | #define PN544_FW_CMD_RESULT_CRYPTOGRAPHIC_ERROR 0x19 | ||
121 | #define PN544_FW_CMD_RESULT_VERSION_CONDITIONS_ERROR 0x1D | ||
122 | #define PN544_FW_CMD_RESULT_MEMORY_ERROR 0x20 | ||
123 | #define PN544_FW_CMD_RESULT_CHUNK_OK 0x21 | ||
97 | #define PN544_FW_CMD_RESULT_WRITE_FAILED 0x74 | 124 | #define PN544_FW_CMD_RESULT_WRITE_FAILED 0x74 |
125 | #define PN544_FW_CMD_RESULT_COMMAND_REJECTED 0xE0 | ||
126 | #define PN544_FW_CMD_RESULT_CHUNK_ERROR 0xE6 | ||
98 | 127 | ||
99 | #define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) | 128 | #define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) |
100 | 129 | ||
@@ -104,11 +133,17 @@ struct pn544_i2c_fw_blob { | |||
104 | #define PN544_FW_I2C_WRITE_DATA_MAX_LEN MIN((PN544_FW_I2C_MAX_PAYLOAD -\ | 133 | #define PN544_FW_I2C_WRITE_DATA_MAX_LEN MIN((PN544_FW_I2C_MAX_PAYLOAD -\ |
105 | PN544_FW_I2C_WRITE_FRAME_HEADER_LEN),\ | 134 | PN544_FW_I2C_WRITE_FRAME_HEADER_LEN),\ |
106 | PN544_FW_WRITE_BUFFER_MAX_LEN) | 135 | PN544_FW_WRITE_BUFFER_MAX_LEN) |
136 | #define PN544_FW_SECURE_CHUNK_WRITE_HEADER_LEN 3 | ||
137 | #define PN544_FW_SECURE_CHUNK_WRITE_DATA_MAX_LEN (PN544_FW_I2C_MAX_PAYLOAD -\ | ||
138 | PN544_FW_SECURE_CHUNK_WRITE_HEADER_LEN) | ||
139 | #define PN544_FW_SECURE_FRAME_HEADER_LEN 3 | ||
140 | #define PN544_FW_SECURE_BLOB_HEADER_LEN 8 | ||
107 | 141 | ||
108 | #define FW_WORK_STATE_IDLE 1 | 142 | #define FW_WORK_STATE_IDLE 1 |
109 | #define FW_WORK_STATE_START 2 | 143 | #define FW_WORK_STATE_START 2 |
110 | #define FW_WORK_STATE_WAIT_WRITE_ANSWER 3 | 144 | #define FW_WORK_STATE_WAIT_WRITE_ANSWER 3 |
111 | #define FW_WORK_STATE_WAIT_CHECK_ANSWER 4 | 145 | #define FW_WORK_STATE_WAIT_CHECK_ANSWER 4 |
146 | #define FW_WORK_STATE_WAIT_SECURE_WRITE_ANSWER 5 | ||
112 | 147 | ||
113 | struct pn544_i2c_phy { | 148 | struct pn544_i2c_phy { |
114 | struct i2c_client *i2c_dev; | 149 | struct i2c_client *i2c_dev; |
@@ -119,6 +154,8 @@ struct pn544_i2c_phy { | |||
119 | unsigned int gpio_fw; | 154 | unsigned int gpio_fw; |
120 | unsigned int en_polarity; | 155 | unsigned int en_polarity; |
121 | 156 | ||
157 | u8 hw_variant; | ||
158 | |||
122 | struct work_struct fw_work; | 159 | struct work_struct fw_work; |
123 | int fw_work_state; | 160 | int fw_work_state; |
124 | char firmware_name[NFC_FIRMWARE_NAME_MAXSIZE + 1]; | 161 | char firmware_name[NFC_FIRMWARE_NAME_MAXSIZE + 1]; |
@@ -127,6 +164,8 @@ struct pn544_i2c_phy { | |||
127 | size_t fw_blob_size; | 164 | size_t fw_blob_size; |
128 | const u8 *fw_blob_data; | 165 | const u8 *fw_blob_data; |
129 | size_t fw_written; | 166 | size_t fw_written; |
167 | size_t fw_size; | ||
168 | |||
130 | int fw_cmd_result; | 169 | int fw_cmd_result; |
131 | 170 | ||
132 | int powered; | 171 | int powered; |
@@ -390,6 +429,8 @@ static int pn544_hci_i2c_fw_read_status(struct pn544_i2c_phy *phy) | |||
390 | switch (response.status) { | 429 | switch (response.status) { |
391 | case 0: | 430 | case 0: |
392 | return 0; | 431 | return 0; |
432 | case PN544_FW_CMD_RESULT_CHUNK_OK: | ||
433 | return response.status; | ||
393 | case PN544_FW_CMD_RESULT_TIMEOUT: | 434 | case PN544_FW_CMD_RESULT_TIMEOUT: |
394 | return -ETIMEDOUT; | 435 | return -ETIMEDOUT; |
395 | case PN544_FW_CMD_RESULT_BAD_CRC: | 436 | case PN544_FW_CMD_RESULT_BAD_CRC: |
@@ -400,9 +441,20 @@ static int pn544_hci_i2c_fw_read_status(struct pn544_i2c_phy *phy) | |||
400 | return -EPROTO; | 441 | return -EPROTO; |
401 | case PN544_FW_CMD_RESULT_INVALID_PARAMETER: | 442 | case PN544_FW_CMD_RESULT_INVALID_PARAMETER: |
402 | return -EINVAL; | 443 | return -EINVAL; |
444 | case PN544_FW_CMD_RESULT_UNSUPPORTED_COMMAND: | ||
445 | return -ENOTSUPP; | ||
403 | case PN544_FW_CMD_RESULT_INVALID_LENGTH: | 446 | case PN544_FW_CMD_RESULT_INVALID_LENGTH: |
404 | return -EBADMSG; | 447 | return -EBADMSG; |
448 | case PN544_FW_CMD_RESULT_CRYPTOGRAPHIC_ERROR: | ||
449 | return -ENOKEY; | ||
450 | case PN544_FW_CMD_RESULT_VERSION_CONDITIONS_ERROR: | ||
451 | return -EINVAL; | ||
452 | case PN544_FW_CMD_RESULT_MEMORY_ERROR: | ||
453 | return -ENOMEM; | ||
454 | case PN544_FW_CMD_RESULT_COMMAND_REJECTED: | ||
455 | return -EACCES; | ||
405 | case PN544_FW_CMD_RESULT_WRITE_FAILED: | 456 | case PN544_FW_CMD_RESULT_WRITE_FAILED: |
457 | case PN544_FW_CMD_RESULT_CHUNK_ERROR: | ||
406 | return -EIO; | 458 | return -EIO; |
407 | default: | 459 | default: |
408 | return -EIO; | 460 | return -EIO; |
@@ -469,7 +521,8 @@ static struct nfc_phy_ops i2c_phy_ops = { | |||
469 | .disable = pn544_hci_i2c_disable, | 521 | .disable = pn544_hci_i2c_disable, |
470 | }; | 522 | }; |
471 | 523 | ||
472 | static int pn544_hci_i2c_fw_download(void *phy_id, const char *firmware_name) | 524 | static int pn544_hci_i2c_fw_download(void *phy_id, const char *firmware_name, |
525 | u8 hw_variant) | ||
473 | { | 526 | { |
474 | struct pn544_i2c_phy *phy = phy_id; | 527 | struct pn544_i2c_phy *phy = phy_id; |
475 | 528 | ||
@@ -477,6 +530,7 @@ static int pn544_hci_i2c_fw_download(void *phy_id, const char *firmware_name) | |||
477 | 530 | ||
478 | strcpy(phy->firmware_name, firmware_name); | 531 | strcpy(phy->firmware_name, firmware_name); |
479 | 532 | ||
533 | phy->hw_variant = hw_variant; | ||
480 | phy->fw_work_state = FW_WORK_STATE_START; | 534 | phy->fw_work_state = FW_WORK_STATE_START; |
481 | 535 | ||
482 | schedule_work(&phy->fw_work); | 536 | schedule_work(&phy->fw_work); |
@@ -598,12 +652,93 @@ static int pn544_hci_i2c_fw_write_chunk(struct pn544_i2c_phy *phy) | |||
598 | return 0; | 652 | return 0; |
599 | } | 653 | } |
600 | 654 | ||
655 | static int pn544_hci_i2c_fw_secure_write_frame_cmd(struct pn544_i2c_phy *phy, | ||
656 | const u8 *data, u16 datalen) | ||
657 | { | ||
658 | u8 buf[PN544_FW_I2C_MAX_PAYLOAD]; | ||
659 | struct pn544_i2c_fw_secure_frame *chunk; | ||
660 | int chunklen; | ||
661 | int r; | ||
662 | |||
663 | if (datalen > PN544_FW_SECURE_CHUNK_WRITE_DATA_MAX_LEN) | ||
664 | datalen = PN544_FW_SECURE_CHUNK_WRITE_DATA_MAX_LEN; | ||
665 | |||
666 | chunk = (struct pn544_i2c_fw_secure_frame *) buf; | ||
667 | |||
668 | chunk->cmd = PN544_FW_CMD_SECURE_CHUNK_WRITE; | ||
669 | |||
670 | put_unaligned_be16(datalen, &chunk->be_datalen); | ||
671 | |||
672 | memcpy(chunk->data, data, datalen); | ||
673 | |||
674 | chunklen = sizeof(chunk->cmd) + sizeof(chunk->be_datalen) + datalen; | ||
675 | |||
676 | r = i2c_master_send(phy->i2c_dev, buf, chunklen); | ||
677 | |||
678 | if (r == chunklen) | ||
679 | return datalen; | ||
680 | else if (r < 0) | ||
681 | return r; | ||
682 | else | ||
683 | return -EIO; | ||
684 | |||
685 | } | ||
686 | |||
687 | static int pn544_hci_i2c_fw_secure_write_frame(struct pn544_i2c_phy *phy) | ||
688 | { | ||
689 | struct pn544_i2c_fw_secure_frame *framep; | ||
690 | int r; | ||
691 | |||
692 | framep = (struct pn544_i2c_fw_secure_frame *) phy->fw_blob_data; | ||
693 | if (phy->fw_written == 0) | ||
694 | phy->fw_blob_size = get_unaligned_be16(&framep->be_datalen) | ||
695 | + PN544_FW_SECURE_FRAME_HEADER_LEN; | ||
696 | |||
697 | /* Only secure write command can be chunked*/ | ||
698 | if (phy->fw_blob_size > PN544_FW_I2C_MAX_PAYLOAD && | ||
699 | framep->cmd != PN544_FW_CMD_SECURE_WRITE) | ||
700 | return -EINVAL; | ||
701 | |||
702 | /* The firmware also have other commands, we just send them directly */ | ||
703 | if (phy->fw_blob_size < PN544_FW_I2C_MAX_PAYLOAD) { | ||
704 | r = i2c_master_send(phy->i2c_dev, | ||
705 | (const char *) phy->fw_blob_data, phy->fw_blob_size); | ||
706 | |||
707 | if (r == phy->fw_blob_size) | ||
708 | goto exit; | ||
709 | else if (r < 0) | ||
710 | return r; | ||
711 | else | ||
712 | return -EIO; | ||
713 | } | ||
714 | |||
715 | r = pn544_hci_i2c_fw_secure_write_frame_cmd(phy, | ||
716 | phy->fw_blob_data + phy->fw_written, | ||
717 | phy->fw_blob_size - phy->fw_written); | ||
718 | if (r < 0) | ||
719 | return r; | ||
720 | |||
721 | exit: | ||
722 | phy->fw_written += r; | ||
723 | phy->fw_work_state = FW_WORK_STATE_WAIT_SECURE_WRITE_ANSWER; | ||
724 | |||
725 | /* SW reset command will not trig any response from PN544 */ | ||
726 | if (framep->cmd == PN544_FW_CMD_RESET) { | ||
727 | pn544_hci_i2c_enable_mode(phy, PN544_FW_MODE); | ||
728 | phy->fw_cmd_result = 0; | ||
729 | schedule_work(&phy->fw_work); | ||
730 | } | ||
731 | |||
732 | return 0; | ||
733 | } | ||
734 | |||
601 | static void pn544_hci_i2c_fw_work(struct work_struct *work) | 735 | static void pn544_hci_i2c_fw_work(struct work_struct *work) |
602 | { | 736 | { |
603 | struct pn544_i2c_phy *phy = container_of(work, struct pn544_i2c_phy, | 737 | struct pn544_i2c_phy *phy = container_of(work, struct pn544_i2c_phy, |
604 | fw_work); | 738 | fw_work); |
605 | int r; | 739 | int r; |
606 | struct pn544_i2c_fw_blob *blob; | 740 | struct pn544_i2c_fw_blob *blob; |
741 | struct pn544_i2c_fw_secure_blob *secure_blob; | ||
607 | 742 | ||
608 | switch (phy->fw_work_state) { | 743 | switch (phy->fw_work_state) { |
609 | case FW_WORK_STATE_START: | 744 | case FW_WORK_STATE_START: |
@@ -614,13 +749,29 @@ static void pn544_hci_i2c_fw_work(struct work_struct *work) | |||
614 | if (r < 0) | 749 | if (r < 0) |
615 | goto exit_state_start; | 750 | goto exit_state_start; |
616 | 751 | ||
617 | blob = (struct pn544_i2c_fw_blob *) phy->fw->data; | ||
618 | phy->fw_blob_size = get_unaligned_be32(&blob->be_size); | ||
619 | phy->fw_blob_dest_addr = get_unaligned_be32(&blob->be_destaddr); | ||
620 | phy->fw_blob_data = blob->data; | ||
621 | |||
622 | phy->fw_written = 0; | 752 | phy->fw_written = 0; |
623 | r = pn544_hci_i2c_fw_write_chunk(phy); | 753 | |
754 | switch (phy->hw_variant) { | ||
755 | case PN544_HW_VARIANT_C2: | ||
756 | blob = (struct pn544_i2c_fw_blob *) phy->fw->data; | ||
757 | phy->fw_blob_size = get_unaligned_be32(&blob->be_size); | ||
758 | phy->fw_blob_dest_addr = get_unaligned_be32( | ||
759 | &blob->be_destaddr); | ||
760 | phy->fw_blob_data = blob->data; | ||
761 | |||
762 | r = pn544_hci_i2c_fw_write_chunk(phy); | ||
763 | break; | ||
764 | case PN544_HW_VARIANT_C3: | ||
765 | secure_blob = (struct pn544_i2c_fw_secure_blob *) | ||
766 | phy->fw->data; | ||
767 | phy->fw_blob_data = secure_blob->data; | ||
768 | phy->fw_size = phy->fw->size; | ||
769 | r = pn544_hci_i2c_fw_secure_write_frame(phy); | ||
770 | break; | ||
771 | default: | ||
772 | r = -ENOTSUPP; | ||
773 | break; | ||
774 | } | ||
624 | 775 | ||
625 | exit_state_start: | 776 | exit_state_start: |
626 | if (r < 0) | 777 | if (r < 0) |
@@ -672,6 +823,35 @@ exit_state_wait_check_answer: | |||
672 | pn544_hci_i2c_fw_work_complete(phy, r); | 823 | pn544_hci_i2c_fw_work_complete(phy, r); |
673 | break; | 824 | break; |
674 | 825 | ||
826 | case FW_WORK_STATE_WAIT_SECURE_WRITE_ANSWER: | ||
827 | r = phy->fw_cmd_result; | ||
828 | if (r < 0) | ||
829 | goto exit_state_wait_secure_write_answer; | ||
830 | |||
831 | if (r == PN544_FW_CMD_RESULT_CHUNK_OK) { | ||
832 | r = pn544_hci_i2c_fw_secure_write_frame(phy); | ||
833 | goto exit_state_wait_secure_write_answer; | ||
834 | } | ||
835 | |||
836 | if (phy->fw_written == phy->fw_blob_size) { | ||
837 | secure_blob = (struct pn544_i2c_fw_secure_blob *) | ||
838 | (phy->fw_blob_data + phy->fw_blob_size); | ||
839 | phy->fw_size -= phy->fw_blob_size + | ||
840 | PN544_FW_SECURE_BLOB_HEADER_LEN; | ||
841 | if (phy->fw_size >= PN544_FW_SECURE_BLOB_HEADER_LEN | ||
842 | + PN544_FW_SECURE_FRAME_HEADER_LEN) { | ||
843 | phy->fw_blob_data = secure_blob->data; | ||
844 | |||
845 | phy->fw_written = 0; | ||
846 | r = pn544_hci_i2c_fw_secure_write_frame(phy); | ||
847 | } | ||
848 | } | ||
849 | |||
850 | exit_state_wait_secure_write_answer: | ||
851 | if (r < 0 || phy->fw_size == 0) | ||
852 | pn544_hci_i2c_fw_work_complete(phy, r); | ||
853 | break; | ||
854 | |||
675 | default: | 855 | default: |
676 | break; | 856 | break; |
677 | } | 857 | } |
diff --git a/drivers/nfc/pn544/pn544.c b/drivers/nfc/pn544/pn544.c index 3df4a109cfad..9c8051d20cea 100644 --- a/drivers/nfc/pn544/pn544.c +++ b/drivers/nfc/pn544/pn544.c | |||
@@ -786,7 +786,7 @@ static int pn544_hci_fw_download(struct nfc_hci_dev *hdev, | |||
786 | if (info->fw_download == NULL) | 786 | if (info->fw_download == NULL) |
787 | return -ENOTSUPP; | 787 | return -ENOTSUPP; |
788 | 788 | ||
789 | return info->fw_download(info->phy_id, firmware_name); | 789 | return info->fw_download(info->phy_id, firmware_name, hdev->sw_romlib); |
790 | } | 790 | } |
791 | 791 | ||
792 | static int pn544_hci_discover_se(struct nfc_hci_dev *hdev) | 792 | static int pn544_hci_discover_se(struct nfc_hci_dev *hdev) |
diff --git a/drivers/nfc/pn544/pn544.h b/drivers/nfc/pn544/pn544.h index 491bf45da358..2aa9233e8086 100644 --- a/drivers/nfc/pn544/pn544.h +++ b/drivers/nfc/pn544/pn544.h | |||
@@ -25,7 +25,8 @@ | |||
25 | #define PN544_HCI_MODE 0 | 25 | #define PN544_HCI_MODE 0 |
26 | #define PN544_FW_MODE 1 | 26 | #define PN544_FW_MODE 1 |
27 | 27 | ||
28 | typedef int (*fw_download_t)(void *context, const char *firmware_name); | 28 | typedef int (*fw_download_t)(void *context, const char *firmware_name, |
29 | u8 hw_variant); | ||
29 | 30 | ||
30 | int pn544_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name, | 31 | int pn544_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name, |
31 | int phy_headroom, int phy_tailroom, int phy_payload, | 32 | int phy_headroom, int phy_tailroom, int phy_payload, |
diff --git a/drivers/nfc/port100.c b/drivers/nfc/port100.c index a8555f81cbba..b7a372af5eb7 100644 --- a/drivers/nfc/port100.c +++ b/drivers/nfc/port100.c | |||
@@ -27,7 +27,8 @@ | |||
27 | #define PORT100_PROTOCOLS (NFC_PROTO_JEWEL_MASK | \ | 27 | #define PORT100_PROTOCOLS (NFC_PROTO_JEWEL_MASK | \ |
28 | NFC_PROTO_MIFARE_MASK | \ | 28 | NFC_PROTO_MIFARE_MASK | \ |
29 | NFC_PROTO_FELICA_MASK | \ | 29 | NFC_PROTO_FELICA_MASK | \ |
30 | NFC_PROTO_NFC_DEP_MASK) | 30 | NFC_PROTO_NFC_DEP_MASK | \ |
31 | NFC_PROTO_ISO14443_MASK) | ||
31 | 32 | ||
32 | #define PORT100_CAPABILITIES (NFC_DIGITAL_DRV_CAPS_IN_CRC | \ | 33 | #define PORT100_CAPABILITIES (NFC_DIGITAL_DRV_CAPS_IN_CRC | \ |
33 | NFC_DIGITAL_DRV_CAPS_TG_CRC) | 34 | NFC_DIGITAL_DRV_CAPS_TG_CRC) |
@@ -139,6 +140,8 @@ static const struct port100_in_rf_setting in_rf_settings[] = { | |||
139 | .in_recv_set_number = 15, | 140 | .in_recv_set_number = 15, |
140 | .in_recv_comm_type = PORT100_COMM_TYPE_IN_106A, | 141 | .in_recv_comm_type = PORT100_COMM_TYPE_IN_106A, |
141 | }, | 142 | }, |
143 | /* Ensures the array has NFC_DIGITAL_RF_TECH_LAST elements */ | ||
144 | [NFC_DIGITAL_RF_TECH_LAST] = { 0 }, | ||
142 | }; | 145 | }; |
143 | 146 | ||
144 | /** | 147 | /** |
@@ -174,6 +177,9 @@ static const struct port100_tg_rf_setting tg_rf_settings[] = { | |||
174 | .tg_set_number = 8, | 177 | .tg_set_number = 8, |
175 | .tg_comm_type = PORT100_COMM_TYPE_TG_424F, | 178 | .tg_comm_type = PORT100_COMM_TYPE_TG_424F, |
176 | }, | 179 | }, |
180 | /* Ensures the array has NFC_DIGITAL_RF_TECH_LAST elements */ | ||
181 | [NFC_DIGITAL_RF_TECH_LAST] = { 0 }, | ||
182 | |||
177 | }; | 183 | }; |
178 | 184 | ||
179 | #define PORT100_IN_PROT_INITIAL_GUARD_TIME 0x00 | 185 | #define PORT100_IN_PROT_INITIAL_GUARD_TIME 0x00 |
@@ -293,6 +299,10 @@ in_protocols[][PORT100_IN_MAX_NUM_PROTOCOLS + 1] = { | |||
293 | { PORT100_IN_PROT_CHECK_CRC, 0 }, | 299 | { PORT100_IN_PROT_CHECK_CRC, 0 }, |
294 | { PORT100_IN_PROT_END, 0 }, | 300 | { PORT100_IN_PROT_END, 0 }, |
295 | }, | 301 | }, |
302 | [NFC_DIGITAL_FRAMING_NFCA_T4T] = { | ||
303 | /* nfc_digital_framing_nfca_standard_with_crc_a */ | ||
304 | { PORT100_IN_PROT_END, 0 }, | ||
305 | }, | ||
296 | [NFC_DIGITAL_FRAMING_NFCA_NFC_DEP] = { | 306 | [NFC_DIGITAL_FRAMING_NFCA_NFC_DEP] = { |
297 | /* nfc_digital_framing_nfca_standard */ | 307 | /* nfc_digital_framing_nfca_standard */ |
298 | { PORT100_IN_PROT_END, 0 }, | 308 | { PORT100_IN_PROT_END, 0 }, |
@@ -330,6 +340,10 @@ in_protocols[][PORT100_IN_MAX_NUM_PROTOCOLS + 1] = { | |||
330 | [NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED] = { | 340 | [NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED] = { |
331 | { PORT100_IN_PROT_END, 0 }, | 341 | { PORT100_IN_PROT_END, 0 }, |
332 | }, | 342 | }, |
343 | /* Ensures the array has NFC_DIGITAL_FRAMING_LAST elements */ | ||
344 | [NFC_DIGITAL_FRAMING_LAST] = { | ||
345 | { PORT100_IN_PROT_END, 0 }, | ||
346 | }, | ||
333 | }; | 347 | }; |
334 | 348 | ||
335 | static struct port100_protocol | 349 | static struct port100_protocol |
@@ -371,6 +385,10 @@ tg_protocols[][PORT100_TG_MAX_NUM_PROTOCOLS + 1] = { | |||
371 | { PORT100_TG_PROT_RF_OFF, 1 }, | 385 | { PORT100_TG_PROT_RF_OFF, 1 }, |
372 | { PORT100_TG_PROT_END, 0 }, | 386 | { PORT100_TG_PROT_END, 0 }, |
373 | }, | 387 | }, |
388 | /* Ensures the array has NFC_DIGITAL_FRAMING_LAST elements */ | ||
389 | [NFC_DIGITAL_FRAMING_LAST] = { | ||
390 | { PORT100_TG_PROT_END, 0 }, | ||
391 | }, | ||
374 | }; | 392 | }; |
375 | 393 | ||
376 | struct port100 { | 394 | struct port100 { |
@@ -1356,10 +1374,7 @@ static struct nfc_digital_ops port100_digital_ops = { | |||
1356 | }; | 1374 | }; |
1357 | 1375 | ||
1358 | static const struct usb_device_id port100_table[] = { | 1376 | static const struct usb_device_id port100_table[] = { |
1359 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE, | 1377 | { USB_DEVICE(SONY_VENDOR_ID, RCS380_PRODUCT_ID), }, |
1360 | .idVendor = SONY_VENDOR_ID, | ||
1361 | .idProduct = RCS380_PRODUCT_ID, | ||
1362 | }, | ||
1363 | { } | 1378 | { } |
1364 | }; | 1379 | }; |
1365 | MODULE_DEVICE_TABLE(usb, port100_table); | 1380 | MODULE_DEVICE_TABLE(usb, port100_table); |
diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c new file mode 100644 index 000000000000..d9babe986473 --- /dev/null +++ b/drivers/nfc/trf7970a.c | |||
@@ -0,0 +1,1370 @@ | |||
1 | /* | ||
2 | * TI TRF7970a RFID/NFC Transceiver Driver | ||
3 | * | ||
4 | * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com | ||
5 | * | ||
6 | * Author: Erick Macias <emacias@ti.com> | ||
7 | * Author: Felipe Balbi <balbi@ti.com> | ||
8 | * Author: Mark A. Greer <mgreer@animalcreek.com> | ||
9 | * | ||
10 | * This program is free software: you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 of | ||
12 | * the License as published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #include <linux/module.h> | ||
16 | #include <linux/device.h> | ||
17 | #include <linux/netdevice.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/nfc.h> | ||
20 | #include <linux/skbuff.h> | ||
21 | #include <linux/delay.h> | ||
22 | #include <linux/gpio.h> | ||
23 | #include <linux/of.h> | ||
24 | #include <linux/of_gpio.h> | ||
25 | #include <linux/spi/spi.h> | ||
26 | #include <linux/regulator/consumer.h> | ||
27 | |||
28 | #include <net/nfc/nfc.h> | ||
29 | #include <net/nfc/digital.h> | ||
30 | |||
31 | /* There are 3 ways the host can communicate with the trf7970a: | ||
32 | * parallel mode, SPI with Slave Select (SS) mode, and SPI without | ||
33 | * SS mode. The driver only supports the two SPI modes. | ||
34 | * | ||
35 | * The trf7970a is very timing sensitive and the VIN, EN2, and EN | ||
36 | * pins must asserted in that order and with specific delays in between. | ||
37 | * The delays used in the driver were provided by TI and have been | ||
38 | * confirmed to work with this driver. | ||
39 | * | ||
40 | * Timeouts are implemented using the delayed workqueue kernel facility. | ||
41 | * Timeouts are required so things don't hang when there is no response | ||
42 | * from the trf7970a (or tag). Using this mechanism creates a race with | ||
43 | * interrupts, however. That is, an interrupt and a timeout could occur | ||
44 | * closely enough together that one is blocked by the mutex while the other | ||
45 | * executes. When the timeout handler executes first and blocks the | ||
46 | * interrupt handler, it will eventually set the state to IDLE so the | ||
47 | * interrupt handler will check the state and exit with no harm done. | ||
48 | * When the interrupt handler executes first and blocks the timeout handler, | ||
49 | * the cancel_delayed_work() call will know that it didn't cancel the | ||
50 | * work item (i.e., timeout) and will return zero. That return code is | ||
51 | * used by the timer handler to indicate that it should ignore the timeout | ||
52 | * once its unblocked. | ||
53 | * | ||
54 | * Aborting an active command isn't as simple as it seems because the only | ||
55 | * way to abort a command that's already been sent to the tag is so turn | ||
56 | * off power to the tag. If we do that, though, we'd have to go through | ||
57 | * the entire anticollision procedure again but the digital layer doesn't | ||
58 | * support that. So, if an abort is received before trf7970a_in_send_cmd() | ||
59 | * has sent the command to the tag, it simply returns -ECANCELED. If the | ||
60 | * command has already been sent to the tag, then the driver continues | ||
61 | * normally and recieves the response data (or error) but just before | ||
62 | * sending the data upstream, it frees the rx_skb and sends -ECANCELED | ||
63 | * upstream instead. If the command failed, that error will be sent | ||
64 | * upstream. | ||
65 | * | ||
66 | * When recieving data from a tag and the interrupt status register has | ||
67 | * only the SRX bit set, it means that all of the data has been received | ||
68 | * (once what's in the fifo has been read). However, depending on timing | ||
69 | * an interrupt status with only the SRX bit set may not be recived. In | ||
70 | * those cases, the timeout mechanism is used to wait 5 ms in case more | ||
71 | * data arrives. After 5 ms, it is assumed that all of the data has been | ||
72 | * received and the accumulated rx data is sent upstream. The | ||
73 | * 'TRF7970A_ST_WAIT_FOR_RX_DATA_CONT' state is used for this purpose | ||
74 | * (i.e., it indicates that some data has been received but we're not sure | ||
75 | * if there is more coming so a timeout in this state means all data has | ||
76 | * been received and there isn't an error). The delay is 5 ms since delays | ||
77 | * over 2 ms have been observed during testing (a little extra just in case). | ||
78 | * | ||
79 | * Type 2 write and sector select commands respond with a 4-bit ACK or NACK. | ||
80 | * Having only 4 bits in the FIFO won't normally generate an interrupt so | ||
81 | * driver enables the '4_bit_RX' bit of the Special Functions register 1 | ||
82 | * to cause an interrupt in that case. Leaving that bit for a read command | ||
83 | * messes up the data returned so it is only enabled when the framing is | ||
84 | * 'NFC_DIGITAL_FRAMING_NFCA_T2T' and the command is not a read command. | ||
85 | * Unfortunately, that means that the driver has to peek into tx frames | ||
86 | * when the framing is 'NFC_DIGITAL_FRAMING_NFCA_T2T'. This is done by | ||
87 | * the trf7970a_per_cmd_config() routine. | ||
88 | * | ||
89 | * ISO/IEC 15693 frames specify whether to use single or double sub-carrier | ||
90 | * frequencies and whether to use low or high data rates in the flags byte | ||
91 | * of the frame. This means that the driver has to peek at all 15693 frames | ||
92 | * to determine what speed to set the communication to. In addition, write | ||
93 | * and lock commands use the OPTION flag to indicate that an EOF must be | ||
94 | * sent to the tag before it will send its response. So the driver has to | ||
95 | * examine all frames for that reason too. | ||
96 | * | ||
97 | * It is unclear how long to wait before sending the EOF. According to the | ||
98 | * Note under Table 1-1 in section 1.6 of | ||
99 | * http://www.ti.com/lit/ug/scbu011/scbu011.pdf, that wait should be at least | ||
100 | * 10 ms for TI Tag-it HF-I tags; however testing has shown that is not long | ||
101 | * enough. For this reason, the driver waits 20 ms which seems to work | ||
102 | * reliably. | ||
103 | */ | ||
104 | |||
105 | #define TRF7970A_SUPPORTED_PROTOCOLS \ | ||
106 | (NFC_PROTO_MIFARE_MASK | NFC_PROTO_ISO14443_MASK | \ | ||
107 | NFC_PROTO_ISO15693_MASK) | ||
108 | |||
109 | /* TX data must be prefixed with a FIFO reset cmd, a cmd that depends | ||
110 | * on what the current framing is, the address of the TX length byte 1 | ||
111 | * register (0x1d), and the 2 byte length of the data to be transmitted. | ||
112 | * That totals 5 bytes. | ||
113 | */ | ||
114 | #define TRF7970A_TX_SKB_HEADROOM 5 | ||
115 | |||
116 | #define TRF7970A_RX_SKB_ALLOC_SIZE 256 | ||
117 | |||
118 | #define TRF7970A_FIFO_SIZE 128 | ||
119 | |||
120 | /* TX length is 3 nibbles long ==> 4KB - 1 bytes max */ | ||
121 | #define TRF7970A_TX_MAX (4096 - 1) | ||
122 | |||
123 | #define TRF7970A_WAIT_FOR_RX_DATA_TIMEOUT 5 | ||
124 | #define TRF7970A_WAIT_FOR_FIFO_DRAIN_TIMEOUT 3 | ||
125 | #define TRF7970A_WAIT_TO_ISSUE_ISO15693_EOF 20 | ||
126 | |||
127 | /* Quirks */ | ||
128 | /* Erratum: When reading IRQ Status register on trf7970a, we must issue a | ||
129 | * read continuous command for IRQ Status and Collision Position registers. | ||
130 | */ | ||
131 | #define TRF7970A_QUIRK_IRQ_STATUS_READ_ERRATA BIT(0) | ||
132 | |||
133 | /* Direct commands */ | ||
134 | #define TRF7970A_CMD_IDLE 0x00 | ||
135 | #define TRF7970A_CMD_SOFT_INIT 0x03 | ||
136 | #define TRF7970A_CMD_RF_COLLISION 0x04 | ||
137 | #define TRF7970A_CMD_RF_COLLISION_RESPONSE_N 0x05 | ||
138 | #define TRF7970A_CMD_RF_COLLISION_RESPONSE_0 0x06 | ||
139 | #define TRF7970A_CMD_FIFO_RESET 0x0f | ||
140 | #define TRF7970A_CMD_TRANSMIT_NO_CRC 0x10 | ||
141 | #define TRF7970A_CMD_TRANSMIT 0x11 | ||
142 | #define TRF7970A_CMD_DELAY_TRANSMIT_NO_CRC 0x12 | ||
143 | #define TRF7970A_CMD_DELAY_TRANSMIT 0x13 | ||
144 | #define TRF7970A_CMD_EOF 0x14 | ||
145 | #define TRF7970A_CMD_CLOSE_SLOT 0x15 | ||
146 | #define TRF7970A_CMD_BLOCK_RX 0x16 | ||
147 | #define TRF7970A_CMD_ENABLE_RX 0x17 | ||
148 | #define TRF7970A_CMD_TEST_EXT_RF 0x18 | ||
149 | #define TRF7970A_CMD_TEST_INT_RF 0x19 | ||
150 | #define TRF7970A_CMD_RX_GAIN_ADJUST 0x1a | ||
151 | |||
152 | /* Bits determining whether its a direct command or register R/W, | ||
153 | * whether to use a continuous SPI transaction or not, and the actual | ||
154 | * direct cmd opcode or regster address. | ||
155 | */ | ||
156 | #define TRF7970A_CMD_BIT_CTRL BIT(7) | ||
157 | #define TRF7970A_CMD_BIT_RW BIT(6) | ||
158 | #define TRF7970A_CMD_BIT_CONTINUOUS BIT(5) | ||
159 | #define TRF7970A_CMD_BIT_OPCODE(opcode) ((opcode) & 0x1f) | ||
160 | |||
161 | /* Registers addresses */ | ||
162 | #define TRF7970A_CHIP_STATUS_CTRL 0x00 | ||
163 | #define TRF7970A_ISO_CTRL 0x01 | ||
164 | #define TRF7970A_ISO14443B_TX_OPTIONS 0x02 | ||
165 | #define TRF7970A_ISO14443A_HIGH_BITRATE_OPTIONS 0x03 | ||
166 | #define TRF7970A_TX_TIMER_SETTING_H_BYTE 0x04 | ||
167 | #define TRF7970A_TX_TIMER_SETTING_L_BYTE 0x05 | ||
168 | #define TRF7970A_TX_PULSE_LENGTH_CTRL 0x06 | ||
169 | #define TRF7970A_RX_NO_RESPONSE_WAIT 0x07 | ||
170 | #define TRF7970A_RX_WAIT_TIME 0x08 | ||
171 | #define TRF7970A_MODULATOR_SYS_CLK_CTRL 0x09 | ||
172 | #define TRF7970A_RX_SPECIAL_SETTINGS 0x0a | ||
173 | #define TRF7970A_REG_IO_CTRL 0x0b | ||
174 | #define TRF7970A_IRQ_STATUS 0x0c | ||
175 | #define TRF7970A_COLLISION_IRQ_MASK 0x0d | ||
176 | #define TRF7970A_COLLISION_POSITION 0x0e | ||
177 | #define TRF7970A_RSSI_OSC_STATUS 0x0f | ||
178 | #define TRF7970A_SPECIAL_FCN_REG1 0x10 | ||
179 | #define TRF7970A_SPECIAL_FCN_REG2 0x11 | ||
180 | #define TRF7970A_RAM1 0x12 | ||
181 | #define TRF7970A_RAM2 0x13 | ||
182 | #define TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS 0x14 | ||
183 | #define TRF7970A_NFC_LOW_FIELD_LEVEL 0x16 | ||
184 | #define TRF7970A_NFCID1 0x17 | ||
185 | #define TRF7970A_NFC_TARGET_LEVEL 0x18 | ||
186 | #define TRF79070A_NFC_TARGET_PROTOCOL 0x19 | ||
187 | #define TRF7970A_TEST_REGISTER1 0x1a | ||
188 | #define TRF7970A_TEST_REGISTER2 0x1b | ||
189 | #define TRF7970A_FIFO_STATUS 0x1c | ||
190 | #define TRF7970A_TX_LENGTH_BYTE1 0x1d | ||
191 | #define TRF7970A_TX_LENGTH_BYTE2 0x1e | ||
192 | #define TRF7970A_FIFO_IO_REGISTER 0x1f | ||
193 | |||
194 | /* Chip Status Control Register Bits */ | ||
195 | #define TRF7970A_CHIP_STATUS_VRS5_3 BIT(0) | ||
196 | #define TRF7970A_CHIP_STATUS_REC_ON BIT(1) | ||
197 | #define TRF7970A_CHIP_STATUS_AGC_ON BIT(2) | ||
198 | #define TRF7970A_CHIP_STATUS_PM_ON BIT(3) | ||
199 | #define TRF7970A_CHIP_STATUS_RF_PWR BIT(4) | ||
200 | #define TRF7970A_CHIP_STATUS_RF_ON BIT(5) | ||
201 | #define TRF7970A_CHIP_STATUS_DIRECT BIT(6) | ||
202 | #define TRF7970A_CHIP_STATUS_STBY BIT(7) | ||
203 | |||
204 | /* ISO Control Register Bits */ | ||
205 | #define TRF7970A_ISO_CTRL_15693_SGL_1OF4_662 0x00 | ||
206 | #define TRF7970A_ISO_CTRL_15693_SGL_1OF256_662 0x01 | ||
207 | #define TRF7970A_ISO_CTRL_15693_SGL_1OF4_2648 0x02 | ||
208 | #define TRF7970A_ISO_CTRL_15693_SGL_1OF256_2648 0x03 | ||
209 | #define TRF7970A_ISO_CTRL_15693_DBL_1OF4_667a 0x04 | ||
210 | #define TRF7970A_ISO_CTRL_15693_DBL_1OF256_667 0x05 | ||
211 | #define TRF7970A_ISO_CTRL_15693_DBL_1OF4_2669 0x06 | ||
212 | #define TRF7970A_ISO_CTRL_15693_DBL_1OF256_2669 0x07 | ||
213 | #define TRF7970A_ISO_CTRL_14443A_106 0x08 | ||
214 | #define TRF7970A_ISO_CTRL_14443A_212 0x09 | ||
215 | #define TRF7970A_ISO_CTRL_14443A_424 0x0a | ||
216 | #define TRF7970A_ISO_CTRL_14443A_848 0x0b | ||
217 | #define TRF7970A_ISO_CTRL_14443B_106 0x0c | ||
218 | #define TRF7970A_ISO_CTRL_14443B_212 0x0d | ||
219 | #define TRF7970A_ISO_CTRL_14443B_424 0x0e | ||
220 | #define TRF7970A_ISO_CTRL_14443B_848 0x0f | ||
221 | #define TRF7970A_ISO_CTRL_FELICA_212 0x1a | ||
222 | #define TRF7970A_ISO_CTRL_FELICA_424 0x1b | ||
223 | #define TRF7970A_ISO_CTRL_RFID BIT(5) | ||
224 | #define TRF7970A_ISO_CTRL_DIR_MODE BIT(6) | ||
225 | #define TRF7970A_ISO_CTRL_RX_CRC_N BIT(7) /* true == No CRC */ | ||
226 | |||
227 | #define TRF7970A_ISO_CTRL_RFID_SPEED_MASK 0x1f | ||
228 | |||
229 | /* Modulator and SYS_CLK Control Register Bits */ | ||
230 | #define TRF7970A_MODULATOR_DEPTH(n) ((n) & 0x7) | ||
231 | #define TRF7970A_MODULATOR_DEPTH_ASK10 (TRF7970A_MODULATOR_DEPTH(0)) | ||
232 | #define TRF7970A_MODULATOR_DEPTH_OOK (TRF7970A_MODULATOR_DEPTH(1)) | ||
233 | #define TRF7970A_MODULATOR_DEPTH_ASK7 (TRF7970A_MODULATOR_DEPTH(2)) | ||
234 | #define TRF7970A_MODULATOR_DEPTH_ASK8_5 (TRF7970A_MODULATOR_DEPTH(3)) | ||
235 | #define TRF7970A_MODULATOR_DEPTH_ASK13 (TRF7970A_MODULATOR_DEPTH(4)) | ||
236 | #define TRF7970A_MODULATOR_DEPTH_ASK16 (TRF7970A_MODULATOR_DEPTH(5)) | ||
237 | #define TRF7970A_MODULATOR_DEPTH_ASK22 (TRF7970A_MODULATOR_DEPTH(6)) | ||
238 | #define TRF7970A_MODULATOR_DEPTH_ASK30 (TRF7970A_MODULATOR_DEPTH(7)) | ||
239 | #define TRF7970A_MODULATOR_EN_ANA BIT(3) | ||
240 | #define TRF7970A_MODULATOR_CLK(n) (((n) & 0x3) << 4) | ||
241 | #define TRF7970A_MODULATOR_CLK_DISABLED (TRF7970A_MODULATOR_CLK(0)) | ||
242 | #define TRF7970A_MODULATOR_CLK_3_6 (TRF7970A_MODULATOR_CLK(1)) | ||
243 | #define TRF7970A_MODULATOR_CLK_6_13 (TRF7970A_MODULATOR_CLK(2)) | ||
244 | #define TRF7970A_MODULATOR_CLK_13_27 (TRF7970A_MODULATOR_CLK(3)) | ||
245 | #define TRF7970A_MODULATOR_EN_OOK BIT(6) | ||
246 | #define TRF7970A_MODULATOR_27MHZ BIT(7) | ||
247 | |||
248 | /* IRQ Status Register Bits */ | ||
249 | #define TRF7970A_IRQ_STATUS_NORESP BIT(0) /* ISO15693 only */ | ||
250 | #define TRF7970A_IRQ_STATUS_COL BIT(1) | ||
251 | #define TRF7970A_IRQ_STATUS_FRAMING_EOF_ERROR BIT(2) | ||
252 | #define TRF7970A_IRQ_STATUS_PARITY_ERROR BIT(3) | ||
253 | #define TRF7970A_IRQ_STATUS_CRC_ERROR BIT(4) | ||
254 | #define TRF7970A_IRQ_STATUS_FIFO BIT(5) | ||
255 | #define TRF7970A_IRQ_STATUS_SRX BIT(6) | ||
256 | #define TRF7970A_IRQ_STATUS_TX BIT(7) | ||
257 | |||
258 | #define TRF7970A_IRQ_STATUS_ERROR \ | ||
259 | (TRF7970A_IRQ_STATUS_COL | \ | ||
260 | TRF7970A_IRQ_STATUS_FRAMING_EOF_ERROR | \ | ||
261 | TRF7970A_IRQ_STATUS_PARITY_ERROR | \ | ||
262 | TRF7970A_IRQ_STATUS_CRC_ERROR) | ||
263 | |||
264 | #define TRF7970A_SPECIAL_FCN_REG1_COL_7_6 BIT(0) | ||
265 | #define TRF7970A_SPECIAL_FCN_REG1_14_ANTICOLL BIT(1) | ||
266 | #define TRF7970A_SPECIAL_FCN_REG1_4_BIT_RX BIT(2) | ||
267 | #define TRF7970A_SPECIAL_FCN_REG1_SP_DIR_MODE BIT(3) | ||
268 | #define TRF7970A_SPECIAL_FCN_REG1_NEXT_SLOT_37US BIT(4) | ||
269 | #define TRF7970A_SPECIAL_FCN_REG1_PAR43 BIT(5) | ||
270 | |||
271 | #define TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS_WLH_124 (0x0 << 2) | ||
272 | #define TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS_WLH_120 (0x1 << 2) | ||
273 | #define TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS_WLH_112 (0x2 << 2) | ||
274 | #define TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS_WLH_96 (0x3 << 2) | ||
275 | #define TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS_WLL_4 0x0 | ||
276 | #define TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS_WLL_8 0x1 | ||
277 | #define TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS_WLL_16 0x2 | ||
278 | #define TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS_WLL_32 0x3 | ||
279 | |||
280 | #define TRF7970A_FIFO_STATUS_OVERFLOW BIT(7) | ||
281 | |||
282 | /* NFC (ISO/IEC 14443A) Type 2 Tag commands */ | ||
283 | #define NFC_T2T_CMD_READ 0x30 | ||
284 | |||
285 | /* ISO 15693 commands codes */ | ||
286 | #define ISO15693_CMD_INVENTORY 0x01 | ||
287 | #define ISO15693_CMD_READ_SINGLE_BLOCK 0x20 | ||
288 | #define ISO15693_CMD_WRITE_SINGLE_BLOCK 0x21 | ||
289 | #define ISO15693_CMD_LOCK_BLOCK 0x22 | ||
290 | #define ISO15693_CMD_READ_MULTIPLE_BLOCK 0x23 | ||
291 | #define ISO15693_CMD_WRITE_MULTIPLE_BLOCK 0x24 | ||
292 | #define ISO15693_CMD_SELECT 0x25 | ||
293 | #define ISO15693_CMD_RESET_TO_READY 0x26 | ||
294 | #define ISO15693_CMD_WRITE_AFI 0x27 | ||
295 | #define ISO15693_CMD_LOCK_AFI 0x28 | ||
296 | #define ISO15693_CMD_WRITE_DSFID 0x29 | ||
297 | #define ISO15693_CMD_LOCK_DSFID 0x2a | ||
298 | #define ISO15693_CMD_GET_SYSTEM_INFO 0x2b | ||
299 | #define ISO15693_CMD_GET_MULTIPLE_BLOCK_SECURITY_STATUS 0x2c | ||
300 | |||
301 | /* ISO 15693 request and response flags */ | ||
302 | #define ISO15693_REQ_FLAG_SUB_CARRIER BIT(0) | ||
303 | #define ISO15693_REQ_FLAG_DATA_RATE BIT(1) | ||
304 | #define ISO15693_REQ_FLAG_INVENTORY BIT(2) | ||
305 | #define ISO15693_REQ_FLAG_PROTOCOL_EXT BIT(3) | ||
306 | #define ISO15693_REQ_FLAG_SELECT BIT(4) | ||
307 | #define ISO15693_REQ_FLAG_AFI BIT(4) | ||
308 | #define ISO15693_REQ_FLAG_ADDRESS BIT(5) | ||
309 | #define ISO15693_REQ_FLAG_NB_SLOTS BIT(5) | ||
310 | #define ISO15693_REQ_FLAG_OPTION BIT(6) | ||
311 | |||
312 | #define ISO15693_REQ_FLAG_SPEED_MASK \ | ||
313 | (ISO15693_REQ_FLAG_SUB_CARRIER | ISO15693_REQ_FLAG_DATA_RATE) | ||
314 | |||
315 | enum trf7970a_state { | ||
316 | TRF7970A_ST_OFF, | ||
317 | TRF7970A_ST_IDLE, | ||
318 | TRF7970A_ST_IDLE_RX_BLOCKED, | ||
319 | TRF7970A_ST_WAIT_FOR_TX_FIFO, | ||
320 | TRF7970A_ST_WAIT_FOR_RX_DATA, | ||
321 | TRF7970A_ST_WAIT_FOR_RX_DATA_CONT, | ||
322 | TRF7970A_ST_WAIT_TO_ISSUE_EOF, | ||
323 | TRF7970A_ST_MAX | ||
324 | }; | ||
325 | |||
326 | struct trf7970a { | ||
327 | enum trf7970a_state state; | ||
328 | struct device *dev; | ||
329 | struct spi_device *spi; | ||
330 | struct regulator *regulator; | ||
331 | struct nfc_digital_dev *ddev; | ||
332 | u32 quirks; | ||
333 | bool powering_up; | ||
334 | bool aborting; | ||
335 | struct sk_buff *tx_skb; | ||
336 | struct sk_buff *rx_skb; | ||
337 | nfc_digital_cmd_complete_t cb; | ||
338 | void *cb_arg; | ||
339 | u8 iso_ctrl; | ||
340 | u8 special_fcn_reg1; | ||
341 | int technology; | ||
342 | int framing; | ||
343 | u8 tx_cmd; | ||
344 | bool issue_eof; | ||
345 | int en2_gpio; | ||
346 | int en_gpio; | ||
347 | struct mutex lock; | ||
348 | unsigned int timeout; | ||
349 | bool ignore_timeout; | ||
350 | struct delayed_work timeout_work; | ||
351 | }; | ||
352 | |||
353 | |||
354 | static int trf7970a_cmd(struct trf7970a *trf, u8 opcode) | ||
355 | { | ||
356 | u8 cmd = TRF7970A_CMD_BIT_CTRL | TRF7970A_CMD_BIT_OPCODE(opcode); | ||
357 | int ret; | ||
358 | |||
359 | dev_dbg(trf->dev, "cmd: 0x%x\n", cmd); | ||
360 | |||
361 | ret = spi_write(trf->spi, &cmd, 1); | ||
362 | if (ret) | ||
363 | dev_err(trf->dev, "%s - cmd: 0x%x, ret: %d\n", __func__, cmd, | ||
364 | ret); | ||
365 | return ret; | ||
366 | } | ||
367 | |||
368 | static int trf7970a_read(struct trf7970a *trf, u8 reg, u8 *val) | ||
369 | { | ||
370 | u8 addr = TRF7970A_CMD_BIT_RW | reg; | ||
371 | int ret; | ||
372 | |||
373 | ret = spi_write_then_read(trf->spi, &addr, 1, val, 1); | ||
374 | if (ret) | ||
375 | dev_err(trf->dev, "%s - addr: 0x%x, ret: %d\n", __func__, addr, | ||
376 | ret); | ||
377 | |||
378 | dev_dbg(trf->dev, "read(0x%x): 0x%x\n", addr, *val); | ||
379 | |||
380 | return ret; | ||
381 | } | ||
382 | |||
383 | static int trf7970a_read_cont(struct trf7970a *trf, u8 reg, | ||
384 | u8 *buf, size_t len) | ||
385 | { | ||
386 | u8 addr = reg | TRF7970A_CMD_BIT_RW | TRF7970A_CMD_BIT_CONTINUOUS; | ||
387 | int ret; | ||
388 | |||
389 | dev_dbg(trf->dev, "read_cont(0x%x, %zd)\n", addr, len); | ||
390 | |||
391 | ret = spi_write_then_read(trf->spi, &addr, 1, buf, len); | ||
392 | if (ret) | ||
393 | dev_err(trf->dev, "%s - addr: 0x%x, ret: %d\n", __func__, addr, | ||
394 | ret); | ||
395 | return ret; | ||
396 | } | ||
397 | |||
398 | static int trf7970a_write(struct trf7970a *trf, u8 reg, u8 val) | ||
399 | { | ||
400 | u8 buf[2] = { reg, val }; | ||
401 | int ret; | ||
402 | |||
403 | dev_dbg(trf->dev, "write(0x%x): 0x%x\n", reg, val); | ||
404 | |||
405 | ret = spi_write(trf->spi, buf, 2); | ||
406 | if (ret) | ||
407 | dev_err(trf->dev, "%s - write: 0x%x 0x%x, ret: %d\n", __func__, | ||
408 | buf[0], buf[1], ret); | ||
409 | |||
410 | return ret; | ||
411 | } | ||
412 | |||
413 | static int trf7970a_read_irqstatus(struct trf7970a *trf, u8 *status) | ||
414 | { | ||
415 | int ret; | ||
416 | u8 buf[2]; | ||
417 | u8 addr; | ||
418 | |||
419 | addr = TRF7970A_IRQ_STATUS | TRF7970A_CMD_BIT_RW; | ||
420 | |||
421 | if (trf->quirks & TRF7970A_QUIRK_IRQ_STATUS_READ_ERRATA) { | ||
422 | addr |= TRF7970A_CMD_BIT_CONTINUOUS; | ||
423 | ret = spi_write_then_read(trf->spi, &addr, 1, buf, 2); | ||
424 | } else { | ||
425 | ret = spi_write_then_read(trf->spi, &addr, 1, buf, 1); | ||
426 | } | ||
427 | |||
428 | if (ret) | ||
429 | dev_err(trf->dev, "%s - irqstatus: Status read failed: %d\n", | ||
430 | __func__, ret); | ||
431 | else | ||
432 | *status = buf[0]; | ||
433 | |||
434 | return ret; | ||
435 | } | ||
436 | |||
437 | static void trf7970a_send_upstream(struct trf7970a *trf) | ||
438 | { | ||
439 | u8 rssi; | ||
440 | |||
441 | dev_kfree_skb_any(trf->tx_skb); | ||
442 | trf->tx_skb = NULL; | ||
443 | |||
444 | if (trf->rx_skb && !IS_ERR(trf->rx_skb) && !trf->aborting) | ||
445 | print_hex_dump_debug("trf7970a rx data: ", DUMP_PREFIX_NONE, | ||
446 | 16, 1, trf->rx_skb->data, trf->rx_skb->len, | ||
447 | false); | ||
448 | |||
449 | /* According to the manual it is "good form" to reset the fifo and | ||
450 | * read the RSSI levels & oscillator status register here. It doesn't | ||
451 | * explain why. | ||
452 | */ | ||
453 | trf7970a_cmd(trf, TRF7970A_CMD_FIFO_RESET); | ||
454 | trf7970a_read(trf, TRF7970A_RSSI_OSC_STATUS, &rssi); | ||
455 | |||
456 | trf->state = TRF7970A_ST_IDLE; | ||
457 | |||
458 | if (trf->aborting) { | ||
459 | dev_dbg(trf->dev, "Abort process complete\n"); | ||
460 | |||
461 | if (!IS_ERR(trf->rx_skb)) { | ||
462 | kfree_skb(trf->rx_skb); | ||
463 | trf->rx_skb = ERR_PTR(-ECANCELED); | ||
464 | } | ||
465 | |||
466 | trf->aborting = false; | ||
467 | } | ||
468 | |||
469 | trf->cb(trf->ddev, trf->cb_arg, trf->rx_skb); | ||
470 | |||
471 | trf->rx_skb = NULL; | ||
472 | } | ||
473 | |||
474 | static void trf7970a_send_err_upstream(struct trf7970a *trf, int errno) | ||
475 | { | ||
476 | dev_dbg(trf->dev, "Error - state: %d, errno: %d\n", trf->state, errno); | ||
477 | |||
478 | kfree_skb(trf->rx_skb); | ||
479 | trf->rx_skb = ERR_PTR(errno); | ||
480 | |||
481 | trf7970a_send_upstream(trf); | ||
482 | } | ||
483 | |||
484 | static int trf7970a_transmit(struct trf7970a *trf, struct sk_buff *skb, | ||
485 | unsigned int len) | ||
486 | { | ||
487 | unsigned int timeout; | ||
488 | int ret; | ||
489 | |||
490 | print_hex_dump_debug("trf7970a tx data: ", DUMP_PREFIX_NONE, | ||
491 | 16, 1, skb->data, len, false); | ||
492 | |||
493 | ret = spi_write(trf->spi, skb->data, len); | ||
494 | if (ret) { | ||
495 | dev_err(trf->dev, "%s - Can't send tx data: %d\n", __func__, | ||
496 | ret); | ||
497 | return ret; | ||
498 | } | ||
499 | |||
500 | skb_pull(skb, len); | ||
501 | |||
502 | if (skb->len > 0) { | ||
503 | trf->state = TRF7970A_ST_WAIT_FOR_TX_FIFO; | ||
504 | timeout = TRF7970A_WAIT_FOR_FIFO_DRAIN_TIMEOUT; | ||
505 | } else { | ||
506 | if (trf->issue_eof) { | ||
507 | trf->state = TRF7970A_ST_WAIT_TO_ISSUE_EOF; | ||
508 | timeout = TRF7970A_WAIT_TO_ISSUE_ISO15693_EOF; | ||
509 | } else { | ||
510 | trf->state = TRF7970A_ST_WAIT_FOR_RX_DATA; | ||
511 | timeout = trf->timeout; | ||
512 | } | ||
513 | } | ||
514 | |||
515 | dev_dbg(trf->dev, "Setting timeout for %d ms, state: %d\n", timeout, | ||
516 | trf->state); | ||
517 | |||
518 | schedule_delayed_work(&trf->timeout_work, msecs_to_jiffies(timeout)); | ||
519 | |||
520 | return 0; | ||
521 | } | ||
522 | |||
523 | static void trf7970a_fill_fifo(struct trf7970a *trf) | ||
524 | { | ||
525 | struct sk_buff *skb = trf->tx_skb; | ||
526 | unsigned int len; | ||
527 | int ret; | ||
528 | u8 fifo_bytes; | ||
529 | |||
530 | ret = trf7970a_read(trf, TRF7970A_FIFO_STATUS, &fifo_bytes); | ||
531 | if (ret) { | ||
532 | trf7970a_send_err_upstream(trf, ret); | ||
533 | return; | ||
534 | } | ||
535 | |||
536 | dev_dbg(trf->dev, "Filling FIFO - fifo_bytes: 0x%x\n", fifo_bytes); | ||
537 | |||
538 | if (fifo_bytes & TRF7970A_FIFO_STATUS_OVERFLOW) { | ||
539 | dev_err(trf->dev, "%s - fifo overflow: 0x%x\n", __func__, | ||
540 | fifo_bytes); | ||
541 | trf7970a_send_err_upstream(trf, -EIO); | ||
542 | return; | ||
543 | } | ||
544 | |||
545 | /* Calculate how much more data can be written to the fifo */ | ||
546 | len = TRF7970A_FIFO_SIZE - fifo_bytes; | ||
547 | len = min(skb->len, len); | ||
548 | |||
549 | ret = trf7970a_transmit(trf, skb, len); | ||
550 | if (ret) | ||
551 | trf7970a_send_err_upstream(trf, ret); | ||
552 | } | ||
553 | |||
554 | static void trf7970a_drain_fifo(struct trf7970a *trf, u8 status) | ||
555 | { | ||
556 | struct sk_buff *skb = trf->rx_skb; | ||
557 | int ret; | ||
558 | u8 fifo_bytes; | ||
559 | |||
560 | if (status & TRF7970A_IRQ_STATUS_ERROR) { | ||
561 | trf7970a_send_err_upstream(trf, -EIO); | ||
562 | return; | ||
563 | } | ||
564 | |||
565 | ret = trf7970a_read(trf, TRF7970A_FIFO_STATUS, &fifo_bytes); | ||
566 | if (ret) { | ||
567 | trf7970a_send_err_upstream(trf, ret); | ||
568 | return; | ||
569 | } | ||
570 | |||
571 | dev_dbg(trf->dev, "Draining FIFO - fifo_bytes: 0x%x\n", fifo_bytes); | ||
572 | |||
573 | if (!fifo_bytes) | ||
574 | goto no_rx_data; | ||
575 | |||
576 | if (fifo_bytes & TRF7970A_FIFO_STATUS_OVERFLOW) { | ||
577 | dev_err(trf->dev, "%s - fifo overflow: 0x%x\n", __func__, | ||
578 | fifo_bytes); | ||
579 | trf7970a_send_err_upstream(trf, -EIO); | ||
580 | return; | ||
581 | } | ||
582 | |||
583 | if (fifo_bytes > skb_tailroom(skb)) { | ||
584 | skb = skb_copy_expand(skb, skb_headroom(skb), | ||
585 | max_t(int, fifo_bytes, | ||
586 | TRF7970A_RX_SKB_ALLOC_SIZE), | ||
587 | GFP_KERNEL); | ||
588 | if (!skb) { | ||
589 | trf7970a_send_err_upstream(trf, -ENOMEM); | ||
590 | return; | ||
591 | } | ||
592 | |||
593 | kfree_skb(trf->rx_skb); | ||
594 | trf->rx_skb = skb; | ||
595 | } | ||
596 | |||
597 | ret = trf7970a_read_cont(trf, TRF7970A_FIFO_IO_REGISTER, | ||
598 | skb_put(skb, fifo_bytes), fifo_bytes); | ||
599 | if (ret) { | ||
600 | trf7970a_send_err_upstream(trf, ret); | ||
601 | return; | ||
602 | } | ||
603 | |||
604 | /* If received Type 2 ACK/NACK, shift right 4 bits and pass up */ | ||
605 | if ((trf->framing == NFC_DIGITAL_FRAMING_NFCA_T2T) && (skb->len == 1) && | ||
606 | (trf->special_fcn_reg1 == | ||
607 | TRF7970A_SPECIAL_FCN_REG1_4_BIT_RX)) { | ||
608 | skb->data[0] >>= 4; | ||
609 | status = TRF7970A_IRQ_STATUS_SRX; | ||
610 | } else { | ||
611 | trf->state = TRF7970A_ST_WAIT_FOR_RX_DATA_CONT; | ||
612 | } | ||
613 | |||
614 | no_rx_data: | ||
615 | if (status == TRF7970A_IRQ_STATUS_SRX) { /* Receive complete */ | ||
616 | trf7970a_send_upstream(trf); | ||
617 | return; | ||
618 | } | ||
619 | |||
620 | dev_dbg(trf->dev, "Setting timeout for %d ms\n", | ||
621 | TRF7970A_WAIT_FOR_RX_DATA_TIMEOUT); | ||
622 | |||
623 | schedule_delayed_work(&trf->timeout_work, | ||
624 | msecs_to_jiffies(TRF7970A_WAIT_FOR_RX_DATA_TIMEOUT)); | ||
625 | } | ||
626 | |||
627 | static irqreturn_t trf7970a_irq(int irq, void *dev_id) | ||
628 | { | ||
629 | struct trf7970a *trf = dev_id; | ||
630 | int ret; | ||
631 | u8 status; | ||
632 | |||
633 | mutex_lock(&trf->lock); | ||
634 | |||
635 | if (trf->state == TRF7970A_ST_OFF) { | ||
636 | mutex_unlock(&trf->lock); | ||
637 | return IRQ_NONE; | ||
638 | } | ||
639 | |||
640 | ret = trf7970a_read_irqstatus(trf, &status); | ||
641 | if (ret) { | ||
642 | mutex_unlock(&trf->lock); | ||
643 | return IRQ_NONE; | ||
644 | } | ||
645 | |||
646 | dev_dbg(trf->dev, "IRQ - state: %d, status: 0x%x\n", trf->state, | ||
647 | status); | ||
648 | |||
649 | if (!status) { | ||
650 | mutex_unlock(&trf->lock); | ||
651 | return IRQ_NONE; | ||
652 | } | ||
653 | |||
654 | switch (trf->state) { | ||
655 | case TRF7970A_ST_IDLE: | ||
656 | case TRF7970A_ST_IDLE_RX_BLOCKED: | ||
657 | /* If getting interrupts caused by RF noise, turn off the | ||
658 | * receiver to avoid unnecessary interrupts. It will be | ||
659 | * turned back on in trf7970a_in_send_cmd() when the next | ||
660 | * command is issued. | ||
661 | */ | ||
662 | if (status & TRF7970A_IRQ_STATUS_ERROR) { | ||
663 | trf7970a_cmd(trf, TRF7970A_CMD_BLOCK_RX); | ||
664 | trf->state = TRF7970A_ST_IDLE_RX_BLOCKED; | ||
665 | } | ||
666 | |||
667 | trf7970a_cmd(trf, TRF7970A_CMD_FIFO_RESET); | ||
668 | break; | ||
669 | case TRF7970A_ST_WAIT_FOR_TX_FIFO: | ||
670 | if (status & TRF7970A_IRQ_STATUS_TX) { | ||
671 | trf->ignore_timeout = | ||
672 | !cancel_delayed_work(&trf->timeout_work); | ||
673 | trf7970a_fill_fifo(trf); | ||
674 | } else { | ||
675 | trf7970a_send_err_upstream(trf, -EIO); | ||
676 | } | ||
677 | break; | ||
678 | case TRF7970A_ST_WAIT_FOR_RX_DATA: | ||
679 | case TRF7970A_ST_WAIT_FOR_RX_DATA_CONT: | ||
680 | if (status & TRF7970A_IRQ_STATUS_SRX) { | ||
681 | trf->ignore_timeout = | ||
682 | !cancel_delayed_work(&trf->timeout_work); | ||
683 | trf7970a_drain_fifo(trf, status); | ||
684 | } else if (!(status & TRF7970A_IRQ_STATUS_TX)) { | ||
685 | trf7970a_send_err_upstream(trf, -EIO); | ||
686 | } | ||
687 | break; | ||
688 | case TRF7970A_ST_WAIT_TO_ISSUE_EOF: | ||
689 | if (status != TRF7970A_IRQ_STATUS_TX) | ||
690 | trf7970a_send_err_upstream(trf, -EIO); | ||
691 | break; | ||
692 | default: | ||
693 | dev_err(trf->dev, "%s - Driver in invalid state: %d\n", | ||
694 | __func__, trf->state); | ||
695 | } | ||
696 | |||
697 | mutex_unlock(&trf->lock); | ||
698 | return IRQ_HANDLED; | ||
699 | } | ||
700 | |||
701 | static void trf7970a_issue_eof(struct trf7970a *trf) | ||
702 | { | ||
703 | int ret; | ||
704 | |||
705 | dev_dbg(trf->dev, "Issuing EOF\n"); | ||
706 | |||
707 | ret = trf7970a_cmd(trf, TRF7970A_CMD_FIFO_RESET); | ||
708 | if (ret) | ||
709 | trf7970a_send_err_upstream(trf, ret); | ||
710 | |||
711 | ret = trf7970a_cmd(trf, TRF7970A_CMD_EOF); | ||
712 | if (ret) | ||
713 | trf7970a_send_err_upstream(trf, ret); | ||
714 | |||
715 | trf->state = TRF7970A_ST_WAIT_FOR_RX_DATA; | ||
716 | |||
717 | dev_dbg(trf->dev, "Setting timeout for %d ms, state: %d\n", | ||
718 | trf->timeout, trf->state); | ||
719 | |||
720 | schedule_delayed_work(&trf->timeout_work, | ||
721 | msecs_to_jiffies(trf->timeout)); | ||
722 | } | ||
723 | |||
724 | static void trf7970a_timeout_work_handler(struct work_struct *work) | ||
725 | { | ||
726 | struct trf7970a *trf = container_of(work, struct trf7970a, | ||
727 | timeout_work.work); | ||
728 | |||
729 | dev_dbg(trf->dev, "Timeout - state: %d, ignore_timeout: %d\n", | ||
730 | trf->state, trf->ignore_timeout); | ||
731 | |||
732 | mutex_lock(&trf->lock); | ||
733 | |||
734 | if (trf->ignore_timeout) | ||
735 | trf->ignore_timeout = false; | ||
736 | else if (trf->state == TRF7970A_ST_WAIT_FOR_RX_DATA_CONT) | ||
737 | trf7970a_send_upstream(trf); /* No more rx data so send up */ | ||
738 | else if (trf->state == TRF7970A_ST_WAIT_TO_ISSUE_EOF) | ||
739 | trf7970a_issue_eof(trf); | ||
740 | else | ||
741 | trf7970a_send_err_upstream(trf, -ETIMEDOUT); | ||
742 | |||
743 | mutex_unlock(&trf->lock); | ||
744 | } | ||
745 | |||
746 | static int trf7970a_init(struct trf7970a *trf) | ||
747 | { | ||
748 | int ret; | ||
749 | |||
750 | dev_dbg(trf->dev, "Initializing device - state: %d\n", trf->state); | ||
751 | |||
752 | ret = trf7970a_cmd(trf, TRF7970A_CMD_SOFT_INIT); | ||
753 | if (ret) | ||
754 | goto err_out; | ||
755 | |||
756 | ret = trf7970a_cmd(trf, TRF7970A_CMD_IDLE); | ||
757 | if (ret) | ||
758 | goto err_out; | ||
759 | |||
760 | ret = trf7970a_write(trf, TRF7970A_MODULATOR_SYS_CLK_CTRL, | ||
761 | TRF7970A_MODULATOR_DEPTH_OOK); | ||
762 | if (ret) | ||
763 | goto err_out; | ||
764 | |||
765 | ret = trf7970a_write(trf, TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS, | ||
766 | TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS_WLH_96 | | ||
767 | TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS_WLL_32); | ||
768 | if (ret) | ||
769 | goto err_out; | ||
770 | |||
771 | ret = trf7970a_write(trf, TRF7970A_SPECIAL_FCN_REG1, 0); | ||
772 | if (ret) | ||
773 | goto err_out; | ||
774 | |||
775 | trf->special_fcn_reg1 = 0; | ||
776 | |||
777 | ret = trf7970a_write(trf, TRF7970A_CHIP_STATUS_CTRL, | ||
778 | TRF7970A_CHIP_STATUS_RF_ON | | ||
779 | TRF7970A_CHIP_STATUS_VRS5_3); | ||
780 | if (ret) | ||
781 | goto err_out; | ||
782 | |||
783 | return 0; | ||
784 | |||
785 | err_out: | ||
786 | dev_dbg(trf->dev, "Couldn't init device: %d\n", ret); | ||
787 | return ret; | ||
788 | } | ||
789 | |||
790 | static void trf7970a_switch_rf_off(struct trf7970a *trf) | ||
791 | { | ||
792 | dev_dbg(trf->dev, "Switching rf off\n"); | ||
793 | |||
794 | gpio_set_value(trf->en_gpio, 0); | ||
795 | gpio_set_value(trf->en2_gpio, 0); | ||
796 | |||
797 | trf->aborting = false; | ||
798 | trf->state = TRF7970A_ST_OFF; | ||
799 | } | ||
800 | |||
801 | static int trf7970a_switch_rf_on(struct trf7970a *trf) | ||
802 | { | ||
803 | unsigned long delay; | ||
804 | int ret; | ||
805 | |||
806 | dev_dbg(trf->dev, "Switching rf on\n"); | ||
807 | |||
808 | if (trf->powering_up) | ||
809 | usleep_range(5000, 6000); | ||
810 | |||
811 | gpio_set_value(trf->en2_gpio, 1); | ||
812 | usleep_range(1000, 2000); | ||
813 | gpio_set_value(trf->en_gpio, 1); | ||
814 | |||
815 | /* The delay between enabling the trf7970a and issuing the first | ||
816 | * command is significantly longer the very first time after powering | ||
817 | * up. Make sure the longer delay is only done the first time. | ||
818 | */ | ||
819 | if (trf->powering_up) { | ||
820 | delay = 20000; | ||
821 | trf->powering_up = false; | ||
822 | } else { | ||
823 | delay = 5000; | ||
824 | } | ||
825 | |||
826 | usleep_range(delay, delay + 1000); | ||
827 | |||
828 | ret = trf7970a_init(trf); | ||
829 | if (ret) | ||
830 | trf7970a_switch_rf_off(trf); | ||
831 | else | ||
832 | trf->state = TRF7970A_ST_IDLE; | ||
833 | |||
834 | return ret; | ||
835 | } | ||
836 | |||
837 | static int trf7970a_switch_rf(struct nfc_digital_dev *ddev, bool on) | ||
838 | { | ||
839 | struct trf7970a *trf = nfc_digital_get_drvdata(ddev); | ||
840 | int ret = 0; | ||
841 | |||
842 | dev_dbg(trf->dev, "Switching RF - state: %d, on: %d\n", trf->state, on); | ||
843 | |||
844 | mutex_lock(&trf->lock); | ||
845 | |||
846 | if (on) { | ||
847 | switch (trf->state) { | ||
848 | case TRF7970A_ST_OFF: | ||
849 | ret = trf7970a_switch_rf_on(trf); | ||
850 | break; | ||
851 | case TRF7970A_ST_IDLE: | ||
852 | case TRF7970A_ST_IDLE_RX_BLOCKED: | ||
853 | break; | ||
854 | default: | ||
855 | dev_err(trf->dev, "%s - Invalid request: %d %d\n", | ||
856 | __func__, trf->state, on); | ||
857 | trf7970a_switch_rf_off(trf); | ||
858 | } | ||
859 | } else { | ||
860 | switch (trf->state) { | ||
861 | case TRF7970A_ST_OFF: | ||
862 | break; | ||
863 | default: | ||
864 | dev_err(trf->dev, "%s - Invalid request: %d %d\n", | ||
865 | __func__, trf->state, on); | ||
866 | /* FALLTHROUGH */ | ||
867 | case TRF7970A_ST_IDLE: | ||
868 | case TRF7970A_ST_IDLE_RX_BLOCKED: | ||
869 | trf7970a_switch_rf_off(trf); | ||
870 | } | ||
871 | } | ||
872 | |||
873 | mutex_unlock(&trf->lock); | ||
874 | return ret; | ||
875 | } | ||
876 | |||
877 | static int trf7970a_config_rf_tech(struct trf7970a *trf, int tech) | ||
878 | { | ||
879 | int ret = 0; | ||
880 | |||
881 | dev_dbg(trf->dev, "rf technology: %d\n", tech); | ||
882 | |||
883 | switch (tech) { | ||
884 | case NFC_DIGITAL_RF_TECH_106A: | ||
885 | trf->iso_ctrl = TRF7970A_ISO_CTRL_14443A_106; | ||
886 | break; | ||
887 | case NFC_DIGITAL_RF_TECH_ISO15693: | ||
888 | trf->iso_ctrl = TRF7970A_ISO_CTRL_15693_SGL_1OF4_2648; | ||
889 | break; | ||
890 | default: | ||
891 | dev_dbg(trf->dev, "Unsupported rf technology: %d\n", tech); | ||
892 | return -EINVAL; | ||
893 | } | ||
894 | |||
895 | trf->technology = tech; | ||
896 | |||
897 | return ret; | ||
898 | } | ||
899 | |||
900 | static int trf7970a_config_framing(struct trf7970a *trf, int framing) | ||
901 | { | ||
902 | dev_dbg(trf->dev, "framing: %d\n", framing); | ||
903 | |||
904 | switch (framing) { | ||
905 | case NFC_DIGITAL_FRAMING_NFCA_SHORT: | ||
906 | case NFC_DIGITAL_FRAMING_NFCA_STANDARD: | ||
907 | trf->tx_cmd = TRF7970A_CMD_TRANSMIT_NO_CRC; | ||
908 | trf->iso_ctrl |= TRF7970A_ISO_CTRL_RX_CRC_N; | ||
909 | break; | ||
910 | case NFC_DIGITAL_FRAMING_NFCA_STANDARD_WITH_CRC_A: | ||
911 | case NFC_DIGITAL_FRAMING_NFCA_T4T: | ||
912 | case NFC_DIGITAL_FRAMING_ISO15693_INVENTORY: | ||
913 | case NFC_DIGITAL_FRAMING_ISO15693_T5T: | ||
914 | trf->tx_cmd = TRF7970A_CMD_TRANSMIT; | ||
915 | trf->iso_ctrl &= ~TRF7970A_ISO_CTRL_RX_CRC_N; | ||
916 | break; | ||
917 | case NFC_DIGITAL_FRAMING_NFCA_T2T: | ||
918 | trf->tx_cmd = TRF7970A_CMD_TRANSMIT; | ||
919 | trf->iso_ctrl |= TRF7970A_ISO_CTRL_RX_CRC_N; | ||
920 | break; | ||
921 | default: | ||
922 | dev_dbg(trf->dev, "Unsupported Framing: %d\n", framing); | ||
923 | return -EINVAL; | ||
924 | } | ||
925 | |||
926 | trf->framing = framing; | ||
927 | |||
928 | return trf7970a_write(trf, TRF7970A_ISO_CTRL, trf->iso_ctrl); | ||
929 | } | ||
930 | |||
931 | static int trf7970a_in_configure_hw(struct nfc_digital_dev *ddev, int type, | ||
932 | int param) | ||
933 | { | ||
934 | struct trf7970a *trf = nfc_digital_get_drvdata(ddev); | ||
935 | int ret = 0; | ||
936 | |||
937 | dev_dbg(trf->dev, "Configure hw - type: %d, param: %d\n", type, param); | ||
938 | |||
939 | mutex_lock(&trf->lock); | ||
940 | |||
941 | if (trf->state == TRF7970A_ST_OFF) { | ||
942 | ret = trf7970a_switch_rf_on(trf); | ||
943 | if (ret) | ||
944 | goto err_out; | ||
945 | } | ||
946 | |||
947 | switch (type) { | ||
948 | case NFC_DIGITAL_CONFIG_RF_TECH: | ||
949 | ret = trf7970a_config_rf_tech(trf, param); | ||
950 | break; | ||
951 | case NFC_DIGITAL_CONFIG_FRAMING: | ||
952 | ret = trf7970a_config_framing(trf, param); | ||
953 | break; | ||
954 | default: | ||
955 | dev_dbg(trf->dev, "Unknown type: %d\n", type); | ||
956 | ret = -EINVAL; | ||
957 | } | ||
958 | |||
959 | err_out: | ||
960 | mutex_unlock(&trf->lock); | ||
961 | return ret; | ||
962 | } | ||
963 | |||
964 | static int trf7970a_is_iso15693_write_or_lock(u8 cmd) | ||
965 | { | ||
966 | switch (cmd) { | ||
967 | case ISO15693_CMD_WRITE_SINGLE_BLOCK: | ||
968 | case ISO15693_CMD_LOCK_BLOCK: | ||
969 | case ISO15693_CMD_WRITE_MULTIPLE_BLOCK: | ||
970 | case ISO15693_CMD_WRITE_AFI: | ||
971 | case ISO15693_CMD_LOCK_AFI: | ||
972 | case ISO15693_CMD_WRITE_DSFID: | ||
973 | case ISO15693_CMD_LOCK_DSFID: | ||
974 | return 1; | ||
975 | break; | ||
976 | default: | ||
977 | return 0; | ||
978 | } | ||
979 | } | ||
980 | |||
981 | static int trf7970a_per_cmd_config(struct trf7970a *trf, struct sk_buff *skb) | ||
982 | { | ||
983 | u8 *req = skb->data; | ||
984 | u8 special_fcn_reg1, iso_ctrl; | ||
985 | int ret; | ||
986 | |||
987 | trf->issue_eof = false; | ||
988 | |||
989 | /* When issuing Type 2 read command, make sure the '4_bit_RX' bit in | ||
990 | * special functions register 1 is cleared; otherwise, its a write or | ||
991 | * sector select command and '4_bit_RX' must be set. | ||
992 | * | ||
993 | * When issuing an ISO 15693 command, inspect the flags byte to see | ||
994 | * what speed to use. Also, remember if the OPTION flag is set on | ||
995 | * a Type 5 write or lock command so the driver will know that it | ||
996 | * has to send an EOF in order to get a response. | ||
997 | */ | ||
998 | if ((trf->technology == NFC_DIGITAL_RF_TECH_106A) && | ||
999 | (trf->framing == NFC_DIGITAL_FRAMING_NFCA_T2T)) { | ||
1000 | if (req[0] == NFC_T2T_CMD_READ) | ||
1001 | special_fcn_reg1 = 0; | ||
1002 | else | ||
1003 | special_fcn_reg1 = TRF7970A_SPECIAL_FCN_REG1_4_BIT_RX; | ||
1004 | |||
1005 | if (special_fcn_reg1 != trf->special_fcn_reg1) { | ||
1006 | ret = trf7970a_write(trf, TRF7970A_SPECIAL_FCN_REG1, | ||
1007 | special_fcn_reg1); | ||
1008 | if (ret) | ||
1009 | return ret; | ||
1010 | |||
1011 | trf->special_fcn_reg1 = special_fcn_reg1; | ||
1012 | } | ||
1013 | } else if (trf->technology == NFC_DIGITAL_RF_TECH_ISO15693) { | ||
1014 | iso_ctrl = trf->iso_ctrl & ~TRF7970A_ISO_CTRL_RFID_SPEED_MASK; | ||
1015 | |||
1016 | switch (req[0] & ISO15693_REQ_FLAG_SPEED_MASK) { | ||
1017 | case 0x00: | ||
1018 | iso_ctrl |= TRF7970A_ISO_CTRL_15693_SGL_1OF4_662; | ||
1019 | break; | ||
1020 | case ISO15693_REQ_FLAG_SUB_CARRIER: | ||
1021 | iso_ctrl |= TRF7970A_ISO_CTRL_15693_DBL_1OF4_667a; | ||
1022 | break; | ||
1023 | case ISO15693_REQ_FLAG_DATA_RATE: | ||
1024 | iso_ctrl |= TRF7970A_ISO_CTRL_15693_SGL_1OF4_2648; | ||
1025 | break; | ||
1026 | case (ISO15693_REQ_FLAG_SUB_CARRIER | | ||
1027 | ISO15693_REQ_FLAG_DATA_RATE): | ||
1028 | iso_ctrl |= TRF7970A_ISO_CTRL_15693_DBL_1OF4_2669; | ||
1029 | break; | ||
1030 | } | ||
1031 | |||
1032 | if (iso_ctrl != trf->iso_ctrl) { | ||
1033 | ret = trf7970a_write(trf, TRF7970A_ISO_CTRL, iso_ctrl); | ||
1034 | if (ret) | ||
1035 | return ret; | ||
1036 | |||
1037 | trf->iso_ctrl = iso_ctrl; | ||
1038 | } | ||
1039 | |||
1040 | if ((trf->framing == NFC_DIGITAL_FRAMING_ISO15693_T5T) && | ||
1041 | trf7970a_is_iso15693_write_or_lock(req[1]) && | ||
1042 | (req[0] & ISO15693_REQ_FLAG_OPTION)) | ||
1043 | trf->issue_eof = true; | ||
1044 | } | ||
1045 | |||
1046 | return 0; | ||
1047 | } | ||
1048 | |||
1049 | static int trf7970a_in_send_cmd(struct nfc_digital_dev *ddev, | ||
1050 | struct sk_buff *skb, u16 timeout, | ||
1051 | nfc_digital_cmd_complete_t cb, void *arg) | ||
1052 | { | ||
1053 | struct trf7970a *trf = nfc_digital_get_drvdata(ddev); | ||
1054 | char *prefix; | ||
1055 | unsigned int len; | ||
1056 | int ret; | ||
1057 | |||
1058 | dev_dbg(trf->dev, "New request - state: %d, timeout: %d ms, len: %d\n", | ||
1059 | trf->state, timeout, skb->len); | ||
1060 | |||
1061 | if (skb->len > TRF7970A_TX_MAX) | ||
1062 | return -EINVAL; | ||
1063 | |||
1064 | mutex_lock(&trf->lock); | ||
1065 | |||
1066 | if ((trf->state != TRF7970A_ST_IDLE) && | ||
1067 | (trf->state != TRF7970A_ST_IDLE_RX_BLOCKED)) { | ||
1068 | dev_err(trf->dev, "%s - Bogus state: %d\n", __func__, | ||
1069 | trf->state); | ||
1070 | ret = -EIO; | ||
1071 | goto out_err; | ||
1072 | } | ||
1073 | |||
1074 | if (trf->aborting) { | ||
1075 | dev_dbg(trf->dev, "Abort process complete\n"); | ||
1076 | trf->aborting = false; | ||
1077 | ret = -ECANCELED; | ||
1078 | goto out_err; | ||
1079 | } | ||
1080 | |||
1081 | trf->rx_skb = nfc_alloc_recv_skb(TRF7970A_RX_SKB_ALLOC_SIZE, | ||
1082 | GFP_KERNEL); | ||
1083 | if (!trf->rx_skb) { | ||
1084 | dev_dbg(trf->dev, "Can't alloc rx_skb\n"); | ||
1085 | ret = -ENOMEM; | ||
1086 | goto out_err; | ||
1087 | } | ||
1088 | |||
1089 | if (trf->state == TRF7970A_ST_IDLE_RX_BLOCKED) { | ||
1090 | ret = trf7970a_cmd(trf, TRF7970A_CMD_ENABLE_RX); | ||
1091 | if (ret) | ||
1092 | goto out_err; | ||
1093 | |||
1094 | trf->state = TRF7970A_ST_IDLE; | ||
1095 | } | ||
1096 | |||
1097 | ret = trf7970a_per_cmd_config(trf, skb); | ||
1098 | if (ret) | ||
1099 | goto out_err; | ||
1100 | |||
1101 | trf->ddev = ddev; | ||
1102 | trf->tx_skb = skb; | ||
1103 | trf->cb = cb; | ||
1104 | trf->cb_arg = arg; | ||
1105 | trf->timeout = timeout; | ||
1106 | trf->ignore_timeout = false; | ||
1107 | |||
1108 | len = skb->len; | ||
1109 | prefix = skb_push(skb, TRF7970A_TX_SKB_HEADROOM); | ||
1110 | |||
1111 | /* TX data must be prefixed with a FIFO reset cmd, a cmd that depends | ||
1112 | * on what the current framing is, the address of the TX length byte 1 | ||
1113 | * register (0x1d), and the 2 byte length of the data to be transmitted. | ||
1114 | */ | ||
1115 | prefix[0] = TRF7970A_CMD_BIT_CTRL | | ||
1116 | TRF7970A_CMD_BIT_OPCODE(TRF7970A_CMD_FIFO_RESET); | ||
1117 | prefix[1] = TRF7970A_CMD_BIT_CTRL | | ||
1118 | TRF7970A_CMD_BIT_OPCODE(trf->tx_cmd); | ||
1119 | prefix[2] = TRF7970A_CMD_BIT_CONTINUOUS | TRF7970A_TX_LENGTH_BYTE1; | ||
1120 | |||
1121 | if (trf->framing == NFC_DIGITAL_FRAMING_NFCA_SHORT) { | ||
1122 | prefix[3] = 0x00; | ||
1123 | prefix[4] = 0x0f; /* 7 bits */ | ||
1124 | } else { | ||
1125 | prefix[3] = (len & 0xf00) >> 4; | ||
1126 | prefix[3] |= ((len & 0xf0) >> 4); | ||
1127 | prefix[4] = ((len & 0x0f) << 4); | ||
1128 | } | ||
1129 | |||
1130 | len = min_t(int, skb->len, TRF7970A_FIFO_SIZE); | ||
1131 | |||
1132 | usleep_range(1000, 2000); | ||
1133 | |||
1134 | ret = trf7970a_transmit(trf, skb, len); | ||
1135 | if (ret) { | ||
1136 | kfree_skb(trf->rx_skb); | ||
1137 | trf->rx_skb = NULL; | ||
1138 | } | ||
1139 | |||
1140 | out_err: | ||
1141 | mutex_unlock(&trf->lock); | ||
1142 | return ret; | ||
1143 | } | ||
1144 | |||
1145 | static int trf7970a_tg_configure_hw(struct nfc_digital_dev *ddev, | ||
1146 | int type, int param) | ||
1147 | { | ||
1148 | struct trf7970a *trf = nfc_digital_get_drvdata(ddev); | ||
1149 | |||
1150 | dev_dbg(trf->dev, "Unsupported interface\n"); | ||
1151 | |||
1152 | return -EINVAL; | ||
1153 | } | ||
1154 | |||
1155 | static int trf7970a_tg_send_cmd(struct nfc_digital_dev *ddev, | ||
1156 | struct sk_buff *skb, u16 timeout, | ||
1157 | nfc_digital_cmd_complete_t cb, void *arg) | ||
1158 | { | ||
1159 | struct trf7970a *trf = nfc_digital_get_drvdata(ddev); | ||
1160 | |||
1161 | dev_dbg(trf->dev, "Unsupported interface\n"); | ||
1162 | |||
1163 | return -EINVAL; | ||
1164 | } | ||
1165 | |||
1166 | static int trf7970a_tg_listen(struct nfc_digital_dev *ddev, | ||
1167 | u16 timeout, nfc_digital_cmd_complete_t cb, void *arg) | ||
1168 | { | ||
1169 | struct trf7970a *trf = nfc_digital_get_drvdata(ddev); | ||
1170 | |||
1171 | dev_dbg(trf->dev, "Unsupported interface\n"); | ||
1172 | |||
1173 | return -EINVAL; | ||
1174 | } | ||
1175 | |||
1176 | static int trf7970a_tg_listen_mdaa(struct nfc_digital_dev *ddev, | ||
1177 | struct digital_tg_mdaa_params *mdaa_params, | ||
1178 | u16 timeout, nfc_digital_cmd_complete_t cb, void *arg) | ||
1179 | { | ||
1180 | struct trf7970a *trf = nfc_digital_get_drvdata(ddev); | ||
1181 | |||
1182 | dev_dbg(trf->dev, "Unsupported interface\n"); | ||
1183 | |||
1184 | return -EINVAL; | ||
1185 | } | ||
1186 | |||
1187 | static void trf7970a_abort_cmd(struct nfc_digital_dev *ddev) | ||
1188 | { | ||
1189 | struct trf7970a *trf = nfc_digital_get_drvdata(ddev); | ||
1190 | |||
1191 | dev_dbg(trf->dev, "Abort process initiated\n"); | ||
1192 | |||
1193 | mutex_lock(&trf->lock); | ||
1194 | trf->aborting = true; | ||
1195 | mutex_unlock(&trf->lock); | ||
1196 | } | ||
1197 | |||
1198 | static struct nfc_digital_ops trf7970a_nfc_ops = { | ||
1199 | .in_configure_hw = trf7970a_in_configure_hw, | ||
1200 | .in_send_cmd = trf7970a_in_send_cmd, | ||
1201 | .tg_configure_hw = trf7970a_tg_configure_hw, | ||
1202 | .tg_send_cmd = trf7970a_tg_send_cmd, | ||
1203 | .tg_listen = trf7970a_tg_listen, | ||
1204 | .tg_listen_mdaa = trf7970a_tg_listen_mdaa, | ||
1205 | .switch_rf = trf7970a_switch_rf, | ||
1206 | .abort_cmd = trf7970a_abort_cmd, | ||
1207 | }; | ||
1208 | |||
1209 | static int trf7970a_probe(struct spi_device *spi) | ||
1210 | { | ||
1211 | struct device_node *np = spi->dev.of_node; | ||
1212 | const struct spi_device_id *id = spi_get_device_id(spi); | ||
1213 | struct trf7970a *trf; | ||
1214 | int ret; | ||
1215 | |||
1216 | if (!np) { | ||
1217 | dev_err(&spi->dev, "No Device Tree entry\n"); | ||
1218 | return -EINVAL; | ||
1219 | } | ||
1220 | |||
1221 | trf = devm_kzalloc(&spi->dev, sizeof(*trf), GFP_KERNEL); | ||
1222 | if (!trf) | ||
1223 | return -ENOMEM; | ||
1224 | |||
1225 | trf->state = TRF7970A_ST_OFF; | ||
1226 | trf->dev = &spi->dev; | ||
1227 | trf->spi = spi; | ||
1228 | trf->quirks = id->driver_data; | ||
1229 | |||
1230 | spi->mode = SPI_MODE_1; | ||
1231 | spi->bits_per_word = 8; | ||
1232 | |||
1233 | /* There are two enable pins - both must be present */ | ||
1234 | trf->en_gpio = of_get_named_gpio(np, "ti,enable-gpios", 0); | ||
1235 | if (!gpio_is_valid(trf->en_gpio)) { | ||
1236 | dev_err(trf->dev, "No EN GPIO property\n"); | ||
1237 | return trf->en_gpio; | ||
1238 | } | ||
1239 | |||
1240 | ret = devm_gpio_request_one(trf->dev, trf->en_gpio, | ||
1241 | GPIOF_DIR_OUT | GPIOF_INIT_LOW, "EN"); | ||
1242 | if (ret) { | ||
1243 | dev_err(trf->dev, "Can't request EN GPIO: %d\n", ret); | ||
1244 | return ret; | ||
1245 | } | ||
1246 | |||
1247 | trf->en2_gpio = of_get_named_gpio(np, "ti,enable-gpios", 1); | ||
1248 | if (!gpio_is_valid(trf->en2_gpio)) { | ||
1249 | dev_err(trf->dev, "No EN2 GPIO property\n"); | ||
1250 | return trf->en2_gpio; | ||
1251 | } | ||
1252 | |||
1253 | ret = devm_gpio_request_one(trf->dev, trf->en2_gpio, | ||
1254 | GPIOF_DIR_OUT | GPIOF_INIT_LOW, "EN2"); | ||
1255 | if (ret) { | ||
1256 | dev_err(trf->dev, "Can't request EN2 GPIO: %d\n", ret); | ||
1257 | return ret; | ||
1258 | } | ||
1259 | |||
1260 | ret = devm_request_threaded_irq(trf->dev, spi->irq, NULL, | ||
1261 | trf7970a_irq, IRQF_TRIGGER_RISING | IRQF_ONESHOT, | ||
1262 | "trf7970a", trf); | ||
1263 | if (ret) { | ||
1264 | dev_err(trf->dev, "Can't request IRQ#%d: %d\n", spi->irq, ret); | ||
1265 | return ret; | ||
1266 | } | ||
1267 | |||
1268 | mutex_init(&trf->lock); | ||
1269 | INIT_DELAYED_WORK(&trf->timeout_work, trf7970a_timeout_work_handler); | ||
1270 | |||
1271 | trf->regulator = devm_regulator_get(&spi->dev, "vin"); | ||
1272 | if (IS_ERR(trf->regulator)) { | ||
1273 | ret = PTR_ERR(trf->regulator); | ||
1274 | dev_err(trf->dev, "Can't get VIN regulator: %d\n", ret); | ||
1275 | goto err_destroy_lock; | ||
1276 | } | ||
1277 | |||
1278 | ret = regulator_enable(trf->regulator); | ||
1279 | if (ret) { | ||
1280 | dev_err(trf->dev, "Can't enable VIN: %d\n", ret); | ||
1281 | goto err_destroy_lock; | ||
1282 | } | ||
1283 | |||
1284 | trf->powering_up = true; | ||
1285 | |||
1286 | trf->ddev = nfc_digital_allocate_device(&trf7970a_nfc_ops, | ||
1287 | TRF7970A_SUPPORTED_PROTOCOLS, | ||
1288 | NFC_DIGITAL_DRV_CAPS_IN_CRC, TRF7970A_TX_SKB_HEADROOM, | ||
1289 | 0); | ||
1290 | if (!trf->ddev) { | ||
1291 | dev_err(trf->dev, "Can't allocate NFC digital device\n"); | ||
1292 | ret = -ENOMEM; | ||
1293 | goto err_disable_regulator; | ||
1294 | } | ||
1295 | |||
1296 | nfc_digital_set_parent_dev(trf->ddev, trf->dev); | ||
1297 | nfc_digital_set_drvdata(trf->ddev, trf); | ||
1298 | spi_set_drvdata(spi, trf); | ||
1299 | |||
1300 | ret = nfc_digital_register_device(trf->ddev); | ||
1301 | if (ret) { | ||
1302 | dev_err(trf->dev, "Can't register NFC digital device: %d\n", | ||
1303 | ret); | ||
1304 | goto err_free_ddev; | ||
1305 | } | ||
1306 | |||
1307 | return 0; | ||
1308 | |||
1309 | err_free_ddev: | ||
1310 | nfc_digital_free_device(trf->ddev); | ||
1311 | err_disable_regulator: | ||
1312 | regulator_disable(trf->regulator); | ||
1313 | err_destroy_lock: | ||
1314 | mutex_destroy(&trf->lock); | ||
1315 | return ret; | ||
1316 | } | ||
1317 | |||
1318 | static int trf7970a_remove(struct spi_device *spi) | ||
1319 | { | ||
1320 | struct trf7970a *trf = spi_get_drvdata(spi); | ||
1321 | |||
1322 | mutex_lock(&trf->lock); | ||
1323 | |||
1324 | trf7970a_switch_rf_off(trf); | ||
1325 | trf7970a_init(trf); | ||
1326 | |||
1327 | switch (trf->state) { | ||
1328 | case TRF7970A_ST_WAIT_FOR_TX_FIFO: | ||
1329 | case TRF7970A_ST_WAIT_FOR_RX_DATA: | ||
1330 | case TRF7970A_ST_WAIT_FOR_RX_DATA_CONT: | ||
1331 | case TRF7970A_ST_WAIT_TO_ISSUE_EOF: | ||
1332 | trf7970a_send_err_upstream(trf, -ECANCELED); | ||
1333 | break; | ||
1334 | default: | ||
1335 | break; | ||
1336 | } | ||
1337 | |||
1338 | mutex_unlock(&trf->lock); | ||
1339 | |||
1340 | nfc_digital_unregister_device(trf->ddev); | ||
1341 | nfc_digital_free_device(trf->ddev); | ||
1342 | |||
1343 | regulator_disable(trf->regulator); | ||
1344 | |||
1345 | mutex_destroy(&trf->lock); | ||
1346 | |||
1347 | return 0; | ||
1348 | } | ||
1349 | |||
1350 | static const struct spi_device_id trf7970a_id_table[] = { | ||
1351 | { "trf7970a", TRF7970A_QUIRK_IRQ_STATUS_READ_ERRATA }, | ||
1352 | { } | ||
1353 | }; | ||
1354 | MODULE_DEVICE_TABLE(spi, trf7970a_id_table); | ||
1355 | |||
1356 | static struct spi_driver trf7970a_spi_driver = { | ||
1357 | .probe = trf7970a_probe, | ||
1358 | .remove = trf7970a_remove, | ||
1359 | .id_table = trf7970a_id_table, | ||
1360 | .driver = { | ||
1361 | .name = "trf7970a", | ||
1362 | .owner = THIS_MODULE, | ||
1363 | }, | ||
1364 | }; | ||
1365 | |||
1366 | module_spi_driver(trf7970a_spi_driver); | ||
1367 | |||
1368 | MODULE_AUTHOR("Mark A. Greer <mgreer@animalcreek.com>"); | ||
1369 | MODULE_LICENSE("GPL v2"); | ||
1370 | MODULE_DESCRIPTION("TI trf7970a RFID/NFC Transceiver Driver"); | ||
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 06299048c4f4..f194ccb8539c 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h | |||
@@ -154,6 +154,10 @@ static inline u16 ieee80211_sn_sub(u16 sn1, u16 sn2) | |||
154 | 802.11e clarifies the figure in section 7.1.2. The frame body is | 154 | 802.11e clarifies the figure in section 7.1.2. The frame body is |
155 | up to 2304 octets long (maximum MSDU size) plus any crypt overhead. */ | 155 | up to 2304 octets long (maximum MSDU size) plus any crypt overhead. */ |
156 | #define IEEE80211_MAX_DATA_LEN 2304 | 156 | #define IEEE80211_MAX_DATA_LEN 2304 |
157 | /* 802.11ad extends maximum MSDU size for DMG (freq > 40Ghz) networks | ||
158 | * to 7920 bytes, see 8.2.3 General frame format | ||
159 | */ | ||
160 | #define IEEE80211_MAX_DATA_LEN_DMG 7920 | ||
157 | /* 30 byte 4 addr hdr, 2 byte QoS, 2304 byte MSDU, 12 byte crypt, 4 byte FCS */ | 161 | /* 30 byte 4 addr hdr, 2 byte QoS, 2304 byte MSDU, 12 byte crypt, 4 byte FCS */ |
158 | #define IEEE80211_MAX_FRAME_LEN 2352 | 162 | #define IEEE80211_MAX_FRAME_LEN 2352 |
159 | 163 | ||
diff --git a/include/linux/mmc/sdio_ids.h b/include/linux/mmc/sdio_ids.h index d8836623f36a..0f01fe065424 100644 --- a/include/linux/mmc/sdio_ids.h +++ b/include/linux/mmc/sdio_ids.h | |||
@@ -31,6 +31,7 @@ | |||
31 | #define SDIO_DEVICE_ID_BROADCOM_4334 0x4334 | 31 | #define SDIO_DEVICE_ID_BROADCOM_4334 0x4334 |
32 | #define SDIO_DEVICE_ID_BROADCOM_4335_4339 0x4335 | 32 | #define SDIO_DEVICE_ID_BROADCOM_4335_4339 0x4335 |
33 | #define SDIO_DEVICE_ID_BROADCOM_43362 43362 | 33 | #define SDIO_DEVICE_ID_BROADCOM_43362 43362 |
34 | #define SDIO_DEVICE_ID_BROADCOM_4354 0x4354 | ||
34 | 35 | ||
35 | #define SDIO_VENDOR_ID_INTEL 0x0089 | 36 | #define SDIO_VENDOR_ID_INTEL 0x0089 |
36 | #define SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX 0x1402 | 37 | #define SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX 0x1402 |
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index dbb788e4f265..b8cc39a4a9a5 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
@@ -91,6 +91,13 @@ struct bt_uuid { | |||
91 | u8 svc_hint; | 91 | u8 svc_hint; |
92 | }; | 92 | }; |
93 | 93 | ||
94 | struct smp_csrk { | ||
95 | bdaddr_t bdaddr; | ||
96 | u8 bdaddr_type; | ||
97 | u8 master; | ||
98 | u8 val[16]; | ||
99 | }; | ||
100 | |||
94 | struct smp_ltk { | 101 | struct smp_ltk { |
95 | struct list_head list; | 102 | struct list_head list; |
96 | bdaddr_t bdaddr; | 103 | bdaddr_t bdaddr; |
@@ -1263,8 +1270,10 @@ void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | |||
1263 | void mgmt_discovering(struct hci_dev *hdev, u8 discovering); | 1270 | void mgmt_discovering(struct hci_dev *hdev, u8 discovering); |
1264 | int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); | 1271 | int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); |
1265 | int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); | 1272 | int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); |
1266 | void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key); | 1273 | void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent); |
1267 | void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk); | 1274 | void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk); |
1275 | void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk, | ||
1276 | bool persistent); | ||
1268 | void mgmt_reenable_advertising(struct hci_dev *hdev); | 1277 | void mgmt_reenable_advertising(struct hci_dev *hdev); |
1269 | void mgmt_smp_complete(struct hci_conn *conn, bool complete); | 1278 | void mgmt_smp_complete(struct hci_conn *conn, bool complete); |
1270 | 1279 | ||
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index 0326648fd799..d4b571c2f9fd 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h | |||
@@ -551,3 +551,15 @@ struct mgmt_ev_new_irk { | |||
551 | bdaddr_t rpa; | 551 | bdaddr_t rpa; |
552 | struct mgmt_irk_info irk; | 552 | struct mgmt_irk_info irk; |
553 | } __packed; | 553 | } __packed; |
554 | |||
555 | struct mgmt_csrk_info { | ||
556 | struct mgmt_addr_info addr; | ||
557 | __u8 master; | ||
558 | __u8 val[16]; | ||
559 | } __packed; | ||
560 | |||
561 | #define MGMT_EV_NEW_CSRK 0x0019 | ||
562 | struct mgmt_ev_new_csrk { | ||
563 | __u8 store_hint; | ||
564 | struct mgmt_csrk_info key; | ||
565 | } __packed; | ||
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 8c9ba44fb7cf..f3539a15c411 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -151,6 +151,7 @@ enum ieee80211_channel_flags { | |||
151 | * @dfs_state: current state of this channel. Only relevant if radar is required | 151 | * @dfs_state: current state of this channel. Only relevant if radar is required |
152 | * on this channel. | 152 | * on this channel. |
153 | * @dfs_state_entered: timestamp (jiffies) when the dfs state was entered. | 153 | * @dfs_state_entered: timestamp (jiffies) when the dfs state was entered. |
154 | * @dfs_cac_ms: DFS CAC time in milliseconds, this is valid for DFS channels. | ||
154 | */ | 155 | */ |
155 | struct ieee80211_channel { | 156 | struct ieee80211_channel { |
156 | enum ieee80211_band band; | 157 | enum ieee80211_band band; |
@@ -165,6 +166,7 @@ struct ieee80211_channel { | |||
165 | int orig_mag, orig_mpwr; | 166 | int orig_mag, orig_mpwr; |
166 | enum nl80211_dfs_state dfs_state; | 167 | enum nl80211_dfs_state dfs_state; |
167 | unsigned long dfs_state_entered; | 168 | unsigned long dfs_state_entered; |
169 | unsigned int dfs_cac_ms; | ||
168 | }; | 170 | }; |
169 | 171 | ||
170 | /** | 172 | /** |
@@ -2503,7 +2505,8 @@ struct cfg80211_ops { | |||
2503 | 2505 | ||
2504 | int (*start_radar_detection)(struct wiphy *wiphy, | 2506 | int (*start_radar_detection)(struct wiphy *wiphy, |
2505 | struct net_device *dev, | 2507 | struct net_device *dev, |
2506 | struct cfg80211_chan_def *chandef); | 2508 | struct cfg80211_chan_def *chandef, |
2509 | u32 cac_time_ms); | ||
2507 | int (*update_ft_ies)(struct wiphy *wiphy, struct net_device *dev, | 2510 | int (*update_ft_ies)(struct wiphy *wiphy, struct net_device *dev, |
2508 | struct cfg80211_update_ft_ies_params *ftie); | 2511 | struct cfg80211_update_ft_ies_params *ftie); |
2509 | int (*crit_proto_start)(struct wiphy *wiphy, | 2512 | int (*crit_proto_start)(struct wiphy *wiphy, |
@@ -3180,6 +3183,7 @@ struct cfg80211_cached_keys; | |||
3180 | * @p2p_started: true if this is a P2P Device that has been started | 3183 | * @p2p_started: true if this is a P2P Device that has been started |
3181 | * @cac_started: true if DFS channel availability check has been started | 3184 | * @cac_started: true if DFS channel availability check has been started |
3182 | * @cac_start_time: timestamp (jiffies) when the dfs state was entered. | 3185 | * @cac_start_time: timestamp (jiffies) when the dfs state was entered. |
3186 | * @cac_time_ms: CAC time in ms | ||
3183 | * @ps: powersave mode is enabled | 3187 | * @ps: powersave mode is enabled |
3184 | * @ps_timeout: dynamic powersave timeout | 3188 | * @ps_timeout: dynamic powersave timeout |
3185 | * @ap_unexpected_nlportid: (private) netlink port ID of application | 3189 | * @ap_unexpected_nlportid: (private) netlink port ID of application |
@@ -3235,6 +3239,7 @@ struct wireless_dev { | |||
3235 | 3239 | ||
3236 | bool cac_started; | 3240 | bool cac_started; |
3237 | unsigned long cac_start_time; | 3241 | unsigned long cac_start_time; |
3242 | unsigned int cac_time_ms; | ||
3238 | 3243 | ||
3239 | #ifdef CONFIG_CFG80211_WEXT | 3244 | #ifdef CONFIG_CFG80211_WEXT |
3240 | /* wext data */ | 3245 | /* wext data */ |
@@ -3667,7 +3672,7 @@ void cfg80211_sched_scan_stopped(struct wiphy *wiphy); | |||
3667 | * cfg80211_inform_bss_width_frame - inform cfg80211 of a received BSS frame | 3672 | * cfg80211_inform_bss_width_frame - inform cfg80211 of a received BSS frame |
3668 | * | 3673 | * |
3669 | * @wiphy: the wiphy reporting the BSS | 3674 | * @wiphy: the wiphy reporting the BSS |
3670 | * @channel: The channel the frame was received on | 3675 | * @rx_channel: The channel the frame was received on |
3671 | * @scan_width: width of the control channel | 3676 | * @scan_width: width of the control channel |
3672 | * @mgmt: the management frame (probe response or beacon) | 3677 | * @mgmt: the management frame (probe response or beacon) |
3673 | * @len: length of the management frame | 3678 | * @len: length of the management frame |
@@ -3682,18 +3687,18 @@ void cfg80211_sched_scan_stopped(struct wiphy *wiphy); | |||
3682 | */ | 3687 | */ |
3683 | struct cfg80211_bss * __must_check | 3688 | struct cfg80211_bss * __must_check |
3684 | cfg80211_inform_bss_width_frame(struct wiphy *wiphy, | 3689 | cfg80211_inform_bss_width_frame(struct wiphy *wiphy, |
3685 | struct ieee80211_channel *channel, | 3690 | struct ieee80211_channel *rx_channel, |
3686 | enum nl80211_bss_scan_width scan_width, | 3691 | enum nl80211_bss_scan_width scan_width, |
3687 | struct ieee80211_mgmt *mgmt, size_t len, | 3692 | struct ieee80211_mgmt *mgmt, size_t len, |
3688 | s32 signal, gfp_t gfp); | 3693 | s32 signal, gfp_t gfp); |
3689 | 3694 | ||
3690 | static inline struct cfg80211_bss * __must_check | 3695 | static inline struct cfg80211_bss * __must_check |
3691 | cfg80211_inform_bss_frame(struct wiphy *wiphy, | 3696 | cfg80211_inform_bss_frame(struct wiphy *wiphy, |
3692 | struct ieee80211_channel *channel, | 3697 | struct ieee80211_channel *rx_channel, |
3693 | struct ieee80211_mgmt *mgmt, size_t len, | 3698 | struct ieee80211_mgmt *mgmt, size_t len, |
3694 | s32 signal, gfp_t gfp) | 3699 | s32 signal, gfp_t gfp) |
3695 | { | 3700 | { |
3696 | return cfg80211_inform_bss_width_frame(wiphy, channel, | 3701 | return cfg80211_inform_bss_width_frame(wiphy, rx_channel, |
3697 | NL80211_BSS_CHAN_WIDTH_20, | 3702 | NL80211_BSS_CHAN_WIDTH_20, |
3698 | mgmt, len, signal, gfp); | 3703 | mgmt, len, signal, gfp); |
3699 | } | 3704 | } |
@@ -3702,7 +3707,7 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy, | |||
3702 | * cfg80211_inform_bss - inform cfg80211 of a new BSS | 3707 | * cfg80211_inform_bss - inform cfg80211 of a new BSS |
3703 | * | 3708 | * |
3704 | * @wiphy: the wiphy reporting the BSS | 3709 | * @wiphy: the wiphy reporting the BSS |
3705 | * @channel: The channel the frame was received on | 3710 | * @rx_channel: The channel the frame was received on |
3706 | * @scan_width: width of the control channel | 3711 | * @scan_width: width of the control channel |
3707 | * @bssid: the BSSID of the BSS | 3712 | * @bssid: the BSSID of the BSS |
3708 | * @tsf: the TSF sent by the peer in the beacon/probe response (or 0) | 3713 | * @tsf: the TSF sent by the peer in the beacon/probe response (or 0) |
@@ -3721,7 +3726,7 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy, | |||
3721 | */ | 3726 | */ |
3722 | struct cfg80211_bss * __must_check | 3727 | struct cfg80211_bss * __must_check |
3723 | cfg80211_inform_bss_width(struct wiphy *wiphy, | 3728 | cfg80211_inform_bss_width(struct wiphy *wiphy, |
3724 | struct ieee80211_channel *channel, | 3729 | struct ieee80211_channel *rx_channel, |
3725 | enum nl80211_bss_scan_width scan_width, | 3730 | enum nl80211_bss_scan_width scan_width, |
3726 | const u8 *bssid, u64 tsf, u16 capability, | 3731 | const u8 *bssid, u64 tsf, u16 capability, |
3727 | u16 beacon_interval, const u8 *ie, size_t ielen, | 3732 | u16 beacon_interval, const u8 *ie, size_t ielen, |
@@ -3729,12 +3734,12 @@ cfg80211_inform_bss_width(struct wiphy *wiphy, | |||
3729 | 3734 | ||
3730 | static inline struct cfg80211_bss * __must_check | 3735 | static inline struct cfg80211_bss * __must_check |
3731 | cfg80211_inform_bss(struct wiphy *wiphy, | 3736 | cfg80211_inform_bss(struct wiphy *wiphy, |
3732 | struct ieee80211_channel *channel, | 3737 | struct ieee80211_channel *rx_channel, |
3733 | const u8 *bssid, u64 tsf, u16 capability, | 3738 | const u8 *bssid, u64 tsf, u16 capability, |
3734 | u16 beacon_interval, const u8 *ie, size_t ielen, | 3739 | u16 beacon_interval, const u8 *ie, size_t ielen, |
3735 | s32 signal, gfp_t gfp) | 3740 | s32 signal, gfp_t gfp) |
3736 | { | 3741 | { |
3737 | return cfg80211_inform_bss_width(wiphy, channel, | 3742 | return cfg80211_inform_bss_width(wiphy, rx_channel, |
3738 | NL80211_BSS_CHAN_WIDTH_20, | 3743 | NL80211_BSS_CHAN_WIDTH_20, |
3739 | bssid, tsf, capability, | 3744 | bssid, tsf, capability, |
3740 | beacon_interval, ie, ielen, signal, | 3745 | beacon_interval, ie, ielen, signal, |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 86faa413b37d..2de7ff42ff3a 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -697,11 +697,11 @@ struct ieee80211_tx_info { | |||
697 | } control; | 697 | } control; |
698 | struct { | 698 | struct { |
699 | struct ieee80211_tx_rate rates[IEEE80211_TX_MAX_RATES]; | 699 | struct ieee80211_tx_rate rates[IEEE80211_TX_MAX_RATES]; |
700 | int ack_signal; | 700 | s32 ack_signal; |
701 | u8 ampdu_ack_len; | 701 | u8 ampdu_ack_len; |
702 | u8 ampdu_len; | 702 | u8 ampdu_len; |
703 | u8 antenna; | 703 | u8 antenna; |
704 | /* 21 bytes free */ | 704 | void *status_driver_data[21 / sizeof(void *)]; |
705 | } status; | 705 | } status; |
706 | struct { | 706 | struct { |
707 | struct ieee80211_tx_rate driver_rates[ | 707 | struct ieee80211_tx_rate driver_rates[ |
@@ -877,11 +877,13 @@ enum mac80211_rx_flags { | |||
877 | * @RX_VHT_FLAG_80MHZ: 80 MHz was used | 877 | * @RX_VHT_FLAG_80MHZ: 80 MHz was used |
878 | * @RX_VHT_FLAG_80P80MHZ: 80+80 MHz was used | 878 | * @RX_VHT_FLAG_80P80MHZ: 80+80 MHz was used |
879 | * @RX_VHT_FLAG_160MHZ: 160 MHz was used | 879 | * @RX_VHT_FLAG_160MHZ: 160 MHz was used |
880 | * @RX_VHT_FLAG_BF: packet was beamformed | ||
880 | */ | 881 | */ |
881 | enum mac80211_rx_vht_flags { | 882 | enum mac80211_rx_vht_flags { |
882 | RX_VHT_FLAG_80MHZ = BIT(0), | 883 | RX_VHT_FLAG_80MHZ = BIT(0), |
883 | RX_VHT_FLAG_80P80MHZ = BIT(1), | 884 | RX_VHT_FLAG_80P80MHZ = BIT(1), |
884 | RX_VHT_FLAG_160MHZ = BIT(2), | 885 | RX_VHT_FLAG_160MHZ = BIT(2), |
886 | RX_VHT_FLAG_BF = BIT(3), | ||
885 | }; | 887 | }; |
886 | 888 | ||
887 | /** | 889 | /** |
diff --git a/include/net/nfc/digital.h b/include/net/nfc/digital.h index 81af21e9bcd4..7655cfe27c34 100644 --- a/include/net/nfc/digital.h +++ b/include/net/nfc/digital.h | |||
@@ -35,6 +35,7 @@ enum { | |||
35 | NFC_DIGITAL_RF_TECH_106A = 0, | 35 | NFC_DIGITAL_RF_TECH_106A = 0, |
36 | NFC_DIGITAL_RF_TECH_212F, | 36 | NFC_DIGITAL_RF_TECH_212F, |
37 | NFC_DIGITAL_RF_TECH_424F, | 37 | NFC_DIGITAL_RF_TECH_424F, |
38 | NFC_DIGITAL_RF_TECH_ISO15693, | ||
38 | 39 | ||
39 | NFC_DIGITAL_RF_TECH_LAST, | 40 | NFC_DIGITAL_RF_TECH_LAST, |
40 | }; | 41 | }; |
@@ -50,6 +51,7 @@ enum { | |||
50 | 51 | ||
51 | NFC_DIGITAL_FRAMING_NFCA_T1T, | 52 | NFC_DIGITAL_FRAMING_NFCA_T1T, |
52 | NFC_DIGITAL_FRAMING_NFCA_T2T, | 53 | NFC_DIGITAL_FRAMING_NFCA_T2T, |
54 | NFC_DIGITAL_FRAMING_NFCA_T4T, | ||
53 | NFC_DIGITAL_FRAMING_NFCA_NFC_DEP, | 55 | NFC_DIGITAL_FRAMING_NFCA_NFC_DEP, |
54 | 56 | ||
55 | NFC_DIGITAL_FRAMING_NFCF, | 57 | NFC_DIGITAL_FRAMING_NFCF, |
@@ -57,6 +59,9 @@ enum { | |||
57 | NFC_DIGITAL_FRAMING_NFCF_NFC_DEP, | 59 | NFC_DIGITAL_FRAMING_NFCF_NFC_DEP, |
58 | NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED, | 60 | NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED, |
59 | 61 | ||
62 | NFC_DIGITAL_FRAMING_ISO15693_INVENTORY, | ||
63 | NFC_DIGITAL_FRAMING_ISO15693_T5T, | ||
64 | |||
60 | NFC_DIGITAL_FRAMING_LAST, | 65 | NFC_DIGITAL_FRAMING_LAST, |
61 | }; | 66 | }; |
62 | 67 | ||
@@ -204,6 +209,8 @@ struct nfc_digital_dev { | |||
204 | u8 curr_rf_tech; | 209 | u8 curr_rf_tech; |
205 | u8 curr_nfc_dep_pni; | 210 | u8 curr_nfc_dep_pni; |
206 | 211 | ||
212 | u16 target_fsc; | ||
213 | |||
207 | int (*skb_check_crc)(struct sk_buff *skb); | 214 | int (*skb_check_crc)(struct sk_buff *skb); |
208 | void (*skb_add_crc)(struct sk_buff *skb); | 215 | void (*skb_add_crc)(struct sk_buff *skb); |
209 | }; | 216 | }; |
diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h index e80894bca1d0..2e8b40c16274 100644 --- a/include/net/nfc/nfc.h +++ b/include/net/nfc/nfc.h | |||
@@ -111,6 +111,9 @@ struct nfc_target { | |||
111 | u8 sensf_res[NFC_SENSF_RES_MAXSIZE]; | 111 | u8 sensf_res[NFC_SENSF_RES_MAXSIZE]; |
112 | u8 hci_reader_gate; | 112 | u8 hci_reader_gate; |
113 | u8 logical_idx; | 113 | u8 logical_idx; |
114 | u8 is_iso15693; | ||
115 | u8 iso15693_dsfid; | ||
116 | u8 iso15693_uid[NFC_ISO15693_UID_MAXSIZE]; | ||
114 | }; | 117 | }; |
115 | 118 | ||
116 | /** | 119 | /** |
diff --git a/include/net/regulatory.h b/include/net/regulatory.h index b07cdc9fa454..75fc1f5a948d 100644 --- a/include/net/regulatory.h +++ b/include/net/regulatory.h | |||
@@ -155,6 +155,7 @@ struct ieee80211_reg_rule { | |||
155 | struct ieee80211_freq_range freq_range; | 155 | struct ieee80211_freq_range freq_range; |
156 | struct ieee80211_power_rule power_rule; | 156 | struct ieee80211_power_rule power_rule; |
157 | u32 flags; | 157 | u32 flags; |
158 | u32 dfs_cac_ms; | ||
158 | }; | 159 | }; |
159 | 160 | ||
160 | struct ieee80211_regdomain { | 161 | struct ieee80211_regdomain { |
@@ -172,14 +173,18 @@ struct ieee80211_regdomain { | |||
172 | #define DBM_TO_MBM(gain) ((gain) * 100) | 173 | #define DBM_TO_MBM(gain) ((gain) * 100) |
173 | #define MBM_TO_DBM(gain) ((gain) / 100) | 174 | #define MBM_TO_DBM(gain) ((gain) / 100) |
174 | 175 | ||
175 | #define REG_RULE(start, end, bw, gain, eirp, reg_flags) \ | 176 | #define REG_RULE_EXT(start, end, bw, gain, eirp, dfs_cac, reg_flags) \ |
176 | { \ | 177 | { \ |
177 | .freq_range.start_freq_khz = MHZ_TO_KHZ(start), \ | 178 | .freq_range.start_freq_khz = MHZ_TO_KHZ(start), \ |
178 | .freq_range.end_freq_khz = MHZ_TO_KHZ(end), \ | 179 | .freq_range.end_freq_khz = MHZ_TO_KHZ(end), \ |
179 | .freq_range.max_bandwidth_khz = MHZ_TO_KHZ(bw), \ | 180 | .freq_range.max_bandwidth_khz = MHZ_TO_KHZ(bw), \ |
180 | .power_rule.max_antenna_gain = DBI_TO_MBI(gain),\ | 181 | .power_rule.max_antenna_gain = DBI_TO_MBI(gain), \ |
181 | .power_rule.max_eirp = DBM_TO_MBM(eirp), \ | 182 | .power_rule.max_eirp = DBM_TO_MBM(eirp), \ |
182 | .flags = reg_flags, \ | 183 | .flags = reg_flags, \ |
184 | .dfs_cac_ms = dfs_cac, \ | ||
183 | } | 185 | } |
184 | 186 | ||
187 | #define REG_RULE(start, end, bw, gain, eirp, reg_flags) \ | ||
188 | REG_RULE_EXT(start, end, bw, gain, eirp, 0, reg_flags) | ||
189 | |||
185 | #endif | 190 | #endif |
diff --git a/include/uapi/linux/nfc.h b/include/uapi/linux/nfc.h index 6ad6cc03ccd3..9789dc95b6a8 100644 --- a/include/uapi/linux/nfc.h +++ b/include/uapi/linux/nfc.h | |||
@@ -150,6 +150,8 @@ enum nfc_commands { | |||
150 | * @NFC_ATTR_SE_TYPE: Secure element type (UICC or EMBEDDED) | 150 | * @NFC_ATTR_SE_TYPE: Secure element type (UICC or EMBEDDED) |
151 | * @NFC_ATTR_FIRMWARE_DOWNLOAD_STATUS: Firmware download operation status | 151 | * @NFC_ATTR_FIRMWARE_DOWNLOAD_STATUS: Firmware download operation status |
152 | * @NFC_ATTR_APDU: Secure element APDU | 152 | * @NFC_ATTR_APDU: Secure element APDU |
153 | * @NFC_ATTR_TARGET_ISO15693_DSFID: ISO 15693 Data Storage Format Identifier | ||
154 | * @NFC_ATTR_TARGET_ISO15693_UID: ISO 15693 Unique Identifier | ||
153 | */ | 155 | */ |
154 | enum nfc_attrs { | 156 | enum nfc_attrs { |
155 | NFC_ATTR_UNSPEC, | 157 | NFC_ATTR_UNSPEC, |
@@ -178,6 +180,8 @@ enum nfc_attrs { | |||
178 | NFC_ATTR_SE_AID, | 180 | NFC_ATTR_SE_AID, |
179 | NFC_ATTR_FIRMWARE_DOWNLOAD_STATUS, | 181 | NFC_ATTR_FIRMWARE_DOWNLOAD_STATUS, |
180 | NFC_ATTR_SE_APDU, | 182 | NFC_ATTR_SE_APDU, |
183 | NFC_ATTR_TARGET_ISO15693_DSFID, | ||
184 | NFC_ATTR_TARGET_ISO15693_UID, | ||
181 | /* private: internal use only */ | 185 | /* private: internal use only */ |
182 | __NFC_ATTR_AFTER_LAST | 186 | __NFC_ATTR_AFTER_LAST |
183 | }; | 187 | }; |
@@ -200,6 +204,7 @@ enum nfc_sdp_attr { | |||
200 | #define NFC_SENSF_RES_MAXSIZE 18 | 204 | #define NFC_SENSF_RES_MAXSIZE 18 |
201 | #define NFC_GB_MAXSIZE 48 | 205 | #define NFC_GB_MAXSIZE 48 |
202 | #define NFC_FIRMWARE_NAME_MAXSIZE 32 | 206 | #define NFC_FIRMWARE_NAME_MAXSIZE 32 |
207 | #define NFC_ISO15693_UID_MAXSIZE 8 | ||
203 | 208 | ||
204 | /* NFC protocols */ | 209 | /* NFC protocols */ |
205 | #define NFC_PROTO_JEWEL 1 | 210 | #define NFC_PROTO_JEWEL 1 |
@@ -208,8 +213,9 @@ enum nfc_sdp_attr { | |||
208 | #define NFC_PROTO_ISO14443 4 | 213 | #define NFC_PROTO_ISO14443 4 |
209 | #define NFC_PROTO_NFC_DEP 5 | 214 | #define NFC_PROTO_NFC_DEP 5 |
210 | #define NFC_PROTO_ISO14443_B 6 | 215 | #define NFC_PROTO_ISO14443_B 6 |
216 | #define NFC_PROTO_ISO15693 7 | ||
211 | 217 | ||
212 | #define NFC_PROTO_MAX 7 | 218 | #define NFC_PROTO_MAX 8 |
213 | 219 | ||
214 | /* NFC communication modes */ | 220 | /* NFC communication modes */ |
215 | #define NFC_COMM_ACTIVE 0 | 221 | #define NFC_COMM_ACTIVE 0 |
@@ -227,6 +233,7 @@ enum nfc_sdp_attr { | |||
227 | #define NFC_PROTO_ISO14443_MASK (1 << NFC_PROTO_ISO14443) | 233 | #define NFC_PROTO_ISO14443_MASK (1 << NFC_PROTO_ISO14443) |
228 | #define NFC_PROTO_NFC_DEP_MASK (1 << NFC_PROTO_NFC_DEP) | 234 | #define NFC_PROTO_NFC_DEP_MASK (1 << NFC_PROTO_NFC_DEP) |
229 | #define NFC_PROTO_ISO14443_B_MASK (1 << NFC_PROTO_ISO14443_B) | 235 | #define NFC_PROTO_ISO14443_B_MASK (1 << NFC_PROTO_ISO14443_B) |
236 | #define NFC_PROTO_ISO15693_MASK (1 << NFC_PROTO_ISO15693) | ||
230 | 237 | ||
231 | /* NFC Secure Elements */ | 238 | /* NFC Secure Elements */ |
232 | #define NFC_SE_UICC 0x1 | 239 | #define NFC_SE_UICC 0x1 |
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index ff72cab3cd3a..1ba9d626aa83 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h | |||
@@ -2335,6 +2335,7 @@ enum nl80211_band_attr { | |||
2335 | * @NL80211_FREQUENCY_ATTR_NO_160MHZ: any 160 MHz (but not 80+80) channel | 2335 | * @NL80211_FREQUENCY_ATTR_NO_160MHZ: any 160 MHz (but not 80+80) channel |
2336 | * using this channel as the primary or any of the secondary channels | 2336 | * using this channel as the primary or any of the secondary channels |
2337 | * isn't possible | 2337 | * isn't possible |
2338 | * @NL80211_FREQUENCY_ATTR_DFS_CAC_TIME: DFS CAC time in milliseconds. | ||
2338 | * @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number | 2339 | * @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number |
2339 | * currently defined | 2340 | * currently defined |
2340 | * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use | 2341 | * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use |
@@ -2353,6 +2354,7 @@ enum nl80211_frequency_attr { | |||
2353 | NL80211_FREQUENCY_ATTR_NO_HT40_PLUS, | 2354 | NL80211_FREQUENCY_ATTR_NO_HT40_PLUS, |
2354 | NL80211_FREQUENCY_ATTR_NO_80MHZ, | 2355 | NL80211_FREQUENCY_ATTR_NO_80MHZ, |
2355 | NL80211_FREQUENCY_ATTR_NO_160MHZ, | 2356 | NL80211_FREQUENCY_ATTR_NO_160MHZ, |
2357 | NL80211_FREQUENCY_ATTR_DFS_CAC_TIME, | ||
2356 | 2358 | ||
2357 | /* keep last */ | 2359 | /* keep last */ |
2358 | __NL80211_FREQUENCY_ATTR_AFTER_LAST, | 2360 | __NL80211_FREQUENCY_ATTR_AFTER_LAST, |
@@ -2449,6 +2451,8 @@ enum nl80211_reg_type { | |||
2449 | * If you don't have one then don't send this. | 2451 | * If you don't have one then don't send this. |
2450 | * @NL80211_ATTR_POWER_RULE_MAX_EIRP: the maximum allowed EIRP for | 2452 | * @NL80211_ATTR_POWER_RULE_MAX_EIRP: the maximum allowed EIRP for |
2451 | * a given frequency range. The value is in mBm (100 * dBm). | 2453 | * a given frequency range. The value is in mBm (100 * dBm). |
2454 | * @NL80211_ATTR_DFS_CAC_TIME: DFS CAC time in milliseconds. | ||
2455 | * If not present or 0 default CAC time will be used. | ||
2452 | * @NL80211_REG_RULE_ATTR_MAX: highest regulatory rule attribute number | 2456 | * @NL80211_REG_RULE_ATTR_MAX: highest regulatory rule attribute number |
2453 | * currently defined | 2457 | * currently defined |
2454 | * @__NL80211_REG_RULE_ATTR_AFTER_LAST: internal use | 2458 | * @__NL80211_REG_RULE_ATTR_AFTER_LAST: internal use |
@@ -2464,6 +2468,8 @@ enum nl80211_reg_rule_attr { | |||
2464 | NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN, | 2468 | NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN, |
2465 | NL80211_ATTR_POWER_RULE_MAX_EIRP, | 2469 | NL80211_ATTR_POWER_RULE_MAX_EIRP, |
2466 | 2470 | ||
2471 | NL80211_ATTR_DFS_CAC_TIME, | ||
2472 | |||
2467 | /* keep last */ | 2473 | /* keep last */ |
2468 | __NL80211_REG_RULE_ATTR_AFTER_LAST, | 2474 | __NL80211_REG_RULE_ATTR_AFTER_LAST, |
2469 | NL80211_REG_RULE_ATTR_MAX = __NL80211_REG_RULE_ATTR_AFTER_LAST - 1 | 2475 | NL80211_REG_RULE_ATTR_MAX = __NL80211_REG_RULE_ATTR_AFTER_LAST - 1 |
diff --git a/net/bluetooth/6lowpan.h b/net/bluetooth/6lowpan.h index 680eac808d74..5d281f1eaf55 100644 --- a/net/bluetooth/6lowpan.h +++ b/net/bluetooth/6lowpan.h | |||
@@ -14,13 +14,34 @@ | |||
14 | #ifndef __6LOWPAN_H | 14 | #ifndef __6LOWPAN_H |
15 | #define __6LOWPAN_H | 15 | #define __6LOWPAN_H |
16 | 16 | ||
17 | #include <linux/errno.h> | ||
17 | #include <linux/skbuff.h> | 18 | #include <linux/skbuff.h> |
18 | #include <net/bluetooth/l2cap.h> | 19 | #include <net/bluetooth/l2cap.h> |
19 | 20 | ||
21 | #if IS_ENABLED(CONFIG_BT_6LOWPAN) | ||
20 | int bt_6lowpan_recv(struct l2cap_conn *conn, struct sk_buff *skb); | 22 | int bt_6lowpan_recv(struct l2cap_conn *conn, struct sk_buff *skb); |
21 | int bt_6lowpan_add_conn(struct l2cap_conn *conn); | 23 | int bt_6lowpan_add_conn(struct l2cap_conn *conn); |
22 | int bt_6lowpan_del_conn(struct l2cap_conn *conn); | 24 | int bt_6lowpan_del_conn(struct l2cap_conn *conn); |
23 | int bt_6lowpan_init(void); | 25 | int bt_6lowpan_init(void); |
24 | void bt_6lowpan_cleanup(void); | 26 | void bt_6lowpan_cleanup(void); |
27 | #else | ||
28 | static int bt_6lowpan_recv(struct l2cap_conn *conn, struct sk_buff *skb) | ||
29 | { | ||
30 | return -EOPNOTSUPP; | ||
31 | } | ||
32 | static int bt_6lowpan_add_conn(struct l2cap_conn *conn) | ||
33 | { | ||
34 | return -EOPNOTSUPP; | ||
35 | } | ||
36 | int bt_6lowpan_del_conn(struct l2cap_conn *conn) | ||
37 | { | ||
38 | return -EOPNOTSUPP; | ||
39 | } | ||
40 | static int bt_6lowpan_init(void) | ||
41 | { | ||
42 | return -EOPNOTSUPP; | ||
43 | } | ||
44 | static void bt_6lowpan_cleanup(void) { } | ||
45 | #endif | ||
25 | 46 | ||
26 | #endif /* __6LOWPAN_H */ | 47 | #endif /* __6LOWPAN_H */ |
diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig index 985b56070d26..06ec14499ca1 100644 --- a/net/bluetooth/Kconfig +++ b/net/bluetooth/Kconfig | |||
@@ -6,13 +6,13 @@ menuconfig BT | |||
6 | tristate "Bluetooth subsystem support" | 6 | tristate "Bluetooth subsystem support" |
7 | depends on NET && !S390 | 7 | depends on NET && !S390 |
8 | depends on RFKILL || !RFKILL | 8 | depends on RFKILL || !RFKILL |
9 | select 6LOWPAN_IPHC if BT_6LOWPAN | ||
9 | select CRC16 | 10 | select CRC16 |
10 | select CRYPTO | 11 | select CRYPTO |
11 | select CRYPTO_BLKCIPHER | 12 | select CRYPTO_BLKCIPHER |
12 | select CRYPTO_AES | 13 | select CRYPTO_AES |
13 | select CRYPTO_ECB | 14 | select CRYPTO_ECB |
14 | select CRYPTO_SHA256 | 15 | select CRYPTO_SHA256 |
15 | select 6LOWPAN_IPHC | ||
16 | help | 16 | help |
17 | Bluetooth is low-cost, low-power, short-range wireless technology. | 17 | Bluetooth is low-cost, low-power, short-range wireless technology. |
18 | It was designed as a replacement for cables and other short-range | 18 | It was designed as a replacement for cables and other short-range |
@@ -40,6 +40,12 @@ menuconfig BT | |||
40 | to Bluetooth kernel modules are provided in the BlueZ packages. For | 40 | to Bluetooth kernel modules are provided in the BlueZ packages. For |
41 | more information, see <http://www.bluez.org/>. | 41 | more information, see <http://www.bluez.org/>. |
42 | 42 | ||
43 | config BT_6LOWPAN | ||
44 | bool "Bluetooth 6LoWPAN support" | ||
45 | depends on BT && IPV6 | ||
46 | help | ||
47 | IPv6 compression over Bluetooth. | ||
48 | |||
43 | source "net/bluetooth/rfcomm/Kconfig" | 49 | source "net/bluetooth/rfcomm/Kconfig" |
44 | 50 | ||
45 | source "net/bluetooth/bnep/Kconfig" | 51 | source "net/bluetooth/bnep/Kconfig" |
diff --git a/net/bluetooth/Makefile b/net/bluetooth/Makefile index 80cb215826e8..ca51246b1016 100644 --- a/net/bluetooth/Makefile +++ b/net/bluetooth/Makefile | |||
@@ -10,6 +10,7 @@ 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 amp.o 6lowpan.o | 13 | a2mp.o amp.o |
14 | bluetooth-$(CONFIG_BT_6LOWPAN) += 6lowpan.o | ||
14 | 15 | ||
15 | subdir-ccflags-y += -D__CHECK_ENDIAN__ | 16 | subdir-ccflags-y += -D__CHECK_ENDIAN__ |
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index f986b9968bdb..9514cc9e850c 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c | |||
@@ -162,7 +162,7 @@ static int a2mp_discover_req(struct amp_mgr *mgr, struct sk_buff *skb, | |||
162 | return -ENOMEM; | 162 | return -ENOMEM; |
163 | } | 163 | } |
164 | 164 | ||
165 | rsp->mtu = __constant_cpu_to_le16(L2CAP_A2MP_DEFAULT_MTU); | 165 | rsp->mtu = cpu_to_le16(L2CAP_A2MP_DEFAULT_MTU); |
166 | rsp->ext_feat = 0; | 166 | rsp->ext_feat = 0; |
167 | 167 | ||
168 | __a2mp_add_cl(mgr, rsp->cl); | 168 | __a2mp_add_cl(mgr, rsp->cl); |
@@ -649,7 +649,7 @@ static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) | |||
649 | if (err) { | 649 | if (err) { |
650 | struct a2mp_cmd_rej rej; | 650 | struct a2mp_cmd_rej rej; |
651 | 651 | ||
652 | rej.reason = __constant_cpu_to_le16(0); | 652 | rej.reason = cpu_to_le16(0); |
653 | hdr = (void *) skb->data; | 653 | hdr = (void *) skb->data; |
654 | 654 | ||
655 | BT_DBG("Send A2MP Rej: cmd 0x%2.2x err %d", hdr->code, err); | 655 | BT_DBG("Send A2MP Rej: cmd 0x%2.2x err %d", hdr->code, err); |
@@ -695,7 +695,13 @@ static void a2mp_chan_state_change_cb(struct l2cap_chan *chan, int state, | |||
695 | static struct sk_buff *a2mp_chan_alloc_skb_cb(struct l2cap_chan *chan, | 695 | static struct sk_buff *a2mp_chan_alloc_skb_cb(struct l2cap_chan *chan, |
696 | unsigned long len, int nb) | 696 | unsigned long len, int nb) |
697 | { | 697 | { |
698 | return bt_skb_alloc(len, GFP_KERNEL); | 698 | struct sk_buff *skb; |
699 | |||
700 | skb = bt_skb_alloc(len, GFP_KERNEL); | ||
701 | if (!skb) | ||
702 | return ERR_PTR(-ENOMEM); | ||
703 | |||
704 | return skb; | ||
699 | } | 705 | } |
700 | 706 | ||
701 | static struct l2cap_ops a2mp_chan_ops = { | 707 | static struct l2cap_ops a2mp_chan_ops = { |
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 7c713c4675ba..d958e2dca52f 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -82,7 +82,7 @@ static void hci_acl_create_connection(struct hci_conn *conn) | |||
82 | cp.pscan_rep_mode = ie->data.pscan_rep_mode; | 82 | cp.pscan_rep_mode = ie->data.pscan_rep_mode; |
83 | cp.pscan_mode = ie->data.pscan_mode; | 83 | cp.pscan_mode = ie->data.pscan_mode; |
84 | cp.clock_offset = ie->data.clock_offset | | 84 | cp.clock_offset = ie->data.clock_offset | |
85 | __constant_cpu_to_le16(0x8000); | 85 | cpu_to_le16(0x8000); |
86 | } | 86 | } |
87 | 87 | ||
88 | memcpy(conn->dev_class, ie->data.dev_class, 3); | 88 | memcpy(conn->dev_class, ie->data.dev_class, 3); |
@@ -182,8 +182,8 @@ bool hci_setup_sync(struct hci_conn *conn, __u16 handle) | |||
182 | 182 | ||
183 | cp.handle = cpu_to_le16(handle); | 183 | cp.handle = cpu_to_le16(handle); |
184 | 184 | ||
185 | cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40); | 185 | cp.tx_bandwidth = cpu_to_le32(0x00001f40); |
186 | cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40); | 186 | cp.rx_bandwidth = cpu_to_le32(0x00001f40); |
187 | cp.voice_setting = cpu_to_le16(conn->setting); | 187 | cp.voice_setting = cpu_to_le16(conn->setting); |
188 | 188 | ||
189 | switch (conn->setting & SCO_AIRMODE_MASK) { | 189 | switch (conn->setting & SCO_AIRMODE_MASK) { |
@@ -225,8 +225,8 @@ void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, | |||
225 | cp.conn_interval_max = cpu_to_le16(max); | 225 | cp.conn_interval_max = cpu_to_le16(max); |
226 | cp.conn_latency = cpu_to_le16(latency); | 226 | cp.conn_latency = cpu_to_le16(latency); |
227 | cp.supervision_timeout = cpu_to_le16(to_multiplier); | 227 | cp.supervision_timeout = cpu_to_le16(to_multiplier); |
228 | cp.min_ce_len = __constant_cpu_to_le16(0x0000); | 228 | cp.min_ce_len = cpu_to_le16(0x0000); |
229 | cp.max_ce_len = __constant_cpu_to_le16(0x0000); | 229 | cp.max_ce_len = cpu_to_le16(0x0000); |
230 | 230 | ||
231 | hci_send_cmd(hdev, HCI_OP_LE_CONN_UPDATE, sizeof(cp), &cp); | 231 | hci_send_cmd(hdev, HCI_OP_LE_CONN_UPDATE, sizeof(cp), &cp); |
232 | } | 232 | } |
@@ -337,9 +337,9 @@ static void hci_conn_idle(struct work_struct *work) | |||
337 | if (lmp_sniffsubr_capable(hdev) && lmp_sniffsubr_capable(conn)) { | 337 | if (lmp_sniffsubr_capable(hdev) && lmp_sniffsubr_capable(conn)) { |
338 | struct hci_cp_sniff_subrate cp; | 338 | struct hci_cp_sniff_subrate cp; |
339 | cp.handle = cpu_to_le16(conn->handle); | 339 | cp.handle = cpu_to_le16(conn->handle); |
340 | cp.max_latency = __constant_cpu_to_le16(0); | 340 | cp.max_latency = cpu_to_le16(0); |
341 | cp.min_remote_timeout = __constant_cpu_to_le16(0); | 341 | cp.min_remote_timeout = cpu_to_le16(0); |
342 | cp.min_local_timeout = __constant_cpu_to_le16(0); | 342 | cp.min_local_timeout = cpu_to_le16(0); |
343 | hci_send_cmd(hdev, HCI_OP_SNIFF_SUBRATE, sizeof(cp), &cp); | 343 | hci_send_cmd(hdev, HCI_OP_SNIFF_SUBRATE, sizeof(cp), &cp); |
344 | } | 344 | } |
345 | 345 | ||
@@ -348,8 +348,8 @@ static void hci_conn_idle(struct work_struct *work) | |||
348 | cp.handle = cpu_to_le16(conn->handle); | 348 | cp.handle = cpu_to_le16(conn->handle); |
349 | cp.max_interval = cpu_to_le16(hdev->sniff_max_interval); | 349 | cp.max_interval = cpu_to_le16(hdev->sniff_max_interval); |
350 | cp.min_interval = cpu_to_le16(hdev->sniff_min_interval); | 350 | cp.min_interval = cpu_to_le16(hdev->sniff_min_interval); |
351 | cp.attempt = __constant_cpu_to_le16(4); | 351 | cp.attempt = cpu_to_le16(4); |
352 | cp.timeout = __constant_cpu_to_le16(1); | 352 | cp.timeout = cpu_to_le16(1); |
353 | hci_send_cmd(hdev, HCI_OP_SNIFF_MODE, sizeof(cp), &cp); | 353 | hci_send_cmd(hdev, HCI_OP_SNIFF_MODE, sizeof(cp), &cp); |
354 | } | 354 | } |
355 | } | 355 | } |
@@ -596,9 +596,9 @@ static void hci_req_add_le_create_conn(struct hci_request *req, | |||
596 | cp.own_address_type = own_addr_type; | 596 | cp.own_address_type = own_addr_type; |
597 | cp.conn_interval_min = cpu_to_le16(conn->le_conn_min_interval); | 597 | cp.conn_interval_min = cpu_to_le16(conn->le_conn_min_interval); |
598 | cp.conn_interval_max = cpu_to_le16(conn->le_conn_max_interval); | 598 | cp.conn_interval_max = cpu_to_le16(conn->le_conn_max_interval); |
599 | cp.supervision_timeout = __constant_cpu_to_le16(0x002a); | 599 | cp.supervision_timeout = cpu_to_le16(0x002a); |
600 | cp.min_ce_len = __constant_cpu_to_le16(0x0000); | 600 | cp.min_ce_len = cpu_to_le16(0x0000); |
601 | cp.max_ce_len = __constant_cpu_to_le16(0x0000); | 601 | cp.max_ce_len = cpu_to_le16(0x0000); |
602 | 602 | ||
603 | hci_req_add(req, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp); | 603 | hci_req_add(req, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp); |
604 | 604 | ||
@@ -781,6 +781,17 @@ int hci_conn_check_link_mode(struct hci_conn *conn) | |||
781 | { | 781 | { |
782 | BT_DBG("hcon %p", conn); | 782 | BT_DBG("hcon %p", conn); |
783 | 783 | ||
784 | /* In Secure Connections Only mode, it is required that Secure | ||
785 | * Connections is used and the link is encrypted with AES-CCM | ||
786 | * using a P-256 authenticated combination key. | ||
787 | */ | ||
788 | if (test_bit(HCI_SC_ONLY, &conn->hdev->flags)) { | ||
789 | if (!hci_conn_sc_enabled(conn) || | ||
790 | !test_bit(HCI_CONN_AES_CCM, &conn->flags) || | ||
791 | conn->key_type != HCI_LK_AUTH_COMBINATION_P256) | ||
792 | return 0; | ||
793 | } | ||
794 | |||
784 | if (hci_conn_ssp_enabled(conn) && !(conn->link_mode & HCI_LM_ENCRYPT)) | 795 | if (hci_conn_ssp_enabled(conn) && !(conn->link_mode & HCI_LM_ENCRYPT)) |
785 | return 0; | 796 | return 0; |
786 | 797 | ||
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 8bbfdea9cbec..1c6ffaa8902f 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -1349,7 +1349,7 @@ static void bredr_setup(struct hci_request *req) | |||
1349 | hci_req_add(req, HCI_OP_SET_EVENT_FLT, 1, &flt_type); | 1349 | hci_req_add(req, HCI_OP_SET_EVENT_FLT, 1, &flt_type); |
1350 | 1350 | ||
1351 | /* Connection accept timeout ~20 secs */ | 1351 | /* Connection accept timeout ~20 secs */ |
1352 | param = __constant_cpu_to_le16(0x7d00); | 1352 | param = cpu_to_le16(0x7d00); |
1353 | hci_req_add(req, HCI_OP_WRITE_CA_TIMEOUT, 2, ¶m); | 1353 | hci_req_add(req, HCI_OP_WRITE_CA_TIMEOUT, 2, ¶m); |
1354 | 1354 | ||
1355 | /* AVM Berlin (31), aka "BlueFRITZ!", reports version 1.2, | 1355 | /* AVM Berlin (31), aka "BlueFRITZ!", reports version 1.2, |
@@ -5270,7 +5270,7 @@ void hci_req_add_le_passive_scan(struct hci_request *req) | |||
5270 | 5270 | ||
5271 | memset(&enable_cp, 0, sizeof(enable_cp)); | 5271 | memset(&enable_cp, 0, sizeof(enable_cp)); |
5272 | enable_cp.enable = LE_SCAN_ENABLE; | 5272 | enable_cp.enable = LE_SCAN_ENABLE; |
5273 | enable_cp.filter_dup = LE_SCAN_FILTER_DUP_DISABLE; | 5273 | enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE; |
5274 | hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp), | 5274 | hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp), |
5275 | &enable_cp); | 5275 | &enable_cp); |
5276 | } | 5276 | } |
@@ -5313,10 +5313,6 @@ void hci_update_background_scan(struct hci_dev *hdev) | |||
5313 | * keep the background scan running. | 5313 | * keep the background scan running. |
5314 | */ | 5314 | */ |
5315 | 5315 | ||
5316 | /* If controller is already scanning we are done. */ | ||
5317 | if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) | ||
5318 | return; | ||
5319 | |||
5320 | /* If controller is connecting, we should not start scanning | 5316 | /* If controller is connecting, we should not start scanning |
5321 | * since some controllers are not able to scan and connect at | 5317 | * since some controllers are not able to scan and connect at |
5322 | * the same time. | 5318 | * the same time. |
@@ -5325,6 +5321,12 @@ void hci_update_background_scan(struct hci_dev *hdev) | |||
5325 | if (conn) | 5321 | if (conn) |
5326 | return; | 5322 | return; |
5327 | 5323 | ||
5324 | /* If controller is currently scanning, we stop it to ensure we | ||
5325 | * don't miss any advertising (due to duplicates filter). | ||
5326 | */ | ||
5327 | if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) | ||
5328 | hci_req_add_le_scan_disable(&req); | ||
5329 | |||
5328 | hci_req_add_le_passive_scan(&req); | 5330 | hci_req_add_le_passive_scan(&req); |
5329 | 5331 | ||
5330 | BT_DBG("%s starting background scanning", hdev->name); | 5332 | BT_DBG("%s starting background scanning", hdev->name); |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index c3b0a08f5ab4..a6a3d32553c5 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -1924,9 +1924,9 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
1924 | bacpy(&cp.bdaddr, &ev->bdaddr); | 1924 | bacpy(&cp.bdaddr, &ev->bdaddr); |
1925 | cp.pkt_type = cpu_to_le16(conn->pkt_type); | 1925 | cp.pkt_type = cpu_to_le16(conn->pkt_type); |
1926 | 1926 | ||
1927 | cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40); | 1927 | cp.tx_bandwidth = cpu_to_le32(0x00001f40); |
1928 | cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40); | 1928 | cp.rx_bandwidth = cpu_to_le32(0x00001f40); |
1929 | cp.max_latency = __constant_cpu_to_le16(0xffff); | 1929 | cp.max_latency = cpu_to_le16(0xffff); |
1930 | cp.content_format = cpu_to_le16(hdev->voice_setting); | 1930 | cp.content_format = cpu_to_le16(hdev->voice_setting); |
1931 | cp.retrans_effort = 0xff; | 1931 | cp.retrans_effort = 0xff; |
1932 | 1932 | ||
@@ -2183,6 +2183,18 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2183 | if (!ev->status) | 2183 | if (!ev->status) |
2184 | conn->state = BT_CONNECTED; | 2184 | conn->state = BT_CONNECTED; |
2185 | 2185 | ||
2186 | /* In Secure Connections Only mode, do not allow any | ||
2187 | * connections that are not encrypted with AES-CCM | ||
2188 | * using a P-256 authenticated combination key. | ||
2189 | */ | ||
2190 | if (test_bit(HCI_SC_ONLY, &hdev->dev_flags) && | ||
2191 | (!test_bit(HCI_CONN_AES_CCM, &conn->flags) || | ||
2192 | conn->key_type != HCI_LK_AUTH_COMBINATION_P256)) { | ||
2193 | hci_proto_connect_cfm(conn, HCI_ERROR_AUTH_FAILURE); | ||
2194 | hci_conn_drop(conn); | ||
2195 | goto unlock; | ||
2196 | } | ||
2197 | |||
2186 | hci_proto_connect_cfm(conn, ev->status); | 2198 | hci_proto_connect_cfm(conn, ev->status); |
2187 | hci_conn_drop(conn); | 2199 | hci_conn_drop(conn); |
2188 | } else | 2200 | } else |
@@ -3157,6 +3169,7 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev, | |||
3157 | case 0x1c: /* SCO interval rejected */ | 3169 | case 0x1c: /* SCO interval rejected */ |
3158 | case 0x1a: /* Unsupported Remote Feature */ | 3170 | case 0x1a: /* Unsupported Remote Feature */ |
3159 | case 0x1f: /* Unspecified error */ | 3171 | case 0x1f: /* Unspecified error */ |
3172 | case 0x20: /* Unsupported LMP Parameter value */ | ||
3160 | if (conn->out) { | 3173 | if (conn->out) { |
3161 | conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | | 3174 | conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | |
3162 | (hdev->esco_type & EDR_ESCO_MASK); | 3175 | (hdev->esco_type & EDR_ESCO_MASK); |
@@ -3961,7 +3974,13 @@ static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
3961 | 3974 | ||
3962 | hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); | 3975 | hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); |
3963 | 3976 | ||
3964 | if (ltk->type & HCI_SMP_STK) { | 3977 | /* Ref. Bluetooth Core SPEC pages 1975 and 2004. STK is a |
3978 | * temporary key used to encrypt a connection following | ||
3979 | * pairing. It is used during the Encrypted Session Setup to | ||
3980 | * distribute the keys. Later, security can be re-established | ||
3981 | * using a distributed LTK. | ||
3982 | */ | ||
3983 | if (ltk->type == HCI_SMP_STK_SLAVE) { | ||
3965 | list_del(<k->list); | 3984 | list_del(<k->list); |
3966 | kfree(ltk); | 3985 | kfree(ltk); |
3967 | } | 3986 | } |
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 68e51a84e72d..b9a418e578e0 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c | |||
@@ -211,22 +211,22 @@ void hci_send_to_monitor(struct hci_dev *hdev, struct sk_buff *skb) | |||
211 | 211 | ||
212 | switch (bt_cb(skb)->pkt_type) { | 212 | switch (bt_cb(skb)->pkt_type) { |
213 | case HCI_COMMAND_PKT: | 213 | case HCI_COMMAND_PKT: |
214 | opcode = __constant_cpu_to_le16(HCI_MON_COMMAND_PKT); | 214 | opcode = cpu_to_le16(HCI_MON_COMMAND_PKT); |
215 | break; | 215 | break; |
216 | case HCI_EVENT_PKT: | 216 | case HCI_EVENT_PKT: |
217 | opcode = __constant_cpu_to_le16(HCI_MON_EVENT_PKT); | 217 | opcode = cpu_to_le16(HCI_MON_EVENT_PKT); |
218 | break; | 218 | break; |
219 | case HCI_ACLDATA_PKT: | 219 | case HCI_ACLDATA_PKT: |
220 | if (bt_cb(skb)->incoming) | 220 | if (bt_cb(skb)->incoming) |
221 | opcode = __constant_cpu_to_le16(HCI_MON_ACL_RX_PKT); | 221 | opcode = cpu_to_le16(HCI_MON_ACL_RX_PKT); |
222 | else | 222 | else |
223 | opcode = __constant_cpu_to_le16(HCI_MON_ACL_TX_PKT); | 223 | opcode = cpu_to_le16(HCI_MON_ACL_TX_PKT); |
224 | break; | 224 | break; |
225 | case HCI_SCODATA_PKT: | 225 | case HCI_SCODATA_PKT: |
226 | if (bt_cb(skb)->incoming) | 226 | if (bt_cb(skb)->incoming) |
227 | opcode = __constant_cpu_to_le16(HCI_MON_SCO_RX_PKT); | 227 | opcode = cpu_to_le16(HCI_MON_SCO_RX_PKT); |
228 | else | 228 | else |
229 | opcode = __constant_cpu_to_le16(HCI_MON_SCO_TX_PKT); | 229 | opcode = cpu_to_le16(HCI_MON_SCO_TX_PKT); |
230 | break; | 230 | break; |
231 | default: | 231 | default: |
232 | return; | 232 | return; |
@@ -319,7 +319,7 @@ static struct sk_buff *create_monitor_event(struct hci_dev *hdev, int event) | |||
319 | bacpy(&ni->bdaddr, &hdev->bdaddr); | 319 | bacpy(&ni->bdaddr, &hdev->bdaddr); |
320 | memcpy(ni->name, hdev->name, 8); | 320 | memcpy(ni->name, hdev->name, 8); |
321 | 321 | ||
322 | opcode = __constant_cpu_to_le16(HCI_MON_NEW_INDEX); | 322 | opcode = cpu_to_le16(HCI_MON_NEW_INDEX); |
323 | break; | 323 | break; |
324 | 324 | ||
325 | case HCI_DEV_UNREG: | 325 | case HCI_DEV_UNREG: |
@@ -327,7 +327,7 @@ static struct sk_buff *create_monitor_event(struct hci_dev *hdev, int event) | |||
327 | if (!skb) | 327 | if (!skb) |
328 | return NULL; | 328 | return NULL; |
329 | 329 | ||
330 | opcode = __constant_cpu_to_le16(HCI_MON_DEL_INDEX); | 330 | opcode = cpu_to_le16(HCI_MON_DEL_INDEX); |
331 | break; | 331 | break; |
332 | 332 | ||
333 | default: | 333 | default: |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 9ed2168fa59f..a1e5bb7d06e8 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -665,7 +665,7 @@ static void l2cap_chan_connect_reject(struct l2cap_chan *chan) | |||
665 | rsp.scid = cpu_to_le16(chan->dcid); | 665 | rsp.scid = cpu_to_le16(chan->dcid); |
666 | rsp.dcid = cpu_to_le16(chan->scid); | 666 | rsp.dcid = cpu_to_le16(chan->scid); |
667 | rsp.result = cpu_to_le16(result); | 667 | rsp.result = cpu_to_le16(result); |
668 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); | 668 | rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); |
669 | 669 | ||
670 | l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); | 670 | l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); |
671 | } | 671 | } |
@@ -727,7 +727,7 @@ static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) | |||
727 | } | 727 | } |
728 | break; | 728 | break; |
729 | case L2CAP_CHAN_CONN_LESS: | 729 | case L2CAP_CHAN_CONN_LESS: |
730 | if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_3DSP)) { | 730 | if (chan->psm == cpu_to_le16(L2CAP_PSM_3DSP)) { |
731 | if (chan->sec_level == BT_SECURITY_LOW) | 731 | if (chan->sec_level == BT_SECURITY_LOW) |
732 | chan->sec_level = BT_SECURITY_SDP; | 732 | chan->sec_level = BT_SECURITY_SDP; |
733 | } | 733 | } |
@@ -738,7 +738,7 @@ static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) | |||
738 | return HCI_AT_NO_BONDING; | 738 | return HCI_AT_NO_BONDING; |
739 | break; | 739 | break; |
740 | case L2CAP_CHAN_CONN_ORIENTED: | 740 | case L2CAP_CHAN_CONN_ORIENTED: |
741 | if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_SDP)) { | 741 | if (chan->psm == cpu_to_le16(L2CAP_PSM_SDP)) { |
742 | if (chan->sec_level == BT_SECURITY_LOW) | 742 | if (chan->sec_level == BT_SECURITY_LOW) |
743 | chan->sec_level = BT_SECURITY_SDP; | 743 | chan->sec_level = BT_SECURITY_SDP; |
744 | 744 | ||
@@ -1273,7 +1273,7 @@ static void l2cap_do_start(struct l2cap_chan *chan) | |||
1273 | } | 1273 | } |
1274 | } else { | 1274 | } else { |
1275 | struct l2cap_info_req req; | 1275 | struct l2cap_info_req req; |
1276 | req.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK); | 1276 | req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK); |
1277 | 1277 | ||
1278 | conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; | 1278 | conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; |
1279 | conn->info_ident = l2cap_get_ident(conn); | 1279 | conn->info_ident = l2cap_get_ident(conn); |
@@ -1370,18 +1370,18 @@ static void l2cap_conn_start(struct l2cap_conn *conn) | |||
1370 | 1370 | ||
1371 | if (l2cap_chan_check_security(chan)) { | 1371 | if (l2cap_chan_check_security(chan)) { |
1372 | if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { | 1372 | if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { |
1373 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND); | 1373 | rsp.result = cpu_to_le16(L2CAP_CR_PEND); |
1374 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHOR_PEND); | 1374 | rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND); |
1375 | chan->ops->defer(chan); | 1375 | chan->ops->defer(chan); |
1376 | 1376 | ||
1377 | } else { | 1377 | } else { |
1378 | l2cap_state_change(chan, BT_CONFIG); | 1378 | l2cap_state_change(chan, BT_CONFIG); |
1379 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); | 1379 | rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); |
1380 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); | 1380 | rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); |
1381 | } | 1381 | } |
1382 | } else { | 1382 | } else { |
1383 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND); | 1383 | rsp.result = cpu_to_le16(L2CAP_CR_PEND); |
1384 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHEN_PEND); | 1384 | rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND); |
1385 | } | 1385 | } |
1386 | 1386 | ||
1387 | l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, | 1387 | l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, |
@@ -2895,9 +2895,9 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code, | |||
2895 | lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen); | 2895 | lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen); |
2896 | 2896 | ||
2897 | if (conn->hcon->type == LE_LINK) | 2897 | if (conn->hcon->type == LE_LINK) |
2898 | lh->cid = __constant_cpu_to_le16(L2CAP_CID_LE_SIGNALING); | 2898 | lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING); |
2899 | else | 2899 | else |
2900 | lh->cid = __constant_cpu_to_le16(L2CAP_CID_SIGNALING); | 2900 | lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING); |
2901 | 2901 | ||
2902 | cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE); | 2902 | cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE); |
2903 | cmd->code = code; | 2903 | cmd->code = code; |
@@ -3010,8 +3010,8 @@ static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan) | |||
3010 | efs.stype = chan->local_stype; | 3010 | efs.stype = chan->local_stype; |
3011 | efs.msdu = cpu_to_le16(chan->local_msdu); | 3011 | efs.msdu = cpu_to_le16(chan->local_msdu); |
3012 | efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); | 3012 | efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); |
3013 | efs.acc_lat = __constant_cpu_to_le32(L2CAP_DEFAULT_ACC_LAT); | 3013 | efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT); |
3014 | efs.flush_to = __constant_cpu_to_le32(L2CAP_EFS_DEFAULT_FLUSH_TO); | 3014 | efs.flush_to = cpu_to_le32(L2CAP_EFS_DEFAULT_FLUSH_TO); |
3015 | break; | 3015 | break; |
3016 | 3016 | ||
3017 | case L2CAP_MODE_STREAMING: | 3017 | case L2CAP_MODE_STREAMING: |
@@ -3152,8 +3152,8 @@ static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan, | |||
3152 | rfc->retrans_timeout = cpu_to_le16((u16) ertm_to); | 3152 | rfc->retrans_timeout = cpu_to_le16((u16) ertm_to); |
3153 | rfc->monitor_timeout = rfc->retrans_timeout; | 3153 | rfc->monitor_timeout = rfc->retrans_timeout; |
3154 | } else { | 3154 | } else { |
3155 | rfc->retrans_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO); | 3155 | rfc->retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO); |
3156 | rfc->monitor_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO); | 3156 | rfc->monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO); |
3157 | } | 3157 | } |
3158 | } | 3158 | } |
3159 | 3159 | ||
@@ -3285,7 +3285,7 @@ done: | |||
3285 | } | 3285 | } |
3286 | 3286 | ||
3287 | req->dcid = cpu_to_le16(chan->dcid); | 3287 | req->dcid = cpu_to_le16(chan->dcid); |
3288 | req->flags = __constant_cpu_to_le16(0); | 3288 | req->flags = cpu_to_le16(0); |
3289 | 3289 | ||
3290 | return ptr - data; | 3290 | return ptr - data; |
3291 | } | 3291 | } |
@@ -3499,7 +3499,7 @@ done: | |||
3499 | } | 3499 | } |
3500 | rsp->scid = cpu_to_le16(chan->dcid); | 3500 | rsp->scid = cpu_to_le16(chan->dcid); |
3501 | rsp->result = cpu_to_le16(result); | 3501 | rsp->result = cpu_to_le16(result); |
3502 | rsp->flags = __constant_cpu_to_le16(0); | 3502 | rsp->flags = cpu_to_le16(0); |
3503 | 3503 | ||
3504 | return ptr - data; | 3504 | return ptr - data; |
3505 | } | 3505 | } |
@@ -3608,7 +3608,7 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, | |||
3608 | } | 3608 | } |
3609 | 3609 | ||
3610 | req->dcid = cpu_to_le16(chan->dcid); | 3610 | req->dcid = cpu_to_le16(chan->dcid); |
3611 | req->flags = __constant_cpu_to_le16(0); | 3611 | req->flags = cpu_to_le16(0); |
3612 | 3612 | ||
3613 | return ptr - data; | 3613 | return ptr - data; |
3614 | } | 3614 | } |
@@ -3639,7 +3639,7 @@ void __l2cap_le_connect_rsp_defer(struct l2cap_chan *chan) | |||
3639 | rsp.mtu = cpu_to_le16(chan->imtu); | 3639 | rsp.mtu = cpu_to_le16(chan->imtu); |
3640 | rsp.mps = cpu_to_le16(chan->mps); | 3640 | rsp.mps = cpu_to_le16(chan->mps); |
3641 | rsp.credits = cpu_to_le16(chan->rx_credits); | 3641 | rsp.credits = cpu_to_le16(chan->rx_credits); |
3642 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); | 3642 | rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); |
3643 | 3643 | ||
3644 | l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), | 3644 | l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), |
3645 | &rsp); | 3645 | &rsp); |
@@ -3654,8 +3654,8 @@ void __l2cap_connect_rsp_defer(struct l2cap_chan *chan) | |||
3654 | 3654 | ||
3655 | rsp.scid = cpu_to_le16(chan->dcid); | 3655 | rsp.scid = cpu_to_le16(chan->dcid); |
3656 | rsp.dcid = cpu_to_le16(chan->scid); | 3656 | rsp.dcid = cpu_to_le16(chan->scid); |
3657 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); | 3657 | rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); |
3658 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); | 3658 | rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); |
3659 | 3659 | ||
3660 | if (chan->hs_hcon) | 3660 | if (chan->hs_hcon) |
3661 | rsp_code = L2CAP_CREATE_CHAN_RSP; | 3661 | rsp_code = L2CAP_CREATE_CHAN_RSP; |
@@ -3684,8 +3684,8 @@ static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len) | |||
3684 | u16 txwin_ext = chan->ack_win; | 3684 | u16 txwin_ext = chan->ack_win; |
3685 | struct l2cap_conf_rfc rfc = { | 3685 | struct l2cap_conf_rfc rfc = { |
3686 | .mode = chan->mode, | 3686 | .mode = chan->mode, |
3687 | .retrans_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO), | 3687 | .retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO), |
3688 | .monitor_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO), | 3688 | .monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO), |
3689 | .max_pdu_size = cpu_to_le16(chan->imtu), | 3689 | .max_pdu_size = cpu_to_le16(chan->imtu), |
3690 | .txwin_size = min_t(u16, chan->ack_win, L2CAP_DEFAULT_TX_WINDOW), | 3690 | .txwin_size = min_t(u16, chan->ack_win, L2CAP_DEFAULT_TX_WINDOW), |
3691 | }; | 3691 | }; |
@@ -3776,7 +3776,7 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, | |||
3776 | l2cap_chan_lock(pchan); | 3776 | l2cap_chan_lock(pchan); |
3777 | 3777 | ||
3778 | /* Check if the ACL is secure enough (if not SDP) */ | 3778 | /* Check if the ACL is secure enough (if not SDP) */ |
3779 | if (psm != __constant_cpu_to_le16(L2CAP_PSM_SDP) && | 3779 | if (psm != cpu_to_le16(L2CAP_PSM_SDP) && |
3780 | !hci_conn_check_link_mode(conn->hcon)) { | 3780 | !hci_conn_check_link_mode(conn->hcon)) { |
3781 | conn->disc_reason = HCI_ERROR_AUTH_FAILURE; | 3781 | conn->disc_reason = HCI_ERROR_AUTH_FAILURE; |
3782 | result = L2CAP_CR_SEC_BLOCK; | 3782 | result = L2CAP_CR_SEC_BLOCK; |
@@ -3861,7 +3861,7 @@ sendresp: | |||
3861 | 3861 | ||
3862 | if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) { | 3862 | if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) { |
3863 | struct l2cap_info_req info; | 3863 | struct l2cap_info_req info; |
3864 | info.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK); | 3864 | info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK); |
3865 | 3865 | ||
3866 | conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; | 3866 | conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; |
3867 | conn->info_ident = l2cap_get_ident(conn); | 3867 | conn->info_ident = l2cap_get_ident(conn); |
@@ -4010,7 +4010,7 @@ static void cmd_reject_invalid_cid(struct l2cap_conn *conn, u8 ident, | |||
4010 | { | 4010 | { |
4011 | struct l2cap_cmd_rej_cid rej; | 4011 | struct l2cap_cmd_rej_cid rej; |
4012 | 4012 | ||
4013 | rej.reason = __constant_cpu_to_le16(L2CAP_REJ_INVALID_CID); | 4013 | rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID); |
4014 | rej.scid = __cpu_to_le16(scid); | 4014 | rej.scid = __cpu_to_le16(scid); |
4015 | rej.dcid = __cpu_to_le16(dcid); | 4015 | rej.dcid = __cpu_to_le16(dcid); |
4016 | 4016 | ||
@@ -4342,8 +4342,8 @@ static inline int l2cap_information_req(struct l2cap_conn *conn, | |||
4342 | u8 buf[8]; | 4342 | u8 buf[8]; |
4343 | u32 feat_mask = l2cap_feat_mask; | 4343 | u32 feat_mask = l2cap_feat_mask; |
4344 | struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; | 4344 | struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; |
4345 | rsp->type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK); | 4345 | rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK); |
4346 | rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS); | 4346 | rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS); |
4347 | if (!disable_ertm) | 4347 | if (!disable_ertm) |
4348 | feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING | 4348 | feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING |
4349 | | L2CAP_FEAT_FCS; | 4349 | | L2CAP_FEAT_FCS; |
@@ -4363,15 +4363,15 @@ static inline int l2cap_information_req(struct l2cap_conn *conn, | |||
4363 | else | 4363 | else |
4364 | l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP; | 4364 | l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP; |
4365 | 4365 | ||
4366 | rsp->type = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN); | 4366 | rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN); |
4367 | rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS); | 4367 | rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS); |
4368 | memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan)); | 4368 | memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan)); |
4369 | l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf), | 4369 | l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf), |
4370 | buf); | 4370 | buf); |
4371 | } else { | 4371 | } else { |
4372 | struct l2cap_info_rsp rsp; | 4372 | struct l2cap_info_rsp rsp; |
4373 | rsp.type = cpu_to_le16(type); | 4373 | rsp.type = cpu_to_le16(type); |
4374 | rsp.result = __constant_cpu_to_le16(L2CAP_IR_NOTSUPP); | 4374 | rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP); |
4375 | l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp), | 4375 | l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp), |
4376 | &rsp); | 4376 | &rsp); |
4377 | } | 4377 | } |
@@ -4416,7 +4416,7 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, | |||
4416 | 4416 | ||
4417 | if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) { | 4417 | if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) { |
4418 | struct l2cap_info_req req; | 4418 | struct l2cap_info_req req; |
4419 | req.type = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN); | 4419 | req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN); |
4420 | 4420 | ||
4421 | conn->info_ident = l2cap_get_ident(conn); | 4421 | conn->info_ident = l2cap_get_ident(conn); |
4422 | 4422 | ||
@@ -4510,8 +4510,8 @@ static int l2cap_create_channel_req(struct l2cap_conn *conn, | |||
4510 | error: | 4510 | error: |
4511 | rsp.dcid = 0; | 4511 | rsp.dcid = 0; |
4512 | rsp.scid = cpu_to_le16(scid); | 4512 | rsp.scid = cpu_to_le16(scid); |
4513 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_BAD_AMP); | 4513 | rsp.result = cpu_to_le16(L2CAP_CR_BAD_AMP); |
4514 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); | 4514 | rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); |
4515 | 4515 | ||
4516 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP, | 4516 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP, |
4517 | sizeof(rsp), &rsp); | 4517 | sizeof(rsp), &rsp); |
@@ -4575,7 +4575,7 @@ static void l2cap_send_move_chan_cfm_icid(struct l2cap_conn *conn, u16 icid) | |||
4575 | BT_DBG("conn %p, icid 0x%4.4x", conn, icid); | 4575 | BT_DBG("conn %p, icid 0x%4.4x", conn, icid); |
4576 | 4576 | ||
4577 | cfm.icid = cpu_to_le16(icid); | 4577 | cfm.icid = cpu_to_le16(icid); |
4578 | cfm.result = __constant_cpu_to_le16(L2CAP_MC_UNCONFIRMED); | 4578 | cfm.result = cpu_to_le16(L2CAP_MC_UNCONFIRMED); |
4579 | 4579 | ||
4580 | l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_MOVE_CHAN_CFM, | 4580 | l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_MOVE_CHAN_CFM, |
4581 | sizeof(cfm), &cfm); | 4581 | sizeof(cfm), &cfm); |
@@ -4758,12 +4758,12 @@ static void l2cap_do_create(struct l2cap_chan *chan, int result, | |||
4758 | 4758 | ||
4759 | if (result == L2CAP_CR_SUCCESS) { | 4759 | if (result == L2CAP_CR_SUCCESS) { |
4760 | /* Send successful response */ | 4760 | /* Send successful response */ |
4761 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); | 4761 | rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); |
4762 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); | 4762 | rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); |
4763 | } else { | 4763 | } else { |
4764 | /* Send negative response */ | 4764 | /* Send negative response */ |
4765 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM); | 4765 | rsp.result = cpu_to_le16(L2CAP_CR_NO_MEM); |
4766 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); | 4766 | rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); |
4767 | } | 4767 | } |
4768 | 4768 | ||
4769 | l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_RSP, | 4769 | l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_RSP, |
@@ -4891,7 +4891,7 @@ static inline int l2cap_move_channel_req(struct l2cap_conn *conn, | |||
4891 | chan = l2cap_get_chan_by_dcid(conn, icid); | 4891 | chan = l2cap_get_chan_by_dcid(conn, icid); |
4892 | if (!chan) { | 4892 | if (!chan) { |
4893 | rsp.icid = cpu_to_le16(icid); | 4893 | rsp.icid = cpu_to_le16(icid); |
4894 | rsp.result = __constant_cpu_to_le16(L2CAP_MR_NOT_ALLOWED); | 4894 | rsp.result = cpu_to_le16(L2CAP_MR_NOT_ALLOWED); |
4895 | l2cap_send_cmd(conn, cmd->ident, L2CAP_MOVE_CHAN_RSP, | 4895 | l2cap_send_cmd(conn, cmd->ident, L2CAP_MOVE_CHAN_RSP, |
4896 | sizeof(rsp), &rsp); | 4896 | sizeof(rsp), &rsp); |
4897 | return 0; | 4897 | return 0; |
@@ -5235,9 +5235,9 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, | |||
5235 | 5235 | ||
5236 | err = l2cap_check_conn_param(min, max, latency, to_multiplier); | 5236 | err = l2cap_check_conn_param(min, max, latency, to_multiplier); |
5237 | if (err) | 5237 | if (err) |
5238 | rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_REJECTED); | 5238 | rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED); |
5239 | else | 5239 | else |
5240 | rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED); | 5240 | rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED); |
5241 | 5241 | ||
5242 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP, | 5242 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP, |
5243 | sizeof(rsp), &rsp); | 5243 | sizeof(rsp), &rsp); |
@@ -5650,7 +5650,7 @@ static inline void l2cap_le_sig_channel(struct l2cap_conn *conn, | |||
5650 | 5650 | ||
5651 | BT_ERR("Wrong link type (%d)", err); | 5651 | BT_ERR("Wrong link type (%d)", err); |
5652 | 5652 | ||
5653 | rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); | 5653 | rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); |
5654 | l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ, | 5654 | l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ, |
5655 | sizeof(rej), &rej); | 5655 | sizeof(rej), &rej); |
5656 | } | 5656 | } |
@@ -5695,7 +5695,7 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn, | |||
5695 | 5695 | ||
5696 | BT_ERR("Wrong link type (%d)", err); | 5696 | BT_ERR("Wrong link type (%d)", err); |
5697 | 5697 | ||
5698 | rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); | 5698 | rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); |
5699 | l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, | 5699 | l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, |
5700 | sizeof(rej), &rej); | 5700 | sizeof(rej), &rej); |
5701 | } | 5701 | } |
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index b247f9d27fed..33cd5615ff1e 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -111,7 +111,7 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) | |||
111 | if (bdaddr_type_is_le(la.l2_bdaddr_type)) { | 111 | if (bdaddr_type_is_le(la.l2_bdaddr_type)) { |
112 | /* We only allow ATT user space socket */ | 112 | /* We only allow ATT user space socket */ |
113 | if (la.l2_cid && | 113 | if (la.l2_cid && |
114 | la.l2_cid != __constant_cpu_to_le16(L2CAP_CID_ATT)) | 114 | la.l2_cid != cpu_to_le16(L2CAP_CID_ATT)) |
115 | return -EINVAL; | 115 | return -EINVAL; |
116 | } | 116 | } |
117 | 117 | ||
@@ -209,7 +209,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, | |||
209 | * ATT. Anything else is an invalid combination. | 209 | * ATT. Anything else is an invalid combination. |
210 | */ | 210 | */ |
211 | if (chan->scid != L2CAP_CID_ATT || | 211 | if (chan->scid != L2CAP_CID_ATT || |
212 | la.l2_cid != __constant_cpu_to_le16(L2CAP_CID_ATT)) | 212 | la.l2_cid != cpu_to_le16(L2CAP_CID_ATT)) |
213 | return -EINVAL; | 213 | return -EINVAL; |
214 | 214 | ||
215 | /* We don't have the hdev available here to make a | 215 | /* We don't have the hdev available here to make a |
@@ -227,7 +227,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, | |||
227 | if (bdaddr_type_is_le(la.l2_bdaddr_type)) { | 227 | if (bdaddr_type_is_le(la.l2_bdaddr_type)) { |
228 | /* We only allow ATT user space socket */ | 228 | /* We only allow ATT user space socket */ |
229 | if (la.l2_cid && | 229 | if (la.l2_cid && |
230 | la.l2_cid != __constant_cpu_to_le16(L2CAP_CID_ATT)) | 230 | la.l2_cid != cpu_to_le16(L2CAP_CID_ATT)) |
231 | return -EINVAL; | 231 | return -EINVAL; |
232 | } | 232 | } |
233 | 233 | ||
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 98e9df3556e7..96670f581bb0 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -108,6 +108,7 @@ static const u16 mgmt_events[] = { | |||
108 | MGMT_EV_DEVICE_UNPAIRED, | 108 | MGMT_EV_DEVICE_UNPAIRED, |
109 | MGMT_EV_PASSKEY_NOTIFY, | 109 | MGMT_EV_PASSKEY_NOTIFY, |
110 | MGMT_EV_NEW_IRK, | 110 | MGMT_EV_NEW_IRK, |
111 | MGMT_EV_NEW_CSRK, | ||
111 | }; | 112 | }; |
112 | 113 | ||
113 | #define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000) | 114 | #define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000) |
@@ -212,7 +213,7 @@ static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status) | |||
212 | 213 | ||
213 | hdr = (void *) skb_put(skb, sizeof(*hdr)); | 214 | hdr = (void *) skb_put(skb, sizeof(*hdr)); |
214 | 215 | ||
215 | hdr->opcode = __constant_cpu_to_le16(MGMT_EV_CMD_STATUS); | 216 | hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS); |
216 | hdr->index = cpu_to_le16(index); | 217 | hdr->index = cpu_to_le16(index); |
217 | hdr->len = cpu_to_le16(sizeof(*ev)); | 218 | hdr->len = cpu_to_le16(sizeof(*ev)); |
218 | 219 | ||
@@ -243,7 +244,7 @@ static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status, | |||
243 | 244 | ||
244 | hdr = (void *) skb_put(skb, sizeof(*hdr)); | 245 | hdr = (void *) skb_put(skb, sizeof(*hdr)); |
245 | 246 | ||
246 | hdr->opcode = __constant_cpu_to_le16(MGMT_EV_CMD_COMPLETE); | 247 | hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE); |
247 | hdr->index = cpu_to_le16(index); | 248 | hdr->index = cpu_to_le16(index); |
248 | hdr->len = cpu_to_le16(sizeof(*ev) + rp_len); | 249 | hdr->len = cpu_to_le16(sizeof(*ev) + rp_len); |
249 | 250 | ||
@@ -269,7 +270,7 @@ static int read_version(struct sock *sk, struct hci_dev *hdev, void *data, | |||
269 | BT_DBG("sock %p", sk); | 270 | BT_DBG("sock %p", sk); |
270 | 271 | ||
271 | rp.version = MGMT_VERSION; | 272 | rp.version = MGMT_VERSION; |
272 | rp.revision = __constant_cpu_to_le16(MGMT_REVISION); | 273 | rp.revision = cpu_to_le16(MGMT_REVISION); |
273 | 274 | ||
274 | return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp, | 275 | return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp, |
275 | sizeof(rp)); | 276 | sizeof(rp)); |
@@ -293,8 +294,8 @@ static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data, | |||
293 | if (!rp) | 294 | if (!rp) |
294 | return -ENOMEM; | 295 | return -ENOMEM; |
295 | 296 | ||
296 | rp->num_commands = __constant_cpu_to_le16(num_commands); | 297 | rp->num_commands = cpu_to_le16(num_commands); |
297 | rp->num_events = __constant_cpu_to_le16(num_events); | 298 | rp->num_events = cpu_to_le16(num_events); |
298 | 299 | ||
299 | for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++) | 300 | for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++) |
300 | put_unaligned_le16(mgmt_commands[i], opcode); | 301 | put_unaligned_le16(mgmt_commands[i], opcode); |
@@ -857,8 +858,8 @@ static void enable_advertising(struct hci_request *req) | |||
857 | return; | 858 | return; |
858 | 859 | ||
859 | memset(&cp, 0, sizeof(cp)); | 860 | memset(&cp, 0, sizeof(cp)); |
860 | cp.min_interval = __constant_cpu_to_le16(0x0800); | 861 | cp.min_interval = cpu_to_le16(0x0800); |
861 | cp.max_interval = __constant_cpu_to_le16(0x0800); | 862 | cp.max_interval = cpu_to_le16(0x0800); |
862 | cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND; | 863 | cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND; |
863 | cp.own_address_type = own_addr_type; | 864 | cp.own_address_type = own_addr_type; |
864 | cp.channel_map = hdev->le_adv_channel_map; | 865 | cp.channel_map = hdev->le_adv_channel_map; |
@@ -1180,7 +1181,7 @@ static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len, | |||
1180 | if (hdev) | 1181 | if (hdev) |
1181 | hdr->index = cpu_to_le16(hdev->id); | 1182 | hdr->index = cpu_to_le16(hdev->id); |
1182 | else | 1183 | else |
1183 | hdr->index = __constant_cpu_to_le16(MGMT_INDEX_NONE); | 1184 | hdr->index = cpu_to_le16(MGMT_INDEX_NONE); |
1184 | hdr->len = cpu_to_le16(data_len); | 1185 | hdr->len = cpu_to_le16(data_len); |
1185 | 1186 | ||
1186 | if (data) | 1187 | if (data) |
@@ -1492,15 +1493,15 @@ static void write_fast_connectable(struct hci_request *req, bool enable) | |||
1492 | type = PAGE_SCAN_TYPE_INTERLACED; | 1493 | type = PAGE_SCAN_TYPE_INTERLACED; |
1493 | 1494 | ||
1494 | /* 160 msec page scan interval */ | 1495 | /* 160 msec page scan interval */ |
1495 | acp.interval = __constant_cpu_to_le16(0x0100); | 1496 | acp.interval = cpu_to_le16(0x0100); |
1496 | } else { | 1497 | } else { |
1497 | type = PAGE_SCAN_TYPE_STANDARD; /* default */ | 1498 | type = PAGE_SCAN_TYPE_STANDARD; /* default */ |
1498 | 1499 | ||
1499 | /* default 1.28 sec page scan */ | 1500 | /* default 1.28 sec page scan */ |
1500 | acp.interval = __constant_cpu_to_le16(0x0800); | 1501 | acp.interval = cpu_to_le16(0x0800); |
1501 | } | 1502 | } |
1502 | 1503 | ||
1503 | acp.window = __constant_cpu_to_le16(0x0012); | 1504 | acp.window = cpu_to_le16(0x0012); |
1504 | 1505 | ||
1505 | if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval || | 1506 | if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval || |
1506 | __cpu_to_le16(hdev->page_scan_window) != acp.window) | 1507 | __cpu_to_le16(hdev->page_scan_window) != acp.window) |
@@ -2351,7 +2352,7 @@ static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2351 | sizeof(struct mgmt_link_key_info); | 2352 | sizeof(struct mgmt_link_key_info); |
2352 | if (expected_len != len) { | 2353 | if (expected_len != len) { |
2353 | BT_ERR("load_link_keys: expected %u bytes, got %u bytes", | 2354 | BT_ERR("load_link_keys: expected %u bytes, got %u bytes", |
2354 | len, expected_len); | 2355 | expected_len, len); |
2355 | return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, | 2356 | return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, |
2356 | MGMT_STATUS_INVALID_PARAMS); | 2357 | MGMT_STATUS_INVALID_PARAMS); |
2357 | } | 2358 | } |
@@ -2761,11 +2762,23 @@ static struct pending_cmd *find_pairing(struct hci_conn *conn) | |||
2761 | 2762 | ||
2762 | static void pairing_complete(struct pending_cmd *cmd, u8 status) | 2763 | static void pairing_complete(struct pending_cmd *cmd, u8 status) |
2763 | { | 2764 | { |
2765 | const struct mgmt_cp_pair_device *cp = cmd->param; | ||
2764 | struct mgmt_rp_pair_device rp; | 2766 | struct mgmt_rp_pair_device rp; |
2765 | struct hci_conn *conn = cmd->user_data; | 2767 | struct hci_conn *conn = cmd->user_data; |
2766 | 2768 | ||
2767 | bacpy(&rp.addr.bdaddr, &conn->dst); | 2769 | /* If we had a pairing failure we might have already received |
2768 | rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type); | 2770 | * the remote Identity Address Information and updated the |
2771 | * hci_conn variables with it, however we would not yet have | ||
2772 | * notified user space of the resolved identity. Therefore, use | ||
2773 | * the address given in the Pair Device command in case the | ||
2774 | * pairing failed. | ||
2775 | */ | ||
2776 | if (status) { | ||
2777 | memcpy(&rp.addr, &cp->addr, sizeof(rp.addr)); | ||
2778 | } else { | ||
2779 | bacpy(&rp.addr.bdaddr, &conn->dst); | ||
2780 | rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type); | ||
2781 | } | ||
2769 | 2782 | ||
2770 | cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status, | 2783 | cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status, |
2771 | &rp, sizeof(rp)); | 2784 | &rp, sizeof(rp)); |
@@ -4427,7 +4440,7 @@ static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data, | |||
4427 | expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info); | 4440 | expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info); |
4428 | if (expected_len != len) { | 4441 | if (expected_len != len) { |
4429 | BT_ERR("load_irks: expected %u bytes, got %u bytes", | 4442 | BT_ERR("load_irks: expected %u bytes, got %u bytes", |
4430 | len, expected_len); | 4443 | expected_len, len); |
4431 | return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS, | 4444 | return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS, |
4432 | MGMT_STATUS_INVALID_PARAMS); | 4445 | MGMT_STATUS_INVALID_PARAMS); |
4433 | } | 4446 | } |
@@ -4507,7 +4520,7 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev, | |||
4507 | sizeof(struct mgmt_ltk_info); | 4520 | sizeof(struct mgmt_ltk_info); |
4508 | if (expected_len != len) { | 4521 | if (expected_len != len) { |
4509 | BT_ERR("load_keys: expected %u bytes, got %u bytes", | 4522 | BT_ERR("load_keys: expected %u bytes, got %u bytes", |
4510 | len, expected_len); | 4523 | expected_len, len); |
4511 | return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, | 4524 | return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, |
4512 | MGMT_STATUS_INVALID_PARAMS); | 4525 | MGMT_STATUS_INVALID_PARAMS); |
4513 | } | 4526 | } |
@@ -5004,7 +5017,7 @@ void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, | |||
5004 | mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL); | 5017 | mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL); |
5005 | } | 5018 | } |
5006 | 5019 | ||
5007 | void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key) | 5020 | void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent) |
5008 | { | 5021 | { |
5009 | struct mgmt_ev_new_long_term_key ev; | 5022 | struct mgmt_ev_new_long_term_key ev; |
5010 | 5023 | ||
@@ -5025,7 +5038,7 @@ void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key) | |||
5025 | (key->bdaddr.b[5] & 0xc0) != 0xc0) | 5038 | (key->bdaddr.b[5] & 0xc0) != 0xc0) |
5026 | ev.store_hint = 0x00; | 5039 | ev.store_hint = 0x00; |
5027 | else | 5040 | else |
5028 | ev.store_hint = 0x01; | 5041 | ev.store_hint = persistent; |
5029 | 5042 | ||
5030 | bacpy(&ev.key.addr.bdaddr, &key->bdaddr); | 5043 | bacpy(&ev.key.addr.bdaddr, &key->bdaddr); |
5031 | ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type); | 5044 | ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type); |
@@ -5072,6 +5085,36 @@ void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk) | |||
5072 | mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL); | 5085 | mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL); |
5073 | } | 5086 | } |
5074 | 5087 | ||
5088 | void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk, | ||
5089 | bool persistent) | ||
5090 | { | ||
5091 | struct mgmt_ev_new_csrk ev; | ||
5092 | |||
5093 | memset(&ev, 0, sizeof(ev)); | ||
5094 | |||
5095 | /* Devices using resolvable or non-resolvable random addresses | ||
5096 | * without providing an indentity resolving key don't require | ||
5097 | * to store signature resolving keys. Their addresses will change | ||
5098 | * the next time around. | ||
5099 | * | ||
5100 | * Only when a remote device provides an identity address | ||
5101 | * make sure the signature resolving key is stored. So allow | ||
5102 | * static random and public addresses here. | ||
5103 | */ | ||
5104 | if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM && | ||
5105 | (csrk->bdaddr.b[5] & 0xc0) != 0xc0) | ||
5106 | ev.store_hint = 0x00; | ||
5107 | else | ||
5108 | ev.store_hint = persistent; | ||
5109 | |||
5110 | bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr); | ||
5111 | ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type); | ||
5112 | ev.key.master = csrk->master; | ||
5113 | memcpy(ev.key.val, csrk->val, sizeof(csrk->val)); | ||
5114 | |||
5115 | mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL); | ||
5116 | } | ||
5117 | |||
5075 | static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data, | 5118 | static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data, |
5076 | u8 data_len) | 5119 | u8 data_len) |
5077 | { | 5120 | { |
@@ -5665,9 +5708,9 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | |||
5665 | 5708 | ||
5666 | ev->rssi = rssi; | 5709 | ev->rssi = rssi; |
5667 | if (cfm_name) | 5710 | if (cfm_name) |
5668 | ev->flags |= __constant_cpu_to_le32(MGMT_DEV_FOUND_CONFIRM_NAME); | 5711 | ev->flags |= cpu_to_le32(MGMT_DEV_FOUND_CONFIRM_NAME); |
5669 | if (!ssp) | 5712 | if (!ssp) |
5670 | ev->flags |= __constant_cpu_to_le32(MGMT_DEV_FOUND_LEGACY_PAIRING); | 5713 | ev->flags |= cpu_to_le32(MGMT_DEV_FOUND_LEGACY_PAIRING); |
5671 | 5714 | ||
5672 | if (eir_len > 0) | 5715 | if (eir_len > 0) |
5673 | memcpy(ev->eir, eir, eir_len); | 5716 | memcpy(ev->eir, eir, eir_len); |
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 21e15318937c..633cceeb943e 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c | |||
@@ -768,7 +768,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, | |||
768 | 768 | ||
769 | bacpy(&addr.l2_bdaddr, dst); | 769 | bacpy(&addr.l2_bdaddr, dst); |
770 | addr.l2_family = AF_BLUETOOTH; | 770 | addr.l2_family = AF_BLUETOOTH; |
771 | addr.l2_psm = __constant_cpu_to_le16(RFCOMM_PSM); | 771 | addr.l2_psm = cpu_to_le16(RFCOMM_PSM); |
772 | addr.l2_cid = 0; | 772 | addr.l2_cid = 0; |
773 | addr.l2_bdaddr_type = BDADDR_BREDR; | 773 | addr.l2_bdaddr_type = BDADDR_BREDR; |
774 | *err = kernel_connect(sock, (struct sockaddr *) &addr, sizeof(addr), O_NONBLOCK); | 774 | *err = kernel_connect(sock, (struct sockaddr *) &addr, sizeof(addr), O_NONBLOCK); |
@@ -2032,7 +2032,7 @@ static int rfcomm_add_listener(bdaddr_t *ba) | |||
2032 | /* Bind socket */ | 2032 | /* Bind socket */ |
2033 | bacpy(&addr.l2_bdaddr, ba); | 2033 | bacpy(&addr.l2_bdaddr, ba); |
2034 | addr.l2_family = AF_BLUETOOTH; | 2034 | addr.l2_family = AF_BLUETOOTH; |
2035 | addr.l2_psm = __constant_cpu_to_le16(RFCOMM_PSM); | 2035 | addr.l2_psm = cpu_to_le16(RFCOMM_PSM); |
2036 | addr.l2_cid = 0; | 2036 | addr.l2_cid = 0; |
2037 | addr.l2_bdaddr_type = BDADDR_BREDR; | 2037 | addr.l2_bdaddr_type = BDADDR_BREDR; |
2038 | err = kernel_bind(sock, (struct sockaddr *) &addr, sizeof(addr)); | 2038 | err = kernel_bind(sock, (struct sockaddr *) &addr, sizeof(addr)); |
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 24fa3964b3c8..ab1e6fcca4c5 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c | |||
@@ -676,20 +676,20 @@ static void sco_conn_defer_accept(struct hci_conn *conn, u16 setting) | |||
676 | bacpy(&cp.bdaddr, &conn->dst); | 676 | bacpy(&cp.bdaddr, &conn->dst); |
677 | cp.pkt_type = cpu_to_le16(conn->pkt_type); | 677 | cp.pkt_type = cpu_to_le16(conn->pkt_type); |
678 | 678 | ||
679 | cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40); | 679 | cp.tx_bandwidth = cpu_to_le32(0x00001f40); |
680 | cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40); | 680 | cp.rx_bandwidth = cpu_to_le32(0x00001f40); |
681 | cp.content_format = cpu_to_le16(setting); | 681 | cp.content_format = cpu_to_le16(setting); |
682 | 682 | ||
683 | switch (setting & SCO_AIRMODE_MASK) { | 683 | switch (setting & SCO_AIRMODE_MASK) { |
684 | case SCO_AIRMODE_TRANSP: | 684 | case SCO_AIRMODE_TRANSP: |
685 | if (conn->pkt_type & ESCO_2EV3) | 685 | if (conn->pkt_type & ESCO_2EV3) |
686 | cp.max_latency = __constant_cpu_to_le16(0x0008); | 686 | cp.max_latency = cpu_to_le16(0x0008); |
687 | else | 687 | else |
688 | cp.max_latency = __constant_cpu_to_le16(0x000D); | 688 | cp.max_latency = cpu_to_le16(0x000D); |
689 | cp.retrans_effort = 0x02; | 689 | cp.retrans_effort = 0x02; |
690 | break; | 690 | break; |
691 | case SCO_AIRMODE_CVSD: | 691 | case SCO_AIRMODE_CVSD: |
692 | cp.max_latency = __constant_cpu_to_le16(0xffff); | 692 | cp.max_latency = cpu_to_le16(0xffff); |
693 | cp.retrans_effort = 0xff; | 693 | cp.retrans_effort = 0xff; |
694 | break; | 694 | break; |
695 | } | 695 | } |
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index f886bcae1b7e..2a7ee7f6cd8b 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c | |||
@@ -35,14 +35,14 @@ | |||
35 | 35 | ||
36 | #define AUTH_REQ_MASK 0x07 | 36 | #define AUTH_REQ_MASK 0x07 |
37 | 37 | ||
38 | static inline void swap128(u8 src[16], u8 dst[16]) | 38 | static inline void swap128(const u8 src[16], u8 dst[16]) |
39 | { | 39 | { |
40 | int i; | 40 | int i; |
41 | for (i = 0; i < 16; i++) | 41 | for (i = 0; i < 16; i++) |
42 | dst[15 - i] = src[i]; | 42 | dst[15 - i] = src[i]; |
43 | } | 43 | } |
44 | 44 | ||
45 | static inline void swap56(u8 src[7], u8 dst[7]) | 45 | static inline void swap56(const u8 src[7], u8 dst[7]) |
46 | { | 46 | { |
47 | int i; | 47 | int i; |
48 | for (i = 0; i < 7; i++) | 48 | for (i = 0; i < 7; i++) |
@@ -53,6 +53,7 @@ static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r) | |||
53 | { | 53 | { |
54 | struct blkcipher_desc desc; | 54 | struct blkcipher_desc desc; |
55 | struct scatterlist sg; | 55 | struct scatterlist sg; |
56 | uint8_t tmp[16], data[16]; | ||
56 | int err; | 57 | int err; |
57 | 58 | ||
58 | if (tfm == NULL) { | 59 | if (tfm == NULL) { |
@@ -63,34 +64,40 @@ static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r) | |||
63 | desc.tfm = tfm; | 64 | desc.tfm = tfm; |
64 | desc.flags = 0; | 65 | desc.flags = 0; |
65 | 66 | ||
66 | err = crypto_blkcipher_setkey(tfm, k, 16); | 67 | /* The most significant octet of key corresponds to k[0] */ |
68 | swap128(k, tmp); | ||
69 | |||
70 | err = crypto_blkcipher_setkey(tfm, tmp, 16); | ||
67 | if (err) { | 71 | if (err) { |
68 | BT_ERR("cipher setkey failed: %d", err); | 72 | BT_ERR("cipher setkey failed: %d", err); |
69 | return err; | 73 | return err; |
70 | } | 74 | } |
71 | 75 | ||
72 | sg_init_one(&sg, r, 16); | 76 | /* Most significant octet of plaintextData corresponds to data[0] */ |
77 | swap128(r, data); | ||
78 | |||
79 | sg_init_one(&sg, data, 16); | ||
73 | 80 | ||
74 | err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16); | 81 | err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16); |
75 | if (err) | 82 | if (err) |
76 | BT_ERR("Encrypt data error %d", err); | 83 | BT_ERR("Encrypt data error %d", err); |
77 | 84 | ||
85 | /* Most significant octet of encryptedData corresponds to data[0] */ | ||
86 | swap128(data, r); | ||
87 | |||
78 | return err; | 88 | return err; |
79 | } | 89 | } |
80 | 90 | ||
81 | static int smp_ah(struct crypto_blkcipher *tfm, u8 irk[16], u8 r[3], u8 res[3]) | 91 | static int smp_ah(struct crypto_blkcipher *tfm, u8 irk[16], u8 r[3], u8 res[3]) |
82 | { | 92 | { |
83 | u8 _res[16], k[16]; | 93 | u8 _res[16]; |
84 | int err; | 94 | int err; |
85 | 95 | ||
86 | /* r' = padding || r */ | 96 | /* r' = padding || r */ |
87 | memset(_res, 0, 13); | 97 | memcpy(_res, r, 3); |
88 | _res[13] = r[2]; | 98 | memset(_res + 3, 0, 13); |
89 | _res[14] = r[1]; | ||
90 | _res[15] = r[0]; | ||
91 | 99 | ||
92 | swap128(irk, k); | 100 | err = smp_e(tfm, irk, _res); |
93 | err = smp_e(tfm, k, _res); | ||
94 | if (err) { | 101 | if (err) { |
95 | BT_ERR("Encrypt error"); | 102 | BT_ERR("Encrypt error"); |
96 | return err; | 103 | return err; |
@@ -102,9 +109,7 @@ static int smp_ah(struct crypto_blkcipher *tfm, u8 irk[16], u8 r[3], u8 res[3]) | |||
102 | * by taking the least significant 24 bits of the output of e as the | 109 | * by taking the least significant 24 bits of the output of e as the |
103 | * result of ah. | 110 | * result of ah. |
104 | */ | 111 | */ |
105 | res[0] = _res[15]; | 112 | memcpy(res, _res, 3); |
106 | res[1] = _res[14]; | ||
107 | res[2] = _res[13]; | ||
108 | 113 | ||
109 | return 0; | 114 | return 0; |
110 | } | 115 | } |
@@ -152,16 +157,15 @@ static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16], | |||
152 | memset(p1, 0, 16); | 157 | memset(p1, 0, 16); |
153 | 158 | ||
154 | /* p1 = pres || preq || _rat || _iat */ | 159 | /* p1 = pres || preq || _rat || _iat */ |
155 | swap56(pres, p1); | 160 | p1[0] = _iat; |
156 | swap56(preq, p1 + 7); | 161 | p1[1] = _rat; |
157 | p1[14] = _rat; | 162 | memcpy(p1 + 2, preq, 7); |
158 | p1[15] = _iat; | 163 | memcpy(p1 + 9, pres, 7); |
159 | |||
160 | memset(p2, 0, 16); | ||
161 | 164 | ||
162 | /* p2 = padding || ia || ra */ | 165 | /* p2 = padding || ia || ra */ |
163 | baswap((bdaddr_t *) (p2 + 4), ia); | 166 | memcpy(p2, ra, 6); |
164 | baswap((bdaddr_t *) (p2 + 10), ra); | 167 | memcpy(p2 + 6, ia, 6); |
168 | memset(p2 + 12, 0, 4); | ||
165 | 169 | ||
166 | /* res = r XOR p1 */ | 170 | /* res = r XOR p1 */ |
167 | u128_xor((u128 *) res, (u128 *) r, (u128 *) p1); | 171 | u128_xor((u128 *) res, (u128 *) r, (u128 *) p1); |
@@ -190,8 +194,8 @@ static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16], u8 r1[16], | |||
190 | int err; | 194 | int err; |
191 | 195 | ||
192 | /* Just least significant octets from r1 and r2 are considered */ | 196 | /* Just least significant octets from r1 and r2 are considered */ |
193 | memcpy(_r, r1 + 8, 8); | 197 | memcpy(_r, r2, 8); |
194 | memcpy(_r + 8, r2 + 8, 8); | 198 | memcpy(_r + 8, r1, 8); |
195 | 199 | ||
196 | err = smp_e(tfm, k, _r); | 200 | err = smp_e(tfm, k, _r); |
197 | if (err) | 201 | if (err) |
@@ -218,7 +222,7 @@ static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code, | |||
218 | 222 | ||
219 | lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); | 223 | lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); |
220 | lh->len = cpu_to_le16(sizeof(code) + dlen); | 224 | lh->len = cpu_to_le16(sizeof(code) + dlen); |
221 | lh->cid = __constant_cpu_to_le16(L2CAP_CID_SMP); | 225 | lh->cid = cpu_to_le16(L2CAP_CID_SMP); |
222 | 226 | ||
223 | memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code)); | 227 | memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code)); |
224 | 228 | ||
@@ -273,8 +277,8 @@ static void build_pairing_cmd(struct l2cap_conn *conn, | |||
273 | u8 local_dist = 0, remote_dist = 0; | 277 | u8 local_dist = 0, remote_dist = 0; |
274 | 278 | ||
275 | if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->dev_flags)) { | 279 | if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->dev_flags)) { |
276 | local_dist = SMP_DIST_ENC_KEY; | 280 | local_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN; |
277 | remote_dist = SMP_DIST_ENC_KEY; | 281 | remote_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN; |
278 | authreq |= SMP_AUTH_BONDING; | 282 | authreq |= SMP_AUTH_BONDING; |
279 | } else { | 283 | } else { |
280 | authreq &= ~SMP_AUTH_BONDING; | 284 | authreq &= ~SMP_AUTH_BONDING; |
@@ -403,16 +407,14 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth, | |||
403 | method = REQ_PASSKEY; | 407 | method = REQ_PASSKEY; |
404 | } | 408 | } |
405 | 409 | ||
406 | /* Generate random passkey. Not valid until confirmed. */ | 410 | /* Generate random passkey. */ |
407 | if (method == CFM_PASSKEY) { | 411 | if (method == CFM_PASSKEY) { |
408 | u8 key[16]; | 412 | memset(smp->tk, 0, sizeof(smp->tk)); |
409 | |||
410 | memset(key, 0, sizeof(key)); | ||
411 | get_random_bytes(&passkey, sizeof(passkey)); | 413 | get_random_bytes(&passkey, sizeof(passkey)); |
412 | passkey %= 1000000; | 414 | passkey %= 1000000; |
413 | put_unaligned_le32(passkey, key); | 415 | put_unaligned_le32(passkey, smp->tk); |
414 | swap128(key, smp->tk); | ||
415 | BT_DBG("PassKey: %d", passkey); | 416 | BT_DBG("PassKey: %d", passkey); |
417 | set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags); | ||
416 | } | 418 | } |
417 | 419 | ||
418 | hci_dev_lock(hcon->hdev); | 420 | hci_dev_lock(hcon->hdev); |
@@ -421,7 +423,7 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth, | |||
421 | ret = mgmt_user_passkey_request(hcon->hdev, &hcon->dst, | 423 | ret = mgmt_user_passkey_request(hcon->hdev, &hcon->dst, |
422 | hcon->type, hcon->dst_type); | 424 | hcon->type, hcon->dst_type); |
423 | else | 425 | else |
424 | ret = mgmt_user_confirm_request(hcon->hdev, &hcon->dst, | 426 | ret = mgmt_user_passkey_notify(hcon->hdev, &hcon->dst, |
425 | hcon->type, hcon->dst_type, | 427 | hcon->type, hcon->dst_type, |
426 | cpu_to_le32(passkey), 0); | 428 | cpu_to_le32(passkey), 0); |
427 | 429 | ||
@@ -438,7 +440,7 @@ static void confirm_work(struct work_struct *work) | |||
438 | struct crypto_blkcipher *tfm = hdev->tfm_aes; | 440 | struct crypto_blkcipher *tfm = hdev->tfm_aes; |
439 | struct smp_cmd_pairing_confirm cp; | 441 | struct smp_cmd_pairing_confirm cp; |
440 | int ret; | 442 | int ret; |
441 | u8 res[16], reason; | 443 | u8 reason; |
442 | 444 | ||
443 | BT_DBG("conn %p", conn); | 445 | BT_DBG("conn %p", conn); |
444 | 446 | ||
@@ -447,7 +449,8 @@ static void confirm_work(struct work_struct *work) | |||
447 | 449 | ||
448 | ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, | 450 | ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, |
449 | conn->hcon->init_addr_type, &conn->hcon->init_addr, | 451 | conn->hcon->init_addr_type, &conn->hcon->init_addr, |
450 | conn->hcon->resp_addr_type, &conn->hcon->resp_addr, res); | 452 | conn->hcon->resp_addr_type, &conn->hcon->resp_addr, |
453 | cp.confirm_val); | ||
451 | 454 | ||
452 | hci_dev_unlock(hdev); | 455 | hci_dev_unlock(hdev); |
453 | 456 | ||
@@ -458,7 +461,6 @@ static void confirm_work(struct work_struct *work) | |||
458 | 461 | ||
459 | clear_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags); | 462 | clear_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags); |
460 | 463 | ||
461 | swap128(res, cp.confirm_val); | ||
462 | smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp); | 464 | smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp); |
463 | 465 | ||
464 | return; | 466 | return; |
@@ -474,7 +476,7 @@ static void random_work(struct work_struct *work) | |||
474 | struct hci_conn *hcon = conn->hcon; | 476 | struct hci_conn *hcon = conn->hcon; |
475 | struct hci_dev *hdev = hcon->hdev; | 477 | struct hci_dev *hdev = hcon->hdev; |
476 | struct crypto_blkcipher *tfm = hdev->tfm_aes; | 478 | struct crypto_blkcipher *tfm = hdev->tfm_aes; |
477 | u8 reason, confirm[16], res[16], key[16]; | 479 | u8 reason, confirm[16]; |
478 | int ret; | 480 | int ret; |
479 | 481 | ||
480 | if (IS_ERR_OR_NULL(tfm)) { | 482 | if (IS_ERR_OR_NULL(tfm)) { |
@@ -489,7 +491,7 @@ static void random_work(struct work_struct *work) | |||
489 | 491 | ||
490 | ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, | 492 | ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, |
491 | hcon->init_addr_type, &hcon->init_addr, | 493 | hcon->init_addr_type, &hcon->init_addr, |
492 | hcon->resp_addr_type, &hcon->resp_addr, res); | 494 | hcon->resp_addr_type, &hcon->resp_addr, confirm); |
493 | 495 | ||
494 | hci_dev_unlock(hdev); | 496 | hci_dev_unlock(hdev); |
495 | 497 | ||
@@ -498,8 +500,6 @@ static void random_work(struct work_struct *work) | |||
498 | goto error; | 500 | goto error; |
499 | } | 501 | } |
500 | 502 | ||
501 | swap128(res, confirm); | ||
502 | |||
503 | if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) { | 503 | if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) { |
504 | BT_ERR("Pairing failed (confirmation values mismatch)"); | 504 | BT_ERR("Pairing failed (confirmation values mismatch)"); |
505 | reason = SMP_CONFIRM_FAILED; | 505 | reason = SMP_CONFIRM_FAILED; |
@@ -511,8 +511,7 @@ static void random_work(struct work_struct *work) | |||
511 | __le64 rand = 0; | 511 | __le64 rand = 0; |
512 | __le16 ediv = 0; | 512 | __le16 ediv = 0; |
513 | 513 | ||
514 | smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, key); | 514 | smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, stk); |
515 | swap128(key, stk); | ||
516 | 515 | ||
517 | memset(stk + smp->enc_key_size, 0, | 516 | memset(stk + smp->enc_key_size, 0, |
518 | SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size); | 517 | SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size); |
@@ -525,15 +524,14 @@ static void random_work(struct work_struct *work) | |||
525 | hci_le_start_enc(hcon, ediv, rand, stk); | 524 | hci_le_start_enc(hcon, ediv, rand, stk); |
526 | hcon->enc_key_size = smp->enc_key_size; | 525 | hcon->enc_key_size = smp->enc_key_size; |
527 | } else { | 526 | } else { |
528 | u8 stk[16], r[16]; | 527 | u8 stk[16]; |
529 | __le64 rand = 0; | 528 | __le64 rand = 0; |
530 | __le16 ediv = 0; | 529 | __le16 ediv = 0; |
531 | 530 | ||
532 | swap128(smp->prnd, r); | 531 | smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd), |
533 | smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r); | 532 | smp->prnd); |
534 | 533 | ||
535 | smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, key); | 534 | smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, stk); |
536 | swap128(key, stk); | ||
537 | 535 | ||
538 | memset(stk + smp->enc_key_size, 0, | 536 | memset(stk + smp->enc_key_size, 0, |
539 | SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size); | 537 | SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size); |
@@ -596,6 +594,9 @@ void smp_chan_destroy(struct l2cap_conn *conn) | |||
596 | complete = test_bit(SMP_FLAG_COMPLETE, &smp->smp_flags); | 594 | complete = test_bit(SMP_FLAG_COMPLETE, &smp->smp_flags); |
597 | mgmt_smp_complete(conn->hcon, complete); | 595 | mgmt_smp_complete(conn->hcon, complete); |
598 | 596 | ||
597 | kfree(smp->csrk); | ||
598 | kfree(smp->slave_csrk); | ||
599 | |||
599 | /* If pairing failed clean up any keys we might have */ | 600 | /* If pairing failed clean up any keys we might have */ |
600 | if (!complete) { | 601 | if (!complete) { |
601 | if (smp->ltk) { | 602 | if (smp->ltk) { |
@@ -625,7 +626,6 @@ int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey) | |||
625 | struct l2cap_conn *conn = hcon->smp_conn; | 626 | struct l2cap_conn *conn = hcon->smp_conn; |
626 | struct smp_chan *smp; | 627 | struct smp_chan *smp; |
627 | u32 value; | 628 | u32 value; |
628 | u8 key[16]; | ||
629 | 629 | ||
630 | BT_DBG(""); | 630 | BT_DBG(""); |
631 | 631 | ||
@@ -637,10 +637,9 @@ int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey) | |||
637 | switch (mgmt_op) { | 637 | switch (mgmt_op) { |
638 | case MGMT_OP_USER_PASSKEY_REPLY: | 638 | case MGMT_OP_USER_PASSKEY_REPLY: |
639 | value = le32_to_cpu(passkey); | 639 | value = le32_to_cpu(passkey); |
640 | memset(key, 0, sizeof(key)); | 640 | memset(smp->tk, 0, sizeof(smp->tk)); |
641 | BT_DBG("PassKey: %d", value); | 641 | BT_DBG("PassKey: %d", value); |
642 | put_unaligned_le32(value, key); | 642 | put_unaligned_le32(value, smp->tk); |
643 | swap128(key, smp->tk); | ||
644 | /* Fall Through */ | 643 | /* Fall Through */ |
645 | case MGMT_OP_USER_CONFIRM_REPLY: | 644 | case MGMT_OP_USER_CONFIRM_REPLY: |
646 | set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags); | 645 | set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags); |
@@ -745,6 +744,11 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb) | |||
745 | smp->prsp[0] = SMP_CMD_PAIRING_RSP; | 744 | smp->prsp[0] = SMP_CMD_PAIRING_RSP; |
746 | memcpy(&smp->prsp[1], rsp, sizeof(*rsp)); | 745 | memcpy(&smp->prsp[1], rsp, sizeof(*rsp)); |
747 | 746 | ||
747 | /* Update remote key distribution in case the remote cleared | ||
748 | * some bits that we had enabled in our request. | ||
749 | */ | ||
750 | smp->remote_key_dist &= rsp->resp_key_dist; | ||
751 | |||
748 | if ((req->auth_req & SMP_AUTH_BONDING) && | 752 | if ((req->auth_req & SMP_AUTH_BONDING) && |
749 | (rsp->auth_req & SMP_AUTH_BONDING)) | 753 | (rsp->auth_req & SMP_AUTH_BONDING)) |
750 | auth = SMP_AUTH_BONDING; | 754 | auth = SMP_AUTH_BONDING; |
@@ -758,10 +762,8 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb) | |||
758 | set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags); | 762 | set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags); |
759 | 763 | ||
760 | /* Can't compose response until we have been confirmed */ | 764 | /* Can't compose response until we have been confirmed */ |
761 | if (!test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) | 765 | if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) |
762 | return 0; | 766 | queue_work(hdev->workqueue, &smp->confirm); |
763 | |||
764 | queue_work(hdev->workqueue, &smp->confirm); | ||
765 | 767 | ||
766 | return 0; | 768 | return 0; |
767 | } | 769 | } |
@@ -779,17 +781,13 @@ static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb) | |||
779 | memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf)); | 781 | memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf)); |
780 | skb_pull(skb, sizeof(smp->pcnf)); | 782 | skb_pull(skb, sizeof(smp->pcnf)); |
781 | 783 | ||
782 | if (conn->hcon->out) { | 784 | if (conn->hcon->out) |
783 | u8 random[16]; | 785 | smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd), |
784 | 786 | smp->prnd); | |
785 | swap128(smp->prnd, random); | 787 | else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) |
786 | smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random), | ||
787 | random); | ||
788 | } else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) { | ||
789 | queue_work(hdev->workqueue, &smp->confirm); | 788 | queue_work(hdev->workqueue, &smp->confirm); |
790 | } else { | 789 | else |
791 | set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags); | 790 | set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags); |
792 | } | ||
793 | 791 | ||
794 | return 0; | 792 | return 0; |
795 | } | 793 | } |
@@ -804,7 +802,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) | |||
804 | if (skb->len < sizeof(smp->rrnd)) | 802 | if (skb->len < sizeof(smp->rrnd)) |
805 | return SMP_UNSPECIFIED; | 803 | return SMP_UNSPECIFIED; |
806 | 804 | ||
807 | swap128(skb->data, smp->rrnd); | 805 | memcpy(smp->rrnd, skb->data, sizeof(smp->rrnd)); |
808 | skb_pull(skb, sizeof(smp->rrnd)); | 806 | skb_pull(skb, sizeof(smp->rrnd)); |
809 | 807 | ||
810 | queue_work(hdev->workqueue, &smp->random); | 808 | queue_work(hdev->workqueue, &smp->random); |
@@ -910,6 +908,12 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) | |||
910 | 908 | ||
911 | authreq = seclevel_to_authreq(sec_level); | 909 | authreq = seclevel_to_authreq(sec_level); |
912 | 910 | ||
911 | /* hcon->auth_type is set by pair_device in mgmt.c. If the MITM | ||
912 | * flag is set we should also set it for the SMP request. | ||
913 | */ | ||
914 | if ((hcon->auth_type & 0x01)) | ||
915 | authreq |= SMP_AUTH_MITM; | ||
916 | |||
913 | if (hcon->link_mode & HCI_LM_MASTER) { | 917 | if (hcon->link_mode & HCI_LM_MASTER) { |
914 | struct smp_cmd_pairing cp; | 918 | struct smp_cmd_pairing cp; |
915 | 919 | ||
@@ -1065,6 +1069,41 @@ static int smp_cmd_ident_addr_info(struct l2cap_conn *conn, | |||
1065 | return 0; | 1069 | return 0; |
1066 | } | 1070 | } |
1067 | 1071 | ||
1072 | static int smp_cmd_sign_info(struct l2cap_conn *conn, struct sk_buff *skb) | ||
1073 | { | ||
1074 | struct smp_cmd_sign_info *rp = (void *) skb->data; | ||
1075 | struct smp_chan *smp = conn->smp_chan; | ||
1076 | struct hci_dev *hdev = conn->hcon->hdev; | ||
1077 | struct smp_csrk *csrk; | ||
1078 | |||
1079 | BT_DBG("conn %p", conn); | ||
1080 | |||
1081 | if (skb->len < sizeof(*rp)) | ||
1082 | return SMP_UNSPECIFIED; | ||
1083 | |||
1084 | /* Ignore this PDU if it wasn't requested */ | ||
1085 | if (!(smp->remote_key_dist & SMP_DIST_SIGN)) | ||
1086 | return 0; | ||
1087 | |||
1088 | /* Mark the information as received */ | ||
1089 | smp->remote_key_dist &= ~SMP_DIST_SIGN; | ||
1090 | |||
1091 | skb_pull(skb, sizeof(*rp)); | ||
1092 | |||
1093 | hci_dev_lock(hdev); | ||
1094 | csrk = kzalloc(sizeof(*csrk), GFP_KERNEL); | ||
1095 | if (csrk) { | ||
1096 | csrk->master = 0x01; | ||
1097 | memcpy(csrk->val, rp->csrk, sizeof(csrk->val)); | ||
1098 | } | ||
1099 | smp->csrk = csrk; | ||
1100 | if (!(smp->remote_key_dist & SMP_DIST_SIGN)) | ||
1101 | smp_distribute_keys(conn); | ||
1102 | hci_dev_unlock(hdev); | ||
1103 | |||
1104 | return 0; | ||
1105 | } | ||
1106 | |||
1068 | int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) | 1107 | int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) |
1069 | { | 1108 | { |
1070 | struct hci_conn *hcon = conn->hcon; | 1109 | struct hci_conn *hcon = conn->hcon; |
@@ -1147,8 +1186,7 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) | |||
1147 | break; | 1186 | break; |
1148 | 1187 | ||
1149 | case SMP_CMD_SIGN_INFO: | 1188 | case SMP_CMD_SIGN_INFO: |
1150 | /* Just ignored */ | 1189 | reason = smp_cmd_sign_info(conn, skb); |
1151 | reason = 0; | ||
1152 | break; | 1190 | break; |
1153 | 1191 | ||
1154 | default: | 1192 | default: |
@@ -1172,20 +1210,40 @@ static void smp_notify_keys(struct l2cap_conn *conn) | |||
1172 | struct smp_chan *smp = conn->smp_chan; | 1210 | struct smp_chan *smp = conn->smp_chan; |
1173 | struct hci_conn *hcon = conn->hcon; | 1211 | struct hci_conn *hcon = conn->hcon; |
1174 | struct hci_dev *hdev = hcon->hdev; | 1212 | struct hci_dev *hdev = hcon->hdev; |
1213 | struct smp_cmd_pairing *req = (void *) &smp->preq[1]; | ||
1214 | struct smp_cmd_pairing *rsp = (void *) &smp->prsp[1]; | ||
1215 | bool persistent; | ||
1175 | 1216 | ||
1176 | if (smp->remote_irk) | 1217 | if (smp->remote_irk) |
1177 | mgmt_new_irk(hdev, smp->remote_irk); | 1218 | mgmt_new_irk(hdev, smp->remote_irk); |
1178 | 1219 | ||
1220 | /* The LTKs and CSRKs should be persistent only if both sides | ||
1221 | * had the bonding bit set in their authentication requests. | ||
1222 | */ | ||
1223 | persistent = !!((req->auth_req & rsp->auth_req) & SMP_AUTH_BONDING); | ||
1224 | |||
1225 | if (smp->csrk) { | ||
1226 | smp->csrk->bdaddr_type = hcon->dst_type; | ||
1227 | bacpy(&smp->csrk->bdaddr, &hcon->dst); | ||
1228 | mgmt_new_csrk(hdev, smp->csrk, persistent); | ||
1229 | } | ||
1230 | |||
1231 | if (smp->slave_csrk) { | ||
1232 | smp->slave_csrk->bdaddr_type = hcon->dst_type; | ||
1233 | bacpy(&smp->slave_csrk->bdaddr, &hcon->dst); | ||
1234 | mgmt_new_csrk(hdev, smp->slave_csrk, persistent); | ||
1235 | } | ||
1236 | |||
1179 | if (smp->ltk) { | 1237 | if (smp->ltk) { |
1180 | smp->ltk->bdaddr_type = hcon->dst_type; | 1238 | smp->ltk->bdaddr_type = hcon->dst_type; |
1181 | bacpy(&smp->ltk->bdaddr, &hcon->dst); | 1239 | bacpy(&smp->ltk->bdaddr, &hcon->dst); |
1182 | mgmt_new_ltk(hdev, smp->ltk); | 1240 | mgmt_new_ltk(hdev, smp->ltk, persistent); |
1183 | } | 1241 | } |
1184 | 1242 | ||
1185 | if (smp->slave_ltk) { | 1243 | if (smp->slave_ltk) { |
1186 | smp->slave_ltk->bdaddr_type = hcon->dst_type; | 1244 | smp->slave_ltk->bdaddr_type = hcon->dst_type; |
1187 | bacpy(&smp->slave_ltk->bdaddr, &hcon->dst); | 1245 | bacpy(&smp->slave_ltk->bdaddr, &hcon->dst); |
1188 | mgmt_new_ltk(hdev, smp->slave_ltk); | 1246 | mgmt_new_ltk(hdev, smp->slave_ltk, persistent); |
1189 | } | 1247 | } |
1190 | } | 1248 | } |
1191 | 1249 | ||
@@ -1274,10 +1332,18 @@ int smp_distribute_keys(struct l2cap_conn *conn) | |||
1274 | 1332 | ||
1275 | if (*keydist & SMP_DIST_SIGN) { | 1333 | if (*keydist & SMP_DIST_SIGN) { |
1276 | struct smp_cmd_sign_info sign; | 1334 | struct smp_cmd_sign_info sign; |
1335 | struct smp_csrk *csrk; | ||
1277 | 1336 | ||
1278 | /* Send a dummy key */ | 1337 | /* Generate a new random key */ |
1279 | get_random_bytes(sign.csrk, sizeof(sign.csrk)); | 1338 | get_random_bytes(sign.csrk, sizeof(sign.csrk)); |
1280 | 1339 | ||
1340 | csrk = kzalloc(sizeof(*csrk), GFP_KERNEL); | ||
1341 | if (csrk) { | ||
1342 | csrk->master = 0x00; | ||
1343 | memcpy(csrk->val, sign.csrk, sizeof(csrk->val)); | ||
1344 | } | ||
1345 | smp->slave_csrk = csrk; | ||
1346 | |||
1281 | smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign); | 1347 | smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign); |
1282 | 1348 | ||
1283 | *keydist &= ~SMP_DIST_SIGN; | 1349 | *keydist &= ~SMP_DIST_SIGN; |
diff --git a/net/bluetooth/smp.h b/net/bluetooth/smp.h index f55d83617218..b6913471815a 100644 --- a/net/bluetooth/smp.h +++ b/net/bluetooth/smp.h | |||
@@ -121,7 +121,7 @@ struct smp_cmd_security_req { | |||
121 | #define SMP_FLAG_LTK_ENCRYPT 4 | 121 | #define SMP_FLAG_LTK_ENCRYPT 4 |
122 | #define SMP_FLAG_COMPLETE 5 | 122 | #define SMP_FLAG_COMPLETE 5 |
123 | 123 | ||
124 | #define SMP_REENCRYPT_TIMEOUT msecs_to_jiffies(250) | 124 | #define SMP_REENCRYPT_TIMEOUT msecs_to_jiffies(500) |
125 | 125 | ||
126 | struct smp_chan { | 126 | struct smp_chan { |
127 | struct l2cap_conn *conn; | 127 | struct l2cap_conn *conn; |
@@ -136,6 +136,8 @@ struct smp_chan { | |||
136 | bdaddr_t id_addr; | 136 | bdaddr_t id_addr; |
137 | u8 id_addr_type; | 137 | u8 id_addr_type; |
138 | u8 irk[16]; | 138 | u8 irk[16]; |
139 | struct smp_csrk *csrk; | ||
140 | struct smp_csrk *slave_csrk; | ||
139 | struct smp_ltk *ltk; | 141 | struct smp_ltk *ltk; |
140 | struct smp_ltk *slave_ltk; | 142 | struct smp_ltk *slave_ltk; |
141 | struct smp_irk *remote_irk; | 143 | struct smp_irk *remote_irk; |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 1acb29109b45..aaa59d719592 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -2914,11 +2914,11 @@ static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy, | |||
2914 | 2914 | ||
2915 | static int ieee80211_start_radar_detection(struct wiphy *wiphy, | 2915 | static int ieee80211_start_radar_detection(struct wiphy *wiphy, |
2916 | struct net_device *dev, | 2916 | struct net_device *dev, |
2917 | struct cfg80211_chan_def *chandef) | 2917 | struct cfg80211_chan_def *chandef, |
2918 | u32 cac_time_ms) | ||
2918 | { | 2919 | { |
2919 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 2920 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
2920 | struct ieee80211_local *local = sdata->local; | 2921 | struct ieee80211_local *local = sdata->local; |
2921 | unsigned long timeout; | ||
2922 | int err; | 2922 | int err; |
2923 | 2923 | ||
2924 | mutex_lock(&local->mtx); | 2924 | mutex_lock(&local->mtx); |
@@ -2937,9 +2937,9 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy, | |||
2937 | if (err) | 2937 | if (err) |
2938 | goto out_unlock; | 2938 | goto out_unlock; |
2939 | 2939 | ||
2940 | timeout = msecs_to_jiffies(IEEE80211_DFS_MIN_CAC_TIME_MS); | ||
2941 | ieee80211_queue_delayed_work(&sdata->local->hw, | 2940 | ieee80211_queue_delayed_work(&sdata->local->hw, |
2942 | &sdata->dfs_cac_timer_work, timeout); | 2941 | &sdata->dfs_cac_timer_work, |
2942 | msecs_to_jiffies(cac_time_ms)); | ||
2943 | 2943 | ||
2944 | out_unlock: | 2944 | out_unlock: |
2945 | mutex_unlock(&local->mtx); | 2945 | mutex_unlock(&local->mtx); |
@@ -3089,52 +3089,11 @@ unlock: | |||
3089 | sdata_unlock(sdata); | 3089 | sdata_unlock(sdata); |
3090 | } | 3090 | } |
3091 | 3091 | ||
3092 | int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | 3092 | static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata, |
3093 | struct cfg80211_csa_settings *params) | 3093 | struct cfg80211_csa_settings *params, |
3094 | u32 *changed) | ||
3094 | { | 3095 | { |
3095 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 3096 | int err; |
3096 | struct ieee80211_local *local = sdata->local; | ||
3097 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
3098 | struct ieee80211_chanctx *chanctx; | ||
3099 | struct ieee80211_if_mesh __maybe_unused *ifmsh; | ||
3100 | int err, num_chanctx, changed = 0; | ||
3101 | |||
3102 | sdata_assert_lock(sdata); | ||
3103 | |||
3104 | if (!list_empty(&local->roc_list) || local->scanning) | ||
3105 | return -EBUSY; | ||
3106 | |||
3107 | if (sdata->wdev.cac_started) | ||
3108 | return -EBUSY; | ||
3109 | |||
3110 | if (cfg80211_chandef_identical(¶ms->chandef, | ||
3111 | &sdata->vif.bss_conf.chandef)) | ||
3112 | return -EINVAL; | ||
3113 | |||
3114 | rcu_read_lock(); | ||
3115 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
3116 | if (!chanctx_conf) { | ||
3117 | rcu_read_unlock(); | ||
3118 | return -EBUSY; | ||
3119 | } | ||
3120 | |||
3121 | /* don't handle for multi-VIF cases */ | ||
3122 | chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf); | ||
3123 | if (chanctx->refcount > 1) { | ||
3124 | rcu_read_unlock(); | ||
3125 | return -EBUSY; | ||
3126 | } | ||
3127 | num_chanctx = 0; | ||
3128 | list_for_each_entry_rcu(chanctx, &local->chanctx_list, list) | ||
3129 | num_chanctx++; | ||
3130 | rcu_read_unlock(); | ||
3131 | |||
3132 | if (num_chanctx > 1) | ||
3133 | return -EBUSY; | ||
3134 | |||
3135 | /* don't allow another channel switch if one is already active. */ | ||
3136 | if (sdata->vif.csa_active) | ||
3137 | return -EBUSY; | ||
3138 | 3097 | ||
3139 | switch (sdata->vif.type) { | 3098 | switch (sdata->vif.type) { |
3140 | case NL80211_IFTYPE_AP: | 3099 | case NL80211_IFTYPE_AP: |
@@ -3170,7 +3129,7 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
3170 | kfree(sdata->u.ap.next_beacon); | 3129 | kfree(sdata->u.ap.next_beacon); |
3171 | return err; | 3130 | return err; |
3172 | } | 3131 | } |
3173 | changed |= err; | 3132 | *changed |= err; |
3174 | 3133 | ||
3175 | break; | 3134 | break; |
3176 | case NL80211_IFTYPE_ADHOC: | 3135 | case NL80211_IFTYPE_ADHOC: |
@@ -3204,15 +3163,15 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
3204 | err = ieee80211_ibss_csa_beacon(sdata, params); | 3163 | err = ieee80211_ibss_csa_beacon(sdata, params); |
3205 | if (err < 0) | 3164 | if (err < 0) |
3206 | return err; | 3165 | return err; |
3207 | changed |= err; | 3166 | *changed |= err; |
3208 | } | 3167 | } |
3209 | 3168 | ||
3210 | ieee80211_send_action_csa(sdata, params); | 3169 | ieee80211_send_action_csa(sdata, params); |
3211 | 3170 | ||
3212 | break; | 3171 | break; |
3213 | #ifdef CONFIG_MAC80211_MESH | 3172 | #ifdef CONFIG_MAC80211_MESH |
3214 | case NL80211_IFTYPE_MESH_POINT: | 3173 | case NL80211_IFTYPE_MESH_POINT: { |
3215 | ifmsh = &sdata->u.mesh; | 3174 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
3216 | 3175 | ||
3217 | if (params->chandef.width != sdata->vif.bss_conf.chandef.width) | 3176 | if (params->chandef.width != sdata->vif.bss_conf.chandef.width) |
3218 | return -EINVAL; | 3177 | return -EINVAL; |
@@ -3237,18 +3196,72 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
3237 | ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE; | 3196 | ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE; |
3238 | return err; | 3197 | return err; |
3239 | } | 3198 | } |
3240 | changed |= err; | 3199 | *changed |= err; |
3241 | } | 3200 | } |
3242 | 3201 | ||
3243 | if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_INIT) | 3202 | if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_INIT) |
3244 | ieee80211_send_action_csa(sdata, params); | 3203 | ieee80211_send_action_csa(sdata, params); |
3245 | 3204 | ||
3246 | break; | 3205 | break; |
3206 | } | ||
3247 | #endif | 3207 | #endif |
3248 | default: | 3208 | default: |
3249 | return -EOPNOTSUPP; | 3209 | return -EOPNOTSUPP; |
3250 | } | 3210 | } |
3251 | 3211 | ||
3212 | return 0; | ||
3213 | } | ||
3214 | |||
3215 | int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | ||
3216 | struct cfg80211_csa_settings *params) | ||
3217 | { | ||
3218 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
3219 | struct ieee80211_local *local = sdata->local; | ||
3220 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
3221 | struct ieee80211_chanctx *chanctx; | ||
3222 | int err, num_chanctx, changed = 0; | ||
3223 | |||
3224 | sdata_assert_lock(sdata); | ||
3225 | |||
3226 | if (!list_empty(&local->roc_list) || local->scanning) | ||
3227 | return -EBUSY; | ||
3228 | |||
3229 | if (sdata->wdev.cac_started) | ||
3230 | return -EBUSY; | ||
3231 | |||
3232 | if (cfg80211_chandef_identical(¶ms->chandef, | ||
3233 | &sdata->vif.bss_conf.chandef)) | ||
3234 | return -EINVAL; | ||
3235 | |||
3236 | rcu_read_lock(); | ||
3237 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
3238 | if (!chanctx_conf) { | ||
3239 | rcu_read_unlock(); | ||
3240 | return -EBUSY; | ||
3241 | } | ||
3242 | |||
3243 | /* don't handle for multi-VIF cases */ | ||
3244 | chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf); | ||
3245 | if (chanctx->refcount > 1) { | ||
3246 | rcu_read_unlock(); | ||
3247 | return -EBUSY; | ||
3248 | } | ||
3249 | num_chanctx = 0; | ||
3250 | list_for_each_entry_rcu(chanctx, &local->chanctx_list, list) | ||
3251 | num_chanctx++; | ||
3252 | rcu_read_unlock(); | ||
3253 | |||
3254 | if (num_chanctx > 1) | ||
3255 | return -EBUSY; | ||
3256 | |||
3257 | /* don't allow another channel switch if one is already active. */ | ||
3258 | if (sdata->vif.csa_active) | ||
3259 | return -EBUSY; | ||
3260 | |||
3261 | err = ieee80211_set_csa_beacon(sdata, params, &changed); | ||
3262 | if (err) | ||
3263 | return err; | ||
3264 | |||
3252 | sdata->csa_radar_required = params->radar_required; | 3265 | sdata->csa_radar_required = params->radar_required; |
3253 | 3266 | ||
3254 | if (params->block_tx) | 3267 | if (params->block_tx) |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index e458ca0dffec..06d28787945b 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -991,7 +991,6 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
991 | struct ieee802_11_elems *elems) | 991 | struct ieee802_11_elems *elems) |
992 | { | 992 | { |
993 | struct ieee80211_local *local = sdata->local; | 993 | struct ieee80211_local *local = sdata->local; |
994 | int freq; | ||
995 | struct cfg80211_bss *cbss; | 994 | struct cfg80211_bss *cbss; |
996 | struct ieee80211_bss *bss; | 995 | struct ieee80211_bss *bss; |
997 | struct sta_info *sta; | 996 | struct sta_info *sta; |
@@ -1003,15 +1002,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
1003 | struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band]; | 1002 | struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band]; |
1004 | bool rates_updated = false; | 1003 | bool rates_updated = false; |
1005 | 1004 | ||
1006 | if (elems->ds_params) | 1005 | channel = ieee80211_get_channel(local->hw.wiphy, rx_status->freq); |
1007 | freq = ieee80211_channel_to_frequency(elems->ds_params[0], | 1006 | if (!channel) |
1008 | band); | ||
1009 | else | ||
1010 | freq = rx_status->freq; | ||
1011 | |||
1012 | channel = ieee80211_get_channel(local->hw.wiphy, freq); | ||
1013 | |||
1014 | if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) | ||
1015 | return; | 1007 | return; |
1016 | 1008 | ||
1017 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && | 1009 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 0d1a0f801b94..222c28b75315 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -1391,6 +1391,7 @@ void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata); | |||
1391 | void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata); | 1391 | void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata); |
1392 | void ieee80211_mgd_conn_tx_status(struct ieee80211_sub_if_data *sdata, | 1392 | void ieee80211_mgd_conn_tx_status(struct ieee80211_sub_if_data *sdata, |
1393 | __le16 fc, bool acked); | 1393 | __le16 fc, bool acked); |
1394 | void ieee80211_mgd_quiesce(struct ieee80211_sub_if_data *sdata); | ||
1394 | void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata); | 1395 | void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata); |
1395 | 1396 | ||
1396 | /* IBSS code */ | 1397 | /* IBSS code */ |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 94f0af29b742..dee50aefd6e8 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -2783,28 +2783,20 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
2783 | struct ieee802_11_elems *elems) | 2783 | struct ieee802_11_elems *elems) |
2784 | { | 2784 | { |
2785 | struct ieee80211_local *local = sdata->local; | 2785 | struct ieee80211_local *local = sdata->local; |
2786 | int freq; | ||
2787 | struct ieee80211_bss *bss; | 2786 | struct ieee80211_bss *bss; |
2788 | struct ieee80211_channel *channel; | 2787 | struct ieee80211_channel *channel; |
2789 | 2788 | ||
2790 | sdata_assert_lock(sdata); | 2789 | sdata_assert_lock(sdata); |
2791 | 2790 | ||
2792 | if (elems->ds_params) | 2791 | channel = ieee80211_get_channel(local->hw.wiphy, rx_status->freq); |
2793 | freq = ieee80211_channel_to_frequency(elems->ds_params[0], | 2792 | if (!channel) |
2794 | rx_status->band); | ||
2795 | else | ||
2796 | freq = rx_status->freq; | ||
2797 | |||
2798 | channel = ieee80211_get_channel(local->hw.wiphy, freq); | ||
2799 | |||
2800 | if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) | ||
2801 | return; | 2793 | return; |
2802 | 2794 | ||
2803 | bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems, | 2795 | bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems, |
2804 | channel); | 2796 | channel); |
2805 | if (bss) { | 2797 | if (bss) { |
2806 | ieee80211_rx_bss_put(local, bss); | ||
2807 | sdata->vif.bss_conf.beacon_rate = bss->beacon_rate; | 2798 | sdata->vif.bss_conf.beacon_rate = bss->beacon_rate; |
2799 | ieee80211_rx_bss_put(local, bss); | ||
2808 | } | 2800 | } |
2809 | } | 2801 | } |
2810 | 2802 | ||
@@ -3599,6 +3591,32 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) | |||
3599 | } | 3591 | } |
3600 | 3592 | ||
3601 | #ifdef CONFIG_PM | 3593 | #ifdef CONFIG_PM |
3594 | void ieee80211_mgd_quiesce(struct ieee80211_sub_if_data *sdata) | ||
3595 | { | ||
3596 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
3597 | u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; | ||
3598 | |||
3599 | sdata_lock(sdata); | ||
3600 | |||
3601 | if (ifmgd->auth_data) { | ||
3602 | /* | ||
3603 | * If we are trying to authenticate while suspending, cfg80211 | ||
3604 | * won't know and won't actually abort those attempts, thus we | ||
3605 | * need to do that ourselves. | ||
3606 | */ | ||
3607 | ieee80211_send_deauth_disassoc(sdata, | ||
3608 | ifmgd->auth_data->bss->bssid, | ||
3609 | IEEE80211_STYPE_DEAUTH, | ||
3610 | WLAN_REASON_DEAUTH_LEAVING, | ||
3611 | false, frame_buf); | ||
3612 | ieee80211_destroy_auth_data(sdata, false); | ||
3613 | cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, | ||
3614 | IEEE80211_DEAUTH_FRAME_LEN); | ||
3615 | } | ||
3616 | |||
3617 | sdata_unlock(sdata); | ||
3618 | } | ||
3619 | |||
3602 | void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) | 3620 | void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) |
3603 | { | 3621 | { |
3604 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 3622 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
@@ -4417,37 +4435,41 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
4417 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 4435 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
4418 | u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; | 4436 | u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; |
4419 | bool tx = !req->local_state_change; | 4437 | bool tx = !req->local_state_change; |
4420 | bool report_frame = false; | ||
4421 | 4438 | ||
4422 | sdata_info(sdata, | 4439 | if (ifmgd->auth_data && |
4423 | "deauthenticating from %pM by local choice (Reason: %u=%s)\n", | 4440 | ether_addr_equal(ifmgd->auth_data->bss->bssid, req->bssid)) { |
4424 | req->bssid, req->reason_code, ieee80211_get_reason_code_string(req->reason_code)); | 4441 | sdata_info(sdata, |
4442 | "aborting authentication with %pM by local choice (Reason: %u=%s)\n", | ||
4443 | req->bssid, req->reason_code, | ||
4444 | ieee80211_get_reason_code_string(req->reason_code)); | ||
4425 | 4445 | ||
4426 | if (ifmgd->auth_data) { | ||
4427 | drv_mgd_prepare_tx(sdata->local, sdata); | 4446 | drv_mgd_prepare_tx(sdata->local, sdata); |
4428 | ieee80211_send_deauth_disassoc(sdata, req->bssid, | 4447 | ieee80211_send_deauth_disassoc(sdata, req->bssid, |
4429 | IEEE80211_STYPE_DEAUTH, | 4448 | IEEE80211_STYPE_DEAUTH, |
4430 | req->reason_code, tx, | 4449 | req->reason_code, tx, |
4431 | frame_buf); | 4450 | frame_buf); |
4432 | ieee80211_destroy_auth_data(sdata, false); | 4451 | ieee80211_destroy_auth_data(sdata, false); |
4452 | cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, | ||
4453 | IEEE80211_DEAUTH_FRAME_LEN); | ||
4433 | 4454 | ||
4434 | report_frame = true; | 4455 | return 0; |
4435 | goto out; | ||
4436 | } | 4456 | } |
4437 | 4457 | ||
4438 | if (ifmgd->associated && | 4458 | if (ifmgd->associated && |
4439 | ether_addr_equal(ifmgd->associated->bssid, req->bssid)) { | 4459 | ether_addr_equal(ifmgd->associated->bssid, req->bssid)) { |
4460 | sdata_info(sdata, | ||
4461 | "deauthenticating from %pM by local choice (Reason: %u=%s)\n", | ||
4462 | req->bssid, req->reason_code, | ||
4463 | ieee80211_get_reason_code_string(req->reason_code)); | ||
4464 | |||
4440 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, | 4465 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, |
4441 | req->reason_code, tx, frame_buf); | 4466 | req->reason_code, tx, frame_buf); |
4442 | report_frame = true; | ||
4443 | } | ||
4444 | |||
4445 | out: | ||
4446 | if (report_frame) | ||
4447 | cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, | 4467 | cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, |
4448 | IEEE80211_DEAUTH_FRAME_LEN); | 4468 | IEEE80211_DEAUTH_FRAME_LEN); |
4469 | return 0; | ||
4470 | } | ||
4449 | 4471 | ||
4450 | return 0; | 4472 | return -ENOTCONN; |
4451 | } | 4473 | } |
4452 | 4474 | ||
4453 | int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | 4475 | int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, |
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index af64fb8e8add..d478b880a0af 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
@@ -100,10 +100,18 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
100 | 100 | ||
101 | /* remove all interfaces that were created in the driver */ | 101 | /* remove all interfaces that were created in the driver */ |
102 | list_for_each_entry(sdata, &local->interfaces, list) { | 102 | list_for_each_entry(sdata, &local->interfaces, list) { |
103 | if (!ieee80211_sdata_running(sdata) || | 103 | if (!ieee80211_sdata_running(sdata)) |
104 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN || | ||
105 | sdata->vif.type == NL80211_IFTYPE_MONITOR) | ||
106 | continue; | 104 | continue; |
105 | switch (sdata->vif.type) { | ||
106 | case NL80211_IFTYPE_AP_VLAN: | ||
107 | case NL80211_IFTYPE_MONITOR: | ||
108 | continue; | ||
109 | case NL80211_IFTYPE_STATION: | ||
110 | ieee80211_mgd_quiesce(sdata); | ||
111 | break; | ||
112 | default: | ||
113 | break; | ||
114 | } | ||
107 | 115 | ||
108 | drv_remove_interface(local, sdata); | 116 | drv_remove_interface(local, sdata); |
109 | } | 117 | } |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 5b617660b0ba..216c45b949e5 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -333,6 +333,8 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
333 | /* in VHT, STBC is binary */ | 333 | /* in VHT, STBC is binary */ |
334 | if (status->flag & RX_FLAG_STBC_MASK) | 334 | if (status->flag & RX_FLAG_STBC_MASK) |
335 | *pos |= IEEE80211_RADIOTAP_VHT_FLAG_STBC; | 335 | *pos |= IEEE80211_RADIOTAP_VHT_FLAG_STBC; |
336 | if (status->vht_flag & RX_VHT_FLAG_BF) | ||
337 | *pos |= IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED; | ||
336 | pos++; | 338 | pos++; |
337 | /* bandwidth */ | 339 | /* bandwidth */ |
338 | if (status->vht_flag & RX_VHT_FLAG_80MHZ) | 340 | if (status->vht_flag & RX_VHT_FLAG_80MHZ) |
@@ -1245,6 +1247,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
1245 | if (ieee80211_is_data(hdr->frame_control)) { | 1247 | if (ieee80211_is_data(hdr->frame_control)) { |
1246 | sta->last_rx_rate_idx = status->rate_idx; | 1248 | sta->last_rx_rate_idx = status->rate_idx; |
1247 | sta->last_rx_rate_flag = status->flag; | 1249 | sta->last_rx_rate_flag = status->flag; |
1250 | sta->last_rx_rate_vht_flag = status->vht_flag; | ||
1248 | sta->last_rx_rate_vht_nss = status->vht_nss; | 1251 | sta->last_rx_rate_vht_nss = status->vht_nss; |
1249 | } | 1252 | } |
1250 | } | 1253 | } |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 836f500dfbf3..3ce7f2c8539a 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -1055,9 +1055,11 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata) | |||
1055 | /* We don't want to restart sched scan anymore. */ | 1055 | /* We don't want to restart sched scan anymore. */ |
1056 | local->sched_scan_req = NULL; | 1056 | local->sched_scan_req = NULL; |
1057 | 1057 | ||
1058 | if (rcu_access_pointer(local->sched_scan_sdata)) | 1058 | if (rcu_access_pointer(local->sched_scan_sdata)) { |
1059 | ret = drv_sched_scan_stop(local, sdata); | 1059 | ret = drv_sched_scan_stop(local, sdata); |
1060 | 1060 | if (!ret) | |
1061 | rcu_assign_pointer(local->sched_scan_sdata, NULL); | ||
1062 | } | ||
1061 | out: | 1063 | out: |
1062 | mutex_unlock(&local->mtx); | 1064 | mutex_unlock(&local->mtx); |
1063 | 1065 | ||
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index cd9f80498c48..19d36d4117e0 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -2900,7 +2900,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | |||
2900 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); | 2900 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); |
2901 | } | 2901 | } |
2902 | 2902 | ||
2903 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 2903 | if (sdata->vif.type == NL80211_IFTYPE_AP) |
2904 | sdata = IEEE80211_DEV_TO_SUB_IF(skb->dev); | 2904 | sdata = IEEE80211_DEV_TO_SUB_IF(skb->dev); |
2905 | if (!ieee80211_tx_prepare(sdata, &tx, skb)) | 2905 | if (!ieee80211_tx_prepare(sdata, &tx, skb)) |
2906 | break; | 2906 | break; |
diff --git a/net/nfc/core.c b/net/nfc/core.c index ca1e65f4b133..819b87702b70 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c | |||
@@ -280,9 +280,6 @@ static struct nfc_target *nfc_find_target(struct nfc_dev *dev, u32 target_idx) | |||
280 | { | 280 | { |
281 | int i; | 281 | int i; |
282 | 282 | ||
283 | if (dev->n_targets == 0) | ||
284 | return NULL; | ||
285 | |||
286 | for (i = 0; i < dev->n_targets; i++) { | 283 | for (i = 0; i < dev->n_targets; i++) { |
287 | if (dev->targets[i].idx == target_idx) | 284 | if (dev->targets[i].idx == target_idx) |
288 | return &dev->targets[i]; | 285 | return &dev->targets[i]; |
@@ -546,9 +543,9 @@ error: | |||
546 | 543 | ||
547 | struct nfc_se *nfc_find_se(struct nfc_dev *dev, u32 se_idx) | 544 | struct nfc_se *nfc_find_se(struct nfc_dev *dev, u32 se_idx) |
548 | { | 545 | { |
549 | struct nfc_se *se, *n; | 546 | struct nfc_se *se; |
550 | 547 | ||
551 | list_for_each_entry_safe(se, n, &dev->secure_elements, list) | 548 | list_for_each_entry(se, &dev->secure_elements, list) |
552 | if (se->idx == se_idx) | 549 | if (se->idx == se_idx) |
553 | return se; | 550 | return se; |
554 | 551 | ||
@@ -655,9 +652,6 @@ int nfc_set_remote_general_bytes(struct nfc_dev *dev, u8 *gb, u8 gb_len) | |||
655 | { | 652 | { |
656 | pr_debug("dev_name=%s gb_len=%d\n", dev_name(&dev->dev), gb_len); | 653 | pr_debug("dev_name=%s gb_len=%d\n", dev_name(&dev->dev), gb_len); |
657 | 654 | ||
658 | if (gb_len > NFC_MAX_GT_LEN) | ||
659 | return -EINVAL; | ||
660 | |||
661 | return nfc_llcp_set_remote_gb(dev, gb, gb_len); | 655 | return nfc_llcp_set_remote_gb(dev, gb, gb_len); |
662 | } | 656 | } |
663 | EXPORT_SYMBOL(nfc_set_remote_general_bytes); | 657 | EXPORT_SYMBOL(nfc_set_remote_general_bytes); |
diff --git a/net/nfc/digital.h b/net/nfc/digital.h index 08b29b55ea63..3759add68b1b 100644 --- a/net/nfc/digital.h +++ b/net/nfc/digital.h | |||
@@ -72,6 +72,12 @@ void digital_poll_next_tech(struct nfc_digital_dev *ddev); | |||
72 | 72 | ||
73 | int digital_in_send_sens_req(struct nfc_digital_dev *ddev, u8 rf_tech); | 73 | int digital_in_send_sens_req(struct nfc_digital_dev *ddev, u8 rf_tech); |
74 | int digital_in_send_sensf_req(struct nfc_digital_dev *ddev, u8 rf_tech); | 74 | int digital_in_send_sensf_req(struct nfc_digital_dev *ddev, u8 rf_tech); |
75 | int digital_in_send_iso15693_inv_req(struct nfc_digital_dev *ddev, u8 rf_tech); | ||
76 | |||
77 | int digital_in_iso_dep_pull_sod(struct nfc_digital_dev *ddev, | ||
78 | struct sk_buff *skb); | ||
79 | int digital_in_iso_dep_push_sod(struct nfc_digital_dev *ddev, | ||
80 | struct sk_buff *skb); | ||
75 | 81 | ||
76 | int digital_target_found(struct nfc_digital_dev *ddev, | 82 | int digital_target_found(struct nfc_digital_dev *ddev, |
77 | struct nfc_target *target, u8 protocol); | 83 | struct nfc_target *target, u8 protocol); |
diff --git a/net/nfc/digital_core.c b/net/nfc/digital_core.c index c129d1571ca6..e01e15dbf1ab 100644 --- a/net/nfc/digital_core.c +++ b/net/nfc/digital_core.c | |||
@@ -25,6 +25,8 @@ | |||
25 | #define DIGITAL_PROTO_NFCF_RF_TECH \ | 25 | #define DIGITAL_PROTO_NFCF_RF_TECH \ |
26 | (NFC_PROTO_FELICA_MASK | NFC_PROTO_NFC_DEP_MASK) | 26 | (NFC_PROTO_FELICA_MASK | NFC_PROTO_NFC_DEP_MASK) |
27 | 27 | ||
28 | #define DIGITAL_PROTO_ISO15693_RF_TECH NFC_PROTO_ISO15693_MASK | ||
29 | |||
28 | struct digital_cmd { | 30 | struct digital_cmd { |
29 | struct list_head queue; | 31 | struct list_head queue; |
30 | 32 | ||
@@ -331,6 +333,18 @@ int digital_target_found(struct nfc_digital_dev *ddev, | |||
331 | } | 333 | } |
332 | break; | 334 | break; |
333 | 335 | ||
336 | case NFC_PROTO_ISO15693: | ||
337 | framing = NFC_DIGITAL_FRAMING_ISO15693_T5T; | ||
338 | check_crc = digital_skb_check_crc_b; | ||
339 | add_crc = digital_skb_add_crc_b; | ||
340 | break; | ||
341 | |||
342 | case NFC_PROTO_ISO14443: | ||
343 | framing = NFC_DIGITAL_FRAMING_NFCA_T4T; | ||
344 | check_crc = digital_skb_check_crc_a; | ||
345 | add_crc = digital_skb_add_crc_a; | ||
346 | break; | ||
347 | |||
334 | default: | 348 | default: |
335 | pr_err("Invalid protocol %d\n", protocol); | 349 | pr_err("Invalid protocol %d\n", protocol); |
336 | return -EINVAL; | 350 | return -EINVAL; |
@@ -461,7 +475,7 @@ static int digital_start_poll(struct nfc_dev *nfc_dev, __u32 im_protocols, | |||
461 | digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_106A, | 475 | digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_106A, |
462 | digital_in_send_sens_req); | 476 | digital_in_send_sens_req); |
463 | 477 | ||
464 | if (im_protocols & DIGITAL_PROTO_NFCF_RF_TECH) { | 478 | if (matching_im_protocols & DIGITAL_PROTO_NFCF_RF_TECH) { |
465 | digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_212F, | 479 | digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_212F, |
466 | digital_in_send_sensf_req); | 480 | digital_in_send_sensf_req); |
467 | 481 | ||
@@ -469,7 +483,11 @@ static int digital_start_poll(struct nfc_dev *nfc_dev, __u32 im_protocols, | |||
469 | digital_in_send_sensf_req); | 483 | digital_in_send_sensf_req); |
470 | } | 484 | } |
471 | 485 | ||
472 | if (tm_protocols & NFC_PROTO_NFC_DEP_MASK) { | 486 | if (matching_im_protocols & DIGITAL_PROTO_ISO15693_RF_TECH) |
487 | digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_ISO15693, | ||
488 | digital_in_send_iso15693_inv_req); | ||
489 | |||
490 | if (matching_tm_protocols & NFC_PROTO_NFC_DEP_MASK) { | ||
473 | if (ddev->ops->tg_listen_mdaa) { | 491 | if (ddev->ops->tg_listen_mdaa) { |
474 | digital_add_poll_tech(ddev, 0, | 492 | digital_add_poll_tech(ddev, 0, |
475 | digital_tg_listen_mdaa); | 493 | digital_tg_listen_mdaa); |
@@ -607,20 +625,30 @@ static void digital_in_send_complete(struct nfc_digital_dev *ddev, void *arg, | |||
607 | 625 | ||
608 | if (IS_ERR(resp)) { | 626 | if (IS_ERR(resp)) { |
609 | rc = PTR_ERR(resp); | 627 | rc = PTR_ERR(resp); |
628 | resp = NULL; | ||
610 | goto done; | 629 | goto done; |
611 | } | 630 | } |
612 | 631 | ||
613 | if (ddev->curr_protocol == NFC_PROTO_MIFARE) | 632 | if (ddev->curr_protocol == NFC_PROTO_MIFARE) { |
614 | rc = digital_in_recv_mifare_res(resp); | 633 | rc = digital_in_recv_mifare_res(resp); |
615 | else | 634 | /* crc check is done in digital_in_recv_mifare_res() */ |
616 | rc = ddev->skb_check_crc(resp); | 635 | goto done; |
636 | } | ||
617 | 637 | ||
638 | if (ddev->curr_protocol == NFC_PROTO_ISO14443) { | ||
639 | rc = digital_in_iso_dep_pull_sod(ddev, resp); | ||
640 | if (rc) | ||
641 | goto done; | ||
642 | } | ||
643 | |||
644 | rc = ddev->skb_check_crc(resp); | ||
645 | |||
646 | done: | ||
618 | if (rc) { | 647 | if (rc) { |
619 | kfree_skb(resp); | 648 | kfree_skb(resp); |
620 | resp = NULL; | 649 | resp = NULL; |
621 | } | 650 | } |
622 | 651 | ||
623 | done: | ||
624 | data_exch->cb(data_exch->cb_context, resp, rc); | 652 | data_exch->cb(data_exch->cb_context, resp, rc); |
625 | 653 | ||
626 | kfree(data_exch); | 654 | kfree(data_exch); |
@@ -632,6 +660,7 @@ static int digital_in_send(struct nfc_dev *nfc_dev, struct nfc_target *target, | |||
632 | { | 660 | { |
633 | struct nfc_digital_dev *ddev = nfc_get_drvdata(nfc_dev); | 661 | struct nfc_digital_dev *ddev = nfc_get_drvdata(nfc_dev); |
634 | struct digital_data_exch *data_exch; | 662 | struct digital_data_exch *data_exch; |
663 | int rc; | ||
635 | 664 | ||
636 | data_exch = kzalloc(sizeof(struct digital_data_exch), GFP_KERNEL); | 665 | data_exch = kzalloc(sizeof(struct digital_data_exch), GFP_KERNEL); |
637 | if (!data_exch) { | 666 | if (!data_exch) { |
@@ -642,13 +671,27 @@ static int digital_in_send(struct nfc_dev *nfc_dev, struct nfc_target *target, | |||
642 | data_exch->cb = cb; | 671 | data_exch->cb = cb; |
643 | data_exch->cb_context = cb_context; | 672 | data_exch->cb_context = cb_context; |
644 | 673 | ||
645 | if (ddev->curr_protocol == NFC_PROTO_NFC_DEP) | 674 | if (ddev->curr_protocol == NFC_PROTO_NFC_DEP) { |
646 | return digital_in_send_dep_req(ddev, target, skb, data_exch); | 675 | rc = digital_in_send_dep_req(ddev, target, skb, data_exch); |
676 | goto exit; | ||
677 | } | ||
678 | |||
679 | if (ddev->curr_protocol == NFC_PROTO_ISO14443) { | ||
680 | rc = digital_in_iso_dep_push_sod(ddev, skb); | ||
681 | if (rc) | ||
682 | goto exit; | ||
683 | } | ||
647 | 684 | ||
648 | ddev->skb_add_crc(skb); | 685 | ddev->skb_add_crc(skb); |
649 | 686 | ||
650 | return digital_in_send_cmd(ddev, skb, 500, digital_in_send_complete, | 687 | rc = digital_in_send_cmd(ddev, skb, 500, digital_in_send_complete, |
651 | data_exch); | 688 | data_exch); |
689 | |||
690 | exit: | ||
691 | if (rc) | ||
692 | kfree(data_exch); | ||
693 | |||
694 | return rc; | ||
652 | } | 695 | } |
653 | 696 | ||
654 | static struct nfc_ops digital_nfc_ops = { | 697 | static struct nfc_ops digital_nfc_ops = { |
@@ -700,6 +743,10 @@ struct nfc_digital_dev *nfc_digital_allocate_device(struct nfc_digital_ops *ops, | |||
700 | ddev->protocols |= NFC_PROTO_FELICA_MASK; | 743 | ddev->protocols |= NFC_PROTO_FELICA_MASK; |
701 | if (supported_protocols & NFC_PROTO_NFC_DEP_MASK) | 744 | if (supported_protocols & NFC_PROTO_NFC_DEP_MASK) |
702 | ddev->protocols |= NFC_PROTO_NFC_DEP_MASK; | 745 | ddev->protocols |= NFC_PROTO_NFC_DEP_MASK; |
746 | if (supported_protocols & NFC_PROTO_ISO15693_MASK) | ||
747 | ddev->protocols |= NFC_PROTO_ISO15693_MASK; | ||
748 | if (supported_protocols & NFC_PROTO_ISO14443_MASK) | ||
749 | ddev->protocols |= NFC_PROTO_ISO14443_MASK; | ||
703 | 750 | ||
704 | ddev->tx_headroom = tx_headroom + DIGITAL_MAX_HEADER_LEN; | 751 | ddev->tx_headroom = tx_headroom + DIGITAL_MAX_HEADER_LEN; |
705 | ddev->tx_tailroom = tx_tailroom + DIGITAL_CRC_LEN; | 752 | ddev->tx_tailroom = tx_tailroom + DIGITAL_CRC_LEN; |
diff --git a/net/nfc/digital_technology.c b/net/nfc/digital_technology.c index 251c8c753ebe..278c3fed27e0 100644 --- a/net/nfc/digital_technology.c +++ b/net/nfc/digital_technology.c | |||
@@ -30,6 +30,7 @@ | |||
30 | 30 | ||
31 | #define DIGITAL_SEL_RES_NFCID1_COMPLETE(sel_res) (!((sel_res) & 0x04)) | 31 | #define DIGITAL_SEL_RES_NFCID1_COMPLETE(sel_res) (!((sel_res) & 0x04)) |
32 | #define DIGITAL_SEL_RES_IS_T2T(sel_res) (!((sel_res) & 0x60)) | 32 | #define DIGITAL_SEL_RES_IS_T2T(sel_res) (!((sel_res) & 0x60)) |
33 | #define DIGITAL_SEL_RES_IS_T4T(sel_res) ((sel_res) & 0x20) | ||
33 | #define DIGITAL_SEL_RES_IS_NFC_DEP(sel_res) ((sel_res) & 0x40) | 34 | #define DIGITAL_SEL_RES_IS_NFC_DEP(sel_res) ((sel_res) & 0x40) |
34 | 35 | ||
35 | #define DIGITAL_SENS_RES_IS_T1T(sens_res) (((sens_res) & 0x0C00) == 0x0C00) | 36 | #define DIGITAL_SENS_RES_IS_T1T(sens_res) (((sens_res) & 0x0C00) == 0x0C00) |
@@ -51,6 +52,34 @@ | |||
51 | #define DIGITAL_SENSF_REQ_RC_SC 1 | 52 | #define DIGITAL_SENSF_REQ_RC_SC 1 |
52 | #define DIGITAL_SENSF_REQ_RC_AP 2 | 53 | #define DIGITAL_SENSF_REQ_RC_AP 2 |
53 | 54 | ||
55 | #define DIGITAL_CMD_ISO15693_INVENTORY_REQ 0x01 | ||
56 | |||
57 | #define DIGITAL_ISO15693_REQ_FLAG_DATA_RATE BIT(1) | ||
58 | #define DIGITAL_ISO15693_REQ_FLAG_INVENTORY BIT(2) | ||
59 | #define DIGITAL_ISO15693_REQ_FLAG_NB_SLOTS BIT(5) | ||
60 | #define DIGITAL_ISO15693_RES_FLAG_ERROR BIT(0) | ||
61 | #define DIGITAL_ISO15693_RES_IS_VALID(flags) \ | ||
62 | (!((flags) & DIGITAL_ISO15693_RES_FLAG_ERROR)) | ||
63 | |||
64 | #define DIGITAL_ISO_DEP_I_PCB 0x02 | ||
65 | #define DIGITAL_ISO_DEP_PNI(pni) ((pni) & 0x01) | ||
66 | |||
67 | #define DIGITAL_ISO_DEP_PCB_TYPE(pcb) ((pcb) & 0xC0) | ||
68 | |||
69 | #define DIGITAL_ISO_DEP_I_BLOCK 0x00 | ||
70 | |||
71 | #define DIGITAL_ISO_DEP_BLOCK_HAS_DID(pcb) ((pcb) & 0x08) | ||
72 | |||
73 | static const u8 digital_ats_fsc[] = { | ||
74 | 16, 24, 32, 40, 48, 64, 96, 128, | ||
75 | }; | ||
76 | |||
77 | #define DIGITAL_ATS_FSCI(t0) ((t0) & 0x0F) | ||
78 | #define DIGITAL_ATS_MAX_FSC 256 | ||
79 | |||
80 | #define DIGITAL_RATS_BYTE1 0xE0 | ||
81 | #define DIGITAL_RATS_PARAM 0x80 | ||
82 | |||
54 | struct digital_sdd_res { | 83 | struct digital_sdd_res { |
55 | u8 nfcid1[4]; | 84 | u8 nfcid1[4]; |
56 | u8 bcc; | 85 | u8 bcc; |
@@ -82,9 +111,127 @@ struct digital_sensf_res { | |||
82 | u8 rd[2]; | 111 | u8 rd[2]; |
83 | } __packed; | 112 | } __packed; |
84 | 113 | ||
114 | struct digital_iso15693_inv_req { | ||
115 | u8 flags; | ||
116 | u8 cmd; | ||
117 | u8 mask_len; | ||
118 | u64 mask; | ||
119 | } __packed; | ||
120 | |||
121 | struct digital_iso15693_inv_res { | ||
122 | u8 flags; | ||
123 | u8 dsfid; | ||
124 | u64 uid; | ||
125 | } __packed; | ||
126 | |||
85 | static int digital_in_send_sdd_req(struct nfc_digital_dev *ddev, | 127 | static int digital_in_send_sdd_req(struct nfc_digital_dev *ddev, |
86 | struct nfc_target *target); | 128 | struct nfc_target *target); |
87 | 129 | ||
130 | int digital_in_iso_dep_pull_sod(struct nfc_digital_dev *ddev, | ||
131 | struct sk_buff *skb) | ||
132 | { | ||
133 | u8 pcb; | ||
134 | u8 block_type; | ||
135 | |||
136 | if (skb->len < 1) | ||
137 | return -EIO; | ||
138 | |||
139 | pcb = *skb->data; | ||
140 | block_type = DIGITAL_ISO_DEP_PCB_TYPE(pcb); | ||
141 | |||
142 | /* No support fo R-block nor S-block */ | ||
143 | if (block_type != DIGITAL_ISO_DEP_I_BLOCK) { | ||
144 | pr_err("ISO_DEP R-block and S-block not supported\n"); | ||
145 | return -EIO; | ||
146 | } | ||
147 | |||
148 | if (DIGITAL_ISO_DEP_BLOCK_HAS_DID(pcb)) { | ||
149 | pr_err("DID field in ISO_DEP PCB not supported\n"); | ||
150 | return -EIO; | ||
151 | } | ||
152 | |||
153 | skb_pull(skb, 1); | ||
154 | |||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | int digital_in_iso_dep_push_sod(struct nfc_digital_dev *ddev, | ||
159 | struct sk_buff *skb) | ||
160 | { | ||
161 | /* | ||
162 | * Chaining not supported so skb->len + 1 PCB byte + 2 CRC bytes must | ||
163 | * not be greater than remote FSC | ||
164 | */ | ||
165 | if (skb->len + 3 > ddev->target_fsc) | ||
166 | return -EIO; | ||
167 | |||
168 | skb_push(skb, 1); | ||
169 | |||
170 | *skb->data = DIGITAL_ISO_DEP_I_PCB | ddev->curr_nfc_dep_pni; | ||
171 | |||
172 | ddev->curr_nfc_dep_pni = | ||
173 | DIGITAL_ISO_DEP_PNI(ddev->curr_nfc_dep_pni + 1); | ||
174 | |||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | static void digital_in_recv_ats(struct nfc_digital_dev *ddev, void *arg, | ||
179 | struct sk_buff *resp) | ||
180 | { | ||
181 | struct nfc_target *target = arg; | ||
182 | u8 fsdi; | ||
183 | int rc; | ||
184 | |||
185 | if (IS_ERR(resp)) { | ||
186 | rc = PTR_ERR(resp); | ||
187 | resp = NULL; | ||
188 | goto exit; | ||
189 | } | ||
190 | |||
191 | if (resp->len < 2) { | ||
192 | rc = -EIO; | ||
193 | goto exit; | ||
194 | } | ||
195 | |||
196 | fsdi = DIGITAL_ATS_FSCI(resp->data[1]); | ||
197 | if (fsdi >= 8) | ||
198 | ddev->target_fsc = DIGITAL_ATS_MAX_FSC; | ||
199 | else | ||
200 | ddev->target_fsc = digital_ats_fsc[fsdi]; | ||
201 | |||
202 | ddev->curr_nfc_dep_pni = 0; | ||
203 | |||
204 | rc = digital_target_found(ddev, target, NFC_PROTO_ISO14443); | ||
205 | |||
206 | exit: | ||
207 | dev_kfree_skb(resp); | ||
208 | kfree(target); | ||
209 | |||
210 | if (rc) | ||
211 | digital_poll_next_tech(ddev); | ||
212 | } | ||
213 | |||
214 | static int digital_in_send_rats(struct nfc_digital_dev *ddev, | ||
215 | struct nfc_target *target) | ||
216 | { | ||
217 | int rc; | ||
218 | struct sk_buff *skb; | ||
219 | |||
220 | skb = digital_skb_alloc(ddev, 2); | ||
221 | if (!skb) | ||
222 | return -ENOMEM; | ||
223 | |||
224 | *skb_put(skb, 1) = DIGITAL_RATS_BYTE1; | ||
225 | *skb_put(skb, 1) = DIGITAL_RATS_PARAM; | ||
226 | |||
227 | rc = digital_in_send_cmd(ddev, skb, 30, digital_in_recv_ats, | ||
228 | target); | ||
229 | if (rc) | ||
230 | kfree_skb(skb); | ||
231 | |||
232 | return rc; | ||
233 | } | ||
234 | |||
88 | static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg, | 235 | static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg, |
89 | struct sk_buff *resp) | 236 | struct sk_buff *resp) |
90 | { | 237 | { |
@@ -122,8 +269,19 @@ static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg, | |||
122 | goto exit_free_skb; | 269 | goto exit_free_skb; |
123 | } | 270 | } |
124 | 271 | ||
272 | target->sel_res = sel_res; | ||
273 | |||
125 | if (DIGITAL_SEL_RES_IS_T2T(sel_res)) { | 274 | if (DIGITAL_SEL_RES_IS_T2T(sel_res)) { |
126 | nfc_proto = NFC_PROTO_MIFARE; | 275 | nfc_proto = NFC_PROTO_MIFARE; |
276 | } else if (DIGITAL_SEL_RES_IS_T4T(sel_res)) { | ||
277 | rc = digital_in_send_rats(ddev, target); | ||
278 | if (rc) | ||
279 | goto exit; | ||
280 | /* | ||
281 | * Skip target_found and don't free it for now. This will be | ||
282 | * done when receiving the ATS | ||
283 | */ | ||
284 | goto exit_free_skb; | ||
127 | } else if (DIGITAL_SEL_RES_IS_NFC_DEP(sel_res)) { | 285 | } else if (DIGITAL_SEL_RES_IS_NFC_DEP(sel_res)) { |
128 | nfc_proto = NFC_PROTO_NFC_DEP; | 286 | nfc_proto = NFC_PROTO_NFC_DEP; |
129 | } else { | 287 | } else { |
@@ -131,8 +289,6 @@ static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg, | |||
131 | goto exit; | 289 | goto exit; |
132 | } | 290 | } |
133 | 291 | ||
134 | target->sel_res = sel_res; | ||
135 | |||
136 | rc = digital_target_found(ddev, target, nfc_proto); | 292 | rc = digital_target_found(ddev, target, nfc_proto); |
137 | 293 | ||
138 | exit: | 294 | exit: |
@@ -473,6 +629,93 @@ int digital_in_send_sensf_req(struct nfc_digital_dev *ddev, u8 rf_tech) | |||
473 | return rc; | 629 | return rc; |
474 | } | 630 | } |
475 | 631 | ||
632 | static void digital_in_recv_iso15693_inv_res(struct nfc_digital_dev *ddev, | ||
633 | void *arg, struct sk_buff *resp) | ||
634 | { | ||
635 | struct digital_iso15693_inv_res *res; | ||
636 | struct nfc_target *target = NULL; | ||
637 | int rc; | ||
638 | |||
639 | if (IS_ERR(resp)) { | ||
640 | rc = PTR_ERR(resp); | ||
641 | resp = NULL; | ||
642 | goto out_free_skb; | ||
643 | } | ||
644 | |||
645 | if (resp->len != sizeof(*res)) { | ||
646 | rc = -EIO; | ||
647 | goto out_free_skb; | ||
648 | } | ||
649 | |||
650 | res = (struct digital_iso15693_inv_res *)resp->data; | ||
651 | |||
652 | if (!DIGITAL_ISO15693_RES_IS_VALID(res->flags)) { | ||
653 | PROTOCOL_ERR("ISO15693 - 10.3.1"); | ||
654 | rc = -EINVAL; | ||
655 | goto out_free_skb; | ||
656 | } | ||
657 | |||
658 | target = kzalloc(sizeof(*target), GFP_KERNEL); | ||
659 | if (!target) { | ||
660 | rc = -ENOMEM; | ||
661 | goto out_free_skb; | ||
662 | } | ||
663 | |||
664 | target->is_iso15693 = 1; | ||
665 | target->iso15693_dsfid = res->dsfid; | ||
666 | memcpy(target->iso15693_uid, &res->uid, sizeof(target->iso15693_uid)); | ||
667 | |||
668 | rc = digital_target_found(ddev, target, NFC_PROTO_ISO15693); | ||
669 | |||
670 | kfree(target); | ||
671 | |||
672 | out_free_skb: | ||
673 | dev_kfree_skb(resp); | ||
674 | |||
675 | if (rc) | ||
676 | digital_poll_next_tech(ddev); | ||
677 | } | ||
678 | |||
679 | int digital_in_send_iso15693_inv_req(struct nfc_digital_dev *ddev, u8 rf_tech) | ||
680 | { | ||
681 | struct digital_iso15693_inv_req *req; | ||
682 | struct sk_buff *skb; | ||
683 | int rc; | ||
684 | |||
685 | rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, | ||
686 | NFC_DIGITAL_RF_TECH_ISO15693); | ||
687 | if (rc) | ||
688 | return rc; | ||
689 | |||
690 | rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, | ||
691 | NFC_DIGITAL_FRAMING_ISO15693_INVENTORY); | ||
692 | if (rc) | ||
693 | return rc; | ||
694 | |||
695 | skb = digital_skb_alloc(ddev, sizeof(*req)); | ||
696 | if (!skb) | ||
697 | return -ENOMEM; | ||
698 | |||
699 | skb_put(skb, sizeof(*req) - sizeof(req->mask)); /* No mask */ | ||
700 | req = (struct digital_iso15693_inv_req *)skb->data; | ||
701 | |||
702 | /* Single sub-carrier, high data rate, no AFI, single slot | ||
703 | * Inventory command | ||
704 | */ | ||
705 | req->flags = DIGITAL_ISO15693_REQ_FLAG_DATA_RATE | | ||
706 | DIGITAL_ISO15693_REQ_FLAG_INVENTORY | | ||
707 | DIGITAL_ISO15693_REQ_FLAG_NB_SLOTS; | ||
708 | req->cmd = DIGITAL_CMD_ISO15693_INVENTORY_REQ; | ||
709 | req->mask_len = 0; | ||
710 | |||
711 | rc = digital_in_send_cmd(ddev, skb, 30, | ||
712 | digital_in_recv_iso15693_inv_res, NULL); | ||
713 | if (rc) | ||
714 | kfree_skb(skb); | ||
715 | |||
716 | return rc; | ||
717 | } | ||
718 | |||
476 | static int digital_tg_send_sel_res(struct nfc_digital_dev *ddev) | 719 | static int digital_tg_send_sel_res(struct nfc_digital_dev *ddev) |
477 | { | 720 | { |
478 | struct sk_buff *skb; | 721 | struct sk_buff *skb; |
diff --git a/net/nfc/hci/llc.c b/net/nfc/hci/llc.c index a07d2b818487..1b90c0531852 100644 --- a/net/nfc/hci/llc.c +++ b/net/nfc/hci/llc.c | |||
@@ -20,14 +20,12 @@ | |||
20 | 20 | ||
21 | #include "llc.h" | 21 | #include "llc.h" |
22 | 22 | ||
23 | static struct list_head llc_engines; | 23 | static LIST_HEAD(llc_engines); |
24 | 24 | ||
25 | int nfc_llc_init(void) | 25 | int nfc_llc_init(void) |
26 | { | 26 | { |
27 | int r; | 27 | int r; |
28 | 28 | ||
29 | INIT_LIST_HEAD(&llc_engines); | ||
30 | |||
31 | r = nfc_llc_nop_register(); | 29 | r = nfc_llc_nop_register(); |
32 | if (r) | 30 | if (r) |
33 | goto exit; | 31 | goto exit; |
diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c index 6184bd1fba3a..b486f12ae243 100644 --- a/net/nfc/llcp_core.c +++ b/net/nfc/llcp_core.c | |||
@@ -27,7 +27,7 @@ | |||
27 | 27 | ||
28 | static u8 llcp_magic[3] = {0x46, 0x66, 0x6d}; | 28 | static u8 llcp_magic[3] = {0x46, 0x66, 0x6d}; |
29 | 29 | ||
30 | static struct list_head llcp_devices; | 30 | static LIST_HEAD(llcp_devices); |
31 | 31 | ||
32 | static void nfc_llcp_rx_skb(struct nfc_llcp_local *local, struct sk_buff *skb); | 32 | static void nfc_llcp_rx_skb(struct nfc_llcp_local *local, struct sk_buff *skb); |
33 | 33 | ||
@@ -293,9 +293,9 @@ static void nfc_llcp_sdreq_timer(unsigned long data) | |||
293 | 293 | ||
294 | struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev) | 294 | struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev) |
295 | { | 295 | { |
296 | struct nfc_llcp_local *local, *n; | 296 | struct nfc_llcp_local *local; |
297 | 297 | ||
298 | list_for_each_entry_safe(local, n, &llcp_devices, list) | 298 | list_for_each_entry(local, &llcp_devices, list) |
299 | if (local->dev == dev) | 299 | if (local->dev == dev) |
300 | return local; | 300 | return local; |
301 | 301 | ||
@@ -609,14 +609,16 @@ u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len) | |||
609 | 609 | ||
610 | int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len) | 610 | int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len) |
611 | { | 611 | { |
612 | struct nfc_llcp_local *local = nfc_llcp_find_local(dev); | 612 | struct nfc_llcp_local *local; |
613 | |||
614 | if (gb_len < 3 || gb_len > NFC_MAX_GT_LEN) | ||
615 | return -EINVAL; | ||
613 | 616 | ||
617 | local = nfc_llcp_find_local(dev); | ||
614 | if (local == NULL) { | 618 | if (local == NULL) { |
615 | pr_err("No LLCP device\n"); | 619 | pr_err("No LLCP device\n"); |
616 | return -ENODEV; | 620 | return -ENODEV; |
617 | } | 621 | } |
618 | if (gb_len < 3) | ||
619 | return -EINVAL; | ||
620 | 622 | ||
621 | memset(local->remote_gb, 0, NFC_MAX_GT_LEN); | 623 | memset(local->remote_gb, 0, NFC_MAX_GT_LEN); |
622 | memcpy(local->remote_gb, gb, gb_len); | 624 | memcpy(local->remote_gb, gb, gb_len); |
@@ -1622,8 +1624,6 @@ void nfc_llcp_unregister_device(struct nfc_dev *dev) | |||
1622 | 1624 | ||
1623 | int __init nfc_llcp_init(void) | 1625 | int __init nfc_llcp_init(void) |
1624 | { | 1626 | { |
1625 | INIT_LIST_HEAD(&llcp_devices); | ||
1626 | |||
1627 | return nfc_llcp_sock_init(); | 1627 | return nfc_llcp_sock_init(); |
1628 | } | 1628 | } |
1629 | 1629 | ||
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c index 56db888b1cd5..6c34ac978501 100644 --- a/net/nfc/nci/core.c +++ b/net/nfc/nci/core.c | |||
@@ -74,7 +74,7 @@ static int __nci_request(struct nci_dev *ndev, | |||
74 | 74 | ||
75 | ndev->req_status = NCI_REQ_PEND; | 75 | ndev->req_status = NCI_REQ_PEND; |
76 | 76 | ||
77 | init_completion(&ndev->req_completion); | 77 | reinit_completion(&ndev->req_completion); |
78 | req(ndev, opt); | 78 | req(ndev, opt); |
79 | completion_rc = | 79 | completion_rc = |
80 | wait_for_completion_interruptible_timeout(&ndev->req_completion, | 80 | wait_for_completion_interruptible_timeout(&ndev->req_completion, |
@@ -709,6 +709,7 @@ struct nci_dev *nci_allocate_device(struct nci_ops *ops, | |||
709 | ndev->ops = ops; | 709 | ndev->ops = ops; |
710 | ndev->tx_headroom = tx_headroom; | 710 | ndev->tx_headroom = tx_headroom; |
711 | ndev->tx_tailroom = tx_tailroom; | 711 | ndev->tx_tailroom = tx_tailroom; |
712 | init_completion(&ndev->req_completion); | ||
712 | 713 | ||
713 | ndev->nfc_dev = nfc_allocate_device(&nci_nfc_ops, | 714 | ndev->nfc_dev = nfc_allocate_device(&nci_nfc_ops, |
714 | supported_protocols, | 715 | supported_protocols, |
diff --git a/net/nfc/nci/spi.c b/net/nfc/nci/spi.c index f1d426f10cce..ec250e77763a 100644 --- a/net/nfc/nci/spi.c +++ b/net/nfc/nci/spi.c | |||
@@ -105,7 +105,7 @@ int nci_spi_send(struct nci_spi *nspi, | |||
105 | if (ret != 0 || nspi->acknowledge_mode == NCI_SPI_CRC_DISABLED) | 105 | if (ret != 0 || nspi->acknowledge_mode == NCI_SPI_CRC_DISABLED) |
106 | goto done; | 106 | goto done; |
107 | 107 | ||
108 | init_completion(&nspi->req_completion); | 108 | reinit_completion(&nspi->req_completion); |
109 | completion_rc = wait_for_completion_interruptible_timeout( | 109 | completion_rc = wait_for_completion_interruptible_timeout( |
110 | &nspi->req_completion, | 110 | &nspi->req_completion, |
111 | NCI_SPI_SEND_TIMEOUT); | 111 | NCI_SPI_SEND_TIMEOUT); |
@@ -145,6 +145,7 @@ struct nci_spi *nci_spi_allocate_spi(struct spi_device *spi, | |||
145 | 145 | ||
146 | nspi->spi = spi; | 146 | nspi->spi = spi; |
147 | nspi->ndev = ndev; | 147 | nspi->ndev = ndev; |
148 | init_completion(&nspi->req_completion); | ||
148 | 149 | ||
149 | return nspi; | 150 | return nspi; |
150 | } | 151 | } |
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index ebbf6fb88b35..43cb1c17e267 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c | |||
@@ -94,6 +94,14 @@ static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target, | |||
94 | target->sensf_res)) | 94 | target->sensf_res)) |
95 | goto nla_put_failure; | 95 | goto nla_put_failure; |
96 | 96 | ||
97 | if (target->is_iso15693) { | ||
98 | if (nla_put_u8(msg, NFC_ATTR_TARGET_ISO15693_DSFID, | ||
99 | target->iso15693_dsfid) || | ||
100 | nla_put(msg, NFC_ATTR_TARGET_ISO15693_UID, | ||
101 | sizeof(target->iso15693_uid), target->iso15693_uid)) | ||
102 | goto nla_put_failure; | ||
103 | } | ||
104 | |||
97 | return genlmsg_end(msg, hdr); | 105 | return genlmsg_end(msg, hdr); |
98 | 106 | ||
99 | nla_put_failure: | 107 | nla_put_failure: |
diff --git a/net/wireless/ap.c b/net/wireless/ap.c index 68602be07cc1..3e02ade508d8 100644 --- a/net/wireless/ap.c +++ b/net/wireless/ap.c | |||
@@ -7,7 +7,7 @@ | |||
7 | 7 | ||
8 | 8 | ||
9 | static int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev, | 9 | static int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev, |
10 | struct net_device *dev) | 10 | struct net_device *dev, bool notify) |
11 | { | 11 | { |
12 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 12 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
13 | int err; | 13 | int err; |
@@ -30,20 +30,21 @@ static int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev, | |||
30 | memset(&wdev->chandef, 0, sizeof(wdev->chandef)); | 30 | memset(&wdev->chandef, 0, sizeof(wdev->chandef)); |
31 | wdev->ssid_len = 0; | 31 | wdev->ssid_len = 0; |
32 | rdev_set_qos_map(rdev, dev, NULL); | 32 | rdev_set_qos_map(rdev, dev, NULL); |
33 | nl80211_send_ap_stopped(wdev); | 33 | if (notify) |
34 | nl80211_send_ap_stopped(wdev); | ||
34 | } | 35 | } |
35 | 36 | ||
36 | return err; | 37 | return err; |
37 | } | 38 | } |
38 | 39 | ||
39 | int cfg80211_stop_ap(struct cfg80211_registered_device *rdev, | 40 | int cfg80211_stop_ap(struct cfg80211_registered_device *rdev, |
40 | struct net_device *dev) | 41 | struct net_device *dev, bool notify) |
41 | { | 42 | { |
42 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 43 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
43 | int err; | 44 | int err; |
44 | 45 | ||
45 | wdev_lock(wdev); | 46 | wdev_lock(wdev); |
46 | err = __cfg80211_stop_ap(rdev, dev); | 47 | err = __cfg80211_stop_ap(rdev, dev, notify); |
47 | wdev_unlock(wdev); | 48 | wdev_unlock(wdev); |
48 | 49 | ||
49 | return err; | 50 | return err; |
diff --git a/net/wireless/chan.c b/net/wireless/chan.c index cd10c1985074..9c9501a35fb5 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c | |||
@@ -490,6 +490,62 @@ static bool cfg80211_chandef_dfs_available(struct wiphy *wiphy, | |||
490 | return r; | 490 | return r; |
491 | } | 491 | } |
492 | 492 | ||
493 | static unsigned int cfg80211_get_chans_dfs_cac_time(struct wiphy *wiphy, | ||
494 | u32 center_freq, | ||
495 | u32 bandwidth) | ||
496 | { | ||
497 | struct ieee80211_channel *c; | ||
498 | u32 start_freq, end_freq, freq; | ||
499 | unsigned int dfs_cac_ms = 0; | ||
500 | |||
501 | start_freq = cfg80211_get_start_freq(center_freq, bandwidth); | ||
502 | end_freq = cfg80211_get_end_freq(center_freq, bandwidth); | ||
503 | |||
504 | for (freq = start_freq; freq <= end_freq; freq += 20) { | ||
505 | c = ieee80211_get_channel(wiphy, freq); | ||
506 | if (!c) | ||
507 | return 0; | ||
508 | |||
509 | if (c->flags & IEEE80211_CHAN_DISABLED) | ||
510 | return 0; | ||
511 | |||
512 | if (!(c->flags & IEEE80211_CHAN_RADAR)) | ||
513 | continue; | ||
514 | |||
515 | if (c->dfs_cac_ms > dfs_cac_ms) | ||
516 | dfs_cac_ms = c->dfs_cac_ms; | ||
517 | } | ||
518 | |||
519 | return dfs_cac_ms; | ||
520 | } | ||
521 | |||
522 | unsigned int | ||
523 | cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy, | ||
524 | const struct cfg80211_chan_def *chandef) | ||
525 | { | ||
526 | int width; | ||
527 | unsigned int t1 = 0, t2 = 0; | ||
528 | |||
529 | if (WARN_ON(!cfg80211_chandef_valid(chandef))) | ||
530 | return 0; | ||
531 | |||
532 | width = cfg80211_chandef_get_width(chandef); | ||
533 | if (width < 0) | ||
534 | return 0; | ||
535 | |||
536 | t1 = cfg80211_get_chans_dfs_cac_time(wiphy, | ||
537 | chandef->center_freq1, | ||
538 | width); | ||
539 | |||
540 | if (!chandef->center_freq2) | ||
541 | return t1; | ||
542 | |||
543 | t2 = cfg80211_get_chans_dfs_cac_time(wiphy, | ||
544 | chandef->center_freq2, | ||
545 | width); | ||
546 | |||
547 | return max(t1, t2); | ||
548 | } | ||
493 | 549 | ||
494 | static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, | 550 | static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, |
495 | u32 center_freq, u32 bandwidth, | 551 | u32 center_freq, u32 bandwidth, |
diff --git a/net/wireless/core.c b/net/wireless/core.c index eb7f40821c09..086cddd03ba6 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -783,7 +783,7 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev, | |||
783 | break; | 783 | break; |
784 | case NL80211_IFTYPE_AP: | 784 | case NL80211_IFTYPE_AP: |
785 | case NL80211_IFTYPE_P2P_GO: | 785 | case NL80211_IFTYPE_P2P_GO: |
786 | cfg80211_stop_ap(rdev, dev); | 786 | cfg80211_stop_ap(rdev, dev, true); |
787 | break; | 787 | break; |
788 | default: | 788 | default: |
789 | break; | 789 | break; |
diff --git a/net/wireless/core.h b/net/wireless/core.h index 40683004d523..5b1fdcadd469 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -166,7 +166,6 @@ static inline void wdev_unlock(struct wireless_dev *wdev) | |||
166 | mutex_unlock(&wdev->mtx); | 166 | mutex_unlock(&wdev->mtx); |
167 | } | 167 | } |
168 | 168 | ||
169 | #define ASSERT_RDEV_LOCK(rdev) ASSERT_RTNL() | ||
170 | #define ASSERT_WDEV_LOCK(wdev) lockdep_assert_held(&(wdev)->mtx) | 169 | #define ASSERT_WDEV_LOCK(wdev) lockdep_assert_held(&(wdev)->mtx) |
171 | 170 | ||
172 | static inline bool cfg80211_has_monitors_only(struct cfg80211_registered_device *rdev) | 171 | static inline bool cfg80211_has_monitors_only(struct cfg80211_registered_device *rdev) |
@@ -246,10 +245,6 @@ void cfg80211_bss_age(struct cfg80211_registered_device *dev, | |||
246 | unsigned long age_secs); | 245 | unsigned long age_secs); |
247 | 246 | ||
248 | /* IBSS */ | 247 | /* IBSS */ |
249 | int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, | ||
250 | struct net_device *dev, | ||
251 | struct cfg80211_ibss_params *params, | ||
252 | struct cfg80211_cached_keys *connkeys); | ||
253 | int cfg80211_join_ibss(struct cfg80211_registered_device *rdev, | 248 | int cfg80211_join_ibss(struct cfg80211_registered_device *rdev, |
254 | struct net_device *dev, | 249 | struct net_device *dev, |
255 | struct cfg80211_ibss_params *params, | 250 | struct cfg80211_ibss_params *params, |
@@ -283,7 +278,7 @@ int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev, | |||
283 | 278 | ||
284 | /* AP */ | 279 | /* AP */ |
285 | int cfg80211_stop_ap(struct cfg80211_registered_device *rdev, | 280 | int cfg80211_stop_ap(struct cfg80211_registered_device *rdev, |
286 | struct net_device *dev); | 281 | struct net_device *dev, bool notify); |
287 | 282 | ||
288 | /* MLME */ | 283 | /* MLME */ |
289 | int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | 284 | int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, |
@@ -402,6 +397,9 @@ void cfg80211_set_dfs_state(struct wiphy *wiphy, | |||
402 | 397 | ||
403 | void cfg80211_dfs_channels_update_work(struct work_struct *work); | 398 | void cfg80211_dfs_channels_update_work(struct work_struct *work); |
404 | 399 | ||
400 | unsigned int | ||
401 | cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy, | ||
402 | const struct cfg80211_chan_def *chandef); | ||
405 | 403 | ||
406 | static inline int | 404 | static inline int |
407 | cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, | 405 | cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, |
diff --git a/net/wireless/genregdb.awk b/net/wireless/genregdb.awk index fdfd3f063a9b..b35da8dc85de 100644 --- a/net/wireless/genregdb.awk +++ b/net/wireless/genregdb.awk | |||
@@ -66,6 +66,7 @@ function parse_reg_rule() | |||
66 | units = $8 | 66 | units = $8 |
67 | sub(/\)/, "", units) | 67 | sub(/\)/, "", units) |
68 | sub(/,/, "", units) | 68 | sub(/,/, "", units) |
69 | dfs_cac = $9 | ||
69 | if (units == "mW") { | 70 | if (units == "mW") { |
70 | if (power == 100) { | 71 | if (power == 100) { |
71 | power = 20 | 72 | power = 20 |
@@ -78,7 +79,12 @@ function parse_reg_rule() | |||
78 | } else { | 79 | } else { |
79 | print "Unknown power value in database!" | 80 | print "Unknown power value in database!" |
80 | } | 81 | } |
82 | } else { | ||
83 | dfs_cac = $8 | ||
81 | } | 84 | } |
85 | sub(/,/, "", dfs_cac) | ||
86 | sub(/\(/, "", dfs_cac) | ||
87 | sub(/\)/, "", dfs_cac) | ||
82 | flagstr = "" | 88 | flagstr = "" |
83 | for (i=8; i<=NF; i++) | 89 | for (i=8; i<=NF; i++) |
84 | flagstr = flagstr $i | 90 | flagstr = flagstr $i |
@@ -111,7 +117,7 @@ function parse_reg_rule() | |||
111 | 117 | ||
112 | } | 118 | } |
113 | flags = flags "0" | 119 | flags = flags "0" |
114 | printf "\t\tREG_RULE(%d, %d, %d, %d, %d, %s),\n", start, end, bw, gain, power, flags | 120 | printf "\t\tREG_RULE_EXT(%d, %d, %d, %d, %d, %d, %s),\n", start, end, bw, gain, power, dfs_cac, flags |
115 | rules++ | 121 | rules++ |
116 | } | 122 | } |
117 | 123 | ||
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index 349db9ddc0d1..a6b5bdad039c 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c | |||
@@ -82,10 +82,10 @@ void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, | |||
82 | } | 82 | } |
83 | EXPORT_SYMBOL(cfg80211_ibss_joined); | 83 | EXPORT_SYMBOL(cfg80211_ibss_joined); |
84 | 84 | ||
85 | int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, | 85 | static int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, |
86 | struct net_device *dev, | 86 | struct net_device *dev, |
87 | struct cfg80211_ibss_params *params, | 87 | struct cfg80211_ibss_params *params, |
88 | struct cfg80211_cached_keys *connkeys) | 88 | struct cfg80211_cached_keys *connkeys) |
89 | { | 89 | { |
90 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 90 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
91 | struct ieee80211_channel *check_chan; | 91 | struct ieee80211_channel *check_chan; |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index d47c9d127b1e..c52ff59a3e96 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -778,7 +778,7 @@ void cfg80211_cac_event(struct net_device *netdev, | |||
778 | switch (event) { | 778 | switch (event) { |
779 | case NL80211_RADAR_CAC_FINISHED: | 779 | case NL80211_RADAR_CAC_FINISHED: |
780 | timeout = wdev->cac_start_time + | 780 | timeout = wdev->cac_start_time + |
781 | msecs_to_jiffies(IEEE80211_DFS_MIN_CAC_TIME_MS); | 781 | msecs_to_jiffies(wdev->cac_time_ms); |
782 | WARN_ON(!time_after_eq(jiffies, timeout)); | 782 | WARN_ON(!time_after_eq(jiffies, timeout)); |
783 | cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_AVAILABLE); | 783 | cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_AVAILABLE); |
784 | break; | 784 | break; |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 2c38b28a85b9..052c1bf8ffac 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -593,6 +593,10 @@ static int nl80211_msg_put_channel(struct sk_buff *msg, | |||
593 | if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_TIME, | 593 | if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_TIME, |
594 | time)) | 594 | time)) |
595 | goto nla_put_failure; | 595 | goto nla_put_failure; |
596 | if (nla_put_u32(msg, | ||
597 | NL80211_FREQUENCY_ATTR_DFS_CAC_TIME, | ||
598 | chan->dfs_cac_ms)) | ||
599 | goto nla_put_failure; | ||
596 | } | 600 | } |
597 | } | 601 | } |
598 | 602 | ||
@@ -3328,7 +3332,7 @@ static int nl80211_stop_ap(struct sk_buff *skb, struct genl_info *info) | |||
3328 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 3332 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
3329 | struct net_device *dev = info->user_ptr[1]; | 3333 | struct net_device *dev = info->user_ptr[1]; |
3330 | 3334 | ||
3331 | return cfg80211_stop_ap(rdev, dev); | 3335 | return cfg80211_stop_ap(rdev, dev, false); |
3332 | } | 3336 | } |
3333 | 3337 | ||
3334 | static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = { | 3338 | static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = { |
@@ -4614,6 +4618,7 @@ static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = | |||
4614 | [NL80211_ATTR_FREQ_RANGE_MAX_BW] = { .type = NLA_U32 }, | 4618 | [NL80211_ATTR_FREQ_RANGE_MAX_BW] = { .type = NLA_U32 }, |
4615 | [NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN] = { .type = NLA_U32 }, | 4619 | [NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN] = { .type = NLA_U32 }, |
4616 | [NL80211_ATTR_POWER_RULE_MAX_EIRP] = { .type = NLA_U32 }, | 4620 | [NL80211_ATTR_POWER_RULE_MAX_EIRP] = { .type = NLA_U32 }, |
4621 | [NL80211_ATTR_DFS_CAC_TIME] = { .type = NLA_U32 }, | ||
4617 | }; | 4622 | }; |
4618 | 4623 | ||
4619 | static int parse_reg_rule(struct nlattr *tb[], | 4624 | static int parse_reg_rule(struct nlattr *tb[], |
@@ -4649,6 +4654,10 @@ static int parse_reg_rule(struct nlattr *tb[], | |||
4649 | power_rule->max_antenna_gain = | 4654 | power_rule->max_antenna_gain = |
4650 | nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]); | 4655 | nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]); |
4651 | 4656 | ||
4657 | if (tb[NL80211_ATTR_DFS_CAC_TIME]) | ||
4658 | reg_rule->dfs_cac_ms = | ||
4659 | nla_get_u32(tb[NL80211_ATTR_DFS_CAC_TIME]); | ||
4660 | |||
4652 | return 0; | 4661 | return 0; |
4653 | } | 4662 | } |
4654 | 4663 | ||
@@ -5136,7 +5145,9 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info) | |||
5136 | nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN, | 5145 | nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN, |
5137 | power_rule->max_antenna_gain) || | 5146 | power_rule->max_antenna_gain) || |
5138 | nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP, | 5147 | nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP, |
5139 | power_rule->max_eirp)) | 5148 | power_rule->max_eirp) || |
5149 | nla_put_u32(msg, NL80211_ATTR_DFS_CAC_TIME, | ||
5150 | reg_rule->dfs_cac_ms)) | ||
5140 | goto nla_put_failure_rcu; | 5151 | goto nla_put_failure_rcu; |
5141 | 5152 | ||
5142 | nla_nest_end(msg, nl_reg_rule); | 5153 | nla_nest_end(msg, nl_reg_rule); |
@@ -5768,6 +5779,7 @@ static int nl80211_start_radar_detection(struct sk_buff *skb, | |||
5768 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 5779 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
5769 | struct cfg80211_chan_def chandef; | 5780 | struct cfg80211_chan_def chandef; |
5770 | enum nl80211_dfs_regions dfs_region; | 5781 | enum nl80211_dfs_regions dfs_region; |
5782 | unsigned int cac_time_ms; | ||
5771 | int err; | 5783 | int err; |
5772 | 5784 | ||
5773 | dfs_region = reg_get_dfs_region(wdev->wiphy); | 5785 | dfs_region = reg_get_dfs_region(wdev->wiphy); |
@@ -5803,11 +5815,17 @@ static int nl80211_start_radar_detection(struct sk_buff *skb, | |||
5803 | if (err) | 5815 | if (err) |
5804 | return err; | 5816 | return err; |
5805 | 5817 | ||
5806 | err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef); | 5818 | cac_time_ms = cfg80211_chandef_dfs_cac_time(&rdev->wiphy, &chandef); |
5819 | if (WARN_ON(!cac_time_ms)) | ||
5820 | cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS; | ||
5821 | |||
5822 | err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef, | ||
5823 | cac_time_ms); | ||
5807 | if (!err) { | 5824 | if (!err) { |
5808 | wdev->chandef = chandef; | 5825 | wdev->chandef = chandef; |
5809 | wdev->cac_started = true; | 5826 | wdev->cac_started = true; |
5810 | wdev->cac_start_time = jiffies; | 5827 | wdev->cac_start_time = jiffies; |
5828 | wdev->cac_time_ms = cac_time_ms; | ||
5811 | } | 5829 | } |
5812 | return err; | 5830 | return err; |
5813 | } | 5831 | } |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 90b82e08ae69..f59aaac586f8 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -91,10 +91,6 @@ static struct regulatory_request __rcu *last_request = | |||
91 | /* To trigger userspace events */ | 91 | /* To trigger userspace events */ |
92 | static struct platform_device *reg_pdev; | 92 | static struct platform_device *reg_pdev; |
93 | 93 | ||
94 | static const struct device_type reg_device_type = { | ||
95 | .uevent = reg_device_uevent, | ||
96 | }; | ||
97 | |||
98 | /* | 94 | /* |
99 | * Central wireless core regulatory domains, we only need two, | 95 | * Central wireless core regulatory domains, we only need two, |
100 | * the current one and a world regulatory domain in case we have no | 96 | * the current one and a world regulatory domain in case we have no |
@@ -244,19 +240,21 @@ static char user_alpha2[2]; | |||
244 | module_param(ieee80211_regdom, charp, 0444); | 240 | module_param(ieee80211_regdom, charp, 0444); |
245 | MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); | 241 | MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); |
246 | 242 | ||
247 | static void reg_kfree_last_request(void) | 243 | static void reg_free_request(struct regulatory_request *lr) |
248 | { | 244 | { |
249 | struct regulatory_request *lr; | ||
250 | |||
251 | lr = get_last_request(); | ||
252 | |||
253 | if (lr != &core_request_world && lr) | 245 | if (lr != &core_request_world && lr) |
254 | kfree_rcu(lr, rcu_head); | 246 | kfree_rcu(lr, rcu_head); |
255 | } | 247 | } |
256 | 248 | ||
257 | static void reg_update_last_request(struct regulatory_request *request) | 249 | static void reg_update_last_request(struct regulatory_request *request) |
258 | { | 250 | { |
259 | reg_kfree_last_request(); | 251 | struct regulatory_request *lr; |
252 | |||
253 | lr = get_last_request(); | ||
254 | if (lr == request) | ||
255 | return; | ||
256 | |||
257 | reg_free_request(lr); | ||
260 | rcu_assign_pointer(last_request, request); | 258 | rcu_assign_pointer(last_request, request); |
261 | } | 259 | } |
262 | 260 | ||
@@ -487,11 +485,16 @@ static inline void reg_regdb_query(const char *alpha2) {} | |||
487 | 485 | ||
488 | /* | 486 | /* |
489 | * This lets us keep regulatory code which is updated on a regulatory | 487 | * This lets us keep regulatory code which is updated on a regulatory |
490 | * basis in userspace. Country information is filled in by | 488 | * basis in userspace. |
491 | * reg_device_uevent | ||
492 | */ | 489 | */ |
493 | static int call_crda(const char *alpha2) | 490 | static int call_crda(const char *alpha2) |
494 | { | 491 | { |
492 | char country[12]; | ||
493 | char *env[] = { country, NULL }; | ||
494 | |||
495 | snprintf(country, sizeof(country), "COUNTRY=%c%c", | ||
496 | alpha2[0], alpha2[1]); | ||
497 | |||
495 | if (!is_world_regdom((char *) alpha2)) | 498 | if (!is_world_regdom((char *) alpha2)) |
496 | pr_info("Calling CRDA for country: %c%c\n", | 499 | pr_info("Calling CRDA for country: %c%c\n", |
497 | alpha2[0], alpha2[1]); | 500 | alpha2[0], alpha2[1]); |
@@ -501,7 +504,7 @@ static int call_crda(const char *alpha2) | |||
501 | /* query internal regulatory database (if it exists) */ | 504 | /* query internal regulatory database (if it exists) */ |
502 | reg_regdb_query(alpha2); | 505 | reg_regdb_query(alpha2); |
503 | 506 | ||
504 | return kobject_uevent(®_pdev->dev.kobj, KOBJ_CHANGE); | 507 | return kobject_uevent_env(®_pdev->dev.kobj, KOBJ_CHANGE, env); |
505 | } | 508 | } |
506 | 509 | ||
507 | static enum reg_request_treatment | 510 | static enum reg_request_treatment |
@@ -755,6 +758,9 @@ static int reg_rules_intersect(const struct ieee80211_regdomain *rd1, | |||
755 | power_rule->max_antenna_gain = min(power_rule1->max_antenna_gain, | 758 | power_rule->max_antenna_gain = min(power_rule1->max_antenna_gain, |
756 | power_rule2->max_antenna_gain); | 759 | power_rule2->max_antenna_gain); |
757 | 760 | ||
761 | intersected_rule->dfs_cac_ms = max(rule1->dfs_cac_ms, | ||
762 | rule2->dfs_cac_ms); | ||
763 | |||
758 | if (!is_valid_reg_rule(intersected_rule)) | 764 | if (!is_valid_reg_rule(intersected_rule)) |
759 | return -EINVAL; | 765 | return -EINVAL; |
760 | 766 | ||
@@ -1077,6 +1083,14 @@ static void handle_channel(struct wiphy *wiphy, | |||
1077 | min_t(int, chan->orig_mag, | 1083 | min_t(int, chan->orig_mag, |
1078 | MBI_TO_DBI(power_rule->max_antenna_gain)); | 1084 | MBI_TO_DBI(power_rule->max_antenna_gain)); |
1079 | chan->max_reg_power = (int) MBM_TO_DBM(power_rule->max_eirp); | 1085 | chan->max_reg_power = (int) MBM_TO_DBM(power_rule->max_eirp); |
1086 | |||
1087 | if (chan->flags & IEEE80211_CHAN_RADAR) { | ||
1088 | if (reg_rule->dfs_cac_ms) | ||
1089 | chan->dfs_cac_ms = reg_rule->dfs_cac_ms; | ||
1090 | else | ||
1091 | chan->dfs_cac_ms = IEEE80211_DFS_MIN_CAC_TIME_MS; | ||
1092 | } | ||
1093 | |||
1080 | if (chan->orig_mpwr) { | 1094 | if (chan->orig_mpwr) { |
1081 | /* | 1095 | /* |
1082 | * Devices that use REGULATORY_COUNTRY_IE_FOLLOW_POWER | 1096 | * Devices that use REGULATORY_COUNTRY_IE_FOLLOW_POWER |
@@ -2255,9 +2269,9 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd) | |||
2255 | const struct ieee80211_reg_rule *reg_rule = NULL; | 2269 | const struct ieee80211_reg_rule *reg_rule = NULL; |
2256 | const struct ieee80211_freq_range *freq_range = NULL; | 2270 | const struct ieee80211_freq_range *freq_range = NULL; |
2257 | const struct ieee80211_power_rule *power_rule = NULL; | 2271 | const struct ieee80211_power_rule *power_rule = NULL; |
2258 | char bw[32]; | 2272 | char bw[32], cac_time[32]; |
2259 | 2273 | ||
2260 | pr_info(" (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)\n"); | 2274 | pr_info(" (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp), (dfs_cac_time)\n"); |
2261 | 2275 | ||
2262 | for (i = 0; i < rd->n_reg_rules; i++) { | 2276 | for (i = 0; i < rd->n_reg_rules; i++) { |
2263 | reg_rule = &rd->reg_rules[i]; | 2277 | reg_rule = &rd->reg_rules[i]; |
@@ -2272,23 +2286,32 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd) | |||
2272 | snprintf(bw, sizeof(bw), "%d KHz", | 2286 | snprintf(bw, sizeof(bw), "%d KHz", |
2273 | freq_range->max_bandwidth_khz); | 2287 | freq_range->max_bandwidth_khz); |
2274 | 2288 | ||
2289 | if (reg_rule->flags & NL80211_RRF_DFS) | ||
2290 | scnprintf(cac_time, sizeof(cac_time), "%u s", | ||
2291 | reg_rule->dfs_cac_ms/1000); | ||
2292 | else | ||
2293 | scnprintf(cac_time, sizeof(cac_time), "N/A"); | ||
2294 | |||
2295 | |||
2275 | /* | 2296 | /* |
2276 | * There may not be documentation for max antenna gain | 2297 | * There may not be documentation for max antenna gain |
2277 | * in certain regions | 2298 | * in certain regions |
2278 | */ | 2299 | */ |
2279 | if (power_rule->max_antenna_gain) | 2300 | if (power_rule->max_antenna_gain) |
2280 | pr_info(" (%d KHz - %d KHz @ %s), (%d mBi, %d mBm)\n", | 2301 | pr_info(" (%d KHz - %d KHz @ %s), (%d mBi, %d mBm), (%s)\n", |
2281 | freq_range->start_freq_khz, | 2302 | freq_range->start_freq_khz, |
2282 | freq_range->end_freq_khz, | 2303 | freq_range->end_freq_khz, |
2283 | bw, | 2304 | bw, |
2284 | power_rule->max_antenna_gain, | 2305 | power_rule->max_antenna_gain, |
2285 | power_rule->max_eirp); | 2306 | power_rule->max_eirp, |
2307 | cac_time); | ||
2286 | else | 2308 | else |
2287 | pr_info(" (%d KHz - %d KHz @ %s), (N/A, %d mBm)\n", | 2309 | pr_info(" (%d KHz - %d KHz @ %s), (N/A, %d mBm), (%s)\n", |
2288 | freq_range->start_freq_khz, | 2310 | freq_range->start_freq_khz, |
2289 | freq_range->end_freq_khz, | 2311 | freq_range->end_freq_khz, |
2290 | bw, | 2312 | bw, |
2291 | power_rule->max_eirp); | 2313 | power_rule->max_eirp, |
2314 | cac_time); | ||
2292 | } | 2315 | } |
2293 | } | 2316 | } |
2294 | 2317 | ||
@@ -2361,9 +2384,6 @@ static int reg_set_rd_user(const struct ieee80211_regdomain *rd, | |||
2361 | { | 2384 | { |
2362 | const struct ieee80211_regdomain *intersected_rd = NULL; | 2385 | const struct ieee80211_regdomain *intersected_rd = NULL; |
2363 | 2386 | ||
2364 | if (is_world_regdom(rd->alpha2)) | ||
2365 | return -EINVAL; | ||
2366 | |||
2367 | if (!regdom_changes(rd->alpha2)) | 2387 | if (!regdom_changes(rd->alpha2)) |
2368 | return -EALREADY; | 2388 | return -EALREADY; |
2369 | 2389 | ||
@@ -2552,26 +2572,6 @@ int set_regdom(const struct ieee80211_regdomain *rd) | |||
2552 | return 0; | 2572 | return 0; |
2553 | } | 2573 | } |
2554 | 2574 | ||
2555 | int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env) | ||
2556 | { | ||
2557 | struct regulatory_request *lr; | ||
2558 | u8 alpha2[2]; | ||
2559 | bool add = false; | ||
2560 | |||
2561 | rcu_read_lock(); | ||
2562 | lr = get_last_request(); | ||
2563 | if (lr && !lr->processed) { | ||
2564 | memcpy(alpha2, lr->alpha2, 2); | ||
2565 | add = true; | ||
2566 | } | ||
2567 | rcu_read_unlock(); | ||
2568 | |||
2569 | if (add) | ||
2570 | return add_uevent_var(env, "COUNTRY=%c%c", | ||
2571 | alpha2[0], alpha2[1]); | ||
2572 | return 0; | ||
2573 | } | ||
2574 | |||
2575 | void wiphy_regulatory_register(struct wiphy *wiphy) | 2575 | void wiphy_regulatory_register(struct wiphy *wiphy) |
2576 | { | 2576 | { |
2577 | struct regulatory_request *lr; | 2577 | struct regulatory_request *lr; |
@@ -2622,8 +2622,6 @@ int __init regulatory_init(void) | |||
2622 | if (IS_ERR(reg_pdev)) | 2622 | if (IS_ERR(reg_pdev)) |
2623 | return PTR_ERR(reg_pdev); | 2623 | return PTR_ERR(reg_pdev); |
2624 | 2624 | ||
2625 | reg_pdev->dev.type = ®_device_type; | ||
2626 | |||
2627 | spin_lock_init(®_requests_lock); | 2625 | spin_lock_init(®_requests_lock); |
2628 | spin_lock_init(®_pending_beacons_lock); | 2626 | spin_lock_init(®_pending_beacons_lock); |
2629 | 2627 | ||
diff --git a/net/wireless/reg.h b/net/wireless/reg.h index 18524617ab62..37c180df34b7 100644 --- a/net/wireless/reg.h +++ b/net/wireless/reg.h | |||
@@ -26,7 +26,6 @@ enum nl80211_dfs_regions reg_get_dfs_region(struct wiphy *wiphy); | |||
26 | int regulatory_hint_user(const char *alpha2, | 26 | int regulatory_hint_user(const char *alpha2, |
27 | enum nl80211_user_reg_hint_type user_reg_hint_type); | 27 | enum nl80211_user_reg_hint_type user_reg_hint_type); |
28 | 28 | ||
29 | int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env); | ||
30 | void wiphy_regulatory_register(struct wiphy *wiphy); | 29 | void wiphy_regulatory_register(struct wiphy *wiphy); |
31 | void wiphy_regulatory_deregister(struct wiphy *wiphy); | 30 | void wiphy_regulatory_deregister(struct wiphy *wiphy); |
32 | 31 | ||
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index d1ed4aebbbb7..7d09a712cb1f 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
@@ -659,9 +659,6 @@ static bool cfg80211_combine_bsses(struct cfg80211_registered_device *dev, | |||
659 | continue; | 659 | continue; |
660 | if (ssidlen && ie[1] != ssidlen) | 660 | if (ssidlen && ie[1] != ssidlen) |
661 | continue; | 661 | continue; |
662 | /* that would be odd ... */ | ||
663 | if (bss->pub.beacon_ies) | ||
664 | continue; | ||
665 | if (WARN_ON_ONCE(bss->pub.hidden_beacon_bss)) | 662 | if (WARN_ON_ONCE(bss->pub.hidden_beacon_bss)) |
666 | continue; | 663 | continue; |
667 | if (WARN_ON_ONCE(!list_empty(&bss->hidden_list))) | 664 | if (WARN_ON_ONCE(!list_empty(&bss->hidden_list))) |
@@ -680,7 +677,8 @@ static bool cfg80211_combine_bsses(struct cfg80211_registered_device *dev, | |||
680 | /* Returned bss is reference counted and must be cleaned up appropriately. */ | 677 | /* Returned bss is reference counted and must be cleaned up appropriately. */ |
681 | static struct cfg80211_internal_bss * | 678 | static struct cfg80211_internal_bss * |
682 | cfg80211_bss_update(struct cfg80211_registered_device *dev, | 679 | cfg80211_bss_update(struct cfg80211_registered_device *dev, |
683 | struct cfg80211_internal_bss *tmp) | 680 | struct cfg80211_internal_bss *tmp, |
681 | bool signal_valid) | ||
684 | { | 682 | { |
685 | struct cfg80211_internal_bss *found = NULL; | 683 | struct cfg80211_internal_bss *found = NULL; |
686 | 684 | ||
@@ -765,7 +763,12 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, | |||
765 | } | 763 | } |
766 | 764 | ||
767 | found->pub.beacon_interval = tmp->pub.beacon_interval; | 765 | found->pub.beacon_interval = tmp->pub.beacon_interval; |
768 | found->pub.signal = tmp->pub.signal; | 766 | /* |
767 | * don't update the signal if beacon was heard on | ||
768 | * adjacent channel. | ||
769 | */ | ||
770 | if (signal_valid) | ||
771 | found->pub.signal = tmp->pub.signal; | ||
769 | found->pub.capability = tmp->pub.capability; | 772 | found->pub.capability = tmp->pub.capability; |
770 | found->ts = tmp->ts; | 773 | found->ts = tmp->ts; |
771 | } else { | 774 | } else { |
@@ -869,13 +872,14 @@ cfg80211_get_bss_channel(struct wiphy *wiphy, const u8 *ie, size_t ielen, | |||
869 | /* Returned bss is reference counted and must be cleaned up appropriately. */ | 872 | /* Returned bss is reference counted and must be cleaned up appropriately. */ |
870 | struct cfg80211_bss* | 873 | struct cfg80211_bss* |
871 | cfg80211_inform_bss_width(struct wiphy *wiphy, | 874 | cfg80211_inform_bss_width(struct wiphy *wiphy, |
872 | struct ieee80211_channel *channel, | 875 | struct ieee80211_channel *rx_channel, |
873 | enum nl80211_bss_scan_width scan_width, | 876 | enum nl80211_bss_scan_width scan_width, |
874 | const u8 *bssid, u64 tsf, u16 capability, | 877 | const u8 *bssid, u64 tsf, u16 capability, |
875 | u16 beacon_interval, const u8 *ie, size_t ielen, | 878 | u16 beacon_interval, const u8 *ie, size_t ielen, |
876 | s32 signal, gfp_t gfp) | 879 | s32 signal, gfp_t gfp) |
877 | { | 880 | { |
878 | struct cfg80211_bss_ies *ies; | 881 | struct cfg80211_bss_ies *ies; |
882 | struct ieee80211_channel *channel; | ||
879 | struct cfg80211_internal_bss tmp = {}, *res; | 883 | struct cfg80211_internal_bss tmp = {}, *res; |
880 | 884 | ||
881 | if (WARN_ON(!wiphy)) | 885 | if (WARN_ON(!wiphy)) |
@@ -885,7 +889,7 @@ cfg80211_inform_bss_width(struct wiphy *wiphy, | |||
885 | (signal < 0 || signal > 100))) | 889 | (signal < 0 || signal > 100))) |
886 | return NULL; | 890 | return NULL; |
887 | 891 | ||
888 | channel = cfg80211_get_bss_channel(wiphy, ie, ielen, channel); | 892 | channel = cfg80211_get_bss_channel(wiphy, ie, ielen, rx_channel); |
889 | if (!channel) | 893 | if (!channel) |
890 | return NULL; | 894 | return NULL; |
891 | 895 | ||
@@ -913,7 +917,8 @@ cfg80211_inform_bss_width(struct wiphy *wiphy, | |||
913 | rcu_assign_pointer(tmp.pub.beacon_ies, ies); | 917 | rcu_assign_pointer(tmp.pub.beacon_ies, ies); |
914 | rcu_assign_pointer(tmp.pub.ies, ies); | 918 | rcu_assign_pointer(tmp.pub.ies, ies); |
915 | 919 | ||
916 | res = cfg80211_bss_update(wiphy_to_dev(wiphy), &tmp); | 920 | res = cfg80211_bss_update(wiphy_to_dev(wiphy), &tmp, |
921 | rx_channel == channel); | ||
917 | if (!res) | 922 | if (!res) |
918 | return NULL; | 923 | return NULL; |
919 | 924 | ||
@@ -929,20 +934,21 @@ EXPORT_SYMBOL(cfg80211_inform_bss_width); | |||
929 | /* Returned bss is reference counted and must be cleaned up appropriately. */ | 934 | /* Returned bss is reference counted and must be cleaned up appropriately. */ |
930 | struct cfg80211_bss * | 935 | struct cfg80211_bss * |
931 | cfg80211_inform_bss_width_frame(struct wiphy *wiphy, | 936 | cfg80211_inform_bss_width_frame(struct wiphy *wiphy, |
932 | struct ieee80211_channel *channel, | 937 | struct ieee80211_channel *rx_channel, |
933 | enum nl80211_bss_scan_width scan_width, | 938 | enum nl80211_bss_scan_width scan_width, |
934 | struct ieee80211_mgmt *mgmt, size_t len, | 939 | struct ieee80211_mgmt *mgmt, size_t len, |
935 | s32 signal, gfp_t gfp) | 940 | s32 signal, gfp_t gfp) |
936 | { | 941 | { |
937 | struct cfg80211_internal_bss tmp = {}, *res; | 942 | struct cfg80211_internal_bss tmp = {}, *res; |
938 | struct cfg80211_bss_ies *ies; | 943 | struct cfg80211_bss_ies *ies; |
944 | struct ieee80211_channel *channel; | ||
939 | size_t ielen = len - offsetof(struct ieee80211_mgmt, | 945 | size_t ielen = len - offsetof(struct ieee80211_mgmt, |
940 | u.probe_resp.variable); | 946 | u.probe_resp.variable); |
941 | 947 | ||
942 | BUILD_BUG_ON(offsetof(struct ieee80211_mgmt, u.probe_resp.variable) != | 948 | BUILD_BUG_ON(offsetof(struct ieee80211_mgmt, u.probe_resp.variable) != |
943 | offsetof(struct ieee80211_mgmt, u.beacon.variable)); | 949 | offsetof(struct ieee80211_mgmt, u.beacon.variable)); |
944 | 950 | ||
945 | trace_cfg80211_inform_bss_width_frame(wiphy, channel, scan_width, mgmt, | 951 | trace_cfg80211_inform_bss_width_frame(wiphy, rx_channel, scan_width, mgmt, |
946 | len, signal); | 952 | len, signal); |
947 | 953 | ||
948 | if (WARN_ON(!mgmt)) | 954 | if (WARN_ON(!mgmt)) |
@@ -959,7 +965,7 @@ cfg80211_inform_bss_width_frame(struct wiphy *wiphy, | |||
959 | return NULL; | 965 | return NULL; |
960 | 966 | ||
961 | channel = cfg80211_get_bss_channel(wiphy, mgmt->u.beacon.variable, | 967 | channel = cfg80211_get_bss_channel(wiphy, mgmt->u.beacon.variable, |
962 | ielen, channel); | 968 | ielen, rx_channel); |
963 | if (!channel) | 969 | if (!channel) |
964 | return NULL; | 970 | return NULL; |
965 | 971 | ||
@@ -983,7 +989,8 @@ cfg80211_inform_bss_width_frame(struct wiphy *wiphy, | |||
983 | tmp.pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int); | 989 | tmp.pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int); |
984 | tmp.pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info); | 990 | tmp.pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info); |
985 | 991 | ||
986 | res = cfg80211_bss_update(wiphy_to_dev(wiphy), &tmp); | 992 | res = cfg80211_bss_update(wiphy_to_dev(wiphy), &tmp, |
993 | rx_channel == channel); | ||
987 | if (!res) | 994 | if (!res) |
988 | return NULL; | 995 | return NULL; |
989 | 996 | ||
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index f04d4c32e96e..acdcb4a81817 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
@@ -64,7 +64,6 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev) | |||
64 | int n_channels, err; | 64 | int n_channels, err; |
65 | 65 | ||
66 | ASSERT_RTNL(); | 66 | ASSERT_RTNL(); |
67 | ASSERT_RDEV_LOCK(rdev); | ||
68 | ASSERT_WDEV_LOCK(wdev); | 67 | ASSERT_WDEV_LOCK(wdev); |
69 | 68 | ||
70 | if (rdev->scan_req || rdev->scan_msg) | 69 | if (rdev->scan_req || rdev->scan_msg) |
diff --git a/net/wireless/util.c b/net/wireless/util.c index 2bb685f3e8fc..e5872ff2c27c 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -854,7 +854,6 @@ void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev) | |||
854 | struct wireless_dev *wdev; | 854 | struct wireless_dev *wdev; |
855 | 855 | ||
856 | ASSERT_RTNL(); | 856 | ASSERT_RTNL(); |
857 | ASSERT_RDEV_LOCK(rdev); | ||
858 | 857 | ||
859 | list_for_each_entry(wdev, &rdev->wdev_list, list) | 858 | list_for_each_entry(wdev, &rdev->wdev_list, list) |
860 | cfg80211_process_wdev_events(wdev); | 859 | cfg80211_process_wdev_events(wdev); |
@@ -867,7 +866,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, | |||
867 | int err; | 866 | int err; |
868 | enum nl80211_iftype otype = dev->ieee80211_ptr->iftype; | 867 | enum nl80211_iftype otype = dev->ieee80211_ptr->iftype; |
869 | 868 | ||
870 | ASSERT_RDEV_LOCK(rdev); | 869 | ASSERT_RTNL(); |
871 | 870 | ||
872 | /* don't support changing VLANs, you just re-create them */ | 871 | /* don't support changing VLANs, you just re-create them */ |
873 | if (otype == NL80211_IFTYPE_AP_VLAN) | 872 | if (otype == NL80211_IFTYPE_AP_VLAN) |
@@ -902,7 +901,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, | |||
902 | 901 | ||
903 | switch (otype) { | 902 | switch (otype) { |
904 | case NL80211_IFTYPE_AP: | 903 | case NL80211_IFTYPE_AP: |
905 | cfg80211_stop_ap(rdev, dev); | 904 | cfg80211_stop_ap(rdev, dev, true); |
906 | break; | 905 | break; |
907 | case NL80211_IFTYPE_ADHOC: | 906 | case NL80211_IFTYPE_ADHOC: |
908 | cfg80211_leave_ibss(rdev, dev, false); | 907 | cfg80211_leave_ibss(rdev, dev, false); |
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c index 14c9a2583ba0..86c331a65664 100644 --- a/net/wireless/wext-sme.c +++ b/net/wireless/wext-sme.c | |||
@@ -21,7 +21,7 @@ int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev, | |||
21 | const u8 *prev_bssid = NULL; | 21 | const u8 *prev_bssid = NULL; |
22 | int err, i; | 22 | int err, i; |
23 | 23 | ||
24 | ASSERT_RDEV_LOCK(rdev); | 24 | ASSERT_RTNL(); |
25 | ASSERT_WDEV_LOCK(wdev); | 25 | ASSERT_WDEV_LOCK(wdev); |
26 | 26 | ||
27 | if (!netif_running(wdev->netdev)) | 27 | if (!netif_running(wdev->netdev)) |