diff options
186 files changed, 15085 insertions, 4189 deletions
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 0a327f4154a2..6bfc1bb318f6 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c | |||
| @@ -57,7 +57,7 @@ struct ath3k_version { | |||
| 57 | unsigned char reserved[0x07]; | 57 | unsigned char reserved[0x07]; |
| 58 | }; | 58 | }; |
| 59 | 59 | ||
| 60 | static struct usb_device_id ath3k_table[] = { | 60 | static const struct usb_device_id ath3k_table[] = { |
| 61 | /* Atheros AR3011 */ | 61 | /* Atheros AR3011 */ |
| 62 | { USB_DEVICE(0x0CF3, 0x3000) }, | 62 | { USB_DEVICE(0x0CF3, 0x3000) }, |
| 63 | 63 | ||
| @@ -112,7 +112,7 @@ MODULE_DEVICE_TABLE(usb, ath3k_table); | |||
| 112 | #define BTUSB_ATH3012 0x80 | 112 | #define BTUSB_ATH3012 0x80 |
| 113 | /* This table is to load patch and sysconfig files | 113 | /* This table is to load patch and sysconfig files |
| 114 | * for AR3012 */ | 114 | * for AR3012 */ |
| 115 | static struct usb_device_id ath3k_blist_tbl[] = { | 115 | static const struct usb_device_id ath3k_blist_tbl[] = { |
| 116 | 116 | ||
| 117 | /* Atheros AR3012 with sflash firmware*/ | 117 | /* Atheros AR3012 with sflash firmware*/ |
| 118 | { USB_DEVICE(0x0CF3, 0x0036), .driver_info = BTUSB_ATH3012 }, | 118 | { USB_DEVICE(0x0CF3, 0x0036), .driver_info = BTUSB_ATH3012 }, |
diff --git a/drivers/bluetooth/bfusb.c b/drivers/bluetooth/bfusb.c index 995aee9cba22..31386998c9a7 100644 --- a/drivers/bluetooth/bfusb.c +++ b/drivers/bluetooth/bfusb.c | |||
| @@ -42,7 +42,7 @@ | |||
| 42 | 42 | ||
| 43 | static struct usb_driver bfusb_driver; | 43 | static struct usb_driver bfusb_driver; |
| 44 | 44 | ||
| 45 | static struct usb_device_id bfusb_table[] = { | 45 | static const struct usb_device_id bfusb_table[] = { |
| 46 | /* AVM BlueFRITZ! USB */ | 46 | /* AVM BlueFRITZ! USB */ |
| 47 | { USB_DEVICE(0x057c, 0x2200) }, | 47 | { USB_DEVICE(0x057c, 0x2200) }, |
| 48 | 48 | ||
| @@ -318,7 +318,6 @@ static inline int bfusb_recv_block(struct bfusb_data *data, int hdr, unsigned ch | |||
| 318 | return -ENOMEM; | 318 | return -ENOMEM; |
| 319 | } | 319 | } |
| 320 | 320 | ||
| 321 | skb->dev = (void *) data->hdev; | ||
| 322 | bt_cb(skb)->pkt_type = pkt_type; | 321 | bt_cb(skb)->pkt_type = pkt_type; |
| 323 | 322 | ||
| 324 | data->reassembly = skb; | 323 | data->reassembly = skb; |
| @@ -333,7 +332,7 @@ static inline int bfusb_recv_block(struct bfusb_data *data, int hdr, unsigned ch | |||
| 333 | memcpy(skb_put(data->reassembly, len), buf, len); | 332 | memcpy(skb_put(data->reassembly, len), buf, len); |
| 334 | 333 | ||
| 335 | if (hdr & 0x08) { | 334 | if (hdr & 0x08) { |
| 336 | hci_recv_frame(data->reassembly); | 335 | hci_recv_frame(data->hdev, data->reassembly); |
| 337 | data->reassembly = NULL; | 336 | data->reassembly = NULL; |
| 338 | } | 337 | } |
| 339 | 338 | ||
| @@ -465,26 +464,18 @@ static int bfusb_close(struct hci_dev *hdev) | |||
| 465 | return 0; | 464 | return 0; |
| 466 | } | 465 | } |
| 467 | 466 | ||
| 468 | static int bfusb_send_frame(struct sk_buff *skb) | 467 | static int bfusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb) |
| 469 | { | 468 | { |
| 470 | struct hci_dev *hdev = (struct hci_dev *) skb->dev; | 469 | struct bfusb_data *data = hci_get_drvdata(hdev); |
| 471 | struct bfusb_data *data; | ||
| 472 | struct sk_buff *nskb; | 470 | struct sk_buff *nskb; |
| 473 | unsigned char buf[3]; | 471 | unsigned char buf[3]; |
| 474 | int sent = 0, size, count; | 472 | int sent = 0, size, count; |
| 475 | 473 | ||
| 476 | BT_DBG("hdev %p skb %p type %d len %d", hdev, skb, bt_cb(skb)->pkt_type, skb->len); | 474 | BT_DBG("hdev %p skb %p type %d len %d", hdev, skb, bt_cb(skb)->pkt_type, skb->len); |
| 477 | 475 | ||
| 478 | if (!hdev) { | ||
| 479 | BT_ERR("Frame for unknown HCI device (hdev=NULL)"); | ||
| 480 | return -ENODEV; | ||
| 481 | } | ||
| 482 | |||
| 483 | if (!test_bit(HCI_RUNNING, &hdev->flags)) | 476 | if (!test_bit(HCI_RUNNING, &hdev->flags)) |
| 484 | return -EBUSY; | 477 | return -EBUSY; |
| 485 | 478 | ||
| 486 | data = hci_get_drvdata(hdev); | ||
| 487 | |||
| 488 | switch (bt_cb(skb)->pkt_type) { | 479 | switch (bt_cb(skb)->pkt_type) { |
| 489 | case HCI_COMMAND_PKT: | 480 | case HCI_COMMAND_PKT: |
| 490 | hdev->stat.cmd_tx++; | 481 | hdev->stat.cmd_tx++; |
| @@ -544,11 +535,6 @@ static int bfusb_send_frame(struct sk_buff *skb) | |||
| 544 | return 0; | 535 | return 0; |
| 545 | } | 536 | } |
| 546 | 537 | ||
| 547 | static int bfusb_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg) | ||
| 548 | { | ||
| 549 | return -ENOIOCTLCMD; | ||
| 550 | } | ||
| 551 | |||
| 552 | static int bfusb_load_firmware(struct bfusb_data *data, | 538 | static int bfusb_load_firmware(struct bfusb_data *data, |
| 553 | const unsigned char *firmware, int count) | 539 | const unsigned char *firmware, int count) |
| 554 | { | 540 | { |
| @@ -699,11 +685,10 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
| 699 | hci_set_drvdata(hdev, data); | 685 | hci_set_drvdata(hdev, data); |
| 700 | SET_HCIDEV_DEV(hdev, &intf->dev); | 686 | SET_HCIDEV_DEV(hdev, &intf->dev); |
| 701 | 687 | ||
| 702 | hdev->open = bfusb_open; | 688 | hdev->open = bfusb_open; |
| 703 | hdev->close = bfusb_close; | 689 | hdev->close = bfusb_close; |
| 704 | hdev->flush = bfusb_flush; | 690 | hdev->flush = bfusb_flush; |
| 705 | hdev->send = bfusb_send_frame; | 691 | hdev->send = bfusb_send_frame; |
| 706 | hdev->ioctl = bfusb_ioctl; | ||
| 707 | 692 | ||
| 708 | if (hci_register_dev(hdev) < 0) { | 693 | if (hci_register_dev(hdev) < 0) { |
| 709 | BT_ERR("Can't register HCI device"); | 694 | BT_ERR("Can't register HCI device"); |
diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index 6c3e3d43c718..57427de864a6 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c | |||
| @@ -399,7 +399,6 @@ static void bluecard_receive(bluecard_info_t *info, unsigned int offset) | |||
| 399 | 399 | ||
| 400 | if (info->rx_state == RECV_WAIT_PACKET_TYPE) { | 400 | if (info->rx_state == RECV_WAIT_PACKET_TYPE) { |
| 401 | 401 | ||
| 402 | info->rx_skb->dev = (void *) info->hdev; | ||
| 403 | bt_cb(info->rx_skb)->pkt_type = buf[i]; | 402 | bt_cb(info->rx_skb)->pkt_type = buf[i]; |
| 404 | 403 | ||
| 405 | switch (bt_cb(info->rx_skb)->pkt_type) { | 404 | switch (bt_cb(info->rx_skb)->pkt_type) { |
| @@ -477,7 +476,7 @@ static void bluecard_receive(bluecard_info_t *info, unsigned int offset) | |||
| 477 | break; | 476 | break; |
| 478 | 477 | ||
| 479 | case RECV_WAIT_DATA: | 478 | case RECV_WAIT_DATA: |
| 480 | hci_recv_frame(info->rx_skb); | 479 | hci_recv_frame(info->hdev, info->rx_skb); |
| 481 | info->rx_skb = NULL; | 480 | info->rx_skb = NULL; |
| 482 | break; | 481 | break; |
| 483 | 482 | ||
| @@ -659,17 +658,9 @@ static int bluecard_hci_close(struct hci_dev *hdev) | |||
| 659 | } | 658 | } |
| 660 | 659 | ||
| 661 | 660 | ||
| 662 | static int bluecard_hci_send_frame(struct sk_buff *skb) | 661 | static int bluecard_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb) |
| 663 | { | 662 | { |
| 664 | bluecard_info_t *info; | 663 | bluecard_info_t *info = hci_get_drvdata(hdev); |
| 665 | struct hci_dev *hdev = (struct hci_dev *)(skb->dev); | ||
| 666 | |||
| 667 | if (!hdev) { | ||
| 668 | BT_ERR("Frame for unknown HCI device (hdev=NULL)"); | ||
| 669 | return -ENODEV; | ||
| 670 | } | ||
| 671 | |||
| 672 | info = hci_get_drvdata(hdev); | ||
| 673 | 664 | ||
| 674 | switch (bt_cb(skb)->pkt_type) { | 665 | switch (bt_cb(skb)->pkt_type) { |
| 675 | case HCI_COMMAND_PKT: | 666 | case HCI_COMMAND_PKT: |
| @@ -693,12 +684,6 @@ static int bluecard_hci_send_frame(struct sk_buff *skb) | |||
| 693 | } | 684 | } |
| 694 | 685 | ||
| 695 | 686 | ||
| 696 | static int bluecard_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg) | ||
| 697 | { | ||
| 698 | return -ENOIOCTLCMD; | ||
| 699 | } | ||
| 700 | |||
| 701 | |||
| 702 | 687 | ||
| 703 | /* ======================== Card services HCI interaction ======================== */ | 688 | /* ======================== Card services HCI interaction ======================== */ |
| 704 | 689 | ||
| @@ -734,11 +719,10 @@ static int bluecard_open(bluecard_info_t *info) | |||
| 734 | hci_set_drvdata(hdev, info); | 719 | hci_set_drvdata(hdev, info); |
| 735 | SET_HCIDEV_DEV(hdev, &info->p_dev->dev); | 720 | SET_HCIDEV_DEV(hdev, &info->p_dev->dev); |
| 736 | 721 | ||
| 737 | hdev->open = bluecard_hci_open; | 722 | hdev->open = bluecard_hci_open; |
| 738 | hdev->close = bluecard_hci_close; | 723 | hdev->close = bluecard_hci_close; |
| 739 | hdev->flush = bluecard_hci_flush; | 724 | hdev->flush = bluecard_hci_flush; |
| 740 | hdev->send = bluecard_hci_send_frame; | 725 | hdev->send = bluecard_hci_send_frame; |
| 741 | hdev->ioctl = bluecard_hci_ioctl; | ||
| 742 | 726 | ||
| 743 | id = inb(iobase + 0x30); | 727 | id = inb(iobase + 0x30); |
| 744 | 728 | ||
diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c index 2fe4a8031348..8a319913c9a9 100644 --- a/drivers/bluetooth/bpa10x.c +++ b/drivers/bluetooth/bpa10x.c | |||
| @@ -37,7 +37,7 @@ | |||
| 37 | 37 | ||
| 38 | #define VERSION "0.10" | 38 | #define VERSION "0.10" |
| 39 | 39 | ||
| 40 | static struct usb_device_id bpa10x_table[] = { | 40 | static const struct usb_device_id bpa10x_table[] = { |
| 41 | /* Tektronix BPA 100/105 (Digianswer) */ | 41 | /* Tektronix BPA 100/105 (Digianswer) */ |
| 42 | { USB_DEVICE(0x08fd, 0x0002) }, | 42 | { USB_DEVICE(0x08fd, 0x0002) }, |
| 43 | 43 | ||
| @@ -129,8 +129,6 @@ static int bpa10x_recv(struct hci_dev *hdev, int queue, void *buf, int count) | |||
| 129 | return -ENOMEM; | 129 | return -ENOMEM; |
| 130 | } | 130 | } |
| 131 | 131 | ||
| 132 | skb->dev = (void *) hdev; | ||
| 133 | |||
| 134 | data->rx_skb[queue] = skb; | 132 | data->rx_skb[queue] = skb; |
| 135 | 133 | ||
| 136 | scb = (void *) skb->cb; | 134 | scb = (void *) skb->cb; |
| @@ -155,7 +153,7 @@ static int bpa10x_recv(struct hci_dev *hdev, int queue, void *buf, int count) | |||
| 155 | data->rx_skb[queue] = NULL; | 153 | data->rx_skb[queue] = NULL; |
| 156 | 154 | ||
| 157 | bt_cb(skb)->pkt_type = scb->type; | 155 | bt_cb(skb)->pkt_type = scb->type; |
| 158 | hci_recv_frame(skb); | 156 | hci_recv_frame(hdev, skb); |
| 159 | } | 157 | } |
| 160 | 158 | ||
| 161 | count -= len; buf += len; | 159 | count -= len; buf += len; |
| @@ -352,9 +350,8 @@ static int bpa10x_flush(struct hci_dev *hdev) | |||
| 352 | return 0; | 350 | return 0; |
| 353 | } | 351 | } |
| 354 | 352 | ||
| 355 | static int bpa10x_send_frame(struct sk_buff *skb) | 353 | static int bpa10x_send_frame(struct hci_dev *hdev, struct sk_buff *skb) |
| 356 | { | 354 | { |
| 357 | struct hci_dev *hdev = (struct hci_dev *) skb->dev; | ||
| 358 | struct bpa10x_data *data = hci_get_drvdata(hdev); | 355 | struct bpa10x_data *data = hci_get_drvdata(hdev); |
| 359 | struct usb_ctrlrequest *dr; | 356 | struct usb_ctrlrequest *dr; |
| 360 | struct urb *urb; | 357 | struct urb *urb; |
| @@ -366,6 +363,8 @@ static int bpa10x_send_frame(struct sk_buff *skb) | |||
| 366 | if (!test_bit(HCI_RUNNING, &hdev->flags)) | 363 | if (!test_bit(HCI_RUNNING, &hdev->flags)) |
| 367 | return -EBUSY; | 364 | return -EBUSY; |
| 368 | 365 | ||
| 366 | skb->dev = (void *) hdev; | ||
| 367 | |||
| 369 | urb = usb_alloc_urb(0, GFP_ATOMIC); | 368 | urb = usb_alloc_urb(0, GFP_ATOMIC); |
| 370 | if (!urb) | 369 | if (!urb) |
| 371 | return -ENOMEM; | 370 | return -ENOMEM; |
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index a1aaa3ba2a4b..73d87994d028 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c | |||
| @@ -247,7 +247,6 @@ static void bt3c_receive(bt3c_info_t *info) | |||
| 247 | 247 | ||
| 248 | if (info->rx_state == RECV_WAIT_PACKET_TYPE) { | 248 | if (info->rx_state == RECV_WAIT_PACKET_TYPE) { |
| 249 | 249 | ||
| 250 | info->rx_skb->dev = (void *) info->hdev; | ||
| 251 | bt_cb(info->rx_skb)->pkt_type = inb(iobase + DATA_L); | 250 | bt_cb(info->rx_skb)->pkt_type = inb(iobase + DATA_L); |
| 252 | inb(iobase + DATA_H); | 251 | inb(iobase + DATA_H); |
| 253 | //printk("bt3c: PACKET_TYPE=%02x\n", bt_cb(info->rx_skb)->pkt_type); | 252 | //printk("bt3c: PACKET_TYPE=%02x\n", bt_cb(info->rx_skb)->pkt_type); |
| @@ -318,7 +317,7 @@ static void bt3c_receive(bt3c_info_t *info) | |||
| 318 | break; | 317 | break; |
| 319 | 318 | ||
| 320 | case RECV_WAIT_DATA: | 319 | case RECV_WAIT_DATA: |
| 321 | hci_recv_frame(info->rx_skb); | 320 | hci_recv_frame(info->hdev, info->rx_skb); |
| 322 | info->rx_skb = NULL; | 321 | info->rx_skb = NULL; |
| 323 | break; | 322 | break; |
| 324 | 323 | ||
| @@ -416,19 +415,11 @@ static int bt3c_hci_close(struct hci_dev *hdev) | |||
| 416 | } | 415 | } |
| 417 | 416 | ||
| 418 | 417 | ||
| 419 | static int bt3c_hci_send_frame(struct sk_buff *skb) | 418 | static int bt3c_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb) |
| 420 | { | 419 | { |
| 421 | bt3c_info_t *info; | 420 | bt3c_info_t *info = hci_get_drvdata(hdev); |
| 422 | struct hci_dev *hdev = (struct hci_dev *)(skb->dev); | ||
| 423 | unsigned long flags; | 421 | unsigned long flags; |
| 424 | 422 | ||
| 425 | if (!hdev) { | ||
| 426 | BT_ERR("Frame for unknown HCI device (hdev=NULL)"); | ||
| 427 | return -ENODEV; | ||
| 428 | } | ||
| 429 | |||
| 430 | info = hci_get_drvdata(hdev); | ||
| 431 | |||
| 432 | switch (bt_cb(skb)->pkt_type) { | 423 | switch (bt_cb(skb)->pkt_type) { |
| 433 | case HCI_COMMAND_PKT: | 424 | case HCI_COMMAND_PKT: |
| 434 | hdev->stat.cmd_tx++; | 425 | hdev->stat.cmd_tx++; |
| @@ -455,12 +446,6 @@ static int bt3c_hci_send_frame(struct sk_buff *skb) | |||
| 455 | } | 446 | } |
| 456 | 447 | ||
| 457 | 448 | ||
| 458 | static int bt3c_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg) | ||
| 459 | { | ||
| 460 | return -ENOIOCTLCMD; | ||
| 461 | } | ||
| 462 | |||
| 463 | |||
| 464 | 449 | ||
| 465 | /* ======================== Card services HCI interaction ======================== */ | 450 | /* ======================== Card services HCI interaction ======================== */ |
| 466 | 451 | ||
| @@ -577,11 +562,10 @@ static int bt3c_open(bt3c_info_t *info) | |||
| 577 | hci_set_drvdata(hdev, info); | 562 | hci_set_drvdata(hdev, info); |
| 578 | SET_HCIDEV_DEV(hdev, &info->p_dev->dev); | 563 | SET_HCIDEV_DEV(hdev, &info->p_dev->dev); |
| 579 | 564 | ||
| 580 | hdev->open = bt3c_hci_open; | 565 | hdev->open = bt3c_hci_open; |
| 581 | hdev->close = bt3c_hci_close; | 566 | hdev->close = bt3c_hci_close; |
| 582 | hdev->flush = bt3c_hci_flush; | 567 | hdev->flush = bt3c_hci_flush; |
| 583 | hdev->send = bt3c_hci_send_frame; | 568 | hdev->send = bt3c_hci_send_frame; |
| 584 | hdev->ioctl = bt3c_hci_ioctl; | ||
| 585 | 569 | ||
| 586 | /* Load firmware */ | 570 | /* Load firmware */ |
| 587 | err = request_firmware(&firmware, "BT3CPCC.bin", &info->p_dev->dev); | 571 | err = request_firmware(&firmware, "BT3CPCC.bin", &info->p_dev->dev); |
diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c index 6e7bd4e4adbb..5cf31c4fe6d1 100644 --- a/drivers/bluetooth/btmrvl_main.c +++ b/drivers/bluetooth/btmrvl_main.c | |||
| @@ -187,7 +187,6 @@ static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 cmd_no, | |||
| 187 | 187 | ||
| 188 | bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT; | 188 | bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT; |
| 189 | 189 | ||
| 190 | skb->dev = (void *) priv->btmrvl_dev.hcidev; | ||
| 191 | skb_queue_head(&priv->adapter->tx_queue, skb); | 190 | skb_queue_head(&priv->adapter->tx_queue, skb); |
| 192 | 191 | ||
| 193 | priv->btmrvl_dev.sendcmdflag = true; | 192 | priv->btmrvl_dev.sendcmdflag = true; |
| @@ -356,26 +355,12 @@ static void btmrvl_free_adapter(struct btmrvl_private *priv) | |||
| 356 | priv->adapter = NULL; | 355 | priv->adapter = NULL; |
| 357 | } | 356 | } |
| 358 | 357 | ||
| 359 | static int btmrvl_ioctl(struct hci_dev *hdev, | 358 | static int btmrvl_send_frame(struct hci_dev *hdev, struct sk_buff *skb) |
| 360 | unsigned int cmd, unsigned long arg) | ||
| 361 | { | 359 | { |
| 362 | return -ENOIOCTLCMD; | 360 | struct btmrvl_private *priv = hci_get_drvdata(hdev); |
| 363 | } | ||
| 364 | |||
| 365 | static int btmrvl_send_frame(struct sk_buff *skb) | ||
| 366 | { | ||
| 367 | struct hci_dev *hdev = (struct hci_dev *) skb->dev; | ||
| 368 | struct btmrvl_private *priv = NULL; | ||
| 369 | 361 | ||
| 370 | BT_DBG("type=%d, len=%d", skb->pkt_type, skb->len); | 362 | BT_DBG("type=%d, len=%d", skb->pkt_type, skb->len); |
| 371 | 363 | ||
| 372 | if (!hdev) { | ||
| 373 | BT_ERR("Frame for unknown HCI device"); | ||
| 374 | return -ENODEV; | ||
| 375 | } | ||
| 376 | |||
| 377 | priv = hci_get_drvdata(hdev); | ||
| 378 | |||
| 379 | if (!test_bit(HCI_RUNNING, &hdev->flags)) { | 364 | if (!test_bit(HCI_RUNNING, &hdev->flags)) { |
| 380 | BT_ERR("Failed testing HCI_RUNING, flags=%lx", hdev->flags); | 365 | BT_ERR("Failed testing HCI_RUNING, flags=%lx", hdev->flags); |
| 381 | print_hex_dump_bytes("data: ", DUMP_PREFIX_OFFSET, | 366 | print_hex_dump_bytes("data: ", DUMP_PREFIX_OFFSET, |
| @@ -650,12 +635,11 @@ int btmrvl_register_hdev(struct btmrvl_private *priv) | |||
| 650 | priv->btmrvl_dev.hcidev = hdev; | 635 | priv->btmrvl_dev.hcidev = hdev; |
| 651 | hci_set_drvdata(hdev, priv); | 636 | hci_set_drvdata(hdev, priv); |
| 652 | 637 | ||
| 653 | hdev->bus = HCI_SDIO; | 638 | hdev->bus = HCI_SDIO; |
| 654 | hdev->open = btmrvl_open; | 639 | hdev->open = btmrvl_open; |
| 655 | hdev->close = btmrvl_close; | 640 | hdev->close = btmrvl_close; |
| 656 | hdev->flush = btmrvl_flush; | 641 | hdev->flush = btmrvl_flush; |
| 657 | hdev->send = btmrvl_send_frame; | 642 | hdev->send = btmrvl_send_frame; |
| 658 | hdev->ioctl = btmrvl_ioctl; | ||
| 659 | hdev->setup = btmrvl_setup; | 643 | hdev->setup = btmrvl_setup; |
| 660 | 644 | ||
| 661 | hdev->dev_type = priv->btmrvl_dev.dev_type; | 645 | hdev->dev_type = priv->btmrvl_dev.dev_type; |
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index 332475e400cf..fabcf5bb48af 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c | |||
| @@ -600,15 +600,14 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv) | |||
| 600 | case HCI_SCODATA_PKT: | 600 | case HCI_SCODATA_PKT: |
| 601 | case HCI_EVENT_PKT: | 601 | case HCI_EVENT_PKT: |
| 602 | bt_cb(skb)->pkt_type = type; | 602 | bt_cb(skb)->pkt_type = type; |
| 603 | skb->dev = (void *)hdev; | ||
| 604 | skb_put(skb, buf_len); | 603 | skb_put(skb, buf_len); |
| 605 | skb_pull(skb, SDIO_HEADER_LEN); | 604 | skb_pull(skb, SDIO_HEADER_LEN); |
| 606 | 605 | ||
| 607 | if (type == HCI_EVENT_PKT) { | 606 | if (type == HCI_EVENT_PKT) { |
| 608 | if (btmrvl_check_evtpkt(priv, skb)) | 607 | if (btmrvl_check_evtpkt(priv, skb)) |
| 609 | hci_recv_frame(skb); | 608 | hci_recv_frame(hdev, skb); |
| 610 | } else { | 609 | } else { |
| 611 | hci_recv_frame(skb); | 610 | hci_recv_frame(hdev, skb); |
| 612 | } | 611 | } |
| 613 | 612 | ||
| 614 | hdev->stat.byte_rx += buf_len; | 613 | hdev->stat.byte_rx += buf_len; |
| @@ -616,12 +615,11 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv) | |||
| 616 | 615 | ||
| 617 | case MRVL_VENDOR_PKT: | 616 | case MRVL_VENDOR_PKT: |
| 618 | bt_cb(skb)->pkt_type = HCI_VENDOR_PKT; | 617 | bt_cb(skb)->pkt_type = HCI_VENDOR_PKT; |
| 619 | skb->dev = (void *)hdev; | ||
| 620 | skb_put(skb, buf_len); | 618 | skb_put(skb, buf_len); |
| 621 | skb_pull(skb, SDIO_HEADER_LEN); | 619 | skb_pull(skb, SDIO_HEADER_LEN); |
| 622 | 620 | ||
| 623 | if (btmrvl_process_event(priv, skb)) | 621 | if (btmrvl_process_event(priv, skb)) |
| 624 | hci_recv_frame(skb); | 622 | hci_recv_frame(hdev, skb); |
| 625 | 623 | ||
| 626 | hdev->stat.byte_rx += buf_len; | 624 | hdev->stat.byte_rx += buf_len; |
| 627 | break; | 625 | break; |
diff --git a/drivers/bluetooth/btsdio.c b/drivers/bluetooth/btsdio.c index 4a9909713874..b61440aaee65 100644 --- a/drivers/bluetooth/btsdio.c +++ b/drivers/bluetooth/btsdio.c | |||
| @@ -157,10 +157,9 @@ static int btsdio_rx_packet(struct btsdio_data *data) | |||
| 157 | 157 | ||
| 158 | data->hdev->stat.byte_rx += len; | 158 | data->hdev->stat.byte_rx += len; |
| 159 | 159 | ||
| 160 | skb->dev = (void *) data->hdev; | ||
| 161 | bt_cb(skb)->pkt_type = hdr[3]; | 160 | bt_cb(skb)->pkt_type = hdr[3]; |
| 162 | 161 | ||
| 163 | err = hci_recv_frame(skb); | 162 | err = hci_recv_frame(data->hdev, skb); |
| 164 | if (err < 0) | 163 | if (err < 0) |
| 165 | return err; | 164 | return err; |
| 166 | 165 | ||
| @@ -255,9 +254,8 @@ static int btsdio_flush(struct hci_dev *hdev) | |||
| 255 | return 0; | 254 | return 0; |
| 256 | } | 255 | } |
| 257 | 256 | ||
| 258 | static int btsdio_send_frame(struct sk_buff *skb) | 257 | static int btsdio_send_frame(struct hci_dev *hdev, struct sk_buff *skb) |
| 259 | { | 258 | { |
| 260 | struct hci_dev *hdev = (struct hci_dev *) skb->dev; | ||
| 261 | struct btsdio_data *data = hci_get_drvdata(hdev); | 259 | struct btsdio_data *data = hci_get_drvdata(hdev); |
| 262 | 260 | ||
| 263 | BT_DBG("%s", hdev->name); | 261 | BT_DBG("%s", hdev->name); |
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c index beb262f2dc4d..a03ecc22a561 100644 --- a/drivers/bluetooth/btuart_cs.c +++ b/drivers/bluetooth/btuart_cs.c | |||
| @@ -198,7 +198,6 @@ static void btuart_receive(btuart_info_t *info) | |||
| 198 | 198 | ||
| 199 | if (info->rx_state == RECV_WAIT_PACKET_TYPE) { | 199 | if (info->rx_state == RECV_WAIT_PACKET_TYPE) { |
| 200 | 200 | ||
| 201 | info->rx_skb->dev = (void *) info->hdev; | ||
| 202 | bt_cb(info->rx_skb)->pkt_type = inb(iobase + UART_RX); | 201 | bt_cb(info->rx_skb)->pkt_type = inb(iobase + UART_RX); |
| 203 | 202 | ||
| 204 | switch (bt_cb(info->rx_skb)->pkt_type) { | 203 | switch (bt_cb(info->rx_skb)->pkt_type) { |
| @@ -265,7 +264,7 @@ static void btuart_receive(btuart_info_t *info) | |||
| 265 | break; | 264 | break; |
| 266 | 265 | ||
| 267 | case RECV_WAIT_DATA: | 266 | case RECV_WAIT_DATA: |
| 268 | hci_recv_frame(info->rx_skb); | 267 | hci_recv_frame(info->hdev, info->rx_skb); |
| 269 | info->rx_skb = NULL; | 268 | info->rx_skb = NULL; |
| 270 | break; | 269 | break; |
| 271 | 270 | ||
| @@ -424,17 +423,9 @@ static int btuart_hci_close(struct hci_dev *hdev) | |||
| 424 | } | 423 | } |
| 425 | 424 | ||
| 426 | 425 | ||
| 427 | static int btuart_hci_send_frame(struct sk_buff *skb) | 426 | static int btuart_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb) |
| 428 | { | 427 | { |
| 429 | btuart_info_t *info; | 428 | btuart_info_t *info = hci_get_drvdata(hdev); |
| 430 | struct hci_dev *hdev = (struct hci_dev *)(skb->dev); | ||
| 431 | |||
| 432 | if (!hdev) { | ||
| 433 | BT_ERR("Frame for unknown HCI device (hdev=NULL)"); | ||
| 434 | return -ENODEV; | ||
| 435 | } | ||
| 436 | |||
| 437 | info = hci_get_drvdata(hdev); | ||
| 438 | 429 | ||
| 439 | switch (bt_cb(skb)->pkt_type) { | 430 | switch (bt_cb(skb)->pkt_type) { |
| 440 | case HCI_COMMAND_PKT: | 431 | case HCI_COMMAND_PKT: |
| @@ -458,12 +449,6 @@ static int btuart_hci_send_frame(struct sk_buff *skb) | |||
| 458 | } | 449 | } |
| 459 | 450 | ||
| 460 | 451 | ||
| 461 | static int btuart_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg) | ||
| 462 | { | ||
| 463 | return -ENOIOCTLCMD; | ||
| 464 | } | ||
| 465 | |||
| 466 | |||
| 467 | 452 | ||
| 468 | /* ======================== Card services HCI interaction ======================== */ | 453 | /* ======================== Card services HCI interaction ======================== */ |
| 469 | 454 | ||
| @@ -495,11 +480,10 @@ static int btuart_open(btuart_info_t *info) | |||
| 495 | hci_set_drvdata(hdev, info); | 480 | hci_set_drvdata(hdev, info); |
| 496 | SET_HCIDEV_DEV(hdev, &info->p_dev->dev); | 481 | SET_HCIDEV_DEV(hdev, &info->p_dev->dev); |
| 497 | 482 | ||
| 498 | hdev->open = btuart_hci_open; | 483 | hdev->open = btuart_hci_open; |
| 499 | hdev->close = btuart_hci_close; | 484 | hdev->close = btuart_hci_close; |
| 500 | hdev->flush = btuart_hci_flush; | 485 | hdev->flush = btuart_hci_flush; |
| 501 | hdev->send = btuart_hci_send_frame; | 486 | hdev->send = btuart_hci_send_frame; |
| 502 | hdev->ioctl = btuart_hci_ioctl; | ||
| 503 | 487 | ||
| 504 | spin_lock_irqsave(&(info->lock), flags); | 488 | spin_lock_irqsave(&(info->lock), flags); |
| 505 | 489 | ||
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index f3dfc0a88fdc..30868fa870f6 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c | |||
| @@ -50,7 +50,7 @@ static struct usb_driver btusb_driver; | |||
| 50 | #define BTUSB_ATH3012 0x80 | 50 | #define BTUSB_ATH3012 0x80 |
| 51 | #define BTUSB_INTEL 0x100 | 51 | #define BTUSB_INTEL 0x100 |
| 52 | 52 | ||
| 53 | static struct usb_device_id btusb_table[] = { | 53 | static const struct usb_device_id btusb_table[] = { |
| 54 | /* Generic Bluetooth USB device */ | 54 | /* Generic Bluetooth USB device */ |
| 55 | { USB_DEVICE_INFO(0xe0, 0x01, 0x01) }, | 55 | { USB_DEVICE_INFO(0xe0, 0x01, 0x01) }, |
| 56 | 56 | ||
| @@ -121,7 +121,7 @@ static struct usb_device_id btusb_table[] = { | |||
| 121 | 121 | ||
| 122 | MODULE_DEVICE_TABLE(usb, btusb_table); | 122 | MODULE_DEVICE_TABLE(usb, btusb_table); |
| 123 | 123 | ||
| 124 | static struct usb_device_id blacklist_table[] = { | 124 | static const struct usb_device_id blacklist_table[] = { |
| 125 | /* CSR BlueCore devices */ | 125 | /* CSR BlueCore devices */ |
| 126 | { USB_DEVICE(0x0a12, 0x0001), .driver_info = BTUSB_CSR }, | 126 | { USB_DEVICE(0x0a12, 0x0001), .driver_info = BTUSB_CSR }, |
| 127 | 127 | ||
| @@ -716,9 +716,8 @@ static int btusb_flush(struct hci_dev *hdev) | |||
| 716 | return 0; | 716 | return 0; |
| 717 | } | 717 | } |
| 718 | 718 | ||
| 719 | static int btusb_send_frame(struct sk_buff *skb) | 719 | static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb) |
| 720 | { | 720 | { |
| 721 | struct hci_dev *hdev = (struct hci_dev *) skb->dev; | ||
| 722 | struct btusb_data *data = hci_get_drvdata(hdev); | 721 | struct btusb_data *data = hci_get_drvdata(hdev); |
| 723 | struct usb_ctrlrequest *dr; | 722 | struct usb_ctrlrequest *dr; |
| 724 | struct urb *urb; | 723 | struct urb *urb; |
| @@ -730,6 +729,8 @@ static int btusb_send_frame(struct sk_buff *skb) | |||
| 730 | if (!test_bit(HCI_RUNNING, &hdev->flags)) | 729 | if (!test_bit(HCI_RUNNING, &hdev->flags)) |
| 731 | return -EBUSY; | 730 | return -EBUSY; |
| 732 | 731 | ||
| 732 | skb->dev = (void *) hdev; | ||
| 733 | |||
| 733 | switch (bt_cb(skb)->pkt_type) { | 734 | switch (bt_cb(skb)->pkt_type) { |
| 734 | case HCI_COMMAND_PKT: | 735 | case HCI_COMMAND_PKT: |
| 735 | urb = usb_alloc_urb(0, GFP_ATOMIC); | 736 | urb = usb_alloc_urb(0, GFP_ATOMIC); |
| @@ -774,7 +775,7 @@ static int btusb_send_frame(struct sk_buff *skb) | |||
| 774 | break; | 775 | break; |
| 775 | 776 | ||
| 776 | case HCI_SCODATA_PKT: | 777 | case HCI_SCODATA_PKT: |
| 777 | if (!data->isoc_tx_ep || hdev->conn_hash.sco_num < 1) | 778 | if (!data->isoc_tx_ep || hci_conn_num(hdev, SCO_LINK) < 1) |
| 778 | return -ENODEV; | 779 | return -ENODEV; |
| 779 | 780 | ||
| 780 | urb = usb_alloc_urb(BTUSB_MAX_ISOC_FRAMES, GFP_ATOMIC); | 781 | urb = usb_alloc_urb(BTUSB_MAX_ISOC_FRAMES, GFP_ATOMIC); |
| @@ -833,8 +834,8 @@ static void btusb_notify(struct hci_dev *hdev, unsigned int evt) | |||
| 833 | 834 | ||
| 834 | BT_DBG("%s evt %d", hdev->name, evt); | 835 | BT_DBG("%s evt %d", hdev->name, evt); |
| 835 | 836 | ||
| 836 | if (hdev->conn_hash.sco_num != data->sco_num) { | 837 | if (hci_conn_num(hdev, SCO_LINK) != data->sco_num) { |
| 837 | data->sco_num = hdev->conn_hash.sco_num; | 838 | data->sco_num = hci_conn_num(hdev, SCO_LINK); |
| 838 | schedule_work(&data->work); | 839 | schedule_work(&data->work); |
| 839 | } | 840 | } |
| 840 | } | 841 | } |
| @@ -889,7 +890,7 @@ static void btusb_work(struct work_struct *work) | |||
| 889 | int new_alts; | 890 | int new_alts; |
| 890 | int err; | 891 | int err; |
| 891 | 892 | ||
| 892 | if (hdev->conn_hash.sco_num > 0) { | 893 | if (data->sco_num > 0) { |
| 893 | if (!test_bit(BTUSB_DID_ISO_RESUME, &data->flags)) { | 894 | if (!test_bit(BTUSB_DID_ISO_RESUME, &data->flags)) { |
| 894 | err = usb_autopm_get_interface(data->isoc ? data->isoc : data->intf); | 895 | err = usb_autopm_get_interface(data->isoc ? data->isoc : data->intf); |
| 895 | if (err < 0) { | 896 | if (err < 0) { |
| @@ -903,9 +904,9 @@ static void btusb_work(struct work_struct *work) | |||
| 903 | 904 | ||
| 904 | if (hdev->voice_setting & 0x0020) { | 905 | if (hdev->voice_setting & 0x0020) { |
| 905 | static const int alts[3] = { 2, 4, 5 }; | 906 | static const int alts[3] = { 2, 4, 5 }; |
| 906 | new_alts = alts[hdev->conn_hash.sco_num - 1]; | 907 | new_alts = alts[data->sco_num - 1]; |
| 907 | } else { | 908 | } else { |
| 908 | new_alts = hdev->conn_hash.sco_num; | 909 | new_alts = data->sco_num; |
| 909 | } | 910 | } |
| 910 | 911 | ||
| 911 | if (data->isoc_altsetting != new_alts) { | 912 | if (data->isoc_altsetting != new_alts) { |
diff --git a/drivers/bluetooth/btwilink.c b/drivers/bluetooth/btwilink.c index 60abf596f60e..f038dba19e36 100644 --- a/drivers/bluetooth/btwilink.c +++ b/drivers/bluetooth/btwilink.c | |||
| @@ -108,10 +108,8 @@ static long st_receive(void *priv_data, struct sk_buff *skb) | |||
| 108 | return -EFAULT; | 108 | return -EFAULT; |
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | skb->dev = (void *) lhst->hdev; | ||
| 112 | |||
| 113 | /* Forward skb to HCI core layer */ | 111 | /* Forward skb to HCI core layer */ |
| 114 | err = hci_recv_frame(skb); | 112 | err = hci_recv_frame(lhst->hdev, skb); |
| 115 | if (err < 0) { | 113 | if (err < 0) { |
| 116 | BT_ERR("Unable to push skb to HCI core(%d)", err); | 114 | BT_ERR("Unable to push skb to HCI core(%d)", err); |
| 117 | return err; | 115 | return err; |
| @@ -253,14 +251,11 @@ static int ti_st_close(struct hci_dev *hdev) | |||
| 253 | return err; | 251 | return err; |
| 254 | } | 252 | } |
| 255 | 253 | ||
| 256 | static int ti_st_send_frame(struct sk_buff *skb) | 254 | static int ti_st_send_frame(struct hci_dev *hdev, struct sk_buff *skb) |
| 257 | { | 255 | { |
| 258 | struct hci_dev *hdev; | ||
| 259 | struct ti_st *hst; | 256 | struct ti_st *hst; |
| 260 | long len; | 257 | long len; |
| 261 | 258 | ||
| 262 | hdev = (struct hci_dev *)skb->dev; | ||
| 263 | |||
| 264 | if (!test_bit(HCI_RUNNING, &hdev->flags)) | 259 | if (!test_bit(HCI_RUNNING, &hdev->flags)) |
| 265 | return -EBUSY; | 260 | return -EBUSY; |
| 266 | 261 | ||
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index 33f3a6950c0e..52eed1f3565d 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c | |||
| @@ -256,9 +256,8 @@ static void dtl1_receive(dtl1_info_t *info) | |||
| 256 | case 0x83: | 256 | case 0x83: |
| 257 | case 0x84: | 257 | case 0x84: |
| 258 | /* send frame to the HCI layer */ | 258 | /* send frame to the HCI layer */ |
| 259 | info->rx_skb->dev = (void *) info->hdev; | ||
| 260 | bt_cb(info->rx_skb)->pkt_type &= 0x0f; | 259 | bt_cb(info->rx_skb)->pkt_type &= 0x0f; |
| 261 | hci_recv_frame(info->rx_skb); | 260 | hci_recv_frame(info->hdev, info->rx_skb); |
| 262 | break; | 261 | break; |
| 263 | default: | 262 | default: |
| 264 | /* unknown packet */ | 263 | /* unknown packet */ |
| @@ -383,20 +382,12 @@ static int dtl1_hci_close(struct hci_dev *hdev) | |||
| 383 | } | 382 | } |
| 384 | 383 | ||
| 385 | 384 | ||
| 386 | static int dtl1_hci_send_frame(struct sk_buff *skb) | 385 | static int dtl1_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb) |
| 387 | { | 386 | { |
| 388 | dtl1_info_t *info; | 387 | dtl1_info_t *info = hci_get_drvdata(hdev); |
| 389 | struct hci_dev *hdev = (struct hci_dev *)(skb->dev); | ||
| 390 | struct sk_buff *s; | 388 | struct sk_buff *s; |
| 391 | nsh_t nsh; | 389 | nsh_t nsh; |
| 392 | 390 | ||
| 393 | if (!hdev) { | ||
| 394 | BT_ERR("Frame for unknown HCI device (hdev=NULL)"); | ||
| 395 | return -ENODEV; | ||
| 396 | } | ||
| 397 | |||
| 398 | info = hci_get_drvdata(hdev); | ||
| 399 | |||
| 400 | switch (bt_cb(skb)->pkt_type) { | 391 | switch (bt_cb(skb)->pkt_type) { |
| 401 | case HCI_COMMAND_PKT: | 392 | case HCI_COMMAND_PKT: |
| 402 | hdev->stat.cmd_tx++; | 393 | hdev->stat.cmd_tx++; |
| @@ -438,12 +429,6 @@ static int dtl1_hci_send_frame(struct sk_buff *skb) | |||
| 438 | } | 429 | } |
| 439 | 430 | ||
| 440 | 431 | ||
| 441 | static int dtl1_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg) | ||
| 442 | { | ||
| 443 | return -ENOIOCTLCMD; | ||
| 444 | } | ||
| 445 | |||
| 446 | |||
| 447 | 432 | ||
| 448 | /* ======================== Card services HCI interaction ======================== */ | 433 | /* ======================== Card services HCI interaction ======================== */ |
| 449 | 434 | ||
| @@ -477,11 +462,10 @@ static int dtl1_open(dtl1_info_t *info) | |||
| 477 | hci_set_drvdata(hdev, info); | 462 | hci_set_drvdata(hdev, info); |
| 478 | SET_HCIDEV_DEV(hdev, &info->p_dev->dev); | 463 | SET_HCIDEV_DEV(hdev, &info->p_dev->dev); |
| 479 | 464 | ||
| 480 | hdev->open = dtl1_hci_open; | 465 | hdev->open = dtl1_hci_open; |
| 481 | hdev->close = dtl1_hci_close; | 466 | hdev->close = dtl1_hci_close; |
| 482 | hdev->flush = dtl1_hci_flush; | 467 | hdev->flush = dtl1_hci_flush; |
| 483 | hdev->send = dtl1_hci_send_frame; | 468 | hdev->send = dtl1_hci_send_frame; |
| 484 | hdev->ioctl = dtl1_hci_ioctl; | ||
| 485 | 469 | ||
| 486 | spin_lock_irqsave(&(info->lock), flags); | 470 | spin_lock_irqsave(&(info->lock), flags); |
| 487 | 471 | ||
diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c index 57e502e06080..0bc87f7abd95 100644 --- a/drivers/bluetooth/hci_bcsp.c +++ b/drivers/bluetooth/hci_bcsp.c | |||
| @@ -522,7 +522,7 @@ static void bcsp_complete_rx_pkt(struct hci_uart *hu) | |||
| 522 | memcpy(skb_push(bcsp->rx_skb, HCI_EVENT_HDR_SIZE), &hdr, HCI_EVENT_HDR_SIZE); | 522 | memcpy(skb_push(bcsp->rx_skb, HCI_EVENT_HDR_SIZE), &hdr, HCI_EVENT_HDR_SIZE); |
| 523 | bt_cb(bcsp->rx_skb)->pkt_type = HCI_EVENT_PKT; | 523 | bt_cb(bcsp->rx_skb)->pkt_type = HCI_EVENT_PKT; |
| 524 | 524 | ||
| 525 | hci_recv_frame(bcsp->rx_skb); | 525 | hci_recv_frame(hu->hdev, bcsp->rx_skb); |
| 526 | } else { | 526 | } else { |
| 527 | BT_ERR ("Packet for unknown channel (%u %s)", | 527 | BT_ERR ("Packet for unknown channel (%u %s)", |
| 528 | bcsp->rx_skb->data[1] & 0x0f, | 528 | bcsp->rx_skb->data[1] & 0x0f, |
| @@ -536,7 +536,7 @@ static void bcsp_complete_rx_pkt(struct hci_uart *hu) | |||
| 536 | /* Pull out BCSP hdr */ | 536 | /* Pull out BCSP hdr */ |
| 537 | skb_pull(bcsp->rx_skb, 4); | 537 | skb_pull(bcsp->rx_skb, 4); |
| 538 | 538 | ||
| 539 | hci_recv_frame(bcsp->rx_skb); | 539 | hci_recv_frame(hu->hdev, bcsp->rx_skb); |
| 540 | } | 540 | } |
| 541 | 541 | ||
| 542 | bcsp->rx_state = BCSP_W4_PKT_DELIMITER; | 542 | bcsp->rx_state = BCSP_W4_PKT_DELIMITER; |
| @@ -655,7 +655,6 @@ static int bcsp_recv(struct hci_uart *hu, void *data, int count) | |||
| 655 | bcsp->rx_count = 0; | 655 | bcsp->rx_count = 0; |
| 656 | return 0; | 656 | return 0; |
| 657 | } | 657 | } |
| 658 | bcsp->rx_skb->dev = (void *) hu->hdev; | ||
| 659 | break; | 658 | break; |
| 660 | } | 659 | } |
| 661 | break; | 660 | break; |
diff --git a/drivers/bluetooth/hci_h4.c b/drivers/bluetooth/hci_h4.c index 8ae9f1ea2bb5..7048a583fe51 100644 --- a/drivers/bluetooth/hci_h4.c +++ b/drivers/bluetooth/hci_h4.c | |||
| @@ -124,30 +124,6 @@ static int h4_enqueue(struct hci_uart *hu, struct sk_buff *skb) | |||
| 124 | return 0; | 124 | return 0; |
| 125 | } | 125 | } |
| 126 | 126 | ||
| 127 | static inline int h4_check_data_len(struct h4_struct *h4, int len) | ||
| 128 | { | ||
| 129 | int room = skb_tailroom(h4->rx_skb); | ||
| 130 | |||
| 131 | BT_DBG("len %d room %d", len, room); | ||
| 132 | |||
| 133 | if (!len) { | ||
| 134 | hci_recv_frame(h4->rx_skb); | ||
| 135 | } else if (len > room) { | ||
| 136 | BT_ERR("Data length is too large"); | ||
| 137 | kfree_skb(h4->rx_skb); | ||
| 138 | } else { | ||
| 139 | h4->rx_state = H4_W4_DATA; | ||
| 140 | h4->rx_count = len; | ||
| 141 | return len; | ||
| 142 | } | ||
| 143 | |||
| 144 | h4->rx_state = H4_W4_PACKET_TYPE; | ||
| 145 | h4->rx_skb = NULL; | ||
| 146 | h4->rx_count = 0; | ||
| 147 | |||
| 148 | return 0; | ||
| 149 | } | ||
| 150 | |||
| 151 | /* Recv data */ | 127 | /* Recv data */ |
| 152 | static int h4_recv(struct hci_uart *hu, void *data, int count) | 128 | static int h4_recv(struct hci_uart *hu, void *data, int count) |
| 153 | { | 129 | { |
diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c index b6154d5a07a5..f6f497450560 100644 --- a/drivers/bluetooth/hci_h5.c +++ b/drivers/bluetooth/hci_h5.c | |||
| @@ -340,7 +340,7 @@ static void h5_complete_rx_pkt(struct hci_uart *hu) | |||
| 340 | /* Remove Three-wire header */ | 340 | /* Remove Three-wire header */ |
| 341 | skb_pull(h5->rx_skb, 4); | 341 | skb_pull(h5->rx_skb, 4); |
| 342 | 342 | ||
| 343 | hci_recv_frame(h5->rx_skb); | 343 | hci_recv_frame(hu->hdev, h5->rx_skb); |
| 344 | h5->rx_skb = NULL; | 344 | h5->rx_skb = NULL; |
| 345 | 345 | ||
| 346 | break; | 346 | break; |
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index bc68a440d432..6e06f6f69152 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c | |||
| @@ -234,21 +234,13 @@ static int hci_uart_close(struct hci_dev *hdev) | |||
| 234 | } | 234 | } |
| 235 | 235 | ||
| 236 | /* Send frames from HCI layer */ | 236 | /* Send frames from HCI layer */ |
| 237 | static int hci_uart_send_frame(struct sk_buff *skb) | 237 | static int hci_uart_send_frame(struct hci_dev *hdev, struct sk_buff *skb) |
| 238 | { | 238 | { |
| 239 | struct hci_dev* hdev = (struct hci_dev *) skb->dev; | 239 | struct hci_uart *hu = hci_get_drvdata(hdev); |
| 240 | struct hci_uart *hu; | ||
| 241 | |||
| 242 | if (!hdev) { | ||
| 243 | BT_ERR("Frame for unknown device (hdev=NULL)"); | ||
| 244 | return -ENODEV; | ||
| 245 | } | ||
| 246 | 240 | ||
| 247 | if (!test_bit(HCI_RUNNING, &hdev->flags)) | 241 | if (!test_bit(HCI_RUNNING, &hdev->flags)) |
| 248 | return -EBUSY; | 242 | return -EBUSY; |
| 249 | 243 | ||
| 250 | hu = hci_get_drvdata(hdev); | ||
| 251 | |||
| 252 | BT_DBG("%s: type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len); | 244 | BT_DBG("%s: type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len); |
| 253 | 245 | ||
| 254 | hu->proto->enqueue(hu, skb); | 246 | hu->proto->enqueue(hu, skb); |
diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c index cfc767938589..69a90b1b5ff5 100644 --- a/drivers/bluetooth/hci_ll.c +++ b/drivers/bluetooth/hci_ll.c | |||
| @@ -110,7 +110,6 @@ static int send_hcill_cmd(u8 cmd, struct hci_uart *hu) | |||
| 110 | /* prepare packet */ | 110 | /* prepare packet */ |
| 111 | hcill_packet = (struct hcill_cmd *) skb_put(skb, 1); | 111 | hcill_packet = (struct hcill_cmd *) skb_put(skb, 1); |
| 112 | hcill_packet->cmd = cmd; | 112 | hcill_packet->cmd = cmd; |
| 113 | skb->dev = (void *) hu->hdev; | ||
| 114 | 113 | ||
| 115 | /* send packet */ | 114 | /* send packet */ |
| 116 | skb_queue_tail(&ll->txq, skb); | 115 | skb_queue_tail(&ll->txq, skb); |
| @@ -346,14 +345,14 @@ static int ll_enqueue(struct hci_uart *hu, struct sk_buff *skb) | |||
| 346 | return 0; | 345 | return 0; |
| 347 | } | 346 | } |
| 348 | 347 | ||
| 349 | static inline int ll_check_data_len(struct ll_struct *ll, int len) | 348 | static inline int ll_check_data_len(struct hci_dev *hdev, struct ll_struct *ll, int len) |
| 350 | { | 349 | { |
| 351 | int room = skb_tailroom(ll->rx_skb); | 350 | int room = skb_tailroom(ll->rx_skb); |
| 352 | 351 | ||
| 353 | BT_DBG("len %d room %d", len, room); | 352 | BT_DBG("len %d room %d", len, room); |
| 354 | 353 | ||
| 355 | if (!len) { | 354 | if (!len) { |
| 356 | hci_recv_frame(ll->rx_skb); | 355 | hci_recv_frame(hdev, ll->rx_skb); |
| 357 | } else if (len > room) { | 356 | } else if (len > room) { |
| 358 | BT_ERR("Data length is too large"); | 357 | BT_ERR("Data length is too large"); |
| 359 | kfree_skb(ll->rx_skb); | 358 | kfree_skb(ll->rx_skb); |
| @@ -395,7 +394,7 @@ static int ll_recv(struct hci_uart *hu, void *data, int count) | |||
| 395 | switch (ll->rx_state) { | 394 | switch (ll->rx_state) { |
| 396 | case HCILL_W4_DATA: | 395 | case HCILL_W4_DATA: |
| 397 | BT_DBG("Complete data"); | 396 | BT_DBG("Complete data"); |
| 398 | hci_recv_frame(ll->rx_skb); | 397 | hci_recv_frame(hu->hdev, ll->rx_skb); |
| 399 | 398 | ||
| 400 | ll->rx_state = HCILL_W4_PACKET_TYPE; | 399 | ll->rx_state = HCILL_W4_PACKET_TYPE; |
| 401 | ll->rx_skb = NULL; | 400 | ll->rx_skb = NULL; |
| @@ -406,7 +405,7 @@ static int ll_recv(struct hci_uart *hu, void *data, int count) | |||
| 406 | 405 | ||
| 407 | BT_DBG("Event header: evt 0x%2.2x plen %d", eh->evt, eh->plen); | 406 | BT_DBG("Event header: evt 0x%2.2x plen %d", eh->evt, eh->plen); |
| 408 | 407 | ||
| 409 | ll_check_data_len(ll, eh->plen); | 408 | ll_check_data_len(hu->hdev, ll, eh->plen); |
| 410 | continue; | 409 | continue; |
| 411 | 410 | ||
| 412 | case HCILL_W4_ACL_HDR: | 411 | case HCILL_W4_ACL_HDR: |
| @@ -415,7 +414,7 @@ static int ll_recv(struct hci_uart *hu, void *data, int count) | |||
| 415 | 414 | ||
| 416 | BT_DBG("ACL header: dlen %d", dlen); | 415 | BT_DBG("ACL header: dlen %d", dlen); |
| 417 | 416 | ||
| 418 | ll_check_data_len(ll, dlen); | 417 | ll_check_data_len(hu->hdev, ll, dlen); |
| 419 | continue; | 418 | continue; |
| 420 | 419 | ||
| 421 | case HCILL_W4_SCO_HDR: | 420 | case HCILL_W4_SCO_HDR: |
| @@ -423,7 +422,7 @@ static int ll_recv(struct hci_uart *hu, void *data, int count) | |||
| 423 | 422 | ||
| 424 | BT_DBG("SCO header: dlen %d", sh->dlen); | 423 | BT_DBG("SCO header: dlen %d", sh->dlen); |
| 425 | 424 | ||
| 426 | ll_check_data_len(ll, sh->dlen); | 425 | ll_check_data_len(hu->hdev, ll, sh->dlen); |
| 427 | continue; | 426 | continue; |
| 428 | } | 427 | } |
| 429 | } | 428 | } |
| @@ -494,7 +493,6 @@ static int ll_recv(struct hci_uart *hu, void *data, int count) | |||
| 494 | return -ENOMEM; | 493 | return -ENOMEM; |
| 495 | } | 494 | } |
| 496 | 495 | ||
| 497 | ll->rx_skb->dev = (void *) hu->hdev; | ||
| 498 | bt_cb(ll->rx_skb)->pkt_type = type; | 496 | bt_cb(ll->rx_skb)->pkt_type = type; |
| 499 | } | 497 | } |
| 500 | 498 | ||
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c index c04a3e6fb37c..7b167385a1c4 100644 --- a/drivers/bluetooth/hci_vhci.c +++ b/drivers/bluetooth/hci_vhci.c | |||
| @@ -81,21 +81,13 @@ static int vhci_flush(struct hci_dev *hdev) | |||
| 81 | return 0; | 81 | return 0; |
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | static int vhci_send_frame(struct sk_buff *skb) | 84 | static int vhci_send_frame(struct hci_dev *hdev, struct sk_buff *skb) |
| 85 | { | 85 | { |
| 86 | struct hci_dev* hdev = (struct hci_dev *) skb->dev; | 86 | struct vhci_data *data = hci_get_drvdata(hdev); |
| 87 | struct vhci_data *data; | ||
| 88 | |||
| 89 | if (!hdev) { | ||
| 90 | BT_ERR("Frame for unknown HCI device (hdev=NULL)"); | ||
| 91 | return -ENODEV; | ||
| 92 | } | ||
| 93 | 87 | ||
| 94 | if (!test_bit(HCI_RUNNING, &hdev->flags)) | 88 | if (!test_bit(HCI_RUNNING, &hdev->flags)) |
| 95 | return -EBUSY; | 89 | return -EBUSY; |
| 96 | 90 | ||
| 97 | data = hci_get_drvdata(hdev); | ||
| 98 | |||
| 99 | memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1); | 91 | memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1); |
| 100 | skb_queue_tail(&data->readq, skb); | 92 | skb_queue_tail(&data->readq, skb); |
| 101 | 93 | ||
| @@ -179,10 +171,9 @@ static inline ssize_t vhci_get_user(struct vhci_data *data, | |||
| 179 | return -ENODEV; | 171 | return -ENODEV; |
| 180 | } | 172 | } |
| 181 | 173 | ||
| 182 | skb->dev = (void *) data->hdev; | ||
| 183 | bt_cb(skb)->pkt_type = pkt_type; | 174 | bt_cb(skb)->pkt_type = pkt_type; |
| 184 | 175 | ||
| 185 | ret = hci_recv_frame(skb); | 176 | ret = hci_recv_frame(data->hdev, skb); |
| 186 | break; | 177 | break; |
| 187 | 178 | ||
| 188 | case HCI_VENDOR_PKT: | 179 | case HCI_VENDOR_PKT: |
diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig index ba81d6292eeb..c63d1159db5c 100644 --- a/drivers/net/wireless/ath/Kconfig +++ b/drivers/net/wireless/ath/Kconfig | |||
| @@ -25,6 +25,23 @@ config ATH_DEBUG | |||
| 25 | Say Y, if you want to debug atheros wireless drivers. | 25 | Say Y, if you want to debug atheros wireless drivers. |
| 26 | Right now only ath9k makes use of this. | 26 | Right now only ath9k makes use of this. |
| 27 | 27 | ||
| 28 | config ATH_REG_DYNAMIC_USER_REG_HINTS | ||
| 29 | bool "Atheros dynamic user regulatory hints" | ||
| 30 | depends on CFG80211_CERTIFICATION_ONUS | ||
| 31 | default n | ||
| 32 | ---help--- | ||
| 33 | Say N. This should only be enabled in countries where | ||
| 34 | this feature is explicitly allowed and only on cards that | ||
| 35 | specifically have been tested for this. | ||
| 36 | |||
| 37 | config ATH_REG_DYNAMIC_USER_CERT_TESTING | ||
| 38 | bool "Atheros dynamic user regulatory testing" | ||
| 39 | depends on ATH_REG_DYNAMIC_USER_REG_HINTS && CFG80211_CERTIFICATION_ONUS | ||
| 40 | default n | ||
| 41 | ---help--- | ||
| 42 | Say N. This should only be enabled on systems | ||
| 43 | undergoing certification testing. | ||
| 44 | |||
| 28 | source "drivers/net/wireless/ath/ath5k/Kconfig" | 45 | source "drivers/net/wireless/ath/ath5k/Kconfig" |
| 29 | source "drivers/net/wireless/ath/ath9k/Kconfig" | 46 | source "drivers/net/wireless/ath/ath9k/Kconfig" |
| 30 | source "drivers/net/wireless/ath/carl9170/Kconfig" | 47 | source "drivers/net/wireless/ath/carl9170/Kconfig" |
diff --git a/drivers/net/wireless/ath/Makefile b/drivers/net/wireless/ath/Makefile index 363b05653c7e..7d023b0f13b4 100644 --- a/drivers/net/wireless/ath/Makefile +++ b/drivers/net/wireless/ath/Makefile | |||
| @@ -12,7 +12,9 @@ obj-$(CONFIG_ATH_COMMON) += ath.o | |||
| 12 | ath-objs := main.o \ | 12 | ath-objs := main.o \ |
| 13 | regd.o \ | 13 | regd.o \ |
| 14 | hw.o \ | 14 | hw.o \ |
| 15 | key.o | 15 | key.o \ |
| 16 | dfs_pattern_detector.o \ | ||
| 17 | dfs_pri_detector.o | ||
| 16 | 18 | ||
| 17 | ath-$(CONFIG_ATH_DEBUG) += debug.o | 19 | ath-$(CONFIG_ATH_DEBUG) += debug.o |
| 18 | ccflags-y += -D__CHECK_ENDIAN__ | 20 | ccflags-y += -D__CHECK_ENDIAN__ |
diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index 834e29ea236c..e46951b8fb92 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c | |||
| @@ -283,7 +283,7 @@ static int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state, | |||
| 283 | 283 | ||
| 284 | if (unlikely(CE_RING_DELTA(nentries_mask, | 284 | if (unlikely(CE_RING_DELTA(nentries_mask, |
| 285 | write_index, sw_index - 1) <= 0)) { | 285 | write_index, sw_index - 1) <= 0)) { |
| 286 | ret = -EIO; | 286 | ret = -ENOSR; |
| 287 | goto exit; | 287 | goto exit; |
| 288 | } | 288 | } |
| 289 | 289 | ||
| @@ -338,38 +338,19 @@ int ath10k_ce_send(struct ath10k_ce_pipe *ce_state, | |||
| 338 | return ret; | 338 | return ret; |
| 339 | } | 339 | } |
| 340 | 340 | ||
| 341 | int ath10k_ce_sendlist_send(struct ath10k_ce_pipe *ce_state, | 341 | int ath10k_ce_num_free_src_entries(struct ath10k_ce_pipe *pipe) |
| 342 | void *per_transfer_context, | ||
| 343 | unsigned int transfer_id, | ||
| 344 | u32 paddr, unsigned int nbytes, | ||
| 345 | u32 flags) | ||
| 346 | { | 342 | { |
| 347 | struct ath10k_ce_ring *src_ring = ce_state->src_ring; | 343 | struct ath10k *ar = pipe->ar; |
| 348 | struct ath10k *ar = ce_state->ar; | ||
| 349 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 344 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
| 350 | unsigned int nentries_mask = src_ring->nentries_mask; | 345 | int delta; |
| 351 | unsigned int sw_index; | ||
| 352 | unsigned int write_index; | ||
| 353 | int delta, ret = -ENOMEM; | ||
| 354 | 346 | ||
| 355 | spin_lock_bh(&ar_pci->ce_lock); | 347 | spin_lock_bh(&ar_pci->ce_lock); |
| 356 | 348 | delta = CE_RING_DELTA(pipe->src_ring->nentries_mask, | |
| 357 | sw_index = src_ring->sw_index; | 349 | pipe->src_ring->write_index, |
| 358 | write_index = src_ring->write_index; | 350 | pipe->src_ring->sw_index - 1); |
| 359 | |||
| 360 | delta = CE_RING_DELTA(nentries_mask, write_index, sw_index - 1); | ||
| 361 | |||
| 362 | if (delta >= 1) { | ||
| 363 | ret = ath10k_ce_send_nolock(ce_state, per_transfer_context, | ||
| 364 | paddr, nbytes, | ||
| 365 | transfer_id, flags); | ||
| 366 | if (ret) | ||
| 367 | ath10k_warn("CE send failed: %d\n", ret); | ||
| 368 | } | ||
| 369 | |||
| 370 | spin_unlock_bh(&ar_pci->ce_lock); | 351 | spin_unlock_bh(&ar_pci->ce_lock); |
| 371 | 352 | ||
| 372 | return ret; | 353 | return delta; |
| 373 | } | 354 | } |
| 374 | 355 | ||
| 375 | int ath10k_ce_recv_buf_enqueue(struct ath10k_ce_pipe *ce_state, | 356 | int ath10k_ce_recv_buf_enqueue(struct ath10k_ce_pipe *ce_state, |
diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h index aec802868341..15d45b5b7615 100644 --- a/drivers/net/wireless/ath/ath10k/ce.h +++ b/drivers/net/wireless/ath/ath10k/ce.h | |||
| @@ -156,21 +156,7 @@ void ath10k_ce_send_cb_register(struct ath10k_ce_pipe *ce_state, | |||
| 156 | void (*send_cb)(struct ath10k_ce_pipe *), | 156 | void (*send_cb)(struct ath10k_ce_pipe *), |
| 157 | int disable_interrupts); | 157 | int disable_interrupts); |
| 158 | 158 | ||
| 159 | /* | 159 | int ath10k_ce_num_free_src_entries(struct ath10k_ce_pipe *pipe); |
| 160 | * Queue a "sendlist" of buffers to be sent using gather to a single | ||
| 161 | * anonymous destination buffer | ||
| 162 | * ce - which copy engine to use | ||
| 163 | * sendlist - list of simple buffers to send using gather | ||
| 164 | * transfer_id - arbitrary ID; reflected to destination | ||
| 165 | * Returns 0 on success; otherwise an error status. | ||
| 166 | * | ||
| 167 | * Implemenation note: Pushes multiple buffers with Gather to Source ring. | ||
| 168 | */ | ||
| 169 | int ath10k_ce_sendlist_send(struct ath10k_ce_pipe *ce_state, | ||
| 170 | void *per_transfer_context, | ||
| 171 | unsigned int transfer_id, | ||
| 172 | u32 paddr, unsigned int nbytes, | ||
| 173 | u32 flags); | ||
| 174 | 160 | ||
| 175 | /*==================Recv=======================*/ | 161 | /*==================Recv=======================*/ |
| 176 | 162 | ||
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 76906d5a082e..1129994fb105 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c | |||
| @@ -59,27 +59,6 @@ static void ath10k_send_suspend_complete(struct ath10k *ar) | |||
| 59 | wake_up(&ar->event_queue); | 59 | wake_up(&ar->event_queue); |
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | static int ath10k_check_fw_version(struct ath10k *ar) | ||
| 63 | { | ||
| 64 | char version[32]; | ||
| 65 | |||
| 66 | if (ar->fw_version_major >= SUPPORTED_FW_MAJOR && | ||
| 67 | ar->fw_version_minor >= SUPPORTED_FW_MINOR && | ||
| 68 | ar->fw_version_release >= SUPPORTED_FW_RELEASE && | ||
| 69 | ar->fw_version_build >= SUPPORTED_FW_BUILD) | ||
| 70 | return 0; | ||
| 71 | |||
| 72 | snprintf(version, sizeof(version), "%u.%u.%u.%u", | ||
| 73 | SUPPORTED_FW_MAJOR, SUPPORTED_FW_MINOR, | ||
| 74 | SUPPORTED_FW_RELEASE, SUPPORTED_FW_BUILD); | ||
| 75 | |||
| 76 | ath10k_warn("WARNING: Firmware version %s is not officially supported.\n", | ||
| 77 | ar->hw->wiphy->fw_version); | ||
| 78 | ath10k_warn("Please upgrade to version %s (or newer)\n", version); | ||
| 79 | |||
| 80 | return 0; | ||
| 81 | } | ||
| 82 | |||
| 83 | static int ath10k_init_connect_htc(struct ath10k *ar) | 62 | static int ath10k_init_connect_htc(struct ath10k *ar) |
| 84 | { | 63 | { |
| 85 | int status; | 64 | int status; |
| @@ -189,8 +168,7 @@ static const struct firmware *ath10k_fetch_fw_file(struct ath10k *ar, | |||
| 189 | return fw; | 168 | return fw; |
| 190 | } | 169 | } |
| 191 | 170 | ||
| 192 | static int ath10k_push_board_ext_data(struct ath10k *ar, | 171 | static int ath10k_push_board_ext_data(struct ath10k *ar) |
| 193 | const struct firmware *fw) | ||
| 194 | { | 172 | { |
| 195 | u32 board_data_size = QCA988X_BOARD_DATA_SZ; | 173 | u32 board_data_size = QCA988X_BOARD_DATA_SZ; |
| 196 | u32 board_ext_data_size = QCA988X_BOARD_EXT_DATA_SZ; | 174 | u32 board_ext_data_size = QCA988X_BOARD_EXT_DATA_SZ; |
| @@ -210,14 +188,14 @@ static int ath10k_push_board_ext_data(struct ath10k *ar, | |||
| 210 | if (board_ext_data_addr == 0) | 188 | if (board_ext_data_addr == 0) |
| 211 | return 0; | 189 | return 0; |
| 212 | 190 | ||
| 213 | if (fw->size != (board_data_size + board_ext_data_size)) { | 191 | if (ar->board_len != (board_data_size + board_ext_data_size)) { |
| 214 | ath10k_err("invalid board (ext) data sizes %zu != %d+%d\n", | 192 | ath10k_err("invalid board (ext) data sizes %zu != %d+%d\n", |
| 215 | fw->size, board_data_size, board_ext_data_size); | 193 | ar->board_len, board_data_size, board_ext_data_size); |
| 216 | return -EINVAL; | 194 | return -EINVAL; |
| 217 | } | 195 | } |
| 218 | 196 | ||
| 219 | ret = ath10k_bmi_write_memory(ar, board_ext_data_addr, | 197 | ret = ath10k_bmi_write_memory(ar, board_ext_data_addr, |
| 220 | fw->data + board_data_size, | 198 | ar->board_data + board_data_size, |
| 221 | board_ext_data_size); | 199 | board_ext_data_size); |
| 222 | if (ret) { | 200 | if (ret) { |
| 223 | ath10k_err("could not write board ext data (%d)\n", ret); | 201 | ath10k_err("could not write board ext data (%d)\n", ret); |
| @@ -236,12 +214,11 @@ static int ath10k_push_board_ext_data(struct ath10k *ar, | |||
| 236 | 214 | ||
| 237 | static int ath10k_download_board_data(struct ath10k *ar) | 215 | static int ath10k_download_board_data(struct ath10k *ar) |
| 238 | { | 216 | { |
| 239 | const struct firmware *fw = ar->board_data; | ||
| 240 | u32 board_data_size = QCA988X_BOARD_DATA_SZ; | 217 | u32 board_data_size = QCA988X_BOARD_DATA_SZ; |
| 241 | u32 address; | 218 | u32 address; |
| 242 | int ret; | 219 | int ret; |
| 243 | 220 | ||
| 244 | ret = ath10k_push_board_ext_data(ar, fw); | 221 | ret = ath10k_push_board_ext_data(ar); |
| 245 | if (ret) { | 222 | if (ret) { |
| 246 | ath10k_err("could not push board ext data (%d)\n", ret); | 223 | ath10k_err("could not push board ext data (%d)\n", ret); |
| 247 | goto exit; | 224 | goto exit; |
| @@ -253,8 +230,9 @@ static int ath10k_download_board_data(struct ath10k *ar) | |||
| 253 | goto exit; | 230 | goto exit; |
| 254 | } | 231 | } |
| 255 | 232 | ||
| 256 | ret = ath10k_bmi_write_memory(ar, address, fw->data, | 233 | ret = ath10k_bmi_write_memory(ar, address, ar->board_data, |
| 257 | min_t(u32, board_data_size, fw->size)); | 234 | min_t(u32, board_data_size, |
| 235 | ar->board_len)); | ||
| 258 | if (ret) { | 236 | if (ret) { |
| 259 | ath10k_err("could not write board data (%d)\n", ret); | 237 | ath10k_err("could not write board data (%d)\n", ret); |
| 260 | goto exit; | 238 | goto exit; |
| @@ -272,17 +250,16 @@ exit: | |||
| 272 | 250 | ||
| 273 | static int ath10k_download_and_run_otp(struct ath10k *ar) | 251 | static int ath10k_download_and_run_otp(struct ath10k *ar) |
| 274 | { | 252 | { |
| 275 | const struct firmware *fw = ar->otp; | ||
| 276 | u32 address = ar->hw_params.patch_load_addr; | 253 | u32 address = ar->hw_params.patch_load_addr; |
| 277 | u32 exec_param; | 254 | u32 exec_param; |
| 278 | int ret; | 255 | int ret; |
| 279 | 256 | ||
| 280 | /* OTP is optional */ | 257 | /* OTP is optional */ |
| 281 | 258 | ||
| 282 | if (!ar->otp) | 259 | if (!ar->otp_data || !ar->otp_len) |
| 283 | return 0; | 260 | return 0; |
| 284 | 261 | ||
| 285 | ret = ath10k_bmi_fast_download(ar, address, fw->data, fw->size); | 262 | ret = ath10k_bmi_fast_download(ar, address, ar->otp_data, ar->otp_len); |
| 286 | if (ret) { | 263 | if (ret) { |
| 287 | ath10k_err("could not write otp (%d)\n", ret); | 264 | ath10k_err("could not write otp (%d)\n", ret); |
| 288 | goto exit; | 265 | goto exit; |
| @@ -301,13 +278,13 @@ exit: | |||
| 301 | 278 | ||
| 302 | static int ath10k_download_fw(struct ath10k *ar) | 279 | static int ath10k_download_fw(struct ath10k *ar) |
| 303 | { | 280 | { |
| 304 | const struct firmware *fw = ar->firmware; | ||
| 305 | u32 address; | 281 | u32 address; |
| 306 | int ret; | 282 | int ret; |
| 307 | 283 | ||
| 308 | address = ar->hw_params.patch_load_addr; | 284 | address = ar->hw_params.patch_load_addr; |
| 309 | 285 | ||
| 310 | ret = ath10k_bmi_fast_download(ar, address, fw->data, fw->size); | 286 | ret = ath10k_bmi_fast_download(ar, address, ar->firmware_data, |
| 287 | ar->firmware_len); | ||
| 311 | if (ret) { | 288 | if (ret) { |
| 312 | ath10k_err("could not write fw (%d)\n", ret); | 289 | ath10k_err("could not write fw (%d)\n", ret); |
| 313 | goto exit; | 290 | goto exit; |
| @@ -319,8 +296,8 @@ exit: | |||
| 319 | 296 | ||
| 320 | static void ath10k_core_free_firmware_files(struct ath10k *ar) | 297 | static void ath10k_core_free_firmware_files(struct ath10k *ar) |
| 321 | { | 298 | { |
| 322 | if (ar->board_data && !IS_ERR(ar->board_data)) | 299 | if (ar->board && !IS_ERR(ar->board)) |
| 323 | release_firmware(ar->board_data); | 300 | release_firmware(ar->board); |
| 324 | 301 | ||
| 325 | if (ar->otp && !IS_ERR(ar->otp)) | 302 | if (ar->otp && !IS_ERR(ar->otp)) |
| 326 | release_firmware(ar->otp); | 303 | release_firmware(ar->otp); |
| @@ -328,12 +305,20 @@ static void ath10k_core_free_firmware_files(struct ath10k *ar) | |||
| 328 | if (ar->firmware && !IS_ERR(ar->firmware)) | 305 | if (ar->firmware && !IS_ERR(ar->firmware)) |
| 329 | release_firmware(ar->firmware); | 306 | release_firmware(ar->firmware); |
| 330 | 307 | ||
| 308 | ar->board = NULL; | ||
| 331 | ar->board_data = NULL; | 309 | ar->board_data = NULL; |
| 310 | ar->board_len = 0; | ||
| 311 | |||
| 332 | ar->otp = NULL; | 312 | ar->otp = NULL; |
| 313 | ar->otp_data = NULL; | ||
| 314 | ar->otp_len = 0; | ||
| 315 | |||
| 333 | ar->firmware = NULL; | 316 | ar->firmware = NULL; |
| 317 | ar->firmware_data = NULL; | ||
| 318 | ar->firmware_len = 0; | ||
| 334 | } | 319 | } |
| 335 | 320 | ||
| 336 | static int ath10k_core_fetch_firmware_files(struct ath10k *ar) | 321 | static int ath10k_core_fetch_firmware_api_1(struct ath10k *ar) |
| 337 | { | 322 | { |
| 338 | int ret = 0; | 323 | int ret = 0; |
| 339 | 324 | ||
| @@ -347,15 +332,18 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar) | |||
| 347 | return -EINVAL; | 332 | return -EINVAL; |
| 348 | } | 333 | } |
| 349 | 334 | ||
| 350 | ar->board_data = ath10k_fetch_fw_file(ar, | 335 | ar->board = ath10k_fetch_fw_file(ar, |
| 351 | ar->hw_params.fw.dir, | 336 | ar->hw_params.fw.dir, |
| 352 | ar->hw_params.fw.board); | 337 | ar->hw_params.fw.board); |
| 353 | if (IS_ERR(ar->board_data)) { | 338 | if (IS_ERR(ar->board)) { |
| 354 | ret = PTR_ERR(ar->board_data); | 339 | ret = PTR_ERR(ar->board); |
| 355 | ath10k_err("could not fetch board data (%d)\n", ret); | 340 | ath10k_err("could not fetch board data (%d)\n", ret); |
| 356 | goto err; | 341 | goto err; |
| 357 | } | 342 | } |
| 358 | 343 | ||
| 344 | ar->board_data = ar->board->data; | ||
| 345 | ar->board_len = ar->board->size; | ||
| 346 | |||
| 359 | ar->firmware = ath10k_fetch_fw_file(ar, | 347 | ar->firmware = ath10k_fetch_fw_file(ar, |
| 360 | ar->hw_params.fw.dir, | 348 | ar->hw_params.fw.dir, |
| 361 | ar->hw_params.fw.fw); | 349 | ar->hw_params.fw.fw); |
| @@ -365,6 +353,9 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar) | |||
| 365 | goto err; | 353 | goto err; |
| 366 | } | 354 | } |
| 367 | 355 | ||
| 356 | ar->firmware_data = ar->firmware->data; | ||
| 357 | ar->firmware_len = ar->firmware->size; | ||
| 358 | |||
| 368 | /* OTP may be undefined. If so, don't fetch it at all */ | 359 | /* OTP may be undefined. If so, don't fetch it at all */ |
| 369 | if (ar->hw_params.fw.otp == NULL) | 360 | if (ar->hw_params.fw.otp == NULL) |
| 370 | return 0; | 361 | return 0; |
| @@ -378,6 +369,9 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar) | |||
| 378 | goto err; | 369 | goto err; |
| 379 | } | 370 | } |
| 380 | 371 | ||
| 372 | ar->otp_data = ar->otp->data; | ||
| 373 | ar->otp_len = ar->otp->size; | ||
| 374 | |||
| 381 | return 0; | 375 | return 0; |
| 382 | 376 | ||
| 383 | err: | 377 | err: |
| @@ -385,6 +379,191 @@ err: | |||
| 385 | return ret; | 379 | return ret; |
| 386 | } | 380 | } |
| 387 | 381 | ||
| 382 | static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name) | ||
| 383 | { | ||
| 384 | size_t magic_len, len, ie_len; | ||
| 385 | int ie_id, i, index, bit, ret; | ||
| 386 | struct ath10k_fw_ie *hdr; | ||
| 387 | const u8 *data; | ||
| 388 | __le32 *timestamp; | ||
| 389 | |||
| 390 | /* first fetch the firmware file (firmware-*.bin) */ | ||
| 391 | ar->firmware = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir, name); | ||
| 392 | if (IS_ERR(ar->firmware)) { | ||
| 393 | ath10k_err("Could not fetch firmware file '%s': %ld\n", | ||
| 394 | name, PTR_ERR(ar->firmware)); | ||
| 395 | return PTR_ERR(ar->firmware); | ||
| 396 | } | ||
| 397 | |||
| 398 | data = ar->firmware->data; | ||
| 399 | len = ar->firmware->size; | ||
| 400 | |||
| 401 | /* magic also includes the null byte, check that as well */ | ||
| 402 | magic_len = strlen(ATH10K_FIRMWARE_MAGIC) + 1; | ||
| 403 | |||
| 404 | if (len < magic_len) { | ||
| 405 | ath10k_err("firmware image too small to contain magic: %zu\n", | ||
| 406 | len); | ||
| 407 | ret = -EINVAL; | ||
| 408 | goto err; | ||
| 409 | } | ||
| 410 | |||
| 411 | if (memcmp(data, ATH10K_FIRMWARE_MAGIC, magic_len) != 0) { | ||
| 412 | ath10k_err("Invalid firmware magic\n"); | ||
| 413 | ret = -EINVAL; | ||
| 414 | goto err; | ||
| 415 | } | ||
| 416 | |||
| 417 | /* jump over the padding */ | ||
| 418 | magic_len = ALIGN(magic_len, 4); | ||
| 419 | |||
| 420 | len -= magic_len; | ||
| 421 | data += magic_len; | ||
| 422 | |||
| 423 | /* loop elements */ | ||
| 424 | while (len > sizeof(struct ath10k_fw_ie)) { | ||
| 425 | hdr = (struct ath10k_fw_ie *)data; | ||
| 426 | |||
| 427 | ie_id = le32_to_cpu(hdr->id); | ||
| 428 | ie_len = le32_to_cpu(hdr->len); | ||
| 429 | |||
| 430 | len -= sizeof(*hdr); | ||
| 431 | data += sizeof(*hdr); | ||
| 432 | |||
| 433 | if (len < ie_len) { | ||
| 434 | ath10k_err("Invalid length for FW IE %d (%zu < %zu)\n", | ||
| 435 | ie_id, len, ie_len); | ||
| 436 | ret = -EINVAL; | ||
| 437 | goto err; | ||
| 438 | } | ||
| 439 | |||
| 440 | switch (ie_id) { | ||
| 441 | case ATH10K_FW_IE_FW_VERSION: | ||
| 442 | if (ie_len > sizeof(ar->hw->wiphy->fw_version) - 1) | ||
| 443 | break; | ||
| 444 | |||
| 445 | memcpy(ar->hw->wiphy->fw_version, data, ie_len); | ||
| 446 | ar->hw->wiphy->fw_version[ie_len] = '\0'; | ||
| 447 | |||
| 448 | ath10k_dbg(ATH10K_DBG_BOOT, | ||
| 449 | "found fw version %s\n", | ||
| 450 | ar->hw->wiphy->fw_version); | ||
| 451 | break; | ||
| 452 | case ATH10K_FW_IE_TIMESTAMP: | ||
| 453 | if (ie_len != sizeof(u32)) | ||
| 454 | break; | ||
| 455 | |||
| 456 | timestamp = (__le32 *)data; | ||
| 457 | |||
| 458 | ath10k_dbg(ATH10K_DBG_BOOT, "found fw timestamp %d\n", | ||
| 459 | le32_to_cpup(timestamp)); | ||
| 460 | break; | ||
| 461 | case ATH10K_FW_IE_FEATURES: | ||
| 462 | ath10k_dbg(ATH10K_DBG_BOOT, | ||
| 463 | "found firmware features ie (%zd B)\n", | ||
| 464 | ie_len); | ||
| 465 | |||
| 466 | for (i = 0; i < ATH10K_FW_FEATURE_COUNT; i++) { | ||
| 467 | index = i / 8; | ||
| 468 | bit = i % 8; | ||
| 469 | |||
| 470 | if (index == ie_len) | ||
| 471 | break; | ||
| 472 | |||
| 473 | if (data[index] & (1 << bit)) | ||
| 474 | __set_bit(i, ar->fw_features); | ||
| 475 | } | ||
| 476 | |||
| 477 | ath10k_dbg_dump(ATH10K_DBG_BOOT, "features", "", | ||
| 478 | ar->fw_features, | ||
| 479 | sizeof(ar->fw_features)); | ||
| 480 | break; | ||
| 481 | case ATH10K_FW_IE_FW_IMAGE: | ||
| 482 | ath10k_dbg(ATH10K_DBG_BOOT, | ||
| 483 | "found fw image ie (%zd B)\n", | ||
| 484 | ie_len); | ||
| 485 | |||
| 486 | ar->firmware_data = data; | ||
| 487 | ar->firmware_len = ie_len; | ||
| 488 | |||
| 489 | break; | ||
| 490 | case ATH10K_FW_IE_OTP_IMAGE: | ||
| 491 | ath10k_dbg(ATH10K_DBG_BOOT, | ||
| 492 | "found otp image ie (%zd B)\n", | ||
| 493 | ie_len); | ||
| 494 | |||
| 495 | ar->otp_data = data; | ||
| 496 | ar->otp_len = ie_len; | ||
| 497 | |||
| 498 | break; | ||
| 499 | default: | ||
| 500 | ath10k_warn("Unknown FW IE: %u\n", | ||
| 501 | le32_to_cpu(hdr->id)); | ||
| 502 | break; | ||
| 503 | } | ||
| 504 | |||
| 505 | /* jump over the padding */ | ||
| 506 | ie_len = ALIGN(ie_len, 4); | ||
| 507 | |||
| 508 | len -= ie_len; | ||
| 509 | data += ie_len; | ||
| 510 | } | ||
| 511 | |||
| 512 | if (!ar->firmware_data || !ar->firmware_len) { | ||
| 513 | ath10k_warn("No ATH10K_FW_IE_FW_IMAGE found from %s, skipping\n", | ||
| 514 | name); | ||
| 515 | ret = -ENOMEDIUM; | ||
| 516 | goto err; | ||
| 517 | } | ||
| 518 | |||
| 519 | /* now fetch the board file */ | ||
| 520 | if (ar->hw_params.fw.board == NULL) { | ||
| 521 | ath10k_err("board data file not defined"); | ||
| 522 | ret = -EINVAL; | ||
| 523 | goto err; | ||
| 524 | } | ||
| 525 | |||
| 526 | ar->board = ath10k_fetch_fw_file(ar, | ||
| 527 | ar->hw_params.fw.dir, | ||
| 528 | ar->hw_params.fw.board); | ||
| 529 | if (IS_ERR(ar->board)) { | ||
| 530 | ret = PTR_ERR(ar->board); | ||
| 531 | ath10k_err("could not fetch board data (%d)\n", ret); | ||
| 532 | goto err; | ||
| 533 | } | ||
| 534 | |||
| 535 | ar->board_data = ar->board->data; | ||
| 536 | ar->board_len = ar->board->size; | ||
| 537 | |||
| 538 | return 0; | ||
| 539 | |||
| 540 | err: | ||
| 541 | ath10k_core_free_firmware_files(ar); | ||
| 542 | return ret; | ||
| 543 | } | ||
| 544 | |||
| 545 | static int ath10k_core_fetch_firmware_files(struct ath10k *ar) | ||
| 546 | { | ||
| 547 | int ret; | ||
| 548 | |||
| 549 | ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API2_FILE); | ||
| 550 | if (ret == 0) { | ||
| 551 | ar->fw_api = 2; | ||
| 552 | goto out; | ||
| 553 | } | ||
| 554 | |||
| 555 | ret = ath10k_core_fetch_firmware_api_1(ar); | ||
| 556 | if (ret) | ||
| 557 | return ret; | ||
| 558 | |||
| 559 | ar->fw_api = 1; | ||
| 560 | |||
| 561 | out: | ||
| 562 | ath10k_dbg(ATH10K_DBG_BOOT, "using fw api %d\n", ar->fw_api); | ||
| 563 | |||
| 564 | return 0; | ||
| 565 | } | ||
| 566 | |||
| 388 | static int ath10k_init_download_firmware(struct ath10k *ar) | 567 | static int ath10k_init_download_firmware(struct ath10k *ar) |
| 389 | { | 568 | { |
| 390 | int ret; | 569 | int ret; |
| @@ -541,6 +720,9 @@ struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev, | |||
| 541 | INIT_WORK(&ar->offchan_tx_work, ath10k_offchan_tx_work); | 720 | INIT_WORK(&ar->offchan_tx_work, ath10k_offchan_tx_work); |
| 542 | skb_queue_head_init(&ar->offchan_tx_queue); | 721 | skb_queue_head_init(&ar->offchan_tx_queue); |
| 543 | 722 | ||
| 723 | INIT_WORK(&ar->wmi_mgmt_tx_work, ath10k_mgmt_over_wmi_tx_work); | ||
| 724 | skb_queue_head_init(&ar->wmi_mgmt_tx_queue); | ||
| 725 | |||
| 544 | init_waitqueue_head(&ar->event_queue); | 726 | init_waitqueue_head(&ar->event_queue); |
| 545 | 727 | ||
| 546 | INIT_WORK(&ar->restart_work, ath10k_core_restart); | 728 | INIT_WORK(&ar->restart_work, ath10k_core_restart); |
| @@ -555,6 +737,8 @@ EXPORT_SYMBOL(ath10k_core_create); | |||
| 555 | 737 | ||
| 556 | void ath10k_core_destroy(struct ath10k *ar) | 738 | void ath10k_core_destroy(struct ath10k *ar) |
| 557 | { | 739 | { |
| 740 | ath10k_debug_destroy(ar); | ||
| 741 | |||
| 558 | flush_workqueue(ar->workqueue); | 742 | flush_workqueue(ar->workqueue); |
| 559 | destroy_workqueue(ar->workqueue); | 743 | destroy_workqueue(ar->workqueue); |
| 560 | 744 | ||
| @@ -566,6 +750,8 @@ int ath10k_core_start(struct ath10k *ar) | |||
| 566 | { | 750 | { |
| 567 | int status; | 751 | int status; |
| 568 | 752 | ||
| 753 | lockdep_assert_held(&ar->conf_mutex); | ||
| 754 | |||
| 569 | ath10k_bmi_start(ar); | 755 | ath10k_bmi_start(ar); |
| 570 | 756 | ||
| 571 | if (ath10k_init_configure_target(ar)) { | 757 | if (ath10k_init_configure_target(ar)) { |
| @@ -616,10 +802,6 @@ int ath10k_core_start(struct ath10k *ar) | |||
| 616 | 802 | ||
| 617 | ath10k_info("firmware %s booted\n", ar->hw->wiphy->fw_version); | 803 | ath10k_info("firmware %s booted\n", ar->hw->wiphy->fw_version); |
| 618 | 804 | ||
| 619 | status = ath10k_check_fw_version(ar); | ||
| 620 | if (status) | ||
| 621 | goto err_disconnect_htc; | ||
| 622 | |||
| 623 | status = ath10k_wmi_cmd_init(ar); | 805 | status = ath10k_wmi_cmd_init(ar); |
| 624 | if (status) { | 806 | if (status) { |
| 625 | ath10k_err("could not send WMI init command (%d)\n", status); | 807 | ath10k_err("could not send WMI init command (%d)\n", status); |
| @@ -642,6 +824,7 @@ int ath10k_core_start(struct ath10k *ar) | |||
| 642 | goto err_disconnect_htc; | 824 | goto err_disconnect_htc; |
| 643 | 825 | ||
| 644 | ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1; | 826 | ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1; |
| 827 | INIT_LIST_HEAD(&ar->arvifs); | ||
| 645 | 828 | ||
| 646 | return 0; | 829 | return 0; |
| 647 | 830 | ||
| @@ -658,6 +841,8 @@ EXPORT_SYMBOL(ath10k_core_start); | |||
| 658 | 841 | ||
| 659 | void ath10k_core_stop(struct ath10k *ar) | 842 | void ath10k_core_stop(struct ath10k *ar) |
| 660 | { | 843 | { |
| 844 | lockdep_assert_held(&ar->conf_mutex); | ||
| 845 | |||
| 661 | ath10k_debug_stop(ar); | 846 | ath10k_debug_stop(ar); |
| 662 | ath10k_htc_stop(&ar->htc); | 847 | ath10k_htc_stop(&ar->htc); |
| 663 | ath10k_htt_detach(&ar->htt); | 848 | ath10k_htt_detach(&ar->htt); |
| @@ -705,15 +890,21 @@ static int ath10k_core_probe_fw(struct ath10k *ar) | |||
| 705 | return ret; | 890 | return ret; |
| 706 | } | 891 | } |
| 707 | 892 | ||
| 893 | mutex_lock(&ar->conf_mutex); | ||
| 894 | |||
| 708 | ret = ath10k_core_start(ar); | 895 | ret = ath10k_core_start(ar); |
| 709 | if (ret) { | 896 | if (ret) { |
| 710 | ath10k_err("could not init core (%d)\n", ret); | 897 | ath10k_err("could not init core (%d)\n", ret); |
| 711 | ath10k_core_free_firmware_files(ar); | 898 | ath10k_core_free_firmware_files(ar); |
| 712 | ath10k_hif_power_down(ar); | 899 | ath10k_hif_power_down(ar); |
| 900 | mutex_unlock(&ar->conf_mutex); | ||
| 713 | return ret; | 901 | return ret; |
| 714 | } | 902 | } |
| 715 | 903 | ||
| 716 | ath10k_core_stop(ar); | 904 | ath10k_core_stop(ar); |
| 905 | |||
| 906 | mutex_unlock(&ar->conf_mutex); | ||
| 907 | |||
| 717 | ath10k_hif_power_down(ar); | 908 | ath10k_hif_power_down(ar); |
| 718 | return 0; | 909 | return 0; |
| 719 | } | 910 | } |
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 292ad4577c98..0934f7633de3 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h | |||
| @@ -43,15 +43,17 @@ | |||
| 43 | /* Antenna noise floor */ | 43 | /* Antenna noise floor */ |
| 44 | #define ATH10K_DEFAULT_NOISE_FLOOR -95 | 44 | #define ATH10K_DEFAULT_NOISE_FLOOR -95 |
| 45 | 45 | ||
| 46 | #define ATH10K_MAX_NUM_MGMT_PENDING 16 | ||
| 47 | |||
| 46 | struct ath10k; | 48 | struct ath10k; |
| 47 | 49 | ||
| 48 | struct ath10k_skb_cb { | 50 | struct ath10k_skb_cb { |
| 49 | dma_addr_t paddr; | 51 | dma_addr_t paddr; |
| 50 | bool is_mapped; | 52 | bool is_mapped; |
| 51 | bool is_aborted; | 53 | bool is_aborted; |
| 54 | u8 vdev_id; | ||
| 52 | 55 | ||
| 53 | struct { | 56 | struct { |
| 54 | u8 vdev_id; | ||
| 55 | u8 tid; | 57 | u8 tid; |
| 56 | bool is_offchan; | 58 | bool is_offchan; |
| 57 | 59 | ||
| @@ -102,11 +104,26 @@ struct ath10k_bmi { | |||
| 102 | bool done_sent; | 104 | bool done_sent; |
| 103 | }; | 105 | }; |
| 104 | 106 | ||
| 107 | #define ATH10K_MAX_MEM_REQS 16 | ||
| 108 | |||
| 109 | struct ath10k_mem_chunk { | ||
| 110 | void *vaddr; | ||
| 111 | dma_addr_t paddr; | ||
| 112 | u32 len; | ||
| 113 | u32 req_id; | ||
| 114 | }; | ||
| 115 | |||
| 105 | struct ath10k_wmi { | 116 | struct ath10k_wmi { |
| 106 | enum ath10k_htc_ep_id eid; | 117 | enum ath10k_htc_ep_id eid; |
| 107 | struct completion service_ready; | 118 | struct completion service_ready; |
| 108 | struct completion unified_ready; | 119 | struct completion unified_ready; |
| 109 | wait_queue_head_t tx_credits_wq; | 120 | wait_queue_head_t tx_credits_wq; |
| 121 | struct wmi_cmd_map *cmd; | ||
| 122 | struct wmi_vdev_param_map *vdev_param; | ||
| 123 | struct wmi_pdev_param_map *pdev_param; | ||
| 124 | |||
| 125 | u32 num_mem_chunks; | ||
| 126 | struct ath10k_mem_chunk mem_chunks[ATH10K_MAX_MEM_REQS]; | ||
| 110 | }; | 127 | }; |
| 111 | 128 | ||
| 112 | struct ath10k_peer_stat { | 129 | struct ath10k_peer_stat { |
| @@ -188,6 +205,8 @@ struct ath10k_peer { | |||
| 188 | #define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5*HZ) | 205 | #define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5*HZ) |
| 189 | 206 | ||
| 190 | struct ath10k_vif { | 207 | struct ath10k_vif { |
| 208 | struct list_head list; | ||
| 209 | |||
| 191 | u32 vdev_id; | 210 | u32 vdev_id; |
| 192 | enum wmi_vdev_type vdev_type; | 211 | enum wmi_vdev_type vdev_type; |
| 193 | enum wmi_vdev_subtype vdev_subtype; | 212 | enum wmi_vdev_subtype vdev_subtype; |
| @@ -198,8 +217,10 @@ struct ath10k_vif { | |||
| 198 | struct ath10k *ar; | 217 | struct ath10k *ar; |
| 199 | struct ieee80211_vif *vif; | 218 | struct ieee80211_vif *vif; |
| 200 | 219 | ||
| 220 | struct work_struct wep_key_work; | ||
| 201 | struct ieee80211_key_conf *wep_keys[WMI_MAX_KEY_INDEX + 1]; | 221 | struct ieee80211_key_conf *wep_keys[WMI_MAX_KEY_INDEX + 1]; |
| 202 | u8 def_wep_key_index; | 222 | u8 def_wep_key_idx; |
| 223 | u8 def_wep_key_newidx; | ||
| 203 | 224 | ||
| 204 | u16 tx_seq_no; | 225 | u16 tx_seq_no; |
| 205 | 226 | ||
| @@ -268,6 +289,12 @@ enum ath10k_fw_features { | |||
| 268 | /* wmi_mgmt_rx_hdr contains extra RSSI information */ | 289 | /* wmi_mgmt_rx_hdr contains extra RSSI information */ |
| 269 | ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX = 0, | 290 | ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX = 0, |
| 270 | 291 | ||
| 292 | /* firmware from 10X branch */ | ||
| 293 | ATH10K_FW_FEATURE_WMI_10X = 1, | ||
| 294 | |||
| 295 | /* firmware support tx frame management over WMI, otherwise it's HTT */ | ||
| 296 | ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX = 2, | ||
| 297 | |||
| 271 | /* keep last */ | 298 | /* keep last */ |
| 272 | ATH10K_FW_FEATURE_COUNT, | 299 | ATH10K_FW_FEATURE_COUNT, |
| 273 | }; | 300 | }; |
| @@ -324,9 +351,19 @@ struct ath10k { | |||
| 324 | } fw; | 351 | } fw; |
| 325 | } hw_params; | 352 | } hw_params; |
| 326 | 353 | ||
| 327 | const struct firmware *board_data; | 354 | const struct firmware *board; |
| 355 | const void *board_data; | ||
| 356 | size_t board_len; | ||
| 357 | |||
| 328 | const struct firmware *otp; | 358 | const struct firmware *otp; |
| 359 | const void *otp_data; | ||
| 360 | size_t otp_len; | ||
| 361 | |||
| 329 | const struct firmware *firmware; | 362 | const struct firmware *firmware; |
| 363 | const void *firmware_data; | ||
| 364 | size_t firmware_len; | ||
| 365 | |||
| 366 | int fw_api; | ||
| 330 | 367 | ||
| 331 | struct { | 368 | struct { |
| 332 | struct completion started; | 369 | struct completion started; |
| @@ -369,6 +406,7 @@ struct ath10k { | |||
| 369 | /* protects shared structure data */ | 406 | /* protects shared structure data */ |
| 370 | spinlock_t data_lock; | 407 | spinlock_t data_lock; |
| 371 | 408 | ||
| 409 | struct list_head arvifs; | ||
| 372 | struct list_head peers; | 410 | struct list_head peers; |
| 373 | wait_queue_head_t peer_mapping_wq; | 411 | wait_queue_head_t peer_mapping_wq; |
| 374 | 412 | ||
| @@ -377,6 +415,9 @@ struct ath10k { | |||
| 377 | struct completion offchan_tx_completed; | 415 | struct completion offchan_tx_completed; |
| 378 | struct sk_buff *offchan_tx_skb; | 416 | struct sk_buff *offchan_tx_skb; |
| 379 | 417 | ||
| 418 | struct work_struct wmi_mgmt_tx_work; | ||
| 419 | struct sk_buff_head wmi_mgmt_tx_queue; | ||
| 420 | |||
| 380 | enum ath10k_state state; | 421 | enum ath10k_state state; |
| 381 | 422 | ||
| 382 | struct work_struct restart_work; | 423 | struct work_struct restart_work; |
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 59615c7f217e..760ff2289e3c 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c | |||
| @@ -618,6 +618,8 @@ int ath10k_debug_start(struct ath10k *ar) | |||
| 618 | { | 618 | { |
| 619 | int ret; | 619 | int ret; |
| 620 | 620 | ||
| 621 | lockdep_assert_held(&ar->conf_mutex); | ||
| 622 | |||
| 621 | ret = ath10k_debug_htt_stats_req(ar); | 623 | ret = ath10k_debug_htt_stats_req(ar); |
| 622 | if (ret) | 624 | if (ret) |
| 623 | /* continue normally anyway, this isn't serious */ | 625 | /* continue normally anyway, this isn't serious */ |
| @@ -628,7 +630,13 @@ int ath10k_debug_start(struct ath10k *ar) | |||
| 628 | 630 | ||
| 629 | void ath10k_debug_stop(struct ath10k *ar) | 631 | void ath10k_debug_stop(struct ath10k *ar) |
| 630 | { | 632 | { |
| 631 | cancel_delayed_work_sync(&ar->debug.htt_stats_dwork); | 633 | lockdep_assert_held(&ar->conf_mutex); |
| 634 | |||
| 635 | /* Must not use _sync to avoid deadlock, we do that in | ||
| 636 | * ath10k_debug_destroy(). The check for htt_stats_mask is to avoid | ||
| 637 | * warning from del_timer(). */ | ||
| 638 | if (ar->debug.htt_stats_mask != 0) | ||
| 639 | cancel_delayed_work(&ar->debug.htt_stats_dwork); | ||
| 632 | } | 640 | } |
| 633 | 641 | ||
| 634 | int ath10k_debug_create(struct ath10k *ar) | 642 | int ath10k_debug_create(struct ath10k *ar) |
| @@ -662,6 +670,11 @@ int ath10k_debug_create(struct ath10k *ar) | |||
| 662 | return 0; | 670 | return 0; |
| 663 | } | 671 | } |
| 664 | 672 | ||
| 673 | void ath10k_debug_destroy(struct ath10k *ar) | ||
| 674 | { | ||
| 675 | cancel_delayed_work_sync(&ar->debug.htt_stats_dwork); | ||
| 676 | } | ||
| 677 | |||
| 665 | #endif /* CONFIG_ATH10K_DEBUGFS */ | 678 | #endif /* CONFIG_ATH10K_DEBUGFS */ |
| 666 | 679 | ||
| 667 | #ifdef CONFIG_ATH10K_DEBUG | 680 | #ifdef CONFIG_ATH10K_DEBUG |
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h index 6576b82a8d86..3cfe3ee90dbe 100644 --- a/drivers/net/wireless/ath/ath10k/debug.h +++ b/drivers/net/wireless/ath/ath10k/debug.h | |||
| @@ -46,6 +46,7 @@ __printf(1, 2) int ath10k_warn(const char *fmt, ...); | |||
| 46 | int ath10k_debug_start(struct ath10k *ar); | 46 | int ath10k_debug_start(struct ath10k *ar); |
| 47 | void ath10k_debug_stop(struct ath10k *ar); | 47 | void ath10k_debug_stop(struct ath10k *ar); |
| 48 | int ath10k_debug_create(struct ath10k *ar); | 48 | int ath10k_debug_create(struct ath10k *ar); |
| 49 | void ath10k_debug_destroy(struct ath10k *ar); | ||
| 49 | void ath10k_debug_read_service_map(struct ath10k *ar, | 50 | void ath10k_debug_read_service_map(struct ath10k *ar, |
| 50 | void *service_map, | 51 | void *service_map, |
| 51 | size_t map_size); | 52 | size_t map_size); |
| @@ -67,6 +68,10 @@ static inline int ath10k_debug_create(struct ath10k *ar) | |||
| 67 | return 0; | 68 | return 0; |
| 68 | } | 69 | } |
| 69 | 70 | ||
| 71 | static inline void ath10k_debug_destroy(struct ath10k *ar) | ||
| 72 | { | ||
| 73 | } | ||
| 74 | |||
| 70 | static inline void ath10k_debug_read_service_map(struct ath10k *ar, | 75 | static inline void ath10k_debug_read_service_map(struct ath10k *ar, |
| 71 | void *service_map, | 76 | void *service_map, |
| 72 | size_t map_size) | 77 | size_t map_size) |
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index 3b93c6a01c6c..d9335e9d0d04 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c | |||
| @@ -308,7 +308,7 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) | |||
| 308 | struct sk_buff *txdesc = NULL; | 308 | struct sk_buff *txdesc = NULL; |
| 309 | struct htt_cmd *cmd; | 309 | struct htt_cmd *cmd; |
| 310 | struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu); | 310 | struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu); |
| 311 | u8 vdev_id = skb_cb->htt.vdev_id; | 311 | u8 vdev_id = skb_cb->vdev_id; |
| 312 | int len = 0; | 312 | int len = 0; |
| 313 | int msdu_id = -1; | 313 | int msdu_id = -1; |
| 314 | int res; | 314 | int res; |
| @@ -384,7 +384,7 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) | |||
| 384 | struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu); | 384 | struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu); |
| 385 | struct sk_buff *txdesc = NULL; | 385 | struct sk_buff *txdesc = NULL; |
| 386 | bool use_frags; | 386 | bool use_frags; |
| 387 | u8 vdev_id = ATH10K_SKB_CB(msdu)->htt.vdev_id; | 387 | u8 vdev_id = ATH10K_SKB_CB(msdu)->vdev_id; |
| 388 | u8 tid; | 388 | u8 tid; |
| 389 | int prefetch_len, desc_len; | 389 | int prefetch_len, desc_len; |
| 390 | int msdu_id = -1; | 390 | int msdu_id = -1; |
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 8c1be7685922..8aeb46d9b534 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h | |||
| @@ -20,12 +20,6 @@ | |||
| 20 | 20 | ||
| 21 | #include "targaddrs.h" | 21 | #include "targaddrs.h" |
| 22 | 22 | ||
| 23 | /* Supported FW version */ | ||
| 24 | #define SUPPORTED_FW_MAJOR 1 | ||
| 25 | #define SUPPORTED_FW_MINOR 0 | ||
| 26 | #define SUPPORTED_FW_RELEASE 0 | ||
| 27 | #define SUPPORTED_FW_BUILD 636 | ||
| 28 | |||
| 29 | /* QCA988X 1.0 definitions (unsupported) */ | 23 | /* QCA988X 1.0 definitions (unsupported) */ |
| 30 | #define QCA988X_HW_1_0_CHIP_ID_REV 0x0 | 24 | #define QCA988X_HW_1_0_CHIP_ID_REV 0x0 |
| 31 | 25 | ||
| @@ -38,6 +32,25 @@ | |||
| 38 | #define QCA988X_HW_2_0_BOARD_DATA_FILE "board.bin" | 32 | #define QCA988X_HW_2_0_BOARD_DATA_FILE "board.bin" |
| 39 | #define QCA988X_HW_2_0_PATCH_LOAD_ADDR 0x1234 | 33 | #define QCA988X_HW_2_0_PATCH_LOAD_ADDR 0x1234 |
| 40 | 34 | ||
| 35 | #define ATH10K_FW_API2_FILE "firmware-2.bin" | ||
| 36 | |||
| 37 | /* includes also the null byte */ | ||
| 38 | #define ATH10K_FIRMWARE_MAGIC "QCA-ATH10K" | ||
| 39 | |||
| 40 | struct ath10k_fw_ie { | ||
| 41 | __le32 id; | ||
| 42 | __le32 len; | ||
| 43 | u8 data[0]; | ||
| 44 | }; | ||
| 45 | |||
| 46 | enum ath10k_fw_ie_type { | ||
| 47 | ATH10K_FW_IE_FW_VERSION = 0, | ||
| 48 | ATH10K_FW_IE_TIMESTAMP = 1, | ||
| 49 | ATH10K_FW_IE_FEATURES = 2, | ||
| 50 | ATH10K_FW_IE_FW_IMAGE = 3, | ||
| 51 | ATH10K_FW_IE_OTP_IMAGE = 4, | ||
| 52 | }; | ||
| 53 | |||
| 41 | /* Known pecularities: | 54 | /* Known pecularities: |
| 42 | * - current FW doesn't support raw rx mode (last tested v599) | 55 | * - current FW doesn't support raw rx mode (last tested v599) |
| 43 | * - current FW dumps upon raw tx mode (last tested v599) | 56 | * - current FW dumps upon raw tx mode (last tested v599) |
| @@ -59,6 +72,7 @@ enum ath10k_mcast2ucast_mode { | |||
| 59 | ATH10K_MCAST2UCAST_ENABLED = 1, | 72 | ATH10K_MCAST2UCAST_ENABLED = 1, |
| 60 | }; | 73 | }; |
| 61 | 74 | ||
| 75 | /* Target specific defines for MAIN firmware */ | ||
| 62 | #define TARGET_NUM_VDEVS 8 | 76 | #define TARGET_NUM_VDEVS 8 |
| 63 | #define TARGET_NUM_PEER_AST 2 | 77 | #define TARGET_NUM_PEER_AST 2 |
| 64 | #define TARGET_NUM_WDS_ENTRIES 32 | 78 | #define TARGET_NUM_WDS_ENTRIES 32 |
| @@ -93,6 +107,36 @@ enum ath10k_mcast2ucast_mode { | |||
| 93 | #define TARGET_NUM_MSDU_DESC (1024 + 400) | 107 | #define TARGET_NUM_MSDU_DESC (1024 + 400) |
| 94 | #define TARGET_MAX_FRAG_ENTRIES 0 | 108 | #define TARGET_MAX_FRAG_ENTRIES 0 |
| 95 | 109 | ||
| 110 | /* Target specific defines for 10.X firmware */ | ||
| 111 | #define TARGET_10X_NUM_VDEVS 16 | ||
| 112 | #define TARGET_10X_NUM_PEER_AST 2 | ||
| 113 | #define TARGET_10X_NUM_WDS_ENTRIES 32 | ||
| 114 | #define TARGET_10X_DMA_BURST_SIZE 0 | ||
| 115 | #define TARGET_10X_MAC_AGGR_DELIM 0 | ||
| 116 | #define TARGET_10X_AST_SKID_LIMIT 16 | ||
| 117 | #define TARGET_10X_NUM_PEERS (128 + (TARGET_10X_NUM_VDEVS)) | ||
| 118 | #define TARGET_10X_NUM_OFFLOAD_PEERS 0 | ||
| 119 | #define TARGET_10X_NUM_OFFLOAD_REORDER_BUFS 0 | ||
| 120 | #define TARGET_10X_NUM_PEER_KEYS 2 | ||
| 121 | #define TARGET_10X_NUM_TIDS 256 | ||
| 122 | #define TARGET_10X_TX_CHAIN_MASK (BIT(0) | BIT(1) | BIT(2)) | ||
| 123 | #define TARGET_10X_RX_CHAIN_MASK (BIT(0) | BIT(1) | BIT(2)) | ||
| 124 | #define TARGET_10X_RX_TIMEOUT_LO_PRI 100 | ||
| 125 | #define TARGET_10X_RX_TIMEOUT_HI_PRI 40 | ||
| 126 | #define TARGET_10X_RX_DECAP_MODE ATH10K_HW_TXRX_NATIVE_WIFI | ||
| 127 | #define TARGET_10X_SCAN_MAX_PENDING_REQS 4 | ||
| 128 | #define TARGET_10X_BMISS_OFFLOAD_MAX_VDEV 2 | ||
| 129 | #define TARGET_10X_ROAM_OFFLOAD_MAX_VDEV 2 | ||
| 130 | #define TARGET_10X_ROAM_OFFLOAD_MAX_AP_PROFILES 8 | ||
| 131 | #define TARGET_10X_GTK_OFFLOAD_MAX_VDEV 3 | ||
| 132 | #define TARGET_10X_NUM_MCAST_GROUPS 0 | ||
| 133 | #define TARGET_10X_NUM_MCAST_TABLE_ELEMS 0 | ||
| 134 | #define TARGET_10X_MCAST2UCAST_MODE ATH10K_MCAST2UCAST_DISABLED | ||
| 135 | #define TARGET_10X_TX_DBG_LOG_SIZE 1024 | ||
| 136 | #define TARGET_10X_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK 1 | ||
| 137 | #define TARGET_10X_VOW_CONFIG 0 | ||
| 138 | #define TARGET_10X_NUM_MSDU_DESC (1024 + 400) | ||
| 139 | #define TARGET_10X_MAX_FRAG_ENTRIES 0 | ||
| 96 | 140 | ||
| 97 | /* Number of Copy Engines supported */ | 141 | /* Number of Copy Engines supported */ |
| 98 | #define CE_COUNT 8 | 142 | #define CE_COUNT 8 |
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 99a9bad3f398..0b1cc516e778 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c | |||
| @@ -334,25 +334,29 @@ static int ath10k_peer_create(struct ath10k *ar, u32 vdev_id, const u8 *addr) | |||
| 334 | 334 | ||
| 335 | static int ath10k_mac_set_rts(struct ath10k_vif *arvif, u32 value) | 335 | static int ath10k_mac_set_rts(struct ath10k_vif *arvif, u32 value) |
| 336 | { | 336 | { |
| 337 | struct ath10k *ar = arvif->ar; | ||
| 338 | u32 vdev_param; | ||
| 339 | |||
| 337 | if (value != 0xFFFFFFFF) | 340 | if (value != 0xFFFFFFFF) |
| 338 | value = min_t(u32, arvif->ar->hw->wiphy->rts_threshold, | 341 | value = min_t(u32, arvif->ar->hw->wiphy->rts_threshold, |
| 339 | ATH10K_RTS_MAX); | 342 | ATH10K_RTS_MAX); |
| 340 | 343 | ||
| 341 | return ath10k_wmi_vdev_set_param(arvif->ar, arvif->vdev_id, | 344 | vdev_param = ar->wmi.vdev_param->rts_threshold; |
| 342 | WMI_VDEV_PARAM_RTS_THRESHOLD, | 345 | return ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, value); |
| 343 | value); | ||
| 344 | } | 346 | } |
| 345 | 347 | ||
| 346 | static int ath10k_mac_set_frag(struct ath10k_vif *arvif, u32 value) | 348 | static int ath10k_mac_set_frag(struct ath10k_vif *arvif, u32 value) |
| 347 | { | 349 | { |
| 350 | struct ath10k *ar = arvif->ar; | ||
| 351 | u32 vdev_param; | ||
| 352 | |||
| 348 | if (value != 0xFFFFFFFF) | 353 | if (value != 0xFFFFFFFF) |
| 349 | value = clamp_t(u32, arvif->ar->hw->wiphy->frag_threshold, | 354 | value = clamp_t(u32, arvif->ar->hw->wiphy->frag_threshold, |
| 350 | ATH10K_FRAGMT_THRESHOLD_MIN, | 355 | ATH10K_FRAGMT_THRESHOLD_MIN, |
| 351 | ATH10K_FRAGMT_THRESHOLD_MAX); | 356 | ATH10K_FRAGMT_THRESHOLD_MAX); |
| 352 | 357 | ||
| 353 | return ath10k_wmi_vdev_set_param(arvif->ar, arvif->vdev_id, | 358 | vdev_param = ar->wmi.vdev_param->fragmentation_threshold; |
| 354 | WMI_VDEV_PARAM_FRAGMENTATION_THRESHOLD, | 359 | return ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, value); |
| 355 | value); | ||
| 356 | } | 360 | } |
| 357 | 361 | ||
| 358 | static int ath10k_peer_delete(struct ath10k *ar, u32 vdev_id, const u8 *addr) | 362 | static int ath10k_peer_delete(struct ath10k *ar, u32 vdev_id, const u8 *addr) |
| @@ -562,12 +566,9 @@ static int ath10k_monitor_stop(struct ath10k *ar) | |||
| 562 | 566 | ||
| 563 | lockdep_assert_held(&ar->conf_mutex); | 567 | lockdep_assert_held(&ar->conf_mutex); |
| 564 | 568 | ||
| 565 | /* For some reasons, ath10k_wmi_vdev_down() here couse | 569 | ret = ath10k_wmi_vdev_down(ar, ar->monitor_vdev_id); |
| 566 | * often ath10k_wmi_vdev_stop() to fail. Next we could | 570 | if (ret) |
| 567 | * not run monitor vdev and driver reload | 571 | ath10k_warn("Monitor vdev down failed: %d\n", ret); |
| 568 | * required. Don't see such problems we skip | ||
| 569 | * ath10k_wmi_vdev_down() here. | ||
| 570 | */ | ||
| 571 | 572 | ||
| 572 | ret = ath10k_wmi_vdev_stop(ar, ar->monitor_vdev_id); | 573 | ret = ath10k_wmi_vdev_stop(ar, ar->monitor_vdev_id); |
| 573 | if (ret) | 574 | if (ret) |
| @@ -677,6 +678,7 @@ static void ath10k_control_ibss(struct ath10k_vif *arvif, | |||
| 677 | struct ieee80211_bss_conf *info, | 678 | struct ieee80211_bss_conf *info, |
| 678 | const u8 self_peer[ETH_ALEN]) | 679 | const u8 self_peer[ETH_ALEN]) |
| 679 | { | 680 | { |
| 681 | u32 vdev_param; | ||
| 680 | int ret = 0; | 682 | int ret = 0; |
| 681 | 683 | ||
| 682 | lockdep_assert_held(&arvif->ar->conf_mutex); | 684 | lockdep_assert_held(&arvif->ar->conf_mutex); |
| @@ -710,8 +712,8 @@ static void ath10k_control_ibss(struct ath10k_vif *arvif, | |||
| 710 | return; | 712 | return; |
| 711 | } | 713 | } |
| 712 | 714 | ||
| 713 | ret = ath10k_wmi_vdev_set_param(arvif->ar, arvif->vdev_id, | 715 | vdev_param = arvif->ar->wmi.vdev_param->atim_window; |
| 714 | WMI_VDEV_PARAM_ATIM_WINDOW, | 716 | ret = ath10k_wmi_vdev_set_param(arvif->ar, arvif->vdev_id, vdev_param, |
| 715 | ATH10K_DEFAULT_ATIM); | 717 | ATH10K_DEFAULT_ATIM); |
| 716 | if (ret) | 718 | if (ret) |
| 717 | ath10k_warn("Failed to set IBSS ATIM for VDEV:%d ret:%d\n", | 719 | ath10k_warn("Failed to set IBSS ATIM for VDEV:%d ret:%d\n", |
| @@ -721,35 +723,30 @@ static void ath10k_control_ibss(struct ath10k_vif *arvif, | |||
| 721 | /* | 723 | /* |
| 722 | * Review this when mac80211 gains per-interface powersave support. | 724 | * Review this when mac80211 gains per-interface powersave support. |
| 723 | */ | 725 | */ |
| 724 | static void ath10k_ps_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | 726 | static int ath10k_mac_vif_setup_ps(struct ath10k_vif *arvif) |
| 725 | { | 727 | { |
| 726 | struct ath10k_generic_iter *ar_iter = data; | 728 | struct ath10k *ar = arvif->ar; |
| 727 | struct ieee80211_conf *conf = &ar_iter->ar->hw->conf; | 729 | struct ieee80211_conf *conf = &ar->hw->conf; |
| 728 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); | ||
| 729 | enum wmi_sta_powersave_param param; | 730 | enum wmi_sta_powersave_param param; |
| 730 | enum wmi_sta_ps_mode psmode; | 731 | enum wmi_sta_ps_mode psmode; |
| 731 | int ret; | 732 | int ret; |
| 732 | 733 | ||
| 733 | lockdep_assert_held(&arvif->ar->conf_mutex); | 734 | lockdep_assert_held(&arvif->ar->conf_mutex); |
| 734 | 735 | ||
| 735 | if (vif->type != NL80211_IFTYPE_STATION) | 736 | if (arvif->vif->type != NL80211_IFTYPE_STATION) |
| 736 | return; | 737 | return 0; |
| 737 | 738 | ||
| 738 | if (conf->flags & IEEE80211_CONF_PS) { | 739 | if (conf->flags & IEEE80211_CONF_PS) { |
| 739 | psmode = WMI_STA_PS_MODE_ENABLED; | 740 | psmode = WMI_STA_PS_MODE_ENABLED; |
| 740 | param = WMI_STA_PS_PARAM_INACTIVITY_TIME; | 741 | param = WMI_STA_PS_PARAM_INACTIVITY_TIME; |
| 741 | 742 | ||
| 742 | ret = ath10k_wmi_set_sta_ps_param(ar_iter->ar, | 743 | ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, param, |
| 743 | arvif->vdev_id, | ||
| 744 | param, | ||
| 745 | conf->dynamic_ps_timeout); | 744 | conf->dynamic_ps_timeout); |
| 746 | if (ret) { | 745 | if (ret) { |
| 747 | ath10k_warn("Failed to set inactivity time for VDEV: %d\n", | 746 | ath10k_warn("Failed to set inactivity time for VDEV: %d\n", |
| 748 | arvif->vdev_id); | 747 | arvif->vdev_id); |
| 749 | return; | 748 | return ret; |
| 750 | } | 749 | } |
| 751 | |||
| 752 | ar_iter->ret = ret; | ||
| 753 | } else { | 750 | } else { |
| 754 | psmode = WMI_STA_PS_MODE_DISABLED; | 751 | psmode = WMI_STA_PS_MODE_DISABLED; |
| 755 | } | 752 | } |
| @@ -757,11 +754,14 @@ static void ath10k_ps_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | |||
| 757 | ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d psmode %s\n", | 754 | ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d psmode %s\n", |
| 758 | arvif->vdev_id, psmode ? "enable" : "disable"); | 755 | arvif->vdev_id, psmode ? "enable" : "disable"); |
| 759 | 756 | ||
| 760 | ar_iter->ret = ath10k_wmi_set_psmode(ar_iter->ar, arvif->vdev_id, | 757 | ret = ath10k_wmi_set_psmode(ar, arvif->vdev_id, psmode); |
| 761 | psmode); | 758 | if (ret) { |
| 762 | if (ar_iter->ret) | ||
| 763 | ath10k_warn("Failed to set PS Mode: %d for VDEV: %d\n", | 759 | ath10k_warn("Failed to set PS Mode: %d for VDEV: %d\n", |
| 764 | psmode, arvif->vdev_id); | 760 | psmode, arvif->vdev_id); |
| 761 | return ret; | ||
| 762 | } | ||
| 763 | |||
| 764 | return 0; | ||
| 765 | } | 765 | } |
| 766 | 766 | ||
| 767 | /**********************/ | 767 | /**********************/ |
| @@ -1031,14 +1031,27 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar, | |||
| 1031 | struct wmi_peer_assoc_complete_arg *arg) | 1031 | struct wmi_peer_assoc_complete_arg *arg) |
| 1032 | { | 1032 | { |
| 1033 | const struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap; | 1033 | const struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap; |
| 1034 | u8 ampdu_factor; | ||
| 1034 | 1035 | ||
| 1035 | if (!vht_cap->vht_supported) | 1036 | if (!vht_cap->vht_supported) |
| 1036 | return; | 1037 | return; |
| 1037 | 1038 | ||
| 1038 | arg->peer_flags |= WMI_PEER_VHT; | 1039 | arg->peer_flags |= WMI_PEER_VHT; |
| 1039 | |||
| 1040 | arg->peer_vht_caps = vht_cap->cap; | 1040 | arg->peer_vht_caps = vht_cap->cap; |
| 1041 | 1041 | ||
| 1042 | |||
| 1043 | ampdu_factor = (vht_cap->cap & | ||
| 1044 | IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK) >> | ||
| 1045 | IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT; | ||
| 1046 | |||
| 1047 | /* Workaround: Some Netgear/Linksys 11ac APs set Rx A-MPDU factor to | ||
| 1048 | * zero in VHT IE. Using it would result in degraded throughput. | ||
| 1049 | * arg->peer_max_mpdu at this point contains HT max_mpdu so keep | ||
| 1050 | * it if VHT max_mpdu is smaller. */ | ||
| 1051 | arg->peer_max_mpdu = max(arg->peer_max_mpdu, | ||
| 1052 | (1U << (IEEE80211_HT_MAX_AMPDU_FACTOR + | ||
| 1053 | ampdu_factor)) - 1); | ||
| 1054 | |||
| 1042 | if (sta->bandwidth == IEEE80211_STA_RX_BW_80) | 1055 | if (sta->bandwidth == IEEE80211_STA_RX_BW_80) |
| 1043 | arg->peer_flags |= WMI_PEER_80MHZ; | 1056 | arg->peer_flags |= WMI_PEER_80MHZ; |
| 1044 | 1057 | ||
| @@ -1124,26 +1137,25 @@ static void ath10k_peer_assoc_h_phymode(struct ath10k *ar, | |||
| 1124 | WARN_ON(phymode == MODE_UNKNOWN); | 1137 | WARN_ON(phymode == MODE_UNKNOWN); |
| 1125 | } | 1138 | } |
| 1126 | 1139 | ||
| 1127 | static int ath10k_peer_assoc(struct ath10k *ar, | 1140 | static int ath10k_peer_assoc_prepare(struct ath10k *ar, |
| 1128 | struct ath10k_vif *arvif, | 1141 | struct ath10k_vif *arvif, |
| 1129 | struct ieee80211_sta *sta, | 1142 | struct ieee80211_sta *sta, |
| 1130 | struct ieee80211_bss_conf *bss_conf) | 1143 | struct ieee80211_bss_conf *bss_conf, |
| 1144 | struct wmi_peer_assoc_complete_arg *arg) | ||
| 1131 | { | 1145 | { |
| 1132 | struct wmi_peer_assoc_complete_arg arg; | ||
| 1133 | |||
| 1134 | lockdep_assert_held(&ar->conf_mutex); | 1146 | lockdep_assert_held(&ar->conf_mutex); |
| 1135 | 1147 | ||
| 1136 | memset(&arg, 0, sizeof(struct wmi_peer_assoc_complete_arg)); | 1148 | memset(arg, 0, sizeof(*arg)); |
| 1137 | 1149 | ||
| 1138 | ath10k_peer_assoc_h_basic(ar, arvif, sta, bss_conf, &arg); | 1150 | ath10k_peer_assoc_h_basic(ar, arvif, sta, bss_conf, arg); |
| 1139 | ath10k_peer_assoc_h_crypto(ar, arvif, &arg); | 1151 | ath10k_peer_assoc_h_crypto(ar, arvif, arg); |
| 1140 | ath10k_peer_assoc_h_rates(ar, sta, &arg); | 1152 | ath10k_peer_assoc_h_rates(ar, sta, arg); |
| 1141 | ath10k_peer_assoc_h_ht(ar, sta, &arg); | 1153 | ath10k_peer_assoc_h_ht(ar, sta, arg); |
| 1142 | ath10k_peer_assoc_h_vht(ar, sta, &arg); | 1154 | ath10k_peer_assoc_h_vht(ar, sta, arg); |
| 1143 | ath10k_peer_assoc_h_qos(ar, arvif, sta, bss_conf, &arg); | 1155 | ath10k_peer_assoc_h_qos(ar, arvif, sta, bss_conf, arg); |
| 1144 | ath10k_peer_assoc_h_phymode(ar, arvif, sta, &arg); | 1156 | ath10k_peer_assoc_h_phymode(ar, arvif, sta, arg); |
| 1145 | 1157 | ||
| 1146 | return ath10k_wmi_peer_assoc(ar, &arg); | 1158 | return 0; |
| 1147 | } | 1159 | } |
| 1148 | 1160 | ||
| 1149 | /* can be called only in mac80211 callbacks due to `key_count` usage */ | 1161 | /* can be called only in mac80211 callbacks due to `key_count` usage */ |
| @@ -1153,6 +1165,7 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw, | |||
| 1153 | { | 1165 | { |
| 1154 | struct ath10k *ar = hw->priv; | 1166 | struct ath10k *ar = hw->priv; |
| 1155 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); | 1167 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); |
| 1168 | struct wmi_peer_assoc_complete_arg peer_arg; | ||
| 1156 | struct ieee80211_sta *ap_sta; | 1169 | struct ieee80211_sta *ap_sta; |
| 1157 | int ret; | 1170 | int ret; |
| 1158 | 1171 | ||
| @@ -1168,15 +1181,24 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw, | |||
| 1168 | return; | 1181 | return; |
| 1169 | } | 1182 | } |
| 1170 | 1183 | ||
| 1171 | ret = ath10k_peer_assoc(ar, arvif, ap_sta, bss_conf); | 1184 | ret = ath10k_peer_assoc_prepare(ar, arvif, ap_sta, |
| 1185 | bss_conf, &peer_arg); | ||
| 1172 | if (ret) { | 1186 | if (ret) { |
| 1173 | ath10k_warn("Peer assoc failed for %pM\n", bss_conf->bssid); | 1187 | ath10k_warn("Peer assoc prepare failed for %pM\n: %d", |
| 1188 | bss_conf->bssid, ret); | ||
| 1174 | rcu_read_unlock(); | 1189 | rcu_read_unlock(); |
| 1175 | return; | 1190 | return; |
| 1176 | } | 1191 | } |
| 1177 | 1192 | ||
| 1178 | rcu_read_unlock(); | 1193 | rcu_read_unlock(); |
| 1179 | 1194 | ||
| 1195 | ret = ath10k_wmi_peer_assoc(ar, &peer_arg); | ||
| 1196 | if (ret) { | ||
| 1197 | ath10k_warn("Peer assoc failed for %pM\n: %d", | ||
| 1198 | bss_conf->bssid, ret); | ||
| 1199 | return; | ||
| 1200 | } | ||
| 1201 | |||
| 1180 | ath10k_dbg(ATH10K_DBG_MAC, | 1202 | ath10k_dbg(ATH10K_DBG_MAC, |
| 1181 | "mac vdev %d up (associated) bssid %pM aid %d\n", | 1203 | "mac vdev %d up (associated) bssid %pM aid %d\n", |
| 1182 | arvif->vdev_id, bss_conf->bssid, bss_conf->aid); | 1204 | arvif->vdev_id, bss_conf->bssid, bss_conf->aid); |
| @@ -1224,19 +1246,28 @@ static void ath10k_bss_disassoc(struct ieee80211_hw *hw, | |||
| 1224 | /* FIXME: why don't we print error if wmi call fails? */ | 1246 | /* FIXME: why don't we print error if wmi call fails? */ |
| 1225 | ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id); | 1247 | ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id); |
| 1226 | 1248 | ||
| 1227 | arvif->def_wep_key_index = 0; | 1249 | arvif->def_wep_key_idx = 0; |
| 1228 | } | 1250 | } |
| 1229 | 1251 | ||
| 1230 | static int ath10k_station_assoc(struct ath10k *ar, struct ath10k_vif *arvif, | 1252 | static int ath10k_station_assoc(struct ath10k *ar, struct ath10k_vif *arvif, |
| 1231 | struct ieee80211_sta *sta) | 1253 | struct ieee80211_sta *sta) |
| 1232 | { | 1254 | { |
| 1255 | struct wmi_peer_assoc_complete_arg peer_arg; | ||
| 1233 | int ret = 0; | 1256 | int ret = 0; |
| 1234 | 1257 | ||
| 1235 | lockdep_assert_held(&ar->conf_mutex); | 1258 | lockdep_assert_held(&ar->conf_mutex); |
| 1236 | 1259 | ||
| 1237 | ret = ath10k_peer_assoc(ar, arvif, sta, NULL); | 1260 | ret = ath10k_peer_assoc_prepare(ar, arvif, sta, NULL, &peer_arg); |
| 1238 | if (ret) { | 1261 | if (ret) { |
| 1239 | ath10k_warn("WMI peer assoc failed for %pM\n", sta->addr); | 1262 | ath10k_warn("WMI peer assoc prepare failed for %pM\n", |
| 1263 | sta->addr); | ||
| 1264 | return ret; | ||
| 1265 | } | ||
| 1266 | |||
| 1267 | ret = ath10k_wmi_peer_assoc(ar, &peer_arg); | ||
| 1268 | if (ret) { | ||
| 1269 | ath10k_warn("Peer assoc failed for STA %pM\n: %d", | ||
| 1270 | sta->addr, ret); | ||
| 1240 | return ret; | 1271 | return ret; |
| 1241 | } | 1272 | } |
| 1242 | 1273 | ||
| @@ -1405,6 +1436,33 @@ static void ath10k_reg_notifier(struct wiphy *wiphy, | |||
| 1405 | /* TX handlers */ | 1436 | /* TX handlers */ |
| 1406 | /***************/ | 1437 | /***************/ |
| 1407 | 1438 | ||
| 1439 | static u8 ath10k_tx_h_get_tid(struct ieee80211_hdr *hdr) | ||
| 1440 | { | ||
| 1441 | if (ieee80211_is_mgmt(hdr->frame_control)) | ||
| 1442 | return HTT_DATA_TX_EXT_TID_MGMT; | ||
| 1443 | |||
| 1444 | if (!ieee80211_is_data_qos(hdr->frame_control)) | ||
| 1445 | return HTT_DATA_TX_EXT_TID_NON_QOS_MCAST_BCAST; | ||
| 1446 | |||
| 1447 | if (!is_unicast_ether_addr(ieee80211_get_DA(hdr))) | ||
| 1448 | return HTT_DATA_TX_EXT_TID_NON_QOS_MCAST_BCAST; | ||
| 1449 | |||
| 1450 | return ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK; | ||
| 1451 | } | ||
| 1452 | |||
| 1453 | static u8 ath10k_tx_h_get_vdev_id(struct ath10k *ar, | ||
| 1454 | struct ieee80211_tx_info *info) | ||
| 1455 | { | ||
| 1456 | if (info->control.vif) | ||
| 1457 | return ath10k_vif_to_arvif(info->control.vif)->vdev_id; | ||
| 1458 | |||
| 1459 | if (ar->monitor_enabled) | ||
| 1460 | return ar->monitor_vdev_id; | ||
| 1461 | |||
| 1462 | ath10k_warn("could not resolve vdev id\n"); | ||
| 1463 | return 0; | ||
| 1464 | } | ||
| 1465 | |||
| 1408 | /* | 1466 | /* |
| 1409 | * Frames sent to the FW have to be in "Native Wifi" format. | 1467 | * Frames sent to the FW have to be in "Native Wifi" format. |
| 1410 | * Strip the QoS field from the 802.11 header. | 1468 | * Strip the QoS field from the 802.11 header. |
| @@ -1425,6 +1483,30 @@ static void ath10k_tx_h_qos_workaround(struct ieee80211_hw *hw, | |||
| 1425 | skb_pull(skb, IEEE80211_QOS_CTL_LEN); | 1483 | skb_pull(skb, IEEE80211_QOS_CTL_LEN); |
| 1426 | } | 1484 | } |
| 1427 | 1485 | ||
| 1486 | static void ath10k_tx_wep_key_work(struct work_struct *work) | ||
| 1487 | { | ||
| 1488 | struct ath10k_vif *arvif = container_of(work, struct ath10k_vif, | ||
| 1489 | wep_key_work); | ||
| 1490 | int ret, keyidx = arvif->def_wep_key_newidx; | ||
| 1491 | |||
| 1492 | if (arvif->def_wep_key_idx == keyidx) | ||
| 1493 | return; | ||
| 1494 | |||
| 1495 | ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d set keyidx %d\n", | ||
| 1496 | arvif->vdev_id, keyidx); | ||
| 1497 | |||
| 1498 | ret = ath10k_wmi_vdev_set_param(arvif->ar, | ||
| 1499 | arvif->vdev_id, | ||
| 1500 | arvif->ar->wmi.vdev_param->def_keyid, | ||
| 1501 | keyidx); | ||
| 1502 | if (ret) { | ||
| 1503 | ath10k_warn("could not update wep keyidx (%d)\n", ret); | ||
| 1504 | return; | ||
| 1505 | } | ||
| 1506 | |||
| 1507 | arvif->def_wep_key_idx = keyidx; | ||
| 1508 | } | ||
| 1509 | |||
| 1428 | static void ath10k_tx_h_update_wep_key(struct sk_buff *skb) | 1510 | static void ath10k_tx_h_update_wep_key(struct sk_buff *skb) |
| 1429 | { | 1511 | { |
| 1430 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1512 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
| @@ -1433,7 +1515,6 @@ static void ath10k_tx_h_update_wep_key(struct sk_buff *skb) | |||
| 1433 | struct ath10k *ar = arvif->ar; | 1515 | struct ath10k *ar = arvif->ar; |
| 1434 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 1516 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
| 1435 | struct ieee80211_key_conf *key = info->control.hw_key; | 1517 | struct ieee80211_key_conf *key = info->control.hw_key; |
| 1436 | int ret; | ||
| 1437 | 1518 | ||
| 1438 | if (!ieee80211_has_protected(hdr->frame_control)) | 1519 | if (!ieee80211_has_protected(hdr->frame_control)) |
| 1439 | return; | 1520 | return; |
| @@ -1445,21 +1526,14 @@ static void ath10k_tx_h_update_wep_key(struct sk_buff *skb) | |||
| 1445 | key->cipher != WLAN_CIPHER_SUITE_WEP104) | 1526 | key->cipher != WLAN_CIPHER_SUITE_WEP104) |
| 1446 | return; | 1527 | return; |
| 1447 | 1528 | ||
| 1448 | if (key->keyidx == arvif->def_wep_key_index) | 1529 | if (key->keyidx == arvif->def_wep_key_idx) |
| 1449 | return; | ||
| 1450 | |||
| 1451 | ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d keyidx %d\n", | ||
| 1452 | arvif->vdev_id, key->keyidx); | ||
| 1453 | |||
| 1454 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, | ||
| 1455 | WMI_VDEV_PARAM_DEF_KEYID, | ||
| 1456 | key->keyidx); | ||
| 1457 | if (ret) { | ||
| 1458 | ath10k_warn("could not update wep keyidx (%d)\n", ret); | ||
| 1459 | return; | 1530 | return; |
| 1460 | } | ||
| 1461 | 1531 | ||
| 1462 | arvif->def_wep_key_index = key->keyidx; | 1532 | /* FIXME: Most likely a few frames will be TXed with an old key. Simply |
| 1533 | * queueing frames until key index is updated is not an option because | ||
| 1534 | * sk_buff may need more processing to be done, e.g. offchannel */ | ||
| 1535 | arvif->def_wep_key_newidx = key->keyidx; | ||
| 1536 | ieee80211_queue_work(ar->hw, &arvif->wep_key_work); | ||
| 1463 | } | 1537 | } |
| 1464 | 1538 | ||
| 1465 | static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar, struct sk_buff *skb) | 1539 | static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar, struct sk_buff *skb) |
| @@ -1489,7 +1563,7 @@ static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar, struct sk_buff *skb) | |||
| 1489 | static void ath10k_tx_htt(struct ath10k *ar, struct sk_buff *skb) | 1563 | static void ath10k_tx_htt(struct ath10k *ar, struct sk_buff *skb) |
| 1490 | { | 1564 | { |
| 1491 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 1565 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
| 1492 | int ret; | 1566 | int ret = 0; |
| 1493 | 1567 | ||
| 1494 | if (ar->htt.target_version_major >= 3) { | 1568 | if (ar->htt.target_version_major >= 3) { |
| 1495 | /* Since HTT 3.0 there is no separate mgmt tx command */ | 1569 | /* Since HTT 3.0 there is no separate mgmt tx command */ |
| @@ -1497,16 +1571,32 @@ static void ath10k_tx_htt(struct ath10k *ar, struct sk_buff *skb) | |||
| 1497 | goto exit; | 1571 | goto exit; |
| 1498 | } | 1572 | } |
| 1499 | 1573 | ||
| 1500 | if (ieee80211_is_mgmt(hdr->frame_control)) | 1574 | if (ieee80211_is_mgmt(hdr->frame_control)) { |
| 1501 | ret = ath10k_htt_mgmt_tx(&ar->htt, skb); | 1575 | if (test_bit(ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX, |
| 1502 | else if (ieee80211_is_nullfunc(hdr->frame_control)) | 1576 | ar->fw_features)) { |
| 1577 | if (skb_queue_len(&ar->wmi_mgmt_tx_queue) >= | ||
| 1578 | ATH10K_MAX_NUM_MGMT_PENDING) { | ||
| 1579 | ath10k_warn("wmi mgmt_tx queue limit reached\n"); | ||
| 1580 | ret = -EBUSY; | ||
| 1581 | goto exit; | ||
| 1582 | } | ||
| 1583 | |||
| 1584 | skb_queue_tail(&ar->wmi_mgmt_tx_queue, skb); | ||
| 1585 | ieee80211_queue_work(ar->hw, &ar->wmi_mgmt_tx_work); | ||
| 1586 | } else { | ||
| 1587 | ret = ath10k_htt_mgmt_tx(&ar->htt, skb); | ||
| 1588 | } | ||
| 1589 | } else if (!test_bit(ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX, | ||
| 1590 | ar->fw_features) && | ||
| 1591 | ieee80211_is_nullfunc(hdr->frame_control)) { | ||
| 1503 | /* FW does not report tx status properly for NullFunc frames | 1592 | /* FW does not report tx status properly for NullFunc frames |
| 1504 | * unless they are sent through mgmt tx path. mac80211 sends | 1593 | * unless they are sent through mgmt tx path. mac80211 sends |
| 1505 | * those frames when it detects link/beacon loss and depends on | 1594 | * those frames when it detects link/beacon loss and depends |
| 1506 | * the tx status to be correct. */ | 1595 | * on the tx status to be correct. */ |
| 1507 | ret = ath10k_htt_mgmt_tx(&ar->htt, skb); | 1596 | ret = ath10k_htt_mgmt_tx(&ar->htt, skb); |
| 1508 | else | 1597 | } else { |
| 1509 | ret = ath10k_htt_tx(&ar->htt, skb); | 1598 | ret = ath10k_htt_tx(&ar->htt, skb); |
| 1599 | } | ||
| 1510 | 1600 | ||
| 1511 | exit: | 1601 | exit: |
| 1512 | if (ret) { | 1602 | if (ret) { |
| @@ -1557,7 +1647,7 @@ void ath10k_offchan_tx_work(struct work_struct *work) | |||
| 1557 | 1647 | ||
| 1558 | hdr = (struct ieee80211_hdr *)skb->data; | 1648 | hdr = (struct ieee80211_hdr *)skb->data; |
| 1559 | peer_addr = ieee80211_get_DA(hdr); | 1649 | peer_addr = ieee80211_get_DA(hdr); |
| 1560 | vdev_id = ATH10K_SKB_CB(skb)->htt.vdev_id; | 1650 | vdev_id = ATH10K_SKB_CB(skb)->vdev_id; |
| 1561 | 1651 | ||
| 1562 | spin_lock_bh(&ar->data_lock); | 1652 | spin_lock_bh(&ar->data_lock); |
| 1563 | peer = ath10k_peer_find(ar, vdev_id, peer_addr); | 1653 | peer = ath10k_peer_find(ar, vdev_id, peer_addr); |
| @@ -1599,6 +1689,36 @@ void ath10k_offchan_tx_work(struct work_struct *work) | |||
| 1599 | } | 1689 | } |
| 1600 | } | 1690 | } |
| 1601 | 1691 | ||
| 1692 | void ath10k_mgmt_over_wmi_tx_purge(struct ath10k *ar) | ||
| 1693 | { | ||
| 1694 | struct sk_buff *skb; | ||
| 1695 | |||
| 1696 | for (;;) { | ||
| 1697 | skb = skb_dequeue(&ar->wmi_mgmt_tx_queue); | ||
| 1698 | if (!skb) | ||
| 1699 | break; | ||
| 1700 | |||
| 1701 | ieee80211_free_txskb(ar->hw, skb); | ||
| 1702 | } | ||
| 1703 | } | ||
| 1704 | |||
| 1705 | void ath10k_mgmt_over_wmi_tx_work(struct work_struct *work) | ||
| 1706 | { | ||
| 1707 | struct ath10k *ar = container_of(work, struct ath10k, wmi_mgmt_tx_work); | ||
| 1708 | struct sk_buff *skb; | ||
| 1709 | int ret; | ||
| 1710 | |||
| 1711 | for (;;) { | ||
| 1712 | skb = skb_dequeue(&ar->wmi_mgmt_tx_queue); | ||
| 1713 | if (!skb) | ||
| 1714 | break; | ||
| 1715 | |||
| 1716 | ret = ath10k_wmi_mgmt_tx(ar, skb); | ||
| 1717 | if (ret) | ||
| 1718 | ath10k_warn("wmi mgmt_tx failed (%d)\n", ret); | ||
| 1719 | } | ||
| 1720 | } | ||
| 1721 | |||
| 1602 | /************/ | 1722 | /************/ |
| 1603 | /* Scanning */ | 1723 | /* Scanning */ |
| 1604 | /************/ | 1724 | /************/ |
| @@ -1722,16 +1842,7 @@ static void ath10k_tx(struct ieee80211_hw *hw, | |||
| 1722 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1842 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
| 1723 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 1843 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
| 1724 | struct ath10k *ar = hw->priv; | 1844 | struct ath10k *ar = hw->priv; |
| 1725 | struct ath10k_vif *arvif = NULL; | 1845 | u8 tid, vdev_id; |
| 1726 | u32 vdev_id = 0; | ||
| 1727 | u8 tid; | ||
| 1728 | |||
| 1729 | if (info->control.vif) { | ||
| 1730 | arvif = ath10k_vif_to_arvif(info->control.vif); | ||
| 1731 | vdev_id = arvif->vdev_id; | ||
| 1732 | } else if (ar->monitor_enabled) { | ||
| 1733 | vdev_id = ar->monitor_vdev_id; | ||
| 1734 | } | ||
| 1735 | 1846 | ||
| 1736 | /* We should disable CCK RATE due to P2P */ | 1847 | /* We should disable CCK RATE due to P2P */ |
| 1737 | if (info->flags & IEEE80211_TX_CTL_NO_CCK_RATE) | 1848 | if (info->flags & IEEE80211_TX_CTL_NO_CCK_RATE) |
| @@ -1739,14 +1850,8 @@ static void ath10k_tx(struct ieee80211_hw *hw, | |||
| 1739 | 1850 | ||
| 1740 | /* we must calculate tid before we apply qos workaround | 1851 | /* we must calculate tid before we apply qos workaround |
| 1741 | * as we'd lose the qos control field */ | 1852 | * as we'd lose the qos control field */ |
| 1742 | tid = HTT_DATA_TX_EXT_TID_NON_QOS_MCAST_BCAST; | 1853 | tid = ath10k_tx_h_get_tid(hdr); |
| 1743 | if (ieee80211_is_mgmt(hdr->frame_control)) { | 1854 | vdev_id = ath10k_tx_h_get_vdev_id(ar, info); |
| 1744 | tid = HTT_DATA_TX_EXT_TID_MGMT; | ||
| 1745 | } else if (ieee80211_is_data_qos(hdr->frame_control) && | ||
| 1746 | is_unicast_ether_addr(ieee80211_get_DA(hdr))) { | ||
| 1747 | u8 *qc = ieee80211_get_qos_ctl(hdr); | ||
| 1748 | tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; | ||
| 1749 | } | ||
| 1750 | 1855 | ||
| 1751 | /* it makes no sense to process injected frames like that */ | 1856 | /* it makes no sense to process injected frames like that */ |
| 1752 | if (info->control.vif && | 1857 | if (info->control.vif && |
| @@ -1757,14 +1862,14 @@ static void ath10k_tx(struct ieee80211_hw *hw, | |||
| 1757 | ath10k_tx_h_seq_no(skb); | 1862 | ath10k_tx_h_seq_no(skb); |
| 1758 | } | 1863 | } |
| 1759 | 1864 | ||
| 1865 | ATH10K_SKB_CB(skb)->vdev_id = vdev_id; | ||
| 1760 | ATH10K_SKB_CB(skb)->htt.is_offchan = false; | 1866 | ATH10K_SKB_CB(skb)->htt.is_offchan = false; |
| 1761 | ATH10K_SKB_CB(skb)->htt.vdev_id = vdev_id; | ||
| 1762 | ATH10K_SKB_CB(skb)->htt.tid = tid; | 1867 | ATH10K_SKB_CB(skb)->htt.tid = tid; |
| 1763 | 1868 | ||
| 1764 | if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) { | 1869 | if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) { |
| 1765 | spin_lock_bh(&ar->data_lock); | 1870 | spin_lock_bh(&ar->data_lock); |
| 1766 | ATH10K_SKB_CB(skb)->htt.is_offchan = true; | 1871 | ATH10K_SKB_CB(skb)->htt.is_offchan = true; |
| 1767 | ATH10K_SKB_CB(skb)->htt.vdev_id = ar->scan.vdev_id; | 1872 | ATH10K_SKB_CB(skb)->vdev_id = ar->scan.vdev_id; |
| 1768 | spin_unlock_bh(&ar->data_lock); | 1873 | spin_unlock_bh(&ar->data_lock); |
| 1769 | 1874 | ||
| 1770 | ath10k_dbg(ATH10K_DBG_MAC, "queued offchannel skb %p\n", skb); | 1875 | ath10k_dbg(ATH10K_DBG_MAC, "queued offchannel skb %p\n", skb); |
| @@ -1786,6 +1891,7 @@ void ath10k_halt(struct ath10k *ar) | |||
| 1786 | 1891 | ||
| 1787 | del_timer_sync(&ar->scan.timeout); | 1892 | del_timer_sync(&ar->scan.timeout); |
| 1788 | ath10k_offchan_tx_purge(ar); | 1893 | ath10k_offchan_tx_purge(ar); |
| 1894 | ath10k_mgmt_over_wmi_tx_purge(ar); | ||
| 1789 | ath10k_peer_cleanup_all(ar); | 1895 | ath10k_peer_cleanup_all(ar); |
| 1790 | ath10k_core_stop(ar); | 1896 | ath10k_core_stop(ar); |
| 1791 | ath10k_hif_power_down(ar); | 1897 | ath10k_hif_power_down(ar); |
| @@ -1832,12 +1938,12 @@ static int ath10k_start(struct ieee80211_hw *hw) | |||
| 1832 | else if (ar->state == ATH10K_STATE_RESTARTING) | 1938 | else if (ar->state == ATH10K_STATE_RESTARTING) |
| 1833 | ar->state = ATH10K_STATE_RESTARTED; | 1939 | ar->state = ATH10K_STATE_RESTARTED; |
| 1834 | 1940 | ||
| 1835 | ret = ath10k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_PMF_QOS, 1); | 1941 | ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->pmf_qos, 1); |
| 1836 | if (ret) | 1942 | if (ret) |
| 1837 | ath10k_warn("could not enable WMI_PDEV_PARAM_PMF_QOS (%d)\n", | 1943 | ath10k_warn("could not enable WMI_PDEV_PARAM_PMF_QOS (%d)\n", |
| 1838 | ret); | 1944 | ret); |
| 1839 | 1945 | ||
| 1840 | ret = ath10k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_DYNAMIC_BW, 0); | 1946 | ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->dynamic_bw, 0); |
| 1841 | if (ret) | 1947 | if (ret) |
| 1842 | ath10k_warn("could not init WMI_PDEV_PARAM_DYNAMIC_BW (%d)\n", | 1948 | ath10k_warn("could not init WMI_PDEV_PARAM_DYNAMIC_BW (%d)\n", |
| 1843 | ret); | 1949 | ret); |
| @@ -1862,32 +1968,29 @@ static void ath10k_stop(struct ieee80211_hw *hw) | |||
| 1862 | ar->state = ATH10K_STATE_OFF; | 1968 | ar->state = ATH10K_STATE_OFF; |
| 1863 | mutex_unlock(&ar->conf_mutex); | 1969 | mutex_unlock(&ar->conf_mutex); |
| 1864 | 1970 | ||
| 1971 | ath10k_mgmt_over_wmi_tx_purge(ar); | ||
| 1972 | |||
| 1865 | cancel_work_sync(&ar->offchan_tx_work); | 1973 | cancel_work_sync(&ar->offchan_tx_work); |
| 1974 | cancel_work_sync(&ar->wmi_mgmt_tx_work); | ||
| 1866 | cancel_work_sync(&ar->restart_work); | 1975 | cancel_work_sync(&ar->restart_work); |
| 1867 | } | 1976 | } |
| 1868 | 1977 | ||
| 1869 | static void ath10k_config_ps(struct ath10k *ar) | 1978 | static int ath10k_config_ps(struct ath10k *ar) |
| 1870 | { | 1979 | { |
| 1871 | struct ath10k_generic_iter ar_iter; | 1980 | struct ath10k_vif *arvif; |
| 1981 | int ret = 0; | ||
| 1872 | 1982 | ||
| 1873 | lockdep_assert_held(&ar->conf_mutex); | 1983 | lockdep_assert_held(&ar->conf_mutex); |
| 1874 | 1984 | ||
| 1875 | /* During HW reconfiguration mac80211 reports all interfaces that were | 1985 | list_for_each_entry(arvif, &ar->arvifs, list) { |
| 1876 | * running until reconfiguration was started. Since FW doesn't have any | 1986 | ret = ath10k_mac_vif_setup_ps(arvif); |
| 1877 | * vdevs at this point we must not iterate over this interface list. | 1987 | if (ret) { |
| 1878 | * This setting will be updated upon add_interface(). */ | 1988 | ath10k_warn("could not setup powersave (%d)\n", ret); |
| 1879 | if (ar->state == ATH10K_STATE_RESTARTED) | 1989 | break; |
| 1880 | return; | 1990 | } |
| 1881 | 1991 | } | |
| 1882 | memset(&ar_iter, 0, sizeof(struct ath10k_generic_iter)); | ||
| 1883 | ar_iter.ar = ar; | ||
| 1884 | |||
| 1885 | ieee80211_iterate_active_interfaces_atomic( | ||
| 1886 | ar->hw, IEEE80211_IFACE_ITER_NORMAL, | ||
| 1887 | ath10k_ps_iter, &ar_iter); | ||
| 1888 | 1992 | ||
| 1889 | if (ar_iter.ret) | 1993 | return ret; |
| 1890 | ath10k_warn("failed to set ps config (%d)\n", ar_iter.ret); | ||
| 1891 | } | 1994 | } |
| 1892 | 1995 | ||
| 1893 | static int ath10k_config(struct ieee80211_hw *hw, u32 changed) | 1996 | static int ath10k_config(struct ieee80211_hw *hw, u32 changed) |
| @@ -1936,6 +2039,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, | |||
| 1936 | int ret = 0; | 2039 | int ret = 0; |
| 1937 | u32 value; | 2040 | u32 value; |
| 1938 | int bit; | 2041 | int bit; |
| 2042 | u32 vdev_param; | ||
| 1939 | 2043 | ||
| 1940 | mutex_lock(&ar->conf_mutex); | 2044 | mutex_lock(&ar->conf_mutex); |
| 1941 | 2045 | ||
| @@ -1944,21 +2048,22 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, | |||
| 1944 | arvif->ar = ar; | 2048 | arvif->ar = ar; |
| 1945 | arvif->vif = vif; | 2049 | arvif->vif = vif; |
| 1946 | 2050 | ||
| 2051 | INIT_WORK(&arvif->wep_key_work, ath10k_tx_wep_key_work); | ||
| 2052 | |||
| 1947 | if ((vif->type == NL80211_IFTYPE_MONITOR) && ar->monitor_present) { | 2053 | if ((vif->type == NL80211_IFTYPE_MONITOR) && ar->monitor_present) { |
| 1948 | ath10k_warn("Only one monitor interface allowed\n"); | 2054 | ath10k_warn("Only one monitor interface allowed\n"); |
| 1949 | ret = -EBUSY; | 2055 | ret = -EBUSY; |
| 1950 | goto exit; | 2056 | goto err; |
| 1951 | } | 2057 | } |
| 1952 | 2058 | ||
| 1953 | bit = ffs(ar->free_vdev_map); | 2059 | bit = ffs(ar->free_vdev_map); |
| 1954 | if (bit == 0) { | 2060 | if (bit == 0) { |
| 1955 | ret = -EBUSY; | 2061 | ret = -EBUSY; |
| 1956 | goto exit; | 2062 | goto err; |
| 1957 | } | 2063 | } |
| 1958 | 2064 | ||
| 1959 | arvif->vdev_id = bit - 1; | 2065 | arvif->vdev_id = bit - 1; |
| 1960 | arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE; | 2066 | arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE; |
| 1961 | ar->free_vdev_map &= ~(1 << arvif->vdev_id); | ||
| 1962 | 2067 | ||
| 1963 | if (ar->p2p) | 2068 | if (ar->p2p) |
| 1964 | arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_DEVICE; | 2069 | arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_DEVICE; |
| @@ -1994,25 +2099,34 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, | |||
| 1994 | arvif->vdev_subtype, vif->addr); | 2099 | arvif->vdev_subtype, vif->addr); |
| 1995 | if (ret) { | 2100 | if (ret) { |
| 1996 | ath10k_warn("WMI vdev create failed: ret %d\n", ret); | 2101 | ath10k_warn("WMI vdev create failed: ret %d\n", ret); |
| 1997 | goto exit; | 2102 | goto err; |
| 1998 | } | 2103 | } |
| 1999 | 2104 | ||
| 2000 | ret = ath10k_wmi_vdev_set_param(ar, 0, WMI_VDEV_PARAM_DEF_KEYID, | 2105 | ar->free_vdev_map &= ~BIT(arvif->vdev_id); |
| 2001 | arvif->def_wep_key_index); | 2106 | list_add(&arvif->list, &ar->arvifs); |
| 2002 | if (ret) | 2107 | |
| 2108 | vdev_param = ar->wmi.vdev_param->def_keyid; | ||
| 2109 | ret = ath10k_wmi_vdev_set_param(ar, 0, vdev_param, | ||
| 2110 | arvif->def_wep_key_idx); | ||
| 2111 | if (ret) { | ||
| 2003 | ath10k_warn("Failed to set default keyid: %d\n", ret); | 2112 | ath10k_warn("Failed to set default keyid: %d\n", ret); |
| 2113 | goto err_vdev_delete; | ||
| 2114 | } | ||
| 2004 | 2115 | ||
| 2005 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, | 2116 | vdev_param = ar->wmi.vdev_param->tx_encap_type; |
| 2006 | WMI_VDEV_PARAM_TX_ENCAP_TYPE, | 2117 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, |
| 2007 | ATH10K_HW_TXRX_NATIVE_WIFI); | 2118 | ATH10K_HW_TXRX_NATIVE_WIFI); |
| 2008 | if (ret) | 2119 | /* 10.X firmware does not support this VDEV parameter. Do not warn */ |
| 2120 | if (ret && ret != -EOPNOTSUPP) { | ||
| 2009 | ath10k_warn("Failed to set TX encap: %d\n", ret); | 2121 | ath10k_warn("Failed to set TX encap: %d\n", ret); |
| 2122 | goto err_vdev_delete; | ||
| 2123 | } | ||
| 2010 | 2124 | ||
| 2011 | if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { | 2125 | if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { |
| 2012 | ret = ath10k_peer_create(ar, arvif->vdev_id, vif->addr); | 2126 | ret = ath10k_peer_create(ar, arvif->vdev_id, vif->addr); |
| 2013 | if (ret) { | 2127 | if (ret) { |
| 2014 | ath10k_warn("Failed to create peer for AP: %d\n", ret); | 2128 | ath10k_warn("Failed to create peer for AP: %d\n", ret); |
| 2015 | goto exit; | 2129 | goto err_vdev_delete; |
| 2016 | } | 2130 | } |
| 2017 | } | 2131 | } |
| 2018 | 2132 | ||
| @@ -2021,39 +2135,62 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, | |||
| 2021 | value = WMI_STA_PS_RX_WAKE_POLICY_WAKE; | 2135 | value = WMI_STA_PS_RX_WAKE_POLICY_WAKE; |
| 2022 | ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, | 2136 | ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, |
| 2023 | param, value); | 2137 | param, value); |
| 2024 | if (ret) | 2138 | if (ret) { |
| 2025 | ath10k_warn("Failed to set RX wake policy: %d\n", ret); | 2139 | ath10k_warn("Failed to set RX wake policy: %d\n", ret); |
| 2140 | goto err_peer_delete; | ||
| 2141 | } | ||
| 2026 | 2142 | ||
| 2027 | param = WMI_STA_PS_PARAM_TX_WAKE_THRESHOLD; | 2143 | param = WMI_STA_PS_PARAM_TX_WAKE_THRESHOLD; |
| 2028 | value = WMI_STA_PS_TX_WAKE_THRESHOLD_ALWAYS; | 2144 | value = WMI_STA_PS_TX_WAKE_THRESHOLD_ALWAYS; |
| 2029 | ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, | 2145 | ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, |
| 2030 | param, value); | 2146 | param, value); |
| 2031 | if (ret) | 2147 | if (ret) { |
| 2032 | ath10k_warn("Failed to set TX wake thresh: %d\n", ret); | 2148 | ath10k_warn("Failed to set TX wake thresh: %d\n", ret); |
| 2149 | goto err_peer_delete; | ||
| 2150 | } | ||
| 2033 | 2151 | ||
| 2034 | param = WMI_STA_PS_PARAM_PSPOLL_COUNT; | 2152 | param = WMI_STA_PS_PARAM_PSPOLL_COUNT; |
| 2035 | value = WMI_STA_PS_PSPOLL_COUNT_NO_MAX; | 2153 | value = WMI_STA_PS_PSPOLL_COUNT_NO_MAX; |
| 2036 | ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, | 2154 | ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, |
| 2037 | param, value); | 2155 | param, value); |
| 2038 | if (ret) | 2156 | if (ret) { |
| 2039 | ath10k_warn("Failed to set PSPOLL count: %d\n", ret); | 2157 | ath10k_warn("Failed to set PSPOLL count: %d\n", ret); |
| 2158 | goto err_peer_delete; | ||
| 2159 | } | ||
| 2040 | } | 2160 | } |
| 2041 | 2161 | ||
| 2042 | ret = ath10k_mac_set_rts(arvif, ar->hw->wiphy->rts_threshold); | 2162 | ret = ath10k_mac_set_rts(arvif, ar->hw->wiphy->rts_threshold); |
| 2043 | if (ret) | 2163 | if (ret) { |
| 2044 | ath10k_warn("failed to set rts threshold for vdev %d (%d)\n", | 2164 | ath10k_warn("failed to set rts threshold for vdev %d (%d)\n", |
| 2045 | arvif->vdev_id, ret); | 2165 | arvif->vdev_id, ret); |
| 2166 | goto err_peer_delete; | ||
| 2167 | } | ||
| 2046 | 2168 | ||
| 2047 | ret = ath10k_mac_set_frag(arvif, ar->hw->wiphy->frag_threshold); | 2169 | ret = ath10k_mac_set_frag(arvif, ar->hw->wiphy->frag_threshold); |
| 2048 | if (ret) | 2170 | if (ret) { |
| 2049 | ath10k_warn("failed to set frag threshold for vdev %d (%d)\n", | 2171 | ath10k_warn("failed to set frag threshold for vdev %d (%d)\n", |
| 2050 | arvif->vdev_id, ret); | 2172 | arvif->vdev_id, ret); |
| 2173 | goto err_peer_delete; | ||
| 2174 | } | ||
| 2051 | 2175 | ||
| 2052 | if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) | 2176 | if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) |
| 2053 | ar->monitor_present = true; | 2177 | ar->monitor_present = true; |
| 2054 | 2178 | ||
| 2055 | exit: | ||
| 2056 | mutex_unlock(&ar->conf_mutex); | 2179 | mutex_unlock(&ar->conf_mutex); |
| 2180 | return 0; | ||
| 2181 | |||
| 2182 | err_peer_delete: | ||
| 2183 | if (arvif->vdev_type == WMI_VDEV_TYPE_AP) | ||
| 2184 | ath10k_wmi_peer_delete(ar, arvif->vdev_id, vif->addr); | ||
| 2185 | |||
| 2186 | err_vdev_delete: | ||
| 2187 | ath10k_wmi_vdev_delete(ar, arvif->vdev_id); | ||
| 2188 | ar->free_vdev_map &= ~BIT(arvif->vdev_id); | ||
| 2189 | list_del(&arvif->list); | ||
| 2190 | |||
| 2191 | err: | ||
| 2192 | mutex_unlock(&ar->conf_mutex); | ||
| 2193 | |||
| 2057 | return ret; | 2194 | return ret; |
| 2058 | } | 2195 | } |
| 2059 | 2196 | ||
| @@ -2066,6 +2203,8 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw, | |||
| 2066 | 2203 | ||
| 2067 | mutex_lock(&ar->conf_mutex); | 2204 | mutex_lock(&ar->conf_mutex); |
| 2068 | 2205 | ||
| 2206 | cancel_work_sync(&arvif->wep_key_work); | ||
| 2207 | |||
| 2069 | spin_lock_bh(&ar->data_lock); | 2208 | spin_lock_bh(&ar->data_lock); |
| 2070 | if (arvif->beacon) { | 2209 | if (arvif->beacon) { |
| 2071 | dev_kfree_skb_any(arvif->beacon); | 2210 | dev_kfree_skb_any(arvif->beacon); |
| @@ -2074,6 +2213,7 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw, | |||
| 2074 | spin_unlock_bh(&ar->data_lock); | 2213 | spin_unlock_bh(&ar->data_lock); |
| 2075 | 2214 | ||
| 2076 | ar->free_vdev_map |= 1 << (arvif->vdev_id); | 2215 | ar->free_vdev_map |= 1 << (arvif->vdev_id); |
| 2216 | list_del(&arvif->list); | ||
| 2077 | 2217 | ||
| 2078 | if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { | 2218 | if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { |
| 2079 | ret = ath10k_peer_delete(arvif->ar, arvif->vdev_id, vif->addr); | 2219 | ret = ath10k_peer_delete(arvif->ar, arvif->vdev_id, vif->addr); |
| @@ -2154,6 +2294,7 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, | |||
| 2154 | struct ath10k *ar = hw->priv; | 2294 | struct ath10k *ar = hw->priv; |
| 2155 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); | 2295 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); |
| 2156 | int ret = 0; | 2296 | int ret = 0; |
| 2297 | u32 vdev_param, pdev_param; | ||
| 2157 | 2298 | ||
| 2158 | mutex_lock(&ar->conf_mutex); | 2299 | mutex_lock(&ar->conf_mutex); |
| 2159 | 2300 | ||
| @@ -2162,8 +2303,8 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, | |||
| 2162 | 2303 | ||
| 2163 | if (changed & BSS_CHANGED_BEACON_INT) { | 2304 | if (changed & BSS_CHANGED_BEACON_INT) { |
| 2164 | arvif->beacon_interval = info->beacon_int; | 2305 | arvif->beacon_interval = info->beacon_int; |
| 2165 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, | 2306 | vdev_param = ar->wmi.vdev_param->beacon_interval; |
| 2166 | WMI_VDEV_PARAM_BEACON_INTERVAL, | 2307 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, |
| 2167 | arvif->beacon_interval); | 2308 | arvif->beacon_interval); |
| 2168 | ath10k_dbg(ATH10K_DBG_MAC, | 2309 | ath10k_dbg(ATH10K_DBG_MAC, |
| 2169 | "mac vdev %d beacon_interval %d\n", | 2310 | "mac vdev %d beacon_interval %d\n", |
| @@ -2179,8 +2320,8 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, | |||
| 2179 | "vdev %d set beacon tx mode to staggered\n", | 2320 | "vdev %d set beacon tx mode to staggered\n", |
| 2180 | arvif->vdev_id); | 2321 | arvif->vdev_id); |
| 2181 | 2322 | ||
| 2182 | ret = ath10k_wmi_pdev_set_param(ar, | 2323 | pdev_param = ar->wmi.pdev_param->beacon_tx_mode; |
| 2183 | WMI_PDEV_PARAM_BEACON_TX_MODE, | 2324 | ret = ath10k_wmi_pdev_set_param(ar, pdev_param, |
| 2184 | WMI_BEACON_STAGGERED_MODE); | 2325 | WMI_BEACON_STAGGERED_MODE); |
| 2185 | if (ret) | 2326 | if (ret) |
| 2186 | ath10k_warn("Failed to set beacon mode for VDEV: %d\n", | 2327 | ath10k_warn("Failed to set beacon mode for VDEV: %d\n", |
| @@ -2194,8 +2335,8 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, | |||
| 2194 | "mac vdev %d dtim_period %d\n", | 2335 | "mac vdev %d dtim_period %d\n", |
| 2195 | arvif->vdev_id, arvif->dtim_period); | 2336 | arvif->vdev_id, arvif->dtim_period); |
| 2196 | 2337 | ||
| 2197 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, | 2338 | vdev_param = ar->wmi.vdev_param->dtim_period; |
| 2198 | WMI_VDEV_PARAM_DTIM_PERIOD, | 2339 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, |
| 2199 | arvif->dtim_period); | 2340 | arvif->dtim_period); |
| 2200 | if (ret) | 2341 | if (ret) |
| 2201 | ath10k_warn("Failed to set dtim period for VDEV: %d\n", | 2342 | ath10k_warn("Failed to set dtim period for VDEV: %d\n", |
| @@ -2262,8 +2403,8 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, | |||
| 2262 | ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d cts_prot %d\n", | 2403 | ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d cts_prot %d\n", |
| 2263 | arvif->vdev_id, cts_prot); | 2404 | arvif->vdev_id, cts_prot); |
| 2264 | 2405 | ||
| 2265 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, | 2406 | vdev_param = ar->wmi.vdev_param->enable_rtscts; |
| 2266 | WMI_VDEV_PARAM_ENABLE_RTSCTS, | 2407 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, |
| 2267 | cts_prot); | 2408 | cts_prot); |
| 2268 | if (ret) | 2409 | if (ret) |
| 2269 | ath10k_warn("Failed to set CTS prot for VDEV: %d\n", | 2410 | ath10k_warn("Failed to set CTS prot for VDEV: %d\n", |
| @@ -2281,8 +2422,8 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, | |||
| 2281 | ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d slot_time %d\n", | 2422 | ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d slot_time %d\n", |
| 2282 | arvif->vdev_id, slottime); | 2423 | arvif->vdev_id, slottime); |
| 2283 | 2424 | ||
| 2284 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, | 2425 | vdev_param = ar->wmi.vdev_param->slot_time; |
| 2285 | WMI_VDEV_PARAM_SLOT_TIME, | 2426 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, |
| 2286 | slottime); | 2427 | slottime); |
| 2287 | if (ret) | 2428 | if (ret) |
| 2288 | ath10k_warn("Failed to set erp slot for VDEV: %d\n", | 2429 | ath10k_warn("Failed to set erp slot for VDEV: %d\n", |
| @@ -2300,8 +2441,8 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, | |||
| 2300 | "mac vdev %d preamble %dn", | 2441 | "mac vdev %d preamble %dn", |
| 2301 | arvif->vdev_id, preamble); | 2442 | arvif->vdev_id, preamble); |
| 2302 | 2443 | ||
| 2303 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, | 2444 | vdev_param = ar->wmi.vdev_param->preamble; |
| 2304 | WMI_VDEV_PARAM_PREAMBLE, | 2445 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, |
| 2305 | preamble); | 2446 | preamble); |
| 2306 | if (ret) | 2447 | if (ret) |
| 2307 | ath10k_warn("Failed to set preamble for VDEV: %d\n", | 2448 | ath10k_warn("Failed to set preamble for VDEV: %d\n", |
| @@ -2751,86 +2892,51 @@ static int ath10k_cancel_remain_on_channel(struct ieee80211_hw *hw) | |||
| 2751 | * Both RTS and Fragmentation threshold are interface-specific | 2892 | * Both RTS and Fragmentation threshold are interface-specific |
| 2752 | * in ath10k, but device-specific in mac80211. | 2893 | * in ath10k, but device-specific in mac80211. |
| 2753 | */ | 2894 | */ |
| 2754 | static void ath10k_set_rts_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | ||
| 2755 | { | ||
| 2756 | struct ath10k_generic_iter *ar_iter = data; | ||
| 2757 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); | ||
| 2758 | u32 rts = ar_iter->ar->hw->wiphy->rts_threshold; | ||
| 2759 | |||
| 2760 | lockdep_assert_held(&arvif->ar->conf_mutex); | ||
| 2761 | |||
| 2762 | /* During HW reconfiguration mac80211 reports all interfaces that were | ||
| 2763 | * running until reconfiguration was started. Since FW doesn't have any | ||
| 2764 | * vdevs at this point we must not iterate over this interface list. | ||
| 2765 | * This setting will be updated upon add_interface(). */ | ||
| 2766 | if (ar_iter->ar->state == ATH10K_STATE_RESTARTED) | ||
| 2767 | return; | ||
| 2768 | |||
| 2769 | ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d rts_threshold %d\n", | ||
| 2770 | arvif->vdev_id, rts); | ||
| 2771 | |||
| 2772 | ar_iter->ret = ath10k_mac_set_rts(arvif, rts); | ||
| 2773 | if (ar_iter->ret) | ||
| 2774 | ath10k_warn("Failed to set RTS threshold for VDEV: %d\n", | ||
| 2775 | arvif->vdev_id); | ||
| 2776 | } | ||
| 2777 | 2895 | ||
| 2778 | static int ath10k_set_rts_threshold(struct ieee80211_hw *hw, u32 value) | 2896 | static int ath10k_set_rts_threshold(struct ieee80211_hw *hw, u32 value) |
| 2779 | { | 2897 | { |
| 2780 | struct ath10k_generic_iter ar_iter; | ||
| 2781 | struct ath10k *ar = hw->priv; | 2898 | struct ath10k *ar = hw->priv; |
| 2782 | 2899 | struct ath10k_vif *arvif; | |
| 2783 | memset(&ar_iter, 0, sizeof(struct ath10k_generic_iter)); | 2900 | int ret = 0; |
| 2784 | ar_iter.ar = ar; | ||
| 2785 | 2901 | ||
| 2786 | mutex_lock(&ar->conf_mutex); | 2902 | mutex_lock(&ar->conf_mutex); |
| 2787 | ieee80211_iterate_active_interfaces_atomic( | 2903 | list_for_each_entry(arvif, &ar->arvifs, list) { |
| 2788 | hw, IEEE80211_IFACE_ITER_NORMAL, | 2904 | ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d rts threshold %d\n", |
| 2789 | ath10k_set_rts_iter, &ar_iter); | 2905 | arvif->vdev_id, value); |
| 2790 | mutex_unlock(&ar->conf_mutex); | ||
| 2791 | |||
| 2792 | return ar_iter.ret; | ||
| 2793 | } | ||
| 2794 | |||
| 2795 | static void ath10k_set_frag_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | ||
| 2796 | { | ||
| 2797 | struct ath10k_generic_iter *ar_iter = data; | ||
| 2798 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); | ||
| 2799 | u32 frag = ar_iter->ar->hw->wiphy->frag_threshold; | ||
| 2800 | |||
| 2801 | lockdep_assert_held(&arvif->ar->conf_mutex); | ||
| 2802 | 2906 | ||
| 2803 | /* During HW reconfiguration mac80211 reports all interfaces that were | 2907 | ret = ath10k_mac_set_rts(arvif, value); |
| 2804 | * running until reconfiguration was started. Since FW doesn't have any | 2908 | if (ret) { |
| 2805 | * vdevs at this point we must not iterate over this interface list. | 2909 | ath10k_warn("could not set rts threshold for vdev %d (%d)\n", |
| 2806 | * This setting will be updated upon add_interface(). */ | 2910 | arvif->vdev_id, ret); |
| 2807 | if (ar_iter->ar->state == ATH10K_STATE_RESTARTED) | 2911 | break; |
| 2808 | return; | 2912 | } |
| 2809 | 2913 | } | |
| 2810 | ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d fragmentation_threshold %d\n", | 2914 | mutex_unlock(&ar->conf_mutex); |
| 2811 | arvif->vdev_id, frag); | ||
| 2812 | 2915 | ||
| 2813 | ar_iter->ret = ath10k_mac_set_frag(arvif, frag); | 2916 | return ret; |
| 2814 | if (ar_iter->ret) | ||
| 2815 | ath10k_warn("Failed to set frag threshold for VDEV: %d\n", | ||
| 2816 | arvif->vdev_id); | ||
| 2817 | } | 2917 | } |
| 2818 | 2918 | ||
| 2819 | static int ath10k_set_frag_threshold(struct ieee80211_hw *hw, u32 value) | 2919 | static int ath10k_set_frag_threshold(struct ieee80211_hw *hw, u32 value) |
| 2820 | { | 2920 | { |
| 2821 | struct ath10k_generic_iter ar_iter; | ||
| 2822 | struct ath10k *ar = hw->priv; | 2921 | struct ath10k *ar = hw->priv; |
| 2823 | 2922 | struct ath10k_vif *arvif; | |
| 2824 | memset(&ar_iter, 0, sizeof(struct ath10k_generic_iter)); | 2923 | int ret = 0; |
| 2825 | ar_iter.ar = ar; | ||
| 2826 | 2924 | ||
| 2827 | mutex_lock(&ar->conf_mutex); | 2925 | mutex_lock(&ar->conf_mutex); |
| 2828 | ieee80211_iterate_active_interfaces_atomic( | 2926 | list_for_each_entry(arvif, &ar->arvifs, list) { |
| 2829 | hw, IEEE80211_IFACE_ITER_NORMAL, | 2927 | ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d fragmentation threshold %d\n", |
| 2830 | ath10k_set_frag_iter, &ar_iter); | 2928 | arvif->vdev_id, value); |
| 2929 | |||
| 2930 | ret = ath10k_mac_set_rts(arvif, value); | ||
| 2931 | if (ret) { | ||
| 2932 | ath10k_warn("could not set fragmentation threshold for vdev %d (%d)\n", | ||
| 2933 | arvif->vdev_id, ret); | ||
| 2934 | break; | ||
| 2935 | } | ||
| 2936 | } | ||
| 2831 | mutex_unlock(&ar->conf_mutex); | 2937 | mutex_unlock(&ar->conf_mutex); |
| 2832 | 2938 | ||
| 2833 | return ar_iter.ret; | 2939 | return ret; |
| 2834 | } | 2940 | } |
| 2835 | 2941 | ||
| 2836 | static void ath10k_flush(struct ieee80211_hw *hw, u32 queues, bool drop) | 2942 | static void ath10k_flush(struct ieee80211_hw *hw, u32 queues, bool drop) |
diff --git a/drivers/net/wireless/ath/ath10k/mac.h b/drivers/net/wireless/ath/ath10k/mac.h index 6fce9bfb19a5..ba1021997b8f 100644 --- a/drivers/net/wireless/ath/ath10k/mac.h +++ b/drivers/net/wireless/ath/ath10k/mac.h | |||
| @@ -34,6 +34,8 @@ struct ath10k_vif *ath10k_get_arvif(struct ath10k *ar, u32 vdev_id); | |||
| 34 | void ath10k_reset_scan(unsigned long ptr); | 34 | void ath10k_reset_scan(unsigned long ptr); |
| 35 | void ath10k_offchan_tx_purge(struct ath10k *ar); | 35 | void ath10k_offchan_tx_purge(struct ath10k *ar); |
| 36 | void ath10k_offchan_tx_work(struct work_struct *work); | 36 | void ath10k_offchan_tx_work(struct work_struct *work); |
| 37 | void ath10k_mgmt_over_wmi_tx_purge(struct ath10k *ar); | ||
| 38 | void ath10k_mgmt_over_wmi_tx_work(struct work_struct *work); | ||
| 37 | void ath10k_halt(struct ath10k *ar); | 39 | void ath10k_halt(struct ath10k *ar); |
| 38 | 40 | ||
| 39 | static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif) | 41 | static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif) |
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index dff23d97bed0..f8d59c7b9082 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c | |||
| @@ -720,18 +720,8 @@ static int ath10k_pci_hif_send_head(struct ath10k *ar, u8 pipe_id, | |||
| 720 | "ath10k tx: data: ", | 720 | "ath10k tx: data: ", |
| 721 | nbuf->data, nbuf->len); | 721 | nbuf->data, nbuf->len); |
| 722 | 722 | ||
| 723 | /* Make sure we have resources to handle this request */ | 723 | ret = ath10k_ce_send(ce_hdl, nbuf, skb_cb->paddr, len, transfer_id, |
| 724 | spin_lock_bh(&pipe_info->pipe_lock); | 724 | flags); |
| 725 | if (!pipe_info->num_sends_allowed) { | ||
| 726 | ath10k_warn("Pipe: %d is full\n", pipe_id); | ||
| 727 | spin_unlock_bh(&pipe_info->pipe_lock); | ||
| 728 | return -ENOSR; | ||
| 729 | } | ||
| 730 | pipe_info->num_sends_allowed--; | ||
| 731 | spin_unlock_bh(&pipe_info->pipe_lock); | ||
| 732 | |||
| 733 | ret = ath10k_ce_sendlist_send(ce_hdl, nbuf, transfer_id, | ||
| 734 | skb_cb->paddr, len, flags); | ||
| 735 | if (ret) | 725 | if (ret) |
| 736 | ath10k_warn("CE send failed: %p\n", nbuf); | 726 | ath10k_warn("CE send failed: %p\n", nbuf); |
| 737 | 727 | ||
| @@ -741,14 +731,7 @@ static int ath10k_pci_hif_send_head(struct ath10k *ar, u8 pipe_id, | |||
| 741 | static u16 ath10k_pci_hif_get_free_queue_number(struct ath10k *ar, u8 pipe) | 731 | static u16 ath10k_pci_hif_get_free_queue_number(struct ath10k *ar, u8 pipe) |
| 742 | { | 732 | { |
| 743 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 733 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
| 744 | struct ath10k_pci_pipe *pipe_info = &(ar_pci->pipe_info[pipe]); | 734 | return ath10k_ce_num_free_src_entries(ar_pci->pipe_info[pipe].ce_hdl); |
| 745 | int ret; | ||
| 746 | |||
| 747 | spin_lock_bh(&pipe_info->pipe_lock); | ||
| 748 | ret = pipe_info->num_sends_allowed; | ||
| 749 | spin_unlock_bh(&pipe_info->pipe_lock); | ||
| 750 | |||
| 751 | return ret; | ||
| 752 | } | 735 | } |
| 753 | 736 | ||
| 754 | static void ath10k_pci_hif_dump_area(struct ath10k *ar) | 737 | static void ath10k_pci_hif_dump_area(struct ath10k *ar) |
| @@ -863,7 +846,6 @@ static int ath10k_pci_start_ce(struct ath10k *ar) | |||
| 863 | ath10k_pci_ce_send_done, | 846 | ath10k_pci_ce_send_done, |
| 864 | disable_interrupts); | 847 | disable_interrupts); |
| 865 | completions += attr->src_nentries; | 848 | completions += attr->src_nentries; |
| 866 | pipe_info->num_sends_allowed = attr->src_nentries - 1; | ||
| 867 | } | 849 | } |
| 868 | 850 | ||
| 869 | if (attr->dest_nentries) { | 851 | if (attr->dest_nentries) { |
| @@ -1033,7 +1015,6 @@ static void ath10k_pci_process_ce(struct ath10k *ar) | |||
| 1033 | */ | 1015 | */ |
| 1034 | spin_lock_bh(&compl->pipe_info->pipe_lock); | 1016 | spin_lock_bh(&compl->pipe_info->pipe_lock); |
| 1035 | list_add_tail(&compl->list, &compl->pipe_info->compl_free); | 1017 | list_add_tail(&compl->list, &compl->pipe_info->compl_free); |
| 1036 | compl->pipe_info->num_sends_allowed += send_done; | ||
| 1037 | spin_unlock_bh(&compl->pipe_info->pipe_lock); | 1018 | spin_unlock_bh(&compl->pipe_info->pipe_lock); |
| 1038 | } | 1019 | } |
| 1039 | 1020 | ||
diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index 7c49f6f96f70..52fb7b973571 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h | |||
| @@ -178,9 +178,6 @@ struct ath10k_pci_pipe { | |||
| 178 | /* List of free CE completion slots */ | 178 | /* List of free CE completion slots */ |
| 179 | struct list_head compl_free; | 179 | struct list_head compl_free; |
| 180 | 180 | ||
| 181 | /* Limit the number of outstanding send requests. */ | ||
| 182 | int num_sends_allowed; | ||
| 183 | |||
| 184 | struct ath10k_pci *ar_pci; | 181 | struct ath10k_pci *ar_pci; |
| 185 | struct tasklet_struct intr; | 182 | struct tasklet_struct intr; |
| 186 | }; | 183 | }; |
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 33cb19eb3d89..ccf3597fd9e2 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c | |||
| @@ -23,6 +23,471 @@ | |||
| 23 | #include "wmi.h" | 23 | #include "wmi.h" |
| 24 | #include "mac.h" | 24 | #include "mac.h" |
| 25 | 25 | ||
| 26 | /* MAIN WMI cmd track */ | ||
| 27 | static struct wmi_cmd_map wmi_cmd_map = { | ||
| 28 | .init_cmdid = WMI_INIT_CMDID, | ||
| 29 | .start_scan_cmdid = WMI_START_SCAN_CMDID, | ||
| 30 | .stop_scan_cmdid = WMI_STOP_SCAN_CMDID, | ||
| 31 | .scan_chan_list_cmdid = WMI_SCAN_CHAN_LIST_CMDID, | ||
| 32 | .scan_sch_prio_tbl_cmdid = WMI_SCAN_SCH_PRIO_TBL_CMDID, | ||
| 33 | .pdev_set_regdomain_cmdid = WMI_PDEV_SET_REGDOMAIN_CMDID, | ||
| 34 | .pdev_set_channel_cmdid = WMI_PDEV_SET_CHANNEL_CMDID, | ||
| 35 | .pdev_set_param_cmdid = WMI_PDEV_SET_PARAM_CMDID, | ||
| 36 | .pdev_pktlog_enable_cmdid = WMI_PDEV_PKTLOG_ENABLE_CMDID, | ||
| 37 | .pdev_pktlog_disable_cmdid = WMI_PDEV_PKTLOG_DISABLE_CMDID, | ||
| 38 | .pdev_set_wmm_params_cmdid = WMI_PDEV_SET_WMM_PARAMS_CMDID, | ||
| 39 | .pdev_set_ht_cap_ie_cmdid = WMI_PDEV_SET_HT_CAP_IE_CMDID, | ||
| 40 | .pdev_set_vht_cap_ie_cmdid = WMI_PDEV_SET_VHT_CAP_IE_CMDID, | ||
| 41 | .pdev_set_dscp_tid_map_cmdid = WMI_PDEV_SET_DSCP_TID_MAP_CMDID, | ||
| 42 | .pdev_set_quiet_mode_cmdid = WMI_PDEV_SET_QUIET_MODE_CMDID, | ||
| 43 | .pdev_green_ap_ps_enable_cmdid = WMI_PDEV_GREEN_AP_PS_ENABLE_CMDID, | ||
| 44 | .pdev_get_tpc_config_cmdid = WMI_PDEV_GET_TPC_CONFIG_CMDID, | ||
| 45 | .pdev_set_base_macaddr_cmdid = WMI_PDEV_SET_BASE_MACADDR_CMDID, | ||
| 46 | .vdev_create_cmdid = WMI_VDEV_CREATE_CMDID, | ||
| 47 | .vdev_delete_cmdid = WMI_VDEV_DELETE_CMDID, | ||
| 48 | .vdev_start_request_cmdid = WMI_VDEV_START_REQUEST_CMDID, | ||
| 49 | .vdev_restart_request_cmdid = WMI_VDEV_RESTART_REQUEST_CMDID, | ||
| 50 | .vdev_up_cmdid = WMI_VDEV_UP_CMDID, | ||
| 51 | .vdev_stop_cmdid = WMI_VDEV_STOP_CMDID, | ||
| 52 | .vdev_down_cmdid = WMI_VDEV_DOWN_CMDID, | ||
| 53 | .vdev_set_param_cmdid = WMI_VDEV_SET_PARAM_CMDID, | ||
| 54 | .vdev_install_key_cmdid = WMI_VDEV_INSTALL_KEY_CMDID, | ||
| 55 | .peer_create_cmdid = WMI_PEER_CREATE_CMDID, | ||
| 56 | .peer_delete_cmdid = WMI_PEER_DELETE_CMDID, | ||
| 57 | .peer_flush_tids_cmdid = WMI_PEER_FLUSH_TIDS_CMDID, | ||
| 58 | .peer_set_param_cmdid = WMI_PEER_SET_PARAM_CMDID, | ||
| 59 | .peer_assoc_cmdid = WMI_PEER_ASSOC_CMDID, | ||
| 60 | .peer_add_wds_entry_cmdid = WMI_PEER_ADD_WDS_ENTRY_CMDID, | ||
| 61 | .peer_remove_wds_entry_cmdid = WMI_PEER_REMOVE_WDS_ENTRY_CMDID, | ||
| 62 | .peer_mcast_group_cmdid = WMI_PEER_MCAST_GROUP_CMDID, | ||
| 63 | .bcn_tx_cmdid = WMI_BCN_TX_CMDID, | ||
| 64 | .pdev_send_bcn_cmdid = WMI_PDEV_SEND_BCN_CMDID, | ||
| 65 | .bcn_tmpl_cmdid = WMI_BCN_TMPL_CMDID, | ||
| 66 | .bcn_filter_rx_cmdid = WMI_BCN_FILTER_RX_CMDID, | ||
| 67 | .prb_req_filter_rx_cmdid = WMI_PRB_REQ_FILTER_RX_CMDID, | ||
| 68 | .mgmt_tx_cmdid = WMI_MGMT_TX_CMDID, | ||
| 69 | .prb_tmpl_cmdid = WMI_PRB_TMPL_CMDID, | ||
| 70 | .addba_clear_resp_cmdid = WMI_ADDBA_CLEAR_RESP_CMDID, | ||
| 71 | .addba_send_cmdid = WMI_ADDBA_SEND_CMDID, | ||
| 72 | .addba_status_cmdid = WMI_ADDBA_STATUS_CMDID, | ||
| 73 | .delba_send_cmdid = WMI_DELBA_SEND_CMDID, | ||
| 74 | .addba_set_resp_cmdid = WMI_ADDBA_SET_RESP_CMDID, | ||
| 75 | .send_singleamsdu_cmdid = WMI_SEND_SINGLEAMSDU_CMDID, | ||
| 76 | .sta_powersave_mode_cmdid = WMI_STA_POWERSAVE_MODE_CMDID, | ||
| 77 | .sta_powersave_param_cmdid = WMI_STA_POWERSAVE_PARAM_CMDID, | ||
| 78 | .sta_mimo_ps_mode_cmdid = WMI_STA_MIMO_PS_MODE_CMDID, | ||
| 79 | .pdev_dfs_enable_cmdid = WMI_PDEV_DFS_ENABLE_CMDID, | ||
| 80 | .pdev_dfs_disable_cmdid = WMI_PDEV_DFS_DISABLE_CMDID, | ||
| 81 | .roam_scan_mode = WMI_ROAM_SCAN_MODE, | ||
| 82 | .roam_scan_rssi_threshold = WMI_ROAM_SCAN_RSSI_THRESHOLD, | ||
| 83 | .roam_scan_period = WMI_ROAM_SCAN_PERIOD, | ||
| 84 | .roam_scan_rssi_change_threshold = WMI_ROAM_SCAN_RSSI_CHANGE_THRESHOLD, | ||
| 85 | .roam_ap_profile = WMI_ROAM_AP_PROFILE, | ||
| 86 | .ofl_scan_add_ap_profile = WMI_ROAM_AP_PROFILE, | ||
| 87 | .ofl_scan_remove_ap_profile = WMI_OFL_SCAN_REMOVE_AP_PROFILE, | ||
| 88 | .ofl_scan_period = WMI_OFL_SCAN_PERIOD, | ||
| 89 | .p2p_dev_set_device_info = WMI_P2P_DEV_SET_DEVICE_INFO, | ||
| 90 | .p2p_dev_set_discoverability = WMI_P2P_DEV_SET_DISCOVERABILITY, | ||
| 91 | .p2p_go_set_beacon_ie = WMI_P2P_GO_SET_BEACON_IE, | ||
| 92 | .p2p_go_set_probe_resp_ie = WMI_P2P_GO_SET_PROBE_RESP_IE, | ||
| 93 | .p2p_set_vendor_ie_data_cmdid = WMI_P2P_SET_VENDOR_IE_DATA_CMDID, | ||
| 94 | .ap_ps_peer_param_cmdid = WMI_AP_PS_PEER_PARAM_CMDID, | ||
| 95 | .ap_ps_peer_uapsd_coex_cmdid = WMI_AP_PS_PEER_UAPSD_COEX_CMDID, | ||
| 96 | .peer_rate_retry_sched_cmdid = WMI_PEER_RATE_RETRY_SCHED_CMDID, | ||
| 97 | .wlan_profile_trigger_cmdid = WMI_WLAN_PROFILE_TRIGGER_CMDID, | ||
| 98 | .wlan_profile_set_hist_intvl_cmdid = | ||
| 99 | WMI_WLAN_PROFILE_SET_HIST_INTVL_CMDID, | ||
| 100 | .wlan_profile_get_profile_data_cmdid = | ||
| 101 | WMI_WLAN_PROFILE_GET_PROFILE_DATA_CMDID, | ||
| 102 | .wlan_profile_enable_profile_id_cmdid = | ||
| 103 | WMI_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID, | ||
| 104 | .wlan_profile_list_profile_id_cmdid = | ||
| 105 | WMI_WLAN_PROFILE_LIST_PROFILE_ID_CMDID, | ||
| 106 | .pdev_suspend_cmdid = WMI_PDEV_SUSPEND_CMDID, | ||
| 107 | .pdev_resume_cmdid = WMI_PDEV_RESUME_CMDID, | ||
| 108 | .add_bcn_filter_cmdid = WMI_ADD_BCN_FILTER_CMDID, | ||
| 109 | .rmv_bcn_filter_cmdid = WMI_RMV_BCN_FILTER_CMDID, | ||
| 110 | .wow_add_wake_pattern_cmdid = WMI_WOW_ADD_WAKE_PATTERN_CMDID, | ||
| 111 | .wow_del_wake_pattern_cmdid = WMI_WOW_DEL_WAKE_PATTERN_CMDID, | ||
| 112 | .wow_enable_disable_wake_event_cmdid = | ||
| 113 | WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID, | ||
| 114 | .wow_enable_cmdid = WMI_WOW_ENABLE_CMDID, | ||
| 115 | .wow_hostwakeup_from_sleep_cmdid = WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID, | ||
| 116 | .rtt_measreq_cmdid = WMI_RTT_MEASREQ_CMDID, | ||
| 117 | .rtt_tsf_cmdid = WMI_RTT_TSF_CMDID, | ||
| 118 | .vdev_spectral_scan_configure_cmdid = | ||
| 119 | WMI_VDEV_SPECTRAL_SCAN_CONFIGURE_CMDID, | ||
| 120 | .vdev_spectral_scan_enable_cmdid = WMI_VDEV_SPECTRAL_SCAN_ENABLE_CMDID, | ||
| 121 | .request_stats_cmdid = WMI_REQUEST_STATS_CMDID, | ||
| 122 | .set_arp_ns_offload_cmdid = WMI_SET_ARP_NS_OFFLOAD_CMDID, | ||
| 123 | .network_list_offload_config_cmdid = | ||
| 124 | WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID, | ||
| 125 | .gtk_offload_cmdid = WMI_GTK_OFFLOAD_CMDID, | ||
| 126 | .csa_offload_enable_cmdid = WMI_CSA_OFFLOAD_ENABLE_CMDID, | ||
| 127 | .csa_offload_chanswitch_cmdid = WMI_CSA_OFFLOAD_CHANSWITCH_CMDID, | ||
| 128 | .chatter_set_mode_cmdid = WMI_CHATTER_SET_MODE_CMDID, | ||
| 129 | .peer_tid_addba_cmdid = WMI_PEER_TID_ADDBA_CMDID, | ||
| 130 | .peer_tid_delba_cmdid = WMI_PEER_TID_DELBA_CMDID, | ||
| 131 | .sta_dtim_ps_method_cmdid = WMI_STA_DTIM_PS_METHOD_CMDID, | ||
| 132 | .sta_uapsd_auto_trig_cmdid = WMI_STA_UAPSD_AUTO_TRIG_CMDID, | ||
| 133 | .sta_keepalive_cmd = WMI_STA_KEEPALIVE_CMD, | ||
| 134 | .echo_cmdid = WMI_ECHO_CMDID, | ||
| 135 | .pdev_utf_cmdid = WMI_PDEV_UTF_CMDID, | ||
| 136 | .dbglog_cfg_cmdid = WMI_DBGLOG_CFG_CMDID, | ||
| 137 | .pdev_qvit_cmdid = WMI_PDEV_QVIT_CMDID, | ||
| 138 | .pdev_ftm_intg_cmdid = WMI_PDEV_FTM_INTG_CMDID, | ||
| 139 | .vdev_set_keepalive_cmdid = WMI_VDEV_SET_KEEPALIVE_CMDID, | ||
| 140 | .vdev_get_keepalive_cmdid = WMI_VDEV_GET_KEEPALIVE_CMDID, | ||
| 141 | .force_fw_hang_cmdid = WMI_FORCE_FW_HANG_CMDID, | ||
| 142 | .gpio_config_cmdid = WMI_GPIO_CONFIG_CMDID, | ||
| 143 | .gpio_output_cmdid = WMI_GPIO_OUTPUT_CMDID, | ||
| 144 | }; | ||
| 145 | |||
| 146 | /* 10.X WMI cmd track */ | ||
| 147 | static struct wmi_cmd_map wmi_10x_cmd_map = { | ||
| 148 | .init_cmdid = WMI_10X_INIT_CMDID, | ||
| 149 | .start_scan_cmdid = WMI_10X_START_SCAN_CMDID, | ||
| 150 | .stop_scan_cmdid = WMI_10X_STOP_SCAN_CMDID, | ||
| 151 | .scan_chan_list_cmdid = WMI_10X_SCAN_CHAN_LIST_CMDID, | ||
| 152 | .scan_sch_prio_tbl_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 153 | .pdev_set_regdomain_cmdid = WMI_10X_PDEV_SET_REGDOMAIN_CMDID, | ||
| 154 | .pdev_set_channel_cmdid = WMI_10X_PDEV_SET_CHANNEL_CMDID, | ||
| 155 | .pdev_set_param_cmdid = WMI_10X_PDEV_SET_PARAM_CMDID, | ||
| 156 | .pdev_pktlog_enable_cmdid = WMI_10X_PDEV_PKTLOG_ENABLE_CMDID, | ||
| 157 | .pdev_pktlog_disable_cmdid = WMI_10X_PDEV_PKTLOG_DISABLE_CMDID, | ||
| 158 | .pdev_set_wmm_params_cmdid = WMI_10X_PDEV_SET_WMM_PARAMS_CMDID, | ||
| 159 | .pdev_set_ht_cap_ie_cmdid = WMI_10X_PDEV_SET_HT_CAP_IE_CMDID, | ||
| 160 | .pdev_set_vht_cap_ie_cmdid = WMI_10X_PDEV_SET_VHT_CAP_IE_CMDID, | ||
| 161 | .pdev_set_dscp_tid_map_cmdid = WMI_10X_PDEV_SET_DSCP_TID_MAP_CMDID, | ||
| 162 | .pdev_set_quiet_mode_cmdid = WMI_10X_PDEV_SET_QUIET_MODE_CMDID, | ||
| 163 | .pdev_green_ap_ps_enable_cmdid = WMI_10X_PDEV_GREEN_AP_PS_ENABLE_CMDID, | ||
| 164 | .pdev_get_tpc_config_cmdid = WMI_10X_PDEV_GET_TPC_CONFIG_CMDID, | ||
| 165 | .pdev_set_base_macaddr_cmdid = WMI_10X_PDEV_SET_BASE_MACADDR_CMDID, | ||
| 166 | .vdev_create_cmdid = WMI_10X_VDEV_CREATE_CMDID, | ||
| 167 | .vdev_delete_cmdid = WMI_10X_VDEV_DELETE_CMDID, | ||
| 168 | .vdev_start_request_cmdid = WMI_10X_VDEV_START_REQUEST_CMDID, | ||
| 169 | .vdev_restart_request_cmdid = WMI_10X_VDEV_RESTART_REQUEST_CMDID, | ||
| 170 | .vdev_up_cmdid = WMI_10X_VDEV_UP_CMDID, | ||
| 171 | .vdev_stop_cmdid = WMI_10X_VDEV_STOP_CMDID, | ||
| 172 | .vdev_down_cmdid = WMI_10X_VDEV_DOWN_CMDID, | ||
| 173 | .vdev_set_param_cmdid = WMI_10X_VDEV_SET_PARAM_CMDID, | ||
| 174 | .vdev_install_key_cmdid = WMI_10X_VDEV_INSTALL_KEY_CMDID, | ||
| 175 | .peer_create_cmdid = WMI_10X_PEER_CREATE_CMDID, | ||
| 176 | .peer_delete_cmdid = WMI_10X_PEER_DELETE_CMDID, | ||
| 177 | .peer_flush_tids_cmdid = WMI_10X_PEER_FLUSH_TIDS_CMDID, | ||
| 178 | .peer_set_param_cmdid = WMI_10X_PEER_SET_PARAM_CMDID, | ||
| 179 | .peer_assoc_cmdid = WMI_10X_PEER_ASSOC_CMDID, | ||
| 180 | .peer_add_wds_entry_cmdid = WMI_10X_PEER_ADD_WDS_ENTRY_CMDID, | ||
| 181 | .peer_remove_wds_entry_cmdid = WMI_10X_PEER_REMOVE_WDS_ENTRY_CMDID, | ||
| 182 | .peer_mcast_group_cmdid = WMI_10X_PEER_MCAST_GROUP_CMDID, | ||
| 183 | .bcn_tx_cmdid = WMI_10X_BCN_TX_CMDID, | ||
| 184 | .pdev_send_bcn_cmdid = WMI_10X_PDEV_SEND_BCN_CMDID, | ||
| 185 | .bcn_tmpl_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 186 | .bcn_filter_rx_cmdid = WMI_10X_BCN_FILTER_RX_CMDID, | ||
| 187 | .prb_req_filter_rx_cmdid = WMI_10X_PRB_REQ_FILTER_RX_CMDID, | ||
| 188 | .mgmt_tx_cmdid = WMI_10X_MGMT_TX_CMDID, | ||
| 189 | .prb_tmpl_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 190 | .addba_clear_resp_cmdid = WMI_10X_ADDBA_CLEAR_RESP_CMDID, | ||
| 191 | .addba_send_cmdid = WMI_10X_ADDBA_SEND_CMDID, | ||
| 192 | .addba_status_cmdid = WMI_10X_ADDBA_STATUS_CMDID, | ||
| 193 | .delba_send_cmdid = WMI_10X_DELBA_SEND_CMDID, | ||
| 194 | .addba_set_resp_cmdid = WMI_10X_ADDBA_SET_RESP_CMDID, | ||
| 195 | .send_singleamsdu_cmdid = WMI_10X_SEND_SINGLEAMSDU_CMDID, | ||
| 196 | .sta_powersave_mode_cmdid = WMI_10X_STA_POWERSAVE_MODE_CMDID, | ||
| 197 | .sta_powersave_param_cmdid = WMI_10X_STA_POWERSAVE_PARAM_CMDID, | ||
| 198 | .sta_mimo_ps_mode_cmdid = WMI_10X_STA_MIMO_PS_MODE_CMDID, | ||
| 199 | .pdev_dfs_enable_cmdid = WMI_10X_PDEV_DFS_ENABLE_CMDID, | ||
| 200 | .pdev_dfs_disable_cmdid = WMI_10X_PDEV_DFS_DISABLE_CMDID, | ||
| 201 | .roam_scan_mode = WMI_10X_ROAM_SCAN_MODE, | ||
| 202 | .roam_scan_rssi_threshold = WMI_10X_ROAM_SCAN_RSSI_THRESHOLD, | ||
| 203 | .roam_scan_period = WMI_10X_ROAM_SCAN_PERIOD, | ||
| 204 | .roam_scan_rssi_change_threshold = | ||
| 205 | WMI_10X_ROAM_SCAN_RSSI_CHANGE_THRESHOLD, | ||
| 206 | .roam_ap_profile = WMI_10X_ROAM_AP_PROFILE, | ||
| 207 | .ofl_scan_add_ap_profile = WMI_10X_OFL_SCAN_ADD_AP_PROFILE, | ||
| 208 | .ofl_scan_remove_ap_profile = WMI_10X_OFL_SCAN_REMOVE_AP_PROFILE, | ||
| 209 | .ofl_scan_period = WMI_10X_OFL_SCAN_PERIOD, | ||
| 210 | .p2p_dev_set_device_info = WMI_10X_P2P_DEV_SET_DEVICE_INFO, | ||
| 211 | .p2p_dev_set_discoverability = WMI_10X_P2P_DEV_SET_DISCOVERABILITY, | ||
| 212 | .p2p_go_set_beacon_ie = WMI_10X_P2P_GO_SET_BEACON_IE, | ||
| 213 | .p2p_go_set_probe_resp_ie = WMI_10X_P2P_GO_SET_PROBE_RESP_IE, | ||
| 214 | .p2p_set_vendor_ie_data_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 215 | .ap_ps_peer_param_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 216 | .ap_ps_peer_uapsd_coex_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 217 | .peer_rate_retry_sched_cmdid = WMI_10X_PEER_RATE_RETRY_SCHED_CMDID, | ||
| 218 | .wlan_profile_trigger_cmdid = WMI_10X_WLAN_PROFILE_TRIGGER_CMDID, | ||
| 219 | .wlan_profile_set_hist_intvl_cmdid = | ||
| 220 | WMI_10X_WLAN_PROFILE_SET_HIST_INTVL_CMDID, | ||
| 221 | .wlan_profile_get_profile_data_cmdid = | ||
| 222 | WMI_10X_WLAN_PROFILE_GET_PROFILE_DATA_CMDID, | ||
| 223 | .wlan_profile_enable_profile_id_cmdid = | ||
| 224 | WMI_10X_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID, | ||
| 225 | .wlan_profile_list_profile_id_cmdid = | ||
| 226 | WMI_10X_WLAN_PROFILE_LIST_PROFILE_ID_CMDID, | ||
| 227 | .pdev_suspend_cmdid = WMI_10X_PDEV_SUSPEND_CMDID, | ||
| 228 | .pdev_resume_cmdid = WMI_10X_PDEV_RESUME_CMDID, | ||
| 229 | .add_bcn_filter_cmdid = WMI_10X_ADD_BCN_FILTER_CMDID, | ||
| 230 | .rmv_bcn_filter_cmdid = WMI_10X_RMV_BCN_FILTER_CMDID, | ||
| 231 | .wow_add_wake_pattern_cmdid = WMI_10X_WOW_ADD_WAKE_PATTERN_CMDID, | ||
| 232 | .wow_del_wake_pattern_cmdid = WMI_10X_WOW_DEL_WAKE_PATTERN_CMDID, | ||
| 233 | .wow_enable_disable_wake_event_cmdid = | ||
| 234 | WMI_10X_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID, | ||
| 235 | .wow_enable_cmdid = WMI_10X_WOW_ENABLE_CMDID, | ||
| 236 | .wow_hostwakeup_from_sleep_cmdid = | ||
| 237 | WMI_10X_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID, | ||
| 238 | .rtt_measreq_cmdid = WMI_10X_RTT_MEASREQ_CMDID, | ||
| 239 | .rtt_tsf_cmdid = WMI_10X_RTT_TSF_CMDID, | ||
| 240 | .vdev_spectral_scan_configure_cmdid = | ||
| 241 | WMI_10X_VDEV_SPECTRAL_SCAN_CONFIGURE_CMDID, | ||
| 242 | .vdev_spectral_scan_enable_cmdid = | ||
| 243 | WMI_10X_VDEV_SPECTRAL_SCAN_ENABLE_CMDID, | ||
| 244 | .request_stats_cmdid = WMI_10X_REQUEST_STATS_CMDID, | ||
| 245 | .set_arp_ns_offload_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 246 | .network_list_offload_config_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 247 | .gtk_offload_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 248 | .csa_offload_enable_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 249 | .csa_offload_chanswitch_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 250 | .chatter_set_mode_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 251 | .peer_tid_addba_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 252 | .peer_tid_delba_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 253 | .sta_dtim_ps_method_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 254 | .sta_uapsd_auto_trig_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 255 | .sta_keepalive_cmd = WMI_CMD_UNSUPPORTED, | ||
| 256 | .echo_cmdid = WMI_10X_ECHO_CMDID, | ||
| 257 | .pdev_utf_cmdid = WMI_10X_PDEV_UTF_CMDID, | ||
| 258 | .dbglog_cfg_cmdid = WMI_10X_DBGLOG_CFG_CMDID, | ||
| 259 | .pdev_qvit_cmdid = WMI_10X_PDEV_QVIT_CMDID, | ||
| 260 | .pdev_ftm_intg_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 261 | .vdev_set_keepalive_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 262 | .vdev_get_keepalive_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 263 | .force_fw_hang_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 264 | .gpio_config_cmdid = WMI_10X_GPIO_CONFIG_CMDID, | ||
| 265 | .gpio_output_cmdid = WMI_10X_GPIO_OUTPUT_CMDID, | ||
| 266 | }; | ||
| 267 | |||
| 268 | /* MAIN WMI VDEV param map */ | ||
| 269 | static struct wmi_vdev_param_map wmi_vdev_param_map = { | ||
| 270 | .rts_threshold = WMI_VDEV_PARAM_RTS_THRESHOLD, | ||
| 271 | .fragmentation_threshold = WMI_VDEV_PARAM_FRAGMENTATION_THRESHOLD, | ||
| 272 | .beacon_interval = WMI_VDEV_PARAM_BEACON_INTERVAL, | ||
| 273 | .listen_interval = WMI_VDEV_PARAM_LISTEN_INTERVAL, | ||
| 274 | .multicast_rate = WMI_VDEV_PARAM_MULTICAST_RATE, | ||
| 275 | .mgmt_tx_rate = WMI_VDEV_PARAM_MGMT_TX_RATE, | ||
| 276 | .slot_time = WMI_VDEV_PARAM_SLOT_TIME, | ||
| 277 | .preamble = WMI_VDEV_PARAM_PREAMBLE, | ||
| 278 | .swba_time = WMI_VDEV_PARAM_SWBA_TIME, | ||
| 279 | .wmi_vdev_stats_update_period = WMI_VDEV_STATS_UPDATE_PERIOD, | ||
| 280 | .wmi_vdev_pwrsave_ageout_time = WMI_VDEV_PWRSAVE_AGEOUT_TIME, | ||
| 281 | .wmi_vdev_host_swba_interval = WMI_VDEV_HOST_SWBA_INTERVAL, | ||
| 282 | .dtim_period = WMI_VDEV_PARAM_DTIM_PERIOD, | ||
| 283 | .wmi_vdev_oc_scheduler_air_time_limit = | ||
| 284 | WMI_VDEV_OC_SCHEDULER_AIR_TIME_LIMIT, | ||
| 285 | .wds = WMI_VDEV_PARAM_WDS, | ||
| 286 | .atim_window = WMI_VDEV_PARAM_ATIM_WINDOW, | ||
| 287 | .bmiss_count_max = WMI_VDEV_PARAM_BMISS_COUNT_MAX, | ||
| 288 | .bmiss_first_bcnt = WMI_VDEV_PARAM_BMISS_FIRST_BCNT, | ||
| 289 | .bmiss_final_bcnt = WMI_VDEV_PARAM_BMISS_FINAL_BCNT, | ||
| 290 | .feature_wmm = WMI_VDEV_PARAM_FEATURE_WMM, | ||
| 291 | .chwidth = WMI_VDEV_PARAM_CHWIDTH, | ||
| 292 | .chextoffset = WMI_VDEV_PARAM_CHEXTOFFSET, | ||
| 293 | .disable_htprotection = WMI_VDEV_PARAM_DISABLE_HTPROTECTION, | ||
| 294 | .sta_quickkickout = WMI_VDEV_PARAM_STA_QUICKKICKOUT, | ||
| 295 | .mgmt_rate = WMI_VDEV_PARAM_MGMT_RATE, | ||
| 296 | .protection_mode = WMI_VDEV_PARAM_PROTECTION_MODE, | ||
| 297 | .fixed_rate = WMI_VDEV_PARAM_FIXED_RATE, | ||
| 298 | .sgi = WMI_VDEV_PARAM_SGI, | ||
| 299 | .ldpc = WMI_VDEV_PARAM_LDPC, | ||
| 300 | .tx_stbc = WMI_VDEV_PARAM_TX_STBC, | ||
| 301 | .rx_stbc = WMI_VDEV_PARAM_RX_STBC, | ||
| 302 | .intra_bss_fwd = WMI_VDEV_PARAM_INTRA_BSS_FWD, | ||
| 303 | .def_keyid = WMI_VDEV_PARAM_DEF_KEYID, | ||
| 304 | .nss = WMI_VDEV_PARAM_NSS, | ||
| 305 | .bcast_data_rate = WMI_VDEV_PARAM_BCAST_DATA_RATE, | ||
| 306 | .mcast_data_rate = WMI_VDEV_PARAM_MCAST_DATA_RATE, | ||
| 307 | .mcast_indicate = WMI_VDEV_PARAM_MCAST_INDICATE, | ||
| 308 | .dhcp_indicate = WMI_VDEV_PARAM_DHCP_INDICATE, | ||
| 309 | .unknown_dest_indicate = WMI_VDEV_PARAM_UNKNOWN_DEST_INDICATE, | ||
| 310 | .ap_keepalive_min_idle_inactive_time_secs = | ||
| 311 | WMI_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS, | ||
| 312 | .ap_keepalive_max_idle_inactive_time_secs = | ||
| 313 | WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS, | ||
| 314 | .ap_keepalive_max_unresponsive_time_secs = | ||
| 315 | WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS, | ||
| 316 | .ap_enable_nawds = WMI_VDEV_PARAM_AP_ENABLE_NAWDS, | ||
| 317 | .mcast2ucast_set = WMI_VDEV_PARAM_UNSUPPORTED, | ||
| 318 | .enable_rtscts = WMI_VDEV_PARAM_ENABLE_RTSCTS, | ||
| 319 | .txbf = WMI_VDEV_PARAM_TXBF, | ||
| 320 | .packet_powersave = WMI_VDEV_PARAM_PACKET_POWERSAVE, | ||
| 321 | .drop_unencry = WMI_VDEV_PARAM_DROP_UNENCRY, | ||
| 322 | .tx_encap_type = WMI_VDEV_PARAM_TX_ENCAP_TYPE, | ||
| 323 | .ap_detect_out_of_sync_sleeping_sta_time_secs = | ||
| 324 | WMI_VDEV_PARAM_UNSUPPORTED, | ||
| 325 | }; | ||
| 326 | |||
| 327 | /* 10.X WMI VDEV param map */ | ||
| 328 | static struct wmi_vdev_param_map wmi_10x_vdev_param_map = { | ||
| 329 | .rts_threshold = WMI_10X_VDEV_PARAM_RTS_THRESHOLD, | ||
| 330 | .fragmentation_threshold = WMI_10X_VDEV_PARAM_FRAGMENTATION_THRESHOLD, | ||
| 331 | .beacon_interval = WMI_10X_VDEV_PARAM_BEACON_INTERVAL, | ||
| 332 | .listen_interval = WMI_10X_VDEV_PARAM_LISTEN_INTERVAL, | ||
| 333 | .multicast_rate = WMI_10X_VDEV_PARAM_MULTICAST_RATE, | ||
| 334 | .mgmt_tx_rate = WMI_10X_VDEV_PARAM_MGMT_TX_RATE, | ||
| 335 | .slot_time = WMI_10X_VDEV_PARAM_SLOT_TIME, | ||
| 336 | .preamble = WMI_10X_VDEV_PARAM_PREAMBLE, | ||
| 337 | .swba_time = WMI_10X_VDEV_PARAM_SWBA_TIME, | ||
| 338 | .wmi_vdev_stats_update_period = WMI_10X_VDEV_STATS_UPDATE_PERIOD, | ||
| 339 | .wmi_vdev_pwrsave_ageout_time = WMI_10X_VDEV_PWRSAVE_AGEOUT_TIME, | ||
| 340 | .wmi_vdev_host_swba_interval = WMI_10X_VDEV_HOST_SWBA_INTERVAL, | ||
| 341 | .dtim_period = WMI_10X_VDEV_PARAM_DTIM_PERIOD, | ||
| 342 | .wmi_vdev_oc_scheduler_air_time_limit = | ||
| 343 | WMI_10X_VDEV_OC_SCHEDULER_AIR_TIME_LIMIT, | ||
| 344 | .wds = WMI_10X_VDEV_PARAM_WDS, | ||
| 345 | .atim_window = WMI_10X_VDEV_PARAM_ATIM_WINDOW, | ||
| 346 | .bmiss_count_max = WMI_10X_VDEV_PARAM_BMISS_COUNT_MAX, | ||
| 347 | .bmiss_first_bcnt = WMI_VDEV_PARAM_UNSUPPORTED, | ||
| 348 | .bmiss_final_bcnt = WMI_VDEV_PARAM_UNSUPPORTED, | ||
| 349 | .feature_wmm = WMI_10X_VDEV_PARAM_FEATURE_WMM, | ||
| 350 | .chwidth = WMI_10X_VDEV_PARAM_CHWIDTH, | ||
| 351 | .chextoffset = WMI_10X_VDEV_PARAM_CHEXTOFFSET, | ||
| 352 | .disable_htprotection = WMI_10X_VDEV_PARAM_DISABLE_HTPROTECTION, | ||
| 353 | .sta_quickkickout = WMI_10X_VDEV_PARAM_STA_QUICKKICKOUT, | ||
| 354 | .mgmt_rate = WMI_10X_VDEV_PARAM_MGMT_RATE, | ||
| 355 | .protection_mode = WMI_10X_VDEV_PARAM_PROTECTION_MODE, | ||
| 356 | .fixed_rate = WMI_10X_VDEV_PARAM_FIXED_RATE, | ||
| 357 | .sgi = WMI_10X_VDEV_PARAM_SGI, | ||
| 358 | .ldpc = WMI_10X_VDEV_PARAM_LDPC, | ||
| 359 | .tx_stbc = WMI_10X_VDEV_PARAM_TX_STBC, | ||
| 360 | .rx_stbc = WMI_10X_VDEV_PARAM_RX_STBC, | ||
| 361 | .intra_bss_fwd = WMI_10X_VDEV_PARAM_INTRA_BSS_FWD, | ||
| 362 | .def_keyid = WMI_10X_VDEV_PARAM_DEF_KEYID, | ||
| 363 | .nss = WMI_10X_VDEV_PARAM_NSS, | ||
| 364 | .bcast_data_rate = WMI_10X_VDEV_PARAM_BCAST_DATA_RATE, | ||
| 365 | .mcast_data_rate = WMI_10X_VDEV_PARAM_MCAST_DATA_RATE, | ||
| 366 | .mcast_indicate = WMI_10X_VDEV_PARAM_MCAST_INDICATE, | ||
| 367 | .dhcp_indicate = WMI_10X_VDEV_PARAM_DHCP_INDICATE, | ||
| 368 | .unknown_dest_indicate = WMI_10X_VDEV_PARAM_UNKNOWN_DEST_INDICATE, | ||
| 369 | .ap_keepalive_min_idle_inactive_time_secs = | ||
| 370 | WMI_10X_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS, | ||
| 371 | .ap_keepalive_max_idle_inactive_time_secs = | ||
| 372 | WMI_10X_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS, | ||
| 373 | .ap_keepalive_max_unresponsive_time_secs = | ||
| 374 | WMI_10X_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS, | ||
| 375 | .ap_enable_nawds = WMI_10X_VDEV_PARAM_AP_ENABLE_NAWDS, | ||
| 376 | .mcast2ucast_set = WMI_10X_VDEV_PARAM_MCAST2UCAST_SET, | ||
| 377 | .enable_rtscts = WMI_10X_VDEV_PARAM_ENABLE_RTSCTS, | ||
| 378 | .txbf = WMI_VDEV_PARAM_UNSUPPORTED, | ||
| 379 | .packet_powersave = WMI_VDEV_PARAM_UNSUPPORTED, | ||
| 380 | .drop_unencry = WMI_VDEV_PARAM_UNSUPPORTED, | ||
| 381 | .tx_encap_type = WMI_VDEV_PARAM_UNSUPPORTED, | ||
| 382 | .ap_detect_out_of_sync_sleeping_sta_time_secs = | ||
| 383 | WMI_10X_VDEV_PARAM_AP_DETECT_OUT_OF_SYNC_SLEEPING_STA_TIME_SECS, | ||
| 384 | }; | ||
| 385 | |||
| 386 | static struct wmi_pdev_param_map wmi_pdev_param_map = { | ||
| 387 | .tx_chain_mask = WMI_PDEV_PARAM_TX_CHAIN_MASK, | ||
| 388 | .rx_chain_mask = WMI_PDEV_PARAM_RX_CHAIN_MASK, | ||
| 389 | .txpower_limit2g = WMI_PDEV_PARAM_TXPOWER_LIMIT2G, | ||
| 390 | .txpower_limit5g = WMI_PDEV_PARAM_TXPOWER_LIMIT5G, | ||
| 391 | .txpower_scale = WMI_PDEV_PARAM_TXPOWER_SCALE, | ||
| 392 | .beacon_gen_mode = WMI_PDEV_PARAM_BEACON_GEN_MODE, | ||
| 393 | .beacon_tx_mode = WMI_PDEV_PARAM_BEACON_TX_MODE, | ||
| 394 | .resmgr_offchan_mode = WMI_PDEV_PARAM_RESMGR_OFFCHAN_MODE, | ||
| 395 | .protection_mode = WMI_PDEV_PARAM_PROTECTION_MODE, | ||
| 396 | .dynamic_bw = WMI_PDEV_PARAM_DYNAMIC_BW, | ||
| 397 | .non_agg_sw_retry_th = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH, | ||
| 398 | .agg_sw_retry_th = WMI_PDEV_PARAM_AGG_SW_RETRY_TH, | ||
| 399 | .sta_kickout_th = WMI_PDEV_PARAM_STA_KICKOUT_TH, | ||
| 400 | .ac_aggrsize_scaling = WMI_PDEV_PARAM_AC_AGGRSIZE_SCALING, | ||
| 401 | .ltr_enable = WMI_PDEV_PARAM_LTR_ENABLE, | ||
| 402 | .ltr_ac_latency_be = WMI_PDEV_PARAM_LTR_AC_LATENCY_BE, | ||
| 403 | .ltr_ac_latency_bk = WMI_PDEV_PARAM_LTR_AC_LATENCY_BK, | ||
| 404 | .ltr_ac_latency_vi = WMI_PDEV_PARAM_LTR_AC_LATENCY_VI, | ||
| 405 | .ltr_ac_latency_vo = WMI_PDEV_PARAM_LTR_AC_LATENCY_VO, | ||
| 406 | .ltr_ac_latency_timeout = WMI_PDEV_PARAM_LTR_AC_LATENCY_TIMEOUT, | ||
| 407 | .ltr_sleep_override = WMI_PDEV_PARAM_LTR_SLEEP_OVERRIDE, | ||
| 408 | .ltr_rx_override = WMI_PDEV_PARAM_LTR_RX_OVERRIDE, | ||
| 409 | .ltr_tx_activity_timeout = WMI_PDEV_PARAM_LTR_TX_ACTIVITY_TIMEOUT, | ||
| 410 | .l1ss_enable = WMI_PDEV_PARAM_L1SS_ENABLE, | ||
| 411 | .dsleep_enable = WMI_PDEV_PARAM_DSLEEP_ENABLE, | ||
| 412 | .pcielp_txbuf_flush = WMI_PDEV_PARAM_PCIELP_TXBUF_FLUSH, | ||
| 413 | .pcielp_txbuf_watermark = WMI_PDEV_PARAM_PCIELP_TXBUF_TMO_EN, | ||
| 414 | .pcielp_txbuf_tmo_en = WMI_PDEV_PARAM_PCIELP_TXBUF_TMO_EN, | ||
| 415 | .pcielp_txbuf_tmo_value = WMI_PDEV_PARAM_PCIELP_TXBUF_TMO_VALUE, | ||
| 416 | .pdev_stats_update_period = WMI_PDEV_PARAM_PDEV_STATS_UPDATE_PERIOD, | ||
| 417 | .vdev_stats_update_period = WMI_PDEV_PARAM_VDEV_STATS_UPDATE_PERIOD, | ||
| 418 | .peer_stats_update_period = WMI_PDEV_PARAM_PEER_STATS_UPDATE_PERIOD, | ||
| 419 | .bcnflt_stats_update_period = WMI_PDEV_PARAM_BCNFLT_STATS_UPDATE_PERIOD, | ||
| 420 | .pmf_qos = WMI_PDEV_PARAM_PMF_QOS, | ||
| 421 | .arp_ac_override = WMI_PDEV_PARAM_ARP_AC_OVERRIDE, | ||
| 422 | .arpdhcp_ac_override = WMI_PDEV_PARAM_UNSUPPORTED, | ||
| 423 | .dcs = WMI_PDEV_PARAM_DCS, | ||
| 424 | .ani_enable = WMI_PDEV_PARAM_ANI_ENABLE, | ||
| 425 | .ani_poll_period = WMI_PDEV_PARAM_ANI_POLL_PERIOD, | ||
| 426 | .ani_listen_period = WMI_PDEV_PARAM_ANI_LISTEN_PERIOD, | ||
| 427 | .ani_ofdm_level = WMI_PDEV_PARAM_ANI_OFDM_LEVEL, | ||
| 428 | .ani_cck_level = WMI_PDEV_PARAM_ANI_CCK_LEVEL, | ||
| 429 | .dyntxchain = WMI_PDEV_PARAM_DYNTXCHAIN, | ||
| 430 | .proxy_sta = WMI_PDEV_PARAM_PROXY_STA, | ||
| 431 | .idle_ps_config = WMI_PDEV_PARAM_IDLE_PS_CONFIG, | ||
| 432 | .power_gating_sleep = WMI_PDEV_PARAM_POWER_GATING_SLEEP, | ||
| 433 | .fast_channel_reset = WMI_PDEV_PARAM_UNSUPPORTED, | ||
| 434 | .burst_dur = WMI_PDEV_PARAM_UNSUPPORTED, | ||
| 435 | .burst_enable = WMI_PDEV_PARAM_UNSUPPORTED, | ||
| 436 | }; | ||
| 437 | |||
| 438 | static struct wmi_pdev_param_map wmi_10x_pdev_param_map = { | ||
| 439 | .tx_chain_mask = WMI_10X_PDEV_PARAM_TX_CHAIN_MASK, | ||
| 440 | .rx_chain_mask = WMI_10X_PDEV_PARAM_RX_CHAIN_MASK, | ||
| 441 | .txpower_limit2g = WMI_10X_PDEV_PARAM_TXPOWER_LIMIT2G, | ||
| 442 | .txpower_limit5g = WMI_10X_PDEV_PARAM_TXPOWER_LIMIT5G, | ||
| 443 | .txpower_scale = WMI_10X_PDEV_PARAM_TXPOWER_SCALE, | ||
| 444 | .beacon_gen_mode = WMI_10X_PDEV_PARAM_BEACON_GEN_MODE, | ||
| 445 | .beacon_tx_mode = WMI_10X_PDEV_PARAM_BEACON_TX_MODE, | ||
| 446 | .resmgr_offchan_mode = WMI_10X_PDEV_PARAM_RESMGR_OFFCHAN_MODE, | ||
| 447 | .protection_mode = WMI_10X_PDEV_PARAM_PROTECTION_MODE, | ||
| 448 | .dynamic_bw = WMI_10X_PDEV_PARAM_DYNAMIC_BW, | ||
| 449 | .non_agg_sw_retry_th = WMI_10X_PDEV_PARAM_NON_AGG_SW_RETRY_TH, | ||
| 450 | .agg_sw_retry_th = WMI_10X_PDEV_PARAM_AGG_SW_RETRY_TH, | ||
| 451 | .sta_kickout_th = WMI_10X_PDEV_PARAM_STA_KICKOUT_TH, | ||
| 452 | .ac_aggrsize_scaling = WMI_10X_PDEV_PARAM_AC_AGGRSIZE_SCALING, | ||
| 453 | .ltr_enable = WMI_10X_PDEV_PARAM_LTR_ENABLE, | ||
| 454 | .ltr_ac_latency_be = WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_BE, | ||
| 455 | .ltr_ac_latency_bk = WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_BK, | ||
| 456 | .ltr_ac_latency_vi = WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_VI, | ||
| 457 | .ltr_ac_latency_vo = WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_VO, | ||
| 458 | .ltr_ac_latency_timeout = WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_TIMEOUT, | ||
| 459 | .ltr_sleep_override = WMI_10X_PDEV_PARAM_LTR_SLEEP_OVERRIDE, | ||
| 460 | .ltr_rx_override = WMI_10X_PDEV_PARAM_LTR_RX_OVERRIDE, | ||
| 461 | .ltr_tx_activity_timeout = WMI_10X_PDEV_PARAM_LTR_TX_ACTIVITY_TIMEOUT, | ||
| 462 | .l1ss_enable = WMI_10X_PDEV_PARAM_L1SS_ENABLE, | ||
| 463 | .dsleep_enable = WMI_10X_PDEV_PARAM_DSLEEP_ENABLE, | ||
| 464 | .pcielp_txbuf_flush = WMI_PDEV_PARAM_UNSUPPORTED, | ||
| 465 | .pcielp_txbuf_watermark = WMI_PDEV_PARAM_UNSUPPORTED, | ||
| 466 | .pcielp_txbuf_tmo_en = WMI_PDEV_PARAM_UNSUPPORTED, | ||
| 467 | .pcielp_txbuf_tmo_value = WMI_PDEV_PARAM_UNSUPPORTED, | ||
| 468 | .pdev_stats_update_period = WMI_10X_PDEV_PARAM_PDEV_STATS_UPDATE_PERIOD, | ||
| 469 | .vdev_stats_update_period = WMI_10X_PDEV_PARAM_VDEV_STATS_UPDATE_PERIOD, | ||
| 470 | .peer_stats_update_period = WMI_10X_PDEV_PARAM_PEER_STATS_UPDATE_PERIOD, | ||
| 471 | .bcnflt_stats_update_period = | ||
| 472 | WMI_10X_PDEV_PARAM_BCNFLT_STATS_UPDATE_PERIOD, | ||
| 473 | .pmf_qos = WMI_10X_PDEV_PARAM_PMF_QOS, | ||
| 474 | .arp_ac_override = WMI_PDEV_PARAM_UNSUPPORTED, | ||
| 475 | .arpdhcp_ac_override = WMI_10X_PDEV_PARAM_ARPDHCP_AC_OVERRIDE, | ||
| 476 | .dcs = WMI_10X_PDEV_PARAM_DCS, | ||
| 477 | .ani_enable = WMI_10X_PDEV_PARAM_ANI_ENABLE, | ||
| 478 | .ani_poll_period = WMI_10X_PDEV_PARAM_ANI_POLL_PERIOD, | ||
| 479 | .ani_listen_period = WMI_10X_PDEV_PARAM_ANI_LISTEN_PERIOD, | ||
| 480 | .ani_ofdm_level = WMI_10X_PDEV_PARAM_ANI_OFDM_LEVEL, | ||
| 481 | .ani_cck_level = WMI_10X_PDEV_PARAM_ANI_CCK_LEVEL, | ||
| 482 | .dyntxchain = WMI_10X_PDEV_PARAM_DYNTXCHAIN, | ||
| 483 | .proxy_sta = WMI_PDEV_PARAM_UNSUPPORTED, | ||
| 484 | .idle_ps_config = WMI_PDEV_PARAM_UNSUPPORTED, | ||
| 485 | .power_gating_sleep = WMI_PDEV_PARAM_UNSUPPORTED, | ||
| 486 | .fast_channel_reset = WMI_10X_PDEV_PARAM_FAST_CHANNEL_RESET, | ||
| 487 | .burst_dur = WMI_10X_PDEV_PARAM_BURST_DUR, | ||
| 488 | .burst_enable = WMI_10X_PDEV_PARAM_BURST_ENABLE, | ||
| 489 | }; | ||
| 490 | |||
| 26 | int ath10k_wmi_wait_for_service_ready(struct ath10k *ar) | 491 | int ath10k_wmi_wait_for_service_ready(struct ath10k *ar) |
| 27 | { | 492 | { |
| 28 | int ret; | 493 | int ret; |
| @@ -64,7 +529,7 @@ static void ath10k_wmi_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb) | |||
| 64 | } | 529 | } |
| 65 | 530 | ||
| 66 | static int ath10k_wmi_cmd_send_nowait(struct ath10k *ar, struct sk_buff *skb, | 531 | static int ath10k_wmi_cmd_send_nowait(struct ath10k *ar, struct sk_buff *skb, |
| 67 | enum wmi_cmd_id cmd_id) | 532 | u32 cmd_id) |
| 68 | { | 533 | { |
| 69 | struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb); | 534 | struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb); |
| 70 | struct wmi_cmd_hdr *cmd_hdr; | 535 | struct wmi_cmd_hdr *cmd_hdr; |
| @@ -144,9 +609,17 @@ static void ath10k_wmi_op_ep_tx_credits(struct ath10k *ar) | |||
| 144 | } | 609 | } |
| 145 | 610 | ||
| 146 | static int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, | 611 | static int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, |
| 147 | enum wmi_cmd_id cmd_id) | 612 | u32 cmd_id) |
| 148 | { | 613 | { |
| 149 | int ret = -EINVAL; | 614 | int ret = -EOPNOTSUPP; |
| 615 | |||
| 616 | might_sleep(); | ||
| 617 | |||
| 618 | if (cmd_id == WMI_CMD_UNSUPPORTED) { | ||
| 619 | ath10k_warn("wmi command %d is not supported by firmware\n", | ||
| 620 | cmd_id); | ||
| 621 | return ret; | ||
| 622 | } | ||
| 150 | 623 | ||
| 151 | wait_event_timeout(ar->wmi.tx_credits_wq, ({ | 624 | wait_event_timeout(ar->wmi.tx_credits_wq, ({ |
| 152 | /* try to send pending beacons first. they take priority */ | 625 | /* try to send pending beacons first. they take priority */ |
| @@ -162,6 +635,57 @@ static int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, | |||
| 162 | return ret; | 635 | return ret; |
| 163 | } | 636 | } |
| 164 | 637 | ||
| 638 | int ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *skb) | ||
| 639 | { | ||
| 640 | int ret = 0; | ||
| 641 | struct wmi_mgmt_tx_cmd *cmd; | ||
| 642 | struct ieee80211_hdr *hdr; | ||
| 643 | struct sk_buff *wmi_skb; | ||
| 644 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
| 645 | int len; | ||
| 646 | u16 fc; | ||
| 647 | |||
| 648 | hdr = (struct ieee80211_hdr *)skb->data; | ||
| 649 | fc = le16_to_cpu(hdr->frame_control); | ||
| 650 | |||
| 651 | if (WARN_ON_ONCE(!ieee80211_is_mgmt(hdr->frame_control))) | ||
| 652 | return -EINVAL; | ||
| 653 | |||
| 654 | len = sizeof(cmd->hdr) + skb->len; | ||
| 655 | len = round_up(len, 4); | ||
| 656 | |||
| 657 | wmi_skb = ath10k_wmi_alloc_skb(len); | ||
| 658 | if (!wmi_skb) | ||
| 659 | return -ENOMEM; | ||
| 660 | |||
| 661 | cmd = (struct wmi_mgmt_tx_cmd *)wmi_skb->data; | ||
| 662 | |||
| 663 | cmd->hdr.vdev_id = __cpu_to_le32(ATH10K_SKB_CB(skb)->vdev_id); | ||
| 664 | cmd->hdr.tx_rate = 0; | ||
| 665 | cmd->hdr.tx_power = 0; | ||
| 666 | cmd->hdr.buf_len = __cpu_to_le32((u32)(skb->len)); | ||
| 667 | |||
| 668 | memcpy(cmd->hdr.peer_macaddr.addr, ieee80211_get_DA(hdr), ETH_ALEN); | ||
| 669 | memcpy(cmd->buf, skb->data, skb->len); | ||
| 670 | |||
| 671 | ath10k_dbg(ATH10K_DBG_WMI, "wmi mgmt tx skb %p len %d ftype %02x stype %02x\n", | ||
| 672 | wmi_skb, wmi_skb->len, fc & IEEE80211_FCTL_FTYPE, | ||
| 673 | fc & IEEE80211_FCTL_STYPE); | ||
| 674 | |||
| 675 | /* Send the management frame buffer to the target */ | ||
| 676 | ret = ath10k_wmi_cmd_send(ar, wmi_skb, ar->wmi.cmd->mgmt_tx_cmdid); | ||
| 677 | if (ret) { | ||
| 678 | dev_kfree_skb_any(skb); | ||
| 679 | return ret; | ||
| 680 | } | ||
| 681 | |||
| 682 | /* TODO: report tx status to mac80211 - temporary just ACK */ | ||
| 683 | info->flags |= IEEE80211_TX_STAT_ACK; | ||
| 684 | ieee80211_tx_status_irqsafe(ar->hw, skb); | ||
| 685 | |||
| 686 | return ret; | ||
| 687 | } | ||
| 688 | |||
| 165 | static int ath10k_wmi_event_scan(struct ath10k *ar, struct sk_buff *skb) | 689 | static int ath10k_wmi_event_scan(struct ath10k *ar, struct sk_buff *skb) |
| 166 | { | 690 | { |
| 167 | struct wmi_scan_event *event = (struct wmi_scan_event *)skb->data; | 691 | struct wmi_scan_event *event = (struct wmi_scan_event *)skb->data; |
| @@ -964,6 +1488,55 @@ static void ath10k_wmi_event_vdev_install_key_complete(struct ath10k *ar, | |||
| 964 | ath10k_dbg(ATH10K_DBG_WMI, "WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID\n"); | 1488 | ath10k_dbg(ATH10K_DBG_WMI, "WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID\n"); |
| 965 | } | 1489 | } |
| 966 | 1490 | ||
| 1491 | static void ath10k_wmi_event_inst_rssi_stats(struct ath10k *ar, | ||
| 1492 | struct sk_buff *skb) | ||
| 1493 | { | ||
| 1494 | ath10k_dbg(ATH10K_DBG_WMI, "WMI_INST_RSSI_STATS_EVENTID\n"); | ||
| 1495 | } | ||
| 1496 | |||
| 1497 | static void ath10k_wmi_event_vdev_standby_req(struct ath10k *ar, | ||
| 1498 | struct sk_buff *skb) | ||
| 1499 | { | ||
| 1500 | ath10k_dbg(ATH10K_DBG_WMI, "WMI_VDEV_STANDBY_REQ_EVENTID\n"); | ||
| 1501 | } | ||
| 1502 | |||
| 1503 | static void ath10k_wmi_event_vdev_resume_req(struct ath10k *ar, | ||
| 1504 | struct sk_buff *skb) | ||
| 1505 | { | ||
| 1506 | ath10k_dbg(ATH10K_DBG_WMI, "WMI_VDEV_RESUME_REQ_EVENTID\n"); | ||
| 1507 | } | ||
| 1508 | |||
| 1509 | static int ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32 req_id, | ||
| 1510 | u32 num_units, u32 unit_len) | ||
| 1511 | { | ||
| 1512 | dma_addr_t paddr; | ||
| 1513 | u32 pool_size; | ||
| 1514 | int idx = ar->wmi.num_mem_chunks; | ||
| 1515 | |||
| 1516 | pool_size = num_units * round_up(unit_len, 4); | ||
| 1517 | |||
| 1518 | if (!pool_size) | ||
| 1519 | return -EINVAL; | ||
| 1520 | |||
| 1521 | ar->wmi.mem_chunks[idx].vaddr = dma_alloc_coherent(ar->dev, | ||
| 1522 | pool_size, | ||
| 1523 | &paddr, | ||
| 1524 | GFP_ATOMIC); | ||
| 1525 | if (!ar->wmi.mem_chunks[idx].vaddr) { | ||
| 1526 | ath10k_warn("failed to allocate memory chunk\n"); | ||
| 1527 | return -ENOMEM; | ||
| 1528 | } | ||
| 1529 | |||
| 1530 | memset(ar->wmi.mem_chunks[idx].vaddr, 0, pool_size); | ||
| 1531 | |||
| 1532 | ar->wmi.mem_chunks[idx].paddr = paddr; | ||
| 1533 | ar->wmi.mem_chunks[idx].len = pool_size; | ||
| 1534 | ar->wmi.mem_chunks[idx].req_id = req_id; | ||
| 1535 | ar->wmi.num_mem_chunks++; | ||
| 1536 | |||
| 1537 | return 0; | ||
| 1538 | } | ||
| 1539 | |||
| 967 | static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar, | 1540 | static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar, |
| 968 | struct sk_buff *skb) | 1541 | struct sk_buff *skb) |
| 969 | { | 1542 | { |
| @@ -988,7 +1561,8 @@ static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar, | |||
| 988 | ar->phy_capability = __le32_to_cpu(ev->phy_capability); | 1561 | ar->phy_capability = __le32_to_cpu(ev->phy_capability); |
| 989 | ar->num_rf_chains = __le32_to_cpu(ev->num_rf_chains); | 1562 | ar->num_rf_chains = __le32_to_cpu(ev->num_rf_chains); |
| 990 | 1563 | ||
| 991 | if (ar->fw_version_build > 636) | 1564 | /* only manually set fw features when not using FW IE format */ |
| 1565 | if (ar->fw_api == 1 && ar->fw_version_build > 636) | ||
| 992 | set_bit(ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX, ar->fw_features); | 1566 | set_bit(ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX, ar->fw_features); |
| 993 | 1567 | ||
| 994 | if (ar->num_rf_chains > WMI_MAX_SPATIAL_STREAM) { | 1568 | if (ar->num_rf_chains > WMI_MAX_SPATIAL_STREAM) { |
| @@ -1035,6 +1609,108 @@ static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar, | |||
| 1035 | complete(&ar->wmi.service_ready); | 1609 | complete(&ar->wmi.service_ready); |
| 1036 | } | 1610 | } |
| 1037 | 1611 | ||
| 1612 | static void ath10k_wmi_10x_service_ready_event_rx(struct ath10k *ar, | ||
| 1613 | struct sk_buff *skb) | ||
| 1614 | { | ||
| 1615 | u32 num_units, req_id, unit_size, num_mem_reqs, num_unit_info, i; | ||
| 1616 | int ret; | ||
| 1617 | struct wmi_service_ready_event_10x *ev = (void *)skb->data; | ||
| 1618 | |||
| 1619 | if (skb->len < sizeof(*ev)) { | ||
| 1620 | ath10k_warn("Service ready event was %d B but expected %zu B. Wrong firmware version?\n", | ||
| 1621 | skb->len, sizeof(*ev)); | ||
| 1622 | return; | ||
| 1623 | } | ||
| 1624 | |||
| 1625 | ar->hw_min_tx_power = __le32_to_cpu(ev->hw_min_tx_power); | ||
| 1626 | ar->hw_max_tx_power = __le32_to_cpu(ev->hw_max_tx_power); | ||
| 1627 | ar->ht_cap_info = __le32_to_cpu(ev->ht_cap_info); | ||
| 1628 | ar->vht_cap_info = __le32_to_cpu(ev->vht_cap_info); | ||
| 1629 | ar->fw_version_major = | ||
| 1630 | (__le32_to_cpu(ev->sw_version) & 0xff000000) >> 24; | ||
| 1631 | ar->fw_version_minor = (__le32_to_cpu(ev->sw_version) & 0x00ffffff); | ||
| 1632 | ar->phy_capability = __le32_to_cpu(ev->phy_capability); | ||
| 1633 | ar->num_rf_chains = __le32_to_cpu(ev->num_rf_chains); | ||
| 1634 | |||
| 1635 | if (ar->num_rf_chains > WMI_MAX_SPATIAL_STREAM) { | ||
| 1636 | ath10k_warn("hardware advertises support for more spatial streams than it should (%d > %d)\n", | ||
| 1637 | ar->num_rf_chains, WMI_MAX_SPATIAL_STREAM); | ||
| 1638 | ar->num_rf_chains = WMI_MAX_SPATIAL_STREAM; | ||
| 1639 | } | ||
| 1640 | |||
| 1641 | ar->ath_common.regulatory.current_rd = | ||
| 1642 | __le32_to_cpu(ev->hal_reg_capabilities.eeprom_rd); | ||
| 1643 | |||
| 1644 | ath10k_debug_read_service_map(ar, ev->wmi_service_bitmap, | ||
| 1645 | sizeof(ev->wmi_service_bitmap)); | ||
| 1646 | |||
| 1647 | if (strlen(ar->hw->wiphy->fw_version) == 0) { | ||
| 1648 | snprintf(ar->hw->wiphy->fw_version, | ||
| 1649 | sizeof(ar->hw->wiphy->fw_version), | ||
| 1650 | "%u.%u", | ||
| 1651 | ar->fw_version_major, | ||
| 1652 | ar->fw_version_minor); | ||
| 1653 | } | ||
| 1654 | |||
| 1655 | num_mem_reqs = __le32_to_cpu(ev->num_mem_reqs); | ||
| 1656 | |||
| 1657 | if (num_mem_reqs > ATH10K_MAX_MEM_REQS) { | ||
| 1658 | ath10k_warn("requested memory chunks number (%d) exceeds the limit\n", | ||
| 1659 | num_mem_reqs); | ||
| 1660 | return; | ||
| 1661 | } | ||
| 1662 | |||
| 1663 | if (!num_mem_reqs) | ||
| 1664 | goto exit; | ||
| 1665 | |||
| 1666 | ath10k_dbg(ATH10K_DBG_WMI, "firmware has requested %d memory chunks\n", | ||
| 1667 | num_mem_reqs); | ||
| 1668 | |||
| 1669 | for (i = 0; i < num_mem_reqs; ++i) { | ||
| 1670 | req_id = __le32_to_cpu(ev->mem_reqs[i].req_id); | ||
| 1671 | num_units = __le32_to_cpu(ev->mem_reqs[i].num_units); | ||
| 1672 | unit_size = __le32_to_cpu(ev->mem_reqs[i].unit_size); | ||
| 1673 | num_unit_info = __le32_to_cpu(ev->mem_reqs[i].num_unit_info); | ||
| 1674 | |||
| 1675 | if (num_unit_info & NUM_UNITS_IS_NUM_PEERS) | ||
| 1676 | /* number of units to allocate is number of | ||
| 1677 | * peers, 1 extra for self peer on target */ | ||
| 1678 | /* this needs to be tied, host and target | ||
| 1679 | * can get out of sync */ | ||
| 1680 | num_units = TARGET_10X_NUM_PEERS + 1; | ||
| 1681 | else if (num_unit_info & NUM_UNITS_IS_NUM_VDEVS) | ||
| 1682 | num_units = TARGET_10X_NUM_VDEVS + 1; | ||
| 1683 | |||
| 1684 | ath10k_dbg(ATH10K_DBG_WMI, | ||
| 1685 | "wmi mem_req_id %d num_units %d num_unit_info %d unit size %d actual units %d\n", | ||
| 1686 | req_id, | ||
| 1687 | __le32_to_cpu(ev->mem_reqs[i].num_units), | ||
| 1688 | num_unit_info, | ||
| 1689 | unit_size, | ||
| 1690 | num_units); | ||
| 1691 | |||
| 1692 | ret = ath10k_wmi_alloc_host_mem(ar, req_id, num_units, | ||
| 1693 | unit_size); | ||
| 1694 | if (ret) | ||
| 1695 | return; | ||
| 1696 | } | ||
| 1697 | |||
| 1698 | exit: | ||
| 1699 | ath10k_dbg(ATH10K_DBG_WMI, | ||
| 1700 | "wmi event service ready sw_ver 0x%08x abi_ver %u phy_cap 0x%08x ht_cap 0x%08x vht_cap 0x%08x vht_supp_msc 0x%08x sys_cap_info 0x%08x mem_reqs %u num_rf_chains %u\n", | ||
| 1701 | __le32_to_cpu(ev->sw_version), | ||
| 1702 | __le32_to_cpu(ev->abi_version), | ||
| 1703 | __le32_to_cpu(ev->phy_capability), | ||
| 1704 | __le32_to_cpu(ev->ht_cap_info), | ||
| 1705 | __le32_to_cpu(ev->vht_cap_info), | ||
| 1706 | __le32_to_cpu(ev->vht_supp_mcs), | ||
| 1707 | __le32_to_cpu(ev->sys_cap_info), | ||
| 1708 | __le32_to_cpu(ev->num_mem_reqs), | ||
| 1709 | __le32_to_cpu(ev->num_rf_chains)); | ||
| 1710 | |||
| 1711 | complete(&ar->wmi.service_ready); | ||
| 1712 | } | ||
| 1713 | |||
| 1038 | static int ath10k_wmi_ready_event_rx(struct ath10k *ar, struct sk_buff *skb) | 1714 | static int ath10k_wmi_ready_event_rx(struct ath10k *ar, struct sk_buff *skb) |
| 1039 | { | 1715 | { |
| 1040 | struct wmi_ready_event *ev = (struct wmi_ready_event *)skb->data; | 1716 | struct wmi_ready_event *ev = (struct wmi_ready_event *)skb->data; |
| @@ -1055,7 +1731,7 @@ static int ath10k_wmi_ready_event_rx(struct ath10k *ar, struct sk_buff *skb) | |||
| 1055 | return 0; | 1731 | return 0; |
| 1056 | } | 1732 | } |
| 1057 | 1733 | ||
| 1058 | static void ath10k_wmi_process_rx(struct ath10k *ar, struct sk_buff *skb) | 1734 | static void ath10k_wmi_main_process_rx(struct ath10k *ar, struct sk_buff *skb) |
| 1059 | { | 1735 | { |
| 1060 | struct wmi_cmd_hdr *cmd_hdr; | 1736 | struct wmi_cmd_hdr *cmd_hdr; |
| 1061 | enum wmi_event_id id; | 1737 | enum wmi_event_id id; |
| @@ -1174,9 +1850,138 @@ static void ath10k_wmi_process_rx(struct ath10k *ar, struct sk_buff *skb) | |||
| 1174 | dev_kfree_skb(skb); | 1850 | dev_kfree_skb(skb); |
| 1175 | } | 1851 | } |
| 1176 | 1852 | ||
| 1853 | static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb) | ||
| 1854 | { | ||
| 1855 | struct wmi_cmd_hdr *cmd_hdr; | ||
| 1856 | enum wmi_10x_event_id id; | ||
| 1857 | u16 len; | ||
| 1858 | |||
| 1859 | cmd_hdr = (struct wmi_cmd_hdr *)skb->data; | ||
| 1860 | id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); | ||
| 1861 | |||
| 1862 | if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL) | ||
| 1863 | return; | ||
| 1864 | |||
| 1865 | len = skb->len; | ||
| 1866 | |||
| 1867 | trace_ath10k_wmi_event(id, skb->data, skb->len); | ||
| 1868 | |||
| 1869 | switch (id) { | ||
| 1870 | case WMI_10X_MGMT_RX_EVENTID: | ||
| 1871 | ath10k_wmi_event_mgmt_rx(ar, skb); | ||
| 1872 | /* mgmt_rx() owns the skb now! */ | ||
| 1873 | return; | ||
| 1874 | case WMI_10X_SCAN_EVENTID: | ||
| 1875 | ath10k_wmi_event_scan(ar, skb); | ||
| 1876 | break; | ||
| 1877 | case WMI_10X_CHAN_INFO_EVENTID: | ||
| 1878 | ath10k_wmi_event_chan_info(ar, skb); | ||
| 1879 | break; | ||
| 1880 | case WMI_10X_ECHO_EVENTID: | ||
| 1881 | ath10k_wmi_event_echo(ar, skb); | ||
| 1882 | break; | ||
| 1883 | case WMI_10X_DEBUG_MESG_EVENTID: | ||
| 1884 | ath10k_wmi_event_debug_mesg(ar, skb); | ||
| 1885 | break; | ||
| 1886 | case WMI_10X_UPDATE_STATS_EVENTID: | ||
| 1887 | ath10k_wmi_event_update_stats(ar, skb); | ||
| 1888 | break; | ||
| 1889 | case WMI_10X_VDEV_START_RESP_EVENTID: | ||
| 1890 | ath10k_wmi_event_vdev_start_resp(ar, skb); | ||
| 1891 | break; | ||
| 1892 | case WMI_10X_VDEV_STOPPED_EVENTID: | ||
| 1893 | ath10k_wmi_event_vdev_stopped(ar, skb); | ||
| 1894 | break; | ||
| 1895 | case WMI_10X_PEER_STA_KICKOUT_EVENTID: | ||
| 1896 | ath10k_wmi_event_peer_sta_kickout(ar, skb); | ||
| 1897 | break; | ||
| 1898 | case WMI_10X_HOST_SWBA_EVENTID: | ||
| 1899 | ath10k_wmi_event_host_swba(ar, skb); | ||
| 1900 | break; | ||
| 1901 | case WMI_10X_TBTTOFFSET_UPDATE_EVENTID: | ||
| 1902 | ath10k_wmi_event_tbttoffset_update(ar, skb); | ||
| 1903 | break; | ||
| 1904 | case WMI_10X_PHYERR_EVENTID: | ||
| 1905 | ath10k_wmi_event_phyerr(ar, skb); | ||
| 1906 | break; | ||
| 1907 | case WMI_10X_ROAM_EVENTID: | ||
| 1908 | ath10k_wmi_event_roam(ar, skb); | ||
| 1909 | break; | ||
| 1910 | case WMI_10X_PROFILE_MATCH: | ||
| 1911 | ath10k_wmi_event_profile_match(ar, skb); | ||
| 1912 | break; | ||
| 1913 | case WMI_10X_DEBUG_PRINT_EVENTID: | ||
| 1914 | ath10k_wmi_event_debug_print(ar, skb); | ||
| 1915 | break; | ||
| 1916 | case WMI_10X_PDEV_QVIT_EVENTID: | ||
| 1917 | ath10k_wmi_event_pdev_qvit(ar, skb); | ||
| 1918 | break; | ||
| 1919 | case WMI_10X_WLAN_PROFILE_DATA_EVENTID: | ||
| 1920 | ath10k_wmi_event_wlan_profile_data(ar, skb); | ||
| 1921 | break; | ||
| 1922 | case WMI_10X_RTT_MEASUREMENT_REPORT_EVENTID: | ||
| 1923 | ath10k_wmi_event_rtt_measurement_report(ar, skb); | ||
| 1924 | break; | ||
| 1925 | case WMI_10X_TSF_MEASUREMENT_REPORT_EVENTID: | ||
| 1926 | ath10k_wmi_event_tsf_measurement_report(ar, skb); | ||
| 1927 | break; | ||
| 1928 | case WMI_10X_RTT_ERROR_REPORT_EVENTID: | ||
| 1929 | ath10k_wmi_event_rtt_error_report(ar, skb); | ||
| 1930 | break; | ||
| 1931 | case WMI_10X_WOW_WAKEUP_HOST_EVENTID: | ||
| 1932 | ath10k_wmi_event_wow_wakeup_host(ar, skb); | ||
| 1933 | break; | ||
| 1934 | case WMI_10X_DCS_INTERFERENCE_EVENTID: | ||
| 1935 | ath10k_wmi_event_dcs_interference(ar, skb); | ||
| 1936 | break; | ||
| 1937 | case WMI_10X_PDEV_TPC_CONFIG_EVENTID: | ||
| 1938 | ath10k_wmi_event_pdev_tpc_config(ar, skb); | ||
| 1939 | break; | ||
| 1940 | case WMI_10X_INST_RSSI_STATS_EVENTID: | ||
| 1941 | ath10k_wmi_event_inst_rssi_stats(ar, skb); | ||
| 1942 | break; | ||
| 1943 | case WMI_10X_VDEV_STANDBY_REQ_EVENTID: | ||
| 1944 | ath10k_wmi_event_vdev_standby_req(ar, skb); | ||
| 1945 | break; | ||
| 1946 | case WMI_10X_VDEV_RESUME_REQ_EVENTID: | ||
| 1947 | ath10k_wmi_event_vdev_resume_req(ar, skb); | ||
| 1948 | break; | ||
| 1949 | case WMI_10X_SERVICE_READY_EVENTID: | ||
| 1950 | ath10k_wmi_10x_service_ready_event_rx(ar, skb); | ||
| 1951 | break; | ||
| 1952 | case WMI_10X_READY_EVENTID: | ||
| 1953 | ath10k_wmi_ready_event_rx(ar, skb); | ||
| 1954 | break; | ||
| 1955 | default: | ||
| 1956 | ath10k_warn("Unknown eventid: %d\n", id); | ||
| 1957 | break; | ||
| 1958 | } | ||
| 1959 | |||
| 1960 | dev_kfree_skb(skb); | ||
| 1961 | } | ||
| 1962 | |||
| 1963 | |||
| 1964 | static void ath10k_wmi_process_rx(struct ath10k *ar, struct sk_buff *skb) | ||
| 1965 | { | ||
| 1966 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) | ||
| 1967 | ath10k_wmi_10x_process_rx(ar, skb); | ||
| 1968 | else | ||
| 1969 | ath10k_wmi_main_process_rx(ar, skb); | ||
| 1970 | } | ||
| 1971 | |||
| 1177 | /* WMI Initialization functions */ | 1972 | /* WMI Initialization functions */ |
| 1178 | int ath10k_wmi_attach(struct ath10k *ar) | 1973 | int ath10k_wmi_attach(struct ath10k *ar) |
| 1179 | { | 1974 | { |
| 1975 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) { | ||
| 1976 | ar->wmi.cmd = &wmi_10x_cmd_map; | ||
| 1977 | ar->wmi.vdev_param = &wmi_10x_vdev_param_map; | ||
| 1978 | ar->wmi.pdev_param = &wmi_10x_pdev_param_map; | ||
| 1979 | } else { | ||
| 1980 | ar->wmi.cmd = &wmi_cmd_map; | ||
| 1981 | ar->wmi.vdev_param = &wmi_vdev_param_map; | ||
| 1982 | ar->wmi.pdev_param = &wmi_pdev_param_map; | ||
| 1983 | } | ||
| 1984 | |||
| 1180 | init_completion(&ar->wmi.service_ready); | 1985 | init_completion(&ar->wmi.service_ready); |
| 1181 | init_completion(&ar->wmi.unified_ready); | 1986 | init_completion(&ar->wmi.unified_ready); |
| 1182 | init_waitqueue_head(&ar->wmi.tx_credits_wq); | 1987 | init_waitqueue_head(&ar->wmi.tx_credits_wq); |
| @@ -1186,6 +1991,17 @@ int ath10k_wmi_attach(struct ath10k *ar) | |||
| 1186 | 1991 | ||
| 1187 | void ath10k_wmi_detach(struct ath10k *ar) | 1992 | void ath10k_wmi_detach(struct ath10k *ar) |
| 1188 | { | 1993 | { |
| 1994 | int i; | ||
| 1995 | |||
| 1996 | /* free the host memory chunks requested by firmware */ | ||
| 1997 | for (i = 0; i < ar->wmi.num_mem_chunks; i++) { | ||
| 1998 | dma_free_coherent(ar->dev, | ||
| 1999 | ar->wmi.mem_chunks[i].len, | ||
| 2000 | ar->wmi.mem_chunks[i].vaddr, | ||
| 2001 | ar->wmi.mem_chunks[i].paddr); | ||
| 2002 | } | ||
| 2003 | |||
| 2004 | ar->wmi.num_mem_chunks = 0; | ||
| 1189 | } | 2005 | } |
| 1190 | 2006 | ||
| 1191 | int ath10k_wmi_connect_htc_service(struct ath10k *ar) | 2007 | int ath10k_wmi_connect_htc_service(struct ath10k *ar) |
| @@ -1237,7 +2053,8 @@ int ath10k_wmi_pdev_set_regdomain(struct ath10k *ar, u16 rd, u16 rd2g, | |||
| 1237 | "wmi pdev regdomain rd %x rd2g %x rd5g %x ctl2g %x ctl5g %x\n", | 2053 | "wmi pdev regdomain rd %x rd2g %x rd5g %x ctl2g %x ctl5g %x\n", |
| 1238 | rd, rd2g, rd5g, ctl2g, ctl5g); | 2054 | rd, rd2g, rd5g, ctl2g, ctl5g); |
| 1239 | 2055 | ||
| 1240 | return ath10k_wmi_cmd_send(ar, skb, WMI_PDEV_SET_REGDOMAIN_CMDID); | 2056 | return ath10k_wmi_cmd_send(ar, skb, |
| 2057 | ar->wmi.cmd->pdev_set_regdomain_cmdid); | ||
| 1241 | } | 2058 | } |
| 1242 | 2059 | ||
| 1243 | int ath10k_wmi_pdev_set_channel(struct ath10k *ar, | 2060 | int ath10k_wmi_pdev_set_channel(struct ath10k *ar, |
| @@ -1267,7 +2084,8 @@ int ath10k_wmi_pdev_set_channel(struct ath10k *ar, | |||
| 1267 | "wmi set channel mode %d freq %d\n", | 2084 | "wmi set channel mode %d freq %d\n", |
| 1268 | arg->mode, arg->freq); | 2085 | arg->mode, arg->freq); |
| 1269 | 2086 | ||
| 1270 | return ath10k_wmi_cmd_send(ar, skb, WMI_PDEV_SET_CHANNEL_CMDID); | 2087 | return ath10k_wmi_cmd_send(ar, skb, |
| 2088 | ar->wmi.cmd->pdev_set_channel_cmdid); | ||
| 1271 | } | 2089 | } |
| 1272 | 2090 | ||
| 1273 | int ath10k_wmi_pdev_suspend_target(struct ath10k *ar) | 2091 | int ath10k_wmi_pdev_suspend_target(struct ath10k *ar) |
| @@ -1282,7 +2100,7 @@ int ath10k_wmi_pdev_suspend_target(struct ath10k *ar) | |||
| 1282 | cmd = (struct wmi_pdev_suspend_cmd *)skb->data; | 2100 | cmd = (struct wmi_pdev_suspend_cmd *)skb->data; |
| 1283 | cmd->suspend_opt = WMI_PDEV_SUSPEND; | 2101 | cmd->suspend_opt = WMI_PDEV_SUSPEND; |
| 1284 | 2102 | ||
| 1285 | return ath10k_wmi_cmd_send(ar, skb, WMI_PDEV_SUSPEND_CMDID); | 2103 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->pdev_suspend_cmdid); |
| 1286 | } | 2104 | } |
| 1287 | 2105 | ||
| 1288 | int ath10k_wmi_pdev_resume_target(struct ath10k *ar) | 2106 | int ath10k_wmi_pdev_resume_target(struct ath10k *ar) |
| @@ -1293,15 +2111,19 @@ int ath10k_wmi_pdev_resume_target(struct ath10k *ar) | |||
| 1293 | if (skb == NULL) | 2111 | if (skb == NULL) |
| 1294 | return -ENOMEM; | 2112 | return -ENOMEM; |
| 1295 | 2113 | ||
| 1296 | return ath10k_wmi_cmd_send(ar, skb, WMI_PDEV_RESUME_CMDID); | 2114 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->pdev_resume_cmdid); |
| 1297 | } | 2115 | } |
| 1298 | 2116 | ||
| 1299 | int ath10k_wmi_pdev_set_param(struct ath10k *ar, enum wmi_pdev_param id, | 2117 | int ath10k_wmi_pdev_set_param(struct ath10k *ar, u32 id, u32 value) |
| 1300 | u32 value) | ||
| 1301 | { | 2118 | { |
| 1302 | struct wmi_pdev_set_param_cmd *cmd; | 2119 | struct wmi_pdev_set_param_cmd *cmd; |
| 1303 | struct sk_buff *skb; | 2120 | struct sk_buff *skb; |
| 1304 | 2121 | ||
| 2122 | if (id == WMI_PDEV_PARAM_UNSUPPORTED) { | ||
| 2123 | ath10k_warn("pdev param %d not supported by firmware\n", id); | ||
| 2124 | return -EOPNOTSUPP; | ||
| 2125 | } | ||
| 2126 | |||
| 1305 | skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); | 2127 | skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); |
| 1306 | if (!skb) | 2128 | if (!skb) |
| 1307 | return -ENOMEM; | 2129 | return -ENOMEM; |
| @@ -1312,15 +2134,16 @@ int ath10k_wmi_pdev_set_param(struct ath10k *ar, enum wmi_pdev_param id, | |||
| 1312 | 2134 | ||
| 1313 | ath10k_dbg(ATH10K_DBG_WMI, "wmi pdev set param %d value %d\n", | 2135 | ath10k_dbg(ATH10K_DBG_WMI, "wmi pdev set param %d value %d\n", |
| 1314 | id, value); | 2136 | id, value); |
| 1315 | return ath10k_wmi_cmd_send(ar, skb, WMI_PDEV_SET_PARAM_CMDID); | 2137 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->pdev_set_param_cmdid); |
| 1316 | } | 2138 | } |
| 1317 | 2139 | ||
| 1318 | int ath10k_wmi_cmd_init(struct ath10k *ar) | 2140 | static int ath10k_wmi_main_cmd_init(struct ath10k *ar) |
| 1319 | { | 2141 | { |
| 1320 | struct wmi_init_cmd *cmd; | 2142 | struct wmi_init_cmd *cmd; |
| 1321 | struct sk_buff *buf; | 2143 | struct sk_buff *buf; |
| 1322 | struct wmi_resource_config config = {}; | 2144 | struct wmi_resource_config config = {}; |
| 1323 | u32 val; | 2145 | u32 len, val; |
| 2146 | int i; | ||
| 1324 | 2147 | ||
| 1325 | config.num_vdevs = __cpu_to_le32(TARGET_NUM_VDEVS); | 2148 | config.num_vdevs = __cpu_to_le32(TARGET_NUM_VDEVS); |
| 1326 | config.num_peers = __cpu_to_le32(TARGET_NUM_PEERS + TARGET_NUM_VDEVS); | 2149 | config.num_peers = __cpu_to_le32(TARGET_NUM_PEERS + TARGET_NUM_VDEVS); |
| @@ -1373,23 +2196,158 @@ int ath10k_wmi_cmd_init(struct ath10k *ar) | |||
| 1373 | config.num_msdu_desc = __cpu_to_le32(TARGET_NUM_MSDU_DESC); | 2196 | config.num_msdu_desc = __cpu_to_le32(TARGET_NUM_MSDU_DESC); |
| 1374 | config.max_frag_entries = __cpu_to_le32(TARGET_MAX_FRAG_ENTRIES); | 2197 | config.max_frag_entries = __cpu_to_le32(TARGET_MAX_FRAG_ENTRIES); |
| 1375 | 2198 | ||
| 1376 | buf = ath10k_wmi_alloc_skb(sizeof(*cmd)); | 2199 | len = sizeof(*cmd) + |
| 2200 | (sizeof(struct host_memory_chunk) * ar->wmi.num_mem_chunks); | ||
| 2201 | |||
| 2202 | buf = ath10k_wmi_alloc_skb(len); | ||
| 1377 | if (!buf) | 2203 | if (!buf) |
| 1378 | return -ENOMEM; | 2204 | return -ENOMEM; |
| 1379 | 2205 | ||
| 1380 | cmd = (struct wmi_init_cmd *)buf->data; | 2206 | cmd = (struct wmi_init_cmd *)buf->data; |
| 1381 | cmd->num_host_mem_chunks = 0; | 2207 | |
| 2208 | if (ar->wmi.num_mem_chunks == 0) { | ||
| 2209 | cmd->num_host_mem_chunks = 0; | ||
| 2210 | goto out; | ||
| 2211 | } | ||
| 2212 | |||
| 2213 | ath10k_dbg(ATH10K_DBG_WMI, "wmi sending %d memory chunks info.\n", | ||
| 2214 | __cpu_to_le32(ar->wmi.num_mem_chunks)); | ||
| 2215 | |||
| 2216 | cmd->num_host_mem_chunks = __cpu_to_le32(ar->wmi.num_mem_chunks); | ||
| 2217 | |||
| 2218 | for (i = 0; i < ar->wmi.num_mem_chunks; i++) { | ||
| 2219 | cmd->host_mem_chunks[i].ptr = | ||
| 2220 | __cpu_to_le32(ar->wmi.mem_chunks[i].paddr); | ||
| 2221 | cmd->host_mem_chunks[i].size = | ||
| 2222 | __cpu_to_le32(ar->wmi.mem_chunks[i].len); | ||
| 2223 | cmd->host_mem_chunks[i].req_id = | ||
| 2224 | __cpu_to_le32(ar->wmi.mem_chunks[i].req_id); | ||
| 2225 | |||
| 2226 | ath10k_dbg(ATH10K_DBG_WMI, | ||
| 2227 | "wmi chunk %d len %d requested, addr 0x%x\n", | ||
| 2228 | i, | ||
| 2229 | cmd->host_mem_chunks[i].size, | ||
| 2230 | cmd->host_mem_chunks[i].ptr); | ||
| 2231 | } | ||
| 2232 | out: | ||
| 1382 | memcpy(&cmd->resource_config, &config, sizeof(config)); | 2233 | memcpy(&cmd->resource_config, &config, sizeof(config)); |
| 1383 | 2234 | ||
| 1384 | ath10k_dbg(ATH10K_DBG_WMI, "wmi init\n"); | 2235 | ath10k_dbg(ATH10K_DBG_WMI, "wmi init\n"); |
| 1385 | return ath10k_wmi_cmd_send(ar, buf, WMI_INIT_CMDID); | 2236 | return ath10k_wmi_cmd_send(ar, buf, ar->wmi.cmd->init_cmdid); |
| 2237 | } | ||
| 2238 | |||
| 2239 | static int ath10k_wmi_10x_cmd_init(struct ath10k *ar) | ||
| 2240 | { | ||
| 2241 | struct wmi_init_cmd_10x *cmd; | ||
| 2242 | struct sk_buff *buf; | ||
| 2243 | struct wmi_resource_config_10x config = {}; | ||
| 2244 | u32 len, val; | ||
| 2245 | int i; | ||
| 2246 | |||
| 2247 | config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS); | ||
| 2248 | config.num_peers = __cpu_to_le32(TARGET_10X_NUM_PEERS); | ||
| 2249 | config.num_peer_keys = __cpu_to_le32(TARGET_10X_NUM_PEER_KEYS); | ||
| 2250 | config.num_tids = __cpu_to_le32(TARGET_10X_NUM_TIDS); | ||
| 2251 | config.ast_skid_limit = __cpu_to_le32(TARGET_10X_AST_SKID_LIMIT); | ||
| 2252 | config.tx_chain_mask = __cpu_to_le32(TARGET_10X_TX_CHAIN_MASK); | ||
| 2253 | config.rx_chain_mask = __cpu_to_le32(TARGET_10X_RX_CHAIN_MASK); | ||
| 2254 | config.rx_timeout_pri_vo = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_LO_PRI); | ||
| 2255 | config.rx_timeout_pri_vi = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_LO_PRI); | ||
| 2256 | config.rx_timeout_pri_be = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_LO_PRI); | ||
| 2257 | config.rx_timeout_pri_bk = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_HI_PRI); | ||
| 2258 | config.rx_decap_mode = __cpu_to_le32(TARGET_10X_RX_DECAP_MODE); | ||
| 2259 | |||
| 2260 | config.scan_max_pending_reqs = | ||
| 2261 | __cpu_to_le32(TARGET_10X_SCAN_MAX_PENDING_REQS); | ||
| 2262 | |||
| 2263 | config.bmiss_offload_max_vdev = | ||
| 2264 | __cpu_to_le32(TARGET_10X_BMISS_OFFLOAD_MAX_VDEV); | ||
| 2265 | |||
| 2266 | config.roam_offload_max_vdev = | ||
| 2267 | __cpu_to_le32(TARGET_10X_ROAM_OFFLOAD_MAX_VDEV); | ||
| 2268 | |||
| 2269 | config.roam_offload_max_ap_profiles = | ||
| 2270 | __cpu_to_le32(TARGET_10X_ROAM_OFFLOAD_MAX_AP_PROFILES); | ||
| 2271 | |||
| 2272 | config.num_mcast_groups = __cpu_to_le32(TARGET_10X_NUM_MCAST_GROUPS); | ||
| 2273 | config.num_mcast_table_elems = | ||
| 2274 | __cpu_to_le32(TARGET_10X_NUM_MCAST_TABLE_ELEMS); | ||
| 2275 | |||
| 2276 | config.mcast2ucast_mode = __cpu_to_le32(TARGET_10X_MCAST2UCAST_MODE); | ||
| 2277 | config.tx_dbg_log_size = __cpu_to_le32(TARGET_10X_TX_DBG_LOG_SIZE); | ||
| 2278 | config.num_wds_entries = __cpu_to_le32(TARGET_10X_NUM_WDS_ENTRIES); | ||
| 2279 | config.dma_burst_size = __cpu_to_le32(TARGET_10X_DMA_BURST_SIZE); | ||
| 2280 | config.mac_aggr_delim = __cpu_to_le32(TARGET_10X_MAC_AGGR_DELIM); | ||
| 2281 | |||
| 2282 | val = TARGET_10X_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK; | ||
| 2283 | config.rx_skip_defrag_timeout_dup_detection_check = __cpu_to_le32(val); | ||
| 2284 | |||
| 2285 | config.vow_config = __cpu_to_le32(TARGET_10X_VOW_CONFIG); | ||
| 2286 | |||
| 2287 | config.num_msdu_desc = __cpu_to_le32(TARGET_10X_NUM_MSDU_DESC); | ||
| 2288 | config.max_frag_entries = __cpu_to_le32(TARGET_10X_MAX_FRAG_ENTRIES); | ||
| 2289 | |||
| 2290 | len = sizeof(*cmd) + | ||
| 2291 | (sizeof(struct host_memory_chunk) * ar->wmi.num_mem_chunks); | ||
| 2292 | |||
| 2293 | buf = ath10k_wmi_alloc_skb(len); | ||
| 2294 | if (!buf) | ||
| 2295 | return -ENOMEM; | ||
| 2296 | |||
| 2297 | cmd = (struct wmi_init_cmd_10x *)buf->data; | ||
| 2298 | |||
| 2299 | if (ar->wmi.num_mem_chunks == 0) { | ||
| 2300 | cmd->num_host_mem_chunks = 0; | ||
| 2301 | goto out; | ||
| 2302 | } | ||
| 2303 | |||
| 2304 | ath10k_dbg(ATH10K_DBG_WMI, "wmi sending %d memory chunks info.\n", | ||
| 2305 | __cpu_to_le32(ar->wmi.num_mem_chunks)); | ||
| 2306 | |||
| 2307 | cmd->num_host_mem_chunks = __cpu_to_le32(ar->wmi.num_mem_chunks); | ||
| 2308 | |||
| 2309 | for (i = 0; i < ar->wmi.num_mem_chunks; i++) { | ||
| 2310 | cmd->host_mem_chunks[i].ptr = | ||
| 2311 | __cpu_to_le32(ar->wmi.mem_chunks[i].paddr); | ||
| 2312 | cmd->host_mem_chunks[i].size = | ||
| 2313 | __cpu_to_le32(ar->wmi.mem_chunks[i].len); | ||
| 2314 | cmd->host_mem_chunks[i].req_id = | ||
| 2315 | __cpu_to_le32(ar->wmi.mem_chunks[i].req_id); | ||
| 2316 | |||
| 2317 | ath10k_dbg(ATH10K_DBG_WMI, | ||
| 2318 | "wmi chunk %d len %d requested, addr 0x%x\n", | ||
| 2319 | i, | ||
| 2320 | cmd->host_mem_chunks[i].size, | ||
| 2321 | cmd->host_mem_chunks[i].ptr); | ||
| 2322 | } | ||
| 2323 | out: | ||
| 2324 | memcpy(&cmd->resource_config, &config, sizeof(config)); | ||
| 2325 | |||
| 2326 | ath10k_dbg(ATH10K_DBG_WMI, "wmi init 10x\n"); | ||
| 2327 | return ath10k_wmi_cmd_send(ar, buf, ar->wmi.cmd->init_cmdid); | ||
| 2328 | } | ||
| 2329 | |||
| 2330 | int ath10k_wmi_cmd_init(struct ath10k *ar) | ||
| 2331 | { | ||
| 2332 | int ret; | ||
| 2333 | |||
| 2334 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) | ||
| 2335 | ret = ath10k_wmi_10x_cmd_init(ar); | ||
| 2336 | else | ||
| 2337 | ret = ath10k_wmi_main_cmd_init(ar); | ||
| 2338 | |||
| 2339 | return ret; | ||
| 1386 | } | 2340 | } |
| 1387 | 2341 | ||
| 1388 | static int ath10k_wmi_start_scan_calc_len(const struct wmi_start_scan_arg *arg) | 2342 | static int ath10k_wmi_start_scan_calc_len(struct ath10k *ar, |
| 2343 | const struct wmi_start_scan_arg *arg) | ||
| 1389 | { | 2344 | { |
| 1390 | int len; | 2345 | int len; |
| 1391 | 2346 | ||
| 1392 | len = sizeof(struct wmi_start_scan_cmd); | 2347 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) |
| 2348 | len = sizeof(struct wmi_start_scan_cmd_10x); | ||
| 2349 | else | ||
| 2350 | len = sizeof(struct wmi_start_scan_cmd); | ||
| 1393 | 2351 | ||
| 1394 | if (arg->ie_len) { | 2352 | if (arg->ie_len) { |
| 1395 | if (!arg->ie) | 2353 | if (!arg->ie) |
| @@ -1449,7 +2407,7 @@ int ath10k_wmi_start_scan(struct ath10k *ar, | |||
| 1449 | int len = 0; | 2407 | int len = 0; |
| 1450 | int i; | 2408 | int i; |
| 1451 | 2409 | ||
| 1452 | len = ath10k_wmi_start_scan_calc_len(arg); | 2410 | len = ath10k_wmi_start_scan_calc_len(ar, arg); |
| 1453 | if (len < 0) | 2411 | if (len < 0) |
| 1454 | return len; /* len contains error code here */ | 2412 | return len; /* len contains error code here */ |
| 1455 | 2413 | ||
| @@ -1481,7 +2439,14 @@ int ath10k_wmi_start_scan(struct ath10k *ar, | |||
| 1481 | cmd->scan_ctrl_flags = __cpu_to_le32(arg->scan_ctrl_flags); | 2439 | cmd->scan_ctrl_flags = __cpu_to_le32(arg->scan_ctrl_flags); |
| 1482 | 2440 | ||
| 1483 | /* TLV list starts after fields included in the struct */ | 2441 | /* TLV list starts after fields included in the struct */ |
| 1484 | off = sizeof(*cmd); | 2442 | /* There's just one filed that differes the two start_scan |
| 2443 | * structures - burst_duration, which we are not using btw, | ||
| 2444 | no point to make the split here, just shift the buffer to fit with | ||
| 2445 | given FW */ | ||
| 2446 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) | ||
| 2447 | off = sizeof(struct wmi_start_scan_cmd_10x); | ||
| 2448 | else | ||
| 2449 | off = sizeof(struct wmi_start_scan_cmd); | ||
| 1485 | 2450 | ||
| 1486 | if (arg->n_channels) { | 2451 | if (arg->n_channels) { |
| 1487 | channels = (void *)skb->data + off; | 2452 | channels = (void *)skb->data + off; |
| @@ -1543,7 +2508,7 @@ int ath10k_wmi_start_scan(struct ath10k *ar, | |||
| 1543 | } | 2508 | } |
| 1544 | 2509 | ||
| 1545 | ath10k_dbg(ATH10K_DBG_WMI, "wmi start scan\n"); | 2510 | ath10k_dbg(ATH10K_DBG_WMI, "wmi start scan\n"); |
| 1546 | return ath10k_wmi_cmd_send(ar, skb, WMI_START_SCAN_CMDID); | 2511 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->start_scan_cmdid); |
| 1547 | } | 2512 | } |
| 1548 | 2513 | ||
| 1549 | void ath10k_wmi_start_scan_init(struct ath10k *ar, | 2514 | void ath10k_wmi_start_scan_init(struct ath10k *ar, |
| @@ -1559,7 +2524,7 @@ void ath10k_wmi_start_scan_init(struct ath10k *ar, | |||
| 1559 | arg->repeat_probe_time = 0; | 2524 | arg->repeat_probe_time = 0; |
| 1560 | arg->probe_spacing_time = 0; | 2525 | arg->probe_spacing_time = 0; |
| 1561 | arg->idle_time = 0; | 2526 | arg->idle_time = 0; |
| 1562 | arg->max_scan_time = 5000; | 2527 | arg->max_scan_time = 20000; |
| 1563 | arg->probe_delay = 5; | 2528 | arg->probe_delay = 5; |
| 1564 | arg->notify_scan_events = WMI_SCAN_EVENT_STARTED | 2529 | arg->notify_scan_events = WMI_SCAN_EVENT_STARTED |
| 1565 | | WMI_SCAN_EVENT_COMPLETED | 2530 | | WMI_SCAN_EVENT_COMPLETED |
| @@ -1603,7 +2568,7 @@ int ath10k_wmi_stop_scan(struct ath10k *ar, const struct wmi_stop_scan_arg *arg) | |||
| 1603 | ath10k_dbg(ATH10K_DBG_WMI, | 2568 | ath10k_dbg(ATH10K_DBG_WMI, |
| 1604 | "wmi stop scan reqid %d req_type %d vdev/scan_id %d\n", | 2569 | "wmi stop scan reqid %d req_type %d vdev/scan_id %d\n", |
| 1605 | arg->req_id, arg->req_type, arg->u.scan_id); | 2570 | arg->req_id, arg->req_type, arg->u.scan_id); |
| 1606 | return ath10k_wmi_cmd_send(ar, skb, WMI_STOP_SCAN_CMDID); | 2571 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->stop_scan_cmdid); |
| 1607 | } | 2572 | } |
| 1608 | 2573 | ||
| 1609 | int ath10k_wmi_vdev_create(struct ath10k *ar, u32 vdev_id, | 2574 | int ath10k_wmi_vdev_create(struct ath10k *ar, u32 vdev_id, |
| @@ -1628,7 +2593,7 @@ int ath10k_wmi_vdev_create(struct ath10k *ar, u32 vdev_id, | |||
| 1628 | "WMI vdev create: id %d type %d subtype %d macaddr %pM\n", | 2593 | "WMI vdev create: id %d type %d subtype %d macaddr %pM\n", |
| 1629 | vdev_id, type, subtype, macaddr); | 2594 | vdev_id, type, subtype, macaddr); |
| 1630 | 2595 | ||
| 1631 | return ath10k_wmi_cmd_send(ar, skb, WMI_VDEV_CREATE_CMDID); | 2596 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_create_cmdid); |
| 1632 | } | 2597 | } |
| 1633 | 2598 | ||
| 1634 | int ath10k_wmi_vdev_delete(struct ath10k *ar, u32 vdev_id) | 2599 | int ath10k_wmi_vdev_delete(struct ath10k *ar, u32 vdev_id) |
| @@ -1646,20 +2611,20 @@ int ath10k_wmi_vdev_delete(struct ath10k *ar, u32 vdev_id) | |||
| 1646 | ath10k_dbg(ATH10K_DBG_WMI, | 2611 | ath10k_dbg(ATH10K_DBG_WMI, |
| 1647 | "WMI vdev delete id %d\n", vdev_id); | 2612 | "WMI vdev delete id %d\n", vdev_id); |
| 1648 | 2613 | ||
| 1649 | return ath10k_wmi_cmd_send(ar, skb, WMI_VDEV_DELETE_CMDID); | 2614 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_delete_cmdid); |
| 1650 | } | 2615 | } |
| 1651 | 2616 | ||
| 1652 | static int ath10k_wmi_vdev_start_restart(struct ath10k *ar, | 2617 | static int ath10k_wmi_vdev_start_restart(struct ath10k *ar, |
| 1653 | const struct wmi_vdev_start_request_arg *arg, | 2618 | const struct wmi_vdev_start_request_arg *arg, |
| 1654 | enum wmi_cmd_id cmd_id) | 2619 | u32 cmd_id) |
| 1655 | { | 2620 | { |
| 1656 | struct wmi_vdev_start_request_cmd *cmd; | 2621 | struct wmi_vdev_start_request_cmd *cmd; |
| 1657 | struct sk_buff *skb; | 2622 | struct sk_buff *skb; |
| 1658 | const char *cmdname; | 2623 | const char *cmdname; |
| 1659 | u32 flags = 0; | 2624 | u32 flags = 0; |
| 1660 | 2625 | ||
| 1661 | if (cmd_id != WMI_VDEV_START_REQUEST_CMDID && | 2626 | if (cmd_id != ar->wmi.cmd->vdev_start_request_cmdid && |
| 1662 | cmd_id != WMI_VDEV_RESTART_REQUEST_CMDID) | 2627 | cmd_id != ar->wmi.cmd->vdev_restart_request_cmdid) |
| 1663 | return -EINVAL; | 2628 | return -EINVAL; |
| 1664 | if (WARN_ON(arg->ssid && arg->ssid_len == 0)) | 2629 | if (WARN_ON(arg->ssid && arg->ssid_len == 0)) |
| 1665 | return -EINVAL; | 2630 | return -EINVAL; |
| @@ -1668,9 +2633,9 @@ static int ath10k_wmi_vdev_start_restart(struct ath10k *ar, | |||
| 1668 | if (WARN_ON(arg->ssid_len > sizeof(cmd->ssid.ssid))) | 2633 | if (WARN_ON(arg->ssid_len > sizeof(cmd->ssid.ssid))) |
| 1669 | return -EINVAL; | 2634 | return -EINVAL; |
| 1670 | 2635 | ||
| 1671 | if (cmd_id == WMI_VDEV_START_REQUEST_CMDID) | 2636 | if (cmd_id == ar->wmi.cmd->vdev_start_request_cmdid) |
| 1672 | cmdname = "start"; | 2637 | cmdname = "start"; |
| 1673 | else if (cmd_id == WMI_VDEV_RESTART_REQUEST_CMDID) | 2638 | else if (cmd_id == ar->wmi.cmd->vdev_restart_request_cmdid) |
| 1674 | cmdname = "restart"; | 2639 | cmdname = "restart"; |
| 1675 | else | 2640 | else |
| 1676 | return -EINVAL; /* should not happen, we already check cmd_id */ | 2641 | return -EINVAL; /* should not happen, we already check cmd_id */ |
| @@ -1721,15 +2686,17 @@ static int ath10k_wmi_vdev_start_restart(struct ath10k *ar, | |||
| 1721 | int ath10k_wmi_vdev_start(struct ath10k *ar, | 2686 | int ath10k_wmi_vdev_start(struct ath10k *ar, |
| 1722 | const struct wmi_vdev_start_request_arg *arg) | 2687 | const struct wmi_vdev_start_request_arg *arg) |
| 1723 | { | 2688 | { |
| 1724 | return ath10k_wmi_vdev_start_restart(ar, arg, | 2689 | u32 cmd_id = ar->wmi.cmd->vdev_start_request_cmdid; |
| 1725 | WMI_VDEV_START_REQUEST_CMDID); | 2690 | |
| 2691 | return ath10k_wmi_vdev_start_restart(ar, arg, cmd_id); | ||
| 1726 | } | 2692 | } |
| 1727 | 2693 | ||
| 1728 | int ath10k_wmi_vdev_restart(struct ath10k *ar, | 2694 | int ath10k_wmi_vdev_restart(struct ath10k *ar, |
| 1729 | const struct wmi_vdev_start_request_arg *arg) | 2695 | const struct wmi_vdev_start_request_arg *arg) |
| 1730 | { | 2696 | { |
| 1731 | return ath10k_wmi_vdev_start_restart(ar, arg, | 2697 | u32 cmd_id = ar->wmi.cmd->vdev_restart_request_cmdid; |
| 1732 | WMI_VDEV_RESTART_REQUEST_CMDID); | 2698 | |
| 2699 | return ath10k_wmi_vdev_start_restart(ar, arg, cmd_id); | ||
| 1733 | } | 2700 | } |
| 1734 | 2701 | ||
| 1735 | int ath10k_wmi_vdev_stop(struct ath10k *ar, u32 vdev_id) | 2702 | int ath10k_wmi_vdev_stop(struct ath10k *ar, u32 vdev_id) |
| @@ -1746,7 +2713,7 @@ int ath10k_wmi_vdev_stop(struct ath10k *ar, u32 vdev_id) | |||
| 1746 | 2713 | ||
| 1747 | ath10k_dbg(ATH10K_DBG_WMI, "wmi vdev stop id 0x%x\n", vdev_id); | 2714 | ath10k_dbg(ATH10K_DBG_WMI, "wmi vdev stop id 0x%x\n", vdev_id); |
| 1748 | 2715 | ||
| 1749 | return ath10k_wmi_cmd_send(ar, skb, WMI_VDEV_STOP_CMDID); | 2716 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_stop_cmdid); |
| 1750 | } | 2717 | } |
| 1751 | 2718 | ||
| 1752 | int ath10k_wmi_vdev_up(struct ath10k *ar, u32 vdev_id, u32 aid, const u8 *bssid) | 2719 | int ath10k_wmi_vdev_up(struct ath10k *ar, u32 vdev_id, u32 aid, const u8 *bssid) |
| @@ -1767,7 +2734,7 @@ int ath10k_wmi_vdev_up(struct ath10k *ar, u32 vdev_id, u32 aid, const u8 *bssid) | |||
| 1767 | "wmi mgmt vdev up id 0x%x assoc id %d bssid %pM\n", | 2734 | "wmi mgmt vdev up id 0x%x assoc id %d bssid %pM\n", |
| 1768 | vdev_id, aid, bssid); | 2735 | vdev_id, aid, bssid); |
| 1769 | 2736 | ||
| 1770 | return ath10k_wmi_cmd_send(ar, skb, WMI_VDEV_UP_CMDID); | 2737 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_up_cmdid); |
| 1771 | } | 2738 | } |
| 1772 | 2739 | ||
| 1773 | int ath10k_wmi_vdev_down(struct ath10k *ar, u32 vdev_id) | 2740 | int ath10k_wmi_vdev_down(struct ath10k *ar, u32 vdev_id) |
| @@ -1785,15 +2752,22 @@ int ath10k_wmi_vdev_down(struct ath10k *ar, u32 vdev_id) | |||
| 1785 | ath10k_dbg(ATH10K_DBG_WMI, | 2752 | ath10k_dbg(ATH10K_DBG_WMI, |
| 1786 | "wmi mgmt vdev down id 0x%x\n", vdev_id); | 2753 | "wmi mgmt vdev down id 0x%x\n", vdev_id); |
| 1787 | 2754 | ||
| 1788 | return ath10k_wmi_cmd_send(ar, skb, WMI_VDEV_DOWN_CMDID); | 2755 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_down_cmdid); |
| 1789 | } | 2756 | } |
| 1790 | 2757 | ||
| 1791 | int ath10k_wmi_vdev_set_param(struct ath10k *ar, u32 vdev_id, | 2758 | int ath10k_wmi_vdev_set_param(struct ath10k *ar, u32 vdev_id, |
| 1792 | enum wmi_vdev_param param_id, u32 param_value) | 2759 | u32 param_id, u32 param_value) |
| 1793 | { | 2760 | { |
| 1794 | struct wmi_vdev_set_param_cmd *cmd; | 2761 | struct wmi_vdev_set_param_cmd *cmd; |
| 1795 | struct sk_buff *skb; | 2762 | struct sk_buff *skb; |
| 1796 | 2763 | ||
| 2764 | if (param_id == WMI_VDEV_PARAM_UNSUPPORTED) { | ||
| 2765 | ath10k_dbg(ATH10K_DBG_WMI, | ||
| 2766 | "vdev param %d not supported by firmware\n", | ||
| 2767 | param_id); | ||
| 2768 | return -EOPNOTSUPP; | ||
| 2769 | } | ||
| 2770 | |||
| 1797 | skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); | 2771 | skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); |
| 1798 | if (!skb) | 2772 | if (!skb) |
| 1799 | return -ENOMEM; | 2773 | return -ENOMEM; |
| @@ -1807,7 +2781,7 @@ int ath10k_wmi_vdev_set_param(struct ath10k *ar, u32 vdev_id, | |||
| 1807 | "wmi vdev id 0x%x set param %d value %d\n", | 2781 | "wmi vdev id 0x%x set param %d value %d\n", |
| 1808 | vdev_id, param_id, param_value); | 2782 | vdev_id, param_id, param_value); |
| 1809 | 2783 | ||
| 1810 | return ath10k_wmi_cmd_send(ar, skb, WMI_VDEV_SET_PARAM_CMDID); | 2784 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_set_param_cmdid); |
| 1811 | } | 2785 | } |
| 1812 | 2786 | ||
| 1813 | int ath10k_wmi_vdev_install_key(struct ath10k *ar, | 2787 | int ath10k_wmi_vdev_install_key(struct ath10k *ar, |
| @@ -1842,7 +2816,8 @@ int ath10k_wmi_vdev_install_key(struct ath10k *ar, | |||
| 1842 | ath10k_dbg(ATH10K_DBG_WMI, | 2816 | ath10k_dbg(ATH10K_DBG_WMI, |
| 1843 | "wmi vdev install key idx %d cipher %d len %d\n", | 2817 | "wmi vdev install key idx %d cipher %d len %d\n", |
| 1844 | arg->key_idx, arg->key_cipher, arg->key_len); | 2818 | arg->key_idx, arg->key_cipher, arg->key_len); |
| 1845 | return ath10k_wmi_cmd_send(ar, skb, WMI_VDEV_INSTALL_KEY_CMDID); | 2819 | return ath10k_wmi_cmd_send(ar, skb, |
| 2820 | ar->wmi.cmd->vdev_install_key_cmdid); | ||
| 1846 | } | 2821 | } |
| 1847 | 2822 | ||
| 1848 | int ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id, | 2823 | int ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id, |
| @@ -1862,7 +2837,7 @@ int ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id, | |||
| 1862 | ath10k_dbg(ATH10K_DBG_WMI, | 2837 | ath10k_dbg(ATH10K_DBG_WMI, |
| 1863 | "wmi peer create vdev_id %d peer_addr %pM\n", | 2838 | "wmi peer create vdev_id %d peer_addr %pM\n", |
| 1864 | vdev_id, peer_addr); | 2839 | vdev_id, peer_addr); |
| 1865 | return ath10k_wmi_cmd_send(ar, skb, WMI_PEER_CREATE_CMDID); | 2840 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_create_cmdid); |
| 1866 | } | 2841 | } |
| 1867 | 2842 | ||
| 1868 | int ath10k_wmi_peer_delete(struct ath10k *ar, u32 vdev_id, | 2843 | int ath10k_wmi_peer_delete(struct ath10k *ar, u32 vdev_id, |
| @@ -1882,7 +2857,7 @@ int ath10k_wmi_peer_delete(struct ath10k *ar, u32 vdev_id, | |||
| 1882 | ath10k_dbg(ATH10K_DBG_WMI, | 2857 | ath10k_dbg(ATH10K_DBG_WMI, |
| 1883 | "wmi peer delete vdev_id %d peer_addr %pM\n", | 2858 | "wmi peer delete vdev_id %d peer_addr %pM\n", |
| 1884 | vdev_id, peer_addr); | 2859 | vdev_id, peer_addr); |
| 1885 | return ath10k_wmi_cmd_send(ar, skb, WMI_PEER_DELETE_CMDID); | 2860 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_delete_cmdid); |
| 1886 | } | 2861 | } |
| 1887 | 2862 | ||
| 1888 | int ath10k_wmi_peer_flush(struct ath10k *ar, u32 vdev_id, | 2863 | int ath10k_wmi_peer_flush(struct ath10k *ar, u32 vdev_id, |
| @@ -1903,7 +2878,7 @@ int ath10k_wmi_peer_flush(struct ath10k *ar, u32 vdev_id, | |||
| 1903 | ath10k_dbg(ATH10K_DBG_WMI, | 2878 | ath10k_dbg(ATH10K_DBG_WMI, |
| 1904 | "wmi peer flush vdev_id %d peer_addr %pM tids %08x\n", | 2879 | "wmi peer flush vdev_id %d peer_addr %pM tids %08x\n", |
| 1905 | vdev_id, peer_addr, tid_bitmap); | 2880 | vdev_id, peer_addr, tid_bitmap); |
| 1906 | return ath10k_wmi_cmd_send(ar, skb, WMI_PEER_FLUSH_TIDS_CMDID); | 2881 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_flush_tids_cmdid); |
| 1907 | } | 2882 | } |
| 1908 | 2883 | ||
| 1909 | int ath10k_wmi_peer_set_param(struct ath10k *ar, u32 vdev_id, | 2884 | int ath10k_wmi_peer_set_param(struct ath10k *ar, u32 vdev_id, |
| @@ -1927,7 +2902,7 @@ int ath10k_wmi_peer_set_param(struct ath10k *ar, u32 vdev_id, | |||
| 1927 | "wmi vdev %d peer 0x%pM set param %d value %d\n", | 2902 | "wmi vdev %d peer 0x%pM set param %d value %d\n", |
| 1928 | vdev_id, peer_addr, param_id, param_value); | 2903 | vdev_id, peer_addr, param_id, param_value); |
| 1929 | 2904 | ||
| 1930 | return ath10k_wmi_cmd_send(ar, skb, WMI_PEER_SET_PARAM_CMDID); | 2905 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_set_param_cmdid); |
| 1931 | } | 2906 | } |
| 1932 | 2907 | ||
| 1933 | int ath10k_wmi_set_psmode(struct ath10k *ar, u32 vdev_id, | 2908 | int ath10k_wmi_set_psmode(struct ath10k *ar, u32 vdev_id, |
| @@ -1948,7 +2923,8 @@ int ath10k_wmi_set_psmode(struct ath10k *ar, u32 vdev_id, | |||
| 1948 | "wmi set powersave id 0x%x mode %d\n", | 2923 | "wmi set powersave id 0x%x mode %d\n", |
| 1949 | vdev_id, psmode); | 2924 | vdev_id, psmode); |
| 1950 | 2925 | ||
| 1951 | return ath10k_wmi_cmd_send(ar, skb, WMI_STA_POWERSAVE_MODE_CMDID); | 2926 | return ath10k_wmi_cmd_send(ar, skb, |
| 2927 | ar->wmi.cmd->sta_powersave_mode_cmdid); | ||
| 1952 | } | 2928 | } |
| 1953 | 2929 | ||
| 1954 | int ath10k_wmi_set_sta_ps_param(struct ath10k *ar, u32 vdev_id, | 2930 | int ath10k_wmi_set_sta_ps_param(struct ath10k *ar, u32 vdev_id, |
| @@ -1970,7 +2946,8 @@ int ath10k_wmi_set_sta_ps_param(struct ath10k *ar, u32 vdev_id, | |||
| 1970 | ath10k_dbg(ATH10K_DBG_WMI, | 2946 | ath10k_dbg(ATH10K_DBG_WMI, |
| 1971 | "wmi sta ps param vdev_id 0x%x param %d value %d\n", | 2947 | "wmi sta ps param vdev_id 0x%x param %d value %d\n", |
| 1972 | vdev_id, param_id, value); | 2948 | vdev_id, param_id, value); |
| 1973 | return ath10k_wmi_cmd_send(ar, skb, WMI_STA_POWERSAVE_PARAM_CMDID); | 2949 | return ath10k_wmi_cmd_send(ar, skb, |
| 2950 | ar->wmi.cmd->sta_powersave_param_cmdid); | ||
| 1974 | } | 2951 | } |
| 1975 | 2952 | ||
| 1976 | int ath10k_wmi_set_ap_ps_param(struct ath10k *ar, u32 vdev_id, const u8 *mac, | 2953 | int ath10k_wmi_set_ap_ps_param(struct ath10k *ar, u32 vdev_id, const u8 *mac, |
| @@ -1996,7 +2973,8 @@ int ath10k_wmi_set_ap_ps_param(struct ath10k *ar, u32 vdev_id, const u8 *mac, | |||
| 1996 | "wmi ap ps param vdev_id 0x%X param %d value %d mac_addr %pM\n", | 2973 | "wmi ap ps param vdev_id 0x%X param %d value %d mac_addr %pM\n", |
| 1997 | vdev_id, param_id, value, mac); | 2974 | vdev_id, param_id, value, mac); |
| 1998 | 2975 | ||
| 1999 | return ath10k_wmi_cmd_send(ar, skb, WMI_AP_PS_PEER_PARAM_CMDID); | 2976 | return ath10k_wmi_cmd_send(ar, skb, |
| 2977 | ar->wmi.cmd->ap_ps_peer_param_cmdid); | ||
| 2000 | } | 2978 | } |
| 2001 | 2979 | ||
| 2002 | int ath10k_wmi_scan_chan_list(struct ath10k *ar, | 2980 | int ath10k_wmi_scan_chan_list(struct ath10k *ar, |
| @@ -2049,7 +3027,7 @@ int ath10k_wmi_scan_chan_list(struct ath10k *ar, | |||
| 2049 | ci->flags |= __cpu_to_le32(flags); | 3027 | ci->flags |= __cpu_to_le32(flags); |
| 2050 | } | 3028 | } |
| 2051 | 3029 | ||
| 2052 | return ath10k_wmi_cmd_send(ar, skb, WMI_SCAN_CHAN_LIST_CMDID); | 3030 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->scan_chan_list_cmdid); |
| 2053 | } | 3031 | } |
| 2054 | 3032 | ||
| 2055 | int ath10k_wmi_peer_assoc(struct ath10k *ar, | 3033 | int ath10k_wmi_peer_assoc(struct ath10k *ar, |
| @@ -2108,7 +3086,7 @@ int ath10k_wmi_peer_assoc(struct ath10k *ar, | |||
| 2108 | ath10k_dbg(ATH10K_DBG_WMI, | 3086 | ath10k_dbg(ATH10K_DBG_WMI, |
| 2109 | "wmi peer assoc vdev %d addr %pM\n", | 3087 | "wmi peer assoc vdev %d addr %pM\n", |
| 2110 | arg->vdev_id, arg->addr); | 3088 | arg->vdev_id, arg->addr); |
| 2111 | return ath10k_wmi_cmd_send(ar, skb, WMI_PEER_ASSOC_CMDID); | 3089 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_assoc_cmdid); |
| 2112 | } | 3090 | } |
| 2113 | 3091 | ||
| 2114 | int ath10k_wmi_beacon_send_nowait(struct ath10k *ar, | 3092 | int ath10k_wmi_beacon_send_nowait(struct ath10k *ar, |
| @@ -2128,7 +3106,7 @@ int ath10k_wmi_beacon_send_nowait(struct ath10k *ar, | |||
| 2128 | cmd->hdr.bcn_len = __cpu_to_le32(arg->bcn_len); | 3106 | cmd->hdr.bcn_len = __cpu_to_le32(arg->bcn_len); |
| 2129 | memcpy(cmd->bcn, arg->bcn, arg->bcn_len); | 3107 | memcpy(cmd->bcn, arg->bcn, arg->bcn_len); |
| 2130 | 3108 | ||
| 2131 | return ath10k_wmi_cmd_send_nowait(ar, skb, WMI_BCN_TX_CMDID); | 3109 | return ath10k_wmi_cmd_send_nowait(ar, skb, ar->wmi.cmd->bcn_tx_cmdid); |
| 2132 | } | 3110 | } |
| 2133 | 3111 | ||
| 2134 | static void ath10k_wmi_pdev_set_wmm_param(struct wmi_wmm_params *params, | 3112 | static void ath10k_wmi_pdev_set_wmm_param(struct wmi_wmm_params *params, |
| @@ -2159,7 +3137,8 @@ int ath10k_wmi_pdev_set_wmm_params(struct ath10k *ar, | |||
| 2159 | ath10k_wmi_pdev_set_wmm_param(&cmd->ac_vo, &arg->ac_vo); | 3137 | ath10k_wmi_pdev_set_wmm_param(&cmd->ac_vo, &arg->ac_vo); |
| 2160 | 3138 | ||
| 2161 | ath10k_dbg(ATH10K_DBG_WMI, "wmi pdev set wmm params\n"); | 3139 | ath10k_dbg(ATH10K_DBG_WMI, "wmi pdev set wmm params\n"); |
| 2162 | return ath10k_wmi_cmd_send(ar, skb, WMI_PDEV_SET_WMM_PARAMS_CMDID); | 3140 | return ath10k_wmi_cmd_send(ar, skb, |
| 3141 | ar->wmi.cmd->pdev_set_wmm_params_cmdid); | ||
| 2163 | } | 3142 | } |
| 2164 | 3143 | ||
| 2165 | int ath10k_wmi_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id) | 3144 | int ath10k_wmi_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id) |
| @@ -2175,7 +3154,7 @@ int ath10k_wmi_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id) | |||
| 2175 | cmd->stats_id = __cpu_to_le32(stats_id); | 3154 | cmd->stats_id = __cpu_to_le32(stats_id); |
| 2176 | 3155 | ||
| 2177 | ath10k_dbg(ATH10K_DBG_WMI, "wmi request stats %d\n", (int)stats_id); | 3156 | ath10k_dbg(ATH10K_DBG_WMI, "wmi request stats %d\n", (int)stats_id); |
| 2178 | return ath10k_wmi_cmd_send(ar, skb, WMI_REQUEST_STATS_CMDID); | 3157 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->request_stats_cmdid); |
| 2179 | } | 3158 | } |
| 2180 | 3159 | ||
| 2181 | int ath10k_wmi_force_fw_hang(struct ath10k *ar, | 3160 | int ath10k_wmi_force_fw_hang(struct ath10k *ar, |
| @@ -2194,5 +3173,5 @@ int ath10k_wmi_force_fw_hang(struct ath10k *ar, | |||
| 2194 | 3173 | ||
| 2195 | ath10k_dbg(ATH10K_DBG_WMI, "wmi force fw hang %d delay %d\n", | 3174 | ath10k_dbg(ATH10K_DBG_WMI, "wmi force fw hang %d delay %d\n", |
| 2196 | type, delay_ms); | 3175 | type, delay_ms); |
| 2197 | return ath10k_wmi_cmd_send(ar, skb, WMI_FORCE_FW_HANG_CMDID); | 3176 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->force_fw_hang_cmdid); |
| 2198 | } | 3177 | } |
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 2c52c23107dd..78c991aec7f9 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h | |||
| @@ -208,6 +208,118 @@ struct wmi_mac_addr { | |||
| 208 | (c_macaddr)[5] = (((pwmi_mac_addr)->word1) >> 8) & 0xff; \ | 208 | (c_macaddr)[5] = (((pwmi_mac_addr)->word1) >> 8) & 0xff; \ |
| 209 | } while (0) | 209 | } while (0) |
| 210 | 210 | ||
| 211 | struct wmi_cmd_map { | ||
| 212 | u32 init_cmdid; | ||
| 213 | u32 start_scan_cmdid; | ||
| 214 | u32 stop_scan_cmdid; | ||
| 215 | u32 scan_chan_list_cmdid; | ||
| 216 | u32 scan_sch_prio_tbl_cmdid; | ||
| 217 | u32 pdev_set_regdomain_cmdid; | ||
| 218 | u32 pdev_set_channel_cmdid; | ||
| 219 | u32 pdev_set_param_cmdid; | ||
| 220 | u32 pdev_pktlog_enable_cmdid; | ||
| 221 | u32 pdev_pktlog_disable_cmdid; | ||
| 222 | u32 pdev_set_wmm_params_cmdid; | ||
| 223 | u32 pdev_set_ht_cap_ie_cmdid; | ||
| 224 | u32 pdev_set_vht_cap_ie_cmdid; | ||
| 225 | u32 pdev_set_dscp_tid_map_cmdid; | ||
| 226 | u32 pdev_set_quiet_mode_cmdid; | ||
| 227 | u32 pdev_green_ap_ps_enable_cmdid; | ||
| 228 | u32 pdev_get_tpc_config_cmdid; | ||
| 229 | u32 pdev_set_base_macaddr_cmdid; | ||
| 230 | u32 vdev_create_cmdid; | ||
| 231 | u32 vdev_delete_cmdid; | ||
| 232 | u32 vdev_start_request_cmdid; | ||
| 233 | u32 vdev_restart_request_cmdid; | ||
| 234 | u32 vdev_up_cmdid; | ||
| 235 | u32 vdev_stop_cmdid; | ||
| 236 | u32 vdev_down_cmdid; | ||
| 237 | u32 vdev_set_param_cmdid; | ||
| 238 | u32 vdev_install_key_cmdid; | ||
| 239 | u32 peer_create_cmdid; | ||
| 240 | u32 peer_delete_cmdid; | ||
| 241 | u32 peer_flush_tids_cmdid; | ||
| 242 | u32 peer_set_param_cmdid; | ||
| 243 | u32 peer_assoc_cmdid; | ||
| 244 | u32 peer_add_wds_entry_cmdid; | ||
| 245 | u32 peer_remove_wds_entry_cmdid; | ||
| 246 | u32 peer_mcast_group_cmdid; | ||
| 247 | u32 bcn_tx_cmdid; | ||
| 248 | u32 pdev_send_bcn_cmdid; | ||
| 249 | u32 bcn_tmpl_cmdid; | ||
| 250 | u32 bcn_filter_rx_cmdid; | ||
| 251 | u32 prb_req_filter_rx_cmdid; | ||
| 252 | u32 mgmt_tx_cmdid; | ||
| 253 | u32 prb_tmpl_cmdid; | ||
| 254 | u32 addba_clear_resp_cmdid; | ||
| 255 | u32 addba_send_cmdid; | ||
| 256 | u32 addba_status_cmdid; | ||
| 257 | u32 delba_send_cmdid; | ||
| 258 | u32 addba_set_resp_cmdid; | ||
| 259 | u32 send_singleamsdu_cmdid; | ||
| 260 | u32 sta_powersave_mode_cmdid; | ||
| 261 | u32 sta_powersave_param_cmdid; | ||
| 262 | u32 sta_mimo_ps_mode_cmdid; | ||
| 263 | u32 pdev_dfs_enable_cmdid; | ||
| 264 | u32 pdev_dfs_disable_cmdid; | ||
| 265 | u32 roam_scan_mode; | ||
| 266 | u32 roam_scan_rssi_threshold; | ||
| 267 | u32 roam_scan_period; | ||
| 268 | u32 roam_scan_rssi_change_threshold; | ||
| 269 | u32 roam_ap_profile; | ||
| 270 | u32 ofl_scan_add_ap_profile; | ||
| 271 | u32 ofl_scan_remove_ap_profile; | ||
| 272 | u32 ofl_scan_period; | ||
| 273 | u32 p2p_dev_set_device_info; | ||
| 274 | u32 p2p_dev_set_discoverability; | ||
| 275 | u32 p2p_go_set_beacon_ie; | ||
| 276 | u32 p2p_go_set_probe_resp_ie; | ||
| 277 | u32 p2p_set_vendor_ie_data_cmdid; | ||
| 278 | u32 ap_ps_peer_param_cmdid; | ||
| 279 | u32 ap_ps_peer_uapsd_coex_cmdid; | ||
| 280 | u32 peer_rate_retry_sched_cmdid; | ||
| 281 | u32 wlan_profile_trigger_cmdid; | ||
| 282 | u32 wlan_profile_set_hist_intvl_cmdid; | ||
| 283 | u32 wlan_profile_get_profile_data_cmdid; | ||
| 284 | u32 wlan_profile_enable_profile_id_cmdid; | ||
| 285 | u32 wlan_profile_list_profile_id_cmdid; | ||
| 286 | u32 pdev_suspend_cmdid; | ||
| 287 | u32 pdev_resume_cmdid; | ||
| 288 | u32 add_bcn_filter_cmdid; | ||
| 289 | u32 rmv_bcn_filter_cmdid; | ||
| 290 | u32 wow_add_wake_pattern_cmdid; | ||
| 291 | u32 wow_del_wake_pattern_cmdid; | ||
| 292 | u32 wow_enable_disable_wake_event_cmdid; | ||
| 293 | u32 wow_enable_cmdid; | ||
| 294 | u32 wow_hostwakeup_from_sleep_cmdid; | ||
| 295 | u32 rtt_measreq_cmdid; | ||
| 296 | u32 rtt_tsf_cmdid; | ||
| 297 | u32 vdev_spectral_scan_configure_cmdid; | ||
| 298 | u32 vdev_spectral_scan_enable_cmdid; | ||
| 299 | u32 request_stats_cmdid; | ||
| 300 | u32 set_arp_ns_offload_cmdid; | ||
| 301 | u32 network_list_offload_config_cmdid; | ||
| 302 | u32 gtk_offload_cmdid; | ||
| 303 | u32 csa_offload_enable_cmdid; | ||
| 304 | u32 csa_offload_chanswitch_cmdid; | ||
| 305 | u32 chatter_set_mode_cmdid; | ||
| 306 | u32 peer_tid_addba_cmdid; | ||
| 307 | u32 peer_tid_delba_cmdid; | ||
| 308 | u32 sta_dtim_ps_method_cmdid; | ||
| 309 | u32 sta_uapsd_auto_trig_cmdid; | ||
| 310 | u32 sta_keepalive_cmd; | ||
| 311 | u32 echo_cmdid; | ||
| 312 | u32 pdev_utf_cmdid; | ||
| 313 | u32 dbglog_cfg_cmdid; | ||
| 314 | u32 pdev_qvit_cmdid; | ||
| 315 | u32 pdev_ftm_intg_cmdid; | ||
| 316 | u32 vdev_set_keepalive_cmdid; | ||
| 317 | u32 vdev_get_keepalive_cmdid; | ||
| 318 | u32 force_fw_hang_cmdid; | ||
| 319 | u32 gpio_config_cmdid; | ||
| 320 | u32 gpio_output_cmdid; | ||
| 321 | }; | ||
| 322 | |||
| 211 | /* | 323 | /* |
| 212 | * wmi command groups. | 324 | * wmi command groups. |
| 213 | */ | 325 | */ |
| @@ -247,7 +359,9 @@ enum wmi_cmd_group { | |||
| 247 | #define WMI_CMD_GRP(grp_id) (((grp_id) << 12) | 0x1) | 359 | #define WMI_CMD_GRP(grp_id) (((grp_id) << 12) | 0x1) |
| 248 | #define WMI_EVT_GRP_START_ID(grp_id) (((grp_id) << 12) | 0x1) | 360 | #define WMI_EVT_GRP_START_ID(grp_id) (((grp_id) << 12) | 0x1) |
| 249 | 361 | ||
| 250 | /* Command IDs and commande events. */ | 362 | #define WMI_CMD_UNSUPPORTED 0 |
| 363 | |||
| 364 | /* Command IDs and command events for MAIN FW. */ | ||
| 251 | enum wmi_cmd_id { | 365 | enum wmi_cmd_id { |
| 252 | WMI_INIT_CMDID = 0x1, | 366 | WMI_INIT_CMDID = 0x1, |
| 253 | 367 | ||
| @@ -488,6 +602,217 @@ enum wmi_event_id { | |||
| 488 | WMI_GPIO_INPUT_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_GPIO), | 602 | WMI_GPIO_INPUT_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_GPIO), |
| 489 | }; | 603 | }; |
| 490 | 604 | ||
| 605 | /* Command IDs and command events for 10.X firmware */ | ||
| 606 | enum wmi_10x_cmd_id { | ||
| 607 | WMI_10X_START_CMDID = 0x9000, | ||
| 608 | WMI_10X_END_CMDID = 0x9FFF, | ||
| 609 | |||
| 610 | /* initialize the wlan sub system */ | ||
| 611 | WMI_10X_INIT_CMDID, | ||
| 612 | |||
| 613 | /* Scan specific commands */ | ||
| 614 | |||
| 615 | WMI_10X_START_SCAN_CMDID = WMI_10X_START_CMDID, | ||
| 616 | WMI_10X_STOP_SCAN_CMDID, | ||
| 617 | WMI_10X_SCAN_CHAN_LIST_CMDID, | ||
| 618 | WMI_10X_ECHO_CMDID, | ||
| 619 | |||
| 620 | /* PDEV(physical device) specific commands */ | ||
| 621 | WMI_10X_PDEV_SET_REGDOMAIN_CMDID, | ||
| 622 | WMI_10X_PDEV_SET_CHANNEL_CMDID, | ||
| 623 | WMI_10X_PDEV_SET_PARAM_CMDID, | ||
| 624 | WMI_10X_PDEV_PKTLOG_ENABLE_CMDID, | ||
| 625 | WMI_10X_PDEV_PKTLOG_DISABLE_CMDID, | ||
| 626 | WMI_10X_PDEV_SET_WMM_PARAMS_CMDID, | ||
| 627 | WMI_10X_PDEV_SET_HT_CAP_IE_CMDID, | ||
| 628 | WMI_10X_PDEV_SET_VHT_CAP_IE_CMDID, | ||
| 629 | WMI_10X_PDEV_SET_BASE_MACADDR_CMDID, | ||
| 630 | WMI_10X_PDEV_SET_DSCP_TID_MAP_CMDID, | ||
| 631 | WMI_10X_PDEV_SET_QUIET_MODE_CMDID, | ||
| 632 | WMI_10X_PDEV_GREEN_AP_PS_ENABLE_CMDID, | ||
| 633 | WMI_10X_PDEV_GET_TPC_CONFIG_CMDID, | ||
| 634 | |||
| 635 | /* VDEV(virtual device) specific commands */ | ||
| 636 | WMI_10X_VDEV_CREATE_CMDID, | ||
| 637 | WMI_10X_VDEV_DELETE_CMDID, | ||
| 638 | WMI_10X_VDEV_START_REQUEST_CMDID, | ||
| 639 | WMI_10X_VDEV_RESTART_REQUEST_CMDID, | ||
| 640 | WMI_10X_VDEV_UP_CMDID, | ||
| 641 | WMI_10X_VDEV_STOP_CMDID, | ||
| 642 | WMI_10X_VDEV_DOWN_CMDID, | ||
| 643 | WMI_10X_VDEV_STANDBY_RESPONSE_CMDID, | ||
| 644 | WMI_10X_VDEV_RESUME_RESPONSE_CMDID, | ||
| 645 | WMI_10X_VDEV_SET_PARAM_CMDID, | ||
| 646 | WMI_10X_VDEV_INSTALL_KEY_CMDID, | ||
| 647 | |||
| 648 | /* peer specific commands */ | ||
| 649 | WMI_10X_PEER_CREATE_CMDID, | ||
| 650 | WMI_10X_PEER_DELETE_CMDID, | ||
| 651 | WMI_10X_PEER_FLUSH_TIDS_CMDID, | ||
| 652 | WMI_10X_PEER_SET_PARAM_CMDID, | ||
| 653 | WMI_10X_PEER_ASSOC_CMDID, | ||
| 654 | WMI_10X_PEER_ADD_WDS_ENTRY_CMDID, | ||
| 655 | WMI_10X_PEER_REMOVE_WDS_ENTRY_CMDID, | ||
| 656 | WMI_10X_PEER_MCAST_GROUP_CMDID, | ||
| 657 | |||
| 658 | /* beacon/management specific commands */ | ||
| 659 | |||
| 660 | WMI_10X_BCN_TX_CMDID, | ||
| 661 | WMI_10X_BCN_PRB_TMPL_CMDID, | ||
| 662 | WMI_10X_BCN_FILTER_RX_CMDID, | ||
| 663 | WMI_10X_PRB_REQ_FILTER_RX_CMDID, | ||
| 664 | WMI_10X_MGMT_TX_CMDID, | ||
| 665 | |||
| 666 | /* commands to directly control ba negotiation directly from host. */ | ||
| 667 | WMI_10X_ADDBA_CLEAR_RESP_CMDID, | ||
| 668 | WMI_10X_ADDBA_SEND_CMDID, | ||
| 669 | WMI_10X_ADDBA_STATUS_CMDID, | ||
| 670 | WMI_10X_DELBA_SEND_CMDID, | ||
| 671 | WMI_10X_ADDBA_SET_RESP_CMDID, | ||
| 672 | WMI_10X_SEND_SINGLEAMSDU_CMDID, | ||
| 673 | |||
| 674 | /* Station power save specific config */ | ||
| 675 | WMI_10X_STA_POWERSAVE_MODE_CMDID, | ||
| 676 | WMI_10X_STA_POWERSAVE_PARAM_CMDID, | ||
| 677 | WMI_10X_STA_MIMO_PS_MODE_CMDID, | ||
| 678 | |||
| 679 | /* set debug log config */ | ||
| 680 | WMI_10X_DBGLOG_CFG_CMDID, | ||
| 681 | |||
| 682 | /* DFS-specific commands */ | ||
| 683 | WMI_10X_PDEV_DFS_ENABLE_CMDID, | ||
| 684 | WMI_10X_PDEV_DFS_DISABLE_CMDID, | ||
| 685 | |||
| 686 | /* QVIT specific command id */ | ||
| 687 | WMI_10X_PDEV_QVIT_CMDID, | ||
| 688 | |||
| 689 | /* Offload Scan and Roaming related commands */ | ||
| 690 | WMI_10X_ROAM_SCAN_MODE, | ||
| 691 | WMI_10X_ROAM_SCAN_RSSI_THRESHOLD, | ||
| 692 | WMI_10X_ROAM_SCAN_PERIOD, | ||
| 693 | WMI_10X_ROAM_SCAN_RSSI_CHANGE_THRESHOLD, | ||
| 694 | WMI_10X_ROAM_AP_PROFILE, | ||
| 695 | WMI_10X_OFL_SCAN_ADD_AP_PROFILE, | ||
| 696 | WMI_10X_OFL_SCAN_REMOVE_AP_PROFILE, | ||
| 697 | WMI_10X_OFL_SCAN_PERIOD, | ||
| 698 | |||
| 699 | /* P2P specific commands */ | ||
| 700 | WMI_10X_P2P_DEV_SET_DEVICE_INFO, | ||
| 701 | WMI_10X_P2P_DEV_SET_DISCOVERABILITY, | ||
| 702 | WMI_10X_P2P_GO_SET_BEACON_IE, | ||
| 703 | WMI_10X_P2P_GO_SET_PROBE_RESP_IE, | ||
| 704 | |||
| 705 | /* AP power save specific config */ | ||
| 706 | WMI_10X_AP_PS_PEER_PARAM_CMDID, | ||
| 707 | WMI_10X_AP_PS_PEER_UAPSD_COEX_CMDID, | ||
| 708 | |||
| 709 | /* Rate-control specific commands */ | ||
| 710 | WMI_10X_PEER_RATE_RETRY_SCHED_CMDID, | ||
| 711 | |||
| 712 | /* WLAN Profiling commands. */ | ||
| 713 | WMI_10X_WLAN_PROFILE_TRIGGER_CMDID, | ||
| 714 | WMI_10X_WLAN_PROFILE_SET_HIST_INTVL_CMDID, | ||
| 715 | WMI_10X_WLAN_PROFILE_GET_PROFILE_DATA_CMDID, | ||
| 716 | WMI_10X_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID, | ||
| 717 | WMI_10X_WLAN_PROFILE_LIST_PROFILE_ID_CMDID, | ||
| 718 | |||
| 719 | /* Suspend resume command Ids */ | ||
| 720 | WMI_10X_PDEV_SUSPEND_CMDID, | ||
| 721 | WMI_10X_PDEV_RESUME_CMDID, | ||
| 722 | |||
| 723 | /* Beacon filter commands */ | ||
| 724 | WMI_10X_ADD_BCN_FILTER_CMDID, | ||
| 725 | WMI_10X_RMV_BCN_FILTER_CMDID, | ||
| 726 | |||
| 727 | /* WOW Specific WMI commands*/ | ||
| 728 | WMI_10X_WOW_ADD_WAKE_PATTERN_CMDID, | ||
| 729 | WMI_10X_WOW_DEL_WAKE_PATTERN_CMDID, | ||
| 730 | WMI_10X_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID, | ||
| 731 | WMI_10X_WOW_ENABLE_CMDID, | ||
| 732 | WMI_10X_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID, | ||
| 733 | |||
| 734 | /* RTT measurement related cmd */ | ||
| 735 | WMI_10X_RTT_MEASREQ_CMDID, | ||
| 736 | WMI_10X_RTT_TSF_CMDID, | ||
| 737 | |||
| 738 | /* transmit beacon by value */ | ||
| 739 | WMI_10X_PDEV_SEND_BCN_CMDID, | ||
| 740 | |||
| 741 | /* F/W stats */ | ||
| 742 | WMI_10X_VDEV_SPECTRAL_SCAN_CONFIGURE_CMDID, | ||
| 743 | WMI_10X_VDEV_SPECTRAL_SCAN_ENABLE_CMDID, | ||
| 744 | WMI_10X_REQUEST_STATS_CMDID, | ||
| 745 | |||
| 746 | /* GPIO Configuration */ | ||
| 747 | WMI_10X_GPIO_CONFIG_CMDID, | ||
| 748 | WMI_10X_GPIO_OUTPUT_CMDID, | ||
| 749 | |||
| 750 | WMI_10X_PDEV_UTF_CMDID = WMI_10X_END_CMDID - 1, | ||
| 751 | }; | ||
| 752 | |||
| 753 | enum wmi_10x_event_id { | ||
| 754 | WMI_10X_SERVICE_READY_EVENTID = 0x8000, | ||
| 755 | WMI_10X_READY_EVENTID, | ||
| 756 | WMI_10X_START_EVENTID = 0x9000, | ||
| 757 | WMI_10X_END_EVENTID = 0x9FFF, | ||
| 758 | |||
| 759 | /* Scan specific events */ | ||
| 760 | WMI_10X_SCAN_EVENTID = WMI_10X_START_EVENTID, | ||
| 761 | WMI_10X_ECHO_EVENTID, | ||
| 762 | WMI_10X_DEBUG_MESG_EVENTID, | ||
| 763 | WMI_10X_UPDATE_STATS_EVENTID, | ||
| 764 | |||
| 765 | /* Instantaneous RSSI event */ | ||
| 766 | WMI_10X_INST_RSSI_STATS_EVENTID, | ||
| 767 | |||
| 768 | /* VDEV specific events */ | ||
| 769 | WMI_10X_VDEV_START_RESP_EVENTID, | ||
| 770 | WMI_10X_VDEV_STANDBY_REQ_EVENTID, | ||
| 771 | WMI_10X_VDEV_RESUME_REQ_EVENTID, | ||
| 772 | WMI_10X_VDEV_STOPPED_EVENTID, | ||
| 773 | |||
| 774 | /* peer specific events */ | ||
| 775 | WMI_10X_PEER_STA_KICKOUT_EVENTID, | ||
| 776 | |||
| 777 | /* beacon/mgmt specific events */ | ||
| 778 | WMI_10X_HOST_SWBA_EVENTID, | ||
| 779 | WMI_10X_TBTTOFFSET_UPDATE_EVENTID, | ||
| 780 | WMI_10X_MGMT_RX_EVENTID, | ||
| 781 | |||
| 782 | /* Channel stats event */ | ||
| 783 | WMI_10X_CHAN_INFO_EVENTID, | ||
| 784 | |||
| 785 | /* PHY Error specific WMI event */ | ||
| 786 | WMI_10X_PHYERR_EVENTID, | ||
| 787 | |||
| 788 | /* Roam event to trigger roaming on host */ | ||
| 789 | WMI_10X_ROAM_EVENTID, | ||
| 790 | |||
| 791 | /* matching AP found from list of profiles */ | ||
| 792 | WMI_10X_PROFILE_MATCH, | ||
| 793 | |||
| 794 | /* debug print message used for tracing FW code while debugging */ | ||
| 795 | WMI_10X_DEBUG_PRINT_EVENTID, | ||
| 796 | /* VI spoecific event */ | ||
| 797 | WMI_10X_PDEV_QVIT_EVENTID, | ||
| 798 | /* FW code profile data in response to profile request */ | ||
| 799 | WMI_10X_WLAN_PROFILE_DATA_EVENTID, | ||
| 800 | |||
| 801 | /*RTT related event ID*/ | ||
| 802 | WMI_10X_RTT_MEASUREMENT_REPORT_EVENTID, | ||
| 803 | WMI_10X_TSF_MEASUREMENT_REPORT_EVENTID, | ||
| 804 | WMI_10X_RTT_ERROR_REPORT_EVENTID, | ||
| 805 | |||
| 806 | WMI_10X_WOW_WAKEUP_HOST_EVENTID, | ||
| 807 | WMI_10X_DCS_INTERFERENCE_EVENTID, | ||
| 808 | |||
| 809 | /* TPC config for the current operating channel */ | ||
| 810 | WMI_10X_PDEV_TPC_CONFIG_EVENTID, | ||
| 811 | |||
| 812 | WMI_10X_GPIO_INPUT_EVENTID, | ||
| 813 | WMI_10X_PDEV_UTF_EVENTID = WMI_10X_END_EVENTID-1, | ||
| 814 | }; | ||
| 815 | |||
| 491 | enum wmi_phy_mode { | 816 | enum wmi_phy_mode { |
| 492 | MODE_11A = 0, /* 11a Mode */ | 817 | MODE_11A = 0, /* 11a Mode */ |
| 493 | MODE_11G = 1, /* 11b/g Mode */ | 818 | MODE_11G = 1, /* 11b/g Mode */ |
| @@ -805,6 +1130,46 @@ struct wmi_service_ready_event { | |||
| 805 | struct wlan_host_mem_req mem_reqs[1]; | 1130 | struct wlan_host_mem_req mem_reqs[1]; |
| 806 | } __packed; | 1131 | } __packed; |
| 807 | 1132 | ||
| 1133 | /* This is the definition from 10.X firmware branch */ | ||
| 1134 | struct wmi_service_ready_event_10x { | ||
| 1135 | __le32 sw_version; | ||
| 1136 | __le32 abi_version; | ||
| 1137 | |||
| 1138 | /* WMI_PHY_CAPABILITY */ | ||
| 1139 | __le32 phy_capability; | ||
| 1140 | |||
| 1141 | /* Maximum number of frag table entries that SW will populate less 1 */ | ||
| 1142 | __le32 max_frag_entry; | ||
| 1143 | __le32 wmi_service_bitmap[WMI_SERVICE_BM_SIZE]; | ||
| 1144 | __le32 num_rf_chains; | ||
| 1145 | |||
| 1146 | /* | ||
| 1147 | * The following field is only valid for service type | ||
| 1148 | * WMI_SERVICE_11AC | ||
| 1149 | */ | ||
| 1150 | __le32 ht_cap_info; /* WMI HT Capability */ | ||
| 1151 | __le32 vht_cap_info; /* VHT capability info field of 802.11ac */ | ||
| 1152 | __le32 vht_supp_mcs; /* VHT Supported MCS Set field Rx/Tx same */ | ||
| 1153 | __le32 hw_min_tx_power; | ||
| 1154 | __le32 hw_max_tx_power; | ||
| 1155 | |||
| 1156 | struct hal_reg_capabilities hal_reg_capabilities; | ||
| 1157 | |||
| 1158 | __le32 sys_cap_info; | ||
| 1159 | __le32 min_pkt_size_enable; /* Enterprise mode short pkt enable */ | ||
| 1160 | |||
| 1161 | /* | ||
| 1162 | * request to host to allocate a chuck of memory and pss it down to FW | ||
| 1163 | * via WM_INIT. FW uses this as FW extesnsion memory for saving its | ||
| 1164 | * data structures. Only valid for low latency interfaces like PCIE | ||
| 1165 | * where FW can access this memory directly (or) by DMA. | ||
| 1166 | */ | ||
| 1167 | __le32 num_mem_reqs; | ||
| 1168 | |||
| 1169 | struct wlan_host_mem_req mem_reqs[1]; | ||
| 1170 | } __packed; | ||
| 1171 | |||
| 1172 | |||
| 808 | #define WMI_SERVICE_READY_TIMEOUT_HZ (5*HZ) | 1173 | #define WMI_SERVICE_READY_TIMEOUT_HZ (5*HZ) |
| 809 | #define WMI_UNIFIED_READY_TIMEOUT_HZ (5*HZ) | 1174 | #define WMI_UNIFIED_READY_TIMEOUT_HZ (5*HZ) |
| 810 | 1175 | ||
| @@ -1012,6 +1377,192 @@ struct wmi_resource_config { | |||
| 1012 | __le32 max_frag_entries; | 1377 | __le32 max_frag_entries; |
| 1013 | } __packed; | 1378 | } __packed; |
| 1014 | 1379 | ||
| 1380 | struct wmi_resource_config_10x { | ||
| 1381 | /* number of virtual devices (VAPs) to support */ | ||
| 1382 | __le32 num_vdevs; | ||
| 1383 | |||
| 1384 | /* number of peer nodes to support */ | ||
| 1385 | __le32 num_peers; | ||
| 1386 | |||
| 1387 | /* number of keys per peer */ | ||
| 1388 | __le32 num_peer_keys; | ||
| 1389 | |||
| 1390 | /* total number of TX/RX data TIDs */ | ||
| 1391 | __le32 num_tids; | ||
| 1392 | |||
| 1393 | /* | ||
| 1394 | * max skid for resolving hash collisions | ||
| 1395 | * | ||
| 1396 | * The address search table is sparse, so that if two MAC addresses | ||
| 1397 | * result in the same hash value, the second of these conflicting | ||
| 1398 | * entries can slide to the next index in the address search table, | ||
| 1399 | * and use it, if it is unoccupied. This ast_skid_limit parameter | ||
| 1400 | * specifies the upper bound on how many subsequent indices to search | ||
| 1401 | * over to find an unoccupied space. | ||
| 1402 | */ | ||
| 1403 | __le32 ast_skid_limit; | ||
| 1404 | |||
| 1405 | /* | ||
| 1406 | * the nominal chain mask for transmit | ||
| 1407 | * | ||
| 1408 | * The chain mask may be modified dynamically, e.g. to operate AP | ||
| 1409 | * tx with a reduced number of chains if no clients are associated. | ||
| 1410 | * This configuration parameter specifies the nominal chain-mask that | ||
| 1411 | * should be used when not operating with a reduced set of tx chains. | ||
| 1412 | */ | ||
| 1413 | __le32 tx_chain_mask; | ||
| 1414 | |||
| 1415 | /* | ||
| 1416 | * the nominal chain mask for receive | ||
| 1417 | * | ||
| 1418 | * The chain mask may be modified dynamically, e.g. for a client | ||
| 1419 | * to use a reduced number of chains for receive if the traffic to | ||
| 1420 | * the client is low enough that it doesn't require downlink MIMO | ||
| 1421 | * or antenna diversity. | ||
| 1422 | * This configuration parameter specifies the nominal chain-mask that | ||
| 1423 | * should be used when not operating with a reduced set of rx chains. | ||
| 1424 | */ | ||
| 1425 | __le32 rx_chain_mask; | ||
| 1426 | |||
| 1427 | /* | ||
| 1428 | * what rx reorder timeout (ms) to use for the AC | ||
| 1429 | * | ||
| 1430 | * Each WMM access class (voice, video, best-effort, background) will | ||
| 1431 | * have its own timeout value to dictate how long to wait for missing | ||
| 1432 | * rx MPDUs to arrive before flushing subsequent MPDUs that have | ||
| 1433 | * already been received. | ||
| 1434 | * This parameter specifies the timeout in milliseconds for each | ||
| 1435 | * class. | ||
| 1436 | */ | ||
| 1437 | __le32 rx_timeout_pri_vi; | ||
| 1438 | __le32 rx_timeout_pri_vo; | ||
| 1439 | __le32 rx_timeout_pri_be; | ||
| 1440 | __le32 rx_timeout_pri_bk; | ||
| 1441 | |||
| 1442 | /* | ||
| 1443 | * what mode the rx should decap packets to | ||
| 1444 | * | ||
| 1445 | * MAC can decap to RAW (no decap), native wifi or Ethernet types | ||
| 1446 | * THis setting also determines the default TX behavior, however TX | ||
| 1447 | * behavior can be modified on a per VAP basis during VAP init | ||
| 1448 | */ | ||
| 1449 | __le32 rx_decap_mode; | ||
| 1450 | |||
| 1451 | /* what is the maximum scan requests than can be queued */ | ||
| 1452 | __le32 scan_max_pending_reqs; | ||
| 1453 | |||
| 1454 | /* maximum VDEV that could use BMISS offload */ | ||
| 1455 | __le32 bmiss_offload_max_vdev; | ||
| 1456 | |||
| 1457 | /* maximum VDEV that could use offload roaming */ | ||
| 1458 | __le32 roam_offload_max_vdev; | ||
| 1459 | |||
| 1460 | /* maximum AP profiles that would push to offload roaming */ | ||
| 1461 | __le32 roam_offload_max_ap_profiles; | ||
| 1462 | |||
| 1463 | /* | ||
| 1464 | * how many groups to use for mcast->ucast conversion | ||
| 1465 | * | ||
| 1466 | * The target's WAL maintains a table to hold information regarding | ||
| 1467 | * which peers belong to a given multicast group, so that if | ||
| 1468 | * multicast->unicast conversion is enabled, the target can convert | ||
| 1469 | * multicast tx frames to a series of unicast tx frames, to each | ||
| 1470 | * peer within the multicast group. | ||
| 1471 | This num_mcast_groups configuration parameter tells the target how | ||
| 1472 | * many multicast groups to provide storage for within its multicast | ||
| 1473 | * group membership table. | ||
| 1474 | */ | ||
| 1475 | __le32 num_mcast_groups; | ||
| 1476 | |||
| 1477 | /* | ||
| 1478 | * size to alloc for the mcast membership table | ||
| 1479 | * | ||
| 1480 | * This num_mcast_table_elems configuration parameter tells the | ||
| 1481 | * target how many peer elements it needs to provide storage for in | ||
| 1482 | * its multicast group membership table. | ||
| 1483 | * These multicast group membership table elements are shared by the | ||
| 1484 | * multicast groups stored within the table. | ||
| 1485 | */ | ||
| 1486 | __le32 num_mcast_table_elems; | ||
| 1487 | |||
| 1488 | /* | ||
| 1489 | * whether/how to do multicast->unicast conversion | ||
| 1490 | * | ||
| 1491 | * This configuration parameter specifies whether the target should | ||
| 1492 | * perform multicast --> unicast conversion on transmit, and if so, | ||
| 1493 | * what to do if it finds no entries in its multicast group | ||
| 1494 | * membership table for the multicast IP address in the tx frame. | ||
| 1495 | * Configuration value: | ||
| 1496 | * 0 -> Do not perform multicast to unicast conversion. | ||
| 1497 | * 1 -> Convert multicast frames to unicast, if the IP multicast | ||
| 1498 | * address from the tx frame is found in the multicast group | ||
| 1499 | * membership table. If the IP multicast address is not found, | ||
| 1500 | * drop the frame. | ||
| 1501 | * 2 -> Convert multicast frames to unicast, if the IP multicast | ||
| 1502 | * address from the tx frame is found in the multicast group | ||
| 1503 | * membership table. If the IP multicast address is not found, | ||
| 1504 | * transmit the frame as multicast. | ||
| 1505 | */ | ||
| 1506 | __le32 mcast2ucast_mode; | ||
| 1507 | |||
| 1508 | /* | ||
| 1509 | * how much memory to allocate for a tx PPDU dbg log | ||
| 1510 | * | ||
| 1511 | * This parameter controls how much memory the target will allocate | ||
| 1512 | * to store a log of tx PPDU meta-information (how large the PPDU | ||
| 1513 | * was, when it was sent, whether it was successful, etc.) | ||
| 1514 | */ | ||
| 1515 | __le32 tx_dbg_log_size; | ||
| 1516 | |||
| 1517 | /* how many AST entries to be allocated for WDS */ | ||
| 1518 | __le32 num_wds_entries; | ||
| 1519 | |||
| 1520 | /* | ||
| 1521 | * MAC DMA burst size, e.g., For target PCI limit can be | ||
| 1522 | * 0 -default, 1 256B | ||
| 1523 | */ | ||
| 1524 | __le32 dma_burst_size; | ||
| 1525 | |||
| 1526 | /* | ||
| 1527 | * Fixed delimiters to be inserted after every MPDU to | ||
| 1528 | * account for interface latency to avoid underrun. | ||
| 1529 | */ | ||
| 1530 | __le32 mac_aggr_delim; | ||
| 1531 | |||
| 1532 | /* | ||
| 1533 | * determine whether target is responsible for detecting duplicate | ||
| 1534 | * non-aggregate MPDU and timing out stale fragments. | ||
| 1535 | * | ||
| 1536 | * A-MPDU reordering is always performed on the target. | ||
| 1537 | * | ||
| 1538 | * 0: target responsible for frag timeout and dup checking | ||
| 1539 | * 1: host responsible for frag timeout and dup checking | ||
| 1540 | */ | ||
| 1541 | __le32 rx_skip_defrag_timeout_dup_detection_check; | ||
| 1542 | |||
| 1543 | /* | ||
| 1544 | * Configuration for VoW : | ||
| 1545 | * No of Video Nodes to be supported | ||
| 1546 | * and Max no of descriptors for each Video link (node). | ||
| 1547 | */ | ||
| 1548 | __le32 vow_config; | ||
| 1549 | |||
| 1550 | /* Number of msdu descriptors target should use */ | ||
| 1551 | __le32 num_msdu_desc; | ||
| 1552 | |||
| 1553 | /* | ||
| 1554 | * Max. number of Tx fragments per MSDU | ||
| 1555 | * This parameter controls the max number of Tx fragments per MSDU. | ||
| 1556 | * This is sent by the target as part of the WMI_SERVICE_READY event | ||
| 1557 | * and is overriden by the OS shim as required. | ||
| 1558 | */ | ||
| 1559 | __le32 max_frag_entries; | ||
| 1560 | } __packed; | ||
| 1561 | |||
| 1562 | |||
| 1563 | #define NUM_UNITS_IS_NUM_VDEVS 0x1 | ||
| 1564 | #define NUM_UNITS_IS_NUM_PEERS 0x2 | ||
| 1565 | |||
| 1015 | /* strucutre describing host memory chunk. */ | 1566 | /* strucutre describing host memory chunk. */ |
| 1016 | struct host_memory_chunk { | 1567 | struct host_memory_chunk { |
| 1017 | /* id of the request that is passed up in service ready */ | 1568 | /* id of the request that is passed up in service ready */ |
| @@ -1033,6 +1584,18 @@ struct wmi_init_cmd { | |||
| 1033 | struct host_memory_chunk host_mem_chunks[1]; | 1584 | struct host_memory_chunk host_mem_chunks[1]; |
| 1034 | } __packed; | 1585 | } __packed; |
| 1035 | 1586 | ||
| 1587 | /* _10x stucture is from 10.X FW API */ | ||
| 1588 | struct wmi_init_cmd_10x { | ||
| 1589 | struct wmi_resource_config_10x resource_config; | ||
| 1590 | __le32 num_host_mem_chunks; | ||
| 1591 | |||
| 1592 | /* | ||
| 1593 | * variable number of host memory chunks. | ||
| 1594 | * This should be the last element in the structure | ||
| 1595 | */ | ||
| 1596 | struct host_memory_chunk host_mem_chunks[1]; | ||
| 1597 | } __packed; | ||
| 1598 | |||
| 1036 | /* TLV for channel list */ | 1599 | /* TLV for channel list */ |
| 1037 | struct wmi_chan_list { | 1600 | struct wmi_chan_list { |
| 1038 | __le32 tag; /* WMI_CHAN_LIST_TAG */ | 1601 | __le32 tag; /* WMI_CHAN_LIST_TAG */ |
| @@ -1152,6 +1715,88 @@ struct wmi_start_scan_cmd { | |||
| 1152 | */ | 1715 | */ |
| 1153 | } __packed; | 1716 | } __packed; |
| 1154 | 1717 | ||
| 1718 | /* This is the definition from 10.X firmware branch */ | ||
| 1719 | struct wmi_start_scan_cmd_10x { | ||
| 1720 | /* Scan ID */ | ||
| 1721 | __le32 scan_id; | ||
| 1722 | |||
| 1723 | /* Scan requestor ID */ | ||
| 1724 | __le32 scan_req_id; | ||
| 1725 | |||
| 1726 | /* VDEV id(interface) that is requesting scan */ | ||
| 1727 | __le32 vdev_id; | ||
| 1728 | |||
| 1729 | /* Scan Priority, input to scan scheduler */ | ||
| 1730 | __le32 scan_priority; | ||
| 1731 | |||
| 1732 | /* Scan events subscription */ | ||
| 1733 | __le32 notify_scan_events; | ||
| 1734 | |||
| 1735 | /* dwell time in msec on active channels */ | ||
| 1736 | __le32 dwell_time_active; | ||
| 1737 | |||
| 1738 | /* dwell time in msec on passive channels */ | ||
| 1739 | __le32 dwell_time_passive; | ||
| 1740 | |||
| 1741 | /* | ||
| 1742 | * min time in msec on the BSS channel,only valid if atleast one | ||
| 1743 | * VDEV is active | ||
| 1744 | */ | ||
| 1745 | __le32 min_rest_time; | ||
| 1746 | |||
| 1747 | /* | ||
| 1748 | * max rest time in msec on the BSS channel,only valid if at least | ||
| 1749 | * one VDEV is active | ||
| 1750 | */ | ||
| 1751 | /* | ||
| 1752 | * the scanner will rest on the bss channel at least min_rest_time | ||
| 1753 | * after min_rest_time the scanner will start checking for tx/rx | ||
| 1754 | * activity on all VDEVs. if there is no activity the scanner will | ||
| 1755 | * switch to off channel. if there is activity the scanner will let | ||
| 1756 | * the radio on the bss channel until max_rest_time expires.at | ||
| 1757 | * max_rest_time scanner will switch to off channel irrespective of | ||
| 1758 | * activity. activity is determined by the idle_time parameter. | ||
| 1759 | */ | ||
| 1760 | __le32 max_rest_time; | ||
| 1761 | |||
| 1762 | /* | ||
| 1763 | * time before sending next set of probe requests. | ||
| 1764 | * The scanner keeps repeating probe requests transmission with | ||
| 1765 | * period specified by repeat_probe_time. | ||
| 1766 | * The number of probe requests specified depends on the ssid_list | ||
| 1767 | * and bssid_list | ||
| 1768 | */ | ||
| 1769 | __le32 repeat_probe_time; | ||
| 1770 | |||
| 1771 | /* time in msec between 2 consequetive probe requests with in a set. */ | ||
| 1772 | __le32 probe_spacing_time; | ||
| 1773 | |||
| 1774 | /* | ||
| 1775 | * data inactivity time in msec on bss channel that will be used by | ||
| 1776 | * scanner for measuring the inactivity. | ||
| 1777 | */ | ||
| 1778 | __le32 idle_time; | ||
| 1779 | |||
| 1780 | /* maximum time in msec allowed for scan */ | ||
| 1781 | __le32 max_scan_time; | ||
| 1782 | |||
| 1783 | /* | ||
| 1784 | * delay in msec before sending first probe request after switching | ||
| 1785 | * to a channel | ||
| 1786 | */ | ||
| 1787 | __le32 probe_delay; | ||
| 1788 | |||
| 1789 | /* Scan control flags */ | ||
| 1790 | __le32 scan_ctrl_flags; | ||
| 1791 | |||
| 1792 | /* | ||
| 1793 | * TLV (tag length value ) paramerters follow the scan_cmd structure. | ||
| 1794 | * TLV can contain channel list, bssid list, ssid list and | ||
| 1795 | * ie. the TLV tags are defined above; | ||
| 1796 | */ | ||
| 1797 | } __packed; | ||
| 1798 | |||
| 1799 | |||
| 1155 | struct wmi_ssid_arg { | 1800 | struct wmi_ssid_arg { |
| 1156 | int len; | 1801 | int len; |
| 1157 | const u8 *ssid; | 1802 | const u8 *ssid; |
| @@ -1509,6 +2154,60 @@ struct wmi_csa_event { | |||
| 1509 | #define VDEV_DEFAULT_STATS_UPDATE_PERIOD 500 | 2154 | #define VDEV_DEFAULT_STATS_UPDATE_PERIOD 500 |
| 1510 | #define PEER_DEFAULT_STATS_UPDATE_PERIOD 500 | 2155 | #define PEER_DEFAULT_STATS_UPDATE_PERIOD 500 |
| 1511 | 2156 | ||
| 2157 | struct wmi_pdev_param_map { | ||
| 2158 | u32 tx_chain_mask; | ||
| 2159 | u32 rx_chain_mask; | ||
| 2160 | u32 txpower_limit2g; | ||
| 2161 | u32 txpower_limit5g; | ||
| 2162 | u32 txpower_scale; | ||
| 2163 | u32 beacon_gen_mode; | ||
| 2164 | u32 beacon_tx_mode; | ||
| 2165 | u32 resmgr_offchan_mode; | ||
| 2166 | u32 protection_mode; | ||
| 2167 | u32 dynamic_bw; | ||
| 2168 | u32 non_agg_sw_retry_th; | ||
| 2169 | u32 agg_sw_retry_th; | ||
| 2170 | u32 sta_kickout_th; | ||
| 2171 | u32 ac_aggrsize_scaling; | ||
| 2172 | u32 ltr_enable; | ||
| 2173 | u32 ltr_ac_latency_be; | ||
| 2174 | u32 ltr_ac_latency_bk; | ||
| 2175 | u32 ltr_ac_latency_vi; | ||
| 2176 | u32 ltr_ac_latency_vo; | ||
| 2177 | u32 ltr_ac_latency_timeout; | ||
| 2178 | u32 ltr_sleep_override; | ||
| 2179 | u32 ltr_rx_override; | ||
| 2180 | u32 ltr_tx_activity_timeout; | ||
| 2181 | u32 l1ss_enable; | ||
| 2182 | u32 dsleep_enable; | ||
| 2183 | u32 pcielp_txbuf_flush; | ||
| 2184 | u32 pcielp_txbuf_watermark; | ||
| 2185 | u32 pcielp_txbuf_tmo_en; | ||
| 2186 | u32 pcielp_txbuf_tmo_value; | ||
| 2187 | u32 pdev_stats_update_period; | ||
| 2188 | u32 vdev_stats_update_period; | ||
| 2189 | u32 peer_stats_update_period; | ||
| 2190 | u32 bcnflt_stats_update_period; | ||
| 2191 | u32 pmf_qos; | ||
| 2192 | u32 arp_ac_override; | ||
| 2193 | u32 arpdhcp_ac_override; | ||
| 2194 | u32 dcs; | ||
| 2195 | u32 ani_enable; | ||
| 2196 | u32 ani_poll_period; | ||
| 2197 | u32 ani_listen_period; | ||
| 2198 | u32 ani_ofdm_level; | ||
| 2199 | u32 ani_cck_level; | ||
| 2200 | u32 dyntxchain; | ||
| 2201 | u32 proxy_sta; | ||
| 2202 | u32 idle_ps_config; | ||
| 2203 | u32 power_gating_sleep; | ||
| 2204 | u32 fast_channel_reset; | ||
| 2205 | u32 burst_dur; | ||
| 2206 | u32 burst_enable; | ||
| 2207 | }; | ||
| 2208 | |||
| 2209 | #define WMI_PDEV_PARAM_UNSUPPORTED 0 | ||
| 2210 | |||
| 1512 | enum wmi_pdev_param { | 2211 | enum wmi_pdev_param { |
| 1513 | /* TX chian mask */ | 2212 | /* TX chian mask */ |
| 1514 | WMI_PDEV_PARAM_TX_CHAIN_MASK = 0x1, | 2213 | WMI_PDEV_PARAM_TX_CHAIN_MASK = 0x1, |
| @@ -1608,6 +2307,97 @@ enum wmi_pdev_param { | |||
| 1608 | WMI_PDEV_PARAM_POWER_GATING_SLEEP, | 2307 | WMI_PDEV_PARAM_POWER_GATING_SLEEP, |
| 1609 | }; | 2308 | }; |
| 1610 | 2309 | ||
| 2310 | enum wmi_10x_pdev_param { | ||
| 2311 | /* TX chian mask */ | ||
| 2312 | WMI_10X_PDEV_PARAM_TX_CHAIN_MASK = 0x1, | ||
| 2313 | /* RX chian mask */ | ||
| 2314 | WMI_10X_PDEV_PARAM_RX_CHAIN_MASK, | ||
| 2315 | /* TX power limit for 2G Radio */ | ||
| 2316 | WMI_10X_PDEV_PARAM_TXPOWER_LIMIT2G, | ||
| 2317 | /* TX power limit for 5G Radio */ | ||
| 2318 | WMI_10X_PDEV_PARAM_TXPOWER_LIMIT5G, | ||
| 2319 | /* TX power scale */ | ||
| 2320 | WMI_10X_PDEV_PARAM_TXPOWER_SCALE, | ||
| 2321 | /* Beacon generation mode . 0: host, 1: target */ | ||
| 2322 | WMI_10X_PDEV_PARAM_BEACON_GEN_MODE, | ||
| 2323 | /* Beacon generation mode . 0: staggered 1: bursted */ | ||
| 2324 | WMI_10X_PDEV_PARAM_BEACON_TX_MODE, | ||
| 2325 | /* | ||
| 2326 | * Resource manager off chan mode . | ||
| 2327 | * 0: turn off off chan mode. 1: turn on offchan mode | ||
| 2328 | */ | ||
| 2329 | WMI_10X_PDEV_PARAM_RESMGR_OFFCHAN_MODE, | ||
| 2330 | /* | ||
| 2331 | * Protection mode: | ||
| 2332 | * 0: no protection 1:use CTS-to-self 2: use RTS/CTS | ||
| 2333 | */ | ||
| 2334 | WMI_10X_PDEV_PARAM_PROTECTION_MODE, | ||
| 2335 | /* Dynamic bandwidth 0: disable 1: enable */ | ||
| 2336 | WMI_10X_PDEV_PARAM_DYNAMIC_BW, | ||
| 2337 | /* Non aggregrate/ 11g sw retry threshold.0-disable */ | ||
| 2338 | WMI_10X_PDEV_PARAM_NON_AGG_SW_RETRY_TH, | ||
| 2339 | /* aggregrate sw retry threshold. 0-disable*/ | ||
| 2340 | WMI_10X_PDEV_PARAM_AGG_SW_RETRY_TH, | ||
| 2341 | /* Station kickout threshold (non of consecutive failures).0-disable */ | ||
| 2342 | WMI_10X_PDEV_PARAM_STA_KICKOUT_TH, | ||
| 2343 | /* Aggerate size scaling configuration per AC */ | ||
| 2344 | WMI_10X_PDEV_PARAM_AC_AGGRSIZE_SCALING, | ||
| 2345 | /* LTR enable */ | ||
| 2346 | WMI_10X_PDEV_PARAM_LTR_ENABLE, | ||
| 2347 | /* LTR latency for BE, in us */ | ||
| 2348 | WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_BE, | ||
| 2349 | /* LTR latency for BK, in us */ | ||
| 2350 | WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_BK, | ||
| 2351 | /* LTR latency for VI, in us */ | ||
| 2352 | WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_VI, | ||
| 2353 | /* LTR latency for VO, in us */ | ||
| 2354 | WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_VO, | ||
| 2355 | /* LTR AC latency timeout, in ms */ | ||
| 2356 | WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_TIMEOUT, | ||
| 2357 | /* LTR platform latency override, in us */ | ||
| 2358 | WMI_10X_PDEV_PARAM_LTR_SLEEP_OVERRIDE, | ||
| 2359 | /* LTR-RX override, in us */ | ||
| 2360 | WMI_10X_PDEV_PARAM_LTR_RX_OVERRIDE, | ||
| 2361 | /* Tx activity timeout for LTR, in us */ | ||
| 2362 | WMI_10X_PDEV_PARAM_LTR_TX_ACTIVITY_TIMEOUT, | ||
| 2363 | /* L1SS state machine enable */ | ||
| 2364 | WMI_10X_PDEV_PARAM_L1SS_ENABLE, | ||
| 2365 | /* Deep sleep state machine enable */ | ||
| 2366 | WMI_10X_PDEV_PARAM_DSLEEP_ENABLE, | ||
| 2367 | /* pdev level stats update period in ms */ | ||
| 2368 | WMI_10X_PDEV_PARAM_PDEV_STATS_UPDATE_PERIOD, | ||
| 2369 | /* vdev level stats update period in ms */ | ||
| 2370 | WMI_10X_PDEV_PARAM_VDEV_STATS_UPDATE_PERIOD, | ||
| 2371 | /* peer level stats update period in ms */ | ||
| 2372 | WMI_10X_PDEV_PARAM_PEER_STATS_UPDATE_PERIOD, | ||
| 2373 | /* beacon filter status update period */ | ||
| 2374 | WMI_10X_PDEV_PARAM_BCNFLT_STATS_UPDATE_PERIOD, | ||
| 2375 | /* QOS Mgmt frame protection MFP/PMF 0: disable, 1: enable */ | ||
| 2376 | WMI_10X_PDEV_PARAM_PMF_QOS, | ||
| 2377 | /* Access category on which ARP and DHCP frames are sent */ | ||
| 2378 | WMI_10X_PDEV_PARAM_ARPDHCP_AC_OVERRIDE, | ||
| 2379 | /* DCS configuration */ | ||
| 2380 | WMI_10X_PDEV_PARAM_DCS, | ||
| 2381 | /* Enable/Disable ANI on target */ | ||
| 2382 | WMI_10X_PDEV_PARAM_ANI_ENABLE, | ||
| 2383 | /* configure the ANI polling period */ | ||
| 2384 | WMI_10X_PDEV_PARAM_ANI_POLL_PERIOD, | ||
| 2385 | /* configure the ANI listening period */ | ||
| 2386 | WMI_10X_PDEV_PARAM_ANI_LISTEN_PERIOD, | ||
| 2387 | /* configure OFDM immunity level */ | ||
| 2388 | WMI_10X_PDEV_PARAM_ANI_OFDM_LEVEL, | ||
| 2389 | /* configure CCK immunity level */ | ||
| 2390 | WMI_10X_PDEV_PARAM_ANI_CCK_LEVEL, | ||
| 2391 | /* Enable/Disable CDD for 1x1 STAs in rate control module */ | ||
| 2392 | WMI_10X_PDEV_PARAM_DYNTXCHAIN, | ||
| 2393 | /* Enable/Disable Fast channel reset*/ | ||
| 2394 | WMI_10X_PDEV_PARAM_FAST_CHANNEL_RESET, | ||
| 2395 | /* Set Bursting DUR */ | ||
| 2396 | WMI_10X_PDEV_PARAM_BURST_DUR, | ||
| 2397 | /* Set Bursting Enable*/ | ||
| 2398 | WMI_10X_PDEV_PARAM_BURST_ENABLE, | ||
| 2399 | }; | ||
| 2400 | |||
| 1611 | struct wmi_pdev_set_param_cmd { | 2401 | struct wmi_pdev_set_param_cmd { |
| 1612 | __le32 param_id; | 2402 | __le32 param_id; |
| 1613 | __le32 param_value; | 2403 | __le32 param_value; |
| @@ -2132,6 +2922,61 @@ enum wmi_rate_preamble { | |||
| 2132 | /* Value to disable fixed rate setting */ | 2922 | /* Value to disable fixed rate setting */ |
| 2133 | #define WMI_FIXED_RATE_NONE (0xff) | 2923 | #define WMI_FIXED_RATE_NONE (0xff) |
| 2134 | 2924 | ||
| 2925 | struct wmi_vdev_param_map { | ||
| 2926 | u32 rts_threshold; | ||
| 2927 | u32 fragmentation_threshold; | ||
| 2928 | u32 beacon_interval; | ||
| 2929 | u32 listen_interval; | ||
| 2930 | u32 multicast_rate; | ||
| 2931 | u32 mgmt_tx_rate; | ||
| 2932 | u32 slot_time; | ||
| 2933 | u32 preamble; | ||
| 2934 | u32 swba_time; | ||
| 2935 | u32 wmi_vdev_stats_update_period; | ||
| 2936 | u32 wmi_vdev_pwrsave_ageout_time; | ||
| 2937 | u32 wmi_vdev_host_swba_interval; | ||
| 2938 | u32 dtim_period; | ||
| 2939 | u32 wmi_vdev_oc_scheduler_air_time_limit; | ||
| 2940 | u32 wds; | ||
| 2941 | u32 atim_window; | ||
| 2942 | u32 bmiss_count_max; | ||
| 2943 | u32 bmiss_first_bcnt; | ||
| 2944 | u32 bmiss_final_bcnt; | ||
| 2945 | u32 feature_wmm; | ||
| 2946 | u32 chwidth; | ||
| 2947 | u32 chextoffset; | ||
| 2948 | u32 disable_htprotection; | ||
| 2949 | u32 sta_quickkickout; | ||
| 2950 | u32 mgmt_rate; | ||
| 2951 | u32 protection_mode; | ||
| 2952 | u32 fixed_rate; | ||
| 2953 | u32 sgi; | ||
| 2954 | u32 ldpc; | ||
| 2955 | u32 tx_stbc; | ||
| 2956 | u32 rx_stbc; | ||
| 2957 | u32 intra_bss_fwd; | ||
| 2958 | u32 def_keyid; | ||
| 2959 | u32 nss; | ||
| 2960 | u32 bcast_data_rate; | ||
| 2961 | u32 mcast_data_rate; | ||
| 2962 | u32 mcast_indicate; | ||
| 2963 | u32 dhcp_indicate; | ||
| 2964 | u32 unknown_dest_indicate; | ||
| 2965 | u32 ap_keepalive_min_idle_inactive_time_secs; | ||
| 2966 | u32 ap_keepalive_max_idle_inactive_time_secs; | ||
| 2967 | u32 ap_keepalive_max_unresponsive_time_secs; | ||
| 2968 | u32 ap_enable_nawds; | ||
| 2969 | u32 mcast2ucast_set; | ||
| 2970 | u32 enable_rtscts; | ||
| 2971 | u32 txbf; | ||
| 2972 | u32 packet_powersave; | ||
| 2973 | u32 drop_unencry; | ||
| 2974 | u32 tx_encap_type; | ||
| 2975 | u32 ap_detect_out_of_sync_sleeping_sta_time_secs; | ||
| 2976 | }; | ||
| 2977 | |||
| 2978 | #define WMI_VDEV_PARAM_UNSUPPORTED 0 | ||
| 2979 | |||
| 2135 | /* the definition of different VDEV parameters */ | 2980 | /* the definition of different VDEV parameters */ |
| 2136 | enum wmi_vdev_param { | 2981 | enum wmi_vdev_param { |
| 2137 | /* RTS Threshold */ | 2982 | /* RTS Threshold */ |
| @@ -2263,6 +3108,121 @@ enum wmi_vdev_param { | |||
| 2263 | WMI_VDEV_PARAM_TX_ENCAP_TYPE, | 3108 | WMI_VDEV_PARAM_TX_ENCAP_TYPE, |
| 2264 | }; | 3109 | }; |
| 2265 | 3110 | ||
| 3111 | /* the definition of different VDEV parameters */ | ||
| 3112 | enum wmi_10x_vdev_param { | ||
| 3113 | /* RTS Threshold */ | ||
| 3114 | WMI_10X_VDEV_PARAM_RTS_THRESHOLD = 0x1, | ||
| 3115 | /* Fragmentation threshold */ | ||
| 3116 | WMI_10X_VDEV_PARAM_FRAGMENTATION_THRESHOLD, | ||
| 3117 | /* beacon interval in TUs */ | ||
| 3118 | WMI_10X_VDEV_PARAM_BEACON_INTERVAL, | ||
| 3119 | /* Listen interval in TUs */ | ||
| 3120 | WMI_10X_VDEV_PARAM_LISTEN_INTERVAL, | ||
| 3121 | /* muticast rate in Mbps */ | ||
| 3122 | WMI_10X_VDEV_PARAM_MULTICAST_RATE, | ||
| 3123 | /* management frame rate in Mbps */ | ||
| 3124 | WMI_10X_VDEV_PARAM_MGMT_TX_RATE, | ||
| 3125 | /* slot time (long vs short) */ | ||
| 3126 | WMI_10X_VDEV_PARAM_SLOT_TIME, | ||
| 3127 | /* preamble (long vs short) */ | ||
| 3128 | WMI_10X_VDEV_PARAM_PREAMBLE, | ||
| 3129 | /* SWBA time (time before tbtt in msec) */ | ||
| 3130 | WMI_10X_VDEV_PARAM_SWBA_TIME, | ||
| 3131 | /* time period for updating VDEV stats */ | ||
| 3132 | WMI_10X_VDEV_STATS_UPDATE_PERIOD, | ||
| 3133 | /* age out time in msec for frames queued for station in power save */ | ||
| 3134 | WMI_10X_VDEV_PWRSAVE_AGEOUT_TIME, | ||
| 3135 | /* | ||
| 3136 | * Host SWBA interval (time in msec before tbtt for SWBA event | ||
| 3137 | * generation). | ||
| 3138 | */ | ||
| 3139 | WMI_10X_VDEV_HOST_SWBA_INTERVAL, | ||
| 3140 | /* DTIM period (specified in units of num beacon intervals) */ | ||
| 3141 | WMI_10X_VDEV_PARAM_DTIM_PERIOD, | ||
| 3142 | /* | ||
| 3143 | * scheduler air time limit for this VDEV. used by off chan | ||
| 3144 | * scheduler. | ||
| 3145 | */ | ||
| 3146 | WMI_10X_VDEV_OC_SCHEDULER_AIR_TIME_LIMIT, | ||
| 3147 | /* enable/dsiable WDS for this VDEV */ | ||
| 3148 | WMI_10X_VDEV_PARAM_WDS, | ||
| 3149 | /* ATIM Window */ | ||
| 3150 | WMI_10X_VDEV_PARAM_ATIM_WINDOW, | ||
| 3151 | /* BMISS max */ | ||
| 3152 | WMI_10X_VDEV_PARAM_BMISS_COUNT_MAX, | ||
| 3153 | /* WMM enables/disabled */ | ||
| 3154 | WMI_10X_VDEV_PARAM_FEATURE_WMM, | ||
| 3155 | /* Channel width */ | ||
| 3156 | WMI_10X_VDEV_PARAM_CHWIDTH, | ||
| 3157 | /* Channel Offset */ | ||
| 3158 | WMI_10X_VDEV_PARAM_CHEXTOFFSET, | ||
| 3159 | /* Disable HT Protection */ | ||
| 3160 | WMI_10X_VDEV_PARAM_DISABLE_HTPROTECTION, | ||
| 3161 | /* Quick STA Kickout */ | ||
| 3162 | WMI_10X_VDEV_PARAM_STA_QUICKKICKOUT, | ||
| 3163 | /* Rate to be used with Management frames */ | ||
| 3164 | WMI_10X_VDEV_PARAM_MGMT_RATE, | ||
| 3165 | /* Protection Mode */ | ||
| 3166 | WMI_10X_VDEV_PARAM_PROTECTION_MODE, | ||
| 3167 | /* Fixed rate setting */ | ||
| 3168 | WMI_10X_VDEV_PARAM_FIXED_RATE, | ||
| 3169 | /* Short GI Enable/Disable */ | ||
| 3170 | WMI_10X_VDEV_PARAM_SGI, | ||
| 3171 | /* Enable LDPC */ | ||
| 3172 | WMI_10X_VDEV_PARAM_LDPC, | ||
| 3173 | /* Enable Tx STBC */ | ||
| 3174 | WMI_10X_VDEV_PARAM_TX_STBC, | ||
| 3175 | /* Enable Rx STBC */ | ||
| 3176 | WMI_10X_VDEV_PARAM_RX_STBC, | ||
| 3177 | /* Intra BSS forwarding */ | ||
| 3178 | WMI_10X_VDEV_PARAM_INTRA_BSS_FWD, | ||
| 3179 | /* Setting Default xmit key for Vdev */ | ||
| 3180 | WMI_10X_VDEV_PARAM_DEF_KEYID, | ||
| 3181 | /* NSS width */ | ||
| 3182 | WMI_10X_VDEV_PARAM_NSS, | ||
| 3183 | /* Set the custom rate for the broadcast data frames */ | ||
| 3184 | WMI_10X_VDEV_PARAM_BCAST_DATA_RATE, | ||
| 3185 | /* Set the custom rate (rate-code) for multicast data frames */ | ||
| 3186 | WMI_10X_VDEV_PARAM_MCAST_DATA_RATE, | ||
| 3187 | /* Tx multicast packet indicate Enable/Disable */ | ||
| 3188 | WMI_10X_VDEV_PARAM_MCAST_INDICATE, | ||
| 3189 | /* Tx DHCP packet indicate Enable/Disable */ | ||
| 3190 | WMI_10X_VDEV_PARAM_DHCP_INDICATE, | ||
| 3191 | /* Enable host inspection of Tx unicast packet to unknown destination */ | ||
| 3192 | WMI_10X_VDEV_PARAM_UNKNOWN_DEST_INDICATE, | ||
| 3193 | |||
| 3194 | /* The minimum amount of time AP begins to consider STA inactive */ | ||
| 3195 | WMI_10X_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS, | ||
| 3196 | |||
| 3197 | /* | ||
| 3198 | * An associated STA is considered inactive when there is no recent | ||
| 3199 | * TX/RX activity and no downlink frames are buffered for it. Once a | ||
| 3200 | * STA exceeds the maximum idle inactive time, the AP will send an | ||
| 3201 | * 802.11 data-null as a keep alive to verify the STA is still | ||
| 3202 | * associated. If the STA does ACK the data-null, or if the data-null | ||
| 3203 | * is buffered and the STA does not retrieve it, the STA will be | ||
| 3204 | * considered unresponsive | ||
| 3205 | * (see WMI_10X_VDEV_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS). | ||
| 3206 | */ | ||
| 3207 | WMI_10X_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS, | ||
| 3208 | |||
| 3209 | /* | ||
| 3210 | * An associated STA is considered unresponsive if there is no recent | ||
| 3211 | * TX/RX activity and downlink frames are buffered for it. Once a STA | ||
| 3212 | * exceeds the maximum unresponsive time, the AP will send a | ||
| 3213 | * WMI_10X_STA_KICKOUT event to the host so the STA can be deleted. */ | ||
| 3214 | WMI_10X_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS, | ||
| 3215 | |||
| 3216 | /* Enable NAWDS : MCAST INSPECT Enable, NAWDS Flag set */ | ||
| 3217 | WMI_10X_VDEV_PARAM_AP_ENABLE_NAWDS, | ||
| 3218 | |||
| 3219 | WMI_10X_VDEV_PARAM_MCAST2UCAST_SET, | ||
| 3220 | /* Enable/Disable RTS-CTS */ | ||
| 3221 | WMI_10X_VDEV_PARAM_ENABLE_RTSCTS, | ||
| 3222 | |||
| 3223 | WMI_10X_VDEV_PARAM_AP_DETECT_OUT_OF_SYNC_SLEEPING_STA_TIME_SECS, | ||
| 3224 | }; | ||
| 3225 | |||
| 2266 | /* slot time long */ | 3226 | /* slot time long */ |
| 2267 | #define WMI_VDEV_SLOT_TIME_LONG 0x1 | 3227 | #define WMI_VDEV_SLOT_TIME_LONG 0x1 |
| 2268 | /* slot time short */ | 3228 | /* slot time short */ |
| @@ -3064,8 +4024,7 @@ int ath10k_wmi_pdev_suspend_target(struct ath10k *ar); | |||
| 3064 | int ath10k_wmi_pdev_resume_target(struct ath10k *ar); | 4024 | int ath10k_wmi_pdev_resume_target(struct ath10k *ar); |
| 3065 | int ath10k_wmi_pdev_set_regdomain(struct ath10k *ar, u16 rd, u16 rd2g, | 4025 | int ath10k_wmi_pdev_set_regdomain(struct ath10k *ar, u16 rd, u16 rd2g, |
| 3066 | u16 rd5g, u16 ctl2g, u16 ctl5g); | 4026 | u16 rd5g, u16 ctl2g, u16 ctl5g); |
| 3067 | int ath10k_wmi_pdev_set_param(struct ath10k *ar, enum wmi_pdev_param id, | 4027 | int ath10k_wmi_pdev_set_param(struct ath10k *ar, u32 id, u32 value); |
| 3068 | u32 value); | ||
| 3069 | int ath10k_wmi_cmd_init(struct ath10k *ar); | 4028 | int ath10k_wmi_cmd_init(struct ath10k *ar); |
| 3070 | int ath10k_wmi_start_scan(struct ath10k *ar, const struct wmi_start_scan_arg *); | 4029 | int ath10k_wmi_start_scan(struct ath10k *ar, const struct wmi_start_scan_arg *); |
| 3071 | void ath10k_wmi_start_scan_init(struct ath10k *ar, struct wmi_start_scan_arg *); | 4030 | void ath10k_wmi_start_scan_init(struct ath10k *ar, struct wmi_start_scan_arg *); |
| @@ -3085,7 +4044,7 @@ int ath10k_wmi_vdev_up(struct ath10k *ar, u32 vdev_id, u32 aid, | |||
| 3085 | const u8 *bssid); | 4044 | const u8 *bssid); |
| 3086 | int ath10k_wmi_vdev_down(struct ath10k *ar, u32 vdev_id); | 4045 | int ath10k_wmi_vdev_down(struct ath10k *ar, u32 vdev_id); |
| 3087 | int ath10k_wmi_vdev_set_param(struct ath10k *ar, u32 vdev_id, | 4046 | int ath10k_wmi_vdev_set_param(struct ath10k *ar, u32 vdev_id, |
| 3088 | enum wmi_vdev_param param_id, u32 param_value); | 4047 | u32 param_id, u32 param_value); |
| 3089 | int ath10k_wmi_vdev_install_key(struct ath10k *ar, | 4048 | int ath10k_wmi_vdev_install_key(struct ath10k *ar, |
| 3090 | const struct wmi_vdev_install_key_arg *arg); | 4049 | const struct wmi_vdev_install_key_arg *arg); |
| 3091 | int ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id, | 4050 | int ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id, |
| @@ -3115,5 +4074,6 @@ int ath10k_wmi_pdev_set_wmm_params(struct ath10k *ar, | |||
| 3115 | int ath10k_wmi_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id); | 4074 | int ath10k_wmi_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id); |
| 3116 | int ath10k_wmi_force_fw_hang(struct ath10k *ar, | 4075 | int ath10k_wmi_force_fw_hang(struct ath10k *ar, |
| 3117 | enum wmi_force_fw_hang_type type, u32 delay_ms); | 4076 | enum wmi_force_fw_hang_type type, u32 delay_ms); |
| 4077 | int ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *skb); | ||
| 3118 | 4078 | ||
| 3119 | #endif /* _WMI_H_ */ | 4079 | #endif /* _WMI_H_ */ |
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 48161edec8de..69f58b073e85 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
| @@ -1663,15 +1663,15 @@ ath5k_tx_frame_completed(struct ath5k_hw *ah, struct sk_buff *skb, | |||
| 1663 | ah->stats.tx_bytes_count += skb->len; | 1663 | ah->stats.tx_bytes_count += skb->len; |
| 1664 | info = IEEE80211_SKB_CB(skb); | 1664 | info = IEEE80211_SKB_CB(skb); |
| 1665 | 1665 | ||
| 1666 | size = min_t(int, sizeof(info->status.rates), sizeof(bf->rates)); | ||
| 1667 | memcpy(info->status.rates, bf->rates, size); | ||
| 1668 | |||
| 1666 | tries[0] = info->status.rates[0].count; | 1669 | tries[0] = info->status.rates[0].count; |
| 1667 | tries[1] = info->status.rates[1].count; | 1670 | tries[1] = info->status.rates[1].count; |
| 1668 | tries[2] = info->status.rates[2].count; | 1671 | tries[2] = info->status.rates[2].count; |
| 1669 | 1672 | ||
| 1670 | ieee80211_tx_info_clear_status(info); | 1673 | ieee80211_tx_info_clear_status(info); |
| 1671 | 1674 | ||
| 1672 | size = min_t(int, sizeof(info->status.rates), sizeof(bf->rates)); | ||
| 1673 | memcpy(info->status.rates, bf->rates, size); | ||
| 1674 | |||
| 1675 | for (i = 0; i < ts->ts_final_idx; i++) { | 1675 | for (i = 0; i < ts->ts_final_idx; i++) { |
| 1676 | struct ieee80211_tx_rate *r = | 1676 | struct ieee80211_tx_rate *r = |
| 1677 | &info->status.rates[i]; | 1677 | &info->status.rates[i]; |
diff --git a/drivers/net/wireless/ath/ath6kl/htc.h b/drivers/net/wireless/ath/ath6kl/htc.h index a2c8ff809793..14cab1403dd6 100644 --- a/drivers/net/wireless/ath/ath6kl/htc.h +++ b/drivers/net/wireless/ath/ath6kl/htc.h | |||
| @@ -60,7 +60,7 @@ | |||
| 60 | /* disable credit flow control on a specific service */ | 60 | /* disable credit flow control on a specific service */ |
| 61 | #define HTC_CONN_FLGS_DISABLE_CRED_FLOW_CTRL (1 << 3) | 61 | #define HTC_CONN_FLGS_DISABLE_CRED_FLOW_CTRL (1 << 3) |
| 62 | #define HTC_CONN_FLGS_SET_RECV_ALLOC_SHIFT 8 | 62 | #define HTC_CONN_FLGS_SET_RECV_ALLOC_SHIFT 8 |
| 63 | #define HTC_CONN_FLGS_SET_RECV_ALLOC_MASK 0xFF00 | 63 | #define HTC_CONN_FLGS_SET_RECV_ALLOC_MASK 0xFF00U |
| 64 | 64 | ||
| 65 | /* connect response status codes */ | 65 | /* connect response status codes */ |
| 66 | #define HTC_SERVICE_SUCCESS 0 | 66 | #define HTC_SERVICE_SUCCESS 0 |
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig index 7944c25c9a43..32f139e2e897 100644 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig | |||
| @@ -84,6 +84,26 @@ config ATH9K_DFS_CERTIFIED | |||
| 84 | developed. At this point enabling this option won't do anything | 84 | developed. At this point enabling this option won't do anything |
| 85 | except increase code size. | 85 | except increase code size. |
| 86 | 86 | ||
| 87 | config ATH9K_TX99 | ||
| 88 | bool "Atheros ath9k TX99 testing support" | ||
| 89 | depends on CFG80211_CERTIFICATION_ONUS | ||
| 90 | default n | ||
| 91 | ---help--- | ||
| 92 | Say N. This should only be enabled on systems undergoing | ||
| 93 | certification testing and evaluation in a controlled environment. | ||
| 94 | Enabling this will only enable TX99 support, all other modes of | ||
| 95 | operation will be disabled. | ||
| 96 | |||
| 97 | TX99 support enables Specific Absorption Rate (SAR) testing. | ||
| 98 | SAR is the unit of measurement for the amount of radio frequency(RF) | ||
| 99 | absorbed by the body when using a wireless device. The RF exposure | ||
| 100 | limits used are expressed in the terms of SAR, which is a measure | ||
| 101 | of the electric and magnetic field strength and power density for | ||
| 102 | transmitters operating at frequencies from 300 kHz to 100 GHz. | ||
| 103 | Regulatory bodies around the world require that wireless device | ||
| 104 | be evaluated to meet the RF exposure limits set forth in the | ||
| 105 | governmental SAR regulations. | ||
| 106 | |||
| 87 | config ATH9K_LEGACY_RATE_CONTROL | 107 | config ATH9K_LEGACY_RATE_CONTROL |
| 88 | bool "Atheros ath9k rate control" | 108 | bool "Atheros ath9k rate control" |
| 89 | depends on ATH9K | 109 | depends on ATH9K |
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 75ee9e7704ce..6205ef5a9321 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile | |||
| @@ -14,9 +14,7 @@ ath9k-$(CONFIG_ATH9K_AHB) += ahb.o | |||
| 14 | ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o | 14 | ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o |
| 15 | ath9k-$(CONFIG_ATH9K_DFS_DEBUGFS) += dfs_debug.o | 15 | ath9k-$(CONFIG_ATH9K_DFS_DEBUGFS) += dfs_debug.o |
| 16 | ath9k-$(CONFIG_ATH9K_DFS_CERTIFIED) += \ | 16 | ath9k-$(CONFIG_ATH9K_DFS_CERTIFIED) += \ |
| 17 | dfs.o \ | 17 | dfs.o |
| 18 | dfs_pattern_detector.o \ | ||
| 19 | dfs_pri_detector.o | ||
| 20 | ath9k-$(CONFIG_PM_SLEEP) += wow.o | 18 | ath9k-$(CONFIG_PM_SLEEP) += wow.o |
| 21 | 19 | ||
| 22 | obj-$(CONFIG_ATH9K) += ath9k.o | 20 | obj-$(CONFIG_ATH9K) += ath9k.o |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c index 17970d49d858..f087117b2e6b 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c | |||
| @@ -680,6 +680,26 @@ static void ar9002_hw_spectral_scan_wait(struct ath_hw *ah) | |||
| 680 | } | 680 | } |
| 681 | } | 681 | } |
| 682 | 682 | ||
| 683 | static void ar9002_hw_tx99_start(struct ath_hw *ah, u32 qnum) | ||
| 684 | { | ||
| 685 | REG_SET_BIT(ah, 0x9864, 0x7f000); | ||
| 686 | REG_SET_BIT(ah, 0x9924, 0x7f00fe); | ||
| 687 | REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS); | ||
| 688 | REG_WRITE(ah, AR_CR, AR_CR_RXD); | ||
| 689 | REG_WRITE(ah, AR_DLCL_IFS(qnum), 0); | ||
| 690 | REG_WRITE(ah, AR_D_GBL_IFS_SIFS, 20); | ||
| 691 | REG_WRITE(ah, AR_D_GBL_IFS_EIFS, 20); | ||
| 692 | REG_WRITE(ah, AR_D_FPCTL, 0x10|qnum); | ||
| 693 | REG_WRITE(ah, AR_TIME_OUT, 0x00000400); | ||
| 694 | REG_WRITE(ah, AR_DRETRY_LIMIT(qnum), 0xffffffff); | ||
| 695 | REG_SET_BIT(ah, AR_QMISC(qnum), AR_Q_MISC_DCU_EARLY_TERM_REQ); | ||
| 696 | } | ||
| 697 | |||
| 698 | static void ar9002_hw_tx99_stop(struct ath_hw *ah) | ||
| 699 | { | ||
| 700 | REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS); | ||
| 701 | } | ||
| 702 | |||
| 683 | void ar9002_hw_attach_phy_ops(struct ath_hw *ah) | 703 | void ar9002_hw_attach_phy_ops(struct ath_hw *ah) |
| 684 | { | 704 | { |
| 685 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); | 705 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); |
| @@ -701,6 +721,8 @@ void ar9002_hw_attach_phy_ops(struct ath_hw *ah) | |||
| 701 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT | 721 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT |
| 702 | ops->set_bt_ant_diversity = ar9002_hw_set_bt_ant_diversity; | 722 | ops->set_bt_ant_diversity = ar9002_hw_set_bt_ant_diversity; |
| 703 | #endif | 723 | #endif |
| 724 | ops->tx99_start = ar9002_hw_tx99_start; | ||
| 725 | ops->tx99_stop = ar9002_hw_tx99_stop; | ||
| 704 | 726 | ||
| 705 | ar9002_hw_set_nf_limits(ah); | 727 | ar9002_hw_set_nf_limits(ah); |
| 706 | } | 728 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index f3adafd33704..11f53589a3f3 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c | |||
| @@ -1617,6 +1617,98 @@ static void ar9003_hw_spectral_scan_wait(struct ath_hw *ah) | |||
| 1617 | } | 1617 | } |
| 1618 | } | 1618 | } |
| 1619 | 1619 | ||
| 1620 | static void ar9003_hw_tx99_start(struct ath_hw *ah, u32 qnum) | ||
| 1621 | { | ||
| 1622 | REG_SET_BIT(ah, AR_PHY_TEST, PHY_AGC_CLR); | ||
| 1623 | REG_SET_BIT(ah, 0x9864, 0x7f000); | ||
| 1624 | REG_SET_BIT(ah, 0x9924, 0x7f00fe); | ||
| 1625 | REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS); | ||
| 1626 | REG_WRITE(ah, AR_CR, AR_CR_RXD); | ||
| 1627 | REG_WRITE(ah, AR_DLCL_IFS(qnum), 0); | ||
| 1628 | REG_WRITE(ah, AR_D_GBL_IFS_SIFS, 20); /* 50 OK */ | ||
| 1629 | REG_WRITE(ah, AR_D_GBL_IFS_EIFS, 20); | ||
| 1630 | REG_WRITE(ah, AR_TIME_OUT, 0x00000400); | ||
| 1631 | REG_WRITE(ah, AR_DRETRY_LIMIT(qnum), 0xffffffff); | ||
| 1632 | REG_SET_BIT(ah, AR_QMISC(qnum), AR_Q_MISC_DCU_EARLY_TERM_REQ); | ||
| 1633 | } | ||
| 1634 | |||
| 1635 | static void ar9003_hw_tx99_stop(struct ath_hw *ah) | ||
| 1636 | { | ||
| 1637 | REG_CLR_BIT(ah, AR_PHY_TEST, PHY_AGC_CLR); | ||
| 1638 | REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS); | ||
| 1639 | } | ||
| 1640 | |||
| 1641 | static void ar9003_hw_tx99_set_txpower(struct ath_hw *ah, u8 txpower) | ||
| 1642 | { | ||
| 1643 | static s16 p_pwr_array[ar9300RateSize] = { 0 }; | ||
| 1644 | unsigned int i; | ||
| 1645 | |||
| 1646 | if (txpower <= MAX_RATE_POWER) { | ||
| 1647 | for (i = 0; i < ar9300RateSize; i++) | ||
| 1648 | p_pwr_array[i] = txpower; | ||
| 1649 | } else { | ||
| 1650 | for (i = 0; i < ar9300RateSize; i++) | ||
| 1651 | p_pwr_array[i] = MAX_RATE_POWER; | ||
| 1652 | } | ||
| 1653 | |||
| 1654 | REG_WRITE(ah, 0xa458, 0); | ||
| 1655 | |||
| 1656 | REG_WRITE(ah, 0xa3c0, | ||
| 1657 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], 24) | | ||
| 1658 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], 16) | | ||
| 1659 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], 8) | | ||
| 1660 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], 0)); | ||
| 1661 | REG_WRITE(ah, 0xa3c4, | ||
| 1662 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_54], 24) | | ||
| 1663 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_48], 16) | | ||
| 1664 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_36], 8) | | ||
| 1665 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], 0)); | ||
| 1666 | REG_WRITE(ah, 0xa3c8, | ||
| 1667 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], 24) | | ||
| 1668 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], 16) | | ||
| 1669 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], 0)); | ||
| 1670 | REG_WRITE(ah, 0xa3cc, | ||
| 1671 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_11S], 24) | | ||
| 1672 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_11L], 16) | | ||
| 1673 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_5S], 8) | | ||
| 1674 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], 0)); | ||
| 1675 | REG_WRITE(ah, 0xa3d0, | ||
| 1676 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_5], 24) | | ||
| 1677 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_4], 16) | | ||
| 1678 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_1_3_9_11_17_19], 8)| | ||
| 1679 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_0_8_16], 0)); | ||
| 1680 | REG_WRITE(ah, 0xa3d4, | ||
| 1681 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_13], 24) | | ||
| 1682 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_12], 16) | | ||
| 1683 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_7], 8) | | ||
| 1684 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_6], 0)); | ||
| 1685 | REG_WRITE(ah, 0xa3e4, | ||
| 1686 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_21], 24) | | ||
| 1687 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_20], 16) | | ||
| 1688 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_15], 8) | | ||
| 1689 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_14], 0)); | ||
| 1690 | REG_WRITE(ah, 0xa3e8, | ||
| 1691 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_23], 24) | | ||
| 1692 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_22], 16) | | ||
| 1693 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_23], 8) | | ||
| 1694 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_22], 0)); | ||
| 1695 | REG_WRITE(ah, 0xa3d8, | ||
| 1696 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_5], 24) | | ||
| 1697 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_4], 16) | | ||
| 1698 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_1_3_9_11_17_19], 8) | | ||
| 1699 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_0_8_16], 0)); | ||
| 1700 | REG_WRITE(ah, 0xa3dc, | ||
| 1701 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_13], 24) | | ||
| 1702 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_12], 16) | | ||
| 1703 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_7], 8) | | ||
| 1704 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_6], 0)); | ||
| 1705 | REG_WRITE(ah, 0xa3ec, | ||
| 1706 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_21], 24) | | ||
| 1707 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_20], 16) | | ||
| 1708 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_15], 8) | | ||
| 1709 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_14], 0)); | ||
| 1710 | } | ||
| 1711 | |||
| 1620 | void ar9003_hw_attach_phy_ops(struct ath_hw *ah) | 1712 | void ar9003_hw_attach_phy_ops(struct ath_hw *ah) |
| 1621 | { | 1713 | { |
| 1622 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); | 1714 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); |
| @@ -1656,6 +1748,9 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah) | |||
| 1656 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT | 1748 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT |
| 1657 | ops->set_bt_ant_diversity = ar9003_hw_set_bt_ant_diversity; | 1749 | ops->set_bt_ant_diversity = ar9003_hw_set_bt_ant_diversity; |
| 1658 | #endif | 1750 | #endif |
| 1751 | ops->tx99_start = ar9003_hw_tx99_start; | ||
| 1752 | ops->tx99_stop = ar9003_hw_tx99_stop; | ||
| 1753 | ops->tx99_set_txpower = ar9003_hw_tx99_set_txpower; | ||
| 1659 | 1754 | ||
| 1660 | ar9003_hw_set_nf_limits(ah); | 1755 | ar9003_hw_set_nf_limits(ah); |
| 1661 | ar9003_hw_set_radar_conf(ah); | 1756 | ar9003_hw_set_radar_conf(ah); |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 14ff7e9dde4c..e7a38d844a6a 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
| @@ -778,6 +778,11 @@ struct ath_softc { | |||
| 778 | enum spectral_mode spectral_mode; | 778 | enum spectral_mode spectral_mode; |
| 779 | struct ath_spec_scan spec_config; | 779 | struct ath_spec_scan spec_config; |
| 780 | 780 | ||
| 781 | struct ieee80211_vif *tx99_vif; | ||
| 782 | struct sk_buff *tx99_skb; | ||
| 783 | bool tx99_state; | ||
| 784 | s16 tx99_power; | ||
| 785 | |||
| 781 | #ifdef CONFIG_PM_SLEEP | 786 | #ifdef CONFIG_PM_SLEEP |
| 782 | atomic_t wow_got_bmiss_intr; | 787 | atomic_t wow_got_bmiss_intr; |
| 783 | atomic_t wow_sleep_proc_intr; /* in the middle of WoW sleep ? */ | 788 | atomic_t wow_sleep_proc_intr; /* in the middle of WoW sleep ? */ |
| @@ -886,6 +891,7 @@ static inline u8 spectral_bitmap_weight(u8 *bins) | |||
| 886 | */ | 891 | */ |
| 887 | enum ath_fft_sample_type { | 892 | enum ath_fft_sample_type { |
| 888 | ATH_FFT_SAMPLE_HT20 = 1, | 893 | ATH_FFT_SAMPLE_HT20 = 1, |
| 894 | ATH_FFT_SAMPLE_HT20_40, | ||
| 889 | }; | 895 | }; |
| 890 | 896 | ||
| 891 | struct fft_sample_tlv { | 897 | struct fft_sample_tlv { |
| @@ -912,6 +918,39 @@ struct fft_sample_ht20 { | |||
| 912 | u8 data[SPECTRAL_HT20_NUM_BINS]; | 918 | u8 data[SPECTRAL_HT20_NUM_BINS]; |
| 913 | } __packed; | 919 | } __packed; |
| 914 | 920 | ||
| 921 | struct fft_sample_ht20_40 { | ||
| 922 | struct fft_sample_tlv tlv; | ||
| 923 | |||
| 924 | u8 channel_type; | ||
| 925 | __be16 freq; | ||
| 926 | |||
| 927 | s8 lower_rssi; | ||
| 928 | s8 upper_rssi; | ||
| 929 | |||
| 930 | __be64 tsf; | ||
| 931 | |||
| 932 | s8 lower_noise; | ||
| 933 | s8 upper_noise; | ||
| 934 | |||
| 935 | __be16 lower_max_magnitude; | ||
| 936 | __be16 upper_max_magnitude; | ||
| 937 | |||
| 938 | u8 lower_max_index; | ||
| 939 | u8 upper_max_index; | ||
| 940 | |||
| 941 | u8 lower_bitmap_weight; | ||
| 942 | u8 upper_bitmap_weight; | ||
| 943 | |||
| 944 | u8 max_exp; | ||
| 945 | |||
| 946 | u8 data[SPECTRAL_HT20_40_NUM_BINS]; | ||
| 947 | } __packed; | ||
| 948 | |||
| 949 | int ath9k_tx99_init(struct ath_softc *sc); | ||
| 950 | void ath9k_tx99_deinit(struct ath_softc *sc); | ||
| 951 | int ath9k_tx99_send(struct ath_softc *sc, struct sk_buff *skb, | ||
| 952 | struct ath_tx_control *txctl); | ||
| 953 | |||
| 915 | void ath9k_tasklet(unsigned long data); | 954 | void ath9k_tasklet(unsigned long data); |
| 916 | int ath_cabq_update(struct ath_softc *); | 955 | int ath_cabq_update(struct ath_softc *); |
| 917 | 956 | ||
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index d8db74b0ef66..278365b8a895 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c | |||
| @@ -63,13 +63,13 @@ static s16 ath9k_hw_get_default_nf(struct ath_hw *ah, | |||
| 63 | return ath9k_hw_get_nf_limits(ah, chan)->nominal; | 63 | return ath9k_hw_get_nf_limits(ah, chan)->nominal; |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan) | 66 | s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan, |
| 67 | s16 nf) | ||
| 67 | { | 68 | { |
| 68 | s8 noise = ATH_DEFAULT_NOISE_FLOOR; | 69 | s8 noise = ATH_DEFAULT_NOISE_FLOOR; |
| 69 | 70 | ||
| 70 | if (chan && chan->noisefloor) { | 71 | if (nf) { |
| 71 | s8 delta = chan->noisefloor - | 72 | s8 delta = nf - ATH9K_NF_CAL_NOISE_THRESH - |
| 72 | ATH9K_NF_CAL_NOISE_THRESH - | ||
| 73 | ath9k_hw_get_default_nf(ah, chan); | 73 | ath9k_hw_get_default_nf(ah, chan); |
| 74 | if (delta > 0) | 74 | if (delta > 0) |
| 75 | noise += delta; | 75 | noise += delta; |
| @@ -392,7 +392,7 @@ bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
| 392 | clear_bit(NFCAL_PENDING, &caldata->cal_flags); | 392 | clear_bit(NFCAL_PENDING, &caldata->cal_flags); |
| 393 | ath9k_hw_update_nfcal_hist_buffer(ah, caldata, nfarray); | 393 | ath9k_hw_update_nfcal_hist_buffer(ah, caldata, nfarray); |
| 394 | chan->noisefloor = h[0].privNF; | 394 | chan->noisefloor = h[0].privNF; |
| 395 | ah->noise = ath9k_hw_getchan_noise(ah, chan); | 395 | ah->noise = ath9k_hw_getchan_noise(ah, chan, chan->noisefloor); |
| 396 | return true; | 396 | return true; |
| 397 | } | 397 | } |
| 398 | EXPORT_SYMBOL(ath9k_hw_getnf); | 398 | EXPORT_SYMBOL(ath9k_hw_getnf); |
diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h index 3d70b8c2bcdd..b8ed95e9a335 100644 --- a/drivers/net/wireless/ath/ath9k/calib.h +++ b/drivers/net/wireless/ath/ath9k/calib.h | |||
| @@ -116,7 +116,8 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, | |||
| 116 | void ath9k_hw_bstuck_nfcal(struct ath_hw *ah); | 116 | void ath9k_hw_bstuck_nfcal(struct ath_hw *ah); |
| 117 | void ath9k_hw_reset_calibration(struct ath_hw *ah, | 117 | void ath9k_hw_reset_calibration(struct ath_hw *ah, |
| 118 | struct ath9k_cal_list *currCal); | 118 | struct ath9k_cal_list *currCal); |
| 119 | s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan); | 119 | s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan, |
| 120 | s16 nf); | ||
| 120 | 121 | ||
| 121 | 122 | ||
| 122 | #endif /* CALIB_H */ | 123 | #endif /* CALIB_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 1be2c787aac9..83a2c59f680b 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
| @@ -1050,6 +1050,9 @@ static ssize_t write_file_spec_scan_ctl(struct file *file, | |||
| 1050 | char buf[32]; | 1050 | char buf[32]; |
| 1051 | ssize_t len; | 1051 | ssize_t len; |
| 1052 | 1052 | ||
| 1053 | if (config_enabled(CONFIG_ATH9K_TX99)) | ||
| 1054 | return -EOPNOTSUPP; | ||
| 1055 | |||
| 1053 | len = min(count, sizeof(buf) - 1); | 1056 | len = min(count, sizeof(buf) - 1); |
| 1054 | if (copy_from_user(buf, user_buf, len)) | 1057 | if (copy_from_user(buf, user_buf, len)) |
| 1055 | return -EFAULT; | 1058 | return -EFAULT; |
| @@ -1775,6 +1778,111 @@ void ath9k_deinit_debug(struct ath_softc *sc) | |||
| 1775 | } | 1778 | } |
| 1776 | } | 1779 | } |
| 1777 | 1780 | ||
| 1781 | static ssize_t read_file_tx99(struct file *file, char __user *user_buf, | ||
| 1782 | size_t count, loff_t *ppos) | ||
| 1783 | { | ||
| 1784 | struct ath_softc *sc = file->private_data; | ||
| 1785 | char buf[3]; | ||
| 1786 | unsigned int len; | ||
| 1787 | |||
| 1788 | len = sprintf(buf, "%d\n", sc->tx99_state); | ||
| 1789 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
| 1790 | } | ||
| 1791 | |||
| 1792 | static ssize_t write_file_tx99(struct file *file, const char __user *user_buf, | ||
| 1793 | size_t count, loff_t *ppos) | ||
| 1794 | { | ||
| 1795 | struct ath_softc *sc = file->private_data; | ||
| 1796 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
| 1797 | char buf[32]; | ||
| 1798 | bool start; | ||
| 1799 | ssize_t len; | ||
| 1800 | int r; | ||
| 1801 | |||
| 1802 | if (sc->nvifs > 1) | ||
| 1803 | return -EOPNOTSUPP; | ||
| 1804 | |||
| 1805 | len = min(count, sizeof(buf) - 1); | ||
| 1806 | if (copy_from_user(buf, user_buf, len)) | ||
| 1807 | return -EFAULT; | ||
| 1808 | |||
| 1809 | if (strtobool(buf, &start)) | ||
| 1810 | return -EINVAL; | ||
| 1811 | |||
| 1812 | if (start == sc->tx99_state) { | ||
| 1813 | if (!start) | ||
| 1814 | return count; | ||
| 1815 | ath_dbg(common, XMIT, "Resetting TX99\n"); | ||
| 1816 | ath9k_tx99_deinit(sc); | ||
| 1817 | } | ||
| 1818 | |||
| 1819 | if (!start) { | ||
| 1820 | ath9k_tx99_deinit(sc); | ||
| 1821 | return count; | ||
| 1822 | } | ||
| 1823 | |||
| 1824 | r = ath9k_tx99_init(sc); | ||
| 1825 | if (r) | ||
| 1826 | return r; | ||
| 1827 | |||
| 1828 | return count; | ||
| 1829 | } | ||
| 1830 | |||
| 1831 | static const struct file_operations fops_tx99 = { | ||
| 1832 | .read = read_file_tx99, | ||
| 1833 | .write = write_file_tx99, | ||
| 1834 | .open = simple_open, | ||
| 1835 | .owner = THIS_MODULE, | ||
| 1836 | .llseek = default_llseek, | ||
| 1837 | }; | ||
| 1838 | |||
| 1839 | static ssize_t read_file_tx99_power(struct file *file, | ||
| 1840 | char __user *user_buf, | ||
| 1841 | size_t count, loff_t *ppos) | ||
| 1842 | { | ||
| 1843 | struct ath_softc *sc = file->private_data; | ||
| 1844 | char buf[32]; | ||
| 1845 | unsigned int len; | ||
| 1846 | |||
| 1847 | len = sprintf(buf, "%d (%d dBm)\n", | ||
| 1848 | sc->tx99_power, | ||
| 1849 | sc->tx99_power / 2); | ||
| 1850 | |||
| 1851 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
| 1852 | } | ||
| 1853 | |||
| 1854 | static ssize_t write_file_tx99_power(struct file *file, | ||
| 1855 | const char __user *user_buf, | ||
| 1856 | size_t count, loff_t *ppos) | ||
| 1857 | { | ||
| 1858 | struct ath_softc *sc = file->private_data; | ||
| 1859 | int r; | ||
| 1860 | u8 tx_power; | ||
| 1861 | |||
| 1862 | r = kstrtou8_from_user(user_buf, count, 0, &tx_power); | ||
| 1863 | if (r) | ||
| 1864 | return r; | ||
| 1865 | |||
| 1866 | if (tx_power > MAX_RATE_POWER) | ||
| 1867 | return -EINVAL; | ||
| 1868 | |||
| 1869 | sc->tx99_power = tx_power; | ||
| 1870 | |||
| 1871 | ath9k_ps_wakeup(sc); | ||
| 1872 | ath9k_hw_tx99_set_txpower(sc->sc_ah, sc->tx99_power); | ||
| 1873 | ath9k_ps_restore(sc); | ||
| 1874 | |||
| 1875 | return count; | ||
| 1876 | } | ||
| 1877 | |||
| 1878 | static const struct file_operations fops_tx99_power = { | ||
| 1879 | .read = read_file_tx99_power, | ||
| 1880 | .write = write_file_tx99_power, | ||
| 1881 | .open = simple_open, | ||
| 1882 | .owner = THIS_MODULE, | ||
| 1883 | .llseek = default_llseek, | ||
| 1884 | }; | ||
| 1885 | |||
| 1778 | int ath9k_init_debug(struct ath_hw *ah) | 1886 | int ath9k_init_debug(struct ath_hw *ah) |
| 1779 | { | 1887 | { |
| 1780 | struct ath_common *common = ath9k_hw_common(ah); | 1888 | struct ath_common *common = ath9k_hw_common(ah); |
| @@ -1866,5 +1974,15 @@ int ath9k_init_debug(struct ath_hw *ah) | |||
| 1866 | debugfs_create_file("btcoex", S_IRUSR, sc->debug.debugfs_phy, sc, | 1974 | debugfs_create_file("btcoex", S_IRUSR, sc->debug.debugfs_phy, sc, |
| 1867 | &fops_btcoex); | 1975 | &fops_btcoex); |
| 1868 | #endif | 1976 | #endif |
| 1977 | if (config_enabled(CONFIG_ATH9K_TX99) && | ||
| 1978 | AR_SREV_9300_20_OR_LATER(ah)) { | ||
| 1979 | debugfs_create_file("tx99", S_IRUSR | S_IWUSR, | ||
| 1980 | sc->debug.debugfs_phy, sc, | ||
| 1981 | &fops_tx99); | ||
| 1982 | debugfs_create_file("tx99_power", S_IRUSR | S_IWUSR, | ||
| 1983 | sc->debug.debugfs_phy, sc, | ||
| 1984 | &fops_tx99_power); | ||
| 1985 | } | ||
| 1986 | |||
| 1869 | return 0; | 1987 | return 0; |
| 1870 | } | 1988 | } |
diff --git a/drivers/net/wireless/ath/ath9k/dfs.h b/drivers/net/wireless/ath/ath9k/dfs.h index 3c839f06a06a..c6fa3d5b5d74 100644 --- a/drivers/net/wireless/ath/ath9k/dfs.h +++ b/drivers/net/wireless/ath/ath9k/dfs.h | |||
| @@ -17,7 +17,7 @@ | |||
| 17 | 17 | ||
| 18 | #ifndef ATH9K_DFS_H | 18 | #ifndef ATH9K_DFS_H |
| 19 | #define ATH9K_DFS_H | 19 | #define ATH9K_DFS_H |
| 20 | #include "dfs_pattern_detector.h" | 20 | #include "../dfs_pattern_detector.h" |
| 21 | 21 | ||
| 22 | #if defined(CONFIG_ATH9K_DFS_CERTIFIED) | 22 | #if defined(CONFIG_ATH9K_DFS_CERTIFIED) |
| 23 | /** | 23 | /** |
diff --git a/drivers/net/wireless/ath/ath9k/dfs_debug.c b/drivers/net/wireless/ath/ath9k/dfs_debug.c index 821599135d8a..90b8342d1ed4 100644 --- a/drivers/net/wireless/ath/ath9k/dfs_debug.c +++ b/drivers/net/wireless/ath/ath9k/dfs_debug.c | |||
| @@ -20,16 +20,16 @@ | |||
| 20 | 20 | ||
| 21 | #include "ath9k.h" | 21 | #include "ath9k.h" |
| 22 | #include "dfs_debug.h" | 22 | #include "dfs_debug.h" |
| 23 | #include "../dfs_pattern_detector.h" | ||
| 23 | 24 | ||
| 24 | 25 | static struct ath_dfs_pool_stats dfs_pool_stats = { 0 }; | |
| 25 | struct ath_dfs_pool_stats global_dfs_pool_stats = { 0 }; | ||
| 26 | 26 | ||
| 27 | #define ATH9K_DFS_STAT(s, p) \ | 27 | #define ATH9K_DFS_STAT(s, p) \ |
| 28 | len += scnprintf(buf + len, size - len, "%28s : %10u\n", s, \ | 28 | len += scnprintf(buf + len, size - len, "%28s : %10u\n", s, \ |
| 29 | sc->debug.stats.dfs_stats.p); | 29 | sc->debug.stats.dfs_stats.p); |
| 30 | #define ATH9K_DFS_POOL_STAT(s, p) \ | 30 | #define ATH9K_DFS_POOL_STAT(s, p) \ |
| 31 | len += scnprintf(buf + len, size - len, "%28s : %10u\n", s, \ | 31 | len += scnprintf(buf + len, size - len, "%28s : %10u\n", s, \ |
| 32 | global_dfs_pool_stats.p); | 32 | dfs_pool_stats.p); |
| 33 | 33 | ||
| 34 | static ssize_t read_file_dfs(struct file *file, char __user *user_buf, | 34 | static ssize_t read_file_dfs(struct file *file, char __user *user_buf, |
| 35 | size_t count, loff_t *ppos) | 35 | size_t count, loff_t *ppos) |
| @@ -44,6 +44,9 @@ static ssize_t read_file_dfs(struct file *file, char __user *user_buf, | |||
| 44 | if (buf == NULL) | 44 | if (buf == NULL) |
| 45 | return -ENOMEM; | 45 | return -ENOMEM; |
| 46 | 46 | ||
| 47 | if (sc->dfs_detector) | ||
| 48 | dfs_pool_stats = sc->dfs_detector->get_stats(sc->dfs_detector); | ||
| 49 | |||
| 47 | len += scnprintf(buf + len, size - len, "DFS support for " | 50 | len += scnprintf(buf + len, size - len, "DFS support for " |
| 48 | "macVersion = 0x%x, macRev = 0x%x: %s\n", | 51 | "macVersion = 0x%x, macRev = 0x%x: %s\n", |
| 49 | hw_ver->macVersion, hw_ver->macRev, | 52 | hw_ver->macVersion, hw_ver->macRev, |
diff --git a/drivers/net/wireless/ath/ath9k/dfs_debug.h b/drivers/net/wireless/ath/ath9k/dfs_debug.h index e36810a4b585..0a7ddf4c88c9 100644 --- a/drivers/net/wireless/ath/ath9k/dfs_debug.h +++ b/drivers/net/wireless/ath/ath9k/dfs_debug.h | |||
| @@ -51,25 +51,11 @@ struct ath_dfs_stats { | |||
| 51 | u32 radar_detected; | 51 | u32 radar_detected; |
| 52 | }; | 52 | }; |
| 53 | 53 | ||
| 54 | /** | ||
| 55 | * struct ath_dfs_pool_stats - DFS Statistics for global pools | ||
| 56 | */ | ||
| 57 | struct ath_dfs_pool_stats { | ||
| 58 | u32 pool_reference; | ||
| 59 | u32 pulse_allocated; | ||
| 60 | u32 pulse_alloc_error; | ||
| 61 | u32 pulse_used; | ||
| 62 | u32 pseq_allocated; | ||
| 63 | u32 pseq_alloc_error; | ||
| 64 | u32 pseq_used; | ||
| 65 | }; | ||
| 66 | #if defined(CONFIG_ATH9K_DFS_DEBUGFS) | 54 | #if defined(CONFIG_ATH9K_DFS_DEBUGFS) |
| 67 | 55 | ||
| 68 | #define DFS_STAT_INC(sc, c) (sc->debug.stats.dfs_stats.c++) | 56 | #define DFS_STAT_INC(sc, c) (sc->debug.stats.dfs_stats.c++) |
| 69 | void ath9k_dfs_init_debug(struct ath_softc *sc); | 57 | void ath9k_dfs_init_debug(struct ath_softc *sc); |
| 70 | 58 | ||
| 71 | #define DFS_POOL_STAT_INC(c) (global_dfs_pool_stats.c++) | ||
| 72 | #define DFS_POOL_STAT_DEC(c) (global_dfs_pool_stats.c--) | ||
| 73 | extern struct ath_dfs_pool_stats global_dfs_pool_stats; | 59 | extern struct ath_dfs_pool_stats global_dfs_pool_stats; |
| 74 | 60 | ||
| 75 | #else | 61 | #else |
| @@ -77,8 +63,6 @@ extern struct ath_dfs_pool_stats global_dfs_pool_stats; | |||
| 77 | #define DFS_STAT_INC(sc, c) do { } while (0) | 63 | #define DFS_STAT_INC(sc, c) do { } while (0) |
| 78 | static inline void ath9k_dfs_init_debug(struct ath_softc *sc) { } | 64 | static inline void ath9k_dfs_init_debug(struct ath_softc *sc) { } |
| 79 | 65 | ||
| 80 | #define DFS_POOL_STAT_INC(c) do { } while (0) | ||
| 81 | #define DFS_POOL_STAT_DEC(c) do { } while (0) | ||
| 82 | #endif /* CONFIG_ATH9K_DFS_DEBUGFS */ | 66 | #endif /* CONFIG_ATH9K_DFS_DEBUGFS */ |
| 83 | 67 | ||
| 84 | #endif /* ATH9K_DFS_DEBUG_H */ | 68 | #endif /* ATH9K_DFS_DEBUG_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index 83f4927aeaca..4f9378ddf07f 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h | |||
| @@ -78,6 +78,22 @@ static inline void ath9k_hw_antdiv_comb_conf_set(struct ath_hw *ah, | |||
| 78 | ath9k_hw_ops(ah)->antdiv_comb_conf_set(ah, antconf); | 78 | ath9k_hw_ops(ah)->antdiv_comb_conf_set(ah, antconf); |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | static inline void ath9k_hw_tx99_start(struct ath_hw *ah, u32 qnum) | ||
| 82 | { | ||
| 83 | ath9k_hw_ops(ah)->tx99_start(ah, qnum); | ||
| 84 | } | ||
| 85 | |||
| 86 | static inline void ath9k_hw_tx99_stop(struct ath_hw *ah) | ||
| 87 | { | ||
| 88 | ath9k_hw_ops(ah)->tx99_stop(ah); | ||
| 89 | } | ||
| 90 | |||
| 91 | static inline void ath9k_hw_tx99_set_txpower(struct ath_hw *ah, u8 power) | ||
| 92 | { | ||
| 93 | if (ath9k_hw_ops(ah)->tx99_set_txpower) | ||
| 94 | ath9k_hw_ops(ah)->tx99_set_txpower(ah, power); | ||
| 95 | } | ||
| 96 | |||
| 81 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT | 97 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT |
| 82 | 98 | ||
| 83 | static inline void ath9k_hw_set_bt_ant_diversity(struct ath_hw *ah, bool enable) | 99 | static inline void ath9k_hw_set_bt_ant_diversity(struct ath_hw *ah, bool enable) |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index dcdbab48709e..54b04155e43b 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
| @@ -1885,7 +1885,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
| 1885 | } else if (caldata) { | 1885 | } else if (caldata) { |
| 1886 | clear_bit(PAPRD_PACKET_SENT, &caldata->cal_flags); | 1886 | clear_bit(PAPRD_PACKET_SENT, &caldata->cal_flags); |
| 1887 | } | 1887 | } |
| 1888 | ah->noise = ath9k_hw_getchan_noise(ah, chan); | 1888 | ah->noise = ath9k_hw_getchan_noise(ah, chan, chan->noisefloor); |
| 1889 | 1889 | ||
| 1890 | if (fastcc) { | 1890 | if (fastcc) { |
| 1891 | r = ath9k_hw_do_fastcc(ah, chan); | 1891 | r = ath9k_hw_do_fastcc(ah, chan); |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 81fcbc756122..9ea24f1cba73 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
| @@ -703,6 +703,10 @@ struct ath_hw_ops { | |||
| 703 | void (*spectral_scan_trigger)(struct ath_hw *ah); | 703 | void (*spectral_scan_trigger)(struct ath_hw *ah); |
| 704 | void (*spectral_scan_wait)(struct ath_hw *ah); | 704 | void (*spectral_scan_wait)(struct ath_hw *ah); |
| 705 | 705 | ||
| 706 | void (*tx99_start)(struct ath_hw *ah, u32 qnum); | ||
| 707 | void (*tx99_stop)(struct ath_hw *ah); | ||
| 708 | void (*tx99_set_txpower)(struct ath_hw *ah, u8 power); | ||
| 709 | |||
| 706 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT | 710 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT |
| 707 | void (*set_bt_ant_diversity)(struct ath_hw *hw, bool enable); | 711 | void (*set_bt_ant_diversity)(struct ath_hw *hw, bool enable); |
| 708 | #endif | 712 | #endif |
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 7df728f36330..e89db64532f5 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
| @@ -680,7 +680,9 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, | |||
| 680 | sc->sc_ah = ah; | 680 | sc->sc_ah = ah; |
| 681 | pCap = &ah->caps; | 681 | pCap = &ah->caps; |
| 682 | 682 | ||
| 683 | sc->dfs_detector = dfs_pattern_detector_init(ah, NL80211_DFS_UNSET); | 683 | common = ath9k_hw_common(ah); |
| 684 | sc->dfs_detector = dfs_pattern_detector_init(common, NL80211_DFS_UNSET); | ||
| 685 | sc->tx99_power = MAX_RATE_POWER + 1; | ||
| 684 | 686 | ||
| 685 | if (!pdata) { | 687 | if (!pdata) { |
| 686 | ah->ah_flags |= AH_USE_EEPROM; | 688 | ah->ah_flags |= AH_USE_EEPROM; |
| @@ -694,7 +696,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, | |||
| 694 | ah->external_reset = pdata->external_reset; | 696 | ah->external_reset = pdata->external_reset; |
| 695 | } | 697 | } |
| 696 | 698 | ||
| 697 | common = ath9k_hw_common(ah); | ||
| 698 | common->ops = &ah->reg_ops; | 699 | common->ops = &ah->reg_ops; |
| 699 | common->bus_ops = bus_ops; | 700 | common->bus_ops = bus_ops; |
| 700 | common->ah = ah; | 701 | common->ah = ah; |
| @@ -785,6 +786,7 @@ err_queues: | |||
| 785 | ath9k_hw_deinit(ah); | 786 | ath9k_hw_deinit(ah); |
| 786 | err_hw: | 787 | err_hw: |
| 787 | ath9k_eeprom_release(sc); | 788 | ath9k_eeprom_release(sc); |
| 789 | dev_kfree_skb_any(sc->tx99_skb); | ||
| 788 | return ret; | 790 | return ret; |
| 789 | } | 791 | } |
| 790 | 792 | ||
| @@ -842,7 +844,6 @@ static const struct ieee80211_iface_limit if_limits[] = { | |||
| 842 | BIT(NL80211_IFTYPE_P2P_GO) }, | 844 | BIT(NL80211_IFTYPE_P2P_GO) }, |
| 843 | }; | 845 | }; |
| 844 | 846 | ||
| 845 | |||
| 846 | static const struct ieee80211_iface_limit if_dfs_limits[] = { | 847 | static const struct ieee80211_iface_limit if_dfs_limits[] = { |
| 847 | { .max = 1, .types = BIT(NL80211_IFTYPE_AP) }, | 848 | { .max = 1, .types = BIT(NL80211_IFTYPE_AP) }, |
| 848 | }; | 849 | }; |
| @@ -903,17 +904,18 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
| 903 | 904 | ||
| 904 | hw->wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR; | 905 | hw->wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR; |
| 905 | 906 | ||
| 906 | hw->wiphy->interface_modes = | 907 | if (!config_enabled(CONFIG_ATH9K_TX99)) { |
| 907 | BIT(NL80211_IFTYPE_P2P_GO) | | 908 | hw->wiphy->interface_modes = |
| 908 | BIT(NL80211_IFTYPE_P2P_CLIENT) | | 909 | BIT(NL80211_IFTYPE_P2P_GO) | |
| 909 | BIT(NL80211_IFTYPE_AP) | | 910 | BIT(NL80211_IFTYPE_P2P_CLIENT) | |
| 910 | BIT(NL80211_IFTYPE_WDS) | | 911 | BIT(NL80211_IFTYPE_AP) | |
| 911 | BIT(NL80211_IFTYPE_STATION) | | 912 | BIT(NL80211_IFTYPE_WDS) | |
| 912 | BIT(NL80211_IFTYPE_ADHOC) | | 913 | BIT(NL80211_IFTYPE_STATION) | |
| 913 | BIT(NL80211_IFTYPE_MESH_POINT); | 914 | BIT(NL80211_IFTYPE_ADHOC) | |
| 914 | 915 | BIT(NL80211_IFTYPE_MESH_POINT); | |
| 915 | hw->wiphy->iface_combinations = if_comb; | 916 | hw->wiphy->iface_combinations = if_comb; |
| 916 | hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); | 917 | hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); |
| 918 | } | ||
| 917 | 919 | ||
| 918 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | 920 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; |
| 919 | 921 | ||
diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c index 84a60644f93a..aed7e29dc50f 100644 --- a/drivers/net/wireless/ath/ath9k/link.c +++ b/drivers/net/wireless/ath/ath9k/link.c | |||
| @@ -28,6 +28,13 @@ void ath_tx_complete_poll_work(struct work_struct *work) | |||
| 28 | int i; | 28 | int i; |
| 29 | bool needreset = false; | 29 | bool needreset = false; |
| 30 | 30 | ||
| 31 | |||
| 32 | if (sc->tx99_state) { | ||
| 33 | ath_dbg(ath9k_hw_common(sc->sc_ah), RESET, | ||
| 34 | "skip tx hung detection on tx99\n"); | ||
| 35 | return; | ||
| 36 | } | ||
| 37 | |||
| 31 | for (i = 0; i < IEEE80211_NUM_ACS; i++) { | 38 | for (i = 0; i < IEEE80211_NUM_ACS; i++) { |
| 32 | txq = sc->tx.txq_map[i]; | 39 | txq = sc->tx.txq_map[i]; |
| 33 | 40 | ||
| @@ -70,7 +77,7 @@ void ath_hw_check(struct work_struct *work) | |||
| 70 | ath9k_ps_wakeup(sc); | 77 | ath9k_ps_wakeup(sc); |
| 71 | is_alive = ath9k_hw_check_alive(sc->sc_ah); | 78 | is_alive = ath9k_hw_check_alive(sc->sc_ah); |
| 72 | 79 | ||
| 73 | if (is_alive && !AR_SREV_9300(sc->sc_ah)) | 80 | if ((is_alive && !AR_SREV_9300(sc->sc_ah)) || sc->tx99_state) |
| 74 | goto out; | 81 | goto out; |
| 75 | else if (!is_alive && AR_SREV_9300(sc->sc_ah)) { | 82 | else if (!is_alive && AR_SREV_9300(sc->sc_ah)) { |
| 76 | ath_dbg(common, RESET, | 83 | ath_dbg(common, RESET, |
| @@ -141,6 +148,9 @@ void ath_hw_pll_work(struct work_struct *work) | |||
| 141 | if (!test_bit(SC_OP_BEACONS, &sc->sc_flags)) | 148 | if (!test_bit(SC_OP_BEACONS, &sc->sc_flags)) |
| 142 | return; | 149 | return; |
| 143 | 150 | ||
| 151 | if (sc->tx99_state) | ||
| 152 | return; | ||
| 153 | |||
| 144 | ath9k_ps_wakeup(sc); | 154 | ath9k_ps_wakeup(sc); |
| 145 | pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah); | 155 | pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah); |
| 146 | ath9k_ps_restore(sc); | 156 | ath9k_ps_restore(sc); |
| @@ -518,7 +528,8 @@ void ath_update_survey_nf(struct ath_softc *sc, int channel) | |||
| 518 | 528 | ||
| 519 | if (chan->noisefloor) { | 529 | if (chan->noisefloor) { |
| 520 | survey->filled |= SURVEY_INFO_NOISE_DBM; | 530 | survey->filled |= SURVEY_INFO_NOISE_DBM; |
| 521 | survey->noise = ath9k_hw_getchan_noise(ah, chan); | 531 | survey->noise = ath9k_hw_getchan_noise(ah, chan, |
| 532 | chan->noisefloor); | ||
| 522 | } | 533 | } |
| 523 | } | 534 | } |
| 524 | 535 | ||
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 20a2fbc1e34f..74f452c7b166 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
| @@ -1046,6 +1046,14 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
| 1046 | 1046 | ||
| 1047 | mutex_lock(&sc->mutex); | 1047 | mutex_lock(&sc->mutex); |
| 1048 | 1048 | ||
| 1049 | if (config_enabled(CONFIG_ATH9K_TX99)) { | ||
| 1050 | if (sc->nvifs >= 1) { | ||
| 1051 | mutex_unlock(&sc->mutex); | ||
| 1052 | return -EOPNOTSUPP; | ||
| 1053 | } | ||
| 1054 | sc->tx99_vif = vif; | ||
| 1055 | } | ||
| 1056 | |||
| 1049 | ath_dbg(common, CONFIG, "Attach a VIF of type: %d\n", vif->type); | 1057 | ath_dbg(common, CONFIG, "Attach a VIF of type: %d\n", vif->type); |
| 1050 | sc->nvifs++; | 1058 | sc->nvifs++; |
| 1051 | 1059 | ||
| @@ -1074,9 +1082,15 @@ static int ath9k_change_interface(struct ieee80211_hw *hw, | |||
| 1074 | struct ath_softc *sc = hw->priv; | 1082 | struct ath_softc *sc = hw->priv; |
| 1075 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1083 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
| 1076 | 1084 | ||
| 1077 | ath_dbg(common, CONFIG, "Change Interface\n"); | ||
| 1078 | mutex_lock(&sc->mutex); | 1085 | mutex_lock(&sc->mutex); |
| 1079 | 1086 | ||
| 1087 | if (config_enabled(CONFIG_ATH9K_TX99)) { | ||
| 1088 | mutex_unlock(&sc->mutex); | ||
| 1089 | return -EOPNOTSUPP; | ||
| 1090 | } | ||
| 1091 | |||
| 1092 | ath_dbg(common, CONFIG, "Change Interface\n"); | ||
| 1093 | |||
| 1080 | if (ath9k_uses_beacons(vif->type)) | 1094 | if (ath9k_uses_beacons(vif->type)) |
| 1081 | ath9k_beacon_remove_slot(sc, vif); | 1095 | ath9k_beacon_remove_slot(sc, vif); |
| 1082 | 1096 | ||
| @@ -1106,6 +1120,7 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, | |||
| 1106 | mutex_lock(&sc->mutex); | 1120 | mutex_lock(&sc->mutex); |
| 1107 | 1121 | ||
| 1108 | sc->nvifs--; | 1122 | sc->nvifs--; |
| 1123 | sc->tx99_vif = NULL; | ||
| 1109 | 1124 | ||
| 1110 | if (ath9k_uses_beacons(vif->type)) | 1125 | if (ath9k_uses_beacons(vif->type)) |
| 1111 | ath9k_beacon_remove_slot(sc, vif); | 1126 | ath9k_beacon_remove_slot(sc, vif); |
| @@ -1127,6 +1142,9 @@ static void ath9k_enable_ps(struct ath_softc *sc) | |||
| 1127 | struct ath_hw *ah = sc->sc_ah; | 1142 | struct ath_hw *ah = sc->sc_ah; |
| 1128 | struct ath_common *common = ath9k_hw_common(ah); | 1143 | struct ath_common *common = ath9k_hw_common(ah); |
| 1129 | 1144 | ||
| 1145 | if (config_enabled(CONFIG_ATH9K_TX99)) | ||
| 1146 | return; | ||
| 1147 | |||
| 1130 | sc->ps_enabled = true; | 1148 | sc->ps_enabled = true; |
| 1131 | if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { | 1149 | if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { |
| 1132 | if ((ah->imask & ATH9K_INT_TIM_TIMER) == 0) { | 1150 | if ((ah->imask & ATH9K_INT_TIM_TIMER) == 0) { |
| @@ -1143,6 +1161,9 @@ static void ath9k_disable_ps(struct ath_softc *sc) | |||
| 1143 | struct ath_hw *ah = sc->sc_ah; | 1161 | struct ath_hw *ah = sc->sc_ah; |
| 1144 | struct ath_common *common = ath9k_hw_common(ah); | 1162 | struct ath_common *common = ath9k_hw_common(ah); |
| 1145 | 1163 | ||
| 1164 | if (config_enabled(CONFIG_ATH9K_TX99)) | ||
| 1165 | return; | ||
| 1166 | |||
| 1146 | sc->ps_enabled = false; | 1167 | sc->ps_enabled = false; |
| 1147 | ath9k_hw_setpower(ah, ATH9K_PM_AWAKE); | 1168 | ath9k_hw_setpower(ah, ATH9K_PM_AWAKE); |
| 1148 | if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { | 1169 | if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { |
| @@ -1166,6 +1187,9 @@ void ath9k_spectral_scan_trigger(struct ieee80211_hw *hw) | |||
| 1166 | struct ath_common *common = ath9k_hw_common(ah); | 1187 | struct ath_common *common = ath9k_hw_common(ah); |
| 1167 | u32 rxfilter; | 1188 | u32 rxfilter; |
| 1168 | 1189 | ||
| 1190 | if (config_enabled(CONFIG_ATH9K_TX99)) | ||
| 1191 | return; | ||
| 1192 | |||
| 1169 | if (!ath9k_hw_ops(ah)->spectral_scan_trigger) { | 1193 | if (!ath9k_hw_ops(ah)->spectral_scan_trigger) { |
| 1170 | ath_err(common, "spectrum analyzer not implemented on this hardware\n"); | 1194 | ath_err(common, "spectrum analyzer not implemented on this hardware\n"); |
| 1171 | return; | 1195 | return; |
| @@ -1745,6 +1769,9 @@ static int ath9k_get_survey(struct ieee80211_hw *hw, int idx, | |||
| 1745 | unsigned long flags; | 1769 | unsigned long flags; |
| 1746 | int pos; | 1770 | int pos; |
| 1747 | 1771 | ||
| 1772 | if (config_enabled(CONFIG_ATH9K_TX99)) | ||
| 1773 | return -EOPNOTSUPP; | ||
| 1774 | |||
| 1748 | spin_lock_irqsave(&common->cc_lock, flags); | 1775 | spin_lock_irqsave(&common->cc_lock, flags); |
| 1749 | if (idx == 0) | 1776 | if (idx == 0) |
| 1750 | ath_update_survey_stats(sc); | 1777 | ath_update_survey_stats(sc); |
| @@ -1777,6 +1804,9 @@ static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class) | |||
| 1777 | struct ath_softc *sc = hw->priv; | 1804 | struct ath_softc *sc = hw->priv; |
| 1778 | struct ath_hw *ah = sc->sc_ah; | 1805 | struct ath_hw *ah = sc->sc_ah; |
| 1779 | 1806 | ||
| 1807 | if (config_enabled(CONFIG_ATH9K_TX99)) | ||
| 1808 | return; | ||
| 1809 | |||
| 1780 | mutex_lock(&sc->mutex); | 1810 | mutex_lock(&sc->mutex); |
| 1781 | ah->coverage_class = coverage_class; | 1811 | ah->coverage_class = coverage_class; |
| 1782 | 1812 | ||
| @@ -2343,6 +2373,134 @@ static void ath9k_channel_switch_beacon(struct ieee80211_hw *hw, | |||
| 2343 | sc->csa_vif = vif; | 2373 | sc->csa_vif = vif; |
| 2344 | } | 2374 | } |
| 2345 | 2375 | ||
| 2376 | static void ath9k_tx99_stop(struct ath_softc *sc) | ||
| 2377 | { | ||
| 2378 | struct ath_hw *ah = sc->sc_ah; | ||
| 2379 | struct ath_common *common = ath9k_hw_common(ah); | ||
| 2380 | |||
| 2381 | ath_drain_all_txq(sc); | ||
| 2382 | ath_startrecv(sc); | ||
| 2383 | |||
| 2384 | ath9k_hw_set_interrupts(ah); | ||
| 2385 | ath9k_hw_enable_interrupts(ah); | ||
| 2386 | |||
| 2387 | ieee80211_wake_queues(sc->hw); | ||
| 2388 | |||
| 2389 | kfree_skb(sc->tx99_skb); | ||
| 2390 | sc->tx99_skb = NULL; | ||
| 2391 | sc->tx99_state = false; | ||
| 2392 | |||
| 2393 | ath9k_hw_tx99_stop(sc->sc_ah); | ||
| 2394 | ath_dbg(common, XMIT, "TX99 stopped\n"); | ||
| 2395 | } | ||
| 2396 | |||
| 2397 | static struct sk_buff *ath9k_build_tx99_skb(struct ath_softc *sc) | ||
| 2398 | { | ||
| 2399 | static u8 PN9Data[] = {0xff, 0x87, 0xb8, 0x59, 0xb7, 0xa1, 0xcc, 0x24, | ||
| 2400 | 0x57, 0x5e, 0x4b, 0x9c, 0x0e, 0xe9, 0xea, 0x50, | ||
| 2401 | 0x2a, 0xbe, 0xb4, 0x1b, 0xb6, 0xb0, 0x5d, 0xf1, | ||
| 2402 | 0xe6, 0x9a, 0xe3, 0x45, 0xfd, 0x2c, 0x53, 0x18, | ||
| 2403 | 0x0c, 0xca, 0xc9, 0xfb, 0x49, 0x37, 0xe5, 0xa8, | ||
| 2404 | 0x51, 0x3b, 0x2f, 0x61, 0xaa, 0x72, 0x18, 0x84, | ||
| 2405 | 0x02, 0x23, 0x23, 0xab, 0x63, 0x89, 0x51, 0xb3, | ||
| 2406 | 0xe7, 0x8b, 0x72, 0x90, 0x4c, 0xe8, 0xfb, 0xc0}; | ||
| 2407 | u32 len = 1200; | ||
| 2408 | struct ieee80211_hw *hw = sc->hw; | ||
| 2409 | struct ieee80211_hdr *hdr; | ||
| 2410 | struct ieee80211_tx_info *tx_info; | ||
| 2411 | struct sk_buff *skb; | ||
| 2412 | |||
| 2413 | skb = alloc_skb(len, GFP_KERNEL); | ||
| 2414 | if (!skb) | ||
| 2415 | return NULL; | ||
| 2416 | |||
| 2417 | skb_put(skb, len); | ||
| 2418 | |||
| 2419 | memset(skb->data, 0, len); | ||
| 2420 | |||
| 2421 | hdr = (struct ieee80211_hdr *)skb->data; | ||
| 2422 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA); | ||
| 2423 | hdr->duration_id = 0; | ||
| 2424 | |||
| 2425 | memcpy(hdr->addr1, hw->wiphy->perm_addr, ETH_ALEN); | ||
| 2426 | memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN); | ||
| 2427 | memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN); | ||
| 2428 | |||
| 2429 | hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); | ||
| 2430 | |||
| 2431 | tx_info = IEEE80211_SKB_CB(skb); | ||
| 2432 | memset(tx_info, 0, sizeof(*tx_info)); | ||
| 2433 | tx_info->band = hw->conf.chandef.chan->band; | ||
| 2434 | tx_info->flags = IEEE80211_TX_CTL_NO_ACK; | ||
| 2435 | tx_info->control.vif = sc->tx99_vif; | ||
| 2436 | |||
| 2437 | memcpy(skb->data + sizeof(*hdr), PN9Data, sizeof(PN9Data)); | ||
| 2438 | |||
| 2439 | return skb; | ||
| 2440 | } | ||
| 2441 | |||
| 2442 | void ath9k_tx99_deinit(struct ath_softc *sc) | ||
| 2443 | { | ||
| 2444 | ath_reset(sc); | ||
| 2445 | |||
| 2446 | ath9k_ps_wakeup(sc); | ||
| 2447 | ath9k_tx99_stop(sc); | ||
| 2448 | ath9k_ps_restore(sc); | ||
| 2449 | } | ||
| 2450 | |||
| 2451 | int ath9k_tx99_init(struct ath_softc *sc) | ||
| 2452 | { | ||
| 2453 | struct ieee80211_hw *hw = sc->hw; | ||
| 2454 | struct ath_hw *ah = sc->sc_ah; | ||
| 2455 | struct ath_common *common = ath9k_hw_common(ah); | ||
| 2456 | struct ath_tx_control txctl; | ||
| 2457 | int r; | ||
| 2458 | |||
| 2459 | if (sc->sc_flags & SC_OP_INVALID) { | ||
| 2460 | ath_err(common, | ||
| 2461 | "driver is in invalid state unable to use TX99"); | ||
| 2462 | return -EINVAL; | ||
| 2463 | } | ||
| 2464 | |||
| 2465 | sc->tx99_skb = ath9k_build_tx99_skb(sc); | ||
| 2466 | if (!sc->tx99_skb) | ||
| 2467 | return -ENOMEM; | ||
| 2468 | |||
| 2469 | memset(&txctl, 0, sizeof(txctl)); | ||
| 2470 | txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO]; | ||
| 2471 | |||
| 2472 | ath_reset(sc); | ||
| 2473 | |||
| 2474 | ath9k_ps_wakeup(sc); | ||
| 2475 | |||
| 2476 | ath9k_hw_disable_interrupts(ah); | ||
| 2477 | atomic_set(&ah->intr_ref_cnt, -1); | ||
| 2478 | ath_drain_all_txq(sc); | ||
| 2479 | ath_stoprecv(sc); | ||
| 2480 | |||
| 2481 | sc->tx99_state = true; | ||
| 2482 | |||
| 2483 | ieee80211_stop_queues(hw); | ||
| 2484 | |||
| 2485 | if (sc->tx99_power == MAX_RATE_POWER + 1) | ||
| 2486 | sc->tx99_power = MAX_RATE_POWER; | ||
| 2487 | |||
| 2488 | ath9k_hw_tx99_set_txpower(ah, sc->tx99_power); | ||
| 2489 | r = ath9k_tx99_send(sc, sc->tx99_skb, &txctl); | ||
| 2490 | if (r) { | ||
| 2491 | ath_dbg(common, XMIT, "Failed to xmit TX99 skb\n"); | ||
| 2492 | return r; | ||
| 2493 | } | ||
| 2494 | |||
| 2495 | ath_dbg(common, XMIT, "TX99 xmit started using %d ( %ddBm)\n", | ||
| 2496 | sc->tx99_power, | ||
| 2497 | sc->tx99_power / 2); | ||
| 2498 | |||
| 2499 | /* We leave the harware awake as it will be chugging on */ | ||
| 2500 | |||
| 2501 | return 0; | ||
| 2502 | } | ||
| 2503 | |||
| 2346 | struct ieee80211_ops ath9k_ops = { | 2504 | struct ieee80211_ops ath9k_ops = { |
| 2347 | .tx = ath9k_tx, | 2505 | .tx = ath9k_tx, |
| 2348 | .start = ath9k_start, | 2506 | .start = ath9k_start, |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 8b788efb41fd..95ddca5495d4 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
| @@ -375,6 +375,9 @@ u32 ath_calcrxfilter(struct ath_softc *sc) | |||
| 375 | { | 375 | { |
| 376 | u32 rfilt; | 376 | u32 rfilt; |
| 377 | 377 | ||
| 378 | if (config_enabled(CONFIG_ATH9K_TX99)) | ||
| 379 | return 0; | ||
| 380 | |||
| 378 | rfilt = ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST | 381 | rfilt = ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST |
| 379 | | ATH9K_RX_FILTER_MCAST; | 382 | | ATH9K_RX_FILTER_MCAST; |
| 380 | 383 | ||
| @@ -972,14 +975,15 @@ static int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr, | |||
| 972 | { | 975 | { |
| 973 | #ifdef CONFIG_ATH9K_DEBUGFS | 976 | #ifdef CONFIG_ATH9K_DEBUGFS |
| 974 | struct ath_hw *ah = sc->sc_ah; | 977 | struct ath_hw *ah = sc->sc_ah; |
| 975 | u8 bins[SPECTRAL_HT20_NUM_BINS]; | 978 | u8 num_bins, *bins, *vdata = (u8 *)hdr; |
| 976 | u8 *vdata = (u8 *)hdr; | 979 | struct fft_sample_ht20 fft_sample_20; |
| 977 | struct fft_sample_ht20 fft_sample; | 980 | struct fft_sample_ht20_40 fft_sample_40; |
| 981 | struct fft_sample_tlv *tlv; | ||
| 978 | struct ath_radar_info *radar_info; | 982 | struct ath_radar_info *radar_info; |
| 979 | struct ath_ht20_mag_info *mag_info; | ||
| 980 | int len = rs->rs_datalen; | 983 | int len = rs->rs_datalen; |
| 981 | int dc_pos; | 984 | int dc_pos; |
| 982 | u16 length, max_magnitude; | 985 | u16 fft_len, length, freq = ah->curchan->chan->center_freq; |
| 986 | enum nl80211_channel_type chan_type; | ||
| 983 | 987 | ||
| 984 | /* AR9280 and before report via ATH9K_PHYERR_RADAR, AR93xx and newer | 988 | /* AR9280 and before report via ATH9K_PHYERR_RADAR, AR93xx and newer |
| 985 | * via ATH9K_PHYERR_SPECTRAL. Haven't seen ATH9K_PHYERR_FALSE_RADAR_EXT | 989 | * via ATH9K_PHYERR_SPECTRAL. Haven't seen ATH9K_PHYERR_FALSE_RADAR_EXT |
| @@ -997,45 +1001,44 @@ static int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr, | |||
| 997 | if (!(radar_info->pulse_bw_info & SPECTRAL_SCAN_BITMASK)) | 1001 | if (!(radar_info->pulse_bw_info & SPECTRAL_SCAN_BITMASK)) |
| 998 | return 0; | 1002 | return 0; |
| 999 | 1003 | ||
| 1000 | /* Variation in the data length is possible and will be fixed later. | 1004 | chan_type = cfg80211_get_chandef_type(&sc->hw->conf.chandef); |
| 1001 | * Note that we only support HT20 for now. | 1005 | if ((chan_type == NL80211_CHAN_HT40MINUS) || |
| 1002 | * | 1006 | (chan_type == NL80211_CHAN_HT40PLUS)) { |
| 1003 | * TODO: add HT20_40 support as well. | 1007 | fft_len = SPECTRAL_HT20_40_TOTAL_DATA_LEN; |
| 1004 | */ | 1008 | num_bins = SPECTRAL_HT20_40_NUM_BINS; |
| 1005 | if ((len > SPECTRAL_HT20_TOTAL_DATA_LEN + 2) || | 1009 | bins = (u8 *)fft_sample_40.data; |
| 1006 | (len < SPECTRAL_HT20_TOTAL_DATA_LEN - 1)) | 1010 | } else { |
| 1007 | return 1; | 1011 | fft_len = SPECTRAL_HT20_TOTAL_DATA_LEN; |
| 1008 | 1012 | num_bins = SPECTRAL_HT20_NUM_BINS; | |
| 1009 | fft_sample.tlv.type = ATH_FFT_SAMPLE_HT20; | 1013 | bins = (u8 *)fft_sample_20.data; |
| 1010 | length = sizeof(fft_sample) - sizeof(fft_sample.tlv); | 1014 | } |
| 1011 | fft_sample.tlv.length = __cpu_to_be16(length); | ||
| 1012 | 1015 | ||
| 1013 | fft_sample.freq = __cpu_to_be16(ah->curchan->chan->center_freq); | 1016 | /* Variation in the data length is possible and will be fixed later */ |
| 1014 | fft_sample.rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0); | 1017 | if ((len > fft_len + 2) || (len < fft_len - 1)) |
| 1015 | fft_sample.noise = ah->noise; | 1018 | return 1; |
| 1016 | 1019 | ||
| 1017 | switch (len - SPECTRAL_HT20_TOTAL_DATA_LEN) { | 1020 | switch (len - fft_len) { |
| 1018 | case 0: | 1021 | case 0: |
| 1019 | /* length correct, nothing to do. */ | 1022 | /* length correct, nothing to do. */ |
| 1020 | memcpy(bins, vdata, SPECTRAL_HT20_NUM_BINS); | 1023 | memcpy(bins, vdata, num_bins); |
| 1021 | break; | 1024 | break; |
| 1022 | case -1: | 1025 | case -1: |
| 1023 | /* first byte missing, duplicate it. */ | 1026 | /* first byte missing, duplicate it. */ |
| 1024 | memcpy(&bins[1], vdata, SPECTRAL_HT20_NUM_BINS - 1); | 1027 | memcpy(&bins[1], vdata, num_bins - 1); |
| 1025 | bins[0] = vdata[0]; | 1028 | bins[0] = vdata[0]; |
| 1026 | break; | 1029 | break; |
| 1027 | case 2: | 1030 | case 2: |
| 1028 | /* MAC added 2 extra bytes at bin 30 and 32, remove them. */ | 1031 | /* MAC added 2 extra bytes at bin 30 and 32, remove them. */ |
| 1029 | memcpy(bins, vdata, 30); | 1032 | memcpy(bins, vdata, 30); |
| 1030 | bins[30] = vdata[31]; | 1033 | bins[30] = vdata[31]; |
| 1031 | memcpy(&bins[31], &vdata[33], SPECTRAL_HT20_NUM_BINS - 31); | 1034 | memcpy(&bins[31], &vdata[33], num_bins - 31); |
| 1032 | break; | 1035 | break; |
| 1033 | case 1: | 1036 | case 1: |
| 1034 | /* MAC added 2 extra bytes AND first byte is missing. */ | 1037 | /* MAC added 2 extra bytes AND first byte is missing. */ |
| 1035 | bins[0] = vdata[0]; | 1038 | bins[0] = vdata[0]; |
| 1036 | memcpy(&bins[0], vdata, 30); | 1039 | memcpy(&bins[1], vdata, 30); |
| 1037 | bins[31] = vdata[31]; | 1040 | bins[31] = vdata[31]; |
| 1038 | memcpy(&bins[32], &vdata[33], SPECTRAL_HT20_NUM_BINS - 32); | 1041 | memcpy(&bins[32], &vdata[33], num_bins - 32); |
| 1039 | break; | 1042 | break; |
| 1040 | default: | 1043 | default: |
| 1041 | return 1; | 1044 | return 1; |
| @@ -1044,23 +1047,93 @@ static int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr, | |||
| 1044 | /* DC value (value in the middle) is the blind spot of the spectral | 1047 | /* DC value (value in the middle) is the blind spot of the spectral |
| 1045 | * sample and invalid, interpolate it. | 1048 | * sample and invalid, interpolate it. |
| 1046 | */ | 1049 | */ |
| 1047 | dc_pos = SPECTRAL_HT20_NUM_BINS / 2; | 1050 | dc_pos = num_bins / 2; |
| 1048 | bins[dc_pos] = (bins[dc_pos + 1] + bins[dc_pos - 1]) / 2; | 1051 | bins[dc_pos] = (bins[dc_pos + 1] + bins[dc_pos - 1]) / 2; |
| 1049 | 1052 | ||
| 1050 | /* mag data is at the end of the frame, in front of radar_info */ | 1053 | if ((chan_type == NL80211_CHAN_HT40MINUS) || |
| 1051 | mag_info = ((struct ath_ht20_mag_info *)radar_info) - 1; | 1054 | (chan_type == NL80211_CHAN_HT40PLUS)) { |
| 1055 | s8 lower_rssi, upper_rssi; | ||
| 1056 | s16 ext_nf; | ||
| 1057 | u8 lower_max_index, upper_max_index; | ||
| 1058 | u8 lower_bitmap_w, upper_bitmap_w; | ||
| 1059 | u16 lower_mag, upper_mag; | ||
| 1060 | struct ath9k_hw_cal_data *caldata = ah->caldata; | ||
| 1061 | struct ath_ht20_40_mag_info *mag_info; | ||
| 1062 | |||
| 1063 | if (caldata) | ||
| 1064 | ext_nf = ath9k_hw_getchan_noise(ah, ah->curchan, | ||
| 1065 | caldata->nfCalHist[3].privNF); | ||
| 1066 | else | ||
| 1067 | ext_nf = ATH_DEFAULT_NOISE_FLOOR; | ||
| 1068 | |||
| 1069 | length = sizeof(fft_sample_40) - sizeof(struct fft_sample_tlv); | ||
| 1070 | fft_sample_40.tlv.type = ATH_FFT_SAMPLE_HT20_40; | ||
| 1071 | fft_sample_40.tlv.length = __cpu_to_be16(length); | ||
| 1072 | fft_sample_40.freq = __cpu_to_be16(freq); | ||
| 1073 | fft_sample_40.channel_type = chan_type; | ||
| 1074 | |||
| 1075 | if (chan_type == NL80211_CHAN_HT40PLUS) { | ||
| 1076 | lower_rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0); | ||
| 1077 | upper_rssi = fix_rssi_inv_only(rs->rs_rssi_ext0); | ||
| 1052 | 1078 | ||
| 1053 | /* copy raw bins without scaling them */ | 1079 | fft_sample_40.lower_noise = ah->noise; |
| 1054 | memcpy(fft_sample.data, bins, SPECTRAL_HT20_NUM_BINS); | 1080 | fft_sample_40.upper_noise = ext_nf; |
| 1055 | fft_sample.max_exp = mag_info->max_exp & 0xf; | 1081 | } else { |
| 1082 | lower_rssi = fix_rssi_inv_only(rs->rs_rssi_ext0); | ||
| 1083 | upper_rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0); | ||
| 1056 | 1084 | ||
| 1057 | max_magnitude = spectral_max_magnitude(mag_info->all_bins); | 1085 | fft_sample_40.lower_noise = ext_nf; |
| 1058 | fft_sample.max_magnitude = __cpu_to_be16(max_magnitude); | 1086 | fft_sample_40.upper_noise = ah->noise; |
| 1059 | fft_sample.max_index = spectral_max_index(mag_info->all_bins); | 1087 | } |
| 1060 | fft_sample.bitmap_weight = spectral_bitmap_weight(mag_info->all_bins); | 1088 | fft_sample_40.lower_rssi = lower_rssi; |
| 1061 | fft_sample.tsf = __cpu_to_be64(tsf); | 1089 | fft_sample_40.upper_rssi = upper_rssi; |
| 1090 | |||
| 1091 | mag_info = ((struct ath_ht20_40_mag_info *)radar_info) - 1; | ||
| 1092 | lower_mag = spectral_max_magnitude(mag_info->lower_bins); | ||
| 1093 | upper_mag = spectral_max_magnitude(mag_info->upper_bins); | ||
| 1094 | fft_sample_40.lower_max_magnitude = __cpu_to_be16(lower_mag); | ||
| 1095 | fft_sample_40.upper_max_magnitude = __cpu_to_be16(upper_mag); | ||
| 1096 | lower_max_index = spectral_max_index(mag_info->lower_bins); | ||
| 1097 | upper_max_index = spectral_max_index(mag_info->upper_bins); | ||
| 1098 | fft_sample_40.lower_max_index = lower_max_index; | ||
| 1099 | fft_sample_40.upper_max_index = upper_max_index; | ||
| 1100 | lower_bitmap_w = spectral_bitmap_weight(mag_info->lower_bins); | ||
| 1101 | upper_bitmap_w = spectral_bitmap_weight(mag_info->upper_bins); | ||
| 1102 | fft_sample_40.lower_bitmap_weight = lower_bitmap_w; | ||
| 1103 | fft_sample_40.upper_bitmap_weight = upper_bitmap_w; | ||
| 1104 | fft_sample_40.max_exp = mag_info->max_exp & 0xf; | ||
| 1105 | |||
| 1106 | fft_sample_40.tsf = __cpu_to_be64(tsf); | ||
| 1107 | |||
| 1108 | tlv = (struct fft_sample_tlv *)&fft_sample_40; | ||
| 1109 | } else { | ||
| 1110 | u8 max_index, bitmap_w; | ||
| 1111 | u16 magnitude; | ||
| 1112 | struct ath_ht20_mag_info *mag_info; | ||
| 1113 | |||
| 1114 | length = sizeof(fft_sample_20) - sizeof(struct fft_sample_tlv); | ||
| 1115 | fft_sample_20.tlv.type = ATH_FFT_SAMPLE_HT20; | ||
| 1116 | fft_sample_20.tlv.length = __cpu_to_be16(length); | ||
| 1117 | fft_sample_20.freq = __cpu_to_be16(freq); | ||
| 1118 | |||
| 1119 | fft_sample_20.rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0); | ||
| 1120 | fft_sample_20.noise = ah->noise; | ||
| 1121 | |||
| 1122 | mag_info = ((struct ath_ht20_mag_info *)radar_info) - 1; | ||
| 1123 | magnitude = spectral_max_magnitude(mag_info->all_bins); | ||
| 1124 | fft_sample_20.max_magnitude = __cpu_to_be16(magnitude); | ||
| 1125 | max_index = spectral_max_index(mag_info->all_bins); | ||
| 1126 | fft_sample_20.max_index = max_index; | ||
| 1127 | bitmap_w = spectral_bitmap_weight(mag_info->all_bins); | ||
| 1128 | fft_sample_20.bitmap_weight = bitmap_w; | ||
| 1129 | fft_sample_20.max_exp = mag_info->max_exp & 0xf; | ||
| 1130 | |||
| 1131 | fft_sample_20.tsf = __cpu_to_be64(tsf); | ||
| 1132 | |||
| 1133 | tlv = (struct fft_sample_tlv *)&fft_sample_20; | ||
| 1134 | } | ||
| 1062 | 1135 | ||
| 1063 | ath_debug_send_fft_sample(sc, &fft_sample.tlv); | 1136 | ath_debug_send_fft_sample(sc, tlv); |
| 1064 | return 1; | 1137 | return 1; |
| 1065 | #else | 1138 | #else |
| 1066 | return 0; | 1139 | return 0; |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 47696d29743c..09cdbcd09739 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
| @@ -1241,12 +1241,13 @@ static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf, | |||
| 1241 | if (bf->bf_next) | 1241 | if (bf->bf_next) |
| 1242 | info.link = bf->bf_next->bf_daddr; | 1242 | info.link = bf->bf_next->bf_daddr; |
| 1243 | else | 1243 | else |
| 1244 | info.link = 0; | 1244 | info.link = (sc->tx99_state) ? bf->bf_daddr : 0; |
| 1245 | 1245 | ||
| 1246 | if (!bf_first) { | 1246 | if (!bf_first) { |
| 1247 | bf_first = bf; | 1247 | bf_first = bf; |
| 1248 | 1248 | ||
| 1249 | info.flags = ATH9K_TXDESC_INTREQ; | 1249 | if (!sc->tx99_state) |
| 1250 | info.flags = ATH9K_TXDESC_INTREQ; | ||
| 1250 | if ((tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) || | 1251 | if ((tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) || |
| 1251 | txq == sc->tx.uapsdq) | 1252 | txq == sc->tx.uapsdq) |
| 1252 | info.flags |= ATH9K_TXDESC_CLRDMASK; | 1253 | info.flags |= ATH9K_TXDESC_CLRDMASK; |
| @@ -1941,7 +1942,7 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, | |||
| 1941 | txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc); | 1942 | txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc); |
| 1942 | } | 1943 | } |
| 1943 | 1944 | ||
| 1944 | if (!edma) { | 1945 | if (!edma || sc->tx99_state) { |
| 1945 | TX_STAT_INC(txq->axq_qnum, txstart); | 1946 | TX_STAT_INC(txq->axq_qnum, txstart); |
| 1946 | ath9k_hw_txstart(ah, txq->axq_qnum); | 1947 | ath9k_hw_txstart(ah, txq->axq_qnum); |
| 1947 | } | 1948 | } |
| @@ -2020,6 +2021,9 @@ static void setup_frame_info(struct ieee80211_hw *hw, | |||
| 2020 | fi->keyix = ATH9K_TXKEYIX_INVALID; | 2021 | fi->keyix = ATH9K_TXKEYIX_INVALID; |
| 2021 | fi->keytype = keytype; | 2022 | fi->keytype = keytype; |
| 2022 | fi->framelen = framelen; | 2023 | fi->framelen = framelen; |
| 2024 | |||
| 2025 | if (!rate) | ||
| 2026 | return; | ||
| 2023 | fi->rtscts_rate = rate->hw_value; | 2027 | fi->rtscts_rate = rate->hw_value; |
| 2024 | if (short_preamble) | 2028 | if (short_preamble) |
| 2025 | fi->rtscts_rate |= rate->hw_value_short; | 2029 | fi->rtscts_rate |= rate->hw_value_short; |
| @@ -2371,6 +2375,8 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, | |||
| 2371 | 2375 | ||
| 2372 | dma_unmap_single(sc->dev, bf->bf_buf_addr, skb->len, DMA_TO_DEVICE); | 2376 | dma_unmap_single(sc->dev, bf->bf_buf_addr, skb->len, DMA_TO_DEVICE); |
| 2373 | bf->bf_buf_addr = 0; | 2377 | bf->bf_buf_addr = 0; |
| 2378 | if (sc->tx99_state) | ||
| 2379 | goto skip_tx_complete; | ||
| 2374 | 2380 | ||
| 2375 | if (bf->bf_state.bfs_paprd) { | 2381 | if (bf->bf_state.bfs_paprd) { |
| 2376 | if (time_after(jiffies, | 2382 | if (time_after(jiffies, |
| @@ -2383,6 +2389,7 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, | |||
| 2383 | ath_debug_stat_tx(sc, bf, ts, txq, tx_flags); | 2389 | ath_debug_stat_tx(sc, bf, ts, txq, tx_flags); |
| 2384 | ath_tx_complete(sc, skb, tx_flags, txq); | 2390 | ath_tx_complete(sc, skb, tx_flags, txq); |
| 2385 | } | 2391 | } |
| 2392 | skip_tx_complete: | ||
| 2386 | /* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't | 2393 | /* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't |
| 2387 | * accidentally reference it later. | 2394 | * accidentally reference it later. |
| 2388 | */ | 2395 | */ |
| @@ -2741,3 +2748,46 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an) | |||
| 2741 | ath_txq_unlock(sc, txq); | 2748 | ath_txq_unlock(sc, txq); |
| 2742 | } | 2749 | } |
| 2743 | } | 2750 | } |
| 2751 | |||
| 2752 | int ath9k_tx99_send(struct ath_softc *sc, struct sk_buff *skb, | ||
| 2753 | struct ath_tx_control *txctl) | ||
| 2754 | { | ||
| 2755 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
| 2756 | struct ath_frame_info *fi = get_frame_info(skb); | ||
| 2757 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
| 2758 | struct ath_buf *bf; | ||
| 2759 | int padpos, padsize; | ||
| 2760 | |||
| 2761 | padpos = ieee80211_hdrlen(hdr->frame_control); | ||
| 2762 | padsize = padpos & 3; | ||
| 2763 | |||
| 2764 | if (padsize && skb->len > padpos) { | ||
| 2765 | if (skb_headroom(skb) < padsize) { | ||
| 2766 | ath_dbg(common, XMIT, | ||
| 2767 | "tx99 padding failed\n"); | ||
| 2768 | return -EINVAL; | ||
| 2769 | } | ||
| 2770 | |||
| 2771 | skb_push(skb, padsize); | ||
| 2772 | memmove(skb->data, skb->data + padsize, padpos); | ||
| 2773 | } | ||
| 2774 | |||
| 2775 | fi->keyix = ATH9K_TXKEYIX_INVALID; | ||
| 2776 | fi->framelen = skb->len + FCS_LEN; | ||
| 2777 | fi->keytype = ATH9K_KEY_TYPE_CLEAR; | ||
| 2778 | |||
| 2779 | bf = ath_tx_setup_buffer(sc, txctl->txq, NULL, skb); | ||
| 2780 | if (!bf) { | ||
| 2781 | ath_dbg(common, XMIT, "tx99 buffer setup failed\n"); | ||
| 2782 | return -EINVAL; | ||
| 2783 | } | ||
| 2784 | |||
| 2785 | ath_set_rates(sc->tx99_vif, NULL, bf); | ||
| 2786 | |||
| 2787 | ath9k_hw_set_desc_link(sc->sc_ah, bf->bf_desc, bf->bf_daddr); | ||
| 2788 | ath9k_hw_tx99_start(sc->sc_ah, txctl->txq->axq_qnum); | ||
| 2789 | |||
| 2790 | ath_tx_send_normal(sc, txctl->txq, NULL, skb); | ||
| 2791 | |||
| 2792 | return 0; | ||
| 2793 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.c b/drivers/net/wireless/ath/dfs_pattern_detector.c index 491305c81fce..a1a69c5db409 100644 --- a/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.c +++ b/drivers/net/wireless/ath/dfs_pattern_detector.c | |||
| @@ -19,7 +19,7 @@ | |||
| 19 | 19 | ||
| 20 | #include "dfs_pattern_detector.h" | 20 | #include "dfs_pattern_detector.h" |
| 21 | #include "dfs_pri_detector.h" | 21 | #include "dfs_pri_detector.h" |
| 22 | #include "ath9k.h" | 22 | #include "ath.h" |
| 23 | 23 | ||
| 24 | /* | 24 | /* |
| 25 | * tolerated deviation of radar time stamp in usecs on both sides | 25 | * tolerated deviation of radar time stamp in usecs on both sides |
| @@ -143,7 +143,6 @@ channel_detector_create(struct dfs_pattern_detector *dpd, u16 freq) | |||
| 143 | { | 143 | { |
| 144 | u32 sz, i; | 144 | u32 sz, i; |
| 145 | struct channel_detector *cd; | 145 | struct channel_detector *cd; |
| 146 | struct ath_common *common = ath9k_hw_common(dpd->ah); | ||
| 147 | 146 | ||
| 148 | cd = kmalloc(sizeof(*cd), GFP_ATOMIC); | 147 | cd = kmalloc(sizeof(*cd), GFP_ATOMIC); |
| 149 | if (cd == NULL) | 148 | if (cd == NULL) |
| @@ -167,7 +166,7 @@ channel_detector_create(struct dfs_pattern_detector *dpd, u16 freq) | |||
| 167 | return cd; | 166 | return cd; |
| 168 | 167 | ||
| 169 | fail: | 168 | fail: |
| 170 | ath_dbg(common, DFS, | 169 | ath_dbg(dpd->common, DFS, |
| 171 | "failed to allocate channel_detector for freq=%d\n", freq); | 170 | "failed to allocate channel_detector for freq=%d\n", freq); |
| 172 | channel_detector_exit(dpd, cd); | 171 | channel_detector_exit(dpd, cd); |
| 173 | return NULL; | 172 | return NULL; |
| @@ -242,7 +241,7 @@ dpd_add_pulse(struct dfs_pattern_detector *dpd, struct pulse_event *event) | |||
| 242 | struct pri_detector *pd = cd->detectors[i]; | 241 | struct pri_detector *pd = cd->detectors[i]; |
| 243 | struct pri_sequence *ps = pd->add_pulse(pd, event); | 242 | struct pri_sequence *ps = pd->add_pulse(pd, event); |
| 244 | if (ps != NULL) { | 243 | if (ps != NULL) { |
| 245 | ath_dbg(ath9k_hw_common(dpd->ah), DFS, | 244 | ath_dbg(dpd->common, DFS, |
| 246 | "DFS: radar found on freq=%d: id=%d, pri=%d, " | 245 | "DFS: radar found on freq=%d: id=%d, pri=%d, " |
| 247 | "count=%d, count_false=%d\n", | 246 | "count=%d, count_false=%d\n", |
| 248 | event->freq, pd->rs->type_id, | 247 | event->freq, pd->rs->type_id, |
| @@ -254,6 +253,12 @@ dpd_add_pulse(struct dfs_pattern_detector *dpd, struct pulse_event *event) | |||
| 254 | return false; | 253 | return false; |
| 255 | } | 254 | } |
| 256 | 255 | ||
| 256 | static struct ath_dfs_pool_stats | ||
| 257 | dpd_get_stats(struct dfs_pattern_detector *dpd) | ||
| 258 | { | ||
| 259 | return global_dfs_pool_stats; | ||
| 260 | } | ||
| 261 | |||
| 257 | static bool dpd_set_domain(struct dfs_pattern_detector *dpd, | 262 | static bool dpd_set_domain(struct dfs_pattern_detector *dpd, |
| 258 | enum nl80211_dfs_regions region) | 263 | enum nl80211_dfs_regions region) |
| 259 | { | 264 | { |
| @@ -284,14 +289,18 @@ static struct dfs_pattern_detector default_dpd = { | |||
| 284 | .exit = dpd_exit, | 289 | .exit = dpd_exit, |
| 285 | .set_dfs_domain = dpd_set_domain, | 290 | .set_dfs_domain = dpd_set_domain, |
| 286 | .add_pulse = dpd_add_pulse, | 291 | .add_pulse = dpd_add_pulse, |
| 292 | .get_stats = dpd_get_stats, | ||
| 287 | .region = NL80211_DFS_UNSET, | 293 | .region = NL80211_DFS_UNSET, |
| 288 | }; | 294 | }; |
| 289 | 295 | ||
| 290 | struct dfs_pattern_detector * | 296 | struct dfs_pattern_detector * |
| 291 | dfs_pattern_detector_init(struct ath_hw *ah, enum nl80211_dfs_regions region) | 297 | dfs_pattern_detector_init(struct ath_common *common, |
| 298 | enum nl80211_dfs_regions region) | ||
| 292 | { | 299 | { |
| 293 | struct dfs_pattern_detector *dpd; | 300 | struct dfs_pattern_detector *dpd; |
| 294 | struct ath_common *common = ath9k_hw_common(ah); | 301 | |
| 302 | if (!config_enabled(CONFIG_CFG80211_CERTIFICATION_ONUS)) | ||
| 303 | return NULL; | ||
| 295 | 304 | ||
| 296 | dpd = kmalloc(sizeof(*dpd), GFP_KERNEL); | 305 | dpd = kmalloc(sizeof(*dpd), GFP_KERNEL); |
| 297 | if (dpd == NULL) | 306 | if (dpd == NULL) |
| @@ -300,7 +309,7 @@ dfs_pattern_detector_init(struct ath_hw *ah, enum nl80211_dfs_regions region) | |||
| 300 | *dpd = default_dpd; | 309 | *dpd = default_dpd; |
| 301 | INIT_LIST_HEAD(&dpd->channel_detectors); | 310 | INIT_LIST_HEAD(&dpd->channel_detectors); |
| 302 | 311 | ||
| 303 | dpd->ah = ah; | 312 | dpd->common = common; |
| 304 | if (dpd->set_dfs_domain(dpd, region)) | 313 | if (dpd->set_dfs_domain(dpd, region)) |
| 305 | return dpd; | 314 | return dpd; |
| 306 | 315 | ||
diff --git a/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.h b/drivers/net/wireless/ath/dfs_pattern_detector.h index 90a5abcc4265..dde2652b787c 100644 --- a/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.h +++ b/drivers/net/wireless/ath/dfs_pattern_detector.h | |||
| @@ -22,6 +22,19 @@ | |||
| 22 | #include <linux/nl80211.h> | 22 | #include <linux/nl80211.h> |
| 23 | 23 | ||
| 24 | /** | 24 | /** |
| 25 | * struct ath_dfs_pool_stats - DFS Statistics for global pools | ||
| 26 | */ | ||
| 27 | struct ath_dfs_pool_stats { | ||
| 28 | u32 pool_reference; | ||
| 29 | u32 pulse_allocated; | ||
| 30 | u32 pulse_alloc_error; | ||
| 31 | u32 pulse_used; | ||
| 32 | u32 pseq_allocated; | ||
| 33 | u32 pseq_alloc_error; | ||
| 34 | u32 pseq_used; | ||
| 35 | }; | ||
| 36 | |||
| 37 | /** | ||
| 25 | * struct pulse_event - describing pulses reported by PHY | 38 | * struct pulse_event - describing pulses reported by PHY |
| 26 | * @ts: pulse time stamp in us | 39 | * @ts: pulse time stamp in us |
| 27 | * @freq: channel frequency in MHz | 40 | * @freq: channel frequency in MHz |
| @@ -77,11 +90,12 @@ struct dfs_pattern_detector { | |||
| 77 | bool (*add_pulse)(struct dfs_pattern_detector *dpd, | 90 | bool (*add_pulse)(struct dfs_pattern_detector *dpd, |
| 78 | struct pulse_event *pe); | 91 | struct pulse_event *pe); |
| 79 | 92 | ||
| 93 | struct ath_dfs_pool_stats (*get_stats)(struct dfs_pattern_detector *dpd); | ||
| 80 | enum nl80211_dfs_regions region; | 94 | enum nl80211_dfs_regions region; |
| 81 | u8 num_radar_types; | 95 | u8 num_radar_types; |
| 82 | u64 last_pulse_ts; | 96 | u64 last_pulse_ts; |
| 83 | /* needed for ath_dbg() */ | 97 | /* needed for ath_dbg() */ |
| 84 | struct ath_hw *ah; | 98 | struct ath_common *common; |
| 85 | 99 | ||
| 86 | const struct radar_detector_specs *radar_spec; | 100 | const struct radar_detector_specs *radar_spec; |
| 87 | struct list_head channel_detectors; | 101 | struct list_head channel_detectors; |
| @@ -92,15 +106,7 @@ struct dfs_pattern_detector { | |||
| 92 | * @param region: DFS domain to be used, can be NL80211_DFS_UNSET at creation | 106 | * @param region: DFS domain to be used, can be NL80211_DFS_UNSET at creation |
| 93 | * @return instance pointer on success, NULL otherwise | 107 | * @return instance pointer on success, NULL otherwise |
| 94 | */ | 108 | */ |
| 95 | #if defined(CONFIG_ATH9K_DFS_CERTIFIED) | ||
| 96 | extern struct dfs_pattern_detector * | 109 | extern struct dfs_pattern_detector * |
| 97 | dfs_pattern_detector_init(struct ath_hw *ah, enum nl80211_dfs_regions region); | 110 | dfs_pattern_detector_init(struct ath_common *common, |
| 98 | #else | 111 | enum nl80211_dfs_regions region); |
| 99 | static inline struct dfs_pattern_detector * | ||
| 100 | dfs_pattern_detector_init(struct ath_hw *ah, enum nl80211_dfs_regions region) | ||
| 101 | { | ||
| 102 | return NULL; | ||
| 103 | } | ||
| 104 | #endif /* CONFIG_ATH9K_DFS_CERTIFIED */ | ||
| 105 | |||
| 106 | #endif /* DFS_PATTERN_DETECTOR_H */ | 112 | #endif /* DFS_PATTERN_DETECTOR_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/dfs_pri_detector.c b/drivers/net/wireless/ath/dfs_pri_detector.c index c718fc379a10..43b608178884 100644 --- a/drivers/net/wireless/ath/ath9k/dfs_pri_detector.c +++ b/drivers/net/wireless/ath/dfs_pri_detector.c | |||
| @@ -17,10 +17,14 @@ | |||
| 17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
| 18 | #include <linux/spinlock.h> | 18 | #include <linux/spinlock.h> |
| 19 | 19 | ||
| 20 | #include "ath9k.h" | 20 | #include "ath.h" |
| 21 | #include "dfs_pattern_detector.h" | 21 | #include "dfs_pattern_detector.h" |
| 22 | #include "dfs_pri_detector.h" | 22 | #include "dfs_pri_detector.h" |
| 23 | #include "dfs_debug.h" | 23 | |
| 24 | struct ath_dfs_pool_stats global_dfs_pool_stats = {}; | ||
| 25 | |||
| 26 | #define DFS_POOL_STAT_INC(c) (global_dfs_pool_stats.c++) | ||
| 27 | #define DFS_POOL_STAT_DEC(c) (global_dfs_pool_stats.c--) | ||
| 24 | 28 | ||
| 25 | /** | 29 | /** |
| 26 | * struct pulse_elem - elements in pulse queue | 30 | * struct pulse_elem - elements in pulse queue |
diff --git a/drivers/net/wireless/ath/ath9k/dfs_pri_detector.h b/drivers/net/wireless/ath/dfs_pri_detector.h index 723962d1abc6..79f0fff4d1e6 100644 --- a/drivers/net/wireless/ath/ath9k/dfs_pri_detector.h +++ b/drivers/net/wireless/ath/dfs_pri_detector.h | |||
| @@ -19,6 +19,8 @@ | |||
| 19 | 19 | ||
| 20 | #include <linux/list.h> | 20 | #include <linux/list.h> |
| 21 | 21 | ||
| 22 | extern struct ath_dfs_pool_stats global_dfs_pool_stats; | ||
| 23 | |||
| 22 | /** | 24 | /** |
| 23 | * struct pri_sequence - sequence of pulses matching one PRI | 25 | * struct pri_sequence - sequence of pulses matching one PRI |
| 24 | * @head: list_head | 26 | * @head: list_head |
diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index 7d077c752dd5..c00687e05688 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c | |||
| @@ -356,14 +356,131 @@ static u16 ath_regd_find_country_by_name(char *alpha2) | |||
| 356 | return -1; | 356 | return -1; |
| 357 | } | 357 | } |
| 358 | 358 | ||
| 359 | static int __ath_reg_dyn_country(struct wiphy *wiphy, | ||
| 360 | struct ath_regulatory *reg, | ||
| 361 | struct regulatory_request *request) | ||
| 362 | { | ||
| 363 | u16 country_code; | ||
| 364 | |||
| 365 | if (!ath_is_world_regd(reg)) | ||
| 366 | return -EINVAL; | ||
| 367 | |||
| 368 | country_code = ath_regd_find_country_by_name(request->alpha2); | ||
| 369 | if (country_code == (u16) -1) | ||
| 370 | return -EINVAL; | ||
| 371 | |||
| 372 | reg->current_rd = COUNTRY_ERD_FLAG; | ||
| 373 | reg->current_rd |= country_code; | ||
| 374 | |||
| 375 | __ath_regd_init(reg); | ||
| 376 | |||
| 377 | ath_reg_apply_world_flags(wiphy, request->initiator, reg); | ||
| 378 | |||
| 379 | return 0; | ||
| 380 | } | ||
| 381 | |||
| 382 | static void ath_reg_dyn_country(struct wiphy *wiphy, | ||
| 383 | struct ath_regulatory *reg, | ||
| 384 | struct regulatory_request *request) | ||
| 385 | { | ||
| 386 | if (__ath_reg_dyn_country(wiphy, reg, request)) | ||
| 387 | return; | ||
| 388 | |||
| 389 | printk(KERN_DEBUG "ath: regdomain 0x%0x " | ||
| 390 | "dynamically updated by %s\n", | ||
| 391 | reg->current_rd, | ||
| 392 | reg_initiator_name(request->initiator)); | ||
| 393 | } | ||
| 394 | |||
| 395 | static bool dynamic_country_user_possible(struct ath_regulatory *reg) | ||
| 396 | { | ||
| 397 | if (config_enabled(CONFIG_ATH_REG_DYNAMIC_USER_CERT_TESTING)) | ||
| 398 | return true; | ||
| 399 | |||
| 400 | switch (reg->country_code) { | ||
| 401 | case CTRY_UNITED_STATES: | ||
| 402 | case CTRY_JAPAN1: | ||
| 403 | case CTRY_JAPAN2: | ||
| 404 | case CTRY_JAPAN3: | ||
| 405 | case CTRY_JAPAN4: | ||
| 406 | case CTRY_JAPAN5: | ||
| 407 | case CTRY_JAPAN6: | ||
| 408 | case CTRY_JAPAN7: | ||
| 409 | case CTRY_JAPAN8: | ||
| 410 | case CTRY_JAPAN9: | ||
| 411 | case CTRY_JAPAN10: | ||
| 412 | case CTRY_JAPAN11: | ||
| 413 | case CTRY_JAPAN12: | ||
| 414 | case CTRY_JAPAN13: | ||
| 415 | case CTRY_JAPAN14: | ||
| 416 | case CTRY_JAPAN15: | ||
| 417 | case CTRY_JAPAN16: | ||
| 418 | case CTRY_JAPAN17: | ||
| 419 | case CTRY_JAPAN18: | ||
| 420 | case CTRY_JAPAN19: | ||
| 421 | case CTRY_JAPAN20: | ||
| 422 | case CTRY_JAPAN21: | ||
| 423 | case CTRY_JAPAN22: | ||
| 424 | case CTRY_JAPAN23: | ||
| 425 | case CTRY_JAPAN24: | ||
| 426 | case CTRY_JAPAN25: | ||
| 427 | case CTRY_JAPAN26: | ||
| 428 | case CTRY_JAPAN27: | ||
| 429 | case CTRY_JAPAN28: | ||
| 430 | case CTRY_JAPAN29: | ||
| 431 | case CTRY_JAPAN30: | ||
| 432 | case CTRY_JAPAN31: | ||
| 433 | case CTRY_JAPAN32: | ||
| 434 | case CTRY_JAPAN33: | ||
| 435 | case CTRY_JAPAN34: | ||
| 436 | case CTRY_JAPAN35: | ||
| 437 | case CTRY_JAPAN36: | ||
| 438 | case CTRY_JAPAN37: | ||
| 439 | case CTRY_JAPAN38: | ||
| 440 | case CTRY_JAPAN39: | ||
| 441 | case CTRY_JAPAN40: | ||
| 442 | case CTRY_JAPAN41: | ||
| 443 | case CTRY_JAPAN42: | ||
| 444 | case CTRY_JAPAN43: | ||
| 445 | case CTRY_JAPAN44: | ||
| 446 | case CTRY_JAPAN45: | ||
| 447 | case CTRY_JAPAN46: | ||
| 448 | case CTRY_JAPAN47: | ||
| 449 | case CTRY_JAPAN48: | ||
| 450 | case CTRY_JAPAN49: | ||
| 451 | case CTRY_JAPAN50: | ||
| 452 | case CTRY_JAPAN51: | ||
| 453 | case CTRY_JAPAN52: | ||
| 454 | case CTRY_JAPAN53: | ||
| 455 | case CTRY_JAPAN54: | ||
| 456 | case CTRY_JAPAN55: | ||
| 457 | case CTRY_JAPAN56: | ||
| 458 | case CTRY_JAPAN57: | ||
| 459 | case CTRY_JAPAN58: | ||
| 460 | case CTRY_JAPAN59: | ||
| 461 | return false; | ||
| 462 | } | ||
| 463 | |||
| 464 | return true; | ||
| 465 | } | ||
| 466 | |||
| 467 | static void ath_reg_dyn_country_user(struct wiphy *wiphy, | ||
| 468 | struct ath_regulatory *reg, | ||
| 469 | struct regulatory_request *request) | ||
| 470 | { | ||
| 471 | if (!config_enabled(CONFIG_ATH_REG_DYNAMIC_USER_REG_HINTS)) | ||
| 472 | return; | ||
| 473 | if (!dynamic_country_user_possible(reg)) | ||
| 474 | return; | ||
| 475 | ath_reg_dyn_country(wiphy, reg, request); | ||
| 476 | } | ||
| 477 | |||
| 359 | void ath_reg_notifier_apply(struct wiphy *wiphy, | 478 | void ath_reg_notifier_apply(struct wiphy *wiphy, |
| 360 | struct regulatory_request *request, | 479 | struct regulatory_request *request, |
| 361 | struct ath_regulatory *reg) | 480 | struct ath_regulatory *reg) |
| 362 | { | 481 | { |
| 363 | struct ath_common *common = container_of(reg, struct ath_common, | 482 | struct ath_common *common = container_of(reg, struct ath_common, |
| 364 | regulatory); | 483 | regulatory); |
| 365 | u16 country_code; | ||
| 366 | |||
| 367 | /* We always apply this */ | 484 | /* We always apply this */ |
| 368 | ath_reg_apply_radar_flags(wiphy); | 485 | ath_reg_apply_radar_flags(wiphy); |
| 369 | 486 | ||
| @@ -388,25 +505,12 @@ void ath_reg_notifier_apply(struct wiphy *wiphy, | |||
| 388 | sizeof(struct ath_regulatory)); | 505 | sizeof(struct ath_regulatory)); |
| 389 | break; | 506 | break; |
| 390 | case NL80211_REGDOM_SET_BY_DRIVER: | 507 | case NL80211_REGDOM_SET_BY_DRIVER: |
| 508 | break; | ||
| 391 | case NL80211_REGDOM_SET_BY_USER: | 509 | case NL80211_REGDOM_SET_BY_USER: |
| 510 | ath_reg_dyn_country_user(wiphy, reg, request); | ||
| 392 | break; | 511 | break; |
| 393 | case NL80211_REGDOM_SET_BY_COUNTRY_IE: | 512 | case NL80211_REGDOM_SET_BY_COUNTRY_IE: |
| 394 | if (!ath_is_world_regd(reg)) | 513 | ath_reg_dyn_country(wiphy, reg, request); |
| 395 | break; | ||
| 396 | |||
| 397 | country_code = ath_regd_find_country_by_name(request->alpha2); | ||
| 398 | if (country_code == (u16) -1) | ||
| 399 | break; | ||
| 400 | |||
| 401 | reg->current_rd = COUNTRY_ERD_FLAG; | ||
| 402 | reg->current_rd |= country_code; | ||
| 403 | |||
| 404 | printk(KERN_DEBUG "ath: regdomain 0x%0x updated by CountryIE\n", | ||
| 405 | reg->current_rd); | ||
| 406 | __ath_regd_init(reg); | ||
| 407 | |||
| 408 | ath_reg_apply_world_flags(wiphy, request->initiator, reg); | ||
| 409 | |||
| 410 | break; | 514 | break; |
| 411 | } | 515 | } |
| 412 | } | 516 | } |
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index a55ae6494c3b..0d950f209dae 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c | |||
| @@ -3212,7 +3212,7 @@ static void associate(struct atmel_private *priv, u16 frame_len, u16 subtype) | |||
| 3212 | if (subtype == IEEE80211_STYPE_REASSOC_RESP && | 3212 | if (subtype == IEEE80211_STYPE_REASSOC_RESP && |
| 3213 | status != WLAN_STATUS_ASSOC_DENIED_RATES && | 3213 | status != WLAN_STATUS_ASSOC_DENIED_RATES && |
| 3214 | status != WLAN_STATUS_CAPS_UNSUPPORTED && | 3214 | status != WLAN_STATUS_CAPS_UNSUPPORTED && |
| 3215 | priv->AssociationRequestRetryCnt < MAX_ASSOCIATION_RETRIES) { | 3215 | priv->ReAssociationRequestRetryCnt < MAX_ASSOCIATION_RETRIES) { |
| 3216 | mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES); | 3216 | mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES); |
| 3217 | priv->ReAssociationRequestRetryCnt++; | 3217 | priv->ReAssociationRequestRetryCnt++; |
| 3218 | send_association_request(priv, 1); | 3218 | send_association_request(priv, 1); |
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 7c970d3ae358..05ee7f10cc8f 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c | |||
| @@ -164,7 +164,8 @@ static void b43_nphy_rf_ctl_override_rev7(struct b43_wldev *dev, u16 field, | |||
| 164 | } | 164 | } |
| 165 | en_addr = en_addrs[override][i]; | 165 | en_addr = en_addrs[override][i]; |
| 166 | 166 | ||
| 167 | val_addr = (i == 0) ? e->val_addr_core0 : e->val_addr_core1; | 167 | if (e) |
| 168 | val_addr = (i == 0) ? e->val_addr_core0 : e->val_addr_core1; | ||
| 168 | 169 | ||
| 169 | if (off) { | 170 | if (off) { |
| 170 | b43_phy_mask(dev, en_addr, ~en_mask); | 171 | b43_phy_mask(dev, en_addr, ~en_mask); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index e13b1a65c65f..3e10b801eee8 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | |||
| @@ -26,7 +26,6 @@ | |||
| 26 | #include <linux/mmc/sdio.h> | 26 | #include <linux/mmc/sdio.h> |
| 27 | #include <linux/mmc/sdio_func.h> | 27 | #include <linux/mmc/sdio_func.h> |
| 28 | #include <linux/mmc/card.h> | 28 | #include <linux/mmc/card.h> |
| 29 | #include <linux/mmc/host.h> | ||
| 30 | #include <linux/platform_data/brcmfmac-sdio.h> | 29 | #include <linux/platform_data/brcmfmac-sdio.h> |
| 31 | 30 | ||
| 32 | #include <defs.h> | 31 | #include <defs.h> |
| @@ -239,7 +238,9 @@ brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, | |||
| 239 | func_num = SDIO_FUNC_1; | 238 | func_num = SDIO_FUNC_1; |
| 240 | reg_size = 4; | 239 | reg_size = 4; |
| 241 | 240 | ||
| 242 | brcmf_sdio_addrprep(sdiodev, reg_size, &addr); | 241 | ret = brcmf_sdio_addrprep(sdiodev, reg_size, &addr); |
| 242 | if (ret) | ||
| 243 | goto done; | ||
| 243 | } | 244 | } |
| 244 | 245 | ||
| 245 | do { | 246 | do { |
| @@ -255,6 +256,7 @@ brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, | |||
| 255 | func_num, addr, data, 4); | 256 | func_num, addr, data, 4); |
| 256 | } while (ret != 0 && retry++ < SDIOH_API_ACCESS_RETRY_LIMIT); | 257 | } while (ret != 0 && retry++ < SDIOH_API_ACCESS_RETRY_LIMIT); |
| 257 | 258 | ||
| 259 | done: | ||
| 258 | if (ret != 0) | 260 | if (ret != 0) |
| 259 | brcmf_err("failed with %d\n", ret); | 261 | brcmf_err("failed with %d\n", ret); |
| 260 | 262 | ||
| @@ -315,8 +317,36 @@ void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr, | |||
| 315 | *ret = retval; | 317 | *ret = retval; |
| 316 | } | 318 | } |
| 317 | 319 | ||
| 320 | static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, | ||
| 321 | bool write, u32 addr, struct sk_buff *pkt) | ||
| 322 | { | ||
| 323 | unsigned int req_sz; | ||
| 324 | |||
| 325 | brcmf_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait); | ||
| 326 | if (brcmf_pm_resume_error(sdiodev)) | ||
| 327 | return -EIO; | ||
| 328 | |||
| 329 | /* Single skb use the standard mmc interface */ | ||
| 330 | req_sz = pkt->len + 3; | ||
| 331 | req_sz &= (uint)~3; | ||
| 332 | |||
| 333 | if (write) | ||
| 334 | return sdio_memcpy_toio(sdiodev->func[fn], addr, | ||
| 335 | ((u8 *)(pkt->data)), | ||
| 336 | req_sz); | ||
| 337 | else if (fn == 1) | ||
| 338 | return sdio_memcpy_fromio(sdiodev->func[fn], | ||
| 339 | ((u8 *)(pkt->data)), | ||
| 340 | addr, req_sz); | ||
| 341 | else | ||
| 342 | /* function 2 read is FIFO operation */ | ||
| 343 | return sdio_readsb(sdiodev->func[fn], | ||
| 344 | ((u8 *)(pkt->data)), addr, | ||
| 345 | req_sz); | ||
| 346 | } | ||
| 347 | |||
| 318 | /** | 348 | /** |
| 319 | * brcmf_sdio_buffrw - SDIO interface function for block data access | 349 | * brcmf_sdio_sglist_rw - SDIO interface function for block data access |
| 320 | * @sdiodev: brcmfmac sdio device | 350 | * @sdiodev: brcmfmac sdio device |
| 321 | * @fn: SDIO function number | 351 | * @fn: SDIO function number |
| 322 | * @write: direction flag | 352 | * @write: direction flag |
| @@ -327,12 +357,13 @@ void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr, | |||
| 327 | * stack for block data access. It assumes that the skb passed down by the | 357 | * stack for block data access. It assumes that the skb passed down by the |
| 328 | * caller has already been padded and aligned. | 358 | * caller has already been padded and aligned. |
| 329 | */ | 359 | */ |
| 330 | static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, | 360 | static int brcmf_sdio_sglist_rw(struct brcmf_sdio_dev *sdiodev, uint fn, |
| 331 | bool write, u32 addr, struct sk_buff_head *pktlist) | 361 | bool write, u32 addr, |
| 362 | struct sk_buff_head *pktlist) | ||
| 332 | { | 363 | { |
| 333 | unsigned int req_sz, func_blk_sz, sg_cnt, sg_data_sz, pkt_offset; | 364 | unsigned int req_sz, func_blk_sz, sg_cnt, sg_data_sz, pkt_offset; |
| 334 | unsigned int max_blks, max_req_sz, orig_offset, dst_offset; | 365 | unsigned int max_req_sz, orig_offset, dst_offset; |
| 335 | unsigned short max_seg_sz, seg_sz; | 366 | unsigned short max_seg_cnt, seg_sz; |
| 336 | unsigned char *pkt_data, *orig_data, *dst_data; | 367 | unsigned char *pkt_data, *orig_data, *dst_data; |
| 337 | struct sk_buff *pkt_next = NULL, *local_pkt_next; | 368 | struct sk_buff *pkt_next = NULL, *local_pkt_next; |
| 338 | struct sk_buff_head local_list, *target_list; | 369 | struct sk_buff_head local_list, *target_list; |
| @@ -341,7 +372,6 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, | |||
| 341 | struct mmc_data mmc_dat; | 372 | struct mmc_data mmc_dat; |
| 342 | struct sg_table st; | 373 | struct sg_table st; |
| 343 | struct scatterlist *sgl; | 374 | struct scatterlist *sgl; |
| 344 | struct mmc_host *host; | ||
| 345 | int ret = 0; | 375 | int ret = 0; |
| 346 | 376 | ||
| 347 | if (!pktlist->qlen) | 377 | if (!pktlist->qlen) |
| @@ -351,27 +381,6 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, | |||
| 351 | if (brcmf_pm_resume_error(sdiodev)) | 381 | if (brcmf_pm_resume_error(sdiodev)) |
| 352 | return -EIO; | 382 | return -EIO; |
| 353 | 383 | ||
| 354 | /* Single skb use the standard mmc interface */ | ||
| 355 | if (pktlist->qlen == 1) { | ||
| 356 | pkt_next = pktlist->next; | ||
| 357 | req_sz = pkt_next->len + 3; | ||
| 358 | req_sz &= (uint)~3; | ||
| 359 | |||
| 360 | if (write) | ||
| 361 | return sdio_memcpy_toio(sdiodev->func[fn], addr, | ||
| 362 | ((u8 *)(pkt_next->data)), | ||
| 363 | req_sz); | ||
| 364 | else if (fn == 1) | ||
| 365 | return sdio_memcpy_fromio(sdiodev->func[fn], | ||
| 366 | ((u8 *)(pkt_next->data)), | ||
| 367 | addr, req_sz); | ||
| 368 | else | ||
| 369 | /* function 2 read is FIFO operation */ | ||
| 370 | return sdio_readsb(sdiodev->func[fn], | ||
| 371 | ((u8 *)(pkt_next->data)), addr, | ||
| 372 | req_sz); | ||
| 373 | } | ||
| 374 | |||
| 375 | target_list = pktlist; | 384 | target_list = pktlist; |
| 376 | /* for host with broken sg support, prepare a page aligned list */ | 385 | /* for host with broken sg support, prepare a page aligned list */ |
| 377 | __skb_queue_head_init(&local_list); | 386 | __skb_queue_head_init(&local_list); |
| @@ -398,38 +407,46 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, | |||
| 398 | target_list = &local_list; | 407 | target_list = &local_list; |
| 399 | } | 408 | } |
| 400 | 409 | ||
| 401 | host = sdiodev->func[fn]->card->host; | ||
| 402 | func_blk_sz = sdiodev->func[fn]->cur_blksize; | 410 | func_blk_sz = sdiodev->func[fn]->cur_blksize; |
| 403 | /* Blocks per command is limited by host count, host transfer | 411 | max_req_sz = sdiodev->max_request_size; |
| 404 | * size and the maximum for IO_RW_EXTENDED of 511 blocks. | 412 | max_seg_cnt = min_t(unsigned short, sdiodev->max_segment_count, |
| 405 | */ | 413 | target_list->qlen); |
| 406 | max_blks = min_t(unsigned int, host->max_blk_count, 511u); | ||
| 407 | max_req_sz = min_t(unsigned int, host->max_req_size, | ||
| 408 | max_blks * func_blk_sz); | ||
| 409 | max_seg_sz = min_t(unsigned short, host->max_segs, SG_MAX_SINGLE_ALLOC); | ||
| 410 | max_seg_sz = min_t(unsigned short, max_seg_sz, target_list->qlen); | ||
| 411 | seg_sz = target_list->qlen; | 414 | seg_sz = target_list->qlen; |
| 412 | pkt_offset = 0; | 415 | pkt_offset = 0; |
| 413 | pkt_next = target_list->next; | 416 | pkt_next = target_list->next; |
| 414 | 417 | ||
| 415 | if (sg_alloc_table(&st, max_seg_sz, GFP_KERNEL)) { | 418 | if (sg_alloc_table(&st, max_seg_cnt, GFP_KERNEL)) { |
| 416 | ret = -ENOMEM; | 419 | ret = -ENOMEM; |
| 417 | goto exit; | 420 | goto exit; |
| 418 | } | 421 | } |
| 419 | 422 | ||
| 423 | memset(&mmc_req, 0, sizeof(struct mmc_request)); | ||
| 424 | memset(&mmc_cmd, 0, sizeof(struct mmc_command)); | ||
| 425 | memset(&mmc_dat, 0, sizeof(struct mmc_data)); | ||
| 426 | |||
| 427 | mmc_dat.sg = st.sgl; | ||
| 428 | mmc_dat.blksz = func_blk_sz; | ||
| 429 | mmc_dat.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ; | ||
| 430 | mmc_cmd.opcode = SD_IO_RW_EXTENDED; | ||
| 431 | mmc_cmd.arg = write ? 1<<31 : 0; /* write flag */ | ||
| 432 | mmc_cmd.arg |= (fn & 0x7) << 28; /* SDIO func num */ | ||
| 433 | mmc_cmd.arg |= 1<<27; /* block mode */ | ||
| 434 | /* for function 1 the addr will be incremented */ | ||
| 435 | mmc_cmd.arg |= (fn == 1) ? 1<<26 : 0; | ||
| 436 | mmc_cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC; | ||
| 437 | mmc_req.cmd = &mmc_cmd; | ||
| 438 | mmc_req.data = &mmc_dat; | ||
| 439 | |||
| 420 | while (seg_sz) { | 440 | while (seg_sz) { |
| 421 | req_sz = 0; | 441 | req_sz = 0; |
| 422 | sg_cnt = 0; | 442 | sg_cnt = 0; |
| 423 | memset(&mmc_req, 0, sizeof(struct mmc_request)); | ||
| 424 | memset(&mmc_cmd, 0, sizeof(struct mmc_command)); | ||
| 425 | memset(&mmc_dat, 0, sizeof(struct mmc_data)); | ||
| 426 | sgl = st.sgl; | 443 | sgl = st.sgl; |
| 427 | /* prep sg table */ | 444 | /* prep sg table */ |
| 428 | while (pkt_next != (struct sk_buff *)target_list) { | 445 | while (pkt_next != (struct sk_buff *)target_list) { |
| 429 | pkt_data = pkt_next->data + pkt_offset; | 446 | pkt_data = pkt_next->data + pkt_offset; |
| 430 | sg_data_sz = pkt_next->len - pkt_offset; | 447 | sg_data_sz = pkt_next->len - pkt_offset; |
| 431 | if (sg_data_sz > host->max_seg_size) | 448 | if (sg_data_sz > sdiodev->max_segment_size) |
| 432 | sg_data_sz = host->max_seg_size; | 449 | sg_data_sz = sdiodev->max_segment_size; |
| 433 | if (sg_data_sz > max_req_sz - req_sz) | 450 | if (sg_data_sz > max_req_sz - req_sz) |
| 434 | sg_data_sz = max_req_sz - req_sz; | 451 | sg_data_sz = max_req_sz - req_sz; |
| 435 | 452 | ||
| @@ -444,7 +461,7 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, | |||
| 444 | pkt_next = pkt_next->next; | 461 | pkt_next = pkt_next->next; |
| 445 | } | 462 | } |
| 446 | 463 | ||
| 447 | if (req_sz >= max_req_sz || sg_cnt >= max_seg_sz) | 464 | if (req_sz >= max_req_sz || sg_cnt >= max_seg_cnt) |
| 448 | break; | 465 | break; |
| 449 | } | 466 | } |
| 450 | seg_sz -= sg_cnt; | 467 | seg_sz -= sg_cnt; |
| @@ -455,27 +472,17 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, | |||
| 455 | ret = -ENOTBLK; | 472 | ret = -ENOTBLK; |
| 456 | goto exit; | 473 | goto exit; |
| 457 | } | 474 | } |
| 458 | mmc_dat.sg = st.sgl; | 475 | |
| 459 | mmc_dat.sg_len = sg_cnt; | 476 | mmc_dat.sg_len = sg_cnt; |
| 460 | mmc_dat.blksz = func_blk_sz; | ||
| 461 | mmc_dat.blocks = req_sz / func_blk_sz; | 477 | mmc_dat.blocks = req_sz / func_blk_sz; |
| 462 | mmc_dat.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ; | ||
| 463 | mmc_cmd.opcode = SD_IO_RW_EXTENDED; | ||
| 464 | mmc_cmd.arg = write ? 1<<31 : 0; /* write flag */ | ||
| 465 | mmc_cmd.arg |= (fn & 0x7) << 28; /* SDIO func num */ | ||
| 466 | mmc_cmd.arg |= 1<<27; /* block mode */ | ||
| 467 | /* incrementing addr for function 1 */ | ||
| 468 | mmc_cmd.arg |= (fn == 1) ? 1<<26 : 0; | ||
| 469 | mmc_cmd.arg |= (addr & 0x1FFFF) << 9; /* address */ | 478 | mmc_cmd.arg |= (addr & 0x1FFFF) << 9; /* address */ |
| 470 | mmc_cmd.arg |= mmc_dat.blocks & 0x1FF; /* block count */ | 479 | mmc_cmd.arg |= mmc_dat.blocks & 0x1FF; /* block count */ |
| 471 | mmc_cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC; | 480 | /* incrementing addr for function 1 */ |
| 472 | mmc_req.cmd = &mmc_cmd; | ||
| 473 | mmc_req.data = &mmc_dat; | ||
| 474 | if (fn == 1) | 481 | if (fn == 1) |
| 475 | addr += req_sz; | 482 | addr += req_sz; |
| 476 | 483 | ||
| 477 | mmc_set_data_timeout(&mmc_dat, sdiodev->func[fn]->card); | 484 | mmc_set_data_timeout(&mmc_dat, sdiodev->func[fn]->card); |
| 478 | mmc_wait_for_req(host, &mmc_req); | 485 | mmc_wait_for_req(sdiodev->func[fn]->card->host, &mmc_req); |
| 479 | 486 | ||
| 480 | ret = mmc_cmd.error ? mmc_cmd.error : mmc_dat.error; | 487 | ret = mmc_cmd.error ? mmc_cmd.error : mmc_dat.error; |
| 481 | if (ret != 0) { | 488 | if (ret != 0) { |
| @@ -546,7 +553,6 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | |||
| 546 | { | 553 | { |
| 547 | uint width; | 554 | uint width; |
| 548 | int err = 0; | 555 | int err = 0; |
| 549 | struct sk_buff_head pkt_list; | ||
| 550 | 556 | ||
| 551 | brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n", | 557 | brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n", |
| 552 | fn, addr, pkt->len); | 558 | fn, addr, pkt->len); |
| @@ -556,19 +562,17 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | |||
| 556 | if (err) | 562 | if (err) |
| 557 | goto done; | 563 | goto done; |
| 558 | 564 | ||
| 559 | skb_queue_head_init(&pkt_list); | 565 | err = brcmf_sdio_buffrw(sdiodev, fn, false, addr, pkt); |
| 560 | skb_queue_tail(&pkt_list, pkt); | ||
| 561 | err = brcmf_sdio_buffrw(sdiodev, fn, false, addr, &pkt_list); | ||
| 562 | skb_dequeue_tail(&pkt_list); | ||
| 563 | 566 | ||
| 564 | done: | 567 | done: |
| 565 | return err; | 568 | return err; |
| 566 | } | 569 | } |
| 567 | 570 | ||
| 568 | int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | 571 | int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, |
| 569 | uint flags, struct sk_buff_head *pktq) | 572 | uint flags, struct sk_buff_head *pktq, uint totlen) |
| 570 | { | 573 | { |
| 571 | uint incr_fix; | 574 | struct sk_buff *glom_skb; |
| 575 | struct sk_buff *skb; | ||
| 572 | uint width; | 576 | uint width; |
| 573 | int err = 0; | 577 | int err = 0; |
| 574 | 578 | ||
| @@ -580,8 +584,22 @@ int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | |||
| 580 | if (err) | 584 | if (err) |
| 581 | goto done; | 585 | goto done; |
| 582 | 586 | ||
| 583 | incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC; | 587 | if (pktq->qlen == 1) |
| 584 | err = brcmf_sdio_buffrw(sdiodev, fn, false, addr, pktq); | 588 | err = brcmf_sdio_buffrw(sdiodev, fn, false, addr, pktq->next); |
| 589 | else if (!sdiodev->sg_support) { | ||
| 590 | glom_skb = brcmu_pkt_buf_get_skb(totlen); | ||
| 591 | if (!glom_skb) | ||
| 592 | return -ENOMEM; | ||
| 593 | err = brcmf_sdio_buffrw(sdiodev, fn, false, addr, glom_skb); | ||
| 594 | if (err) | ||
| 595 | goto done; | ||
| 596 | |||
| 597 | skb_queue_walk(pktq, skb) { | ||
| 598 | memcpy(skb->data, glom_skb->data, skb->len); | ||
| 599 | skb_pull(glom_skb, skb->len); | ||
| 600 | } | ||
| 601 | } else | ||
| 602 | err = brcmf_sdio_sglist_rw(sdiodev, fn, false, addr, pktq); | ||
| 585 | 603 | ||
| 586 | done: | 604 | done: |
| 587 | return err; | 605 | return err; |
| @@ -592,7 +610,7 @@ brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | |||
| 592 | uint flags, u8 *buf, uint nbytes) | 610 | uint flags, u8 *buf, uint nbytes) |
| 593 | { | 611 | { |
| 594 | struct sk_buff *mypkt; | 612 | struct sk_buff *mypkt; |
| 595 | struct sk_buff_head pktq; | 613 | uint width; |
| 596 | int err; | 614 | int err; |
| 597 | 615 | ||
| 598 | mypkt = brcmu_pkt_buf_get_skb(nbytes); | 616 | mypkt = brcmu_pkt_buf_get_skb(nbytes); |
| @@ -603,10 +621,12 @@ brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | |||
| 603 | } | 621 | } |
| 604 | 622 | ||
| 605 | memcpy(mypkt->data, buf, nbytes); | 623 | memcpy(mypkt->data, buf, nbytes); |
| 606 | __skb_queue_head_init(&pktq); | 624 | |
| 607 | __skb_queue_tail(&pktq, mypkt); | 625 | width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; |
| 608 | err = brcmf_sdcard_send_pkt(sdiodev, addr, fn, flags, &pktq); | 626 | err = brcmf_sdio_addrprep(sdiodev, width, &addr); |
| 609 | __skb_dequeue_tail(&pktq); | 627 | |
| 628 | if (!err) | ||
| 629 | err = brcmf_sdio_buffrw(sdiodev, fn, true, addr, mypkt); | ||
| 610 | 630 | ||
| 611 | brcmu_pkt_buf_free_skb(mypkt); | 631 | brcmu_pkt_buf_free_skb(mypkt); |
| 612 | return err; | 632 | return err; |
| @@ -617,16 +637,26 @@ int | |||
| 617 | brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | 637 | brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, |
| 618 | uint flags, struct sk_buff_head *pktq) | 638 | uint flags, struct sk_buff_head *pktq) |
| 619 | { | 639 | { |
| 640 | struct sk_buff *skb; | ||
| 620 | uint width; | 641 | uint width; |
| 621 | int err = 0; | 642 | int err; |
| 622 | 643 | ||
| 623 | brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n", | 644 | brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n", |
| 624 | fn, addr, pktq->qlen); | 645 | fn, addr, pktq->qlen); |
| 625 | 646 | ||
| 626 | width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; | 647 | width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; |
| 627 | brcmf_sdio_addrprep(sdiodev, width, &addr); | 648 | err = brcmf_sdio_addrprep(sdiodev, width, &addr); |
| 649 | if (err) | ||
| 650 | return err; | ||
| 628 | 651 | ||
| 629 | err = brcmf_sdio_buffrw(sdiodev, fn, true, addr, pktq); | 652 | if (pktq->qlen == 1 || !sdiodev->sg_support) |
| 653 | skb_queue_walk(pktq, skb) { | ||
| 654 | err = brcmf_sdio_buffrw(sdiodev, fn, true, addr, skb); | ||
| 655 | if (err) | ||
| 656 | break; | ||
| 657 | } | ||
| 658 | else | ||
| 659 | err = brcmf_sdio_sglist_rw(sdiodev, fn, true, addr, pktq); | ||
| 630 | 660 | ||
| 631 | return err; | 661 | return err; |
| 632 | } | 662 | } |
| @@ -639,7 +669,6 @@ brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address, | |||
| 639 | struct sk_buff *pkt; | 669 | struct sk_buff *pkt; |
| 640 | u32 sdaddr; | 670 | u32 sdaddr; |
| 641 | uint dsize; | 671 | uint dsize; |
| 642 | struct sk_buff_head pkt_list; | ||
| 643 | 672 | ||
| 644 | dsize = min_t(uint, SBSDIO_SB_OFT_ADDR_LIMIT, size); | 673 | dsize = min_t(uint, SBSDIO_SB_OFT_ADDR_LIMIT, size); |
| 645 | pkt = dev_alloc_skb(dsize); | 674 | pkt = dev_alloc_skb(dsize); |
| @@ -648,7 +677,6 @@ brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address, | |||
| 648 | return -EIO; | 677 | return -EIO; |
| 649 | } | 678 | } |
| 650 | pkt->priority = 0; | 679 | pkt->priority = 0; |
| 651 | skb_queue_head_init(&pkt_list); | ||
| 652 | 680 | ||
| 653 | /* Determine initial transfer parameters */ | 681 | /* Determine initial transfer parameters */ |
| 654 | sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK; | 682 | sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK; |
| @@ -676,10 +704,8 @@ brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address, | |||
| 676 | skb_put(pkt, dsize); | 704 | skb_put(pkt, dsize); |
| 677 | if (write) | 705 | if (write) |
| 678 | memcpy(pkt->data, data, dsize); | 706 | memcpy(pkt->data, data, dsize); |
| 679 | skb_queue_tail(&pkt_list, pkt); | ||
| 680 | bcmerror = brcmf_sdio_buffrw(sdiodev, SDIO_FUNC_1, write, | 707 | bcmerror = brcmf_sdio_buffrw(sdiodev, SDIO_FUNC_1, write, |
| 681 | sdaddr, &pkt_list); | 708 | sdaddr, pkt); |
| 682 | skb_dequeue_tail(&pkt_list); | ||
| 683 | if (bcmerror) { | 709 | if (bcmerror) { |
| 684 | brcmf_err("membytes transfer failed\n"); | 710 | brcmf_err("membytes transfer failed\n"); |
| 685 | break; | 711 | break; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c index 2a23bf2b904d..905704e335d7 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/mmc/sdio_func.h> | 21 | #include <linux/mmc/sdio_func.h> |
| 22 | #include <linux/mmc/sdio_ids.h> | 22 | #include <linux/mmc/sdio_ids.h> |
| 23 | #include <linux/mmc/card.h> | 23 | #include <linux/mmc/card.h> |
| 24 | #include <linux/mmc/host.h> | ||
| 24 | #include <linux/suspend.h> | 25 | #include <linux/suspend.h> |
| 25 | #include <linux/errno.h> | 26 | #include <linux/errno.h> |
| 26 | #include <linux/sched.h> /* request_irq() */ | 27 | #include <linux/sched.h> /* request_irq() */ |
| @@ -315,6 +316,8 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, | |||
| 315 | int err; | 316 | int err; |
| 316 | struct brcmf_sdio_dev *sdiodev; | 317 | struct brcmf_sdio_dev *sdiodev; |
| 317 | struct brcmf_bus *bus_if; | 318 | struct brcmf_bus *bus_if; |
| 319 | struct mmc_host *host; | ||
| 320 | uint max_blocks; | ||
| 318 | 321 | ||
| 319 | brcmf_dbg(SDIO, "Enter\n"); | 322 | brcmf_dbg(SDIO, "Enter\n"); |
| 320 | brcmf_dbg(SDIO, "Class=%x\n", func->class); | 323 | brcmf_dbg(SDIO, "Class=%x\n", func->class); |
| @@ -361,6 +364,20 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, | |||
| 361 | brcmf_err("F2 error, probe failed %d...\n", err); | 364 | brcmf_err("F2 error, probe failed %d...\n", err); |
| 362 | goto fail; | 365 | goto fail; |
| 363 | } | 366 | } |
| 367 | |||
| 368 | /* | ||
| 369 | * determine host related variables after brcmf_sdio_probe() | ||
| 370 | * as func->cur_blksize is properly set and F2 init has been | ||
| 371 | * completed successfully. | ||
| 372 | */ | ||
| 373 | host = func->card->host; | ||
| 374 | sdiodev->sg_support = host->max_segs > 1; | ||
| 375 | max_blocks = min_t(uint, host->max_blk_count, 511u); | ||
| 376 | sdiodev->max_request_size = min_t(uint, host->max_req_size, | ||
| 377 | max_blocks * func->cur_blksize); | ||
| 378 | sdiodev->max_segment_count = min_t(uint, host->max_segs, | ||
| 379 | SG_MAX_SINGLE_ALLOC); | ||
| 380 | sdiodev->max_segment_size = host->max_seg_size; | ||
| 364 | brcmf_dbg(SDIO, "F2 init completed...\n"); | 381 | brcmf_dbg(SDIO, "F2 init completed...\n"); |
| 365 | return 0; | 382 | return 0; |
| 366 | 383 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index 67f05db4b9b8..b02953c4ade7 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | |||
| @@ -1147,6 +1147,8 @@ static int brcmf_sdio_hdparse(struct brcmf_sdio *bus, u8 *header, | |||
| 1147 | u8 rx_seq, fc, tx_seq_max; | 1147 | u8 rx_seq, fc, tx_seq_max; |
| 1148 | u32 swheader; | 1148 | u32 swheader; |
| 1149 | 1149 | ||
| 1150 | trace_brcmf_sdpcm_hdr(false, header); | ||
| 1151 | |||
| 1150 | /* hw header */ | 1152 | /* hw header */ |
| 1151 | len = get_unaligned_le16(header); | 1153 | len = get_unaligned_le16(header); |
| 1152 | checksum = get_unaligned_le16(header + sizeof(u16)); | 1154 | checksum = get_unaligned_le16(header + sizeof(u16)); |
| @@ -1269,6 +1271,7 @@ static void brcmf_sdio_hdpack(struct brcmf_sdio *bus, u8 *header, | |||
| 1269 | SDPCM_DOFFSET_MASK; | 1271 | SDPCM_DOFFSET_MASK; |
| 1270 | *(((__le32 *)header) + 1) = cpu_to_le32(sw_header); | 1272 | *(((__le32 *)header) + 1) = cpu_to_le32(sw_header); |
| 1271 | *(((__le32 *)header) + 2) = 0; | 1273 | *(((__le32 *)header) + 2) = 0; |
| 1274 | trace_brcmf_sdpcm_hdr(true, header); | ||
| 1272 | } | 1275 | } |
| 1273 | 1276 | ||
| 1274 | static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | 1277 | static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) |
| @@ -1389,7 +1392,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
| 1389 | sdio_claim_host(bus->sdiodev->func[1]); | 1392 | sdio_claim_host(bus->sdiodev->func[1]); |
| 1390 | errcode = brcmf_sdcard_recv_chain(bus->sdiodev, | 1393 | errcode = brcmf_sdcard_recv_chain(bus->sdiodev, |
| 1391 | bus->sdiodev->sbwad, | 1394 | bus->sdiodev->sbwad, |
| 1392 | SDIO_FUNC_2, F2SYNC, &bus->glom); | 1395 | SDIO_FUNC_2, F2SYNC, &bus->glom, dlen); |
| 1393 | sdio_release_host(bus->sdiodev->func[1]); | 1396 | sdio_release_host(bus->sdiodev->func[1]); |
| 1394 | bus->sdcnt.f2rxdata++; | 1397 | bus->sdcnt.f2rxdata++; |
| 1395 | 1398 | ||
| @@ -1877,6 +1880,56 @@ brcmf_sdbrcm_wait_event_wakeup(struct brcmf_sdio *bus) | |||
| 1877 | /* bit mask of data length chopped from the previous packet */ | 1880 | /* bit mask of data length chopped from the previous packet */ |
| 1878 | #define ALIGN_SKB_CHOP_LEN_MASK 0x7fff | 1881 | #define ALIGN_SKB_CHOP_LEN_MASK 0x7fff |
| 1879 | 1882 | ||
| 1883 | static int brcmf_sdio_txpkt_prep_sg(struct brcmf_sdio_dev *sdiodev, | ||
| 1884 | struct sk_buff_head *pktq, | ||
| 1885 | struct sk_buff *pkt, uint chan) | ||
| 1886 | { | ||
| 1887 | struct sk_buff *pkt_pad; | ||
| 1888 | u16 tail_pad, tail_chop, sg_align; | ||
| 1889 | unsigned int blksize; | ||
| 1890 | u8 *dat_buf; | ||
| 1891 | int ntail; | ||
| 1892 | |||
| 1893 | blksize = sdiodev->func[SDIO_FUNC_2]->cur_blksize; | ||
| 1894 | sg_align = 4; | ||
| 1895 | if (sdiodev->pdata && sdiodev->pdata->sd_sgentry_align > 4) | ||
| 1896 | sg_align = sdiodev->pdata->sd_sgentry_align; | ||
| 1897 | /* sg entry alignment should be a divisor of block size */ | ||
| 1898 | WARN_ON(blksize % sg_align); | ||
| 1899 | |||
| 1900 | /* Check tail padding */ | ||
| 1901 | pkt_pad = NULL; | ||
| 1902 | tail_chop = pkt->len % sg_align; | ||
| 1903 | tail_pad = sg_align - tail_chop; | ||
| 1904 | tail_pad += blksize - (pkt->len + tail_pad) % blksize; | ||
| 1905 | if (skb_tailroom(pkt) < tail_pad && pkt->len > blksize) { | ||
| 1906 | pkt_pad = brcmu_pkt_buf_get_skb(tail_pad + tail_chop); | ||
| 1907 | if (pkt_pad == NULL) | ||
| 1908 | return -ENOMEM; | ||
| 1909 | memcpy(pkt_pad->data, | ||
| 1910 | pkt->data + pkt->len - tail_chop, | ||
| 1911 | tail_chop); | ||
| 1912 | *(u32 *)(pkt_pad->cb) = ALIGN_SKB_FLAG + tail_chop; | ||
| 1913 | skb_trim(pkt, pkt->len - tail_chop); | ||
| 1914 | __skb_queue_after(pktq, pkt, pkt_pad); | ||
| 1915 | } else { | ||
| 1916 | ntail = pkt->data_len + tail_pad - | ||
| 1917 | (pkt->end - pkt->tail); | ||
| 1918 | if (skb_cloned(pkt) || ntail > 0) | ||
| 1919 | if (pskb_expand_head(pkt, 0, ntail, GFP_ATOMIC)) | ||
| 1920 | return -ENOMEM; | ||
| 1921 | if (skb_linearize(pkt)) | ||
| 1922 | return -ENOMEM; | ||
| 1923 | dat_buf = (u8 *)(pkt->data); | ||
| 1924 | __skb_put(pkt, tail_pad); | ||
| 1925 | } | ||
| 1926 | |||
| 1927 | if (pkt_pad) | ||
| 1928 | return pkt->len + tail_chop; | ||
| 1929 | else | ||
| 1930 | return pkt->len - tail_pad; | ||
| 1931 | } | ||
| 1932 | |||
| 1880 | /** | 1933 | /** |
| 1881 | * brcmf_sdio_txpkt_prep - packet preparation for transmit | 1934 | * brcmf_sdio_txpkt_prep - packet preparation for transmit |
| 1882 | * @bus: brcmf_sdio structure pointer | 1935 | * @bus: brcmf_sdio structure pointer |
| @@ -1893,24 +1946,16 @@ static int | |||
| 1893 | brcmf_sdio_txpkt_prep(struct brcmf_sdio *bus, struct sk_buff_head *pktq, | 1946 | brcmf_sdio_txpkt_prep(struct brcmf_sdio *bus, struct sk_buff_head *pktq, |
| 1894 | uint chan) | 1947 | uint chan) |
| 1895 | { | 1948 | { |
| 1896 | u16 head_pad, tail_pad, tail_chop, head_align, sg_align; | 1949 | u16 head_pad, head_align; |
| 1897 | int ntail; | 1950 | struct sk_buff *pkt_next; |
| 1898 | struct sk_buff *pkt_next, *pkt_new; | ||
| 1899 | u8 *dat_buf; | 1951 | u8 *dat_buf; |
| 1900 | unsigned blksize = bus->sdiodev->func[SDIO_FUNC_2]->cur_blksize; | 1952 | int err; |
| 1901 | struct brcmf_sdio_hdrinfo hd_info = {0}; | 1953 | struct brcmf_sdio_hdrinfo hd_info = {0}; |
| 1902 | 1954 | ||
| 1903 | /* SDIO ADMA requires at least 32 bit alignment */ | 1955 | /* SDIO ADMA requires at least 32 bit alignment */ |
| 1904 | head_align = 4; | 1956 | head_align = 4; |
| 1905 | sg_align = 4; | 1957 | if (bus->sdiodev->pdata && bus->sdiodev->pdata->sd_head_align > 4) |
| 1906 | if (bus->sdiodev->pdata) { | 1958 | head_align = bus->sdiodev->pdata->sd_head_align; |
| 1907 | head_align = bus->sdiodev->pdata->sd_head_align > 4 ? | ||
| 1908 | bus->sdiodev->pdata->sd_head_align : 4; | ||
| 1909 | sg_align = bus->sdiodev->pdata->sd_sgentry_align > 4 ? | ||
| 1910 | bus->sdiodev->pdata->sd_sgentry_align : 4; | ||
| 1911 | } | ||
| 1912 | /* sg entry alignment should be a divisor of block size */ | ||
| 1913 | WARN_ON(blksize % sg_align); | ||
| 1914 | 1959 | ||
| 1915 | pkt_next = pktq->next; | 1960 | pkt_next = pktq->next; |
| 1916 | dat_buf = (u8 *)(pkt_next->data); | 1961 | dat_buf = (u8 *)(pkt_next->data); |
| @@ -1929,40 +1974,20 @@ brcmf_sdio_txpkt_prep(struct brcmf_sdio *bus, struct sk_buff_head *pktq, | |||
| 1929 | memset(dat_buf, 0, head_pad + bus->tx_hdrlen); | 1974 | memset(dat_buf, 0, head_pad + bus->tx_hdrlen); |
| 1930 | } | 1975 | } |
| 1931 | 1976 | ||
| 1932 | /* Check tail padding */ | 1977 | if (bus->sdiodev->sg_support && pktq->qlen > 1) { |
| 1933 | pkt_new = NULL; | 1978 | err = brcmf_sdio_txpkt_prep_sg(bus->sdiodev, pktq, |
| 1934 | tail_chop = pkt_next->len % sg_align; | 1979 | pkt_next, chan); |
| 1935 | tail_pad = sg_align - tail_chop; | 1980 | if (err < 0) |
| 1936 | tail_pad += blksize - (pkt_next->len + tail_pad) % blksize; | 1981 | return err; |
| 1937 | if (skb_tailroom(pkt_next) < tail_pad && pkt_next->len > blksize) { | 1982 | hd_info.len = (u16)err; |
| 1938 | pkt_new = brcmu_pkt_buf_get_skb(tail_pad + tail_chop); | ||
| 1939 | if (pkt_new == NULL) | ||
| 1940 | return -ENOMEM; | ||
| 1941 | memcpy(pkt_new->data, | ||
| 1942 | pkt_next->data + pkt_next->len - tail_chop, | ||
| 1943 | tail_chop); | ||
| 1944 | *(u32 *)(pkt_new->cb) = ALIGN_SKB_FLAG + tail_chop; | ||
| 1945 | skb_trim(pkt_next, pkt_next->len - tail_chop); | ||
| 1946 | __skb_queue_after(pktq, pkt_next, pkt_new); | ||
| 1947 | } else { | 1983 | } else { |
| 1948 | ntail = pkt_next->data_len + tail_pad - | 1984 | hd_info.len = pkt_next->len; |
| 1949 | (pkt_next->end - pkt_next->tail); | ||
| 1950 | if (skb_cloned(pkt_next) || ntail > 0) | ||
| 1951 | if (pskb_expand_head(pkt_next, 0, ntail, GFP_ATOMIC)) | ||
| 1952 | return -ENOMEM; | ||
| 1953 | if (skb_linearize(pkt_next)) | ||
| 1954 | return -ENOMEM; | ||
| 1955 | dat_buf = (u8 *)(pkt_next->data); | ||
| 1956 | __skb_put(pkt_next, tail_pad); | ||
| 1957 | } | 1985 | } |
| 1958 | 1986 | ||
| 1959 | /* Now prep the header */ | ||
| 1960 | if (pkt_new) | ||
| 1961 | hd_info.len = pkt_next->len + tail_chop; | ||
| 1962 | else | ||
| 1963 | hd_info.len = pkt_next->len - tail_pad; | ||
| 1964 | hd_info.channel = chan; | 1987 | hd_info.channel = chan; |
| 1965 | hd_info.dat_offset = head_pad + bus->tx_hdrlen; | 1988 | hd_info.dat_offset = head_pad + bus->tx_hdrlen; |
| 1989 | |||
| 1990 | /* Now fill the header */ | ||
| 1966 | brcmf_sdio_hdpack(bus, dat_buf, &hd_info); | 1991 | brcmf_sdio_hdpack(bus, dat_buf, &hd_info); |
| 1967 | 1992 | ||
| 1968 | if (BRCMF_BYTES_ON() && | 1993 | if (BRCMF_BYTES_ON() && |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h index c9b06b4e71f7..fc0d4f0129db 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h | |||
| @@ -178,6 +178,10 @@ struct brcmf_sdio_dev { | |||
| 178 | bool irq_en; /* irq enable flags */ | 178 | bool irq_en; /* irq enable flags */ |
| 179 | spinlock_t irq_en_lock; | 179 | spinlock_t irq_en_lock; |
| 180 | bool irq_wake; /* irq wake enable flags */ | 180 | bool irq_wake; /* irq wake enable flags */ |
| 181 | bool sg_support; | ||
| 182 | uint max_request_size; | ||
| 183 | ushort max_segment_count; | ||
| 184 | uint max_segment_size; | ||
| 181 | }; | 185 | }; |
| 182 | 186 | ||
| 183 | /* Register/deregister interrupt handler. */ | 187 | /* Register/deregister interrupt handler. */ |
| @@ -216,7 +220,7 @@ int brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | |||
| 216 | int brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | 220 | int brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, |
| 217 | uint flags, u8 *buf, uint nbytes); | 221 | uint flags, u8 *buf, uint nbytes); |
| 218 | int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | 222 | int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, |
| 219 | uint flags, struct sk_buff_head *pktq); | 223 | uint flags, struct sk_buff_head *pktq, uint totlen); |
| 220 | 224 | ||
| 221 | /* Flags bits */ | 225 | /* Flags bits */ |
| 222 | 226 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h index bc2917112899..3c67529b9074 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h | |||
| @@ -78,13 +78,15 @@ TRACE_EVENT(brcmf_hexdump, | |||
| 78 | TP_ARGS(data, len), | 78 | TP_ARGS(data, len), |
| 79 | TP_STRUCT__entry( | 79 | TP_STRUCT__entry( |
| 80 | __field(unsigned long, len) | 80 | __field(unsigned long, len) |
| 81 | __field(unsigned long, addr) | ||
| 81 | __dynamic_array(u8, hdata, len) | 82 | __dynamic_array(u8, hdata, len) |
| 82 | ), | 83 | ), |
| 83 | TP_fast_assign( | 84 | TP_fast_assign( |
| 84 | __entry->len = len; | 85 | __entry->len = len; |
| 86 | __entry->addr = (unsigned long)data; | ||
| 85 | memcpy(__get_dynamic_array(hdata), data, len); | 87 | memcpy(__get_dynamic_array(hdata), data, len); |
| 86 | ), | 88 | ), |
| 87 | TP_printk("hexdump [length=%lu]", __entry->len) | 89 | TP_printk("hexdump [addr=%lx, length=%lu]", __entry->addr, __entry->len) |
| 88 | ); | 90 | ); |
| 89 | 91 | ||
| 90 | TRACE_EVENT(brcmf_bdchdr, | 92 | TRACE_EVENT(brcmf_bdchdr, |
| @@ -108,6 +110,23 @@ TRACE_EVENT(brcmf_bdchdr, | |||
| 108 | TP_printk("bdc: prio=%d siglen=%d", __entry->prio, __entry->siglen) | 110 | TP_printk("bdc: prio=%d siglen=%d", __entry->prio, __entry->siglen) |
| 109 | ); | 111 | ); |
| 110 | 112 | ||
| 113 | TRACE_EVENT(brcmf_sdpcm_hdr, | ||
| 114 | TP_PROTO(bool tx, void *data), | ||
| 115 | TP_ARGS(tx, data), | ||
| 116 | TP_STRUCT__entry( | ||
| 117 | __field(u8, tx) | ||
| 118 | __field(u16, len) | ||
| 119 | __array(u8, hdr, 12) | ||
| 120 | ), | ||
| 121 | TP_fast_assign( | ||
| 122 | memcpy(__entry->hdr, data, 12); | ||
| 123 | __entry->len = __entry->hdr[0] | (__entry->hdr[1] << 8); | ||
| 124 | __entry->tx = tx ? 1 : 0; | ||
| 125 | ), | ||
| 126 | TP_printk("sdpcm: %s len %u, seq %d", __entry->tx ? "TX" : "RX", | ||
| 127 | __entry->len, __entry->hdr[4]) | ||
| 128 | ); | ||
| 129 | |||
| 111 | #ifdef CONFIG_BRCM_TRACING | 130 | #ifdef CONFIG_BRCM_TRACING |
| 112 | 131 | ||
| 113 | #undef TRACE_INCLUDE_PATH | 132 | #undef TRACE_INCLUDE_PATH |
diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c index da442b81370a..1fef5240e6ad 100644 --- a/drivers/net/wireless/iwlwifi/dvm/tx.c +++ b/drivers/net/wireless/iwlwifi/dvm/tx.c | |||
| @@ -433,27 +433,19 @@ int iwlagn_tx_skb(struct iwl_priv *priv, | |||
| 433 | /* Copy MAC header from skb into command buffer */ | 433 | /* Copy MAC header from skb into command buffer */ |
| 434 | memcpy(tx_cmd->hdr, hdr, hdr_len); | 434 | memcpy(tx_cmd->hdr, hdr, hdr_len); |
| 435 | 435 | ||
| 436 | txq_id = info->hw_queue; | ||
| 437 | |||
| 436 | if (is_agg) | 438 | if (is_agg) |
| 437 | txq_id = priv->tid_data[sta_id][tid].agg.txq_id; | 439 | txq_id = priv->tid_data[sta_id][tid].agg.txq_id; |
| 438 | else if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { | 440 | else if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { |
| 439 | /* | 441 | /* |
| 440 | * Send this frame after DTIM -- there's a special queue | ||
| 441 | * reserved for this for contexts that support AP mode. | ||
| 442 | */ | ||
| 443 | txq_id = ctx->mcast_queue; | ||
| 444 | |||
| 445 | /* | ||
| 446 | * The microcode will clear the more data | 442 | * The microcode will clear the more data |
| 447 | * bit in the last frame it transmits. | 443 | * bit in the last frame it transmits. |
| 448 | */ | 444 | */ |
| 449 | hdr->frame_control |= | 445 | hdr->frame_control |= |
| 450 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); | 446 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); |
| 451 | } else if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) | 447 | } |
| 452 | txq_id = IWL_AUX_QUEUE; | ||
| 453 | else | ||
| 454 | txq_id = ctx->ac_to_queue[skb_get_queue_mapping(skb)]; | ||
| 455 | 448 | ||
| 456 | WARN_ON_ONCE(!is_agg && txq_id != info->hw_queue); | ||
| 457 | WARN_ON_ONCE(is_agg && | 449 | WARN_ON_ONCE(is_agg && |
| 458 | priv->queue_to_mac80211[txq_id] != info->hw_queue); | 450 | priv->queue_to_mac80211[txq_id] != info->hw_queue); |
| 459 | 451 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c index 76e14c046d94..85879dbaa402 100644 --- a/drivers/net/wireless/iwlwifi/iwl-7000.c +++ b/drivers/net/wireless/iwlwifi/iwl-7000.c | |||
| @@ -83,6 +83,8 @@ | |||
| 83 | #define IWL7260_TX_POWER_VERSION 0xffff /* meaningless */ | 83 | #define IWL7260_TX_POWER_VERSION 0xffff /* meaningless */ |
| 84 | #define IWL3160_NVM_VERSION 0x709 | 84 | #define IWL3160_NVM_VERSION 0x709 |
| 85 | #define IWL3160_TX_POWER_VERSION 0xffff /* meaningless */ | 85 | #define IWL3160_TX_POWER_VERSION 0xffff /* meaningless */ |
| 86 | #define IWL7265_NVM_VERSION 0x0a1d | ||
| 87 | #define IWL7265_TX_POWER_VERSION 0xffff /* meaningless */ | ||
| 86 | 88 | ||
| 87 | #define IWL7260_FW_PRE "iwlwifi-7260-" | 89 | #define IWL7260_FW_PRE "iwlwifi-7260-" |
| 88 | #define IWL7260_MODULE_FIRMWARE(api) IWL7260_FW_PRE __stringify(api) ".ucode" | 90 | #define IWL7260_MODULE_FIRMWARE(api) IWL7260_FW_PRE __stringify(api) ".ucode" |
| @@ -90,6 +92,9 @@ | |||
| 90 | #define IWL3160_FW_PRE "iwlwifi-3160-" | 92 | #define IWL3160_FW_PRE "iwlwifi-3160-" |
| 91 | #define IWL3160_MODULE_FIRMWARE(api) IWL3160_FW_PRE __stringify(api) ".ucode" | 93 | #define IWL3160_MODULE_FIRMWARE(api) IWL3160_FW_PRE __stringify(api) ".ucode" |
| 92 | 94 | ||
| 95 | #define IWL7265_FW_PRE "iwlwifi-7265-" | ||
| 96 | #define IWL7265_MODULE_FIRMWARE(api) IWL7265_FW_PRE __stringify(api) ".ucode" | ||
| 97 | |||
| 93 | static const struct iwl_base_params iwl7000_base_params = { | 98 | static const struct iwl_base_params iwl7000_base_params = { |
| 94 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 99 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
| 95 | .num_of_queues = IWLAGN_NUM_QUEUES, | 100 | .num_of_queues = IWLAGN_NUM_QUEUES, |
| @@ -182,5 +187,14 @@ const struct iwl_cfg iwl3160_n_cfg = { | |||
| 182 | .nvm_calib_ver = IWL3160_TX_POWER_VERSION, | 187 | .nvm_calib_ver = IWL3160_TX_POWER_VERSION, |
| 183 | }; | 188 | }; |
| 184 | 189 | ||
| 190 | const struct iwl_cfg iwl7265_2ac_cfg = { | ||
| 191 | .name = "Intel(R) Dual Band Wireless AC 7265", | ||
| 192 | .fw_name_pre = IWL7265_FW_PRE, | ||
| 193 | IWL_DEVICE_7000, | ||
| 194 | .ht_params = &iwl7000_ht_params, | ||
| 195 | .nvm_ver = IWL7265_NVM_VERSION, | ||
| 196 | .nvm_calib_ver = IWL7265_TX_POWER_VERSION, | ||
| 197 | }; | ||
| 198 | |||
| 185 | MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); | 199 | MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); |
| 186 | MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL3160_UCODE_API_OK)); | 200 | MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL3160_UCODE_API_OK)); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h index b03c25e14903..18f232e8e812 100644 --- a/drivers/net/wireless/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/iwlwifi/iwl-config.h | |||
| @@ -293,6 +293,7 @@ extern const struct iwl_cfg iwl7260_n_cfg; | |||
| 293 | extern const struct iwl_cfg iwl3160_2ac_cfg; | 293 | extern const struct iwl_cfg iwl3160_2ac_cfg; |
| 294 | extern const struct iwl_cfg iwl3160_2n_cfg; | 294 | extern const struct iwl_cfg iwl3160_2n_cfg; |
| 295 | extern const struct iwl_cfg iwl3160_n_cfg; | 295 | extern const struct iwl_cfg iwl3160_n_cfg; |
| 296 | extern const struct iwl_cfg iwl7265_2ac_cfg; | ||
| 296 | #endif /* CONFIG_IWLMVM */ | 297 | #endif /* CONFIG_IWLMVM */ |
| 297 | 298 | ||
| 298 | #endif /* __IWL_CONFIG_H__ */ | 299 | #endif /* __IWL_CONFIG_H__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index a276af476e2d..54a4fdc631b7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h | |||
| @@ -394,6 +394,38 @@ | |||
| 394 | #define CSR_DRAM_INT_TBL_ENABLE (1 << 31) | 394 | #define CSR_DRAM_INT_TBL_ENABLE (1 << 31) |
| 395 | #define CSR_DRAM_INIT_TBL_WRAP_CHECK (1 << 27) | 395 | #define CSR_DRAM_INIT_TBL_WRAP_CHECK (1 << 27) |
| 396 | 396 | ||
| 397 | /* SECURE boot registers */ | ||
| 398 | #define CSR_SECURE_BOOT_CONFIG_ADDR (0x100) | ||
| 399 | enum secure_boot_config_reg { | ||
| 400 | CSR_SECURE_BOOT_CONFIG_INSPECTOR_BURNED_IN_OTP = 0x00000001, | ||
| 401 | CSR_SECURE_BOOT_CONFIG_INSPECTOR_NOT_REQ = 0x00000002, | ||
| 402 | }; | ||
| 403 | |||
| 404 | #define CSR_SECURE_BOOT_CPU1_STATUS_ADDR (0x100) | ||
| 405 | #define CSR_SECURE_BOOT_CPU2_STATUS_ADDR (0x100) | ||
| 406 | enum secure_boot_status_reg { | ||
| 407 | CSR_SECURE_BOOT_CPU_STATUS_VERF_STATUS = 0x00000003, | ||
| 408 | CSR_SECURE_BOOT_CPU_STATUS_VERF_COMPLETED = 0x00000002, | ||
| 409 | CSR_SECURE_BOOT_CPU_STATUS_VERF_SUCCESS = 0x00000004, | ||
| 410 | CSR_SECURE_BOOT_CPU_STATUS_VERF_FAIL = 0x00000008, | ||
| 411 | CSR_SECURE_BOOT_CPU_STATUS_SIGN_VERF_FAIL = 0x00000010, | ||
| 412 | }; | ||
| 413 | |||
| 414 | #define CSR_UCODE_LOAD_STATUS_ADDR (0x100) | ||
| 415 | enum secure_load_status_reg { | ||
| 416 | CSR_CPU_STATUS_LOADING_STARTED = 0x00000001, | ||
| 417 | CSR_CPU_STATUS_LOADING_COMPLETED = 0x00000002, | ||
| 418 | CSR_CPU_STATUS_NUM_OF_LAST_COMPLETED = 0x000000F8, | ||
| 419 | CSR_CPU_STATUS_NUM_OF_LAST_LOADED_BLOCK = 0x0000FF00, | ||
| 420 | }; | ||
| 421 | |||
| 422 | #define CSR_SECURE_INSPECTOR_CODE_ADDR (0x100) | ||
| 423 | #define CSR_SECURE_INSPECTOR_DATA_ADDR (0x100) | ||
| 424 | |||
| 425 | #define CSR_SECURE_TIME_OUT (100) | ||
| 426 | |||
| 427 | #define FH_TCSR_0_REG0 (0x1D00) | ||
| 428 | |||
| 397 | /* | 429 | /* |
| 398 | * HBUS (Host-side Bus) | 430 | * HBUS (Host-side Bus) |
| 399 | * | 431 | * |
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index 99e1da3123c9..ff570027e9dd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c | |||
| @@ -483,6 +483,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, | |||
| 483 | const u8 *tlv_data; | 483 | const u8 *tlv_data; |
| 484 | char buildstr[25]; | 484 | char buildstr[25]; |
| 485 | u32 build; | 485 | u32 build; |
| 486 | int num_of_cpus; | ||
| 486 | 487 | ||
| 487 | if (len < sizeof(*ucode)) { | 488 | if (len < sizeof(*ucode)) { |
| 488 | IWL_ERR(drv, "uCode has invalid length: %zd\n", len); | 489 | IWL_ERR(drv, "uCode has invalid length: %zd\n", len); |
| @@ -692,6 +693,42 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, | |||
| 692 | goto invalid_tlv_len; | 693 | goto invalid_tlv_len; |
| 693 | drv->fw.phy_config = le32_to_cpup((__le32 *)tlv_data); | 694 | drv->fw.phy_config = le32_to_cpup((__le32 *)tlv_data); |
| 694 | break; | 695 | break; |
| 696 | case IWL_UCODE_TLV_SECURE_SEC_RT: | ||
| 697 | iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_REGULAR, | ||
| 698 | tlv_len); | ||
| 699 | drv->fw.mvm_fw = true; | ||
| 700 | drv->fw.img[IWL_UCODE_REGULAR].is_secure = true; | ||
| 701 | break; | ||
| 702 | case IWL_UCODE_TLV_SECURE_SEC_INIT: | ||
| 703 | iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_INIT, | ||
| 704 | tlv_len); | ||
| 705 | drv->fw.mvm_fw = true; | ||
| 706 | drv->fw.img[IWL_UCODE_INIT].is_secure = true; | ||
| 707 | break; | ||
| 708 | case IWL_UCODE_TLV_SECURE_SEC_WOWLAN: | ||
| 709 | iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_WOWLAN, | ||
| 710 | tlv_len); | ||
| 711 | drv->fw.mvm_fw = true; | ||
| 712 | drv->fw.img[IWL_UCODE_WOWLAN].is_secure = true; | ||
| 713 | break; | ||
| 714 | case IWL_UCODE_TLV_NUM_OF_CPU: | ||
| 715 | if (tlv_len != sizeof(u32)) | ||
| 716 | goto invalid_tlv_len; | ||
| 717 | num_of_cpus = | ||
| 718 | le32_to_cpup((__le32 *)tlv_data); | ||
| 719 | |||
| 720 | if (num_of_cpus == 2) { | ||
| 721 | drv->fw.img[IWL_UCODE_REGULAR].is_dual_cpus = | ||
| 722 | true; | ||
| 723 | drv->fw.img[IWL_UCODE_INIT].is_dual_cpus = | ||
| 724 | true; | ||
| 725 | drv->fw.img[IWL_UCODE_WOWLAN].is_dual_cpus = | ||
| 726 | true; | ||
| 727 | } else if ((num_of_cpus > 2) || (num_of_cpus < 1)) { | ||
| 728 | IWL_ERR(drv, "Driver support upto 2 CPUs\n"); | ||
| 729 | return -EINVAL; | ||
| 730 | } | ||
| 731 | break; | ||
| 695 | default: | 732 | default: |
| 696 | IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type); | 733 | IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type); |
| 697 | break; | 734 | break; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/iwlwifi/iwl-fw-file.h index 8b6c6fd95ed0..6c6c35c5228c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw-file.h | |||
| @@ -121,6 +121,10 @@ enum iwl_ucode_tlv_type { | |||
| 121 | IWL_UCODE_TLV_SEC_WOWLAN = 21, | 121 | IWL_UCODE_TLV_SEC_WOWLAN = 21, |
| 122 | IWL_UCODE_TLV_DEF_CALIB = 22, | 122 | IWL_UCODE_TLV_DEF_CALIB = 22, |
| 123 | IWL_UCODE_TLV_PHY_SKU = 23, | 123 | IWL_UCODE_TLV_PHY_SKU = 23, |
| 124 | IWL_UCODE_TLV_SECURE_SEC_RT = 24, | ||
| 125 | IWL_UCODE_TLV_SECURE_SEC_INIT = 25, | ||
| 126 | IWL_UCODE_TLV_SECURE_SEC_WOWLAN = 26, | ||
| 127 | IWL_UCODE_TLV_NUM_OF_CPU = 27, | ||
| 124 | }; | 128 | }; |
| 125 | 129 | ||
| 126 | struct iwl_ucode_tlv { | 130 | struct iwl_ucode_tlv { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h index a1223680bc70..87b66a821ec8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw.h | |||
| @@ -75,11 +75,23 @@ | |||
| 75 | * @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P. | 75 | * @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P. |
| 76 | * @IWL_UCODE_TLV_FLAGS_DW_BC_TABLE: The SCD byte count table is in DWORDS | 76 | * @IWL_UCODE_TLV_FLAGS_DW_BC_TABLE: The SCD byte count table is in DWORDS |
| 77 | * @IWL_UCODE_TLV_FLAGS_UAPSD: This uCode image supports uAPSD | 77 | * @IWL_UCODE_TLV_FLAGS_UAPSD: This uCode image supports uAPSD |
| 78 | * @IWL_UCODE_TLV_FLAGS_SHORT_BL: 16 entries of black list instead of 64 in scan | ||
| 79 | * offload profile config command. | ||
| 78 | * @IWL_UCODE_TLV_FLAGS_RX_ENERGY_API: supports rx signal strength api | 80 | * @IWL_UCODE_TLV_FLAGS_RX_ENERGY_API: supports rx signal strength api |
| 79 | * @IWL_UCODE_TLV_FLAGS_TIME_EVENT_API_V2: using the new time event API. | 81 | * @IWL_UCODE_TLV_FLAGS_TIME_EVENT_API_V2: using the new time event API. |
| 80 | * @IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS: D3 image supports up to six | 82 | * @IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS: D3 image supports up to six |
| 81 | * (rather than two) IPv6 addresses | 83 | * (rather than two) IPv6 addresses |
| 82 | * @IWL_UCODE_TLV_FLAGS_BF_UPDATED: new beacon filtering API | 84 | * @IWL_UCODE_TLV_FLAGS_BF_UPDATED: new beacon filtering API |
| 85 | * @IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID: not sending a probe with the SSID element | ||
| 86 | * from the probe request template. | ||
| 87 | * @IWL_UCODE_TLV_FLAGS_D3_CONTINUITY_API: modified D3 API to allow keeping | ||
| 88 | * connection when going back to D0 | ||
| 89 | * @IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL: new NS offload (small version) | ||
| 90 | * @IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE: new NS offload (large version) | ||
| 91 | * @IWL_UCODE_TLV_FLAGS_SCHED_SCAN: this uCode image supports scheduled scan. | ||
| 92 | * @IWL_UCODE_TLV_FLAGS_STA_KEY_CMD: new ADD_STA and ADD_STA_KEY command API | ||
| 93 | * @IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD: support device wide power command | ||
| 94 | * containing CAM (Continuous Active Mode) indication. | ||
| 83 | */ | 95 | */ |
| 84 | enum iwl_ucode_tlv_flag { | 96 | enum iwl_ucode_tlv_flag { |
| 85 | IWL_UCODE_TLV_FLAGS_PAN = BIT(0), | 97 | IWL_UCODE_TLV_FLAGS_PAN = BIT(0), |
| @@ -87,11 +99,20 @@ enum iwl_ucode_tlv_flag { | |||
| 87 | IWL_UCODE_TLV_FLAGS_MFP = BIT(2), | 99 | IWL_UCODE_TLV_FLAGS_MFP = BIT(2), |
| 88 | IWL_UCODE_TLV_FLAGS_P2P = BIT(3), | 100 | IWL_UCODE_TLV_FLAGS_P2P = BIT(3), |
| 89 | IWL_UCODE_TLV_FLAGS_DW_BC_TABLE = BIT(4), | 101 | IWL_UCODE_TLV_FLAGS_DW_BC_TABLE = BIT(4), |
| 102 | IWL_UCODE_TLV_FLAGS_NEWBT_COEX = BIT(5), | ||
| 90 | IWL_UCODE_TLV_FLAGS_UAPSD = BIT(6), | 103 | IWL_UCODE_TLV_FLAGS_UAPSD = BIT(6), |
| 104 | IWL_UCODE_TLV_FLAGS_SHORT_BL = BIT(7), | ||
| 91 | IWL_UCODE_TLV_FLAGS_RX_ENERGY_API = BIT(8), | 105 | IWL_UCODE_TLV_FLAGS_RX_ENERGY_API = BIT(8), |
| 92 | IWL_UCODE_TLV_FLAGS_TIME_EVENT_API_V2 = BIT(9), | 106 | IWL_UCODE_TLV_FLAGS_TIME_EVENT_API_V2 = BIT(9), |
| 93 | IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS = BIT(10), | 107 | IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS = BIT(10), |
| 94 | IWL_UCODE_TLV_FLAGS_BF_UPDATED = BIT(11), | 108 | IWL_UCODE_TLV_FLAGS_BF_UPDATED = BIT(11), |
| 109 | IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID = BIT(12), | ||
| 110 | IWL_UCODE_TLV_FLAGS_D3_CONTINUITY_API = BIT(14), | ||
| 111 | IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL = BIT(15), | ||
| 112 | IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE = BIT(16), | ||
| 113 | IWL_UCODE_TLV_FLAGS_SCHED_SCAN = BIT(17), | ||
| 114 | IWL_UCODE_TLV_FLAGS_STA_KEY_CMD = BIT(19), | ||
| 115 | IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD = BIT(20), | ||
| 95 | }; | 116 | }; |
| 96 | 117 | ||
| 97 | /* The default calibrate table size if not specified by firmware file */ | 118 | /* The default calibrate table size if not specified by firmware file */ |
| @@ -133,7 +154,8 @@ enum iwl_ucode_sec { | |||
| 133 | * For 16.0 uCode and above, there is no differentiation between sections, | 154 | * For 16.0 uCode and above, there is no differentiation between sections, |
| 134 | * just an offset to the HW address. | 155 | * just an offset to the HW address. |
| 135 | */ | 156 | */ |
| 136 | #define IWL_UCODE_SECTION_MAX 4 | 157 | #define IWL_UCODE_SECTION_MAX 6 |
| 158 | #define IWL_UCODE_FIRST_SECTION_OF_SECOND_CPU (IWL_UCODE_SECTION_MAX/2) | ||
| 137 | 159 | ||
| 138 | struct iwl_ucode_capabilities { | 160 | struct iwl_ucode_capabilities { |
| 139 | u32 max_probe_length; | 161 | u32 max_probe_length; |
| @@ -150,6 +172,8 @@ struct fw_desc { | |||
| 150 | 172 | ||
| 151 | struct fw_img { | 173 | struct fw_img { |
| 152 | struct fw_desc sec[IWL_UCODE_SECTION_MAX]; | 174 | struct fw_desc sec[IWL_UCODE_SECTION_MAX]; |
| 175 | bool is_secure; | ||
| 176 | bool is_dual_cpus; | ||
| 153 | }; | 177 | }; |
| 154 | 178 | ||
| 155 | /* uCode version contains 4 values: Major/Minor/API/Serial */ | 179 | /* uCode version contains 4 values: Major/Minor/API/Serial */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index ff8cc75c189d..a70c7b9d9bad 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h | |||
| @@ -97,6 +97,8 @@ | |||
| 97 | 97 | ||
| 98 | #define APMG_PCIDEV_STT_VAL_L1_ACT_DIS (0x00000800) | 98 | #define APMG_PCIDEV_STT_VAL_L1_ACT_DIS (0x00000800) |
| 99 | 99 | ||
| 100 | #define APMG_RTC_INT_STT_RFKILL (0x10000000) | ||
| 101 | |||
| 100 | /* Device system time */ | 102 | /* Device system time */ |
| 101 | #define DEVICE_SYSTEM_TIME_REG 0xA0206C | 103 | #define DEVICE_SYSTEM_TIME_REG 0xA0206C |
| 102 | 104 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 80b47508647c..c6bac7c90b00 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
| @@ -601,7 +601,7 @@ static inline int iwl_trans_send_cmd(struct iwl_trans *trans, | |||
| 601 | { | 601 | { |
| 602 | int ret; | 602 | int ret; |
| 603 | 603 | ||
| 604 | if (trans->state != IWL_TRANS_FW_ALIVE) { | 604 | if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) { |
| 605 | IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); | 605 | IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); |
| 606 | return -EIO; | 606 | return -EIO; |
| 607 | } | 607 | } |
| @@ -640,8 +640,8 @@ static inline void iwl_trans_free_tx_cmd(struct iwl_trans *trans, | |||
| 640 | static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, | 640 | static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, |
| 641 | struct iwl_device_cmd *dev_cmd, int queue) | 641 | struct iwl_device_cmd *dev_cmd, int queue) |
| 642 | { | 642 | { |
| 643 | WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, | 643 | if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) |
| 644 | "%s bad state = %d", __func__, trans->state); | 644 | IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); |
| 645 | 645 | ||
| 646 | return trans->ops->tx(trans, skb, dev_cmd, queue); | 646 | return trans->ops->tx(trans, skb, dev_cmd, queue); |
| 647 | } | 647 | } |
| @@ -649,16 +649,16 @@ static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, | |||
| 649 | static inline void iwl_trans_reclaim(struct iwl_trans *trans, int queue, | 649 | static inline void iwl_trans_reclaim(struct iwl_trans *trans, int queue, |
| 650 | int ssn, struct sk_buff_head *skbs) | 650 | int ssn, struct sk_buff_head *skbs) |
| 651 | { | 651 | { |
| 652 | WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, | 652 | if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) |
| 653 | "%s bad state = %d", __func__, trans->state); | 653 | IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); |
| 654 | 654 | ||
| 655 | trans->ops->reclaim(trans, queue, ssn, skbs); | 655 | trans->ops->reclaim(trans, queue, ssn, skbs); |
| 656 | } | 656 | } |
| 657 | 657 | ||
| 658 | static inline void iwl_trans_txq_disable(struct iwl_trans *trans, int queue) | 658 | static inline void iwl_trans_txq_disable(struct iwl_trans *trans, int queue) |
| 659 | { | 659 | { |
| 660 | WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, | 660 | if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) |
| 661 | "%s bad state = %d", __func__, trans->state); | 661 | IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); |
| 662 | 662 | ||
| 663 | trans->ops->txq_disable(trans, queue); | 663 | trans->ops->txq_disable(trans, queue); |
| 664 | } | 664 | } |
| @@ -669,8 +669,8 @@ static inline void iwl_trans_txq_enable(struct iwl_trans *trans, int queue, | |||
| 669 | { | 669 | { |
| 670 | might_sleep(); | 670 | might_sleep(); |
| 671 | 671 | ||
| 672 | WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, | 672 | if (unlikely((trans->state != IWL_TRANS_FW_ALIVE))) |
| 673 | "%s bad state = %d", __func__, trans->state); | 673 | IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); |
| 674 | 674 | ||
| 675 | trans->ops->txq_enable(trans, queue, fifo, sta_id, tid, | 675 | trans->ops->txq_enable(trans, queue, fifo, sta_id, tid, |
| 676 | frame_limit, ssn); | 676 | frame_limit, ssn); |
| @@ -685,8 +685,8 @@ static inline void iwl_trans_ac_txq_enable(struct iwl_trans *trans, int queue, | |||
| 685 | 685 | ||
| 686 | static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans) | 686 | static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans) |
| 687 | { | 687 | { |
| 688 | WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, | 688 | if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) |
| 689 | "%s bad state = %d", __func__, trans->state); | 689 | IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); |
| 690 | 690 | ||
| 691 | return trans->ops->wait_tx_queue_empty(trans); | 691 | return trans->ops->wait_tx_queue_empty(trans); |
| 692 | } | 692 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c index 0fad98b85f60..5b630f12bbff 100644 --- a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c +++ b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c | |||
| @@ -98,126 +98,258 @@ static const u8 iwl_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = { | |||
| 98 | 98 | ||
| 99 | #undef EVENT_PRIO_ANT | 99 | #undef EVENT_PRIO_ANT |
| 100 | 100 | ||
| 101 | /* BT Antenna Coupling Threshold (dB) */ | ||
| 102 | #define IWL_BT_ANTENNA_COUPLING_THRESHOLD (35) | ||
| 103 | #define IWL_BT_LOAD_FORCE_SISO_THRESHOLD (3) | ||
| 104 | |||
| 105 | #define BT_ENABLE_REDUCED_TXPOWER_THRESHOLD (-62) | 101 | #define BT_ENABLE_REDUCED_TXPOWER_THRESHOLD (-62) |
| 106 | #define BT_DISABLE_REDUCED_TXPOWER_THRESHOLD (-65) | 102 | #define BT_DISABLE_REDUCED_TXPOWER_THRESHOLD (-65) |
| 107 | #define BT_REDUCED_TX_POWER_BIT BIT(7) | 103 | #define BT_ANTENNA_COUPLING_THRESHOLD (30) |
| 108 | |||
| 109 | static inline bool is_loose_coex(void) | ||
| 110 | { | ||
| 111 | return iwlwifi_mod_params.ant_coupling > | ||
| 112 | IWL_BT_ANTENNA_COUPLING_THRESHOLD; | ||
| 113 | } | ||
| 114 | 104 | ||
| 115 | int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm) | 105 | int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm) |
| 116 | { | 106 | { |
| 107 | if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWBT_COEX)) | ||
| 108 | return 0; | ||
| 109 | |||
| 117 | return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_PRIO_TABLE, CMD_SYNC, | 110 | return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_PRIO_TABLE, CMD_SYNC, |
| 118 | sizeof(struct iwl_bt_coex_prio_tbl_cmd), | 111 | sizeof(struct iwl_bt_coex_prio_tbl_cmd), |
| 119 | &iwl_bt_prio_tbl); | 112 | &iwl_bt_prio_tbl); |
| 120 | } | 113 | } |
| 121 | 114 | ||
| 122 | static int iwl_send_bt_env(struct iwl_mvm *mvm, u8 action, u8 type) | 115 | const u32 iwl_bt_ack_kill_msk[BT_KILL_MSK_MAX] = { |
| 123 | { | ||
| 124 | struct iwl_bt_coex_prot_env_cmd env_cmd; | ||
| 125 | int ret; | ||
| 126 | |||
| 127 | env_cmd.action = action; | ||
| 128 | env_cmd.type = type; | ||
| 129 | ret = iwl_mvm_send_cmd_pdu(mvm, BT_COEX_PROT_ENV, CMD_SYNC, | ||
| 130 | sizeof(env_cmd), &env_cmd); | ||
| 131 | if (ret) | ||
| 132 | IWL_ERR(mvm, "failed to send BT env command\n"); | ||
| 133 | return ret; | ||
| 134 | } | ||
| 135 | |||
| 136 | enum iwl_bt_kill_msk { | ||
| 137 | BT_KILL_MSK_DEFAULT, | ||
| 138 | BT_KILL_MSK_SCO_HID_A2DP, | ||
| 139 | BT_KILL_MSK_REDUCED_TXPOW, | ||
| 140 | BT_KILL_MSK_MAX, | ||
| 141 | }; | ||
| 142 | |||
| 143 | static const u32 iwl_bt_ack_kill_msk[BT_KILL_MSK_MAX] = { | ||
| 144 | [BT_KILL_MSK_DEFAULT] = 0xffff0000, | 116 | [BT_KILL_MSK_DEFAULT] = 0xffff0000, |
| 145 | [BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff, | 117 | [BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff, |
| 146 | [BT_KILL_MSK_REDUCED_TXPOW] = 0, | 118 | [BT_KILL_MSK_REDUCED_TXPOW] = 0, |
| 147 | }; | 119 | }; |
| 148 | 120 | ||
| 149 | static const u32 iwl_bt_cts_kill_msk[BT_KILL_MSK_MAX] = { | 121 | const u32 iwl_bt_cts_kill_msk[BT_KILL_MSK_MAX] = { |
| 150 | [BT_KILL_MSK_DEFAULT] = 0xffff0000, | 122 | [BT_KILL_MSK_DEFAULT] = 0xffff0000, |
| 151 | [BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff, | 123 | [BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff, |
| 152 | [BT_KILL_MSK_REDUCED_TXPOW] = 0, | 124 | [BT_KILL_MSK_REDUCED_TXPOW] = 0, |
| 153 | }; | 125 | }; |
| 154 | 126 | ||
| 155 | #define IWL_BT_DEFAULT_BOOST (0xf0f0f0f0) | 127 | static const __le32 iwl_bt_prio_boost[BT_COEX_BOOST_SIZE] = { |
| 156 | 128 | cpu_to_le32(0xf0f0f0f0), | |
| 157 | /* Tight Coex */ | 129 | cpu_to_le32(0xc0c0c0c0), |
| 158 | static const __le32 iwl_tight_lookup[BT_COEX_LUT_SIZE] = { | 130 | cpu_to_le32(0xfcfcfcfc), |
| 159 | cpu_to_le32(0xaaaaaaaa), | 131 | cpu_to_le32(0xff00ff00), |
| 160 | cpu_to_le32(0xaaaaaaaa), | ||
| 161 | cpu_to_le32(0xaeaaaaaa), | ||
| 162 | cpu_to_le32(0xaaaaaaaa), | ||
| 163 | cpu_to_le32(0xcc00ff28), | ||
| 164 | cpu_to_le32(0x0000aaaa), | ||
| 165 | cpu_to_le32(0xcc00aaaa), | ||
| 166 | cpu_to_le32(0x0000aaaa), | ||
| 167 | cpu_to_le32(0xc0004000), | ||
| 168 | cpu_to_le32(0x00000000), | ||
| 169 | cpu_to_le32(0xf0005000), | ||
| 170 | cpu_to_le32(0xf0005000), | ||
| 171 | }; | 132 | }; |
| 172 | 133 | ||
| 173 | /* Loose Coex */ | 134 | static const __le32 iwl_single_shared_ant[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = { |
| 174 | static const __le32 iwl_loose_lookup[BT_COEX_LUT_SIZE] = { | 135 | { |
| 175 | cpu_to_le32(0xaaaaaaaa), | 136 | cpu_to_le32(0x40000000), |
| 176 | cpu_to_le32(0xaaaaaaaa), | 137 | cpu_to_le32(0x00000000), |
| 177 | cpu_to_le32(0xaaaaaaaa), | 138 | cpu_to_le32(0x44000000), |
| 178 | cpu_to_le32(0xaaaaaaaa), | 139 | cpu_to_le32(0x00000000), |
| 179 | cpu_to_le32(0xcc00ff28), | 140 | cpu_to_le32(0x40000000), |
| 180 | cpu_to_le32(0x0000aaaa), | 141 | cpu_to_le32(0x00000000), |
| 181 | cpu_to_le32(0xcc00aaaa), | 142 | cpu_to_le32(0x44000000), |
| 182 | cpu_to_le32(0x0000aaaa), | 143 | cpu_to_le32(0x00000000), |
| 183 | cpu_to_le32(0x00000000), | 144 | cpu_to_le32(0xc0004000), |
| 184 | cpu_to_le32(0x00000000), | 145 | cpu_to_le32(0xf0005000), |
| 185 | cpu_to_le32(0xf0005000), | 146 | cpu_to_le32(0xc0004000), |
| 186 | cpu_to_le32(0xf0005000), | 147 | cpu_to_le32(0xf0005000), |
| 148 | }, | ||
| 149 | { | ||
| 150 | cpu_to_le32(0x40000000), | ||
| 151 | cpu_to_le32(0x00000000), | ||
| 152 | cpu_to_le32(0x44000000), | ||
| 153 | cpu_to_le32(0x00000000), | ||
| 154 | cpu_to_le32(0x40000000), | ||
| 155 | cpu_to_le32(0x00000000), | ||
| 156 | cpu_to_le32(0x44000000), | ||
| 157 | cpu_to_le32(0x00000000), | ||
| 158 | cpu_to_le32(0xc0004000), | ||
| 159 | cpu_to_le32(0xf0005000), | ||
| 160 | cpu_to_le32(0xc0004000), | ||
| 161 | cpu_to_le32(0xf0005000), | ||
| 162 | }, | ||
| 163 | { | ||
| 164 | cpu_to_le32(0x40000000), | ||
| 165 | cpu_to_le32(0x00000000), | ||
| 166 | cpu_to_le32(0x44000000), | ||
| 167 | cpu_to_le32(0x00000000), | ||
| 168 | cpu_to_le32(0x40000000), | ||
| 169 | cpu_to_le32(0x00000000), | ||
| 170 | cpu_to_le32(0x44000000), | ||
| 171 | cpu_to_le32(0x00000000), | ||
| 172 | cpu_to_le32(0xc0004000), | ||
| 173 | cpu_to_le32(0xf0005000), | ||
| 174 | cpu_to_le32(0xc0004000), | ||
| 175 | cpu_to_le32(0xf0005000), | ||
| 176 | }, | ||
| 187 | }; | 177 | }; |
| 188 | 178 | ||
| 189 | /* Full concurrency */ | 179 | static const __le32 iwl_combined_lookup[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = { |
| 190 | static const __le32 iwl_concurrent_lookup[BT_COEX_LUT_SIZE] = { | 180 | { |
| 191 | cpu_to_le32(0xaaaaaaaa), | 181 | /* Tight */ |
| 192 | cpu_to_le32(0xaaaaaaaa), | 182 | cpu_to_le32(0xaaaaaaaa), |
| 193 | cpu_to_le32(0xaaaaaaaa), | 183 | cpu_to_le32(0xaaaaaaaa), |
| 194 | cpu_to_le32(0xaaaaaaaa), | 184 | cpu_to_le32(0xaeaaaaaa), |
| 195 | cpu_to_le32(0xaaaaaaaa), | 185 | cpu_to_le32(0xaaaaaaaa), |
| 196 | cpu_to_le32(0xaaaaaaaa), | 186 | cpu_to_le32(0xcc00ff28), |
| 197 | cpu_to_le32(0xaaaaaaaa), | 187 | cpu_to_le32(0x0000aaaa), |
| 198 | cpu_to_le32(0xaaaaaaaa), | 188 | cpu_to_le32(0xcc00aaaa), |
| 199 | cpu_to_le32(0x00000000), | 189 | cpu_to_le32(0x0000aaaa), |
| 200 | cpu_to_le32(0x00000000), | 190 | cpu_to_le32(0xc0004000), |
| 201 | cpu_to_le32(0x00000000), | 191 | cpu_to_le32(0x00000000), |
| 202 | cpu_to_le32(0x00000000), | 192 | cpu_to_le32(0xf0005000), |
| 193 | cpu_to_le32(0xf0005000), | ||
| 194 | }, | ||
| 195 | { | ||
| 196 | /* Loose */ | ||
| 197 | cpu_to_le32(0xaaaaaaaa), | ||
| 198 | cpu_to_le32(0xaaaaaaaa), | ||
| 199 | cpu_to_le32(0xaaaaaaaa), | ||
| 200 | cpu_to_le32(0xaaaaaaaa), | ||
| 201 | cpu_to_le32(0xcc00ff28), | ||
| 202 | cpu_to_le32(0x0000aaaa), | ||
| 203 | cpu_to_le32(0xcc00aaaa), | ||
| 204 | cpu_to_le32(0x0000aaaa), | ||
| 205 | cpu_to_le32(0x00000000), | ||
| 206 | cpu_to_le32(0x00000000), | ||
| 207 | cpu_to_le32(0xf0005000), | ||
| 208 | cpu_to_le32(0xf0005000), | ||
| 209 | }, | ||
| 210 | { | ||
| 211 | /* Tx Tx disabled */ | ||
| 212 | cpu_to_le32(0xaaaaaaaa), | ||
| 213 | cpu_to_le32(0xaaaaaaaa), | ||
| 214 | cpu_to_le32(0xaaaaaaaa), | ||
| 215 | cpu_to_le32(0xaaaaaaaa), | ||
| 216 | cpu_to_le32(0xcc00ff28), | ||
| 217 | cpu_to_le32(0x0000aaaa), | ||
| 218 | cpu_to_le32(0xcc00aaaa), | ||
| 219 | cpu_to_le32(0x0000aaaa), | ||
| 220 | cpu_to_le32(0xC0004000), | ||
| 221 | cpu_to_le32(0xC0004000), | ||
| 222 | cpu_to_le32(0xF0005000), | ||
| 223 | cpu_to_le32(0xF0005000), | ||
| 224 | }, | ||
| 203 | }; | 225 | }; |
| 204 | 226 | ||
| 205 | /* single shared antenna */ | 227 | /* 20MHz / 40MHz below / 40Mhz above*/ |
| 206 | static const __le32 iwl_single_shared_ant_lookup[BT_COEX_LUT_SIZE] = { | 228 | static const __le64 iwl_ci_mask[][3] = { |
| 207 | cpu_to_le32(0x40000000), | 229 | /* dummy entry for channel 0 */ |
| 208 | cpu_to_le32(0x00000000), | 230 | {cpu_to_le64(0), cpu_to_le64(0), cpu_to_le64(0)}, |
| 209 | cpu_to_le32(0x44000000), | 231 | { |
| 210 | cpu_to_le32(0x00000000), | 232 | cpu_to_le64(0x0000001FFFULL), |
| 211 | cpu_to_le32(0x40000000), | 233 | cpu_to_le64(0x0ULL), |
| 212 | cpu_to_le32(0x00000000), | 234 | cpu_to_le64(0x00007FFFFFULL), |
| 213 | cpu_to_le32(0x44000000), | 235 | }, |
| 214 | cpu_to_le32(0x00000000), | 236 | { |
| 215 | cpu_to_le32(0xC0004000), | 237 | cpu_to_le64(0x000000FFFFULL), |
| 216 | cpu_to_le32(0xF0005000), | 238 | cpu_to_le64(0x0ULL), |
| 217 | cpu_to_le32(0xC0004000), | 239 | cpu_to_le64(0x0003FFFFFFULL), |
| 218 | cpu_to_le32(0xF0005000), | 240 | }, |
| 241 | { | ||
| 242 | cpu_to_le64(0x000003FFFCULL), | ||
| 243 | cpu_to_le64(0x0ULL), | ||
| 244 | cpu_to_le64(0x000FFFFFFCULL), | ||
| 245 | }, | ||
| 246 | { | ||
| 247 | cpu_to_le64(0x00001FFFE0ULL), | ||
| 248 | cpu_to_le64(0x0ULL), | ||
| 249 | cpu_to_le64(0x007FFFFFE0ULL), | ||
| 250 | }, | ||
| 251 | { | ||
| 252 | cpu_to_le64(0x00007FFF80ULL), | ||
| 253 | cpu_to_le64(0x00007FFFFFULL), | ||
| 254 | cpu_to_le64(0x01FFFFFF80ULL), | ||
| 255 | }, | ||
| 256 | { | ||
| 257 | cpu_to_le64(0x0003FFFC00ULL), | ||
| 258 | cpu_to_le64(0x0003FFFFFFULL), | ||
| 259 | cpu_to_le64(0x0FFFFFFC00ULL), | ||
| 260 | }, | ||
| 261 | { | ||
| 262 | cpu_to_le64(0x000FFFF000ULL), | ||
| 263 | cpu_to_le64(0x000FFFFFFCULL), | ||
| 264 | cpu_to_le64(0x3FFFFFF000ULL), | ||
| 265 | }, | ||
| 266 | { | ||
| 267 | cpu_to_le64(0x007FFF8000ULL), | ||
| 268 | cpu_to_le64(0x007FFFFFE0ULL), | ||
| 269 | cpu_to_le64(0xFFFFFF8000ULL), | ||
| 270 | }, | ||
| 271 | { | ||
| 272 | cpu_to_le64(0x01FFFE0000ULL), | ||
| 273 | cpu_to_le64(0x01FFFFFF80ULL), | ||
| 274 | cpu_to_le64(0xFFFFFE0000ULL), | ||
| 275 | }, | ||
| 276 | { | ||
| 277 | cpu_to_le64(0x0FFFF00000ULL), | ||
| 278 | cpu_to_le64(0x0FFFFFFC00ULL), | ||
| 279 | cpu_to_le64(0x0ULL), | ||
| 280 | }, | ||
| 281 | { | ||
| 282 | cpu_to_le64(0x3FFFC00000ULL), | ||
| 283 | cpu_to_le64(0x3FFFFFF000ULL), | ||
| 284 | cpu_to_le64(0x0) | ||
| 285 | }, | ||
| 286 | { | ||
| 287 | cpu_to_le64(0xFFFE000000ULL), | ||
| 288 | cpu_to_le64(0xFFFFFF8000ULL), | ||
| 289 | cpu_to_le64(0x0) | ||
| 290 | }, | ||
| 291 | { | ||
| 292 | cpu_to_le64(0xFFF8000000ULL), | ||
| 293 | cpu_to_le64(0xFFFFFE0000ULL), | ||
| 294 | cpu_to_le64(0x0) | ||
| 295 | }, | ||
| 296 | { | ||
| 297 | cpu_to_le64(0xFE00000000ULL), | ||
| 298 | cpu_to_le64(0x0ULL), | ||
| 299 | cpu_to_le64(0x0) | ||
| 300 | }, | ||
| 219 | }; | 301 | }; |
| 220 | 302 | ||
| 303 | static const __le32 iwl_bt_mprio_lut[BT_COEX_MULTI_PRIO_LUT_SIZE] = { | ||
| 304 | cpu_to_le32(0x22002200), | ||
| 305 | cpu_to_le32(0x33113311), | ||
| 306 | }; | ||
| 307 | |||
| 308 | static enum iwl_bt_coex_lut_type | ||
| 309 | iwl_get_coex_type(struct iwl_mvm *mvm, const struct ieee80211_vif *vif) | ||
| 310 | { | ||
| 311 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
| 312 | enum iwl_bt_coex_lut_type ret; | ||
| 313 | u16 phy_ctx_id; | ||
| 314 | |||
| 315 | /* | ||
| 316 | * Checking that we hold mvm->mutex is a good idea, but the rate | ||
| 317 | * control can't acquire the mutex since it runs in Tx path. | ||
| 318 | * So this is racy in that case, but in the worst case, the AMPDU | ||
| 319 | * size limit will be wrong for a short time which is not a big | ||
| 320 | * issue. | ||
| 321 | */ | ||
| 322 | |||
| 323 | rcu_read_lock(); | ||
| 324 | |||
| 325 | chanctx_conf = rcu_dereference(vif->chanctx_conf); | ||
| 326 | |||
| 327 | if (!chanctx_conf || | ||
| 328 | chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ) { | ||
| 329 | rcu_read_unlock(); | ||
| 330 | return BT_COEX_LOOSE_LUT; | ||
| 331 | } | ||
| 332 | |||
| 333 | ret = BT_COEX_TX_DIS_LUT; | ||
| 334 | |||
| 335 | if (mvm->cfg->bt_shared_single_ant) { | ||
| 336 | rcu_read_unlock(); | ||
| 337 | return ret; | ||
| 338 | } | ||
| 339 | |||
| 340 | phy_ctx_id = *((u16 *)chanctx_conf->drv_priv); | ||
| 341 | |||
| 342 | if (mvm->last_bt_ci_cmd.primary_ch_phy_id == phy_ctx_id) | ||
| 343 | ret = le32_to_cpu(mvm->last_bt_notif.primary_ch_lut); | ||
| 344 | else if (mvm->last_bt_ci_cmd.secondary_ch_phy_id == phy_ctx_id) | ||
| 345 | ret = le32_to_cpu(mvm->last_bt_notif.secondary_ch_lut); | ||
| 346 | /* else - default = TX TX disallowed */ | ||
| 347 | |||
| 348 | rcu_read_unlock(); | ||
| 349 | |||
| 350 | return ret; | ||
| 351 | } | ||
| 352 | |||
| 221 | int iwl_send_bt_init_conf(struct iwl_mvm *mvm) | 353 | int iwl_send_bt_init_conf(struct iwl_mvm *mvm) |
| 222 | { | 354 | { |
| 223 | struct iwl_bt_coex_cmd *bt_cmd; | 355 | struct iwl_bt_coex_cmd *bt_cmd; |
| @@ -228,17 +360,10 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm) | |||
| 228 | .flags = CMD_SYNC, | 360 | .flags = CMD_SYNC, |
| 229 | }; | 361 | }; |
| 230 | int ret; | 362 | int ret; |
| 363 | u32 flags; | ||
| 231 | 364 | ||
| 232 | /* go to CALIB state in internal BT-Coex state machine */ | 365 | if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWBT_COEX)) |
| 233 | ret = iwl_send_bt_env(mvm, BT_COEX_ENV_OPEN, | 366 | return 0; |
| 234 | BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); | ||
| 235 | if (ret) | ||
| 236 | return ret; | ||
| 237 | |||
| 238 | ret = iwl_send_bt_env(mvm, BT_COEX_ENV_CLOSE, | ||
| 239 | BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); | ||
| 240 | if (ret) | ||
| 241 | return ret; | ||
| 242 | 367 | ||
| 243 | bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL); | 368 | bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL); |
| 244 | if (!bt_cmd) | 369 | if (!bt_cmd) |
| @@ -246,40 +371,52 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm) | |||
| 246 | cmd.data[0] = bt_cmd; | 371 | cmd.data[0] = bt_cmd; |
| 247 | 372 | ||
| 248 | bt_cmd->max_kill = 5; | 373 | bt_cmd->max_kill = 5; |
| 249 | bt_cmd->bt3_time_t7_value = 1; | 374 | bt_cmd->bt4_antenna_isolation_thr = BT_ANTENNA_COUPLING_THRESHOLD, |
| 250 | bt_cmd->bt3_prio_sample_time = 2; | 375 | bt_cmd->bt4_antenna_isolation = iwlwifi_mod_params.ant_coupling, |
| 251 | bt_cmd->bt3_timer_t2_value = 0xc; | 376 | bt_cmd->bt4_tx_tx_delta_freq_thr = 15, |
| 377 | bt_cmd->bt4_tx_rx_max_freq0 = 15, | ||
| 252 | 378 | ||
| 253 | bt_cmd->flags = iwlwifi_mod_params.bt_coex_active ? | 379 | flags = iwlwifi_mod_params.bt_coex_active ? |
| 254 | BT_COEX_NW : BT_COEX_DISABLE; | 380 | BT_COEX_NW : BT_COEX_DISABLE; |
| 255 | bt_cmd->flags |= BT_CH_PRIMARY_EN | BT_SYNC_2_BT_DISABLE; | 381 | flags |= BT_CH_PRIMARY_EN | BT_CH_SECONDARY_EN | BT_SYNC_2_BT_DISABLE; |
| 382 | bt_cmd->flags = cpu_to_le32(flags); | ||
| 256 | 383 | ||
| 257 | bt_cmd->valid_bit_msk = cpu_to_le16(BT_VALID_ENABLE | | 384 | bt_cmd->valid_bit_msk = cpu_to_le32(BT_VALID_ENABLE | |
| 258 | BT_VALID_BT_PRIO_BOOST | | 385 | BT_VALID_BT_PRIO_BOOST | |
| 259 | BT_VALID_MAX_KILL | | 386 | BT_VALID_MAX_KILL | |
| 260 | BT_VALID_3W_TMRS | | 387 | BT_VALID_3W_TMRS | |
| 261 | BT_VALID_KILL_ACK | | 388 | BT_VALID_KILL_ACK | |
| 262 | BT_VALID_KILL_CTS | | 389 | BT_VALID_KILL_CTS | |
| 263 | BT_VALID_REDUCED_TX_POWER | | 390 | BT_VALID_REDUCED_TX_POWER | |
| 264 | BT_VALID_LUT); | 391 | BT_VALID_LUT | |
| 392 | BT_VALID_WIFI_RX_SW_PRIO_BOOST | | ||
| 393 | BT_VALID_WIFI_TX_SW_PRIO_BOOST | | ||
| 394 | BT_VALID_MULTI_PRIO_LUT | | ||
| 395 | BT_VALID_CORUN_LUT_20 | | ||
| 396 | BT_VALID_CORUN_LUT_40 | | ||
| 397 | BT_VALID_ANT_ISOLATION | | ||
| 398 | BT_VALID_ANT_ISOLATION_THRS | | ||
| 399 | BT_VALID_TXTX_DELTA_FREQ_THRS | | ||
| 400 | BT_VALID_TXRX_MAX_FREQ_0); | ||
| 265 | 401 | ||
| 266 | if (mvm->cfg->bt_shared_single_ant) | 402 | if (mvm->cfg->bt_shared_single_ant) |
| 267 | memcpy(&bt_cmd->decision_lut, iwl_single_shared_ant_lookup, | 403 | memcpy(&bt_cmd->decision_lut, iwl_single_shared_ant, |
| 268 | sizeof(iwl_single_shared_ant_lookup)); | 404 | sizeof(iwl_single_shared_ant)); |
| 269 | else if (is_loose_coex()) | ||
| 270 | memcpy(&bt_cmd->decision_lut, iwl_loose_lookup, | ||
| 271 | sizeof(iwl_tight_lookup)); | ||
| 272 | else | 405 | else |
| 273 | memcpy(&bt_cmd->decision_lut, iwl_tight_lookup, | 406 | memcpy(&bt_cmd->decision_lut, iwl_combined_lookup, |
| 274 | sizeof(iwl_tight_lookup)); | 407 | sizeof(iwl_combined_lookup)); |
| 275 | 408 | ||
| 276 | bt_cmd->bt_prio_boost = cpu_to_le32(IWL_BT_DEFAULT_BOOST); | 409 | memcpy(&bt_cmd->bt_prio_boost, iwl_bt_prio_boost, |
| 410 | sizeof(iwl_bt_prio_boost)); | ||
| 411 | memcpy(&bt_cmd->bt4_multiprio_lut, iwl_bt_mprio_lut, | ||
| 412 | sizeof(iwl_bt_mprio_lut)); | ||
| 277 | bt_cmd->kill_ack_msk = | 413 | bt_cmd->kill_ack_msk = |
| 278 | cpu_to_le32(iwl_bt_ack_kill_msk[BT_KILL_MSK_DEFAULT]); | 414 | cpu_to_le32(iwl_bt_ack_kill_msk[BT_KILL_MSK_DEFAULT]); |
| 279 | bt_cmd->kill_cts_msk = | 415 | bt_cmd->kill_cts_msk = |
| 280 | cpu_to_le32(iwl_bt_cts_kill_msk[BT_KILL_MSK_DEFAULT]); | 416 | cpu_to_le32(iwl_bt_cts_kill_msk[BT_KILL_MSK_DEFAULT]); |
| 281 | 417 | ||
| 282 | memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif)); | 418 | memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif)); |
| 419 | memset(&mvm->last_bt_ci_cmd, 0, sizeof(mvm->last_bt_ci_cmd)); | ||
| 283 | 420 | ||
| 284 | ret = iwl_mvm_send_cmd(mvm, &cmd); | 421 | ret = iwl_mvm_send_cmd(mvm, &cmd); |
| 285 | 422 | ||
| @@ -334,13 +471,17 @@ static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm, | |||
| 334 | if (!bt_cmd) | 471 | if (!bt_cmd) |
| 335 | return -ENOMEM; | 472 | return -ENOMEM; |
| 336 | cmd.data[0] = bt_cmd; | 473 | cmd.data[0] = bt_cmd; |
| 474 | bt_cmd->flags = cpu_to_le32(BT_COEX_NW); | ||
| 337 | 475 | ||
| 338 | bt_cmd->kill_ack_msk = cpu_to_le32(iwl_bt_ack_kill_msk[bt_kill_msk]); | 476 | bt_cmd->kill_ack_msk = cpu_to_le32(iwl_bt_ack_kill_msk[bt_kill_msk]); |
| 339 | bt_cmd->kill_cts_msk = cpu_to_le32(iwl_bt_cts_kill_msk[bt_kill_msk]); | 477 | bt_cmd->kill_cts_msk = cpu_to_le32(iwl_bt_cts_kill_msk[bt_kill_msk]); |
| 340 | bt_cmd->valid_bit_msk = | 478 | bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_ENABLE | |
| 341 | cpu_to_le16(BT_VALID_KILL_ACK | BT_VALID_KILL_CTS); | 479 | BT_VALID_KILL_ACK | |
| 480 | BT_VALID_KILL_CTS); | ||
| 342 | 481 | ||
| 343 | IWL_DEBUG_COEX(mvm, "bt_kill_msk = %d\n", bt_kill_msk); | 482 | IWL_DEBUG_COEX(mvm, "ACK Kill msk = 0x%08x, CTS Kill msk = 0x%08x\n", |
| 483 | iwl_bt_ack_kill_msk[bt_kill_msk], | ||
| 484 | iwl_bt_cts_kill_msk[bt_kill_msk]); | ||
| 344 | 485 | ||
| 345 | ret = iwl_mvm_send_cmd(mvm, &cmd); | 486 | ret = iwl_mvm_send_cmd(mvm, &cmd); |
| 346 | 487 | ||
| @@ -380,8 +521,10 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, | |||
| 380 | if (!bt_cmd) | 521 | if (!bt_cmd) |
| 381 | return -ENOMEM; | 522 | return -ENOMEM; |
| 382 | cmd.data[0] = bt_cmd; | 523 | cmd.data[0] = bt_cmd; |
| 524 | bt_cmd->flags = cpu_to_le32(BT_COEX_NW); | ||
| 383 | 525 | ||
| 384 | bt_cmd->valid_bit_msk = cpu_to_le16(BT_VALID_REDUCED_TX_POWER), | 526 | bt_cmd->valid_bit_msk = |
| 527 | cpu_to_le32(BT_VALID_ENABLE | BT_VALID_REDUCED_TX_POWER); | ||
| 385 | bt_cmd->bt_reduced_tx_power = sta_id; | 528 | bt_cmd->bt_reduced_tx_power = sta_id; |
| 386 | 529 | ||
| 387 | if (enable) | 530 | if (enable) |
| @@ -403,8 +546,25 @@ struct iwl_bt_iterator_data { | |||
| 403 | struct iwl_mvm *mvm; | 546 | struct iwl_mvm *mvm; |
| 404 | u32 num_bss_ifaces; | 547 | u32 num_bss_ifaces; |
| 405 | bool reduced_tx_power; | 548 | bool reduced_tx_power; |
| 549 | struct ieee80211_chanctx_conf *primary; | ||
| 550 | struct ieee80211_chanctx_conf *secondary; | ||
| 406 | }; | 551 | }; |
| 407 | 552 | ||
| 553 | static inline | ||
| 554 | void iwl_mvm_bt_coex_enable_rssi_event(struct iwl_mvm *mvm, | ||
| 555 | struct ieee80211_vif *vif, | ||
| 556 | bool enable, int rssi) | ||
| 557 | { | ||
| 558 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
| 559 | |||
| 560 | mvmvif->bf_data.last_bt_coex_event = rssi; | ||
| 561 | mvmvif->bf_data.bt_coex_max_thold = | ||
| 562 | enable ? BT_ENABLE_REDUCED_TXPOWER_THRESHOLD : 0; | ||
| 563 | mvmvif->bf_data.bt_coex_min_thold = | ||
| 564 | enable ? BT_DISABLE_REDUCED_TXPOWER_THRESHOLD : 0; | ||
| 565 | } | ||
| 566 | |||
| 567 | /* must be called under rcu_read_lock */ | ||
| 408 | static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, | 568 | static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, |
| 409 | struct ieee80211_vif *vif) | 569 | struct ieee80211_vif *vif) |
| 410 | { | 570 | { |
| @@ -413,65 +573,94 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, | |||
| 413 | struct iwl_mvm *mvm = data->mvm; | 573 | struct iwl_mvm *mvm = data->mvm; |
| 414 | struct ieee80211_chanctx_conf *chanctx_conf; | 574 | struct ieee80211_chanctx_conf *chanctx_conf; |
| 415 | enum ieee80211_smps_mode smps_mode; | 575 | enum ieee80211_smps_mode smps_mode; |
| 416 | enum ieee80211_band band; | ||
| 417 | int ave_rssi; | 576 | int ave_rssi; |
| 418 | 577 | ||
| 419 | lockdep_assert_held(&mvm->mutex); | 578 | lockdep_assert_held(&mvm->mutex); |
| 420 | if (vif->type != NL80211_IFTYPE_STATION) | ||
| 421 | return; | ||
| 422 | 579 | ||
| 423 | rcu_read_lock(); | 580 | if (vif->type != NL80211_IFTYPE_STATION && |
| 424 | chanctx_conf = rcu_dereference(vif->chanctx_conf); | 581 | vif->type != NL80211_IFTYPE_AP) |
| 425 | if (chanctx_conf && chanctx_conf->def.chan) | 582 | return; |
| 426 | band = chanctx_conf->def.chan->band; | ||
| 427 | else | ||
| 428 | band = -1; | ||
| 429 | rcu_read_unlock(); | ||
| 430 | 583 | ||
| 431 | smps_mode = IEEE80211_SMPS_AUTOMATIC; | 584 | smps_mode = IEEE80211_SMPS_AUTOMATIC; |
| 432 | 585 | ||
| 433 | /* non associated BSSes aren't to be considered */ | 586 | chanctx_conf = rcu_dereference(vif->chanctx_conf); |
| 434 | if (!vif->bss_conf.assoc) | 587 | |
| 588 | /* If channel context is invalid or not on 2.4GHz .. */ | ||
| 589 | if ((!chanctx_conf || | ||
| 590 | chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ)) { | ||
| 591 | /* ... and it is an associated STATION, relax constraints */ | ||
| 592 | if (vif->type == NL80211_IFTYPE_STATION && vif->bss_conf.assoc) | ||
| 593 | iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, | ||
| 594 | smps_mode); | ||
| 595 | iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0); | ||
| 435 | return; | 596 | return; |
| 597 | } | ||
| 598 | |||
| 599 | /* SoftAP / GO will always be primary */ | ||
| 600 | if (vif->type == NL80211_IFTYPE_AP) { | ||
| 601 | if (!mvmvif->ap_ibss_active) | ||
| 602 | return; | ||
| 603 | |||
| 604 | /* the Ack / Cts kill mask must be default if AP / GO */ | ||
| 605 | data->reduced_tx_power = false; | ||
| 436 | 606 | ||
| 437 | if (band != IEEE80211_BAND_2GHZ) { | 607 | if (chanctx_conf == data->primary) |
| 438 | iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, | 608 | return; |
| 439 | smps_mode); | 609 | |
| 610 | /* downgrade the current primary no matter what its type is */ | ||
| 611 | data->secondary = data->primary; | ||
| 612 | data->primary = chanctx_conf; | ||
| 440 | return; | 613 | return; |
| 441 | } | 614 | } |
| 442 | 615 | ||
| 443 | if (data->notif->bt_status) | 616 | data->num_bss_ifaces++; |
| 444 | smps_mode = IEEE80211_SMPS_DYNAMIC; | 617 | |
| 618 | /* we are now a STA / P2P Client, and take associated ones only */ | ||
| 619 | if (!vif->bss_conf.assoc) | ||
| 620 | return; | ||
| 621 | |||
| 622 | /* STA / P2P Client, try to be primary if first vif */ | ||
| 623 | if (!data->primary || data->primary == chanctx_conf) | ||
| 624 | data->primary = chanctx_conf; | ||
| 625 | else if (!data->secondary) | ||
| 626 | /* if secondary is not NULL, it might be a GO */ | ||
| 627 | data->secondary = chanctx_conf; | ||
| 445 | 628 | ||
| 446 | if (data->notif->bt_traffic_load >= IWL_BT_LOAD_FORCE_SISO_THRESHOLD) | 629 | if (le32_to_cpu(data->notif->bt_activity_grading) >= BT_HIGH_TRAFFIC) |
| 447 | smps_mode = IEEE80211_SMPS_STATIC; | 630 | smps_mode = IEEE80211_SMPS_STATIC; |
| 631 | else if (le32_to_cpu(data->notif->bt_activity_grading) >= | ||
| 632 | BT_LOW_TRAFFIC) | ||
| 633 | smps_mode = IEEE80211_SMPS_DYNAMIC; | ||
| 448 | 634 | ||
| 449 | IWL_DEBUG_COEX(data->mvm, | 635 | IWL_DEBUG_COEX(data->mvm, |
| 450 | "mac %d: bt_status %d traffic_load %d smps_req %d\n", | 636 | "mac %d: bt_status %d bt_activity_grading %d smps_req %d\n", |
| 451 | mvmvif->id, data->notif->bt_status, | 637 | mvmvif->id, data->notif->bt_status, |
| 452 | data->notif->bt_traffic_load, smps_mode); | 638 | data->notif->bt_activity_grading, smps_mode); |
| 453 | 639 | ||
| 454 | iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, smps_mode); | 640 | iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, smps_mode); |
| 455 | 641 | ||
| 456 | /* don't reduce the Tx power if in loose scheme */ | 642 | /* don't reduce the Tx power if in loose scheme */ |
| 457 | if (is_loose_coex()) | 643 | if (iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT || |
| 644 | mvm->cfg->bt_shared_single_ant) { | ||
| 645 | data->reduced_tx_power = false; | ||
| 646 | iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0); | ||
| 458 | return; | 647 | return; |
| 648 | } | ||
| 459 | 649 | ||
| 460 | data->num_bss_ifaces++; | 650 | /* reduced Txpower only if BT is on, so ...*/ |
| 461 | 651 | if (!data->notif->bt_status) { | |
| 462 | /* reduced Txpower only if there are open BT connections, so ...*/ | ||
| 463 | if (!BT_MBOX_MSG(data->notif, 3, OPEN_CON_2)) { | ||
| 464 | /* ... cancel reduced Tx power ... */ | 652 | /* ... cancel reduced Tx power ... */ |
| 465 | if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false)) | 653 | if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false)) |
| 466 | IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n"); | 654 | IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n"); |
| 467 | data->reduced_tx_power = false; | 655 | data->reduced_tx_power = false; |
| 468 | 656 | ||
| 469 | /* ... and there is no need to get reports on RSSI any more. */ | 657 | /* ... and there is no need to get reports on RSSI any more. */ |
| 470 | ieee80211_disable_rssi_reports(vif); | 658 | iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0); |
| 471 | return; | 659 | return; |
| 472 | } | 660 | } |
| 473 | 661 | ||
| 474 | ave_rssi = ieee80211_ave_rssi(vif); | 662 | /* try to get the avg rssi from fw */ |
| 663 | ave_rssi = mvmvif->bf_data.ave_beacon_signal; | ||
| 475 | 664 | ||
| 476 | /* if the RSSI isn't valid, fake it is very low */ | 665 | /* if the RSSI isn't valid, fake it is very low */ |
| 477 | if (!ave_rssi) | 666 | if (!ave_rssi) |
| @@ -499,8 +688,7 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, | |||
| 499 | } | 688 | } |
| 500 | 689 | ||
| 501 | /* Begin to monitor the RSSI: it may influence the reduced Tx power */ | 690 | /* Begin to monitor the RSSI: it may influence the reduced Tx power */ |
| 502 | ieee80211_enable_rssi_reports(vif, BT_DISABLE_REDUCED_TXPOWER_THRESHOLD, | 691 | iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, true, ave_rssi); |
| 503 | BT_ENABLE_REDUCED_TXPOWER_THRESHOLD); | ||
| 504 | } | 692 | } |
| 505 | 693 | ||
| 506 | static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm) | 694 | static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm) |
| @@ -510,11 +698,72 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm) | |||
| 510 | .notif = &mvm->last_bt_notif, | 698 | .notif = &mvm->last_bt_notif, |
| 511 | .reduced_tx_power = true, | 699 | .reduced_tx_power = true, |
| 512 | }; | 700 | }; |
| 701 | struct iwl_bt_coex_ci_cmd cmd = {}; | ||
| 702 | u8 ci_bw_idx; | ||
| 513 | 703 | ||
| 704 | rcu_read_lock(); | ||
| 514 | ieee80211_iterate_active_interfaces_atomic( | 705 | ieee80211_iterate_active_interfaces_atomic( |
| 515 | mvm->hw, IEEE80211_IFACE_ITER_NORMAL, | 706 | mvm->hw, IEEE80211_IFACE_ITER_NORMAL, |
| 516 | iwl_mvm_bt_notif_iterator, &data); | 707 | iwl_mvm_bt_notif_iterator, &data); |
| 517 | 708 | ||
| 709 | if (data.primary) { | ||
| 710 | struct ieee80211_chanctx_conf *chan = data.primary; | ||
| 711 | if (WARN_ON(!chan->def.chan)) { | ||
| 712 | rcu_read_unlock(); | ||
| 713 | return; | ||
| 714 | } | ||
| 715 | |||
| 716 | if (chan->def.width < NL80211_CHAN_WIDTH_40) { | ||
| 717 | ci_bw_idx = 0; | ||
| 718 | cmd.co_run_bw_primary = 0; | ||
| 719 | } else { | ||
| 720 | cmd.co_run_bw_primary = 1; | ||
| 721 | if (chan->def.center_freq1 > | ||
| 722 | chan->def.chan->center_freq) | ||
| 723 | ci_bw_idx = 2; | ||
| 724 | else | ||
| 725 | ci_bw_idx = 1; | ||
| 726 | } | ||
| 727 | |||
| 728 | cmd.bt_primary_ci = | ||
| 729 | iwl_ci_mask[chan->def.chan->hw_value][ci_bw_idx]; | ||
| 730 | cmd.primary_ch_phy_id = *((u16 *)data.primary->drv_priv); | ||
| 731 | } | ||
| 732 | |||
| 733 | if (data.secondary) { | ||
| 734 | struct ieee80211_chanctx_conf *chan = data.secondary; | ||
| 735 | if (WARN_ON(!data.secondary->def.chan)) { | ||
| 736 | rcu_read_unlock(); | ||
| 737 | return; | ||
| 738 | } | ||
| 739 | |||
| 740 | if (chan->def.width < NL80211_CHAN_WIDTH_40) { | ||
| 741 | ci_bw_idx = 0; | ||
| 742 | cmd.co_run_bw_secondary = 0; | ||
| 743 | } else { | ||
| 744 | cmd.co_run_bw_secondary = 1; | ||
| 745 | if (chan->def.center_freq1 > | ||
| 746 | chan->def.chan->center_freq) | ||
| 747 | ci_bw_idx = 2; | ||
| 748 | else | ||
| 749 | ci_bw_idx = 1; | ||
| 750 | } | ||
| 751 | |||
| 752 | cmd.bt_secondary_ci = | ||
| 753 | iwl_ci_mask[chan->def.chan->hw_value][ci_bw_idx]; | ||
| 754 | cmd.secondary_ch_phy_id = *((u16 *)data.primary->drv_priv); | ||
| 755 | } | ||
| 756 | |||
| 757 | rcu_read_unlock(); | ||
| 758 | |||
| 759 | /* Don't spam the fw with the same command over and over */ | ||
| 760 | if (memcmp(&cmd, &mvm->last_bt_ci_cmd, sizeof(cmd))) { | ||
| 761 | if (iwl_mvm_send_cmd_pdu(mvm, BT_COEX_CI, CMD_SYNC, | ||
| 762 | sizeof(cmd), &cmd)) | ||
| 763 | IWL_ERR(mvm, "Failed to send BT_CI cmd"); | ||
| 764 | memcpy(&mvm->last_bt_ci_cmd, &cmd, sizeof(cmd)); | ||
| 765 | } | ||
| 766 | |||
| 518 | /* | 767 | /* |
| 519 | * If there are no BSS / P2P client interfaces, reduced Tx Power is | 768 | * If there are no BSS / P2P client interfaces, reduced Tx Power is |
| 520 | * irrelevant since it is based on the RSSI coming from the beacon. | 769 | * irrelevant since it is based on the RSSI coming from the beacon. |
| @@ -536,12 +785,18 @@ int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm, | |||
| 536 | 785 | ||
| 537 | 786 | ||
| 538 | IWL_DEBUG_COEX(mvm, "BT Coex Notification received\n"); | 787 | IWL_DEBUG_COEX(mvm, "BT Coex Notification received\n"); |
| 539 | IWL_DEBUG_COEX(mvm, "\tBT %salive\n", notif->bt_status ? "" : "not "); | 788 | IWL_DEBUG_COEX(mvm, "\tBT status: %s\n", |
| 789 | notif->bt_status ? "ON" : "OFF"); | ||
| 540 | IWL_DEBUG_COEX(mvm, "\tBT open conn %d\n", notif->bt_open_conn); | 790 | IWL_DEBUG_COEX(mvm, "\tBT open conn %d\n", notif->bt_open_conn); |
| 541 | IWL_DEBUG_COEX(mvm, "\tBT traffic load %d\n", notif->bt_traffic_load); | 791 | IWL_DEBUG_COEX(mvm, "\tBT ci compliance %d\n", notif->bt_ci_compliance); |
| 792 | IWL_DEBUG_COEX(mvm, "\tBT primary_ch_lut %d\n", | ||
| 793 | le32_to_cpu(notif->primary_ch_lut)); | ||
| 794 | IWL_DEBUG_COEX(mvm, "\tBT secondary_ch_lut %d\n", | ||
| 795 | le32_to_cpu(notif->secondary_ch_lut)); | ||
| 796 | IWL_DEBUG_COEX(mvm, "\tBT activity grading %d\n", | ||
| 797 | le32_to_cpu(notif->bt_activity_grading)); | ||
| 542 | IWL_DEBUG_COEX(mvm, "\tBT agg traffic load %d\n", | 798 | IWL_DEBUG_COEX(mvm, "\tBT agg traffic load %d\n", |
| 543 | notif->bt_agg_traffic_load); | 799 | notif->bt_agg_traffic_load); |
| 544 | IWL_DEBUG_COEX(mvm, "\tBT ci compliance %d\n", notif->bt_ci_compliance); | ||
| 545 | 800 | ||
| 546 | /* remember this notification for future use: rssi fluctuations */ | 801 | /* remember this notification for future use: rssi fluctuations */ |
| 547 | memcpy(&mvm->last_bt_notif, notif, sizeof(mvm->last_bt_notif)); | 802 | memcpy(&mvm->last_bt_notif, notif, sizeof(mvm->last_bt_notif)); |
| @@ -565,6 +820,18 @@ static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac, | |||
| 565 | struct ieee80211_sta *sta; | 820 | struct ieee80211_sta *sta; |
| 566 | struct iwl_mvm_sta *mvmsta; | 821 | struct iwl_mvm_sta *mvmsta; |
| 567 | 822 | ||
| 823 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
| 824 | |||
| 825 | rcu_read_lock(); | ||
| 826 | chanctx_conf = rcu_dereference(vif->chanctx_conf); | ||
| 827 | /* If channel context is invalid or not on 2.4GHz - don't count it */ | ||
| 828 | if (!chanctx_conf || | ||
| 829 | chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ) { | ||
| 830 | rcu_read_unlock(); | ||
| 831 | return; | ||
| 832 | } | ||
| 833 | rcu_read_unlock(); | ||
| 834 | |||
| 568 | if (vif->type != NL80211_IFTYPE_STATION || | 835 | if (vif->type != NL80211_IFTYPE_STATION || |
| 569 | mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT) | 836 | mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT) |
| 570 | return; | 837 | return; |
| @@ -594,15 +861,15 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
| 594 | }; | 861 | }; |
| 595 | int ret; | 862 | int ret; |
| 596 | 863 | ||
| 597 | mutex_lock(&mvm->mutex); | 864 | lockdep_assert_held(&mvm->mutex); |
| 598 | 865 | ||
| 599 | /* Rssi update while not associated ?! */ | 866 | /* Rssi update while not associated ?! */ |
| 600 | if (WARN_ON_ONCE(mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT)) | 867 | if (WARN_ON_ONCE(mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT)) |
| 601 | goto out_unlock; | 868 | return; |
| 602 | 869 | ||
| 603 | /* No open connection - reports should be disabled */ | 870 | /* No BT - reports should be disabled */ |
| 604 | if (!BT_MBOX_MSG(&mvm->last_bt_notif, 3, OPEN_CON_2)) | 871 | if (!mvm->last_bt_notif.bt_status) |
| 605 | goto out_unlock; | 872 | return; |
| 606 | 873 | ||
| 607 | IWL_DEBUG_COEX(mvm, "RSSI for %pM is now %s\n", vif->bss_conf.bssid, | 874 | IWL_DEBUG_COEX(mvm, "RSSI for %pM is now %s\n", vif->bss_conf.bssid, |
| 608 | rssi_event == RSSI_EVENT_HIGH ? "HIGH" : "LOW"); | 875 | rssi_event == RSSI_EVENT_HIGH ? "HIGH" : "LOW"); |
| @@ -611,7 +878,8 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
| 611 | * Check if rssi is good enough for reduced Tx power, but not in loose | 878 | * Check if rssi is good enough for reduced Tx power, but not in loose |
| 612 | * scheme. | 879 | * scheme. |
| 613 | */ | 880 | */ |
| 614 | if (rssi_event == RSSI_EVENT_LOW || is_loose_coex()) | 881 | if (rssi_event == RSSI_EVENT_LOW || mvm->cfg->bt_shared_single_ant || |
| 882 | iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT) | ||
| 615 | ret = iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, | 883 | ret = iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, |
| 616 | false); | 884 | false); |
| 617 | else | 885 | else |
| @@ -633,12 +901,52 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
| 633 | 901 | ||
| 634 | if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm, data.reduced_tx_power)) | 902 | if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm, data.reduced_tx_power)) |
| 635 | IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n"); | 903 | IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n"); |
| 904 | } | ||
| 905 | |||
| 906 | #define LINK_QUAL_AGG_TIME_LIMIT_DEF (4000) | ||
| 907 | #define LINK_QUAL_AGG_TIME_LIMIT_BT_ACT (1200) | ||
| 636 | 908 | ||
| 637 | out_unlock: | 909 | u16 iwl_mvm_bt_coex_agg_time_limit(struct iwl_mvm *mvm, |
| 638 | mutex_unlock(&mvm->mutex); | 910 | struct ieee80211_sta *sta) |
| 911 | { | ||
| 912 | struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv; | ||
| 913 | enum iwl_bt_coex_lut_type lut_type; | ||
| 914 | |||
| 915 | if (le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) < | ||
| 916 | BT_LOW_TRAFFIC) | ||
| 917 | return LINK_QUAL_AGG_TIME_LIMIT_DEF; | ||
| 918 | |||
| 919 | lut_type = iwl_get_coex_type(mvm, mvmsta->vif); | ||
| 920 | |||
| 921 | if (lut_type == BT_COEX_LOOSE_LUT) | ||
| 922 | return LINK_QUAL_AGG_TIME_LIMIT_DEF; | ||
| 923 | |||
| 924 | /* tight coex, high bt traffic, reduce AGG time limit */ | ||
| 925 | return LINK_QUAL_AGG_TIME_LIMIT_BT_ACT; | ||
| 926 | } | ||
| 927 | |||
| 928 | bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm, | ||
| 929 | struct ieee80211_sta *sta) | ||
| 930 | { | ||
| 931 | struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv; | ||
| 932 | |||
| 933 | if (le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) < | ||
| 934 | BT_HIGH_TRAFFIC) | ||
| 935 | return true; | ||
| 936 | |||
| 937 | /* | ||
| 938 | * In Tight, BT can't Rx while we Tx, so use both antennas since BT is | ||
| 939 | * already killed. | ||
| 940 | * In Loose, BT can Rx while we Tx, so forbid MIMO to let BT Rx while we | ||
| 941 | * Tx. | ||
| 942 | */ | ||
| 943 | return iwl_get_coex_type(mvm, mvmsta->vif) == BT_COEX_TIGHT_LUT; | ||
| 639 | } | 944 | } |
| 640 | 945 | ||
| 641 | void iwl_mvm_bt_coex_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | 946 | void iwl_mvm_bt_coex_vif_change(struct iwl_mvm *mvm) |
| 642 | { | 947 | { |
| 948 | if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWBT_COEX)) | ||
| 949 | return; | ||
| 950 | |||
| 643 | iwl_mvm_bt_coex_notif_handle(mvm); | 951 | iwl_mvm_bt_coex_notif_handle(mvm); |
| 644 | } | 952 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/constants.h b/drivers/net/wireless/iwlwifi/mvm/constants.h index 2bf29f7992ee..4b6d670c3509 100644 --- a/drivers/net/wireless/iwlwifi/mvm/constants.h +++ b/drivers/net/wireless/iwlwifi/mvm/constants.h | |||
| @@ -70,7 +70,9 @@ | |||
| 70 | #define IWL_MVM_UAPSD_RX_DATA_TIMEOUT (50 * USEC_PER_MSEC) | 70 | #define IWL_MVM_UAPSD_RX_DATA_TIMEOUT (50 * USEC_PER_MSEC) |
| 71 | #define IWL_MVM_UAPSD_TX_DATA_TIMEOUT (50 * USEC_PER_MSEC) | 71 | #define IWL_MVM_UAPSD_TX_DATA_TIMEOUT (50 * USEC_PER_MSEC) |
| 72 | #define IWL_MVM_PS_HEAVY_TX_THLD_PACKETS 20 | 72 | #define IWL_MVM_PS_HEAVY_TX_THLD_PACKETS 20 |
| 73 | #define IWL_MVM_PS_HEAVY_RX_THLD_PACKETS 20 | 73 | #define IWL_MVM_PS_HEAVY_RX_THLD_PACKETS 8 |
| 74 | #define IWL_MVM_PS_SNOOZE_HEAVY_TX_THLD_PACKETS 30 | ||
| 75 | #define IWL_MVM_PS_SNOOZE_HEAVY_RX_THLD_PACKETS 20 | ||
| 74 | #define IWL_MVM_PS_HEAVY_TX_THLD_PERCENT 50 | 76 | #define IWL_MVM_PS_HEAVY_TX_THLD_PERCENT 50 |
| 75 | #define IWL_MVM_PS_HEAVY_RX_THLD_PERCENT 50 | 77 | #define IWL_MVM_PS_HEAVY_RX_THLD_PERCENT 50 |
| 76 | #define IWL_MVM_PS_SNOOZE_INTERVAL 25 | 78 | #define IWL_MVM_PS_SNOOZE_INTERVAL 25 |
diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c index 417639f77b01..6f45966817bb 100644 --- a/drivers/net/wireless/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/iwlwifi/mvm/d3.c | |||
| @@ -67,6 +67,7 @@ | |||
| 67 | #include <net/cfg80211.h> | 67 | #include <net/cfg80211.h> |
| 68 | #include <net/ipv6.h> | 68 | #include <net/ipv6.h> |
| 69 | #include <net/tcp.h> | 69 | #include <net/tcp.h> |
| 70 | #include <net/addrconf.h> | ||
| 70 | #include "iwl-modparams.h" | 71 | #include "iwl-modparams.h" |
| 71 | #include "fw-api.h" | 72 | #include "fw-api.h" |
| 72 | #include "mvm.h" | 73 | #include "mvm.h" |
| @@ -381,14 +382,74 @@ static int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm, | |||
| 381 | union { | 382 | union { |
| 382 | struct iwl_proto_offload_cmd_v1 v1; | 383 | struct iwl_proto_offload_cmd_v1 v1; |
| 383 | struct iwl_proto_offload_cmd_v2 v2; | 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; | ||
| 384 | } cmd = {}; | 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 | }; | ||
| 385 | struct iwl_proto_offload_cmd_common *common; | 394 | struct iwl_proto_offload_cmd_common *common; |
| 386 | u32 enabled = 0, size; | 395 | u32 enabled = 0, size; |
| 396 | u32 capa_flags = mvm->fw->ucode_capa.flags; | ||
| 387 | #if IS_ENABLED(CONFIG_IPV6) | 397 | #if IS_ENABLED(CONFIG_IPV6) |
| 388 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 398 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
| 389 | int i; | 399 | int i; |
| 390 | 400 | ||
| 391 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS) { | 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) { | ||
| 392 | if (mvmvif->num_target_ipv6_addrs) { | 453 | if (mvmvif->num_target_ipv6_addrs) { |
| 393 | enabled |= IWL_D3_PROTO_OFFLOAD_NS; | 454 | enabled |= IWL_D3_PROTO_OFFLOAD_NS; |
| 394 | memcpy(cmd.v2.ndp_mac_addr, vif->addr, ETH_ALEN); | 455 | memcpy(cmd.v2.ndp_mac_addr, vif->addr, ETH_ALEN); |
| @@ -419,7 +480,13 @@ static int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm, | |||
| 419 | } | 480 | } |
| 420 | #endif | 481 | #endif |
| 421 | 482 | ||
| 422 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS) { | 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) { | ||
| 423 | common = &cmd.v2.common; | 490 | common = &cmd.v2.common; |
| 424 | size = sizeof(cmd.v2); | 491 | size = sizeof(cmd.v2); |
| 425 | } else { | 492 | } else { |
| @@ -438,8 +505,8 @@ static int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm, | |||
| 438 | 505 | ||
| 439 | common->enabled = cpu_to_le32(enabled); | 506 | common->enabled = cpu_to_le32(enabled); |
| 440 | 507 | ||
| 441 | return iwl_mvm_send_cmd_pdu(mvm, PROT_OFFLOAD_CONFIG_CMD, CMD_SYNC, | 508 | hcmd.len[0] = size; |
| 442 | size, &cmd); | 509 | return iwl_mvm_send_cmd(mvm, &hcmd); |
| 443 | } | 510 | } |
| 444 | 511 | ||
| 445 | enum iwl_mvm_tcp_packet_type { | 512 | enum iwl_mvm_tcp_packet_type { |
| @@ -793,6 +860,74 @@ static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
| 793 | return 0; | 860 | return 0; |
| 794 | } | 861 | } |
| 795 | 862 | ||
| 863 | static int iwl_mvm_get_last_nonqos_seq(struct iwl_mvm *mvm, | ||
| 864 | struct ieee80211_vif *vif) | ||
| 865 | { | ||
| 866 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
| 867 | struct iwl_nonqos_seq_query_cmd query_cmd = { | ||
| 868 | .get_set_flag = cpu_to_le32(IWL_NONQOS_SEQ_GET), | ||
| 869 | .mac_id_n_color = | ||
| 870 | cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, | ||
| 871 | mvmvif->color)), | ||
| 872 | }; | ||
| 873 | struct iwl_host_cmd cmd = { | ||
| 874 | .id = NON_QOS_TX_COUNTER_CMD, | ||
| 875 | .flags = CMD_SYNC | CMD_WANT_SKB, | ||
| 876 | }; | ||
| 877 | int err; | ||
| 878 | u32 size; | ||
| 879 | |||
| 880 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_D3_CONTINUITY_API) { | ||
| 881 | cmd.data[0] = &query_cmd; | ||
| 882 | cmd.len[0] = sizeof(query_cmd); | ||
| 883 | } | ||
| 884 | |||
| 885 | err = iwl_mvm_send_cmd(mvm, &cmd); | ||
| 886 | if (err) | ||
| 887 | return err; | ||
| 888 | |||
| 889 | size = le32_to_cpu(cmd.resp_pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | ||
| 890 | size -= sizeof(cmd.resp_pkt->hdr); | ||
| 891 | if (size < sizeof(__le16)) { | ||
| 892 | err = -EINVAL; | ||
| 893 | } else { | ||
| 894 | err = le16_to_cpup((__le16 *)cmd.resp_pkt->data); | ||
| 895 | /* new API returns next, not last-used seqno */ | ||
| 896 | if (mvm->fw->ucode_capa.flags & | ||
| 897 | IWL_UCODE_TLV_FLAGS_D3_CONTINUITY_API) | ||
| 898 | err -= 0x10; | ||
| 899 | } | ||
| 900 | |||
| 901 | iwl_free_resp(&cmd); | ||
| 902 | return err; | ||
| 903 | } | ||
| 904 | |||
| 905 | void iwl_mvm_set_last_nonqos_seq(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | ||
| 906 | { | ||
| 907 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
| 908 | struct iwl_nonqos_seq_query_cmd query_cmd = { | ||
| 909 | .get_set_flag = cpu_to_le32(IWL_NONQOS_SEQ_SET), | ||
| 910 | .mac_id_n_color = | ||
| 911 | cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, | ||
| 912 | mvmvif->color)), | ||
| 913 | .value = cpu_to_le16(mvmvif->seqno), | ||
| 914 | }; | ||
| 915 | |||
| 916 | /* return if called during restart, not resume from D3 */ | ||
| 917 | if (!mvmvif->seqno_valid) | ||
| 918 | return; | ||
| 919 | |||
| 920 | mvmvif->seqno_valid = false; | ||
| 921 | |||
| 922 | if (!(mvm->fw->ucode_capa.flags & | ||
| 923 | IWL_UCODE_TLV_FLAGS_D3_CONTINUITY_API)) | ||
| 924 | return; | ||
| 925 | |||
| 926 | if (iwl_mvm_send_cmd_pdu(mvm, NON_QOS_TX_COUNTER_CMD, CMD_SYNC, | ||
| 927 | sizeof(query_cmd), &query_cmd)) | ||
| 928 | IWL_ERR(mvm, "failed to set non-QoS seqno\n"); | ||
| 929 | } | ||
| 930 | |||
| 796 | static int __iwl_mvm_suspend(struct ieee80211_hw *hw, | 931 | static int __iwl_mvm_suspend(struct ieee80211_hw *hw, |
| 797 | struct cfg80211_wowlan *wowlan, | 932 | struct cfg80211_wowlan *wowlan, |
| 798 | bool test) | 933 | bool test) |
| @@ -829,7 +964,6 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, | |||
| 829 | }; | 964 | }; |
| 830 | int ret, i; | 965 | int ret, i; |
| 831 | int len __maybe_unused; | 966 | int len __maybe_unused; |
| 832 | u16 seq; | ||
| 833 | u8 old_aux_sta_id, old_ap_sta_id = IWL_MVM_STATION_COUNT; | 967 | u8 old_aux_sta_id, old_ap_sta_id = IWL_MVM_STATION_COUNT; |
| 834 | 968 | ||
| 835 | if (!wowlan) { | 969 | if (!wowlan) { |
| @@ -872,26 +1006,15 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, | |||
| 872 | 1006 | ||
| 873 | mvm_ap_sta = (struct iwl_mvm_sta *)ap_sta->drv_priv; | 1007 | mvm_ap_sta = (struct iwl_mvm_sta *)ap_sta->drv_priv; |
| 874 | 1008 | ||
| 875 | /* | ||
| 876 | * The D3 firmware still hardcodes the AP station ID for the | ||
| 877 | * BSS we're associated with as 0. Store the real STA ID here | ||
| 878 | * and assign 0. When we leave this function, we'll restore | ||
| 879 | * the original value for the resume code. | ||
| 880 | */ | ||
| 881 | old_ap_sta_id = mvm_ap_sta->sta_id; | ||
| 882 | mvm_ap_sta->sta_id = 0; | ||
| 883 | mvmvif->ap_sta_id = 0; | ||
| 884 | |||
| 885 | /* TODO: wowlan_config_cmd.wowlan_ba_teardown_tids */ | 1009 | /* TODO: wowlan_config_cmd.wowlan_ba_teardown_tids */ |
| 886 | 1010 | ||
| 887 | wowlan_config_cmd.is_11n_connection = ap_sta->ht_cap.ht_supported; | 1011 | wowlan_config_cmd.is_11n_connection = ap_sta->ht_cap.ht_supported; |
| 888 | 1012 | ||
| 889 | /* | 1013 | /* Query the last used seqno and set it */ |
| 890 | * We know the last used seqno, and the uCode expects to know that | 1014 | ret = iwl_mvm_get_last_nonqos_seq(mvm, vif); |
| 891 | * one, it will increment before TX. | 1015 | if (ret < 0) |
| 892 | */ | 1016 | goto out_noreset; |
| 893 | seq = mvm_ap_sta->last_seq_ctl & IEEE80211_SCTL_SEQ; | 1017 | wowlan_config_cmd.non_qos_seq = cpu_to_le16(ret); |
| 894 | wowlan_config_cmd.non_qos_seq = cpu_to_le16(seq); | ||
| 895 | 1018 | ||
| 896 | /* | 1019 | /* |
| 897 | * For QoS counters, we store the one to use next, so subtract 0x10 | 1020 | * For QoS counters, we store the one to use next, so subtract 0x10 |
| @@ -899,7 +1022,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, | |||
| 899 | * increment after using the value (i.e. store the next value to use). | 1022 | * increment after using the value (i.e. store the next value to use). |
| 900 | */ | 1023 | */ |
| 901 | for (i = 0; i < IWL_MAX_TID_COUNT; i++) { | 1024 | for (i = 0; i < IWL_MAX_TID_COUNT; i++) { |
| 902 | seq = mvm_ap_sta->tid_data[i].seq_number; | 1025 | u16 seq = mvm_ap_sta->tid_data[i].seq_number; |
| 903 | seq -= 0x10; | 1026 | seq -= 0x10; |
| 904 | wowlan_config_cmd.qos_seq[i] = cpu_to_le16(seq); | 1027 | wowlan_config_cmd.qos_seq[i] = cpu_to_le16(seq); |
| 905 | } | 1028 | } |
| @@ -945,6 +1068,16 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, | |||
| 945 | iwl_trans_stop_device(mvm->trans); | 1068 | iwl_trans_stop_device(mvm->trans); |
| 946 | 1069 | ||
| 947 | /* | 1070 | /* |
| 1071 | * The D3 firmware still hardcodes the AP station ID for the | ||
| 1072 | * BSS we're associated with as 0. Store the real STA ID here | ||
| 1073 | * and assign 0. When we leave this function, we'll restore | ||
| 1074 | * the original value for the resume code. | ||
| 1075 | */ | ||
| 1076 | old_ap_sta_id = mvm_ap_sta->sta_id; | ||
| 1077 | mvm_ap_sta->sta_id = 0; | ||
| 1078 | mvmvif->ap_sta_id = 0; | ||
| 1079 | |||
| 1080 | /* | ||
| 948 | * Set the HW restart bit -- this is mostly true as we're | 1081 | * Set the HW restart bit -- this is mostly true as we're |
| 949 | * going to load new firmware and reprogram that, though | 1082 | * going to load new firmware and reprogram that, though |
| 950 | * the reprogramming is going to be manual to avoid adding | 1083 | * the reprogramming is going to be manual to avoid adding |
| @@ -1059,6 +1192,10 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, | |||
| 1059 | if (ret) | 1192 | if (ret) |
| 1060 | goto out; | 1193 | goto out; |
| 1061 | 1194 | ||
| 1195 | ret = iwl_mvm_power_update_device_mode(mvm); | ||
| 1196 | if (ret) | ||
| 1197 | goto out; | ||
| 1198 | |||
| 1062 | ret = iwl_mvm_power_update_mode(mvm, vif); | 1199 | ret = iwl_mvm_power_update_mode(mvm, vif); |
| 1063 | if (ret) | 1200 | if (ret) |
| 1064 | goto out; | 1201 | goto out; |
| @@ -1109,16 +1246,26 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
| 1109 | return __iwl_mvm_suspend(hw, wowlan, false); | 1246 | return __iwl_mvm_suspend(hw, wowlan, false); |
| 1110 | } | 1247 | } |
| 1111 | 1248 | ||
| 1249 | /* converted data from the different status responses */ | ||
| 1250 | struct iwl_wowlan_status_data { | ||
| 1251 | u16 pattern_number; | ||
| 1252 | u16 qos_seq_ctr[8]; | ||
| 1253 | u32 wakeup_reasons; | ||
| 1254 | u32 wake_packet_length; | ||
| 1255 | u32 wake_packet_bufsize; | ||
| 1256 | const u8 *wake_packet; | ||
| 1257 | }; | ||
| 1258 | |||
| 1112 | static void iwl_mvm_report_wakeup_reasons(struct iwl_mvm *mvm, | 1259 | static void iwl_mvm_report_wakeup_reasons(struct iwl_mvm *mvm, |
| 1113 | struct ieee80211_vif *vif, | 1260 | struct ieee80211_vif *vif, |
| 1114 | struct iwl_wowlan_status *status) | 1261 | struct iwl_wowlan_status_data *status) |
| 1115 | { | 1262 | { |
| 1116 | struct sk_buff *pkt = NULL; | 1263 | struct sk_buff *pkt = NULL; |
| 1117 | struct cfg80211_wowlan_wakeup wakeup = { | 1264 | struct cfg80211_wowlan_wakeup wakeup = { |
| 1118 | .pattern_idx = -1, | 1265 | .pattern_idx = -1, |
| 1119 | }; | 1266 | }; |
| 1120 | struct cfg80211_wowlan_wakeup *wakeup_report = &wakeup; | 1267 | struct cfg80211_wowlan_wakeup *wakeup_report = &wakeup; |
| 1121 | u32 reasons = le32_to_cpu(status->wakeup_reasons); | 1268 | u32 reasons = status->wakeup_reasons; |
| 1122 | 1269 | ||
| 1123 | if (reasons == IWL_WOWLAN_WAKEUP_BY_NON_WIRELESS) { | 1270 | if (reasons == IWL_WOWLAN_WAKEUP_BY_NON_WIRELESS) { |
| 1124 | wakeup_report = NULL; | 1271 | wakeup_report = NULL; |
| @@ -1130,7 +1277,7 @@ static void iwl_mvm_report_wakeup_reasons(struct iwl_mvm *mvm, | |||
| 1130 | 1277 | ||
| 1131 | if (reasons & IWL_WOWLAN_WAKEUP_BY_PATTERN) | 1278 | if (reasons & IWL_WOWLAN_WAKEUP_BY_PATTERN) |
| 1132 | wakeup.pattern_idx = | 1279 | wakeup.pattern_idx = |
| 1133 | le16_to_cpu(status->pattern_number); | 1280 | status->pattern_number; |
| 1134 | 1281 | ||
| 1135 | if (reasons & (IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_MISSED_BEACON | | 1282 | if (reasons & (IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_MISSED_BEACON | |
| 1136 | IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_DEAUTH)) | 1283 | IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_DEAUTH)) |
| @@ -1158,8 +1305,8 @@ static void iwl_mvm_report_wakeup_reasons(struct iwl_mvm *mvm, | |||
| 1158 | wakeup.tcp_match = true; | 1305 | wakeup.tcp_match = true; |
| 1159 | 1306 | ||
| 1160 | if (status->wake_packet_bufsize) { | 1307 | if (status->wake_packet_bufsize) { |
| 1161 | int pktsize = le32_to_cpu(status->wake_packet_bufsize); | 1308 | int pktsize = status->wake_packet_bufsize; |
| 1162 | int pktlen = le32_to_cpu(status->wake_packet_length); | 1309 | int pktlen = status->wake_packet_length; |
| 1163 | const u8 *pktdata = status->wake_packet; | 1310 | const u8 *pktdata = status->wake_packet; |
| 1164 | struct ieee80211_hdr *hdr = (void *)pktdata; | 1311 | struct ieee80211_hdr *hdr = (void *)pktdata; |
| 1165 | int truncated = pktlen - pktsize; | 1312 | int truncated = pktlen - pktsize; |
| @@ -1239,8 +1386,229 @@ static void iwl_mvm_report_wakeup_reasons(struct iwl_mvm *mvm, | |||
| 1239 | kfree_skb(pkt); | 1386 | kfree_skb(pkt); |
| 1240 | } | 1387 | } |
| 1241 | 1388 | ||
| 1389 | static void iwl_mvm_aes_sc_to_seq(struct aes_sc *sc, | ||
| 1390 | struct ieee80211_key_seq *seq) | ||
| 1391 | { | ||
| 1392 | u64 pn; | ||
| 1393 | |||
| 1394 | pn = le64_to_cpu(sc->pn); | ||
| 1395 | seq->ccmp.pn[0] = pn >> 40; | ||
| 1396 | seq->ccmp.pn[1] = pn >> 32; | ||
| 1397 | seq->ccmp.pn[2] = pn >> 24; | ||
| 1398 | seq->ccmp.pn[3] = pn >> 16; | ||
| 1399 | seq->ccmp.pn[4] = pn >> 8; | ||
| 1400 | seq->ccmp.pn[5] = pn; | ||
| 1401 | } | ||
| 1402 | |||
| 1403 | static void iwl_mvm_tkip_sc_to_seq(struct tkip_sc *sc, | ||
| 1404 | struct ieee80211_key_seq *seq) | ||
| 1405 | { | ||
| 1406 | seq->tkip.iv32 = le32_to_cpu(sc->iv32); | ||
| 1407 | seq->tkip.iv16 = le16_to_cpu(sc->iv16); | ||
| 1408 | } | ||
| 1409 | |||
| 1410 | static void iwl_mvm_set_aes_rx_seq(struct aes_sc *scs, | ||
| 1411 | struct ieee80211_key_conf *key) | ||
| 1412 | { | ||
| 1413 | int tid; | ||
| 1414 | |||
| 1415 | BUILD_BUG_ON(IWL_NUM_RSC != IEEE80211_NUM_TIDS); | ||
| 1416 | |||
| 1417 | for (tid = 0; tid < IWL_NUM_RSC; tid++) { | ||
| 1418 | struct ieee80211_key_seq seq = {}; | ||
| 1419 | |||
| 1420 | iwl_mvm_aes_sc_to_seq(&scs[tid], &seq); | ||
| 1421 | ieee80211_set_key_rx_seq(key, tid, &seq); | ||
| 1422 | } | ||
| 1423 | } | ||
| 1424 | |||
| 1425 | static void iwl_mvm_set_tkip_rx_seq(struct tkip_sc *scs, | ||
| 1426 | struct ieee80211_key_conf *key) | ||
| 1427 | { | ||
| 1428 | int tid; | ||
| 1429 | |||
| 1430 | BUILD_BUG_ON(IWL_NUM_RSC != IEEE80211_NUM_TIDS); | ||
| 1431 | |||
| 1432 | for (tid = 0; tid < IWL_NUM_RSC; tid++) { | ||
| 1433 | struct ieee80211_key_seq seq = {}; | ||
| 1434 | |||
| 1435 | iwl_mvm_tkip_sc_to_seq(&scs[tid], &seq); | ||
| 1436 | ieee80211_set_key_rx_seq(key, tid, &seq); | ||
| 1437 | } | ||
| 1438 | } | ||
| 1439 | |||
| 1440 | static void iwl_mvm_set_key_rx_seq(struct ieee80211_key_conf *key, | ||
| 1441 | struct iwl_wowlan_status_v6 *status) | ||
| 1442 | { | ||
| 1443 | union iwl_all_tsc_rsc *rsc = &status->gtk.rsc.all_tsc_rsc; | ||
| 1444 | |||
| 1445 | switch (key->cipher) { | ||
| 1446 | case WLAN_CIPHER_SUITE_CCMP: | ||
| 1447 | iwl_mvm_set_aes_rx_seq(rsc->aes.multicast_rsc, key); | ||
| 1448 | break; | ||
| 1449 | case WLAN_CIPHER_SUITE_TKIP: | ||
| 1450 | iwl_mvm_set_tkip_rx_seq(rsc->tkip.multicast_rsc, key); | ||
| 1451 | break; | ||
| 1452 | default: | ||
| 1453 | WARN_ON(1); | ||
| 1454 | } | ||
| 1455 | } | ||
| 1456 | |||
| 1457 | struct iwl_mvm_d3_gtk_iter_data { | ||
| 1458 | struct iwl_wowlan_status_v6 *status; | ||
| 1459 | void *last_gtk; | ||
| 1460 | u32 cipher; | ||
| 1461 | bool find_phase, unhandled_cipher; | ||
| 1462 | int num_keys; | ||
| 1463 | }; | ||
| 1464 | |||
| 1465 | static void iwl_mvm_d3_update_gtks(struct ieee80211_hw *hw, | ||
| 1466 | struct ieee80211_vif *vif, | ||
| 1467 | struct ieee80211_sta *sta, | ||
| 1468 | struct ieee80211_key_conf *key, | ||
| 1469 | void *_data) | ||
| 1470 | { | ||
| 1471 | struct iwl_mvm_d3_gtk_iter_data *data = _data; | ||
| 1472 | |||
| 1473 | if (data->unhandled_cipher) | ||
| 1474 | return; | ||
| 1475 | |||
| 1476 | switch (key->cipher) { | ||
| 1477 | case WLAN_CIPHER_SUITE_WEP40: | ||
| 1478 | case WLAN_CIPHER_SUITE_WEP104: | ||
| 1479 | /* ignore WEP completely, nothing to do */ | ||
| 1480 | return; | ||
| 1481 | case WLAN_CIPHER_SUITE_CCMP: | ||
| 1482 | case WLAN_CIPHER_SUITE_TKIP: | ||
| 1483 | /* we support these */ | ||
| 1484 | break; | ||
| 1485 | default: | ||
| 1486 | /* everything else (even CMAC for MFP) - disconnect from AP */ | ||
| 1487 | data->unhandled_cipher = true; | ||
| 1488 | return; | ||
| 1489 | } | ||
| 1490 | |||
| 1491 | data->num_keys++; | ||
| 1492 | |||
| 1493 | /* | ||
| 1494 | * pairwise key - update sequence counters only; | ||
| 1495 | * note that this assumes no TDLS sessions are active | ||
| 1496 | */ | ||
| 1497 | if (sta) { | ||
| 1498 | struct ieee80211_key_seq seq = {}; | ||
| 1499 | union iwl_all_tsc_rsc *sc = &data->status->gtk.rsc.all_tsc_rsc; | ||
| 1500 | |||
| 1501 | if (data->find_phase) | ||
| 1502 | return; | ||
| 1503 | |||
| 1504 | switch (key->cipher) { | ||
| 1505 | case WLAN_CIPHER_SUITE_CCMP: | ||
| 1506 | iwl_mvm_aes_sc_to_seq(&sc->aes.tsc, &seq); | ||
| 1507 | iwl_mvm_set_aes_rx_seq(sc->aes.unicast_rsc, key); | ||
| 1508 | break; | ||
| 1509 | case WLAN_CIPHER_SUITE_TKIP: | ||
| 1510 | iwl_mvm_tkip_sc_to_seq(&sc->tkip.tsc, &seq); | ||
| 1511 | iwl_mvm_set_tkip_rx_seq(sc->tkip.unicast_rsc, key); | ||
| 1512 | break; | ||
| 1513 | } | ||
| 1514 | ieee80211_set_key_tx_seq(key, &seq); | ||
| 1515 | |||
| 1516 | /* that's it for this key */ | ||
| 1517 | return; | ||
| 1518 | } | ||
| 1519 | |||
| 1520 | if (data->find_phase) { | ||
| 1521 | data->last_gtk = key; | ||
| 1522 | data->cipher = key->cipher; | ||
| 1523 | return; | ||
| 1524 | } | ||
| 1525 | |||
| 1526 | if (data->status->num_of_gtk_rekeys) | ||
| 1527 | ieee80211_remove_key(key); | ||
| 1528 | else if (data->last_gtk == key) | ||
| 1529 | iwl_mvm_set_key_rx_seq(key, data->status); | ||
| 1530 | } | ||
| 1531 | |||
| 1532 | static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm, | ||
| 1533 | struct ieee80211_vif *vif, | ||
| 1534 | struct iwl_wowlan_status_v6 *status) | ||
| 1535 | { | ||
| 1536 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
| 1537 | struct iwl_mvm_d3_gtk_iter_data gtkdata = { | ||
| 1538 | .status = status, | ||
| 1539 | }; | ||
| 1540 | |||
| 1541 | if (!status || !vif->bss_conf.bssid) | ||
| 1542 | return false; | ||
| 1543 | |||
| 1544 | /* find last GTK that we used initially, if any */ | ||
| 1545 | gtkdata.find_phase = true; | ||
| 1546 | ieee80211_iter_keys(mvm->hw, vif, | ||
| 1547 | iwl_mvm_d3_update_gtks, >kdata); | ||
| 1548 | /* not trying to keep connections with MFP/unhandled ciphers */ | ||
| 1549 | if (gtkdata.unhandled_cipher) | ||
| 1550 | return false; | ||
| 1551 | if (!gtkdata.num_keys) | ||
| 1552 | return true; | ||
| 1553 | if (!gtkdata.last_gtk) | ||
| 1554 | return false; | ||
| 1555 | |||
| 1556 | /* | ||
| 1557 | * invalidate all other GTKs that might still exist and update | ||
| 1558 | * the one that we used | ||
| 1559 | */ | ||
| 1560 | gtkdata.find_phase = false; | ||
| 1561 | ieee80211_iter_keys(mvm->hw, vif, | ||
| 1562 | iwl_mvm_d3_update_gtks, >kdata); | ||
| 1563 | |||
| 1564 | if (status->num_of_gtk_rekeys) { | ||
| 1565 | struct ieee80211_key_conf *key; | ||
| 1566 | struct { | ||
| 1567 | struct ieee80211_key_conf conf; | ||
| 1568 | u8 key[32]; | ||
| 1569 | } conf = { | ||
| 1570 | .conf.cipher = gtkdata.cipher, | ||
| 1571 | .conf.keyidx = status->gtk.key_index, | ||
| 1572 | }; | ||
| 1573 | |||
| 1574 | switch (gtkdata.cipher) { | ||
| 1575 | case WLAN_CIPHER_SUITE_CCMP: | ||
| 1576 | conf.conf.keylen = WLAN_KEY_LEN_CCMP; | ||
| 1577 | memcpy(conf.conf.key, status->gtk.decrypt_key, | ||
| 1578 | WLAN_KEY_LEN_CCMP); | ||
| 1579 | break; | ||
| 1580 | case WLAN_CIPHER_SUITE_TKIP: | ||
| 1581 | conf.conf.keylen = WLAN_KEY_LEN_TKIP; | ||
| 1582 | memcpy(conf.conf.key, status->gtk.decrypt_key, 16); | ||
| 1583 | /* leave TX MIC key zeroed, we don't use it anyway */ | ||
| 1584 | memcpy(conf.conf.key + | ||
| 1585 | NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY, | ||
| 1586 | status->gtk.tkip_mic_key, 8); | ||
| 1587 | break; | ||
| 1588 | } | ||
| 1589 | |||
| 1590 | key = ieee80211_gtk_rekey_add(vif, &conf.conf); | ||
| 1591 | if (IS_ERR(key)) | ||
| 1592 | return false; | ||
| 1593 | iwl_mvm_set_key_rx_seq(key, status); | ||
| 1594 | } | ||
| 1595 | |||
| 1596 | if (status->num_of_gtk_rekeys) { | ||
| 1597 | __be64 replay_ctr = | ||
| 1598 | cpu_to_be64(le64_to_cpu(status->replay_ctr)); | ||
| 1599 | ieee80211_gtk_rekey_notify(vif, vif->bss_conf.bssid, | ||
| 1600 | (void *)&replay_ctr, GFP_KERNEL); | ||
| 1601 | } | ||
| 1602 | |||
| 1603 | mvmvif->seqno_valid = true; | ||
| 1604 | /* +0x10 because the set API expects next-to-use, not last-used */ | ||
| 1605 | mvmvif->seqno = le16_to_cpu(status->non_qos_seq_ctr) + 0x10; | ||
| 1606 | |||
| 1607 | return true; | ||
| 1608 | } | ||
| 1609 | |||
| 1242 | /* releases the MVM mutex */ | 1610 | /* releases the MVM mutex */ |
| 1243 | static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, | 1611 | static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, |
| 1244 | struct ieee80211_vif *vif) | 1612 | struct ieee80211_vif *vif) |
| 1245 | { | 1613 | { |
| 1246 | u32 base = mvm->error_event_table; | 1614 | u32 base = mvm->error_event_table; |
| @@ -1253,8 +1621,12 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, | |||
| 1253 | .id = WOWLAN_GET_STATUSES, | 1621 | .id = WOWLAN_GET_STATUSES, |
| 1254 | .flags = CMD_SYNC | CMD_WANT_SKB, | 1622 | .flags = CMD_SYNC | CMD_WANT_SKB, |
| 1255 | }; | 1623 | }; |
| 1256 | struct iwl_wowlan_status *status; | 1624 | struct iwl_wowlan_status_data status; |
| 1257 | int ret, len; | 1625 | struct iwl_wowlan_status_v6 *status_v6; |
| 1626 | int ret, len, status_size, i; | ||
| 1627 | bool keep; | ||
| 1628 | struct ieee80211_sta *ap_sta; | ||
| 1629 | struct iwl_mvm_sta *mvm_ap_sta; | ||
| 1258 | 1630 | ||
| 1259 | iwl_trans_read_mem_bytes(mvm->trans, base, | 1631 | iwl_trans_read_mem_bytes(mvm->trans, base, |
| 1260 | &err_info, sizeof(err_info)); | 1632 | &err_info, sizeof(err_info)); |
| @@ -1287,32 +1659,83 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, | |||
| 1287 | if (!cmd.resp_pkt) | 1659 | if (!cmd.resp_pkt) |
| 1288 | goto out_unlock; | 1660 | goto out_unlock; |
| 1289 | 1661 | ||
| 1662 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_D3_CONTINUITY_API) | ||
| 1663 | status_size = sizeof(struct iwl_wowlan_status_v6); | ||
| 1664 | else | ||
| 1665 | status_size = sizeof(struct iwl_wowlan_status_v4); | ||
| 1666 | |||
| 1290 | len = le32_to_cpu(cmd.resp_pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | 1667 | len = le32_to_cpu(cmd.resp_pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; |
| 1291 | if (len - sizeof(struct iwl_cmd_header) < sizeof(*status)) { | 1668 | if (len - sizeof(struct iwl_cmd_header) < status_size) { |
| 1292 | IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); | 1669 | IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); |
| 1293 | goto out_free_resp; | 1670 | goto out_free_resp; |
| 1294 | } | 1671 | } |
| 1295 | 1672 | ||
| 1296 | status = (void *)cmd.resp_pkt->data; | 1673 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_D3_CONTINUITY_API) { |
| 1674 | status_v6 = (void *)cmd.resp_pkt->data; | ||
| 1675 | |||
| 1676 | status.pattern_number = le16_to_cpu(status_v6->pattern_number); | ||
| 1677 | for (i = 0; i < 8; i++) | ||
| 1678 | status.qos_seq_ctr[i] = | ||
| 1679 | le16_to_cpu(status_v6->qos_seq_ctr[i]); | ||
| 1680 | status.wakeup_reasons = le32_to_cpu(status_v6->wakeup_reasons); | ||
| 1681 | status.wake_packet_length = | ||
| 1682 | le32_to_cpu(status_v6->wake_packet_length); | ||
| 1683 | status.wake_packet_bufsize = | ||
| 1684 | le32_to_cpu(status_v6->wake_packet_bufsize); | ||
| 1685 | status.wake_packet = status_v6->wake_packet; | ||
| 1686 | } else { | ||
| 1687 | struct iwl_wowlan_status_v4 *status_v4; | ||
| 1688 | status_v6 = NULL; | ||
| 1689 | status_v4 = (void *)cmd.resp_pkt->data; | ||
| 1690 | |||
| 1691 | status.pattern_number = le16_to_cpu(status_v4->pattern_number); | ||
| 1692 | for (i = 0; i < 8; i++) | ||
| 1693 | status.qos_seq_ctr[i] = | ||
| 1694 | le16_to_cpu(status_v4->qos_seq_ctr[i]); | ||
| 1695 | status.wakeup_reasons = le32_to_cpu(status_v4->wakeup_reasons); | ||
| 1696 | status.wake_packet_length = | ||
| 1697 | le32_to_cpu(status_v4->wake_packet_length); | ||
| 1698 | status.wake_packet_bufsize = | ||
| 1699 | le32_to_cpu(status_v4->wake_packet_bufsize); | ||
| 1700 | status.wake_packet = status_v4->wake_packet; | ||
| 1701 | } | ||
| 1297 | 1702 | ||
| 1298 | if (len - sizeof(struct iwl_cmd_header) != | 1703 | if (len - sizeof(struct iwl_cmd_header) != |
| 1299 | sizeof(*status) + | 1704 | status_size + ALIGN(status.wake_packet_bufsize, 4)) { |
| 1300 | ALIGN(le32_to_cpu(status->wake_packet_bufsize), 4)) { | ||
| 1301 | IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); | 1705 | IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); |
| 1302 | goto out_free_resp; | 1706 | goto out_free_resp; |
| 1303 | } | 1707 | } |
| 1304 | 1708 | ||
| 1709 | /* still at hard-coded place 0 for D3 image */ | ||
| 1710 | ap_sta = rcu_dereference_protected( | ||
| 1711 | mvm->fw_id_to_mac_id[0], | ||
| 1712 | lockdep_is_held(&mvm->mutex)); | ||
| 1713 | if (IS_ERR_OR_NULL(ap_sta)) | ||
| 1714 | goto out_free_resp; | ||
| 1715 | |||
| 1716 | mvm_ap_sta = (struct iwl_mvm_sta *)ap_sta->drv_priv; | ||
| 1717 | for (i = 0; i < IWL_MAX_TID_COUNT; i++) { | ||
| 1718 | u16 seq = status.qos_seq_ctr[i]; | ||
| 1719 | /* firmware stores last-used value, we store next value */ | ||
| 1720 | seq += 0x10; | ||
| 1721 | mvm_ap_sta->tid_data[i].seq_number = seq; | ||
| 1722 | } | ||
| 1723 | |||
| 1305 | /* now we have all the data we need, unlock to avoid mac80211 issues */ | 1724 | /* now we have all the data we need, unlock to avoid mac80211 issues */ |
| 1306 | mutex_unlock(&mvm->mutex); | 1725 | mutex_unlock(&mvm->mutex); |
| 1307 | 1726 | ||
| 1308 | iwl_mvm_report_wakeup_reasons(mvm, vif, status); | 1727 | iwl_mvm_report_wakeup_reasons(mvm, vif, &status); |
| 1728 | |||
| 1729 | keep = iwl_mvm_setup_connection_keep(mvm, vif, status_v6); | ||
| 1730 | |||
| 1309 | iwl_free_resp(&cmd); | 1731 | iwl_free_resp(&cmd); |
| 1310 | return; | 1732 | return keep; |
| 1311 | 1733 | ||
| 1312 | out_free_resp: | 1734 | out_free_resp: |
| 1313 | iwl_free_resp(&cmd); | 1735 | iwl_free_resp(&cmd); |
| 1314 | out_unlock: | 1736 | out_unlock: |
| 1315 | mutex_unlock(&mvm->mutex); | 1737 | mutex_unlock(&mvm->mutex); |
| 1738 | return false; | ||
| 1316 | } | 1739 | } |
| 1317 | 1740 | ||
| 1318 | static void iwl_mvm_read_d3_sram(struct iwl_mvm *mvm) | 1741 | static void iwl_mvm_read_d3_sram(struct iwl_mvm *mvm) |
| @@ -1335,6 +1758,17 @@ static void iwl_mvm_read_d3_sram(struct iwl_mvm *mvm) | |||
| 1335 | #endif | 1758 | #endif |
| 1336 | } | 1759 | } |
| 1337 | 1760 | ||
| 1761 | static void iwl_mvm_d3_disconnect_iter(void *data, u8 *mac, | ||
| 1762 | struct ieee80211_vif *vif) | ||
| 1763 | { | ||
| 1764 | /* skip the one we keep connection on */ | ||
| 1765 | if (data == vif) | ||
| 1766 | return; | ||
| 1767 | |||
| 1768 | if (vif->type == NL80211_IFTYPE_STATION) | ||
| 1769 | ieee80211_resume_disconnect(vif); | ||
| 1770 | } | ||
| 1771 | |||
| 1338 | static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) | 1772 | static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) |
| 1339 | { | 1773 | { |
| 1340 | struct iwl_d3_iter_data resume_iter_data = { | 1774 | struct iwl_d3_iter_data resume_iter_data = { |
| @@ -1343,6 +1777,7 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) | |||
| 1343 | struct ieee80211_vif *vif = NULL; | 1777 | struct ieee80211_vif *vif = NULL; |
| 1344 | int ret; | 1778 | int ret; |
| 1345 | enum iwl_d3_status d3_status; | 1779 | enum iwl_d3_status d3_status; |
| 1780 | bool keep = false; | ||
| 1346 | 1781 | ||
| 1347 | mutex_lock(&mvm->mutex); | 1782 | mutex_lock(&mvm->mutex); |
| 1348 | 1783 | ||
| @@ -1368,7 +1803,7 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) | |||
| 1368 | /* query SRAM first in case we want event logging */ | 1803 | /* query SRAM first in case we want event logging */ |
| 1369 | iwl_mvm_read_d3_sram(mvm); | 1804 | iwl_mvm_read_d3_sram(mvm); |
| 1370 | 1805 | ||
| 1371 | iwl_mvm_query_wakeup_reasons(mvm, vif); | 1806 | keep = iwl_mvm_query_wakeup_reasons(mvm, vif); |
| 1372 | /* has unlocked the mutex, so skip that */ | 1807 | /* has unlocked the mutex, so skip that */ |
| 1373 | goto out; | 1808 | goto out; |
| 1374 | 1809 | ||
| @@ -1376,8 +1811,10 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) | |||
| 1376 | mutex_unlock(&mvm->mutex); | 1811 | mutex_unlock(&mvm->mutex); |
| 1377 | 1812 | ||
| 1378 | out: | 1813 | out: |
| 1379 | if (!test && vif) | 1814 | if (!test) |
| 1380 | ieee80211_resume_disconnect(vif); | 1815 | ieee80211_iterate_active_interfaces_rtnl(mvm->hw, |
| 1816 | IEEE80211_IFACE_ITER_NORMAL, | ||
| 1817 | iwl_mvm_d3_disconnect_iter, keep ? vif : NULL); | ||
| 1381 | 1818 | ||
| 1382 | /* return 1 to reconfigure the device */ | 1819 | /* return 1 to reconfigure the device */ |
| 1383 | set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status); | 1820 | set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index aac81b8984b0..0675f0c8ef93 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c | |||
| @@ -246,58 +246,56 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, | |||
| 246 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 246 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
| 247 | } | 247 | } |
| 248 | 248 | ||
| 249 | static ssize_t iwl_dbgfs_power_down_allow_write(struct file *file, | 249 | static ssize_t iwl_dbgfs_disable_power_off_read(struct file *file, |
| 250 | const char __user *user_buf, | 250 | char __user *user_buf, |
| 251 | size_t count, loff_t *ppos) | 251 | size_t count, loff_t *ppos) |
| 252 | { | 252 | { |
| 253 | struct iwl_mvm *mvm = file->private_data; | 253 | struct iwl_mvm *mvm = file->private_data; |
| 254 | char buf[8] = {}; | 254 | char buf[64]; |
| 255 | int allow; | 255 | int bufsz = sizeof(buf); |
| 256 | 256 | int pos = 0; | |
| 257 | if (!mvm->ucode_loaded) | ||
| 258 | return -EIO; | ||
| 259 | |||
| 260 | if (copy_from_user(buf, user_buf, sizeof(buf))) | ||
| 261 | return -EFAULT; | ||
| 262 | |||
| 263 | if (sscanf(buf, "%d", &allow) != 1) | ||
| 264 | return -EINVAL; | ||
| 265 | |||
| 266 | IWL_DEBUG_POWER(mvm, "%s device power down\n", | ||
| 267 | allow ? "allow" : "prevent"); | ||
| 268 | 257 | ||
| 269 | /* | 258 | pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off_d0=%d\n", |
| 270 | * TODO: Send REPLY_DEBUG_CMD (0xf0) when FW support it | 259 | mvm->disable_power_off); |
| 271 | */ | 260 | pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off_d3=%d\n", |
| 261 | mvm->disable_power_off_d3); | ||
| 272 | 262 | ||
| 273 | return count; | 263 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
| 274 | } | 264 | } |
| 275 | 265 | ||
| 276 | static ssize_t iwl_dbgfs_power_down_d3_allow_write(struct file *file, | 266 | static ssize_t iwl_dbgfs_disable_power_off_write(struct file *file, |
| 277 | const char __user *user_buf, | 267 | const char __user *user_buf, |
| 278 | size_t count, loff_t *ppos) | 268 | size_t count, loff_t *ppos) |
| 279 | { | 269 | { |
| 280 | struct iwl_mvm *mvm = file->private_data; | 270 | struct iwl_mvm *mvm = file->private_data; |
| 281 | char buf[8] = {}; | 271 | char buf[64] = {}; |
| 282 | int allow; | 272 | int ret; |
| 273 | int val; | ||
| 283 | 274 | ||
| 284 | if (copy_from_user(buf, user_buf, sizeof(buf))) | 275 | if (!mvm->ucode_loaded) |
| 276 | return -EIO; | ||
| 277 | |||
| 278 | count = min_t(size_t, count, sizeof(buf) - 1); | ||
| 279 | if (copy_from_user(buf, user_buf, count)) | ||
| 285 | return -EFAULT; | 280 | return -EFAULT; |
| 286 | 281 | ||
| 287 | if (sscanf(buf, "%d", &allow) != 1) | 282 | if (!strncmp("disable_power_off_d0=", buf, 21)) { |
| 283 | if (sscanf(buf + 21, "%d", &val) != 1) | ||
| 284 | return -EINVAL; | ||
| 285 | mvm->disable_power_off = val; | ||
| 286 | } else if (!strncmp("disable_power_off_d3=", buf, 21)) { | ||
| 287 | if (sscanf(buf + 21, "%d", &val) != 1) | ||
| 288 | return -EINVAL; | ||
| 289 | mvm->disable_power_off_d3 = val; | ||
| 290 | } else { | ||
| 288 | return -EINVAL; | 291 | return -EINVAL; |
| 292 | } | ||
| 289 | 293 | ||
| 290 | IWL_DEBUG_POWER(mvm, "%s device power down in d3\n", | 294 | mutex_lock(&mvm->mutex); |
| 291 | allow ? "allow" : "prevent"); | 295 | ret = iwl_mvm_power_update_device_mode(mvm); |
| 292 | 296 | mutex_unlock(&mvm->mutex); | |
| 293 | /* | ||
| 294 | * TODO: When WoWLAN FW alive notification happens, driver will send | ||
| 295 | * REPLY_DEBUG_CMD setting power_down_allow flag according to | ||
| 296 | * mvm->prevent_power_down_d3 | ||
| 297 | */ | ||
| 298 | mvm->prevent_power_down_d3 = !allow; | ||
| 299 | 297 | ||
| 300 | return count; | 298 | return ret ?: count; |
| 301 | } | 299 | } |
| 302 | 300 | ||
| 303 | static void iwl_dbgfs_update_pm(struct iwl_mvm *mvm, | 301 | static void iwl_dbgfs_update_pm(struct iwl_mvm *mvm, |
| @@ -371,7 +369,8 @@ static ssize_t iwl_dbgfs_pm_params_write(struct file *file, | |||
| 371 | int val; | 369 | int val; |
| 372 | int ret; | 370 | int ret; |
| 373 | 371 | ||
| 374 | if (copy_from_user(buf, user_buf, sizeof(buf))) | 372 | count = min_t(size_t, count, sizeof(buf) - 1); |
| 373 | if (copy_from_user(buf, user_buf, count)) | ||
| 375 | return -EFAULT; | 374 | return -EFAULT; |
| 376 | 375 | ||
| 377 | if (!strncmp("keep_alive=", buf, 11)) { | 376 | if (!strncmp("keep_alive=", buf, 11)) { |
| @@ -394,7 +393,9 @@ static ssize_t iwl_dbgfs_pm_params_write(struct file *file, | |||
| 394 | if (sscanf(buf + 16, "%d", &val) != 1) | 393 | if (sscanf(buf + 16, "%d", &val) != 1) |
| 395 | return -EINVAL; | 394 | return -EINVAL; |
| 396 | param = MVM_DEBUGFS_PM_TX_DATA_TIMEOUT; | 395 | param = MVM_DEBUGFS_PM_TX_DATA_TIMEOUT; |
| 397 | } else if (!strncmp("disable_power_off=", buf, 18)) { | 396 | } else if (!strncmp("disable_power_off=", buf, 18) && |
| 397 | !(mvm->fw->ucode_capa.flags & | ||
| 398 | IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD)) { | ||
| 398 | if (sscanf(buf + 18, "%d", &val) != 1) | 399 | if (sscanf(buf + 18, "%d", &val) != 1) |
| 399 | return -EINVAL; | 400 | return -EINVAL; |
| 400 | param = MVM_DEBUGFS_PM_DISABLE_POWER_OFF; | 401 | param = MVM_DEBUGFS_PM_DISABLE_POWER_OFF; |
| @@ -581,15 +582,21 @@ static ssize_t iwl_dbgfs_bt_notif_read(struct file *file, char __user *user_buf, | |||
| 581 | BT_MBOX_PRINT(3, UPDATE_REQUEST, true); | 582 | BT_MBOX_PRINT(3, UPDATE_REQUEST, true); |
| 582 | 583 | ||
| 583 | pos += scnprintf(buf+pos, bufsz-pos, "bt_status = %d\n", | 584 | pos += scnprintf(buf+pos, bufsz-pos, "bt_status = %d\n", |
| 584 | notif->bt_status); | 585 | notif->bt_status); |
| 585 | pos += scnprintf(buf+pos, bufsz-pos, "bt_open_conn = %d\n", | 586 | pos += scnprintf(buf+pos, bufsz-pos, "bt_open_conn = %d\n", |
| 586 | notif->bt_open_conn); | 587 | notif->bt_open_conn); |
| 587 | pos += scnprintf(buf+pos, bufsz-pos, "bt_traffic_load = %d\n", | 588 | pos += scnprintf(buf+pos, bufsz-pos, "bt_traffic_load = %d\n", |
| 588 | notif->bt_traffic_load); | 589 | notif->bt_traffic_load); |
| 589 | pos += scnprintf(buf+pos, bufsz-pos, "bt_agg_traffic_load = %d\n", | 590 | pos += scnprintf(buf+pos, bufsz-pos, "bt_agg_traffic_load = %d\n", |
| 590 | notif->bt_agg_traffic_load); | 591 | notif->bt_agg_traffic_load); |
| 591 | pos += scnprintf(buf+pos, bufsz-pos, "bt_ci_compliance = %d\n", | 592 | pos += scnprintf(buf+pos, bufsz-pos, "bt_ci_compliance = %d\n", |
| 592 | notif->bt_ci_compliance); | 593 | notif->bt_ci_compliance); |
| 594 | pos += scnprintf(buf+pos, bufsz-pos, "primary_ch_lut = %d\n", | ||
| 595 | le32_to_cpu(notif->primary_ch_lut)); | ||
| 596 | pos += scnprintf(buf+pos, bufsz-pos, "secondary_ch_lut = %d\n", | ||
| 597 | le32_to_cpu(notif->secondary_ch_lut)); | ||
| 598 | pos += scnprintf(buf+pos, bufsz-pos, "bt_activity_grading = %d\n", | ||
| 599 | le32_to_cpu(notif->bt_activity_grading)); | ||
| 593 | 600 | ||
| 594 | mutex_unlock(&mvm->mutex); | 601 | mutex_unlock(&mvm->mutex); |
| 595 | 602 | ||
| @@ -600,6 +607,38 @@ static ssize_t iwl_dbgfs_bt_notif_read(struct file *file, char __user *user_buf, | |||
| 600 | } | 607 | } |
| 601 | #undef BT_MBOX_PRINT | 608 | #undef BT_MBOX_PRINT |
| 602 | 609 | ||
| 610 | static ssize_t iwl_dbgfs_bt_cmd_read(struct file *file, char __user *user_buf, | ||
| 611 | size_t count, loff_t *ppos) | ||
| 612 | { | ||
| 613 | struct iwl_mvm *mvm = file->private_data; | ||
| 614 | struct iwl_bt_coex_ci_cmd *cmd = &mvm->last_bt_ci_cmd; | ||
| 615 | char buf[256]; | ||
| 616 | int bufsz = sizeof(buf); | ||
| 617 | int pos = 0; | ||
| 618 | |||
| 619 | mutex_lock(&mvm->mutex); | ||
| 620 | |||
| 621 | pos += scnprintf(buf+pos, bufsz-pos, "Channel inhibition CMD\n"); | ||
| 622 | pos += scnprintf(buf+pos, bufsz-pos, | ||
| 623 | "\tPrimary Channel Bitmap 0x%016llx Fat: %d\n", | ||
| 624 | le64_to_cpu(cmd->bt_primary_ci), | ||
| 625 | !!cmd->co_run_bw_primary); | ||
| 626 | pos += scnprintf(buf+pos, bufsz-pos, | ||
| 627 | "\tSecondary Channel Bitmap 0x%016llx Fat: %d\n", | ||
| 628 | le64_to_cpu(cmd->bt_secondary_ci), | ||
| 629 | !!cmd->co_run_bw_secondary); | ||
| 630 | |||
| 631 | pos += scnprintf(buf+pos, bufsz-pos, "BT Configuration CMD\n"); | ||
| 632 | pos += scnprintf(buf+pos, bufsz-pos, "\tACK Kill Mask 0x%08x\n", | ||
| 633 | iwl_bt_ack_kill_msk[mvm->bt_kill_msk]); | ||
| 634 | pos += scnprintf(buf+pos, bufsz-pos, "\tCTS Kill Mask 0x%08x\n", | ||
| 635 | iwl_bt_cts_kill_msk[mvm->bt_kill_msk]); | ||
| 636 | |||
| 637 | mutex_unlock(&mvm->mutex); | ||
| 638 | |||
| 639 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
| 640 | } | ||
| 641 | |||
| 603 | #define PRINT_STATS_LE32(_str, _val) \ | 642 | #define PRINT_STATS_LE32(_str, _val) \ |
| 604 | pos += scnprintf(buf + pos, bufsz - pos, \ | 643 | pos += scnprintf(buf + pos, bufsz - pos, \ |
| 605 | fmt_table, _str, \ | 644 | fmt_table, _str, \ |
| @@ -615,9 +654,11 @@ static ssize_t iwl_dbgfs_fw_rx_stats_read(struct file *file, | |||
| 615 | int pos = 0; | 654 | int pos = 0; |
| 616 | char *buf; | 655 | char *buf; |
| 617 | int ret; | 656 | int ret; |
| 618 | int bufsz = sizeof(struct mvm_statistics_rx_phy) * 20 + | 657 | /* 43 is the size of each data line, 33 is the size of each header */ |
| 619 | sizeof(struct mvm_statistics_rx_non_phy) * 10 + | 658 | size_t bufsz = |
| 620 | sizeof(struct mvm_statistics_rx_ht_phy) * 10 + 200; | 659 | ((sizeof(struct mvm_statistics_rx) / sizeof(__le32)) * 43) + |
| 660 | (4 * 33) + 1; | ||
| 661 | |||
| 621 | struct mvm_statistics_rx_phy *ofdm; | 662 | struct mvm_statistics_rx_phy *ofdm; |
| 622 | struct mvm_statistics_rx_phy *cck; | 663 | struct mvm_statistics_rx_phy *cck; |
| 623 | struct mvm_statistics_rx_non_phy *general; | 664 | struct mvm_statistics_rx_non_phy *general; |
| @@ -712,6 +753,7 @@ static ssize_t iwl_dbgfs_fw_rx_stats_read(struct file *file, | |||
| 712 | PRINT_STATS_LE32("beacon_energy_b", general->beacon_energy_b); | 753 | PRINT_STATS_LE32("beacon_energy_b", general->beacon_energy_b); |
| 713 | PRINT_STATS_LE32("beacon_energy_c", general->beacon_energy_c); | 754 | PRINT_STATS_LE32("beacon_energy_c", general->beacon_energy_c); |
| 714 | PRINT_STATS_LE32("num_bt_kills", general->num_bt_kills); | 755 | PRINT_STATS_LE32("num_bt_kills", general->num_bt_kills); |
| 756 | PRINT_STATS_LE32("mac_id", general->mac_id); | ||
| 715 | PRINT_STATS_LE32("directed_data_mpdu", general->directed_data_mpdu); | 757 | PRINT_STATS_LE32("directed_data_mpdu", general->directed_data_mpdu); |
| 716 | 758 | ||
| 717 | pos += scnprintf(buf + pos, bufsz - pos, fmt_header, | 759 | pos += scnprintf(buf + pos, bufsz - pos, fmt_header, |
| @@ -757,6 +799,59 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct file *file, | |||
| 757 | return count; | 799 | return count; |
| 758 | } | 800 | } |
| 759 | 801 | ||
| 802 | static ssize_t | ||
| 803 | iwl_dbgfs_scan_ant_rxchain_read(struct file *file, | ||
| 804 | char __user *user_buf, | ||
| 805 | size_t count, loff_t *ppos) | ||
| 806 | { | ||
| 807 | struct iwl_mvm *mvm = file->private_data; | ||
| 808 | int pos = 0; | ||
| 809 | char buf[32]; | ||
| 810 | const size_t bufsz = sizeof(buf); | ||
| 811 | |||
| 812 | /* print which antennas were set for the scan command by the user */ | ||
| 813 | pos += scnprintf(buf + pos, bufsz - pos, "Antennas for scan: "); | ||
| 814 | if (mvm->scan_rx_ant & ANT_A) | ||
| 815 | pos += scnprintf(buf + pos, bufsz - pos, "A"); | ||
| 816 | if (mvm->scan_rx_ant & ANT_B) | ||
| 817 | pos += scnprintf(buf + pos, bufsz - pos, "B"); | ||
| 818 | if (mvm->scan_rx_ant & ANT_C) | ||
| 819 | pos += scnprintf(buf + pos, bufsz - pos, "C"); | ||
| 820 | pos += scnprintf(buf + pos, bufsz - pos, " (%hhx)\n", mvm->scan_rx_ant); | ||
| 821 | |||
| 822 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
| 823 | } | ||
| 824 | |||
| 825 | static ssize_t | ||
| 826 | iwl_dbgfs_scan_ant_rxchain_write(struct file *file, | ||
| 827 | const char __user *user_buf, | ||
| 828 | size_t count, loff_t *ppos) | ||
| 829 | { | ||
| 830 | struct iwl_mvm *mvm = file->private_data; | ||
| 831 | char buf[8]; | ||
| 832 | int buf_size; | ||
| 833 | u8 scan_rx_ant; | ||
| 834 | |||
| 835 | memset(buf, 0, sizeof(buf)); | ||
| 836 | buf_size = min(count, sizeof(buf) - 1); | ||
| 837 | |||
| 838 | /* get the argument from the user and check if it is valid */ | ||
| 839 | if (copy_from_user(buf, user_buf, buf_size)) | ||
| 840 | return -EFAULT; | ||
| 841 | if (sscanf(buf, "%hhx", &scan_rx_ant) != 1) | ||
| 842 | return -EINVAL; | ||
| 843 | if (scan_rx_ant > ANT_ABC) | ||
| 844 | return -EINVAL; | ||
| 845 | if (scan_rx_ant & ~iwl_fw_valid_rx_ant(mvm->fw)) | ||
| 846 | return -EINVAL; | ||
| 847 | |||
| 848 | /* change the rx antennas for scan command */ | ||
| 849 | mvm->scan_rx_ant = scan_rx_ant; | ||
| 850 | |||
| 851 | return count; | ||
| 852 | } | ||
| 853 | |||
| 854 | |||
| 760 | static void iwl_dbgfs_update_bf(struct ieee80211_vif *vif, | 855 | static void iwl_dbgfs_update_bf(struct ieee80211_vif *vif, |
| 761 | enum iwl_dbgfs_bf_mask param, int value) | 856 | enum iwl_dbgfs_bf_mask param, int value) |
| 762 | { | 857 | { |
| @@ -968,7 +1063,8 @@ static ssize_t iwl_dbgfs_d3_sram_write(struct file *file, | |||
| 968 | char buf[8] = {}; | 1063 | char buf[8] = {}; |
| 969 | int store; | 1064 | int store; |
| 970 | 1065 | ||
| 971 | if (copy_from_user(buf, user_buf, sizeof(buf))) | 1066 | count = min_t(size_t, count, sizeof(buf) - 1); |
| 1067 | if (copy_from_user(buf, user_buf, count)) | ||
| 972 | return -EFAULT; | 1068 | return -EFAULT; |
| 973 | 1069 | ||
| 974 | if (sscanf(buf, "%d", &store) != 1) | 1070 | if (sscanf(buf, "%d", &store) != 1) |
| @@ -1063,10 +1159,12 @@ MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain); | |||
| 1063 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(sram); | 1159 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(sram); |
| 1064 | MVM_DEBUGFS_READ_FILE_OPS(stations); | 1160 | MVM_DEBUGFS_READ_FILE_OPS(stations); |
| 1065 | MVM_DEBUGFS_READ_FILE_OPS(bt_notif); | 1161 | MVM_DEBUGFS_READ_FILE_OPS(bt_notif); |
| 1066 | MVM_DEBUGFS_WRITE_FILE_OPS(power_down_allow); | 1162 | MVM_DEBUGFS_READ_FILE_OPS(bt_cmd); |
| 1067 | MVM_DEBUGFS_WRITE_FILE_OPS(power_down_d3_allow); | 1163 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(disable_power_off); |
| 1068 | MVM_DEBUGFS_READ_FILE_OPS(fw_rx_stats); | 1164 | MVM_DEBUGFS_READ_FILE_OPS(fw_rx_stats); |
| 1069 | MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart); | 1165 | MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart); |
| 1166 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain); | ||
| 1167 | |||
| 1070 | #ifdef CONFIG_PM_SLEEP | 1168 | #ifdef CONFIG_PM_SLEEP |
| 1071 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram); | 1169 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram); |
| 1072 | #endif | 1170 | #endif |
| @@ -1087,10 +1185,14 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) | |||
| 1087 | MVM_DEBUGFS_ADD_FILE(sram, mvm->debugfs_dir, S_IWUSR | S_IRUSR); | 1185 | MVM_DEBUGFS_ADD_FILE(sram, mvm->debugfs_dir, S_IWUSR | S_IRUSR); |
| 1088 | MVM_DEBUGFS_ADD_FILE(stations, dbgfs_dir, S_IRUSR); | 1186 | MVM_DEBUGFS_ADD_FILE(stations, dbgfs_dir, S_IRUSR); |
| 1089 | MVM_DEBUGFS_ADD_FILE(bt_notif, dbgfs_dir, S_IRUSR); | 1187 | MVM_DEBUGFS_ADD_FILE(bt_notif, dbgfs_dir, S_IRUSR); |
| 1090 | MVM_DEBUGFS_ADD_FILE(power_down_allow, mvm->debugfs_dir, S_IWUSR); | 1188 | MVM_DEBUGFS_ADD_FILE(bt_cmd, dbgfs_dir, S_IRUSR); |
| 1091 | MVM_DEBUGFS_ADD_FILE(power_down_d3_allow, mvm->debugfs_dir, S_IWUSR); | 1189 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD) |
| 1190 | MVM_DEBUGFS_ADD_FILE(disable_power_off, mvm->debugfs_dir, | ||
| 1191 | S_IRUSR | S_IWUSR); | ||
| 1092 | MVM_DEBUGFS_ADD_FILE(fw_rx_stats, mvm->debugfs_dir, S_IRUSR); | 1192 | MVM_DEBUGFS_ADD_FILE(fw_rx_stats, mvm->debugfs_dir, S_IRUSR); |
| 1093 | MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR); | 1193 | MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR); |
| 1194 | MVM_DEBUGFS_ADD_FILE(scan_ant_rxchain, mvm->debugfs_dir, | ||
| 1195 | S_IWUSR | S_IRUSR); | ||
| 1094 | #ifdef CONFIG_PM_SLEEP | 1196 | #ifdef CONFIG_PM_SLEEP |
| 1095 | MVM_DEBUGFS_ADD_FILE(d3_sram, mvm->debugfs_dir, S_IRUSR | S_IWUSR); | 1197 | MVM_DEBUGFS_ADD_FILE(d3_sram, mvm->debugfs_dir, S_IRUSR | S_IWUSR); |
| 1096 | MVM_DEBUGFS_ADD_FILE(d3_test, mvm->debugfs_dir, S_IRUSR); | 1198 | MVM_DEBUGFS_ADD_FILE(d3_test, mvm->debugfs_dir, S_IRUSR); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h index 05c61d6f384e..4ea5e24ca92d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h | |||
| @@ -82,6 +82,8 @@ | |||
| 82 | * @BT_USE_DEFAULTS: | 82 | * @BT_USE_DEFAULTS: |
| 83 | * @BT_SYNC_2_BT_DISABLE: | 83 | * @BT_SYNC_2_BT_DISABLE: |
| 84 | * @BT_COEX_CORUNNING_TBL_EN: | 84 | * @BT_COEX_CORUNNING_TBL_EN: |
| 85 | * | ||
| 86 | * The COEX_MODE must be set for each command. Even if it is not changed. | ||
| 85 | */ | 87 | */ |
| 86 | enum iwl_bt_coex_flags { | 88 | enum iwl_bt_coex_flags { |
| 87 | BT_CH_PRIMARY_EN = BIT(0), | 89 | BT_CH_PRIMARY_EN = BIT(0), |
| @@ -95,14 +97,16 @@ enum iwl_bt_coex_flags { | |||
| 95 | BT_COEX_NW = 0x3 << BT_COEX_MODE_POS, | 97 | BT_COEX_NW = 0x3 << BT_COEX_MODE_POS, |
| 96 | BT_USE_DEFAULTS = BIT(6), | 98 | BT_USE_DEFAULTS = BIT(6), |
| 97 | BT_SYNC_2_BT_DISABLE = BIT(7), | 99 | BT_SYNC_2_BT_DISABLE = BIT(7), |
| 98 | /* | 100 | BT_COEX_CORUNNING_TBL_EN = BIT(8), |
| 99 | * For future use - when the flags will be enlarged | 101 | BT_COEX_MPLUT_TBL_EN = BIT(9), |
| 100 | * BT_COEX_CORUNNING_TBL_EN = BIT(8), | 102 | /* Bit 10 is reserved */ |
| 101 | */ | 103 | BT_COEX_WF_PRIO_BOOST_CHECK_EN = BIT(11), |
| 102 | }; | 104 | }; |
| 103 | 105 | ||
| 104 | /* | 106 | /* |
| 105 | * indicates what has changed in the BT_COEX command. | 107 | * indicates what has changed in the BT_COEX command. |
| 108 | * BT_VALID_ENABLE must be set for each command. Commands without this bit will | ||
| 109 | * discarded by the firmware | ||
| 106 | */ | 110 | */ |
| 107 | enum iwl_bt_coex_valid_bit_msk { | 111 | enum iwl_bt_coex_valid_bit_msk { |
| 108 | BT_VALID_ENABLE = BIT(0), | 112 | BT_VALID_ENABLE = BIT(0), |
| @@ -121,11 +125,8 @@ enum iwl_bt_coex_valid_bit_msk { | |||
| 121 | BT_VALID_CORUN_LUT_40 = BIT(13), | 125 | BT_VALID_CORUN_LUT_40 = BIT(13), |
| 122 | BT_VALID_ANT_ISOLATION = BIT(14), | 126 | BT_VALID_ANT_ISOLATION = BIT(14), |
| 123 | BT_VALID_ANT_ISOLATION_THRS = BIT(15), | 127 | BT_VALID_ANT_ISOLATION_THRS = BIT(15), |
| 124 | /* | 128 | BT_VALID_TXTX_DELTA_FREQ_THRS = BIT(16), |
| 125 | * For future use - when the valid flags will be enlarged | 129 | BT_VALID_TXRX_MAX_FREQ_0 = BIT(17), |
| 126 | * BT_VALID_TXTX_DELTA_FREQ_THRS = BIT(16), | ||
| 127 | * BT_VALID_TXRX_MAX_FREQ_0 = BIT(17), | ||
| 128 | */ | ||
| 129 | }; | 130 | }; |
| 130 | 131 | ||
| 131 | /** | 132 | /** |
| @@ -142,48 +143,88 @@ enum iwl_bt_reduced_tx_power { | |||
| 142 | BT_REDUCED_TX_POWER_DATA = BIT(1), | 143 | BT_REDUCED_TX_POWER_DATA = BIT(1), |
| 143 | }; | 144 | }; |
| 144 | 145 | ||
| 146 | enum iwl_bt_coex_lut_type { | ||
| 147 | BT_COEX_TIGHT_LUT = 0, | ||
| 148 | BT_COEX_LOOSE_LUT, | ||
| 149 | BT_COEX_TX_DIS_LUT, | ||
| 150 | |||
| 151 | BT_COEX_MAX_LUT, | ||
| 152 | }; | ||
| 153 | |||
| 145 | #define BT_COEX_LUT_SIZE (12) | 154 | #define BT_COEX_LUT_SIZE (12) |
| 155 | #define BT_COEX_CORUN_LUT_SIZE (32) | ||
| 156 | #define BT_COEX_MULTI_PRIO_LUT_SIZE (2) | ||
| 157 | #define BT_COEX_BOOST_SIZE (4) | ||
| 158 | #define BT_REDUCED_TX_POWER_BIT BIT(7) | ||
| 146 | 159 | ||
| 147 | /** | 160 | /** |
| 148 | * struct iwl_bt_coex_cmd - bt coex configuration command | 161 | * struct iwl_bt_coex_cmd - bt coex configuration command |
| 149 | * @flags:&enum iwl_bt_coex_flags | 162 | * @flags:&enum iwl_bt_coex_flags |
| 150 | * @lead_time: | ||
| 151 | * @max_kill: | 163 | * @max_kill: |
| 152 | * @bt3_time_t7_value: | ||
| 153 | * @kill_ack_msk: | ||
| 154 | * @kill_cts_msk: | ||
| 155 | * @bt3_prio_sample_time: | ||
| 156 | * @bt3_timer_t2_value: | ||
| 157 | * @bt4_reaction_time: | ||
| 158 | * @decision_lut[12]: | ||
| 159 | * @bt_reduced_tx_power: enum %iwl_bt_reduced_tx_power | 164 | * @bt_reduced_tx_power: enum %iwl_bt_reduced_tx_power |
| 160 | * @valid_bit_msk: enum %iwl_bt_coex_valid_bit_msk | 165 | * @bt4_antenna_isolation: |
| 161 | * @bt_prio_boost: values for PTA boost register | 166 | * @bt4_antenna_isolation_thr: |
| 167 | * @bt4_tx_tx_delta_freq_thr: | ||
| 168 | * @bt4_tx_rx_max_freq0: | ||
| 169 | * @bt_prio_boost: | ||
| 162 | * @wifi_tx_prio_boost: SW boost of wifi tx priority | 170 | * @wifi_tx_prio_boost: SW boost of wifi tx priority |
| 163 | * @wifi_rx_prio_boost: SW boost of wifi rx priority | 171 | * @wifi_rx_prio_boost: SW boost of wifi rx priority |
| 172 | * @kill_ack_msk: | ||
| 173 | * @kill_cts_msk: | ||
| 174 | * @decision_lut: | ||
| 175 | * @bt4_multiprio_lut: | ||
| 176 | * @bt4_corun_lut20: | ||
| 177 | * @bt4_corun_lut40: | ||
| 178 | * @valid_bit_msk: enum %iwl_bt_coex_valid_bit_msk | ||
| 164 | * | 179 | * |
| 165 | * The structure is used for the BT_COEX command. | 180 | * The structure is used for the BT_COEX command. |
| 166 | */ | 181 | */ |
| 167 | struct iwl_bt_coex_cmd { | 182 | struct iwl_bt_coex_cmd { |
| 168 | u8 flags; | 183 | __le32 flags; |
| 169 | u8 lead_time; | ||
| 170 | u8 max_kill; | 184 | u8 max_kill; |
| 171 | u8 bt3_time_t7_value; | 185 | u8 bt_reduced_tx_power; |
| 186 | u8 reserved[2]; | ||
| 187 | |||
| 188 | u8 bt4_antenna_isolation; | ||
| 189 | u8 bt4_antenna_isolation_thr; | ||
| 190 | u8 bt4_tx_tx_delta_freq_thr; | ||
| 191 | u8 bt4_tx_rx_max_freq0; | ||
| 192 | |||
| 193 | __le32 bt_prio_boost[BT_COEX_BOOST_SIZE]; | ||
| 194 | __le32 wifi_tx_prio_boost; | ||
| 195 | __le32 wifi_rx_prio_boost; | ||
| 172 | __le32 kill_ack_msk; | 196 | __le32 kill_ack_msk; |
| 173 | __le32 kill_cts_msk; | 197 | __le32 kill_cts_msk; |
| 174 | u8 bt3_prio_sample_time; | 198 | |
| 175 | u8 bt3_timer_t2_value; | 199 | __le32 decision_lut[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE]; |
| 176 | __le16 bt4_reaction_time; | 200 | __le32 bt4_multiprio_lut[BT_COEX_MULTI_PRIO_LUT_SIZE]; |
| 177 | __le32 decision_lut[BT_COEX_LUT_SIZE]; | 201 | __le32 bt4_corun_lut20[BT_COEX_CORUN_LUT_SIZE]; |
| 178 | u8 bt_reduced_tx_power; | 202 | __le32 bt4_corun_lut40[BT_COEX_CORUN_LUT_SIZE]; |
| 179 | u8 reserved; | 203 | |
| 180 | __le16 valid_bit_msk; | 204 | __le32 valid_bit_msk; |
| 181 | __le32 bt_prio_boost; | ||
| 182 | u8 reserved2; | ||
| 183 | u8 wifi_tx_prio_boost; | ||
| 184 | __le16 wifi_rx_prio_boost; | ||
| 185 | } __packed; /* BT_COEX_CMD_API_S_VER_3 */ | 205 | } __packed; /* BT_COEX_CMD_API_S_VER_3 */ |
| 186 | 206 | ||
| 207 | /** | ||
| 208 | * struct iwl_bt_coex_ci_cmd - bt coex channel inhibition command | ||
| 209 | * @bt_primary_ci: | ||
| 210 | * @bt_secondary_ci: | ||
| 211 | * @co_run_bw_primary: | ||
| 212 | * @co_run_bw_secondary: | ||
| 213 | * @primary_ch_phy_id: | ||
| 214 | * @secondary_ch_phy_id: | ||
| 215 | * | ||
| 216 | * Used for BT_COEX_CI command | ||
| 217 | */ | ||
| 218 | struct iwl_bt_coex_ci_cmd { | ||
| 219 | __le64 bt_primary_ci; | ||
| 220 | __le64 bt_secondary_ci; | ||
| 221 | |||
| 222 | u8 co_run_bw_primary; | ||
| 223 | u8 co_run_bw_secondary; | ||
| 224 | u8 primary_ch_phy_id; | ||
| 225 | u8 secondary_ch_phy_id; | ||
| 226 | } __packed; /* BT_CI_MSG_API_S_VER_1 */ | ||
| 227 | |||
| 187 | #define BT_MBOX(n_dw, _msg, _pos, _nbits) \ | 228 | #define BT_MBOX(n_dw, _msg, _pos, _nbits) \ |
| 188 | BT_MBOX##n_dw##_##_msg##_POS = (_pos), \ | 229 | BT_MBOX##n_dw##_##_msg##_POS = (_pos), \ |
| 189 | BT_MBOX##n_dw##_##_msg = BITS(_nbits) << BT_MBOX##n_dw##_##_msg##_POS | 230 | BT_MBOX##n_dw##_##_msg = BITS(_nbits) << BT_MBOX##n_dw##_##_msg##_POS |
| @@ -244,23 +285,39 @@ enum iwl_bt_mxbox_dw3 { | |||
| 244 | ((le32_to_cpu((_notif)->mbox_msg[(_num)]) & BT_MBOX##_num##_##_field)\ | 285 | ((le32_to_cpu((_notif)->mbox_msg[(_num)]) & BT_MBOX##_num##_##_field)\ |
| 245 | >> BT_MBOX##_num##_##_field##_POS) | 286 | >> BT_MBOX##_num##_##_field##_POS) |
| 246 | 287 | ||
| 288 | enum iwl_bt_activity_grading { | ||
| 289 | BT_OFF = 0, | ||
| 290 | BT_ON_NO_CONNECTION = 1, | ||
| 291 | BT_LOW_TRAFFIC = 2, | ||
| 292 | BT_HIGH_TRAFFIC = 3, | ||
| 293 | }; | ||
| 294 | |||
| 247 | /** | 295 | /** |
| 248 | * struct iwl_bt_coex_profile_notif - notification about BT coex | 296 | * struct iwl_bt_coex_profile_notif - notification about BT coex |
| 249 | * @mbox_msg: message from BT to WiFi | 297 | * @mbox_msg: message from BT to WiFi |
| 250 | * @:bt_status: 0 - off, 1 - on | 298 | * @msg_idx: the index of the message |
| 251 | * @:bt_open_conn: number of BT connections open | 299 | * @bt_status: 0 - off, 1 - on |
| 252 | * @:bt_traffic_load: load of BT traffic | 300 | * @bt_open_conn: number of BT connections open |
| 253 | * @:bt_agg_traffic_load: aggregated load of BT traffic | 301 | * @bt_traffic_load: load of BT traffic |
| 254 | * @:bt_ci_compliance: 0 - no CI compliance, 1 - CI compliant | 302 | * @bt_agg_traffic_load: aggregated load of BT traffic |
| 303 | * @bt_ci_compliance: 0 - no CI compliance, 1 - CI compliant | ||
| 304 | * @primary_ch_lut: LUT used for primary channel | ||
| 305 | * @secondary_ch_lut: LUT used for secondary channel | ||
| 306 | * @bt_activity_grading: the activity of BT enum %iwl_bt_activity_grading | ||
| 255 | */ | 307 | */ |
| 256 | struct iwl_bt_coex_profile_notif { | 308 | struct iwl_bt_coex_profile_notif { |
| 257 | __le32 mbox_msg[4]; | 309 | __le32 mbox_msg[4]; |
| 310 | __le32 msg_idx; | ||
| 258 | u8 bt_status; | 311 | u8 bt_status; |
| 259 | u8 bt_open_conn; | 312 | u8 bt_open_conn; |
| 260 | u8 bt_traffic_load; | 313 | u8 bt_traffic_load; |
| 261 | u8 bt_agg_traffic_load; | 314 | u8 bt_agg_traffic_load; |
| 262 | u8 bt_ci_compliance; | 315 | u8 bt_ci_compliance; |
| 263 | u8 reserved[3]; | 316 | u8 reserved[3]; |
| 317 | |||
| 318 | __le32 primary_ch_lut; | ||
| 319 | __le32 secondary_ch_lut; | ||
| 320 | __le32 bt_activity_grading; | ||
| 264 | } __packed; /* BT_COEX_PROFILE_NTFY_API_S_VER_2 */ | 321 | } __packed; /* BT_COEX_PROFILE_NTFY_API_S_VER_2 */ |
| 265 | 322 | ||
| 266 | enum iwl_bt_coex_prio_table_event { | 323 | enum iwl_bt_coex_prio_table_event { |
| @@ -300,20 +357,4 @@ struct iwl_bt_coex_prio_tbl_cmd { | |||
| 300 | u8 prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX]; | 357 | u8 prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX]; |
| 301 | } __packed; | 358 | } __packed; |
| 302 | 359 | ||
| 303 | enum iwl_bt_coex_env_action { | ||
| 304 | BT_COEX_ENV_CLOSE = 0, | ||
| 305 | BT_COEX_ENV_OPEN = 1, | ||
| 306 | }; /* BT_COEX_PROT_ENV_ACTION_API_E_VER_1 */ | ||
| 307 | |||
| 308 | /** | ||
| 309 | * struct iwl_bt_coex_prot_env_cmd - BT Protection Envelope | ||
| 310 | * @action: enum %iwl_bt_coex_env_action | ||
| 311 | * @type: enum %iwl_bt_coex_prio_table_event | ||
| 312 | */ | ||
| 313 | struct iwl_bt_coex_prot_env_cmd { | ||
| 314 | u8 action; /* 0 = closed, 1 = open */ | ||
| 315 | u8 type; /* 0 .. 15 */ | ||
| 316 | u8 reserved[2]; | ||
| 317 | } __packed; | ||
| 318 | |||
| 319 | #endif /* __fw_api_bt_coex_h__ */ | 360 | #endif /* __fw_api_bt_coex_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h index df72fcdf8170..4e7dd8cf87dc 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h | |||
| @@ -100,7 +100,12 @@ enum iwl_proto_offloads { | |||
| 100 | 100 | ||
| 101 | #define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V1 2 | 101 | #define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V1 2 |
| 102 | #define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V2 6 | 102 | #define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V2 6 |
| 103 | #define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_MAX 6 | 103 | #define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V3L 12 |
| 104 | #define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V3S 4 | ||
| 105 | #define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_MAX 12 | ||
| 106 | |||
| 107 | #define IWL_PROTO_OFFLOAD_NUM_NS_CONFIG_V3L 4 | ||
| 108 | #define IWL_PROTO_OFFLOAD_NUM_NS_CONFIG_V3S 2 | ||
| 104 | 109 | ||
| 105 | /** | 110 | /** |
| 106 | * struct iwl_proto_offload_cmd_common - ARP/NS offload common part | 111 | * struct iwl_proto_offload_cmd_common - ARP/NS offload common part |
| @@ -155,6 +160,43 @@ struct iwl_proto_offload_cmd_v2 { | |||
| 155 | u8 reserved2[3]; | 160 | u8 reserved2[3]; |
| 156 | } __packed; /* PROT_OFFLOAD_CONFIG_CMD_DB_S_VER_2 */ | 161 | } __packed; /* PROT_OFFLOAD_CONFIG_CMD_DB_S_VER_2 */ |
| 157 | 162 | ||
| 163 | struct iwl_ns_config { | ||
| 164 | struct in6_addr source_ipv6_addr; | ||
| 165 | struct in6_addr dest_ipv6_addr; | ||
| 166 | u8 target_mac_addr[ETH_ALEN]; | ||
| 167 | __le16 reserved; | ||
| 168 | } __packed; /* NS_OFFLOAD_CONFIG */ | ||
| 169 | |||
| 170 | struct iwl_targ_addr { | ||
| 171 | struct in6_addr addr; | ||
| 172 | __le32 config_num; | ||
| 173 | } __packed; /* TARGET_IPV6_ADDRESS */ | ||
| 174 | |||
| 175 | /** | ||
| 176 | * struct iwl_proto_offload_cmd_v3_small - ARP/NS offload configuration | ||
| 177 | * @common: common/IPv4 configuration | ||
| 178 | * @target_ipv6_addr: target IPv6 addresses | ||
| 179 | * @ns_config: NS offload configurations | ||
| 180 | */ | ||
| 181 | struct iwl_proto_offload_cmd_v3_small { | ||
| 182 | struct iwl_proto_offload_cmd_common common; | ||
| 183 | __le32 num_valid_ipv6_addrs; | ||
| 184 | struct iwl_targ_addr targ_addrs[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V3S]; | ||
| 185 | struct iwl_ns_config ns_config[IWL_PROTO_OFFLOAD_NUM_NS_CONFIG_V3S]; | ||
| 186 | } __packed; /* PROT_OFFLOAD_CONFIG_CMD_DB_S_VER_3 */ | ||
| 187 | |||
| 188 | /** | ||
| 189 | * struct iwl_proto_offload_cmd_v3_large - ARP/NS offload configuration | ||
| 190 | * @common: common/IPv4 configuration | ||
| 191 | * @target_ipv6_addr: target IPv6 addresses | ||
| 192 | * @ns_config: NS offload configurations | ||
| 193 | */ | ||
| 194 | struct iwl_proto_offload_cmd_v3_large { | ||
| 195 | struct iwl_proto_offload_cmd_common common; | ||
| 196 | __le32 num_valid_ipv6_addrs; | ||
| 197 | struct iwl_targ_addr targ_addrs[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V3L]; | ||
| 198 | struct iwl_ns_config ns_config[IWL_PROTO_OFFLOAD_NUM_NS_CONFIG_V3L]; | ||
| 199 | } __packed; /* PROT_OFFLOAD_CONFIG_CMD_DB_S_VER_3 */ | ||
| 158 | 200 | ||
| 159 | /* | 201 | /* |
| 160 | * WOWLAN_PATTERNS | 202 | * WOWLAN_PATTERNS |
| @@ -293,7 +335,7 @@ enum iwl_wowlan_wakeup_reason { | |||
| 293 | IWL_WOWLAN_WAKEUP_BY_REM_WAKE_WAKEUP_PACKET = BIT(12), | 335 | IWL_WOWLAN_WAKEUP_BY_REM_WAKE_WAKEUP_PACKET = BIT(12), |
| 294 | }; /* WOWLAN_WAKE_UP_REASON_API_E_VER_2 */ | 336 | }; /* WOWLAN_WAKE_UP_REASON_API_E_VER_2 */ |
| 295 | 337 | ||
| 296 | struct iwl_wowlan_status { | 338 | struct iwl_wowlan_status_v4 { |
| 297 | __le64 replay_ctr; | 339 | __le64 replay_ctr; |
| 298 | __le16 pattern_number; | 340 | __le16 pattern_number; |
| 299 | __le16 non_qos_seq_ctr; | 341 | __le16 non_qos_seq_ctr; |
| @@ -308,6 +350,29 @@ struct iwl_wowlan_status { | |||
| 308 | u8 wake_packet[]; /* can be truncated from _length to _bufsize */ | 350 | u8 wake_packet[]; /* can be truncated from _length to _bufsize */ |
| 309 | } __packed; /* WOWLAN_STATUSES_API_S_VER_4 */ | 351 | } __packed; /* WOWLAN_STATUSES_API_S_VER_4 */ |
| 310 | 352 | ||
| 353 | struct iwl_wowlan_gtk_status { | ||
| 354 | u8 key_index; | ||
| 355 | u8 reserved[3]; | ||
| 356 | u8 decrypt_key[16]; | ||
| 357 | u8 tkip_mic_key[8]; | ||
| 358 | struct iwl_wowlan_rsc_tsc_params_cmd rsc; | ||
| 359 | } __packed; | ||
| 360 | |||
| 361 | struct iwl_wowlan_status_v6 { | ||
| 362 | struct iwl_wowlan_gtk_status gtk; | ||
| 363 | __le64 replay_ctr; | ||
| 364 | __le16 pattern_number; | ||
| 365 | __le16 non_qos_seq_ctr; | ||
| 366 | __le16 qos_seq_ctr[8]; | ||
| 367 | __le32 wakeup_reasons; | ||
| 368 | __le32 num_of_gtk_rekeys; | ||
| 369 | __le32 transmitted_ndps; | ||
| 370 | __le32 received_beacons; | ||
| 371 | __le32 wake_packet_length; | ||
| 372 | __le32 wake_packet_bufsize; | ||
| 373 | u8 wake_packet[]; /* can be truncated from _length to _bufsize */ | ||
| 374 | } __packed; /* WOWLAN_STATUSES_API_S_VER_6 */ | ||
| 375 | |||
| 311 | #define IWL_WOWLAN_TCP_MAX_PACKET_LEN 64 | 376 | #define IWL_WOWLAN_TCP_MAX_PACKET_LEN 64 |
| 312 | #define IWL_WOWLAN_REMOTE_WAKE_MAX_PACKET_LEN 128 | 377 | #define IWL_WOWLAN_REMOTE_WAKE_MAX_PACKET_LEN 128 |
| 313 | #define IWL_WOWLAN_REMOTE_WAKE_MAX_TOKENS 2048 | 378 | #define IWL_WOWLAN_REMOTE_WAKE_MAX_TOKENS 2048 |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h index 98b1feb43d38..39c3148bdfa8 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h | |||
| @@ -170,12 +170,14 @@ struct iwl_mac_data_ap { | |||
| 170 | * @beacon_tsf: beacon transmit time in TSF | 170 | * @beacon_tsf: beacon transmit time in TSF |
| 171 | * @bi: beacon interval in TU | 171 | * @bi: beacon interval in TU |
| 172 | * @bi_reciprocal: 2^32 / bi | 172 | * @bi_reciprocal: 2^32 / bi |
| 173 | * @beacon_template: beacon template ID | ||
| 173 | */ | 174 | */ |
| 174 | struct iwl_mac_data_ibss { | 175 | struct iwl_mac_data_ibss { |
| 175 | __le32 beacon_time; | 176 | __le32 beacon_time; |
| 176 | __le64 beacon_tsf; | 177 | __le64 beacon_tsf; |
| 177 | __le32 bi; | 178 | __le32 bi; |
| 178 | __le32 bi_reciprocal; | 179 | __le32 bi_reciprocal; |
| 180 | __le32 beacon_template; | ||
| 179 | } __packed; /* IBSS_MAC_DATA_API_S_VER_1 */ | 181 | } __packed; /* IBSS_MAC_DATA_API_S_VER_1 */ |
| 180 | 182 | ||
| 181 | /** | 183 | /** |
| @@ -372,4 +374,13 @@ static inline u32 iwl_mvm_reciprocal(u32 v) | |||
| 372 | return 0xFFFFFFFF / v; | 374 | return 0xFFFFFFFF / v; |
| 373 | } | 375 | } |
| 374 | 376 | ||
| 377 | #define IWL_NONQOS_SEQ_GET 0x1 | ||
| 378 | #define IWL_NONQOS_SEQ_SET 0x2 | ||
| 379 | struct iwl_nonqos_seq_query_cmd { | ||
| 380 | __le32 get_set_flag; | ||
| 381 | __le32 mac_id_n_color; | ||
| 382 | __le16 value; | ||
| 383 | __le16 reserved; | ||
| 384 | } __packed; /* NON_QOS_TX_COUNTER_GET_SET_API_S_VER_1 */ | ||
| 385 | |||
| 375 | #endif /* __fw_api_mac_h__ */ | 386 | #endif /* __fw_api_mac_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h index 8e7ab41079ca..5cb93ae5cd2f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h | |||
| @@ -132,6 +132,33 @@ struct iwl_powertable_cmd { | |||
| 132 | } __packed; | 132 | } __packed; |
| 133 | 133 | ||
| 134 | /** | 134 | /** |
| 135 | * enum iwl_device_power_flags - masks for device power command flags | ||
| 136 | * @DEVIC_POWER_FLAGS_POWER_SAVE_ENA_MSK: '1' Allow to save power by turning off | ||
| 137 | * receiver and transmitter. '0' - does not allow. This flag should be | ||
| 138 | * always set to '1' unless one need to disable actual power down for debug | ||
| 139 | * purposes. | ||
| 140 | * @DEVICE_POWER_FLAGS_CAM_MSK: '1' CAM (Continuous Active Mode) is set, meaning | ||
| 141 | * that power management is disabled. '0' Power management is enabled, one | ||
| 142 | * of power schemes is applied. | ||
| 143 | */ | ||
| 144 | enum iwl_device_power_flags { | ||
| 145 | DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK = BIT(0), | ||
| 146 | DEVICE_POWER_FLAGS_CAM_MSK = BIT(13), | ||
| 147 | }; | ||
| 148 | |||
| 149 | /** | ||
| 150 | * struct iwl_device_power_cmd - device wide power command. | ||
| 151 | * DEVICE_POWER_CMD = 0x77 (command, has simple generic response) | ||
| 152 | * | ||
| 153 | * @flags: Power table command flags from DEVICE_POWER_FLAGS_* | ||
| 154 | */ | ||
| 155 | struct iwl_device_power_cmd { | ||
| 156 | /* PM_POWER_TABLE_CMD_API_S_VER_6 */ | ||
| 157 | __le16 flags; | ||
| 158 | __le16 reserved; | ||
| 159 | } __packed; | ||
| 160 | |||
| 161 | /** | ||
| 135 | * struct iwl_mac_power_cmd - New power command containing uAPSD support | 162 | * struct iwl_mac_power_cmd - New power command containing uAPSD support |
| 136 | * MAC_PM_POWER_TABLE = 0xA9 (command, has simple generic response) | 163 | * MAC_PM_POWER_TABLE = 0xA9 (command, has simple generic response) |
| 137 | * @id_and_color: MAC contex identifier | 164 | * @id_and_color: MAC contex identifier |
| @@ -290,7 +317,7 @@ struct iwl_beacon_filter_cmd { | |||
| 290 | #define IWL_BF_ESCAPE_TIMER_MIN 0 | 317 | #define IWL_BF_ESCAPE_TIMER_MIN 0 |
| 291 | 318 | ||
| 292 | #define IWL_BA_ESCAPE_TIMER_DEFAULT 6 | 319 | #define IWL_BA_ESCAPE_TIMER_DEFAULT 6 |
| 293 | #define IWL_BA_ESCAPE_TIMER_D3 6 | 320 | #define IWL_BA_ESCAPE_TIMER_D3 9 |
| 294 | #define IWL_BA_ESCAPE_TIMER_MAX 1024 | 321 | #define IWL_BA_ESCAPE_TIMER_MAX 1024 |
| 295 | #define IWL_BA_ESCAPE_TIMER_MIN 0 | 322 | #define IWL_BA_ESCAPE_TIMER_MIN 0 |
| 296 | 323 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h index fdd33bc0a594..538f1c7a5966 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h | |||
| @@ -68,6 +68,7 @@ | |||
| 68 | /* | 68 | /* |
| 69 | * These serve as indexes into | 69 | * These serve as indexes into |
| 70 | * struct iwl_rate_info fw_rate_idx_to_plcp[IWL_RATE_COUNT]; | 70 | * struct iwl_rate_info fw_rate_idx_to_plcp[IWL_RATE_COUNT]; |
| 71 | * TODO: avoid overlap between legacy and HT rates | ||
| 71 | */ | 72 | */ |
| 72 | enum { | 73 | enum { |
| 73 | IWL_RATE_1M_INDEX = 0, | 74 | IWL_RATE_1M_INDEX = 0, |
| @@ -78,18 +79,31 @@ enum { | |||
| 78 | IWL_LAST_CCK_RATE = IWL_RATE_11M_INDEX, | 79 | IWL_LAST_CCK_RATE = IWL_RATE_11M_INDEX, |
| 79 | IWL_RATE_6M_INDEX, | 80 | IWL_RATE_6M_INDEX, |
| 80 | IWL_FIRST_OFDM_RATE = IWL_RATE_6M_INDEX, | 81 | IWL_FIRST_OFDM_RATE = IWL_RATE_6M_INDEX, |
| 82 | IWL_RATE_MCS_0_INDEX = IWL_RATE_6M_INDEX, | ||
| 83 | IWL_FIRST_HT_RATE = IWL_RATE_MCS_0_INDEX, | ||
| 84 | IWL_FIRST_VHT_RATE = IWL_RATE_MCS_0_INDEX, | ||
| 81 | IWL_RATE_9M_INDEX, | 85 | IWL_RATE_9M_INDEX, |
| 82 | IWL_RATE_12M_INDEX, | 86 | IWL_RATE_12M_INDEX, |
| 87 | IWL_RATE_MCS_1_INDEX = IWL_RATE_12M_INDEX, | ||
| 83 | IWL_RATE_18M_INDEX, | 88 | IWL_RATE_18M_INDEX, |
| 89 | IWL_RATE_MCS_2_INDEX = IWL_RATE_18M_INDEX, | ||
| 84 | IWL_RATE_24M_INDEX, | 90 | IWL_RATE_24M_INDEX, |
| 91 | IWL_RATE_MCS_3_INDEX = IWL_RATE_24M_INDEX, | ||
| 85 | IWL_RATE_36M_INDEX, | 92 | IWL_RATE_36M_INDEX, |
| 93 | IWL_RATE_MCS_4_INDEX = IWL_RATE_36M_INDEX, | ||
| 86 | IWL_RATE_48M_INDEX, | 94 | IWL_RATE_48M_INDEX, |
| 95 | IWL_RATE_MCS_5_INDEX = IWL_RATE_48M_INDEX, | ||
| 87 | IWL_RATE_54M_INDEX, | 96 | IWL_RATE_54M_INDEX, |
| 97 | IWL_RATE_MCS_6_INDEX = IWL_RATE_54M_INDEX, | ||
| 88 | IWL_LAST_NON_HT_RATE = IWL_RATE_54M_INDEX, | 98 | IWL_LAST_NON_HT_RATE = IWL_RATE_54M_INDEX, |
| 89 | IWL_RATE_60M_INDEX, | 99 | IWL_RATE_60M_INDEX, |
| 90 | IWL_LAST_OFDM_RATE = IWL_RATE_60M_INDEX, | 100 | IWL_RATE_MCS_7_INDEX = IWL_RATE_60M_INDEX, |
| 101 | IWL_LAST_HT_RATE = IWL_RATE_MCS_7_INDEX, | ||
| 102 | IWL_RATE_MCS_8_INDEX, | ||
| 103 | IWL_RATE_MCS_9_INDEX, | ||
| 104 | IWL_LAST_VHT_RATE = IWL_RATE_MCS_9_INDEX, | ||
| 91 | IWL_RATE_COUNT_LEGACY = IWL_LAST_NON_HT_RATE + 1, | 105 | IWL_RATE_COUNT_LEGACY = IWL_LAST_NON_HT_RATE + 1, |
| 92 | IWL_RATE_COUNT, | 106 | IWL_RATE_COUNT = IWL_LAST_VHT_RATE + 1, |
| 93 | }; | 107 | }; |
| 94 | 108 | ||
| 95 | #define IWL_RATE_BIT_MSK(r) BIT(IWL_RATE_##r##M_INDEX) | 109 | #define IWL_RATE_BIT_MSK(r) BIT(IWL_RATE_##r##M_INDEX) |
| @@ -108,6 +122,7 @@ enum { | |||
| 108 | IWL_RATE_2M_PLCP = 20, | 122 | IWL_RATE_2M_PLCP = 20, |
| 109 | IWL_RATE_5M_PLCP = 55, | 123 | IWL_RATE_5M_PLCP = 55, |
| 110 | IWL_RATE_11M_PLCP = 110, | 124 | IWL_RATE_11M_PLCP = 110, |
| 125 | IWL_RATE_INVM_PLCP = -1, | ||
| 111 | }; | 126 | }; |
| 112 | 127 | ||
| 113 | /* | 128 | /* |
| @@ -164,6 +179,8 @@ enum { | |||
| 164 | * which is the duplicate 20 MHz MCS (bit 5 set, all others zero.) | 179 | * which is the duplicate 20 MHz MCS (bit 5 set, all others zero.) |
| 165 | */ | 180 | */ |
| 166 | #define RATE_HT_MCS_RATE_CODE_MSK 0x7 | 181 | #define RATE_HT_MCS_RATE_CODE_MSK 0x7 |
| 182 | #define RATE_HT_MCS_NSS_POS 3 | ||
| 183 | #define RATE_HT_MCS_NSS_MSK (3 << RATE_HT_MCS_NSS_POS) | ||
| 167 | 184 | ||
| 168 | /* Bit 10: (1) Use Green Field preamble */ | 185 | /* Bit 10: (1) Use Green Field preamble */ |
| 169 | #define RATE_HT_MCS_GF_POS 10 | 186 | #define RATE_HT_MCS_GF_POS 10 |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h index 83cb9b992ea4..c3782b48ded1 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h | |||
| @@ -356,6 +356,7 @@ struct iwl_scan_complete_notif { | |||
| 356 | /* scan offload */ | 356 | /* scan offload */ |
| 357 | #define IWL_MAX_SCAN_CHANNELS 40 | 357 | #define IWL_MAX_SCAN_CHANNELS 40 |
| 358 | #define IWL_SCAN_MAX_BLACKLIST_LEN 64 | 358 | #define IWL_SCAN_MAX_BLACKLIST_LEN 64 |
| 359 | #define IWL_SCAN_SHORT_BLACKLIST_LEN 16 | ||
| 359 | #define IWL_SCAN_MAX_PROFILES 11 | 360 | #define IWL_SCAN_MAX_PROFILES 11 |
| 360 | #define SCAN_OFFLOAD_PROBE_REQ_SIZE 512 | 361 | #define SCAN_OFFLOAD_PROBE_REQ_SIZE 512 |
| 361 | 362 | ||
| @@ -368,6 +369,12 @@ struct iwl_scan_complete_notif { | |||
| 368 | #define IWL_FULL_SCAN_MULTIPLIER 5 | 369 | #define IWL_FULL_SCAN_MULTIPLIER 5 |
| 369 | #define IWL_FAST_SCHED_SCAN_ITERATIONS 3 | 370 | #define IWL_FAST_SCHED_SCAN_ITERATIONS 3 |
| 370 | 371 | ||
| 372 | enum scan_framework_client { | ||
| 373 | SCAN_CLIENT_SCHED_SCAN = BIT(0), | ||
| 374 | SCAN_CLIENT_NETDETECT = BIT(1), | ||
| 375 | SCAN_CLIENT_ASSET_TRACKING = BIT(2), | ||
| 376 | }; | ||
| 377 | |||
| 371 | /** | 378 | /** |
| 372 | * struct iwl_scan_offload_cmd - SCAN_REQUEST_FIXED_PART_API_S_VER_6 | 379 | * struct iwl_scan_offload_cmd - SCAN_REQUEST_FIXED_PART_API_S_VER_6 |
| 373 | * @scan_flags: see enum iwl_scan_flags | 380 | * @scan_flags: see enum iwl_scan_flags |
| @@ -449,11 +456,12 @@ struct iwl_scan_offload_cfg { | |||
| 449 | * iwl_scan_offload_blacklist - SCAN_OFFLOAD_BLACKLIST_S | 456 | * iwl_scan_offload_blacklist - SCAN_OFFLOAD_BLACKLIST_S |
| 450 | * @ssid: MAC address to filter out | 457 | * @ssid: MAC address to filter out |
| 451 | * @reported_rssi: AP rssi reported to the host | 458 | * @reported_rssi: AP rssi reported to the host |
| 459 | * @client_bitmap: clients ignore this entry - enum scan_framework_client | ||
| 452 | */ | 460 | */ |
| 453 | struct iwl_scan_offload_blacklist { | 461 | struct iwl_scan_offload_blacklist { |
| 454 | u8 ssid[ETH_ALEN]; | 462 | u8 ssid[ETH_ALEN]; |
| 455 | u8 reported_rssi; | 463 | u8 reported_rssi; |
| 456 | u8 reserved; | 464 | u8 client_bitmap; |
| 457 | } __packed; | 465 | } __packed; |
| 458 | 466 | ||
| 459 | enum iwl_scan_offload_network_type { | 467 | enum iwl_scan_offload_network_type { |
| @@ -475,6 +483,7 @@ enum iwl_scan_offload_band_selection { | |||
| 475 | * @aut_alg: authentication olgorithm to match - bitmap | 483 | * @aut_alg: authentication olgorithm to match - bitmap |
| 476 | * @network_type: enum iwl_scan_offload_network_type | 484 | * @network_type: enum iwl_scan_offload_network_type |
| 477 | * @band_selection: enum iwl_scan_offload_band_selection | 485 | * @band_selection: enum iwl_scan_offload_band_selection |
| 486 | * @client_bitmap: clients waiting for match - enum scan_framework_client | ||
| 478 | */ | 487 | */ |
| 479 | struct iwl_scan_offload_profile { | 488 | struct iwl_scan_offload_profile { |
| 480 | u8 ssid_index; | 489 | u8 ssid_index; |
| @@ -482,7 +491,8 @@ struct iwl_scan_offload_profile { | |||
| 482 | u8 auth_alg; | 491 | u8 auth_alg; |
| 483 | u8 network_type; | 492 | u8 network_type; |
| 484 | u8 band_selection; | 493 | u8 band_selection; |
| 485 | u8 reserved[3]; | 494 | u8 client_bitmap; |
| 495 | u8 reserved[2]; | ||
| 486 | } __packed; | 496 | } __packed; |
| 487 | 497 | ||
| 488 | /** | 498 | /** |
| @@ -491,13 +501,18 @@ struct iwl_scan_offload_profile { | |||
| 491 | * @profiles: profiles to search for match | 501 | * @profiles: profiles to search for match |
| 492 | * @blacklist_len: length of blacklist | 502 | * @blacklist_len: length of blacklist |
| 493 | * @num_profiles: num of profiles in the list | 503 | * @num_profiles: num of profiles in the list |
| 504 | * @match_notify: clients waiting for match found notification | ||
| 505 | * @pass_match: clients waiting for the results | ||
| 506 | * @active_clients: active clients bitmap - enum scan_framework_client | ||
| 494 | */ | 507 | */ |
| 495 | struct iwl_scan_offload_profile_cfg { | 508 | struct iwl_scan_offload_profile_cfg { |
| 496 | struct iwl_scan_offload_blacklist blacklist[IWL_SCAN_MAX_BLACKLIST_LEN]; | ||
| 497 | struct iwl_scan_offload_profile profiles[IWL_SCAN_MAX_PROFILES]; | 509 | struct iwl_scan_offload_profile profiles[IWL_SCAN_MAX_PROFILES]; |
| 498 | u8 blacklist_len; | 510 | u8 blacklist_len; |
| 499 | u8 num_profiles; | 511 | u8 num_profiles; |
| 500 | u8 reserved[2]; | 512 | u8 match_notify; |
| 513 | u8 pass_match; | ||
| 514 | u8 active_clients; | ||
| 515 | u8 reserved[3]; | ||
| 501 | } __packed; | 516 | } __packed; |
| 502 | 517 | ||
| 503 | /** | 518 | /** |
| @@ -560,4 +575,15 @@ struct iwl_scan_offload_complete { | |||
| 560 | u8 reserved; | 575 | u8 reserved; |
| 561 | } __packed; | 576 | } __packed; |
| 562 | 577 | ||
| 578 | /** | ||
| 579 | * iwl_sched_scan_results - SCAN_OFFLOAD_MATCH_FOUND_NTF_API_S_VER_1 | ||
| 580 | * @ssid_bitmap: SSIDs indexes found in this iteration | ||
| 581 | * @client_bitmap: clients that are active and wait for this notification | ||
| 582 | */ | ||
| 583 | struct iwl_sched_scan_results { | ||
| 584 | __le16 ssid_bitmap; | ||
| 585 | u8 client_bitmap; | ||
| 586 | u8 reserved; | ||
| 587 | }; | ||
| 588 | |||
| 563 | #endif | 589 | #endif |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h index a30691a8a85b..4aca5933a65d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h | |||
| @@ -247,7 +247,7 @@ struct iwl_mvm_keyinfo { | |||
| 247 | } __packed; | 247 | } __packed; |
| 248 | 248 | ||
| 249 | /** | 249 | /** |
| 250 | * struct iwl_mvm_add_sta_cmd - Add / modify a station in the fw's station table | 250 | * struct iwl_mvm_add_sta_cmd_v5 - Add/modify a station in the fw's sta table. |
| 251 | * ( REPLY_ADD_STA = 0x18 ) | 251 | * ( REPLY_ADD_STA = 0x18 ) |
| 252 | * @add_modify: 1: modify existing, 0: add new station | 252 | * @add_modify: 1: modify existing, 0: add new station |
| 253 | * @unicast_tx_key_id: unicast tx key id. Relevant only when unicast key sent | 253 | * @unicast_tx_key_id: unicast tx key id. Relevant only when unicast key sent |
| @@ -286,7 +286,7 @@ struct iwl_mvm_keyinfo { | |||
| 286 | * ADD_STA sets up the table entry for one station, either creating a new | 286 | * ADD_STA sets up the table entry for one station, either creating a new |
| 287 | * entry, or modifying a pre-existing one. | 287 | * entry, or modifying a pre-existing one. |
| 288 | */ | 288 | */ |
| 289 | struct iwl_mvm_add_sta_cmd { | 289 | struct iwl_mvm_add_sta_cmd_v5 { |
| 290 | u8 add_modify; | 290 | u8 add_modify; |
| 291 | u8 unicast_tx_key_id; | 291 | u8 unicast_tx_key_id; |
| 292 | u8 multicast_tx_key_id; | 292 | u8 multicast_tx_key_id; |
| @@ -313,6 +313,57 @@ struct iwl_mvm_add_sta_cmd { | |||
| 313 | } __packed; /* ADD_STA_CMD_API_S_VER_5 */ | 313 | } __packed; /* ADD_STA_CMD_API_S_VER_5 */ |
| 314 | 314 | ||
| 315 | /** | 315 | /** |
| 316 | * struct iwl_mvm_add_sta_cmd_v6 - Add / modify a station | ||
| 317 | * VER_6 of this command is quite similar to VER_5 except | ||
| 318 | * exclusion of all fields related to the security key installation. | ||
| 319 | */ | ||
| 320 | struct iwl_mvm_add_sta_cmd_v6 { | ||
| 321 | u8 add_modify; | ||
| 322 | u8 reserved1; | ||
| 323 | __le16 tid_disable_tx; | ||
| 324 | __le32 mac_id_n_color; | ||
| 325 | u8 addr[ETH_ALEN]; /* _STA_ID_MODIFY_INFO_API_S_VER_1 */ | ||
| 326 | __le16 reserved2; | ||
| 327 | u8 sta_id; | ||
| 328 | u8 modify_mask; | ||
| 329 | __le16 reserved3; | ||
| 330 | __le32 station_flags; | ||
| 331 | __le32 station_flags_msk; | ||
| 332 | u8 add_immediate_ba_tid; | ||
| 333 | u8 remove_immediate_ba_tid; | ||
| 334 | __le16 add_immediate_ba_ssn; | ||
| 335 | __le16 sleep_tx_count; | ||
| 336 | __le16 sleep_state_flags; | ||
| 337 | __le16 assoc_id; | ||
| 338 | __le16 beamform_flags; | ||
| 339 | __le32 tfd_queue_msk; | ||
| 340 | } __packed; /* ADD_STA_CMD_API_S_VER_6 */ | ||
| 341 | |||
| 342 | /** | ||
| 343 | * struct iwl_mvm_add_sta_key_cmd - add/modify sta key | ||
| 344 | * ( REPLY_ADD_STA_KEY = 0x17 ) | ||
| 345 | * @sta_id: index of station in uCode's station table | ||
| 346 | * @key_offset: key offset in key storage | ||
| 347 | * @key_flags: type %iwl_sta_key_flag | ||
| 348 | * @key: key material data | ||
| 349 | * @key2: key material data | ||
| 350 | * @rx_secur_seq_cnt: RX security sequence counter for the key | ||
| 351 | * @tkip_rx_tsc_byte2: TSC[2] for key mix ph1 detection | ||
| 352 | * @tkip_rx_ttak: 10-byte unicast TKIP TTAK for Rx | ||
| 353 | */ | ||
| 354 | struct iwl_mvm_add_sta_key_cmd { | ||
| 355 | u8 sta_id; | ||
| 356 | u8 key_offset; | ||
| 357 | __le16 key_flags; | ||
| 358 | u8 key[16]; | ||
| 359 | u8 key2[16]; | ||
| 360 | u8 rx_secur_seq_cnt[16]; | ||
| 361 | u8 tkip_rx_tsc_byte2; | ||
| 362 | u8 reserved; | ||
| 363 | __le16 tkip_rx_ttak[5]; | ||
| 364 | } __packed; /* ADD_MODIFY_STA_KEY_API_S_VER_1 */ | ||
| 365 | |||
| 366 | /** | ||
| 316 | * enum iwl_mvm_add_sta_rsp_status - status in the response to ADD_STA command | 367 | * enum iwl_mvm_add_sta_rsp_status - status in the response to ADD_STA command |
| 317 | * @ADD_STA_SUCCESS: operation was executed successfully | 368 | * @ADD_STA_SUCCESS: operation was executed successfully |
| 318 | * @ADD_STA_STATIONS_OVERLOAD: no room left in the fw's station table | 369 | * @ADD_STA_STATIONS_OVERLOAD: no room left in the fw's station table |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h index 66264cc5a016..bad5a552dd8d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h | |||
| @@ -72,17 +72,17 @@ | |||
| 72 | #include "fw-api-d3.h" | 72 | #include "fw-api-d3.h" |
| 73 | #include "fw-api-bt-coex.h" | 73 | #include "fw-api-bt-coex.h" |
| 74 | 74 | ||
| 75 | /* queue and FIFO numbers by usage */ | 75 | /* maximal number of Tx queues in any platform */ |
| 76 | #define IWL_MVM_MAX_QUEUES 20 | ||
| 77 | |||
| 78 | /* Tx queue numbers */ | ||
| 76 | enum { | 79 | enum { |
| 77 | IWL_MVM_OFFCHANNEL_QUEUE = 8, | 80 | IWL_MVM_OFFCHANNEL_QUEUE = 8, |
| 78 | IWL_MVM_CMD_QUEUE = 9, | 81 | IWL_MVM_CMD_QUEUE = 9, |
| 79 | IWL_MVM_AUX_QUEUE = 15, | ||
| 80 | IWL_MVM_FIRST_AGG_QUEUE = 16, | ||
| 81 | IWL_MVM_NUM_QUEUES = 20, | ||
| 82 | IWL_MVM_LAST_AGG_QUEUE = IWL_MVM_NUM_QUEUES - 1, | ||
| 83 | IWL_MVM_CMD_FIFO = 7 | ||
| 84 | }; | 82 | }; |
| 85 | 83 | ||
| 84 | #define IWL_MVM_CMD_FIFO 7 | ||
| 85 | |||
| 86 | #define IWL_MVM_STATION_COUNT 16 | 86 | #define IWL_MVM_STATION_COUNT 16 |
| 87 | 87 | ||
| 88 | /* commands */ | 88 | /* commands */ |
| @@ -97,6 +97,7 @@ enum { | |||
| 97 | DBG_CFG = 0x9, | 97 | DBG_CFG = 0x9, |
| 98 | 98 | ||
| 99 | /* station table */ | 99 | /* station table */ |
| 100 | ADD_STA_KEY = 0x17, | ||
| 100 | ADD_STA = 0x18, | 101 | ADD_STA = 0x18, |
| 101 | REMOVE_STA = 0x19, | 102 | REMOVE_STA = 0x19, |
| 102 | 103 | ||
| @@ -114,6 +115,7 @@ enum { | |||
| 114 | TIME_EVENT_NOTIFICATION = 0x2a, | 115 | TIME_EVENT_NOTIFICATION = 0x2a, |
| 115 | BINDING_CONTEXT_CMD = 0x2b, | 116 | BINDING_CONTEXT_CMD = 0x2b, |
| 116 | TIME_QUOTA_CMD = 0x2c, | 117 | TIME_QUOTA_CMD = 0x2c, |
| 118 | NON_QOS_TX_COUNTER_CMD = 0x2d, | ||
| 117 | 119 | ||
| 118 | LQ_CMD = 0x4e, | 120 | LQ_CMD = 0x4e, |
| 119 | 121 | ||
| @@ -130,6 +132,7 @@ enum { | |||
| 130 | SCAN_OFFLOAD_COMPLETE = 0x6D, | 132 | SCAN_OFFLOAD_COMPLETE = 0x6D, |
| 131 | SCAN_OFFLOAD_UPDATE_PROFILES_CMD = 0x6E, | 133 | SCAN_OFFLOAD_UPDATE_PROFILES_CMD = 0x6E, |
| 132 | SCAN_OFFLOAD_CONFIG_CMD = 0x6f, | 134 | SCAN_OFFLOAD_CONFIG_CMD = 0x6f, |
| 135 | MATCH_FOUND_NOTIFICATION = 0xd9, | ||
| 133 | 136 | ||
| 134 | /* Phy */ | 137 | /* Phy */ |
| 135 | PHY_CONFIGURATION_CMD = 0x6a, | 138 | PHY_CONFIGURATION_CMD = 0x6a, |
| @@ -178,6 +181,7 @@ enum { | |||
| 178 | BT_COEX_PRIO_TABLE = 0xcc, | 181 | BT_COEX_PRIO_TABLE = 0xcc, |
| 179 | BT_COEX_PROT_ENV = 0xcd, | 182 | BT_COEX_PROT_ENV = 0xcd, |
| 180 | BT_PROFILE_NOTIFICATION = 0xce, | 183 | BT_PROFILE_NOTIFICATION = 0xce, |
| 184 | BT_COEX_CI = 0x5d, | ||
| 181 | 185 | ||
| 182 | REPLY_BEACON_FILTERING_CMD = 0xd2, | 186 | REPLY_BEACON_FILTERING_CMD = 0xd2, |
| 183 | 187 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c index c76299a3a1e0..83fc5ca04433 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/iwlwifi/mvm/fw.c | |||
| @@ -199,7 +199,7 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, | |||
| 199 | */ | 199 | */ |
| 200 | 200 | ||
| 201 | for (i = 0; i < IWL_MAX_HW_QUEUES; i++) { | 201 | for (i = 0; i < IWL_MAX_HW_QUEUES; i++) { |
| 202 | if (i < IWL_MVM_FIRST_AGG_QUEUE && i != IWL_MVM_CMD_QUEUE) | 202 | if (i < mvm->first_agg_queue && i != IWL_MVM_CMD_QUEUE) |
| 203 | mvm->queue_to_mac80211[i] = i; | 203 | mvm->queue_to_mac80211[i] = i; |
| 204 | else | 204 | else |
| 205 | mvm->queue_to_mac80211[i] = IWL_INVALID_MAC80211_QUEUE; | 205 | mvm->queue_to_mac80211[i] = IWL_INVALID_MAC80211_QUEUE; |
| @@ -243,7 +243,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) | |||
| 243 | 243 | ||
| 244 | lockdep_assert_held(&mvm->mutex); | 244 | lockdep_assert_held(&mvm->mutex); |
| 245 | 245 | ||
| 246 | if (mvm->init_ucode_run) | 246 | if (mvm->init_ucode_complete) |
| 247 | return 0; | 247 | return 0; |
| 248 | 248 | ||
| 249 | iwl_init_notification_wait(&mvm->notif_wait, | 249 | iwl_init_notification_wait(&mvm->notif_wait, |
| @@ -264,6 +264,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) | |||
| 264 | if (ret) | 264 | if (ret) |
| 265 | goto error; | 265 | goto error; |
| 266 | 266 | ||
| 267 | /* Read the NVM only at driver load time, no need to do this twice */ | ||
| 267 | if (read_nvm) { | 268 | if (read_nvm) { |
| 268 | /* Read nvm */ | 269 | /* Read nvm */ |
| 269 | ret = iwl_nvm_init(mvm); | 270 | ret = iwl_nvm_init(mvm); |
| @@ -273,6 +274,10 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) | |||
| 273 | } | 274 | } |
| 274 | } | 275 | } |
| 275 | 276 | ||
| 277 | /* In case we read the NVM from external file, load it to the NIC */ | ||
| 278 | if (iwlwifi_mod_params.nvm_file) | ||
| 279 | iwl_mvm_load_nvm_to_nic(mvm); | ||
| 280 | |||
| 276 | ret = iwl_nvm_check_version(mvm->nvm_data, mvm->trans); | 281 | ret = iwl_nvm_check_version(mvm->nvm_data, mvm->trans); |
| 277 | WARN_ON(ret); | 282 | WARN_ON(ret); |
| 278 | 283 | ||
| @@ -310,7 +315,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) | |||
| 310 | ret = iwl_wait_notification(&mvm->notif_wait, &calib_wait, | 315 | ret = iwl_wait_notification(&mvm->notif_wait, &calib_wait, |
| 311 | MVM_UCODE_CALIB_TIMEOUT); | 316 | MVM_UCODE_CALIB_TIMEOUT); |
| 312 | if (!ret) | 317 | if (!ret) |
| 313 | mvm->init_ucode_run = true; | 318 | mvm->init_ucode_complete = true; |
| 314 | goto out; | 319 | goto out; |
| 315 | 320 | ||
| 316 | error: | 321 | error: |
| @@ -353,8 +358,12 @@ int iwl_mvm_up(struct iwl_mvm *mvm) | |||
| 353 | if (ret) | 358 | if (ret) |
| 354 | return ret; | 359 | return ret; |
| 355 | 360 | ||
| 356 | /* If we were in RFKILL during module loading, load init ucode now */ | 361 | /* |
| 357 | if (!mvm->init_ucode_run) { | 362 | * If we haven't completed the run of the init ucode during |
| 363 | * module loading, load init ucode now | ||
| 364 | * (for example, if we were in RFKILL) | ||
| 365 | */ | ||
| 366 | if (!mvm->init_ucode_complete) { | ||
| 358 | ret = iwl_run_init_mvm_ucode(mvm, false); | 367 | ret = iwl_run_init_mvm_ucode(mvm, false); |
| 359 | if (ret && !iwlmvm_mod_params.init_dbg) { | 368 | if (ret && !iwlmvm_mod_params.init_dbg) { |
| 360 | IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", ret); | 369 | IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", ret); |
| @@ -424,6 +433,10 @@ int iwl_mvm_up(struct iwl_mvm *mvm) | |||
| 424 | goto error; | 433 | goto error; |
| 425 | } | 434 | } |
| 426 | 435 | ||
| 436 | ret = iwl_mvm_power_update_device_mode(mvm); | ||
| 437 | if (ret) | ||
| 438 | goto error; | ||
| 439 | |||
| 427 | IWL_DEBUG_INFO(mvm, "RT uCode started.\n"); | 440 | IWL_DEBUG_INFO(mvm, "RT uCode started.\n"); |
| 428 | return 0; | 441 | return 0; |
| 429 | error: | 442 | error: |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c index 5fe23a5ea9b6..ab5a7ac90dcd 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | |||
| @@ -80,7 +80,7 @@ struct iwl_mvm_mac_iface_iterator_data { | |||
| 80 | struct ieee80211_vif *vif; | 80 | struct ieee80211_vif *vif; |
| 81 | unsigned long available_mac_ids[BITS_TO_LONGS(NUM_MAC_INDEX_DRIVER)]; | 81 | unsigned long available_mac_ids[BITS_TO_LONGS(NUM_MAC_INDEX_DRIVER)]; |
| 82 | unsigned long available_tsf_ids[BITS_TO_LONGS(NUM_TSF_IDS)]; | 82 | unsigned long available_tsf_ids[BITS_TO_LONGS(NUM_TSF_IDS)]; |
| 83 | unsigned long used_hw_queues[BITS_TO_LONGS(IWL_MVM_FIRST_AGG_QUEUE)]; | 83 | unsigned long used_hw_queues[BITS_TO_LONGS(IWL_MVM_MAX_QUEUES)]; |
| 84 | enum iwl_tsf_id preferred_tsf; | 84 | enum iwl_tsf_id preferred_tsf; |
| 85 | bool found_vif; | 85 | bool found_vif; |
| 86 | }; | 86 | }; |
| @@ -218,7 +218,7 @@ static int iwl_mvm_mac_ctxt_allocate_resources(struct iwl_mvm *mvm, | |||
| 218 | .preferred_tsf = NUM_TSF_IDS, | 218 | .preferred_tsf = NUM_TSF_IDS, |
| 219 | .used_hw_queues = { | 219 | .used_hw_queues = { |
| 220 | BIT(IWL_MVM_OFFCHANNEL_QUEUE) | | 220 | BIT(IWL_MVM_OFFCHANNEL_QUEUE) | |
| 221 | BIT(IWL_MVM_AUX_QUEUE) | | 221 | BIT(mvm->aux_queue) | |
| 222 | BIT(IWL_MVM_CMD_QUEUE) | 222 | BIT(IWL_MVM_CMD_QUEUE) |
| 223 | }, | 223 | }, |
| 224 | .found_vif = false, | 224 | .found_vif = false, |
| @@ -242,9 +242,17 @@ static int iwl_mvm_mac_ctxt_allocate_resources(struct iwl_mvm *mvm, | |||
| 242 | * that we should share it with another interface. | 242 | * that we should share it with another interface. |
| 243 | */ | 243 | */ |
| 244 | 244 | ||
| 245 | /* Currently, MAC ID 0 should be used only for the managed vif */ | 245 | /* Currently, MAC ID 0 should be used only for the managed/IBSS vif */ |
| 246 | if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) | 246 | switch (vif->type) { |
| 247 | case NL80211_IFTYPE_ADHOC: | ||
| 248 | break; | ||
| 249 | case NL80211_IFTYPE_STATION: | ||
| 250 | if (!vif->p2p) | ||
| 251 | break; | ||
| 252 | /* fall through */ | ||
| 253 | default: | ||
| 247 | __clear_bit(0, data.available_mac_ids); | 254 | __clear_bit(0, data.available_mac_ids); |
| 255 | } | ||
| 248 | 256 | ||
| 249 | ieee80211_iterate_active_interfaces_atomic( | 257 | ieee80211_iterate_active_interfaces_atomic( |
| 250 | mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL, | 258 | mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL, |
| @@ -302,9 +310,9 @@ static int iwl_mvm_mac_ctxt_allocate_resources(struct iwl_mvm *mvm, | |||
| 302 | /* Find available queues, and allocate them to the ACs */ | 310 | /* Find available queues, and allocate them to the ACs */ |
| 303 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | 311 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { |
| 304 | u8 queue = find_first_zero_bit(data.used_hw_queues, | 312 | u8 queue = find_first_zero_bit(data.used_hw_queues, |
| 305 | IWL_MVM_FIRST_AGG_QUEUE); | 313 | mvm->first_agg_queue); |
| 306 | 314 | ||
| 307 | if (queue >= IWL_MVM_FIRST_AGG_QUEUE) { | 315 | if (queue >= mvm->first_agg_queue) { |
| 308 | IWL_ERR(mvm, "Failed to allocate queue\n"); | 316 | IWL_ERR(mvm, "Failed to allocate queue\n"); |
| 309 | ret = -EIO; | 317 | ret = -EIO; |
| 310 | goto exit_fail; | 318 | goto exit_fail; |
| @@ -317,9 +325,9 @@ static int iwl_mvm_mac_ctxt_allocate_resources(struct iwl_mvm *mvm, | |||
| 317 | /* Allocate the CAB queue for softAP and GO interfaces */ | 325 | /* Allocate the CAB queue for softAP and GO interfaces */ |
| 318 | if (vif->type == NL80211_IFTYPE_AP) { | 326 | if (vif->type == NL80211_IFTYPE_AP) { |
| 319 | u8 queue = find_first_zero_bit(data.used_hw_queues, | 327 | u8 queue = find_first_zero_bit(data.used_hw_queues, |
| 320 | IWL_MVM_FIRST_AGG_QUEUE); | 328 | mvm->first_agg_queue); |
| 321 | 329 | ||
| 322 | if (queue >= IWL_MVM_FIRST_AGG_QUEUE) { | 330 | if (queue >= mvm->first_agg_queue) { |
| 323 | IWL_ERR(mvm, "Failed to allocate cab queue\n"); | 331 | IWL_ERR(mvm, "Failed to allocate cab queue\n"); |
| 324 | ret = -EIO; | 332 | ret = -EIO; |
| 325 | goto exit_fail; | 333 | goto exit_fail; |
| @@ -559,8 +567,12 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm, | |||
| 559 | cmd->qos_flags |= cpu_to_le32(MAC_QOS_FLG_UPDATE_EDCA); | 567 | cmd->qos_flags |= cpu_to_le32(MAC_QOS_FLG_UPDATE_EDCA); |
| 560 | 568 | ||
| 561 | /* Don't use cts to self as the fw doesn't support it currently. */ | 569 | /* Don't use cts to self as the fw doesn't support it currently. */ |
| 562 | if (vif->bss_conf.use_cts_prot) | 570 | if (vif->bss_conf.use_cts_prot) { |
| 563 | cmd->protection_flags |= cpu_to_le32(MAC_PROT_FLG_TGG_PROTECT); | 571 | cmd->protection_flags |= cpu_to_le32(MAC_PROT_FLG_TGG_PROTECT); |
| 572 | if (IWL_UCODE_API(mvm->fw->ucode_ver) >= 8) | ||
| 573 | cmd->protection_flags |= | ||
| 574 | cpu_to_le32(MAC_PROT_FLG_SELF_CTS_EN); | ||
| 575 | } | ||
| 564 | 576 | ||
| 565 | /* | 577 | /* |
| 566 | * I think that we should enable these 2 flags regardless the HT PROT | 578 | * I think that we should enable these 2 flags regardless the HT PROT |
| @@ -712,6 +724,31 @@ static int iwl_mvm_mac_ctxt_cmd_listener(struct iwl_mvm *mvm, | |||
| 712 | return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd); | 724 | return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd); |
| 713 | } | 725 | } |
| 714 | 726 | ||
| 727 | static int iwl_mvm_mac_ctxt_cmd_ibss(struct iwl_mvm *mvm, | ||
| 728 | struct ieee80211_vif *vif, | ||
| 729 | u32 action) | ||
| 730 | { | ||
| 731 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
| 732 | struct iwl_mac_ctx_cmd cmd = {}; | ||
| 733 | |||
| 734 | WARN_ON(vif->type != NL80211_IFTYPE_ADHOC); | ||
| 735 | |||
| 736 | iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); | ||
| 737 | |||
| 738 | cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_BEACON | | ||
| 739 | MAC_FILTER_IN_PROBE_REQUEST); | ||
| 740 | |||
| 741 | /* cmd.ibss.beacon_time/cmd.ibss.beacon_tsf are curently ignored */ | ||
| 742 | cmd.ibss.bi = cpu_to_le32(vif->bss_conf.beacon_int); | ||
| 743 | cmd.ibss.bi_reciprocal = | ||
| 744 | cpu_to_le32(iwl_mvm_reciprocal(vif->bss_conf.beacon_int)); | ||
| 745 | |||
| 746 | /* TODO: Assumes that the beacon id == mac context id */ | ||
| 747 | cmd.ibss.beacon_template = cpu_to_le32(mvmvif->id); | ||
| 748 | |||
| 749 | return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd); | ||
| 750 | } | ||
| 751 | |||
| 715 | struct iwl_mvm_go_iterator_data { | 752 | struct iwl_mvm_go_iterator_data { |
| 716 | bool go_active; | 753 | bool go_active; |
| 717 | }; | 754 | }; |
| @@ -721,7 +758,8 @@ static void iwl_mvm_go_iterator(void *_data, u8 *mac, struct ieee80211_vif *vif) | |||
| 721 | struct iwl_mvm_go_iterator_data *data = _data; | 758 | struct iwl_mvm_go_iterator_data *data = _data; |
| 722 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 759 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
| 723 | 760 | ||
| 724 | if (vif->type == NL80211_IFTYPE_AP && vif->p2p && mvmvif->ap_active) | 761 | if (vif->type == NL80211_IFTYPE_AP && vif->p2p && |
| 762 | mvmvif->ap_ibss_active) | ||
| 725 | data->go_active = true; | 763 | data->go_active = true; |
| 726 | } | 764 | } |
| 727 | 765 | ||
| @@ -833,9 +871,10 @@ static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm, | |||
| 833 | cpu_to_le32(iwl_mvm_mac80211_idx_to_hwrate(rate)); | 871 | cpu_to_le32(iwl_mvm_mac80211_idx_to_hwrate(rate)); |
| 834 | 872 | ||
| 835 | /* Set up TX beacon command fields */ | 873 | /* Set up TX beacon command fields */ |
| 836 | iwl_mvm_mac_ctxt_set_tim(mvm, &beacon_cmd, | 874 | if (vif->type == NL80211_IFTYPE_AP) |
| 837 | beacon->data, | 875 | iwl_mvm_mac_ctxt_set_tim(mvm, &beacon_cmd, |
| 838 | beacon_skb_len); | 876 | beacon->data, |
| 877 | beacon_skb_len); | ||
| 839 | 878 | ||
| 840 | /* Submit command */ | 879 | /* Submit command */ |
| 841 | cmd.len[0] = sizeof(beacon_cmd); | 880 | cmd.len[0] = sizeof(beacon_cmd); |
| @@ -848,14 +887,15 @@ static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm, | |||
| 848 | return iwl_mvm_send_cmd(mvm, &cmd); | 887 | return iwl_mvm_send_cmd(mvm, &cmd); |
| 849 | } | 888 | } |
| 850 | 889 | ||
| 851 | /* The beacon template for the AP/GO context has changed and needs update */ | 890 | /* The beacon template for the AP/GO/IBSS has changed and needs update */ |
| 852 | int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm, | 891 | int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm, |
| 853 | struct ieee80211_vif *vif) | 892 | struct ieee80211_vif *vif) |
| 854 | { | 893 | { |
| 855 | struct sk_buff *beacon; | 894 | struct sk_buff *beacon; |
| 856 | int ret; | 895 | int ret; |
| 857 | 896 | ||
| 858 | WARN_ON(vif->type != NL80211_IFTYPE_AP); | 897 | WARN_ON(vif->type != NL80211_IFTYPE_AP && |
| 898 | vif->type != NL80211_IFTYPE_ADHOC); | ||
| 859 | 899 | ||
| 860 | beacon = ieee80211_beacon_get(mvm->hw, vif); | 900 | beacon = ieee80211_beacon_get(mvm->hw, vif); |
| 861 | if (!beacon) | 901 | if (!beacon) |
| @@ -1018,6 +1058,8 @@ static int iwl_mvm_mac_ctx_send(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
| 1018 | return iwl_mvm_mac_ctxt_cmd_listener(mvm, vif, action); | 1058 | return iwl_mvm_mac_ctxt_cmd_listener(mvm, vif, action); |
| 1019 | case NL80211_IFTYPE_P2P_DEVICE: | 1059 | case NL80211_IFTYPE_P2P_DEVICE: |
| 1020 | return iwl_mvm_mac_ctxt_cmd_p2p_device(mvm, vif, action); | 1060 | return iwl_mvm_mac_ctxt_cmd_p2p_device(mvm, vif, action); |
| 1061 | case NL80211_IFTYPE_ADHOC: | ||
| 1062 | return iwl_mvm_mac_ctxt_cmd_ibss(mvm, vif, action); | ||
| 1021 | default: | 1063 | default: |
| 1022 | break; | 1064 | break; |
| 1023 | } | 1065 | } |
| @@ -1038,6 +1080,9 @@ int iwl_mvm_mac_ctxt_add(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
| 1038 | if (ret) | 1080 | if (ret) |
| 1039 | return ret; | 1081 | return ret; |
| 1040 | 1082 | ||
| 1083 | /* will only do anything at resume from D3 time */ | ||
| 1084 | iwl_mvm_set_last_nonqos_seq(mvm, vif); | ||
| 1085 | |||
| 1041 | mvmvif->uploaded = true; | 1086 | mvmvif->uploaded = true; |
| 1042 | return 0; | 1087 | return 0; |
| 1043 | } | 1088 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 9833cdf6177c..f40685c3764e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
| @@ -77,6 +77,7 @@ | |||
| 77 | #include "iwl-eeprom-parse.h" | 77 | #include "iwl-eeprom-parse.h" |
| 78 | #include "fw-api-scan.h" | 78 | #include "fw-api-scan.h" |
| 79 | #include "iwl-phy-db.h" | 79 | #include "iwl-phy-db.h" |
| 80 | #include "testmode.h" | ||
| 80 | 81 | ||
| 81 | static const struct ieee80211_iface_limit iwl_mvm_limits[] = { | 82 | static const struct ieee80211_iface_limit iwl_mvm_limits[] = { |
| 82 | { | 83 | { |
| @@ -138,6 +139,14 @@ static void iwl_mvm_reset_phy_ctxts(struct iwl_mvm *mvm) | |||
| 138 | } | 139 | } |
| 139 | } | 140 | } |
| 140 | 141 | ||
| 142 | static int iwl_mvm_max_scan_ie_len(struct iwl_mvm *mvm) | ||
| 143 | { | ||
| 144 | /* we create the 802.11 header and SSID element */ | ||
| 145 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID) | ||
| 146 | return mvm->fw->ucode_capa.max_probe_length - 24 - 2; | ||
| 147 | return mvm->fw->ucode_capa.max_probe_length - 24 - 34; | ||
| 148 | } | ||
| 149 | |||
| 141 | int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | 150 | int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) |
| 142 | { | 151 | { |
| 143 | struct ieee80211_hw *hw = mvm->hw; | 152 | struct ieee80211_hw *hw = mvm->hw; |
| @@ -158,7 +167,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
| 158 | IEEE80211_HW_SUPPORTS_STATIC_SMPS | | 167 | IEEE80211_HW_SUPPORTS_STATIC_SMPS | |
| 159 | IEEE80211_HW_SUPPORTS_UAPSD; | 168 | IEEE80211_HW_SUPPORTS_UAPSD; |
| 160 | 169 | ||
| 161 | hw->queues = IWL_MVM_FIRST_AGG_QUEUE; | 170 | hw->queues = mvm->first_agg_queue; |
| 162 | hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE; | 171 | hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE; |
| 163 | hw->rate_control_algorithm = "iwl-mvm-rs"; | 172 | hw->rate_control_algorithm = "iwl-mvm-rs"; |
| 164 | 173 | ||
| @@ -181,6 +190,10 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
| 181 | BIT(NL80211_IFTYPE_P2P_GO) | | 190 | BIT(NL80211_IFTYPE_P2P_GO) | |
| 182 | BIT(NL80211_IFTYPE_P2P_DEVICE); | 191 | BIT(NL80211_IFTYPE_P2P_DEVICE); |
| 183 | 192 | ||
| 193 | /* IBSS has bugs in older versions */ | ||
| 194 | if (IWL_UCODE_API(mvm->fw->ucode_ver) >= 8) | ||
| 195 | hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC); | ||
| 196 | |||
| 184 | hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | | 197 | hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | |
| 185 | WIPHY_FLAG_DISABLE_BEACON_HINTS | | 198 | WIPHY_FLAG_DISABLE_BEACON_HINTS | |
| 186 | WIPHY_FLAG_IBSS_RSN; | 199 | WIPHY_FLAG_IBSS_RSN; |
| @@ -212,9 +225,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
| 212 | 225 | ||
| 213 | iwl_mvm_reset_phy_ctxts(mvm); | 226 | iwl_mvm_reset_phy_ctxts(mvm); |
| 214 | 227 | ||
| 215 | /* we create the 802.11 header and a max-length SSID element */ | 228 | hw->wiphy->max_scan_ie_len = iwl_mvm_max_scan_ie_len(mvm); |
| 216 | hw->wiphy->max_scan_ie_len = | 229 | |
| 217 | mvm->fw->ucode_capa.max_probe_length - 24 - 34; | ||
| 218 | hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX; | 230 | hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX; |
| 219 | 231 | ||
| 220 | if (mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels) | 232 | if (mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels) |
| @@ -231,6 +243,15 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
| 231 | else | 243 | else |
| 232 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | 244 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; |
| 233 | 245 | ||
| 246 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_SCHED_SCAN) { | ||
| 247 | hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; | ||
| 248 | hw->wiphy->max_sched_scan_ssids = PROBE_OPTION_MAX; | ||
| 249 | hw->wiphy->max_match_sets = IWL_SCAN_MAX_PROFILES; | ||
| 250 | /* we create the 802.11 header and zero length SSID IE. */ | ||
| 251 | hw->wiphy->max_sched_scan_ie_len = | ||
| 252 | SCAN_OFFLOAD_PROBE_REQ_SIZE - 24 - 2; | ||
| 253 | } | ||
| 254 | |||
| 234 | hw->wiphy->features |= NL80211_FEATURE_P2P_GO_CTWIN | | 255 | hw->wiphy->features |= NL80211_FEATURE_P2P_GO_CTWIN | |
| 235 | NL80211_FEATURE_P2P_GO_OPPPS; | 256 | NL80211_FEATURE_P2P_GO_OPPPS; |
| 236 | 257 | ||
| @@ -548,7 +569,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, | |||
| 548 | * In short: there's not much we can do at this point, other than | 569 | * In short: there's not much we can do at this point, other than |
| 549 | * allocating resources :) | 570 | * allocating resources :) |
| 550 | */ | 571 | */ |
| 551 | if (vif->type == NL80211_IFTYPE_AP) { | 572 | if (vif->type == NL80211_IFTYPE_AP || |
| 573 | vif->type == NL80211_IFTYPE_ADHOC) { | ||
| 552 | u32 qmask = iwl_mvm_mac_get_queues_mask(mvm, vif); | 574 | u32 qmask = iwl_mvm_mac_get_queues_mask(mvm, vif); |
| 553 | ret = iwl_mvm_allocate_int_sta(mvm, &mvmvif->bcast_sta, | 575 | ret = iwl_mvm_allocate_int_sta(mvm, &mvmvif->bcast_sta, |
| 554 | qmask); | 576 | qmask); |
| @@ -698,7 +720,14 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw, | |||
| 698 | * For AP/GO interface, the tear down of the resources allocated to the | 720 | * For AP/GO interface, the tear down of the resources allocated to the |
| 699 | * interface is be handled as part of the stop_ap flow. | 721 | * interface is be handled as part of the stop_ap flow. |
| 700 | */ | 722 | */ |
| 701 | if (vif->type == NL80211_IFTYPE_AP) { | 723 | if (vif->type == NL80211_IFTYPE_AP || |
| 724 | vif->type == NL80211_IFTYPE_ADHOC) { | ||
| 725 | #ifdef CONFIG_NL80211_TESTMODE | ||
| 726 | if (vif == mvm->noa_vif) { | ||
| 727 | mvm->noa_vif = NULL; | ||
| 728 | mvm->noa_duration = 0; | ||
| 729 | } | ||
| 730 | #endif | ||
| 702 | iwl_mvm_dealloc_int_sta(mvm, &mvmvif->bcast_sta); | 731 | iwl_mvm_dealloc_int_sta(mvm, &mvmvif->bcast_sta); |
| 703 | goto out_release; | 732 | goto out_release; |
| 704 | } | 733 | } |
| @@ -796,6 +825,27 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | |||
| 796 | return; | 825 | return; |
| 797 | } | 826 | } |
| 798 | iwl_mvm_configure_mcast_filter(mvm, vif); | 827 | iwl_mvm_configure_mcast_filter(mvm, vif); |
| 828 | |||
| 829 | if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, | ||
| 830 | &mvm->status)) { | ||
| 831 | /* | ||
| 832 | * If we're restarting then the firmware will | ||
| 833 | * obviously have lost synchronisation with | ||
| 834 | * the AP. It will attempt to synchronise by | ||
| 835 | * itself, but we can make it more reliable by | ||
| 836 | * scheduling a session protection time event. | ||
| 837 | * | ||
| 838 | * The firmware needs to receive a beacon to | ||
| 839 | * catch up with synchronisation, use 110% of | ||
| 840 | * the beacon interval. | ||
| 841 | * | ||
| 842 | * Set a large maximum delay to allow for more | ||
| 843 | * than a single interface. | ||
| 844 | */ | ||
| 845 | u32 dur = (11 * vif->bss_conf.beacon_int) / 10; | ||
| 846 | iwl_mvm_protect_session(mvm, vif, dur, dur, | ||
| 847 | 5 * dur); | ||
| 848 | } | ||
| 799 | } else if (mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) { | 849 | } else if (mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) { |
| 800 | /* remove AP station now that the MAC is unassoc */ | 850 | /* remove AP station now that the MAC is unassoc */ |
| 801 | ret = iwl_mvm_rm_sta_id(mvm, vif, mvmvif->ap_sta_id); | 851 | ret = iwl_mvm_rm_sta_id(mvm, vif, mvmvif->ap_sta_id); |
| @@ -819,7 +869,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | |||
| 819 | if (ret) | 869 | if (ret) |
| 820 | IWL_ERR(mvm, "failed to update power mode\n"); | 870 | IWL_ERR(mvm, "failed to update power mode\n"); |
| 821 | } | 871 | } |
| 822 | iwl_mvm_bt_coex_vif_assoc(mvm, vif); | 872 | iwl_mvm_bt_coex_vif_change(mvm); |
| 823 | } else if (changes & BSS_CHANGED_BEACON_INFO) { | 873 | } else if (changes & BSS_CHANGED_BEACON_INFO) { |
| 824 | /* | 874 | /* |
| 825 | * We received a beacon _after_ association so | 875 | * We received a beacon _after_ association so |
| @@ -848,7 +898,8 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | |||
| 848 | } | 898 | } |
| 849 | } | 899 | } |
| 850 | 900 | ||
| 851 | static int iwl_mvm_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | 901 | static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw, |
| 902 | struct ieee80211_vif *vif) | ||
| 852 | { | 903 | { |
| 853 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 904 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
| 854 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 905 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
| @@ -871,7 +922,7 @@ static int iwl_mvm_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
| 871 | if (ret) | 922 | if (ret) |
| 872 | goto out_remove; | 923 | goto out_remove; |
| 873 | 924 | ||
| 874 | mvmvif->ap_active = true; | 925 | mvmvif->ap_ibss_active = true; |
| 875 | 926 | ||
| 876 | /* Send the bcast station. At this stage the TBTT and DTIM time events | 927 | /* Send the bcast station. At this stage the TBTT and DTIM time events |
| 877 | * are added and applied to the scheduler */ | 928 | * are added and applied to the scheduler */ |
| @@ -883,10 +934,12 @@ static int iwl_mvm_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
| 883 | if (ret) | 934 | if (ret) |
| 884 | goto out_rm_bcast; | 935 | goto out_rm_bcast; |
| 885 | 936 | ||
| 886 | /* Need to update the P2P Device MAC */ | 937 | /* Need to update the P2P Device MAC (only GO, IBSS is single vif) */ |
| 887 | if (vif->p2p && mvm->p2p_device_vif) | 938 | if (vif->p2p && mvm->p2p_device_vif) |
| 888 | iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif); | 939 | iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif); |
| 889 | 940 | ||
| 941 | iwl_mvm_bt_coex_vif_change(mvm); | ||
| 942 | |||
| 890 | mutex_unlock(&mvm->mutex); | 943 | mutex_unlock(&mvm->mutex); |
| 891 | return 0; | 944 | return 0; |
| 892 | 945 | ||
| @@ -901,7 +954,8 @@ out_unlock: | |||
| 901 | return ret; | 954 | return ret; |
| 902 | } | 955 | } |
| 903 | 956 | ||
| 904 | static void iwl_mvm_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | 957 | static void iwl_mvm_stop_ap_ibss(struct ieee80211_hw *hw, |
| 958 | struct ieee80211_vif *vif) | ||
| 905 | { | 959 | { |
| 906 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 960 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
| 907 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 961 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
| @@ -910,9 +964,11 @@ static void iwl_mvm_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
| 910 | 964 | ||
| 911 | mutex_lock(&mvm->mutex); | 965 | mutex_lock(&mvm->mutex); |
| 912 | 966 | ||
| 913 | mvmvif->ap_active = false; | 967 | mvmvif->ap_ibss_active = false; |
| 968 | |||
| 969 | iwl_mvm_bt_coex_vif_change(mvm); | ||
| 914 | 970 | ||
| 915 | /* Need to update the P2P Device MAC */ | 971 | /* Need to update the P2P Device MAC (only GO, IBSS is single vif) */ |
| 916 | if (vif->p2p && mvm->p2p_device_vif) | 972 | if (vif->p2p && mvm->p2p_device_vif) |
| 917 | iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif); | 973 | iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif); |
| 918 | 974 | ||
| @@ -924,10 +980,11 @@ static void iwl_mvm_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
| 924 | mutex_unlock(&mvm->mutex); | 980 | mutex_unlock(&mvm->mutex); |
| 925 | } | 981 | } |
| 926 | 982 | ||
| 927 | static void iwl_mvm_bss_info_changed_ap(struct iwl_mvm *mvm, | 983 | static void |
| 928 | struct ieee80211_vif *vif, | 984 | iwl_mvm_bss_info_changed_ap_ibss(struct iwl_mvm *mvm, |
| 929 | struct ieee80211_bss_conf *bss_conf, | 985 | struct ieee80211_vif *vif, |
| 930 | u32 changes) | 986 | struct ieee80211_bss_conf *bss_conf, |
| 987 | u32 changes) | ||
| 931 | { | 988 | { |
| 932 | /* Need to send a new beacon template to the FW */ | 989 | /* Need to send a new beacon template to the FW */ |
| 933 | if (changes & BSS_CHANGED_BEACON) { | 990 | if (changes & BSS_CHANGED_BEACON) { |
| @@ -950,7 +1007,8 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw, | |||
| 950 | iwl_mvm_bss_info_changed_station(mvm, vif, bss_conf, changes); | 1007 | iwl_mvm_bss_info_changed_station(mvm, vif, bss_conf, changes); |
| 951 | break; | 1008 | break; |
| 952 | case NL80211_IFTYPE_AP: | 1009 | case NL80211_IFTYPE_AP: |
| 953 | iwl_mvm_bss_info_changed_ap(mvm, vif, bss_conf, changes); | 1010 | case NL80211_IFTYPE_ADHOC: |
| 1011 | iwl_mvm_bss_info_changed_ap_ibss(mvm, vif, bss_conf, changes); | ||
| 954 | break; | 1012 | break; |
| 955 | default: | 1013 | default: |
| 956 | /* shouldn't happen */ | 1014 | /* shouldn't happen */ |
| @@ -1163,7 +1221,54 @@ static void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw, | |||
| 1163 | 1221 | ||
| 1164 | mutex_lock(&mvm->mutex); | 1222 | mutex_lock(&mvm->mutex); |
| 1165 | /* Try really hard to protect the session and hear a beacon */ | 1223 | /* Try really hard to protect the session and hear a beacon */ |
| 1166 | iwl_mvm_protect_session(mvm, vif, duration, min_duration); | 1224 | iwl_mvm_protect_session(mvm, vif, duration, min_duration, 500); |
| 1225 | mutex_unlock(&mvm->mutex); | ||
| 1226 | } | ||
| 1227 | |||
| 1228 | static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw, | ||
| 1229 | struct ieee80211_vif *vif, | ||
| 1230 | struct cfg80211_sched_scan_request *req, | ||
| 1231 | struct ieee80211_sched_scan_ies *ies) | ||
| 1232 | { | ||
| 1233 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | ||
| 1234 | int ret; | ||
| 1235 | |||
| 1236 | mutex_lock(&mvm->mutex); | ||
| 1237 | |||
| 1238 | if (mvm->scan_status != IWL_MVM_SCAN_NONE) { | ||
| 1239 | IWL_DEBUG_SCAN(mvm, | ||
| 1240 | "SCHED SCAN request during internal scan - abort\n"); | ||
| 1241 | ret = -EBUSY; | ||
| 1242 | goto out; | ||
| 1243 | } | ||
| 1244 | |||
| 1245 | mvm->scan_status = IWL_MVM_SCAN_SCHED; | ||
| 1246 | |||
| 1247 | ret = iwl_mvm_config_sched_scan(mvm, vif, req, ies); | ||
| 1248 | if (ret) | ||
| 1249 | goto err; | ||
| 1250 | |||
| 1251 | ret = iwl_mvm_config_sched_scan_profiles(mvm, req); | ||
| 1252 | if (ret) | ||
| 1253 | goto err; | ||
| 1254 | |||
| 1255 | ret = iwl_mvm_sched_scan_start(mvm, req); | ||
| 1256 | if (!ret) | ||
| 1257 | goto out; | ||
| 1258 | err: | ||
| 1259 | mvm->scan_status = IWL_MVM_SCAN_NONE; | ||
| 1260 | out: | ||
| 1261 | mutex_unlock(&mvm->mutex); | ||
| 1262 | return ret; | ||
| 1263 | } | ||
| 1264 | |||
| 1265 | static void iwl_mvm_mac_sched_scan_stop(struct ieee80211_hw *hw, | ||
| 1266 | struct ieee80211_vif *vif) | ||
| 1267 | { | ||
| 1268 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | ||
| 1269 | |||
| 1270 | mutex_lock(&mvm->mutex); | ||
| 1271 | iwl_mvm_sched_scan_stop(mvm); | ||
| 1167 | mutex_unlock(&mvm->mutex); | 1272 | mutex_unlock(&mvm->mutex); |
| 1168 | } | 1273 | } |
| 1169 | 1274 | ||
| @@ -1207,8 +1312,13 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw, | |||
| 1207 | 1312 | ||
| 1208 | switch (cmd) { | 1313 | switch (cmd) { |
| 1209 | case SET_KEY: | 1314 | case SET_KEY: |
| 1210 | if (vif->type == NL80211_IFTYPE_AP && !sta) { | 1315 | if ((vif->type == NL80211_IFTYPE_ADHOC || |
| 1211 | /* GTK on AP interface is a TX-only key, return 0 */ | 1316 | vif->type == NL80211_IFTYPE_AP) && !sta) { |
| 1317 | /* | ||
| 1318 | * GTK on AP interface is a TX-only key, return 0; | ||
| 1319 | * on IBSS they're per-station and because we're lazy | ||
| 1320 | * we don't support them for RX, so do the same. | ||
| 1321 | */ | ||
| 1212 | ret = 0; | 1322 | ret = 0; |
| 1213 | key->hw_key_idx = STA_KEY_IDX_INVALID; | 1323 | key->hw_key_idx = STA_KEY_IDX_INVALID; |
| 1214 | break; | 1324 | break; |
| @@ -1252,6 +1362,9 @@ static void iwl_mvm_mac_update_tkip_key(struct ieee80211_hw *hw, | |||
| 1252 | { | 1362 | { |
| 1253 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 1363 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
| 1254 | 1364 | ||
| 1365 | if (keyconf->hw_key_idx == STA_KEY_IDX_INVALID) | ||
| 1366 | return; | ||
| 1367 | |||
| 1255 | iwl_mvm_update_tkip_key(mvm, vif, keyconf, sta, iv32, phase1key); | 1368 | iwl_mvm_update_tkip_key(mvm, vif, keyconf, sta, iv32, phase1key); |
| 1256 | } | 1369 | } |
| 1257 | 1370 | ||
| @@ -1445,6 +1558,7 @@ static void iwl_mvm_change_chanctx(struct ieee80211_hw *hw, | |||
| 1445 | iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx->def, | 1558 | iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx->def, |
| 1446 | ctx->rx_chains_static, | 1559 | ctx->rx_chains_static, |
| 1447 | ctx->rx_chains_dynamic); | 1560 | ctx->rx_chains_dynamic); |
| 1561 | iwl_mvm_bt_coex_vif_change(mvm); | ||
| 1448 | mutex_unlock(&mvm->mutex); | 1562 | mutex_unlock(&mvm->mutex); |
| 1449 | } | 1563 | } |
| 1450 | 1564 | ||
| @@ -1464,14 +1578,14 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw, | |||
| 1464 | 1578 | ||
| 1465 | switch (vif->type) { | 1579 | switch (vif->type) { |
| 1466 | case NL80211_IFTYPE_AP: | 1580 | case NL80211_IFTYPE_AP: |
| 1581 | case NL80211_IFTYPE_ADHOC: | ||
| 1467 | /* | 1582 | /* |
| 1468 | * The AP binding flow is handled as part of the start_ap flow | 1583 | * The AP binding flow is handled as part of the start_ap flow |
| 1469 | * (in bss_info_changed). | 1584 | * (in bss_info_changed), similarly for IBSS. |
| 1470 | */ | 1585 | */ |
| 1471 | ret = 0; | 1586 | ret = 0; |
| 1472 | goto out_unlock; | 1587 | goto out_unlock; |
| 1473 | case NL80211_IFTYPE_STATION: | 1588 | case NL80211_IFTYPE_STATION: |
| 1474 | case NL80211_IFTYPE_ADHOC: | ||
| 1475 | case NL80211_IFTYPE_MONITOR: | 1589 | case NL80211_IFTYPE_MONITOR: |
| 1476 | break; | 1590 | break; |
| 1477 | default: | 1591 | default: |
| @@ -1517,10 +1631,10 @@ static void iwl_mvm_unassign_vif_chanctx(struct ieee80211_hw *hw, | |||
| 1517 | 1631 | ||
| 1518 | iwl_mvm_remove_time_event(mvm, mvmvif, &mvmvif->time_event_data); | 1632 | iwl_mvm_remove_time_event(mvm, mvmvif, &mvmvif->time_event_data); |
| 1519 | 1633 | ||
| 1520 | if (vif->type == NL80211_IFTYPE_AP) | ||
| 1521 | goto out_unlock; | ||
| 1522 | |||
| 1523 | switch (vif->type) { | 1634 | switch (vif->type) { |
| 1635 | case NL80211_IFTYPE_AP: | ||
| 1636 | case NL80211_IFTYPE_ADHOC: | ||
| 1637 | goto out_unlock; | ||
| 1524 | case NL80211_IFTYPE_MONITOR: | 1638 | case NL80211_IFTYPE_MONITOR: |
| 1525 | mvmvif->monitor_active = false; | 1639 | mvmvif->monitor_active = false; |
| 1526 | iwl_mvm_update_quotas(mvm, NULL); | 1640 | iwl_mvm_update_quotas(mvm, NULL); |
| @@ -1550,14 +1664,72 @@ static int iwl_mvm_set_tim(struct ieee80211_hw *hw, | |||
| 1550 | return iwl_mvm_mac_ctxt_beacon_changed(mvm, mvm_sta->vif); | 1664 | return iwl_mvm_mac_ctxt_beacon_changed(mvm, mvm_sta->vif); |
| 1551 | } | 1665 | } |
| 1552 | 1666 | ||
| 1553 | static void iwl_mvm_mac_rssi_callback(struct ieee80211_hw *hw, | 1667 | #ifdef CONFIG_NL80211_TESTMODE |
| 1668 | static const struct nla_policy iwl_mvm_tm_policy[IWL_MVM_TM_ATTR_MAX + 1] = { | ||
| 1669 | [IWL_MVM_TM_ATTR_CMD] = { .type = NLA_U32 }, | ||
| 1670 | [IWL_MVM_TM_ATTR_NOA_DURATION] = { .type = NLA_U32 }, | ||
| 1671 | [IWL_MVM_TM_ATTR_BEACON_FILTER_STATE] = { .type = NLA_U32 }, | ||
| 1672 | }; | ||
| 1673 | |||
| 1674 | static int __iwl_mvm_mac_testmode_cmd(struct iwl_mvm *mvm, | ||
| 1554 | struct ieee80211_vif *vif, | 1675 | struct ieee80211_vif *vif, |
| 1555 | enum ieee80211_rssi_event rssi_event) | 1676 | void *data, int len) |
| 1677 | { | ||
| 1678 | struct nlattr *tb[IWL_MVM_TM_ATTR_MAX + 1]; | ||
| 1679 | int err; | ||
| 1680 | u32 noa_duration; | ||
| 1681 | |||
| 1682 | err = nla_parse(tb, IWL_MVM_TM_ATTR_MAX, data, len, iwl_mvm_tm_policy); | ||
| 1683 | if (err) | ||
| 1684 | return err; | ||
| 1685 | |||
| 1686 | if (!tb[IWL_MVM_TM_ATTR_CMD]) | ||
| 1687 | return -EINVAL; | ||
| 1688 | |||
| 1689 | switch (nla_get_u32(tb[IWL_MVM_TM_ATTR_CMD])) { | ||
| 1690 | case IWL_MVM_TM_CMD_SET_NOA: | ||
| 1691 | if (!vif || vif->type != NL80211_IFTYPE_AP || !vif->p2p || | ||
| 1692 | !vif->bss_conf.enable_beacon || | ||
| 1693 | !tb[IWL_MVM_TM_ATTR_NOA_DURATION]) | ||
| 1694 | return -EINVAL; | ||
| 1695 | |||
| 1696 | noa_duration = nla_get_u32(tb[IWL_MVM_TM_ATTR_NOA_DURATION]); | ||
| 1697 | if (noa_duration >= vif->bss_conf.beacon_int) | ||
| 1698 | return -EINVAL; | ||
| 1699 | |||
| 1700 | mvm->noa_duration = noa_duration; | ||
| 1701 | mvm->noa_vif = vif; | ||
| 1702 | |||
| 1703 | return iwl_mvm_update_quotas(mvm, NULL); | ||
| 1704 | case IWL_MVM_TM_CMD_SET_BEACON_FILTER: | ||
| 1705 | /* must be associated client vif - ignore authorized */ | ||
| 1706 | if (!vif || vif->type != NL80211_IFTYPE_STATION || | ||
| 1707 | !vif->bss_conf.assoc || !vif->bss_conf.dtim_period || | ||
| 1708 | !tb[IWL_MVM_TM_ATTR_BEACON_FILTER_STATE]) | ||
| 1709 | return -EINVAL; | ||
| 1710 | |||
| 1711 | if (nla_get_u32(tb[IWL_MVM_TM_ATTR_BEACON_FILTER_STATE])) | ||
| 1712 | return iwl_mvm_enable_beacon_filter(mvm, vif); | ||
| 1713 | return iwl_mvm_disable_beacon_filter(mvm, vif); | ||
| 1714 | } | ||
| 1715 | |||
| 1716 | return -EOPNOTSUPP; | ||
| 1717 | } | ||
| 1718 | |||
| 1719 | static int iwl_mvm_mac_testmode_cmd(struct ieee80211_hw *hw, | ||
| 1720 | struct ieee80211_vif *vif, | ||
| 1721 | void *data, int len) | ||
| 1556 | { | 1722 | { |
| 1557 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 1723 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
| 1724 | int err; | ||
| 1558 | 1725 | ||
| 1559 | iwl_mvm_bt_rssi_event(mvm, vif, rssi_event); | 1726 | mutex_lock(&mvm->mutex); |
| 1727 | err = __iwl_mvm_mac_testmode_cmd(mvm, vif, data, len); | ||
| 1728 | mutex_unlock(&mvm->mutex); | ||
| 1729 | |||
| 1730 | return err; | ||
| 1560 | } | 1731 | } |
| 1732 | #endif | ||
| 1561 | 1733 | ||
| 1562 | struct ieee80211_ops iwl_mvm_hw_ops = { | 1734 | struct ieee80211_ops iwl_mvm_hw_ops = { |
| 1563 | .tx = iwl_mvm_mac_tx, | 1735 | .tx = iwl_mvm_mac_tx, |
| @@ -1578,23 +1750,27 @@ struct ieee80211_ops iwl_mvm_hw_ops = { | |||
| 1578 | .set_rts_threshold = iwl_mvm_mac_set_rts_threshold, | 1750 | .set_rts_threshold = iwl_mvm_mac_set_rts_threshold, |
| 1579 | .conf_tx = iwl_mvm_mac_conf_tx, | 1751 | .conf_tx = iwl_mvm_mac_conf_tx, |
| 1580 | .mgd_prepare_tx = iwl_mvm_mac_mgd_prepare_tx, | 1752 | .mgd_prepare_tx = iwl_mvm_mac_mgd_prepare_tx, |
| 1753 | .sched_scan_start = iwl_mvm_mac_sched_scan_start, | ||
| 1754 | .sched_scan_stop = iwl_mvm_mac_sched_scan_stop, | ||
| 1581 | .set_key = iwl_mvm_mac_set_key, | 1755 | .set_key = iwl_mvm_mac_set_key, |
| 1582 | .update_tkip_key = iwl_mvm_mac_update_tkip_key, | 1756 | .update_tkip_key = iwl_mvm_mac_update_tkip_key, |
| 1583 | .remain_on_channel = iwl_mvm_roc, | 1757 | .remain_on_channel = iwl_mvm_roc, |
| 1584 | .cancel_remain_on_channel = iwl_mvm_cancel_roc, | 1758 | .cancel_remain_on_channel = iwl_mvm_cancel_roc, |
| 1585 | .rssi_callback = iwl_mvm_mac_rssi_callback, | ||
| 1586 | |||
| 1587 | .add_chanctx = iwl_mvm_add_chanctx, | 1759 | .add_chanctx = iwl_mvm_add_chanctx, |
| 1588 | .remove_chanctx = iwl_mvm_remove_chanctx, | 1760 | .remove_chanctx = iwl_mvm_remove_chanctx, |
| 1589 | .change_chanctx = iwl_mvm_change_chanctx, | 1761 | .change_chanctx = iwl_mvm_change_chanctx, |
| 1590 | .assign_vif_chanctx = iwl_mvm_assign_vif_chanctx, | 1762 | .assign_vif_chanctx = iwl_mvm_assign_vif_chanctx, |
| 1591 | .unassign_vif_chanctx = iwl_mvm_unassign_vif_chanctx, | 1763 | .unassign_vif_chanctx = iwl_mvm_unassign_vif_chanctx, |
| 1592 | 1764 | ||
| 1593 | .start_ap = iwl_mvm_start_ap, | 1765 | .start_ap = iwl_mvm_start_ap_ibss, |
| 1594 | .stop_ap = iwl_mvm_stop_ap, | 1766 | .stop_ap = iwl_mvm_stop_ap_ibss, |
| 1767 | .join_ibss = iwl_mvm_start_ap_ibss, | ||
| 1768 | .leave_ibss = iwl_mvm_stop_ap_ibss, | ||
| 1595 | 1769 | ||
| 1596 | .set_tim = iwl_mvm_set_tim, | 1770 | .set_tim = iwl_mvm_set_tim, |
| 1597 | 1771 | ||
| 1772 | CFG80211_TESTMODE_CMD(iwl_mvm_mac_testmode_cmd) | ||
| 1773 | |||
| 1598 | #ifdef CONFIG_PM_SLEEP | 1774 | #ifdef CONFIG_PM_SLEEP |
| 1599 | /* look at d3.c */ | 1775 | /* look at d3.c */ |
| 1600 | .suspend = iwl_mvm_suspend, | 1776 | .suspend = iwl_mvm_suspend, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index b0389279cc1e..6235cb729f5c 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h | |||
| @@ -162,6 +162,7 @@ enum iwl_power_scheme { | |||
| 162 | struct iwl_mvm_power_ops { | 162 | struct iwl_mvm_power_ops { |
| 163 | int (*power_update_mode)(struct iwl_mvm *mvm, | 163 | int (*power_update_mode)(struct iwl_mvm *mvm, |
| 164 | struct ieee80211_vif *vif); | 164 | struct ieee80211_vif *vif); |
| 165 | int (*power_update_device_mode)(struct iwl_mvm *mvm); | ||
| 165 | int (*power_disable)(struct iwl_mvm *mvm, struct ieee80211_vif *vif); | 166 | int (*power_disable)(struct iwl_mvm *mvm, struct ieee80211_vif *vif); |
| 166 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 167 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
| 167 | int (*power_dbgfs_read)(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 168 | int (*power_dbgfs_read)(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
| @@ -241,12 +242,18 @@ enum iwl_mvm_smps_type_request { | |||
| 241 | * @last_beacon_signal: last beacon rssi signal in dbm | 242 | * @last_beacon_signal: last beacon rssi signal in dbm |
| 242 | * @ave_beacon_signal: average beacon signal | 243 | * @ave_beacon_signal: average beacon signal |
| 243 | * @last_cqm_event: rssi of the last cqm event | 244 | * @last_cqm_event: rssi of the last cqm event |
| 245 | * @bt_coex_min_thold: minimum threshold for BT coex | ||
| 246 | * @bt_coex_max_thold: maximum threshold for BT coex | ||
| 247 | * @last_bt_coex_event: rssi of the last BT coex event | ||
| 244 | */ | 248 | */ |
| 245 | struct iwl_mvm_vif_bf_data { | 249 | struct iwl_mvm_vif_bf_data { |
| 246 | bool bf_enabled; | 250 | bool bf_enabled; |
| 247 | bool ba_enabled; | 251 | bool ba_enabled; |
| 248 | s8 ave_beacon_signal; | 252 | s8 ave_beacon_signal; |
| 249 | s8 last_cqm_event; | 253 | s8 last_cqm_event; |
| 254 | s8 bt_coex_min_thold; | ||
| 255 | s8 bt_coex_max_thold; | ||
| 256 | s8 last_bt_coex_event; | ||
| 250 | }; | 257 | }; |
| 251 | 258 | ||
| 252 | /** | 259 | /** |
| @@ -255,8 +262,8 @@ struct iwl_mvm_vif_bf_data { | |||
| 255 | * @color: to solve races upon MAC addition and removal | 262 | * @color: to solve races upon MAC addition and removal |
| 256 | * @ap_sta_id: the sta_id of the AP - valid only if VIF type is STA | 263 | * @ap_sta_id: the sta_id of the AP - valid only if VIF type is STA |
| 257 | * @uploaded: indicates the MAC context has been added to the device | 264 | * @uploaded: indicates the MAC context has been added to the device |
| 258 | * @ap_active: indicates that ap context is configured, and that the interface | 265 | * @ap_ibss_active: indicates that AP/IBSS is configured and that the interface |
| 259 | * should get quota etc. | 266 | * should get quota etc. |
| 260 | * @monitor_active: indicates that monitor context is configured, and that the | 267 | * @monitor_active: indicates that monitor context is configured, and that the |
| 261 | * interface should get quota etc. | 268 | * interface should get quota etc. |
| 262 | * @queue_params: QoS params for this MAC | 269 | * @queue_params: QoS params for this MAC |
| @@ -272,7 +279,7 @@ struct iwl_mvm_vif { | |||
| 272 | u8 ap_sta_id; | 279 | u8 ap_sta_id; |
| 273 | 280 | ||
| 274 | bool uploaded; | 281 | bool uploaded; |
| 275 | bool ap_active; | 282 | bool ap_ibss_active; |
| 276 | bool monitor_active; | 283 | bool monitor_active; |
| 277 | struct iwl_mvm_vif_bf_data bf_data; | 284 | struct iwl_mvm_vif_bf_data bf_data; |
| 278 | 285 | ||
| @@ -306,6 +313,9 @@ struct iwl_mvm_vif { | |||
| 306 | 313 | ||
| 307 | int tx_key_idx; | 314 | int tx_key_idx; |
| 308 | 315 | ||
| 316 | bool seqno_valid; | ||
| 317 | u16 seqno; | ||
| 318 | |||
| 309 | #if IS_ENABLED(CONFIG_IPV6) | 319 | #if IS_ENABLED(CONFIG_IPV6) |
| 310 | /* IPv6 addresses for WoWLAN */ | 320 | /* IPv6 addresses for WoWLAN */ |
| 311 | struct in6_addr target_ipv6_addrs[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_MAX]; | 321 | struct in6_addr target_ipv6_addrs[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_MAX]; |
| @@ -333,6 +343,7 @@ iwl_mvm_vif_from_mac80211(struct ieee80211_vif *vif) | |||
| 333 | enum iwl_scan_status { | 343 | enum iwl_scan_status { |
| 334 | IWL_MVM_SCAN_NONE, | 344 | IWL_MVM_SCAN_NONE, |
| 335 | IWL_MVM_SCAN_OS, | 345 | IWL_MVM_SCAN_OS, |
| 346 | IWL_MVM_SCAN_SCHED, | ||
| 336 | }; | 347 | }; |
| 337 | 348 | ||
| 338 | /** | 349 | /** |
| @@ -434,7 +445,7 @@ struct iwl_mvm { | |||
| 434 | 445 | ||
| 435 | enum iwl_ucode_type cur_ucode; | 446 | enum iwl_ucode_type cur_ucode; |
| 436 | bool ucode_loaded; | 447 | bool ucode_loaded; |
| 437 | bool init_ucode_run; | 448 | bool init_ucode_complete; |
| 438 | u32 error_event_table; | 449 | u32 error_event_table; |
| 439 | u32 log_event_table; | 450 | u32 log_event_table; |
| 440 | 451 | ||
| @@ -470,6 +481,9 @@ struct iwl_mvm { | |||
| 470 | enum iwl_scan_status scan_status; | 481 | enum iwl_scan_status scan_status; |
| 471 | struct iwl_scan_cmd *scan_cmd; | 482 | struct iwl_scan_cmd *scan_cmd; |
| 472 | 483 | ||
| 484 | /* rx chain antennas set through debugfs for the scan command */ | ||
| 485 | u8 scan_rx_ant; | ||
| 486 | |||
| 473 | /* Internal station */ | 487 | /* Internal station */ |
| 474 | struct iwl_mvm_int_sta aux_sta; | 488 | struct iwl_mvm_int_sta aux_sta; |
| 475 | 489 | ||
| @@ -479,7 +493,8 @@ struct iwl_mvm { | |||
| 479 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 493 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
| 480 | struct dentry *debugfs_dir; | 494 | struct dentry *debugfs_dir; |
| 481 | u32 dbgfs_sram_offset, dbgfs_sram_len; | 495 | u32 dbgfs_sram_offset, dbgfs_sram_len; |
| 482 | bool prevent_power_down_d3; | 496 | bool disable_power_off; |
| 497 | bool disable_power_off_d3; | ||
| 483 | #endif | 498 | #endif |
| 484 | 499 | ||
| 485 | struct iwl_mvm_phy_ctxt phy_ctxts[NUM_PHY_CTX]; | 500 | struct iwl_mvm_phy_ctxt phy_ctxts[NUM_PHY_CTX]; |
| @@ -523,12 +538,23 @@ struct iwl_mvm { | |||
| 523 | /* BT-Coex */ | 538 | /* BT-Coex */ |
| 524 | u8 bt_kill_msk; | 539 | u8 bt_kill_msk; |
| 525 | struct iwl_bt_coex_profile_notif last_bt_notif; | 540 | struct iwl_bt_coex_profile_notif last_bt_notif; |
| 541 | struct iwl_bt_coex_ci_cmd last_bt_ci_cmd; | ||
| 526 | 542 | ||
| 527 | /* Thermal Throttling and CTkill */ | 543 | /* Thermal Throttling and CTkill */ |
| 528 | struct iwl_mvm_tt_mgmt thermal_throttle; | 544 | struct iwl_mvm_tt_mgmt thermal_throttle; |
| 529 | s32 temperature; /* Celsius */ | 545 | s32 temperature; /* Celsius */ |
| 530 | 546 | ||
| 531 | const struct iwl_mvm_power_ops *pm_ops; | 547 | const struct iwl_mvm_power_ops *pm_ops; |
| 548 | |||
| 549 | #ifdef CONFIG_NL80211_TESTMODE | ||
| 550 | u32 noa_duration; | ||
| 551 | struct ieee80211_vif *noa_vif; | ||
| 552 | #endif | ||
| 553 | |||
| 554 | /* Tx queues */ | ||
| 555 | u8 aux_queue; | ||
| 556 | u8 first_agg_queue; | ||
| 557 | u8 last_agg_queue; | ||
| 532 | }; | 558 | }; |
| 533 | 559 | ||
| 534 | /* Extract MVM priv from op_mode and _hw */ | 560 | /* Extract MVM priv from op_mode and _hw */ |
| @@ -570,6 +596,9 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm); | |||
| 570 | /* Utils */ | 596 | /* Utils */ |
| 571 | int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags, | 597 | int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags, |
| 572 | enum ieee80211_band band); | 598 | enum ieee80211_band band); |
| 599 | void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags, | ||
| 600 | enum ieee80211_band band, | ||
| 601 | struct ieee80211_tx_rate *r); | ||
| 573 | u8 iwl_mvm_mac80211_idx_to_hwrate(int rate_idx); | 602 | u8 iwl_mvm_mac80211_idx_to_hwrate(int rate_idx); |
| 574 | void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm); | 603 | void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm); |
| 575 | void iwl_mvm_dump_sram(struct iwl_mvm *mvm); | 604 | void iwl_mvm_dump_sram(struct iwl_mvm *mvm); |
| @@ -608,6 +637,7 @@ int iwl_mvm_rx_statistics(struct iwl_mvm *mvm, | |||
| 608 | 637 | ||
| 609 | /* NVM */ | 638 | /* NVM */ |
| 610 | int iwl_nvm_init(struct iwl_mvm *mvm); | 639 | int iwl_nvm_init(struct iwl_mvm *mvm); |
| 640 | int iwl_mvm_load_nvm_to_nic(struct iwl_mvm *mvm); | ||
| 611 | 641 | ||
| 612 | int iwl_mvm_up(struct iwl_mvm *mvm); | 642 | int iwl_mvm_up(struct iwl_mvm *mvm); |
| 613 | int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm); | 643 | int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm); |
| @@ -682,6 +712,23 @@ int iwl_mvm_rx_scan_complete(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | |||
| 682 | struct iwl_device_cmd *cmd); | 712 | struct iwl_device_cmd *cmd); |
| 683 | void iwl_mvm_cancel_scan(struct iwl_mvm *mvm); | 713 | void iwl_mvm_cancel_scan(struct iwl_mvm *mvm); |
| 684 | 714 | ||
| 715 | /* Scheduled scan */ | ||
| 716 | int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm, | ||
| 717 | struct iwl_rx_cmd_buffer *rxb, | ||
| 718 | struct iwl_device_cmd *cmd); | ||
| 719 | int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm, | ||
| 720 | struct ieee80211_vif *vif, | ||
| 721 | struct cfg80211_sched_scan_request *req, | ||
| 722 | struct ieee80211_sched_scan_ies *ies); | ||
| 723 | int iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm, | ||
| 724 | struct cfg80211_sched_scan_request *req); | ||
| 725 | int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, | ||
| 726 | struct cfg80211_sched_scan_request *req); | ||
| 727 | void iwl_mvm_sched_scan_stop(struct iwl_mvm *mvm); | ||
| 728 | int iwl_mvm_rx_sched_scan_results(struct iwl_mvm *mvm, | ||
| 729 | struct iwl_rx_cmd_buffer *rxb, | ||
| 730 | struct iwl_device_cmd *cmd); | ||
| 731 | |||
| 685 | /* MVM debugfs */ | 732 | /* MVM debugfs */ |
| 686 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 733 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
| 687 | int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir); | 734 | int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir); |
| @@ -720,6 +767,13 @@ static inline int iwl_mvm_power_disable(struct iwl_mvm *mvm, | |||
| 720 | return mvm->pm_ops->power_disable(mvm, vif); | 767 | return mvm->pm_ops->power_disable(mvm, vif); |
| 721 | } | 768 | } |
| 722 | 769 | ||
| 770 | static inline int iwl_mvm_power_update_device_mode(struct iwl_mvm *mvm) | ||
| 771 | { | ||
| 772 | if (mvm->pm_ops->power_update_device_mode) | ||
| 773 | return mvm->pm_ops->power_update_device_mode(mvm); | ||
| 774 | return 0; | ||
| 775 | } | ||
| 776 | |||
| 723 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 777 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
| 724 | static inline int iwl_mvm_power_dbgfs_read(struct iwl_mvm *mvm, | 778 | static inline int iwl_mvm_power_dbgfs_read(struct iwl_mvm *mvm, |
| 725 | struct ieee80211_vif *vif, | 779 | struct ieee80211_vif *vif, |
| @@ -745,6 +799,15 @@ void iwl_mvm_ipv6_addr_change(struct ieee80211_hw *hw, | |||
| 745 | void iwl_mvm_set_default_unicast_key(struct ieee80211_hw *hw, | 799 | void iwl_mvm_set_default_unicast_key(struct ieee80211_hw *hw, |
| 746 | struct ieee80211_vif *vif, int idx); | 800 | struct ieee80211_vif *vif, int idx); |
| 747 | extern const struct file_operations iwl_dbgfs_d3_test_ops; | 801 | extern const struct file_operations iwl_dbgfs_d3_test_ops; |
| 802 | #ifdef CONFIG_PM_SLEEP | ||
| 803 | void iwl_mvm_set_last_nonqos_seq(struct iwl_mvm *mvm, | ||
| 804 | struct ieee80211_vif *vif); | ||
| 805 | #else | ||
| 806 | static inline void | ||
| 807 | iwl_mvm_set_last_nonqos_seq(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | ||
| 808 | { | ||
| 809 | } | ||
| 810 | #endif | ||
| 748 | 811 | ||
| 749 | /* BT Coex */ | 812 | /* BT Coex */ |
| 750 | int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm); | 813 | int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm); |
| @@ -754,7 +817,20 @@ int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm, | |||
| 754 | struct iwl_device_cmd *cmd); | 817 | struct iwl_device_cmd *cmd); |
| 755 | void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 818 | void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
| 756 | enum ieee80211_rssi_event rssi_event); | 819 | enum ieee80211_rssi_event rssi_event); |
| 757 | void iwl_mvm_bt_coex_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif); | 820 | void iwl_mvm_bt_coex_vif_change(struct iwl_mvm *mvm); |
| 821 | u16 iwl_mvm_bt_coex_agg_time_limit(struct iwl_mvm *mvm, | ||
| 822 | struct ieee80211_sta *sta); | ||
| 823 | bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm, | ||
| 824 | struct ieee80211_sta *sta); | ||
| 825 | |||
| 826 | enum iwl_bt_kill_msk { | ||
| 827 | BT_KILL_MSK_DEFAULT, | ||
| 828 | BT_KILL_MSK_SCO_HID_A2DP, | ||
| 829 | BT_KILL_MSK_REDUCED_TXPOW, | ||
| 830 | BT_KILL_MSK_MAX, | ||
| 831 | }; | ||
| 832 | extern const u32 iwl_bt_ack_kill_msk[BT_KILL_MSK_MAX]; | ||
| 833 | extern const u32 iwl_bt_cts_kill_msk[BT_KILL_MSK_MAX]; | ||
| 758 | 834 | ||
| 759 | /* beacon filtering */ | 835 | /* beacon filtering */ |
| 760 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 836 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c index edb94ea31654..2beffd028b67 100644 --- a/drivers/net/wireless/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c | |||
| @@ -77,7 +77,7 @@ static const int nvm_to_read[] = { | |||
| 77 | 77 | ||
| 78 | /* Default NVM size to read */ | 78 | /* Default NVM size to read */ |
| 79 | #define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024) | 79 | #define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024) |
| 80 | #define IWL_MAX_NVM_SECTION_SIZE 6000 | 80 | #define IWL_MAX_NVM_SECTION_SIZE 7000 |
| 81 | 81 | ||
| 82 | #define NVM_WRITE_OPCODE 1 | 82 | #define NVM_WRITE_OPCODE 1 |
| 83 | #define NVM_READ_OPCODE 0 | 83 | #define NVM_READ_OPCODE 0 |
| @@ -259,6 +259,8 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm) | |||
| 259 | #define MAX_NVM_FILE_LEN 16384 | 259 | #define MAX_NVM_FILE_LEN 16384 |
| 260 | 260 | ||
| 261 | /* | 261 | /* |
| 262 | * Reads external NVM from a file into mvm->nvm_sections | ||
| 263 | * | ||
| 262 | * HOW TO CREATE THE NVM FILE FORMAT: | 264 | * HOW TO CREATE THE NVM FILE FORMAT: |
| 263 | * ------------------------------ | 265 | * ------------------------------ |
| 264 | * 1. create hex file, format: | 266 | * 1. create hex file, format: |
| @@ -277,20 +279,23 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm) | |||
| 277 | * | 279 | * |
| 278 | * 4. save as "iNVM_xxx.bin" under /lib/firmware | 280 | * 4. save as "iNVM_xxx.bin" under /lib/firmware |
| 279 | */ | 281 | */ |
| 280 | static int iwl_mvm_load_external_nvm(struct iwl_mvm *mvm) | 282 | static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm) |
| 281 | { | 283 | { |
| 282 | int ret, section_id, section_size; | 284 | int ret, section_size; |
| 285 | u16 section_id; | ||
| 283 | const struct firmware *fw_entry; | 286 | const struct firmware *fw_entry; |
| 284 | const struct { | 287 | const struct { |
| 285 | __le16 word1; | 288 | __le16 word1; |
| 286 | __le16 word2; | 289 | __le16 word2; |
| 287 | u8 data[]; | 290 | u8 data[]; |
| 288 | } *file_sec; | 291 | } *file_sec; |
| 289 | const u8 *eof; | 292 | const u8 *eof, *temp; |
| 290 | 293 | ||
| 291 | #define NVM_WORD1_LEN(x) (8 * (x & 0x03FF)) | 294 | #define NVM_WORD1_LEN(x) (8 * (x & 0x03FF)) |
| 292 | #define NVM_WORD2_ID(x) (x >> 12) | 295 | #define NVM_WORD2_ID(x) (x >> 12) |
| 293 | 296 | ||
| 297 | IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from external NVM\n"); | ||
| 298 | |||
| 294 | /* | 299 | /* |
| 295 | * Obtain NVM image via request_firmware. Since we already used | 300 | * Obtain NVM image via request_firmware. Since we already used |
| 296 | * request_firmware_nowait() for the firmware binary load and only | 301 | * request_firmware_nowait() for the firmware binary load and only |
| @@ -362,12 +367,18 @@ static int iwl_mvm_load_external_nvm(struct iwl_mvm *mvm) | |||
| 362 | break; | 367 | break; |
| 363 | } | 368 | } |
| 364 | 369 | ||
| 365 | ret = iwl_nvm_write_section(mvm, section_id, file_sec->data, | 370 | temp = kmemdup(file_sec->data, section_size, GFP_KERNEL); |
| 366 | section_size); | 371 | if (!temp) { |
| 367 | if (ret < 0) { | 372 | ret = -ENOMEM; |
| 368 | IWL_ERR(mvm, "iwl_mvm_send_cmd failed: %d\n", ret); | 373 | break; |
| 374 | } | ||
| 375 | if (WARN_ON(section_id >= NVM_NUM_OF_SECTIONS)) { | ||
| 376 | IWL_ERR(mvm, "Invalid NVM section ID\n"); | ||
| 377 | ret = -EINVAL; | ||
| 369 | break; | 378 | break; |
| 370 | } | 379 | } |
| 380 | mvm->nvm_sections[section_id].data = temp; | ||
| 381 | mvm->nvm_sections[section_id].length = section_size; | ||
| 371 | 382 | ||
| 372 | /* advance to the next section */ | 383 | /* advance to the next section */ |
| 373 | file_sec = (void *)(file_sec->data + section_size); | 384 | file_sec = (void *)(file_sec->data + section_size); |
| @@ -377,6 +388,28 @@ out: | |||
| 377 | return ret; | 388 | return ret; |
| 378 | } | 389 | } |
| 379 | 390 | ||
| 391 | /* Loads the NVM data stored in mvm->nvm_sections into the NIC */ | ||
| 392 | int iwl_mvm_load_nvm_to_nic(struct iwl_mvm *mvm) | ||
| 393 | { | ||
| 394 | int i, ret; | ||
| 395 | u16 section_id; | ||
| 396 | struct iwl_nvm_section *sections = mvm->nvm_sections; | ||
| 397 | |||
| 398 | IWL_DEBUG_EEPROM(mvm->trans->dev, "'Write to NVM\n"); | ||
| 399 | |||
| 400 | for (i = 0; i < ARRAY_SIZE(nvm_to_read); i++) { | ||
| 401 | section_id = nvm_to_read[i]; | ||
| 402 | ret = iwl_nvm_write_section(mvm, section_id, | ||
| 403 | sections[section_id].data, | ||
| 404 | sections[section_id].length); | ||
| 405 | if (ret < 0) { | ||
| 406 | IWL_ERR(mvm, "iwl_mvm_send_cmd failed: %d\n", ret); | ||
| 407 | break; | ||
| 408 | } | ||
| 409 | } | ||
| 410 | return ret; | ||
| 411 | } | ||
| 412 | |||
| 380 | int iwl_nvm_init(struct iwl_mvm *mvm) | 413 | int iwl_nvm_init(struct iwl_mvm *mvm) |
| 381 | { | 414 | { |
| 382 | int ret, i, section; | 415 | int ret, i, section; |
| @@ -385,36 +418,36 @@ int iwl_nvm_init(struct iwl_mvm *mvm) | |||
| 385 | /* load external NVM if configured */ | 418 | /* load external NVM if configured */ |
| 386 | if (iwlwifi_mod_params.nvm_file) { | 419 | if (iwlwifi_mod_params.nvm_file) { |
| 387 | /* move to External NVM flow */ | 420 | /* move to External NVM flow */ |
| 388 | ret = iwl_mvm_load_external_nvm(mvm); | 421 | ret = iwl_mvm_read_external_nvm(mvm); |
| 389 | if (ret) | 422 | if (ret) |
| 390 | return ret; | 423 | return ret; |
| 391 | } | 424 | } else { |
| 392 | 425 | /* Read From FW NVM */ | |
| 393 | /* Read From FW NVM */ | 426 | IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from NVM\n"); |
| 394 | IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from NVM\n"); | 427 | |
| 395 | 428 | /* TODO: find correct NVM max size for a section */ | |
| 396 | /* TODO: find correct NVM max size for a section */ | 429 | nvm_buffer = kmalloc(mvm->cfg->base_params->eeprom_size, |
| 397 | nvm_buffer = kmalloc(mvm->cfg->base_params->eeprom_size, | 430 | GFP_KERNEL); |
| 398 | GFP_KERNEL); | 431 | if (!nvm_buffer) |
| 399 | if (!nvm_buffer) | 432 | return -ENOMEM; |
| 400 | return -ENOMEM; | 433 | for (i = 0; i < ARRAY_SIZE(nvm_to_read); i++) { |
| 401 | for (i = 0; i < ARRAY_SIZE(nvm_to_read); i++) { | 434 | section = nvm_to_read[i]; |
| 402 | section = nvm_to_read[i]; | 435 | /* we override the constness for initial read */ |
| 403 | /* we override the constness for initial read */ | 436 | ret = iwl_nvm_read_section(mvm, section, nvm_buffer); |
| 404 | ret = iwl_nvm_read_section(mvm, section, nvm_buffer); | 437 | if (ret < 0) |
| 405 | if (ret < 0) | 438 | break; |
| 406 | break; | 439 | temp = kmemdup(nvm_buffer, ret, GFP_KERNEL); |
| 407 | temp = kmemdup(nvm_buffer, ret, GFP_KERNEL); | 440 | if (!temp) { |
| 408 | if (!temp) { | 441 | ret = -ENOMEM; |
| 409 | ret = -ENOMEM; | 442 | break; |
| 410 | break; | 443 | } |
| 444 | mvm->nvm_sections[section].data = temp; | ||
| 445 | mvm->nvm_sections[section].length = ret; | ||
| 411 | } | 446 | } |
| 412 | mvm->nvm_sections[section].data = temp; | 447 | kfree(nvm_buffer); |
| 413 | mvm->nvm_sections[section].length = ret; | 448 | if (ret < 0) |
| 449 | return ret; | ||
| 414 | } | 450 | } |
| 415 | kfree(nvm_buffer); | ||
| 416 | if (ret < 0) | ||
| 417 | return ret; | ||
| 418 | 451 | ||
| 419 | mvm->nvm_data = iwl_parse_nvm_sections(mvm); | 452 | mvm->nvm_data = iwl_parse_nvm_sections(mvm); |
| 420 | if (!mvm->nvm_data) | 453 | if (!mvm->nvm_data) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index 2fcc8ef88a68..59b7cb3c6134 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c | |||
| @@ -224,6 +224,10 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { | |||
| 224 | 224 | ||
| 225 | RX_HANDLER(SCAN_REQUEST_CMD, iwl_mvm_rx_scan_response, false), | 225 | RX_HANDLER(SCAN_REQUEST_CMD, iwl_mvm_rx_scan_response, false), |
| 226 | RX_HANDLER(SCAN_COMPLETE_NOTIFICATION, iwl_mvm_rx_scan_complete, false), | 226 | RX_HANDLER(SCAN_COMPLETE_NOTIFICATION, iwl_mvm_rx_scan_complete, false), |
| 227 | RX_HANDLER(SCAN_OFFLOAD_COMPLETE, | ||
| 228 | iwl_mvm_rx_scan_offload_complete_notif, false), | ||
| 229 | RX_HANDLER(MATCH_FOUND_NOTIFICATION, iwl_mvm_rx_sched_scan_results, | ||
| 230 | false), | ||
| 227 | 231 | ||
| 228 | RX_HANDLER(RADIO_VERSION_NOTIFICATION, iwl_mvm_rx_radio_ver, false), | 232 | RX_HANDLER(RADIO_VERSION_NOTIFICATION, iwl_mvm_rx_radio_ver, false), |
| 229 | RX_HANDLER(CARD_STATE_NOTIFICATION, iwl_mvm_rx_card_state_notif, false), | 233 | RX_HANDLER(CARD_STATE_NOTIFICATION, iwl_mvm_rx_card_state_notif, false), |
| @@ -249,6 +253,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = { | |||
| 249 | CMD(TIME_EVENT_NOTIFICATION), | 253 | CMD(TIME_EVENT_NOTIFICATION), |
| 250 | CMD(BINDING_CONTEXT_CMD), | 254 | CMD(BINDING_CONTEXT_CMD), |
| 251 | CMD(TIME_QUOTA_CMD), | 255 | CMD(TIME_QUOTA_CMD), |
| 256 | CMD(NON_QOS_TX_COUNTER_CMD), | ||
| 252 | CMD(RADIO_VERSION_NOTIFICATION), | 257 | CMD(RADIO_VERSION_NOTIFICATION), |
| 253 | CMD(SCAN_REQUEST_CMD), | 258 | CMD(SCAN_REQUEST_CMD), |
| 254 | CMD(SCAN_ABORT_CMD), | 259 | CMD(SCAN_ABORT_CMD), |
| @@ -260,10 +265,12 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = { | |||
| 260 | CMD(CALIB_RES_NOTIF_PHY_DB), | 265 | CMD(CALIB_RES_NOTIF_PHY_DB), |
| 261 | CMD(SET_CALIB_DEFAULT_CMD), | 266 | CMD(SET_CALIB_DEFAULT_CMD), |
| 262 | CMD(CALIBRATION_COMPLETE_NOTIFICATION), | 267 | CMD(CALIBRATION_COMPLETE_NOTIFICATION), |
| 268 | CMD(ADD_STA_KEY), | ||
| 263 | CMD(ADD_STA), | 269 | CMD(ADD_STA), |
| 264 | CMD(REMOVE_STA), | 270 | CMD(REMOVE_STA), |
| 265 | CMD(LQ_CMD), | 271 | CMD(LQ_CMD), |
| 266 | CMD(SCAN_OFFLOAD_CONFIG_CMD), | 272 | CMD(SCAN_OFFLOAD_CONFIG_CMD), |
| 273 | CMD(MATCH_FOUND_NOTIFICATION), | ||
| 267 | CMD(SCAN_OFFLOAD_REQUEST_CMD), | 274 | CMD(SCAN_OFFLOAD_REQUEST_CMD), |
| 268 | CMD(SCAN_OFFLOAD_ABORT_CMD), | 275 | CMD(SCAN_OFFLOAD_ABORT_CMD), |
| 269 | CMD(SCAN_OFFLOAD_COMPLETE), | 276 | CMD(SCAN_OFFLOAD_COMPLETE), |
| @@ -303,6 +310,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = { | |||
| 303 | CMD(REPLY_BEACON_FILTERING_CMD), | 310 | CMD(REPLY_BEACON_FILTERING_CMD), |
| 304 | CMD(REPLY_THERMAL_MNG_BACKOFF), | 311 | CMD(REPLY_THERMAL_MNG_BACKOFF), |
| 305 | CMD(MAC_PM_POWER_TABLE), | 312 | CMD(MAC_PM_POWER_TABLE), |
| 313 | CMD(BT_COEX_CI), | ||
| 306 | }; | 314 | }; |
| 307 | #undef CMD | 315 | #undef CMD |
| 308 | 316 | ||
| @@ -344,6 +352,14 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
| 344 | 352 | ||
| 345 | mvm->restart_fw = iwlwifi_mod_params.restart_fw ? -1 : 0; | 353 | mvm->restart_fw = iwlwifi_mod_params.restart_fw ? -1 : 0; |
| 346 | 354 | ||
| 355 | mvm->aux_queue = 15; | ||
| 356 | mvm->first_agg_queue = 16; | ||
| 357 | mvm->last_agg_queue = mvm->cfg->base_params->num_of_queues - 1; | ||
| 358 | if (mvm->cfg->base_params->num_of_queues == 16) { | ||
| 359 | mvm->aux_queue = 11; | ||
| 360 | mvm->first_agg_queue = 12; | ||
| 361 | } | ||
| 362 | |||
| 347 | mutex_init(&mvm->mutex); | 363 | mutex_init(&mvm->mutex); |
| 348 | spin_lock_init(&mvm->async_handlers_lock); | 364 | spin_lock_init(&mvm->async_handlers_lock); |
| 349 | INIT_LIST_HEAD(&mvm->time_event_list); | 365 | INIT_LIST_HEAD(&mvm->time_event_list); |
| @@ -401,24 +417,32 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
| 401 | IWL_INFO(mvm, "Detected %s, REV=0x%X\n", | 417 | IWL_INFO(mvm, "Detected %s, REV=0x%X\n", |
| 402 | mvm->cfg->name, mvm->trans->hw_rev); | 418 | mvm->cfg->name, mvm->trans->hw_rev); |
| 403 | 419 | ||
| 404 | err = iwl_trans_start_hw(mvm->trans); | ||
| 405 | if (err) | ||
| 406 | goto out_free; | ||
| 407 | |||
| 408 | iwl_mvm_tt_initialize(mvm); | 420 | iwl_mvm_tt_initialize(mvm); |
| 409 | 421 | ||
| 410 | mutex_lock(&mvm->mutex); | 422 | /* |
| 411 | err = iwl_run_init_mvm_ucode(mvm, true); | 423 | * If the NVM exists in an external file, |
| 412 | mutex_unlock(&mvm->mutex); | 424 | * there is no need to unnecessarily power up the NIC at driver load |
| 413 | /* returns 0 if successful, 1 if success but in rfkill */ | 425 | */ |
| 414 | if (err < 0 && !iwlmvm_mod_params.init_dbg) { | 426 | if (iwlwifi_mod_params.nvm_file) { |
| 415 | IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", err); | 427 | iwl_nvm_init(mvm); |
| 416 | goto out_free; | 428 | } else { |
| 417 | } | 429 | err = iwl_trans_start_hw(mvm->trans); |
| 430 | if (err) | ||
| 431 | goto out_free; | ||
| 432 | |||
| 433 | mutex_lock(&mvm->mutex); | ||
| 434 | err = iwl_run_init_mvm_ucode(mvm, true); | ||
| 435 | mutex_unlock(&mvm->mutex); | ||
| 436 | /* returns 0 if successful, 1 if success but in rfkill */ | ||
| 437 | if (err < 0 && !iwlmvm_mod_params.init_dbg) { | ||
| 438 | IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", err); | ||
| 439 | goto out_free; | ||
| 440 | } | ||
| 418 | 441 | ||
| 419 | /* Stop the hw after the ALIVE and NVM has been read */ | 442 | /* Stop the hw after the ALIVE and NVM has been read */ |
| 420 | if (!iwlmvm_mod_params.init_dbg) | 443 | if (!iwlmvm_mod_params.init_dbg) |
| 421 | iwl_trans_stop_hw(mvm->trans, false); | 444 | iwl_trans_stop_hw(mvm->trans, false); |
| 445 | } | ||
| 422 | 446 | ||
| 423 | scan_size = sizeof(struct iwl_scan_cmd) + | 447 | scan_size = sizeof(struct iwl_scan_cmd) + |
| 424 | mvm->fw->ucode_capa.max_probe_length + | 448 | mvm->fw->ucode_capa.max_probe_length + |
| @@ -449,7 +473,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
| 449 | out_free: | 473 | out_free: |
| 450 | iwl_phy_db_free(mvm->phy_db); | 474 | iwl_phy_db_free(mvm->phy_db); |
| 451 | kfree(mvm->scan_cmd); | 475 | kfree(mvm->scan_cmd); |
| 452 | iwl_trans_stop_hw(trans, true); | 476 | if (!iwlwifi_mod_params.nvm_file) |
| 477 | iwl_trans_stop_hw(trans, true); | ||
| 453 | ieee80211_free_hw(mvm->hw); | 478 | ieee80211_free_hw(mvm->hw); |
| 454 | return NULL; | 479 | return NULL; |
| 455 | } | 480 | } |
| @@ -715,6 +740,9 @@ static void iwl_mvm_nic_restart(struct iwl_mvm *mvm) | |||
| 715 | case IWL_MVM_SCAN_OS: | 740 | case IWL_MVM_SCAN_OS: |
| 716 | ieee80211_scan_completed(mvm->hw, true); | 741 | ieee80211_scan_completed(mvm->hw, true); |
| 717 | break; | 742 | break; |
| 743 | case IWL_MVM_SCAN_SCHED: | ||
| 744 | ieee80211_sched_scan_stopped(mvm->hw); | ||
| 745 | break; | ||
| 718 | } | 746 | } |
| 719 | 747 | ||
| 720 | if (mvm->restart_fw > 0) | 748 | if (mvm->restart_fw > 0) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c index d58e393324ef..550824aa84ea 100644 --- a/drivers/net/wireless/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/iwlwifi/mvm/power.c | |||
| @@ -300,11 +300,6 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, | |||
| 300 | } | 300 | } |
| 301 | 301 | ||
| 302 | if (cmd->flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK)) { | 302 | if (cmd->flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK)) { |
| 303 | cmd->rx_data_timeout_uapsd = | ||
| 304 | cpu_to_le32(IWL_MVM_UAPSD_RX_DATA_TIMEOUT); | ||
| 305 | cmd->tx_data_timeout_uapsd = | ||
| 306 | cpu_to_le32(IWL_MVM_UAPSD_TX_DATA_TIMEOUT); | ||
| 307 | |||
| 308 | if (cmd->uapsd_ac_flags == (BIT(IEEE80211_AC_VO) | | 303 | if (cmd->uapsd_ac_flags == (BIT(IEEE80211_AC_VO) | |
| 309 | BIT(IEEE80211_AC_VI) | | 304 | BIT(IEEE80211_AC_VI) | |
| 310 | BIT(IEEE80211_AC_BE) | | 305 | BIT(IEEE80211_AC_BE) | |
| @@ -319,10 +314,31 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, | |||
| 319 | } | 314 | } |
| 320 | 315 | ||
| 321 | cmd->uapsd_max_sp = IWL_UAPSD_MAX_SP; | 316 | cmd->uapsd_max_sp = IWL_UAPSD_MAX_SP; |
| 322 | cmd->heavy_tx_thld_packets = | 317 | |
| 323 | IWL_MVM_PS_HEAVY_TX_THLD_PACKETS; | 318 | if (mvm->cur_ucode == IWL_UCODE_WOWLAN || cmd->flags & |
| 324 | cmd->heavy_rx_thld_packets = | 319 | cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) { |
| 325 | IWL_MVM_PS_HEAVY_RX_THLD_PACKETS; | 320 | cmd->rx_data_timeout_uapsd = |
| 321 | cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT); | ||
| 322 | cmd->tx_data_timeout_uapsd = | ||
| 323 | cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT); | ||
| 324 | } else { | ||
| 325 | cmd->rx_data_timeout_uapsd = | ||
| 326 | cpu_to_le32(IWL_MVM_UAPSD_RX_DATA_TIMEOUT); | ||
| 327 | cmd->tx_data_timeout_uapsd = | ||
| 328 | cpu_to_le32(IWL_MVM_UAPSD_TX_DATA_TIMEOUT); | ||
| 329 | } | ||
| 330 | |||
| 331 | if (cmd->flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) { | ||
| 332 | cmd->heavy_tx_thld_packets = | ||
| 333 | IWL_MVM_PS_SNOOZE_HEAVY_TX_THLD_PACKETS; | ||
| 334 | cmd->heavy_rx_thld_packets = | ||
| 335 | IWL_MVM_PS_SNOOZE_HEAVY_RX_THLD_PACKETS; | ||
| 336 | } else { | ||
| 337 | cmd->heavy_tx_thld_packets = | ||
| 338 | IWL_MVM_PS_HEAVY_TX_THLD_PACKETS; | ||
| 339 | cmd->heavy_rx_thld_packets = | ||
| 340 | IWL_MVM_PS_HEAVY_RX_THLD_PACKETS; | ||
| 341 | } | ||
| 326 | cmd->heavy_tx_thld_percentage = | 342 | cmd->heavy_tx_thld_percentage = |
| 327 | IWL_MVM_PS_HEAVY_TX_THLD_PERCENT; | 343 | IWL_MVM_PS_HEAVY_TX_THLD_PERCENT; |
| 328 | cmd->heavy_rx_thld_percentage = | 344 | cmd->heavy_rx_thld_percentage = |
| @@ -430,6 +446,32 @@ static int iwl_mvm_power_mac_disable(struct iwl_mvm *mvm, | |||
| 430 | sizeof(cmd), &cmd); | 446 | sizeof(cmd), &cmd); |
| 431 | } | 447 | } |
| 432 | 448 | ||
| 449 | static int iwl_mvm_power_update_device(struct iwl_mvm *mvm) | ||
| 450 | { | ||
| 451 | struct iwl_device_power_cmd cmd = { | ||
| 452 | .flags = cpu_to_le16(DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK), | ||
| 453 | }; | ||
| 454 | |||
| 455 | if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD)) | ||
| 456 | return 0; | ||
| 457 | |||
| 458 | if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM) | ||
| 459 | cmd.flags |= cpu_to_le16(DEVICE_POWER_FLAGS_CAM_MSK); | ||
| 460 | |||
| 461 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
| 462 | if ((mvm->cur_ucode == IWL_UCODE_WOWLAN) ? mvm->disable_power_off_d3 : | ||
| 463 | mvm->disable_power_off) | ||
| 464 | cmd.flags &= | ||
| 465 | cpu_to_le16(~DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK); | ||
| 466 | #endif | ||
| 467 | IWL_DEBUG_POWER(mvm, | ||
| 468 | "Sending device power command with flags = 0x%X\n", | ||
| 469 | cmd.flags); | ||
| 470 | |||
| 471 | return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_SYNC, sizeof(cmd), | ||
| 472 | &cmd); | ||
| 473 | } | ||
| 474 | |||
| 433 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 475 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
| 434 | static int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm, | 476 | static int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm, |
| 435 | struct ieee80211_vif *vif, char *buf, | 477 | struct ieee80211_vif *vif, char *buf, |
| @@ -440,10 +482,11 @@ static int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm, | |||
| 440 | 482 | ||
| 441 | iwl_mvm_power_build_cmd(mvm, vif, &cmd); | 483 | iwl_mvm_power_build_cmd(mvm, vif, &cmd); |
| 442 | 484 | ||
| 443 | pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off = %d\n", | 485 | if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD)) |
| 444 | (cmd.flags & | 486 | pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off = %d\n", |
| 445 | cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK)) ? | 487 | (cmd.flags & |
| 446 | 0 : 1); | 488 | cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK)) ? |
| 489 | 0 : 1); | ||
| 447 | pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n", | 490 | pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n", |
| 448 | iwlmvm_mod_params.power_scheme); | 491 | iwlmvm_mod_params.power_scheme); |
| 449 | pos += scnprintf(buf+pos, bufsz-pos, "flags = 0x%x\n", | 492 | pos += scnprintf(buf+pos, bufsz-pos, "flags = 0x%x\n", |
| @@ -609,6 +652,7 @@ int iwl_mvm_update_beacon_filter(struct iwl_mvm *mvm, | |||
| 609 | 652 | ||
| 610 | const struct iwl_mvm_power_ops pm_mac_ops = { | 653 | const struct iwl_mvm_power_ops pm_mac_ops = { |
| 611 | .power_update_mode = iwl_mvm_power_mac_update_mode, | 654 | .power_update_mode = iwl_mvm_power_mac_update_mode, |
| 655 | .power_update_device_mode = iwl_mvm_power_update_device, | ||
| 612 | .power_disable = iwl_mvm_power_mac_disable, | 656 | .power_disable = iwl_mvm_power_mac_disable, |
| 613 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 657 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
| 614 | .power_dbgfs_read = iwl_mvm_power_mac_dbgfs_read, | 658 | .power_dbgfs_read = iwl_mvm_power_mac_dbgfs_read, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/quota.c b/drivers/net/wireless/iwlwifi/mvm/quota.c index 5c6ae16ec52b..17e2bc827f9a 100644 --- a/drivers/net/wireless/iwlwifi/mvm/quota.c +++ b/drivers/net/wireless/iwlwifi/mvm/quota.c | |||
| @@ -110,7 +110,8 @@ static void iwl_mvm_quota_iterator(void *_data, u8 *mac, | |||
| 110 | data->n_interfaces[id]++; | 110 | data->n_interfaces[id]++; |
| 111 | break; | 111 | break; |
| 112 | case NL80211_IFTYPE_AP: | 112 | case NL80211_IFTYPE_AP: |
| 113 | if (mvmvif->ap_active) | 113 | case NL80211_IFTYPE_ADHOC: |
| 114 | if (mvmvif->ap_ibss_active) | ||
| 114 | data->n_interfaces[id]++; | 115 | data->n_interfaces[id]++; |
| 115 | break; | 116 | break; |
| 116 | case NL80211_IFTYPE_MONITOR: | 117 | case NL80211_IFTYPE_MONITOR: |
| @@ -119,16 +120,45 @@ static void iwl_mvm_quota_iterator(void *_data, u8 *mac, | |||
| 119 | break; | 120 | break; |
| 120 | case NL80211_IFTYPE_P2P_DEVICE: | 121 | case NL80211_IFTYPE_P2P_DEVICE: |
| 121 | break; | 122 | break; |
| 122 | case NL80211_IFTYPE_ADHOC: | ||
| 123 | if (vif->bss_conf.ibss_joined) | ||
| 124 | data->n_interfaces[id]++; | ||
| 125 | break; | ||
| 126 | default: | 123 | default: |
| 127 | WARN_ON_ONCE(1); | 124 | WARN_ON_ONCE(1); |
| 128 | break; | 125 | break; |
| 129 | } | 126 | } |
| 130 | } | 127 | } |
| 131 | 128 | ||
| 129 | static void iwl_mvm_adjust_quota_for_noa(struct iwl_mvm *mvm, | ||
| 130 | struct iwl_time_quota_cmd *cmd) | ||
| 131 | { | ||
| 132 | #ifdef CONFIG_NL80211_TESTMODE | ||
| 133 | struct iwl_mvm_vif *mvmvif; | ||
| 134 | int i, phy_id = -1, beacon_int = 0; | ||
| 135 | |||
| 136 | if (!mvm->noa_duration || !mvm->noa_vif) | ||
| 137 | return; | ||
| 138 | |||
| 139 | mvmvif = iwl_mvm_vif_from_mac80211(mvm->noa_vif); | ||
| 140 | if (!mvmvif->ap_ibss_active) | ||
| 141 | return; | ||
| 142 | |||
| 143 | phy_id = mvmvif->phy_ctxt->id; | ||
| 144 | beacon_int = mvm->noa_vif->bss_conf.beacon_int; | ||
| 145 | |||
| 146 | for (i = 0; i < MAX_BINDINGS; i++) { | ||
| 147 | u32 id_n_c = le32_to_cpu(cmd->quotas[i].id_and_color); | ||
| 148 | u32 id = (id_n_c & FW_CTXT_ID_MSK) >> FW_CTXT_ID_POS; | ||
| 149 | u32 quota = le32_to_cpu(cmd->quotas[i].quota); | ||
| 150 | |||
| 151 | if (id != phy_id) | ||
| 152 | continue; | ||
| 153 | |||
| 154 | quota *= (beacon_int - mvm->noa_duration); | ||
| 155 | quota /= beacon_int; | ||
| 156 | |||
| 157 | cmd->quotas[i].quota = cpu_to_le32(quota); | ||
| 158 | } | ||
| 159 | #endif | ||
| 160 | } | ||
| 161 | |||
| 132 | int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif) | 162 | int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif) |
| 133 | { | 163 | { |
| 134 | struct iwl_time_quota_cmd cmd = {}; | 164 | struct iwl_time_quota_cmd cmd = {}; |
| @@ -196,6 +226,8 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif) | |||
| 196 | /* Give the remainder of the session to the first binding */ | 226 | /* Give the remainder of the session to the first binding */ |
| 197 | le32_add_cpu(&cmd.quotas[0].quota, quota_rem); | 227 | le32_add_cpu(&cmd.quotas[0].quota, quota_rem); |
| 198 | 228 | ||
| 229 | iwl_mvm_adjust_quota_for_noa(mvm, &cmd); | ||
| 230 | |||
| 199 | ret = iwl_mvm_send_cmd_pdu(mvm, TIME_QUOTA_CMD, CMD_SYNC, | 231 | ret = iwl_mvm_send_cmd_pdu(mvm, TIME_QUOTA_CMD, CMD_SYNC, |
| 200 | sizeof(cmd), &cmd); | 232 | sizeof(cmd), &cmd); |
| 201 | if (ret) | 233 | if (ret) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 4ffaa3fa153f..a0b4cc8d9c3b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c | |||
| @@ -82,13 +82,24 @@ static const u8 ant_toggle_lookup[] = { | |||
| 82 | [ANT_ABC] = ANT_ABC, | 82 | [ANT_ABC] = ANT_ABC, |
| 83 | }; | 83 | }; |
| 84 | 84 | ||
| 85 | #define IWL_DECLARE_RATE_INFO(r, s, rp, rn) \ | 85 | #define IWL_DECLARE_RATE_INFO(r, s, rp, rn) \ |
| 86 | [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \ | 86 | [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \ |
| 87 | IWL_RATE_SISO_##s##M_PLCP, \ | 87 | IWL_RATE_HT_SISO_MCS_##s##_PLCP, \ |
| 88 | IWL_RATE_MIMO2_##s##M_PLCP,\ | 88 | IWL_RATE_HT_MIMO2_MCS_##s##_PLCP, \ |
| 89 | IWL_RATE_##rp##M_INDEX, \ | 89 | IWL_RATE_VHT_SISO_MCS_##s##_PLCP, \ |
| 90 | IWL_RATE_VHT_MIMO2_MCS_##s##_PLCP,\ | ||
| 91 | IWL_RATE_##rp##M_INDEX, \ | ||
| 90 | IWL_RATE_##rn##M_INDEX } | 92 | IWL_RATE_##rn##M_INDEX } |
| 91 | 93 | ||
| 94 | #define IWL_DECLARE_MCS_RATE(s) \ | ||
| 95 | [IWL_RATE_MCS_##s##_INDEX] = { IWL_RATE_INVM_PLCP, \ | ||
| 96 | IWL_RATE_HT_SISO_MCS_##s##_PLCP, \ | ||
| 97 | IWL_RATE_HT_MIMO2_MCS_##s##_PLCP, \ | ||
| 98 | IWL_RATE_VHT_SISO_MCS_##s##_PLCP, \ | ||
| 99 | IWL_RATE_VHT_MIMO2_MCS_##s##_PLCP, \ | ||
| 100 | IWL_RATE_INVM_INDEX, \ | ||
| 101 | IWL_RATE_INVM_INDEX } | ||
| 102 | |||
| 92 | /* | 103 | /* |
| 93 | * Parameter order: | 104 | * Parameter order: |
| 94 | * rate, ht rate, prev rate, next rate | 105 | * rate, ht rate, prev rate, next rate |
| @@ -102,16 +113,17 @@ static const struct iwl_rs_rate_info iwl_rates[IWL_RATE_COUNT] = { | |||
| 102 | IWL_DECLARE_RATE_INFO(2, INV, 1, 5), /* 2mbps */ | 113 | IWL_DECLARE_RATE_INFO(2, INV, 1, 5), /* 2mbps */ |
| 103 | IWL_DECLARE_RATE_INFO(5, INV, 2, 11), /*5.5mbps */ | 114 | IWL_DECLARE_RATE_INFO(5, INV, 2, 11), /*5.5mbps */ |
| 104 | IWL_DECLARE_RATE_INFO(11, INV, 9, 12), /* 11mbps */ | 115 | IWL_DECLARE_RATE_INFO(11, INV, 9, 12), /* 11mbps */ |
| 105 | IWL_DECLARE_RATE_INFO(6, 6, 5, 11), /* 6mbps */ | 116 | IWL_DECLARE_RATE_INFO(6, 0, 5, 11), /* 6mbps ; MCS 0 */ |
| 106 | IWL_DECLARE_RATE_INFO(9, 6, 6, 11), /* 9mbps */ | 117 | IWL_DECLARE_RATE_INFO(9, INV, 6, 11), /* 9mbps */ |
| 107 | IWL_DECLARE_RATE_INFO(12, 12, 11, 18), /* 12mbps */ | 118 | IWL_DECLARE_RATE_INFO(12, 1, 11, 18), /* 12mbps ; MCS 1 */ |
| 108 | IWL_DECLARE_RATE_INFO(18, 18, 12, 24), /* 18mbps */ | 119 | IWL_DECLARE_RATE_INFO(18, 2, 12, 24), /* 18mbps ; MCS 2 */ |
| 109 | IWL_DECLARE_RATE_INFO(24, 24, 18, 36), /* 24mbps */ | 120 | IWL_DECLARE_RATE_INFO(24, 3, 18, 36), /* 24mbps ; MCS 3 */ |
| 110 | IWL_DECLARE_RATE_INFO(36, 36, 24, 48), /* 36mbps */ | 121 | IWL_DECLARE_RATE_INFO(36, 4, 24, 48), /* 36mbps ; MCS 4 */ |
| 111 | IWL_DECLARE_RATE_INFO(48, 48, 36, 54), /* 48mbps */ | 122 | IWL_DECLARE_RATE_INFO(48, 5, 36, 54), /* 48mbps ; MCS 5 */ |
| 112 | IWL_DECLARE_RATE_INFO(54, 54, 48, INV), /* 54mbps */ | 123 | IWL_DECLARE_RATE_INFO(54, 6, 48, INV), /* 54mbps ; MCS 6 */ |
| 113 | IWL_DECLARE_RATE_INFO(60, 60, 48, INV), /* 60mbps */ | 124 | IWL_DECLARE_MCS_RATE(7), /* MCS 7 */ |
| 114 | /* FIXME:RS: ^^ should be INV (legacy) */ | 125 | IWL_DECLARE_MCS_RATE(8), /* MCS 8 */ |
| 126 | IWL_DECLARE_MCS_RATE(9), /* MCS 9 */ | ||
| 115 | }; | 127 | }; |
| 116 | 128 | ||
| 117 | static inline u8 rs_extract_rate(u32 rate_n_flags) | 129 | static inline u8 rs_extract_rate(u32 rate_n_flags) |
| @@ -124,26 +136,30 @@ static int iwl_hwrate_to_plcp_idx(u32 rate_n_flags) | |||
| 124 | { | 136 | { |
| 125 | int idx = 0; | 137 | int idx = 0; |
| 126 | 138 | ||
| 127 | /* HT rate format */ | ||
| 128 | if (rate_n_flags & RATE_MCS_HT_MSK) { | 139 | if (rate_n_flags & RATE_MCS_HT_MSK) { |
| 129 | idx = rs_extract_rate(rate_n_flags); | 140 | idx = rate_n_flags & RATE_HT_MCS_RATE_CODE_MSK; |
| 130 | 141 | idx += IWL_RATE_MCS_0_INDEX; | |
| 131 | WARN_ON_ONCE(idx >= IWL_RATE_MIMO3_6M_PLCP); | ||
| 132 | if (idx >= IWL_RATE_MIMO2_6M_PLCP) | ||
| 133 | idx = idx - IWL_RATE_MIMO2_6M_PLCP; | ||
| 134 | 142 | ||
| 135 | idx += IWL_FIRST_OFDM_RATE; | 143 | /* skip 9M not supported in HT*/ |
| 136 | /* skip 9M not supported in ht*/ | ||
| 137 | if (idx >= IWL_RATE_9M_INDEX) | 144 | if (idx >= IWL_RATE_9M_INDEX) |
| 138 | idx += 1; | 145 | idx += 1; |
| 139 | if ((idx >= IWL_FIRST_OFDM_RATE) && (idx <= IWL_LAST_OFDM_RATE)) | 146 | if ((idx >= IWL_FIRST_HT_RATE) && (idx <= IWL_LAST_HT_RATE)) |
| 140 | return idx; | 147 | return idx; |
| 148 | } else if (rate_n_flags & RATE_MCS_VHT_MSK) { | ||
| 149 | idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK; | ||
| 150 | idx += IWL_RATE_MCS_0_INDEX; | ||
| 141 | 151 | ||
| 142 | /* legacy rate format, search for match in table */ | 152 | /* skip 9M not supported in VHT*/ |
| 153 | if (idx >= IWL_RATE_9M_INDEX) | ||
| 154 | idx++; | ||
| 155 | if ((idx >= IWL_FIRST_VHT_RATE) && (idx <= IWL_LAST_VHT_RATE)) | ||
| 156 | return idx; | ||
| 143 | } else { | 157 | } else { |
| 158 | /* legacy rate format, search for match in table */ | ||
| 159 | |||
| 160 | u8 legacy_rate = rs_extract_rate(rate_n_flags); | ||
| 144 | for (idx = 0; idx < ARRAY_SIZE(iwl_rates); idx++) | 161 | for (idx = 0; idx < ARRAY_SIZE(iwl_rates); idx++) |
| 145 | if (iwl_rates[idx].plcp == | 162 | if (iwl_rates[idx].plcp == legacy_rate) |
| 146 | rs_extract_rate(rate_n_flags)) | ||
| 147 | return idx; | 163 | return idx; |
| 148 | } | 164 | } |
| 149 | 165 | ||
| @@ -155,6 +171,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, | |||
| 155 | struct ieee80211_sta *sta, | 171 | struct ieee80211_sta *sta, |
| 156 | struct iwl_lq_sta *lq_sta); | 172 | struct iwl_lq_sta *lq_sta); |
| 157 | static void rs_fill_link_cmd(struct iwl_mvm *mvm, | 173 | static void rs_fill_link_cmd(struct iwl_mvm *mvm, |
| 174 | struct ieee80211_sta *sta, | ||
| 158 | struct iwl_lq_sta *lq_sta, u32 rate_n_flags); | 175 | struct iwl_lq_sta *lq_sta, u32 rate_n_flags); |
| 159 | static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search); | 176 | static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search); |
| 160 | 177 | ||
| @@ -180,35 +197,52 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, | |||
| 180 | */ | 197 | */ |
| 181 | 198 | ||
| 182 | static s32 expected_tpt_legacy[IWL_RATE_COUNT] = { | 199 | static s32 expected_tpt_legacy[IWL_RATE_COUNT] = { |
| 183 | 7, 13, 35, 58, 40, 57, 72, 98, 121, 154, 177, 186, 0 | 200 | 7, 13, 35, 58, 40, 57, 72, 98, 121, 154, 177, 186, 0, 0, 0 |
| 184 | }; | 201 | }; |
| 185 | 202 | ||
| 186 | static s32 expected_tpt_siso20MHz[4][IWL_RATE_COUNT] = { | 203 | /* Expected TpT tables. 4 indexes: |
| 187 | {0, 0, 0, 0, 42, 0, 76, 102, 124, 159, 183, 193, 202}, /* Norm */ | 204 | * 0 - NGI, 1 - SGI, 2 - AGG+NGI, 3 - AGG+SGI |
| 188 | {0, 0, 0, 0, 46, 0, 82, 110, 132, 168, 192, 202, 210}, /* SGI */ | 205 | */ |
| 189 | {0, 0, 0, 0, 47, 0, 91, 133, 171, 242, 305, 334, 362}, /* AGG */ | 206 | static s32 expected_tpt_siso_20MHz[4][IWL_RATE_COUNT] = { |
| 190 | {0, 0, 0, 0, 52, 0, 101, 145, 187, 264, 330, 361, 390}, /* AGG+SGI */ | 207 | {0, 0, 0, 0, 42, 0, 76, 102, 124, 159, 183, 193, 202, 216, 0}, |
| 208 | {0, 0, 0, 0, 46, 0, 82, 110, 132, 168, 192, 202, 210, 225, 0}, | ||
| 209 | {0, 0, 0, 0, 49, 0, 97, 145, 192, 285, 375, 420, 464, 551, 0}, | ||
| 210 | {0, 0, 0, 0, 54, 0, 108, 160, 213, 315, 415, 465, 513, 608, 0}, | ||
| 191 | }; | 211 | }; |
| 192 | 212 | ||
| 193 | static s32 expected_tpt_siso40MHz[4][IWL_RATE_COUNT] = { | 213 | static s32 expected_tpt_siso_40MHz[4][IWL_RATE_COUNT] = { |
| 194 | {0, 0, 0, 0, 77, 0, 127, 160, 184, 220, 242, 250, 257}, /* Norm */ | 214 | {0, 0, 0, 0, 77, 0, 127, 160, 184, 220, 242, 250, 257, 269, 275}, |
| 195 | {0, 0, 0, 0, 83, 0, 135, 169, 193, 229, 250, 257, 264}, /* SGI */ | 215 | {0, 0, 0, 0, 83, 0, 135, 169, 193, 229, 250, 257, 264, 275, 280}, |
| 196 | {0, 0, 0, 0, 94, 0, 177, 249, 313, 423, 512, 550, 586}, /* AGG */ | 216 | {0, 0, 0, 0, 101, 0, 199, 295, 389, 570, 744, 828, 911, 1070, 1173}, |
| 197 | {0, 0, 0, 0, 104, 0, 193, 270, 338, 454, 545, 584, 620}, /* AGG+SGI */ | 217 | {0, 0, 0, 0, 112, 0, 220, 326, 429, 629, 819, 912, 1000, 1173, 1284}, |
| 218 | }; | ||
| 219 | |||
| 220 | static s32 expected_tpt_siso_80MHz[4][IWL_RATE_COUNT] = { | ||
| 221 | {0, 0, 0, 0, 130, 0, 191, 223, 244, 273, 288, 294, 298, 305, 308}, | ||
| 222 | {0, 0, 0, 0, 138, 0, 200, 231, 251, 279, 293, 298, 302, 308, 312}, | ||
| 223 | {0, 0, 0, 0, 217, 0, 429, 634, 834, 1220, 1585, 1760, 1931, 2258, 2466}, | ||
| 224 | {0, 0, 0, 0, 241, 0, 475, 701, 921, 1343, 1741, 1931, 2117, 2468, 2691}, | ||
| 198 | }; | 225 | }; |
| 199 | 226 | ||
| 200 | static s32 expected_tpt_mimo2_20MHz[4][IWL_RATE_COUNT] = { | 227 | static s32 expected_tpt_mimo2_20MHz[4][IWL_RATE_COUNT] = { |
| 201 | {0, 0, 0, 0, 74, 0, 123, 155, 179, 214, 236, 244, 251}, /* Norm */ | 228 | {0, 0, 0, 0, 74, 0, 123, 155, 179, 213, 235, 243, 250, 261, 0}, |
| 202 | {0, 0, 0, 0, 81, 0, 131, 164, 188, 223, 243, 251, 257}, /* SGI */ | 229 | {0, 0, 0, 0, 81, 0, 131, 164, 187, 221, 242, 250, 256, 267, 0}, |
| 203 | {0, 0, 0, 0, 89, 0, 167, 235, 296, 402, 488, 526, 560}, /* AGG */ | 230 | {0, 0, 0, 0, 98, 0, 193, 286, 375, 550, 718, 799, 878, 1032, 0}, |
| 204 | {0, 0, 0, 0, 97, 0, 182, 255, 320, 431, 520, 558, 593}, /* AGG+SGI*/ | 231 | {0, 0, 0, 0, 109, 0, 214, 316, 414, 607, 790, 879, 965, 1132, 0}, |
| 205 | }; | 232 | }; |
| 206 | 233 | ||
| 207 | static s32 expected_tpt_mimo2_40MHz[4][IWL_RATE_COUNT] = { | 234 | static s32 expected_tpt_mimo2_40MHz[4][IWL_RATE_COUNT] = { |
| 208 | {0, 0, 0, 0, 123, 0, 182, 214, 235, 264, 279, 285, 289}, /* Norm */ | 235 | {0, 0, 0, 0, 123, 0, 182, 214, 235, 264, 279, 285, 289, 296, 300}, |
| 209 | {0, 0, 0, 0, 131, 0, 191, 222, 242, 270, 284, 289, 293}, /* SGI */ | 236 | {0, 0, 0, 0, 131, 0, 191, 222, 242, 270, 284, 289, 293, 300, 303}, |
| 210 | {0, 0, 0, 0, 171, 0, 305, 410, 496, 634, 731, 771, 805}, /* AGG */ | 237 | {0, 0, 0, 0, 200, 0, 390, 571, 741, 1067, 1365, 1505, 1640, 1894, 2053}, |
| 211 | {0, 0, 0, 0, 186, 0, 329, 439, 527, 667, 764, 803, 838}, /* AGG+SGI */ | 238 | {0, 0, 0, 0, 221, 0, 430, 630, 816, 1169, 1490, 1641, 1784, 2053, 2221}, |
| 239 | }; | ||
| 240 | |||
| 241 | static s32 expected_tpt_mimo2_80MHz[4][IWL_RATE_COUNT] = { | ||
| 242 | {0, 0, 0, 0, 182, 0, 240, 264, 278, 299, 308, 311, 313, 317, 319}, | ||
| 243 | {0, 0, 0, 0, 190, 0, 247, 269, 282, 302, 310, 313, 315, 319, 320}, | ||
| 244 | {0, 0, 0, 0, 428, 0, 833, 1215, 1577, 2254, 2863, 3147, 3418, 3913, 4219}, | ||
| 245 | {0, 0, 0, 0, 474, 0, 920, 1338, 1732, 2464, 3116, 3418, 3705, 4225, 4545}, | ||
| 212 | }; | 246 | }; |
| 213 | 247 | ||
| 214 | /* mbps, mcs */ | 248 | /* mbps, mcs */ |
| @@ -263,7 +297,7 @@ static void rs_program_fix_rate(struct iwl_mvm *mvm, | |||
| 263 | lq_sta->lq.sta_id, lq_sta->dbg_fixed_rate); | 297 | lq_sta->lq.sta_id, lq_sta->dbg_fixed_rate); |
| 264 | 298 | ||
| 265 | if (lq_sta->dbg_fixed_rate) { | 299 | if (lq_sta->dbg_fixed_rate) { |
| 266 | rs_fill_link_cmd(NULL, lq_sta, lq_sta->dbg_fixed_rate); | 300 | rs_fill_link_cmd(NULL, NULL, lq_sta, lq_sta->dbg_fixed_rate); |
| 267 | iwl_mvm_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC, false); | 301 | iwl_mvm_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC, false); |
| 268 | } | 302 | } |
| 269 | } | 303 | } |
| @@ -275,17 +309,6 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_mvm *mvm, | |||
| 275 | { | 309 | { |
| 276 | int ret = -EAGAIN; | 310 | int ret = -EAGAIN; |
| 277 | 311 | ||
| 278 | /* | ||
| 279 | * Don't create TX aggregation sessions when in high | ||
| 280 | * BT traffic, as they would just be disrupted by BT. | ||
| 281 | */ | ||
| 282 | if (BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD) >= 2) { | ||
| 283 | IWL_DEBUG_COEX(mvm, "BT traffic (%d), no aggregation allowed\n", | ||
| 284 | BT_MBOX_MSG(&mvm->last_bt_notif, | ||
| 285 | 3, TRAFFIC_LOAD)); | ||
| 286 | return ret; | ||
| 287 | } | ||
| 288 | |||
| 289 | IWL_DEBUG_HT(mvm, "Starting Tx agg: STA: %pM tid: %d\n", | 312 | IWL_DEBUG_HT(mvm, "Starting Tx agg: STA: %pM tid: %d\n", |
| 290 | sta->addr, tid); | 313 | sta->addr, tid); |
| 291 | ret = ieee80211_start_tx_ba_session(sta, tid, 5000); | 314 | ret = ieee80211_start_tx_ba_session(sta, tid, 5000); |
| @@ -416,49 +439,54 @@ static int rs_collect_tx_data(struct iwl_scale_tbl_info *tbl, | |||
| 416 | */ | 439 | */ |
| 417 | /* FIXME:RS:remove this function and put the flags statically in the table */ | 440 | /* FIXME:RS:remove this function and put the flags statically in the table */ |
| 418 | static u32 rate_n_flags_from_tbl(struct iwl_mvm *mvm, | 441 | static u32 rate_n_flags_from_tbl(struct iwl_mvm *mvm, |
| 419 | struct iwl_scale_tbl_info *tbl, | 442 | struct iwl_scale_tbl_info *tbl, int index) |
| 420 | int index, u8 use_green) | ||
| 421 | { | 443 | { |
| 422 | u32 rate_n_flags = 0; | 444 | u32 rate_n_flags = 0; |
| 423 | 445 | ||
| 446 | rate_n_flags |= ((tbl->ant_type << RATE_MCS_ANT_POS) & | ||
| 447 | RATE_MCS_ANT_ABC_MSK); | ||
| 448 | |||
| 424 | if (is_legacy(tbl->lq_type)) { | 449 | if (is_legacy(tbl->lq_type)) { |
| 425 | rate_n_flags = iwl_rates[index].plcp; | 450 | rate_n_flags |= iwl_rates[index].plcp; |
| 426 | if (index >= IWL_FIRST_CCK_RATE && index <= IWL_LAST_CCK_RATE) | 451 | if (index >= IWL_FIRST_CCK_RATE && index <= IWL_LAST_CCK_RATE) |
| 427 | rate_n_flags |= RATE_MCS_CCK_MSK; | 452 | rate_n_flags |= RATE_MCS_CCK_MSK; |
| 428 | } else if (is_Ht(tbl->lq_type)) { | 453 | return rate_n_flags; |
| 429 | if (index > IWL_LAST_OFDM_RATE) { | 454 | } |
| 455 | |||
| 456 | if (is_ht(tbl->lq_type)) { | ||
| 457 | if (index < IWL_FIRST_HT_RATE || index > IWL_LAST_HT_RATE) { | ||
| 430 | IWL_ERR(mvm, "Invalid HT rate index %d\n", index); | 458 | IWL_ERR(mvm, "Invalid HT rate index %d\n", index); |
| 431 | index = IWL_LAST_OFDM_RATE; | 459 | index = IWL_LAST_HT_RATE; |
| 432 | } | 460 | } |
| 433 | rate_n_flags = RATE_MCS_HT_MSK; | 461 | rate_n_flags |= RATE_MCS_HT_MSK; |
| 434 | 462 | ||
| 435 | if (is_siso(tbl->lq_type)) | 463 | if (is_ht_siso(tbl->lq_type)) |
| 436 | rate_n_flags |= iwl_rates[index].plcp_siso; | 464 | rate_n_flags |= iwl_rates[index].plcp_ht_siso; |
| 437 | else if (is_mimo2(tbl->lq_type)) | 465 | else if (is_ht_mimo2(tbl->lq_type)) |
| 438 | rate_n_flags |= iwl_rates[index].plcp_mimo2; | 466 | rate_n_flags |= iwl_rates[index].plcp_ht_mimo2; |
| 439 | else | 467 | else |
| 440 | WARN_ON_ONCE(1); | 468 | WARN_ON_ONCE(1); |
| 469 | } else if (is_vht(tbl->lq_type)) { | ||
| 470 | if (index < IWL_FIRST_VHT_RATE || index > IWL_LAST_VHT_RATE) { | ||
| 471 | IWL_ERR(mvm, "Invalid VHT rate index %d\n", index); | ||
| 472 | index = IWL_LAST_VHT_RATE; | ||
| 473 | } | ||
| 474 | rate_n_flags |= RATE_MCS_VHT_MSK; | ||
| 475 | if (is_vht_siso(tbl->lq_type)) | ||
| 476 | rate_n_flags |= iwl_rates[index].plcp_vht_siso; | ||
| 477 | else if (is_vht_mimo2(tbl->lq_type)) | ||
| 478 | rate_n_flags |= iwl_rates[index].plcp_vht_mimo2; | ||
| 479 | else | ||
| 480 | WARN_ON_ONCE(1); | ||
| 481 | |||
| 441 | } else { | 482 | } else { |
| 442 | IWL_ERR(mvm, "Invalid tbl->lq_type %d\n", tbl->lq_type); | 483 | IWL_ERR(mvm, "Invalid tbl->lq_type %d\n", tbl->lq_type); |
| 443 | } | 484 | } |
| 444 | 485 | ||
| 445 | rate_n_flags |= ((tbl->ant_type << RATE_MCS_ANT_POS) & | 486 | rate_n_flags |= tbl->bw; |
| 446 | RATE_MCS_ANT_ABC_MSK); | 487 | if (tbl->is_SGI) |
| 447 | 488 | rate_n_flags |= RATE_MCS_SGI_MSK; | |
| 448 | if (is_Ht(tbl->lq_type)) { | 489 | |
| 449 | if (tbl->is_ht40) | ||
| 450 | rate_n_flags |= RATE_MCS_CHAN_WIDTH_40; | ||
| 451 | if (tbl->is_SGI) | ||
| 452 | rate_n_flags |= RATE_MCS_SGI_MSK; | ||
| 453 | |||
| 454 | if (use_green) { | ||
| 455 | rate_n_flags |= RATE_HT_MCS_GF_MSK; | ||
| 456 | if (is_siso(tbl->lq_type) && tbl->is_SGI) { | ||
| 457 | rate_n_flags &= ~RATE_MCS_SGI_MSK; | ||
| 458 | IWL_ERR(mvm, "GF was set with SGI:SISO\n"); | ||
| 459 | } | ||
| 460 | } | ||
| 461 | } | ||
| 462 | return rate_n_flags; | 490 | return rate_n_flags; |
| 463 | } | 491 | } |
| 464 | 492 | ||
| @@ -473,7 +501,7 @@ static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags, | |||
| 473 | { | 501 | { |
| 474 | u32 ant_msk = (rate_n_flags & RATE_MCS_ANT_ABC_MSK); | 502 | u32 ant_msk = (rate_n_flags & RATE_MCS_ANT_ABC_MSK); |
| 475 | u8 num_of_ant = get_num_of_ant_from_rate(rate_n_flags); | 503 | u8 num_of_ant = get_num_of_ant_from_rate(rate_n_flags); |
| 476 | u8 mcs; | 504 | u8 nss; |
| 477 | 505 | ||
| 478 | memset(tbl, 0, offsetof(struct iwl_scale_tbl_info, win)); | 506 | memset(tbl, 0, offsetof(struct iwl_scale_tbl_info, win)); |
| 479 | *rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags); | 507 | *rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags); |
| @@ -483,41 +511,62 @@ static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags, | |||
| 483 | return -EINVAL; | 511 | return -EINVAL; |
| 484 | } | 512 | } |
| 485 | tbl->is_SGI = 0; /* default legacy setup */ | 513 | tbl->is_SGI = 0; /* default legacy setup */ |
| 486 | tbl->is_ht40 = 0; | 514 | tbl->bw = 0; |
| 487 | tbl->ant_type = (ant_msk >> RATE_MCS_ANT_POS); | 515 | tbl->ant_type = (ant_msk >> RATE_MCS_ANT_POS); |
| 488 | tbl->lq_type = LQ_NONE; | 516 | tbl->lq_type = LQ_NONE; |
| 489 | tbl->max_search = IWL_MAX_SEARCH; | 517 | tbl->max_search = IWL_MAX_SEARCH; |
| 490 | 518 | ||
| 491 | /* legacy rate format */ | 519 | /* Legacy */ |
| 492 | if (!(rate_n_flags & RATE_MCS_HT_MSK)) { | 520 | if (!(rate_n_flags & RATE_MCS_HT_MSK) && |
| 521 | !(rate_n_flags & RATE_MCS_VHT_MSK)) { | ||
| 493 | if (num_of_ant == 1) { | 522 | if (num_of_ant == 1) { |
| 494 | if (band == IEEE80211_BAND_5GHZ) | 523 | if (band == IEEE80211_BAND_5GHZ) |
| 495 | tbl->lq_type = LQ_A; | 524 | tbl->lq_type = LQ_LEGACY_A; |
| 496 | else | 525 | else |
| 497 | tbl->lq_type = LQ_G; | 526 | tbl->lq_type = LQ_LEGACY_G; |
| 498 | } | 527 | } |
| 499 | /* HT rate format */ | 528 | |
| 500 | } else { | 529 | return 0; |
| 501 | if (rate_n_flags & RATE_MCS_SGI_MSK) | 530 | } |
| 502 | tbl->is_SGI = 1; | 531 | |
| 503 | 532 | /* HT or VHT */ | |
| 504 | if (rate_n_flags & RATE_MCS_CHAN_WIDTH_40) /* TODO */ | 533 | if (rate_n_flags & RATE_MCS_SGI_MSK) |
| 505 | tbl->is_ht40 = 1; | 534 | tbl->is_SGI = 1; |
| 506 | 535 | ||
| 507 | mcs = rs_extract_rate(rate_n_flags); | 536 | tbl->bw = rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK; |
| 508 | 537 | ||
| 509 | /* SISO */ | 538 | if (rate_n_flags & RATE_MCS_HT_MSK) { |
| 510 | if (mcs <= IWL_RATE_SISO_60M_PLCP) { | 539 | nss = ((rate_n_flags & RATE_HT_MCS_NSS_MSK) >> |
| 511 | if (num_of_ant == 1) | 540 | RATE_HT_MCS_NSS_POS) + 1; |
| 512 | tbl->lq_type = LQ_SISO; /*else NONE*/ | 541 | |
| 513 | /* MIMO2 */ | 542 | if (nss == 1) { |
| 514 | } else if (mcs <= IWL_RATE_MIMO2_60M_PLCP) { | 543 | tbl->lq_type = LQ_HT_SISO; |
| 515 | if (num_of_ant == 2) | 544 | WARN_ON_ONCE(num_of_ant != 1); |
| 516 | tbl->lq_type = LQ_MIMO2; | 545 | } else if (nss == 2) { |
| 546 | tbl->lq_type = LQ_HT_MIMO2; | ||
| 547 | WARN_ON_ONCE(num_of_ant != 2); | ||
| 548 | } else { | ||
| 549 | WARN_ON_ONCE(1); | ||
| 550 | } | ||
| 551 | } else if (rate_n_flags & RATE_MCS_VHT_MSK) { | ||
| 552 | nss = ((rate_n_flags & RATE_VHT_MCS_NSS_MSK) >> | ||
| 553 | RATE_VHT_MCS_NSS_POS) + 1; | ||
| 554 | |||
| 555 | if (nss == 1) { | ||
| 556 | tbl->lq_type = LQ_VHT_SISO; | ||
| 557 | WARN_ON_ONCE(num_of_ant != 1); | ||
| 558 | } else if (nss == 2) { | ||
| 559 | tbl->lq_type = LQ_VHT_MIMO2; | ||
| 560 | WARN_ON_ONCE(num_of_ant != 2); | ||
| 517 | } else { | 561 | } else { |
| 518 | WARN_ON_ONCE(num_of_ant == 3); | 562 | WARN_ON_ONCE(1); |
| 519 | } | 563 | } |
| 520 | } | 564 | } |
| 565 | |||
| 566 | WARN_ON_ONCE(tbl->bw == RATE_MCS_CHAN_WIDTH_160); | ||
| 567 | WARN_ON_ONCE(tbl->bw == RATE_MCS_CHAN_WIDTH_80 && | ||
| 568 | !is_vht(tbl->lq_type)); | ||
| 569 | |||
| 521 | return 0; | 570 | return 0; |
| 522 | } | 571 | } |
| 523 | 572 | ||
| @@ -550,22 +599,6 @@ static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags, | |||
| 550 | } | 599 | } |
| 551 | 600 | ||
| 552 | /** | 601 | /** |
| 553 | * Green-field mode is valid if the station supports it and | ||
| 554 | * there are no non-GF stations present in the BSS. | ||
| 555 | */ | ||
| 556 | static bool rs_use_green(struct ieee80211_sta *sta) | ||
| 557 | { | ||
| 558 | /* | ||
| 559 | * There's a bug somewhere in this code that causes the | ||
| 560 | * scaling to get stuck because GF+SGI can't be combined | ||
| 561 | * in SISO rates. Until we find that bug, disable GF, it | ||
| 562 | * has only limited benefit and we still interoperate with | ||
| 563 | * GF APs since we can always receive GF transmissions. | ||
| 564 | */ | ||
| 565 | return false; | ||
| 566 | } | ||
| 567 | |||
| 568 | /** | ||
| 569 | * rs_get_supported_rates - get the available rates | 602 | * rs_get_supported_rates - get the available rates |
| 570 | * | 603 | * |
| 571 | * if management frame or broadcast frame only return | 604 | * if management frame or broadcast frame only return |
| @@ -576,16 +609,15 @@ static u16 rs_get_supported_rates(struct iwl_lq_sta *lq_sta, | |||
| 576 | struct ieee80211_hdr *hdr, | 609 | struct ieee80211_hdr *hdr, |
| 577 | enum iwl_table_type rate_type) | 610 | enum iwl_table_type rate_type) |
| 578 | { | 611 | { |
| 579 | if (is_legacy(rate_type)) { | 612 | if (is_legacy(rate_type)) |
| 580 | return lq_sta->active_legacy_rate; | 613 | return lq_sta->active_legacy_rate; |
| 581 | } else { | 614 | else if (is_siso(rate_type)) |
| 582 | if (is_siso(rate_type)) | 615 | return lq_sta->active_siso_rate; |
| 583 | return lq_sta->active_siso_rate; | 616 | else if (is_mimo2(rate_type)) |
| 584 | else { | 617 | return lq_sta->active_mimo2_rate; |
| 585 | WARN_ON_ONCE(!is_mimo2(rate_type)); | 618 | |
| 586 | return lq_sta->active_mimo2_rate; | 619 | WARN_ON_ONCE(1); |
| 587 | } | 620 | return 0; |
| 588 | } | ||
| 589 | } | 621 | } |
| 590 | 622 | ||
| 591 | static u16 rs_get_adjacent_rate(struct iwl_mvm *mvm, u8 index, u16 rate_mask, | 623 | static u16 rs_get_adjacent_rate(struct iwl_mvm *mvm, u8 index, u16 rate_mask, |
| @@ -652,7 +684,6 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta, | |||
| 652 | u16 rate_mask; | 684 | u16 rate_mask; |
| 653 | u16 high_low; | 685 | u16 high_low; |
| 654 | u8 switch_to_legacy = 0; | 686 | u8 switch_to_legacy = 0; |
| 655 | u8 is_green = lq_sta->is_green; | ||
| 656 | struct iwl_mvm *mvm = lq_sta->drv; | 687 | struct iwl_mvm *mvm = lq_sta->drv; |
| 657 | 688 | ||
| 658 | /* check if we need to switch from HT to legacy rates. | 689 | /* check if we need to switch from HT to legacy rates. |
| @@ -662,15 +693,15 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta, | |||
| 662 | switch_to_legacy = 1; | 693 | switch_to_legacy = 1; |
| 663 | scale_index = rs_ht_to_legacy[scale_index]; | 694 | scale_index = rs_ht_to_legacy[scale_index]; |
| 664 | if (lq_sta->band == IEEE80211_BAND_5GHZ) | 695 | if (lq_sta->band == IEEE80211_BAND_5GHZ) |
| 665 | tbl->lq_type = LQ_A; | 696 | tbl->lq_type = LQ_LEGACY_A; |
| 666 | else | 697 | else |
| 667 | tbl->lq_type = LQ_G; | 698 | tbl->lq_type = LQ_LEGACY_G; |
| 668 | 699 | ||
| 669 | if (num_of_ant(tbl->ant_type) > 1) | 700 | if (num_of_ant(tbl->ant_type) > 1) |
| 670 | tbl->ant_type = | 701 | tbl->ant_type = |
| 671 | first_antenna(iwl_fw_valid_tx_ant(mvm->fw)); | 702 | first_antenna(iwl_fw_valid_tx_ant(mvm->fw)); |
| 672 | 703 | ||
| 673 | tbl->is_ht40 = 0; | 704 | tbl->bw = 0; |
| 674 | tbl->is_SGI = 0; | 705 | tbl->is_SGI = 0; |
| 675 | tbl->max_search = IWL_MAX_SEARCH; | 706 | tbl->max_search = IWL_MAX_SEARCH; |
| 676 | } | 707 | } |
| @@ -701,7 +732,7 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta, | |||
| 701 | low = scale_index; | 732 | low = scale_index; |
| 702 | 733 | ||
| 703 | out: | 734 | out: |
| 704 | return rate_n_flags_from_tbl(lq_sta->drv, tbl, low, is_green); | 735 | return rate_n_flags_from_tbl(lq_sta->drv, tbl, low); |
| 705 | } | 736 | } |
| 706 | 737 | ||
| 707 | /* | 738 | /* |
| @@ -714,6 +745,18 @@ static bool table_type_matches(struct iwl_scale_tbl_info *a, | |||
| 714 | (a->is_SGI == b->is_SGI); | 745 | (a->is_SGI == b->is_SGI); |
| 715 | } | 746 | } |
| 716 | 747 | ||
| 748 | static u32 rs_ch_width_from_mac_flags(enum mac80211_rate_control_flags flags) | ||
| 749 | { | ||
| 750 | if (flags & IEEE80211_TX_RC_40_MHZ_WIDTH) | ||
| 751 | return RATE_MCS_CHAN_WIDTH_40; | ||
| 752 | else if (flags & IEEE80211_TX_RC_80_MHZ_WIDTH) | ||
| 753 | return RATE_MCS_CHAN_WIDTH_80; | ||
| 754 | else if (flags & IEEE80211_TX_RC_160_MHZ_WIDTH) | ||
| 755 | return RATE_MCS_CHAN_WIDTH_160; | ||
| 756 | |||
| 757 | return RATE_MCS_CHAN_WIDTH_20; | ||
| 758 | } | ||
| 759 | |||
| 717 | /* | 760 | /* |
| 718 | * mac80211 sends us Tx status | 761 | * mac80211 sends us Tx status |
| 719 | */ | 762 | */ |
| @@ -783,16 +826,23 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband, | |||
| 783 | */ | 826 | */ |
| 784 | if (info->band == IEEE80211_BAND_2GHZ) | 827 | if (info->band == IEEE80211_BAND_2GHZ) |
| 785 | mac_index += IWL_FIRST_OFDM_RATE; | 828 | mac_index += IWL_FIRST_OFDM_RATE; |
| 829 | } else if (mac_flags & IEEE80211_TX_RC_VHT_MCS) { | ||
| 830 | mac_index &= RATE_VHT_MCS_RATE_CODE_MSK; | ||
| 831 | if (mac_index >= (IWL_RATE_9M_INDEX - IWL_FIRST_OFDM_RATE)) | ||
| 832 | mac_index++; | ||
| 786 | } | 833 | } |
| 834 | |||
| 787 | /* Here we actually compare this rate to the latest LQ command */ | 835 | /* Here we actually compare this rate to the latest LQ command */ |
| 788 | if ((mac_index < 0) || | 836 | if ((mac_index < 0) || |
| 789 | (tbl_type.is_SGI != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) || | 837 | (tbl_type.is_SGI != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) || |
| 790 | (tbl_type.is_ht40 != !!(mac_flags & IEEE80211_TX_RC_40_MHZ_WIDTH)) || | 838 | (tbl_type.bw != rs_ch_width_from_mac_flags(mac_flags)) || |
| 791 | (tbl_type.ant_type != info->status.antenna) || | 839 | (tbl_type.ant_type != info->status.antenna) || |
| 792 | (!!(tx_rate & RATE_MCS_HT_MSK) != | 840 | (!!(tx_rate & RATE_MCS_HT_MSK) != |
| 793 | !!(mac_flags & IEEE80211_TX_RC_MCS)) || | 841 | !!(mac_flags & IEEE80211_TX_RC_MCS)) || |
| 842 | (!!(tx_rate & RATE_MCS_VHT_MSK) != | ||
| 843 | !!(mac_flags & IEEE80211_TX_RC_VHT_MCS)) || | ||
| 794 | (!!(tx_rate & RATE_HT_MCS_GF_MSK) != | 844 | (!!(tx_rate & RATE_HT_MCS_GF_MSK) != |
| 795 | !!(mac_flags & IEEE80211_TX_RC_GREEN_FIELD)) || | 845 | !!(mac_flags & IEEE80211_TX_RC_GREEN_FIELD)) || |
| 796 | (rs_index != mac_index)) { | 846 | (rs_index != mac_index)) { |
| 797 | IWL_DEBUG_RATE(mvm, | 847 | IWL_DEBUG_RATE(mvm, |
| 798 | "initial rate %d does not match %d (0x%x)\n", | 848 | "initial rate %d does not match %d (0x%x)\n", |
| @@ -947,7 +997,8 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta, | |||
| 947 | s32 (*ht_tbl_pointer)[IWL_RATE_COUNT]; | 997 | s32 (*ht_tbl_pointer)[IWL_RATE_COUNT]; |
| 948 | 998 | ||
| 949 | /* Check for invalid LQ type */ | 999 | /* Check for invalid LQ type */ |
| 950 | if (WARN_ON_ONCE(!is_legacy(tbl->lq_type) && !is_Ht(tbl->lq_type))) { | 1000 | if (WARN_ON_ONCE(!is_legacy(tbl->lq_type) && !is_ht(tbl->lq_type) && |
| 1001 | !(is_vht(tbl->lq_type)))) { | ||
| 951 | tbl->expected_tpt = expected_tpt_legacy; | 1002 | tbl->expected_tpt = expected_tpt_legacy; |
| 952 | return; | 1003 | return; |
| 953 | } | 1004 | } |
| @@ -958,18 +1009,40 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta, | |||
| 958 | return; | 1009 | return; |
| 959 | } | 1010 | } |
| 960 | 1011 | ||
| 1012 | ht_tbl_pointer = expected_tpt_mimo2_20MHz; | ||
| 961 | /* Choose among many HT tables depending on number of streams | 1013 | /* Choose among many HT tables depending on number of streams |
| 962 | * (SISO/MIMO2), channel width (20/40), SGI, and aggregation | 1014 | * (SISO/MIMO2), channel width (20/40/80), SGI, and aggregation |
| 963 | * status */ | 1015 | * status */ |
| 964 | if (is_siso(tbl->lq_type) && !tbl->is_ht40) | 1016 | if (is_siso(tbl->lq_type)) { |
| 965 | ht_tbl_pointer = expected_tpt_siso20MHz; | 1017 | switch (tbl->bw) { |
| 966 | else if (is_siso(tbl->lq_type)) | 1018 | case RATE_MCS_CHAN_WIDTH_20: |
| 967 | ht_tbl_pointer = expected_tpt_siso40MHz; | 1019 | ht_tbl_pointer = expected_tpt_siso_20MHz; |
| 968 | else if (is_mimo2(tbl->lq_type) && !tbl->is_ht40) | 1020 | break; |
| 969 | ht_tbl_pointer = expected_tpt_mimo2_20MHz; | 1021 | case RATE_MCS_CHAN_WIDTH_40: |
| 970 | else { | 1022 | ht_tbl_pointer = expected_tpt_siso_40MHz; |
| 971 | WARN_ON_ONCE(!is_mimo2(tbl->lq_type)); | 1023 | break; |
| 972 | ht_tbl_pointer = expected_tpt_mimo2_40MHz; | 1024 | case RATE_MCS_CHAN_WIDTH_80: |
| 1025 | ht_tbl_pointer = expected_tpt_siso_80MHz; | ||
| 1026 | break; | ||
| 1027 | default: | ||
| 1028 | WARN_ON_ONCE(1); | ||
| 1029 | } | ||
| 1030 | } else if (is_mimo2(tbl->lq_type)) { | ||
| 1031 | switch (tbl->bw) { | ||
| 1032 | case RATE_MCS_CHAN_WIDTH_20: | ||
| 1033 | ht_tbl_pointer = expected_tpt_mimo2_20MHz; | ||
| 1034 | break; | ||
| 1035 | case RATE_MCS_CHAN_WIDTH_40: | ||
| 1036 | ht_tbl_pointer = expected_tpt_mimo2_40MHz; | ||
| 1037 | break; | ||
| 1038 | case RATE_MCS_CHAN_WIDTH_80: | ||
| 1039 | ht_tbl_pointer = expected_tpt_mimo2_80MHz; | ||
| 1040 | break; | ||
| 1041 | default: | ||
| 1042 | WARN_ON_ONCE(1); | ||
| 1043 | } | ||
| 1044 | } else { | ||
| 1045 | WARN_ON_ONCE(1); | ||
| 973 | } | 1046 | } |
| 974 | 1047 | ||
| 975 | if (!tbl->is_SGI && !lq_sta->is_agg) /* Normal */ | 1048 | if (!tbl->is_SGI && !lq_sta->is_agg) /* Normal */ |
| @@ -1084,9 +1157,47 @@ static s32 rs_get_best_rate(struct iwl_mvm *mvm, | |||
| 1084 | return new_rate; | 1157 | return new_rate; |
| 1085 | } | 1158 | } |
| 1086 | 1159 | ||
| 1087 | static bool iwl_is_ht40_tx_allowed(struct ieee80211_sta *sta) | 1160 | /* Move to the next action and wrap around to the first action in case |
| 1161 | * we're at the last action. Assumes actions start at 0. | ||
| 1162 | */ | ||
| 1163 | static inline void rs_move_next_action(struct iwl_scale_tbl_info *tbl, | ||
| 1164 | u8 last_action) | ||
| 1165 | { | ||
| 1166 | BUILD_BUG_ON(IWL_LEGACY_FIRST_ACTION != 0); | ||
| 1167 | BUILD_BUG_ON(IWL_SISO_FIRST_ACTION != 0); | ||
| 1168 | BUILD_BUG_ON(IWL_MIMO2_FIRST_ACTION != 0); | ||
| 1169 | |||
| 1170 | tbl->action = (tbl->action + 1) % (last_action + 1); | ||
| 1171 | } | ||
| 1172 | |||
| 1173 | static void rs_set_bw_from_sta(struct iwl_scale_tbl_info *tbl, | ||
| 1174 | struct ieee80211_sta *sta) | ||
| 1175 | { | ||
| 1176 | if (sta->bandwidth >= IEEE80211_STA_RX_BW_80) | ||
| 1177 | tbl->bw = RATE_MCS_CHAN_WIDTH_80; | ||
| 1178 | else if (sta->bandwidth >= IEEE80211_STA_RX_BW_40) | ||
| 1179 | tbl->bw = RATE_MCS_CHAN_WIDTH_40; | ||
| 1180 | else | ||
| 1181 | tbl->bw = RATE_MCS_CHAN_WIDTH_20; | ||
| 1182 | } | ||
| 1183 | |||
| 1184 | static bool rs_sgi_allowed(struct iwl_scale_tbl_info *tbl, | ||
| 1185 | struct ieee80211_sta *sta) | ||
| 1088 | { | 1186 | { |
| 1089 | return sta->bandwidth >= IEEE80211_STA_RX_BW_40; | 1187 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; |
| 1188 | struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap; | ||
| 1189 | |||
| 1190 | if (is_ht20(tbl) && (ht_cap->cap & | ||
| 1191 | IEEE80211_HT_CAP_SGI_20)) | ||
| 1192 | return true; | ||
| 1193 | if (is_ht40(tbl) && (ht_cap->cap & | ||
| 1194 | IEEE80211_HT_CAP_SGI_40)) | ||
| 1195 | return true; | ||
| 1196 | if (is_ht80(tbl) && (vht_cap->cap & | ||
| 1197 | IEEE80211_VHT_CAP_SHORT_GI_80)) | ||
| 1198 | return true; | ||
| 1199 | |||
| 1200 | return false; | ||
| 1090 | } | 1201 | } |
| 1091 | 1202 | ||
| 1092 | /* | 1203 | /* |
| @@ -1099,7 +1210,6 @@ static int rs_switch_to_mimo2(struct iwl_mvm *mvm, | |||
| 1099 | { | 1210 | { |
| 1100 | u16 rate_mask; | 1211 | u16 rate_mask; |
| 1101 | s32 rate; | 1212 | s32 rate; |
| 1102 | s8 is_green = lq_sta->is_green; | ||
| 1103 | 1213 | ||
| 1104 | if (!sta->ht_cap.ht_supported) | 1214 | if (!sta->ht_cap.ht_supported) |
| 1105 | return -1; | 1215 | return -1; |
| @@ -1113,16 +1223,12 @@ static int rs_switch_to_mimo2(struct iwl_mvm *mvm, | |||
| 1113 | 1223 | ||
| 1114 | IWL_DEBUG_RATE(mvm, "LQ: try to switch to MIMO2\n"); | 1224 | IWL_DEBUG_RATE(mvm, "LQ: try to switch to MIMO2\n"); |
| 1115 | 1225 | ||
| 1116 | tbl->lq_type = LQ_MIMO2; | 1226 | tbl->lq_type = lq_sta->is_vht ? LQ_VHT_MIMO2 : LQ_HT_MIMO2; |
| 1117 | tbl->action = 0; | 1227 | tbl->action = 0; |
| 1118 | tbl->max_search = IWL_MAX_SEARCH; | 1228 | tbl->max_search = IWL_MAX_SEARCH; |
| 1119 | rate_mask = lq_sta->active_mimo2_rate; | 1229 | rate_mask = lq_sta->active_mimo2_rate; |
| 1120 | 1230 | ||
| 1121 | if (iwl_is_ht40_tx_allowed(sta)) | 1231 | rs_set_bw_from_sta(tbl, sta); |
| 1122 | tbl->is_ht40 = 1; | ||
| 1123 | else | ||
| 1124 | tbl->is_ht40 = 0; | ||
| 1125 | |||
| 1126 | rs_set_expected_tpt_table(lq_sta, tbl); | 1232 | rs_set_expected_tpt_table(lq_sta, tbl); |
| 1127 | 1233 | ||
| 1128 | rate = rs_get_best_rate(mvm, lq_sta, tbl, rate_mask, index); | 1234 | rate = rs_get_best_rate(mvm, lq_sta, tbl, rate_mask, index); |
| @@ -1134,10 +1240,10 @@ static int rs_switch_to_mimo2(struct iwl_mvm *mvm, | |||
| 1134 | rate, rate_mask); | 1240 | rate, rate_mask); |
| 1135 | return -1; | 1241 | return -1; |
| 1136 | } | 1242 | } |
| 1137 | tbl->current_rate = rate_n_flags_from_tbl(mvm, tbl, rate, is_green); | 1243 | tbl->current_rate = rate_n_flags_from_tbl(mvm, tbl, rate); |
| 1138 | 1244 | ||
| 1139 | IWL_DEBUG_RATE(mvm, "LQ: Switch to new mcs %X index is green %X\n", | 1245 | IWL_DEBUG_RATE(mvm, "LQ: Switch to new mcs %X index\n", |
| 1140 | tbl->current_rate, is_green); | 1246 | tbl->current_rate); |
| 1141 | return 0; | 1247 | return 0; |
| 1142 | } | 1248 | } |
| 1143 | 1249 | ||
| @@ -1150,7 +1256,6 @@ static int rs_switch_to_siso(struct iwl_mvm *mvm, | |||
| 1150 | struct iwl_scale_tbl_info *tbl, int index) | 1256 | struct iwl_scale_tbl_info *tbl, int index) |
| 1151 | { | 1257 | { |
| 1152 | u16 rate_mask; | 1258 | u16 rate_mask; |
| 1153 | u8 is_green = lq_sta->is_green; | ||
| 1154 | s32 rate; | 1259 | s32 rate; |
| 1155 | 1260 | ||
| 1156 | if (!sta->ht_cap.ht_supported) | 1261 | if (!sta->ht_cap.ht_supported) |
| @@ -1158,19 +1263,12 @@ static int rs_switch_to_siso(struct iwl_mvm *mvm, | |||
| 1158 | 1263 | ||
| 1159 | IWL_DEBUG_RATE(mvm, "LQ: try to switch to SISO\n"); | 1264 | IWL_DEBUG_RATE(mvm, "LQ: try to switch to SISO\n"); |
| 1160 | 1265 | ||
| 1161 | tbl->lq_type = LQ_SISO; | 1266 | tbl->lq_type = lq_sta->is_vht ? LQ_VHT_SISO : LQ_HT_SISO; |
| 1162 | tbl->action = 0; | 1267 | tbl->action = 0; |
| 1163 | tbl->max_search = IWL_MAX_SEARCH; | 1268 | tbl->max_search = IWL_MAX_SEARCH; |
| 1164 | rate_mask = lq_sta->active_siso_rate; | 1269 | rate_mask = lq_sta->active_siso_rate; |
| 1165 | 1270 | ||
| 1166 | if (iwl_is_ht40_tx_allowed(sta)) | 1271 | rs_set_bw_from_sta(tbl, sta); |
| 1167 | tbl->is_ht40 = 1; | ||
| 1168 | else | ||
| 1169 | tbl->is_ht40 = 0; | ||
| 1170 | |||
| 1171 | if (is_green) | ||
| 1172 | tbl->is_SGI = 0; /*11n spec: no SGI in SISO+Greenfield*/ | ||
| 1173 | |||
| 1174 | rs_set_expected_tpt_table(lq_sta, tbl); | 1272 | rs_set_expected_tpt_table(lq_sta, tbl); |
| 1175 | rate = rs_get_best_rate(mvm, lq_sta, tbl, rate_mask, index); | 1273 | rate = rs_get_best_rate(mvm, lq_sta, tbl, rate_mask, index); |
| 1176 | 1274 | ||
| @@ -1181,9 +1279,9 @@ static int rs_switch_to_siso(struct iwl_mvm *mvm, | |||
| 1181 | rate, rate_mask); | 1279 | rate, rate_mask); |
| 1182 | return -1; | 1280 | return -1; |
| 1183 | } | 1281 | } |
| 1184 | tbl->current_rate = rate_n_flags_from_tbl(mvm, tbl, rate, is_green); | 1282 | tbl->current_rate = rate_n_flags_from_tbl(mvm, tbl, rate); |
| 1185 | IWL_DEBUG_RATE(mvm, "LQ: Switch to new mcs %X index is green %X\n", | 1283 | IWL_DEBUG_RATE(mvm, "LQ: Switch to new mcs %X index\n", |
| 1186 | tbl->current_rate, is_green); | 1284 | tbl->current_rate); |
| 1187 | return 0; | 1285 | return 0; |
| 1188 | } | 1286 | } |
| 1189 | 1287 | ||
| @@ -1211,14 +1309,10 @@ static int rs_move_legacy_other(struct iwl_mvm *mvm, | |||
| 1211 | while (1) { | 1309 | while (1) { |
| 1212 | lq_sta->action_counter++; | 1310 | lq_sta->action_counter++; |
| 1213 | switch (tbl->action) { | 1311 | switch (tbl->action) { |
| 1214 | case IWL_LEGACY_SWITCH_ANTENNA1: | 1312 | case IWL_LEGACY_SWITCH_ANTENNA: |
| 1215 | case IWL_LEGACY_SWITCH_ANTENNA2: | ||
| 1216 | IWL_DEBUG_RATE(mvm, "LQ: Legacy toggle Antenna\n"); | 1313 | IWL_DEBUG_RATE(mvm, "LQ: Legacy toggle Antenna\n"); |
| 1217 | 1314 | ||
| 1218 | if ((tbl->action == IWL_LEGACY_SWITCH_ANTENNA1 && | 1315 | if (tx_chains_num <= 1) |
| 1219 | tx_chains_num <= 1) || | ||
| 1220 | (tbl->action == IWL_LEGACY_SWITCH_ANTENNA2 && | ||
| 1221 | tx_chains_num <= 2)) | ||
| 1222 | break; | 1316 | break; |
| 1223 | 1317 | ||
| 1224 | /* Don't change antenna if success has been great */ | 1318 | /* Don't change antenna if success has been great */ |
| @@ -1273,9 +1367,7 @@ static int rs_move_legacy_other(struct iwl_mvm *mvm, | |||
| 1273 | default: | 1367 | default: |
| 1274 | WARN_ON_ONCE(1); | 1368 | WARN_ON_ONCE(1); |
| 1275 | } | 1369 | } |
| 1276 | tbl->action++; | 1370 | rs_move_next_action(tbl, IWL_LEGACY_LAST_ACTION); |
| 1277 | if (tbl->action > IWL_LEGACY_SWITCH_MIMO2) | ||
| 1278 | tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; | ||
| 1279 | 1371 | ||
| 1280 | if (tbl->action == start_action) | 1372 | if (tbl->action == start_action) |
| 1281 | break; | 1373 | break; |
| @@ -1285,9 +1377,7 @@ static int rs_move_legacy_other(struct iwl_mvm *mvm, | |||
| 1285 | 1377 | ||
| 1286 | out: | 1378 | out: |
| 1287 | lq_sta->search_better_tbl = 1; | 1379 | lq_sta->search_better_tbl = 1; |
| 1288 | tbl->action++; | 1380 | rs_move_next_action(tbl, IWL_LEGACY_LAST_ACTION); |
| 1289 | if (tbl->action > IWL_LEGACY_SWITCH_MIMO2) | ||
| 1290 | tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; | ||
| 1291 | if (update_search_tbl_counter) | 1381 | if (update_search_tbl_counter) |
| 1292 | search_tbl->action = tbl->action; | 1382 | search_tbl->action = tbl->action; |
| 1293 | return 0; | 1383 | return 0; |
| @@ -1300,12 +1390,10 @@ static int rs_move_siso_to_other(struct iwl_mvm *mvm, | |||
| 1300 | struct iwl_lq_sta *lq_sta, | 1390 | struct iwl_lq_sta *lq_sta, |
| 1301 | struct ieee80211_sta *sta, int index) | 1391 | struct ieee80211_sta *sta, int index) |
| 1302 | { | 1392 | { |
| 1303 | u8 is_green = lq_sta->is_green; | ||
| 1304 | struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); | 1393 | struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); |
| 1305 | struct iwl_scale_tbl_info *search_tbl = | 1394 | struct iwl_scale_tbl_info *search_tbl = |
| 1306 | &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); | 1395 | &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); |
| 1307 | struct iwl_rate_scale_data *window = &(tbl->win[index]); | 1396 | struct iwl_rate_scale_data *window = &(tbl->win[index]); |
| 1308 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; | ||
| 1309 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 1397 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - |
| 1310 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 1398 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); |
| 1311 | u8 start_action; | 1399 | u8 start_action; |
| @@ -1314,40 +1402,17 @@ static int rs_move_siso_to_other(struct iwl_mvm *mvm, | |||
| 1314 | u8 update_search_tbl_counter = 0; | 1402 | u8 update_search_tbl_counter = 0; |
| 1315 | int ret; | 1403 | int ret; |
| 1316 | 1404 | ||
| 1317 | switch (BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD)) { | 1405 | if (tbl->action == IWL_SISO_SWITCH_MIMO2 && |
| 1318 | case IWL_BT_COEX_TRAFFIC_LOAD_NONE: | 1406 | !iwl_mvm_bt_coex_is_mimo_allowed(mvm, sta)) |
| 1319 | /* nothing */ | 1407 | tbl->action = IWL_SISO_SWITCH_ANTENNA; |
| 1320 | break; | ||
| 1321 | case IWL_BT_COEX_TRAFFIC_LOAD_LOW: | ||
| 1322 | /* avoid antenna B unless MIMO */ | ||
| 1323 | if (tbl->action == IWL_SISO_SWITCH_ANTENNA2) | ||
| 1324 | tbl->action = IWL_SISO_SWITCH_MIMO2; | ||
| 1325 | break; | ||
| 1326 | case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: | ||
| 1327 | case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: | ||
| 1328 | /* avoid antenna B and MIMO */ | ||
| 1329 | valid_tx_ant = | ||
| 1330 | first_antenna(iwl_fw_valid_tx_ant(mvm->fw)); | ||
| 1331 | if (tbl->action != IWL_SISO_SWITCH_ANTENNA1) | ||
| 1332 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; | ||
| 1333 | break; | ||
| 1334 | default: | ||
| 1335 | IWL_ERR(mvm, "Invalid BT load %d", | ||
| 1336 | BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD)); | ||
| 1337 | break; | ||
| 1338 | } | ||
| 1339 | 1408 | ||
| 1340 | start_action = tbl->action; | 1409 | start_action = tbl->action; |
| 1341 | while (1) { | 1410 | while (1) { |
| 1342 | lq_sta->action_counter++; | 1411 | lq_sta->action_counter++; |
| 1343 | switch (tbl->action) { | 1412 | switch (tbl->action) { |
| 1344 | case IWL_SISO_SWITCH_ANTENNA1: | 1413 | case IWL_SISO_SWITCH_ANTENNA: |
| 1345 | case IWL_SISO_SWITCH_ANTENNA2: | ||
| 1346 | IWL_DEBUG_RATE(mvm, "LQ: SISO toggle Antenna\n"); | 1414 | IWL_DEBUG_RATE(mvm, "LQ: SISO toggle Antenna\n"); |
| 1347 | if ((tbl->action == IWL_SISO_SWITCH_ANTENNA1 && | 1415 | if (tx_chains_num <= 1) |
| 1348 | tx_chains_num <= 1) || | ||
| 1349 | (tbl->action == IWL_SISO_SWITCH_ANTENNA2 && | ||
| 1350 | tx_chains_num <= 2)) | ||
| 1351 | break; | 1416 | break; |
| 1352 | 1417 | ||
| 1353 | if (window->success_ratio >= IWL_RS_GOOD_RATIO && | 1418 | if (window->success_ratio >= IWL_RS_GOOD_RATIO && |
| @@ -1380,23 +1445,12 @@ static int rs_move_siso_to_other(struct iwl_mvm *mvm, | |||
| 1380 | goto out; | 1445 | goto out; |
| 1381 | break; | 1446 | break; |
| 1382 | case IWL_SISO_SWITCH_GI: | 1447 | case IWL_SISO_SWITCH_GI: |
| 1383 | if (!tbl->is_ht40 && !(ht_cap->cap & | 1448 | if (!rs_sgi_allowed(tbl, sta)) |
| 1384 | IEEE80211_HT_CAP_SGI_20)) | ||
| 1385 | break; | ||
| 1386 | if (tbl->is_ht40 && !(ht_cap->cap & | ||
| 1387 | IEEE80211_HT_CAP_SGI_40)) | ||
| 1388 | break; | 1449 | break; |
| 1389 | 1450 | ||
| 1390 | IWL_DEBUG_RATE(mvm, "LQ: SISO toggle SGI/NGI\n"); | 1451 | IWL_DEBUG_RATE(mvm, "LQ: SISO toggle SGI/NGI\n"); |
| 1391 | 1452 | ||
| 1392 | memcpy(search_tbl, tbl, sz); | 1453 | memcpy(search_tbl, tbl, sz); |
| 1393 | if (is_green) { | ||
| 1394 | if (!tbl->is_SGI) | ||
| 1395 | break; | ||
| 1396 | else | ||
| 1397 | IWL_ERR(mvm, | ||
| 1398 | "SGI was set in GF+SISO\n"); | ||
| 1399 | } | ||
| 1400 | search_tbl->is_SGI = !tbl->is_SGI; | 1454 | search_tbl->is_SGI = !tbl->is_SGI; |
| 1401 | rs_set_expected_tpt_table(lq_sta, search_tbl); | 1455 | rs_set_expected_tpt_table(lq_sta, search_tbl); |
| 1402 | if (tbl->is_SGI) { | 1456 | if (tbl->is_SGI) { |
| @@ -1405,16 +1459,13 @@ static int rs_move_siso_to_other(struct iwl_mvm *mvm, | |||
| 1405 | break; | 1459 | break; |
| 1406 | } | 1460 | } |
| 1407 | search_tbl->current_rate = | 1461 | search_tbl->current_rate = |
| 1408 | rate_n_flags_from_tbl(mvm, search_tbl, | 1462 | rate_n_flags_from_tbl(mvm, search_tbl, index); |
| 1409 | index, is_green); | ||
| 1410 | update_search_tbl_counter = 1; | 1463 | update_search_tbl_counter = 1; |
| 1411 | goto out; | 1464 | goto out; |
| 1412 | default: | 1465 | default: |
| 1413 | WARN_ON_ONCE(1); | 1466 | WARN_ON_ONCE(1); |
| 1414 | } | 1467 | } |
| 1415 | tbl->action++; | 1468 | rs_move_next_action(tbl, IWL_SISO_LAST_ACTION); |
| 1416 | if (tbl->action > IWL_SISO_SWITCH_GI) | ||
| 1417 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; | ||
| 1418 | 1469 | ||
| 1419 | if (tbl->action == start_action) | 1470 | if (tbl->action == start_action) |
| 1420 | break; | 1471 | break; |
| @@ -1424,9 +1475,7 @@ static int rs_move_siso_to_other(struct iwl_mvm *mvm, | |||
| 1424 | 1475 | ||
| 1425 | out: | 1476 | out: |
| 1426 | lq_sta->search_better_tbl = 1; | 1477 | lq_sta->search_better_tbl = 1; |
| 1427 | tbl->action++; | 1478 | rs_move_next_action(tbl, IWL_SISO_LAST_ACTION); |
| 1428 | if (tbl->action > IWL_SISO_SWITCH_GI) | ||
| 1429 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; | ||
| 1430 | if (update_search_tbl_counter) | 1479 | if (update_search_tbl_counter) |
| 1431 | search_tbl->action = tbl->action; | 1480 | search_tbl->action = tbl->action; |
| 1432 | 1481 | ||
| @@ -1440,63 +1489,20 @@ static int rs_move_mimo2_to_other(struct iwl_mvm *mvm, | |||
| 1440 | struct iwl_lq_sta *lq_sta, | 1489 | struct iwl_lq_sta *lq_sta, |
| 1441 | struct ieee80211_sta *sta, int index) | 1490 | struct ieee80211_sta *sta, int index) |
| 1442 | { | 1491 | { |
| 1443 | s8 is_green = lq_sta->is_green; | ||
| 1444 | struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); | 1492 | struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); |
| 1445 | struct iwl_scale_tbl_info *search_tbl = | 1493 | struct iwl_scale_tbl_info *search_tbl = |
| 1446 | &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); | 1494 | &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); |
| 1447 | struct iwl_rate_scale_data *window = &(tbl->win[index]); | ||
| 1448 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; | ||
| 1449 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 1495 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - |
| 1450 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 1496 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); |
| 1451 | u8 start_action; | 1497 | u8 start_action; |
| 1452 | u8 valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw); | 1498 | u8 valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw); |
| 1453 | u8 tx_chains_num = num_of_ant(valid_tx_ant); | ||
| 1454 | u8 update_search_tbl_counter = 0; | 1499 | u8 update_search_tbl_counter = 0; |
| 1455 | int ret; | 1500 | int ret; |
| 1456 | 1501 | ||
| 1457 | switch (BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD)) { | ||
| 1458 | case IWL_BT_COEX_TRAFFIC_LOAD_NONE: | ||
| 1459 | /* nothing */ | ||
| 1460 | break; | ||
| 1461 | case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: | ||
| 1462 | case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: | ||
| 1463 | /* avoid antenna B and MIMO */ | ||
| 1464 | if (tbl->action != IWL_MIMO2_SWITCH_SISO_A) | ||
| 1465 | tbl->action = IWL_MIMO2_SWITCH_SISO_A; | ||
| 1466 | break; | ||
| 1467 | case IWL_BT_COEX_TRAFFIC_LOAD_LOW: | ||
| 1468 | /* avoid antenna B unless MIMO */ | ||
| 1469 | if (tbl->action == IWL_MIMO2_SWITCH_SISO_B) | ||
| 1470 | tbl->action = IWL_MIMO2_SWITCH_SISO_A; | ||
| 1471 | break; | ||
| 1472 | default: | ||
| 1473 | IWL_ERR(mvm, "Invalid BT load %d", | ||
| 1474 | BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD)); | ||
| 1475 | break; | ||
| 1476 | } | ||
| 1477 | |||
| 1478 | start_action = tbl->action; | 1502 | start_action = tbl->action; |
| 1479 | while (1) { | 1503 | while (1) { |
| 1480 | lq_sta->action_counter++; | 1504 | lq_sta->action_counter++; |
| 1481 | switch (tbl->action) { | 1505 | switch (tbl->action) { |
| 1482 | case IWL_MIMO2_SWITCH_ANTENNA1: | ||
| 1483 | case IWL_MIMO2_SWITCH_ANTENNA2: | ||
| 1484 | IWL_DEBUG_RATE(mvm, "LQ: MIMO2 toggle Antennas\n"); | ||
| 1485 | |||
| 1486 | if (tx_chains_num <= 2) | ||
| 1487 | break; | ||
| 1488 | |||
| 1489 | if (window->success_ratio >= IWL_RS_GOOD_RATIO) | ||
| 1490 | break; | ||
| 1491 | |||
| 1492 | memcpy(search_tbl, tbl, sz); | ||
| 1493 | if (rs_toggle_antenna(valid_tx_ant, | ||
| 1494 | &search_tbl->current_rate, | ||
| 1495 | search_tbl)) { | ||
| 1496 | update_search_tbl_counter = 1; | ||
| 1497 | goto out; | ||
| 1498 | } | ||
| 1499 | break; | ||
| 1500 | case IWL_MIMO2_SWITCH_SISO_A: | 1506 | case IWL_MIMO2_SWITCH_SISO_A: |
| 1501 | case IWL_MIMO2_SWITCH_SISO_B: | 1507 | case IWL_MIMO2_SWITCH_SISO_B: |
| 1502 | IWL_DEBUG_RATE(mvm, "LQ: MIMO2 switch to SISO\n"); | 1508 | IWL_DEBUG_RATE(mvm, "LQ: MIMO2 switch to SISO\n"); |
| @@ -1521,11 +1527,7 @@ static int rs_move_mimo2_to_other(struct iwl_mvm *mvm, | |||
| 1521 | break; | 1527 | break; |
| 1522 | 1528 | ||
| 1523 | case IWL_MIMO2_SWITCH_GI: | 1529 | case IWL_MIMO2_SWITCH_GI: |
| 1524 | if (!tbl->is_ht40 && !(ht_cap->cap & | 1530 | if (!rs_sgi_allowed(tbl, sta)) |
| 1525 | IEEE80211_HT_CAP_SGI_20)) | ||
| 1526 | break; | ||
| 1527 | if (tbl->is_ht40 && !(ht_cap->cap & | ||
| 1528 | IEEE80211_HT_CAP_SGI_40)) | ||
| 1529 | break; | 1531 | break; |
| 1530 | 1532 | ||
| 1531 | IWL_DEBUG_RATE(mvm, "LQ: MIMO2 toggle SGI/NGI\n"); | 1533 | IWL_DEBUG_RATE(mvm, "LQ: MIMO2 toggle SGI/NGI\n"); |
| @@ -1546,16 +1548,13 @@ static int rs_move_mimo2_to_other(struct iwl_mvm *mvm, | |||
| 1546 | break; | 1548 | break; |
| 1547 | } | 1549 | } |
| 1548 | search_tbl->current_rate = | 1550 | search_tbl->current_rate = |
| 1549 | rate_n_flags_from_tbl(mvm, search_tbl, | 1551 | rate_n_flags_from_tbl(mvm, search_tbl, index); |
| 1550 | index, is_green); | ||
| 1551 | update_search_tbl_counter = 1; | 1552 | update_search_tbl_counter = 1; |
| 1552 | goto out; | 1553 | goto out; |
| 1553 | default: | 1554 | default: |
| 1554 | WARN_ON_ONCE(1); | 1555 | WARN_ON_ONCE(1); |
| 1555 | } | 1556 | } |
| 1556 | tbl->action++; | 1557 | rs_move_next_action(tbl, IWL_MIMO2_LAST_ACTION); |
| 1557 | if (tbl->action > IWL_MIMO2_SWITCH_GI) | ||
| 1558 | tbl->action = IWL_MIMO2_SWITCH_ANTENNA1; | ||
| 1559 | 1558 | ||
| 1560 | if (tbl->action == start_action) | 1559 | if (tbl->action == start_action) |
| 1561 | break; | 1560 | break; |
| @@ -1564,9 +1563,7 @@ static int rs_move_mimo2_to_other(struct iwl_mvm *mvm, | |||
| 1564 | return 0; | 1563 | return 0; |
| 1565 | out: | 1564 | out: |
| 1566 | lq_sta->search_better_tbl = 1; | 1565 | lq_sta->search_better_tbl = 1; |
| 1567 | tbl->action++; | 1566 | rs_move_next_action(tbl, IWL_MIMO2_LAST_ACTION); |
| 1568 | if (tbl->action > IWL_MIMO2_SWITCH_GI) | ||
| 1569 | tbl->action = IWL_MIMO2_SWITCH_ANTENNA1; | ||
| 1570 | if (update_search_tbl_counter) | 1567 | if (update_search_tbl_counter) |
| 1571 | search_tbl->action = tbl->action; | 1568 | search_tbl->action = tbl->action; |
| 1572 | 1569 | ||
| @@ -1660,15 +1657,16 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search) | |||
| 1660 | * setup rate table in uCode | 1657 | * setup rate table in uCode |
| 1661 | */ | 1658 | */ |
| 1662 | static void rs_update_rate_tbl(struct iwl_mvm *mvm, | 1659 | static void rs_update_rate_tbl(struct iwl_mvm *mvm, |
| 1660 | struct ieee80211_sta *sta, | ||
| 1663 | struct iwl_lq_sta *lq_sta, | 1661 | struct iwl_lq_sta *lq_sta, |
| 1664 | struct iwl_scale_tbl_info *tbl, | 1662 | struct iwl_scale_tbl_info *tbl, |
| 1665 | int index, u8 is_green) | 1663 | int index) |
| 1666 | { | 1664 | { |
| 1667 | u32 rate; | 1665 | u32 rate; |
| 1668 | 1666 | ||
| 1669 | /* Update uCode's rate table. */ | 1667 | /* Update uCode's rate table. */ |
| 1670 | rate = rate_n_flags_from_tbl(mvm, tbl, index, is_green); | 1668 | rate = rate_n_flags_from_tbl(mvm, tbl, index); |
| 1671 | rs_fill_link_cmd(mvm, lq_sta, rate); | 1669 | rs_fill_link_cmd(mvm, sta, lq_sta, rate); |
| 1672 | iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, CMD_ASYNC, false); | 1670 | iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, CMD_ASYNC, false); |
| 1673 | } | 1671 | } |
| 1674 | 1672 | ||
| @@ -1712,7 +1710,6 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, | |||
| 1712 | u8 update_lq = 0; | 1710 | u8 update_lq = 0; |
| 1713 | struct iwl_scale_tbl_info *tbl, *tbl1; | 1711 | struct iwl_scale_tbl_info *tbl, *tbl1; |
| 1714 | u16 rate_scale_index_msk = 0; | 1712 | u16 rate_scale_index_msk = 0; |
| 1715 | u8 is_green = 0; | ||
| 1716 | u8 active_tbl = 0; | 1713 | u8 active_tbl = 0; |
| 1717 | u8 done_search = 0; | 1714 | u8 done_search = 0; |
| 1718 | u16 high_low; | 1715 | u16 high_low; |
| @@ -1754,11 +1751,6 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, | |||
| 1754 | active_tbl = 1 - lq_sta->active_tbl; | 1751 | active_tbl = 1 - lq_sta->active_tbl; |
| 1755 | 1752 | ||
| 1756 | tbl = &(lq_sta->lq_info[active_tbl]); | 1753 | tbl = &(lq_sta->lq_info[active_tbl]); |
| 1757 | if (is_legacy(tbl->lq_type)) | ||
| 1758 | lq_sta->is_green = 0; | ||
| 1759 | else | ||
| 1760 | lq_sta->is_green = rs_use_green(sta); | ||
| 1761 | is_green = lq_sta->is_green; | ||
| 1762 | 1754 | ||
| 1763 | /* current tx rate */ | 1755 | /* current tx rate */ |
| 1764 | index = lq_sta->last_txrate_idx; | 1756 | index = lq_sta->last_txrate_idx; |
| @@ -1797,7 +1789,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, | |||
| 1797 | tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); | 1789 | tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); |
| 1798 | /* get "active" rate info */ | 1790 | /* get "active" rate info */ |
| 1799 | index = iwl_hwrate_to_plcp_idx(tbl->current_rate); | 1791 | index = iwl_hwrate_to_plcp_idx(tbl->current_rate); |
| 1800 | rs_update_rate_tbl(mvm, lq_sta, tbl, index, is_green); | 1792 | rs_update_rate_tbl(mvm, sta, lq_sta, tbl, index); |
| 1801 | } | 1793 | } |
| 1802 | return; | 1794 | return; |
| 1803 | } | 1795 | } |
| @@ -1978,24 +1970,24 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, | |||
| 1978 | (current_tpt > (100 * tbl->expected_tpt[low])))) | 1970 | (current_tpt > (100 * tbl->expected_tpt[low])))) |
| 1979 | scale_action = 0; | 1971 | scale_action = 0; |
| 1980 | 1972 | ||
| 1981 | if ((BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD) >= | 1973 | if ((le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) >= |
| 1982 | IWL_BT_COEX_TRAFFIC_LOAD_HIGH) && (is_mimo(tbl->lq_type))) { | 1974 | IWL_BT_COEX_TRAFFIC_LOAD_HIGH) && (is_mimo(tbl->lq_type))) { |
| 1983 | if (lq_sta->last_bt_traffic > | 1975 | if (lq_sta->last_bt_traffic > |
| 1984 | BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD)) { | 1976 | le32_to_cpu(mvm->last_bt_notif.bt_activity_grading)) { |
| 1985 | /* | 1977 | /* |
| 1986 | * don't set scale_action, don't want to scale up if | 1978 | * don't set scale_action, don't want to scale up if |
| 1987 | * the rate scale doesn't otherwise think that is a | 1979 | * the rate scale doesn't otherwise think that is a |
| 1988 | * good idea. | 1980 | * good idea. |
| 1989 | */ | 1981 | */ |
| 1990 | } else if (lq_sta->last_bt_traffic <= | 1982 | } else if (lq_sta->last_bt_traffic <= |
| 1991 | BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD)) { | 1983 | le32_to_cpu(mvm->last_bt_notif.bt_activity_grading)) { |
| 1992 | scale_action = -1; | 1984 | scale_action = -1; |
| 1993 | } | 1985 | } |
| 1994 | } | 1986 | } |
| 1995 | lq_sta->last_bt_traffic = | 1987 | lq_sta->last_bt_traffic = |
| 1996 | BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD); | 1988 | le32_to_cpu(mvm->last_bt_notif.bt_activity_grading); |
| 1997 | 1989 | ||
| 1998 | if ((BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD) >= | 1990 | if ((le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) >= |
| 1999 | IWL_BT_COEX_TRAFFIC_LOAD_HIGH) && is_mimo(tbl->lq_type)) { | 1991 | IWL_BT_COEX_TRAFFIC_LOAD_HIGH) && is_mimo(tbl->lq_type)) { |
| 2000 | /* search for a new modulation */ | 1992 | /* search for a new modulation */ |
| 2001 | rs_stay_in_table(lq_sta, true); | 1993 | rs_stay_in_table(lq_sta, true); |
| @@ -2032,7 +2024,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, | |||
| 2032 | lq_update: | 2024 | lq_update: |
| 2033 | /* Replace uCode's rate table for the destination station. */ | 2025 | /* Replace uCode's rate table for the destination station. */ |
| 2034 | if (update_lq) | 2026 | if (update_lq) |
| 2035 | rs_update_rate_tbl(mvm, lq_sta, tbl, index, is_green); | 2027 | rs_update_rate_tbl(mvm, sta, lq_sta, tbl, index); |
| 2036 | 2028 | ||
| 2037 | rs_stay_in_table(lq_sta, false); | 2029 | rs_stay_in_table(lq_sta, false); |
| 2038 | 2030 | ||
| @@ -2071,7 +2063,7 @@ lq_update: | |||
| 2071 | IWL_DEBUG_RATE(mvm, | 2063 | IWL_DEBUG_RATE(mvm, |
| 2072 | "Switch current mcs: %X index: %d\n", | 2064 | "Switch current mcs: %X index: %d\n", |
| 2073 | tbl->current_rate, index); | 2065 | tbl->current_rate, index); |
| 2074 | rs_fill_link_cmd(mvm, lq_sta, tbl->current_rate); | 2066 | rs_fill_link_cmd(mvm, sta, lq_sta, tbl->current_rate); |
| 2075 | iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, CMD_ASYNC, false); | 2067 | iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, CMD_ASYNC, false); |
| 2076 | } else { | 2068 | } else { |
| 2077 | done_search = 1; | 2069 | done_search = 1; |
| @@ -2113,7 +2105,7 @@ lq_update: | |||
| 2113 | } | 2105 | } |
| 2114 | 2106 | ||
| 2115 | out: | 2107 | out: |
| 2116 | tbl->current_rate = rate_n_flags_from_tbl(mvm, tbl, index, is_green); | 2108 | tbl->current_rate = rate_n_flags_from_tbl(mvm, tbl, index); |
| 2117 | lq_sta->last_txrate_idx = index; | 2109 | lq_sta->last_txrate_idx = index; |
| 2118 | } | 2110 | } |
| 2119 | 2111 | ||
| @@ -2140,7 +2132,6 @@ static void rs_initialize_lq(struct iwl_mvm *mvm, | |||
| 2140 | int rate_idx; | 2132 | int rate_idx; |
| 2141 | int i; | 2133 | int i; |
| 2142 | u32 rate; | 2134 | u32 rate; |
| 2143 | u8 use_green = rs_use_green(sta); | ||
| 2144 | u8 active_tbl = 0; | 2135 | u8 active_tbl = 0; |
| 2145 | u8 valid_tx_ant; | 2136 | u8 valid_tx_ant; |
| 2146 | 2137 | ||
| @@ -2172,10 +2163,10 @@ static void rs_initialize_lq(struct iwl_mvm *mvm, | |||
| 2172 | if (!rs_is_valid_ant(valid_tx_ant, tbl->ant_type)) | 2163 | if (!rs_is_valid_ant(valid_tx_ant, tbl->ant_type)) |
| 2173 | rs_toggle_antenna(valid_tx_ant, &rate, tbl); | 2164 | rs_toggle_antenna(valid_tx_ant, &rate, tbl); |
| 2174 | 2165 | ||
| 2175 | rate = rate_n_flags_from_tbl(mvm, tbl, rate_idx, use_green); | 2166 | rate = rate_n_flags_from_tbl(mvm, tbl, rate_idx); |
| 2176 | tbl->current_rate = rate; | 2167 | tbl->current_rate = rate; |
| 2177 | rs_set_expected_tpt_table(lq_sta, tbl); | 2168 | rs_set_expected_tpt_table(lq_sta, tbl); |
| 2178 | rs_fill_link_cmd(NULL, lq_sta, rate); | 2169 | rs_fill_link_cmd(NULL, NULL, lq_sta, rate); |
| 2179 | /* TODO restore station should remember the lq cmd */ | 2170 | /* TODO restore station should remember the lq cmd */ |
| 2180 | iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, CMD_SYNC, true); | 2171 | iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, CMD_SYNC, true); |
| 2181 | } | 2172 | } |
| @@ -2190,7 +2181,6 @@ static void rs_get_rate(void *mvm_r, struct ieee80211_sta *sta, void *mvm_sta, | |||
| 2190 | struct iwl_mvm *mvm __maybe_unused = IWL_OP_MODE_GET_MVM(op_mode); | 2181 | struct iwl_mvm *mvm __maybe_unused = IWL_OP_MODE_GET_MVM(op_mode); |
| 2191 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 2182 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
| 2192 | struct iwl_lq_sta *lq_sta = mvm_sta; | 2183 | struct iwl_lq_sta *lq_sta = mvm_sta; |
| 2193 | int rate_idx; | ||
| 2194 | 2184 | ||
| 2195 | IWL_DEBUG_RATE_LIMIT(mvm, "rate scale calculate new rate for skb\n"); | 2185 | IWL_DEBUG_RATE_LIMIT(mvm, "rate scale calculate new rate for skb\n"); |
| 2196 | 2186 | ||
| @@ -2215,36 +2205,9 @@ static void rs_get_rate(void *mvm_r, struct ieee80211_sta *sta, void *mvm_sta, | |||
| 2215 | if (rate_control_send_low(sta, mvm_sta, txrc)) | 2205 | if (rate_control_send_low(sta, mvm_sta, txrc)) |
| 2216 | return; | 2206 | return; |
| 2217 | 2207 | ||
| 2218 | rate_idx = lq_sta->last_txrate_idx; | 2208 | iwl_mvm_hwrate_to_tx_rate(lq_sta->last_rate_n_flags, |
| 2219 | 2209 | info->band, &info->control.rates[0]); | |
| 2220 | if (lq_sta->last_rate_n_flags & RATE_MCS_HT_MSK) { | 2210 | |
| 2221 | rate_idx -= IWL_FIRST_OFDM_RATE; | ||
| 2222 | /* 6M and 9M shared same MCS index */ | ||
| 2223 | rate_idx = (rate_idx > 0) ? (rate_idx - 1) : 0; | ||
| 2224 | WARN_ON_ONCE(rs_extract_rate(lq_sta->last_rate_n_flags) >= | ||
| 2225 | IWL_RATE_MIMO3_6M_PLCP); | ||
| 2226 | if (rs_extract_rate(lq_sta->last_rate_n_flags) >= | ||
| 2227 | IWL_RATE_MIMO2_6M_PLCP) | ||
| 2228 | rate_idx = rate_idx + MCS_INDEX_PER_STREAM; | ||
| 2229 | info->control.rates[0].flags = IEEE80211_TX_RC_MCS; | ||
| 2230 | if (lq_sta->last_rate_n_flags & RATE_MCS_SGI_MSK) | ||
| 2231 | info->control.rates[0].flags |= IEEE80211_TX_RC_SHORT_GI; | ||
| 2232 | if (lq_sta->last_rate_n_flags & RATE_MCS_CHAN_WIDTH_40) /* TODO */ | ||
| 2233 | info->control.rates[0].flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; | ||
| 2234 | if (lq_sta->last_rate_n_flags & RATE_HT_MCS_GF_MSK) | ||
| 2235 | info->control.rates[0].flags |= IEEE80211_TX_RC_GREEN_FIELD; | ||
| 2236 | } else { | ||
| 2237 | /* Check for invalid rates */ | ||
| 2238 | if ((rate_idx < 0) || (rate_idx >= IWL_RATE_COUNT_LEGACY) || | ||
| 2239 | ((sband->band == IEEE80211_BAND_5GHZ) && | ||
| 2240 | (rate_idx < IWL_FIRST_OFDM_RATE))) | ||
| 2241 | rate_idx = rate_lowest_index(sband, sta); | ||
| 2242 | /* On valid 5 GHz rate, adjust index */ | ||
| 2243 | else if (sband->band == IEEE80211_BAND_5GHZ) | ||
| 2244 | rate_idx -= IWL_FIRST_OFDM_RATE; | ||
| 2245 | info->control.rates[0].flags = 0; | ||
| 2246 | } | ||
| 2247 | info->control.rates[0].idx = rate_idx; | ||
| 2248 | info->control.rates[0].count = 1; | 2211 | info->control.rates[0].count = 1; |
| 2249 | } | 2212 | } |
| 2250 | 2213 | ||
| @@ -2261,6 +2224,24 @@ static void *rs_alloc_sta(void *mvm_rate, struct ieee80211_sta *sta, | |||
| 2261 | return &sta_priv->lq_sta; | 2224 | return &sta_priv->lq_sta; |
| 2262 | } | 2225 | } |
| 2263 | 2226 | ||
| 2227 | static int rs_vht_highest_rx_mcs_index(struct ieee80211_sta_vht_cap *vht_cap, | ||
| 2228 | int nss) | ||
| 2229 | { | ||
| 2230 | u16 rx_mcs = le16_to_cpu(vht_cap->vht_mcs.rx_mcs_map) & | ||
| 2231 | (0x3 << (2 * (nss - 1))); | ||
| 2232 | rx_mcs >>= (2 * (nss - 1)); | ||
| 2233 | |||
| 2234 | if (rx_mcs == IEEE80211_VHT_MCS_SUPPORT_0_7) | ||
| 2235 | return IWL_RATE_MCS_7_INDEX; | ||
| 2236 | else if (rx_mcs == IEEE80211_VHT_MCS_SUPPORT_0_8) | ||
| 2237 | return IWL_RATE_MCS_8_INDEX; | ||
| 2238 | else if (rx_mcs == IEEE80211_VHT_MCS_SUPPORT_0_9) | ||
| 2239 | return IWL_RATE_MCS_9_INDEX; | ||
| 2240 | |||
| 2241 | WARN_ON_ONCE(rx_mcs != IEEE80211_VHT_MCS_NOT_SUPPORTED); | ||
| 2242 | return -1; | ||
| 2243 | } | ||
| 2244 | |||
| 2264 | /* | 2245 | /* |
| 2265 | * Called after adding a new station to initialize rate scaling | 2246 | * Called after adding a new station to initialize rate scaling |
| 2266 | */ | 2247 | */ |
| @@ -2270,6 +2251,7 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
| 2270 | int i, j; | 2251 | int i, j; |
| 2271 | struct ieee80211_hw *hw = mvm->hw; | 2252 | struct ieee80211_hw *hw = mvm->hw; |
| 2272 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; | 2253 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; |
| 2254 | struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap; | ||
| 2273 | struct iwl_mvm_sta *sta_priv; | 2255 | struct iwl_mvm_sta *sta_priv; |
| 2274 | struct iwl_lq_sta *lq_sta; | 2256 | struct iwl_lq_sta *lq_sta; |
| 2275 | struct ieee80211_supported_band *sband; | 2257 | struct ieee80211_supported_band *sband; |
| @@ -2298,7 +2280,6 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
| 2298 | 2280 | ||
| 2299 | lq_sta->max_rate_idx = -1; | 2281 | lq_sta->max_rate_idx = -1; |
| 2300 | lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX; | 2282 | lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX; |
| 2301 | lq_sta->is_green = rs_use_green(sta); | ||
| 2302 | lq_sta->band = sband->band; | 2283 | lq_sta->band = sband->band; |
| 2303 | /* | 2284 | /* |
| 2304 | * active legacy rates as per supported rates bitmap | 2285 | * active legacy rates as per supported rates bitmap |
| @@ -2308,25 +2289,54 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
| 2308 | for_each_set_bit(i, &supp, BITS_PER_LONG) | 2289 | for_each_set_bit(i, &supp, BITS_PER_LONG) |
| 2309 | lq_sta->active_legacy_rate |= BIT(sband->bitrates[i].hw_value); | 2290 | lq_sta->active_legacy_rate |= BIT(sband->bitrates[i].hw_value); |
| 2310 | 2291 | ||
| 2311 | /* | 2292 | /* TODO: should probably account for rx_highest for both HT/VHT */ |
| 2312 | * active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3), | 2293 | if (!vht_cap || !vht_cap->vht_supported) { |
| 2313 | * supp_rates[] does not; shift to convert format, force 9 MBits off. | 2294 | /* active_siso_rate mask includes 9 MBits (bit 5), |
| 2314 | */ | 2295 | * and CCK (bits 0-3), supp_rates[] does not; |
| 2315 | lq_sta->active_siso_rate = ht_cap->mcs.rx_mask[0] << 1; | 2296 | * shift to convert format, force 9 MBits off. |
| 2316 | lq_sta->active_siso_rate |= ht_cap->mcs.rx_mask[0] & 0x1; | 2297 | */ |
| 2317 | lq_sta->active_siso_rate &= ~((u16)0x2); | 2298 | lq_sta->active_siso_rate = ht_cap->mcs.rx_mask[0] << 1; |
| 2318 | lq_sta->active_siso_rate <<= IWL_FIRST_OFDM_RATE; | 2299 | lq_sta->active_siso_rate |= ht_cap->mcs.rx_mask[0] & 0x1; |
| 2300 | lq_sta->active_siso_rate &= ~((u16)0x2); | ||
| 2301 | lq_sta->active_siso_rate <<= IWL_FIRST_OFDM_RATE; | ||
| 2302 | |||
| 2303 | /* Same here */ | ||
| 2304 | lq_sta->active_mimo2_rate = ht_cap->mcs.rx_mask[1] << 1; | ||
| 2305 | lq_sta->active_mimo2_rate |= ht_cap->mcs.rx_mask[1] & 0x1; | ||
| 2306 | lq_sta->active_mimo2_rate &= ~((u16)0x2); | ||
| 2307 | lq_sta->active_mimo2_rate <<= IWL_FIRST_OFDM_RATE; | ||
| 2308 | |||
| 2309 | lq_sta->is_vht = false; | ||
| 2310 | } else { | ||
| 2311 | int highest_mcs = rs_vht_highest_rx_mcs_index(vht_cap, 1); | ||
| 2312 | if (highest_mcs >= IWL_RATE_MCS_0_INDEX) { | ||
| 2313 | for (i = IWL_RATE_MCS_0_INDEX; i <= highest_mcs; i++) { | ||
| 2314 | if (i == IWL_RATE_9M_INDEX) | ||
| 2315 | continue; | ||
| 2316 | |||
| 2317 | lq_sta->active_siso_rate |= BIT(i); | ||
| 2318 | } | ||
| 2319 | } | ||
| 2320 | |||
| 2321 | highest_mcs = rs_vht_highest_rx_mcs_index(vht_cap, 2); | ||
| 2322 | if (highest_mcs >= IWL_RATE_MCS_0_INDEX) { | ||
| 2323 | for (i = IWL_RATE_MCS_0_INDEX; i <= highest_mcs; i++) { | ||
| 2324 | if (i == IWL_RATE_9M_INDEX) | ||
| 2325 | continue; | ||
| 2319 | 2326 | ||
| 2320 | /* Same here */ | 2327 | lq_sta->active_mimo2_rate |= BIT(i); |
| 2321 | lq_sta->active_mimo2_rate = ht_cap->mcs.rx_mask[1] << 1; | 2328 | } |
| 2322 | lq_sta->active_mimo2_rate |= ht_cap->mcs.rx_mask[1] & 0x1; | 2329 | } |
| 2323 | lq_sta->active_mimo2_rate &= ~((u16)0x2); | 2330 | |
| 2324 | lq_sta->active_mimo2_rate <<= IWL_FIRST_OFDM_RATE; | 2331 | /* TODO: avoid MCS9 in 20Mhz which isn't valid for 11ac */ |
| 2332 | lq_sta->is_vht = true; | ||
| 2333 | } | ||
| 2325 | 2334 | ||
| 2326 | IWL_DEBUG_RATE(mvm, | 2335 | IWL_DEBUG_RATE(mvm, |
| 2327 | "SISO-RATE=%X MIMO2-RATE=%X\n", | 2336 | "SISO-RATE=%X MIMO2-RATE=%X VHT=%d\n", |
| 2328 | lq_sta->active_siso_rate, | 2337 | lq_sta->active_siso_rate, |
| 2329 | lq_sta->active_mimo2_rate); | 2338 | lq_sta->active_mimo2_rate, |
| 2339 | lq_sta->is_vht); | ||
| 2330 | 2340 | ||
| 2331 | /* These values will be overridden later */ | 2341 | /* These values will be overridden later */ |
| 2332 | lq_sta->lq.single_stream_ant_msk = | 2342 | lq_sta->lq.single_stream_ant_msk = |
| @@ -2358,6 +2368,7 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
| 2358 | } | 2368 | } |
| 2359 | 2369 | ||
| 2360 | static void rs_fill_link_cmd(struct iwl_mvm *mvm, | 2370 | static void rs_fill_link_cmd(struct iwl_mvm *mvm, |
| 2371 | struct ieee80211_sta *sta, | ||
| 2361 | struct iwl_lq_sta *lq_sta, u32 new_rate) | 2372 | struct iwl_lq_sta *lq_sta, u32 new_rate) |
| 2362 | { | 2373 | { |
| 2363 | struct iwl_scale_tbl_info tbl_type; | 2374 | struct iwl_scale_tbl_info tbl_type; |
| @@ -2429,7 +2440,6 @@ static void rs_fill_link_cmd(struct iwl_mvm *mvm, | |||
| 2429 | rs_get_tbl_info_from_mcs(new_rate, lq_sta->band, &tbl_type, | 2440 | rs_get_tbl_info_from_mcs(new_rate, lq_sta->band, &tbl_type, |
| 2430 | &rate_idx); | 2441 | &rate_idx); |
| 2431 | 2442 | ||
| 2432 | |||
| 2433 | /* Indicate to uCode which entries might be MIMO. | 2443 | /* Indicate to uCode which entries might be MIMO. |
| 2434 | * If initial rate was MIMO, this will finally end up | 2444 | * If initial rate was MIMO, this will finally end up |
| 2435 | * as (IWL_HT_NUMBER_TRY * 2), after 2nd pass, otherwise 0. */ | 2445 | * as (IWL_HT_NUMBER_TRY * 2), after 2nd pass, otherwise 0. */ |
| @@ -2455,7 +2465,9 @@ static void rs_fill_link_cmd(struct iwl_mvm *mvm, | |||
| 2455 | } | 2465 | } |
| 2456 | 2466 | ||
| 2457 | /* Don't allow HT rates after next pass. | 2467 | /* Don't allow HT rates after next pass. |
| 2458 | * rs_get_lower_rate() will change type to LQ_A or LQ_G. */ | 2468 | * rs_get_lower_rate() will change type to LQ_LEGACY_A |
| 2469 | * or LQ_LEGACY_G. | ||
| 2470 | */ | ||
| 2459 | use_ht_possible = 0; | 2471 | use_ht_possible = 0; |
| 2460 | 2472 | ||
| 2461 | /* Override next rate if needed for debug purposes */ | 2473 | /* Override next rate if needed for debug purposes */ |
| @@ -2474,12 +2486,9 @@ static void rs_fill_link_cmd(struct iwl_mvm *mvm, | |||
| 2474 | lq_cmd->agg_time_limit = | 2486 | lq_cmd->agg_time_limit = |
| 2475 | cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); | 2487 | cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); |
| 2476 | 2488 | ||
| 2477 | /* | 2489 | if (sta) |
| 2478 | * overwrite if needed, pass aggregation time limit | 2490 | lq_cmd->agg_time_limit = |
| 2479 | * to uCode in uSec - This is racy - but heh, at least it helps... | 2491 | cpu_to_le16(iwl_mvm_bt_coex_agg_time_limit(mvm, sta)); |
| 2480 | */ | ||
| 2481 | if (mvm && BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD) >= 2) | ||
| 2482 | lq_cmd->agg_time_limit = cpu_to_le16(1200); | ||
| 2483 | } | 2492 | } |
| 2484 | 2493 | ||
| 2485 | static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) | 2494 | static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) |
| @@ -2586,16 +2595,18 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, | |||
| 2586 | (iwl_fw_valid_tx_ant(mvm->fw) & ANT_B) ? "ANT_B," : "", | 2595 | (iwl_fw_valid_tx_ant(mvm->fw) & ANT_B) ? "ANT_B," : "", |
| 2587 | (iwl_fw_valid_tx_ant(mvm->fw) & ANT_C) ? "ANT_C" : ""); | 2596 | (iwl_fw_valid_tx_ant(mvm->fw) & ANT_C) ? "ANT_C" : ""); |
| 2588 | desc += sprintf(buff+desc, "lq type %s\n", | 2597 | desc += sprintf(buff+desc, "lq type %s\n", |
| 2589 | (is_legacy(tbl->lq_type)) ? "legacy" : "HT"); | 2598 | (is_legacy(tbl->lq_type)) ? "legacy" : |
| 2590 | if (is_Ht(tbl->lq_type)) { | 2599 | is_vht(tbl->lq_type) ? "VHT" : "HT"); |
| 2600 | if (is_ht(tbl->lq_type)) { | ||
| 2591 | desc += sprintf(buff+desc, " %s", | 2601 | desc += sprintf(buff+desc, " %s", |
| 2592 | (is_siso(tbl->lq_type)) ? "SISO" : "MIMO2"); | 2602 | (is_siso(tbl->lq_type)) ? "SISO" : "MIMO2"); |
| 2593 | desc += sprintf(buff+desc, " %s", | 2603 | desc += sprintf(buff+desc, " %s", |
| 2594 | (tbl->is_ht40) ? "40MHz" : "20MHz"); | 2604 | (is_ht20(tbl)) ? "20MHz" : |
| 2595 | desc += sprintf(buff+desc, " %s %s %s\n", | 2605 | (is_ht40(tbl)) ? "40MHz" : |
| 2606 | (is_ht80(tbl)) ? "80Mhz" : "BAD BW"); | ||
| 2607 | desc += sprintf(buff+desc, " %s %s\n", | ||
| 2596 | (tbl->is_SGI) ? "SGI" : "", | 2608 | (tbl->is_SGI) ? "SGI" : "", |
| 2597 | (lq_sta->is_green) ? "GF enabled" : "", | 2609 | (lq_sta->is_agg) ? "AGG on" : ""); |
| 2598 | (lq_sta->is_agg) ? "AGG on" : ""); | ||
| 2599 | } | 2610 | } |
| 2600 | desc += sprintf(buff+desc, "last tx rate=0x%X\n", | 2611 | desc += sprintf(buff+desc, "last tx rate=0x%X\n", |
| 2601 | lq_sta->last_rate_n_flags); | 2612 | lq_sta->last_rate_n_flags); |
| @@ -2653,7 +2664,7 @@ static ssize_t rs_sta_dbgfs_stats_table_read(struct file *file, | |||
| 2653 | int desc = 0; | 2664 | int desc = 0; |
| 2654 | int i, j; | 2665 | int i, j; |
| 2655 | ssize_t ret; | 2666 | ssize_t ret; |
| 2656 | 2667 | struct iwl_scale_tbl_info *tbl; | |
| 2657 | struct iwl_lq_sta *lq_sta = file->private_data; | 2668 | struct iwl_lq_sta *lq_sta = file->private_data; |
| 2658 | 2669 | ||
| 2659 | buff = kmalloc(1024, GFP_KERNEL); | 2670 | buff = kmalloc(1024, GFP_KERNEL); |
| @@ -2661,21 +2672,23 @@ static ssize_t rs_sta_dbgfs_stats_table_read(struct file *file, | |||
| 2661 | return -ENOMEM; | 2672 | return -ENOMEM; |
| 2662 | 2673 | ||
| 2663 | for (i = 0; i < LQ_SIZE; i++) { | 2674 | for (i = 0; i < LQ_SIZE; i++) { |
| 2675 | tbl = &(lq_sta->lq_info[i]); | ||
| 2664 | desc += sprintf(buff+desc, | 2676 | desc += sprintf(buff+desc, |
| 2665 | "%s type=%d SGI=%d HT40=%d DUP=0 GF=%d\n" | 2677 | "%s type=%d SGI=%d BW=%s DUP=0\n" |
| 2666 | "rate=0x%X\n", | 2678 | "rate=0x%X\n", |
| 2667 | lq_sta->active_tbl == i ? "*" : "x", | 2679 | lq_sta->active_tbl == i ? "*" : "x", |
| 2668 | lq_sta->lq_info[i].lq_type, | 2680 | tbl->lq_type, |
| 2669 | lq_sta->lq_info[i].is_SGI, | 2681 | tbl->is_SGI, |
| 2670 | lq_sta->lq_info[i].is_ht40, | 2682 | is_ht20(tbl) ? "20Mhz" : |
| 2671 | lq_sta->is_green, | 2683 | is_ht40(tbl) ? "40Mhz" : |
| 2672 | lq_sta->lq_info[i].current_rate); | 2684 | is_ht80(tbl) ? "80Mhz" : "ERR", |
| 2685 | tbl->current_rate); | ||
| 2673 | for (j = 0; j < IWL_RATE_COUNT; j++) { | 2686 | for (j = 0; j < IWL_RATE_COUNT; j++) { |
| 2674 | desc += sprintf(buff+desc, | 2687 | desc += sprintf(buff+desc, |
| 2675 | "counter=%d success=%d %%=%d\n", | 2688 | "counter=%d success=%d %%=%d\n", |
| 2676 | lq_sta->lq_info[i].win[j].counter, | 2689 | tbl->win[j].counter, |
| 2677 | lq_sta->lq_info[i].win[j].success_counter, | 2690 | tbl->win[j].success_counter, |
| 2678 | lq_sta->lq_info[i].win[j].success_ratio); | 2691 | tbl->win[j].success_ratio); |
| 2679 | } | 2692 | } |
| 2680 | } | 2693 | } |
| 2681 | ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc); | 2694 | ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.h b/drivers/net/wireless/iwlwifi/mvm/rs.h index 465d40ee176f..5d5344f7070b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.h +++ b/drivers/net/wireless/iwlwifi/mvm/rs.h | |||
| @@ -35,9 +35,11 @@ | |||
| 35 | #include "iwl-trans.h" | 35 | #include "iwl-trans.h" |
| 36 | 36 | ||
| 37 | struct iwl_rs_rate_info { | 37 | struct iwl_rs_rate_info { |
| 38 | u8 plcp; /* uCode API: IWL_RATE_6M_PLCP, etc. */ | 38 | u8 plcp; /* uCode API: IWL_RATE_6M_PLCP, etc. */ |
| 39 | u8 plcp_siso; /* uCode API: IWL_RATE_SISO_6M_PLCP, etc. */ | 39 | u8 plcp_ht_siso; /* uCode API: IWL_RATE_SISO_6M_PLCP, etc. */ |
| 40 | u8 plcp_mimo2; /* uCode API: IWL_RATE_MIMO2_6M_PLCP, etc. */ | 40 | u8 plcp_ht_mimo2; /* uCode API: IWL_RATE_MIMO2_6M_PLCP, etc. */ |
| 41 | u8 plcp_vht_siso; | ||
| 42 | u8 plcp_vht_mimo2; | ||
| 41 | u8 prev_rs; /* previous rate used in rs algo */ | 43 | u8 prev_rs; /* previous rate used in rs algo */ |
| 42 | u8 next_rs; /* next rate used in rs algo */ | 44 | u8 next_rs; /* next rate used in rs algo */ |
| 43 | }; | 45 | }; |
| @@ -83,35 +85,52 @@ enum { | |||
| 83 | #define IWL_RATE_11M_MASK (1 << IWL_RATE_11M_INDEX) | 85 | #define IWL_RATE_11M_MASK (1 << IWL_RATE_11M_INDEX) |
| 84 | 86 | ||
| 85 | 87 | ||
| 86 | /* uCode API values for OFDM high-throughput (HT) bit rates */ | 88 | /* uCode API values for HT/VHT bit rates */ |
| 87 | enum { | 89 | enum { |
| 88 | IWL_RATE_SISO_6M_PLCP = 0, | 90 | IWL_RATE_HT_SISO_MCS_0_PLCP = 0, |
| 89 | IWL_RATE_SISO_12M_PLCP = 1, | 91 | IWL_RATE_HT_SISO_MCS_1_PLCP = 1, |
| 90 | IWL_RATE_SISO_18M_PLCP = 2, | 92 | IWL_RATE_HT_SISO_MCS_2_PLCP = 2, |
| 91 | IWL_RATE_SISO_24M_PLCP = 3, | 93 | IWL_RATE_HT_SISO_MCS_3_PLCP = 3, |
| 92 | IWL_RATE_SISO_36M_PLCP = 4, | 94 | IWL_RATE_HT_SISO_MCS_4_PLCP = 4, |
| 93 | IWL_RATE_SISO_48M_PLCP = 5, | 95 | IWL_RATE_HT_SISO_MCS_5_PLCP = 5, |
| 94 | IWL_RATE_SISO_54M_PLCP = 6, | 96 | IWL_RATE_HT_SISO_MCS_6_PLCP = 6, |
| 95 | IWL_RATE_SISO_60M_PLCP = 7, | 97 | IWL_RATE_HT_SISO_MCS_7_PLCP = 7, |
| 96 | IWL_RATE_MIMO2_6M_PLCP = 0x8, | 98 | IWL_RATE_HT_MIMO2_MCS_0_PLCP = 0x8, |
| 97 | IWL_RATE_MIMO2_12M_PLCP = 0x9, | 99 | IWL_RATE_HT_MIMO2_MCS_1_PLCP = 0x9, |
| 98 | IWL_RATE_MIMO2_18M_PLCP = 0xa, | 100 | IWL_RATE_HT_MIMO2_MCS_2_PLCP = 0xA, |
| 99 | IWL_RATE_MIMO2_24M_PLCP = 0xb, | 101 | IWL_RATE_HT_MIMO2_MCS_3_PLCP = 0xB, |
| 100 | IWL_RATE_MIMO2_36M_PLCP = 0xc, | 102 | IWL_RATE_HT_MIMO2_MCS_4_PLCP = 0xC, |
| 101 | IWL_RATE_MIMO2_48M_PLCP = 0xd, | 103 | IWL_RATE_HT_MIMO2_MCS_5_PLCP = 0xD, |
| 102 | IWL_RATE_MIMO2_54M_PLCP = 0xe, | 104 | IWL_RATE_HT_MIMO2_MCS_6_PLCP = 0xE, |
| 103 | IWL_RATE_MIMO2_60M_PLCP = 0xf, | 105 | IWL_RATE_HT_MIMO2_MCS_7_PLCP = 0xF, |
| 104 | IWL_RATE_MIMO3_6M_PLCP = 0x10, | 106 | IWL_RATE_VHT_SISO_MCS_0_PLCP = 0, |
| 105 | IWL_RATE_MIMO3_12M_PLCP = 0x11, | 107 | IWL_RATE_VHT_SISO_MCS_1_PLCP = 1, |
| 106 | IWL_RATE_MIMO3_18M_PLCP = 0x12, | 108 | IWL_RATE_VHT_SISO_MCS_2_PLCP = 2, |
| 107 | IWL_RATE_MIMO3_24M_PLCP = 0x13, | 109 | IWL_RATE_VHT_SISO_MCS_3_PLCP = 3, |
| 108 | IWL_RATE_MIMO3_36M_PLCP = 0x14, | 110 | IWL_RATE_VHT_SISO_MCS_4_PLCP = 4, |
| 109 | IWL_RATE_MIMO3_48M_PLCP = 0x15, | 111 | IWL_RATE_VHT_SISO_MCS_5_PLCP = 5, |
| 110 | IWL_RATE_MIMO3_54M_PLCP = 0x16, | 112 | IWL_RATE_VHT_SISO_MCS_6_PLCP = 6, |
| 111 | IWL_RATE_MIMO3_60M_PLCP = 0x17, | 113 | IWL_RATE_VHT_SISO_MCS_7_PLCP = 7, |
| 112 | IWL_RATE_SISO_INVM_PLCP, | 114 | IWL_RATE_VHT_SISO_MCS_8_PLCP = 8, |
| 113 | IWL_RATE_MIMO2_INVM_PLCP = IWL_RATE_SISO_INVM_PLCP, | 115 | IWL_RATE_VHT_SISO_MCS_9_PLCP = 9, |
| 114 | IWL_RATE_MIMO3_INVM_PLCP = IWL_RATE_SISO_INVM_PLCP, | 116 | IWL_RATE_VHT_MIMO2_MCS_0_PLCP = 0x10, |
| 117 | IWL_RATE_VHT_MIMO2_MCS_1_PLCP = 0x11, | ||
| 118 | IWL_RATE_VHT_MIMO2_MCS_2_PLCP = 0x12, | ||
| 119 | IWL_RATE_VHT_MIMO2_MCS_3_PLCP = 0x13, | ||
| 120 | IWL_RATE_VHT_MIMO2_MCS_4_PLCP = 0x14, | ||
| 121 | IWL_RATE_VHT_MIMO2_MCS_5_PLCP = 0x15, | ||
| 122 | IWL_RATE_VHT_MIMO2_MCS_6_PLCP = 0x16, | ||
| 123 | IWL_RATE_VHT_MIMO2_MCS_7_PLCP = 0x17, | ||
| 124 | IWL_RATE_VHT_MIMO2_MCS_8_PLCP = 0x18, | ||
| 125 | IWL_RATE_VHT_MIMO2_MCS_9_PLCP = 0x19, | ||
| 126 | IWL_RATE_HT_SISO_MCS_INV_PLCP, | ||
| 127 | IWL_RATE_HT_MIMO2_MCS_INV_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP, | ||
| 128 | IWL_RATE_VHT_SISO_MCS_INV_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP, | ||
| 129 | IWL_RATE_VHT_MIMO2_MCS_INV_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP, | ||
| 130 | IWL_RATE_HT_SISO_MCS_8_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP, | ||
| 131 | IWL_RATE_HT_SISO_MCS_9_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP, | ||
| 132 | IWL_RATE_HT_MIMO2_MCS_8_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP, | ||
| 133 | IWL_RATE_HT_MIMO2_MCS_9_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP, | ||
| 115 | }; | 134 | }; |
| 116 | 135 | ||
| 117 | #define IWL_RATES_MASK ((1 << IWL_RATE_COUNT) - 1) | 136 | #define IWL_RATES_MASK ((1 << IWL_RATE_COUNT) - 1) |
| @@ -139,25 +158,33 @@ enum { | |||
| 139 | #define IWL_RATE_DECREASE_TH 1920 /* 15% */ | 158 | #define IWL_RATE_DECREASE_TH 1920 /* 15% */ |
| 140 | 159 | ||
| 141 | /* possible actions when in legacy mode */ | 160 | /* possible actions when in legacy mode */ |
| 142 | #define IWL_LEGACY_SWITCH_ANTENNA1 0 | 161 | enum { |
| 143 | #define IWL_LEGACY_SWITCH_ANTENNA2 1 | 162 | IWL_LEGACY_SWITCH_ANTENNA, |
| 144 | #define IWL_LEGACY_SWITCH_SISO 2 | 163 | IWL_LEGACY_SWITCH_SISO, |
| 145 | #define IWL_LEGACY_SWITCH_MIMO2 3 | 164 | IWL_LEGACY_SWITCH_MIMO2, |
| 165 | IWL_LEGACY_FIRST_ACTION = IWL_LEGACY_SWITCH_ANTENNA, | ||
| 166 | IWL_LEGACY_LAST_ACTION = IWL_LEGACY_SWITCH_MIMO2, | ||
| 167 | }; | ||
| 146 | 168 | ||
| 147 | /* possible actions when in siso mode */ | 169 | /* possible actions when in siso mode */ |
| 148 | #define IWL_SISO_SWITCH_ANTENNA1 0 | 170 | enum { |
| 149 | #define IWL_SISO_SWITCH_ANTENNA2 1 | 171 | IWL_SISO_SWITCH_ANTENNA, |
| 150 | #define IWL_SISO_SWITCH_MIMO2 2 | 172 | IWL_SISO_SWITCH_MIMO2, |
| 151 | #define IWL_SISO_SWITCH_GI 3 | 173 | IWL_SISO_SWITCH_GI, |
| 174 | IWL_SISO_FIRST_ACTION = IWL_SISO_SWITCH_ANTENNA, | ||
| 175 | IWL_SISO_LAST_ACTION = IWL_SISO_SWITCH_GI, | ||
| 176 | }; | ||
| 152 | 177 | ||
| 153 | /* possible actions when in mimo mode */ | 178 | /* possible actions when in mimo mode */ |
| 154 | #define IWL_MIMO2_SWITCH_ANTENNA1 0 | 179 | enum { |
| 155 | #define IWL_MIMO2_SWITCH_ANTENNA2 1 | 180 | IWL_MIMO2_SWITCH_SISO_A, |
| 156 | #define IWL_MIMO2_SWITCH_SISO_A 2 | 181 | IWL_MIMO2_SWITCH_SISO_B, |
| 157 | #define IWL_MIMO2_SWITCH_SISO_B 3 | 182 | IWL_MIMO2_SWITCH_GI, |
| 158 | #define IWL_MIMO2_SWITCH_GI 4 | 183 | IWL_MIMO2_FIRST_ACTION = IWL_MIMO2_SWITCH_SISO_A, |
| 184 | IWL_MIMO2_LAST_ACTION = IWL_MIMO2_SWITCH_GI, | ||
| 185 | }; | ||
| 159 | 186 | ||
| 160 | #define IWL_MAX_SEARCH IWL_MIMO2_SWITCH_GI | 187 | #define IWL_MAX_SEARCH IWL_MIMO2_LAST_ACTION |
| 161 | 188 | ||
| 162 | #define IWL_ACTION_LIMIT 3 /* # possible actions */ | 189 | #define IWL_ACTION_LIMIT 3 /* # possible actions */ |
| 163 | 190 | ||
| @@ -188,20 +215,31 @@ enum { | |||
| 188 | 215 | ||
| 189 | enum iwl_table_type { | 216 | enum iwl_table_type { |
| 190 | LQ_NONE, | 217 | LQ_NONE, |
| 191 | LQ_G, /* legacy types */ | 218 | LQ_LEGACY_G, /* legacy types */ |
| 192 | LQ_A, | 219 | LQ_LEGACY_A, |
| 193 | LQ_SISO, /* high-throughput types */ | 220 | LQ_HT_SISO, /* HT types */ |
| 194 | LQ_MIMO2, | 221 | LQ_HT_MIMO2, |
| 222 | LQ_VHT_SISO, /* VHT types */ | ||
| 223 | LQ_VHT_MIMO2, | ||
| 195 | LQ_MAX, | 224 | LQ_MAX, |
| 196 | }; | 225 | }; |
| 197 | 226 | ||
| 198 | #define is_legacy(tbl) (((tbl) == LQ_G) || ((tbl) == LQ_A)) | 227 | #define is_legacy(tbl) (((tbl) == LQ_LEGACY_G) || ((tbl) == LQ_LEGACY_A)) |
| 199 | #define is_siso(tbl) ((tbl) == LQ_SISO) | 228 | #define is_ht_siso(tbl) ((tbl) == LQ_HT_SISO) |
| 200 | #define is_mimo2(tbl) ((tbl) == LQ_MIMO2) | 229 | #define is_ht_mimo2(tbl) ((tbl) == LQ_HT_MIMO2) |
| 201 | #define is_mimo(tbl) is_mimo2(tbl) | 230 | #define is_vht_siso(tbl) ((tbl) == LQ_VHT_SISO) |
| 202 | #define is_Ht(tbl) (is_siso(tbl) || is_mimo(tbl)) | 231 | #define is_vht_mimo2(tbl) ((tbl) == LQ_VHT_MIMO2) |
| 203 | #define is_a_band(tbl) ((tbl) == LQ_A) | 232 | #define is_siso(tbl) (is_ht_siso(tbl) || is_vht_siso(tbl)) |
| 204 | #define is_g_and(tbl) ((tbl) == LQ_G) | 233 | #define is_mimo2(tbl) (is_ht_mimo2(tbl) || is_vht_mimo2(tbl)) |
| 234 | #define is_mimo(tbl) (is_mimo2(tbl)) | ||
| 235 | #define is_ht(tbl) (is_ht_siso(tbl) || is_ht_mimo2(tbl)) | ||
| 236 | #define is_vht(tbl) (is_vht_siso(tbl) || is_vht_mimo2(tbl)) | ||
| 237 | #define is_a_band(tbl) ((tbl) == LQ_LEGACY_A) | ||
| 238 | #define is_g_band(tbl) ((tbl) == LQ_LEGACY_G) | ||
| 239 | |||
| 240 | #define is_ht20(tbl) (tbl->bw == RATE_MCS_CHAN_WIDTH_20) | ||
| 241 | #define is_ht40(tbl) (tbl->bw == RATE_MCS_CHAN_WIDTH_40) | ||
| 242 | #define is_ht80(tbl) (tbl->bw == RATE_MCS_CHAN_WIDTH_80) | ||
| 205 | 243 | ||
| 206 | #define IWL_MAX_MCS_DISPLAY_SIZE 12 | 244 | #define IWL_MAX_MCS_DISPLAY_SIZE 12 |
| 207 | 245 | ||
| @@ -232,7 +270,7 @@ struct iwl_scale_tbl_info { | |||
| 232 | enum iwl_table_type lq_type; | 270 | enum iwl_table_type lq_type; |
| 233 | u8 ant_type; | 271 | u8 ant_type; |
| 234 | u8 is_SGI; /* 1 = short guard interval */ | 272 | u8 is_SGI; /* 1 = short guard interval */ |
| 235 | u8 is_ht40; /* 1 = 40 MHz channel width */ | 273 | u32 bw; /* channel bandwidth; RATE_MCS_CHAN_WIDTH_XX */ |
| 236 | u8 action; /* change modulation; IWL_[LEGACY/SISO/MIMO]_SWITCH_* */ | 274 | u8 action; /* change modulation; IWL_[LEGACY/SISO/MIMO]_SWITCH_* */ |
| 237 | u8 max_search; /* maximun number of tables we can search */ | 275 | u8 max_search; /* maximun number of tables we can search */ |
| 238 | s32 *expected_tpt; /* throughput metrics; expected_tpt_G, etc. */ | 276 | s32 *expected_tpt; /* throughput metrics; expected_tpt_G, etc. */ |
| @@ -262,7 +300,7 @@ struct iwl_lq_sta { | |||
| 262 | u64 flush_timer; /* time staying in mode before new search */ | 300 | u64 flush_timer; /* time staying in mode before new search */ |
| 263 | 301 | ||
| 264 | u8 action_counter; /* # mode-switch actions tried */ | 302 | u8 action_counter; /* # mode-switch actions tried */ |
| 265 | u8 is_green; | 303 | bool is_vht; |
| 266 | enum ieee80211_band band; | 304 | enum ieee80211_band band; |
| 267 | 305 | ||
| 268 | /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ | 306 | /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c index 2a8cb5a60535..a4af5019a496 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/iwlwifi/mvm/rx.c | |||
| @@ -422,6 +422,27 @@ static void iwl_mvm_stat_iterator(void *_data, u8 *mac, | |||
| 422 | 422 | ||
| 423 | mvmvif->bf_data.ave_beacon_signal = sig; | 423 | mvmvif->bf_data.ave_beacon_signal = sig; |
| 424 | 424 | ||
| 425 | /* BT Coex */ | ||
| 426 | if (mvmvif->bf_data.bt_coex_min_thold != | ||
| 427 | mvmvif->bf_data.bt_coex_max_thold) { | ||
| 428 | last_event = mvmvif->bf_data.last_bt_coex_event; | ||
| 429 | if (sig > mvmvif->bf_data.bt_coex_max_thold && | ||
| 430 | (last_event <= mvmvif->bf_data.bt_coex_min_thold || | ||
| 431 | last_event == 0)) { | ||
| 432 | mvmvif->bf_data.last_bt_coex_event = sig; | ||
| 433 | IWL_DEBUG_RX(mvm, "cqm_iterator bt coex high %d\n", | ||
| 434 | sig); | ||
| 435 | iwl_mvm_bt_rssi_event(mvm, vif, RSSI_EVENT_HIGH); | ||
| 436 | } else if (sig < mvmvif->bf_data.bt_coex_min_thold && | ||
| 437 | (last_event >= mvmvif->bf_data.bt_coex_max_thold || | ||
| 438 | last_event == 0)) { | ||
| 439 | mvmvif->bf_data.last_bt_coex_event = sig; | ||
| 440 | IWL_DEBUG_RX(mvm, "cqm_iterator bt coex low %d\n", | ||
| 441 | sig); | ||
| 442 | iwl_mvm_bt_rssi_event(mvm, vif, RSSI_EVENT_LOW); | ||
| 443 | } | ||
| 444 | } | ||
| 445 | |||
| 425 | if (!(vif->driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI)) | 446 | if (!(vif->driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI)) |
| 426 | return; | 447 | return; |
| 427 | 448 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index 621fb71f282a..dff7592e1ff8 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c | |||
| @@ -74,8 +74,12 @@ | |||
| 74 | static inline __le16 iwl_mvm_scan_rx_chain(struct iwl_mvm *mvm) | 74 | static inline __le16 iwl_mvm_scan_rx_chain(struct iwl_mvm *mvm) |
| 75 | { | 75 | { |
| 76 | u16 rx_chain; | 76 | u16 rx_chain; |
| 77 | u8 rx_ant = iwl_fw_valid_rx_ant(mvm->fw); | 77 | u8 rx_ant; |
| 78 | 78 | ||
| 79 | if (mvm->scan_rx_ant != ANT_NONE) | ||
| 80 | rx_ant = mvm->scan_rx_ant; | ||
| 81 | else | ||
| 82 | rx_ant = iwl_fw_valid_rx_ant(mvm->fw); | ||
| 79 | rx_chain = rx_ant << PHY_RX_CHAIN_VALID_POS; | 83 | rx_chain = rx_ant << PHY_RX_CHAIN_VALID_POS; |
| 80 | rx_chain |= rx_ant << PHY_RX_CHAIN_FORCE_MIMO_SEL_POS; | 84 | rx_chain |= rx_ant << PHY_RX_CHAIN_FORCE_MIMO_SEL_POS; |
| 81 | rx_chain |= rx_ant << PHY_RX_CHAIN_FORCE_SEL_POS; | 85 | rx_chain |= rx_ant << PHY_RX_CHAIN_FORCE_SEL_POS; |
| @@ -93,10 +97,10 @@ static inline __le32 iwl_mvm_scan_max_out_time(struct ieee80211_vif *vif) | |||
| 93 | 97 | ||
| 94 | static inline __le32 iwl_mvm_scan_suspend_time(struct ieee80211_vif *vif) | 98 | static inline __le32 iwl_mvm_scan_suspend_time(struct ieee80211_vif *vif) |
| 95 | { | 99 | { |
| 96 | if (vif->bss_conf.assoc) | 100 | if (!vif->bss_conf.assoc) |
| 97 | return cpu_to_le32(vif->bss_conf.beacon_int); | ||
| 98 | else | ||
| 99 | return 0; | 101 | return 0; |
| 102 | |||
| 103 | return cpu_to_le32(ieee80211_tu_to_usec(vif->bss_conf.beacon_int)); | ||
| 100 | } | 104 | } |
| 101 | 105 | ||
| 102 | static inline __le32 | 106 | static inline __le32 |
| @@ -133,11 +137,12 @@ iwl_mvm_scan_rate_n_flags(struct iwl_mvm *mvm, enum ieee80211_band band, | |||
| 133 | * request. | 137 | * request. |
| 134 | */ | 138 | */ |
| 135 | static void iwl_mvm_scan_fill_ssids(struct iwl_scan_cmd *cmd, | 139 | static void iwl_mvm_scan_fill_ssids(struct iwl_scan_cmd *cmd, |
| 136 | struct cfg80211_scan_request *req) | 140 | struct cfg80211_scan_request *req, |
| 141 | int first) | ||
| 137 | { | 142 | { |
| 138 | int fw_idx, req_idx; | 143 | int fw_idx, req_idx; |
| 139 | 144 | ||
| 140 | for (req_idx = req->n_ssids - 1, fw_idx = 0; req_idx > 0; | 145 | for (req_idx = req->n_ssids - 1, fw_idx = 0; req_idx >= first; |
| 141 | req_idx--, fw_idx++) { | 146 | req_idx--, fw_idx++) { |
| 142 | cmd->direct_scan[fw_idx].id = WLAN_EID_SSID; | 147 | cmd->direct_scan[fw_idx].id = WLAN_EID_SSID; |
| 143 | cmd->direct_scan[fw_idx].len = req->ssids[req_idx].ssid_len; | 148 | cmd->direct_scan[fw_idx].len = req->ssids[req_idx].ssid_len; |
| @@ -153,9 +158,9 @@ static void iwl_mvm_scan_fill_ssids(struct iwl_scan_cmd *cmd, | |||
| 153 | * just to notify that this scan is active and not passive. | 158 | * just to notify that this scan is active and not passive. |
| 154 | * In order to notify the FW of the number of SSIDs we wish to scan (including | 159 | * In order to notify the FW of the number of SSIDs we wish to scan (including |
| 155 | * the zero-length one), we need to set the corresponding bits in chan->type, | 160 | * the zero-length one), we need to set the corresponding bits in chan->type, |
| 156 | * one for each SSID, and set the active bit (first). The first SSID is already | 161 | * one for each SSID, and set the active bit (first). If the first SSID is |
| 157 | * included in the probe template, so we need to set only req->n_ssids - 1 bits | 162 | * already included in the probe template, so we need to set only |
| 158 | * in addition to the first bit. | 163 | * req->n_ssids - 1 bits in addition to the first bit. |
| 159 | */ | 164 | */ |
| 160 | static u16 iwl_mvm_get_active_dwell(enum ieee80211_band band, int n_ssids) | 165 | static u16 iwl_mvm_get_active_dwell(enum ieee80211_band band, int n_ssids) |
| 161 | { | 166 | { |
| @@ -170,7 +175,8 @@ static u16 iwl_mvm_get_passive_dwell(enum ieee80211_band band) | |||
| 170 | } | 175 | } |
| 171 | 176 | ||
| 172 | static void iwl_mvm_scan_fill_channels(struct iwl_scan_cmd *cmd, | 177 | static void iwl_mvm_scan_fill_channels(struct iwl_scan_cmd *cmd, |
| 173 | struct cfg80211_scan_request *req) | 178 | struct cfg80211_scan_request *req, |
| 179 | bool basic_ssid) | ||
| 174 | { | 180 | { |
| 175 | u16 passive_dwell = iwl_mvm_get_passive_dwell(req->channels[0]->band); | 181 | u16 passive_dwell = iwl_mvm_get_passive_dwell(req->channels[0]->band); |
| 176 | u16 active_dwell = iwl_mvm_get_active_dwell(req->channels[0]->band, | 182 | u16 active_dwell = iwl_mvm_get_active_dwell(req->channels[0]->band, |
| @@ -178,10 +184,14 @@ static void iwl_mvm_scan_fill_channels(struct iwl_scan_cmd *cmd, | |||
| 178 | struct iwl_scan_channel *chan = (struct iwl_scan_channel *) | 184 | struct iwl_scan_channel *chan = (struct iwl_scan_channel *) |
| 179 | (cmd->data + le16_to_cpu(cmd->tx_cmd.len)); | 185 | (cmd->data + le16_to_cpu(cmd->tx_cmd.len)); |
| 180 | int i; | 186 | int i; |
| 187 | int type = BIT(req->n_ssids) - 1; | ||
| 188 | |||
| 189 | if (!basic_ssid) | ||
| 190 | type |= BIT(req->n_ssids); | ||
| 181 | 191 | ||
| 182 | for (i = 0; i < cmd->channel_count; i++) { | 192 | for (i = 0; i < cmd->channel_count; i++) { |
| 183 | chan->channel = cpu_to_le16(req->channels[i]->hw_value); | 193 | chan->channel = cpu_to_le16(req->channels[i]->hw_value); |
| 184 | chan->type = cpu_to_le32(BIT(req->n_ssids) - 1); | 194 | chan->type = cpu_to_le32(type); |
| 185 | if (req->channels[i]->flags & IEEE80211_CHAN_PASSIVE_SCAN) | 195 | if (req->channels[i]->flags & IEEE80211_CHAN_PASSIVE_SCAN) |
| 186 | chan->type &= cpu_to_le32(~SCAN_CHANNEL_TYPE_ACTIVE); | 196 | chan->type &= cpu_to_le32(~SCAN_CHANNEL_TYPE_ACTIVE); |
| 187 | chan->active_dwell = cpu_to_le16(active_dwell); | 197 | chan->active_dwell = cpu_to_le16(active_dwell); |
| @@ -268,6 +278,8 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm, | |||
| 268 | u32 status; | 278 | u32 status; |
| 269 | int ssid_len = 0; | 279 | int ssid_len = 0; |
| 270 | u8 *ssid = NULL; | 280 | u8 *ssid = NULL; |
| 281 | bool basic_ssid = !(mvm->fw->ucode_capa.flags & | ||
| 282 | IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID); | ||
| 271 | 283 | ||
| 272 | lockdep_assert_held(&mvm->mutex); | 284 | lockdep_assert_held(&mvm->mutex); |
| 273 | BUG_ON(mvm->scan_cmd == NULL); | 285 | BUG_ON(mvm->scan_cmd == NULL); |
| @@ -302,14 +314,16 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm, | |||
| 302 | if (req->n_ssids > 0) { | 314 | if (req->n_ssids > 0) { |
| 303 | cmd->passive2active = cpu_to_le16(1); | 315 | cmd->passive2active = cpu_to_le16(1); |
| 304 | cmd->scan_flags |= SCAN_FLAGS_PASSIVE2ACTIVE; | 316 | cmd->scan_flags |= SCAN_FLAGS_PASSIVE2ACTIVE; |
| 305 | ssid = req->ssids[0].ssid; | 317 | if (basic_ssid) { |
| 306 | ssid_len = req->ssids[0].ssid_len; | 318 | ssid = req->ssids[0].ssid; |
| 319 | ssid_len = req->ssids[0].ssid_len; | ||
| 320 | } | ||
| 307 | } else { | 321 | } else { |
| 308 | cmd->passive2active = 0; | 322 | cmd->passive2active = 0; |
| 309 | cmd->scan_flags &= ~SCAN_FLAGS_PASSIVE2ACTIVE; | 323 | cmd->scan_flags &= ~SCAN_FLAGS_PASSIVE2ACTIVE; |
| 310 | } | 324 | } |
| 311 | 325 | ||
| 312 | iwl_mvm_scan_fill_ssids(cmd, req); | 326 | iwl_mvm_scan_fill_ssids(cmd, req, basic_ssid ? 1 : 0); |
| 313 | 327 | ||
| 314 | cmd->tx_cmd.tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL); | 328 | cmd->tx_cmd.tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL); |
| 315 | cmd->tx_cmd.sta_id = mvm->aux_sta.sta_id; | 329 | cmd->tx_cmd.sta_id = mvm->aux_sta.sta_id; |
| @@ -326,7 +340,7 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm, | |||
| 326 | req->ie, req->ie_len, | 340 | req->ie, req->ie_len, |
| 327 | mvm->fw->ucode_capa.max_probe_length)); | 341 | mvm->fw->ucode_capa.max_probe_length)); |
| 328 | 342 | ||
| 329 | iwl_mvm_scan_fill_channels(cmd, req); | 343 | iwl_mvm_scan_fill_channels(cmd, req, basic_ssid); |
| 330 | 344 | ||
| 331 | cmd->len = cpu_to_le16(sizeof(struct iwl_scan_cmd) + | 345 | cmd->len = cpu_to_le16(sizeof(struct iwl_scan_cmd) + |
| 332 | le16_to_cpu(cmd->tx_cmd.len) + | 346 | le16_to_cpu(cmd->tx_cmd.len) + |
| @@ -377,6 +391,21 @@ int iwl_mvm_rx_scan_complete(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | |||
| 377 | return 0; | 391 | return 0; |
| 378 | } | 392 | } |
| 379 | 393 | ||
| 394 | int iwl_mvm_rx_sched_scan_results(struct iwl_mvm *mvm, | ||
| 395 | struct iwl_rx_cmd_buffer *rxb, | ||
| 396 | struct iwl_device_cmd *cmd) | ||
| 397 | { | ||
| 398 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
| 399 | struct iwl_sched_scan_results *notif = (void *)pkt->data; | ||
| 400 | |||
| 401 | if (notif->client_bitmap & SCAN_CLIENT_SCHED_SCAN) { | ||
| 402 | IWL_DEBUG_SCAN(mvm, "Scheduled scan results\n"); | ||
| 403 | ieee80211_sched_scan_results(mvm->hw); | ||
| 404 | } | ||
| 405 | |||
| 406 | return 0; | ||
| 407 | } | ||
| 408 | |||
| 380 | static bool iwl_mvm_scan_abort_notif(struct iwl_notif_wait_data *notif_wait, | 409 | static bool iwl_mvm_scan_abort_notif(struct iwl_notif_wait_data *notif_wait, |
| 381 | struct iwl_rx_packet *pkt, void *data) | 410 | struct iwl_rx_packet *pkt, void *data) |
| 382 | { | 411 | { |
| @@ -447,3 +476,406 @@ void iwl_mvm_cancel_scan(struct iwl_mvm *mvm) | |||
| 447 | out_remove_notif: | 476 | out_remove_notif: |
| 448 | iwl_remove_notification(&mvm->notif_wait, &wait_scan_abort); | 477 | iwl_remove_notification(&mvm->notif_wait, &wait_scan_abort); |
| 449 | } | 478 | } |
| 479 | |||
| 480 | int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm, | ||
| 481 | struct iwl_rx_cmd_buffer *rxb, | ||
| 482 | struct iwl_device_cmd *cmd) | ||
| 483 | { | ||
| 484 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
| 485 | struct iwl_scan_offload_complete *scan_notif = (void *)pkt->data; | ||
| 486 | |||
| 487 | IWL_DEBUG_SCAN(mvm, "Scheduled scan completed, status %s\n", | ||
| 488 | scan_notif->status == IWL_SCAN_OFFLOAD_COMPLETED ? | ||
| 489 | "completed" : "aborted"); | ||
| 490 | |||
| 491 | mvm->scan_status = IWL_MVM_SCAN_NONE; | ||
| 492 | ieee80211_sched_scan_stopped(mvm->hw); | ||
| 493 | |||
| 494 | return 0; | ||
| 495 | } | ||
| 496 | |||
| 497 | static void iwl_scan_offload_build_tx_cmd(struct iwl_mvm *mvm, | ||
| 498 | struct ieee80211_vif *vif, | ||
| 499 | struct ieee80211_sched_scan_ies *ies, | ||
| 500 | enum ieee80211_band band, | ||
| 501 | struct iwl_tx_cmd *cmd, | ||
| 502 | u8 *data) | ||
| 503 | { | ||
| 504 | u16 cmd_len; | ||
| 505 | |||
| 506 | cmd->tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL); | ||
| 507 | cmd->life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE); | ||
| 508 | cmd->sta_id = mvm->aux_sta.sta_id; | ||
| 509 | |||
| 510 | cmd->rate_n_flags = iwl_mvm_scan_rate_n_flags(mvm, band, false); | ||
| 511 | |||
| 512 | cmd_len = iwl_mvm_fill_probe_req((struct ieee80211_mgmt *)data, | ||
| 513 | vif->addr, | ||
| 514 | 1, NULL, 0, | ||
| 515 | ies->ie[band], ies->len[band], | ||
| 516 | SCAN_OFFLOAD_PROBE_REQ_SIZE); | ||
| 517 | cmd->len = cpu_to_le16(cmd_len); | ||
| 518 | } | ||
| 519 | |||
| 520 | static void iwl_build_scan_cmd(struct iwl_mvm *mvm, | ||
| 521 | struct ieee80211_vif *vif, | ||
| 522 | struct cfg80211_sched_scan_request *req, | ||
| 523 | struct iwl_scan_offload_cmd *scan) | ||
| 524 | { | ||
| 525 | scan->channel_count = | ||
| 526 | mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels + | ||
| 527 | mvm->nvm_data->bands[IEEE80211_BAND_5GHZ].n_channels; | ||
| 528 | scan->quiet_time = cpu_to_le16(IWL_ACTIVE_QUIET_TIME); | ||
| 529 | scan->quiet_plcp_th = cpu_to_le16(IWL_PLCP_QUIET_THRESH); | ||
| 530 | scan->good_CRC_th = IWL_GOOD_CRC_TH_DEFAULT; | ||
| 531 | scan->rx_chain = iwl_mvm_scan_rx_chain(mvm); | ||
| 532 | scan->max_out_time = cpu_to_le32(200 * 1024); | ||
| 533 | scan->suspend_time = iwl_mvm_scan_suspend_time(vif); | ||
| 534 | scan->filter_flags |= cpu_to_le32(MAC_FILTER_ACCEPT_GRP | | ||
| 535 | MAC_FILTER_IN_BEACON); | ||
| 536 | scan->scan_type = cpu_to_le32(SCAN_TYPE_BACKGROUND); | ||
| 537 | scan->rep_count = cpu_to_le32(1); | ||
| 538 | } | ||
| 539 | |||
| 540 | static int iwl_ssid_exist(u8 *ssid, u8 ssid_len, struct iwl_ssid_ie *ssid_list) | ||
| 541 | { | ||
| 542 | int i; | ||
| 543 | |||
| 544 | for (i = 0; i < PROBE_OPTION_MAX; i++) { | ||
| 545 | if (!ssid_list[i].len) | ||
| 546 | break; | ||
| 547 | if (ssid_list[i].len == ssid_len && | ||
| 548 | !memcmp(ssid_list->ssid, ssid, ssid_len)) | ||
| 549 | return i; | ||
| 550 | } | ||
| 551 | return -1; | ||
| 552 | } | ||
| 553 | |||
| 554 | static void iwl_scan_offload_build_ssid(struct cfg80211_sched_scan_request *req, | ||
| 555 | struct iwl_scan_offload_cmd *scan, | ||
| 556 | u32 *ssid_bitmap) | ||
| 557 | { | ||
| 558 | int i, j; | ||
| 559 | int index; | ||
| 560 | |||
| 561 | /* | ||
| 562 | * copy SSIDs from match list. | ||
| 563 | * iwl_config_sched_scan_profiles() uses the order of these ssids to | ||
| 564 | * config match list. | ||
| 565 | */ | ||
| 566 | for (i = 0; i < req->n_match_sets && i < PROBE_OPTION_MAX; i++) { | ||
| 567 | scan->direct_scan[i].id = WLAN_EID_SSID; | ||
| 568 | scan->direct_scan[i].len = req->match_sets[i].ssid.ssid_len; | ||
| 569 | memcpy(scan->direct_scan[i].ssid, req->match_sets[i].ssid.ssid, | ||
| 570 | scan->direct_scan[i].len); | ||
| 571 | } | ||
| 572 | |||
| 573 | /* add SSIDs from scan SSID list */ | ||
| 574 | *ssid_bitmap = 0; | ||
| 575 | for (j = 0; j < req->n_ssids && i < PROBE_OPTION_MAX; j++) { | ||
| 576 | index = iwl_ssid_exist(req->ssids[j].ssid, | ||
| 577 | req->ssids[j].ssid_len, | ||
| 578 | scan->direct_scan); | ||
| 579 | if (index < 0) { | ||
| 580 | if (!req->ssids[j].ssid_len) | ||
| 581 | continue; | ||
| 582 | scan->direct_scan[i].id = WLAN_EID_SSID; | ||
| 583 | scan->direct_scan[i].len = req->ssids[j].ssid_len; | ||
| 584 | memcpy(scan->direct_scan[i].ssid, req->ssids[j].ssid, | ||
| 585 | scan->direct_scan[i].len); | ||
| 586 | *ssid_bitmap |= BIT(i + 1); | ||
| 587 | i++; | ||
| 588 | } else { | ||
| 589 | *ssid_bitmap |= BIT(index + 1); | ||
| 590 | } | ||
| 591 | } | ||
| 592 | } | ||
| 593 | |||
| 594 | static void iwl_build_channel_cfg(struct iwl_mvm *mvm, | ||
| 595 | struct cfg80211_sched_scan_request *req, | ||
| 596 | struct iwl_scan_channel_cfg *channels, | ||
| 597 | enum ieee80211_band band, | ||
| 598 | int *head, int *tail, | ||
| 599 | u32 ssid_bitmap) | ||
| 600 | { | ||
| 601 | struct ieee80211_supported_band *s_band; | ||
| 602 | int n_probes = req->n_ssids; | ||
| 603 | int n_channels = req->n_channels; | ||
| 604 | u8 active_dwell, passive_dwell; | ||
| 605 | int i, j, index = 0; | ||
| 606 | bool partial; | ||
| 607 | |||
| 608 | /* | ||
| 609 | * We have to configure all supported channels, even if we don't want to | ||
| 610 | * scan on them, but we have to send channels in the order that we want | ||
| 611 | * to scan. So add requested channels to head of the list and others to | ||
| 612 | * the end. | ||
| 613 | */ | ||
| 614 | active_dwell = iwl_mvm_get_active_dwell(band, n_probes); | ||
| 615 | passive_dwell = iwl_mvm_get_passive_dwell(band); | ||
| 616 | s_band = &mvm->nvm_data->bands[band]; | ||
| 617 | |||
| 618 | for (i = 0; i < s_band->n_channels && *head <= *tail; i++) { | ||
| 619 | partial = false; | ||
| 620 | for (j = 0; j < n_channels; j++) | ||
| 621 | if (s_band->channels[i].center_freq == | ||
| 622 | req->channels[j]->center_freq) { | ||
| 623 | index = *head; | ||
| 624 | (*head)++; | ||
| 625 | /* | ||
| 626 | * Channels that came with the request will be | ||
| 627 | * in partial scan . | ||
| 628 | */ | ||
| 629 | partial = true; | ||
| 630 | break; | ||
| 631 | } | ||
| 632 | if (!partial) { | ||
| 633 | index = *tail; | ||
| 634 | (*tail)--; | ||
| 635 | } | ||
| 636 | channels->channel_number[index] = | ||
| 637 | cpu_to_le16(ieee80211_frequency_to_channel( | ||
| 638 | s_band->channels[i].center_freq)); | ||
| 639 | channels->dwell_time[index][0] = active_dwell; | ||
| 640 | channels->dwell_time[index][1] = passive_dwell; | ||
| 641 | |||
| 642 | channels->iter_count[index] = cpu_to_le16(1); | ||
| 643 | channels->iter_interval[index] = 0; | ||
| 644 | |||
| 645 | if (!(s_band->channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN)) | ||
| 646 | channels->type[index] |= | ||
| 647 | cpu_to_le32(IWL_SCAN_OFFLOAD_CHANNEL_ACTIVE); | ||
| 648 | |||
| 649 | channels->type[index] |= | ||
| 650 | cpu_to_le32(IWL_SCAN_OFFLOAD_CHANNEL_FULL); | ||
| 651 | if (partial) | ||
| 652 | channels->type[index] |= | ||
| 653 | cpu_to_le32(IWL_SCAN_OFFLOAD_CHANNEL_PARTIAL); | ||
| 654 | |||
| 655 | if (s_band->channels[i].flags & IEEE80211_CHAN_NO_HT40) | ||
| 656 | channels->type[index] |= | ||
| 657 | cpu_to_le32(IWL_SCAN_OFFLOAD_CHANNEL_NARROW); | ||
| 658 | |||
| 659 | /* scan for all SSIDs from req->ssids */ | ||
| 660 | channels->type[index] |= cpu_to_le32(ssid_bitmap); | ||
| 661 | } | ||
| 662 | } | ||
| 663 | |||
| 664 | int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm, | ||
| 665 | struct ieee80211_vif *vif, | ||
| 666 | struct cfg80211_sched_scan_request *req, | ||
| 667 | struct ieee80211_sched_scan_ies *ies) | ||
| 668 | { | ||
| 669 | int supported_bands = 0; | ||
| 670 | int band_2ghz = mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels; | ||
| 671 | int band_5ghz = mvm->nvm_data->bands[IEEE80211_BAND_5GHZ].n_channels; | ||
| 672 | int head = 0; | ||
| 673 | int tail = band_2ghz + band_5ghz; | ||
| 674 | u32 ssid_bitmap; | ||
| 675 | int cmd_len; | ||
| 676 | int ret; | ||
| 677 | |||
| 678 | struct iwl_scan_offload_cfg *scan_cfg; | ||
| 679 | struct iwl_host_cmd cmd = { | ||
| 680 | .id = SCAN_OFFLOAD_CONFIG_CMD, | ||
| 681 | .flags = CMD_SYNC, | ||
| 682 | }; | ||
| 683 | |||
| 684 | lockdep_assert_held(&mvm->mutex); | ||
| 685 | |||
| 686 | if (band_2ghz) | ||
| 687 | supported_bands++; | ||
| 688 | if (band_5ghz) | ||
| 689 | supported_bands++; | ||
| 690 | |||
| 691 | cmd_len = sizeof(struct iwl_scan_offload_cfg) + | ||
| 692 | supported_bands * SCAN_OFFLOAD_PROBE_REQ_SIZE; | ||
| 693 | |||
| 694 | scan_cfg = kzalloc(cmd_len, GFP_KERNEL); | ||
| 695 | if (!scan_cfg) | ||
| 696 | return -ENOMEM; | ||
| 697 | |||
| 698 | iwl_build_scan_cmd(mvm, vif, req, &scan_cfg->scan_cmd); | ||
| 699 | scan_cfg->scan_cmd.len = cpu_to_le16(cmd_len); | ||
| 700 | |||
| 701 | iwl_scan_offload_build_ssid(req, &scan_cfg->scan_cmd, &ssid_bitmap); | ||
| 702 | /* build tx frames for supported bands */ | ||
| 703 | if (band_2ghz) { | ||
| 704 | iwl_scan_offload_build_tx_cmd(mvm, vif, ies, | ||
| 705 | IEEE80211_BAND_2GHZ, | ||
| 706 | &scan_cfg->scan_cmd.tx_cmd[0], | ||
| 707 | scan_cfg->data); | ||
| 708 | iwl_build_channel_cfg(mvm, req, &scan_cfg->channel_cfg, | ||
| 709 | IEEE80211_BAND_2GHZ, &head, &tail, | ||
| 710 | ssid_bitmap); | ||
| 711 | } | ||
| 712 | if (band_5ghz) { | ||
| 713 | iwl_scan_offload_build_tx_cmd(mvm, vif, ies, | ||
| 714 | IEEE80211_BAND_5GHZ, | ||
| 715 | &scan_cfg->scan_cmd.tx_cmd[1], | ||
| 716 | scan_cfg->data + | ||
| 717 | SCAN_OFFLOAD_PROBE_REQ_SIZE); | ||
| 718 | iwl_build_channel_cfg(mvm, req, &scan_cfg->channel_cfg, | ||
| 719 | IEEE80211_BAND_5GHZ, &head, &tail, | ||
| 720 | ssid_bitmap); | ||
| 721 | } | ||
| 722 | |||
| 723 | cmd.data[0] = scan_cfg; | ||
| 724 | cmd.len[0] = cmd_len; | ||
| 725 | cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; | ||
| 726 | |||
| 727 | IWL_DEBUG_SCAN(mvm, "Sending scheduled scan config\n"); | ||
| 728 | |||
| 729 | ret = iwl_mvm_send_cmd(mvm, &cmd); | ||
| 730 | kfree(scan_cfg); | ||
| 731 | return ret; | ||
| 732 | } | ||
| 733 | |||
| 734 | int iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm, | ||
| 735 | struct cfg80211_sched_scan_request *req) | ||
| 736 | { | ||
| 737 | struct iwl_scan_offload_profile *profile; | ||
| 738 | struct iwl_scan_offload_profile_cfg *profile_cfg; | ||
| 739 | struct iwl_scan_offload_blacklist *blacklist; | ||
| 740 | struct iwl_host_cmd cmd = { | ||
| 741 | .id = SCAN_OFFLOAD_UPDATE_PROFILES_CMD, | ||
| 742 | .flags = CMD_SYNC, | ||
| 743 | .len[1] = sizeof(*profile_cfg), | ||
| 744 | .dataflags[0] = IWL_HCMD_DFL_NOCOPY, | ||
| 745 | .dataflags[1] = IWL_HCMD_DFL_NOCOPY, | ||
| 746 | }; | ||
| 747 | int blacklist_len; | ||
| 748 | int i; | ||
| 749 | int ret; | ||
| 750 | |||
| 751 | if (WARN_ON(req->n_match_sets > IWL_SCAN_MAX_PROFILES)) | ||
| 752 | return -EIO; | ||
| 753 | |||
| 754 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_SHORT_BL) | ||
| 755 | blacklist_len = IWL_SCAN_SHORT_BLACKLIST_LEN; | ||
| 756 | else | ||
| 757 | blacklist_len = IWL_SCAN_MAX_BLACKLIST_LEN; | ||
| 758 | |||
| 759 | blacklist = kzalloc(sizeof(*blacklist) * blacklist_len, GFP_KERNEL); | ||
| 760 | if (!blacklist) | ||
| 761 | return -ENOMEM; | ||
| 762 | |||
| 763 | profile_cfg = kzalloc(sizeof(*profile_cfg), GFP_KERNEL); | ||
| 764 | if (!profile_cfg) { | ||
| 765 | ret = -ENOMEM; | ||
| 766 | goto free_blacklist; | ||
| 767 | } | ||
| 768 | |||
| 769 | cmd.data[0] = blacklist; | ||
| 770 | cmd.len[0] = sizeof(*blacklist) * blacklist_len; | ||
| 771 | cmd.data[1] = profile_cfg; | ||
| 772 | |||
| 773 | /* No blacklist configuration */ | ||
| 774 | |||
| 775 | profile_cfg->num_profiles = req->n_match_sets; | ||
| 776 | profile_cfg->active_clients = SCAN_CLIENT_SCHED_SCAN; | ||
| 777 | profile_cfg->pass_match = SCAN_CLIENT_SCHED_SCAN; | ||
| 778 | profile_cfg->match_notify = SCAN_CLIENT_SCHED_SCAN; | ||
| 779 | |||
| 780 | for (i = 0; i < req->n_match_sets; i++) { | ||
| 781 | profile = &profile_cfg->profiles[i]; | ||
| 782 | profile->ssid_index = i; | ||
| 783 | /* Support any cipher and auth algorithm */ | ||
| 784 | profile->unicast_cipher = 0xff; | ||
| 785 | profile->auth_alg = 0xff; | ||
| 786 | profile->network_type = IWL_NETWORK_TYPE_ANY; | ||
| 787 | profile->band_selection = IWL_SCAN_OFFLOAD_SELECT_ANY; | ||
| 788 | profile->client_bitmap = SCAN_CLIENT_SCHED_SCAN; | ||
| 789 | } | ||
| 790 | |||
| 791 | IWL_DEBUG_SCAN(mvm, "Sending scheduled scan profile config\n"); | ||
| 792 | |||
| 793 | ret = iwl_mvm_send_cmd(mvm, &cmd); | ||
| 794 | kfree(profile_cfg); | ||
| 795 | free_blacklist: | ||
| 796 | kfree(blacklist); | ||
| 797 | |||
| 798 | return ret; | ||
| 799 | } | ||
| 800 | |||
| 801 | int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, | ||
| 802 | struct cfg80211_sched_scan_request *req) | ||
| 803 | { | ||
| 804 | struct iwl_scan_offload_req scan_req = { | ||
| 805 | .watchdog = IWL_SCHED_SCAN_WATCHDOG, | ||
| 806 | |||
| 807 | .schedule_line[0].iterations = IWL_FAST_SCHED_SCAN_ITERATIONS, | ||
| 808 | .schedule_line[0].delay = req->interval / 1000, | ||
| 809 | .schedule_line[0].full_scan_mul = 1, | ||
| 810 | |||
| 811 | .schedule_line[1].iterations = 0xff, | ||
| 812 | .schedule_line[1].delay = req->interval / 1000, | ||
| 813 | .schedule_line[1].full_scan_mul = IWL_FULL_SCAN_MULTIPLIER, | ||
| 814 | }; | ||
| 815 | |||
| 816 | if (req->n_match_sets && req->match_sets[0].ssid.ssid_len) { | ||
| 817 | IWL_DEBUG_SCAN(mvm, | ||
| 818 | "Sending scheduled scan with filtering, filter len %d\n", | ||
| 819 | req->n_match_sets); | ||
| 820 | scan_req.flags |= | ||
| 821 | cpu_to_le16(IWL_SCAN_OFFLOAD_FLAG_FILTER_SSID); | ||
| 822 | } else { | ||
| 823 | IWL_DEBUG_SCAN(mvm, | ||
| 824 | "Sending Scheduled scan without filtering\n"); | ||
| 825 | } | ||
| 826 | |||
| 827 | return iwl_mvm_send_cmd_pdu(mvm, SCAN_OFFLOAD_REQUEST_CMD, CMD_SYNC, | ||
| 828 | sizeof(scan_req), &scan_req); | ||
| 829 | } | ||
| 830 | |||
| 831 | static int iwl_mvm_send_sched_scan_abort(struct iwl_mvm *mvm) | ||
| 832 | { | ||
| 833 | int ret; | ||
| 834 | struct iwl_host_cmd cmd = { | ||
| 835 | .id = SCAN_OFFLOAD_ABORT_CMD, | ||
| 836 | .flags = CMD_SYNC, | ||
| 837 | }; | ||
| 838 | u32 status; | ||
| 839 | |||
| 840 | /* Exit instantly with error when device is not ready | ||
| 841 | * to receive scan abort command or it does not perform | ||
| 842 | * scheduled scan currently */ | ||
| 843 | if (mvm->scan_status != IWL_MVM_SCAN_SCHED) | ||
| 844 | return -EIO; | ||
| 845 | |||
| 846 | ret = iwl_mvm_send_cmd_status(mvm, &cmd, &status); | ||
| 847 | if (ret) | ||
| 848 | return ret; | ||
| 849 | |||
| 850 | if (status != CAN_ABORT_STATUS) { | ||
| 851 | /* | ||
| 852 | * The scan abort will return 1 for success or | ||
| 853 | * 2 for "failure". A failure condition can be | ||
| 854 | * due to simply not being in an active scan which | ||
| 855 | * can occur if we send the scan abort before the | ||
| 856 | * microcode has notified us that a scan is completed. | ||
| 857 | */ | ||
| 858 | IWL_DEBUG_SCAN(mvm, "SCAN OFFLOAD ABORT ret %d.\n", status); | ||
| 859 | ret = -EIO; | ||
| 860 | } | ||
| 861 | |||
| 862 | return ret; | ||
| 863 | } | ||
| 864 | |||
| 865 | void iwl_mvm_sched_scan_stop(struct iwl_mvm *mvm) | ||
| 866 | { | ||
| 867 | int ret; | ||
| 868 | |||
| 869 | lockdep_assert_held(&mvm->mutex); | ||
| 870 | |||
| 871 | if (mvm->scan_status != IWL_MVM_SCAN_SCHED) { | ||
| 872 | IWL_DEBUG_SCAN(mvm, "No offloaded scan to stop\n"); | ||
| 873 | return; | ||
| 874 | } | ||
| 875 | |||
| 876 | ret = iwl_mvm_send_sched_scan_abort(mvm); | ||
| 877 | if (ret) | ||
| 878 | IWL_DEBUG_SCAN(mvm, "Send stop offload scan failed %d\n", ret); | ||
| 879 | else | ||
| 880 | IWL_DEBUG_SCAN(mvm, "Successfully sent stop offload scan\n"); | ||
| 881 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index 44add291531b..329952363a54 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c | |||
| @@ -66,6 +66,115 @@ | |||
| 66 | #include "sta.h" | 66 | #include "sta.h" |
| 67 | #include "rs.h" | 67 | #include "rs.h" |
| 68 | 68 | ||
| 69 | static void iwl_mvm_add_sta_cmd_v6_to_v5(struct iwl_mvm_add_sta_cmd_v6 *cmd_v6, | ||
| 70 | struct iwl_mvm_add_sta_cmd_v5 *cmd_v5) | ||
| 71 | { | ||
| 72 | memset(cmd_v5, 0, sizeof(*cmd_v5)); | ||
| 73 | |||
| 74 | cmd_v5->add_modify = cmd_v6->add_modify; | ||
| 75 | cmd_v5->tid_disable_tx = cmd_v6->tid_disable_tx; | ||
| 76 | cmd_v5->mac_id_n_color = cmd_v6->mac_id_n_color; | ||
| 77 | memcpy(cmd_v5->addr, cmd_v6->addr, ETH_ALEN); | ||
| 78 | cmd_v5->sta_id = cmd_v6->sta_id; | ||
| 79 | cmd_v5->modify_mask = cmd_v6->modify_mask; | ||
| 80 | cmd_v5->station_flags = cmd_v6->station_flags; | ||
| 81 | cmd_v5->station_flags_msk = cmd_v6->station_flags_msk; | ||
| 82 | cmd_v5->add_immediate_ba_tid = cmd_v6->add_immediate_ba_tid; | ||
| 83 | cmd_v5->remove_immediate_ba_tid = cmd_v6->remove_immediate_ba_tid; | ||
| 84 | cmd_v5->add_immediate_ba_ssn = cmd_v6->add_immediate_ba_ssn; | ||
| 85 | cmd_v5->sleep_tx_count = cmd_v6->sleep_tx_count; | ||
| 86 | cmd_v5->sleep_state_flags = cmd_v6->sleep_state_flags; | ||
| 87 | cmd_v5->assoc_id = cmd_v6->assoc_id; | ||
| 88 | cmd_v5->beamform_flags = cmd_v6->beamform_flags; | ||
| 89 | cmd_v5->tfd_queue_msk = cmd_v6->tfd_queue_msk; | ||
| 90 | } | ||
| 91 | |||
| 92 | static void | ||
| 93 | iwl_mvm_add_sta_key_to_add_sta_cmd_v5(struct iwl_mvm_add_sta_key_cmd *key_cmd, | ||
| 94 | struct iwl_mvm_add_sta_cmd_v5 *sta_cmd, | ||
| 95 | u32 mac_id_n_color) | ||
| 96 | { | ||
| 97 | memset(sta_cmd, 0, sizeof(*sta_cmd)); | ||
| 98 | |||
| 99 | sta_cmd->sta_id = key_cmd->sta_id; | ||
| 100 | sta_cmd->add_modify = STA_MODE_MODIFY; | ||
| 101 | sta_cmd->modify_mask = STA_MODIFY_KEY; | ||
| 102 | sta_cmd->mac_id_n_color = cpu_to_le32(mac_id_n_color); | ||
| 103 | |||
| 104 | sta_cmd->key.key_offset = key_cmd->key_offset; | ||
| 105 | sta_cmd->key.key_flags = key_cmd->key_flags; | ||
| 106 | memcpy(sta_cmd->key.key, key_cmd->key, sizeof(sta_cmd->key.key)); | ||
| 107 | sta_cmd->key.tkip_rx_tsc_byte2 = key_cmd->tkip_rx_tsc_byte2; | ||
| 108 | memcpy(sta_cmd->key.tkip_rx_ttak, key_cmd->tkip_rx_ttak, | ||
| 109 | sizeof(sta_cmd->key.tkip_rx_ttak)); | ||
| 110 | } | ||
| 111 | |||
| 112 | static int iwl_mvm_send_add_sta_cmd_status(struct iwl_mvm *mvm, | ||
| 113 | struct iwl_mvm_add_sta_cmd_v6 *cmd, | ||
| 114 | int *status) | ||
| 115 | { | ||
| 116 | struct iwl_mvm_add_sta_cmd_v5 cmd_v5; | ||
| 117 | |||
| 118 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_STA_KEY_CMD) | ||
| 119 | return iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(*cmd), | ||
| 120 | cmd, status); | ||
| 121 | |||
| 122 | iwl_mvm_add_sta_cmd_v6_to_v5(cmd, &cmd_v5); | ||
| 123 | |||
| 124 | return iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd_v5), | ||
| 125 | &cmd_v5, status); | ||
| 126 | } | ||
| 127 | |||
| 128 | static int iwl_mvm_send_add_sta_cmd(struct iwl_mvm *mvm, u32 flags, | ||
| 129 | struct iwl_mvm_add_sta_cmd_v6 *cmd) | ||
| 130 | { | ||
| 131 | struct iwl_mvm_add_sta_cmd_v5 cmd_v5; | ||
| 132 | |||
| 133 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_STA_KEY_CMD) | ||
| 134 | return iwl_mvm_send_cmd_pdu(mvm, ADD_STA, flags, | ||
| 135 | sizeof(*cmd), cmd); | ||
| 136 | |||
| 137 | iwl_mvm_add_sta_cmd_v6_to_v5(cmd, &cmd_v5); | ||
| 138 | |||
| 139 | return iwl_mvm_send_cmd_pdu(mvm, ADD_STA, flags, sizeof(cmd_v5), | ||
| 140 | &cmd_v5); | ||
| 141 | } | ||
| 142 | |||
| 143 | static int | ||
| 144 | iwl_mvm_send_add_sta_key_cmd_status(struct iwl_mvm *mvm, | ||
| 145 | struct iwl_mvm_add_sta_key_cmd *cmd, | ||
| 146 | u32 mac_id_n_color, | ||
| 147 | int *status) | ||
| 148 | { | ||
| 149 | struct iwl_mvm_add_sta_cmd_v5 sta_cmd; | ||
| 150 | |||
| 151 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_STA_KEY_CMD) | ||
| 152 | return iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA_KEY, | ||
| 153 | sizeof(*cmd), cmd, status); | ||
| 154 | |||
| 155 | iwl_mvm_add_sta_key_to_add_sta_cmd_v5(cmd, &sta_cmd, mac_id_n_color); | ||
| 156 | |||
| 157 | return iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(sta_cmd), | ||
| 158 | &sta_cmd, status); | ||
| 159 | } | ||
| 160 | |||
| 161 | static int iwl_mvm_send_add_sta_key_cmd(struct iwl_mvm *mvm, | ||
| 162 | u32 flags, | ||
| 163 | struct iwl_mvm_add_sta_key_cmd *cmd, | ||
| 164 | u32 mac_id_n_color) | ||
| 165 | { | ||
| 166 | struct iwl_mvm_add_sta_cmd_v5 sta_cmd; | ||
| 167 | |||
| 168 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_STA_KEY_CMD) | ||
| 169 | return iwl_mvm_send_cmd_pdu(mvm, ADD_STA_KEY, flags, | ||
| 170 | sizeof(*cmd), cmd); | ||
| 171 | |||
| 172 | iwl_mvm_add_sta_key_to_add_sta_cmd_v5(cmd, &sta_cmd, mac_id_n_color); | ||
| 173 | |||
| 174 | return iwl_mvm_send_cmd_pdu(mvm, ADD_STA, flags, sizeof(sta_cmd), | ||
| 175 | &sta_cmd); | ||
| 176 | } | ||
| 177 | |||
| 69 | static int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm) | 178 | static int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm) |
| 70 | { | 179 | { |
| 71 | int sta_id; | 180 | int sta_id; |
| @@ -87,7 +196,7 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
| 87 | bool update) | 196 | bool update) |
| 88 | { | 197 | { |
| 89 | struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; | 198 | struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; |
| 90 | struct iwl_mvm_add_sta_cmd add_sta_cmd; | 199 | struct iwl_mvm_add_sta_cmd_v6 add_sta_cmd; |
| 91 | int ret; | 200 | int ret; |
| 92 | u32 status; | 201 | u32 status; |
| 93 | u32 agg_size = 0, mpdu_dens = 0; | 202 | u32 agg_size = 0, mpdu_dens = 0; |
| @@ -175,8 +284,7 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
| 175 | cpu_to_le32(mpdu_dens << STA_FLG_AGG_MPDU_DENS_SHIFT); | 284 | cpu_to_le32(mpdu_dens << STA_FLG_AGG_MPDU_DENS_SHIFT); |
| 176 | 285 | ||
| 177 | status = ADD_STA_SUCCESS; | 286 | status = ADD_STA_SUCCESS; |
| 178 | ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(add_sta_cmd), | 287 | ret = iwl_mvm_send_add_sta_cmd_status(mvm, &add_sta_cmd, &status); |
| 179 | &add_sta_cmd, &status); | ||
| 180 | if (ret) | 288 | if (ret) |
| 181 | return ret; | 289 | return ret; |
| 182 | 290 | ||
| @@ -229,8 +337,12 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm, | |||
| 229 | if (vif->hw_queue[i] != IEEE80211_INVAL_HW_QUEUE) | 337 | if (vif->hw_queue[i] != IEEE80211_INVAL_HW_QUEUE) |
| 230 | mvm_sta->tfd_queue_msk |= BIT(vif->hw_queue[i]); | 338 | mvm_sta->tfd_queue_msk |= BIT(vif->hw_queue[i]); |
| 231 | 339 | ||
| 232 | /* for HW restart - need to reset the seq_number etc... */ | 340 | /* for HW restart - reset everything but the sequence number */ |
| 233 | memset(mvm_sta->tid_data, 0, sizeof(mvm_sta->tid_data)); | 341 | for (i = 0; i < IWL_MAX_TID_COUNT; i++) { |
| 342 | u16 seq = mvm_sta->tid_data[i].seq_number; | ||
| 343 | memset(&mvm_sta->tid_data[i], 0, sizeof(mvm_sta->tid_data[i])); | ||
| 344 | mvm_sta->tid_data[i].seq_number = seq; | ||
| 345 | } | ||
| 234 | 346 | ||
| 235 | ret = iwl_mvm_sta_send_to_fw(mvm, sta, false); | 347 | ret = iwl_mvm_sta_send_to_fw(mvm, sta, false); |
| 236 | if (ret) | 348 | if (ret) |
| @@ -256,7 +368,7 @@ int iwl_mvm_update_sta(struct iwl_mvm *mvm, | |||
| 256 | int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, | 368 | int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, |
| 257 | bool drain) | 369 | bool drain) |
| 258 | { | 370 | { |
| 259 | struct iwl_mvm_add_sta_cmd cmd = {}; | 371 | struct iwl_mvm_add_sta_cmd_v6 cmd = {}; |
| 260 | int ret; | 372 | int ret; |
| 261 | u32 status; | 373 | u32 status; |
| 262 | 374 | ||
| @@ -269,8 +381,7 @@ int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, | |||
| 269 | cmd.station_flags_msk = cpu_to_le32(STA_FLG_DRAIN_FLOW); | 381 | cmd.station_flags_msk = cpu_to_le32(STA_FLG_DRAIN_FLOW); |
| 270 | 382 | ||
| 271 | status = ADD_STA_SUCCESS; | 383 | status = ADD_STA_SUCCESS; |
| 272 | ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd), | 384 | ret = iwl_mvm_send_add_sta_cmd_status(mvm, &cmd, &status); |
| 273 | &cmd, &status); | ||
| 274 | if (ret) | 385 | if (ret) |
| 275 | return ret; | 386 | return ret; |
| 276 | 387 | ||
| @@ -469,13 +580,13 @@ static int iwl_mvm_add_int_sta_common(struct iwl_mvm *mvm, | |||
| 469 | const u8 *addr, | 580 | const u8 *addr, |
| 470 | u16 mac_id, u16 color) | 581 | u16 mac_id, u16 color) |
| 471 | { | 582 | { |
| 472 | struct iwl_mvm_add_sta_cmd cmd; | 583 | struct iwl_mvm_add_sta_cmd_v6 cmd; |
| 473 | int ret; | 584 | int ret; |
| 474 | u32 status; | 585 | u32 status; |
| 475 | 586 | ||
| 476 | lockdep_assert_held(&mvm->mutex); | 587 | lockdep_assert_held(&mvm->mutex); |
| 477 | 588 | ||
| 478 | memset(&cmd, 0, sizeof(struct iwl_mvm_add_sta_cmd)); | 589 | memset(&cmd, 0, sizeof(struct iwl_mvm_add_sta_cmd_v6)); |
| 479 | cmd.sta_id = sta->sta_id; | 590 | cmd.sta_id = sta->sta_id; |
| 480 | cmd.mac_id_n_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mac_id, | 591 | cmd.mac_id_n_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mac_id, |
| 481 | color)); | 592 | color)); |
| @@ -485,8 +596,7 @@ static int iwl_mvm_add_int_sta_common(struct iwl_mvm *mvm, | |||
| 485 | if (addr) | 596 | if (addr) |
| 486 | memcpy(cmd.addr, addr, ETH_ALEN); | 597 | memcpy(cmd.addr, addr, ETH_ALEN); |
| 487 | 598 | ||
| 488 | ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd), | 599 | ret = iwl_mvm_send_add_sta_cmd_status(mvm, &cmd, &status); |
| 489 | &cmd, &status); | ||
| 490 | if (ret) | 600 | if (ret) |
| 491 | return ret; | 601 | return ret; |
| 492 | 602 | ||
| @@ -534,10 +644,14 @@ int iwl_mvm_send_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
| 534 | struct iwl_mvm_int_sta *bsta) | 644 | struct iwl_mvm_int_sta *bsta) |
| 535 | { | 645 | { |
| 536 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 646 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
| 537 | static const u8 baddr[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; | 647 | static const u8 _baddr[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; |
| 648 | static const u8 *baddr = _baddr; | ||
| 538 | 649 | ||
| 539 | lockdep_assert_held(&mvm->mutex); | 650 | lockdep_assert_held(&mvm->mutex); |
| 540 | 651 | ||
| 652 | if (vif->type == NL80211_IFTYPE_ADHOC) | ||
| 653 | baddr = vif->bss_conf.bssid; | ||
| 654 | |||
| 541 | if (WARN_ON_ONCE(bsta->sta_id == IWL_MVM_STATION_COUNT)) | 655 | if (WARN_ON_ONCE(bsta->sta_id == IWL_MVM_STATION_COUNT)) |
| 542 | return -ENOSPC; | 656 | return -ENOSPC; |
| 543 | 657 | ||
| @@ -614,7 +728,7 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
| 614 | int tid, u16 ssn, bool start) | 728 | int tid, u16 ssn, bool start) |
| 615 | { | 729 | { |
| 616 | struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; | 730 | struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; |
| 617 | struct iwl_mvm_add_sta_cmd cmd = {}; | 731 | struct iwl_mvm_add_sta_cmd_v6 cmd = {}; |
| 618 | int ret; | 732 | int ret; |
| 619 | u32 status; | 733 | u32 status; |
| 620 | 734 | ||
| @@ -638,8 +752,7 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
| 638 | STA_MODIFY_REMOVE_BA_TID; | 752 | STA_MODIFY_REMOVE_BA_TID; |
| 639 | 753 | ||
| 640 | status = ADD_STA_SUCCESS; | 754 | status = ADD_STA_SUCCESS; |
| 641 | ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd), | 755 | ret = iwl_mvm_send_add_sta_cmd_status(mvm, &cmd, &status); |
| 642 | &cmd, &status); | ||
| 643 | if (ret) | 756 | if (ret) |
| 644 | return ret; | 757 | return ret; |
| 645 | 758 | ||
| @@ -674,7 +787,7 @@ static int iwl_mvm_sta_tx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
| 674 | int tid, u8 queue, bool start) | 787 | int tid, u8 queue, bool start) |
| 675 | { | 788 | { |
| 676 | struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; | 789 | struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; |
| 677 | struct iwl_mvm_add_sta_cmd cmd = {}; | 790 | struct iwl_mvm_add_sta_cmd_v6 cmd = {}; |
| 678 | int ret; | 791 | int ret; |
| 679 | u32 status; | 792 | u32 status; |
| 680 | 793 | ||
| @@ -696,8 +809,7 @@ static int iwl_mvm_sta_tx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
| 696 | cmd.tid_disable_tx = cpu_to_le16(mvm_sta->tid_disable_agg); | 809 | cmd.tid_disable_tx = cpu_to_le16(mvm_sta->tid_disable_agg); |
| 697 | 810 | ||
| 698 | status = ADD_STA_SUCCESS; | 811 | status = ADD_STA_SUCCESS; |
| 699 | ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd), | 812 | ret = iwl_mvm_send_add_sta_cmd_status(mvm, &cmd, &status); |
| 700 | &cmd, &status); | ||
| 701 | if (ret) | 813 | if (ret) |
| 702 | return ret; | 814 | return ret; |
| 703 | 815 | ||
| @@ -743,13 +855,13 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
| 743 | 855 | ||
| 744 | lockdep_assert_held(&mvm->mutex); | 856 | lockdep_assert_held(&mvm->mutex); |
| 745 | 857 | ||
| 746 | for (txq_id = IWL_MVM_FIRST_AGG_QUEUE; | 858 | for (txq_id = mvm->first_agg_queue; |
| 747 | txq_id <= IWL_MVM_LAST_AGG_QUEUE; txq_id++) | 859 | txq_id <= mvm->last_agg_queue; txq_id++) |
| 748 | if (mvm->queue_to_mac80211[txq_id] == | 860 | if (mvm->queue_to_mac80211[txq_id] == |
| 749 | IWL_INVALID_MAC80211_QUEUE) | 861 | IWL_INVALID_MAC80211_QUEUE) |
| 750 | break; | 862 | break; |
| 751 | 863 | ||
| 752 | if (txq_id > IWL_MVM_LAST_AGG_QUEUE) { | 864 | if (txq_id > mvm->last_agg_queue) { |
| 753 | IWL_ERR(mvm, "Failed to allocate agg queue\n"); | 865 | IWL_ERR(mvm, "Failed to allocate agg queue\n"); |
| 754 | return -EIO; | 866 | return -EIO; |
| 755 | } | 867 | } |
| @@ -987,10 +1099,11 @@ static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm, | |||
| 987 | u32 cmd_flags) | 1099 | u32 cmd_flags) |
| 988 | { | 1100 | { |
| 989 | __le16 key_flags; | 1101 | __le16 key_flags; |
| 990 | struct iwl_mvm_add_sta_cmd cmd = {}; | 1102 | struct iwl_mvm_add_sta_key_cmd cmd = {}; |
| 991 | int ret, status; | 1103 | int ret, status; |
| 992 | u16 keyidx; | 1104 | u16 keyidx; |
| 993 | int i; | 1105 | int i; |
| 1106 | u32 mac_id_n_color = mvm_sta->mac_id_n_color; | ||
| 994 | 1107 | ||
| 995 | keyidx = (keyconf->keyidx << STA_KEY_FLG_KEYID_POS) & | 1108 | keyidx = (keyconf->keyidx << STA_KEY_FLG_KEYID_POS) & |
| 996 | STA_KEY_FLG_KEYID_MSK; | 1109 | STA_KEY_FLG_KEYID_MSK; |
| @@ -1000,14 +1113,14 @@ static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm, | |||
| 1000 | switch (keyconf->cipher) { | 1113 | switch (keyconf->cipher) { |
| 1001 | case WLAN_CIPHER_SUITE_TKIP: | 1114 | case WLAN_CIPHER_SUITE_TKIP: |
| 1002 | key_flags |= cpu_to_le16(STA_KEY_FLG_TKIP); | 1115 | key_flags |= cpu_to_le16(STA_KEY_FLG_TKIP); |
| 1003 | cmd.key.tkip_rx_tsc_byte2 = tkip_iv32; | 1116 | cmd.tkip_rx_tsc_byte2 = tkip_iv32; |
| 1004 | for (i = 0; i < 5; i++) | 1117 | for (i = 0; i < 5; i++) |
| 1005 | cmd.key.tkip_rx_ttak[i] = cpu_to_le16(tkip_p1k[i]); | 1118 | cmd.tkip_rx_ttak[i] = cpu_to_le16(tkip_p1k[i]); |
| 1006 | memcpy(cmd.key.key, keyconf->key, keyconf->keylen); | 1119 | memcpy(cmd.key, keyconf->key, keyconf->keylen); |
| 1007 | break; | 1120 | break; |
| 1008 | case WLAN_CIPHER_SUITE_CCMP: | 1121 | case WLAN_CIPHER_SUITE_CCMP: |
| 1009 | key_flags |= cpu_to_le16(STA_KEY_FLG_CCM); | 1122 | key_flags |= cpu_to_le16(STA_KEY_FLG_CCM); |
| 1010 | memcpy(cmd.key.key, keyconf->key, keyconf->keylen); | 1123 | memcpy(cmd.key, keyconf->key, keyconf->keylen); |
| 1011 | break; | 1124 | break; |
| 1012 | default: | 1125 | default: |
| 1013 | WARN_ON(1); | 1126 | WARN_ON(1); |
| @@ -1017,20 +1130,18 @@ static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm, | |||
| 1017 | if (!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE)) | 1130 | if (!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE)) |
| 1018 | key_flags |= cpu_to_le16(STA_KEY_MULTICAST); | 1131 | key_flags |= cpu_to_le16(STA_KEY_MULTICAST); |
| 1019 | 1132 | ||
| 1020 | cmd.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color); | 1133 | cmd.key_offset = keyconf->hw_key_idx; |
| 1021 | cmd.key.key_offset = keyconf->hw_key_idx; | 1134 | cmd.key_flags = key_flags; |
| 1022 | cmd.key.key_flags = key_flags; | ||
| 1023 | cmd.add_modify = STA_MODE_MODIFY; | ||
| 1024 | cmd.modify_mask = STA_MODIFY_KEY; | ||
| 1025 | cmd.sta_id = sta_id; | 1135 | cmd.sta_id = sta_id; |
| 1026 | 1136 | ||
| 1027 | status = ADD_STA_SUCCESS; | 1137 | status = ADD_STA_SUCCESS; |
| 1028 | if (cmd_flags == CMD_SYNC) | 1138 | if (cmd_flags == CMD_SYNC) |
| 1029 | ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd), | 1139 | ret = iwl_mvm_send_add_sta_key_cmd_status(mvm, &cmd, |
| 1030 | &cmd, &status); | 1140 | mac_id_n_color, |
| 1141 | &status); | ||
| 1031 | else | 1142 | else |
| 1032 | ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC, | 1143 | ret = iwl_mvm_send_add_sta_key_cmd(mvm, CMD_ASYNC, &cmd, |
| 1033 | sizeof(cmd), &cmd); | 1144 | mac_id_n_color); |
| 1034 | 1145 | ||
| 1035 | switch (status) { | 1146 | switch (status) { |
| 1036 | case ADD_STA_SUCCESS: | 1147 | case ADD_STA_SUCCESS: |
| @@ -1197,7 +1308,7 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, | |||
| 1197 | struct ieee80211_key_conf *keyconf) | 1308 | struct ieee80211_key_conf *keyconf) |
| 1198 | { | 1309 | { |
| 1199 | struct iwl_mvm_sta *mvm_sta; | 1310 | struct iwl_mvm_sta *mvm_sta; |
| 1200 | struct iwl_mvm_add_sta_cmd cmd = {}; | 1311 | struct iwl_mvm_add_sta_key_cmd cmd = {}; |
| 1201 | __le16 key_flags; | 1312 | __le16 key_flags; |
| 1202 | int ret, status; | 1313 | int ret, status; |
| 1203 | u8 sta_id; | 1314 | u8 sta_id; |
| @@ -1252,17 +1363,14 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, | |||
| 1252 | if (!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE)) | 1363 | if (!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE)) |
| 1253 | key_flags |= cpu_to_le16(STA_KEY_MULTICAST); | 1364 | key_flags |= cpu_to_le16(STA_KEY_MULTICAST); |
| 1254 | 1365 | ||
| 1255 | cmd.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color); | 1366 | cmd.key_flags = key_flags; |
| 1256 | cmd.key.key_flags = key_flags; | 1367 | cmd.key_offset = keyconf->hw_key_idx; |
| 1257 | cmd.key.key_offset = keyconf->hw_key_idx; | ||
| 1258 | cmd.sta_id = sta_id; | 1368 | cmd.sta_id = sta_id; |
| 1259 | 1369 | ||
| 1260 | cmd.modify_mask = STA_MODIFY_KEY; | ||
| 1261 | cmd.add_modify = STA_MODE_MODIFY; | ||
| 1262 | |||
| 1263 | status = ADD_STA_SUCCESS; | 1370 | status = ADD_STA_SUCCESS; |
| 1264 | ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd), | 1371 | ret = iwl_mvm_send_add_sta_key_cmd_status(mvm, &cmd, |
| 1265 | &cmd, &status); | 1372 | mvm_sta->mac_id_n_color, |
| 1373 | &status); | ||
| 1266 | 1374 | ||
| 1267 | switch (status) { | 1375 | switch (status) { |
| 1268 | case ADD_STA_SUCCESS: | 1376 | case ADD_STA_SUCCESS: |
| @@ -1309,7 +1417,7 @@ void iwl_mvm_sta_modify_ps_wake(struct iwl_mvm *mvm, | |||
| 1309 | struct ieee80211_sta *sta) | 1417 | struct ieee80211_sta *sta) |
| 1310 | { | 1418 | { |
| 1311 | struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv; | 1419 | struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv; |
| 1312 | struct iwl_mvm_add_sta_cmd cmd = { | 1420 | struct iwl_mvm_add_sta_cmd_v6 cmd = { |
| 1313 | .add_modify = STA_MODE_MODIFY, | 1421 | .add_modify = STA_MODE_MODIFY, |
| 1314 | .sta_id = mvmsta->sta_id, | 1422 | .sta_id = mvmsta->sta_id, |
| 1315 | .station_flags_msk = cpu_to_le32(STA_FLG_PS), | 1423 | .station_flags_msk = cpu_to_le32(STA_FLG_PS), |
| @@ -1317,7 +1425,7 @@ void iwl_mvm_sta_modify_ps_wake(struct iwl_mvm *mvm, | |||
| 1317 | }; | 1425 | }; |
| 1318 | int ret; | 1426 | int ret; |
| 1319 | 1427 | ||
| 1320 | ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC, sizeof(cmd), &cmd); | 1428 | ret = iwl_mvm_send_add_sta_cmd(mvm, CMD_ASYNC, &cmd); |
| 1321 | if (ret) | 1429 | if (ret) |
| 1322 | IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret); | 1430 | IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret); |
| 1323 | } | 1431 | } |
| @@ -1331,7 +1439,7 @@ void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm, | |||
| 1331 | (reason == IEEE80211_FRAME_RELEASE_UAPSD) ? | 1439 | (reason == IEEE80211_FRAME_RELEASE_UAPSD) ? |
| 1332 | STA_SLEEP_STATE_UAPSD : STA_SLEEP_STATE_PS_POLL; | 1440 | STA_SLEEP_STATE_UAPSD : STA_SLEEP_STATE_PS_POLL; |
| 1333 | struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv; | 1441 | struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv; |
| 1334 | struct iwl_mvm_add_sta_cmd cmd = { | 1442 | struct iwl_mvm_add_sta_cmd_v6 cmd = { |
| 1335 | .add_modify = STA_MODE_MODIFY, | 1443 | .add_modify = STA_MODE_MODIFY, |
| 1336 | .sta_id = mvmsta->sta_id, | 1444 | .sta_id = mvmsta->sta_id, |
| 1337 | .modify_mask = STA_MODIFY_SLEEPING_STA_TX_COUNT, | 1445 | .modify_mask = STA_MODIFY_SLEEPING_STA_TX_COUNT, |
| @@ -1346,7 +1454,7 @@ void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm, | |||
| 1346 | int ret; | 1454 | int ret; |
| 1347 | 1455 | ||
| 1348 | /* TODO: somehow the fw doesn't seem to take PS_POLL into account */ | 1456 | /* TODO: somehow the fw doesn't seem to take PS_POLL into account */ |
| 1349 | ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC, sizeof(cmd), &cmd); | 1457 | ret = iwl_mvm_send_add_sta_cmd(mvm, CMD_ASYNC, &cmd); |
| 1350 | if (ret) | 1458 | if (ret) |
| 1351 | IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret); | 1459 | IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret); |
| 1352 | } | 1460 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.h b/drivers/net/wireless/iwlwifi/mvm/sta.h index 94b265eb32b8..4dfc359a4bdd 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.h +++ b/drivers/net/wireless/iwlwifi/mvm/sta.h | |||
| @@ -293,10 +293,6 @@ struct iwl_mvm_sta { | |||
| 293 | struct iwl_lq_sta lq_sta; | 293 | struct iwl_lq_sta lq_sta; |
| 294 | struct ieee80211_vif *vif; | 294 | struct ieee80211_vif *vif; |
| 295 | 295 | ||
| 296 | #ifdef CONFIG_PM_SLEEP | ||
| 297 | u16 last_seq_ctl; | ||
| 298 | #endif | ||
| 299 | |||
| 300 | /* Temporary, until the new TLC will control the Tx protection */ | 296 | /* Temporary, until the new TLC will control the Tx protection */ |
| 301 | s8 tx_protection; | 297 | s8 tx_protection; |
| 302 | bool tt_tx_protection; | 298 | bool tt_tx_protection; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/testmode.h b/drivers/net/wireless/iwlwifi/mvm/testmode.h new file mode 100644 index 000000000000..eb74391d91ca --- /dev/null +++ b/drivers/net/wireless/iwlwifi/mvm/testmode.h | |||
| @@ -0,0 +1,95 @@ | |||
| 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) 2013 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) 2013 Intel Corporation. All rights reserved. | ||
| 34 | * All rights reserved. | ||
| 35 | * | ||
| 36 | * Redistribution and use in source and binary forms, with or without | ||
| 37 | * modification, are permitted provided that the following conditions | ||
| 38 | * are met: | ||
| 39 | * | ||
| 40 | * * Redistributions of source code must retain the above copyright | ||
| 41 | * notice, this list of conditions and the following disclaimer. | ||
| 42 | * * Redistributions in binary form must reproduce the above copyright | ||
| 43 | * notice, this list of conditions and the following disclaimer in | ||
| 44 | * the documentation and/or other materials provided with the | ||
| 45 | * distribution. | ||
| 46 | * * Neither the name Intel Corporation nor the names of its | ||
| 47 | * contributors may be used to endorse or promote products derived | ||
| 48 | * from this software without specific prior written permission. | ||
| 49 | * | ||
| 50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
| 51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
| 52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
| 53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
| 54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
| 55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
| 56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
| 57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
| 58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| 59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
| 60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 61 | * | ||
| 62 | *****************************************************************************/ | ||
| 63 | |||
| 64 | #ifndef __IWL_MVM_TESTMODE_H__ | ||
| 65 | #define __IWL_MVM_TESTMODE_H__ | ||
| 66 | |||
| 67 | /** | ||
| 68 | * enum iwl_mvm_testmode_attrs - testmode attributes inside NL80211_ATTR_TESTDATA | ||
| 69 | * @IWL_MVM_TM_ATTR_UNSPEC: (invalid attribute) | ||
| 70 | * @IWL_MVM_TM_ATTR_CMD: sub command, see &enum iwl_mvm_testmode_commands (u32) | ||
| 71 | * @IWL_MVM_TM_ATTR_NOA_DURATION: requested NoA duration (u32) | ||
| 72 | * @IWL_MVM_TM_ATTR_BEACON_FILTER_STATE: beacon filter state (0 or 1, u32) | ||
| 73 | */ | ||
| 74 | enum iwl_mvm_testmode_attrs { | ||
| 75 | IWL_MVM_TM_ATTR_UNSPEC, | ||
| 76 | IWL_MVM_TM_ATTR_CMD, | ||
| 77 | IWL_MVM_TM_ATTR_NOA_DURATION, | ||
| 78 | IWL_MVM_TM_ATTR_BEACON_FILTER_STATE, | ||
| 79 | |||
| 80 | /* keep last */ | ||
| 81 | NUM_IWL_MVM_TM_ATTRS, | ||
| 82 | IWL_MVM_TM_ATTR_MAX = NUM_IWL_MVM_TM_ATTRS - 1, | ||
| 83 | }; | ||
| 84 | |||
| 85 | /** | ||
| 86 | * enum iwl_mvm_testmode_commands - MVM testmode commands | ||
| 87 | * @IWL_MVM_TM_CMD_SET_NOA: set NoA on GO vif for testing | ||
| 88 | * @IWL_MVM_TM_CMD_SET_BEACON_FILTER: turn beacon filtering off/on | ||
| 89 | */ | ||
| 90 | enum iwl_mvm_testmode_commands { | ||
| 91 | IWL_MVM_TM_CMD_SET_NOA, | ||
| 92 | IWL_MVM_TM_CMD_SET_BEACON_FILTER, | ||
| 93 | }; | ||
| 94 | |||
| 95 | #endif /* __IWL_MVM_TESTMODE_H__ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c index 76a3c177e100..33cf56fdfc41 100644 --- a/drivers/net/wireless/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c | |||
| @@ -387,7 +387,8 @@ static int iwl_mvm_time_event_send_add(struct iwl_mvm *mvm, | |||
| 387 | 387 | ||
| 388 | void iwl_mvm_protect_session(struct iwl_mvm *mvm, | 388 | void iwl_mvm_protect_session(struct iwl_mvm *mvm, |
| 389 | struct ieee80211_vif *vif, | 389 | struct ieee80211_vif *vif, |
| 390 | u32 duration, u32 min_duration) | 390 | u32 duration, u32 min_duration, |
| 391 | u32 max_delay) | ||
| 391 | { | 392 | { |
| 392 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 393 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
| 393 | struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data; | 394 | struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data; |
| @@ -426,7 +427,7 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm, | |||
| 426 | cpu_to_le32(iwl_read_prph(mvm->trans, DEVICE_SYSTEM_TIME_REG)); | 427 | cpu_to_le32(iwl_read_prph(mvm->trans, DEVICE_SYSTEM_TIME_REG)); |
| 427 | 428 | ||
| 428 | time_cmd.max_frags = TE_V2_FRAG_NONE; | 429 | time_cmd.max_frags = TE_V2_FRAG_NONE; |
| 429 | time_cmd.max_delay = cpu_to_le32(500); | 430 | time_cmd.max_delay = cpu_to_le32(max_delay); |
| 430 | /* TODO: why do we need to interval = bi if it is not periodic? */ | 431 | /* TODO: why do we need to interval = bi if it is not periodic? */ |
| 431 | time_cmd.interval = cpu_to_le32(1); | 432 | time_cmd.interval = cpu_to_le32(1); |
| 432 | time_cmd.duration = cpu_to_le32(duration); | 433 | time_cmd.duration = cpu_to_le32(duration); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.h b/drivers/net/wireless/iwlwifi/mvm/time-event.h index f86c51065ed3..d9c8d6cfa2db 100644 --- a/drivers/net/wireless/iwlwifi/mvm/time-event.h +++ b/drivers/net/wireless/iwlwifi/mvm/time-event.h | |||
| @@ -123,6 +123,7 @@ | |||
| 123 | * @duration: the duration of the session in TU. | 123 | * @duration: the duration of the session in TU. |
| 124 | * @min_duration: will start a new session if the current session will end | 124 | * @min_duration: will start a new session if the current session will end |
| 125 | * in less than min_duration. | 125 | * in less than min_duration. |
| 126 | * @max_delay: maximum delay before starting the time event (in TU) | ||
| 126 | * | 127 | * |
| 127 | * This function can be used to start a session protection which means that the | 128 | * This function can be used to start a session protection which means that the |
| 128 | * fw will stay on the channel for %duration_ms milliseconds. This function | 129 | * fw will stay on the channel for %duration_ms milliseconds. This function |
| @@ -133,7 +134,8 @@ | |||
| 133 | */ | 134 | */ |
| 134 | void iwl_mvm_protect_session(struct iwl_mvm *mvm, | 135 | void iwl_mvm_protect_session(struct iwl_mvm *mvm, |
| 135 | struct ieee80211_vif *vif, | 136 | struct ieee80211_vif *vif, |
| 136 | u32 duration, u32 min_duration); | 137 | u32 duration, u32 min_duration, |
| 138 | u32 max_delay); | ||
| 137 | 139 | ||
| 138 | /** | 140 | /** |
| 139 | * iwl_mvm_stop_session_protection - cancel the session protection. | 141 | * iwl_mvm_stop_session_protection - cancel the session protection. |
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index e05440d90319..43d97c33a75a 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c | |||
| @@ -417,7 +417,7 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
| 417 | 417 | ||
| 418 | spin_unlock(&mvmsta->lock); | 418 | spin_unlock(&mvmsta->lock); |
| 419 | 419 | ||
| 420 | if (txq_id < IWL_MVM_FIRST_AGG_QUEUE) | 420 | if (txq_id < mvm->first_agg_queue) |
| 421 | atomic_inc(&mvm->pending_frames[mvmsta->sta_id]); | 421 | atomic_inc(&mvm->pending_frames[mvmsta->sta_id]); |
| 422 | 422 | ||
| 423 | return 0; | 423 | return 0; |
| @@ -511,16 +511,10 @@ const char *iwl_mvm_get_tx_fail_reason(u32 status) | |||
| 511 | } | 511 | } |
| 512 | #endif /* CONFIG_IWLWIFI_DEBUG */ | 512 | #endif /* CONFIG_IWLWIFI_DEBUG */ |
| 513 | 513 | ||
| 514 | /** | 514 | void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags, |
| 515 | * translate ucode response to mac80211 tx status control values | 515 | enum ieee80211_band band, |
| 516 | */ | 516 | struct ieee80211_tx_rate *r) |
| 517 | static void iwl_mvm_hwrate_to_tx_control(u32 rate_n_flags, | ||
| 518 | struct ieee80211_tx_info *info) | ||
| 519 | { | 517 | { |
| 520 | struct ieee80211_tx_rate *r = &info->status.rates[0]; | ||
| 521 | |||
| 522 | info->status.antenna = | ||
| 523 | ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS); | ||
| 524 | if (rate_n_flags & RATE_HT_MCS_GF_MSK) | 518 | if (rate_n_flags & RATE_HT_MCS_GF_MSK) |
| 525 | r->flags |= IEEE80211_TX_RC_GREEN_FIELD; | 519 | r->flags |= IEEE80211_TX_RC_GREEN_FIELD; |
| 526 | switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) { | 520 | switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) { |
| @@ -549,10 +543,23 @@ static void iwl_mvm_hwrate_to_tx_control(u32 rate_n_flags, | |||
| 549 | r->flags |= IEEE80211_TX_RC_VHT_MCS; | 543 | r->flags |= IEEE80211_TX_RC_VHT_MCS; |
| 550 | } else { | 544 | } else { |
| 551 | r->idx = iwl_mvm_legacy_rate_to_mac80211_idx(rate_n_flags, | 545 | r->idx = iwl_mvm_legacy_rate_to_mac80211_idx(rate_n_flags, |
| 552 | info->band); | 546 | band); |
| 553 | } | 547 | } |
| 554 | } | 548 | } |
| 555 | 549 | ||
| 550 | /** | ||
| 551 | * translate ucode response to mac80211 tx status control values | ||
| 552 | */ | ||
| 553 | static void iwl_mvm_hwrate_to_tx_status(u32 rate_n_flags, | ||
| 554 | struct ieee80211_tx_info *info) | ||
| 555 | { | ||
| 556 | struct ieee80211_tx_rate *r = &info->status.rates[0]; | ||
| 557 | |||
| 558 | info->status.antenna = | ||
| 559 | ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS); | ||
| 560 | iwl_mvm_hwrate_to_tx_rate(rate_n_flags, info->band, r); | ||
| 561 | } | ||
| 562 | |||
| 556 | static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, | 563 | static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, |
| 557 | struct iwl_rx_packet *pkt) | 564 | struct iwl_rx_packet *pkt) |
| 558 | { | 565 | { |
| @@ -602,11 +609,11 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, | |||
| 602 | } | 609 | } |
| 603 | 610 | ||
| 604 | info->status.rates[0].count = tx_resp->failure_frame + 1; | 611 | info->status.rates[0].count = tx_resp->failure_frame + 1; |
| 605 | iwl_mvm_hwrate_to_tx_control(le32_to_cpu(tx_resp->initial_rate), | 612 | iwl_mvm_hwrate_to_tx_status(le32_to_cpu(tx_resp->initial_rate), |
| 606 | info); | 613 | info); |
| 607 | 614 | ||
| 608 | /* Single frame failure in an AMPDU queue => send BAR */ | 615 | /* Single frame failure in an AMPDU queue => send BAR */ |
| 609 | if (txq_id >= IWL_MVM_FIRST_AGG_QUEUE && | 616 | if (txq_id >= mvm->first_agg_queue && |
| 610 | !(info->flags & IEEE80211_TX_STAT_ACK)) | 617 | !(info->flags & IEEE80211_TX_STAT_ACK)) |
| 611 | info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; | 618 | info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; |
| 612 | 619 | ||
| @@ -619,7 +626,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, | |||
| 619 | ieee80211_tx_status_ni(mvm->hw, skb); | 626 | ieee80211_tx_status_ni(mvm->hw, skb); |
| 620 | } | 627 | } |
| 621 | 628 | ||
| 622 | if (txq_id >= IWL_MVM_FIRST_AGG_QUEUE) { | 629 | if (txq_id >= mvm->first_agg_queue) { |
| 623 | /* If this is an aggregation queue, we use the ssn since: | 630 | /* If this is an aggregation queue, we use the ssn since: |
| 624 | * ssn = wifi seq_num % 256. | 631 | * ssn = wifi seq_num % 256. |
| 625 | * The seq_ctl is the sequence control of the packet to which | 632 | * The seq_ctl is the sequence control of the packet to which |
| @@ -668,10 +675,6 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, | |||
| 668 | iwl_mvm_check_ratid_empty(mvm, sta, tid); | 675 | iwl_mvm_check_ratid_empty(mvm, sta, tid); |
| 669 | spin_unlock_bh(&mvmsta->lock); | 676 | spin_unlock_bh(&mvmsta->lock); |
| 670 | } | 677 | } |
| 671 | |||
| 672 | #ifdef CONFIG_PM_SLEEP | ||
| 673 | mvmsta->last_seq_ctl = seq_ctl; | ||
| 674 | #endif | ||
| 675 | } else { | 678 | } else { |
| 676 | sta = NULL; | 679 | sta = NULL; |
| 677 | mvmsta = NULL; | 680 | mvmsta = NULL; |
| @@ -681,7 +684,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, | |||
| 681 | * If the txq is not an AMPDU queue, there is no chance we freed | 684 | * If the txq is not an AMPDU queue, there is no chance we freed |
| 682 | * several skbs. Check that out... | 685 | * several skbs. Check that out... |
| 683 | */ | 686 | */ |
| 684 | if (txq_id < IWL_MVM_FIRST_AGG_QUEUE && !WARN_ON(skb_freed > 1) && | 687 | if (txq_id < mvm->first_agg_queue && !WARN_ON(skb_freed > 1) && |
| 685 | atomic_sub_and_test(skb_freed, &mvm->pending_frames[sta_id])) { | 688 | atomic_sub_and_test(skb_freed, &mvm->pending_frames[sta_id])) { |
| 686 | if (mvmsta) { | 689 | if (mvmsta) { |
| 687 | /* | 690 | /* |
| @@ -777,7 +780,7 @@ static void iwl_mvm_rx_tx_cmd_agg(struct iwl_mvm *mvm, | |||
| 777 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); | 780 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); |
| 778 | struct ieee80211_sta *sta; | 781 | struct ieee80211_sta *sta; |
| 779 | 782 | ||
| 780 | if (WARN_ON_ONCE(SEQ_TO_QUEUE(sequence) < IWL_MVM_FIRST_AGG_QUEUE)) | 783 | if (WARN_ON_ONCE(SEQ_TO_QUEUE(sequence) < mvm->first_agg_queue)) |
| 781 | return; | 784 | return; |
| 782 | 785 | ||
| 783 | if (WARN_ON_ONCE(tid == IWL_TID_NON_QOS)) | 786 | if (WARN_ON_ONCE(tid == IWL_TID_NON_QOS)) |
| @@ -904,8 +907,8 @@ int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | |||
| 904 | info->flags |= IEEE80211_TX_STAT_AMPDU; | 907 | info->flags |= IEEE80211_TX_STAT_AMPDU; |
| 905 | info->status.ampdu_ack_len = ba_notif->txed_2_done; | 908 | info->status.ampdu_ack_len = ba_notif->txed_2_done; |
| 906 | info->status.ampdu_len = ba_notif->txed; | 909 | info->status.ampdu_len = ba_notif->txed; |
| 907 | iwl_mvm_hwrate_to_tx_control(tid_data->rate_n_flags, | 910 | iwl_mvm_hwrate_to_tx_status(tid_data->rate_n_flags, |
| 908 | info); | 911 | info); |
| 909 | } | 912 | } |
| 910 | } | 913 | } |
| 911 | 914 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c index a9c357491434..ed69e9b78e82 100644 --- a/drivers/net/wireless/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/iwlwifi/mvm/utils.c | |||
| @@ -466,7 +466,7 @@ void iwl_mvm_dump_sram(struct iwl_mvm *mvm) | |||
| 466 | ofs = img->sec[IWL_UCODE_SECTION_DATA].offset; | 466 | ofs = img->sec[IWL_UCODE_SECTION_DATA].offset; |
| 467 | len = img->sec[IWL_UCODE_SECTION_DATA].len; | 467 | len = img->sec[IWL_UCODE_SECTION_DATA].len; |
| 468 | 468 | ||
| 469 | buf = kzalloc(len, GFP_KERNEL); | 469 | buf = kzalloc(len, GFP_ATOMIC); |
| 470 | if (!buf) | 470 | if (!buf) |
| 471 | return; | 471 | return; |
| 472 | 472 | ||
diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c index 26108a1a29fa..941c0c88f982 100644 --- a/drivers/net/wireless/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/iwlwifi/pcie/drv.c | |||
| @@ -268,7 +268,7 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { | |||
| 268 | #endif /* CONFIG_IWLDVM */ | 268 | #endif /* CONFIG_IWLDVM */ |
| 269 | 269 | ||
| 270 | #if IS_ENABLED(CONFIG_IWLMVM) | 270 | #if IS_ENABLED(CONFIG_IWLMVM) |
| 271 | /* 7000 Series */ | 271 | /* 7260 Series */ |
| 272 | {IWL_PCI_DEVICE(0x08B1, 0x4070, iwl7260_2ac_cfg)}, | 272 | {IWL_PCI_DEVICE(0x08B1, 0x4070, iwl7260_2ac_cfg)}, |
| 273 | {IWL_PCI_DEVICE(0x08B1, 0x4072, iwl7260_2ac_cfg)}, | 273 | {IWL_PCI_DEVICE(0x08B1, 0x4072, iwl7260_2ac_cfg)}, |
| 274 | {IWL_PCI_DEVICE(0x08B1, 0x4170, iwl7260_2ac_cfg)}, | 274 | {IWL_PCI_DEVICE(0x08B1, 0x4170, iwl7260_2ac_cfg)}, |
| @@ -350,6 +350,9 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { | |||
| 350 | {IWL_PCI_DEVICE(0x08B4, 0x8270, iwl3160_2ac_cfg)}, | 350 | {IWL_PCI_DEVICE(0x08B4, 0x8270, iwl3160_2ac_cfg)}, |
| 351 | {IWL_PCI_DEVICE(0x08B3, 0x8470, iwl3160_2ac_cfg)}, | 351 | {IWL_PCI_DEVICE(0x08B3, 0x8470, iwl3160_2ac_cfg)}, |
| 352 | {IWL_PCI_DEVICE(0x08B3, 0x8570, iwl3160_2ac_cfg)}, | 352 | {IWL_PCI_DEVICE(0x08B3, 0x8570, iwl3160_2ac_cfg)}, |
| 353 | |||
| 354 | /* 7265 Series */ | ||
| 355 | {IWL_PCI_DEVICE(0x095A, 0x5010, iwl7265_2ac_cfg)}, | ||
| 353 | #endif /* CONFIG_IWLMVM */ | 356 | #endif /* CONFIG_IWLMVM */ |
| 354 | 357 | ||
| 355 | {0} | 358 | {0} |
| @@ -391,7 +394,6 @@ out_free_drv: | |||
| 391 | iwl_drv_stop(trans_pcie->drv); | 394 | iwl_drv_stop(trans_pcie->drv); |
| 392 | out_free_trans: | 395 | out_free_trans: |
| 393 | iwl_trans_pcie_free(iwl_trans); | 396 | iwl_trans_pcie_free(iwl_trans); |
| 394 | pci_set_drvdata(pdev, NULL); | ||
| 395 | return ret; | 397 | return ret; |
| 396 | } | 398 | } |
| 397 | 399 | ||
| @@ -402,8 +404,6 @@ static void iwl_pci_remove(struct pci_dev *pdev) | |||
| 402 | 404 | ||
| 403 | iwl_drv_stop(trans_pcie->drv); | 405 | iwl_drv_stop(trans_pcie->drv); |
| 404 | iwl_trans_pcie_free(trans); | 406 | iwl_trans_pcie_free(trans); |
| 405 | |||
| 406 | pci_set_drvdata(pdev, NULL); | ||
| 407 | } | 407 | } |
| 408 | 408 | ||
| 409 | #ifdef CONFIG_PM_SLEEP | 409 | #ifdef CONFIG_PM_SLEEP |
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index c3f904d422b0..5d9337bec67a 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c | |||
| @@ -220,6 +220,9 @@ static int iwl_pcie_apm_init(struct iwl_trans *trans) | |||
| 220 | iwl_set_bits_prph(trans, APMG_PCIDEV_STT_REG, | 220 | iwl_set_bits_prph(trans, APMG_PCIDEV_STT_REG, |
| 221 | APMG_PCIDEV_STT_VAL_L1_ACT_DIS); | 221 | APMG_PCIDEV_STT_VAL_L1_ACT_DIS); |
| 222 | 222 | ||
| 223 | /* Clear the interrupt in APMG if the NIC is in RFKILL */ | ||
| 224 | iwl_write_prph(trans, APMG_RTC_INT_STT_REG, APMG_RTC_INT_STT_RFKILL); | ||
| 225 | |||
| 223 | set_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status); | 226 | set_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status); |
| 224 | 227 | ||
| 225 | out: | 228 | out: |
| @@ -443,22 +446,138 @@ static int iwl_pcie_load_section(struct iwl_trans *trans, u8 section_num, | |||
| 443 | return ret; | 446 | return ret; |
| 444 | } | 447 | } |
| 445 | 448 | ||
| 449 | static int iwl_pcie_secure_set(struct iwl_trans *trans, int cpu) | ||
| 450 | { | ||
| 451 | int shift_param; | ||
| 452 | u32 address; | ||
| 453 | int ret = 0; | ||
| 454 | |||
| 455 | if (cpu == 1) { | ||
| 456 | shift_param = 0; | ||
| 457 | address = CSR_SECURE_BOOT_CPU1_STATUS_ADDR; | ||
| 458 | } else { | ||
| 459 | shift_param = 16; | ||
| 460 | address = CSR_SECURE_BOOT_CPU2_STATUS_ADDR; | ||
| 461 | } | ||
| 462 | |||
| 463 | /* set CPU to started */ | ||
| 464 | iwl_trans_set_bits_mask(trans, | ||
| 465 | CSR_UCODE_LOAD_STATUS_ADDR, | ||
| 466 | CSR_CPU_STATUS_LOADING_STARTED << shift_param, | ||
| 467 | 1); | ||
| 468 | |||
| 469 | /* set last complete descriptor number */ | ||
| 470 | iwl_trans_set_bits_mask(trans, | ||
| 471 | CSR_UCODE_LOAD_STATUS_ADDR, | ||
| 472 | CSR_CPU_STATUS_NUM_OF_LAST_COMPLETED | ||
| 473 | << shift_param, | ||
| 474 | 1); | ||
| 475 | |||
| 476 | /* set last loaded block */ | ||
| 477 | iwl_trans_set_bits_mask(trans, | ||
| 478 | CSR_UCODE_LOAD_STATUS_ADDR, | ||
| 479 | CSR_CPU_STATUS_NUM_OF_LAST_LOADED_BLOCK | ||
| 480 | << shift_param, | ||
| 481 | 1); | ||
| 482 | |||
| 483 | /* image loading complete */ | ||
| 484 | iwl_trans_set_bits_mask(trans, | ||
| 485 | CSR_UCODE_LOAD_STATUS_ADDR, | ||
| 486 | CSR_CPU_STATUS_LOADING_COMPLETED | ||
| 487 | << shift_param, | ||
| 488 | 1); | ||
| 489 | |||
| 490 | /* set FH_TCSR_0_REG */ | ||
| 491 | iwl_trans_set_bits_mask(trans, FH_TCSR_0_REG0, 0x00400000, 1); | ||
| 492 | |||
| 493 | /* verify image verification started */ | ||
| 494 | ret = iwl_poll_bit(trans, address, | ||
| 495 | CSR_SECURE_BOOT_CPU_STATUS_VERF_STATUS, | ||
| 496 | CSR_SECURE_BOOT_CPU_STATUS_VERF_STATUS, | ||
| 497 | CSR_SECURE_TIME_OUT); | ||
| 498 | if (ret < 0) { | ||
| 499 | IWL_ERR(trans, "secure boot process didn't start\n"); | ||
| 500 | return ret; | ||
| 501 | } | ||
| 502 | |||
| 503 | /* wait for image verification to complete */ | ||
| 504 | ret = iwl_poll_bit(trans, address, | ||
| 505 | CSR_SECURE_BOOT_CPU_STATUS_VERF_COMPLETED, | ||
| 506 | CSR_SECURE_BOOT_CPU_STATUS_VERF_COMPLETED, | ||
| 507 | CSR_SECURE_TIME_OUT); | ||
| 508 | |||
| 509 | if (ret < 0) { | ||
| 510 | IWL_ERR(trans, "Time out on secure boot process\n"); | ||
| 511 | return ret; | ||
| 512 | } | ||
| 513 | |||
| 514 | return 0; | ||
| 515 | } | ||
| 516 | |||
| 446 | static int iwl_pcie_load_given_ucode(struct iwl_trans *trans, | 517 | static int iwl_pcie_load_given_ucode(struct iwl_trans *trans, |
| 447 | const struct fw_img *image) | 518 | const struct fw_img *image) |
| 448 | { | 519 | { |
| 449 | int i, ret = 0; | 520 | int i, ret = 0; |
| 450 | 521 | ||
| 451 | for (i = 0; i < IWL_UCODE_SECTION_MAX; i++) { | 522 | IWL_DEBUG_FW(trans, |
| 523 | "working with %s image\n", | ||
| 524 | image->is_secure ? "Secured" : "Non Secured"); | ||
| 525 | IWL_DEBUG_FW(trans, | ||
| 526 | "working with %s CPU\n", | ||
| 527 | image->is_dual_cpus ? "Dual" : "Single"); | ||
| 528 | |||
| 529 | /* configure the ucode to be ready to get the secured image */ | ||
| 530 | if (image->is_secure) { | ||
| 531 | /* set secure boot inspector addresses */ | ||
| 532 | iwl_write32(trans, CSR_SECURE_INSPECTOR_CODE_ADDR, 0); | ||
| 533 | iwl_write32(trans, CSR_SECURE_INSPECTOR_DATA_ADDR, 0); | ||
| 534 | |||
| 535 | /* release CPU1 reset if secure inspector image burned in OTP */ | ||
| 536 | iwl_write32(trans, CSR_RESET, 0); | ||
| 537 | } | ||
| 538 | |||
| 539 | /* load to FW the binary sections of CPU1 */ | ||
| 540 | IWL_DEBUG_INFO(trans, "Loading CPU1\n"); | ||
| 541 | for (i = 0; | ||
| 542 | i < IWL_UCODE_FIRST_SECTION_OF_SECOND_CPU; | ||
| 543 | i++) { | ||
| 452 | if (!image->sec[i].data) | 544 | if (!image->sec[i].data) |
| 453 | break; | 545 | break; |
| 454 | |||
| 455 | ret = iwl_pcie_load_section(trans, i, &image->sec[i]); | 546 | ret = iwl_pcie_load_section(trans, i, &image->sec[i]); |
| 456 | if (ret) | 547 | if (ret) |
| 457 | return ret; | 548 | return ret; |
| 458 | } | 549 | } |
| 459 | 550 | ||
| 460 | /* Remove all resets to allow NIC to operate */ | 551 | /* configure the ucode to start secure process on CPU1 */ |
| 461 | iwl_write32(trans, CSR_RESET, 0); | 552 | if (image->is_secure) { |
| 553 | /* config CPU1 to start secure protocol */ | ||
| 554 | ret = iwl_pcie_secure_set(trans, 1); | ||
| 555 | if (ret) | ||
| 556 | return ret; | ||
| 557 | } else { | ||
| 558 | /* Remove all resets to allow NIC to operate */ | ||
| 559 | iwl_write32(trans, CSR_RESET, 0); | ||
| 560 | } | ||
| 561 | |||
| 562 | if (image->is_dual_cpus) { | ||
| 563 | /* load to FW the binary sections of CPU2 */ | ||
| 564 | IWL_DEBUG_INFO(trans, "working w/ DUAL CPUs - Loading CPU2\n"); | ||
| 565 | for (i = IWL_UCODE_FIRST_SECTION_OF_SECOND_CPU; | ||
| 566 | i < IWL_UCODE_SECTION_MAX; i++) { | ||
| 567 | if (!image->sec[i].data) | ||
| 568 | break; | ||
| 569 | ret = iwl_pcie_load_section(trans, i, &image->sec[i]); | ||
| 570 | if (ret) | ||
| 571 | return ret; | ||
| 572 | } | ||
| 573 | |||
| 574 | if (image->is_secure) { | ||
| 575 | /* set CPU2 for secure protocol */ | ||
| 576 | ret = iwl_pcie_secure_set(trans, 2); | ||
| 577 | if (ret) | ||
| 578 | return ret; | ||
| 579 | } | ||
| 580 | } | ||
| 462 | 581 | ||
| 463 | return 0; | 582 | return 0; |
| 464 | } | 583 | } |
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index 1424335163b9..f644fcf861a8 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c | |||
| @@ -1465,7 +1465,8 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans, | |||
| 1465 | spin_unlock_bh(&txq->lock); | 1465 | spin_unlock_bh(&txq->lock); |
| 1466 | } | 1466 | } |
| 1467 | 1467 | ||
| 1468 | #define HOST_COMPLETE_TIMEOUT (2 * HZ) | 1468 | #define HOST_COMPLETE_TIMEOUT (2 * HZ) |
| 1469 | #define COMMAND_POKE_TIMEOUT (HZ / 10) | ||
| 1469 | 1470 | ||
| 1470 | static int iwl_pcie_send_hcmd_async(struct iwl_trans *trans, | 1471 | static int iwl_pcie_send_hcmd_async(struct iwl_trans *trans, |
| 1471 | struct iwl_host_cmd *cmd) | 1472 | struct iwl_host_cmd *cmd) |
| @@ -1493,6 +1494,7 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans, | |||
| 1493 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 1494 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
| 1494 | int cmd_idx; | 1495 | int cmd_idx; |
| 1495 | int ret; | 1496 | int ret; |
| 1497 | int timeout = HOST_COMPLETE_TIMEOUT; | ||
| 1496 | 1498 | ||
| 1497 | IWL_DEBUG_INFO(trans, "Attempting to send sync command %s\n", | 1499 | IWL_DEBUG_INFO(trans, "Attempting to send sync command %s\n", |
| 1498 | get_cmd_string(trans_pcie, cmd->id)); | 1500 | get_cmd_string(trans_pcie, cmd->id)); |
| @@ -1517,10 +1519,29 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans, | |||
| 1517 | return ret; | 1519 | return ret; |
| 1518 | } | 1520 | } |
| 1519 | 1521 | ||
| 1520 | ret = wait_event_timeout(trans_pcie->wait_command_queue, | 1522 | while (timeout > 0) { |
| 1521 | !test_bit(STATUS_HCMD_ACTIVE, | 1523 | unsigned long flags; |
| 1522 | &trans_pcie->status), | 1524 | |
| 1523 | HOST_COMPLETE_TIMEOUT); | 1525 | timeout -= COMMAND_POKE_TIMEOUT; |
| 1526 | ret = wait_event_timeout(trans_pcie->wait_command_queue, | ||
| 1527 | !test_bit(STATUS_HCMD_ACTIVE, | ||
| 1528 | &trans_pcie->status), | ||
| 1529 | COMMAND_POKE_TIMEOUT); | ||
| 1530 | if (ret) | ||
| 1531 | break; | ||
| 1532 | /* poke the device - it may have lost the command */ | ||
| 1533 | if (iwl_trans_grab_nic_access(trans, true, &flags)) { | ||
| 1534 | iwl_trans_release_nic_access(trans, &flags); | ||
| 1535 | IWL_DEBUG_INFO(trans, | ||
| 1536 | "Tried to wake NIC for command %s\n", | ||
| 1537 | get_cmd_string(trans_pcie, cmd->id)); | ||
| 1538 | } else { | ||
| 1539 | IWL_ERR(trans, "Failed to poke NIC for command %s\n", | ||
| 1540 | get_cmd_string(trans_pcie, cmd->id)); | ||
| 1541 | break; | ||
| 1542 | } | ||
| 1543 | } | ||
| 1544 | |||
| 1524 | if (!ret) { | 1545 | if (!ret) { |
| 1525 | if (test_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status)) { | 1546 | if (test_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status)) { |
| 1526 | struct iwl_txq *txq = | 1547 | struct iwl_txq *txq = |
| @@ -1541,6 +1562,9 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans, | |||
| 1541 | "Clearing HCMD_ACTIVE for command %s\n", | 1562 | "Clearing HCMD_ACTIVE for command %s\n", |
| 1542 | get_cmd_string(trans_pcie, cmd->id)); | 1563 | get_cmd_string(trans_pcie, cmd->id)); |
| 1543 | ret = -ETIMEDOUT; | 1564 | ret = -ETIMEDOUT; |
| 1565 | |||
| 1566 | iwl_op_mode_nic_error(trans->op_mode); | ||
| 1567 | |||
| 1544 | goto cancel; | 1568 | goto cancel; |
| 1545 | } | 1569 | } |
| 1546 | } | 1570 | } |
diff --git a/drivers/net/wireless/libertas/firmware.c b/drivers/net/wireless/libertas/firmware.c index c0f9e7e862f6..51b92b5df119 100644 --- a/drivers/net/wireless/libertas/firmware.c +++ b/drivers/net/wireless/libertas/firmware.c | |||
| @@ -53,6 +53,11 @@ static void main_firmware_cb(const struct firmware *firmware, void *context) | |||
| 53 | 53 | ||
| 54 | /* Firmware found! */ | 54 | /* Firmware found! */ |
| 55 | lbs_fw_loaded(priv, 0, priv->helper_fw, firmware); | 55 | lbs_fw_loaded(priv, 0, priv->helper_fw, firmware); |
| 56 | if (priv->helper_fw) { | ||
| 57 | release_firmware (priv->helper_fw); | ||
| 58 | priv->helper_fw = NULL; | ||
| 59 | } | ||
| 60 | release_firmware (firmware); | ||
| 56 | } | 61 | } |
| 57 | 62 | ||
| 58 | static void helper_firmware_cb(const struct firmware *firmware, void *context) | 63 | static void helper_firmware_cb(const struct firmware *firmware, void *context) |
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c index c94dd6802672..ef8c98e21098 100644 --- a/drivers/net/wireless/libertas/if_cs.c +++ b/drivers/net/wireless/libertas/if_cs.c | |||
| @@ -754,14 +754,14 @@ static void if_cs_prog_firmware(struct lbs_private *priv, int ret, | |||
| 754 | if (ret == 0 && (card->model != MODEL_8305)) | 754 | if (ret == 0 && (card->model != MODEL_8305)) |
| 755 | ret = if_cs_prog_real(card, mainfw); | 755 | ret = if_cs_prog_real(card, mainfw); |
| 756 | if (ret) | 756 | if (ret) |
| 757 | goto out; | 757 | return; |
| 758 | 758 | ||
| 759 | /* Now actually get the IRQ */ | 759 | /* Now actually get the IRQ */ |
| 760 | ret = request_irq(card->p_dev->irq, if_cs_interrupt, | 760 | ret = request_irq(card->p_dev->irq, if_cs_interrupt, |
| 761 | IRQF_SHARED, DRV_NAME, card); | 761 | IRQF_SHARED, DRV_NAME, card); |
| 762 | if (ret) { | 762 | if (ret) { |
| 763 | pr_err("error in request_irq\n"); | 763 | pr_err("error in request_irq\n"); |
| 764 | goto out; | 764 | return; |
| 765 | } | 765 | } |
| 766 | 766 | ||
| 767 | /* | 767 | /* |
| @@ -777,10 +777,6 @@ static void if_cs_prog_firmware(struct lbs_private *priv, int ret, | |||
| 777 | pr_err("could not activate card\n"); | 777 | pr_err("could not activate card\n"); |
| 778 | free_irq(card->p_dev->irq, card); | 778 | free_irq(card->p_dev->irq, card); |
| 779 | } | 779 | } |
| 780 | |||
| 781 | out: | ||
| 782 | release_firmware(helper); | ||
| 783 | release_firmware(mainfw); | ||
| 784 | } | 780 | } |
| 785 | 781 | ||
| 786 | 782 | ||
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index 45578335e420..991238afd1b6 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c | |||
| @@ -708,20 +708,16 @@ static void if_sdio_do_prog_firmware(struct lbs_private *priv, int ret, | |||
| 708 | 708 | ||
| 709 | ret = if_sdio_prog_helper(card, helper); | 709 | ret = if_sdio_prog_helper(card, helper); |
| 710 | if (ret) | 710 | if (ret) |
| 711 | goto out; | 711 | return; |
| 712 | 712 | ||
| 713 | lbs_deb_sdio("Helper firmware loaded\n"); | 713 | lbs_deb_sdio("Helper firmware loaded\n"); |
| 714 | 714 | ||
| 715 | ret = if_sdio_prog_real(card, mainfw); | 715 | ret = if_sdio_prog_real(card, mainfw); |
| 716 | if (ret) | 716 | if (ret) |
| 717 | goto out; | 717 | return; |
| 718 | 718 | ||
| 719 | lbs_deb_sdio("Firmware loaded\n"); | 719 | lbs_deb_sdio("Firmware loaded\n"); |
| 720 | if_sdio_finish_power_on(card); | 720 | if_sdio_finish_power_on(card); |
| 721 | |||
| 722 | out: | ||
| 723 | release_firmware(helper); | ||
| 724 | release_firmware(mainfw); | ||
| 725 | } | 721 | } |
| 726 | 722 | ||
| 727 | static int if_sdio_prog_firmware(struct if_sdio_card *card) | 723 | static int if_sdio_prog_firmware(struct if_sdio_card *card) |
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c index 5d39ec880d84..83669151bb82 100644 --- a/drivers/net/wireless/libertas/if_spi.c +++ b/drivers/net/wireless/libertas/if_spi.c | |||
| @@ -1094,11 +1094,7 @@ static int if_spi_init_card(struct if_spi_card *card) | |||
| 1094 | goto out; | 1094 | goto out; |
| 1095 | 1095 | ||
| 1096 | out: | 1096 | out: |
| 1097 | release_firmware(helper); | ||
| 1098 | release_firmware(mainfw); | ||
| 1099 | |||
| 1100 | lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err); | 1097 | lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err); |
| 1101 | |||
| 1102 | return err; | 1098 | return err; |
| 1103 | } | 1099 | } |
| 1104 | 1100 | ||
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index 27980778d992..dff08a2896a3 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c | |||
| @@ -844,7 +844,7 @@ static void if_usb_prog_firmware(struct lbs_private *priv, int ret, | |||
| 844 | cardp->fw = fw; | 844 | cardp->fw = fw; |
| 845 | if (check_fwfile_format(cardp->fw->data, cardp->fw->size)) { | 845 | if (check_fwfile_format(cardp->fw->data, cardp->fw->size)) { |
| 846 | ret = -EINVAL; | 846 | ret = -EINVAL; |
| 847 | goto release_fw; | 847 | goto done; |
| 848 | } | 848 | } |
| 849 | 849 | ||
| 850 | /* Cancel any pending usb business */ | 850 | /* Cancel any pending usb business */ |
| @@ -861,7 +861,7 @@ restart: | |||
| 861 | if (if_usb_submit_rx_urb_fwload(cardp) < 0) { | 861 | if (if_usb_submit_rx_urb_fwload(cardp) < 0) { |
| 862 | lbs_deb_usbd(&cardp->udev->dev, "URB submission is failed\n"); | 862 | lbs_deb_usbd(&cardp->udev->dev, "URB submission is failed\n"); |
| 863 | ret = -EIO; | 863 | ret = -EIO; |
| 864 | goto release_fw; | 864 | goto done; |
| 865 | } | 865 | } |
| 866 | 866 | ||
| 867 | cardp->bootcmdresp = 0; | 867 | cardp->bootcmdresp = 0; |
| @@ -883,14 +883,14 @@ restart: | |||
| 883 | usb_kill_urb(cardp->tx_urb); | 883 | usb_kill_urb(cardp->tx_urb); |
| 884 | if (if_usb_submit_rx_urb(cardp) < 0) | 884 | if (if_usb_submit_rx_urb(cardp) < 0) |
| 885 | ret = -EIO; | 885 | ret = -EIO; |
| 886 | goto release_fw; | 886 | goto done; |
| 887 | } else if (cardp->bootcmdresp <= 0) { | 887 | } else if (cardp->bootcmdresp <= 0) { |
| 888 | if (--reset_count >= 0) { | 888 | if (--reset_count >= 0) { |
| 889 | if_usb_reset_device(cardp); | 889 | if_usb_reset_device(cardp); |
| 890 | goto restart; | 890 | goto restart; |
| 891 | } | 891 | } |
| 892 | ret = -EIO; | 892 | ret = -EIO; |
| 893 | goto release_fw; | 893 | goto done; |
| 894 | } | 894 | } |
| 895 | 895 | ||
| 896 | i = 0; | 896 | i = 0; |
| @@ -921,14 +921,14 @@ restart: | |||
| 921 | 921 | ||
| 922 | pr_info("FW download failure, time = %d ms\n", i * 100); | 922 | pr_info("FW download failure, time = %d ms\n", i * 100); |
| 923 | ret = -EIO; | 923 | ret = -EIO; |
| 924 | goto release_fw; | 924 | goto done; |
| 925 | } | 925 | } |
| 926 | 926 | ||
| 927 | cardp->priv->fw_ready = 1; | 927 | cardp->priv->fw_ready = 1; |
| 928 | if_usb_submit_rx_urb(cardp); | 928 | if_usb_submit_rx_urb(cardp); |
| 929 | 929 | ||
| 930 | if (lbs_start_card(priv)) | 930 | if (lbs_start_card(priv)) |
| 931 | goto release_fw; | 931 | goto done; |
| 932 | 932 | ||
| 933 | if_usb_setup_firmware(priv); | 933 | if_usb_setup_firmware(priv); |
| 934 | 934 | ||
| @@ -939,11 +939,8 @@ restart: | |||
| 939 | if (lbs_host_sleep_cfg(priv, priv->wol_criteria, NULL)) | 939 | if (lbs_host_sleep_cfg(priv, priv->wol_criteria, NULL)) |
| 940 | priv->ehs_remove_supported = false; | 940 | priv->ehs_remove_supported = false; |
| 941 | 941 | ||
| 942 | release_fw: | ||
| 943 | release_firmware(cardp->fw); | ||
| 944 | cardp->fw = NULL; | ||
| 945 | |||
| 946 | done: | 942 | done: |
| 943 | cardp->fw = NULL; | ||
| 947 | lbs_deb_leave(LBS_DEB_USB); | 944 | lbs_deb_leave(LBS_DEB_USB); |
| 948 | } | 945 | } |
| 949 | 946 | ||
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index a18b0051a745..006b8bcb2e31 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig | |||
| @@ -58,11 +58,11 @@ config RT61PCI | |||
| 58 | 58 | ||
| 59 | config RT2800PCI | 59 | config RT2800PCI |
| 60 | tristate "Ralink rt27xx/rt28xx/rt30xx (PCI/PCIe/PCMCIA) support" | 60 | tristate "Ralink rt27xx/rt28xx/rt30xx (PCI/PCIe/PCMCIA) support" |
| 61 | depends on PCI || SOC_RT288X || SOC_RT305X | 61 | depends on PCI |
| 62 | select RT2800_LIB | 62 | select RT2800_LIB |
| 63 | select RT2800_LIB_MMIO | ||
| 63 | select RT2X00_LIB_MMIO | 64 | select RT2X00_LIB_MMIO |
| 64 | select RT2X00_LIB_PCI if PCI | 65 | select RT2X00_LIB_PCI |
| 65 | select RT2X00_LIB_SOC if SOC_RT288X || SOC_RT305X | ||
| 66 | select RT2X00_LIB_FIRMWARE | 66 | select RT2X00_LIB_FIRMWARE |
| 67 | select RT2X00_LIB_CRYPTO | 67 | select RT2X00_LIB_CRYPTO |
| 68 | select CRC_CCITT | 68 | select CRC_CCITT |
| @@ -199,9 +199,30 @@ config RT2800USB_UNKNOWN | |||
| 199 | 199 | ||
| 200 | endif | 200 | endif |
| 201 | 201 | ||
| 202 | config RT2800SOC | ||
| 203 | tristate "Ralink WiSoC support" | ||
| 204 | depends on SOC_RT288X || SOC_RT305X | ||
| 205 | select RT2X00_LIB_SOC | ||
| 206 | select RT2X00_LIB_MMIO | ||
| 207 | select RT2X00_LIB_CRYPTO | ||
| 208 | select RT2X00_LIB_FIRMWARE | ||
| 209 | select RT2800_LIB | ||
| 210 | select RT2800_LIB_MMIO | ||
| 211 | ---help--- | ||
| 212 | This adds support for Ralink WiSoC devices. | ||
| 213 | Supported chips: RT2880, RT3050, RT3052, RT3350, RT3352. | ||
| 214 | |||
| 215 | When compiled as a module, this driver will be called rt2800soc. | ||
| 216 | |||
| 217 | |||
| 202 | config RT2800_LIB | 218 | config RT2800_LIB |
| 203 | tristate | 219 | tristate |
| 204 | 220 | ||
| 221 | config RT2800_LIB_MMIO | ||
| 222 | tristate | ||
| 223 | select RT2X00_LIB_MMIO | ||
| 224 | select RT2800_LIB | ||
| 225 | |||
| 205 | config RT2X00_LIB_MMIO | 226 | config RT2X00_LIB_MMIO |
| 206 | tristate | 227 | tristate |
| 207 | 228 | ||
diff --git a/drivers/net/wireless/rt2x00/Makefile b/drivers/net/wireless/rt2x00/Makefile index f069d8bc5b67..24a66015a495 100644 --- a/drivers/net/wireless/rt2x00/Makefile +++ b/drivers/net/wireless/rt2x00/Makefile | |||
| @@ -14,6 +14,7 @@ obj-$(CONFIG_RT2X00_LIB_PCI) += rt2x00pci.o | |||
| 14 | obj-$(CONFIG_RT2X00_LIB_SOC) += rt2x00soc.o | 14 | obj-$(CONFIG_RT2X00_LIB_SOC) += rt2x00soc.o |
| 15 | obj-$(CONFIG_RT2X00_LIB_USB) += rt2x00usb.o | 15 | obj-$(CONFIG_RT2X00_LIB_USB) += rt2x00usb.o |
| 16 | obj-$(CONFIG_RT2800_LIB) += rt2800lib.o | 16 | obj-$(CONFIG_RT2800_LIB) += rt2800lib.o |
| 17 | obj-$(CONFIG_RT2800_LIB_MMIO) += rt2800mmio.o | ||
| 17 | obj-$(CONFIG_RT2400PCI) += rt2400pci.o | 18 | obj-$(CONFIG_RT2400PCI) += rt2400pci.o |
| 18 | obj-$(CONFIG_RT2500PCI) += rt2500pci.o | 19 | obj-$(CONFIG_RT2500PCI) += rt2500pci.o |
| 19 | obj-$(CONFIG_RT61PCI) += rt61pci.o | 20 | obj-$(CONFIG_RT61PCI) += rt61pci.o |
| @@ -21,3 +22,4 @@ obj-$(CONFIG_RT2800PCI) += rt2800pci.o | |||
| 21 | obj-$(CONFIG_RT2500USB) += rt2500usb.o | 22 | obj-$(CONFIG_RT2500USB) += rt2500usb.o |
| 22 | obj-$(CONFIG_RT73USB) += rt73usb.o | 23 | obj-$(CONFIG_RT73USB) += rt73usb.o |
| 23 | obj-$(CONFIG_RT2800USB) += rt2800usb.o | 24 | obj-$(CONFIG_RT2800USB) += rt2800usb.o |
| 25 | obj-$(CONFIG_RT2800SOC) += rt2800soc.o | ||
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 3d53a09da5a1..38ed9a3e44c8 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c | |||
| @@ -1261,7 +1261,7 @@ static void rt2400pci_fill_rxdone(struct queue_entry *entry, | |||
| 1261 | */ | 1261 | */ |
| 1262 | rxdesc->timestamp = ((u64)rx_high << 32) | rx_low; | 1262 | rxdesc->timestamp = ((u64)rx_high << 32) | rx_low; |
| 1263 | rxdesc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL) & ~0x08; | 1263 | rxdesc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL) & ~0x08; |
| 1264 | rxdesc->rssi = rt2x00_get_field32(word2, RXD_W3_RSSI) - | 1264 | rxdesc->rssi = rt2x00_get_field32(word3, RXD_W3_RSSI) - |
| 1265 | entry->queue->rt2x00dev->rssi_offset; | 1265 | entry->queue->rt2x00dev->rssi_offset; |
| 1266 | rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); | 1266 | rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); |
| 1267 | 1267 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index aa8789423937..c5738f14c4ba 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
| @@ -7450,7 +7450,6 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
| 7450 | char *default_power2; | 7450 | char *default_power2; |
| 7451 | char *default_power3; | 7451 | char *default_power3; |
| 7452 | unsigned int i; | 7452 | unsigned int i; |
| 7453 | u16 eeprom; | ||
| 7454 | u32 reg; | 7453 | u32 reg; |
| 7455 | 7454 | ||
| 7456 | /* | 7455 | /* |
| @@ -7499,46 +7498,48 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
| 7499 | rt2x00dev->hw->max_report_rates = 7; | 7498 | rt2x00dev->hw->max_report_rates = 7; |
| 7500 | rt2x00dev->hw->max_rate_tries = 1; | 7499 | rt2x00dev->hw->max_rate_tries = 1; |
| 7501 | 7500 | ||
| 7502 | rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); | ||
| 7503 | |||
| 7504 | /* | 7501 | /* |
| 7505 | * Initialize hw_mode information. | 7502 | * Initialize hw_mode information. |
| 7506 | */ | 7503 | */ |
| 7507 | spec->supported_bands = SUPPORT_BAND_2GHZ; | ||
| 7508 | spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; | 7504 | spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; |
| 7509 | 7505 | ||
| 7510 | if (rt2x00_rf(rt2x00dev, RF2820) || | 7506 | switch (rt2x00dev->chip.rf) { |
| 7511 | rt2x00_rf(rt2x00dev, RF2720)) { | 7507 | case RF2720: |
| 7508 | case RF2820: | ||
| 7512 | spec->num_channels = 14; | 7509 | spec->num_channels = 14; |
| 7513 | spec->channels = rf_vals; | 7510 | spec->channels = rf_vals; |
| 7514 | } else if (rt2x00_rf(rt2x00dev, RF2850) || | 7511 | break; |
| 7515 | rt2x00_rf(rt2x00dev, RF2750)) { | 7512 | |
| 7516 | spec->supported_bands |= SUPPORT_BAND_5GHZ; | 7513 | case RF2750: |
| 7514 | case RF2850: | ||
| 7517 | spec->num_channels = ARRAY_SIZE(rf_vals); | 7515 | spec->num_channels = ARRAY_SIZE(rf_vals); |
| 7518 | spec->channels = rf_vals; | 7516 | spec->channels = rf_vals; |
| 7519 | } else if (rt2x00_rf(rt2x00dev, RF3020) || | 7517 | break; |
| 7520 | rt2x00_rf(rt2x00dev, RF2020) || | 7518 | |
| 7521 | rt2x00_rf(rt2x00dev, RF3021) || | 7519 | case RF2020: |
| 7522 | rt2x00_rf(rt2x00dev, RF3022) || | 7520 | case RF3020: |
| 7523 | rt2x00_rf(rt2x00dev, RF3070) || | 7521 | case RF3021: |
| 7524 | rt2x00_rf(rt2x00dev, RF3290) || | 7522 | case RF3022: |
| 7525 | rt2x00_rf(rt2x00dev, RF3320) || | 7523 | case RF3070: |
| 7526 | rt2x00_rf(rt2x00dev, RF3322) || | 7524 | case RF3290: |
| 7527 | rt2x00_rf(rt2x00dev, RF5360) || | 7525 | case RF3320: |
| 7528 | rt2x00_rf(rt2x00dev, RF5370) || | 7526 | case RF3322: |
| 7529 | rt2x00_rf(rt2x00dev, RF5372) || | 7527 | case RF5360: |
| 7530 | rt2x00_rf(rt2x00dev, RF5390) || | 7528 | case RF5370: |
| 7531 | rt2x00_rf(rt2x00dev, RF5392)) { | 7529 | case RF5372: |
| 7530 | case RF5390: | ||
| 7531 | case RF5392: | ||
| 7532 | spec->num_channels = 14; | 7532 | spec->num_channels = 14; |
| 7533 | spec->channels = rf_vals_3x; | 7533 | spec->channels = rf_vals_3x; |
| 7534 | } else if (rt2x00_rf(rt2x00dev, RF3052) || | 7534 | break; |
| 7535 | rt2x00_rf(rt2x00dev, RF3053)) { | 7535 | |
| 7536 | spec->supported_bands |= SUPPORT_BAND_5GHZ; | 7536 | case RF3052: |
| 7537 | case RF3053: | ||
| 7537 | spec->num_channels = ARRAY_SIZE(rf_vals_3x); | 7538 | spec->num_channels = ARRAY_SIZE(rf_vals_3x); |
| 7538 | spec->channels = rf_vals_3x; | 7539 | spec->channels = rf_vals_3x; |
| 7539 | } else if (rt2x00_rf(rt2x00dev, RF5592)) { | 7540 | break; |
| 7540 | spec->supported_bands |= SUPPORT_BAND_5GHZ; | ||
| 7541 | 7541 | ||
| 7542 | case RF5592: | ||
| 7542 | rt2800_register_read(rt2x00dev, MAC_DEBUG_INDEX, ®); | 7543 | rt2800_register_read(rt2x00dev, MAC_DEBUG_INDEX, ®); |
| 7543 | if (rt2x00_get_field32(reg, MAC_DEBUG_INDEX_XTAL)) { | 7544 | if (rt2x00_get_field32(reg, MAC_DEBUG_INDEX_XTAL)) { |
| 7544 | spec->num_channels = ARRAY_SIZE(rf_vals_5592_xtal40); | 7545 | spec->num_channels = ARRAY_SIZE(rf_vals_5592_xtal40); |
| @@ -7547,11 +7548,16 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
| 7547 | spec->num_channels = ARRAY_SIZE(rf_vals_5592_xtal20); | 7548 | spec->num_channels = ARRAY_SIZE(rf_vals_5592_xtal20); |
| 7548 | spec->channels = rf_vals_5592_xtal20; | 7549 | spec->channels = rf_vals_5592_xtal20; |
| 7549 | } | 7550 | } |
| 7551 | break; | ||
| 7550 | } | 7552 | } |
| 7551 | 7553 | ||
| 7552 | if (WARN_ON_ONCE(!spec->channels)) | 7554 | if (WARN_ON_ONCE(!spec->channels)) |
| 7553 | return -ENODEV; | 7555 | return -ENODEV; |
| 7554 | 7556 | ||
| 7557 | spec->supported_bands = SUPPORT_BAND_2GHZ; | ||
| 7558 | if (spec->num_channels > 14) | ||
| 7559 | spec->supported_bands |= SUPPORT_BAND_5GHZ; | ||
| 7560 | |||
| 7555 | /* | 7561 | /* |
| 7556 | * Initialize HT information. | 7562 | * Initialize HT information. |
| 7557 | */ | 7563 | */ |
| @@ -7566,22 +7572,21 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
| 7566 | IEEE80211_HT_CAP_SGI_20 | | 7572 | IEEE80211_HT_CAP_SGI_20 | |
| 7567 | IEEE80211_HT_CAP_SGI_40; | 7573 | IEEE80211_HT_CAP_SGI_40; |
| 7568 | 7574 | ||
| 7569 | if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) >= 2) | 7575 | if (rt2x00dev->default_ant.tx_chain_num >= 2) |
| 7570 | spec->ht.cap |= IEEE80211_HT_CAP_TX_STBC; | 7576 | spec->ht.cap |= IEEE80211_HT_CAP_TX_STBC; |
| 7571 | 7577 | ||
| 7572 | spec->ht.cap |= | 7578 | spec->ht.cap |= rt2x00dev->default_ant.rx_chain_num << |
| 7573 | rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) << | 7579 | IEEE80211_HT_CAP_RX_STBC_SHIFT; |
| 7574 | IEEE80211_HT_CAP_RX_STBC_SHIFT; | ||
| 7575 | 7580 | ||
| 7576 | spec->ht.ampdu_factor = 3; | 7581 | spec->ht.ampdu_factor = 3; |
| 7577 | spec->ht.ampdu_density = 4; | 7582 | spec->ht.ampdu_density = 4; |
| 7578 | spec->ht.mcs.tx_params = | 7583 | spec->ht.mcs.tx_params = |
| 7579 | IEEE80211_HT_MCS_TX_DEFINED | | 7584 | IEEE80211_HT_MCS_TX_DEFINED | |
| 7580 | IEEE80211_HT_MCS_TX_RX_DIFF | | 7585 | IEEE80211_HT_MCS_TX_RX_DIFF | |
| 7581 | ((rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) - 1) << | 7586 | ((rt2x00dev->default_ant.tx_chain_num - 1) << |
| 7582 | IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); | 7587 | IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); |
| 7583 | 7588 | ||
| 7584 | switch (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH)) { | 7589 | switch (rt2x00dev->default_ant.rx_chain_num) { |
| 7585 | case 3: | 7590 | case 3: |
| 7586 | spec->ht.mcs.rx_mask[2] = 0xff; | 7591 | spec->ht.mcs.rx_mask[2] = 0xff; |
| 7587 | case 2: | 7592 | case 2: |
diff --git a/drivers/net/wireless/rt2x00/rt2800mmio.c b/drivers/net/wireless/rt2x00/rt2800mmio.c new file mode 100644 index 000000000000..ae152280e071 --- /dev/null +++ b/drivers/net/wireless/rt2x00/rt2800mmio.c | |||
| @@ -0,0 +1,873 @@ | |||
| 1 | /* Copyright (C) 2009 - 2010 Ivo van Doorn <IvDoorn@gmail.com> | ||
| 2 | * Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com> | ||
| 3 | * Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org> | ||
| 4 | * Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com> | ||
| 5 | * Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de> | ||
| 6 | * Copyright (C) 2009 Mark Asselstine <asselsm@gmail.com> | ||
| 7 | * Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com> | ||
| 8 | * Copyright (C) 2009 Bart Zolnierkiewicz <bzolnier@gmail.com> | ||
| 9 | * <http://rt2x00.serialmonkey.com> | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or modify | ||
| 12 | * it under the terms of the GNU General Public License as published by | ||
| 13 | * the Free Software Foundation; either version 2 of the License, or | ||
| 14 | * (at your option) any later version. | ||
| 15 | * | ||
| 16 | * This program is distributed in the hope that it will be useful, | ||
| 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 19 | * GNU General Public License for more details. | ||
| 20 | * | ||
| 21 | * You should have received a copy of the GNU General Public License | ||
| 22 | * along with this program; if not, write to the | ||
| 23 | * Free Software Foundation, Inc., | ||
| 24 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
| 25 | */ | ||
| 26 | |||
| 27 | /* Module: rt2800mmio | ||
| 28 | * Abstract: rt2800 MMIO device routines. | ||
| 29 | */ | ||
| 30 | |||
| 31 | #include <linux/kernel.h> | ||
| 32 | #include <linux/module.h> | ||
| 33 | #include <linux/export.h> | ||
| 34 | |||
| 35 | #include "rt2x00.h" | ||
| 36 | #include "rt2x00mmio.h" | ||
| 37 | #include "rt2800.h" | ||
| 38 | #include "rt2800lib.h" | ||
| 39 | #include "rt2800mmio.h" | ||
| 40 | |||
| 41 | /* | ||
| 42 | * TX descriptor initialization | ||
| 43 | */ | ||
| 44 | __le32 *rt2800mmio_get_txwi(struct queue_entry *entry) | ||
| 45 | { | ||
| 46 | return (__le32 *) entry->skb->data; | ||
| 47 | } | ||
| 48 | EXPORT_SYMBOL_GPL(rt2800mmio_get_txwi); | ||
| 49 | |||
| 50 | void rt2800mmio_write_tx_desc(struct queue_entry *entry, | ||
| 51 | struct txentry_desc *txdesc) | ||
| 52 | { | ||
| 53 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | ||
| 54 | struct queue_entry_priv_mmio *entry_priv = entry->priv_data; | ||
| 55 | __le32 *txd = entry_priv->desc; | ||
| 56 | u32 word; | ||
| 57 | const unsigned int txwi_size = entry->queue->winfo_size; | ||
| 58 | |||
| 59 | /* | ||
| 60 | * The buffers pointed by SD_PTR0/SD_LEN0 and SD_PTR1/SD_LEN1 | ||
| 61 | * must contains a TXWI structure + 802.11 header + padding + 802.11 | ||
| 62 | * data. We choose to have SD_PTR0/SD_LEN0 only contains TXWI and | ||
| 63 | * SD_PTR1/SD_LEN1 contains 802.11 header + padding + 802.11 | ||
| 64 | * data. It means that LAST_SEC0 is always 0. | ||
| 65 | */ | ||
| 66 | |||
| 67 | /* | ||
| 68 | * Initialize TX descriptor | ||
| 69 | */ | ||
| 70 | word = 0; | ||
| 71 | rt2x00_set_field32(&word, TXD_W0_SD_PTR0, skbdesc->skb_dma); | ||
| 72 | rt2x00_desc_write(txd, 0, word); | ||
| 73 | |||
| 74 | word = 0; | ||
| 75 | rt2x00_set_field32(&word, TXD_W1_SD_LEN1, entry->skb->len); | ||
| 76 | rt2x00_set_field32(&word, TXD_W1_LAST_SEC1, | ||
| 77 | !test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); | ||
| 78 | rt2x00_set_field32(&word, TXD_W1_BURST, | ||
| 79 | test_bit(ENTRY_TXD_BURST, &txdesc->flags)); | ||
| 80 | rt2x00_set_field32(&word, TXD_W1_SD_LEN0, txwi_size); | ||
| 81 | rt2x00_set_field32(&word, TXD_W1_LAST_SEC0, 0); | ||
| 82 | rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 0); | ||
| 83 | rt2x00_desc_write(txd, 1, word); | ||
| 84 | |||
| 85 | word = 0; | ||
| 86 | rt2x00_set_field32(&word, TXD_W2_SD_PTR1, | ||
| 87 | skbdesc->skb_dma + txwi_size); | ||
| 88 | rt2x00_desc_write(txd, 2, word); | ||
| 89 | |||
| 90 | word = 0; | ||
| 91 | rt2x00_set_field32(&word, TXD_W3_WIV, | ||
| 92 | !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags)); | ||
| 93 | rt2x00_set_field32(&word, TXD_W3_QSEL, 2); | ||
| 94 | rt2x00_desc_write(txd, 3, word); | ||
| 95 | |||
| 96 | /* | ||
| 97 | * Register descriptor details in skb frame descriptor. | ||
| 98 | */ | ||
| 99 | skbdesc->desc = txd; | ||
| 100 | skbdesc->desc_len = TXD_DESC_SIZE; | ||
| 101 | } | ||
| 102 | EXPORT_SYMBOL_GPL(rt2800mmio_write_tx_desc); | ||
| 103 | |||
| 104 | /* | ||
| 105 | * RX control handlers | ||
| 106 | */ | ||
| 107 | void rt2800mmio_fill_rxdone(struct queue_entry *entry, | ||
| 108 | struct rxdone_entry_desc *rxdesc) | ||
| 109 | { | ||
| 110 | struct queue_entry_priv_mmio *entry_priv = entry->priv_data; | ||
| 111 | __le32 *rxd = entry_priv->desc; | ||
| 112 | u32 word; | ||
| 113 | |||
| 114 | rt2x00_desc_read(rxd, 3, &word); | ||
| 115 | |||
| 116 | if (rt2x00_get_field32(word, RXD_W3_CRC_ERROR)) | ||
| 117 | rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; | ||
| 118 | |||
| 119 | /* | ||
| 120 | * Unfortunately we don't know the cipher type used during | ||
| 121 | * decryption. This prevents us from correct providing | ||
| 122 | * correct statistics through debugfs. | ||
| 123 | */ | ||
| 124 | rxdesc->cipher_status = rt2x00_get_field32(word, RXD_W3_CIPHER_ERROR); | ||
| 125 | |||
| 126 | if (rt2x00_get_field32(word, RXD_W3_DECRYPTED)) { | ||
| 127 | /* | ||
| 128 | * Hardware has stripped IV/EIV data from 802.11 frame during | ||
| 129 | * decryption. Unfortunately the descriptor doesn't contain | ||
| 130 | * any fields with the EIV/IV data either, so they can't | ||
| 131 | * be restored by rt2x00lib. | ||
| 132 | */ | ||
| 133 | rxdesc->flags |= RX_FLAG_IV_STRIPPED; | ||
| 134 | |||
| 135 | /* | ||
| 136 | * The hardware has already checked the Michael Mic and has | ||
| 137 | * stripped it from the frame. Signal this to mac80211. | ||
| 138 | */ | ||
| 139 | rxdesc->flags |= RX_FLAG_MMIC_STRIPPED; | ||
| 140 | |||
| 141 | if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS) | ||
| 142 | rxdesc->flags |= RX_FLAG_DECRYPTED; | ||
| 143 | else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC) | ||
| 144 | rxdesc->flags |= RX_FLAG_MMIC_ERROR; | ||
| 145 | } | ||
| 146 | |||
| 147 | if (rt2x00_get_field32(word, RXD_W3_MY_BSS)) | ||
| 148 | rxdesc->dev_flags |= RXDONE_MY_BSS; | ||
| 149 | |||
| 150 | if (rt2x00_get_field32(word, RXD_W3_L2PAD)) | ||
| 151 | rxdesc->dev_flags |= RXDONE_L2PAD; | ||
| 152 | |||
| 153 | /* | ||
| 154 | * Process the RXWI structure that is at the start of the buffer. | ||
| 155 | */ | ||
| 156 | rt2800_process_rxwi(entry, rxdesc); | ||
| 157 | } | ||
| 158 | EXPORT_SYMBOL_GPL(rt2800mmio_fill_rxdone); | ||
| 159 | |||
| 160 | /* | ||
| 161 | * Interrupt functions. | ||
| 162 | */ | ||
| 163 | static void rt2800mmio_wakeup(struct rt2x00_dev *rt2x00dev) | ||
| 164 | { | ||
| 165 | struct ieee80211_conf conf = { .flags = 0 }; | ||
| 166 | struct rt2x00lib_conf libconf = { .conf = &conf }; | ||
| 167 | |||
| 168 | rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); | ||
| 169 | } | ||
| 170 | |||
| 171 | static bool rt2800mmio_txdone_entry_check(struct queue_entry *entry, u32 status) | ||
| 172 | { | ||
| 173 | __le32 *txwi; | ||
| 174 | u32 word; | ||
| 175 | int wcid, tx_wcid; | ||
| 176 | |||
| 177 | wcid = rt2x00_get_field32(status, TX_STA_FIFO_WCID); | ||
| 178 | |||
| 179 | txwi = rt2800_drv_get_txwi(entry); | ||
| 180 | rt2x00_desc_read(txwi, 1, &word); | ||
| 181 | tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID); | ||
| 182 | |||
| 183 | return (tx_wcid == wcid); | ||
| 184 | } | ||
| 185 | |||
| 186 | static bool rt2800mmio_txdone_find_entry(struct queue_entry *entry, void *data) | ||
| 187 | { | ||
| 188 | u32 status = *(u32 *)data; | ||
| 189 | |||
| 190 | /* | ||
| 191 | * rt2800pci hardware might reorder frames when exchanging traffic | ||
| 192 | * with multiple BA enabled STAs. | ||
| 193 | * | ||
| 194 | * For example, a tx queue | ||
| 195 | * [ STA1 | STA2 | STA1 | STA2 ] | ||
| 196 | * can result in tx status reports | ||
| 197 | * [ STA1 | STA1 | STA2 | STA2 ] | ||
| 198 | * when the hw decides to aggregate the frames for STA1 into one AMPDU. | ||
| 199 | * | ||
| 200 | * To mitigate this effect, associate the tx status to the first frame | ||
| 201 | * in the tx queue with a matching wcid. | ||
| 202 | */ | ||
| 203 | if (rt2800mmio_txdone_entry_check(entry, status) && | ||
| 204 | !test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) { | ||
| 205 | /* | ||
| 206 | * Got a matching frame, associate the tx status with | ||
| 207 | * the frame | ||
| 208 | */ | ||
| 209 | entry->status = status; | ||
| 210 | set_bit(ENTRY_DATA_STATUS_SET, &entry->flags); | ||
| 211 | return true; | ||
| 212 | } | ||
| 213 | |||
| 214 | /* Check the next frame */ | ||
| 215 | return false; | ||
| 216 | } | ||
| 217 | |||
| 218 | static bool rt2800mmio_txdone_match_first(struct queue_entry *entry, void *data) | ||
| 219 | { | ||
| 220 | u32 status = *(u32 *)data; | ||
| 221 | |||
| 222 | /* | ||
| 223 | * Find the first frame without tx status and assign this status to it | ||
| 224 | * regardless if it matches or not. | ||
| 225 | */ | ||
| 226 | if (!test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) { | ||
| 227 | /* | ||
| 228 | * Got a matching frame, associate the tx status with | ||
| 229 | * the frame | ||
| 230 | */ | ||
| 231 | entry->status = status; | ||
| 232 | set_bit(ENTRY_DATA_STATUS_SET, &entry->flags); | ||
| 233 | return true; | ||
| 234 | } | ||
| 235 | |||
| 236 | /* Check the next frame */ | ||
| 237 | return false; | ||
| 238 | } | ||
| 239 | static bool rt2800mmio_txdone_release_entries(struct queue_entry *entry, | ||
| 240 | void *data) | ||
| 241 | { | ||
| 242 | if (test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) { | ||
| 243 | rt2800_txdone_entry(entry, entry->status, | ||
| 244 | rt2800mmio_get_txwi(entry)); | ||
| 245 | return false; | ||
| 246 | } | ||
| 247 | |||
| 248 | /* No more frames to release */ | ||
| 249 | return true; | ||
| 250 | } | ||
| 251 | |||
| 252 | static bool rt2800mmio_txdone(struct rt2x00_dev *rt2x00dev) | ||
| 253 | { | ||
| 254 | struct data_queue *queue; | ||
| 255 | u32 status; | ||
| 256 | u8 qid; | ||
| 257 | int max_tx_done = 16; | ||
| 258 | |||
| 259 | while (kfifo_get(&rt2x00dev->txstatus_fifo, &status)) { | ||
| 260 | qid = rt2x00_get_field32(status, TX_STA_FIFO_PID_QUEUE); | ||
| 261 | if (unlikely(qid >= QID_RX)) { | ||
| 262 | /* | ||
| 263 | * Unknown queue, this shouldn't happen. Just drop | ||
| 264 | * this tx status. | ||
| 265 | */ | ||
| 266 | rt2x00_warn(rt2x00dev, "Got TX status report with unexpected pid %u, dropping\n", | ||
| 267 | qid); | ||
| 268 | break; | ||
| 269 | } | ||
| 270 | |||
| 271 | queue = rt2x00queue_get_tx_queue(rt2x00dev, qid); | ||
| 272 | if (unlikely(queue == NULL)) { | ||
| 273 | /* | ||
| 274 | * The queue is NULL, this shouldn't happen. Stop | ||
| 275 | * processing here and drop the tx status | ||
| 276 | */ | ||
| 277 | rt2x00_warn(rt2x00dev, "Got TX status for an unavailable queue %u, dropping\n", | ||
| 278 | qid); | ||
| 279 | break; | ||
| 280 | } | ||
| 281 | |||
| 282 | if (unlikely(rt2x00queue_empty(queue))) { | ||
| 283 | /* | ||
| 284 | * The queue is empty. Stop processing here | ||
| 285 | * and drop the tx status. | ||
| 286 | */ | ||
| 287 | rt2x00_warn(rt2x00dev, "Got TX status for an empty queue %u, dropping\n", | ||
| 288 | qid); | ||
| 289 | break; | ||
| 290 | } | ||
| 291 | |||
| 292 | /* | ||
| 293 | * Let's associate this tx status with the first | ||
| 294 | * matching frame. | ||
| 295 | */ | ||
| 296 | if (!rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, | ||
| 297 | Q_INDEX, &status, | ||
| 298 | rt2800mmio_txdone_find_entry)) { | ||
| 299 | /* | ||
| 300 | * We cannot match the tx status to any frame, so just | ||
| 301 | * use the first one. | ||
| 302 | */ | ||
| 303 | if (!rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, | ||
| 304 | Q_INDEX, &status, | ||
| 305 | rt2800mmio_txdone_match_first)) { | ||
| 306 | rt2x00_warn(rt2x00dev, "No frame found for TX status on queue %u, dropping\n", | ||
| 307 | qid); | ||
| 308 | break; | ||
| 309 | } | ||
| 310 | } | ||
| 311 | |||
| 312 | /* | ||
| 313 | * Release all frames with a valid tx status. | ||
| 314 | */ | ||
| 315 | rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, | ||
| 316 | Q_INDEX, NULL, | ||
| 317 | rt2800mmio_txdone_release_entries); | ||
| 318 | |||
| 319 | if (--max_tx_done == 0) | ||
| 320 | break; | ||
| 321 | } | ||
| 322 | |||
| 323 | return !max_tx_done; | ||
| 324 | } | ||
| 325 | |||
| 326 | static inline void rt2800mmio_enable_interrupt(struct rt2x00_dev *rt2x00dev, | ||
| 327 | struct rt2x00_field32 irq_field) | ||
| 328 | { | ||
| 329 | u32 reg; | ||
| 330 | |||
| 331 | /* | ||
| 332 | * Enable a single interrupt. The interrupt mask register | ||
| 333 | * access needs locking. | ||
| 334 | */ | ||
| 335 | spin_lock_irq(&rt2x00dev->irqmask_lock); | ||
| 336 | rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, ®); | ||
| 337 | rt2x00_set_field32(®, irq_field, 1); | ||
| 338 | rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg); | ||
| 339 | spin_unlock_irq(&rt2x00dev->irqmask_lock); | ||
| 340 | } | ||
| 341 | |||
| 342 | void rt2800mmio_txstatus_tasklet(unsigned long data) | ||
| 343 | { | ||
| 344 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
| 345 | if (rt2800mmio_txdone(rt2x00dev)) | ||
| 346 | tasklet_schedule(&rt2x00dev->txstatus_tasklet); | ||
| 347 | |||
| 348 | /* | ||
| 349 | * No need to enable the tx status interrupt here as we always | ||
| 350 | * leave it enabled to minimize the possibility of a tx status | ||
| 351 | * register overflow. See comment in interrupt handler. | ||
| 352 | */ | ||
| 353 | } | ||
| 354 | EXPORT_SYMBOL_GPL(rt2800mmio_txstatus_tasklet); | ||
| 355 | |||
| 356 | void rt2800mmio_pretbtt_tasklet(unsigned long data) | ||
| 357 | { | ||
| 358 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
| 359 | rt2x00lib_pretbtt(rt2x00dev); | ||
| 360 | if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | ||
| 361 | rt2800mmio_enable_interrupt(rt2x00dev, INT_MASK_CSR_PRE_TBTT); | ||
| 362 | } | ||
| 363 | EXPORT_SYMBOL_GPL(rt2800mmio_pretbtt_tasklet); | ||
| 364 | |||
| 365 | void rt2800mmio_tbtt_tasklet(unsigned long data) | ||
| 366 | { | ||
| 367 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
| 368 | struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; | ||
| 369 | u32 reg; | ||
| 370 | |||
| 371 | rt2x00lib_beacondone(rt2x00dev); | ||
| 372 | |||
| 373 | if (rt2x00dev->intf_ap_count) { | ||
| 374 | /* | ||
| 375 | * The rt2800pci hardware tbtt timer is off by 1us per tbtt | ||
| 376 | * causing beacon skew and as a result causing problems with | ||
| 377 | * some powersaving clients over time. Shorten the beacon | ||
| 378 | * interval every 64 beacons by 64us to mitigate this effect. | ||
| 379 | */ | ||
| 380 | if (drv_data->tbtt_tick == (BCN_TBTT_OFFSET - 2)) { | ||
| 381 | rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, ®); | ||
| 382 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, | ||
| 383 | (rt2x00dev->beacon_int * 16) - 1); | ||
| 384 | rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg); | ||
| 385 | } else if (drv_data->tbtt_tick == (BCN_TBTT_OFFSET - 1)) { | ||
| 386 | rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, ®); | ||
| 387 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, | ||
| 388 | (rt2x00dev->beacon_int * 16)); | ||
| 389 | rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg); | ||
| 390 | } | ||
| 391 | drv_data->tbtt_tick++; | ||
| 392 | drv_data->tbtt_tick %= BCN_TBTT_OFFSET; | ||
| 393 | } | ||
| 394 | |||
| 395 | if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | ||
| 396 | rt2800mmio_enable_interrupt(rt2x00dev, INT_MASK_CSR_TBTT); | ||
| 397 | } | ||
| 398 | EXPORT_SYMBOL_GPL(rt2800mmio_tbtt_tasklet); | ||
| 399 | |||
| 400 | void rt2800mmio_rxdone_tasklet(unsigned long data) | ||
| 401 | { | ||
| 402 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
| 403 | if (rt2x00mmio_rxdone(rt2x00dev)) | ||
| 404 | tasklet_schedule(&rt2x00dev->rxdone_tasklet); | ||
| 405 | else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | ||
| 406 | rt2800mmio_enable_interrupt(rt2x00dev, INT_MASK_CSR_RX_DONE); | ||
| 407 | } | ||
| 408 | EXPORT_SYMBOL_GPL(rt2800mmio_rxdone_tasklet); | ||
| 409 | |||
| 410 | void rt2800mmio_autowake_tasklet(unsigned long data) | ||
| 411 | { | ||
| 412 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
| 413 | rt2800mmio_wakeup(rt2x00dev); | ||
| 414 | if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | ||
| 415 | rt2800mmio_enable_interrupt(rt2x00dev, | ||
| 416 | INT_MASK_CSR_AUTO_WAKEUP); | ||
| 417 | } | ||
| 418 | EXPORT_SYMBOL_GPL(rt2800mmio_autowake_tasklet); | ||
| 419 | |||
| 420 | static void rt2800mmio_txstatus_interrupt(struct rt2x00_dev *rt2x00dev) | ||
| 421 | { | ||
| 422 | u32 status; | ||
| 423 | int i; | ||
| 424 | |||
| 425 | /* | ||
| 426 | * The TX_FIFO_STATUS interrupt needs special care. We should | ||
| 427 | * read TX_STA_FIFO but we should do it immediately as otherwise | ||
| 428 | * the register can overflow and we would lose status reports. | ||
| 429 | * | ||
| 430 | * Hence, read the TX_STA_FIFO register and copy all tx status | ||
| 431 | * reports into a kernel FIFO which is handled in the txstatus | ||
| 432 | * tasklet. We use a tasklet to process the tx status reports | ||
| 433 | * because we can schedule the tasklet multiple times (when the | ||
| 434 | * interrupt fires again during tx status processing). | ||
| 435 | * | ||
| 436 | * Furthermore we don't disable the TX_FIFO_STATUS | ||
| 437 | * interrupt here but leave it enabled so that the TX_STA_FIFO | ||
| 438 | * can also be read while the tx status tasklet gets executed. | ||
| 439 | * | ||
| 440 | * Since we have only one producer and one consumer we don't | ||
| 441 | * need to lock the kfifo. | ||
| 442 | */ | ||
| 443 | for (i = 0; i < rt2x00dev->tx->limit; i++) { | ||
| 444 | rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO, &status); | ||
| 445 | |||
| 446 | if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID)) | ||
| 447 | break; | ||
| 448 | |||
| 449 | if (!kfifo_put(&rt2x00dev->txstatus_fifo, &status)) { | ||
| 450 | rt2x00_warn(rt2x00dev, "TX status FIFO overrun, drop tx status report\n"); | ||
| 451 | break; | ||
| 452 | } | ||
| 453 | } | ||
| 454 | |||
| 455 | /* Schedule the tasklet for processing the tx status. */ | ||
| 456 | tasklet_schedule(&rt2x00dev->txstatus_tasklet); | ||
| 457 | } | ||
| 458 | |||
| 459 | irqreturn_t rt2800mmio_interrupt(int irq, void *dev_instance) | ||
| 460 | { | ||
| 461 | struct rt2x00_dev *rt2x00dev = dev_instance; | ||
| 462 | u32 reg, mask; | ||
| 463 | |||
| 464 | /* Read status and ACK all interrupts */ | ||
| 465 | rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, ®); | ||
| 466 | rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg); | ||
| 467 | |||
| 468 | if (!reg) | ||
| 469 | return IRQ_NONE; | ||
| 470 | |||
| 471 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | ||
| 472 | return IRQ_HANDLED; | ||
| 473 | |||
| 474 | /* | ||
| 475 | * Since INT_MASK_CSR and INT_SOURCE_CSR use the same bits | ||
| 476 | * for interrupts and interrupt masks we can just use the value of | ||
| 477 | * INT_SOURCE_CSR to create the interrupt mask. | ||
| 478 | */ | ||
| 479 | mask = ~reg; | ||
| 480 | |||
| 481 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) { | ||
| 482 | rt2800mmio_txstatus_interrupt(rt2x00dev); | ||
| 483 | /* | ||
| 484 | * Never disable the TX_FIFO_STATUS interrupt. | ||
| 485 | */ | ||
| 486 | rt2x00_set_field32(&mask, INT_MASK_CSR_TX_FIFO_STATUS, 1); | ||
| 487 | } | ||
| 488 | |||
| 489 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT)) | ||
| 490 | tasklet_hi_schedule(&rt2x00dev->pretbtt_tasklet); | ||
| 491 | |||
| 492 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT)) | ||
| 493 | tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet); | ||
| 494 | |||
| 495 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE)) | ||
| 496 | tasklet_schedule(&rt2x00dev->rxdone_tasklet); | ||
| 497 | |||
| 498 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP)) | ||
| 499 | tasklet_schedule(&rt2x00dev->autowake_tasklet); | ||
| 500 | |||
| 501 | /* | ||
| 502 | * Disable all interrupts for which a tasklet was scheduled right now, | ||
| 503 | * the tasklet will reenable the appropriate interrupts. | ||
| 504 | */ | ||
| 505 | spin_lock(&rt2x00dev->irqmask_lock); | ||
| 506 | rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, ®); | ||
| 507 | reg &= mask; | ||
| 508 | rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg); | ||
| 509 | spin_unlock(&rt2x00dev->irqmask_lock); | ||
| 510 | |||
| 511 | return IRQ_HANDLED; | ||
| 512 | } | ||
| 513 | EXPORT_SYMBOL_GPL(rt2800mmio_interrupt); | ||
| 514 | |||
| 515 | void rt2800mmio_toggle_irq(struct rt2x00_dev *rt2x00dev, | ||
| 516 | enum dev_state state) | ||
| 517 | { | ||
| 518 | u32 reg; | ||
| 519 | unsigned long flags; | ||
| 520 | |||
| 521 | /* | ||
| 522 | * When interrupts are being enabled, the interrupt registers | ||
| 523 | * should clear the register to assure a clean state. | ||
| 524 | */ | ||
| 525 | if (state == STATE_RADIO_IRQ_ON) { | ||
| 526 | rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, ®); | ||
| 527 | rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg); | ||
| 528 | } | ||
| 529 | |||
| 530 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); | ||
| 531 | reg = 0; | ||
| 532 | if (state == STATE_RADIO_IRQ_ON) { | ||
| 533 | rt2x00_set_field32(®, INT_MASK_CSR_RX_DONE, 1); | ||
| 534 | rt2x00_set_field32(®, INT_MASK_CSR_TBTT, 1); | ||
| 535 | rt2x00_set_field32(®, INT_MASK_CSR_PRE_TBTT, 1); | ||
| 536 | rt2x00_set_field32(®, INT_MASK_CSR_TX_FIFO_STATUS, 1); | ||
| 537 | rt2x00_set_field32(®, INT_MASK_CSR_AUTO_WAKEUP, 1); | ||
| 538 | } | ||
| 539 | rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg); | ||
| 540 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); | ||
| 541 | |||
| 542 | if (state == STATE_RADIO_IRQ_OFF) { | ||
| 543 | /* | ||
| 544 | * Wait for possibly running tasklets to finish. | ||
| 545 | */ | ||
| 546 | tasklet_kill(&rt2x00dev->txstatus_tasklet); | ||
| 547 | tasklet_kill(&rt2x00dev->rxdone_tasklet); | ||
| 548 | tasklet_kill(&rt2x00dev->autowake_tasklet); | ||
| 549 | tasklet_kill(&rt2x00dev->tbtt_tasklet); | ||
| 550 | tasklet_kill(&rt2x00dev->pretbtt_tasklet); | ||
| 551 | } | ||
| 552 | } | ||
| 553 | EXPORT_SYMBOL_GPL(rt2800mmio_toggle_irq); | ||
| 554 | |||
| 555 | /* | ||
| 556 | * Queue handlers. | ||
| 557 | */ | ||
| 558 | void rt2800mmio_start_queue(struct data_queue *queue) | ||
| 559 | { | ||
| 560 | struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; | ||
| 561 | u32 reg; | ||
| 562 | |||
| 563 | switch (queue->qid) { | ||
| 564 | case QID_RX: | ||
| 565 | rt2x00mmio_register_read(rt2x00dev, MAC_SYS_CTRL, ®); | ||
| 566 | rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 1); | ||
| 567 | rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, reg); | ||
| 568 | break; | ||
| 569 | case QID_BEACON: | ||
| 570 | rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, ®); | ||
| 571 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); | ||
| 572 | rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); | ||
| 573 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); | ||
| 574 | rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg); | ||
| 575 | |||
| 576 | rt2x00mmio_register_read(rt2x00dev, INT_TIMER_EN, ®); | ||
| 577 | rt2x00_set_field32(®, INT_TIMER_EN_PRE_TBTT_TIMER, 1); | ||
| 578 | rt2x00mmio_register_write(rt2x00dev, INT_TIMER_EN, reg); | ||
| 579 | break; | ||
| 580 | default: | ||
| 581 | break; | ||
| 582 | } | ||
| 583 | } | ||
| 584 | EXPORT_SYMBOL_GPL(rt2800mmio_start_queue); | ||
| 585 | |||
| 586 | void rt2800mmio_kick_queue(struct data_queue *queue) | ||
| 587 | { | ||
| 588 | struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; | ||
| 589 | struct queue_entry *entry; | ||
| 590 | |||
| 591 | switch (queue->qid) { | ||
| 592 | case QID_AC_VO: | ||
| 593 | case QID_AC_VI: | ||
| 594 | case QID_AC_BE: | ||
| 595 | case QID_AC_BK: | ||
| 596 | entry = rt2x00queue_get_entry(queue, Q_INDEX); | ||
| 597 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX(queue->qid), | ||
| 598 | entry->entry_idx); | ||
| 599 | break; | ||
| 600 | case QID_MGMT: | ||
| 601 | entry = rt2x00queue_get_entry(queue, Q_INDEX); | ||
| 602 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX(5), | ||
| 603 | entry->entry_idx); | ||
| 604 | break; | ||
| 605 | default: | ||
| 606 | break; | ||
| 607 | } | ||
| 608 | } | ||
| 609 | EXPORT_SYMBOL_GPL(rt2800mmio_kick_queue); | ||
| 610 | |||
| 611 | void rt2800mmio_stop_queue(struct data_queue *queue) | ||
| 612 | { | ||
| 613 | struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; | ||
| 614 | u32 reg; | ||
| 615 | |||
| 616 | switch (queue->qid) { | ||
| 617 | case QID_RX: | ||
| 618 | rt2x00mmio_register_read(rt2x00dev, MAC_SYS_CTRL, ®); | ||
| 619 | rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 0); | ||
| 620 | rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, reg); | ||
| 621 | break; | ||
| 622 | case QID_BEACON: | ||
| 623 | rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, ®); | ||
| 624 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 0); | ||
| 625 | rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0); | ||
| 626 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); | ||
| 627 | rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg); | ||
| 628 | |||
| 629 | rt2x00mmio_register_read(rt2x00dev, INT_TIMER_EN, ®); | ||
| 630 | rt2x00_set_field32(®, INT_TIMER_EN_PRE_TBTT_TIMER, 0); | ||
| 631 | rt2x00mmio_register_write(rt2x00dev, INT_TIMER_EN, reg); | ||
| 632 | |||
| 633 | /* | ||
| 634 | * Wait for current invocation to finish. The tasklet | ||
| 635 | * won't be scheduled anymore afterwards since we disabled | ||
| 636 | * the TBTT and PRE TBTT timer. | ||
| 637 | */ | ||
| 638 | tasklet_kill(&rt2x00dev->tbtt_tasklet); | ||
| 639 | tasklet_kill(&rt2x00dev->pretbtt_tasklet); | ||
| 640 | |||
| 641 | break; | ||
| 642 | default: | ||
| 643 | break; | ||
| 644 | } | ||
| 645 | } | ||
| 646 | EXPORT_SYMBOL_GPL(rt2800mmio_stop_queue); | ||
| 647 | |||
| 648 | void rt2800mmio_queue_init(struct data_queue *queue) | ||
| 649 | { | ||
| 650 | struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; | ||
| 651 | unsigned short txwi_size, rxwi_size; | ||
| 652 | |||
| 653 | rt2800_get_txwi_rxwi_size(rt2x00dev, &txwi_size, &rxwi_size); | ||
| 654 | |||
| 655 | switch (queue->qid) { | ||
| 656 | case QID_RX: | ||
| 657 | queue->limit = 128; | ||
| 658 | queue->data_size = AGGREGATION_SIZE; | ||
| 659 | queue->desc_size = RXD_DESC_SIZE; | ||
| 660 | queue->winfo_size = rxwi_size; | ||
| 661 | queue->priv_size = sizeof(struct queue_entry_priv_mmio); | ||
| 662 | break; | ||
| 663 | |||
| 664 | case QID_AC_VO: | ||
| 665 | case QID_AC_VI: | ||
| 666 | case QID_AC_BE: | ||
| 667 | case QID_AC_BK: | ||
| 668 | queue->limit = 64; | ||
| 669 | queue->data_size = AGGREGATION_SIZE; | ||
| 670 | queue->desc_size = TXD_DESC_SIZE; | ||
| 671 | queue->winfo_size = txwi_size; | ||
| 672 | queue->priv_size = sizeof(struct queue_entry_priv_mmio); | ||
| 673 | break; | ||
| 674 | |||
| 675 | case QID_BEACON: | ||
| 676 | queue->limit = 8; | ||
| 677 | queue->data_size = 0; /* No DMA required for beacons */ | ||
| 678 | queue->desc_size = TXD_DESC_SIZE; | ||
| 679 | queue->winfo_size = txwi_size; | ||
| 680 | queue->priv_size = sizeof(struct queue_entry_priv_mmio); | ||
| 681 | break; | ||
| 682 | |||
| 683 | case QID_ATIM: | ||
| 684 | /* fallthrough */ | ||
| 685 | default: | ||
| 686 | BUG(); | ||
| 687 | break; | ||
| 688 | } | ||
| 689 | } | ||
| 690 | EXPORT_SYMBOL_GPL(rt2800mmio_queue_init); | ||
| 691 | |||
| 692 | /* | ||
| 693 | * Initialization functions. | ||
| 694 | */ | ||
| 695 | bool rt2800mmio_get_entry_state(struct queue_entry *entry) | ||
| 696 | { | ||
| 697 | struct queue_entry_priv_mmio *entry_priv = entry->priv_data; | ||
| 698 | u32 word; | ||
| 699 | |||
| 700 | if (entry->queue->qid == QID_RX) { | ||
| 701 | rt2x00_desc_read(entry_priv->desc, 1, &word); | ||
| 702 | |||
| 703 | return (!rt2x00_get_field32(word, RXD_W1_DMA_DONE)); | ||
| 704 | } else { | ||
| 705 | rt2x00_desc_read(entry_priv->desc, 1, &word); | ||
| 706 | |||
| 707 | return (!rt2x00_get_field32(word, TXD_W1_DMA_DONE)); | ||
| 708 | } | ||
| 709 | } | ||
| 710 | EXPORT_SYMBOL_GPL(rt2800mmio_get_entry_state); | ||
| 711 | |||
| 712 | void rt2800mmio_clear_entry(struct queue_entry *entry) | ||
| 713 | { | ||
| 714 | struct queue_entry_priv_mmio *entry_priv = entry->priv_data; | ||
| 715 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | ||
| 716 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | ||
| 717 | u32 word; | ||
| 718 | |||
| 719 | if (entry->queue->qid == QID_RX) { | ||
| 720 | rt2x00_desc_read(entry_priv->desc, 0, &word); | ||
| 721 | rt2x00_set_field32(&word, RXD_W0_SDP0, skbdesc->skb_dma); | ||
| 722 | rt2x00_desc_write(entry_priv->desc, 0, word); | ||
| 723 | |||
| 724 | rt2x00_desc_read(entry_priv->desc, 1, &word); | ||
| 725 | rt2x00_set_field32(&word, RXD_W1_DMA_DONE, 0); | ||
| 726 | rt2x00_desc_write(entry_priv->desc, 1, word); | ||
| 727 | |||
| 728 | /* | ||
| 729 | * Set RX IDX in register to inform hardware that we have | ||
| 730 | * handled this entry and it is available for reuse again. | ||
| 731 | */ | ||
| 732 | rt2x00mmio_register_write(rt2x00dev, RX_CRX_IDX, | ||
| 733 | entry->entry_idx); | ||
| 734 | } else { | ||
| 735 | rt2x00_desc_read(entry_priv->desc, 1, &word); | ||
| 736 | rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 1); | ||
| 737 | rt2x00_desc_write(entry_priv->desc, 1, word); | ||
| 738 | } | ||
| 739 | } | ||
| 740 | EXPORT_SYMBOL_GPL(rt2800mmio_clear_entry); | ||
| 741 | |||
| 742 | int rt2800mmio_init_queues(struct rt2x00_dev *rt2x00dev) | ||
| 743 | { | ||
| 744 | struct queue_entry_priv_mmio *entry_priv; | ||
| 745 | |||
| 746 | /* | ||
| 747 | * Initialize registers. | ||
| 748 | */ | ||
| 749 | entry_priv = rt2x00dev->tx[0].entries[0].priv_data; | ||
| 750 | rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR0, | ||
| 751 | entry_priv->desc_dma); | ||
| 752 | rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT0, | ||
| 753 | rt2x00dev->tx[0].limit); | ||
| 754 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX0, 0); | ||
| 755 | rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX0, 0); | ||
| 756 | |||
| 757 | entry_priv = rt2x00dev->tx[1].entries[0].priv_data; | ||
| 758 | rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR1, | ||
| 759 | entry_priv->desc_dma); | ||
| 760 | rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT1, | ||
| 761 | rt2x00dev->tx[1].limit); | ||
| 762 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX1, 0); | ||
| 763 | rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX1, 0); | ||
| 764 | |||
| 765 | entry_priv = rt2x00dev->tx[2].entries[0].priv_data; | ||
| 766 | rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR2, | ||
| 767 | entry_priv->desc_dma); | ||
| 768 | rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT2, | ||
| 769 | rt2x00dev->tx[2].limit); | ||
| 770 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX2, 0); | ||
| 771 | rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX2, 0); | ||
| 772 | |||
| 773 | entry_priv = rt2x00dev->tx[3].entries[0].priv_data; | ||
| 774 | rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR3, | ||
| 775 | entry_priv->desc_dma); | ||
| 776 | rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT3, | ||
| 777 | rt2x00dev->tx[3].limit); | ||
| 778 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX3, 0); | ||
| 779 | rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX3, 0); | ||
| 780 | |||
| 781 | rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR4, 0); | ||
| 782 | rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT4, 0); | ||
| 783 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX4, 0); | ||
| 784 | rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX4, 0); | ||
| 785 | |||
| 786 | rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR5, 0); | ||
| 787 | rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT5, 0); | ||
| 788 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX5, 0); | ||
| 789 | rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX5, 0); | ||
| 790 | |||
| 791 | entry_priv = rt2x00dev->rx->entries[0].priv_data; | ||
| 792 | rt2x00mmio_register_write(rt2x00dev, RX_BASE_PTR, | ||
| 793 | entry_priv->desc_dma); | ||
| 794 | rt2x00mmio_register_write(rt2x00dev, RX_MAX_CNT, | ||
| 795 | rt2x00dev->rx[0].limit); | ||
| 796 | rt2x00mmio_register_write(rt2x00dev, RX_CRX_IDX, | ||
| 797 | rt2x00dev->rx[0].limit - 1); | ||
| 798 | rt2x00mmio_register_write(rt2x00dev, RX_DRX_IDX, 0); | ||
| 799 | |||
| 800 | rt2800_disable_wpdma(rt2x00dev); | ||
| 801 | |||
| 802 | rt2x00mmio_register_write(rt2x00dev, DELAY_INT_CFG, 0); | ||
| 803 | |||
| 804 | return 0; | ||
| 805 | } | ||
| 806 | EXPORT_SYMBOL_GPL(rt2800mmio_init_queues); | ||
| 807 | |||
| 808 | int rt2800mmio_init_registers(struct rt2x00_dev *rt2x00dev) | ||
| 809 | { | ||
| 810 | u32 reg; | ||
| 811 | |||
| 812 | /* | ||
| 813 | * Reset DMA indexes | ||
| 814 | */ | ||
| 815 | rt2x00mmio_register_read(rt2x00dev, WPDMA_RST_IDX, ®); | ||
| 816 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, 1); | ||
| 817 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, 1); | ||
| 818 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, 1); | ||
| 819 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX3, 1); | ||
| 820 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX4, 1); | ||
| 821 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX5, 1); | ||
| 822 | rt2x00_set_field32(®, WPDMA_RST_IDX_DRX_IDX0, 1); | ||
| 823 | rt2x00mmio_register_write(rt2x00dev, WPDMA_RST_IDX, reg); | ||
| 824 | |||
| 825 | rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f); | ||
| 826 | rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00); | ||
| 827 | |||
| 828 | if (rt2x00_is_pcie(rt2x00dev) && | ||
| 829 | (rt2x00_rt(rt2x00dev, RT3090) || | ||
| 830 | rt2x00_rt(rt2x00dev, RT3390) || | ||
| 831 | rt2x00_rt(rt2x00dev, RT3572) || | ||
| 832 | rt2x00_rt(rt2x00dev, RT3593) || | ||
| 833 | rt2x00_rt(rt2x00dev, RT5390) || | ||
| 834 | rt2x00_rt(rt2x00dev, RT5392) || | ||
| 835 | rt2x00_rt(rt2x00dev, RT5592))) { | ||
| 836 | rt2x00mmio_register_read(rt2x00dev, AUX_CTRL, ®); | ||
| 837 | rt2x00_set_field32(®, AUX_CTRL_FORCE_PCIE_CLK, 1); | ||
| 838 | rt2x00_set_field32(®, AUX_CTRL_WAKE_PCIE_EN, 1); | ||
| 839 | rt2x00mmio_register_write(rt2x00dev, AUX_CTRL, reg); | ||
| 840 | } | ||
| 841 | |||
| 842 | rt2x00mmio_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); | ||
| 843 | |||
| 844 | reg = 0; | ||
| 845 | rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1); | ||
| 846 | rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1); | ||
| 847 | rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, reg); | ||
| 848 | |||
| 849 | rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); | ||
| 850 | |||
| 851 | return 0; | ||
| 852 | } | ||
| 853 | EXPORT_SYMBOL_GPL(rt2800mmio_init_registers); | ||
| 854 | |||
| 855 | /* | ||
| 856 | * Device state switch handlers. | ||
| 857 | */ | ||
| 858 | int rt2800mmio_enable_radio(struct rt2x00_dev *rt2x00dev) | ||
| 859 | { | ||
| 860 | /* Wait for DMA, ignore error until we initialize queues. */ | ||
| 861 | rt2800_wait_wpdma_ready(rt2x00dev); | ||
| 862 | |||
| 863 | if (unlikely(rt2800mmio_init_queues(rt2x00dev))) | ||
| 864 | return -EIO; | ||
| 865 | |||
| 866 | return rt2800_enable_radio(rt2x00dev); | ||
| 867 | } | ||
| 868 | EXPORT_SYMBOL_GPL(rt2800mmio_enable_radio); | ||
| 869 | |||
| 870 | MODULE_AUTHOR(DRV_PROJECT); | ||
| 871 | MODULE_VERSION(DRV_VERSION); | ||
| 872 | MODULE_DESCRIPTION("rt2800 MMIO library"); | ||
| 873 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/net/wireless/rt2x00/rt2800mmio.h b/drivers/net/wireless/rt2x00/rt2800mmio.h new file mode 100644 index 000000000000..6a10de3eee3e --- /dev/null +++ b/drivers/net/wireless/rt2x00/rt2800mmio.h | |||
| @@ -0,0 +1,165 @@ | |||
| 1 | /* Copyright (C) 2009 - 2010 Ivo van Doorn <IvDoorn@gmail.com> | ||
| 2 | * Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com> | ||
| 3 | * Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org> | ||
| 4 | * Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com> | ||
| 5 | * Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de> | ||
| 6 | * Copyright (C) 2009 Mark Asselstine <asselsm@gmail.com> | ||
| 7 | * Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com> | ||
| 8 | * Copyright (C) 2009 Bart Zolnierkiewicz <bzolnier@gmail.com> | ||
| 9 | * <http://rt2x00.serialmonkey.com> | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or modify | ||
| 12 | * it under the terms of the GNU General Public License as published by | ||
| 13 | * the Free Software Foundation; either version 2 of the License, or | ||
| 14 | * (at your option) any later version. | ||
| 15 | * | ||
| 16 | * This program is distributed in the hope that it will be useful, | ||
| 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 19 | * GNU General Public License for more details. | ||
| 20 | * | ||
| 21 | * You should have received a copy of the GNU General Public License | ||
| 22 | * along with this program; if not, write to the | ||
| 23 | * Free Software Foundation, Inc., | ||
| 24 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
| 25 | */ | ||
| 26 | |||
| 27 | /* Module: rt2800mmio | ||
| 28 | * Abstract: forward declarations for the rt2800mmio module. | ||
| 29 | */ | ||
| 30 | |||
| 31 | #ifndef RT2800MMIO_H | ||
| 32 | #define RT2800MMIO_H | ||
| 33 | |||
| 34 | /* | ||
| 35 | * Queue register offset macros | ||
| 36 | */ | ||
| 37 | #define TX_QUEUE_REG_OFFSET 0x10 | ||
| 38 | #define TX_BASE_PTR(__x) (TX_BASE_PTR0 + ((__x) * TX_QUEUE_REG_OFFSET)) | ||
| 39 | #define TX_MAX_CNT(__x) (TX_MAX_CNT0 + ((__x) * TX_QUEUE_REG_OFFSET)) | ||
| 40 | #define TX_CTX_IDX(__x) (TX_CTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET)) | ||
| 41 | #define TX_DTX_IDX(__x) (TX_DTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET)) | ||
| 42 | |||
| 43 | /* | ||
| 44 | * DMA descriptor defines. | ||
| 45 | */ | ||
| 46 | #define TXD_DESC_SIZE (4 * sizeof(__le32)) | ||
| 47 | #define RXD_DESC_SIZE (4 * sizeof(__le32)) | ||
| 48 | |||
| 49 | /* | ||
| 50 | * TX descriptor format for TX, PRIO and Beacon Ring. | ||
| 51 | */ | ||
| 52 | |||
| 53 | /* | ||
| 54 | * Word0 | ||
| 55 | */ | ||
| 56 | #define TXD_W0_SD_PTR0 FIELD32(0xffffffff) | ||
| 57 | |||
| 58 | /* | ||
| 59 | * Word1 | ||
| 60 | */ | ||
| 61 | #define TXD_W1_SD_LEN1 FIELD32(0x00003fff) | ||
| 62 | #define TXD_W1_LAST_SEC1 FIELD32(0x00004000) | ||
| 63 | #define TXD_W1_BURST FIELD32(0x00008000) | ||
| 64 | #define TXD_W1_SD_LEN0 FIELD32(0x3fff0000) | ||
| 65 | #define TXD_W1_LAST_SEC0 FIELD32(0x40000000) | ||
| 66 | #define TXD_W1_DMA_DONE FIELD32(0x80000000) | ||
| 67 | |||
| 68 | /* | ||
| 69 | * Word2 | ||
| 70 | */ | ||
| 71 | #define TXD_W2_SD_PTR1 FIELD32(0xffffffff) | ||
| 72 | |||
| 73 | /* | ||
| 74 | * Word3 | ||
| 75 | * WIV: Wireless Info Valid. 1: Driver filled WI, 0: DMA needs to copy WI | ||
| 76 | * QSEL: Select on-chip FIFO ID for 2nd-stage output scheduler. | ||
| 77 | * 0:MGMT, 1:HCCA 2:EDCA | ||
| 78 | */ | ||
| 79 | #define TXD_W3_WIV FIELD32(0x01000000) | ||
| 80 | #define TXD_W3_QSEL FIELD32(0x06000000) | ||
| 81 | #define TXD_W3_TCO FIELD32(0x20000000) | ||
| 82 | #define TXD_W3_UCO FIELD32(0x40000000) | ||
| 83 | #define TXD_W3_ICO FIELD32(0x80000000) | ||
| 84 | |||
| 85 | /* | ||
| 86 | * RX descriptor format for RX Ring. | ||
| 87 | */ | ||
| 88 | |||
| 89 | /* | ||
| 90 | * Word0 | ||
| 91 | */ | ||
| 92 | #define RXD_W0_SDP0 FIELD32(0xffffffff) | ||
| 93 | |||
| 94 | /* | ||
| 95 | * Word1 | ||
| 96 | */ | ||
| 97 | #define RXD_W1_SDL1 FIELD32(0x00003fff) | ||
| 98 | #define RXD_W1_SDL0 FIELD32(0x3fff0000) | ||
| 99 | #define RXD_W1_LS0 FIELD32(0x40000000) | ||
| 100 | #define RXD_W1_DMA_DONE FIELD32(0x80000000) | ||
| 101 | |||
| 102 | /* | ||
| 103 | * Word2 | ||
| 104 | */ | ||
| 105 | #define RXD_W2_SDP1 FIELD32(0xffffffff) | ||
| 106 | |||
| 107 | /* | ||
| 108 | * Word3 | ||
| 109 | * AMSDU: RX with 802.3 header, not 802.11 header. | ||
| 110 | * DECRYPTED: This frame is being decrypted. | ||
| 111 | */ | ||
| 112 | #define RXD_W3_BA FIELD32(0x00000001) | ||
| 113 | #define RXD_W3_DATA FIELD32(0x00000002) | ||
| 114 | #define RXD_W3_NULLDATA FIELD32(0x00000004) | ||
| 115 | #define RXD_W3_FRAG FIELD32(0x00000008) | ||
| 116 | #define RXD_W3_UNICAST_TO_ME FIELD32(0x00000010) | ||
| 117 | #define RXD_W3_MULTICAST FIELD32(0x00000020) | ||
| 118 | #define RXD_W3_BROADCAST FIELD32(0x00000040) | ||
| 119 | #define RXD_W3_MY_BSS FIELD32(0x00000080) | ||
| 120 | #define RXD_W3_CRC_ERROR FIELD32(0x00000100) | ||
| 121 | #define RXD_W3_CIPHER_ERROR FIELD32(0x00000600) | ||
| 122 | #define RXD_W3_AMSDU FIELD32(0x00000800) | ||
| 123 | #define RXD_W3_HTC FIELD32(0x00001000) | ||
| 124 | #define RXD_W3_RSSI FIELD32(0x00002000) | ||
| 125 | #define RXD_W3_L2PAD FIELD32(0x00004000) | ||
| 126 | #define RXD_W3_AMPDU FIELD32(0x00008000) | ||
| 127 | #define RXD_W3_DECRYPTED FIELD32(0x00010000) | ||
| 128 | #define RXD_W3_PLCP_SIGNAL FIELD32(0x00020000) | ||
| 129 | #define RXD_W3_PLCP_RSSI FIELD32(0x00040000) | ||
| 130 | |||
| 131 | /* TX descriptor initialization */ | ||
| 132 | __le32 *rt2800mmio_get_txwi(struct queue_entry *entry); | ||
| 133 | void rt2800mmio_write_tx_desc(struct queue_entry *entry, | ||
| 134 | struct txentry_desc *txdesc); | ||
| 135 | |||
| 136 | /* RX control handlers */ | ||
| 137 | void rt2800mmio_fill_rxdone(struct queue_entry *entry, | ||
| 138 | struct rxdone_entry_desc *rxdesc); | ||
| 139 | |||
| 140 | /* Interrupt functions */ | ||
| 141 | void rt2800mmio_txstatus_tasklet(unsigned long data); | ||
| 142 | void rt2800mmio_pretbtt_tasklet(unsigned long data); | ||
| 143 | void rt2800mmio_tbtt_tasklet(unsigned long data); | ||
| 144 | void rt2800mmio_rxdone_tasklet(unsigned long data); | ||
| 145 | void rt2800mmio_autowake_tasklet(unsigned long data); | ||
| 146 | irqreturn_t rt2800mmio_interrupt(int irq, void *dev_instance); | ||
| 147 | void rt2800mmio_toggle_irq(struct rt2x00_dev *rt2x00dev, | ||
| 148 | enum dev_state state); | ||
| 149 | |||
| 150 | /* Queue handlers */ | ||
| 151 | void rt2800mmio_start_queue(struct data_queue *queue); | ||
| 152 | void rt2800mmio_kick_queue(struct data_queue *queue); | ||
| 153 | void rt2800mmio_stop_queue(struct data_queue *queue); | ||
| 154 | void rt2800mmio_queue_init(struct data_queue *queue); | ||
| 155 | |||
| 156 | /* Initialization functions */ | ||
| 157 | bool rt2800mmio_get_entry_state(struct queue_entry *entry); | ||
| 158 | void rt2800mmio_clear_entry(struct queue_entry *entry); | ||
| 159 | int rt2800mmio_init_queues(struct rt2x00_dev *rt2x00dev); | ||
| 160 | int rt2800mmio_init_registers(struct rt2x00_dev *rt2x00dev); | ||
| 161 | |||
| 162 | /* Device state switch handlers. */ | ||
| 163 | int rt2800mmio_enable_radio(struct rt2x00_dev *rt2x00dev); | ||
| 164 | |||
| 165 | #endif /* RT2800MMIO_H */ | ||
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index f8f2abbfbb65..b504455b4fec 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c | |||
| @@ -37,14 +37,13 @@ | |||
| 37 | #include <linux/kernel.h> | 37 | #include <linux/kernel.h> |
| 38 | #include <linux/module.h> | 38 | #include <linux/module.h> |
| 39 | #include <linux/pci.h> | 39 | #include <linux/pci.h> |
| 40 | #include <linux/platform_device.h> | ||
| 41 | #include <linux/eeprom_93cx6.h> | 40 | #include <linux/eeprom_93cx6.h> |
| 42 | 41 | ||
| 43 | #include "rt2x00.h" | 42 | #include "rt2x00.h" |
| 44 | #include "rt2x00mmio.h" | 43 | #include "rt2x00mmio.h" |
| 45 | #include "rt2x00pci.h" | 44 | #include "rt2x00pci.h" |
| 46 | #include "rt2x00soc.h" | ||
| 47 | #include "rt2800lib.h" | 45 | #include "rt2800lib.h" |
| 46 | #include "rt2800mmio.h" | ||
| 48 | #include "rt2800.h" | 47 | #include "rt2800.h" |
| 49 | #include "rt2800pci.h" | 48 | #include "rt2800pci.h" |
| 50 | 49 | ||
| @@ -90,27 +89,6 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token) | |||
| 90 | rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); | 89 | rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); |
| 91 | } | 90 | } |
| 92 | 91 | ||
| 93 | #if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X) | ||
| 94 | static int rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) | ||
| 95 | { | ||
| 96 | void __iomem *base_addr = ioremap(0x1F040000, EEPROM_SIZE); | ||
| 97 | |||
| 98 | if (!base_addr) | ||
| 99 | return -ENOMEM; | ||
| 100 | |||
| 101 | memcpy_fromio(rt2x00dev->eeprom, base_addr, EEPROM_SIZE); | ||
| 102 | |||
| 103 | iounmap(base_addr); | ||
| 104 | return 0; | ||
| 105 | } | ||
| 106 | #else | ||
| 107 | static inline int rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) | ||
| 108 | { | ||
| 109 | return -ENOMEM; | ||
| 110 | } | ||
| 111 | #endif /* CONFIG_SOC_RT288X || CONFIG_SOC_RT305X */ | ||
| 112 | |||
| 113 | #ifdef CONFIG_PCI | ||
| 114 | static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom) | 92 | static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom) |
| 115 | { | 93 | { |
| 116 | struct rt2x00_dev *rt2x00dev = eeprom->data; | 94 | struct rt2x00_dev *rt2x00dev = eeprom->data; |
| @@ -183,112 +161,6 @@ static inline int rt2800pci_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev) | |||
| 183 | { | 161 | { |
| 184 | return rt2800_read_eeprom_efuse(rt2x00dev); | 162 | return rt2800_read_eeprom_efuse(rt2x00dev); |
| 185 | } | 163 | } |
| 186 | #else | ||
| 187 | static inline int rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev) | ||
| 188 | { | ||
| 189 | return -EOPNOTSUPP; | ||
| 190 | } | ||
| 191 | |||
| 192 | static inline int rt2800pci_efuse_detect(struct rt2x00_dev *rt2x00dev) | ||
| 193 | { | ||
| 194 | return 0; | ||
| 195 | } | ||
| 196 | |||
| 197 | static inline int rt2800pci_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev) | ||
| 198 | { | ||
| 199 | return -EOPNOTSUPP; | ||
| 200 | } | ||
| 201 | #endif /* CONFIG_PCI */ | ||
| 202 | |||
| 203 | /* | ||
| 204 | * Queue handlers. | ||
| 205 | */ | ||
| 206 | static void rt2800pci_start_queue(struct data_queue *queue) | ||
| 207 | { | ||
| 208 | struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; | ||
| 209 | u32 reg; | ||
| 210 | |||
| 211 | switch (queue->qid) { | ||
| 212 | case QID_RX: | ||
| 213 | rt2x00mmio_register_read(rt2x00dev, MAC_SYS_CTRL, ®); | ||
| 214 | rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 1); | ||
| 215 | rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, reg); | ||
| 216 | break; | ||
| 217 | case QID_BEACON: | ||
| 218 | rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, ®); | ||
| 219 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); | ||
| 220 | rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); | ||
| 221 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); | ||
| 222 | rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg); | ||
| 223 | |||
| 224 | rt2x00mmio_register_read(rt2x00dev, INT_TIMER_EN, ®); | ||
| 225 | rt2x00_set_field32(®, INT_TIMER_EN_PRE_TBTT_TIMER, 1); | ||
| 226 | rt2x00mmio_register_write(rt2x00dev, INT_TIMER_EN, reg); | ||
| 227 | break; | ||
| 228 | default: | ||
| 229 | break; | ||
| 230 | } | ||
| 231 | } | ||
| 232 | |||
| 233 | static void rt2800pci_kick_queue(struct data_queue *queue) | ||
| 234 | { | ||
| 235 | struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; | ||
| 236 | struct queue_entry *entry; | ||
| 237 | |||
| 238 | switch (queue->qid) { | ||
| 239 | case QID_AC_VO: | ||
| 240 | case QID_AC_VI: | ||
| 241 | case QID_AC_BE: | ||
| 242 | case QID_AC_BK: | ||
| 243 | entry = rt2x00queue_get_entry(queue, Q_INDEX); | ||
| 244 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX(queue->qid), | ||
| 245 | entry->entry_idx); | ||
| 246 | break; | ||
| 247 | case QID_MGMT: | ||
| 248 | entry = rt2x00queue_get_entry(queue, Q_INDEX); | ||
| 249 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX(5), | ||
| 250 | entry->entry_idx); | ||
| 251 | break; | ||
| 252 | default: | ||
| 253 | break; | ||
| 254 | } | ||
| 255 | } | ||
| 256 | |||
| 257 | static void rt2800pci_stop_queue(struct data_queue *queue) | ||
| 258 | { | ||
| 259 | struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; | ||
| 260 | u32 reg; | ||
| 261 | |||
| 262 | switch (queue->qid) { | ||
| 263 | case QID_RX: | ||
| 264 | rt2x00mmio_register_read(rt2x00dev, MAC_SYS_CTRL, ®); | ||
| 265 | rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 0); | ||
| 266 | rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, reg); | ||
| 267 | break; | ||
| 268 | case QID_BEACON: | ||
| 269 | rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, ®); | ||
| 270 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 0); | ||
| 271 | rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0); | ||
| 272 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); | ||
| 273 | rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg); | ||
| 274 | |||
| 275 | rt2x00mmio_register_read(rt2x00dev, INT_TIMER_EN, ®); | ||
| 276 | rt2x00_set_field32(®, INT_TIMER_EN_PRE_TBTT_TIMER, 0); | ||
| 277 | rt2x00mmio_register_write(rt2x00dev, INT_TIMER_EN, reg); | ||
| 278 | |||
| 279 | /* | ||
| 280 | * Wait for current invocation to finish. The tasklet | ||
| 281 | * won't be scheduled anymore afterwards since we disabled | ||
| 282 | * the TBTT and PRE TBTT timer. | ||
| 283 | */ | ||
| 284 | tasklet_kill(&rt2x00dev->tbtt_tasklet); | ||
| 285 | tasklet_kill(&rt2x00dev->pretbtt_tasklet); | ||
| 286 | |||
| 287 | break; | ||
| 288 | default: | ||
| 289 | break; | ||
| 290 | } | ||
| 291 | } | ||
| 292 | 164 | ||
| 293 | /* | 165 | /* |
| 294 | * Firmware functions | 166 | * Firmware functions |
| @@ -332,217 +204,13 @@ static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev, | |||
| 332 | } | 204 | } |
| 333 | 205 | ||
| 334 | /* | 206 | /* |
| 335 | * Initialization functions. | ||
| 336 | */ | ||
| 337 | static bool rt2800pci_get_entry_state(struct queue_entry *entry) | ||
| 338 | { | ||
| 339 | struct queue_entry_priv_mmio *entry_priv = entry->priv_data; | ||
| 340 | u32 word; | ||
| 341 | |||
| 342 | if (entry->queue->qid == QID_RX) { | ||
| 343 | rt2x00_desc_read(entry_priv->desc, 1, &word); | ||
| 344 | |||
| 345 | return (!rt2x00_get_field32(word, RXD_W1_DMA_DONE)); | ||
| 346 | } else { | ||
| 347 | rt2x00_desc_read(entry_priv->desc, 1, &word); | ||
| 348 | |||
| 349 | return (!rt2x00_get_field32(word, TXD_W1_DMA_DONE)); | ||
| 350 | } | ||
| 351 | } | ||
| 352 | |||
| 353 | static void rt2800pci_clear_entry(struct queue_entry *entry) | ||
| 354 | { | ||
| 355 | struct queue_entry_priv_mmio *entry_priv = entry->priv_data; | ||
| 356 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | ||
| 357 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | ||
| 358 | u32 word; | ||
| 359 | |||
| 360 | if (entry->queue->qid == QID_RX) { | ||
| 361 | rt2x00_desc_read(entry_priv->desc, 0, &word); | ||
| 362 | rt2x00_set_field32(&word, RXD_W0_SDP0, skbdesc->skb_dma); | ||
| 363 | rt2x00_desc_write(entry_priv->desc, 0, word); | ||
| 364 | |||
| 365 | rt2x00_desc_read(entry_priv->desc, 1, &word); | ||
| 366 | rt2x00_set_field32(&word, RXD_W1_DMA_DONE, 0); | ||
| 367 | rt2x00_desc_write(entry_priv->desc, 1, word); | ||
| 368 | |||
| 369 | /* | ||
| 370 | * Set RX IDX in register to inform hardware that we have | ||
| 371 | * handled this entry and it is available for reuse again. | ||
| 372 | */ | ||
| 373 | rt2x00mmio_register_write(rt2x00dev, RX_CRX_IDX, | ||
| 374 | entry->entry_idx); | ||
| 375 | } else { | ||
| 376 | rt2x00_desc_read(entry_priv->desc, 1, &word); | ||
| 377 | rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 1); | ||
| 378 | rt2x00_desc_write(entry_priv->desc, 1, word); | ||
| 379 | } | ||
| 380 | } | ||
| 381 | |||
| 382 | static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev) | ||
| 383 | { | ||
| 384 | struct queue_entry_priv_mmio *entry_priv; | ||
| 385 | |||
| 386 | /* | ||
| 387 | * Initialize registers. | ||
| 388 | */ | ||
| 389 | entry_priv = rt2x00dev->tx[0].entries[0].priv_data; | ||
| 390 | rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR0, | ||
| 391 | entry_priv->desc_dma); | ||
| 392 | rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT0, | ||
| 393 | rt2x00dev->tx[0].limit); | ||
| 394 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX0, 0); | ||
| 395 | rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX0, 0); | ||
| 396 | |||
| 397 | entry_priv = rt2x00dev->tx[1].entries[0].priv_data; | ||
| 398 | rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR1, | ||
| 399 | entry_priv->desc_dma); | ||
| 400 | rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT1, | ||
| 401 | rt2x00dev->tx[1].limit); | ||
| 402 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX1, 0); | ||
| 403 | rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX1, 0); | ||
| 404 | |||
| 405 | entry_priv = rt2x00dev->tx[2].entries[0].priv_data; | ||
| 406 | rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR2, | ||
| 407 | entry_priv->desc_dma); | ||
| 408 | rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT2, | ||
| 409 | rt2x00dev->tx[2].limit); | ||
| 410 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX2, 0); | ||
| 411 | rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX2, 0); | ||
| 412 | |||
| 413 | entry_priv = rt2x00dev->tx[3].entries[0].priv_data; | ||
| 414 | rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR3, | ||
| 415 | entry_priv->desc_dma); | ||
| 416 | rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT3, | ||
| 417 | rt2x00dev->tx[3].limit); | ||
| 418 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX3, 0); | ||
| 419 | rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX3, 0); | ||
| 420 | |||
| 421 | rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR4, 0); | ||
| 422 | rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT4, 0); | ||
| 423 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX4, 0); | ||
| 424 | rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX4, 0); | ||
| 425 | |||
| 426 | rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR5, 0); | ||
| 427 | rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT5, 0); | ||
| 428 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX5, 0); | ||
| 429 | rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX5, 0); | ||
| 430 | |||
| 431 | entry_priv = rt2x00dev->rx->entries[0].priv_data; | ||
| 432 | rt2x00mmio_register_write(rt2x00dev, RX_BASE_PTR, | ||
| 433 | entry_priv->desc_dma); | ||
| 434 | rt2x00mmio_register_write(rt2x00dev, RX_MAX_CNT, | ||
| 435 | rt2x00dev->rx[0].limit); | ||
| 436 | rt2x00mmio_register_write(rt2x00dev, RX_CRX_IDX, | ||
| 437 | rt2x00dev->rx[0].limit - 1); | ||
| 438 | rt2x00mmio_register_write(rt2x00dev, RX_DRX_IDX, 0); | ||
| 439 | |||
| 440 | rt2800_disable_wpdma(rt2x00dev); | ||
| 441 | |||
| 442 | rt2x00mmio_register_write(rt2x00dev, DELAY_INT_CFG, 0); | ||
| 443 | |||
| 444 | return 0; | ||
| 445 | } | ||
| 446 | |||
| 447 | /* | ||
| 448 | * Device state switch handlers. | 207 | * Device state switch handlers. |
| 449 | */ | 208 | */ |
| 450 | static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | ||
| 451 | enum dev_state state) | ||
| 452 | { | ||
| 453 | u32 reg; | ||
| 454 | unsigned long flags; | ||
| 455 | |||
| 456 | /* | ||
| 457 | * When interrupts are being enabled, the interrupt registers | ||
| 458 | * should clear the register to assure a clean state. | ||
| 459 | */ | ||
| 460 | if (state == STATE_RADIO_IRQ_ON) { | ||
| 461 | rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, ®); | ||
| 462 | rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg); | ||
| 463 | } | ||
| 464 | |||
| 465 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); | ||
| 466 | reg = 0; | ||
| 467 | if (state == STATE_RADIO_IRQ_ON) { | ||
| 468 | rt2x00_set_field32(®, INT_MASK_CSR_RX_DONE, 1); | ||
| 469 | rt2x00_set_field32(®, INT_MASK_CSR_TBTT, 1); | ||
| 470 | rt2x00_set_field32(®, INT_MASK_CSR_PRE_TBTT, 1); | ||
| 471 | rt2x00_set_field32(®, INT_MASK_CSR_TX_FIFO_STATUS, 1); | ||
| 472 | rt2x00_set_field32(®, INT_MASK_CSR_AUTO_WAKEUP, 1); | ||
| 473 | } | ||
| 474 | rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg); | ||
| 475 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); | ||
| 476 | |||
| 477 | if (state == STATE_RADIO_IRQ_OFF) { | ||
| 478 | /* | ||
| 479 | * Wait for possibly running tasklets to finish. | ||
| 480 | */ | ||
| 481 | tasklet_kill(&rt2x00dev->txstatus_tasklet); | ||
| 482 | tasklet_kill(&rt2x00dev->rxdone_tasklet); | ||
| 483 | tasklet_kill(&rt2x00dev->autowake_tasklet); | ||
| 484 | tasklet_kill(&rt2x00dev->tbtt_tasklet); | ||
| 485 | tasklet_kill(&rt2x00dev->pretbtt_tasklet); | ||
| 486 | } | ||
| 487 | } | ||
| 488 | |||
| 489 | static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev) | ||
| 490 | { | ||
| 491 | u32 reg; | ||
| 492 | |||
| 493 | /* | ||
| 494 | * Reset DMA indexes | ||
| 495 | */ | ||
| 496 | rt2x00mmio_register_read(rt2x00dev, WPDMA_RST_IDX, ®); | ||
| 497 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, 1); | ||
| 498 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, 1); | ||
| 499 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, 1); | ||
| 500 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX3, 1); | ||
| 501 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX4, 1); | ||
| 502 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX5, 1); | ||
| 503 | rt2x00_set_field32(®, WPDMA_RST_IDX_DRX_IDX0, 1); | ||
| 504 | rt2x00mmio_register_write(rt2x00dev, WPDMA_RST_IDX, reg); | ||
| 505 | |||
| 506 | rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f); | ||
| 507 | rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00); | ||
| 508 | |||
| 509 | if (rt2x00_is_pcie(rt2x00dev) && | ||
| 510 | (rt2x00_rt(rt2x00dev, RT3090) || | ||
| 511 | rt2x00_rt(rt2x00dev, RT3390) || | ||
| 512 | rt2x00_rt(rt2x00dev, RT3572) || | ||
| 513 | rt2x00_rt(rt2x00dev, RT3593) || | ||
| 514 | rt2x00_rt(rt2x00dev, RT5390) || | ||
| 515 | rt2x00_rt(rt2x00dev, RT5392) || | ||
| 516 | rt2x00_rt(rt2x00dev, RT5592))) { | ||
| 517 | rt2x00mmio_register_read(rt2x00dev, AUX_CTRL, ®); | ||
| 518 | rt2x00_set_field32(®, AUX_CTRL_FORCE_PCIE_CLK, 1); | ||
| 519 | rt2x00_set_field32(®, AUX_CTRL_WAKE_PCIE_EN, 1); | ||
| 520 | rt2x00mmio_register_write(rt2x00dev, AUX_CTRL, reg); | ||
| 521 | } | ||
| 522 | |||
| 523 | rt2x00mmio_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); | ||
| 524 | |||
| 525 | reg = 0; | ||
| 526 | rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1); | ||
| 527 | rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1); | ||
| 528 | rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, reg); | ||
| 529 | |||
| 530 | rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); | ||
| 531 | |||
| 532 | return 0; | ||
| 533 | } | ||
| 534 | |||
| 535 | static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev) | 209 | static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev) |
| 536 | { | 210 | { |
| 537 | int retval; | 211 | int retval; |
| 538 | 212 | ||
| 539 | /* Wait for DMA, ignore error until we initialize queues. */ | 213 | retval = rt2800mmio_enable_radio(rt2x00dev); |
| 540 | rt2800_wait_wpdma_ready(rt2x00dev); | ||
| 541 | |||
| 542 | if (unlikely(rt2800pci_init_queues(rt2x00dev))) | ||
| 543 | return -EIO; | ||
| 544 | |||
| 545 | retval = rt2800_enable_radio(rt2x00dev); | ||
| 546 | if (retval) | 214 | if (retval) |
| 547 | return retval; | 215 | return retval; |
| 548 | 216 | ||
| @@ -559,15 +227,6 @@ static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev) | |||
| 559 | return retval; | 227 | return retval; |
| 560 | } | 228 | } |
| 561 | 229 | ||
| 562 | static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev) | ||
| 563 | { | ||
| 564 | if (rt2x00_is_soc(rt2x00dev)) { | ||
| 565 | rt2800_disable_radio(rt2x00dev); | ||
| 566 | rt2x00mmio_register_write(rt2x00dev, PWR_PIN_CFG, 0); | ||
| 567 | rt2x00mmio_register_write(rt2x00dev, TX_PIN_CFG, 0); | ||
| 568 | } | ||
| 569 | } | ||
| 570 | |||
| 571 | static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev, | 230 | static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev, |
| 572 | enum dev_state state) | 231 | enum dev_state state) |
| 573 | { | 232 | { |
| @@ -601,12 +260,11 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev, | |||
| 601 | * After the radio has been disabled, the device should | 260 | * After the radio has been disabled, the device should |
| 602 | * be put to sleep for powersaving. | 261 | * be put to sleep for powersaving. |
| 603 | */ | 262 | */ |
| 604 | rt2800pci_disable_radio(rt2x00dev); | ||
| 605 | rt2800pci_set_state(rt2x00dev, STATE_SLEEP); | 263 | rt2800pci_set_state(rt2x00dev, STATE_SLEEP); |
| 606 | break; | 264 | break; |
| 607 | case STATE_RADIO_IRQ_ON: | 265 | case STATE_RADIO_IRQ_ON: |
| 608 | case STATE_RADIO_IRQ_OFF: | 266 | case STATE_RADIO_IRQ_OFF: |
| 609 | rt2800pci_toggle_irq(rt2x00dev, state); | 267 | rt2800mmio_toggle_irq(rt2x00dev, state); |
| 610 | break; | 268 | break; |
| 611 | case STATE_DEEP_SLEEP: | 269 | case STATE_DEEP_SLEEP: |
| 612 | case STATE_SLEEP: | 270 | case STATE_SLEEP: |
| @@ -627,479 +285,13 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev, | |||
| 627 | } | 285 | } |
| 628 | 286 | ||
| 629 | /* | 287 | /* |
| 630 | * TX descriptor initialization | ||
| 631 | */ | ||
| 632 | static __le32 *rt2800pci_get_txwi(struct queue_entry *entry) | ||
| 633 | { | ||
| 634 | return (__le32 *) entry->skb->data; | ||
| 635 | } | ||
| 636 | |||
| 637 | static void rt2800pci_write_tx_desc(struct queue_entry *entry, | ||
| 638 | struct txentry_desc *txdesc) | ||
| 639 | { | ||
| 640 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | ||
| 641 | struct queue_entry_priv_mmio *entry_priv = entry->priv_data; | ||
| 642 | __le32 *txd = entry_priv->desc; | ||
| 643 | u32 word; | ||
| 644 | const unsigned int txwi_size = entry->queue->winfo_size; | ||
| 645 | |||
| 646 | /* | ||
| 647 | * The buffers pointed by SD_PTR0/SD_LEN0 and SD_PTR1/SD_LEN1 | ||
| 648 | * must contains a TXWI structure + 802.11 header + padding + 802.11 | ||
| 649 | * data. We choose to have SD_PTR0/SD_LEN0 only contains TXWI and | ||
| 650 | * SD_PTR1/SD_LEN1 contains 802.11 header + padding + 802.11 | ||
| 651 | * data. It means that LAST_SEC0 is always 0. | ||
| 652 | */ | ||
| 653 | |||
| 654 | /* | ||
| 655 | * Initialize TX descriptor | ||
| 656 | */ | ||
| 657 | word = 0; | ||
| 658 | rt2x00_set_field32(&word, TXD_W0_SD_PTR0, skbdesc->skb_dma); | ||
| 659 | rt2x00_desc_write(txd, 0, word); | ||
| 660 | |||
| 661 | word = 0; | ||
| 662 | rt2x00_set_field32(&word, TXD_W1_SD_LEN1, entry->skb->len); | ||
| 663 | rt2x00_set_field32(&word, TXD_W1_LAST_SEC1, | ||
| 664 | !test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); | ||
| 665 | rt2x00_set_field32(&word, TXD_W1_BURST, | ||
| 666 | test_bit(ENTRY_TXD_BURST, &txdesc->flags)); | ||
| 667 | rt2x00_set_field32(&word, TXD_W1_SD_LEN0, txwi_size); | ||
| 668 | rt2x00_set_field32(&word, TXD_W1_LAST_SEC0, 0); | ||
| 669 | rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 0); | ||
| 670 | rt2x00_desc_write(txd, 1, word); | ||
| 671 | |||
| 672 | word = 0; | ||
| 673 | rt2x00_set_field32(&word, TXD_W2_SD_PTR1, | ||
| 674 | skbdesc->skb_dma + txwi_size); | ||
| 675 | rt2x00_desc_write(txd, 2, word); | ||
| 676 | |||
| 677 | word = 0; | ||
| 678 | rt2x00_set_field32(&word, TXD_W3_WIV, | ||
| 679 | !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags)); | ||
| 680 | rt2x00_set_field32(&word, TXD_W3_QSEL, 2); | ||
| 681 | rt2x00_desc_write(txd, 3, word); | ||
| 682 | |||
| 683 | /* | ||
| 684 | * Register descriptor details in skb frame descriptor. | ||
| 685 | */ | ||
| 686 | skbdesc->desc = txd; | ||
| 687 | skbdesc->desc_len = TXD_DESC_SIZE; | ||
| 688 | } | ||
| 689 | |||
| 690 | /* | ||
| 691 | * RX control handlers | ||
| 692 | */ | ||
| 693 | static void rt2800pci_fill_rxdone(struct queue_entry *entry, | ||
| 694 | struct rxdone_entry_desc *rxdesc) | ||
| 695 | { | ||
| 696 | struct queue_entry_priv_mmio *entry_priv = entry->priv_data; | ||
| 697 | __le32 *rxd = entry_priv->desc; | ||
| 698 | u32 word; | ||
| 699 | |||
| 700 | rt2x00_desc_read(rxd, 3, &word); | ||
| 701 | |||
| 702 | if (rt2x00_get_field32(word, RXD_W3_CRC_ERROR)) | ||
| 703 | rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; | ||
| 704 | |||
| 705 | /* | ||
| 706 | * Unfortunately we don't know the cipher type used during | ||
| 707 | * decryption. This prevents us from correct providing | ||
| 708 | * correct statistics through debugfs. | ||
| 709 | */ | ||
| 710 | rxdesc->cipher_status = rt2x00_get_field32(word, RXD_W3_CIPHER_ERROR); | ||
| 711 | |||
| 712 | if (rt2x00_get_field32(word, RXD_W3_DECRYPTED)) { | ||
| 713 | /* | ||
| 714 | * Hardware has stripped IV/EIV data from 802.11 frame during | ||
| 715 | * decryption. Unfortunately the descriptor doesn't contain | ||
| 716 | * any fields with the EIV/IV data either, so they can't | ||
| 717 | * be restored by rt2x00lib. | ||
| 718 | */ | ||
| 719 | rxdesc->flags |= RX_FLAG_IV_STRIPPED; | ||
| 720 | |||
| 721 | /* | ||
| 722 | * The hardware has already checked the Michael Mic and has | ||
| 723 | * stripped it from the frame. Signal this to mac80211. | ||
| 724 | */ | ||
| 725 | rxdesc->flags |= RX_FLAG_MMIC_STRIPPED; | ||
| 726 | |||
| 727 | if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS) | ||
| 728 | rxdesc->flags |= RX_FLAG_DECRYPTED; | ||
| 729 | else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC) | ||
| 730 | rxdesc->flags |= RX_FLAG_MMIC_ERROR; | ||
| 731 | } | ||
| 732 | |||
| 733 | if (rt2x00_get_field32(word, RXD_W3_MY_BSS)) | ||
| 734 | rxdesc->dev_flags |= RXDONE_MY_BSS; | ||
| 735 | |||
| 736 | if (rt2x00_get_field32(word, RXD_W3_L2PAD)) | ||
| 737 | rxdesc->dev_flags |= RXDONE_L2PAD; | ||
| 738 | |||
| 739 | /* | ||
| 740 | * Process the RXWI structure that is at the start of the buffer. | ||
| 741 | */ | ||
| 742 | rt2800_process_rxwi(entry, rxdesc); | ||
| 743 | } | ||
| 744 | |||
| 745 | /* | ||
| 746 | * Interrupt functions. | ||
| 747 | */ | ||
| 748 | static void rt2800pci_wakeup(struct rt2x00_dev *rt2x00dev) | ||
| 749 | { | ||
| 750 | struct ieee80211_conf conf = { .flags = 0 }; | ||
| 751 | struct rt2x00lib_conf libconf = { .conf = &conf }; | ||
| 752 | |||
| 753 | rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); | ||
| 754 | } | ||
| 755 | |||
| 756 | static bool rt2800pci_txdone_entry_check(struct queue_entry *entry, u32 status) | ||
| 757 | { | ||
| 758 | __le32 *txwi; | ||
| 759 | u32 word; | ||
| 760 | int wcid, tx_wcid; | ||
| 761 | |||
| 762 | wcid = rt2x00_get_field32(status, TX_STA_FIFO_WCID); | ||
| 763 | |||
| 764 | txwi = rt2800_drv_get_txwi(entry); | ||
| 765 | rt2x00_desc_read(txwi, 1, &word); | ||
| 766 | tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID); | ||
| 767 | |||
| 768 | return (tx_wcid == wcid); | ||
| 769 | } | ||
| 770 | |||
| 771 | static bool rt2800pci_txdone_find_entry(struct queue_entry *entry, void *data) | ||
| 772 | { | ||
| 773 | u32 status = *(u32 *)data; | ||
| 774 | |||
| 775 | /* | ||
| 776 | * rt2800pci hardware might reorder frames when exchanging traffic | ||
| 777 | * with multiple BA enabled STAs. | ||
| 778 | * | ||
| 779 | * For example, a tx queue | ||
| 780 | * [ STA1 | STA2 | STA1 | STA2 ] | ||
| 781 | * can result in tx status reports | ||
| 782 | * [ STA1 | STA1 | STA2 | STA2 ] | ||
| 783 | * when the hw decides to aggregate the frames for STA1 into one AMPDU. | ||
| 784 | * | ||
| 785 | * To mitigate this effect, associate the tx status to the first frame | ||
| 786 | * in the tx queue with a matching wcid. | ||
| 787 | */ | ||
| 788 | if (rt2800pci_txdone_entry_check(entry, status) && | ||
| 789 | !test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) { | ||
| 790 | /* | ||
| 791 | * Got a matching frame, associate the tx status with | ||
| 792 | * the frame | ||
| 793 | */ | ||
| 794 | entry->status = status; | ||
| 795 | set_bit(ENTRY_DATA_STATUS_SET, &entry->flags); | ||
| 796 | return true; | ||
| 797 | } | ||
| 798 | |||
| 799 | /* Check the next frame */ | ||
| 800 | return false; | ||
| 801 | } | ||
| 802 | |||
| 803 | static bool rt2800pci_txdone_match_first(struct queue_entry *entry, void *data) | ||
| 804 | { | ||
| 805 | u32 status = *(u32 *)data; | ||
| 806 | |||
| 807 | /* | ||
| 808 | * Find the first frame without tx status and assign this status to it | ||
| 809 | * regardless if it matches or not. | ||
| 810 | */ | ||
| 811 | if (!test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) { | ||
| 812 | /* | ||
| 813 | * Got a matching frame, associate the tx status with | ||
| 814 | * the frame | ||
| 815 | */ | ||
| 816 | entry->status = status; | ||
| 817 | set_bit(ENTRY_DATA_STATUS_SET, &entry->flags); | ||
| 818 | return true; | ||
| 819 | } | ||
| 820 | |||
| 821 | /* Check the next frame */ | ||
| 822 | return false; | ||
| 823 | } | ||
| 824 | static bool rt2800pci_txdone_release_entries(struct queue_entry *entry, | ||
| 825 | void *data) | ||
| 826 | { | ||
| 827 | if (test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) { | ||
| 828 | rt2800_txdone_entry(entry, entry->status, | ||
| 829 | rt2800pci_get_txwi(entry)); | ||
| 830 | return false; | ||
| 831 | } | ||
| 832 | |||
| 833 | /* No more frames to release */ | ||
| 834 | return true; | ||
| 835 | } | ||
| 836 | |||
| 837 | static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) | ||
| 838 | { | ||
| 839 | struct data_queue *queue; | ||
| 840 | u32 status; | ||
| 841 | u8 qid; | ||
| 842 | int max_tx_done = 16; | ||
| 843 | |||
| 844 | while (kfifo_get(&rt2x00dev->txstatus_fifo, &status)) { | ||
| 845 | qid = rt2x00_get_field32(status, TX_STA_FIFO_PID_QUEUE); | ||
| 846 | if (unlikely(qid >= QID_RX)) { | ||
| 847 | /* | ||
| 848 | * Unknown queue, this shouldn't happen. Just drop | ||
| 849 | * this tx status. | ||
| 850 | */ | ||
| 851 | rt2x00_warn(rt2x00dev, "Got TX status report with unexpected pid %u, dropping\n", | ||
| 852 | qid); | ||
| 853 | break; | ||
| 854 | } | ||
| 855 | |||
| 856 | queue = rt2x00queue_get_tx_queue(rt2x00dev, qid); | ||
| 857 | if (unlikely(queue == NULL)) { | ||
| 858 | /* | ||
| 859 | * The queue is NULL, this shouldn't happen. Stop | ||
| 860 | * processing here and drop the tx status | ||
| 861 | */ | ||
| 862 | rt2x00_warn(rt2x00dev, "Got TX status for an unavailable queue %u, dropping\n", | ||
| 863 | qid); | ||
| 864 | break; | ||
| 865 | } | ||
| 866 | |||
| 867 | if (unlikely(rt2x00queue_empty(queue))) { | ||
| 868 | /* | ||
| 869 | * The queue is empty. Stop processing here | ||
| 870 | * and drop the tx status. | ||
| 871 | */ | ||
| 872 | rt2x00_warn(rt2x00dev, "Got TX status for an empty queue %u, dropping\n", | ||
| 873 | qid); | ||
| 874 | break; | ||
| 875 | } | ||
| 876 | |||
| 877 | /* | ||
| 878 | * Let's associate this tx status with the first | ||
| 879 | * matching frame. | ||
| 880 | */ | ||
| 881 | if (!rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, | ||
| 882 | Q_INDEX, &status, | ||
| 883 | rt2800pci_txdone_find_entry)) { | ||
| 884 | /* | ||
| 885 | * We cannot match the tx status to any frame, so just | ||
| 886 | * use the first one. | ||
| 887 | */ | ||
| 888 | if (!rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, | ||
| 889 | Q_INDEX, &status, | ||
| 890 | rt2800pci_txdone_match_first)) { | ||
| 891 | rt2x00_warn(rt2x00dev, "No frame found for TX status on queue %u, dropping\n", | ||
| 892 | qid); | ||
| 893 | break; | ||
| 894 | } | ||
| 895 | } | ||
| 896 | |||
| 897 | /* | ||
| 898 | * Release all frames with a valid tx status. | ||
| 899 | */ | ||
| 900 | rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, | ||
| 901 | Q_INDEX, NULL, | ||
| 902 | rt2800pci_txdone_release_entries); | ||
| 903 | |||
| 904 | if (--max_tx_done == 0) | ||
| 905 | break; | ||
| 906 | } | ||
| 907 | |||
| 908 | return !max_tx_done; | ||
| 909 | } | ||
| 910 | |||
| 911 | static inline void rt2800pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, | ||
| 912 | struct rt2x00_field32 irq_field) | ||
| 913 | { | ||
| 914 | u32 reg; | ||
| 915 | |||
| 916 | /* | ||
| 917 | * Enable a single interrupt. The interrupt mask register | ||
| 918 | * access needs locking. | ||
| 919 | */ | ||
| 920 | spin_lock_irq(&rt2x00dev->irqmask_lock); | ||
| 921 | rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, ®); | ||
| 922 | rt2x00_set_field32(®, irq_field, 1); | ||
| 923 | rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg); | ||
| 924 | spin_unlock_irq(&rt2x00dev->irqmask_lock); | ||
| 925 | } | ||
| 926 | |||
| 927 | static void rt2800pci_txstatus_tasklet(unsigned long data) | ||
| 928 | { | ||
| 929 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
| 930 | if (rt2800pci_txdone(rt2x00dev)) | ||
| 931 | tasklet_schedule(&rt2x00dev->txstatus_tasklet); | ||
| 932 | |||
| 933 | /* | ||
| 934 | * No need to enable the tx status interrupt here as we always | ||
| 935 | * leave it enabled to minimize the possibility of a tx status | ||
| 936 | * register overflow. See comment in interrupt handler. | ||
| 937 | */ | ||
| 938 | } | ||
| 939 | |||
| 940 | static void rt2800pci_pretbtt_tasklet(unsigned long data) | ||
| 941 | { | ||
| 942 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
| 943 | rt2x00lib_pretbtt(rt2x00dev); | ||
| 944 | if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | ||
| 945 | rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_PRE_TBTT); | ||
| 946 | } | ||
| 947 | |||
| 948 | static void rt2800pci_tbtt_tasklet(unsigned long data) | ||
| 949 | { | ||
| 950 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
| 951 | struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; | ||
| 952 | u32 reg; | ||
| 953 | |||
| 954 | rt2x00lib_beacondone(rt2x00dev); | ||
| 955 | |||
| 956 | if (rt2x00dev->intf_ap_count) { | ||
| 957 | /* | ||
| 958 | * The rt2800pci hardware tbtt timer is off by 1us per tbtt | ||
| 959 | * causing beacon skew and as a result causing problems with | ||
| 960 | * some powersaving clients over time. Shorten the beacon | ||
| 961 | * interval every 64 beacons by 64us to mitigate this effect. | ||
| 962 | */ | ||
| 963 | if (drv_data->tbtt_tick == (BCN_TBTT_OFFSET - 2)) { | ||
| 964 | rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, ®); | ||
| 965 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, | ||
| 966 | (rt2x00dev->beacon_int * 16) - 1); | ||
| 967 | rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg); | ||
| 968 | } else if (drv_data->tbtt_tick == (BCN_TBTT_OFFSET - 1)) { | ||
| 969 | rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, ®); | ||
| 970 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, | ||
| 971 | (rt2x00dev->beacon_int * 16)); | ||
| 972 | rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg); | ||
| 973 | } | ||
| 974 | drv_data->tbtt_tick++; | ||
| 975 | drv_data->tbtt_tick %= BCN_TBTT_OFFSET; | ||
| 976 | } | ||
| 977 | |||
| 978 | if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | ||
| 979 | rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_TBTT); | ||
| 980 | } | ||
| 981 | |||
| 982 | static void rt2800pci_rxdone_tasklet(unsigned long data) | ||
| 983 | { | ||
| 984 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
| 985 | if (rt2x00mmio_rxdone(rt2x00dev)) | ||
| 986 | tasklet_schedule(&rt2x00dev->rxdone_tasklet); | ||
| 987 | else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | ||
| 988 | rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RX_DONE); | ||
| 989 | } | ||
| 990 | |||
| 991 | static void rt2800pci_autowake_tasklet(unsigned long data) | ||
| 992 | { | ||
| 993 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
| 994 | rt2800pci_wakeup(rt2x00dev); | ||
| 995 | if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | ||
| 996 | rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_AUTO_WAKEUP); | ||
| 997 | } | ||
| 998 | |||
| 999 | static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev) | ||
| 1000 | { | ||
| 1001 | u32 status; | ||
| 1002 | int i; | ||
| 1003 | |||
| 1004 | /* | ||
| 1005 | * The TX_FIFO_STATUS interrupt needs special care. We should | ||
| 1006 | * read TX_STA_FIFO but we should do it immediately as otherwise | ||
| 1007 | * the register can overflow and we would lose status reports. | ||
| 1008 | * | ||
| 1009 | * Hence, read the TX_STA_FIFO register and copy all tx status | ||
| 1010 | * reports into a kernel FIFO which is handled in the txstatus | ||
| 1011 | * tasklet. We use a tasklet to process the tx status reports | ||
| 1012 | * because we can schedule the tasklet multiple times (when the | ||
| 1013 | * interrupt fires again during tx status processing). | ||
| 1014 | * | ||
| 1015 | * Furthermore we don't disable the TX_FIFO_STATUS | ||
| 1016 | * interrupt here but leave it enabled so that the TX_STA_FIFO | ||
| 1017 | * can also be read while the tx status tasklet gets executed. | ||
| 1018 | * | ||
| 1019 | * Since we have only one producer and one consumer we don't | ||
| 1020 | * need to lock the kfifo. | ||
| 1021 | */ | ||
| 1022 | for (i = 0; i < rt2x00dev->tx->limit; i++) { | ||
| 1023 | rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO, &status); | ||
| 1024 | |||
| 1025 | if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID)) | ||
| 1026 | break; | ||
| 1027 | |||
| 1028 | if (!kfifo_put(&rt2x00dev->txstatus_fifo, &status)) { | ||
| 1029 | rt2x00_warn(rt2x00dev, "TX status FIFO overrun, drop tx status report\n"); | ||
| 1030 | break; | ||
| 1031 | } | ||
| 1032 | } | ||
| 1033 | |||
| 1034 | /* Schedule the tasklet for processing the tx status. */ | ||
| 1035 | tasklet_schedule(&rt2x00dev->txstatus_tasklet); | ||
| 1036 | } | ||
| 1037 | |||
| 1038 | static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) | ||
| 1039 | { | ||
| 1040 | struct rt2x00_dev *rt2x00dev = dev_instance; | ||
| 1041 | u32 reg, mask; | ||
| 1042 | |||
| 1043 | /* Read status and ACK all interrupts */ | ||
| 1044 | rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, ®); | ||
| 1045 | rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg); | ||
| 1046 | |||
| 1047 | if (!reg) | ||
| 1048 | return IRQ_NONE; | ||
| 1049 | |||
| 1050 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | ||
| 1051 | return IRQ_HANDLED; | ||
| 1052 | |||
| 1053 | /* | ||
| 1054 | * Since INT_MASK_CSR and INT_SOURCE_CSR use the same bits | ||
| 1055 | * for interrupts and interrupt masks we can just use the value of | ||
| 1056 | * INT_SOURCE_CSR to create the interrupt mask. | ||
| 1057 | */ | ||
| 1058 | mask = ~reg; | ||
| 1059 | |||
| 1060 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) { | ||
| 1061 | rt2800pci_txstatus_interrupt(rt2x00dev); | ||
| 1062 | /* | ||
| 1063 | * Never disable the TX_FIFO_STATUS interrupt. | ||
| 1064 | */ | ||
| 1065 | rt2x00_set_field32(&mask, INT_MASK_CSR_TX_FIFO_STATUS, 1); | ||
| 1066 | } | ||
| 1067 | |||
| 1068 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT)) | ||
| 1069 | tasklet_hi_schedule(&rt2x00dev->pretbtt_tasklet); | ||
| 1070 | |||
| 1071 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT)) | ||
| 1072 | tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet); | ||
| 1073 | |||
| 1074 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE)) | ||
| 1075 | tasklet_schedule(&rt2x00dev->rxdone_tasklet); | ||
| 1076 | |||
| 1077 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP)) | ||
| 1078 | tasklet_schedule(&rt2x00dev->autowake_tasklet); | ||
| 1079 | |||
| 1080 | /* | ||
| 1081 | * Disable all interrupts for which a tasklet was scheduled right now, | ||
| 1082 | * the tasklet will reenable the appropriate interrupts. | ||
| 1083 | */ | ||
| 1084 | spin_lock(&rt2x00dev->irqmask_lock); | ||
| 1085 | rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, ®); | ||
| 1086 | reg &= mask; | ||
| 1087 | rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg); | ||
| 1088 | spin_unlock(&rt2x00dev->irqmask_lock); | ||
| 1089 | |||
| 1090 | return IRQ_HANDLED; | ||
| 1091 | } | ||
| 1092 | |||
| 1093 | /* | ||
| 1094 | * Device probe functions. | 288 | * Device probe functions. |
| 1095 | */ | 289 | */ |
| 1096 | static int rt2800pci_read_eeprom(struct rt2x00_dev *rt2x00dev) | 290 | static int rt2800pci_read_eeprom(struct rt2x00_dev *rt2x00dev) |
| 1097 | { | 291 | { |
| 1098 | int retval; | 292 | int retval; |
| 1099 | 293 | ||
| 1100 | if (rt2x00_is_soc(rt2x00dev)) | 294 | if (rt2800pci_efuse_detect(rt2x00dev)) |
| 1101 | retval = rt2800pci_read_eeprom_soc(rt2x00dev); | ||
| 1102 | else if (rt2800pci_efuse_detect(rt2x00dev)) | ||
| 1103 | retval = rt2800pci_read_eeprom_efuse(rt2x00dev); | 295 | retval = rt2800pci_read_eeprom_efuse(rt2x00dev); |
| 1104 | else | 296 | else |
| 1105 | retval = rt2800pci_read_eeprom_pci(rt2x00dev); | 297 | retval = rt2800pci_read_eeprom_pci(rt2x00dev); |
| @@ -1145,25 +337,25 @@ static const struct rt2800_ops rt2800pci_rt2800_ops = { | |||
| 1145 | .read_eeprom = rt2800pci_read_eeprom, | 337 | .read_eeprom = rt2800pci_read_eeprom, |
| 1146 | .hwcrypt_disabled = rt2800pci_hwcrypt_disabled, | 338 | .hwcrypt_disabled = rt2800pci_hwcrypt_disabled, |
| 1147 | .drv_write_firmware = rt2800pci_write_firmware, | 339 | .drv_write_firmware = rt2800pci_write_firmware, |
| 1148 | .drv_init_registers = rt2800pci_init_registers, | 340 | .drv_init_registers = rt2800mmio_init_registers, |
| 1149 | .drv_get_txwi = rt2800pci_get_txwi, | 341 | .drv_get_txwi = rt2800mmio_get_txwi, |
| 1150 | }; | 342 | }; |
| 1151 | 343 | ||
| 1152 | static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { | 344 | static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { |
| 1153 | .irq_handler = rt2800pci_interrupt, | 345 | .irq_handler = rt2800mmio_interrupt, |
| 1154 | .txstatus_tasklet = rt2800pci_txstatus_tasklet, | 346 | .txstatus_tasklet = rt2800mmio_txstatus_tasklet, |
| 1155 | .pretbtt_tasklet = rt2800pci_pretbtt_tasklet, | 347 | .pretbtt_tasklet = rt2800mmio_pretbtt_tasklet, |
| 1156 | .tbtt_tasklet = rt2800pci_tbtt_tasklet, | 348 | .tbtt_tasklet = rt2800mmio_tbtt_tasklet, |
| 1157 | .rxdone_tasklet = rt2800pci_rxdone_tasklet, | 349 | .rxdone_tasklet = rt2800mmio_rxdone_tasklet, |
| 1158 | .autowake_tasklet = rt2800pci_autowake_tasklet, | 350 | .autowake_tasklet = rt2800mmio_autowake_tasklet, |
| 1159 | .probe_hw = rt2800_probe_hw, | 351 | .probe_hw = rt2800_probe_hw, |
| 1160 | .get_firmware_name = rt2800pci_get_firmware_name, | 352 | .get_firmware_name = rt2800pci_get_firmware_name, |
| 1161 | .check_firmware = rt2800_check_firmware, | 353 | .check_firmware = rt2800_check_firmware, |
| 1162 | .load_firmware = rt2800_load_firmware, | 354 | .load_firmware = rt2800_load_firmware, |
| 1163 | .initialize = rt2x00mmio_initialize, | 355 | .initialize = rt2x00mmio_initialize, |
| 1164 | .uninitialize = rt2x00mmio_uninitialize, | 356 | .uninitialize = rt2x00mmio_uninitialize, |
| 1165 | .get_entry_state = rt2800pci_get_entry_state, | 357 | .get_entry_state = rt2800mmio_get_entry_state, |
| 1166 | .clear_entry = rt2800pci_clear_entry, | 358 | .clear_entry = rt2800mmio_clear_entry, |
| 1167 | .set_device_state = rt2800pci_set_device_state, | 359 | .set_device_state = rt2800pci_set_device_state, |
| 1168 | .rfkill_poll = rt2800_rfkill_poll, | 360 | .rfkill_poll = rt2800_rfkill_poll, |
| 1169 | .link_stats = rt2800_link_stats, | 361 | .link_stats = rt2800_link_stats, |
| @@ -1171,15 +363,15 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { | |||
| 1171 | .link_tuner = rt2800_link_tuner, | 363 | .link_tuner = rt2800_link_tuner, |
| 1172 | .gain_calibration = rt2800_gain_calibration, | 364 | .gain_calibration = rt2800_gain_calibration, |
| 1173 | .vco_calibration = rt2800_vco_calibration, | 365 | .vco_calibration = rt2800_vco_calibration, |
| 1174 | .start_queue = rt2800pci_start_queue, | 366 | .start_queue = rt2800mmio_start_queue, |
| 1175 | .kick_queue = rt2800pci_kick_queue, | 367 | .kick_queue = rt2800mmio_kick_queue, |
| 1176 | .stop_queue = rt2800pci_stop_queue, | 368 | .stop_queue = rt2800mmio_stop_queue, |
| 1177 | .flush_queue = rt2x00mmio_flush_queue, | 369 | .flush_queue = rt2x00mmio_flush_queue, |
| 1178 | .write_tx_desc = rt2800pci_write_tx_desc, | 370 | .write_tx_desc = rt2800mmio_write_tx_desc, |
| 1179 | .write_tx_data = rt2800_write_tx_data, | 371 | .write_tx_data = rt2800_write_tx_data, |
| 1180 | .write_beacon = rt2800_write_beacon, | 372 | .write_beacon = rt2800_write_beacon, |
| 1181 | .clear_beacon = rt2800_clear_beacon, | 373 | .clear_beacon = rt2800_clear_beacon, |
| 1182 | .fill_rxdone = rt2800pci_fill_rxdone, | 374 | .fill_rxdone = rt2800mmio_fill_rxdone, |
| 1183 | .config_shared_key = rt2800_config_shared_key, | 375 | .config_shared_key = rt2800_config_shared_key, |
| 1184 | .config_pairwise_key = rt2800_config_pairwise_key, | 376 | .config_pairwise_key = rt2800_config_pairwise_key, |
| 1185 | .config_filter = rt2800_config_filter, | 377 | .config_filter = rt2800_config_filter, |
| @@ -1191,49 +383,6 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { | |||
| 1191 | .sta_remove = rt2800_sta_remove, | 383 | .sta_remove = rt2800_sta_remove, |
| 1192 | }; | 384 | }; |
| 1193 | 385 | ||
| 1194 | static void rt2800pci_queue_init(struct data_queue *queue) | ||
| 1195 | { | ||
| 1196 | struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; | ||
| 1197 | unsigned short txwi_size, rxwi_size; | ||
| 1198 | |||
| 1199 | rt2800_get_txwi_rxwi_size(rt2x00dev, &txwi_size, &rxwi_size); | ||
| 1200 | |||
| 1201 | switch (queue->qid) { | ||
| 1202 | case QID_RX: | ||
| 1203 | queue->limit = 128; | ||
| 1204 | queue->data_size = AGGREGATION_SIZE; | ||
| 1205 | queue->desc_size = RXD_DESC_SIZE; | ||
| 1206 | queue->winfo_size = rxwi_size; | ||
| 1207 | queue->priv_size = sizeof(struct queue_entry_priv_mmio); | ||
| 1208 | break; | ||
| 1209 | |||
| 1210 | case QID_AC_VO: | ||
| 1211 | case QID_AC_VI: | ||
| 1212 | case QID_AC_BE: | ||
| 1213 | case QID_AC_BK: | ||
| 1214 | queue->limit = 64; | ||
| 1215 | queue->data_size = AGGREGATION_SIZE; | ||
| 1216 | queue->desc_size = TXD_DESC_SIZE; | ||
| 1217 | queue->winfo_size = txwi_size; | ||
| 1218 | queue->priv_size = sizeof(struct queue_entry_priv_mmio); | ||
| 1219 | break; | ||
| 1220 | |||
| 1221 | case QID_BEACON: | ||
| 1222 | queue->limit = 8; | ||
| 1223 | queue->data_size = 0; /* No DMA required for beacons */ | ||
| 1224 | queue->desc_size = TXD_DESC_SIZE; | ||
| 1225 | queue->winfo_size = txwi_size; | ||
| 1226 | queue->priv_size = sizeof(struct queue_entry_priv_mmio); | ||
| 1227 | break; | ||
| 1228 | |||
| 1229 | case QID_ATIM: | ||
| 1230 | /* fallthrough */ | ||
| 1231 | default: | ||
| 1232 | BUG(); | ||
| 1233 | break; | ||
| 1234 | } | ||
| 1235 | } | ||
| 1236 | |||
| 1237 | static const struct rt2x00_ops rt2800pci_ops = { | 386 | static const struct rt2x00_ops rt2800pci_ops = { |
| 1238 | .name = KBUILD_MODNAME, | 387 | .name = KBUILD_MODNAME, |
| 1239 | .drv_data_size = sizeof(struct rt2800_drv_data), | 388 | .drv_data_size = sizeof(struct rt2800_drv_data), |
| @@ -1241,7 +390,7 @@ static const struct rt2x00_ops rt2800pci_ops = { | |||
| 1241 | .eeprom_size = EEPROM_SIZE, | 390 | .eeprom_size = EEPROM_SIZE, |
| 1242 | .rf_size = RF_SIZE, | 391 | .rf_size = RF_SIZE, |
| 1243 | .tx_queues = NUM_TX_QUEUES, | 392 | .tx_queues = NUM_TX_QUEUES, |
| 1244 | .queue_init = rt2800pci_queue_init, | 393 | .queue_init = rt2800mmio_queue_init, |
| 1245 | .lib = &rt2800pci_rt2x00_ops, | 394 | .lib = &rt2800pci_rt2x00_ops, |
| 1246 | .drv = &rt2800pci_rt2800_ops, | 395 | .drv = &rt2800pci_rt2800_ops, |
| 1247 | .hw = &rt2800pci_mac80211_ops, | 396 | .hw = &rt2800pci_mac80211_ops, |
| @@ -1253,7 +402,6 @@ static const struct rt2x00_ops rt2800pci_ops = { | |||
| 1253 | /* | 402 | /* |
| 1254 | * RT2800pci module information. | 403 | * RT2800pci module information. |
| 1255 | */ | 404 | */ |
| 1256 | #ifdef CONFIG_PCI | ||
| 1257 | static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { | 405 | static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { |
| 1258 | { PCI_DEVICE(0x1814, 0x0601) }, | 406 | { PCI_DEVICE(0x1814, 0x0601) }, |
| 1259 | { PCI_DEVICE(0x1814, 0x0681) }, | 407 | { PCI_DEVICE(0x1814, 0x0681) }, |
| @@ -1298,38 +446,15 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { | |||
| 1298 | #endif | 446 | #endif |
| 1299 | { 0, } | 447 | { 0, } |
| 1300 | }; | 448 | }; |
| 1301 | #endif /* CONFIG_PCI */ | ||
| 1302 | 449 | ||
| 1303 | MODULE_AUTHOR(DRV_PROJECT); | 450 | MODULE_AUTHOR(DRV_PROJECT); |
| 1304 | MODULE_VERSION(DRV_VERSION); | 451 | MODULE_VERSION(DRV_VERSION); |
| 1305 | MODULE_DESCRIPTION("Ralink RT2800 PCI & PCMCIA Wireless LAN driver."); | 452 | MODULE_DESCRIPTION("Ralink RT2800 PCI & PCMCIA Wireless LAN driver."); |
| 1306 | MODULE_SUPPORTED_DEVICE("Ralink RT2860 PCI & PCMCIA chipset based cards"); | 453 | MODULE_SUPPORTED_DEVICE("Ralink RT2860 PCI & PCMCIA chipset based cards"); |
| 1307 | #ifdef CONFIG_PCI | ||
| 1308 | MODULE_FIRMWARE(FIRMWARE_RT2860); | 454 | MODULE_FIRMWARE(FIRMWARE_RT2860); |
| 1309 | MODULE_DEVICE_TABLE(pci, rt2800pci_device_table); | 455 | MODULE_DEVICE_TABLE(pci, rt2800pci_device_table); |
| 1310 | #endif /* CONFIG_PCI */ | ||
| 1311 | MODULE_LICENSE("GPL"); | 456 | MODULE_LICENSE("GPL"); |
| 1312 | 457 | ||
| 1313 | #if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X) | ||
| 1314 | static int rt2800soc_probe(struct platform_device *pdev) | ||
| 1315 | { | ||
| 1316 | return rt2x00soc_probe(pdev, &rt2800pci_ops); | ||
| 1317 | } | ||
| 1318 | |||
| 1319 | static struct platform_driver rt2800soc_driver = { | ||
| 1320 | .driver = { | ||
| 1321 | .name = "rt2800_wmac", | ||
| 1322 | .owner = THIS_MODULE, | ||
| 1323 | .mod_name = KBUILD_MODNAME, | ||
| 1324 | }, | ||
| 1325 | .probe = rt2800soc_probe, | ||
| 1326 | .remove = rt2x00soc_remove, | ||
| 1327 | .suspend = rt2x00soc_suspend, | ||
| 1328 | .resume = rt2x00soc_resume, | ||
| 1329 | }; | ||
| 1330 | #endif /* CONFIG_SOC_RT288X || CONFIG_SOC_RT305X */ | ||
| 1331 | |||
| 1332 | #ifdef CONFIG_PCI | ||
| 1333 | static int rt2800pci_probe(struct pci_dev *pci_dev, | 458 | static int rt2800pci_probe(struct pci_dev *pci_dev, |
| 1334 | const struct pci_device_id *id) | 459 | const struct pci_device_id *id) |
| 1335 | { | 460 | { |
| @@ -1344,39 +469,5 @@ static struct pci_driver rt2800pci_driver = { | |||
| 1344 | .suspend = rt2x00pci_suspend, | 469 | .suspend = rt2x00pci_suspend, |
| 1345 | .resume = rt2x00pci_resume, | 470 | .resume = rt2x00pci_resume, |
| 1346 | }; | 471 | }; |
| 1347 | #endif /* CONFIG_PCI */ | ||
| 1348 | |||
| 1349 | static int __init rt2800pci_init(void) | ||
| 1350 | { | ||
| 1351 | int ret = 0; | ||
| 1352 | |||
| 1353 | #if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X) | ||
| 1354 | ret = platform_driver_register(&rt2800soc_driver); | ||
| 1355 | if (ret) | ||
| 1356 | return ret; | ||
| 1357 | #endif | ||
| 1358 | #ifdef CONFIG_PCI | ||
| 1359 | ret = pci_register_driver(&rt2800pci_driver); | ||
| 1360 | if (ret) { | ||
| 1361 | #if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X) | ||
| 1362 | platform_driver_unregister(&rt2800soc_driver); | ||
| 1363 | #endif | ||
| 1364 | return ret; | ||
| 1365 | } | ||
| 1366 | #endif | ||
| 1367 | |||
| 1368 | return ret; | ||
| 1369 | } | ||
| 1370 | |||
| 1371 | static void __exit rt2800pci_exit(void) | ||
| 1372 | { | ||
| 1373 | #ifdef CONFIG_PCI | ||
| 1374 | pci_unregister_driver(&rt2800pci_driver); | ||
| 1375 | #endif | ||
| 1376 | #if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X) | ||
| 1377 | platform_driver_unregister(&rt2800soc_driver); | ||
| 1378 | #endif | ||
| 1379 | } | ||
| 1380 | 472 | ||
| 1381 | module_init(rt2800pci_init); | 473 | module_pci_driver(rt2800pci_driver); |
| 1382 | module_exit(rt2800pci_exit); | ||
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.h b/drivers/net/wireless/rt2x00/rt2800pci.h index ab22a087c50d..a81c9ee281c0 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.h +++ b/drivers/net/wireless/rt2x00/rt2800pci.h | |||
| @@ -35,107 +35,10 @@ | |||
| 35 | #define RT2800PCI_H | 35 | #define RT2800PCI_H |
| 36 | 36 | ||
| 37 | /* | 37 | /* |
| 38 | * Queue register offset macros | ||
| 39 | */ | ||
| 40 | #define TX_QUEUE_REG_OFFSET 0x10 | ||
| 41 | #define TX_BASE_PTR(__x) (TX_BASE_PTR0 + ((__x) * TX_QUEUE_REG_OFFSET)) | ||
| 42 | #define TX_MAX_CNT(__x) (TX_MAX_CNT0 + ((__x) * TX_QUEUE_REG_OFFSET)) | ||
| 43 | #define TX_CTX_IDX(__x) (TX_CTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET)) | ||
| 44 | #define TX_DTX_IDX(__x) (TX_DTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET)) | ||
| 45 | |||
| 46 | /* | ||
| 47 | * 8051 firmware image. | 38 | * 8051 firmware image. |
| 48 | */ | 39 | */ |
| 49 | #define FIRMWARE_RT2860 "rt2860.bin" | 40 | #define FIRMWARE_RT2860 "rt2860.bin" |
| 50 | #define FIRMWARE_RT3290 "rt3290.bin" | 41 | #define FIRMWARE_RT3290 "rt3290.bin" |
| 51 | #define FIRMWARE_IMAGE_BASE 0x2000 | 42 | #define FIRMWARE_IMAGE_BASE 0x2000 |
| 52 | 43 | ||
| 53 | /* | ||
| 54 | * DMA descriptor defines. | ||
| 55 | */ | ||
| 56 | #define TXD_DESC_SIZE (4 * sizeof(__le32)) | ||
| 57 | #define RXD_DESC_SIZE (4 * sizeof(__le32)) | ||
| 58 | |||
| 59 | /* | ||
| 60 | * TX descriptor format for TX, PRIO and Beacon Ring. | ||
| 61 | */ | ||
| 62 | |||
| 63 | /* | ||
| 64 | * Word0 | ||
| 65 | */ | ||
| 66 | #define TXD_W0_SD_PTR0 FIELD32(0xffffffff) | ||
| 67 | |||
| 68 | /* | ||
| 69 | * Word1 | ||
| 70 | */ | ||
| 71 | #define TXD_W1_SD_LEN1 FIELD32(0x00003fff) | ||
| 72 | #define TXD_W1_LAST_SEC1 FIELD32(0x00004000) | ||
| 73 | #define TXD_W1_BURST FIELD32(0x00008000) | ||
| 74 | #define TXD_W1_SD_LEN0 FIELD32(0x3fff0000) | ||
| 75 | #define TXD_W1_LAST_SEC0 FIELD32(0x40000000) | ||
| 76 | #define TXD_W1_DMA_DONE FIELD32(0x80000000) | ||
| 77 | |||
| 78 | /* | ||
| 79 | * Word2 | ||
| 80 | */ | ||
| 81 | #define TXD_W2_SD_PTR1 FIELD32(0xffffffff) | ||
| 82 | |||
| 83 | /* | ||
| 84 | * Word3 | ||
| 85 | * WIV: Wireless Info Valid. 1: Driver filled WI, 0: DMA needs to copy WI | ||
| 86 | * QSEL: Select on-chip FIFO ID for 2nd-stage output scheduler. | ||
| 87 | * 0:MGMT, 1:HCCA 2:EDCA | ||
| 88 | */ | ||
| 89 | #define TXD_W3_WIV FIELD32(0x01000000) | ||
| 90 | #define TXD_W3_QSEL FIELD32(0x06000000) | ||
| 91 | #define TXD_W3_TCO FIELD32(0x20000000) | ||
| 92 | #define TXD_W3_UCO FIELD32(0x40000000) | ||
| 93 | #define TXD_W3_ICO FIELD32(0x80000000) | ||
| 94 | |||
| 95 | /* | ||
| 96 | * RX descriptor format for RX Ring. | ||
| 97 | */ | ||
| 98 | |||
| 99 | /* | ||
| 100 | * Word0 | ||
| 101 | */ | ||
| 102 | #define RXD_W0_SDP0 FIELD32(0xffffffff) | ||
| 103 | |||
| 104 | /* | ||
| 105 | * Word1 | ||
| 106 | */ | ||
| 107 | #define RXD_W1_SDL1 FIELD32(0x00003fff) | ||
| 108 | #define RXD_W1_SDL0 FIELD32(0x3fff0000) | ||
| 109 | #define RXD_W1_LS0 FIELD32(0x40000000) | ||
| 110 | #define RXD_W1_DMA_DONE FIELD32(0x80000000) | ||
| 111 | |||
| 112 | /* | ||
| 113 | * Word2 | ||
| 114 | */ | ||
| 115 | #define RXD_W2_SDP1 FIELD32(0xffffffff) | ||
| 116 | |||
| 117 | /* | ||
| 118 | * Word3 | ||
| 119 | * AMSDU: RX with 802.3 header, not 802.11 header. | ||
| 120 | * DECRYPTED: This frame is being decrypted. | ||
| 121 | */ | ||
| 122 | #define RXD_W3_BA FIELD32(0x00000001) | ||
| 123 | #define RXD_W3_DATA FIELD32(0x00000002) | ||
| 124 | #define RXD_W3_NULLDATA FIELD32(0x00000004) | ||
| 125 | #define RXD_W3_FRAG FIELD32(0x00000008) | ||
| 126 | #define RXD_W3_UNICAST_TO_ME FIELD32(0x00000010) | ||
| 127 | #define RXD_W3_MULTICAST FIELD32(0x00000020) | ||
| 128 | #define RXD_W3_BROADCAST FIELD32(0x00000040) | ||
| 129 | #define RXD_W3_MY_BSS FIELD32(0x00000080) | ||
| 130 | #define RXD_W3_CRC_ERROR FIELD32(0x00000100) | ||
| 131 | #define RXD_W3_CIPHER_ERROR FIELD32(0x00000600) | ||
| 132 | #define RXD_W3_AMSDU FIELD32(0x00000800) | ||
| 133 | #define RXD_W3_HTC FIELD32(0x00001000) | ||
| 134 | #define RXD_W3_RSSI FIELD32(0x00002000) | ||
| 135 | #define RXD_W3_L2PAD FIELD32(0x00004000) | ||
| 136 | #define RXD_W3_AMPDU FIELD32(0x00008000) | ||
| 137 | #define RXD_W3_DECRYPTED FIELD32(0x00010000) | ||
| 138 | #define RXD_W3_PLCP_SIGNAL FIELD32(0x00020000) | ||
| 139 | #define RXD_W3_PLCP_RSSI FIELD32(0x00040000) | ||
| 140 | |||
| 141 | #endif /* RT2800PCI_H */ | 44 | #endif /* RT2800PCI_H */ |
diff --git a/drivers/net/wireless/rt2x00/rt2800soc.c b/drivers/net/wireless/rt2x00/rt2800soc.c new file mode 100644 index 000000000000..1359227ca411 --- /dev/null +++ b/drivers/net/wireless/rt2x00/rt2800soc.c | |||
| @@ -0,0 +1,263 @@ | |||
| 1 | /* Copyright (C) 2009 - 2010 Ivo van Doorn <IvDoorn@gmail.com> | ||
| 2 | * Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com> | ||
| 3 | * Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org> | ||
| 4 | * Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com> | ||
| 5 | * Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de> | ||
| 6 | * Copyright (C) 2009 Mark Asselstine <asselsm@gmail.com> | ||
| 7 | * Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com> | ||
| 8 | * Copyright (C) 2009 Bart Zolnierkiewicz <bzolnier@gmail.com> | ||
| 9 | * <http://rt2x00.serialmonkey.com> | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or modify | ||
| 12 | * it under the terms of the GNU General Public License as published by | ||
| 13 | * the Free Software Foundation; either version 2 of the License, or | ||
| 14 | * (at your option) any later version. | ||
| 15 | * | ||
| 16 | * This program is distributed in the hope that it will be useful, | ||
| 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 19 | * GNU General Public License for more details. | ||
| 20 | * | ||
| 21 | * You should have received a copy of the GNU General Public License | ||
| 22 | * along with this program; if not, write to the | ||
| 23 | * Free Software Foundation, Inc., | ||
| 24 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
| 25 | */ | ||
| 26 | |||
| 27 | /* Module: rt2800soc | ||
| 28 | * Abstract: rt2800 WiSoC specific routines. | ||
| 29 | */ | ||
| 30 | |||
| 31 | #include <linux/etherdevice.h> | ||
| 32 | #include <linux/init.h> | ||
| 33 | #include <linux/kernel.h> | ||
| 34 | #include <linux/module.h> | ||
| 35 | #include <linux/platform_device.h> | ||
| 36 | |||
| 37 | #include "rt2x00.h" | ||
| 38 | #include "rt2x00mmio.h" | ||
| 39 | #include "rt2x00soc.h" | ||
| 40 | #include "rt2800.h" | ||
| 41 | #include "rt2800lib.h" | ||
| 42 | #include "rt2800mmio.h" | ||
| 43 | |||
| 44 | /* Allow hardware encryption to be disabled. */ | ||
| 45 | static bool modparam_nohwcrypt; | ||
| 46 | module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); | ||
| 47 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); | ||
| 48 | |||
| 49 | static bool rt2800soc_hwcrypt_disabled(struct rt2x00_dev *rt2x00dev) | ||
| 50 | { | ||
| 51 | return modparam_nohwcrypt; | ||
| 52 | } | ||
| 53 | |||
| 54 | static void rt2800soc_disable_radio(struct rt2x00_dev *rt2x00dev) | ||
| 55 | { | ||
| 56 | rt2800_disable_radio(rt2x00dev); | ||
| 57 | rt2x00mmio_register_write(rt2x00dev, PWR_PIN_CFG, 0); | ||
| 58 | rt2x00mmio_register_write(rt2x00dev, TX_PIN_CFG, 0); | ||
| 59 | } | ||
| 60 | |||
| 61 | static int rt2800soc_set_device_state(struct rt2x00_dev *rt2x00dev, | ||
| 62 | enum dev_state state) | ||
| 63 | { | ||
| 64 | int retval = 0; | ||
| 65 | |||
| 66 | switch (state) { | ||
| 67 | case STATE_RADIO_ON: | ||
| 68 | retval = rt2800mmio_enable_radio(rt2x00dev); | ||
| 69 | break; | ||
| 70 | |||
| 71 | case STATE_RADIO_OFF: | ||
| 72 | rt2800soc_disable_radio(rt2x00dev); | ||
| 73 | break; | ||
| 74 | |||
| 75 | case STATE_RADIO_IRQ_ON: | ||
| 76 | case STATE_RADIO_IRQ_OFF: | ||
| 77 | rt2800mmio_toggle_irq(rt2x00dev, state); | ||
| 78 | break; | ||
| 79 | |||
| 80 | case STATE_DEEP_SLEEP: | ||
| 81 | case STATE_SLEEP: | ||
| 82 | case STATE_STANDBY: | ||
| 83 | case STATE_AWAKE: | ||
| 84 | /* These states are not supported, but don't report an error */ | ||
| 85 | retval = 0; | ||
| 86 | break; | ||
| 87 | |||
| 88 | default: | ||
| 89 | retval = -ENOTSUPP; | ||
| 90 | break; | ||
| 91 | } | ||
| 92 | |||
| 93 | if (unlikely(retval)) | ||
| 94 | rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n", | ||
| 95 | state, retval); | ||
| 96 | |||
| 97 | return retval; | ||
| 98 | } | ||
| 99 | |||
| 100 | static int rt2800soc_read_eeprom(struct rt2x00_dev *rt2x00dev) | ||
| 101 | { | ||
| 102 | void __iomem *base_addr = ioremap(0x1F040000, EEPROM_SIZE); | ||
| 103 | |||
| 104 | if (!base_addr) | ||
| 105 | return -ENOMEM; | ||
| 106 | |||
| 107 | memcpy_fromio(rt2x00dev->eeprom, base_addr, EEPROM_SIZE); | ||
| 108 | |||
| 109 | iounmap(base_addr); | ||
| 110 | return 0; | ||
| 111 | } | ||
| 112 | |||
| 113 | /* Firmware functions */ | ||
| 114 | static char *rt2800soc_get_firmware_name(struct rt2x00_dev *rt2x00dev) | ||
| 115 | { | ||
| 116 | WARN_ON_ONCE(1); | ||
| 117 | return NULL; | ||
| 118 | } | ||
| 119 | |||
| 120 | static int rt2800soc_load_firmware(struct rt2x00_dev *rt2x00dev, | ||
| 121 | const u8 *data, const size_t len) | ||
| 122 | { | ||
| 123 | WARN_ON_ONCE(1); | ||
| 124 | return 0; | ||
| 125 | } | ||
| 126 | |||
| 127 | static int rt2800soc_check_firmware(struct rt2x00_dev *rt2x00dev, | ||
| 128 | const u8 *data, const size_t len) | ||
| 129 | { | ||
| 130 | WARN_ON_ONCE(1); | ||
| 131 | return 0; | ||
| 132 | } | ||
| 133 | |||
| 134 | static int rt2800soc_write_firmware(struct rt2x00_dev *rt2x00dev, | ||
| 135 | const u8 *data, const size_t len) | ||
| 136 | { | ||
| 137 | WARN_ON_ONCE(1); | ||
| 138 | return 0; | ||
| 139 | } | ||
| 140 | |||
| 141 | static const struct ieee80211_ops rt2800soc_mac80211_ops = { | ||
| 142 | .tx = rt2x00mac_tx, | ||
| 143 | .start = rt2x00mac_start, | ||
| 144 | .stop = rt2x00mac_stop, | ||
| 145 | .add_interface = rt2x00mac_add_interface, | ||
| 146 | .remove_interface = rt2x00mac_remove_interface, | ||
| 147 | .config = rt2x00mac_config, | ||
| 148 | .configure_filter = rt2x00mac_configure_filter, | ||
| 149 | .set_key = rt2x00mac_set_key, | ||
| 150 | .sw_scan_start = rt2x00mac_sw_scan_start, | ||
| 151 | .sw_scan_complete = rt2x00mac_sw_scan_complete, | ||
| 152 | .get_stats = rt2x00mac_get_stats, | ||
| 153 | .get_tkip_seq = rt2800_get_tkip_seq, | ||
| 154 | .set_rts_threshold = rt2800_set_rts_threshold, | ||
| 155 | .sta_add = rt2x00mac_sta_add, | ||
| 156 | .sta_remove = rt2x00mac_sta_remove, | ||
| 157 | .bss_info_changed = rt2x00mac_bss_info_changed, | ||
| 158 | .conf_tx = rt2800_conf_tx, | ||
| 159 | .get_tsf = rt2800_get_tsf, | ||
| 160 | .rfkill_poll = rt2x00mac_rfkill_poll, | ||
| 161 | .ampdu_action = rt2800_ampdu_action, | ||
| 162 | .flush = rt2x00mac_flush, | ||
| 163 | .get_survey = rt2800_get_survey, | ||
| 164 | .get_ringparam = rt2x00mac_get_ringparam, | ||
| 165 | .tx_frames_pending = rt2x00mac_tx_frames_pending, | ||
| 166 | }; | ||
| 167 | |||
| 168 | static const struct rt2800_ops rt2800soc_rt2800_ops = { | ||
| 169 | .register_read = rt2x00mmio_register_read, | ||
| 170 | .register_read_lock = rt2x00mmio_register_read, /* same for SoCs */ | ||
| 171 | .register_write = rt2x00mmio_register_write, | ||
| 172 | .register_write_lock = rt2x00mmio_register_write, /* same for SoCs */ | ||
| 173 | .register_multiread = rt2x00mmio_register_multiread, | ||
| 174 | .register_multiwrite = rt2x00mmio_register_multiwrite, | ||
| 175 | .regbusy_read = rt2x00mmio_regbusy_read, | ||
| 176 | .read_eeprom = rt2800soc_read_eeprom, | ||
| 177 | .hwcrypt_disabled = rt2800soc_hwcrypt_disabled, | ||
| 178 | .drv_write_firmware = rt2800soc_write_firmware, | ||
| 179 | .drv_init_registers = rt2800mmio_init_registers, | ||
| 180 | .drv_get_txwi = rt2800mmio_get_txwi, | ||
| 181 | }; | ||
| 182 | |||
| 183 | static const struct rt2x00lib_ops rt2800soc_rt2x00_ops = { | ||
| 184 | .irq_handler = rt2800mmio_interrupt, | ||
| 185 | .txstatus_tasklet = rt2800mmio_txstatus_tasklet, | ||
| 186 | .pretbtt_tasklet = rt2800mmio_pretbtt_tasklet, | ||
| 187 | .tbtt_tasklet = rt2800mmio_tbtt_tasklet, | ||
| 188 | .rxdone_tasklet = rt2800mmio_rxdone_tasklet, | ||
| 189 | .autowake_tasklet = rt2800mmio_autowake_tasklet, | ||
| 190 | .probe_hw = rt2800_probe_hw, | ||
| 191 | .get_firmware_name = rt2800soc_get_firmware_name, | ||
| 192 | .check_firmware = rt2800soc_check_firmware, | ||
| 193 | .load_firmware = rt2800soc_load_firmware, | ||
| 194 | .initialize = rt2x00mmio_initialize, | ||
| 195 | .uninitialize = rt2x00mmio_uninitialize, | ||
| 196 | .get_entry_state = rt2800mmio_get_entry_state, | ||
| 197 | .clear_entry = rt2800mmio_clear_entry, | ||
| 198 | .set_device_state = rt2800soc_set_device_state, | ||
| 199 | .rfkill_poll = rt2800_rfkill_poll, | ||
| 200 | .link_stats = rt2800_link_stats, | ||
| 201 | .reset_tuner = rt2800_reset_tuner, | ||
| 202 | .link_tuner = rt2800_link_tuner, | ||
| 203 | .gain_calibration = rt2800_gain_calibration, | ||
| 204 | .vco_calibration = rt2800_vco_calibration, | ||
| 205 | .start_queue = rt2800mmio_start_queue, | ||
| 206 | .kick_queue = rt2800mmio_kick_queue, | ||
| 207 | .stop_queue = rt2800mmio_stop_queue, | ||
| 208 | .flush_queue = rt2x00mmio_flush_queue, | ||
| 209 | .write_tx_desc = rt2800mmio_write_tx_desc, | ||
| 210 | .write_tx_data = rt2800_write_tx_data, | ||
| 211 | .write_beacon = rt2800_write_beacon, | ||
| 212 | .clear_beacon = rt2800_clear_beacon, | ||
| 213 | .fill_rxdone = rt2800mmio_fill_rxdone, | ||
| 214 | .config_shared_key = rt2800_config_shared_key, | ||
| 215 | .config_pairwise_key = rt2800_config_pairwise_key, | ||
| 216 | .config_filter = rt2800_config_filter, | ||
| 217 | .config_intf = rt2800_config_intf, | ||
| 218 | .config_erp = rt2800_config_erp, | ||
| 219 | .config_ant = rt2800_config_ant, | ||
| 220 | .config = rt2800_config, | ||
| 221 | .sta_add = rt2800_sta_add, | ||
| 222 | .sta_remove = rt2800_sta_remove, | ||
| 223 | }; | ||
| 224 | |||
| 225 | static const struct rt2x00_ops rt2800soc_ops = { | ||
| 226 | .name = KBUILD_MODNAME, | ||
| 227 | .drv_data_size = sizeof(struct rt2800_drv_data), | ||
| 228 | .max_ap_intf = 8, | ||
| 229 | .eeprom_size = EEPROM_SIZE, | ||
| 230 | .rf_size = RF_SIZE, | ||
| 231 | .tx_queues = NUM_TX_QUEUES, | ||
| 232 | .queue_init = rt2800mmio_queue_init, | ||
| 233 | .lib = &rt2800soc_rt2x00_ops, | ||
| 234 | .drv = &rt2800soc_rt2800_ops, | ||
| 235 | .hw = &rt2800soc_mac80211_ops, | ||
| 236 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS | ||
| 237 | .debugfs = &rt2800_rt2x00debug, | ||
| 238 | #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ | ||
| 239 | }; | ||
| 240 | |||
| 241 | static int rt2800soc_probe(struct platform_device *pdev) | ||
| 242 | { | ||
| 243 | return rt2x00soc_probe(pdev, &rt2800soc_ops); | ||
| 244 | } | ||
| 245 | |||
| 246 | static struct platform_driver rt2800soc_driver = { | ||
| 247 | .driver = { | ||
| 248 | .name = "rt2800_wmac", | ||
| 249 | .owner = THIS_MODULE, | ||
| 250 | .mod_name = KBUILD_MODNAME, | ||
| 251 | }, | ||
| 252 | .probe = rt2800soc_probe, | ||
| 253 | .remove = rt2x00soc_remove, | ||
| 254 | .suspend = rt2x00soc_suspend, | ||
| 255 | .resume = rt2x00soc_resume, | ||
| 256 | }; | ||
| 257 | |||
| 258 | module_platform_driver(rt2800soc_driver); | ||
| 259 | |||
| 260 | MODULE_AUTHOR(DRV_PROJECT); | ||
| 261 | MODULE_VERSION(DRV_VERSION); | ||
| 262 | MODULE_DESCRIPTION("Ralink WiSoC Wireless LAN driver."); | ||
| 263 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 96677ce55da4..997df03a0c2e 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c | |||
| @@ -148,6 +148,8 @@ static bool rt2800usb_txstatus_timeout(struct rt2x00_dev *rt2x00dev) | |||
| 148 | return false; | 148 | return false; |
| 149 | } | 149 | } |
| 150 | 150 | ||
| 151 | #define TXSTATUS_READ_INTERVAL 1000000 | ||
| 152 | |||
| 151 | static bool rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev, | 153 | static bool rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev, |
| 152 | int urb_status, u32 tx_status) | 154 | int urb_status, u32 tx_status) |
| 153 | { | 155 | { |
| @@ -176,8 +178,9 @@ static bool rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev, | |||
| 176 | queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); | 178 | queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); |
| 177 | 179 | ||
| 178 | if (rt2800usb_txstatus_pending(rt2x00dev)) { | 180 | if (rt2800usb_txstatus_pending(rt2x00dev)) { |
| 179 | /* Read register after 250 us */ | 181 | /* Read register after 1 ms */ |
| 180 | hrtimer_start(&rt2x00dev->txstatus_timer, ktime_set(0, 250000), | 182 | hrtimer_start(&rt2x00dev->txstatus_timer, |
| 183 | ktime_set(0, TXSTATUS_READ_INTERVAL), | ||
| 181 | HRTIMER_MODE_REL); | 184 | HRTIMER_MODE_REL); |
| 182 | return false; | 185 | return false; |
| 183 | } | 186 | } |
| @@ -202,8 +205,9 @@ static void rt2800usb_async_read_tx_status(struct rt2x00_dev *rt2x00dev) | |||
| 202 | if (test_and_set_bit(TX_STATUS_READING, &rt2x00dev->flags)) | 205 | if (test_and_set_bit(TX_STATUS_READING, &rt2x00dev->flags)) |
| 203 | return; | 206 | return; |
| 204 | 207 | ||
| 205 | /* Read TX_STA_FIFO register after 500 us */ | 208 | /* Read TX_STA_FIFO register after 2 ms */ |
| 206 | hrtimer_start(&rt2x00dev->txstatus_timer, ktime_set(0, 500000), | 209 | hrtimer_start(&rt2x00dev->txstatus_timer, |
| 210 | ktime_set(0, 2*TXSTATUS_READ_INTERVAL), | ||
| 207 | HRTIMER_MODE_REL); | 211 | HRTIMER_MODE_REL); |
| 208 | } | 212 | } |
| 209 | 213 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 51f17cfb93f9..7c157857f5ce 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
| @@ -754,6 +754,9 @@ void rt2x00mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop) | |||
| 754 | struct rt2x00_dev *rt2x00dev = hw->priv; | 754 | struct rt2x00_dev *rt2x00dev = hw->priv; |
| 755 | struct data_queue *queue; | 755 | struct data_queue *queue; |
| 756 | 756 | ||
| 757 | if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) | ||
| 758 | return; | ||
| 759 | |||
| 757 | tx_queue_for_each(rt2x00dev, queue) | 760 | tx_queue_for_each(rt2x00dev, queue) |
| 758 | rt2x00queue_flush_queue(queue, drop); | 761 | rt2x00queue_flush_queue(queue, drop); |
| 759 | } | 762 | } |
diff --git a/drivers/nfc/Kconfig b/drivers/nfc/Kconfig index b0b64ccb7d7d..c1fb20603338 100644 --- a/drivers/nfc/Kconfig +++ b/drivers/nfc/Kconfig | |||
| @@ -46,6 +46,16 @@ config NFC_SIM | |||
| 46 | 46 | ||
| 47 | If unsure, say N. | 47 | If unsure, say N. |
| 48 | 48 | ||
| 49 | config NFC_PORT100 | ||
| 50 | tristate "Sony NFC Port-100 Series USB device support" | ||
| 51 | depends on USB | ||
| 52 | depends on NFC_DIGITAL | ||
| 53 | help | ||
| 54 | This adds support for Sony Port-100 chip based USB devices such as the | ||
| 55 | RC-S380 dongle. | ||
| 56 | |||
| 57 | If unsure, say N. | ||
| 58 | |||
| 49 | source "drivers/nfc/pn544/Kconfig" | 59 | source "drivers/nfc/pn544/Kconfig" |
| 50 | source "drivers/nfc/microread/Kconfig" | 60 | source "drivers/nfc/microread/Kconfig" |
| 51 | 61 | ||
diff --git a/drivers/nfc/Makefile b/drivers/nfc/Makefile index be7636abcb3f..c715fe8582a8 100644 --- a/drivers/nfc/Makefile +++ b/drivers/nfc/Makefile | |||
| @@ -8,5 +8,6 @@ obj-$(CONFIG_NFC_PN533) += pn533.o | |||
| 8 | obj-$(CONFIG_NFC_WILINK) += nfcwilink.o | 8 | obj-$(CONFIG_NFC_WILINK) += nfcwilink.o |
| 9 | obj-$(CONFIG_NFC_MEI_PHY) += mei_phy.o | 9 | 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 | 12 | ||
| 12 | ccflags-$(CONFIG_NFC_DEBUG) := -DDEBUG | 13 | ccflags-$(CONFIG_NFC_DEBUG) := -DDEBUG |
diff --git a/drivers/nfc/mei_phy.c b/drivers/nfc/mei_phy.c index 606bf55e76ec..85f90090cc1d 100644 --- a/drivers/nfc/mei_phy.c +++ b/drivers/nfc/mei_phy.c | |||
| @@ -18,6 +18,8 @@ | |||
| 18 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 18 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 22 | |||
| 21 | #include <linux/module.h> | 23 | #include <linux/module.h> |
| 22 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
| 23 | #include <linux/nfc.h> | 25 | #include <linux/nfc.h> |
| @@ -60,13 +62,13 @@ int nfc_mei_phy_enable(void *phy_id) | |||
| 60 | 62 | ||
| 61 | r = mei_cl_enable_device(phy->device); | 63 | r = mei_cl_enable_device(phy->device); |
| 62 | if (r < 0) { | 64 | if (r < 0) { |
| 63 | pr_err("MEI_PHY: Could not enable device\n"); | 65 | pr_err("Could not enable device\n"); |
| 64 | return r; | 66 | return r; |
| 65 | } | 67 | } |
| 66 | 68 | ||
| 67 | r = mei_cl_register_event_cb(phy->device, nfc_mei_event_cb, phy); | 69 | r = mei_cl_register_event_cb(phy->device, nfc_mei_event_cb, phy); |
| 68 | if (r) { | 70 | if (r) { |
| 69 | pr_err("MEY_PHY: Event cb registration failed\n"); | 71 | pr_err("Event cb registration failed\n"); |
| 70 | mei_cl_disable_device(phy->device); | 72 | mei_cl_disable_device(phy->device); |
| 71 | phy->powered = 0; | 73 | phy->powered = 0; |
| 72 | 74 | ||
diff --git a/drivers/nfc/microread/i2c.c b/drivers/nfc/microread/i2c.c index 101089495bf8..696e3467eccc 100644 --- a/drivers/nfc/microread/i2c.c +++ b/drivers/nfc/microread/i2c.c | |||
| @@ -18,6 +18,8 @@ | |||
| 18 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 18 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 22 | |||
| 21 | #include <linux/module.h> | 23 | #include <linux/module.h> |
| 22 | #include <linux/i2c.h> | 24 | #include <linux/i2c.h> |
| 23 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
| @@ -95,12 +97,8 @@ static int check_crc(struct sk_buff *skb) | |||
| 95 | crc = crc ^ skb->data[i]; | 97 | crc = crc ^ skb->data[i]; |
| 96 | 98 | ||
| 97 | if (crc != skb->data[skb->len-1]) { | 99 | if (crc != skb->data[skb->len-1]) { |
| 98 | pr_err(MICROREAD_I2C_DRIVER_NAME | 100 | pr_err("CRC error 0x%x != 0x%x\n", crc, skb->data[skb->len-1]); |
| 99 | ": CRC error 0x%x != 0x%x\n", | 101 | pr_info("%s: BAD CRC\n", __func__); |
| 100 | crc, skb->data[skb->len-1]); | ||
| 101 | |||
| 102 | pr_info(DRIVER_DESC ": %s : BAD CRC\n", __func__); | ||
| 103 | |||
| 104 | return -EPERM; | 102 | return -EPERM; |
| 105 | } | 103 | } |
| 106 | 104 | ||
| @@ -160,18 +158,15 @@ static int microread_i2c_read(struct microread_i2c_phy *phy, | |||
| 160 | u8 tmp[MICROREAD_I2C_LLC_MAX_SIZE - 1]; | 158 | u8 tmp[MICROREAD_I2C_LLC_MAX_SIZE - 1]; |
| 161 | struct i2c_client *client = phy->i2c_dev; | 159 | struct i2c_client *client = phy->i2c_dev; |
| 162 | 160 | ||
| 163 | pr_debug("%s\n", __func__); | ||
| 164 | |||
| 165 | r = i2c_master_recv(client, &len, 1); | 161 | r = i2c_master_recv(client, &len, 1); |
| 166 | if (r != 1) { | 162 | if (r != 1) { |
| 167 | dev_err(&client->dev, "cannot read len byte\n"); | 163 | nfc_err(&client->dev, "cannot read len byte\n"); |
| 168 | return -EREMOTEIO; | 164 | return -EREMOTEIO; |
| 169 | } | 165 | } |
| 170 | 166 | ||
| 171 | if ((len < MICROREAD_I2C_LLC_MIN_SIZE) || | 167 | if ((len < MICROREAD_I2C_LLC_MIN_SIZE) || |
| 172 | (len > MICROREAD_I2C_LLC_MAX_SIZE)) { | 168 | (len > MICROREAD_I2C_LLC_MAX_SIZE)) { |
| 173 | dev_err(&client->dev, "invalid len byte\n"); | 169 | nfc_err(&client->dev, "invalid len byte\n"); |
| 174 | pr_err("invalid len byte\n"); | ||
| 175 | r = -EBADMSG; | 170 | r = -EBADMSG; |
| 176 | goto flush; | 171 | goto flush; |
| 177 | } | 172 | } |
| @@ -228,7 +223,6 @@ static irqreturn_t microread_i2c_irq_thread_fn(int irq, void *phy_id) | |||
| 228 | } | 223 | } |
| 229 | 224 | ||
| 230 | client = phy->i2c_dev; | 225 | client = phy->i2c_dev; |
| 231 | dev_dbg(&client->dev, "IRQ\n"); | ||
| 232 | 226 | ||
| 233 | if (phy->hard_fault != 0) | 227 | if (phy->hard_fault != 0) |
| 234 | return IRQ_HANDLED; | 228 | return IRQ_HANDLED; |
| @@ -263,20 +257,18 @@ static int microread_i2c_probe(struct i2c_client *client, | |||
| 263 | dev_get_platdata(&client->dev); | 257 | dev_get_platdata(&client->dev); |
| 264 | int r; | 258 | int r; |
| 265 | 259 | ||
| 266 | dev_dbg(&client->dev, "client %p", client); | 260 | dev_dbg(&client->dev, "client %p\n", client); |
| 267 | 261 | ||
| 268 | if (!pdata) { | 262 | if (!pdata) { |
| 269 | dev_err(&client->dev, "client %p: missing platform data", | 263 | nfc_err(&client->dev, "client %p: missing platform data\n", |
| 270 | client); | 264 | client); |
| 271 | return -EINVAL; | 265 | return -EINVAL; |
| 272 | } | 266 | } |
| 273 | 267 | ||
| 274 | phy = devm_kzalloc(&client->dev, sizeof(struct microread_i2c_phy), | 268 | phy = devm_kzalloc(&client->dev, sizeof(struct microread_i2c_phy), |
| 275 | GFP_KERNEL); | 269 | GFP_KERNEL); |
| 276 | if (!phy) { | 270 | if (!phy) |
| 277 | dev_err(&client->dev, "Can't allocate microread phy"); | ||
| 278 | return -ENOMEM; | 271 | return -ENOMEM; |
| 279 | } | ||
| 280 | 272 | ||
| 281 | i2c_set_clientdata(client, phy); | 273 | i2c_set_clientdata(client, phy); |
| 282 | phy->i2c_dev = client; | 274 | phy->i2c_dev = client; |
| @@ -285,7 +277,7 @@ static int microread_i2c_probe(struct i2c_client *client, | |||
| 285 | IRQF_TRIGGER_RISING | IRQF_ONESHOT, | 277 | IRQF_TRIGGER_RISING | IRQF_ONESHOT, |
| 286 | MICROREAD_I2C_DRIVER_NAME, phy); | 278 | MICROREAD_I2C_DRIVER_NAME, phy); |
| 287 | if (r) { | 279 | if (r) { |
| 288 | dev_err(&client->dev, "Unable to register IRQ handler"); | 280 | nfc_err(&client->dev, "Unable to register IRQ handler\n"); |
| 289 | return r; | 281 | return r; |
| 290 | } | 282 | } |
| 291 | 283 | ||
| @@ -296,7 +288,7 @@ static int microread_i2c_probe(struct i2c_client *client, | |||
| 296 | if (r < 0) | 288 | if (r < 0) |
| 297 | goto err_irq; | 289 | goto err_irq; |
| 298 | 290 | ||
| 299 | dev_info(&client->dev, "Probed"); | 291 | nfc_info(&client->dev, "Probed"); |
| 300 | 292 | ||
| 301 | return 0; | 293 | return 0; |
| 302 | 294 | ||
| @@ -310,8 +302,6 @@ static int microread_i2c_remove(struct i2c_client *client) | |||
| 310 | { | 302 | { |
| 311 | struct microread_i2c_phy *phy = i2c_get_clientdata(client); | 303 | struct microread_i2c_phy *phy = i2c_get_clientdata(client); |
| 312 | 304 | ||
| 313 | dev_dbg(&client->dev, "%s\n", __func__); | ||
| 314 | |||
| 315 | microread_remove(phy->hdev); | 305 | microread_remove(phy->hdev); |
| 316 | 306 | ||
| 317 | free_irq(client->irq, phy); | 307 | free_irq(client->irq, phy); |
diff --git a/drivers/nfc/microread/mei.c b/drivers/nfc/microread/mei.c index cdf1bc53b257..72fafec3d460 100644 --- a/drivers/nfc/microread/mei.c +++ b/drivers/nfc/microread/mei.c | |||
| @@ -18,6 +18,8 @@ | |||
| 18 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 18 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 22 | |||
| 21 | #include <linux/module.h> | 23 | #include <linux/module.h> |
| 22 | #include <linux/mod_devicetable.h> | 24 | #include <linux/mod_devicetable.h> |
| 23 | #include <linux/nfc.h> | 25 | #include <linux/nfc.h> |
| @@ -59,8 +61,6 @@ static int microread_mei_remove(struct mei_cl_device *device) | |||
| 59 | { | 61 | { |
| 60 | struct nfc_mei_phy *phy = mei_cl_get_drvdata(device); | 62 | struct nfc_mei_phy *phy = mei_cl_get_drvdata(device); |
| 61 | 63 | ||
| 62 | pr_info("Removing microread\n"); | ||
| 63 | |||
| 64 | microread_remove(phy->hdev); | 64 | microread_remove(phy->hdev); |
| 65 | 65 | ||
| 66 | nfc_mei_phy_free(phy); | 66 | nfc_mei_phy_free(phy); |
diff --git a/drivers/nfc/microread/microread.c b/drivers/nfc/microread/microread.c index cdb9f6de132a..970ded6bfcf5 100644 --- a/drivers/nfc/microread/microread.c +++ b/drivers/nfc/microread/microread.c | |||
| @@ -18,6 +18,8 @@ | |||
| 18 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 18 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 22 | |||
| 21 | #include <linux/module.h> | 23 | #include <linux/module.h> |
| 22 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
| 23 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
| @@ -546,7 +548,7 @@ exit: | |||
| 546 | kfree_skb(skb); | 548 | kfree_skb(skb); |
| 547 | 549 | ||
| 548 | if (r) | 550 | if (r) |
| 549 | pr_err("Failed to handle discovered target err=%d", r); | 551 | pr_err("Failed to handle discovered target err=%d\n", r); |
| 550 | } | 552 | } |
| 551 | 553 | ||
| 552 | static int microread_event_received(struct nfc_hci_dev *hdev, u8 gate, | 554 | static int microread_event_received(struct nfc_hci_dev *hdev, u8 gate, |
| @@ -656,7 +658,6 @@ int microread_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name, | |||
| 656 | 658 | ||
| 657 | info = kzalloc(sizeof(struct microread_info), GFP_KERNEL); | 659 | info = kzalloc(sizeof(struct microread_info), GFP_KERNEL); |
| 658 | if (!info) { | 660 | if (!info) { |
| 659 | pr_err("Cannot allocate memory for microread_info.\n"); | ||
| 660 | r = -ENOMEM; | 661 | r = -ENOMEM; |
| 661 | goto err_info_alloc; | 662 | goto err_info_alloc; |
| 662 | } | 663 | } |
| @@ -686,7 +687,7 @@ int microread_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name, | |||
| 686 | MICROREAD_CMD_TAILROOM, | 687 | MICROREAD_CMD_TAILROOM, |
| 687 | phy_payload); | 688 | phy_payload); |
| 688 | if (!info->hdev) { | 689 | if (!info->hdev) { |
| 689 | pr_err("Cannot allocate nfc hdev.\n"); | 690 | pr_err("Cannot allocate nfc hdev\n"); |
| 690 | r = -ENOMEM; | 691 | r = -ENOMEM; |
| 691 | goto err_alloc_hdev; | 692 | goto err_alloc_hdev; |
| 692 | } | 693 | } |
diff --git a/drivers/nfc/nfcsim.c b/drivers/nfc/nfcsim.c index 9a53f13c88df..93111fa8d282 100644 --- a/drivers/nfc/nfcsim.c +++ b/drivers/nfc/nfcsim.c | |||
| @@ -19,10 +19,10 @@ | |||
| 19 | #include <linux/nfc.h> | 19 | #include <linux/nfc.h> |
| 20 | #include <net/nfc/nfc.h> | 20 | #include <net/nfc/nfc.h> |
| 21 | 21 | ||
| 22 | #define DEV_ERR(_dev, fmt, args...) nfc_dev_err(&_dev->nfc_dev->dev, \ | 22 | #define DEV_ERR(_dev, fmt, args...) nfc_err(&_dev->nfc_dev->dev, \ |
| 23 | "%s: " fmt, __func__, ## args) | 23 | "%s: " fmt, __func__, ## args) |
| 24 | 24 | ||
| 25 | #define DEV_DBG(_dev, fmt, args...) nfc_dev_dbg(&_dev->nfc_dev->dev, \ | 25 | #define DEV_DBG(_dev, fmt, args...) dev_dbg(&_dev->nfc_dev->dev, \ |
| 26 | "%s: " fmt, __func__, ## args) | 26 | "%s: " fmt, __func__, ## args) |
| 27 | 27 | ||
| 28 | #define NFCSIM_VERSION "0.1" | 28 | #define NFCSIM_VERSION "0.1" |
| @@ -64,7 +64,7 @@ static struct workqueue_struct *wq; | |||
| 64 | 64 | ||
| 65 | static void nfcsim_cleanup_dev(struct nfcsim *dev, u8 shutdown) | 65 | static void nfcsim_cleanup_dev(struct nfcsim *dev, u8 shutdown) |
| 66 | { | 66 | { |
| 67 | DEV_DBG(dev, "shutdown=%d", shutdown); | 67 | DEV_DBG(dev, "shutdown=%d\n", shutdown); |
| 68 | 68 | ||
| 69 | mutex_lock(&dev->lock); | 69 | mutex_lock(&dev->lock); |
| 70 | 70 | ||
| @@ -84,7 +84,7 @@ static int nfcsim_target_found(struct nfcsim *dev) | |||
| 84 | { | 84 | { |
| 85 | struct nfc_target nfc_tgt; | 85 | struct nfc_target nfc_tgt; |
| 86 | 86 | ||
| 87 | DEV_DBG(dev, ""); | 87 | DEV_DBG(dev, "\n"); |
| 88 | 88 | ||
| 89 | memset(&nfc_tgt, 0, sizeof(struct nfc_target)); | 89 | memset(&nfc_tgt, 0, sizeof(struct nfc_target)); |
| 90 | 90 | ||
| @@ -98,7 +98,7 @@ static int nfcsim_dev_up(struct nfc_dev *nfc_dev) | |||
| 98 | { | 98 | { |
| 99 | struct nfcsim *dev = nfc_get_drvdata(nfc_dev); | 99 | struct nfcsim *dev = nfc_get_drvdata(nfc_dev); |
| 100 | 100 | ||
| 101 | DEV_DBG(dev, ""); | 101 | DEV_DBG(dev, "\n"); |
| 102 | 102 | ||
| 103 | mutex_lock(&dev->lock); | 103 | mutex_lock(&dev->lock); |
| 104 | 104 | ||
| @@ -113,7 +113,7 @@ static int nfcsim_dev_down(struct nfc_dev *nfc_dev) | |||
| 113 | { | 113 | { |
| 114 | struct nfcsim *dev = nfc_get_drvdata(nfc_dev); | 114 | struct nfcsim *dev = nfc_get_drvdata(nfc_dev); |
| 115 | 115 | ||
| 116 | DEV_DBG(dev, ""); | 116 | DEV_DBG(dev, "\n"); |
| 117 | 117 | ||
| 118 | mutex_lock(&dev->lock); | 118 | mutex_lock(&dev->lock); |
| 119 | 119 | ||
| @@ -143,7 +143,7 @@ static int nfcsim_dep_link_up(struct nfc_dev *nfc_dev, | |||
| 143 | 143 | ||
| 144 | remote_gb = nfc_get_local_general_bytes(peer->nfc_dev, &remote_gb_len); | 144 | remote_gb = nfc_get_local_general_bytes(peer->nfc_dev, &remote_gb_len); |
| 145 | if (!remote_gb) { | 145 | if (!remote_gb) { |
| 146 | DEV_ERR(peer, "Can't get remote general bytes"); | 146 | DEV_ERR(peer, "Can't get remote general bytes\n"); |
| 147 | 147 | ||
| 148 | mutex_unlock(&peer->lock); | 148 | mutex_unlock(&peer->lock); |
| 149 | return -EINVAL; | 149 | return -EINVAL; |
| @@ -155,7 +155,7 @@ static int nfcsim_dep_link_up(struct nfc_dev *nfc_dev, | |||
| 155 | 155 | ||
| 156 | rc = nfc_set_remote_general_bytes(nfc_dev, remote_gb, remote_gb_len); | 156 | rc = nfc_set_remote_general_bytes(nfc_dev, remote_gb, remote_gb_len); |
| 157 | if (rc) { | 157 | if (rc) { |
| 158 | DEV_ERR(dev, "Can't set remote general bytes"); | 158 | DEV_ERR(dev, "Can't set remote general bytes\n"); |
| 159 | mutex_unlock(&dev->lock); | 159 | mutex_unlock(&dev->lock); |
| 160 | return rc; | 160 | return rc; |
| 161 | } | 161 | } |
| @@ -172,7 +172,7 @@ static int nfcsim_dep_link_down(struct nfc_dev *nfc_dev) | |||
| 172 | { | 172 | { |
| 173 | struct nfcsim *dev = nfc_get_drvdata(nfc_dev); | 173 | struct nfcsim *dev = nfc_get_drvdata(nfc_dev); |
| 174 | 174 | ||
| 175 | DEV_DBG(dev, ""); | 175 | DEV_DBG(dev, "\n"); |
| 176 | 176 | ||
| 177 | nfcsim_cleanup_dev(dev, 0); | 177 | nfcsim_cleanup_dev(dev, 0); |
| 178 | 178 | ||
| @@ -188,7 +188,7 @@ static int nfcsim_start_poll(struct nfc_dev *nfc_dev, | |||
| 188 | mutex_lock(&dev->lock); | 188 | mutex_lock(&dev->lock); |
| 189 | 189 | ||
| 190 | if (dev->polling_mode != NFCSIM_POLL_NONE) { | 190 | if (dev->polling_mode != NFCSIM_POLL_NONE) { |
| 191 | DEV_ERR(dev, "Already in polling mode"); | 191 | DEV_ERR(dev, "Already in polling mode\n"); |
| 192 | rc = -EBUSY; | 192 | rc = -EBUSY; |
| 193 | goto exit; | 193 | goto exit; |
| 194 | } | 194 | } |
| @@ -200,7 +200,7 @@ static int nfcsim_start_poll(struct nfc_dev *nfc_dev, | |||
| 200 | dev->polling_mode |= NFCSIM_POLL_TARGET; | 200 | dev->polling_mode |= NFCSIM_POLL_TARGET; |
| 201 | 201 | ||
| 202 | if (dev->polling_mode == NFCSIM_POLL_NONE) { | 202 | if (dev->polling_mode == NFCSIM_POLL_NONE) { |
| 203 | DEV_ERR(dev, "Unsupported polling mode"); | 203 | DEV_ERR(dev, "Unsupported polling mode\n"); |
| 204 | rc = -EINVAL; | 204 | rc = -EINVAL; |
| 205 | goto exit; | 205 | goto exit; |
| 206 | } | 206 | } |
| @@ -210,7 +210,7 @@ static int nfcsim_start_poll(struct nfc_dev *nfc_dev, | |||
| 210 | 210 | ||
| 211 | queue_delayed_work(wq, &dev->poll_work, 0); | 211 | queue_delayed_work(wq, &dev->poll_work, 0); |
| 212 | 212 | ||
| 213 | DEV_DBG(dev, "Start polling: im: 0x%X, tm: 0x%X", im_protocols, | 213 | DEV_DBG(dev, "Start polling: im: 0x%X, tm: 0x%X\n", im_protocols, |
| 214 | tm_protocols); | 214 | tm_protocols); |
| 215 | 215 | ||
| 216 | rc = 0; | 216 | rc = 0; |
| @@ -224,7 +224,7 @@ static void nfcsim_stop_poll(struct nfc_dev *nfc_dev) | |||
| 224 | { | 224 | { |
| 225 | struct nfcsim *dev = nfc_get_drvdata(nfc_dev); | 225 | struct nfcsim *dev = nfc_get_drvdata(nfc_dev); |
| 226 | 226 | ||
| 227 | DEV_DBG(dev, "Stop poll"); | 227 | DEV_DBG(dev, "Stop poll\n"); |
| 228 | 228 | ||
| 229 | mutex_lock(&dev->lock); | 229 | mutex_lock(&dev->lock); |
| 230 | 230 | ||
| @@ -240,7 +240,7 @@ static int nfcsim_activate_target(struct nfc_dev *nfc_dev, | |||
| 240 | { | 240 | { |
| 241 | struct nfcsim *dev = nfc_get_drvdata(nfc_dev); | 241 | struct nfcsim *dev = nfc_get_drvdata(nfc_dev); |
| 242 | 242 | ||
| 243 | DEV_DBG(dev, ""); | 243 | DEV_DBG(dev, "\n"); |
| 244 | 244 | ||
| 245 | return -ENOTSUPP; | 245 | return -ENOTSUPP; |
| 246 | } | 246 | } |
| @@ -250,7 +250,7 @@ static void nfcsim_deactivate_target(struct nfc_dev *nfc_dev, | |||
| 250 | { | 250 | { |
| 251 | struct nfcsim *dev = nfc_get_drvdata(nfc_dev); | 251 | struct nfcsim *dev = nfc_get_drvdata(nfc_dev); |
| 252 | 252 | ||
| 253 | DEV_DBG(dev, ""); | 253 | DEV_DBG(dev, "\n"); |
| 254 | } | 254 | } |
| 255 | 255 | ||
| 256 | static void nfcsim_wq_recv(struct work_struct *work) | 256 | static void nfcsim_wq_recv(struct work_struct *work) |
| @@ -267,7 +267,7 @@ static void nfcsim_wq_recv(struct work_struct *work) | |||
| 267 | 267 | ||
| 268 | if (dev->initiator) { | 268 | if (dev->initiator) { |
| 269 | if (!dev->cb) { | 269 | if (!dev->cb) { |
| 270 | DEV_ERR(dev, "Null recv callback"); | 270 | DEV_ERR(dev, "Null recv callback\n"); |
| 271 | dev_kfree_skb(dev->clone_skb); | 271 | dev_kfree_skb(dev->clone_skb); |
| 272 | goto exit; | 272 | goto exit; |
| 273 | } | 273 | } |
| @@ -310,7 +310,7 @@ static int nfcsim_tx(struct nfc_dev *nfc_dev, struct nfc_target *target, | |||
| 310 | peer->clone_skb = skb_clone(skb, GFP_KERNEL); | 310 | peer->clone_skb = skb_clone(skb, GFP_KERNEL); |
| 311 | 311 | ||
| 312 | if (!peer->clone_skb) { | 312 | if (!peer->clone_skb) { |
| 313 | DEV_ERR(dev, "skb_clone failed"); | 313 | DEV_ERR(dev, "skb_clone failed\n"); |
| 314 | mutex_unlock(&peer->lock); | 314 | mutex_unlock(&peer->lock); |
| 315 | err = -ENOMEM; | 315 | err = -ENOMEM; |
| 316 | goto exit; | 316 | goto exit; |
| @@ -397,13 +397,13 @@ static void nfcsim_wq_poll(struct work_struct *work) | |||
| 397 | nfcsim_set_polling_mode(dev); | 397 | nfcsim_set_polling_mode(dev); |
| 398 | 398 | ||
| 399 | if (dev->curr_polling_mode == NFCSIM_POLL_NONE) { | 399 | if (dev->curr_polling_mode == NFCSIM_POLL_NONE) { |
| 400 | DEV_DBG(dev, "Not polling"); | 400 | DEV_DBG(dev, "Not polling\n"); |
| 401 | goto unlock; | 401 | goto unlock; |
| 402 | } | 402 | } |
| 403 | 403 | ||
| 404 | DEV_DBG(dev, "Polling as %s", | 404 | DEV_DBG(dev, "Polling as %s", |
| 405 | dev->curr_polling_mode == NFCSIM_POLL_INITIATOR ? | 405 | dev->curr_polling_mode == NFCSIM_POLL_INITIATOR ? |
| 406 | "initiator" : "target"); | 406 | "initiator\n" : "target\n"); |
| 407 | 407 | ||
| 408 | if (dev->curr_polling_mode == NFCSIM_POLL_TARGET) | 408 | if (dev->curr_polling_mode == NFCSIM_POLL_TARGET) |
| 409 | goto sched_work; | 409 | goto sched_work; |
diff --git a/drivers/nfc/nfcwilink.c b/drivers/nfc/nfcwilink.c index 59f95d8fc98c..71308645593f 100644 --- a/drivers/nfc/nfcwilink.c +++ b/drivers/nfc/nfcwilink.c | |||
| @@ -146,13 +146,11 @@ static int nfcwilink_get_bts_file_name(struct nfcwilink *drv, char *file_name) | |||
| 146 | unsigned long comp_ret; | 146 | unsigned long comp_ret; |
| 147 | int rc; | 147 | int rc; |
| 148 | 148 | ||
| 149 | nfc_dev_dbg(&drv->pdev->dev, "get_bts_file_name entry"); | ||
| 150 | |||
| 151 | skb = nfcwilink_skb_alloc(sizeof(struct nci_vs_nfcc_info_cmd), | 149 | skb = nfcwilink_skb_alloc(sizeof(struct nci_vs_nfcc_info_cmd), |
| 152 | GFP_KERNEL); | 150 | GFP_KERNEL); |
| 153 | if (!skb) { | 151 | if (!skb) { |
| 154 | nfc_dev_err(&drv->pdev->dev, | 152 | nfc_err(&drv->pdev->dev, |
| 155 | "no memory for nci_vs_nfcc_info_cmd"); | 153 | "no memory for nci_vs_nfcc_info_cmd\n"); |
| 156 | return -ENOMEM; | 154 | return -ENOMEM; |
| 157 | } | 155 | } |
| 158 | 156 | ||
| @@ -170,21 +168,19 @@ static int nfcwilink_get_bts_file_name(struct nfcwilink *drv, char *file_name) | |||
| 170 | 168 | ||
| 171 | comp_ret = wait_for_completion_timeout(&drv->completed, | 169 | comp_ret = wait_for_completion_timeout(&drv->completed, |
| 172 | msecs_to_jiffies(NFCWILINK_CMD_TIMEOUT)); | 170 | msecs_to_jiffies(NFCWILINK_CMD_TIMEOUT)); |
| 173 | nfc_dev_dbg(&drv->pdev->dev, "wait_for_completion_timeout returned %ld", | 171 | dev_dbg(&drv->pdev->dev, "wait_for_completion_timeout returned %ld\n", |
| 174 | comp_ret); | 172 | comp_ret); |
| 175 | if (comp_ret == 0) { | 173 | if (comp_ret == 0) { |
| 176 | nfc_dev_err(&drv->pdev->dev, | 174 | nfc_err(&drv->pdev->dev, |
| 177 | "timeout on wait_for_completion_timeout"); | 175 | "timeout on wait_for_completion_timeout\n"); |
| 178 | return -ETIMEDOUT; | 176 | return -ETIMEDOUT; |
| 179 | } | 177 | } |
| 180 | 178 | ||
| 181 | nfc_dev_dbg(&drv->pdev->dev, "nci_vs_nfcc_info_rsp: plen %d, status %d", | 179 | dev_dbg(&drv->pdev->dev, "nci_vs_nfcc_info_rsp: plen %d, status %d\n", |
| 182 | drv->nfcc_info.plen, | 180 | drv->nfcc_info.plen, drv->nfcc_info.status); |
| 183 | drv->nfcc_info.status); | ||
| 184 | 181 | ||
| 185 | if ((drv->nfcc_info.plen != 5) || (drv->nfcc_info.status != 0)) { | 182 | if ((drv->nfcc_info.plen != 5) || (drv->nfcc_info.status != 0)) { |
| 186 | nfc_dev_err(&drv->pdev->dev, | 183 | nfc_err(&drv->pdev->dev, "invalid nci_vs_nfcc_info_rsp\n"); |
| 187 | "invalid nci_vs_nfcc_info_rsp"); | ||
| 188 | return -EINVAL; | 184 | return -EINVAL; |
| 189 | } | 185 | } |
| 190 | 186 | ||
| @@ -195,7 +191,7 @@ static int nfcwilink_get_bts_file_name(struct nfcwilink *drv, char *file_name) | |||
| 195 | drv->nfcc_info.sw_ver_z, | 191 | drv->nfcc_info.sw_ver_z, |
| 196 | drv->nfcc_info.patch_id); | 192 | drv->nfcc_info.patch_id); |
| 197 | 193 | ||
| 198 | nfc_dev_info(&drv->pdev->dev, "nfcwilink FW file name: %s", file_name); | 194 | nfc_info(&drv->pdev->dev, "nfcwilink FW file name: %s\n", file_name); |
| 199 | 195 | ||
| 200 | return 0; | 196 | return 0; |
| 201 | } | 197 | } |
| @@ -207,15 +203,13 @@ static int nfcwilink_send_bts_cmd(struct nfcwilink *drv, __u8 *data, int len) | |||
| 207 | unsigned long comp_ret; | 203 | unsigned long comp_ret; |
| 208 | int rc; | 204 | int rc; |
| 209 | 205 | ||
| 210 | nfc_dev_dbg(&drv->pdev->dev, "send_bts_cmd entry"); | ||
| 211 | |||
| 212 | /* verify valid cmd for the NFC channel */ | 206 | /* verify valid cmd for the NFC channel */ |
| 213 | if ((len <= sizeof(struct nfcwilink_hdr)) || | 207 | if ((len <= sizeof(struct nfcwilink_hdr)) || |
| 214 | (len > BTS_FILE_CMD_MAX_LEN) || | 208 | (len > BTS_FILE_CMD_MAX_LEN) || |
| 215 | (hdr->chnl != NFCWILINK_CHNL) || | 209 | (hdr->chnl != NFCWILINK_CHNL) || |
| 216 | (hdr->opcode != NFCWILINK_OPCODE)) { | 210 | (hdr->opcode != NFCWILINK_OPCODE)) { |
| 217 | nfc_dev_err(&drv->pdev->dev, | 211 | nfc_err(&drv->pdev->dev, |
| 218 | "ignoring invalid bts cmd, len %d, chnl %d, opcode %d", | 212 | "ignoring invalid bts cmd, len %d, chnl %d, opcode %d\n", |
| 219 | len, hdr->chnl, hdr->opcode); | 213 | len, hdr->chnl, hdr->opcode); |
| 220 | return 0; | 214 | return 0; |
| 221 | } | 215 | } |
| @@ -226,7 +220,7 @@ static int nfcwilink_send_bts_cmd(struct nfcwilink *drv, __u8 *data, int len) | |||
| 226 | 220 | ||
| 227 | skb = nfcwilink_skb_alloc(len, GFP_KERNEL); | 221 | skb = nfcwilink_skb_alloc(len, GFP_KERNEL); |
| 228 | if (!skb) { | 222 | if (!skb) { |
| 229 | nfc_dev_err(&drv->pdev->dev, "no memory for bts cmd"); | 223 | nfc_err(&drv->pdev->dev, "no memory for bts cmd\n"); |
| 230 | return -ENOMEM; | 224 | return -ENOMEM; |
| 231 | } | 225 | } |
| 232 | 226 | ||
| @@ -238,11 +232,11 @@ static int nfcwilink_send_bts_cmd(struct nfcwilink *drv, __u8 *data, int len) | |||
| 238 | 232 | ||
| 239 | comp_ret = wait_for_completion_timeout(&drv->completed, | 233 | comp_ret = wait_for_completion_timeout(&drv->completed, |
| 240 | msecs_to_jiffies(NFCWILINK_CMD_TIMEOUT)); | 234 | msecs_to_jiffies(NFCWILINK_CMD_TIMEOUT)); |
| 241 | nfc_dev_dbg(&drv->pdev->dev, "wait_for_completion_timeout returned %ld", | 235 | dev_dbg(&drv->pdev->dev, "wait_for_completion_timeout returned %ld\n", |
| 242 | comp_ret); | 236 | comp_ret); |
| 243 | if (comp_ret == 0) { | 237 | if (comp_ret == 0) { |
| 244 | nfc_dev_err(&drv->pdev->dev, | 238 | nfc_err(&drv->pdev->dev, |
| 245 | "timeout on wait_for_completion_timeout"); | 239 | "timeout on wait_for_completion_timeout\n"); |
| 246 | return -ETIMEDOUT; | 240 | return -ETIMEDOUT; |
| 247 | } | 241 | } |
| 248 | 242 | ||
| @@ -257,8 +251,6 @@ static int nfcwilink_download_fw(struct nfcwilink *drv) | |||
| 257 | __u8 *ptr; | 251 | __u8 *ptr; |
| 258 | int len, rc; | 252 | int len, rc; |
| 259 | 253 | ||
| 260 | nfc_dev_dbg(&drv->pdev->dev, "download_fw entry"); | ||
| 261 | |||
| 262 | set_bit(NFCWILINK_FW_DOWNLOAD, &drv->flags); | 254 | set_bit(NFCWILINK_FW_DOWNLOAD, &drv->flags); |
| 263 | 255 | ||
| 264 | rc = nfcwilink_get_bts_file_name(drv, file_name); | 256 | rc = nfcwilink_get_bts_file_name(drv, file_name); |
| @@ -267,7 +259,7 @@ static int nfcwilink_download_fw(struct nfcwilink *drv) | |||
| 267 | 259 | ||
| 268 | rc = request_firmware(&fw, file_name, &drv->pdev->dev); | 260 | rc = request_firmware(&fw, file_name, &drv->pdev->dev); |
| 269 | if (rc) { | 261 | if (rc) { |
| 270 | nfc_dev_err(&drv->pdev->dev, "request_firmware failed %d", rc); | 262 | nfc_err(&drv->pdev->dev, "request_firmware failed %d\n", rc); |
| 271 | 263 | ||
| 272 | /* if the file is not found, don't exit with failure */ | 264 | /* if the file is not found, don't exit with failure */ |
| 273 | if (rc == -ENOENT) | 265 | if (rc == -ENOENT) |
| @@ -280,14 +272,14 @@ static int nfcwilink_download_fw(struct nfcwilink *drv) | |||
| 280 | ptr = (__u8 *)fw->data; | 272 | ptr = (__u8 *)fw->data; |
| 281 | 273 | ||
| 282 | if ((len == 0) || (ptr == NULL)) { | 274 | if ((len == 0) || (ptr == NULL)) { |
| 283 | nfc_dev_dbg(&drv->pdev->dev, | 275 | dev_dbg(&drv->pdev->dev, |
| 284 | "request_firmware returned size %d", len); | 276 | "request_firmware returned size %d\n", len); |
| 285 | goto release_fw; | 277 | goto release_fw; |
| 286 | } | 278 | } |
| 287 | 279 | ||
| 288 | if (__le32_to_cpu(((struct bts_file_hdr *)ptr)->magic) != | 280 | if (__le32_to_cpu(((struct bts_file_hdr *)ptr)->magic) != |
| 289 | BTS_FILE_HDR_MAGIC) { | 281 | BTS_FILE_HDR_MAGIC) { |
| 290 | nfc_dev_err(&drv->pdev->dev, "wrong bts magic number"); | 282 | nfc_err(&drv->pdev->dev, "wrong bts magic number\n"); |
| 291 | rc = -EINVAL; | 283 | rc = -EINVAL; |
| 292 | goto release_fw; | 284 | goto release_fw; |
| 293 | } | 285 | } |
| @@ -302,8 +294,8 @@ static int nfcwilink_download_fw(struct nfcwilink *drv) | |||
| 302 | action_len = | 294 | action_len = |
| 303 | __le16_to_cpu(((struct bts_file_action *)ptr)->len); | 295 | __le16_to_cpu(((struct bts_file_action *)ptr)->len); |
| 304 | 296 | ||
| 305 | nfc_dev_dbg(&drv->pdev->dev, "bts_file_action type %d, len %d", | 297 | dev_dbg(&drv->pdev->dev, "bts_file_action type %d, len %d\n", |
| 306 | action_type, action_len); | 298 | action_type, action_len); |
| 307 | 299 | ||
| 308 | switch (action_type) { | 300 | switch (action_type) { |
| 309 | case BTS_FILE_ACTION_TYPE_SEND_CMD: | 301 | case BTS_FILE_ACTION_TYPE_SEND_CMD: |
| @@ -333,8 +325,6 @@ static void nfcwilink_register_complete(void *priv_data, char data) | |||
| 333 | { | 325 | { |
| 334 | struct nfcwilink *drv = priv_data; | 326 | struct nfcwilink *drv = priv_data; |
| 335 | 327 | ||
| 336 | nfc_dev_dbg(&drv->pdev->dev, "register_complete entry"); | ||
| 337 | |||
| 338 | /* store ST registration status */ | 328 | /* store ST registration status */ |
| 339 | drv->st_register_cb_status = data; | 329 | drv->st_register_cb_status = data; |
| 340 | 330 | ||
| @@ -356,7 +346,7 @@ static long nfcwilink_receive(void *priv_data, struct sk_buff *skb) | |||
| 356 | return -EFAULT; | 346 | return -EFAULT; |
| 357 | } | 347 | } |
| 358 | 348 | ||
| 359 | nfc_dev_dbg(&drv->pdev->dev, "receive entry, len %d", skb->len); | 349 | dev_dbg(&drv->pdev->dev, "receive entry, len %d\n", skb->len); |
| 360 | 350 | ||
| 361 | /* strip the ST header | 351 | /* strip the ST header |
| 362 | (apart for the chnl byte, which is not received in the hdr) */ | 352 | (apart for the chnl byte, which is not received in the hdr) */ |
| @@ -370,7 +360,7 @@ static long nfcwilink_receive(void *priv_data, struct sk_buff *skb) | |||
| 370 | /* Forward skb to NCI core layer */ | 360 | /* Forward skb to NCI core layer */ |
| 371 | rc = nci_recv_frame(drv->ndev, skb); | 361 | rc = nci_recv_frame(drv->ndev, skb); |
| 372 | if (rc < 0) { | 362 | if (rc < 0) { |
| 373 | nfc_dev_err(&drv->pdev->dev, "nci_recv_frame failed %d", rc); | 363 | nfc_err(&drv->pdev->dev, "nci_recv_frame failed %d\n", rc); |
| 374 | return rc; | 364 | return rc; |
| 375 | } | 365 | } |
| 376 | 366 | ||
| @@ -396,8 +386,6 @@ static int nfcwilink_open(struct nci_dev *ndev) | |||
| 396 | unsigned long comp_ret; | 386 | unsigned long comp_ret; |
| 397 | int rc; | 387 | int rc; |
| 398 | 388 | ||
| 399 | nfc_dev_dbg(&drv->pdev->dev, "open entry"); | ||
| 400 | |||
| 401 | if (test_and_set_bit(NFCWILINK_RUNNING, &drv->flags)) { | 389 | if (test_and_set_bit(NFCWILINK_RUNNING, &drv->flags)) { |
| 402 | rc = -EBUSY; | 390 | rc = -EBUSY; |
| 403 | goto exit; | 391 | goto exit; |
| @@ -415,9 +403,9 @@ static int nfcwilink_open(struct nci_dev *ndev) | |||
| 415 | &drv->completed, | 403 | &drv->completed, |
| 416 | msecs_to_jiffies(NFCWILINK_REGISTER_TIMEOUT)); | 404 | msecs_to_jiffies(NFCWILINK_REGISTER_TIMEOUT)); |
| 417 | 405 | ||
| 418 | nfc_dev_dbg(&drv->pdev->dev, | 406 | dev_dbg(&drv->pdev->dev, |
| 419 | "wait_for_completion_timeout returned %ld", | 407 | "wait_for_completion_timeout returned %ld\n", |
| 420 | comp_ret); | 408 | comp_ret); |
| 421 | 409 | ||
| 422 | if (comp_ret == 0) { | 410 | if (comp_ret == 0) { |
| 423 | /* timeout */ | 411 | /* timeout */ |
| @@ -425,13 +413,12 @@ static int nfcwilink_open(struct nci_dev *ndev) | |||
| 425 | goto clear_exit; | 413 | goto clear_exit; |
| 426 | } else if (drv->st_register_cb_status != 0) { | 414 | } else if (drv->st_register_cb_status != 0) { |
| 427 | rc = drv->st_register_cb_status; | 415 | rc = drv->st_register_cb_status; |
| 428 | nfc_dev_err(&drv->pdev->dev, | 416 | nfc_err(&drv->pdev->dev, |
| 429 | "st_register_cb failed %d", rc); | 417 | "st_register_cb failed %d\n", rc); |
| 430 | goto clear_exit; | 418 | goto clear_exit; |
| 431 | } | 419 | } |
| 432 | } else { | 420 | } else { |
| 433 | nfc_dev_err(&drv->pdev->dev, | 421 | nfc_err(&drv->pdev->dev, "st_register failed %d\n", rc); |
| 434 | "st_register failed %d", rc); | ||
| 435 | goto clear_exit; | 422 | goto clear_exit; |
| 436 | } | 423 | } |
| 437 | } | 424 | } |
| @@ -441,8 +428,8 @@ static int nfcwilink_open(struct nci_dev *ndev) | |||
| 441 | drv->st_write = nfcwilink_proto.write; | 428 | drv->st_write = nfcwilink_proto.write; |
| 442 | 429 | ||
| 443 | if (nfcwilink_download_fw(drv)) { | 430 | if (nfcwilink_download_fw(drv)) { |
| 444 | nfc_dev_err(&drv->pdev->dev, "nfcwilink_download_fw failed %d", | 431 | nfc_err(&drv->pdev->dev, "nfcwilink_download_fw failed %d\n", |
| 445 | rc); | 432 | rc); |
| 446 | /* open should succeed, even if the FW download failed */ | 433 | /* open should succeed, even if the FW download failed */ |
| 447 | } | 434 | } |
| 448 | 435 | ||
| @@ -460,14 +447,12 @@ static int nfcwilink_close(struct nci_dev *ndev) | |||
| 460 | struct nfcwilink *drv = nci_get_drvdata(ndev); | 447 | struct nfcwilink *drv = nci_get_drvdata(ndev); |
| 461 | int rc; | 448 | int rc; |
| 462 | 449 | ||
| 463 | nfc_dev_dbg(&drv->pdev->dev, "close entry"); | ||
| 464 | |||
| 465 | if (!test_and_clear_bit(NFCWILINK_RUNNING, &drv->flags)) | 450 | if (!test_and_clear_bit(NFCWILINK_RUNNING, &drv->flags)) |
| 466 | return 0; | 451 | return 0; |
| 467 | 452 | ||
| 468 | rc = st_unregister(&nfcwilink_proto); | 453 | rc = st_unregister(&nfcwilink_proto); |
| 469 | if (rc) | 454 | if (rc) |
| 470 | nfc_dev_err(&drv->pdev->dev, "st_unregister failed %d", rc); | 455 | nfc_err(&drv->pdev->dev, "st_unregister failed %d\n", rc); |
| 471 | 456 | ||
| 472 | drv->st_write = NULL; | 457 | drv->st_write = NULL; |
| 473 | 458 | ||
| @@ -480,7 +465,7 @@ static int nfcwilink_send(struct nci_dev *ndev, struct sk_buff *skb) | |||
| 480 | struct nfcwilink_hdr hdr = {NFCWILINK_CHNL, NFCWILINK_OPCODE, 0x0000}; | 465 | struct nfcwilink_hdr hdr = {NFCWILINK_CHNL, NFCWILINK_OPCODE, 0x0000}; |
| 481 | long len; | 466 | long len; |
| 482 | 467 | ||
| 483 | nfc_dev_dbg(&drv->pdev->dev, "send entry, len %d", skb->len); | 468 | dev_dbg(&drv->pdev->dev, "send entry, len %d\n", skb->len); |
| 484 | 469 | ||
| 485 | if (!test_bit(NFCWILINK_RUNNING, &drv->flags)) { | 470 | if (!test_bit(NFCWILINK_RUNNING, &drv->flags)) { |
| 486 | kfree_skb(skb); | 471 | kfree_skb(skb); |
| @@ -498,7 +483,7 @@ static int nfcwilink_send(struct nci_dev *ndev, struct sk_buff *skb) | |||
| 498 | len = drv->st_write(skb); | 483 | len = drv->st_write(skb); |
| 499 | if (len < 0) { | 484 | if (len < 0) { |
| 500 | kfree_skb(skb); | 485 | kfree_skb(skb); |
| 501 | nfc_dev_err(&drv->pdev->dev, "st_write failed %ld", len); | 486 | nfc_err(&drv->pdev->dev, "st_write failed %ld\n", len); |
| 502 | return -EFAULT; | 487 | return -EFAULT; |
| 503 | } | 488 | } |
| 504 | 489 | ||
| @@ -517,8 +502,6 @@ static int nfcwilink_probe(struct platform_device *pdev) | |||
| 517 | int rc; | 502 | int rc; |
| 518 | __u32 protocols; | 503 | __u32 protocols; |
| 519 | 504 | ||
| 520 | nfc_dev_dbg(&pdev->dev, "probe entry"); | ||
| 521 | |||
| 522 | drv = devm_kzalloc(&pdev->dev, sizeof(struct nfcwilink), GFP_KERNEL); | 505 | drv = devm_kzalloc(&pdev->dev, sizeof(struct nfcwilink), GFP_KERNEL); |
| 523 | if (!drv) { | 506 | if (!drv) { |
| 524 | rc = -ENOMEM; | 507 | rc = -ENOMEM; |
| @@ -538,7 +521,7 @@ static int nfcwilink_probe(struct platform_device *pdev) | |||
| 538 | NFCWILINK_HDR_LEN, | 521 | NFCWILINK_HDR_LEN, |
| 539 | 0); | 522 | 0); |
| 540 | if (!drv->ndev) { | 523 | if (!drv->ndev) { |
| 541 | nfc_dev_err(&pdev->dev, "nci_allocate_device failed"); | 524 | nfc_err(&pdev->dev, "nci_allocate_device failed\n"); |
| 542 | rc = -ENOMEM; | 525 | rc = -ENOMEM; |
| 543 | goto exit; | 526 | goto exit; |
| 544 | } | 527 | } |
| @@ -548,7 +531,7 @@ static int nfcwilink_probe(struct platform_device *pdev) | |||
| 548 | 531 | ||
| 549 | rc = nci_register_device(drv->ndev); | 532 | rc = nci_register_device(drv->ndev); |
| 550 | if (rc < 0) { | 533 | if (rc < 0) { |
| 551 | nfc_dev_err(&pdev->dev, "nci_register_device failed %d", rc); | 534 | nfc_err(&pdev->dev, "nci_register_device failed %d\n", rc); |
| 552 | goto free_dev_exit; | 535 | goto free_dev_exit; |
| 553 | } | 536 | } |
| 554 | 537 | ||
| @@ -568,8 +551,6 @@ static int nfcwilink_remove(struct platform_device *pdev) | |||
| 568 | struct nfcwilink *drv = dev_get_drvdata(&pdev->dev); | 551 | struct nfcwilink *drv = dev_get_drvdata(&pdev->dev); |
| 569 | struct nci_dev *ndev; | 552 | struct nci_dev *ndev; |
| 570 | 553 | ||
| 571 | nfc_dev_dbg(&pdev->dev, "remove entry"); | ||
| 572 | |||
| 573 | if (!drv) | 554 | if (!drv) |
| 574 | return -EFAULT; | 555 | return -EFAULT; |
| 575 | 556 | ||
| @@ -578,8 +559,6 @@ static int nfcwilink_remove(struct platform_device *pdev) | |||
| 578 | nci_unregister_device(ndev); | 559 | nci_unregister_device(ndev); |
| 579 | nci_free_device(ndev); | 560 | nci_free_device(ndev); |
| 580 | 561 | ||
| 581 | dev_set_drvdata(&pdev->dev, NULL); | ||
| 582 | |||
| 583 | return 0; | 562 | return 0; |
| 584 | } | 563 | } |
| 585 | 564 | ||
diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index 5df730be88a3..2daf04c07338 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c | |||
| @@ -150,6 +150,7 @@ MODULE_DEVICE_TABLE(usb, pn533_table); | |||
| 150 | #define PN533_CMD_TG_INIT_AS_TARGET 0x8c | 150 | #define PN533_CMD_TG_INIT_AS_TARGET 0x8c |
| 151 | #define PN533_CMD_TG_GET_DATA 0x86 | 151 | #define PN533_CMD_TG_GET_DATA 0x86 |
| 152 | #define PN533_CMD_TG_SET_DATA 0x8e | 152 | #define PN533_CMD_TG_SET_DATA 0x8e |
| 153 | #define PN533_CMD_TG_SET_META_DATA 0x94 | ||
| 153 | #define PN533_CMD_UNDEF 0xff | 154 | #define PN533_CMD_UNDEF 0xff |
| 154 | 155 | ||
| 155 | #define PN533_CMD_RESPONSE(cmd) (cmd + 1) | 156 | #define PN533_CMD_RESPONSE(cmd) (cmd + 1) |
| @@ -373,6 +374,8 @@ struct pn533 { | |||
| 373 | struct delayed_work poll_work; | 374 | struct delayed_work poll_work; |
| 374 | struct work_struct mi_rx_work; | 375 | struct work_struct mi_rx_work; |
| 375 | struct work_struct mi_tx_work; | 376 | struct work_struct mi_tx_work; |
| 377 | struct work_struct mi_tm_rx_work; | ||
| 378 | struct work_struct mi_tm_tx_work; | ||
| 376 | struct work_struct tg_work; | 379 | struct work_struct tg_work; |
| 377 | struct work_struct rf_work; | 380 | struct work_struct rf_work; |
| 378 | 381 | ||
| @@ -387,6 +390,7 @@ struct pn533 { | |||
| 387 | struct pn533_poll_modulations *poll_mod_active[PN533_POLL_MOD_MAX + 1]; | 390 | struct pn533_poll_modulations *poll_mod_active[PN533_POLL_MOD_MAX + 1]; |
| 388 | u8 poll_mod_count; | 391 | u8 poll_mod_count; |
| 389 | u8 poll_mod_curr; | 392 | u8 poll_mod_curr; |
| 393 | u8 poll_dep; | ||
| 390 | u32 poll_protocols; | 394 | u32 poll_protocols; |
| 391 | u32 listen_protocols; | 395 | u32 listen_protocols; |
| 392 | struct timer_list listen_timer; | 396 | struct timer_list listen_timer; |
| @@ -722,32 +726,32 @@ static void pn533_recv_response(struct urb *urb) | |||
| 722 | break; /* success */ | 726 | break; /* success */ |
| 723 | case -ECONNRESET: | 727 | case -ECONNRESET: |
| 724 | case -ENOENT: | 728 | case -ENOENT: |
| 725 | nfc_dev_dbg(&dev->interface->dev, | 729 | dev_dbg(&dev->interface->dev, |
| 726 | "The urb has been canceled (status %d)", | 730 | "The urb has been canceled (status %d)\n", |
| 727 | urb->status); | 731 | urb->status); |
| 728 | goto sched_wq; | 732 | goto sched_wq; |
| 729 | case -ESHUTDOWN: | 733 | case -ESHUTDOWN: |
| 730 | default: | 734 | default: |
| 731 | nfc_dev_err(&dev->interface->dev, | 735 | nfc_err(&dev->interface->dev, |
| 732 | "Urb failure (status %d)", urb->status); | 736 | "Urb failure (status %d)\n", urb->status); |
| 733 | goto sched_wq; | 737 | goto sched_wq; |
| 734 | } | 738 | } |
| 735 | 739 | ||
| 736 | in_frame = dev->in_urb->transfer_buffer; | 740 | in_frame = dev->in_urb->transfer_buffer; |
| 737 | 741 | ||
| 738 | nfc_dev_dbg(&dev->interface->dev, "Received a frame."); | 742 | dev_dbg(&dev->interface->dev, "Received a frame\n"); |
| 739 | print_hex_dump_debug("PN533 RX: ", DUMP_PREFIX_NONE, 16, 1, in_frame, | 743 | print_hex_dump_debug("PN533 RX: ", DUMP_PREFIX_NONE, 16, 1, in_frame, |
| 740 | dev->ops->rx_frame_size(in_frame), false); | 744 | dev->ops->rx_frame_size(in_frame), false); |
| 741 | 745 | ||
| 742 | if (!dev->ops->rx_is_frame_valid(in_frame, dev)) { | 746 | if (!dev->ops->rx_is_frame_valid(in_frame, dev)) { |
| 743 | nfc_dev_err(&dev->interface->dev, "Received an invalid frame"); | 747 | nfc_err(&dev->interface->dev, "Received an invalid frame\n"); |
| 744 | cmd->status = -EIO; | 748 | cmd->status = -EIO; |
| 745 | goto sched_wq; | 749 | goto sched_wq; |
| 746 | } | 750 | } |
| 747 | 751 | ||
| 748 | if (!pn533_rx_frame_is_cmd_response(dev, in_frame)) { | 752 | if (!pn533_rx_frame_is_cmd_response(dev, in_frame)) { |
| 749 | nfc_dev_err(&dev->interface->dev, | 753 | nfc_err(&dev->interface->dev, |
| 750 | "It it not the response to the last command"); | 754 | "It it not the response to the last command\n"); |
| 751 | cmd->status = -EIO; | 755 | cmd->status = -EIO; |
| 752 | goto sched_wq; | 756 | goto sched_wq; |
| 753 | } | 757 | } |
| @@ -777,29 +781,29 @@ static void pn533_recv_ack(struct urb *urb) | |||
| 777 | break; /* success */ | 781 | break; /* success */ |
| 778 | case -ECONNRESET: | 782 | case -ECONNRESET: |
| 779 | case -ENOENT: | 783 | case -ENOENT: |
| 780 | nfc_dev_dbg(&dev->interface->dev, | 784 | dev_dbg(&dev->interface->dev, |
| 781 | "The urb has been stopped (status %d)", | 785 | "The urb has been stopped (status %d)\n", |
| 782 | urb->status); | 786 | urb->status); |
| 783 | goto sched_wq; | 787 | goto sched_wq; |
| 784 | case -ESHUTDOWN: | 788 | case -ESHUTDOWN: |
| 785 | default: | 789 | default: |
| 786 | nfc_dev_err(&dev->interface->dev, | 790 | nfc_err(&dev->interface->dev, |
| 787 | "Urb failure (status %d)", urb->status); | 791 | "Urb failure (status %d)\n", urb->status); |
| 788 | goto sched_wq; | 792 | goto sched_wq; |
| 789 | } | 793 | } |
| 790 | 794 | ||
| 791 | in_frame = dev->in_urb->transfer_buffer; | 795 | in_frame = dev->in_urb->transfer_buffer; |
| 792 | 796 | ||
| 793 | if (!pn533_std_rx_frame_is_ack(in_frame)) { | 797 | if (!pn533_std_rx_frame_is_ack(in_frame)) { |
| 794 | nfc_dev_err(&dev->interface->dev, "Received an invalid ack"); | 798 | nfc_err(&dev->interface->dev, "Received an invalid ack\n"); |
| 795 | cmd->status = -EIO; | 799 | cmd->status = -EIO; |
| 796 | goto sched_wq; | 800 | goto sched_wq; |
| 797 | } | 801 | } |
| 798 | 802 | ||
| 799 | rc = pn533_submit_urb_for_response(dev, GFP_ATOMIC); | 803 | rc = pn533_submit_urb_for_response(dev, GFP_ATOMIC); |
| 800 | if (rc) { | 804 | if (rc) { |
| 801 | nfc_dev_err(&dev->interface->dev, | 805 | nfc_err(&dev->interface->dev, |
| 802 | "usb_submit_urb failed with result %d", rc); | 806 | "usb_submit_urb failed with result %d\n", rc); |
| 803 | cmd->status = rc; | 807 | cmd->status = rc; |
| 804 | goto sched_wq; | 808 | goto sched_wq; |
| 805 | } | 809 | } |
| @@ -823,8 +827,6 @@ static int pn533_send_ack(struct pn533 *dev, gfp_t flags) | |||
| 823 | /* spec 7.1.1.3: Preamble, SoPC (2), ACK Code (2), Postamble */ | 827 | /* spec 7.1.1.3: Preamble, SoPC (2), ACK Code (2), Postamble */ |
| 824 | int rc; | 828 | int rc; |
| 825 | 829 | ||
| 826 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | ||
| 827 | |||
| 828 | dev->out_urb->transfer_buffer = ack; | 830 | dev->out_urb->transfer_buffer = ack; |
| 829 | dev->out_urb->transfer_buffer_length = sizeof(ack); | 831 | dev->out_urb->transfer_buffer_length = sizeof(ack); |
| 830 | rc = usb_submit_urb(dev->out_urb, flags); | 832 | rc = usb_submit_urb(dev->out_urb, flags); |
| @@ -927,7 +929,7 @@ static int __pn533_send_async(struct pn533 *dev, u8 cmd_code, | |||
| 927 | struct pn533_cmd *cmd; | 929 | struct pn533_cmd *cmd; |
| 928 | int rc = 0; | 930 | int rc = 0; |
| 929 | 931 | ||
| 930 | nfc_dev_dbg(&dev->interface->dev, "Sending command 0x%x", cmd_code); | 932 | dev_dbg(&dev->interface->dev, "Sending command 0x%x\n", cmd_code); |
| 931 | 933 | ||
| 932 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 934 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
| 933 | if (!cmd) | 935 | if (!cmd) |
| @@ -954,8 +956,8 @@ static int __pn533_send_async(struct pn533 *dev, u8 cmd_code, | |||
| 954 | goto unlock; | 956 | goto unlock; |
| 955 | } | 957 | } |
| 956 | 958 | ||
| 957 | nfc_dev_dbg(&dev->interface->dev, "%s Queueing command 0x%x", __func__, | 959 | dev_dbg(&dev->interface->dev, "%s Queueing command 0x%x\n", |
| 958 | cmd_code); | 960 | __func__, cmd_code); |
| 959 | 961 | ||
| 960 | INIT_LIST_HEAD(&cmd->queue); | 962 | INIT_LIST_HEAD(&cmd->queue); |
| 961 | list_add_tail(&cmd->queue, &dev->cmd_queue); | 963 | list_add_tail(&cmd->queue, &dev->cmd_queue); |
| @@ -1168,14 +1170,14 @@ static void pn533_send_complete(struct urb *urb) | |||
| 1168 | break; /* success */ | 1170 | break; /* success */ |
| 1169 | case -ECONNRESET: | 1171 | case -ECONNRESET: |
| 1170 | case -ENOENT: | 1172 | case -ENOENT: |
| 1171 | nfc_dev_dbg(&dev->interface->dev, | 1173 | dev_dbg(&dev->interface->dev, |
| 1172 | "The urb has been stopped (status %d)", | 1174 | "The urb has been stopped (status %d)\n", |
| 1173 | urb->status); | 1175 | urb->status); |
| 1174 | break; | 1176 | break; |
| 1175 | case -ESHUTDOWN: | 1177 | case -ESHUTDOWN: |
| 1176 | default: | 1178 | default: |
| 1177 | nfc_dev_err(&dev->interface->dev, | 1179 | nfc_err(&dev->interface->dev, "Urb failure (status %d)\n", |
| 1178 | "Urb failure (status %d)", urb->status); | 1180 | urb->status); |
| 1179 | } | 1181 | } |
| 1180 | } | 1182 | } |
| 1181 | 1183 | ||
| @@ -1452,8 +1454,8 @@ static int pn533_target_found(struct pn533 *dev, u8 tg, u8 *tgdata, | |||
| 1452 | struct nfc_target nfc_tgt; | 1454 | struct nfc_target nfc_tgt; |
| 1453 | int rc; | 1455 | int rc; |
| 1454 | 1456 | ||
| 1455 | nfc_dev_dbg(&dev->interface->dev, "%s - modulation=%d", __func__, | 1457 | dev_dbg(&dev->interface->dev, "%s: modulation=%d\n", |
| 1456 | dev->poll_mod_curr); | 1458 | __func__, dev->poll_mod_curr); |
| 1457 | 1459 | ||
| 1458 | if (tg != 1) | 1460 | if (tg != 1) |
| 1459 | return -EPROTO; | 1461 | return -EPROTO; |
| @@ -1475,8 +1477,8 @@ static int pn533_target_found(struct pn533 *dev, u8 tg, u8 *tgdata, | |||
| 1475 | rc = pn533_target_found_type_b(&nfc_tgt, tgdata, tgdata_len); | 1477 | rc = pn533_target_found_type_b(&nfc_tgt, tgdata, tgdata_len); |
| 1476 | break; | 1478 | break; |
| 1477 | default: | 1479 | default: |
| 1478 | nfc_dev_err(&dev->interface->dev, | 1480 | nfc_err(&dev->interface->dev, |
| 1479 | "Unknown current poll modulation"); | 1481 | "Unknown current poll modulation\n"); |
| 1480 | return -EPROTO; | 1482 | return -EPROTO; |
| 1481 | } | 1483 | } |
| 1482 | 1484 | ||
| @@ -1484,14 +1486,14 @@ static int pn533_target_found(struct pn533 *dev, u8 tg, u8 *tgdata, | |||
| 1484 | return rc; | 1486 | return rc; |
| 1485 | 1487 | ||
| 1486 | if (!(nfc_tgt.supported_protocols & dev->poll_protocols)) { | 1488 | if (!(nfc_tgt.supported_protocols & dev->poll_protocols)) { |
| 1487 | nfc_dev_dbg(&dev->interface->dev, | 1489 | dev_dbg(&dev->interface->dev, |
| 1488 | "The Tg found doesn't have the desired protocol"); | 1490 | "The Tg found doesn't have the desired protocol\n"); |
| 1489 | return -EAGAIN; | 1491 | return -EAGAIN; |
| 1490 | } | 1492 | } |
| 1491 | 1493 | ||
| 1492 | nfc_dev_dbg(&dev->interface->dev, | 1494 | dev_dbg(&dev->interface->dev, |
| 1493 | "Target found - supported protocols: 0x%x", | 1495 | "Target found - supported protocols: 0x%x\n", |
| 1494 | nfc_tgt.supported_protocols); | 1496 | nfc_tgt.supported_protocols); |
| 1495 | 1497 | ||
| 1496 | dev->tgt_available_prots = nfc_tgt.supported_protocols; | 1498 | dev->tgt_available_prots = nfc_tgt.supported_protocols; |
| 1497 | 1499 | ||
| @@ -1548,7 +1550,8 @@ static int pn533_start_poll_complete(struct pn533 *dev, struct sk_buff *resp) | |||
| 1548 | u8 nbtg, tg, *tgdata; | 1550 | u8 nbtg, tg, *tgdata; |
| 1549 | int rc, tgdata_len; | 1551 | int rc, tgdata_len; |
| 1550 | 1552 | ||
| 1551 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 1553 | /* Toggle the DEP polling */ |
| 1554 | dev->poll_dep = 1; | ||
| 1552 | 1555 | ||
| 1553 | nbtg = resp->data[0]; | 1556 | nbtg = resp->data[0]; |
| 1554 | tg = resp->data[1]; | 1557 | tg = resp->data[1]; |
| @@ -1624,37 +1627,130 @@ static struct sk_buff *pn533_alloc_poll_tg_frame(struct pn533 *dev) | |||
| 1624 | 1627 | ||
| 1625 | #define PN533_CMD_DATAEXCH_HEAD_LEN 1 | 1628 | #define PN533_CMD_DATAEXCH_HEAD_LEN 1 |
| 1626 | #define PN533_CMD_DATAEXCH_DATA_MAXLEN 262 | 1629 | #define PN533_CMD_DATAEXCH_DATA_MAXLEN 262 |
| 1630 | static void pn533_wq_tm_mi_recv(struct work_struct *work); | ||
| 1631 | static struct sk_buff *pn533_build_response(struct pn533 *dev); | ||
| 1632 | |||
| 1627 | static int pn533_tm_get_data_complete(struct pn533 *dev, void *arg, | 1633 | static int pn533_tm_get_data_complete(struct pn533 *dev, void *arg, |
| 1628 | struct sk_buff *resp) | 1634 | struct sk_buff *resp) |
| 1629 | { | 1635 | { |
| 1630 | u8 status; | 1636 | struct sk_buff *skb; |
| 1637 | u8 status, ret, mi; | ||
| 1638 | int rc; | ||
| 1631 | 1639 | ||
| 1632 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 1640 | dev_dbg(&dev->interface->dev, "%s\n", __func__); |
| 1633 | 1641 | ||
| 1634 | if (IS_ERR(resp)) | 1642 | if (IS_ERR(resp)) { |
| 1643 | skb_queue_purge(&dev->resp_q); | ||
| 1635 | return PTR_ERR(resp); | 1644 | return PTR_ERR(resp); |
| 1645 | } | ||
| 1636 | 1646 | ||
| 1637 | status = resp->data[0]; | 1647 | status = resp->data[0]; |
| 1648 | |||
| 1649 | ret = status & PN533_CMD_RET_MASK; | ||
| 1650 | mi = status & PN533_CMD_MI_MASK; | ||
| 1651 | |||
| 1638 | skb_pull(resp, sizeof(status)); | 1652 | skb_pull(resp, sizeof(status)); |
| 1639 | 1653 | ||
| 1640 | if (status != 0) { | 1654 | if (ret != PN533_CMD_RET_SUCCESS) { |
| 1641 | nfc_tm_deactivated(dev->nfc_dev); | 1655 | rc = -EIO; |
| 1642 | dev->tgt_mode = 0; | 1656 | goto error; |
| 1643 | dev_kfree_skb(resp); | ||
| 1644 | return 0; | ||
| 1645 | } | 1657 | } |
| 1646 | 1658 | ||
| 1647 | return nfc_tm_data_received(dev->nfc_dev, resp); | 1659 | skb_queue_tail(&dev->resp_q, resp); |
| 1660 | |||
| 1661 | if (mi) { | ||
| 1662 | queue_work(dev->wq, &dev->mi_tm_rx_work); | ||
| 1663 | return -EINPROGRESS; | ||
| 1664 | } | ||
| 1665 | |||
| 1666 | skb = pn533_build_response(dev); | ||
| 1667 | if (!skb) { | ||
| 1668 | rc = -EIO; | ||
| 1669 | goto error; | ||
| 1670 | } | ||
| 1671 | |||
| 1672 | return nfc_tm_data_received(dev->nfc_dev, skb); | ||
| 1673 | |||
| 1674 | error: | ||
| 1675 | nfc_tm_deactivated(dev->nfc_dev); | ||
| 1676 | dev->tgt_mode = 0; | ||
| 1677 | skb_queue_purge(&dev->resp_q); | ||
| 1678 | dev_kfree_skb(resp); | ||
| 1679 | |||
| 1680 | return rc; | ||
| 1681 | } | ||
| 1682 | |||
| 1683 | static void pn533_wq_tm_mi_recv(struct work_struct *work) | ||
| 1684 | { | ||
| 1685 | struct pn533 *dev = container_of(work, struct pn533, mi_tm_rx_work); | ||
| 1686 | struct sk_buff *skb; | ||
| 1687 | int rc; | ||
| 1688 | |||
| 1689 | dev_dbg(&dev->interface->dev, "%s\n", __func__); | ||
| 1690 | |||
| 1691 | skb = pn533_alloc_skb(dev, 0); | ||
| 1692 | if (!skb) | ||
| 1693 | return; | ||
| 1694 | |||
| 1695 | rc = pn533_send_cmd_direct_async(dev, | ||
| 1696 | PN533_CMD_TG_GET_DATA, | ||
| 1697 | skb, | ||
| 1698 | pn533_tm_get_data_complete, | ||
| 1699 | NULL); | ||
| 1700 | |||
| 1701 | if (rc < 0) | ||
| 1702 | dev_kfree_skb(skb); | ||
| 1703 | |||
| 1704 | return; | ||
| 1705 | } | ||
| 1706 | |||
| 1707 | static int pn533_tm_send_complete(struct pn533 *dev, void *arg, | ||
| 1708 | struct sk_buff *resp); | ||
| 1709 | static void pn533_wq_tm_mi_send(struct work_struct *work) | ||
| 1710 | { | ||
| 1711 | struct pn533 *dev = container_of(work, struct pn533, mi_tm_tx_work); | ||
| 1712 | struct sk_buff *skb; | ||
| 1713 | int rc; | ||
| 1714 | |||
| 1715 | dev_dbg(&dev->interface->dev, "%s\n", __func__); | ||
| 1716 | |||
| 1717 | /* Grab the first skb in the queue */ | ||
| 1718 | skb = skb_dequeue(&dev->fragment_skb); | ||
| 1719 | if (skb == NULL) { /* No more data */ | ||
| 1720 | /* Reset the queue for future use */ | ||
| 1721 | skb_queue_head_init(&dev->fragment_skb); | ||
| 1722 | goto error; | ||
| 1723 | } | ||
| 1724 | |||
| 1725 | /* last entry - remove MI bit */ | ||
| 1726 | if (skb_queue_len(&dev->fragment_skb) == 0) { | ||
| 1727 | rc = pn533_send_cmd_direct_async(dev, PN533_CMD_TG_SET_DATA, | ||
| 1728 | skb, pn533_tm_send_complete, NULL); | ||
| 1729 | } else | ||
| 1730 | rc = pn533_send_cmd_direct_async(dev, | ||
| 1731 | PN533_CMD_TG_SET_META_DATA, | ||
| 1732 | skb, pn533_tm_send_complete, NULL); | ||
| 1733 | |||
| 1734 | if (rc == 0) /* success */ | ||
| 1735 | return; | ||
| 1736 | |||
| 1737 | dev_err(&dev->interface->dev, | ||
| 1738 | "Error %d when trying to perform set meta data_exchange", rc); | ||
| 1739 | |||
| 1740 | dev_kfree_skb(skb); | ||
| 1741 | |||
| 1742 | error: | ||
| 1743 | pn533_send_ack(dev, GFP_KERNEL); | ||
| 1744 | queue_work(dev->wq, &dev->cmd_work); | ||
| 1648 | } | 1745 | } |
| 1649 | 1746 | ||
| 1650 | static void pn533_wq_tg_get_data(struct work_struct *work) | 1747 | static void pn533_wq_tg_get_data(struct work_struct *work) |
| 1651 | { | 1748 | { |
| 1652 | struct pn533 *dev = container_of(work, struct pn533, tg_work); | 1749 | struct pn533 *dev = container_of(work, struct pn533, tg_work); |
| 1653 | |||
| 1654 | struct sk_buff *skb; | 1750 | struct sk_buff *skb; |
| 1655 | int rc; | 1751 | int rc; |
| 1656 | 1752 | ||
| 1657 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 1753 | dev_dbg(&dev->interface->dev, "%s\n", __func__); |
| 1658 | 1754 | ||
| 1659 | skb = pn533_alloc_skb(dev, 0); | 1755 | skb = pn533_alloc_skb(dev, 0); |
| 1660 | if (!skb) | 1756 | if (!skb) |
| @@ -1676,7 +1772,7 @@ static int pn533_init_target_complete(struct pn533 *dev, struct sk_buff *resp) | |||
| 1676 | size_t gb_len; | 1772 | size_t gb_len; |
| 1677 | int rc; | 1773 | int rc; |
| 1678 | 1774 | ||
| 1679 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 1775 | dev_dbg(&dev->interface->dev, "%s\n", __func__); |
| 1680 | 1776 | ||
| 1681 | if (resp->len < ATR_REQ_GB_OFFSET + 1) | 1777 | if (resp->len < ATR_REQ_GB_OFFSET + 1) |
| 1682 | return -EINVAL; | 1778 | return -EINVAL; |
| @@ -1684,8 +1780,8 @@ static int pn533_init_target_complete(struct pn533 *dev, struct sk_buff *resp) | |||
| 1684 | mode = resp->data[0]; | 1780 | mode = resp->data[0]; |
| 1685 | cmd = &resp->data[1]; | 1781 | cmd = &resp->data[1]; |
| 1686 | 1782 | ||
| 1687 | nfc_dev_dbg(&dev->interface->dev, "Target mode 0x%x len %d\n", | 1783 | dev_dbg(&dev->interface->dev, "Target mode 0x%x len %d\n", |
| 1688 | mode, resp->len); | 1784 | mode, resp->len); |
| 1689 | 1785 | ||
| 1690 | if ((mode & PN533_INIT_TARGET_RESP_FRAME_MASK) == | 1786 | if ((mode & PN533_INIT_TARGET_RESP_FRAME_MASK) == |
| 1691 | PN533_INIT_TARGET_RESP_ACTIVE) | 1787 | PN533_INIT_TARGET_RESP_ACTIVE) |
| @@ -1700,8 +1796,8 @@ static int pn533_init_target_complete(struct pn533 *dev, struct sk_buff *resp) | |||
| 1700 | rc = nfc_tm_activated(dev->nfc_dev, NFC_PROTO_NFC_DEP_MASK, | 1796 | rc = nfc_tm_activated(dev->nfc_dev, NFC_PROTO_NFC_DEP_MASK, |
| 1701 | comm_mode, gb, gb_len); | 1797 | comm_mode, gb, gb_len); |
| 1702 | if (rc < 0) { | 1798 | if (rc < 0) { |
| 1703 | nfc_dev_err(&dev->interface->dev, | 1799 | nfc_err(&dev->interface->dev, |
| 1704 | "Error when signaling target activation"); | 1800 | "Error when signaling target activation\n"); |
| 1705 | return rc; | 1801 | return rc; |
| 1706 | } | 1802 | } |
| 1707 | 1803 | ||
| @@ -1715,7 +1811,7 @@ static void pn533_listen_mode_timer(unsigned long data) | |||
| 1715 | { | 1811 | { |
| 1716 | struct pn533 *dev = (struct pn533 *)data; | 1812 | struct pn533 *dev = (struct pn533 *)data; |
| 1717 | 1813 | ||
| 1718 | nfc_dev_dbg(&dev->interface->dev, "Listen mode timeout"); | 1814 | dev_dbg(&dev->interface->dev, "Listen mode timeout\n"); |
| 1719 | 1815 | ||
| 1720 | dev->cancel_listen = 1; | 1816 | dev->cancel_listen = 1; |
| 1721 | 1817 | ||
| @@ -1730,13 +1826,12 @@ static int pn533_rf_complete(struct pn533 *dev, void *arg, | |||
| 1730 | { | 1826 | { |
| 1731 | int rc = 0; | 1827 | int rc = 0; |
| 1732 | 1828 | ||
| 1733 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 1829 | dev_dbg(&dev->interface->dev, "%s\n", __func__); |
| 1734 | 1830 | ||
| 1735 | if (IS_ERR(resp)) { | 1831 | if (IS_ERR(resp)) { |
| 1736 | rc = PTR_ERR(resp); | 1832 | rc = PTR_ERR(resp); |
| 1737 | 1833 | ||
| 1738 | nfc_dev_err(&dev->interface->dev, "%s RF setting error %d", | 1834 | nfc_err(&dev->interface->dev, "RF setting error %d", rc); |
| 1739 | __func__, rc); | ||
| 1740 | 1835 | ||
| 1741 | return rc; | 1836 | return rc; |
| 1742 | } | 1837 | } |
| @@ -1754,7 +1849,7 @@ static void pn533_wq_rf(struct work_struct *work) | |||
| 1754 | struct sk_buff *skb; | 1849 | struct sk_buff *skb; |
| 1755 | int rc; | 1850 | int rc; |
| 1756 | 1851 | ||
| 1757 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 1852 | dev_dbg(&dev->interface->dev, "%s\n", __func__); |
| 1758 | 1853 | ||
| 1759 | skb = pn533_alloc_skb(dev, 2); | 1854 | skb = pn533_alloc_skb(dev, 2); |
| 1760 | if (!skb) | 1855 | if (!skb) |
| @@ -1767,25 +1862,136 @@ static void pn533_wq_rf(struct work_struct *work) | |||
| 1767 | pn533_rf_complete, NULL); | 1862 | pn533_rf_complete, NULL); |
| 1768 | if (rc < 0) { | 1863 | if (rc < 0) { |
| 1769 | dev_kfree_skb(skb); | 1864 | dev_kfree_skb(skb); |
| 1770 | nfc_dev_err(&dev->interface->dev, "RF setting error %d", rc); | 1865 | nfc_err(&dev->interface->dev, "RF setting error %d\n", rc); |
| 1771 | } | 1866 | } |
| 1772 | 1867 | ||
| 1773 | return; | 1868 | return; |
| 1774 | } | 1869 | } |
| 1775 | 1870 | ||
| 1871 | static int pn533_poll_dep_complete(struct pn533 *dev, void *arg, | ||
| 1872 | struct sk_buff *resp) | ||
| 1873 | { | ||
| 1874 | struct pn533_cmd_jump_dep_response *rsp; | ||
| 1875 | struct nfc_target nfc_target; | ||
| 1876 | u8 target_gt_len; | ||
| 1877 | int rc; | ||
| 1878 | |||
| 1879 | if (IS_ERR(resp)) | ||
| 1880 | return PTR_ERR(resp); | ||
| 1881 | |||
| 1882 | rsp = (struct pn533_cmd_jump_dep_response *)resp->data; | ||
| 1883 | |||
| 1884 | rc = rsp->status & PN533_CMD_RET_MASK; | ||
| 1885 | if (rc != PN533_CMD_RET_SUCCESS) { | ||
| 1886 | /* Not target found, turn radio off */ | ||
| 1887 | queue_work(dev->wq, &dev->rf_work); | ||
| 1888 | |||
| 1889 | dev_kfree_skb(resp); | ||
| 1890 | return 0; | ||
| 1891 | } | ||
| 1892 | |||
| 1893 | dev_dbg(&dev->interface->dev, "Creating new target"); | ||
| 1894 | |||
| 1895 | nfc_target.supported_protocols = NFC_PROTO_NFC_DEP_MASK; | ||
| 1896 | nfc_target.nfcid1_len = 10; | ||
| 1897 | memcpy(nfc_target.nfcid1, rsp->nfcid3t, nfc_target.nfcid1_len); | ||
| 1898 | rc = nfc_targets_found(dev->nfc_dev, &nfc_target, 1); | ||
| 1899 | if (rc) | ||
| 1900 | goto error; | ||
| 1901 | |||
| 1902 | dev->tgt_available_prots = 0; | ||
| 1903 | dev->tgt_active_prot = NFC_PROTO_NFC_DEP; | ||
| 1904 | |||
| 1905 | /* ATR_RES general bytes are located at offset 17 */ | ||
| 1906 | target_gt_len = resp->len - 17; | ||
| 1907 | rc = nfc_set_remote_general_bytes(dev->nfc_dev, | ||
| 1908 | rsp->gt, target_gt_len); | ||
| 1909 | if (!rc) { | ||
| 1910 | rc = nfc_dep_link_is_up(dev->nfc_dev, | ||
| 1911 | dev->nfc_dev->targets[0].idx, | ||
| 1912 | 0, NFC_RF_INITIATOR); | ||
| 1913 | |||
| 1914 | if (!rc) | ||
| 1915 | pn533_poll_reset_mod_list(dev); | ||
| 1916 | } | ||
| 1917 | error: | ||
| 1918 | dev_kfree_skb(resp); | ||
| 1919 | return rc; | ||
| 1920 | } | ||
| 1921 | |||
| 1922 | #define PASSIVE_DATA_LEN 5 | ||
| 1923 | static int pn533_poll_dep(struct nfc_dev *nfc_dev) | ||
| 1924 | { | ||
| 1925 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); | ||
| 1926 | struct sk_buff *skb; | ||
| 1927 | int rc, skb_len; | ||
| 1928 | u8 *next, nfcid3[NFC_NFCID3_MAXSIZE]; | ||
| 1929 | u8 passive_data[PASSIVE_DATA_LEN] = {0x00, 0xff, 0xff, 0x00, 0x3}; | ||
| 1930 | |||
| 1931 | dev_dbg(&dev->interface->dev, "%s", __func__); | ||
| 1932 | |||
| 1933 | if (!dev->gb) { | ||
| 1934 | dev->gb = nfc_get_local_general_bytes(nfc_dev, &dev->gb_len); | ||
| 1935 | |||
| 1936 | if (!dev->gb || !dev->gb_len) { | ||
| 1937 | dev->poll_dep = 0; | ||
| 1938 | queue_work(dev->wq, &dev->rf_work); | ||
| 1939 | } | ||
| 1940 | } | ||
| 1941 | |||
| 1942 | skb_len = 3 + dev->gb_len; /* ActPass + BR + Next */ | ||
| 1943 | skb_len += PASSIVE_DATA_LEN; | ||
| 1944 | |||
| 1945 | /* NFCID3 */ | ||
| 1946 | skb_len += NFC_NFCID3_MAXSIZE; | ||
| 1947 | nfcid3[0] = 0x1; | ||
| 1948 | nfcid3[1] = 0xfe; | ||
| 1949 | get_random_bytes(nfcid3 + 2, 6); | ||
| 1950 | |||
| 1951 | skb = pn533_alloc_skb(dev, skb_len); | ||
| 1952 | if (!skb) | ||
| 1953 | return -ENOMEM; | ||
| 1954 | |||
| 1955 | *skb_put(skb, 1) = 0x01; /* Active */ | ||
| 1956 | *skb_put(skb, 1) = 0x02; /* 424 kbps */ | ||
| 1957 | |||
| 1958 | next = skb_put(skb, 1); /* Next */ | ||
| 1959 | *next = 0; | ||
| 1960 | |||
| 1961 | /* Copy passive data */ | ||
| 1962 | memcpy(skb_put(skb, PASSIVE_DATA_LEN), passive_data, PASSIVE_DATA_LEN); | ||
| 1963 | *next |= 1; | ||
| 1964 | |||
| 1965 | /* Copy NFCID3 (which is NFCID2 from SENSF_RES) */ | ||
| 1966 | memcpy(skb_put(skb, NFC_NFCID3_MAXSIZE), nfcid3, | ||
| 1967 | NFC_NFCID3_MAXSIZE); | ||
| 1968 | *next |= 2; | ||
| 1969 | |||
| 1970 | memcpy(skb_put(skb, dev->gb_len), dev->gb, dev->gb_len); | ||
| 1971 | *next |= 4; /* We have some Gi */ | ||
| 1972 | |||
| 1973 | rc = pn533_send_cmd_async(dev, PN533_CMD_IN_JUMP_FOR_DEP, skb, | ||
| 1974 | pn533_poll_dep_complete, NULL); | ||
| 1975 | |||
| 1976 | if (rc < 0) | ||
| 1977 | dev_kfree_skb(skb); | ||
| 1978 | |||
| 1979 | return rc; | ||
| 1980 | } | ||
| 1981 | |||
| 1776 | static int pn533_poll_complete(struct pn533 *dev, void *arg, | 1982 | static int pn533_poll_complete(struct pn533 *dev, void *arg, |
| 1777 | struct sk_buff *resp) | 1983 | struct sk_buff *resp) |
| 1778 | { | 1984 | { |
| 1779 | struct pn533_poll_modulations *cur_mod; | 1985 | struct pn533_poll_modulations *cur_mod; |
| 1780 | int rc; | 1986 | int rc; |
| 1781 | 1987 | ||
| 1782 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 1988 | dev_dbg(&dev->interface->dev, "%s\n", __func__); |
| 1783 | 1989 | ||
| 1784 | if (IS_ERR(resp)) { | 1990 | if (IS_ERR(resp)) { |
| 1785 | rc = PTR_ERR(resp); | 1991 | rc = PTR_ERR(resp); |
| 1786 | 1992 | ||
| 1787 | nfc_dev_err(&dev->interface->dev, "%s Poll complete error %d", | 1993 | nfc_err(&dev->interface->dev, "%s Poll complete error %d\n", |
| 1788 | __func__, rc); | 1994 | __func__, rc); |
| 1789 | 1995 | ||
| 1790 | if (rc == -ENOENT) { | 1996 | if (rc == -ENOENT) { |
| 1791 | if (dev->poll_mod_count != 0) | 1997 | if (dev->poll_mod_count != 0) |
| @@ -1793,8 +1999,8 @@ static int pn533_poll_complete(struct pn533 *dev, void *arg, | |||
| 1793 | else | 1999 | else |
| 1794 | goto stop_poll; | 2000 | goto stop_poll; |
| 1795 | } else if (rc < 0) { | 2001 | } else if (rc < 0) { |
| 1796 | nfc_dev_err(&dev->interface->dev, | 2002 | nfc_err(&dev->interface->dev, |
| 1797 | "Error %d when running poll", rc); | 2003 | "Error %d when running poll\n", rc); |
| 1798 | goto stop_poll; | 2004 | goto stop_poll; |
| 1799 | } | 2005 | } |
| 1800 | } | 2006 | } |
| @@ -1813,7 +2019,7 @@ static int pn533_poll_complete(struct pn533 *dev, void *arg, | |||
| 1813 | goto done; | 2019 | goto done; |
| 1814 | 2020 | ||
| 1815 | if (!dev->poll_mod_count) { | 2021 | if (!dev->poll_mod_count) { |
| 1816 | nfc_dev_dbg(&dev->interface->dev, "Polling has been stopped."); | 2022 | dev_dbg(&dev->interface->dev, "Polling has been stopped\n"); |
| 1817 | goto done; | 2023 | goto done; |
| 1818 | } | 2024 | } |
| 1819 | 2025 | ||
| @@ -1826,7 +2032,7 @@ done: | |||
| 1826 | return rc; | 2032 | return rc; |
| 1827 | 2033 | ||
| 1828 | stop_poll: | 2034 | stop_poll: |
| 1829 | nfc_dev_err(&dev->interface->dev, "Polling operation has been stopped"); | 2035 | nfc_err(&dev->interface->dev, "Polling operation has been stopped\n"); |
| 1830 | 2036 | ||
| 1831 | pn533_poll_reset_mod_list(dev); | 2037 | pn533_poll_reset_mod_list(dev); |
| 1832 | dev->poll_protocols = 0; | 2038 | dev->poll_protocols = 0; |
| @@ -1856,8 +2062,13 @@ static int pn533_send_poll_frame(struct pn533 *dev) | |||
| 1856 | 2062 | ||
| 1857 | mod = dev->poll_mod_active[dev->poll_mod_curr]; | 2063 | mod = dev->poll_mod_active[dev->poll_mod_curr]; |
| 1858 | 2064 | ||
| 1859 | nfc_dev_dbg(&dev->interface->dev, "%s mod len %d\n", | 2065 | dev_dbg(&dev->interface->dev, "%s mod len %d\n", |
| 1860 | __func__, mod->len); | 2066 | __func__, mod->len); |
| 2067 | |||
| 2068 | if (dev->poll_dep) { | ||
| 2069 | dev->poll_dep = 0; | ||
| 2070 | return pn533_poll_dep(dev->nfc_dev); | ||
| 2071 | } | ||
| 1861 | 2072 | ||
| 1862 | if (mod->len == 0) { /* Listen mode */ | 2073 | if (mod->len == 0) { /* Listen mode */ |
| 1863 | cmd_code = PN533_CMD_TG_INIT_AS_TARGET; | 2074 | cmd_code = PN533_CMD_TG_INIT_AS_TARGET; |
| @@ -1868,7 +2079,7 @@ static int pn533_send_poll_frame(struct pn533 *dev) | |||
| 1868 | } | 2079 | } |
| 1869 | 2080 | ||
| 1870 | if (!skb) { | 2081 | if (!skb) { |
| 1871 | nfc_dev_err(&dev->interface->dev, "Failed to allocate skb."); | 2082 | nfc_err(&dev->interface->dev, "Failed to allocate skb\n"); |
| 1872 | return -ENOMEM; | 2083 | return -ENOMEM; |
| 1873 | } | 2084 | } |
| 1874 | 2085 | ||
| @@ -1876,7 +2087,7 @@ static int pn533_send_poll_frame(struct pn533 *dev) | |||
| 1876 | NULL); | 2087 | NULL); |
| 1877 | if (rc < 0) { | 2088 | if (rc < 0) { |
| 1878 | dev_kfree_skb(skb); | 2089 | dev_kfree_skb(skb); |
| 1879 | nfc_dev_err(&dev->interface->dev, "Polling loop error %d", rc); | 2090 | nfc_err(&dev->interface->dev, "Polling loop error %d\n", rc); |
| 1880 | } | 2091 | } |
| 1881 | 2092 | ||
| 1882 | return rc; | 2093 | return rc; |
| @@ -1890,9 +2101,9 @@ static void pn533_wq_poll(struct work_struct *work) | |||
| 1890 | 2101 | ||
| 1891 | cur_mod = dev->poll_mod_active[dev->poll_mod_curr]; | 2102 | cur_mod = dev->poll_mod_active[dev->poll_mod_curr]; |
| 1892 | 2103 | ||
| 1893 | nfc_dev_dbg(&dev->interface->dev, | 2104 | dev_dbg(&dev->interface->dev, |
| 1894 | "%s cancel_listen %d modulation len %d", | 2105 | "%s cancel_listen %d modulation len %d\n", |
| 1895 | __func__, dev->cancel_listen, cur_mod->len); | 2106 | __func__, dev->cancel_listen, cur_mod->len); |
| 1896 | 2107 | ||
| 1897 | if (dev->cancel_listen == 1) { | 2108 | if (dev->cancel_listen == 1) { |
| 1898 | dev->cancel_listen = 0; | 2109 | dev->cancel_listen = 0; |
| @@ -1913,21 +2124,23 @@ static int pn533_start_poll(struct nfc_dev *nfc_dev, | |||
| 1913 | u32 im_protocols, u32 tm_protocols) | 2124 | u32 im_protocols, u32 tm_protocols) |
| 1914 | { | 2125 | { |
| 1915 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); | 2126 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); |
| 2127 | struct pn533_poll_modulations *cur_mod; | ||
| 1916 | u8 rand_mod; | 2128 | u8 rand_mod; |
| 2129 | int rc; | ||
| 1917 | 2130 | ||
| 1918 | nfc_dev_dbg(&dev->interface->dev, | 2131 | dev_dbg(&dev->interface->dev, |
| 1919 | "%s: im protocols 0x%x tm protocols 0x%x", | 2132 | "%s: im protocols 0x%x tm protocols 0x%x\n", |
| 1920 | __func__, im_protocols, tm_protocols); | 2133 | __func__, im_protocols, tm_protocols); |
| 1921 | 2134 | ||
| 1922 | if (dev->tgt_active_prot) { | 2135 | if (dev->tgt_active_prot) { |
| 1923 | nfc_dev_err(&dev->interface->dev, | 2136 | nfc_err(&dev->interface->dev, |
| 1924 | "Cannot poll with a target already activated"); | 2137 | "Cannot poll with a target already activated\n"); |
| 1925 | return -EBUSY; | 2138 | return -EBUSY; |
| 1926 | } | 2139 | } |
| 1927 | 2140 | ||
| 1928 | if (dev->tgt_mode) { | 2141 | if (dev->tgt_mode) { |
| 1929 | nfc_dev_err(&dev->interface->dev, | 2142 | nfc_err(&dev->interface->dev, |
| 1930 | "Cannot poll while already being activated"); | 2143 | "Cannot poll while already being activated\n"); |
| 1931 | return -EBUSY; | 2144 | return -EBUSY; |
| 1932 | } | 2145 | } |
| 1933 | 2146 | ||
| @@ -1946,20 +2159,26 @@ static int pn533_start_poll(struct nfc_dev *nfc_dev, | |||
| 1946 | rand_mod %= dev->poll_mod_count; | 2159 | rand_mod %= dev->poll_mod_count; |
| 1947 | dev->poll_mod_curr = rand_mod; | 2160 | dev->poll_mod_curr = rand_mod; |
| 1948 | 2161 | ||
| 1949 | return pn533_send_poll_frame(dev); | 2162 | cur_mod = dev->poll_mod_active[dev->poll_mod_curr]; |
| 2163 | |||
| 2164 | rc = pn533_send_poll_frame(dev); | ||
| 2165 | |||
| 2166 | /* Start listen timer */ | ||
| 2167 | if (!rc && cur_mod->len == 0 && dev->poll_mod_count > 1) | ||
| 2168 | mod_timer(&dev->listen_timer, jiffies + PN533_LISTEN_TIME * HZ); | ||
| 2169 | |||
| 2170 | return rc; | ||
| 1950 | } | 2171 | } |
| 1951 | 2172 | ||
| 1952 | static void pn533_stop_poll(struct nfc_dev *nfc_dev) | 2173 | static void pn533_stop_poll(struct nfc_dev *nfc_dev) |
| 1953 | { | 2174 | { |
| 1954 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); | 2175 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); |
| 1955 | 2176 | ||
| 1956 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | ||
| 1957 | |||
| 1958 | del_timer(&dev->listen_timer); | 2177 | del_timer(&dev->listen_timer); |
| 1959 | 2178 | ||
| 1960 | if (!dev->poll_mod_count) { | 2179 | if (!dev->poll_mod_count) { |
| 1961 | nfc_dev_dbg(&dev->interface->dev, | 2180 | dev_dbg(&dev->interface->dev, |
| 1962 | "Polling operation was not running"); | 2181 | "Polling operation was not running\n"); |
| 1963 | return; | 2182 | return; |
| 1964 | } | 2183 | } |
| 1965 | 2184 | ||
| @@ -1973,11 +2192,10 @@ static int pn533_activate_target_nfcdep(struct pn533 *dev) | |||
| 1973 | struct pn533_cmd_activate_response *rsp; | 2192 | struct pn533_cmd_activate_response *rsp; |
| 1974 | u16 gt_len; | 2193 | u16 gt_len; |
| 1975 | int rc; | 2194 | int rc; |
| 1976 | |||
| 1977 | struct sk_buff *skb; | 2195 | struct sk_buff *skb; |
| 1978 | struct sk_buff *resp; | 2196 | struct sk_buff *resp; |
| 1979 | 2197 | ||
| 1980 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 2198 | dev_dbg(&dev->interface->dev, "%s\n", __func__); |
| 1981 | 2199 | ||
| 1982 | skb = pn533_alloc_skb(dev, sizeof(u8) * 2); /*TG + Next*/ | 2200 | skb = pn533_alloc_skb(dev, sizeof(u8) * 2); /*TG + Next*/ |
| 1983 | if (!skb) | 2201 | if (!skb) |
| @@ -1993,8 +2211,8 @@ static int pn533_activate_target_nfcdep(struct pn533 *dev) | |||
| 1993 | rsp = (struct pn533_cmd_activate_response *)resp->data; | 2211 | rsp = (struct pn533_cmd_activate_response *)resp->data; |
| 1994 | rc = rsp->status & PN533_CMD_RET_MASK; | 2212 | rc = rsp->status & PN533_CMD_RET_MASK; |
| 1995 | if (rc != PN533_CMD_RET_SUCCESS) { | 2213 | if (rc != PN533_CMD_RET_SUCCESS) { |
| 1996 | nfc_dev_err(&dev->interface->dev, | 2214 | nfc_err(&dev->interface->dev, |
| 1997 | "Target activation failed (error 0x%x)", rc); | 2215 | "Target activation failed (error 0x%x)\n", rc); |
| 1998 | dev_kfree_skb(resp); | 2216 | dev_kfree_skb(resp); |
| 1999 | return -EIO; | 2217 | return -EIO; |
| 2000 | } | 2218 | } |
| @@ -2013,39 +2231,38 @@ static int pn533_activate_target(struct nfc_dev *nfc_dev, | |||
| 2013 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); | 2231 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); |
| 2014 | int rc; | 2232 | int rc; |
| 2015 | 2233 | ||
| 2016 | nfc_dev_dbg(&dev->interface->dev, "%s - protocol=%u", __func__, | 2234 | dev_dbg(&dev->interface->dev, "%s: protocol=%u\n", __func__, protocol); |
| 2017 | protocol); | ||
| 2018 | 2235 | ||
| 2019 | if (dev->poll_mod_count) { | 2236 | if (dev->poll_mod_count) { |
| 2020 | nfc_dev_err(&dev->interface->dev, | 2237 | nfc_err(&dev->interface->dev, |
| 2021 | "Cannot activate while polling"); | 2238 | "Cannot activate while polling\n"); |
| 2022 | return -EBUSY; | 2239 | return -EBUSY; |
| 2023 | } | 2240 | } |
| 2024 | 2241 | ||
| 2025 | if (dev->tgt_active_prot) { | 2242 | if (dev->tgt_active_prot) { |
| 2026 | nfc_dev_err(&dev->interface->dev, | 2243 | nfc_err(&dev->interface->dev, |
| 2027 | "There is already an active target"); | 2244 | "There is already an active target\n"); |
| 2028 | return -EBUSY; | 2245 | return -EBUSY; |
| 2029 | } | 2246 | } |
| 2030 | 2247 | ||
| 2031 | if (!dev->tgt_available_prots) { | 2248 | if (!dev->tgt_available_prots) { |
| 2032 | nfc_dev_err(&dev->interface->dev, | 2249 | nfc_err(&dev->interface->dev, |
| 2033 | "There is no available target to activate"); | 2250 | "There is no available target to activate\n"); |
| 2034 | return -EINVAL; | 2251 | return -EINVAL; |
| 2035 | } | 2252 | } |
| 2036 | 2253 | ||
| 2037 | if (!(dev->tgt_available_prots & (1 << protocol))) { | 2254 | if (!(dev->tgt_available_prots & (1 << protocol))) { |
| 2038 | nfc_dev_err(&dev->interface->dev, | 2255 | nfc_err(&dev->interface->dev, |
| 2039 | "Target doesn't support requested proto %u", | 2256 | "Target doesn't support requested proto %u\n", |
| 2040 | protocol); | 2257 | protocol); |
| 2041 | return -EINVAL; | 2258 | return -EINVAL; |
| 2042 | } | 2259 | } |
| 2043 | 2260 | ||
| 2044 | if (protocol == NFC_PROTO_NFC_DEP) { | 2261 | if (protocol == NFC_PROTO_NFC_DEP) { |
| 2045 | rc = pn533_activate_target_nfcdep(dev); | 2262 | rc = pn533_activate_target_nfcdep(dev); |
| 2046 | if (rc) { | 2263 | if (rc) { |
| 2047 | nfc_dev_err(&dev->interface->dev, | 2264 | nfc_err(&dev->interface->dev, |
| 2048 | "Activating target with DEP failed %d", rc); | 2265 | "Activating target with DEP failed %d\n", rc); |
| 2049 | return rc; | 2266 | return rc; |
| 2050 | } | 2267 | } |
| 2051 | } | 2268 | } |
| @@ -2060,16 +2277,14 @@ static void pn533_deactivate_target(struct nfc_dev *nfc_dev, | |||
| 2060 | struct nfc_target *target) | 2277 | struct nfc_target *target) |
| 2061 | { | 2278 | { |
| 2062 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); | 2279 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); |
| 2063 | |||
| 2064 | struct sk_buff *skb; | 2280 | struct sk_buff *skb; |
| 2065 | struct sk_buff *resp; | 2281 | struct sk_buff *resp; |
| 2066 | |||
| 2067 | int rc; | 2282 | int rc; |
| 2068 | 2283 | ||
| 2069 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 2284 | dev_dbg(&dev->interface->dev, "%s\n", __func__); |
| 2070 | 2285 | ||
| 2071 | if (!dev->tgt_active_prot) { | 2286 | if (!dev->tgt_active_prot) { |
| 2072 | nfc_dev_err(&dev->interface->dev, "There is no active target"); | 2287 | nfc_err(&dev->interface->dev, "There is no active target\n"); |
| 2073 | return; | 2288 | return; |
| 2074 | } | 2289 | } |
| 2075 | 2290 | ||
| @@ -2088,8 +2303,8 @@ static void pn533_deactivate_target(struct nfc_dev *nfc_dev, | |||
| 2088 | 2303 | ||
| 2089 | rc = resp->data[0] & PN533_CMD_RET_MASK; | 2304 | rc = resp->data[0] & PN533_CMD_RET_MASK; |
| 2090 | if (rc != PN533_CMD_RET_SUCCESS) | 2305 | if (rc != PN533_CMD_RET_SUCCESS) |
| 2091 | nfc_dev_err(&dev->interface->dev, | 2306 | nfc_err(&dev->interface->dev, |
| 2092 | "Error 0x%x when releasing the target", rc); | 2307 | "Error 0x%x when releasing the target\n", rc); |
| 2093 | 2308 | ||
| 2094 | dev_kfree_skb(resp); | 2309 | dev_kfree_skb(resp); |
| 2095 | return; | 2310 | return; |
| @@ -2111,8 +2326,8 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, | |||
| 2111 | 2326 | ||
| 2112 | if (dev->tgt_available_prots && | 2327 | if (dev->tgt_available_prots && |
| 2113 | !(dev->tgt_available_prots & (1 << NFC_PROTO_NFC_DEP))) { | 2328 | !(dev->tgt_available_prots & (1 << NFC_PROTO_NFC_DEP))) { |
| 2114 | nfc_dev_err(&dev->interface->dev, | 2329 | nfc_err(&dev->interface->dev, |
| 2115 | "The target does not support DEP"); | 2330 | "The target does not support DEP\n"); |
| 2116 | rc = -EINVAL; | 2331 | rc = -EINVAL; |
| 2117 | goto error; | 2332 | goto error; |
| 2118 | } | 2333 | } |
| @@ -2121,15 +2336,15 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, | |||
| 2121 | 2336 | ||
| 2122 | rc = rsp->status & PN533_CMD_RET_MASK; | 2337 | rc = rsp->status & PN533_CMD_RET_MASK; |
| 2123 | if (rc != PN533_CMD_RET_SUCCESS) { | 2338 | if (rc != PN533_CMD_RET_SUCCESS) { |
| 2124 | nfc_dev_err(&dev->interface->dev, | 2339 | nfc_err(&dev->interface->dev, |
| 2125 | "Bringing DEP link up failed (error 0x%x)", rc); | 2340 | "Bringing DEP link up failed (error 0x%x)\n", rc); |
| 2126 | goto error; | 2341 | goto error; |
| 2127 | } | 2342 | } |
| 2128 | 2343 | ||
| 2129 | if (!dev->tgt_available_prots) { | 2344 | if (!dev->tgt_available_prots) { |
| 2130 | struct nfc_target nfc_target; | 2345 | struct nfc_target nfc_target; |
| 2131 | 2346 | ||
| 2132 | nfc_dev_dbg(&dev->interface->dev, "Creating new target"); | 2347 | dev_dbg(&dev->interface->dev, "Creating new target\n"); |
| 2133 | 2348 | ||
| 2134 | nfc_target.supported_protocols = NFC_PROTO_NFC_DEP_MASK; | 2349 | nfc_target.supported_protocols = NFC_PROTO_NFC_DEP_MASK; |
| 2135 | nfc_target.nfcid1_len = 10; | 2350 | nfc_target.nfcid1_len = 10; |
| @@ -2158,7 +2373,6 @@ error: | |||
| 2158 | } | 2373 | } |
| 2159 | 2374 | ||
| 2160 | static int pn533_rf_field(struct nfc_dev *nfc_dev, u8 rf); | 2375 | static int pn533_rf_field(struct nfc_dev *nfc_dev, u8 rf); |
| 2161 | #define PASSIVE_DATA_LEN 5 | ||
| 2162 | static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, | 2376 | static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, |
| 2163 | u8 comm_mode, u8 *gb, size_t gb_len) | 2377 | u8 comm_mode, u8 *gb, size_t gb_len) |
| 2164 | { | 2378 | { |
| @@ -2166,20 +2380,19 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, | |||
| 2166 | struct sk_buff *skb; | 2380 | struct sk_buff *skb; |
| 2167 | int rc, skb_len; | 2381 | int rc, skb_len; |
| 2168 | u8 *next, *arg, nfcid3[NFC_NFCID3_MAXSIZE]; | 2382 | u8 *next, *arg, nfcid3[NFC_NFCID3_MAXSIZE]; |
| 2169 | |||
| 2170 | u8 passive_data[PASSIVE_DATA_LEN] = {0x00, 0xff, 0xff, 0x00, 0x3}; | 2383 | u8 passive_data[PASSIVE_DATA_LEN] = {0x00, 0xff, 0xff, 0x00, 0x3}; |
| 2171 | 2384 | ||
| 2172 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 2385 | dev_dbg(&dev->interface->dev, "%s\n", __func__); |
| 2173 | 2386 | ||
| 2174 | if (dev->poll_mod_count) { | 2387 | if (dev->poll_mod_count) { |
| 2175 | nfc_dev_err(&dev->interface->dev, | 2388 | nfc_err(&dev->interface->dev, |
| 2176 | "Cannot bring the DEP link up while polling"); | 2389 | "Cannot bring the DEP link up while polling\n"); |
| 2177 | return -EBUSY; | 2390 | return -EBUSY; |
| 2178 | } | 2391 | } |
| 2179 | 2392 | ||
| 2180 | if (dev->tgt_active_prot) { | 2393 | if (dev->tgt_active_prot) { |
| 2181 | nfc_dev_err(&dev->interface->dev, | 2394 | nfc_err(&dev->interface->dev, |
| 2182 | "There is already an active target"); | 2395 | "There is already an active target\n"); |
| 2183 | return -EBUSY; | 2396 | return -EBUSY; |
| 2184 | } | 2397 | } |
| 2185 | 2398 | ||
| @@ -2249,7 +2462,7 @@ static int pn533_dep_link_down(struct nfc_dev *nfc_dev) | |||
| 2249 | { | 2462 | { |
| 2250 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); | 2463 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); |
| 2251 | 2464 | ||
| 2252 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 2465 | dev_dbg(&dev->interface->dev, "%s\n", __func__); |
| 2253 | 2466 | ||
| 2254 | pn533_poll_reset_mod_list(dev); | 2467 | pn533_poll_reset_mod_list(dev); |
| 2255 | 2468 | ||
| @@ -2274,7 +2487,7 @@ static struct sk_buff *pn533_build_response(struct pn533 *dev) | |||
| 2274 | struct sk_buff *skb, *tmp, *t; | 2487 | struct sk_buff *skb, *tmp, *t; |
| 2275 | unsigned int skb_len = 0, tmp_len = 0; | 2488 | unsigned int skb_len = 0, tmp_len = 0; |
| 2276 | 2489 | ||
| 2277 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 2490 | dev_dbg(&dev->interface->dev, "%s\n", __func__); |
| 2278 | 2491 | ||
| 2279 | if (skb_queue_empty(&dev->resp_q)) | 2492 | if (skb_queue_empty(&dev->resp_q)) |
| 2280 | return NULL; | 2493 | return NULL; |
| @@ -2287,8 +2500,8 @@ static struct sk_buff *pn533_build_response(struct pn533 *dev) | |||
| 2287 | skb_queue_walk_safe(&dev->resp_q, tmp, t) | 2500 | skb_queue_walk_safe(&dev->resp_q, tmp, t) |
| 2288 | skb_len += tmp->len; | 2501 | skb_len += tmp->len; |
| 2289 | 2502 | ||
| 2290 | nfc_dev_dbg(&dev->interface->dev, "%s total length %d\n", | 2503 | dev_dbg(&dev->interface->dev, "%s total length %d\n", |
| 2291 | __func__, skb_len); | 2504 | __func__, skb_len); |
| 2292 | 2505 | ||
| 2293 | skb = alloc_skb(skb_len, GFP_KERNEL); | 2506 | skb = alloc_skb(skb_len, GFP_KERNEL); |
| 2294 | if (skb == NULL) | 2507 | if (skb == NULL) |
| @@ -2315,7 +2528,7 @@ static int pn533_data_exchange_complete(struct pn533 *dev, void *_arg, | |||
| 2315 | int rc = 0; | 2528 | int rc = 0; |
| 2316 | u8 status, ret, mi; | 2529 | u8 status, ret, mi; |
| 2317 | 2530 | ||
| 2318 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 2531 | dev_dbg(&dev->interface->dev, "%s\n", __func__); |
| 2319 | 2532 | ||
| 2320 | if (IS_ERR(resp)) { | 2533 | if (IS_ERR(resp)) { |
| 2321 | rc = PTR_ERR(resp); | 2534 | rc = PTR_ERR(resp); |
| @@ -2329,8 +2542,8 @@ static int pn533_data_exchange_complete(struct pn533 *dev, void *_arg, | |||
| 2329 | skb_pull(resp, sizeof(status)); | 2542 | skb_pull(resp, sizeof(status)); |
| 2330 | 2543 | ||
| 2331 | if (ret != PN533_CMD_RET_SUCCESS) { | 2544 | if (ret != PN533_CMD_RET_SUCCESS) { |
| 2332 | nfc_dev_err(&dev->interface->dev, | 2545 | nfc_err(&dev->interface->dev, |
| 2333 | "Exchanging data failed (error 0x%x)", ret); | 2546 | "Exchanging data failed (error 0x%x)\n", ret); |
| 2334 | rc = -EIO; | 2547 | rc = -EIO; |
| 2335 | goto error; | 2548 | goto error; |
| 2336 | } | 2549 | } |
| @@ -2388,14 +2601,17 @@ static int pn533_fill_fragment_skbs(struct pn533 *dev, struct sk_buff *skb) | |||
| 2388 | break; | 2601 | break; |
| 2389 | } | 2602 | } |
| 2390 | 2603 | ||
| 2391 | /* Reserve the TG/MI byte */ | 2604 | if (!dev->tgt_mode) { |
| 2392 | skb_reserve(frag, 1); | 2605 | /* Reserve the TG/MI byte */ |
| 2606 | skb_reserve(frag, 1); | ||
| 2393 | 2607 | ||
| 2394 | /* MI + TG */ | 2608 | /* MI + TG */ |
| 2395 | if (frag_size == PN533_CMD_DATAFRAME_MAXLEN) | 2609 | if (frag_size == PN533_CMD_DATAFRAME_MAXLEN) |
| 2396 | *skb_push(frag, sizeof(u8)) = (PN533_CMD_MI_MASK | 1); | 2610 | *skb_push(frag, sizeof(u8)) = |
| 2397 | else | 2611 | (PN533_CMD_MI_MASK | 1); |
| 2398 | *skb_push(frag, sizeof(u8)) = 1; /* TG */ | 2612 | else |
| 2613 | *skb_push(frag, sizeof(u8)) = 1; /* TG */ | ||
| 2614 | } | ||
| 2399 | 2615 | ||
| 2400 | memcpy(skb_put(frag, frag_size), skb->data, frag_size); | 2616 | memcpy(skb_put(frag, frag_size), skb->data, frag_size); |
| 2401 | 2617 | ||
| @@ -2420,11 +2636,11 @@ static int pn533_transceive(struct nfc_dev *nfc_dev, | |||
| 2420 | struct pn533_data_exchange_arg *arg = NULL; | 2636 | struct pn533_data_exchange_arg *arg = NULL; |
| 2421 | int rc; | 2637 | int rc; |
| 2422 | 2638 | ||
| 2423 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 2639 | dev_dbg(&dev->interface->dev, "%s\n", __func__); |
| 2424 | 2640 | ||
| 2425 | if (!dev->tgt_active_prot) { | 2641 | if (!dev->tgt_active_prot) { |
| 2426 | nfc_dev_err(&dev->interface->dev, | 2642 | nfc_err(&dev->interface->dev, |
| 2427 | "Can't exchange data if there is no active target"); | 2643 | "Can't exchange data if there is no active target\n"); |
| 2428 | rc = -EINVAL; | 2644 | rc = -EINVAL; |
| 2429 | goto error; | 2645 | goto error; |
| 2430 | } | 2646 | } |
| @@ -2487,13 +2703,18 @@ static int pn533_tm_send_complete(struct pn533 *dev, void *arg, | |||
| 2487 | { | 2703 | { |
| 2488 | u8 status; | 2704 | u8 status; |
| 2489 | 2705 | ||
| 2490 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 2706 | dev_dbg(&dev->interface->dev, "%s\n", __func__); |
| 2491 | 2707 | ||
| 2492 | if (IS_ERR(resp)) | 2708 | if (IS_ERR(resp)) |
| 2493 | return PTR_ERR(resp); | 2709 | return PTR_ERR(resp); |
| 2494 | 2710 | ||
| 2495 | status = resp->data[0]; | 2711 | status = resp->data[0]; |
| 2496 | 2712 | ||
| 2713 | /* Prepare for the next round */ | ||
| 2714 | if (skb_queue_len(&dev->fragment_skb) > 0) { | ||
| 2715 | queue_work(dev->wq, &dev->mi_tm_tx_work); | ||
| 2716 | return -EINPROGRESS; | ||
| 2717 | } | ||
| 2497 | dev_kfree_skb(resp); | 2718 | dev_kfree_skb(resp); |
| 2498 | 2719 | ||
| 2499 | if (status != 0) { | 2720 | if (status != 0) { |
| @@ -2514,19 +2735,34 @@ static int pn533_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb) | |||
| 2514 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); | 2735 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); |
| 2515 | int rc; | 2736 | int rc; |
| 2516 | 2737 | ||
| 2517 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 2738 | dev_dbg(&dev->interface->dev, "%s\n", __func__); |
| 2518 | 2739 | ||
| 2740 | /* let's split in multiple chunks if size's too big */ | ||
| 2519 | if (skb->len > PN533_CMD_DATAEXCH_DATA_MAXLEN) { | 2741 | if (skb->len > PN533_CMD_DATAEXCH_DATA_MAXLEN) { |
| 2520 | nfc_dev_err(&dev->interface->dev, | 2742 | rc = pn533_fill_fragment_skbs(dev, skb); |
| 2521 | "Data length greater than the max allowed: %d", | 2743 | if (rc <= 0) |
| 2522 | PN533_CMD_DATAEXCH_DATA_MAXLEN); | 2744 | goto error; |
| 2523 | return -ENOSYS; | 2745 | |
| 2746 | /* get the first skb */ | ||
| 2747 | skb = skb_dequeue(&dev->fragment_skb); | ||
| 2748 | if (!skb) { | ||
| 2749 | rc = -EIO; | ||
| 2750 | goto error; | ||
| 2751 | } | ||
| 2752 | |||
| 2753 | rc = pn533_send_data_async(dev, PN533_CMD_TG_SET_META_DATA, skb, | ||
| 2754 | pn533_tm_send_complete, NULL); | ||
| 2755 | } else { | ||
| 2756 | /* Send th skb */ | ||
| 2757 | rc = pn533_send_data_async(dev, PN533_CMD_TG_SET_DATA, skb, | ||
| 2758 | pn533_tm_send_complete, NULL); | ||
| 2524 | } | 2759 | } |
| 2525 | 2760 | ||
| 2526 | rc = pn533_send_data_async(dev, PN533_CMD_TG_SET_DATA, skb, | 2761 | error: |
| 2527 | pn533_tm_send_complete, NULL); | 2762 | if (rc < 0) { |
| 2528 | if (rc < 0) | ||
| 2529 | dev_kfree_skb(skb); | 2763 | dev_kfree_skb(skb); |
| 2764 | skb_queue_purge(&dev->fragment_skb); | ||
| 2765 | } | ||
| 2530 | 2766 | ||
| 2531 | return rc; | 2767 | return rc; |
| 2532 | } | 2768 | } |
| @@ -2534,11 +2770,10 @@ static int pn533_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb) | |||
| 2534 | static void pn533_wq_mi_recv(struct work_struct *work) | 2770 | static void pn533_wq_mi_recv(struct work_struct *work) |
| 2535 | { | 2771 | { |
| 2536 | struct pn533 *dev = container_of(work, struct pn533, mi_rx_work); | 2772 | struct pn533 *dev = container_of(work, struct pn533, mi_rx_work); |
| 2537 | |||
| 2538 | struct sk_buff *skb; | 2773 | struct sk_buff *skb; |
| 2539 | int rc; | 2774 | int rc; |
| 2540 | 2775 | ||
| 2541 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 2776 | dev_dbg(&dev->interface->dev, "%s\n", __func__); |
| 2542 | 2777 | ||
| 2543 | skb = pn533_alloc_skb(dev, PN533_CMD_DATAEXCH_HEAD_LEN); | 2778 | skb = pn533_alloc_skb(dev, PN533_CMD_DATAEXCH_HEAD_LEN); |
| 2544 | if (!skb) | 2779 | if (!skb) |
| @@ -2570,8 +2805,8 @@ static void pn533_wq_mi_recv(struct work_struct *work) | |||
| 2570 | if (rc == 0) /* success */ | 2805 | if (rc == 0) /* success */ |
| 2571 | return; | 2806 | return; |
| 2572 | 2807 | ||
| 2573 | nfc_dev_err(&dev->interface->dev, | 2808 | nfc_err(&dev->interface->dev, |
| 2574 | "Error %d when trying to perform data_exchange", rc); | 2809 | "Error %d when trying to perform data_exchange\n", rc); |
| 2575 | 2810 | ||
| 2576 | dev_kfree_skb(skb); | 2811 | dev_kfree_skb(skb); |
| 2577 | kfree(dev->cmd_complete_mi_arg); | 2812 | kfree(dev->cmd_complete_mi_arg); |
| @@ -2587,7 +2822,7 @@ static void pn533_wq_mi_send(struct work_struct *work) | |||
| 2587 | struct sk_buff *skb; | 2822 | struct sk_buff *skb; |
| 2588 | int rc; | 2823 | int rc; |
| 2589 | 2824 | ||
| 2590 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 2825 | dev_dbg(&dev->interface->dev, "%s\n", __func__); |
| 2591 | 2826 | ||
| 2592 | /* Grab the first skb in the queue */ | 2827 | /* Grab the first skb in the queue */ |
| 2593 | skb = skb_dequeue(&dev->fragment_skb); | 2828 | skb = skb_dequeue(&dev->fragment_skb); |
| @@ -2625,8 +2860,8 @@ static void pn533_wq_mi_send(struct work_struct *work) | |||
| 2625 | if (rc == 0) /* success */ | 2860 | if (rc == 0) /* success */ |
| 2626 | return; | 2861 | return; |
| 2627 | 2862 | ||
| 2628 | nfc_dev_err(&dev->interface->dev, | 2863 | nfc_err(&dev->interface->dev, |
| 2629 | "Error %d when trying to perform data_exchange", rc); | 2864 | "Error %d when trying to perform data_exchange\n", rc); |
| 2630 | 2865 | ||
| 2631 | dev_kfree_skb(skb); | 2866 | dev_kfree_skb(skb); |
| 2632 | kfree(dev->cmd_complete_dep_arg); | 2867 | kfree(dev->cmd_complete_dep_arg); |
| @@ -2641,10 +2876,9 @@ static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata, | |||
| 2641 | { | 2876 | { |
| 2642 | struct sk_buff *skb; | 2877 | struct sk_buff *skb; |
| 2643 | struct sk_buff *resp; | 2878 | struct sk_buff *resp; |
| 2644 | |||
| 2645 | int skb_len; | 2879 | int skb_len; |
| 2646 | 2880 | ||
| 2647 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 2881 | dev_dbg(&dev->interface->dev, "%s\n", __func__); |
| 2648 | 2882 | ||
| 2649 | skb_len = sizeof(cfgitem) + cfgdata_len; /* cfgitem + cfgdata */ | 2883 | skb_len = sizeof(cfgitem) + cfgdata_len; /* cfgitem + cfgdata */ |
| 2650 | 2884 | ||
| @@ -2691,7 +2925,7 @@ static int pn533_pasori_fw_reset(struct pn533 *dev) | |||
| 2691 | struct sk_buff *skb; | 2925 | struct sk_buff *skb; |
| 2692 | struct sk_buff *resp; | 2926 | struct sk_buff *resp; |
| 2693 | 2927 | ||
| 2694 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 2928 | dev_dbg(&dev->interface->dev, "%s\n", __func__); |
| 2695 | 2929 | ||
| 2696 | skb = pn533_alloc_skb(dev, sizeof(u8)); | 2930 | skb = pn533_alloc_skb(dev, sizeof(u8)); |
| 2697 | if (!skb) | 2931 | if (!skb) |
| @@ -2717,7 +2951,7 @@ static void pn533_acr122_poweron_rdr_resp(struct urb *urb) | |||
| 2717 | { | 2951 | { |
| 2718 | struct pn533_acr122_poweron_rdr_arg *arg = urb->context; | 2952 | struct pn533_acr122_poweron_rdr_arg *arg = urb->context; |
| 2719 | 2953 | ||
| 2720 | nfc_dev_dbg(&urb->dev->dev, "%s", __func__); | 2954 | dev_dbg(&urb->dev->dev, "%s\n", __func__); |
| 2721 | 2955 | ||
| 2722 | print_hex_dump_debug("ACR122 RX: ", DUMP_PREFIX_NONE, 16, 1, | 2956 | print_hex_dump_debug("ACR122 RX: ", DUMP_PREFIX_NONE, 16, 1, |
| 2723 | urb->transfer_buffer, urb->transfer_buffer_length, | 2957 | urb->transfer_buffer, urb->transfer_buffer_length, |
| @@ -2737,7 +2971,7 @@ static int pn533_acr122_poweron_rdr(struct pn533 *dev) | |||
| 2737 | void *cntx; | 2971 | void *cntx; |
| 2738 | struct pn533_acr122_poweron_rdr_arg arg; | 2972 | struct pn533_acr122_poweron_rdr_arg arg; |
| 2739 | 2973 | ||
| 2740 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 2974 | dev_dbg(&dev->interface->dev, "%s\n", __func__); |
| 2741 | 2975 | ||
| 2742 | init_completion(&arg.done); | 2976 | init_completion(&arg.done); |
| 2743 | cntx = dev->in_urb->context; /* backup context */ | 2977 | cntx = dev->in_urb->context; /* backup context */ |
| @@ -2755,16 +2989,15 @@ static int pn533_acr122_poweron_rdr(struct pn533 *dev) | |||
| 2755 | 2989 | ||
| 2756 | rc = usb_submit_urb(dev->out_urb, GFP_KERNEL); | 2990 | rc = usb_submit_urb(dev->out_urb, GFP_KERNEL); |
| 2757 | if (rc) { | 2991 | if (rc) { |
| 2758 | nfc_dev_err(&dev->interface->dev, | 2992 | nfc_err(&dev->interface->dev, |
| 2759 | "Reader power on cmd error %d", rc); | 2993 | "Reader power on cmd error %d\n", rc); |
| 2760 | return rc; | 2994 | return rc; |
| 2761 | } | 2995 | } |
| 2762 | 2996 | ||
| 2763 | rc = usb_submit_urb(dev->in_urb, GFP_KERNEL); | 2997 | rc = usb_submit_urb(dev->in_urb, GFP_KERNEL); |
| 2764 | if (rc) { | 2998 | if (rc) { |
| 2765 | nfc_dev_err(&dev->interface->dev, | 2999 | nfc_err(&dev->interface->dev, |
| 2766 | "Can't submit for reader power on cmd response %d", | 3000 | "Can't submit reader poweron cmd response %d\n", rc); |
| 2767 | rc); | ||
| 2768 | return rc; | 3001 | return rc; |
| 2769 | } | 3002 | } |
| 2770 | 3003 | ||
| @@ -2785,20 +3018,19 @@ static int pn533_rf_field(struct nfc_dev *nfc_dev, u8 rf) | |||
| 2785 | rc = pn533_set_configuration(dev, PN533_CFGITEM_RF_FIELD, | 3018 | rc = pn533_set_configuration(dev, PN533_CFGITEM_RF_FIELD, |
| 2786 | (u8 *)&rf_field, 1); | 3019 | (u8 *)&rf_field, 1); |
| 2787 | if (rc) { | 3020 | if (rc) { |
| 2788 | nfc_dev_err(&dev->interface->dev, | 3021 | nfc_err(&dev->interface->dev, "Error on setting RF field\n"); |
| 2789 | "Error on setting RF field"); | ||
| 2790 | return rc; | 3022 | return rc; |
| 2791 | } | 3023 | } |
| 2792 | 3024 | ||
| 2793 | return rc; | 3025 | return rc; |
| 2794 | } | 3026 | } |
| 2795 | 3027 | ||
| 2796 | int pn533_dev_up(struct nfc_dev *nfc_dev) | 3028 | static int pn533_dev_up(struct nfc_dev *nfc_dev) |
| 2797 | { | 3029 | { |
| 2798 | return pn533_rf_field(nfc_dev, 1); | 3030 | return pn533_rf_field(nfc_dev, 1); |
| 2799 | } | 3031 | } |
| 2800 | 3032 | ||
| 2801 | int pn533_dev_down(struct nfc_dev *nfc_dev) | 3033 | static int pn533_dev_down(struct nfc_dev *nfc_dev) |
| 2802 | { | 3034 | { |
| 2803 | return pn533_rf_field(nfc_dev, 0); | 3035 | return pn533_rf_field(nfc_dev, 0); |
| 2804 | } | 3036 | } |
| @@ -2839,16 +3071,16 @@ static int pn533_setup(struct pn533 *dev) | |||
| 2839 | break; | 3071 | break; |
| 2840 | 3072 | ||
| 2841 | default: | 3073 | default: |
| 2842 | nfc_dev_err(&dev->interface->dev, "Unknown device type %d\n", | 3074 | nfc_err(&dev->interface->dev, "Unknown device type %d\n", |
| 2843 | dev->device_type); | 3075 | dev->device_type); |
| 2844 | return -EINVAL; | 3076 | return -EINVAL; |
| 2845 | } | 3077 | } |
| 2846 | 3078 | ||
| 2847 | rc = pn533_set_configuration(dev, PN533_CFGITEM_MAX_RETRIES, | 3079 | rc = pn533_set_configuration(dev, PN533_CFGITEM_MAX_RETRIES, |
| 2848 | (u8 *)&max_retries, sizeof(max_retries)); | 3080 | (u8 *)&max_retries, sizeof(max_retries)); |
| 2849 | if (rc) { | 3081 | if (rc) { |
| 2850 | nfc_dev_err(&dev->interface->dev, | 3082 | nfc_err(&dev->interface->dev, |
| 2851 | "Error on setting MAX_RETRIES config"); | 3083 | "Error on setting MAX_RETRIES config\n"); |
| 2852 | return rc; | 3084 | return rc; |
| 2853 | } | 3085 | } |
| 2854 | 3086 | ||
| @@ -2856,8 +3088,7 @@ static int pn533_setup(struct pn533 *dev) | |||
| 2856 | rc = pn533_set_configuration(dev, PN533_CFGITEM_TIMING, | 3088 | rc = pn533_set_configuration(dev, PN533_CFGITEM_TIMING, |
| 2857 | (u8 *)&timing, sizeof(timing)); | 3089 | (u8 *)&timing, sizeof(timing)); |
| 2858 | if (rc) { | 3090 | if (rc) { |
| 2859 | nfc_dev_err(&dev->interface->dev, | 3091 | nfc_err(&dev->interface->dev, "Error on setting RF timings\n"); |
| 2860 | "Error on setting RF timings"); | ||
| 2861 | return rc; | 3092 | return rc; |
| 2862 | } | 3093 | } |
| 2863 | 3094 | ||
| @@ -2871,8 +3102,8 @@ static int pn533_setup(struct pn533 *dev) | |||
| 2871 | rc = pn533_set_configuration(dev, PN533_CFGITEM_PASORI, | 3102 | rc = pn533_set_configuration(dev, PN533_CFGITEM_PASORI, |
| 2872 | pasori_cfg, 3); | 3103 | pasori_cfg, 3); |
| 2873 | if (rc) { | 3104 | if (rc) { |
| 2874 | nfc_dev_err(&dev->interface->dev, | 3105 | nfc_err(&dev->interface->dev, |
| 2875 | "Error while settings PASORI config"); | 3106 | "Error while settings PASORI config\n"); |
| 2876 | return rc; | 3107 | return rc; |
| 2877 | } | 3108 | } |
| 2878 | 3109 | ||
| @@ -2917,8 +3148,8 @@ static int pn533_probe(struct usb_interface *interface, | |||
| 2917 | } | 3148 | } |
| 2918 | 3149 | ||
| 2919 | if (!in_endpoint || !out_endpoint) { | 3150 | if (!in_endpoint || !out_endpoint) { |
| 2920 | nfc_dev_err(&interface->dev, | 3151 | nfc_err(&interface->dev, |
| 2921 | "Could not find bulk-in or bulk-out endpoint"); | 3152 | "Could not find bulk-in or bulk-out endpoint\n"); |
| 2922 | rc = -ENODEV; | 3153 | rc = -ENODEV; |
| 2923 | goto error; | 3154 | goto error; |
| 2924 | } | 3155 | } |
| @@ -2941,6 +3172,8 @@ static int pn533_probe(struct usb_interface *interface, | |||
| 2941 | INIT_WORK(&dev->mi_rx_work, pn533_wq_mi_recv); | 3172 | INIT_WORK(&dev->mi_rx_work, pn533_wq_mi_recv); |
| 2942 | INIT_WORK(&dev->mi_tx_work, pn533_wq_mi_send); | 3173 | INIT_WORK(&dev->mi_tx_work, pn533_wq_mi_send); |
| 2943 | INIT_WORK(&dev->tg_work, pn533_wq_tg_get_data); | 3174 | INIT_WORK(&dev->tg_work, pn533_wq_tg_get_data); |
| 3175 | INIT_WORK(&dev->mi_tm_rx_work, pn533_wq_tm_mi_recv); | ||
| 3176 | INIT_WORK(&dev->mi_tm_tx_work, pn533_wq_tm_mi_send); | ||
| 2944 | INIT_DELAYED_WORK(&dev->poll_work, pn533_wq_poll); | 3177 | INIT_DELAYED_WORK(&dev->poll_work, pn533_wq_poll); |
| 2945 | INIT_WORK(&dev->rf_work, pn533_wq_rf); | 3178 | INIT_WORK(&dev->rf_work, pn533_wq_rf); |
| 2946 | dev->wq = alloc_ordered_workqueue("pn533", 0); | 3179 | dev->wq = alloc_ordered_workqueue("pn533", 0); |
| @@ -2978,16 +3211,15 @@ static int pn533_probe(struct usb_interface *interface, | |||
| 2978 | 3211 | ||
| 2979 | rc = pn533_acr122_poweron_rdr(dev); | 3212 | rc = pn533_acr122_poweron_rdr(dev); |
| 2980 | if (rc < 0) { | 3213 | if (rc < 0) { |
| 2981 | nfc_dev_err(&dev->interface->dev, | 3214 | nfc_err(&dev->interface->dev, |
| 2982 | "Couldn't poweron the reader (error %d)", | 3215 | "Couldn't poweron the reader (error %d)\n", rc); |
| 2983 | rc); | ||
| 2984 | goto destroy_wq; | 3216 | goto destroy_wq; |
| 2985 | } | 3217 | } |
| 2986 | break; | 3218 | break; |
| 2987 | 3219 | ||
| 2988 | default: | 3220 | default: |
| 2989 | nfc_dev_err(&dev->interface->dev, "Unknown device type %d\n", | 3221 | nfc_err(&dev->interface->dev, "Unknown device type %d\n", |
| 2990 | dev->device_type); | 3222 | dev->device_type); |
| 2991 | rc = -EINVAL; | 3223 | rc = -EINVAL; |
| 2992 | goto destroy_wq; | 3224 | goto destroy_wq; |
| 2993 | } | 3225 | } |
| @@ -2997,9 +3229,9 @@ static int pn533_probe(struct usb_interface *interface, | |||
| 2997 | if (rc < 0) | 3229 | if (rc < 0) |
| 2998 | goto destroy_wq; | 3230 | goto destroy_wq; |
| 2999 | 3231 | ||
| 3000 | nfc_dev_info(&dev->interface->dev, | 3232 | nfc_info(&dev->interface->dev, |
| 3001 | "NXP PN5%02X firmware ver %d.%d now attached", | 3233 | "NXP PN5%02X firmware ver %d.%d now attached\n", |
| 3002 | fw_ver.ic, fw_ver.ver, fw_ver.rev); | 3234 | fw_ver.ic, fw_ver.ver, fw_ver.rev); |
| 3003 | 3235 | ||
| 3004 | 3236 | ||
| 3005 | dev->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols, | 3237 | dev->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols, |
| @@ -3070,7 +3302,7 @@ static void pn533_disconnect(struct usb_interface *interface) | |||
| 3070 | usb_free_urb(dev->out_urb); | 3302 | usb_free_urb(dev->out_urb); |
| 3071 | kfree(dev); | 3303 | kfree(dev); |
| 3072 | 3304 | ||
| 3073 | nfc_dev_info(&interface->dev, "NXP PN533 NFC device disconnected"); | 3305 | nfc_info(&interface->dev, "NXP PN533 NFC device disconnected\n"); |
| 3074 | } | 3306 | } |
| 3075 | 3307 | ||
| 3076 | static struct usb_driver pn533_driver = { | 3308 | static struct usb_driver pn533_driver = { |
diff --git a/drivers/nfc/pn544/i2c.c b/drivers/nfc/pn544/i2c.c index 01e27d4bdd0d..b158ee1c2ac6 100644 --- a/drivers/nfc/pn544/i2c.c +++ b/drivers/nfc/pn544/i2c.c | |||
| @@ -18,6 +18,8 @@ | |||
| 18 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 18 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 22 | |||
| 21 | #include <linux/crc-ccitt.h> | 23 | #include <linux/crc-ccitt.h> |
| 22 | #include <linux/module.h> | 24 | #include <linux/module.h> |
| 23 | #include <linux/i2c.h> | 25 | #include <linux/i2c.h> |
| @@ -151,8 +153,7 @@ static void pn544_hci_i2c_platform_init(struct pn544_i2c_phy *phy) | |||
| 151 | char rset_cmd[] = { 0x05, 0xF9, 0x04, 0x00, 0xC3, 0xE5 }; | 153 | char rset_cmd[] = { 0x05, 0xF9, 0x04, 0x00, 0xC3, 0xE5 }; |
| 152 | int count = sizeof(rset_cmd); | 154 | int count = sizeof(rset_cmd); |
| 153 | 155 | ||
| 154 | pr_info(DRIVER_DESC ": %s\n", __func__); | 156 | nfc_info(&phy->i2c_dev->dev, "Detecting nfc_en polarity\n"); |
| 155 | dev_info(&phy->i2c_dev->dev, "Detecting nfc_en polarity\n"); | ||
| 156 | 157 | ||
| 157 | /* Disable fw download */ | 158 | /* Disable fw download */ |
| 158 | gpio_set_value(phy->gpio_fw, 0); | 159 | gpio_set_value(phy->gpio_fw, 0); |
| @@ -173,7 +174,7 @@ static void pn544_hci_i2c_platform_init(struct pn544_i2c_phy *phy) | |||
| 173 | dev_dbg(&phy->i2c_dev->dev, "Sending reset cmd\n"); | 174 | dev_dbg(&phy->i2c_dev->dev, "Sending reset cmd\n"); |
| 174 | ret = i2c_master_send(phy->i2c_dev, rset_cmd, count); | 175 | ret = i2c_master_send(phy->i2c_dev, rset_cmd, count); |
| 175 | if (ret == count) { | 176 | if (ret == count) { |
| 176 | dev_info(&phy->i2c_dev->dev, | 177 | nfc_info(&phy->i2c_dev->dev, |
| 177 | "nfc_en polarity : active %s\n", | 178 | "nfc_en polarity : active %s\n", |
| 178 | (polarity == 0 ? "low" : "high")); | 179 | (polarity == 0 ? "low" : "high")); |
| 179 | goto out; | 180 | goto out; |
| @@ -181,7 +182,7 @@ static void pn544_hci_i2c_platform_init(struct pn544_i2c_phy *phy) | |||
| 181 | } | 182 | } |
| 182 | } | 183 | } |
| 183 | 184 | ||
| 184 | dev_err(&phy->i2c_dev->dev, | 185 | nfc_err(&phy->i2c_dev->dev, |
| 185 | "Could not detect nfc_en polarity, fallback to active high\n"); | 186 | "Could not detect nfc_en polarity, fallback to active high\n"); |
| 186 | 187 | ||
| 187 | out: | 188 | out: |
| @@ -201,7 +202,7 @@ static int pn544_hci_i2c_enable(void *phy_id) | |||
| 201 | { | 202 | { |
| 202 | struct pn544_i2c_phy *phy = phy_id; | 203 | struct pn544_i2c_phy *phy = phy_id; |
| 203 | 204 | ||
| 204 | pr_info(DRIVER_DESC ": %s\n", __func__); | 205 | pr_info("%s\n", __func__); |
| 205 | 206 | ||
| 206 | pn544_hci_i2c_enable_mode(phy, PN544_HCI_MODE); | 207 | pn544_hci_i2c_enable_mode(phy, PN544_HCI_MODE); |
| 207 | 208 | ||
| @@ -214,8 +215,6 @@ static void pn544_hci_i2c_disable(void *phy_id) | |||
| 214 | { | 215 | { |
| 215 | struct pn544_i2c_phy *phy = phy_id; | 216 | struct pn544_i2c_phy *phy = phy_id; |
| 216 | 217 | ||
| 217 | pr_info(DRIVER_DESC ": %s\n", __func__); | ||
| 218 | |||
| 219 | gpio_set_value(phy->gpio_fw, 0); | 218 | gpio_set_value(phy->gpio_fw, 0); |
| 220 | gpio_set_value(phy->gpio_en, !phy->en_polarity); | 219 | gpio_set_value(phy->gpio_en, !phy->en_polarity); |
| 221 | usleep_range(10000, 15000); | 220 | usleep_range(10000, 15000); |
| @@ -298,11 +297,9 @@ static int check_crc(u8 *buf, int buflen) | |||
| 298 | crc = ~crc; | 297 | crc = ~crc; |
| 299 | 298 | ||
| 300 | if (buf[len - 2] != (crc & 0xff) || buf[len - 1] != (crc >> 8)) { | 299 | if (buf[len - 2] != (crc & 0xff) || buf[len - 1] != (crc >> 8)) { |
| 301 | pr_err(PN544_HCI_I2C_DRIVER_NAME | 300 | pr_err("CRC error 0x%x != 0x%x 0x%x\n", |
| 302 | ": CRC error 0x%x != 0x%x 0x%x\n", | ||
| 303 | crc, buf[len - 1], buf[len - 2]); | 301 | crc, buf[len - 1], buf[len - 2]); |
| 304 | 302 | pr_info("%s: BAD CRC\n", __func__); | |
| 305 | pr_info(DRIVER_DESC ": %s : BAD CRC\n", __func__); | ||
| 306 | print_hex_dump(KERN_DEBUG, "crc: ", DUMP_PREFIX_NONE, | 303 | print_hex_dump(KERN_DEBUG, "crc: ", DUMP_PREFIX_NONE, |
| 307 | 16, 2, buf, buflen, false); | 304 | 16, 2, buf, buflen, false); |
| 308 | return -EPERM; | 305 | return -EPERM; |
| @@ -328,13 +325,13 @@ static int pn544_hci_i2c_read(struct pn544_i2c_phy *phy, struct sk_buff **skb) | |||
| 328 | 325 | ||
| 329 | r = i2c_master_recv(client, &len, 1); | 326 | r = i2c_master_recv(client, &len, 1); |
| 330 | if (r != 1) { | 327 | if (r != 1) { |
| 331 | dev_err(&client->dev, "cannot read len byte\n"); | 328 | nfc_err(&client->dev, "cannot read len byte\n"); |
| 332 | return -EREMOTEIO; | 329 | return -EREMOTEIO; |
| 333 | } | 330 | } |
| 334 | 331 | ||
| 335 | if ((len < (PN544_HCI_I2C_LLC_MIN_SIZE - 1)) || | 332 | if ((len < (PN544_HCI_I2C_LLC_MIN_SIZE - 1)) || |
| 336 | (len > (PN544_HCI_I2C_LLC_MAX_SIZE - 1))) { | 333 | (len > (PN544_HCI_I2C_LLC_MAX_SIZE - 1))) { |
| 337 | dev_err(&client->dev, "invalid len byte\n"); | 334 | nfc_err(&client->dev, "invalid len byte\n"); |
| 338 | r = -EBADMSG; | 335 | r = -EBADMSG; |
| 339 | goto flush; | 336 | goto flush; |
| 340 | } | 337 | } |
| @@ -386,7 +383,7 @@ static int pn544_hci_i2c_fw_read_status(struct pn544_i2c_phy *phy) | |||
| 386 | 383 | ||
| 387 | r = i2c_master_recv(client, (char *) &response, sizeof(response)); | 384 | r = i2c_master_recv(client, (char *) &response, sizeof(response)); |
| 388 | if (r != sizeof(response)) { | 385 | if (r != sizeof(response)) { |
| 389 | dev_err(&client->dev, "cannot read fw status\n"); | 386 | nfc_err(&client->dev, "cannot read fw status\n"); |
| 390 | return -EIO; | 387 | return -EIO; |
| 391 | } | 388 | } |
| 392 | 389 | ||
| @@ -478,8 +475,7 @@ static int pn544_hci_i2c_fw_download(void *phy_id, const char *firmware_name) | |||
| 478 | { | 475 | { |
| 479 | struct pn544_i2c_phy *phy = phy_id; | 476 | struct pn544_i2c_phy *phy = phy_id; |
| 480 | 477 | ||
| 481 | pr_info(DRIVER_DESC ": Starting Firmware Download (%s)\n", | 478 | pr_info("Starting Firmware Download (%s)\n", firmware_name); |
| 482 | firmware_name); | ||
| 483 | 479 | ||
| 484 | strcpy(phy->firmware_name, firmware_name); | 480 | strcpy(phy->firmware_name, firmware_name); |
| 485 | 481 | ||
| @@ -493,7 +489,7 @@ static int pn544_hci_i2c_fw_download(void *phy_id, const char *firmware_name) | |||
| 493 | static void pn544_hci_i2c_fw_work_complete(struct pn544_i2c_phy *phy, | 489 | static void pn544_hci_i2c_fw_work_complete(struct pn544_i2c_phy *phy, |
| 494 | int result) | 490 | int result) |
| 495 | { | 491 | { |
| 496 | pr_info(DRIVER_DESC ": Firmware Download Complete, result=%d\n", result); | 492 | pr_info("Firmware Download Complete, result=%d\n", result); |
| 497 | 493 | ||
| 498 | pn544_hci_i2c_disable(phy); | 494 | pn544_hci_i2c_disable(phy); |
| 499 | 495 | ||
| @@ -694,14 +690,14 @@ static int pn544_hci_i2c_probe(struct i2c_client *client, | |||
| 694 | dev_dbg(&client->dev, "IRQ: %d\n", client->irq); | 690 | dev_dbg(&client->dev, "IRQ: %d\n", client->irq); |
| 695 | 691 | ||
| 696 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | 692 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { |
| 697 | dev_err(&client->dev, "Need I2C_FUNC_I2C\n"); | 693 | nfc_err(&client->dev, "Need I2C_FUNC_I2C\n"); |
| 698 | return -ENODEV; | 694 | return -ENODEV; |
| 699 | } | 695 | } |
| 700 | 696 | ||
| 701 | phy = devm_kzalloc(&client->dev, sizeof(struct pn544_i2c_phy), | 697 | phy = devm_kzalloc(&client->dev, sizeof(struct pn544_i2c_phy), |
| 702 | GFP_KERNEL); | 698 | GFP_KERNEL); |
| 703 | if (!phy) { | 699 | if (!phy) { |
| 704 | dev_err(&client->dev, | 700 | nfc_err(&client->dev, |
| 705 | "Cannot allocate memory for pn544 i2c phy.\n"); | 701 | "Cannot allocate memory for pn544 i2c phy.\n"); |
| 706 | return -ENOMEM; | 702 | return -ENOMEM; |
| 707 | } | 703 | } |
| @@ -714,18 +710,18 @@ static int pn544_hci_i2c_probe(struct i2c_client *client, | |||
| 714 | 710 | ||
| 715 | pdata = client->dev.platform_data; | 711 | pdata = client->dev.platform_data; |
| 716 | if (pdata == NULL) { | 712 | if (pdata == NULL) { |
| 717 | dev_err(&client->dev, "No platform data\n"); | 713 | nfc_err(&client->dev, "No platform data\n"); |
| 718 | return -EINVAL; | 714 | return -EINVAL; |
| 719 | } | 715 | } |
| 720 | 716 | ||
| 721 | if (pdata->request_resources == NULL) { | 717 | if (pdata->request_resources == NULL) { |
| 722 | dev_err(&client->dev, "request_resources() missing\n"); | 718 | nfc_err(&client->dev, "request_resources() missing\n"); |
| 723 | return -EINVAL; | 719 | return -EINVAL; |
| 724 | } | 720 | } |
| 725 | 721 | ||
| 726 | r = pdata->request_resources(client); | 722 | r = pdata->request_resources(client); |
| 727 | if (r) { | 723 | if (r) { |
| 728 | dev_err(&client->dev, "Cannot get platform resources\n"); | 724 | nfc_err(&client->dev, "Cannot get platform resources\n"); |
| 729 | return r; | 725 | return r; |
| 730 | } | 726 | } |
| 731 | 727 | ||
| @@ -739,7 +735,7 @@ static int pn544_hci_i2c_probe(struct i2c_client *client, | |||
| 739 | IRQF_TRIGGER_RISING | IRQF_ONESHOT, | 735 | IRQF_TRIGGER_RISING | IRQF_ONESHOT, |
| 740 | PN544_HCI_I2C_DRIVER_NAME, phy); | 736 | PN544_HCI_I2C_DRIVER_NAME, phy); |
| 741 | if (r < 0) { | 737 | if (r < 0) { |
| 742 | dev_err(&client->dev, "Unable to register IRQ handler\n"); | 738 | nfc_err(&client->dev, "Unable to register IRQ handler\n"); |
| 743 | goto err_rti; | 739 | goto err_rti; |
| 744 | } | 740 | } |
| 745 | 741 | ||
diff --git a/drivers/nfc/pn544/pn544.c b/drivers/nfc/pn544/pn544.c index 078e62feba17..74cfa0a88b9e 100644 --- a/drivers/nfc/pn544/pn544.c +++ b/drivers/nfc/pn544/pn544.c | |||
| @@ -18,6 +18,8 @@ | |||
| 18 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 18 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 22 | |||
| 21 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
| 22 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
| 23 | #include <linux/module.h> | 25 | #include <linux/module.h> |
| @@ -41,6 +43,7 @@ enum pn544_state { | |||
| 41 | 43 | ||
| 42 | /* Proprietary commands */ | 44 | /* Proprietary commands */ |
| 43 | #define PN544_WRITE 0x3f | 45 | #define PN544_WRITE 0x3f |
| 46 | #define PN544_TEST_SWP 0x21 | ||
| 44 | 47 | ||
| 45 | /* Proprietary gates, events, commands and registers */ | 48 | /* Proprietary gates, events, commands and registers */ |
| 46 | 49 | ||
| @@ -81,14 +84,17 @@ enum pn544_state { | |||
| 81 | #define PN544_PL_NFCT_DEACTIVATED 0x09 | 84 | #define PN544_PL_NFCT_DEACTIVATED 0x09 |
| 82 | 85 | ||
| 83 | #define PN544_SWP_MGMT_GATE 0xA0 | 86 | #define PN544_SWP_MGMT_GATE 0xA0 |
| 87 | #define PN544_SWP_DEFAULT_MODE 0x01 | ||
| 84 | 88 | ||
| 85 | #define PN544_NFC_WI_MGMT_GATE 0xA1 | 89 | #define PN544_NFC_WI_MGMT_GATE 0xA1 |
| 90 | #define PN544_NFC_ESE_DEFAULT_MODE 0x01 | ||
| 86 | 91 | ||
| 87 | #define PN544_HCI_EVT_SND_DATA 0x01 | 92 | #define PN544_HCI_EVT_SND_DATA 0x01 |
| 88 | #define PN544_HCI_EVT_ACTIVATED 0x02 | 93 | #define PN544_HCI_EVT_ACTIVATED 0x02 |
| 89 | #define PN544_HCI_EVT_DEACTIVATED 0x03 | 94 | #define PN544_HCI_EVT_DEACTIVATED 0x03 |
| 90 | #define PN544_HCI_EVT_RCV_DATA 0x04 | 95 | #define PN544_HCI_EVT_RCV_DATA 0x04 |
| 91 | #define PN544_HCI_EVT_CONTINUE_MI 0x05 | 96 | #define PN544_HCI_EVT_CONTINUE_MI 0x05 |
| 97 | #define PN544_HCI_EVT_SWITCH_MODE 0x03 | ||
| 92 | 98 | ||
| 93 | #define PN544_HCI_CMD_ATTREQUEST 0x12 | 99 | #define PN544_HCI_CMD_ATTREQUEST 0x12 |
| 94 | #define PN544_HCI_CMD_CONTINUE_ACTIVATION 0x13 | 100 | #define PN544_HCI_CMD_CONTINUE_ACTIVATION 0x13 |
| @@ -187,13 +193,6 @@ static int pn544_hci_ready(struct nfc_hci_dev *hdev) | |||
| 187 | 193 | ||
| 188 | {{0x9e, 0xb4}, 0x00}, | 194 | {{0x9e, 0xb4}, 0x00}, |
| 189 | 195 | ||
| 190 | {{0x9e, 0xd9}, 0xff}, | ||
| 191 | {{0x9e, 0xda}, 0xff}, | ||
| 192 | {{0x9e, 0xdb}, 0x23}, | ||
| 193 | {{0x9e, 0xdc}, 0x21}, | ||
| 194 | {{0x9e, 0xdd}, 0x22}, | ||
| 195 | {{0x9e, 0xde}, 0x24}, | ||
| 196 | |||
| 197 | {{0x9c, 0x01}, 0x08}, | 196 | {{0x9c, 0x01}, 0x08}, |
| 198 | 197 | ||
| 199 | {{0x9e, 0xaa}, 0x01}, | 198 | {{0x9e, 0xaa}, 0x01}, |
| @@ -394,7 +393,7 @@ static int pn544_hci_start_poll(struct nfc_hci_dev *hdev, | |||
| 394 | if ((im_protocols | tm_protocols) & NFC_PROTO_NFC_DEP_MASK) { | 393 | if ((im_protocols | tm_protocols) & NFC_PROTO_NFC_DEP_MASK) { |
| 395 | hdev->gb = nfc_get_local_general_bytes(hdev->ndev, | 394 | hdev->gb = nfc_get_local_general_bytes(hdev->ndev, |
| 396 | &hdev->gb_len); | 395 | &hdev->gb_len); |
| 397 | pr_debug("generate local bytes %p", hdev->gb); | 396 | pr_debug("generate local bytes %p\n", hdev->gb); |
| 398 | if (hdev->gb == NULL || hdev->gb_len == 0) { | 397 | if (hdev->gb == NULL || hdev->gb_len == 0) { |
| 399 | im_protocols &= ~NFC_PROTO_NFC_DEP_MASK; | 398 | im_protocols &= ~NFC_PROTO_NFC_DEP_MASK; |
| 400 | tm_protocols &= ~NFC_PROTO_NFC_DEP_MASK; | 399 | tm_protocols &= ~NFC_PROTO_NFC_DEP_MASK; |
| @@ -696,7 +695,7 @@ static int pn544_hci_tm_send(struct nfc_hci_dev *hdev, struct sk_buff *skb) | |||
| 696 | static int pn544_hci_check_presence(struct nfc_hci_dev *hdev, | 695 | static int pn544_hci_check_presence(struct nfc_hci_dev *hdev, |
| 697 | struct nfc_target *target) | 696 | struct nfc_target *target) |
| 698 | { | 697 | { |
| 699 | pr_debug("supported protocol %d", target->supported_protocols); | 698 | pr_debug("supported protocol %d\b", target->supported_protocols); |
| 700 | if (target->supported_protocols & (NFC_PROTO_ISO14443_MASK | | 699 | if (target->supported_protocols & (NFC_PROTO_ISO14443_MASK | |
| 701 | NFC_PROTO_ISO14443_B_MASK)) { | 700 | NFC_PROTO_ISO14443_B_MASK)) { |
| 702 | return nfc_hci_send_cmd(hdev, target->hci_reader_gate, | 701 | return nfc_hci_send_cmd(hdev, target->hci_reader_gate, |
| @@ -733,7 +732,7 @@ static int pn544_hci_event_received(struct nfc_hci_dev *hdev, u8 gate, u8 event, | |||
| 733 | struct sk_buff *rgb_skb = NULL; | 732 | struct sk_buff *rgb_skb = NULL; |
| 734 | int r; | 733 | int r; |
| 735 | 734 | ||
| 736 | pr_debug("hci event %d", event); | 735 | pr_debug("hci event %d\n", event); |
| 737 | switch (event) { | 736 | switch (event) { |
| 738 | case PN544_HCI_EVT_ACTIVATED: | 737 | case PN544_HCI_EVT_ACTIVATED: |
| 739 | if (gate == PN544_RF_READER_NFCIP1_INITIATOR_GATE) { | 738 | if (gate == PN544_RF_READER_NFCIP1_INITIATOR_GATE) { |
| @@ -764,7 +763,7 @@ static int pn544_hci_event_received(struct nfc_hci_dev *hdev, u8 gate, u8 event, | |||
| 764 | } | 763 | } |
| 765 | 764 | ||
| 766 | if (skb->data[0] != 0) { | 765 | if (skb->data[0] != 0) { |
| 767 | pr_debug("data0 %d", skb->data[0]); | 766 | pr_debug("data0 %d\n", skb->data[0]); |
| 768 | r = -EPROTO; | 767 | r = -EPROTO; |
| 769 | goto exit; | 768 | goto exit; |
| 770 | } | 769 | } |
| @@ -792,6 +791,108 @@ static int pn544_hci_fw_download(struct nfc_hci_dev *hdev, | |||
| 792 | return info->fw_download(info->phy_id, firmware_name); | 791 | return info->fw_download(info->phy_id, firmware_name); |
| 793 | } | 792 | } |
| 794 | 793 | ||
| 794 | static int pn544_hci_discover_se(struct nfc_hci_dev *hdev) | ||
| 795 | { | ||
| 796 | u32 se_idx = 0; | ||
| 797 | u8 ese_mode = 0x01; /* Default mode */ | ||
| 798 | struct sk_buff *res_skb; | ||
| 799 | int r; | ||
| 800 | |||
| 801 | r = nfc_hci_send_cmd(hdev, PN544_SYS_MGMT_GATE, PN544_TEST_SWP, | ||
| 802 | NULL, 0, &res_skb); | ||
| 803 | |||
| 804 | if (r == 0) { | ||
| 805 | if (res_skb->len == 2 && res_skb->data[0] == 0x00) | ||
| 806 | nfc_add_se(hdev->ndev, se_idx++, NFC_SE_UICC); | ||
| 807 | |||
| 808 | kfree_skb(res_skb); | ||
| 809 | } | ||
| 810 | |||
| 811 | r = nfc_hci_send_event(hdev, PN544_NFC_WI_MGMT_GATE, | ||
| 812 | PN544_HCI_EVT_SWITCH_MODE, | ||
| 813 | &ese_mode, 1); | ||
| 814 | if (r == 0) | ||
| 815 | nfc_add_se(hdev->ndev, se_idx++, NFC_SE_EMBEDDED); | ||
| 816 | |||
| 817 | return !se_idx; | ||
| 818 | } | ||
| 819 | |||
| 820 | #define PN544_SE_MODE_OFF 0x00 | ||
| 821 | #define PN544_SE_MODE_ON 0x01 | ||
| 822 | static int pn544_hci_enable_se(struct nfc_hci_dev *hdev, u32 se_idx) | ||
| 823 | { | ||
| 824 | struct nfc_se *se; | ||
| 825 | u8 enable = PN544_SE_MODE_ON; | ||
| 826 | static struct uicc_gatelist { | ||
| 827 | u8 head; | ||
| 828 | u8 adr[2]; | ||
| 829 | u8 value; | ||
| 830 | } uicc_gatelist[] = { | ||
| 831 | {0x00, {0x9e, 0xd9}, 0x23}, | ||
| 832 | {0x00, {0x9e, 0xda}, 0x21}, | ||
| 833 | {0x00, {0x9e, 0xdb}, 0x22}, | ||
| 834 | {0x00, {0x9e, 0xdc}, 0x24}, | ||
| 835 | }; | ||
| 836 | struct uicc_gatelist *p = uicc_gatelist; | ||
| 837 | int count = ARRAY_SIZE(uicc_gatelist); | ||
| 838 | struct sk_buff *res_skb; | ||
| 839 | int r; | ||
| 840 | |||
| 841 | se = nfc_find_se(hdev->ndev, se_idx); | ||
| 842 | |||
| 843 | switch (se->type) { | ||
| 844 | case NFC_SE_UICC: | ||
| 845 | while (count--) { | ||
| 846 | r = nfc_hci_send_cmd(hdev, PN544_SYS_MGMT_GATE, | ||
| 847 | PN544_WRITE, (u8 *)p, 4, &res_skb); | ||
| 848 | if (r < 0) | ||
| 849 | return r; | ||
| 850 | |||
| 851 | if (res_skb->len != 1) { | ||
| 852 | kfree_skb(res_skb); | ||
| 853 | return -EPROTO; | ||
| 854 | } | ||
| 855 | |||
| 856 | if (res_skb->data[0] != p->value) { | ||
| 857 | kfree_skb(res_skb); | ||
| 858 | return -EIO; | ||
| 859 | } | ||
| 860 | |||
| 861 | kfree_skb(res_skb); | ||
| 862 | |||
| 863 | p++; | ||
| 864 | } | ||
| 865 | |||
| 866 | return nfc_hci_set_param(hdev, PN544_SWP_MGMT_GATE, | ||
| 867 | PN544_SWP_DEFAULT_MODE, &enable, 1); | ||
| 868 | case NFC_SE_EMBEDDED: | ||
| 869 | return nfc_hci_set_param(hdev, PN544_NFC_WI_MGMT_GATE, | ||
| 870 | PN544_NFC_ESE_DEFAULT_MODE, &enable, 1); | ||
| 871 | |||
| 872 | default: | ||
| 873 | return -EINVAL; | ||
| 874 | } | ||
| 875 | } | ||
| 876 | |||
| 877 | static int pn544_hci_disable_se(struct nfc_hci_dev *hdev, u32 se_idx) | ||
| 878 | { | ||
| 879 | struct nfc_se *se; | ||
| 880 | u8 disable = PN544_SE_MODE_OFF; | ||
| 881 | |||
| 882 | se = nfc_find_se(hdev->ndev, se_idx); | ||
| 883 | |||
| 884 | switch (se->type) { | ||
| 885 | case NFC_SE_UICC: | ||
| 886 | return nfc_hci_set_param(hdev, PN544_SWP_MGMT_GATE, | ||
| 887 | PN544_SWP_DEFAULT_MODE, &disable, 1); | ||
| 888 | case NFC_SE_EMBEDDED: | ||
| 889 | return nfc_hci_set_param(hdev, PN544_NFC_WI_MGMT_GATE, | ||
| 890 | PN544_NFC_ESE_DEFAULT_MODE, &disable, 1); | ||
| 891 | default: | ||
| 892 | return -EINVAL; | ||
| 893 | } | ||
| 894 | } | ||
| 895 | |||
| 795 | static struct nfc_hci_ops pn544_hci_ops = { | 896 | static struct nfc_hci_ops pn544_hci_ops = { |
| 796 | .open = pn544_hci_open, | 897 | .open = pn544_hci_open, |
| 797 | .close = pn544_hci_close, | 898 | .close = pn544_hci_close, |
| @@ -807,6 +908,9 @@ static struct nfc_hci_ops pn544_hci_ops = { | |||
| 807 | .check_presence = pn544_hci_check_presence, | 908 | .check_presence = pn544_hci_check_presence, |
| 808 | .event_received = pn544_hci_event_received, | 909 | .event_received = pn544_hci_event_received, |
| 809 | .fw_download = pn544_hci_fw_download, | 910 | .fw_download = pn544_hci_fw_download, |
| 911 | .discover_se = pn544_hci_discover_se, | ||
| 912 | .enable_se = pn544_hci_enable_se, | ||
| 913 | .disable_se = pn544_hci_disable_se, | ||
| 810 | }; | 914 | }; |
| 811 | 915 | ||
| 812 | int pn544_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name, | 916 | int pn544_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name, |
| @@ -820,7 +924,6 @@ int pn544_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name, | |||
| 820 | 924 | ||
| 821 | info = kzalloc(sizeof(struct pn544_hci_info), GFP_KERNEL); | 925 | info = kzalloc(sizeof(struct pn544_hci_info), GFP_KERNEL); |
| 822 | if (!info) { | 926 | if (!info) { |
| 823 | pr_err("Cannot allocate memory for pn544_hci_info.\n"); | ||
| 824 | r = -ENOMEM; | 927 | r = -ENOMEM; |
| 825 | goto err_info_alloc; | 928 | goto err_info_alloc; |
| 826 | } | 929 | } |
| @@ -853,7 +956,7 @@ int pn544_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name, | |||
| 853 | phy_headroom + PN544_CMDS_HEADROOM, | 956 | phy_headroom + PN544_CMDS_HEADROOM, |
| 854 | phy_tailroom, phy_payload); | 957 | phy_tailroom, phy_payload); |
| 855 | if (!info->hdev) { | 958 | if (!info->hdev) { |
| 856 | pr_err("Cannot allocate nfc hdev.\n"); | 959 | pr_err("Cannot allocate nfc hdev\n"); |
| 857 | r = -ENOMEM; | 960 | r = -ENOMEM; |
| 858 | goto err_alloc_hdev; | 961 | goto err_alloc_hdev; |
| 859 | } | 962 | } |
diff --git a/drivers/nfc/port100.c b/drivers/nfc/port100.c new file mode 100644 index 000000000000..8a0571eb2627 --- /dev/null +++ b/drivers/nfc/port100.c | |||
| @@ -0,0 +1,1529 @@ | |||
| 1 | /* | ||
| 2 | * Sony NFC Port-100 Series driver | ||
| 3 | * Copyright (c) 2013, Intel Corporation. | ||
| 4 | * | ||
| 5 | * Partly based/Inspired by Stephen Tiedemann's nfcpy | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms and conditions of the GNU General Public License, | ||
| 9 | * version 2, as published by the Free Software Foundation. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
| 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 14 | * more details. | ||
| 15 | * | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <linux/module.h> | ||
| 19 | #include <linux/usb.h> | ||
| 20 | #include <net/nfc/digital.h> | ||
| 21 | |||
| 22 | #define VERSION "0.1" | ||
| 23 | |||
| 24 | #define SONY_VENDOR_ID 0x054c | ||
| 25 | #define RCS380_PRODUCT_ID 0x06c1 | ||
| 26 | |||
| 27 | #define PORT100_PROTOCOLS (NFC_PROTO_JEWEL_MASK | \ | ||
| 28 | NFC_PROTO_MIFARE_MASK | \ | ||
| 29 | NFC_PROTO_FELICA_MASK | \ | ||
| 30 | NFC_PROTO_NFC_DEP_MASK) | ||
| 31 | |||
| 32 | #define PORT100_CAPABILITIES (NFC_DIGITAL_DRV_CAPS_IN_CRC | \ | ||
| 33 | NFC_DIGITAL_DRV_CAPS_TG_CRC) | ||
| 34 | |||
| 35 | /* Standard port100 frame definitions */ | ||
| 36 | #define PORT100_FRAME_HEADER_LEN (sizeof(struct port100_frame) \ | ||
| 37 | + 2) /* data[0] CC, data[1] SCC */ | ||
| 38 | #define PORT100_FRAME_TAIL_LEN 2 /* data[len] DCS, data[len + 1] postamble*/ | ||
| 39 | |||
| 40 | #define PORT100_COMM_RF_HEAD_MAX_LEN (sizeof(struct port100_tg_comm_rf_cmd)) | ||
| 41 | |||
| 42 | /* | ||
| 43 | * Max extended frame payload len, excluding CC and SCC | ||
| 44 | * which are already in PORT100_FRAME_HEADER_LEN. | ||
| 45 | */ | ||
| 46 | #define PORT100_FRAME_MAX_PAYLOAD_LEN 1001 | ||
| 47 | |||
| 48 | #define PORT100_FRAME_ACK_SIZE 6 /* Preamble (1), SoPC (2), ACK Code (2), | ||
| 49 | Postamble (1) */ | ||
| 50 | static u8 ack_frame[PORT100_FRAME_ACK_SIZE] = { | ||
| 51 | 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 | ||
| 52 | }; | ||
| 53 | |||
| 54 | #define PORT100_FRAME_CHECKSUM(f) (f->data[le16_to_cpu(f->datalen)]) | ||
| 55 | #define PORT100_FRAME_POSTAMBLE(f) (f->data[le16_to_cpu(f->datalen) + 1]) | ||
| 56 | |||
| 57 | /* start of frame */ | ||
| 58 | #define PORT100_FRAME_SOF 0x00FF | ||
| 59 | #define PORT100_FRAME_EXT 0xFFFF | ||
| 60 | #define PORT100_FRAME_ACK 0x00FF | ||
| 61 | |||
| 62 | /* Port-100 command: in or out */ | ||
| 63 | #define PORT100_FRAME_DIRECTION(f) (f->data[0]) /* CC */ | ||
| 64 | #define PORT100_FRAME_DIR_OUT 0xD6 | ||
| 65 | #define PORT100_FRAME_DIR_IN 0xD7 | ||
| 66 | |||
| 67 | /* Port-100 sub-command */ | ||
| 68 | #define PORT100_FRAME_CMD(f) (f->data[1]) /* SCC */ | ||
| 69 | |||
| 70 | #define PORT100_CMD_GET_FIRMWARE_VERSION 0x20 | ||
| 71 | #define PORT100_CMD_GET_COMMAND_TYPE 0x28 | ||
| 72 | #define PORT100_CMD_SET_COMMAND_TYPE 0x2A | ||
| 73 | |||
| 74 | #define PORT100_CMD_IN_SET_RF 0x00 | ||
| 75 | #define PORT100_CMD_IN_SET_PROTOCOL 0x02 | ||
| 76 | #define PORT100_CMD_IN_COMM_RF 0x04 | ||
| 77 | |||
| 78 | #define PORT100_CMD_TG_SET_RF 0x40 | ||
| 79 | #define PORT100_CMD_TG_SET_PROTOCOL 0x42 | ||
| 80 | #define PORT100_CMD_TG_SET_RF_OFF 0x46 | ||
| 81 | #define PORT100_CMD_TG_COMM_RF 0x48 | ||
| 82 | |||
| 83 | #define PORT100_CMD_SWITCH_RF 0x06 | ||
| 84 | |||
| 85 | #define PORT100_CMD_RESPONSE(cmd) (cmd + 1) | ||
| 86 | |||
| 87 | #define PORT100_CMD_TYPE_IS_SUPPORTED(mask, cmd_type) \ | ||
| 88 | ((mask) & (0x01 << (cmd_type))) | ||
| 89 | #define PORT100_CMD_TYPE_0 0 | ||
| 90 | #define PORT100_CMD_TYPE_1 1 | ||
| 91 | |||
| 92 | #define PORT100_CMD_STATUS_OK 0x00 | ||
| 93 | #define PORT100_CMD_STATUS_TIMEOUT 0x80 | ||
| 94 | |||
| 95 | #define PORT100_MDAA_TGT_HAS_BEEN_ACTIVATED_MASK 0x01 | ||
| 96 | #define PORT100_MDAA_TGT_WAS_ACTIVATED_MASK 0x02 | ||
| 97 | |||
| 98 | struct port100; | ||
| 99 | |||
| 100 | typedef void (*port100_send_async_complete_t)(struct port100 *dev, void *arg, | ||
| 101 | struct sk_buff *resp); | ||
| 102 | |||
| 103 | /** | ||
| 104 | * Setting sets structure for in_set_rf command | ||
| 105 | * | ||
| 106 | * @in_*_set_number: Represent the entry indexes in the port-100 RF Base Table. | ||
| 107 | * This table contains multiple RF setting sets required for RF | ||
| 108 | * communication. | ||
| 109 | * | ||
| 110 | * @in_*_comm_type: Theses fields set the communication type to be used. | ||
| 111 | */ | ||
| 112 | struct port100_in_rf_setting { | ||
| 113 | u8 in_send_set_number; | ||
| 114 | u8 in_send_comm_type; | ||
| 115 | u8 in_recv_set_number; | ||
| 116 | u8 in_recv_comm_type; | ||
| 117 | } __packed; | ||
| 118 | |||
| 119 | #define PORT100_COMM_TYPE_IN_212F 0x01 | ||
| 120 | #define PORT100_COMM_TYPE_IN_424F 0x02 | ||
| 121 | #define PORT100_COMM_TYPE_IN_106A 0x03 | ||
| 122 | |||
| 123 | static const struct port100_in_rf_setting in_rf_settings[] = { | ||
| 124 | [NFC_DIGITAL_RF_TECH_212F] = { | ||
| 125 | .in_send_set_number = 1, | ||
| 126 | .in_send_comm_type = PORT100_COMM_TYPE_IN_212F, | ||
| 127 | .in_recv_set_number = 15, | ||
| 128 | .in_recv_comm_type = PORT100_COMM_TYPE_IN_212F, | ||
| 129 | }, | ||
| 130 | [NFC_DIGITAL_RF_TECH_424F] = { | ||
| 131 | .in_send_set_number = 1, | ||
| 132 | .in_send_comm_type = PORT100_COMM_TYPE_IN_424F, | ||
| 133 | .in_recv_set_number = 15, | ||
| 134 | .in_recv_comm_type = PORT100_COMM_TYPE_IN_424F, | ||
| 135 | }, | ||
| 136 | [NFC_DIGITAL_RF_TECH_106A] = { | ||
| 137 | .in_send_set_number = 2, | ||
| 138 | .in_send_comm_type = PORT100_COMM_TYPE_IN_106A, | ||
| 139 | .in_recv_set_number = 15, | ||
| 140 | .in_recv_comm_type = PORT100_COMM_TYPE_IN_106A, | ||
| 141 | }, | ||
| 142 | }; | ||
| 143 | |||
| 144 | /** | ||
| 145 | * Setting sets structure for tg_set_rf command | ||
| 146 | * | ||
| 147 | * @tg_set_number: Represents the entry index in the port-100 RF Base Table. | ||
| 148 | * This table contains multiple RF setting sets required for RF | ||
| 149 | * communication. this field is used for both send and receive | ||
| 150 | * settings. | ||
| 151 | * | ||
| 152 | * @tg_comm_type: Sets the communication type to be used to send and receive | ||
| 153 | * data. | ||
| 154 | */ | ||
| 155 | struct port100_tg_rf_setting { | ||
| 156 | u8 tg_set_number; | ||
| 157 | u8 tg_comm_type; | ||
| 158 | } __packed; | ||
| 159 | |||
| 160 | #define PORT100_COMM_TYPE_TG_106A 0x0B | ||
| 161 | #define PORT100_COMM_TYPE_TG_212F 0x0C | ||
| 162 | #define PORT100_COMM_TYPE_TG_424F 0x0D | ||
| 163 | |||
| 164 | static const struct port100_tg_rf_setting tg_rf_settings[] = { | ||
| 165 | [NFC_DIGITAL_RF_TECH_106A] = { | ||
| 166 | .tg_set_number = 8, | ||
| 167 | .tg_comm_type = PORT100_COMM_TYPE_TG_106A, | ||
| 168 | }, | ||
| 169 | [NFC_DIGITAL_RF_TECH_212F] = { | ||
| 170 | .tg_set_number = 8, | ||
| 171 | .tg_comm_type = PORT100_COMM_TYPE_TG_212F, | ||
| 172 | }, | ||
| 173 | [NFC_DIGITAL_RF_TECH_424F] = { | ||
| 174 | .tg_set_number = 8, | ||
| 175 | .tg_comm_type = PORT100_COMM_TYPE_TG_424F, | ||
| 176 | }, | ||
| 177 | }; | ||
| 178 | |||
| 179 | #define PORT100_IN_PROT_INITIAL_GUARD_TIME 0x00 | ||
| 180 | #define PORT100_IN_PROT_ADD_CRC 0x01 | ||
| 181 | #define PORT100_IN_PROT_CHECK_CRC 0x02 | ||
| 182 | #define PORT100_IN_PROT_MULTI_CARD 0x03 | ||
| 183 | #define PORT100_IN_PROT_ADD_PARITY 0x04 | ||
| 184 | #define PORT100_IN_PROT_CHECK_PARITY 0x05 | ||
| 185 | #define PORT100_IN_PROT_BITWISE_AC_RECV_MODE 0x06 | ||
| 186 | #define PORT100_IN_PROT_VALID_BIT_NUMBER 0x07 | ||
| 187 | #define PORT100_IN_PROT_CRYPTO1 0x08 | ||
| 188 | #define PORT100_IN_PROT_ADD_SOF 0x09 | ||
| 189 | #define PORT100_IN_PROT_CHECK_SOF 0x0A | ||
| 190 | #define PORT100_IN_PROT_ADD_EOF 0x0B | ||
| 191 | #define PORT100_IN_PROT_CHECK_EOF 0x0C | ||
| 192 | #define PORT100_IN_PROT_DEAF_TIME 0x0E | ||
| 193 | #define PORT100_IN_PROT_CRM 0x0F | ||
| 194 | #define PORT100_IN_PROT_CRM_MIN_LEN 0x10 | ||
| 195 | #define PORT100_IN_PROT_T1_TAG_FRAME 0x11 | ||
| 196 | #define PORT100_IN_PROT_RFCA 0x12 | ||
| 197 | #define PORT100_IN_PROT_GUARD_TIME_AT_INITIATOR 0x13 | ||
| 198 | #define PORT100_IN_PROT_END 0x14 | ||
| 199 | |||
| 200 | #define PORT100_IN_MAX_NUM_PROTOCOLS 19 | ||
| 201 | |||
| 202 | #define PORT100_TG_PROT_TU 0x00 | ||
| 203 | #define PORT100_TG_PROT_RF_OFF 0x01 | ||
| 204 | #define PORT100_TG_PROT_CRM 0x02 | ||
| 205 | #define PORT100_TG_PROT_END 0x03 | ||
| 206 | |||
| 207 | #define PORT100_TG_MAX_NUM_PROTOCOLS 3 | ||
| 208 | |||
| 209 | struct port100_protocol { | ||
| 210 | u8 number; | ||
| 211 | u8 value; | ||
| 212 | } __packed; | ||
| 213 | |||
| 214 | static struct port100_protocol | ||
| 215 | in_protocols[][PORT100_IN_MAX_NUM_PROTOCOLS + 1] = { | ||
| 216 | [NFC_DIGITAL_FRAMING_NFCA_SHORT] = { | ||
| 217 | { PORT100_IN_PROT_INITIAL_GUARD_TIME, 6 }, | ||
| 218 | { PORT100_IN_PROT_ADD_CRC, 0 }, | ||
| 219 | { PORT100_IN_PROT_CHECK_CRC, 0 }, | ||
| 220 | { PORT100_IN_PROT_MULTI_CARD, 0 }, | ||
| 221 | { PORT100_IN_PROT_ADD_PARITY, 0 }, | ||
| 222 | { PORT100_IN_PROT_CHECK_PARITY, 1 }, | ||
| 223 | { PORT100_IN_PROT_BITWISE_AC_RECV_MODE, 0 }, | ||
| 224 | { PORT100_IN_PROT_VALID_BIT_NUMBER, 7 }, | ||
| 225 | { PORT100_IN_PROT_CRYPTO1, 0 }, | ||
| 226 | { PORT100_IN_PROT_ADD_SOF, 0 }, | ||
| 227 | { PORT100_IN_PROT_CHECK_SOF, 0 }, | ||
| 228 | { PORT100_IN_PROT_ADD_EOF, 0 }, | ||
| 229 | { PORT100_IN_PROT_CHECK_EOF, 0 }, | ||
| 230 | { PORT100_IN_PROT_DEAF_TIME, 4 }, | ||
| 231 | { PORT100_IN_PROT_CRM, 0 }, | ||
| 232 | { PORT100_IN_PROT_CRM_MIN_LEN, 0 }, | ||
| 233 | { PORT100_IN_PROT_T1_TAG_FRAME, 0 }, | ||
| 234 | { PORT100_IN_PROT_RFCA, 0 }, | ||
| 235 | { PORT100_IN_PROT_GUARD_TIME_AT_INITIATOR, 6 }, | ||
| 236 | { PORT100_IN_PROT_END, 0 }, | ||
| 237 | }, | ||
| 238 | [NFC_DIGITAL_FRAMING_NFCA_STANDARD] = { | ||
| 239 | { PORT100_IN_PROT_INITIAL_GUARD_TIME, 6 }, | ||
| 240 | { PORT100_IN_PROT_ADD_CRC, 0 }, | ||
| 241 | { PORT100_IN_PROT_CHECK_CRC, 0 }, | ||
| 242 | { PORT100_IN_PROT_MULTI_CARD, 0 }, | ||
| 243 | { PORT100_IN_PROT_ADD_PARITY, 1 }, | ||
| 244 | { PORT100_IN_PROT_CHECK_PARITY, 1 }, | ||
| 245 | { PORT100_IN_PROT_BITWISE_AC_RECV_MODE, 0 }, | ||
| 246 | { PORT100_IN_PROT_VALID_BIT_NUMBER, 8 }, | ||
| 247 | { PORT100_IN_PROT_CRYPTO1, 0 }, | ||
| 248 | { PORT100_IN_PROT_ADD_SOF, 0 }, | ||
| 249 | { PORT100_IN_PROT_CHECK_SOF, 0 }, | ||
| 250 | { PORT100_IN_PROT_ADD_EOF, 0 }, | ||
| 251 | { PORT100_IN_PROT_CHECK_EOF, 0 }, | ||
| 252 | { PORT100_IN_PROT_DEAF_TIME, 4 }, | ||
| 253 | { PORT100_IN_PROT_CRM, 0 }, | ||
| 254 | { PORT100_IN_PROT_CRM_MIN_LEN, 0 }, | ||
| 255 | { PORT100_IN_PROT_T1_TAG_FRAME, 0 }, | ||
| 256 | { PORT100_IN_PROT_RFCA, 0 }, | ||
| 257 | { PORT100_IN_PROT_GUARD_TIME_AT_INITIATOR, 6 }, | ||
| 258 | { PORT100_IN_PROT_END, 0 }, | ||
| 259 | }, | ||
| 260 | [NFC_DIGITAL_FRAMING_NFCA_STANDARD_WITH_CRC_A] = { | ||
| 261 | { PORT100_IN_PROT_INITIAL_GUARD_TIME, 6 }, | ||
| 262 | { PORT100_IN_PROT_ADD_CRC, 1 }, | ||
| 263 | { PORT100_IN_PROT_CHECK_CRC, 1 }, | ||
| 264 | { PORT100_IN_PROT_MULTI_CARD, 0 }, | ||
| 265 | { PORT100_IN_PROT_ADD_PARITY, 1 }, | ||
| 266 | { PORT100_IN_PROT_CHECK_PARITY, 1 }, | ||
| 267 | { PORT100_IN_PROT_BITWISE_AC_RECV_MODE, 0 }, | ||
| 268 | { PORT100_IN_PROT_VALID_BIT_NUMBER, 8 }, | ||
| 269 | { PORT100_IN_PROT_CRYPTO1, 0 }, | ||
| 270 | { PORT100_IN_PROT_ADD_SOF, 0 }, | ||
| 271 | { PORT100_IN_PROT_CHECK_SOF, 0 }, | ||
| 272 | { PORT100_IN_PROT_ADD_EOF, 0 }, | ||
| 273 | { PORT100_IN_PROT_CHECK_EOF, 0 }, | ||
| 274 | { PORT100_IN_PROT_DEAF_TIME, 4 }, | ||
| 275 | { PORT100_IN_PROT_CRM, 0 }, | ||
| 276 | { PORT100_IN_PROT_CRM_MIN_LEN, 0 }, | ||
| 277 | { PORT100_IN_PROT_T1_TAG_FRAME, 0 }, | ||
| 278 | { PORT100_IN_PROT_RFCA, 0 }, | ||
| 279 | { PORT100_IN_PROT_GUARD_TIME_AT_INITIATOR, 6 }, | ||
| 280 | { PORT100_IN_PROT_END, 0 }, | ||
| 281 | }, | ||
| 282 | [NFC_DIGITAL_FRAMING_NFCA_T1T] = { | ||
| 283 | /* nfc_digital_framing_nfca_short */ | ||
| 284 | { PORT100_IN_PROT_ADD_CRC, 2 }, | ||
| 285 | { PORT100_IN_PROT_CHECK_CRC, 2 }, | ||
| 286 | { PORT100_IN_PROT_VALID_BIT_NUMBER, 8 }, | ||
| 287 | { PORT100_IN_PROT_T1_TAG_FRAME, 2 }, | ||
| 288 | { PORT100_IN_PROT_END, 0 }, | ||
| 289 | }, | ||
| 290 | [NFC_DIGITAL_FRAMING_NFCA_T2T] = { | ||
| 291 | /* nfc_digital_framing_nfca_standard */ | ||
| 292 | { PORT100_IN_PROT_ADD_CRC, 1 }, | ||
| 293 | { PORT100_IN_PROT_CHECK_CRC, 0 }, | ||
| 294 | { PORT100_IN_PROT_END, 0 }, | ||
| 295 | }, | ||
| 296 | [NFC_DIGITAL_FRAMING_NFCA_NFC_DEP] = { | ||
| 297 | /* nfc_digital_framing_nfca_standard */ | ||
| 298 | { PORT100_IN_PROT_END, 0 }, | ||
| 299 | }, | ||
| 300 | [NFC_DIGITAL_FRAMING_NFCF] = { | ||
| 301 | { PORT100_IN_PROT_INITIAL_GUARD_TIME, 18 }, | ||
| 302 | { PORT100_IN_PROT_ADD_CRC, 1 }, | ||
| 303 | { PORT100_IN_PROT_CHECK_CRC, 1 }, | ||
| 304 | { PORT100_IN_PROT_MULTI_CARD, 0 }, | ||
| 305 | { PORT100_IN_PROT_ADD_PARITY, 0 }, | ||
| 306 | { PORT100_IN_PROT_CHECK_PARITY, 0 }, | ||
| 307 | { PORT100_IN_PROT_BITWISE_AC_RECV_MODE, 0 }, | ||
| 308 | { PORT100_IN_PROT_VALID_BIT_NUMBER, 8 }, | ||
| 309 | { PORT100_IN_PROT_CRYPTO1, 0 }, | ||
| 310 | { PORT100_IN_PROT_ADD_SOF, 0 }, | ||
| 311 | { PORT100_IN_PROT_CHECK_SOF, 0 }, | ||
| 312 | { PORT100_IN_PROT_ADD_EOF, 0 }, | ||
| 313 | { PORT100_IN_PROT_CHECK_EOF, 0 }, | ||
| 314 | { PORT100_IN_PROT_DEAF_TIME, 4 }, | ||
| 315 | { PORT100_IN_PROT_CRM, 0 }, | ||
| 316 | { PORT100_IN_PROT_CRM_MIN_LEN, 0 }, | ||
| 317 | { PORT100_IN_PROT_T1_TAG_FRAME, 0 }, | ||
| 318 | { PORT100_IN_PROT_RFCA, 0 }, | ||
| 319 | { PORT100_IN_PROT_GUARD_TIME_AT_INITIATOR, 6 }, | ||
| 320 | { PORT100_IN_PROT_END, 0 }, | ||
| 321 | }, | ||
| 322 | [NFC_DIGITAL_FRAMING_NFCF_T3T] = { | ||
| 323 | /* nfc_digital_framing_nfcf */ | ||
| 324 | { PORT100_IN_PROT_END, 0 }, | ||
| 325 | }, | ||
| 326 | [NFC_DIGITAL_FRAMING_NFCF_NFC_DEP] = { | ||
| 327 | /* nfc_digital_framing_nfcf */ | ||
| 328 | { PORT100_IN_PROT_END, 0 }, | ||
| 329 | }, | ||
| 330 | [NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED] = { | ||
| 331 | { PORT100_IN_PROT_END, 0 }, | ||
| 332 | }, | ||
| 333 | }; | ||
| 334 | |||
| 335 | static struct port100_protocol | ||
| 336 | tg_protocols[][PORT100_TG_MAX_NUM_PROTOCOLS + 1] = { | ||
| 337 | [NFC_DIGITAL_FRAMING_NFCA_SHORT] = { | ||
| 338 | { PORT100_TG_PROT_END, 0 }, | ||
| 339 | }, | ||
| 340 | [NFC_DIGITAL_FRAMING_NFCA_STANDARD] = { | ||
| 341 | { PORT100_TG_PROT_END, 0 }, | ||
| 342 | }, | ||
| 343 | [NFC_DIGITAL_FRAMING_NFCA_STANDARD_WITH_CRC_A] = { | ||
| 344 | { PORT100_TG_PROT_END, 0 }, | ||
| 345 | }, | ||
| 346 | [NFC_DIGITAL_FRAMING_NFCA_T1T] = { | ||
| 347 | { PORT100_TG_PROT_END, 0 }, | ||
| 348 | }, | ||
| 349 | [NFC_DIGITAL_FRAMING_NFCA_T2T] = { | ||
| 350 | { PORT100_TG_PROT_END, 0 }, | ||
| 351 | }, | ||
| 352 | [NFC_DIGITAL_FRAMING_NFCA_NFC_DEP] = { | ||
| 353 | { PORT100_TG_PROT_TU, 1 }, | ||
| 354 | { PORT100_TG_PROT_RF_OFF, 0 }, | ||
| 355 | { PORT100_TG_PROT_CRM, 7 }, | ||
| 356 | { PORT100_TG_PROT_END, 0 }, | ||
| 357 | }, | ||
| 358 | [NFC_DIGITAL_FRAMING_NFCF] = { | ||
| 359 | { PORT100_TG_PROT_END, 0 }, | ||
| 360 | }, | ||
| 361 | [NFC_DIGITAL_FRAMING_NFCF_T3T] = { | ||
| 362 | { PORT100_TG_PROT_END, 0 }, | ||
| 363 | }, | ||
| 364 | [NFC_DIGITAL_FRAMING_NFCF_NFC_DEP] = { | ||
| 365 | { PORT100_TG_PROT_TU, 1 }, | ||
| 366 | { PORT100_TG_PROT_RF_OFF, 0 }, | ||
| 367 | { PORT100_TG_PROT_CRM, 7 }, | ||
| 368 | { PORT100_TG_PROT_END, 0 }, | ||
| 369 | }, | ||
| 370 | [NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED] = { | ||
| 371 | { PORT100_TG_PROT_RF_OFF, 1 }, | ||
| 372 | { PORT100_TG_PROT_END, 0 }, | ||
| 373 | }, | ||
| 374 | }; | ||
| 375 | |||
| 376 | struct port100 { | ||
| 377 | struct nfc_digital_dev *nfc_digital_dev; | ||
| 378 | |||
| 379 | int skb_headroom; | ||
| 380 | int skb_tailroom; | ||
| 381 | |||
| 382 | struct usb_device *udev; | ||
| 383 | struct usb_interface *interface; | ||
| 384 | |||
| 385 | struct urb *out_urb; | ||
| 386 | struct urb *in_urb; | ||
| 387 | |||
| 388 | struct work_struct cmd_complete_work; | ||
| 389 | |||
| 390 | u8 cmd_type; | ||
| 391 | |||
| 392 | /* The digital stack serializes commands to be sent. There is no need | ||
| 393 | * for any queuing/locking mechanism at driver level. | ||
| 394 | */ | ||
| 395 | struct port100_cmd *cmd; | ||
| 396 | }; | ||
| 397 | |||
| 398 | struct port100_cmd { | ||
| 399 | u8 code; | ||
| 400 | int status; | ||
| 401 | struct sk_buff *req; | ||
| 402 | struct sk_buff *resp; | ||
| 403 | int resp_len; | ||
| 404 | port100_send_async_complete_t complete_cb; | ||
| 405 | void *complete_cb_context; | ||
| 406 | }; | ||
| 407 | |||
| 408 | struct port100_frame { | ||
| 409 | u8 preamble; | ||
| 410 | __be16 start_frame; | ||
| 411 | __be16 extended_frame; | ||
| 412 | __le16 datalen; | ||
| 413 | u8 datalen_checksum; | ||
| 414 | u8 data[]; | ||
| 415 | } __packed; | ||
| 416 | |||
| 417 | struct port100_ack_frame { | ||
| 418 | u8 preamble; | ||
| 419 | __be16 start_frame; | ||
| 420 | __be16 ack_frame; | ||
| 421 | u8 postambule; | ||
| 422 | } __packed; | ||
| 423 | |||
| 424 | struct port100_cb_arg { | ||
| 425 | nfc_digital_cmd_complete_t complete_cb; | ||
| 426 | void *complete_arg; | ||
| 427 | u8 mdaa; | ||
| 428 | }; | ||
| 429 | |||
| 430 | struct port100_tg_comm_rf_cmd { | ||
| 431 | __le16 guard_time; | ||
| 432 | __le16 send_timeout; | ||
| 433 | u8 mdaa; | ||
| 434 | u8 nfca_param[6]; | ||
| 435 | u8 nfcf_param[18]; | ||
| 436 | u8 mf_halted; | ||
| 437 | u8 arae_flag; | ||
| 438 | __le16 recv_timeout; | ||
| 439 | u8 data[]; | ||
| 440 | } __packed; | ||
| 441 | |||
| 442 | struct port100_tg_comm_rf_res { | ||
| 443 | u8 comm_type; | ||
| 444 | u8 ar_status; | ||
| 445 | u8 target_activated; | ||
| 446 | __le32 status; | ||
| 447 | u8 data[]; | ||
| 448 | } __packed; | ||
| 449 | |||
| 450 | /* The rule: value + checksum = 0 */ | ||
| 451 | static inline u8 port100_checksum(u16 value) | ||
| 452 | { | ||
| 453 | return ~(((u8 *)&value)[0] + ((u8 *)&value)[1]) + 1; | ||
| 454 | } | ||
| 455 | |||
| 456 | /* The rule: sum(data elements) + checksum = 0 */ | ||
| 457 | static u8 port100_data_checksum(u8 *data, int datalen) | ||
| 458 | { | ||
| 459 | u8 sum = 0; | ||
| 460 | int i; | ||
| 461 | |||
| 462 | for (i = 0; i < datalen; i++) | ||
| 463 | sum += data[i]; | ||
| 464 | |||
| 465 | return port100_checksum(sum); | ||
| 466 | } | ||
| 467 | |||
| 468 | static void port100_tx_frame_init(void *_frame, u8 cmd_code) | ||
| 469 | { | ||
| 470 | struct port100_frame *frame = _frame; | ||
| 471 | |||
| 472 | frame->preamble = 0; | ||
| 473 | frame->start_frame = cpu_to_be16(PORT100_FRAME_SOF); | ||
| 474 | frame->extended_frame = cpu_to_be16(PORT100_FRAME_EXT); | ||
| 475 | PORT100_FRAME_DIRECTION(frame) = PORT100_FRAME_DIR_OUT; | ||
| 476 | PORT100_FRAME_CMD(frame) = cmd_code; | ||
| 477 | frame->datalen = cpu_to_le16(2); | ||
| 478 | } | ||
| 479 | |||
| 480 | static void port100_tx_frame_finish(void *_frame) | ||
| 481 | { | ||
| 482 | struct port100_frame *frame = _frame; | ||
| 483 | |||
| 484 | frame->datalen_checksum = port100_checksum(le16_to_cpu(frame->datalen)); | ||
| 485 | |||
| 486 | PORT100_FRAME_CHECKSUM(frame) = | ||
| 487 | port100_data_checksum(frame->data, le16_to_cpu(frame->datalen)); | ||
| 488 | |||
| 489 | PORT100_FRAME_POSTAMBLE(frame) = 0; | ||
| 490 | } | ||
| 491 | |||
| 492 | static void port100_tx_update_payload_len(void *_frame, int len) | ||
| 493 | { | ||
| 494 | struct port100_frame *frame = _frame; | ||
| 495 | |||
| 496 | frame->datalen = cpu_to_le16(le16_to_cpu(frame->datalen) + len); | ||
| 497 | } | ||
| 498 | |||
| 499 | static bool port100_rx_frame_is_valid(void *_frame) | ||
| 500 | { | ||
| 501 | u8 checksum; | ||
| 502 | struct port100_frame *frame = _frame; | ||
| 503 | |||
| 504 | if (frame->start_frame != cpu_to_be16(PORT100_FRAME_SOF) || | ||
| 505 | frame->extended_frame != cpu_to_be16(PORT100_FRAME_EXT)) | ||
| 506 | return false; | ||
| 507 | |||
| 508 | checksum = port100_checksum(le16_to_cpu(frame->datalen)); | ||
| 509 | if (checksum != frame->datalen_checksum) | ||
| 510 | return false; | ||
| 511 | |||
| 512 | checksum = port100_data_checksum(frame->data, | ||
| 513 | le16_to_cpu(frame->datalen)); | ||
| 514 | if (checksum != PORT100_FRAME_CHECKSUM(frame)) | ||
| 515 | return false; | ||
| 516 | |||
| 517 | return true; | ||
| 518 | } | ||
| 519 | |||
| 520 | static bool port100_rx_frame_is_ack(struct port100_ack_frame *frame) | ||
| 521 | { | ||
| 522 | return (frame->start_frame == cpu_to_be16(PORT100_FRAME_SOF) && | ||
| 523 | frame->ack_frame == cpu_to_be16(PORT100_FRAME_ACK)); | ||
| 524 | } | ||
| 525 | |||
| 526 | static inline int port100_rx_frame_size(void *frame) | ||
| 527 | { | ||
| 528 | struct port100_frame *f = frame; | ||
| 529 | |||
| 530 | return sizeof(struct port100_frame) + le16_to_cpu(f->datalen) + | ||
| 531 | PORT100_FRAME_TAIL_LEN; | ||
| 532 | } | ||
| 533 | |||
| 534 | static bool port100_rx_frame_is_cmd_response(struct port100 *dev, void *frame) | ||
| 535 | { | ||
| 536 | struct port100_frame *f = frame; | ||
| 537 | |||
| 538 | return (PORT100_FRAME_CMD(f) == PORT100_CMD_RESPONSE(dev->cmd->code)); | ||
| 539 | } | ||
| 540 | |||
| 541 | static void port100_recv_response(struct urb *urb) | ||
| 542 | { | ||
| 543 | struct port100 *dev = urb->context; | ||
| 544 | struct port100_cmd *cmd = dev->cmd; | ||
| 545 | u8 *in_frame; | ||
| 546 | |||
| 547 | cmd->status = urb->status; | ||
| 548 | |||
| 549 | switch (urb->status) { | ||
| 550 | case 0: | ||
| 551 | break; /* success */ | ||
| 552 | case -ECONNRESET: | ||
| 553 | case -ENOENT: | ||
| 554 | nfc_err(&dev->interface->dev, | ||
| 555 | "The urb has been canceled (status %d)", urb->status); | ||
| 556 | goto sched_wq; | ||
| 557 | case -ESHUTDOWN: | ||
| 558 | default: | ||
| 559 | nfc_err(&dev->interface->dev, "Urb failure (status %d)", | ||
| 560 | urb->status); | ||
| 561 | goto sched_wq; | ||
| 562 | } | ||
| 563 | |||
| 564 | in_frame = dev->in_urb->transfer_buffer; | ||
| 565 | |||
| 566 | if (!port100_rx_frame_is_valid(in_frame)) { | ||
| 567 | nfc_err(&dev->interface->dev, "Received an invalid frame"); | ||
| 568 | cmd->status = -EIO; | ||
| 569 | goto sched_wq; | ||
| 570 | } | ||
| 571 | |||
| 572 | print_hex_dump_debug("PORT100 RX: ", DUMP_PREFIX_NONE, 16, 1, in_frame, | ||
| 573 | port100_rx_frame_size(in_frame), false); | ||
| 574 | |||
| 575 | if (!port100_rx_frame_is_cmd_response(dev, in_frame)) { | ||
| 576 | nfc_err(&dev->interface->dev, | ||
| 577 | "It's not the response to the last command"); | ||
| 578 | cmd->status = -EIO; | ||
| 579 | goto sched_wq; | ||
| 580 | } | ||
| 581 | |||
| 582 | sched_wq: | ||
| 583 | schedule_work(&dev->cmd_complete_work); | ||
| 584 | } | ||
| 585 | |||
| 586 | static int port100_submit_urb_for_response(struct port100 *dev, gfp_t flags) | ||
| 587 | { | ||
| 588 | dev->in_urb->complete = port100_recv_response; | ||
| 589 | |||
| 590 | return usb_submit_urb(dev->in_urb, flags); | ||
| 591 | } | ||
| 592 | |||
| 593 | static void port100_recv_ack(struct urb *urb) | ||
| 594 | { | ||
| 595 | struct port100 *dev = urb->context; | ||
| 596 | struct port100_cmd *cmd = dev->cmd; | ||
| 597 | struct port100_ack_frame *in_frame; | ||
| 598 | int rc; | ||
| 599 | |||
| 600 | cmd->status = urb->status; | ||
| 601 | |||
| 602 | switch (urb->status) { | ||
| 603 | case 0: | ||
| 604 | break; /* success */ | ||
| 605 | case -ECONNRESET: | ||
| 606 | case -ENOENT: | ||
| 607 | nfc_err(&dev->interface->dev, | ||
| 608 | "The urb has been stopped (status %d)", urb->status); | ||
| 609 | goto sched_wq; | ||
| 610 | case -ESHUTDOWN: | ||
| 611 | default: | ||
| 612 | nfc_err(&dev->interface->dev, "Urb failure (status %d)", | ||
| 613 | urb->status); | ||
| 614 | goto sched_wq; | ||
| 615 | } | ||
| 616 | |||
| 617 | in_frame = dev->in_urb->transfer_buffer; | ||
| 618 | |||
| 619 | if (!port100_rx_frame_is_ack(in_frame)) { | ||
| 620 | nfc_err(&dev->interface->dev, "Received an invalid ack"); | ||
| 621 | cmd->status = -EIO; | ||
| 622 | goto sched_wq; | ||
| 623 | } | ||
| 624 | |||
| 625 | rc = port100_submit_urb_for_response(dev, GFP_ATOMIC); | ||
| 626 | if (rc) { | ||
| 627 | nfc_err(&dev->interface->dev, | ||
| 628 | "usb_submit_urb failed with result %d", rc); | ||
| 629 | cmd->status = rc; | ||
| 630 | goto sched_wq; | ||
| 631 | } | ||
| 632 | |||
| 633 | return; | ||
| 634 | |||
| 635 | sched_wq: | ||
| 636 | schedule_work(&dev->cmd_complete_work); | ||
| 637 | } | ||
| 638 | |||
| 639 | static int port100_submit_urb_for_ack(struct port100 *dev, gfp_t flags) | ||
| 640 | { | ||
| 641 | dev->in_urb->complete = port100_recv_ack; | ||
| 642 | |||
| 643 | return usb_submit_urb(dev->in_urb, flags); | ||
| 644 | } | ||
| 645 | |||
| 646 | static int port100_send_ack(struct port100 *dev) | ||
| 647 | { | ||
| 648 | int rc; | ||
| 649 | |||
| 650 | dev->out_urb->transfer_buffer = ack_frame; | ||
| 651 | dev->out_urb->transfer_buffer_length = sizeof(ack_frame); | ||
| 652 | rc = usb_submit_urb(dev->out_urb, GFP_KERNEL); | ||
| 653 | |||
| 654 | return rc; | ||
| 655 | } | ||
| 656 | |||
| 657 | static int port100_send_frame_async(struct port100 *dev, struct sk_buff *out, | ||
| 658 | struct sk_buff *in, int in_len) | ||
| 659 | { | ||
| 660 | int rc; | ||
| 661 | |||
| 662 | dev->out_urb->transfer_buffer = out->data; | ||
| 663 | dev->out_urb->transfer_buffer_length = out->len; | ||
| 664 | |||
| 665 | dev->in_urb->transfer_buffer = in->data; | ||
| 666 | dev->in_urb->transfer_buffer_length = in_len; | ||
| 667 | |||
| 668 | print_hex_dump_debug("PORT100 TX: ", DUMP_PREFIX_NONE, 16, 1, | ||
| 669 | out->data, out->len, false); | ||
| 670 | |||
| 671 | rc = usb_submit_urb(dev->out_urb, GFP_KERNEL); | ||
| 672 | if (rc) | ||
| 673 | return rc; | ||
| 674 | |||
| 675 | rc = port100_submit_urb_for_ack(dev, GFP_KERNEL); | ||
| 676 | if (rc) | ||
| 677 | goto error; | ||
| 678 | |||
| 679 | return 0; | ||
| 680 | |||
| 681 | error: | ||
| 682 | usb_unlink_urb(dev->out_urb); | ||
| 683 | return rc; | ||
| 684 | } | ||
| 685 | |||
| 686 | static void port100_build_cmd_frame(struct port100 *dev, u8 cmd_code, | ||
| 687 | struct sk_buff *skb) | ||
| 688 | { | ||
| 689 | /* payload is already there, just update datalen */ | ||
| 690 | int payload_len = skb->len; | ||
| 691 | |||
| 692 | skb_push(skb, PORT100_FRAME_HEADER_LEN); | ||
| 693 | skb_put(skb, PORT100_FRAME_TAIL_LEN); | ||
| 694 | |||
| 695 | port100_tx_frame_init(skb->data, cmd_code); | ||
| 696 | port100_tx_update_payload_len(skb->data, payload_len); | ||
| 697 | port100_tx_frame_finish(skb->data); | ||
| 698 | } | ||
| 699 | |||
| 700 | static void port100_send_async_complete(struct port100 *dev) | ||
| 701 | { | ||
| 702 | struct port100_cmd *cmd = dev->cmd; | ||
| 703 | int status = cmd->status; | ||
| 704 | |||
| 705 | struct sk_buff *req = cmd->req; | ||
| 706 | struct sk_buff *resp = cmd->resp; | ||
| 707 | |||
| 708 | dev_kfree_skb(req); | ||
| 709 | |||
| 710 | dev->cmd = NULL; | ||
| 711 | |||
| 712 | if (status < 0) { | ||
| 713 | cmd->complete_cb(dev, cmd->complete_cb_context, | ||
| 714 | ERR_PTR(status)); | ||
| 715 | dev_kfree_skb(resp); | ||
| 716 | goto done; | ||
| 717 | } | ||
| 718 | |||
| 719 | skb_put(resp, port100_rx_frame_size(resp->data)); | ||
| 720 | skb_pull(resp, PORT100_FRAME_HEADER_LEN); | ||
| 721 | skb_trim(resp, resp->len - PORT100_FRAME_TAIL_LEN); | ||
| 722 | |||
| 723 | cmd->complete_cb(dev, cmd->complete_cb_context, resp); | ||
| 724 | |||
| 725 | done: | ||
| 726 | kfree(cmd); | ||
| 727 | } | ||
| 728 | |||
| 729 | static int port100_send_cmd_async(struct port100 *dev, u8 cmd_code, | ||
| 730 | struct sk_buff *req, | ||
| 731 | port100_send_async_complete_t complete_cb, | ||
| 732 | void *complete_cb_context) | ||
| 733 | { | ||
| 734 | struct port100_cmd *cmd; | ||
| 735 | struct sk_buff *resp; | ||
| 736 | int rc; | ||
| 737 | int resp_len = PORT100_FRAME_HEADER_LEN + | ||
| 738 | PORT100_FRAME_MAX_PAYLOAD_LEN + | ||
| 739 | PORT100_FRAME_TAIL_LEN; | ||
| 740 | |||
| 741 | resp = alloc_skb(resp_len, GFP_KERNEL); | ||
| 742 | if (!resp) | ||
| 743 | return -ENOMEM; | ||
| 744 | |||
| 745 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
| 746 | if (!cmd) { | ||
| 747 | dev_kfree_skb(resp); | ||
| 748 | return -ENOMEM; | ||
| 749 | } | ||
| 750 | |||
| 751 | cmd->code = cmd_code; | ||
| 752 | cmd->req = req; | ||
| 753 | cmd->resp = resp; | ||
| 754 | cmd->resp_len = resp_len; | ||
| 755 | cmd->complete_cb = complete_cb; | ||
| 756 | cmd->complete_cb_context = complete_cb_context; | ||
| 757 | |||
| 758 | port100_build_cmd_frame(dev, cmd_code, req); | ||
| 759 | |||
| 760 | dev->cmd = cmd; | ||
| 761 | |||
| 762 | rc = port100_send_frame_async(dev, req, resp, resp_len); | ||
| 763 | if (rc) { | ||
| 764 | kfree(cmd); | ||
| 765 | dev_kfree_skb(resp); | ||
| 766 | dev->cmd = NULL; | ||
| 767 | } | ||
| 768 | |||
| 769 | return rc; | ||
| 770 | } | ||
| 771 | |||
| 772 | struct port100_sync_cmd_response { | ||
| 773 | struct sk_buff *resp; | ||
| 774 | struct completion done; | ||
| 775 | }; | ||
| 776 | |||
| 777 | static void port100_wq_cmd_complete(struct work_struct *work) | ||
| 778 | { | ||
| 779 | struct port100 *dev = container_of(work, struct port100, | ||
| 780 | cmd_complete_work); | ||
| 781 | |||
| 782 | port100_send_async_complete(dev); | ||
| 783 | } | ||
| 784 | |||
| 785 | static void port100_send_sync_complete(struct port100 *dev, void *_arg, | ||
| 786 | struct sk_buff *resp) | ||
| 787 | { | ||
| 788 | struct port100_sync_cmd_response *arg = _arg; | ||
| 789 | |||
| 790 | arg->resp = resp; | ||
| 791 | complete(&arg->done); | ||
| 792 | } | ||
| 793 | |||
| 794 | static struct sk_buff *port100_send_cmd_sync(struct port100 *dev, u8 cmd_code, | ||
| 795 | struct sk_buff *req) | ||
| 796 | { | ||
| 797 | int rc; | ||
| 798 | struct port100_sync_cmd_response arg; | ||
| 799 | |||
| 800 | init_completion(&arg.done); | ||
| 801 | |||
| 802 | rc = port100_send_cmd_async(dev, cmd_code, req, | ||
| 803 | port100_send_sync_complete, &arg); | ||
| 804 | if (rc) { | ||
| 805 | dev_kfree_skb(req); | ||
| 806 | return ERR_PTR(rc); | ||
| 807 | } | ||
| 808 | |||
| 809 | wait_for_completion(&arg.done); | ||
| 810 | |||
| 811 | return arg.resp; | ||
| 812 | } | ||
| 813 | |||
| 814 | static void port100_send_complete(struct urb *urb) | ||
| 815 | { | ||
| 816 | struct port100 *dev = urb->context; | ||
| 817 | |||
| 818 | switch (urb->status) { | ||
| 819 | case 0: | ||
| 820 | break; /* success */ | ||
| 821 | case -ECONNRESET: | ||
| 822 | case -ENOENT: | ||
| 823 | nfc_err(&dev->interface->dev, | ||
| 824 | "The urb has been stopped (status %d)", urb->status); | ||
| 825 | break; | ||
| 826 | case -ESHUTDOWN: | ||
| 827 | default: | ||
| 828 | nfc_err(&dev->interface->dev, "Urb failure (status %d)", | ||
| 829 | urb->status); | ||
| 830 | } | ||
| 831 | } | ||
| 832 | |||
| 833 | static void port100_abort_cmd(struct nfc_digital_dev *ddev) | ||
| 834 | { | ||
| 835 | struct port100 *dev = nfc_digital_get_drvdata(ddev); | ||
| 836 | |||
| 837 | /* An ack will cancel the last issued command */ | ||
| 838 | port100_send_ack(dev); | ||
| 839 | |||
| 840 | /* cancel the urb request */ | ||
| 841 | usb_kill_urb(dev->in_urb); | ||
| 842 | } | ||
| 843 | |||
| 844 | static struct sk_buff *port100_alloc_skb(struct port100 *dev, unsigned int size) | ||
| 845 | { | ||
| 846 | struct sk_buff *skb; | ||
| 847 | |||
| 848 | skb = alloc_skb(dev->skb_headroom + dev->skb_tailroom + size, | ||
| 849 | GFP_KERNEL); | ||
| 850 | if (skb) | ||
| 851 | skb_reserve(skb, dev->skb_headroom); | ||
| 852 | |||
| 853 | return skb; | ||
| 854 | } | ||
| 855 | |||
| 856 | static int port100_set_command_type(struct port100 *dev, u8 command_type) | ||
| 857 | { | ||
| 858 | struct sk_buff *skb; | ||
| 859 | struct sk_buff *resp; | ||
| 860 | int rc; | ||
| 861 | |||
| 862 | skb = port100_alloc_skb(dev, 1); | ||
| 863 | if (!skb) | ||
| 864 | return -ENOMEM; | ||
| 865 | |||
| 866 | *skb_put(skb, sizeof(u8)) = command_type; | ||
| 867 | |||
| 868 | resp = port100_send_cmd_sync(dev, PORT100_CMD_SET_COMMAND_TYPE, skb); | ||
| 869 | if (IS_ERR(resp)) | ||
| 870 | return PTR_ERR(resp); | ||
| 871 | |||
| 872 | rc = resp->data[0]; | ||
| 873 | |||
| 874 | dev_kfree_skb(resp); | ||
| 875 | |||
| 876 | return rc; | ||
| 877 | } | ||
| 878 | |||
| 879 | static u64 port100_get_command_type_mask(struct port100 *dev) | ||
| 880 | { | ||
| 881 | struct sk_buff *skb; | ||
| 882 | struct sk_buff *resp; | ||
| 883 | u64 mask; | ||
| 884 | |||
| 885 | skb = port100_alloc_skb(dev, 0); | ||
| 886 | if (!skb) | ||
| 887 | return -ENOMEM; | ||
| 888 | |||
| 889 | resp = port100_send_cmd_sync(dev, PORT100_CMD_GET_COMMAND_TYPE, skb); | ||
| 890 | if (IS_ERR(resp)) | ||
| 891 | return PTR_ERR(resp); | ||
| 892 | |||
| 893 | if (resp->len < 8) | ||
| 894 | mask = 0; | ||
| 895 | else | ||
| 896 | mask = be64_to_cpu(*(__be64 *)resp->data); | ||
| 897 | |||
| 898 | dev_kfree_skb(resp); | ||
| 899 | |||
| 900 | return mask; | ||
| 901 | } | ||
| 902 | |||
| 903 | static u16 port100_get_firmware_version(struct port100 *dev) | ||
| 904 | { | ||
| 905 | struct sk_buff *skb; | ||
| 906 | struct sk_buff *resp; | ||
| 907 | u16 fw_ver; | ||
| 908 | |||
| 909 | skb = port100_alloc_skb(dev, 0); | ||
| 910 | if (!skb) | ||
| 911 | return 0; | ||
| 912 | |||
| 913 | resp = port100_send_cmd_sync(dev, PORT100_CMD_GET_FIRMWARE_VERSION, | ||
| 914 | skb); | ||
| 915 | if (IS_ERR(resp)) | ||
| 916 | return 0; | ||
| 917 | |||
| 918 | fw_ver = le16_to_cpu(*(__le16 *)resp->data); | ||
| 919 | |||
| 920 | dev_kfree_skb(resp); | ||
| 921 | |||
| 922 | return fw_ver; | ||
| 923 | } | ||
| 924 | |||
| 925 | static int port100_switch_rf(struct nfc_digital_dev *ddev, bool on) | ||
| 926 | { | ||
| 927 | struct port100 *dev = nfc_digital_get_drvdata(ddev); | ||
| 928 | struct sk_buff *skb, *resp; | ||
| 929 | |||
| 930 | skb = port100_alloc_skb(dev, 1); | ||
| 931 | if (!skb) | ||
| 932 | return -ENOMEM; | ||
| 933 | |||
| 934 | *skb_put(skb, 1) = on ? 1 : 0; | ||
| 935 | |||
| 936 | resp = port100_send_cmd_sync(dev, PORT100_CMD_SWITCH_RF, skb); | ||
| 937 | |||
| 938 | if (IS_ERR(resp)) | ||
| 939 | return PTR_ERR(resp); | ||
| 940 | |||
| 941 | dev_kfree_skb(resp); | ||
| 942 | |||
| 943 | return 0; | ||
| 944 | } | ||
| 945 | |||
| 946 | static int port100_in_set_rf(struct nfc_digital_dev *ddev, u8 rf) | ||
| 947 | { | ||
| 948 | struct port100 *dev = nfc_digital_get_drvdata(ddev); | ||
| 949 | struct sk_buff *skb; | ||
| 950 | struct sk_buff *resp; | ||
| 951 | int rc; | ||
| 952 | |||
| 953 | if (rf >= NFC_DIGITAL_RF_TECH_LAST) | ||
| 954 | return -EINVAL; | ||
| 955 | |||
| 956 | skb = port100_alloc_skb(dev, sizeof(struct port100_in_rf_setting)); | ||
| 957 | if (!skb) | ||
| 958 | return -ENOMEM; | ||
| 959 | |||
| 960 | memcpy(skb_put(skb, sizeof(struct port100_in_rf_setting)), | ||
| 961 | &in_rf_settings[rf], | ||
| 962 | sizeof(struct port100_in_rf_setting)); | ||
| 963 | |||
| 964 | resp = port100_send_cmd_sync(dev, PORT100_CMD_IN_SET_RF, skb); | ||
| 965 | |||
| 966 | if (IS_ERR(resp)) | ||
| 967 | return PTR_ERR(resp); | ||
| 968 | |||
| 969 | rc = resp->data[0]; | ||
| 970 | |||
| 971 | dev_kfree_skb(resp); | ||
| 972 | |||
| 973 | return rc; | ||
| 974 | } | ||
| 975 | |||
| 976 | static int port100_in_set_framing(struct nfc_digital_dev *ddev, int param) | ||
| 977 | { | ||
| 978 | struct port100 *dev = nfc_digital_get_drvdata(ddev); | ||
| 979 | struct port100_protocol *protocols; | ||
| 980 | struct sk_buff *skb; | ||
| 981 | struct sk_buff *resp; | ||
| 982 | int num_protocols; | ||
| 983 | size_t size; | ||
| 984 | int rc; | ||
| 985 | |||
| 986 | if (param >= NFC_DIGITAL_FRAMING_LAST) | ||
| 987 | return -EINVAL; | ||
| 988 | |||
| 989 | protocols = in_protocols[param]; | ||
| 990 | |||
| 991 | num_protocols = 0; | ||
| 992 | while (protocols[num_protocols].number != PORT100_IN_PROT_END) | ||
| 993 | num_protocols++; | ||
| 994 | |||
| 995 | if (!num_protocols) | ||
| 996 | return 0; | ||
| 997 | |||
| 998 | size = sizeof(struct port100_protocol) * num_protocols; | ||
| 999 | |||
| 1000 | skb = port100_alloc_skb(dev, size); | ||
| 1001 | if (!skb) | ||
| 1002 | return -ENOMEM; | ||
| 1003 | |||
| 1004 | memcpy(skb_put(skb, size), protocols, size); | ||
| 1005 | |||
| 1006 | resp = port100_send_cmd_sync(dev, PORT100_CMD_IN_SET_PROTOCOL, skb); | ||
| 1007 | |||
| 1008 | if (IS_ERR(resp)) | ||
| 1009 | return PTR_ERR(resp); | ||
| 1010 | |||
| 1011 | rc = resp->data[0]; | ||
| 1012 | |||
| 1013 | dev_kfree_skb(resp); | ||
| 1014 | |||
| 1015 | return rc; | ||
| 1016 | } | ||
| 1017 | |||
| 1018 | static int port100_in_configure_hw(struct nfc_digital_dev *ddev, int type, | ||
| 1019 | int param) | ||
| 1020 | { | ||
| 1021 | if (type == NFC_DIGITAL_CONFIG_RF_TECH) | ||
| 1022 | return port100_in_set_rf(ddev, param); | ||
| 1023 | |||
| 1024 | if (type == NFC_DIGITAL_CONFIG_FRAMING) | ||
| 1025 | return port100_in_set_framing(ddev, param); | ||
| 1026 | |||
| 1027 | return -EINVAL; | ||
| 1028 | } | ||
| 1029 | |||
| 1030 | static void port100_in_comm_rf_complete(struct port100 *dev, void *arg, | ||
| 1031 | struct sk_buff *resp) | ||
| 1032 | { | ||
| 1033 | struct port100_cb_arg *cb_arg = arg; | ||
| 1034 | nfc_digital_cmd_complete_t cb = cb_arg->complete_cb; | ||
| 1035 | u32 status; | ||
| 1036 | int rc; | ||
| 1037 | |||
| 1038 | if (IS_ERR(resp)) { | ||
| 1039 | rc = PTR_ERR(resp); | ||
| 1040 | goto exit; | ||
| 1041 | } | ||
| 1042 | |||
| 1043 | if (resp->len < 4) { | ||
| 1044 | nfc_err(&dev->interface->dev, | ||
| 1045 | "Invalid packet length received.\n"); | ||
| 1046 | rc = -EIO; | ||
| 1047 | goto error; | ||
| 1048 | } | ||
| 1049 | |||
| 1050 | status = le32_to_cpu(*(__le32 *)resp->data); | ||
| 1051 | |||
| 1052 | skb_pull(resp, sizeof(u32)); | ||
| 1053 | |||
| 1054 | if (status == PORT100_CMD_STATUS_TIMEOUT) { | ||
| 1055 | rc = -ETIMEDOUT; | ||
| 1056 | goto error; | ||
| 1057 | } | ||
| 1058 | |||
| 1059 | if (status != PORT100_CMD_STATUS_OK) { | ||
| 1060 | nfc_err(&dev->interface->dev, | ||
| 1061 | "in_comm_rf failed with status 0x%08x\n", status); | ||
| 1062 | rc = -EIO; | ||
| 1063 | goto error; | ||
| 1064 | } | ||
| 1065 | |||
| 1066 | /* Remove collision bits byte */ | ||
| 1067 | skb_pull(resp, 1); | ||
| 1068 | |||
| 1069 | goto exit; | ||
| 1070 | |||
| 1071 | error: | ||
| 1072 | kfree_skb(resp); | ||
| 1073 | resp = ERR_PTR(rc); | ||
| 1074 | |||
| 1075 | exit: | ||
| 1076 | cb(dev->nfc_digital_dev, cb_arg->complete_arg, resp); | ||
| 1077 | |||
| 1078 | kfree(cb_arg); | ||
| 1079 | } | ||
| 1080 | |||
| 1081 | static int port100_in_send_cmd(struct nfc_digital_dev *ddev, | ||
| 1082 | struct sk_buff *skb, u16 _timeout, | ||
| 1083 | nfc_digital_cmd_complete_t cb, void *arg) | ||
| 1084 | { | ||
| 1085 | struct port100 *dev = nfc_digital_get_drvdata(ddev); | ||
| 1086 | struct port100_cb_arg *cb_arg; | ||
| 1087 | __le16 timeout; | ||
| 1088 | |||
| 1089 | cb_arg = kzalloc(sizeof(struct port100_cb_arg), GFP_KERNEL); | ||
| 1090 | if (!cb_arg) | ||
| 1091 | return -ENOMEM; | ||
| 1092 | |||
| 1093 | cb_arg->complete_cb = cb; | ||
| 1094 | cb_arg->complete_arg = arg; | ||
| 1095 | |||
| 1096 | timeout = cpu_to_le16(_timeout * 10); | ||
| 1097 | |||
| 1098 | memcpy(skb_push(skb, sizeof(__le16)), &timeout, sizeof(__le16)); | ||
| 1099 | |||
| 1100 | return port100_send_cmd_async(dev, PORT100_CMD_IN_COMM_RF, skb, | ||
| 1101 | port100_in_comm_rf_complete, cb_arg); | ||
| 1102 | } | ||
| 1103 | |||
| 1104 | static int port100_tg_set_rf(struct nfc_digital_dev *ddev, u8 rf) | ||
| 1105 | { | ||
| 1106 | struct port100 *dev = nfc_digital_get_drvdata(ddev); | ||
| 1107 | struct sk_buff *skb; | ||
| 1108 | struct sk_buff *resp; | ||
| 1109 | int rc; | ||
| 1110 | |||
| 1111 | if (rf >= NFC_DIGITAL_RF_TECH_LAST) | ||
| 1112 | return -EINVAL; | ||
| 1113 | |||
| 1114 | skb = port100_alloc_skb(dev, sizeof(struct port100_tg_rf_setting)); | ||
| 1115 | if (!skb) | ||
| 1116 | return -ENOMEM; | ||
| 1117 | |||
| 1118 | memcpy(skb_put(skb, sizeof(struct port100_tg_rf_setting)), | ||
| 1119 | &tg_rf_settings[rf], | ||
| 1120 | sizeof(struct port100_tg_rf_setting)); | ||
| 1121 | |||
| 1122 | resp = port100_send_cmd_sync(dev, PORT100_CMD_TG_SET_RF, skb); | ||
| 1123 | |||
| 1124 | if (IS_ERR(resp)) | ||
| 1125 | return PTR_ERR(resp); | ||
| 1126 | |||
| 1127 | rc = resp->data[0]; | ||
| 1128 | |||
| 1129 | dev_kfree_skb(resp); | ||
| 1130 | |||
| 1131 | return rc; | ||
| 1132 | } | ||
| 1133 | |||
| 1134 | static int port100_tg_set_framing(struct nfc_digital_dev *ddev, int param) | ||
| 1135 | { | ||
| 1136 | struct port100 *dev = nfc_digital_get_drvdata(ddev); | ||
| 1137 | struct port100_protocol *protocols; | ||
| 1138 | struct sk_buff *skb; | ||
| 1139 | struct sk_buff *resp; | ||
| 1140 | int rc; | ||
| 1141 | int num_protocols; | ||
| 1142 | size_t size; | ||
| 1143 | |||
| 1144 | if (param >= NFC_DIGITAL_FRAMING_LAST) | ||
| 1145 | return -EINVAL; | ||
| 1146 | |||
| 1147 | protocols = tg_protocols[param]; | ||
| 1148 | |||
| 1149 | num_protocols = 0; | ||
| 1150 | while (protocols[num_protocols].number != PORT100_TG_PROT_END) | ||
| 1151 | num_protocols++; | ||
| 1152 | |||
| 1153 | if (!num_protocols) | ||
| 1154 | return 0; | ||
| 1155 | |||
| 1156 | size = sizeof(struct port100_protocol) * num_protocols; | ||
| 1157 | |||
| 1158 | skb = port100_alloc_skb(dev, size); | ||
| 1159 | if (!skb) | ||
| 1160 | return -ENOMEM; | ||
| 1161 | |||
| 1162 | memcpy(skb_put(skb, size), protocols, size); | ||
| 1163 | |||
| 1164 | resp = port100_send_cmd_sync(dev, PORT100_CMD_TG_SET_PROTOCOL, skb); | ||
| 1165 | |||
| 1166 | if (IS_ERR(resp)) | ||
| 1167 | return PTR_ERR(resp); | ||
| 1168 | |||
| 1169 | rc = resp->data[0]; | ||
| 1170 | |||
| 1171 | dev_kfree_skb(resp); | ||
| 1172 | |||
| 1173 | return rc; | ||
| 1174 | } | ||
| 1175 | |||
| 1176 | static int port100_tg_configure_hw(struct nfc_digital_dev *ddev, int type, | ||
| 1177 | int param) | ||
| 1178 | { | ||
| 1179 | if (type == NFC_DIGITAL_CONFIG_RF_TECH) | ||
| 1180 | return port100_tg_set_rf(ddev, param); | ||
| 1181 | |||
| 1182 | if (type == NFC_DIGITAL_CONFIG_FRAMING) | ||
| 1183 | return port100_tg_set_framing(ddev, param); | ||
| 1184 | |||
| 1185 | return -EINVAL; | ||
| 1186 | } | ||
| 1187 | |||
| 1188 | static bool port100_tg_target_activated(struct port100 *dev, u8 tgt_activated) | ||
| 1189 | { | ||
| 1190 | u8 mask; | ||
| 1191 | |||
| 1192 | switch (dev->cmd_type) { | ||
| 1193 | case PORT100_CMD_TYPE_0: | ||
| 1194 | mask = PORT100_MDAA_TGT_HAS_BEEN_ACTIVATED_MASK; | ||
| 1195 | break; | ||
| 1196 | case PORT100_CMD_TYPE_1: | ||
| 1197 | mask = PORT100_MDAA_TGT_HAS_BEEN_ACTIVATED_MASK | | ||
| 1198 | PORT100_MDAA_TGT_WAS_ACTIVATED_MASK; | ||
| 1199 | break; | ||
| 1200 | default: | ||
| 1201 | nfc_err(&dev->interface->dev, "Unknonwn command type.\n"); | ||
| 1202 | return false; | ||
| 1203 | } | ||
| 1204 | |||
| 1205 | return ((tgt_activated & mask) == mask); | ||
| 1206 | } | ||
| 1207 | |||
| 1208 | static void port100_tg_comm_rf_complete(struct port100 *dev, void *arg, | ||
| 1209 | struct sk_buff *resp) | ||
| 1210 | { | ||
| 1211 | u32 status; | ||
| 1212 | struct port100_cb_arg *cb_arg = arg; | ||
| 1213 | nfc_digital_cmd_complete_t cb = cb_arg->complete_cb; | ||
| 1214 | struct port100_tg_comm_rf_res *hdr; | ||
| 1215 | |||
| 1216 | if (IS_ERR(resp)) | ||
| 1217 | goto exit; | ||
| 1218 | |||
| 1219 | hdr = (struct port100_tg_comm_rf_res *)resp->data; | ||
| 1220 | |||
| 1221 | status = le32_to_cpu(hdr->status); | ||
| 1222 | |||
| 1223 | if (cb_arg->mdaa && | ||
| 1224 | !port100_tg_target_activated(dev, hdr->target_activated)) { | ||
| 1225 | kfree_skb(resp); | ||
| 1226 | resp = ERR_PTR(-ETIMEDOUT); | ||
| 1227 | |||
| 1228 | goto exit; | ||
| 1229 | } | ||
| 1230 | |||
| 1231 | skb_pull(resp, sizeof(struct port100_tg_comm_rf_res)); | ||
| 1232 | |||
| 1233 | if (status != PORT100_CMD_STATUS_OK) { | ||
| 1234 | kfree_skb(resp); | ||
| 1235 | |||
| 1236 | if (status == PORT100_CMD_STATUS_TIMEOUT) | ||
| 1237 | resp = ERR_PTR(-ETIMEDOUT); | ||
| 1238 | else | ||
| 1239 | resp = ERR_PTR(-EIO); | ||
| 1240 | } | ||
| 1241 | |||
| 1242 | exit: | ||
| 1243 | cb(dev->nfc_digital_dev, cb_arg->complete_arg, resp); | ||
| 1244 | |||
| 1245 | kfree(cb_arg); | ||
| 1246 | } | ||
| 1247 | |||
| 1248 | static int port100_tg_send_cmd(struct nfc_digital_dev *ddev, | ||
| 1249 | struct sk_buff *skb, u16 timeout, | ||
| 1250 | nfc_digital_cmd_complete_t cb, void *arg) | ||
| 1251 | { | ||
| 1252 | struct port100 *dev = nfc_digital_get_drvdata(ddev); | ||
| 1253 | struct port100_tg_comm_rf_cmd *hdr; | ||
| 1254 | struct port100_cb_arg *cb_arg; | ||
| 1255 | |||
| 1256 | cb_arg = kzalloc(sizeof(struct port100_cb_arg), GFP_KERNEL); | ||
| 1257 | if (!cb_arg) | ||
| 1258 | return -ENOMEM; | ||
| 1259 | |||
| 1260 | cb_arg->complete_cb = cb; | ||
| 1261 | cb_arg->complete_arg = arg; | ||
| 1262 | |||
| 1263 | skb_push(skb, sizeof(struct port100_tg_comm_rf_cmd)); | ||
| 1264 | |||
| 1265 | hdr = (struct port100_tg_comm_rf_cmd *)skb->data; | ||
| 1266 | |||
| 1267 | memset(hdr, 0, sizeof(struct port100_tg_comm_rf_cmd)); | ||
| 1268 | hdr->guard_time = cpu_to_le16(500); | ||
| 1269 | hdr->send_timeout = cpu_to_le16(0xFFFF); | ||
| 1270 | hdr->recv_timeout = cpu_to_le16(timeout); | ||
| 1271 | |||
| 1272 | return port100_send_cmd_async(dev, PORT100_CMD_TG_COMM_RF, skb, | ||
| 1273 | port100_tg_comm_rf_complete, cb_arg); | ||
| 1274 | } | ||
| 1275 | |||
| 1276 | static int port100_listen_mdaa(struct nfc_digital_dev *ddev, | ||
| 1277 | struct digital_tg_mdaa_params *params, | ||
| 1278 | u16 timeout, | ||
| 1279 | nfc_digital_cmd_complete_t cb, void *arg) | ||
| 1280 | { | ||
| 1281 | struct port100 *dev = nfc_digital_get_drvdata(ddev); | ||
| 1282 | struct port100_tg_comm_rf_cmd *hdr; | ||
| 1283 | struct port100_cb_arg *cb_arg; | ||
| 1284 | struct sk_buff *skb; | ||
| 1285 | int rc; | ||
| 1286 | |||
| 1287 | rc = port100_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, | ||
| 1288 | NFC_DIGITAL_RF_TECH_106A); | ||
| 1289 | if (rc) | ||
| 1290 | return rc; | ||
| 1291 | |||
| 1292 | rc = port100_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, | ||
| 1293 | NFC_DIGITAL_FRAMING_NFCA_NFC_DEP); | ||
| 1294 | if (rc) | ||
| 1295 | return rc; | ||
| 1296 | |||
| 1297 | cb_arg = kzalloc(sizeof(struct port100_cb_arg), GFP_KERNEL); | ||
| 1298 | if (!cb_arg) | ||
| 1299 | return -ENOMEM; | ||
| 1300 | |||
| 1301 | cb_arg->complete_cb = cb; | ||
| 1302 | cb_arg->complete_arg = arg; | ||
| 1303 | cb_arg->mdaa = 1; | ||
| 1304 | |||
| 1305 | skb = port100_alloc_skb(dev, 0); | ||
| 1306 | if (!skb) { | ||
| 1307 | kfree(cb_arg); | ||
| 1308 | return -ENOMEM; | ||
| 1309 | } | ||
| 1310 | |||
| 1311 | skb_push(skb, sizeof(struct port100_tg_comm_rf_cmd)); | ||
| 1312 | hdr = (struct port100_tg_comm_rf_cmd *)skb->data; | ||
| 1313 | |||
| 1314 | memset(hdr, 0, sizeof(struct port100_tg_comm_rf_cmd)); | ||
| 1315 | |||
| 1316 | hdr->guard_time = 0; | ||
| 1317 | hdr->send_timeout = cpu_to_le16(0xFFFF); | ||
| 1318 | hdr->mdaa = 1; | ||
| 1319 | hdr->nfca_param[0] = (params->sens_res >> 8) & 0xFF; | ||
| 1320 | hdr->nfca_param[1] = params->sens_res & 0xFF; | ||
| 1321 | memcpy(hdr->nfca_param + 2, params->nfcid1, 3); | ||
| 1322 | hdr->nfca_param[5] = params->sel_res; | ||
| 1323 | memcpy(hdr->nfcf_param, params->nfcid2, 8); | ||
| 1324 | hdr->nfcf_param[16] = (params->sc >> 8) & 0xFF; | ||
| 1325 | hdr->nfcf_param[17] = params->sc & 0xFF; | ||
| 1326 | hdr->recv_timeout = cpu_to_le16(timeout); | ||
| 1327 | |||
| 1328 | return port100_send_cmd_async(dev, PORT100_CMD_TG_COMM_RF, skb, | ||
| 1329 | port100_tg_comm_rf_complete, cb_arg); | ||
| 1330 | } | ||
| 1331 | |||
| 1332 | static int port100_listen(struct nfc_digital_dev *ddev, u16 timeout, | ||
| 1333 | nfc_digital_cmd_complete_t cb, void *arg) | ||
| 1334 | { | ||
| 1335 | struct port100 *dev = nfc_digital_get_drvdata(ddev); | ||
| 1336 | struct sk_buff *skb; | ||
| 1337 | |||
| 1338 | skb = port100_alloc_skb(dev, 0); | ||
| 1339 | if (!skb) | ||
| 1340 | return -ENOMEM; | ||
| 1341 | |||
| 1342 | return port100_tg_send_cmd(ddev, skb, timeout, cb, arg); | ||
| 1343 | } | ||
| 1344 | |||
| 1345 | static struct nfc_digital_ops port100_digital_ops = { | ||
| 1346 | .in_configure_hw = port100_in_configure_hw, | ||
| 1347 | .in_send_cmd = port100_in_send_cmd, | ||
| 1348 | |||
| 1349 | .tg_listen_mdaa = port100_listen_mdaa, | ||
| 1350 | .tg_listen = port100_listen, | ||
| 1351 | .tg_configure_hw = port100_tg_configure_hw, | ||
| 1352 | .tg_send_cmd = port100_tg_send_cmd, | ||
| 1353 | |||
| 1354 | .switch_rf = port100_switch_rf, | ||
| 1355 | .abort_cmd = port100_abort_cmd, | ||
| 1356 | }; | ||
| 1357 | |||
| 1358 | static const struct usb_device_id port100_table[] = { | ||
| 1359 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE, | ||
| 1360 | .idVendor = SONY_VENDOR_ID, | ||
| 1361 | .idProduct = RCS380_PRODUCT_ID, | ||
| 1362 | }, | ||
| 1363 | { } | ||
| 1364 | }; | ||
| 1365 | MODULE_DEVICE_TABLE(usb, port100_table); | ||
| 1366 | |||
| 1367 | static int port100_probe(struct usb_interface *interface, | ||
| 1368 | const struct usb_device_id *id) | ||
| 1369 | { | ||
| 1370 | struct port100 *dev; | ||
| 1371 | int rc; | ||
| 1372 | struct usb_host_interface *iface_desc; | ||
| 1373 | struct usb_endpoint_descriptor *endpoint; | ||
| 1374 | int in_endpoint; | ||
| 1375 | int out_endpoint; | ||
| 1376 | u16 fw_version; | ||
| 1377 | u64 cmd_type_mask; | ||
| 1378 | int i; | ||
| 1379 | |||
| 1380 | dev = devm_kzalloc(&interface->dev, sizeof(struct port100), GFP_KERNEL); | ||
| 1381 | if (!dev) | ||
| 1382 | return -ENOMEM; | ||
| 1383 | |||
| 1384 | dev->udev = usb_get_dev(interface_to_usbdev(interface)); | ||
| 1385 | dev->interface = interface; | ||
| 1386 | usb_set_intfdata(interface, dev); | ||
| 1387 | |||
| 1388 | in_endpoint = out_endpoint = 0; | ||
| 1389 | iface_desc = interface->cur_altsetting; | ||
| 1390 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { | ||
| 1391 | endpoint = &iface_desc->endpoint[i].desc; | ||
| 1392 | |||
| 1393 | if (!in_endpoint && usb_endpoint_is_bulk_in(endpoint)) | ||
| 1394 | in_endpoint = endpoint->bEndpointAddress; | ||
| 1395 | |||
| 1396 | if (!out_endpoint && usb_endpoint_is_bulk_out(endpoint)) | ||
| 1397 | out_endpoint = endpoint->bEndpointAddress; | ||
| 1398 | } | ||
| 1399 | |||
| 1400 | if (!in_endpoint || !out_endpoint) { | ||
| 1401 | nfc_err(&interface->dev, | ||
| 1402 | "Could not find bulk-in or bulk-out endpoint\n"); | ||
| 1403 | rc = -ENODEV; | ||
| 1404 | goto error; | ||
| 1405 | } | ||
| 1406 | |||
| 1407 | dev->in_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
| 1408 | dev->out_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
| 1409 | |||
| 1410 | if (!dev->in_urb || !dev->out_urb) { | ||
| 1411 | nfc_err(&interface->dev, "Could not allocate USB URBs\n"); | ||
| 1412 | rc = -ENOMEM; | ||
| 1413 | goto error; | ||
| 1414 | } | ||
| 1415 | |||
| 1416 | usb_fill_bulk_urb(dev->in_urb, dev->udev, | ||
| 1417 | usb_rcvbulkpipe(dev->udev, in_endpoint), | ||
| 1418 | NULL, 0, NULL, dev); | ||
| 1419 | usb_fill_bulk_urb(dev->out_urb, dev->udev, | ||
| 1420 | usb_sndbulkpipe(dev->udev, out_endpoint), | ||
| 1421 | NULL, 0, port100_send_complete, dev); | ||
| 1422 | |||
| 1423 | dev->skb_headroom = PORT100_FRAME_HEADER_LEN + | ||
| 1424 | PORT100_COMM_RF_HEAD_MAX_LEN; | ||
| 1425 | dev->skb_tailroom = PORT100_FRAME_TAIL_LEN; | ||
| 1426 | |||
| 1427 | INIT_WORK(&dev->cmd_complete_work, port100_wq_cmd_complete); | ||
| 1428 | |||
| 1429 | /* The first thing to do with the Port-100 is to set the command type | ||
| 1430 | * to be used. If supported we use command type 1. 0 otherwise. | ||
| 1431 | */ | ||
| 1432 | cmd_type_mask = port100_get_command_type_mask(dev); | ||
| 1433 | if (!cmd_type_mask) { | ||
| 1434 | nfc_err(&interface->dev, | ||
| 1435 | "Could not get supported command types.\n"); | ||
| 1436 | rc = -ENODEV; | ||
| 1437 | goto error; | ||
| 1438 | } | ||
| 1439 | |||
| 1440 | if (PORT100_CMD_TYPE_IS_SUPPORTED(cmd_type_mask, PORT100_CMD_TYPE_1)) | ||
| 1441 | dev->cmd_type = PORT100_CMD_TYPE_1; | ||
| 1442 | else | ||
| 1443 | dev->cmd_type = PORT100_CMD_TYPE_0; | ||
| 1444 | |||
| 1445 | rc = port100_set_command_type(dev, dev->cmd_type); | ||
| 1446 | if (rc) { | ||
| 1447 | nfc_err(&interface->dev, | ||
| 1448 | "The device does not support command type %u.\n", | ||
| 1449 | dev->cmd_type); | ||
| 1450 | goto error; | ||
| 1451 | } | ||
| 1452 | |||
| 1453 | fw_version = port100_get_firmware_version(dev); | ||
| 1454 | if (!fw_version) | ||
| 1455 | nfc_err(&interface->dev, | ||
| 1456 | "Could not get device firmware version.\n"); | ||
| 1457 | |||
| 1458 | nfc_info(&interface->dev, | ||
| 1459 | "Sony NFC Port-100 Series attached (firmware v%x.%02x)\n", | ||
| 1460 | (fw_version & 0xFF00) >> 8, fw_version & 0xFF); | ||
| 1461 | |||
| 1462 | dev->nfc_digital_dev = nfc_digital_allocate_device(&port100_digital_ops, | ||
| 1463 | PORT100_PROTOCOLS, | ||
| 1464 | PORT100_CAPABILITIES, | ||
| 1465 | dev->skb_headroom, | ||
| 1466 | dev->skb_tailroom); | ||
| 1467 | if (!dev->nfc_digital_dev) { | ||
| 1468 | nfc_err(&interface->dev, | ||
| 1469 | "Could not allocate nfc_digital_dev.\n"); | ||
| 1470 | rc = -ENOMEM; | ||
| 1471 | goto error; | ||
| 1472 | } | ||
| 1473 | |||
| 1474 | nfc_digital_set_parent_dev(dev->nfc_digital_dev, &interface->dev); | ||
| 1475 | nfc_digital_set_drvdata(dev->nfc_digital_dev, dev); | ||
| 1476 | |||
| 1477 | rc = nfc_digital_register_device(dev->nfc_digital_dev); | ||
| 1478 | if (rc) { | ||
| 1479 | nfc_err(&interface->dev, | ||
| 1480 | "Could not register digital device.\n"); | ||
| 1481 | goto free_nfc_dev; | ||
| 1482 | } | ||
| 1483 | |||
| 1484 | return 0; | ||
| 1485 | |||
| 1486 | free_nfc_dev: | ||
| 1487 | nfc_digital_free_device(dev->nfc_digital_dev); | ||
| 1488 | |||
| 1489 | error: | ||
| 1490 | usb_free_urb(dev->in_urb); | ||
| 1491 | usb_free_urb(dev->out_urb); | ||
| 1492 | usb_put_dev(dev->udev); | ||
| 1493 | |||
| 1494 | return rc; | ||
| 1495 | } | ||
| 1496 | |||
| 1497 | static void port100_disconnect(struct usb_interface *interface) | ||
| 1498 | { | ||
| 1499 | struct port100 *dev; | ||
| 1500 | |||
| 1501 | dev = usb_get_intfdata(interface); | ||
| 1502 | usb_set_intfdata(interface, NULL); | ||
| 1503 | |||
| 1504 | nfc_digital_unregister_device(dev->nfc_digital_dev); | ||
| 1505 | nfc_digital_free_device(dev->nfc_digital_dev); | ||
| 1506 | |||
| 1507 | usb_kill_urb(dev->in_urb); | ||
| 1508 | usb_kill_urb(dev->out_urb); | ||
| 1509 | |||
| 1510 | usb_free_urb(dev->in_urb); | ||
| 1511 | usb_free_urb(dev->out_urb); | ||
| 1512 | |||
| 1513 | kfree(dev->cmd); | ||
| 1514 | |||
| 1515 | nfc_info(&interface->dev, "Sony Port-100 NFC device disconnected"); | ||
| 1516 | } | ||
| 1517 | |||
| 1518 | static struct usb_driver port100_driver = { | ||
| 1519 | .name = "port100", | ||
| 1520 | .probe = port100_probe, | ||
| 1521 | .disconnect = port100_disconnect, | ||
| 1522 | .id_table = port100_table, | ||
| 1523 | }; | ||
| 1524 | |||
| 1525 | module_usb_driver(port100_driver); | ||
| 1526 | |||
| 1527 | MODULE_DESCRIPTION("NFC Port-100 series usb driver ver " VERSION); | ||
| 1528 | MODULE_VERSION(VERSION); | ||
| 1529 | MODULE_LICENSE("GPL"); | ||
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index d0de412bfa43..2cc9517fb0d5 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h | |||
| @@ -218,11 +218,10 @@ void baswap(bdaddr_t *dst, bdaddr_t *src); | |||
| 218 | 218 | ||
| 219 | struct bt_sock { | 219 | struct bt_sock { |
| 220 | struct sock sk; | 220 | struct sock sk; |
| 221 | bdaddr_t src; | ||
| 222 | bdaddr_t dst; | ||
| 223 | struct list_head accept_q; | 221 | struct list_head accept_q; |
| 224 | struct sock *parent; | 222 | struct sock *parent; |
| 225 | unsigned long flags; | 223 | unsigned long flags; |
| 224 | void (*skb_msg_name)(struct sk_buff *, void *, int *); | ||
| 226 | }; | 225 | }; |
| 227 | 226 | ||
| 228 | enum { | 227 | enum { |
| @@ -285,6 +284,8 @@ struct bt_skb_cb { | |||
| 285 | __u8 force_active; | 284 | __u8 force_active; |
| 286 | struct l2cap_ctrl control; | 285 | struct l2cap_ctrl control; |
| 287 | struct hci_req_ctrl req; | 286 | struct hci_req_ctrl req; |
| 287 | bdaddr_t bdaddr; | ||
| 288 | __le16 psm; | ||
| 288 | }; | 289 | }; |
| 289 | #define bt_cb(skb) ((struct bt_skb_cb *)((skb)->cb)) | 290 | #define bt_cb(skb) ((struct bt_skb_cb *)((skb)->cb)) |
| 290 | 291 | ||
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index b90eec5e9c06..b096f5f73789 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h | |||
| @@ -64,16 +64,20 @@ | |||
| 64 | #define HCI_AMP 0x01 | 64 | #define HCI_AMP 0x01 |
| 65 | 65 | ||
| 66 | /* First BR/EDR Controller shall have ID = 0 */ | 66 | /* First BR/EDR Controller shall have ID = 0 */ |
| 67 | #define HCI_BREDR_ID 0 | 67 | #define AMP_ID_BREDR 0x00 |
| 68 | |||
| 69 | /* AMP controller types */ | ||
| 70 | #define AMP_TYPE_BREDR 0x00 | ||
| 71 | #define AMP_TYPE_80211 0x01 | ||
| 68 | 72 | ||
| 69 | /* AMP controller status */ | 73 | /* AMP controller status */ |
| 70 | #define AMP_CTRL_POWERED_DOWN 0x00 | 74 | #define AMP_STATUS_POWERED_DOWN 0x00 |
| 71 | #define AMP_CTRL_BLUETOOTH_ONLY 0x01 | 75 | #define AMP_STATUS_BLUETOOTH_ONLY 0x01 |
| 72 | #define AMP_CTRL_NO_CAPACITY 0x02 | 76 | #define AMP_STATUS_NO_CAPACITY 0x02 |
| 73 | #define AMP_CTRL_LOW_CAPACITY 0x03 | 77 | #define AMP_STATUS_LOW_CAPACITY 0x03 |
| 74 | #define AMP_CTRL_MEDIUM_CAPACITY 0x04 | 78 | #define AMP_STATUS_MEDIUM_CAPACITY 0x04 |
| 75 | #define AMP_CTRL_HIGH_CAPACITY 0x05 | 79 | #define AMP_STATUS_HIGH_CAPACITY 0x05 |
| 76 | #define AMP_CTRL_FULL_CAPACITY 0x06 | 80 | #define AMP_STATUS_FULL_CAPACITY 0x06 |
| 77 | 81 | ||
| 78 | /* HCI device quirks */ | 82 | /* HCI device quirks */ |
| 79 | enum { | 83 | enum { |
| @@ -118,7 +122,7 @@ enum { | |||
| 118 | HCI_SSP_ENABLED, | 122 | HCI_SSP_ENABLED, |
| 119 | HCI_HS_ENABLED, | 123 | HCI_HS_ENABLED, |
| 120 | HCI_LE_ENABLED, | 124 | HCI_LE_ENABLED, |
| 121 | HCI_LE_PERIPHERAL, | 125 | HCI_ADVERTISING, |
| 122 | HCI_CONNECTABLE, | 126 | HCI_CONNECTABLE, |
| 123 | HCI_DISCOVERABLE, | 127 | HCI_DISCOVERABLE, |
| 124 | HCI_LINK_SECURITY, | 128 | HCI_LINK_SECURITY, |
| @@ -811,6 +815,14 @@ struct hci_cp_host_buffer_size { | |||
| 811 | __le16 sco_max_pkt; | 815 | __le16 sco_max_pkt; |
| 812 | } __packed; | 816 | } __packed; |
| 813 | 817 | ||
| 818 | #define HCI_OP_READ_NUM_SUPPORTED_IAC 0x0c38 | ||
| 819 | struct hci_rp_read_num_supported_iac { | ||
| 820 | __u8 status; | ||
| 821 | __u8 num_iac; | ||
| 822 | } __packed; | ||
| 823 | |||
| 824 | #define HCI_OP_READ_CURRENT_IAC_LAP 0x0c39 | ||
| 825 | |||
| 814 | #define HCI_OP_WRITE_INQUIRY_MODE 0x0c45 | 826 | #define HCI_OP_WRITE_INQUIRY_MODE 0x0c45 |
| 815 | 827 | ||
| 816 | #define HCI_MAX_EIR_LENGTH 240 | 828 | #define HCI_MAX_EIR_LENGTH 240 |
| @@ -847,6 +859,8 @@ struct hci_rp_read_inq_rsp_tx_power { | |||
| 847 | 859 | ||
| 848 | #define HCI_OP_SET_EVENT_MASK_PAGE_2 0x0c63 | 860 | #define HCI_OP_SET_EVENT_MASK_PAGE_2 0x0c63 |
| 849 | 861 | ||
| 862 | #define HCI_OP_READ_LOCATION_DATA 0x0c64 | ||
| 863 | |||
| 850 | #define HCI_OP_READ_FLOW_CONTROL_MODE 0x0c66 | 864 | #define HCI_OP_READ_FLOW_CONTROL_MODE 0x0c66 |
| 851 | struct hci_rp_read_flow_control_mode { | 865 | struct hci_rp_read_flow_control_mode { |
| 852 | __u8 status; | 866 | __u8 status; |
| @@ -1042,6 +1056,23 @@ struct hci_rp_le_read_local_features { | |||
| 1042 | 1056 | ||
| 1043 | #define HCI_OP_LE_SET_RANDOM_ADDR 0x2005 | 1057 | #define HCI_OP_LE_SET_RANDOM_ADDR 0x2005 |
| 1044 | 1058 | ||
| 1059 | #define LE_ADV_IND 0x00 | ||
| 1060 | #define LE_ADV_DIRECT_IND 0x01 | ||
| 1061 | #define LE_ADV_SCAN_IND 0x02 | ||
| 1062 | #define LE_ADV_NONCONN_IND 0x03 | ||
| 1063 | |||
| 1064 | #define HCI_OP_LE_SET_ADV_PARAM 0x2006 | ||
| 1065 | struct hci_cp_le_set_adv_param { | ||
| 1066 | __le16 min_interval; | ||
| 1067 | __le16 max_interval; | ||
| 1068 | __u8 type; | ||
| 1069 | __u8 own_address_type; | ||
| 1070 | __u8 direct_addr_type; | ||
| 1071 | bdaddr_t direct_addr; | ||
| 1072 | __u8 channel_map; | ||
| 1073 | __u8 filter_policy; | ||
| 1074 | } __packed; | ||
| 1075 | |||
| 1045 | #define HCI_OP_LE_READ_ADV_TX_POWER 0x2007 | 1076 | #define HCI_OP_LE_READ_ADV_TX_POWER 0x2007 |
| 1046 | struct hci_rp_le_read_adv_tx_power { | 1077 | struct hci_rp_le_read_adv_tx_power { |
| 1047 | __u8 status; | 1078 | __u8 status; |
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index e3ea48d6c992..2dc467939be7 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
| @@ -159,11 +159,14 @@ struct hci_dev { | |||
| 159 | __u16 manufacturer; | 159 | __u16 manufacturer; |
| 160 | __u16 lmp_subver; | 160 | __u16 lmp_subver; |
| 161 | __u16 voice_setting; | 161 | __u16 voice_setting; |
| 162 | __u8 num_iac; | ||
| 162 | __u8 io_capability; | 163 | __u8 io_capability; |
| 163 | __s8 inq_tx_power; | 164 | __s8 inq_tx_power; |
| 164 | __u16 page_scan_interval; | 165 | __u16 page_scan_interval; |
| 165 | __u16 page_scan_window; | 166 | __u16 page_scan_window; |
| 166 | __u8 page_scan_type; | 167 | __u8 page_scan_type; |
| 168 | __u16 le_scan_interval; | ||
| 169 | __u16 le_scan_window; | ||
| 167 | 170 | ||
| 168 | __u16 devid_source; | 171 | __u16 devid_source; |
| 169 | __u16 devid_vendor; | 172 | __u16 devid_vendor; |
| @@ -285,9 +288,8 @@ struct hci_dev { | |||
| 285 | int (*close)(struct hci_dev *hdev); | 288 | int (*close)(struct hci_dev *hdev); |
| 286 | int (*flush)(struct hci_dev *hdev); | 289 | int (*flush)(struct hci_dev *hdev); |
| 287 | int (*setup)(struct hci_dev *hdev); | 290 | int (*setup)(struct hci_dev *hdev); |
| 288 | int (*send)(struct sk_buff *skb); | 291 | int (*send)(struct hci_dev *hdev, struct sk_buff *skb); |
| 289 | void (*notify)(struct hci_dev *hdev, unsigned int evt); | 292 | void (*notify)(struct hci_dev *hdev, unsigned int evt); |
| 290 | int (*ioctl)(struct hci_dev *hdev, unsigned int cmd, unsigned long arg); | ||
| 291 | }; | 293 | }; |
| 292 | 294 | ||
| 293 | #define HCI_PHY_HANDLE(handle) (handle & 0xff) | 295 | #define HCI_PHY_HANDLE(handle) (handle & 0xff) |
| @@ -299,6 +301,8 @@ struct hci_conn { | |||
| 299 | 301 | ||
| 300 | bdaddr_t dst; | 302 | bdaddr_t dst; |
| 301 | __u8 dst_type; | 303 | __u8 dst_type; |
| 304 | bdaddr_t src; | ||
| 305 | __u8 src_type; | ||
| 302 | __u16 handle; | 306 | __u16 handle; |
| 303 | __u16 state; | 307 | __u16 state; |
| 304 | __u8 mode; | 308 | __u8 mode; |
| @@ -703,19 +707,6 @@ static inline void hci_set_drvdata(struct hci_dev *hdev, void *data) | |||
| 703 | dev_set_drvdata(&hdev->dev, data); | 707 | dev_set_drvdata(&hdev->dev, data); |
| 704 | } | 708 | } |
| 705 | 709 | ||
| 706 | /* hci_dev_list shall be locked */ | ||
| 707 | static inline uint8_t __hci_num_ctrl(void) | ||
| 708 | { | ||
| 709 | uint8_t count = 0; | ||
| 710 | struct list_head *p; | ||
| 711 | |||
| 712 | list_for_each(p, &hci_dev_list) { | ||
| 713 | count++; | ||
| 714 | } | ||
| 715 | |||
| 716 | return count; | ||
| 717 | } | ||
| 718 | |||
| 719 | struct hci_dev *hci_dev_get(int index); | 710 | struct hci_dev *hci_dev_get(int index); |
| 720 | struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src); | 711 | struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src); |
| 721 | 712 | ||
| @@ -768,7 +759,7 @@ int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr); | |||
| 768 | 759 | ||
| 769 | void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb); | 760 | void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb); |
| 770 | 761 | ||
| 771 | int hci_recv_frame(struct sk_buff *skb); | 762 | int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb); |
| 772 | int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count); | 763 | int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count); |
| 773 | int hci_recv_stream_fragment(struct hci_dev *hdev, void *data, int count); | 764 | int hci_recv_stream_fragment(struct hci_dev *hdev, void *data, int count); |
| 774 | 765 | ||
| @@ -807,22 +798,6 @@ void hci_conn_del_sysfs(struct hci_conn *conn); | |||
| 807 | #define lmp_host_le_capable(dev) (!!((dev)->features[1][0] & LMP_HOST_LE)) | 798 | #define lmp_host_le_capable(dev) (!!((dev)->features[1][0] & LMP_HOST_LE)) |
| 808 | #define lmp_host_le_br_capable(dev) (!!((dev)->features[1][0] & LMP_HOST_LE_BREDR)) | 799 | #define lmp_host_le_br_capable(dev) (!!((dev)->features[1][0] & LMP_HOST_LE_BREDR)) |
| 809 | 800 | ||
| 810 | /* returns true if at least one AMP active */ | ||
| 811 | static inline bool hci_amp_capable(void) | ||
| 812 | { | ||
| 813 | struct hci_dev *hdev; | ||
| 814 | bool ret = false; | ||
| 815 | |||
| 816 | read_lock(&hci_dev_list_lock); | ||
| 817 | list_for_each_entry(hdev, &hci_dev_list, list) | ||
| 818 | if (hdev->amp_type == HCI_AMP && | ||
| 819 | test_bit(HCI_UP, &hdev->flags)) | ||
| 820 | ret = true; | ||
| 821 | read_unlock(&hci_dev_list_lock); | ||
| 822 | |||
| 823 | return ret; | ||
| 824 | } | ||
| 825 | |||
| 826 | /* ----- HCI protocols ----- */ | 801 | /* ----- HCI protocols ----- */ |
| 827 | #define HCI_PROTO_DEFER 0x01 | 802 | #define HCI_PROTO_DEFER 0x01 |
| 828 | 803 | ||
| @@ -1120,24 +1095,24 @@ void hci_sock_dev_event(struct hci_dev *hdev, int event); | |||
| 1120 | #define DISCOV_BREDR_INQUIRY_LEN 0x08 | 1095 | #define DISCOV_BREDR_INQUIRY_LEN 0x08 |
| 1121 | 1096 | ||
| 1122 | int mgmt_control(struct sock *sk, struct msghdr *msg, size_t len); | 1097 | int mgmt_control(struct sock *sk, struct msghdr *msg, size_t len); |
| 1123 | int mgmt_index_added(struct hci_dev *hdev); | 1098 | void mgmt_index_added(struct hci_dev *hdev); |
| 1124 | int mgmt_index_removed(struct hci_dev *hdev); | 1099 | void mgmt_index_removed(struct hci_dev *hdev); |
| 1125 | int mgmt_set_powered_failed(struct hci_dev *hdev, int err); | 1100 | void mgmt_set_powered_failed(struct hci_dev *hdev, int err); |
| 1126 | int mgmt_powered(struct hci_dev *hdev, u8 powered); | 1101 | int mgmt_powered(struct hci_dev *hdev, u8 powered); |
| 1127 | int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable); | 1102 | int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable); |
| 1128 | int mgmt_connectable(struct hci_dev *hdev, u8 connectable); | 1103 | int mgmt_connectable(struct hci_dev *hdev, u8 connectable); |
| 1129 | int mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status); | 1104 | int mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status); |
| 1130 | int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, | 1105 | int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, |
| 1131 | bool persistent); | 1106 | bool persistent); |
| 1132 | int mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | 1107 | void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, |
| 1133 | u8 addr_type, u32 flags, u8 *name, u8 name_len, | 1108 | u8 addr_type, u32 flags, u8 *name, u8 name_len, |
| 1134 | u8 *dev_class); | 1109 | u8 *dev_class); |
| 1135 | int mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, | 1110 | void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, |
| 1136 | u8 link_type, u8 addr_type, u8 reason); | 1111 | u8 link_type, u8 addr_type, u8 reason); |
| 1137 | int mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, | 1112 | void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, |
| 1138 | u8 link_type, u8 addr_type, u8 status); | 1113 | u8 link_type, u8 addr_type, u8 status); |
| 1139 | int mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | 1114 | void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, |
| 1140 | u8 addr_type, u8 status); | 1115 | u8 addr_type, u8 status); |
| 1141 | int mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure); | 1116 | int mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure); |
| 1142 | int mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, | 1117 | int mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, |
| 1143 | u8 status); | 1118 | u8 status); |
| @@ -1168,16 +1143,16 @@ int mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class, | |||
| 1168 | int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status); | 1143 | int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status); |
| 1169 | int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash, | 1144 | int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash, |
| 1170 | u8 *randomizer, u8 status); | 1145 | u8 *randomizer, u8 status); |
| 1171 | int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | 1146 | void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, |
| 1172 | u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name, | 1147 | u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name, |
| 1173 | u8 ssp, u8 *eir, u16 eir_len); | 1148 | u8 ssp, u8 *eir, u16 eir_len); |
| 1174 | int mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | 1149 | void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, |
| 1175 | u8 addr_type, s8 rssi, u8 *name, u8 name_len); | 1150 | u8 addr_type, s8 rssi, u8 *name, u8 name_len); |
| 1176 | int mgmt_discovering(struct hci_dev *hdev, u8 discovering); | 1151 | void mgmt_discovering(struct hci_dev *hdev, u8 discovering); |
| 1177 | int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); | 1152 | int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); |
| 1178 | int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); | 1153 | int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); |
| 1179 | bool mgmt_valid_hdev(struct hci_dev *hdev); | ||
| 1180 | int mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent); | 1154 | int mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent); |
| 1155 | void mgmt_reenable_advertising(struct hci_dev *hdev); | ||
| 1181 | 1156 | ||
| 1182 | /* HCI info for socket */ | 1157 | /* HCI info for socket */ |
| 1183 | #define hci_pi(sk) ((struct hci_pinfo *) sk) | 1158 | #define hci_pi(sk) ((struct hci_pinfo *) sk) |
| @@ -1214,8 +1189,6 @@ void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, | |||
| 1214 | void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8], | 1189 | void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8], |
| 1215 | __u8 ltk[16]); | 1190 | __u8 ltk[16]); |
| 1216 | 1191 | ||
| 1217 | u8 bdaddr_to_le(u8 bdaddr_type); | ||
| 1218 | |||
| 1219 | #define SCO_AIRMODE_MASK 0x0003 | 1192 | #define SCO_AIRMODE_MASK 0x0003 |
| 1220 | #define SCO_AIRMODE_CVSD 0x0000 | 1193 | #define SCO_AIRMODE_CVSD 0x0000 |
| 1221 | #define SCO_AIRMODE_TRANSP 0x0003 | 1194 | #define SCO_AIRMODE_TRANSP 0x0003 |
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index f141b5f6e4f1..07757a2af942 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h | |||
| @@ -131,6 +131,7 @@ struct l2cap_conninfo { | |||
| 131 | 131 | ||
| 132 | /* L2CAP fixed channels */ | 132 | /* L2CAP fixed channels */ |
| 133 | #define L2CAP_FC_L2CAP 0x02 | 133 | #define L2CAP_FC_L2CAP 0x02 |
| 134 | #define L2CAP_FC_CONNLESS 0x04 | ||
| 134 | #define L2CAP_FC_A2MP 0x08 | 135 | #define L2CAP_FC_A2MP 0x08 |
| 135 | 136 | ||
| 136 | /* L2CAP Control Field bit masks */ | 137 | /* L2CAP Control Field bit masks */ |
| @@ -237,6 +238,7 @@ struct l2cap_conn_rsp { | |||
| 237 | /* protocol/service multiplexer (PSM) */ | 238 | /* protocol/service multiplexer (PSM) */ |
| 238 | #define L2CAP_PSM_SDP 0x0001 | 239 | #define L2CAP_PSM_SDP 0x0001 |
| 239 | #define L2CAP_PSM_RFCOMM 0x0003 | 240 | #define L2CAP_PSM_RFCOMM 0x0003 |
| 241 | #define L2CAP_PSM_3DSP 0x0021 | ||
| 240 | 242 | ||
| 241 | /* channel indentifier */ | 243 | /* channel indentifier */ |
| 242 | #define L2CAP_CID_SIGNALING 0x0001 | 244 | #define L2CAP_CID_SIGNALING 0x0001 |
| @@ -442,7 +444,12 @@ struct l2cap_chan { | |||
| 442 | 444 | ||
| 443 | __u8 state; | 445 | __u8 state; |
| 444 | 446 | ||
| 447 | bdaddr_t dst; | ||
| 448 | __u8 dst_type; | ||
| 449 | bdaddr_t src; | ||
| 450 | __u8 src_type; | ||
| 445 | __le16 psm; | 451 | __le16 psm; |
| 452 | __le16 sport; | ||
| 446 | __u16 dcid; | 453 | __u16 dcid; |
| 447 | __u16 scid; | 454 | __u16 scid; |
| 448 | 455 | ||
| @@ -453,8 +460,6 @@ struct l2cap_chan { | |||
| 453 | __u8 chan_type; | 460 | __u8 chan_type; |
| 454 | __u8 chan_policy; | 461 | __u8 chan_policy; |
| 455 | 462 | ||
| 456 | __le16 sport; | ||
| 457 | |||
| 458 | __u8 sec_level; | 463 | __u8 sec_level; |
| 459 | 464 | ||
| 460 | __u8 ident; | 465 | __u8 ident; |
| @@ -549,6 +554,7 @@ struct l2cap_ops { | |||
| 549 | int state); | 554 | int state); |
| 550 | void (*ready) (struct l2cap_chan *chan); | 555 | void (*ready) (struct l2cap_chan *chan); |
| 551 | void (*defer) (struct l2cap_chan *chan); | 556 | void (*defer) (struct l2cap_chan *chan); |
| 557 | void (*resume) (struct l2cap_chan *chan); | ||
| 552 | struct sk_buff *(*alloc_skb) (struct l2cap_chan *chan, | 558 | struct sk_buff *(*alloc_skb) (struct l2cap_chan *chan, |
| 553 | unsigned long len, int nb); | 559 | unsigned long len, int nb); |
| 554 | }; | 560 | }; |
| @@ -557,9 +563,6 @@ struct l2cap_conn { | |||
| 557 | struct hci_conn *hcon; | 563 | struct hci_conn *hcon; |
| 558 | struct hci_chan *hchan; | 564 | struct hci_chan *hchan; |
| 559 | 565 | ||
| 560 | bdaddr_t *dst; | ||
| 561 | bdaddr_t *src; | ||
| 562 | |||
| 563 | unsigned int mtu; | 566 | unsigned int mtu; |
| 564 | 567 | ||
| 565 | __u32 feat_mask; | 568 | __u32 feat_mask; |
| @@ -650,6 +653,7 @@ enum { | |||
| 650 | FLAG_FLUSHABLE, | 653 | FLAG_FLUSHABLE, |
| 651 | FLAG_EXT_CTRL, | 654 | FLAG_EXT_CTRL, |
| 652 | FLAG_EFS_ENABLE, | 655 | FLAG_EFS_ENABLE, |
| 656 | FLAG_DEFER_SETUP, | ||
| 653 | }; | 657 | }; |
| 654 | 658 | ||
| 655 | enum { | 659 | enum { |
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index 2ad433bb9a2e..518c5c84e39a 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h | |||
| @@ -362,6 +362,13 @@ struct mgmt_cp_set_static_address { | |||
| 362 | } __packed; | 362 | } __packed; |
| 363 | #define MGMT_SET_STATIC_ADDRESS_SIZE 6 | 363 | #define MGMT_SET_STATIC_ADDRESS_SIZE 6 |
| 364 | 364 | ||
| 365 | #define MGMT_OP_SET_SCAN_PARAMS 0x002C | ||
| 366 | struct mgmt_cp_set_scan_params { | ||
| 367 | __le16 interval; | ||
| 368 | __le16 window; | ||
| 369 | } __packed; | ||
| 370 | #define MGMT_SET_SCAN_PARAMS_SIZE 4 | ||
| 371 | |||
| 365 | #define MGMT_EV_CMD_COMPLETE 0x0001 | 372 | #define MGMT_EV_CMD_COMPLETE 0x0001 |
| 366 | struct mgmt_ev_cmd_complete { | 373 | struct mgmt_ev_cmd_complete { |
| 367 | __le16 opcode; | 374 | __le16 opcode; |
diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h index b7f43e76a5c5..486213a1aed8 100644 --- a/include/net/bluetooth/rfcomm.h +++ b/include/net/bluetooth/rfcomm.h | |||
| @@ -300,6 +300,8 @@ struct rfcomm_conninfo { | |||
| 300 | 300 | ||
| 301 | struct rfcomm_pinfo { | 301 | struct rfcomm_pinfo { |
| 302 | struct bt_sock bt; | 302 | struct bt_sock bt; |
| 303 | bdaddr_t src; | ||
| 304 | bdaddr_t dst; | ||
| 303 | struct rfcomm_dlc *dlc; | 305 | struct rfcomm_dlc *dlc; |
| 304 | u8 channel; | 306 | u8 channel; |
| 305 | u8 sec_level; | 307 | u8 sec_level; |
diff --git a/include/net/bluetooth/sco.h b/include/net/bluetooth/sco.h index e252a31ee6b6..2019d1a0996a 100644 --- a/include/net/bluetooth/sco.h +++ b/include/net/bluetooth/sco.h | |||
| @@ -55,9 +55,6 @@ struct sco_conninfo { | |||
| 55 | struct sco_conn { | 55 | struct sco_conn { |
| 56 | struct hci_conn *hcon; | 56 | struct hci_conn *hcon; |
| 57 | 57 | ||
| 58 | bdaddr_t *dst; | ||
| 59 | bdaddr_t *src; | ||
| 60 | |||
| 61 | spinlock_t lock; | 58 | spinlock_t lock; |
| 62 | struct sock *sk; | 59 | struct sock *sk; |
| 63 | 60 | ||
| @@ -72,6 +69,8 @@ struct sco_conn { | |||
| 72 | 69 | ||
| 73 | struct sco_pinfo { | 70 | struct sco_pinfo { |
| 74 | struct bt_sock bt; | 71 | struct bt_sock bt; |
| 72 | bdaddr_t src; | ||
| 73 | bdaddr_t dst; | ||
| 75 | __u32 flags; | 74 | __u32 flags; |
| 76 | __u16 setting; | 75 | __u16 setting; |
| 77 | struct sco_conn *conn; | 76 | struct sco_conn *conn; |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 45f6bf591104..419202ce3f95 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
| @@ -3483,6 +3483,15 @@ void wiphy_apply_custom_regulatory(struct wiphy *wiphy, | |||
| 3483 | const struct ieee80211_reg_rule *freq_reg_info(struct wiphy *wiphy, | 3483 | const struct ieee80211_reg_rule *freq_reg_info(struct wiphy *wiphy, |
| 3484 | u32 center_freq); | 3484 | u32 center_freq); |
| 3485 | 3485 | ||
| 3486 | /** | ||
| 3487 | * reg_initiator_name - map regulatory request initiator enum to name | ||
| 3488 | * @initiator: the regulatory request initiator | ||
| 3489 | * | ||
| 3490 | * You can use this to map the regulatory request initiator enum to a | ||
| 3491 | * proper string representation. | ||
| 3492 | */ | ||
| 3493 | const char *reg_initiator_name(enum nl80211_reg_initiator initiator); | ||
| 3494 | |||
| 3486 | /* | 3495 | /* |
| 3487 | * callbacks for asynchronous cfg80211 methods, notification | 3496 | * callbacks for asynchronous cfg80211 methods, notification |
| 3488 | * functions and BSS handling helpers | 3497 | * functions and BSS handling helpers |
diff --git a/include/net/nfc/digital.h b/include/net/nfc/digital.h new file mode 100644 index 000000000000..36acecd5f06c --- /dev/null +++ b/include/net/nfc/digital.h | |||
| @@ -0,0 +1,227 @@ | |||
| 1 | /* | ||
| 2 | * NFC Digital Protocol stack | ||
| 3 | * Copyright (c) 2013, Intel Corporation. | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify it | ||
| 6 | * under the terms and conditions of the GNU General Public License, | ||
| 7 | * version 2, as published by the Free Software Foundation. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
| 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 12 | * more details. | ||
| 13 | * | ||
| 14 | */ | ||
| 15 | |||
| 16 | #ifndef __NFC_DIGITAL_H | ||
| 17 | #define __NFC_DIGITAL_H | ||
| 18 | |||
| 19 | #include <linux/skbuff.h> | ||
| 20 | #include <net/nfc/nfc.h> | ||
| 21 | |||
| 22 | /** | ||
| 23 | * Configuration types for in_configure_hw and tg_configure_hw. | ||
| 24 | */ | ||
| 25 | enum { | ||
| 26 | NFC_DIGITAL_CONFIG_RF_TECH = 0, | ||
| 27 | NFC_DIGITAL_CONFIG_FRAMING, | ||
| 28 | }; | ||
| 29 | |||
| 30 | /** | ||
| 31 | * RF technology values passed as param argument to in_configure_hw and | ||
| 32 | * tg_configure_hw for NFC_DIGITAL_CONFIG_RF_TECH configuration type. | ||
| 33 | */ | ||
| 34 | enum { | ||
| 35 | NFC_DIGITAL_RF_TECH_106A = 0, | ||
| 36 | NFC_DIGITAL_RF_TECH_212F, | ||
| 37 | NFC_DIGITAL_RF_TECH_424F, | ||
| 38 | |||
| 39 | NFC_DIGITAL_RF_TECH_LAST, | ||
| 40 | }; | ||
| 41 | |||
| 42 | /** | ||
| 43 | * Framing configuration passed as param argument to in_configure_hw and | ||
| 44 | * tg_configure_hw for NFC_DIGITAL_CONFIG_FRAMING configuration type. | ||
| 45 | */ | ||
| 46 | enum { | ||
| 47 | NFC_DIGITAL_FRAMING_NFCA_SHORT = 0, | ||
| 48 | NFC_DIGITAL_FRAMING_NFCA_STANDARD, | ||
| 49 | NFC_DIGITAL_FRAMING_NFCA_STANDARD_WITH_CRC_A, | ||
| 50 | |||
| 51 | NFC_DIGITAL_FRAMING_NFCA_T1T, | ||
| 52 | NFC_DIGITAL_FRAMING_NFCA_T2T, | ||
| 53 | NFC_DIGITAL_FRAMING_NFCA_NFC_DEP, | ||
| 54 | |||
| 55 | NFC_DIGITAL_FRAMING_NFCF, | ||
| 56 | NFC_DIGITAL_FRAMING_NFCF_T3T, | ||
| 57 | NFC_DIGITAL_FRAMING_NFCF_NFC_DEP, | ||
| 58 | NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED, | ||
| 59 | |||
| 60 | NFC_DIGITAL_FRAMING_LAST, | ||
| 61 | }; | ||
| 62 | |||
| 63 | #define DIGITAL_MDAA_NFCID1_SIZE 3 | ||
| 64 | |||
| 65 | struct digital_tg_mdaa_params { | ||
| 66 | u16 sens_res; | ||
| 67 | u8 nfcid1[DIGITAL_MDAA_NFCID1_SIZE]; | ||
| 68 | u8 sel_res; | ||
| 69 | |||
| 70 | u8 nfcid2[NFC_NFCID2_MAXSIZE]; | ||
| 71 | u16 sc; | ||
| 72 | }; | ||
| 73 | |||
| 74 | struct nfc_digital_dev; | ||
| 75 | |||
| 76 | /** | ||
| 77 | * nfc_digital_cmd_complete_t - Definition of command result callback | ||
| 78 | * | ||
| 79 | * @ddev: nfc_digital_device ref | ||
| 80 | * @arg: user data | ||
| 81 | * @resp: response data | ||
| 82 | * | ||
| 83 | * resp pointer can be an error code and will be checked with IS_ERR() macro. | ||
| 84 | * The callback is responsible for freeing resp sk_buff. | ||
| 85 | */ | ||
| 86 | typedef void (*nfc_digital_cmd_complete_t)(struct nfc_digital_dev *ddev, | ||
| 87 | void *arg, struct sk_buff *resp); | ||
| 88 | |||
| 89 | /** | ||
| 90 | * Device side NFC Digital operations | ||
| 91 | * | ||
| 92 | * Initiator mode: | ||
| 93 | * @in_configure_hw: Hardware configuration for RF technology and communication | ||
| 94 | * framing in initiator mode. This is a synchronous function. | ||
| 95 | * @in_send_cmd: Initiator mode data exchange using RF technology and framing | ||
| 96 | * previously set with in_configure_hw. The peer response is returned | ||
| 97 | * through callback cb. If an io error occurs or the peer didn't reply | ||
| 98 | * within the specified timeout (ms), the error code is passed back through | ||
| 99 | * the resp pointer. This is an asynchronous function. | ||
| 100 | * | ||
| 101 | * Target mode: Only NFC-DEP protocol is supported in target mode. | ||
| 102 | * @tg_configure_hw: Hardware configuration for RF technology and communication | ||
| 103 | * framing in target mode. This is a synchronous function. | ||
| 104 | * @tg_send_cmd: Target mode data exchange using RF technology and framing | ||
| 105 | * previously set with tg_configure_hw. The peer next command is returned | ||
| 106 | * through callback cb. If an io error occurs or the peer didn't reply | ||
| 107 | * within the specified timeout (ms), the error code is passed back through | ||
| 108 | * the resp pointer. This is an asynchronous function. | ||
| 109 | * @tg_listen: Put the device in listen mode waiting for data from the peer | ||
| 110 | * device. This is an asynchronous function. | ||
| 111 | * @tg_listen_mdaa: If supported, put the device in automatic listen mode with | ||
| 112 | * mode detection and automatic anti-collision. In this mode, the device | ||
| 113 | * automatically detects the RF technology and executes the anti-collision | ||
| 114 | * detection using the command responses specified in mdaa_params. The | ||
| 115 | * mdaa_params structure contains SENS_RES, NFCID1, and SEL_RES for 106A RF | ||
| 116 | * tech. NFCID2 and system code (sc) for 212F and 424F. The driver returns | ||
| 117 | * the NFC-DEP ATR_REQ command through cb. The digital stack deducts the RF | ||
| 118 | * tech by analyzing the SoD of the frame containing the ATR_REQ command. | ||
| 119 | * This is an asynchronous function. | ||
| 120 | * | ||
| 121 | * @switch_rf: Turns device radio on or off. The stack does not call explicitly | ||
| 122 | * switch_rf to turn the radio on. A call to in|tg_configure_hw must turn | ||
| 123 | * the device radio on. | ||
| 124 | * @abort_cmd: Discard the last sent command. | ||
| 125 | */ | ||
| 126 | struct nfc_digital_ops { | ||
| 127 | int (*in_configure_hw)(struct nfc_digital_dev *ddev, int type, | ||
| 128 | int param); | ||
| 129 | int (*in_send_cmd)(struct nfc_digital_dev *ddev, struct sk_buff *skb, | ||
| 130 | u16 timeout, nfc_digital_cmd_complete_t cb, | ||
| 131 | void *arg); | ||
| 132 | |||
| 133 | int (*tg_configure_hw)(struct nfc_digital_dev *ddev, int type, | ||
| 134 | int param); | ||
| 135 | int (*tg_send_cmd)(struct nfc_digital_dev *ddev, struct sk_buff *skb, | ||
| 136 | u16 timeout, nfc_digital_cmd_complete_t cb, | ||
| 137 | void *arg); | ||
| 138 | int (*tg_listen)(struct nfc_digital_dev *ddev, u16 timeout, | ||
| 139 | nfc_digital_cmd_complete_t cb, void *arg); | ||
| 140 | int (*tg_listen_mdaa)(struct nfc_digital_dev *ddev, | ||
| 141 | struct digital_tg_mdaa_params *mdaa_params, | ||
| 142 | u16 timeout, nfc_digital_cmd_complete_t cb, | ||
| 143 | void *arg); | ||
| 144 | |||
| 145 | int (*switch_rf)(struct nfc_digital_dev *ddev, bool on); | ||
| 146 | void (*abort_cmd)(struct nfc_digital_dev *ddev); | ||
| 147 | }; | ||
| 148 | |||
| 149 | #define NFC_DIGITAL_POLL_MODE_COUNT_MAX 6 /* 106A, 212F, and 424F in & tg */ | ||
| 150 | |||
| 151 | typedef int (*digital_poll_t)(struct nfc_digital_dev *ddev, u8 rf_tech); | ||
| 152 | |||
| 153 | struct digital_poll_tech { | ||
| 154 | u8 rf_tech; | ||
| 155 | digital_poll_t poll_func; | ||
| 156 | }; | ||
| 157 | |||
| 158 | /** | ||
| 159 | * Driver capabilities - bit mask made of the following values | ||
| 160 | * | ||
| 161 | * @NFC_DIGITAL_DRV_CAPS_IN_CRC: The driver handles CRC calculation in initiator | ||
| 162 | * mode. | ||
| 163 | * @NFC_DIGITAL_DRV_CAPS_TG_CRC: The driver handles CRC calculation in target | ||
| 164 | * mode. | ||
| 165 | */ | ||
| 166 | #define NFC_DIGITAL_DRV_CAPS_IN_CRC 0x0001 | ||
| 167 | #define NFC_DIGITAL_DRV_CAPS_TG_CRC 0x0002 | ||
| 168 | |||
| 169 | struct nfc_digital_dev { | ||
| 170 | struct nfc_dev *nfc_dev; | ||
| 171 | struct nfc_digital_ops *ops; | ||
| 172 | |||
| 173 | u32 protocols; | ||
| 174 | |||
| 175 | int tx_headroom; | ||
| 176 | int tx_tailroom; | ||
| 177 | |||
| 178 | u32 driver_capabilities; | ||
| 179 | void *driver_data; | ||
| 180 | |||
| 181 | struct digital_poll_tech poll_techs[NFC_DIGITAL_POLL_MODE_COUNT_MAX]; | ||
| 182 | u8 poll_tech_count; | ||
| 183 | u8 poll_tech_index; | ||
| 184 | struct mutex poll_lock; | ||
| 185 | |||
| 186 | struct work_struct cmd_work; | ||
| 187 | struct work_struct cmd_complete_work; | ||
| 188 | struct list_head cmd_queue; | ||
| 189 | struct mutex cmd_lock; | ||
| 190 | |||
| 191 | struct work_struct poll_work; | ||
| 192 | |||
| 193 | u8 curr_protocol; | ||
| 194 | u8 curr_rf_tech; | ||
| 195 | u8 curr_nfc_dep_pni; | ||
| 196 | |||
| 197 | int (*skb_check_crc)(struct sk_buff *skb); | ||
| 198 | void (*skb_add_crc)(struct sk_buff *skb); | ||
| 199 | }; | ||
| 200 | |||
| 201 | struct nfc_digital_dev *nfc_digital_allocate_device(struct nfc_digital_ops *ops, | ||
| 202 | __u32 supported_protocols, | ||
| 203 | __u32 driver_capabilities, | ||
| 204 | int tx_headroom, | ||
| 205 | int tx_tailroom); | ||
| 206 | void nfc_digital_free_device(struct nfc_digital_dev *ndev); | ||
| 207 | int nfc_digital_register_device(struct nfc_digital_dev *ndev); | ||
| 208 | void nfc_digital_unregister_device(struct nfc_digital_dev *ndev); | ||
| 209 | |||
| 210 | static inline void nfc_digital_set_parent_dev(struct nfc_digital_dev *ndev, | ||
| 211 | struct device *dev) | ||
| 212 | { | ||
| 213 | nfc_set_parent_dev(ndev->nfc_dev, dev); | ||
| 214 | } | ||
| 215 | |||
| 216 | static inline void nfc_digital_set_drvdata(struct nfc_digital_dev *dev, | ||
| 217 | void *data) | ||
| 218 | { | ||
| 219 | dev->driver_data = data; | ||
| 220 | } | ||
| 221 | |||
| 222 | static inline void *nfc_digital_get_drvdata(struct nfc_digital_dev *dev) | ||
| 223 | { | ||
| 224 | return dev->driver_data; | ||
| 225 | } | ||
| 226 | |||
| 227 | #endif /* __NFC_DIGITAL_H */ | ||
diff --git a/include/net/nfc/hci.h b/include/net/nfc/hci.h index b64b7bce4b94..2eca2960ca9c 100644 --- a/include/net/nfc/hci.h +++ b/include/net/nfc/hci.h | |||
| @@ -24,12 +24,6 @@ | |||
| 24 | 24 | ||
| 25 | #include <net/nfc/nfc.h> | 25 | #include <net/nfc/nfc.h> |
| 26 | 26 | ||
| 27 | struct nfc_phy_ops { | ||
| 28 | int (*write)(void *dev_id, struct sk_buff *skb); | ||
| 29 | int (*enable)(void *dev_id); | ||
| 30 | void (*disable)(void *dev_id); | ||
| 31 | }; | ||
| 32 | |||
| 33 | struct nfc_hci_dev; | 27 | struct nfc_hci_dev; |
| 34 | 28 | ||
| 35 | struct nfc_hci_ops { | 29 | struct nfc_hci_ops { |
diff --git a/include/net/nfc/nci.h b/include/net/nfc/nci.h index 88785e5c6b2c..e5aa5acafea0 100644 --- a/include/net/nfc/nci.h +++ b/include/net/nfc/nci.h | |||
| @@ -166,6 +166,10 @@ | |||
| 166 | #define NCI_GID_NFCEE_MGMT 0x2 | 166 | #define NCI_GID_NFCEE_MGMT 0x2 |
| 167 | #define NCI_GID_PROPRIETARY 0xf | 167 | #define NCI_GID_PROPRIETARY 0xf |
| 168 | 168 | ||
| 169 | /* ----- NCI over SPI head/crc(tail) room needed for outgoing frames ----- */ | ||
| 170 | #define NCI_SPI_HDR_LEN 4 | ||
| 171 | #define NCI_SPI_CRC_LEN 2 | ||
| 172 | |||
| 169 | /* ---- NCI Packet structures ---- */ | 173 | /* ---- NCI Packet structures ---- */ |
| 170 | #define NCI_CTRL_HDR_SIZE 3 | 174 | #define NCI_CTRL_HDR_SIZE 3 |
| 171 | #define NCI_DATA_HDR_SIZE 3 | 175 | #define NCI_DATA_HDR_SIZE 3 |
diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h index 99fc1f3a392a..6126f1f992b4 100644 --- a/include/net/nfc/nci_core.h +++ b/include/net/nfc/nci_core.h | |||
| @@ -207,19 +207,9 @@ int nci_to_errno(__u8 code); | |||
| 207 | #define NCI_SPI_CRC_ENABLED 0x01 | 207 | #define NCI_SPI_CRC_ENABLED 0x01 |
| 208 | 208 | ||
| 209 | /* ----- NCI SPI structures ----- */ | 209 | /* ----- NCI SPI structures ----- */ |
| 210 | struct nci_spi_dev; | 210 | struct nci_spi { |
| 211 | 211 | struct nci_dev *ndev; | |
| 212 | struct nci_spi_ops { | ||
| 213 | int (*open)(struct nci_spi_dev *ndev); | ||
| 214 | int (*close)(struct nci_spi_dev *ndev); | ||
| 215 | void (*assert_int)(struct nci_spi_dev *ndev); | ||
| 216 | void (*deassert_int)(struct nci_spi_dev *ndev); | ||
| 217 | }; | ||
| 218 | |||
| 219 | struct nci_spi_dev { | ||
| 220 | struct nci_dev *nci_dev; | ||
| 221 | struct spi_device *spi; | 212 | struct spi_device *spi; |
| 222 | struct nci_spi_ops *ops; | ||
| 223 | 213 | ||
| 224 | unsigned int xfer_udelay; /* microseconds delay between | 214 | unsigned int xfer_udelay; /* microseconds delay between |
| 225 | transactions */ | 215 | transactions */ |
| @@ -227,31 +217,15 @@ struct nci_spi_dev { | |||
| 227 | 217 | ||
| 228 | struct completion req_completion; | 218 | struct completion req_completion; |
| 229 | u8 req_result; | 219 | u8 req_result; |
| 230 | |||
| 231 | void *driver_data; | ||
| 232 | }; | 220 | }; |
| 233 | 221 | ||
| 234 | /* ----- NCI SPI Devices ----- */ | 222 | /* ----- NCI SPI ----- */ |
| 235 | struct nci_spi_dev *nci_spi_allocate_device(struct spi_device *spi, | 223 | struct nci_spi *nci_spi_allocate_spi(struct spi_device *spi, |
| 236 | struct nci_spi_ops *ops, | 224 | u8 acknowledge_mode, unsigned int delay, |
| 237 | u32 supported_protocols, | 225 | struct nci_dev *ndev); |
| 238 | u32 supported_se, | 226 | int nci_spi_send(struct nci_spi *nspi, |
| 239 | u8 acknowledge_mode, | 227 | struct completion *write_handshake_completion, |
| 240 | unsigned int delay); | 228 | struct sk_buff *skb); |
| 241 | void nci_spi_free_device(struct nci_spi_dev *ndev); | 229 | struct sk_buff *nci_spi_read(struct nci_spi *nspi); |
| 242 | int nci_spi_register_device(struct nci_spi_dev *ndev); | ||
| 243 | void nci_spi_unregister_device(struct nci_spi_dev *ndev); | ||
| 244 | int nci_spi_recv_frame(struct nci_spi_dev *ndev); | ||
| 245 | |||
| 246 | static inline void nci_spi_set_drvdata(struct nci_spi_dev *ndev, | ||
| 247 | void *data) | ||
| 248 | { | ||
| 249 | ndev->driver_data = data; | ||
| 250 | } | ||
| 251 | |||
| 252 | static inline void *nci_spi_get_drvdata(struct nci_spi_dev *ndev) | ||
| 253 | { | ||
| 254 | return ndev->driver_data; | ||
| 255 | } | ||
| 256 | 230 | ||
| 257 | #endif /* __NCI_CORE_H */ | 231 | #endif /* __NCI_CORE_H */ |
diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h index f68ee68e4e3e..82fc4e43fc6e 100644 --- a/include/net/nfc/nfc.h +++ b/include/net/nfc/nfc.h | |||
| @@ -28,9 +28,14 @@ | |||
| 28 | #include <linux/device.h> | 28 | #include <linux/device.h> |
| 29 | #include <linux/skbuff.h> | 29 | #include <linux/skbuff.h> |
| 30 | 30 | ||
| 31 | #define nfc_dev_info(dev, fmt, arg...) dev_info((dev), "NFC: " fmt "\n", ## arg) | 31 | #define nfc_info(dev, fmt, ...) dev_info((dev), "NFC: " fmt, ##__VA_ARGS__) |
| 32 | #define nfc_dev_err(dev, fmt, arg...) dev_err((dev), "NFC: " fmt "\n", ## arg) | 32 | #define nfc_err(dev, fmt, ...) dev_err((dev), "NFC: " fmt, ##__VA_ARGS__) |
| 33 | #define nfc_dev_dbg(dev, fmt, arg...) dev_dbg((dev), fmt "\n", ## arg) | 33 | |
| 34 | struct nfc_phy_ops { | ||
| 35 | int (*write)(void *dev_id, struct sk_buff *skb); | ||
| 36 | int (*enable)(void *dev_id); | ||
| 37 | void (*disable)(void *dev_id); | ||
| 38 | }; | ||
| 34 | 39 | ||
| 35 | struct nfc_dev; | 40 | struct nfc_dev; |
| 36 | 41 | ||
| @@ -48,6 +53,8 @@ struct nfc_dev; | |||
| 48 | typedef void (*data_exchange_cb_t)(void *context, struct sk_buff *skb, | 53 | typedef void (*data_exchange_cb_t)(void *context, struct sk_buff *skb, |
| 49 | int err); | 54 | int err); |
| 50 | 55 | ||
| 56 | typedef void (*se_io_cb_t)(void *context, u8 *apdu, size_t apdu_len, int err); | ||
| 57 | |||
| 51 | struct nfc_target; | 58 | struct nfc_target; |
| 52 | 59 | ||
| 53 | struct nfc_ops { | 60 | struct nfc_ops { |
| @@ -74,12 +81,23 @@ struct nfc_ops { | |||
| 74 | int (*discover_se)(struct nfc_dev *dev); | 81 | int (*discover_se)(struct nfc_dev *dev); |
| 75 | int (*enable_se)(struct nfc_dev *dev, u32 se_idx); | 82 | int (*enable_se)(struct nfc_dev *dev, u32 se_idx); |
| 76 | int (*disable_se)(struct nfc_dev *dev, u32 se_idx); | 83 | int (*disable_se)(struct nfc_dev *dev, u32 se_idx); |
| 84 | int (*se_io) (struct nfc_dev *dev, u32 se_idx, | ||
| 85 | u8 *apdu, size_t apdu_length, | ||
| 86 | se_io_cb_t cb, void *cb_context); | ||
| 77 | }; | 87 | }; |
| 78 | 88 | ||
| 79 | #define NFC_TARGET_IDX_ANY -1 | 89 | #define NFC_TARGET_IDX_ANY -1 |
| 80 | #define NFC_MAX_GT_LEN 48 | 90 | #define NFC_MAX_GT_LEN 48 |
| 81 | #define NFC_ATR_RES_GT_OFFSET 15 | 91 | #define NFC_ATR_RES_GT_OFFSET 15 |
| 82 | 92 | ||
| 93 | /** | ||
| 94 | * struct nfc_target - NFC target descriptiom | ||
| 95 | * | ||
| 96 | * @sens_res: 2 bytes describing the target SENS_RES response, if the target | ||
| 97 | * is a type A one. The %sens_res most significant byte must be byte 2 | ||
| 98 | * as described by the NFC Forum digital specification (i.e. the platform | ||
| 99 | * configuration one) while %sens_res least significant byte is byte 1. | ||
| 100 | */ | ||
| 83 | struct nfc_target { | 101 | struct nfc_target { |
| 84 | u32 idx; | 102 | u32 idx; |
| 85 | u32 supported_protocols; | 103 | u32 supported_protocols; |
| @@ -243,5 +261,6 @@ void nfc_driver_failure(struct nfc_dev *dev, int err); | |||
| 243 | 261 | ||
| 244 | int nfc_add_se(struct nfc_dev *dev, u32 se_idx, u16 type); | 262 | int nfc_add_se(struct nfc_dev *dev, u32 se_idx, u16 type); |
| 245 | int nfc_remove_se(struct nfc_dev *dev, u32 se_idx); | 263 | int nfc_remove_se(struct nfc_dev *dev, u32 se_idx); |
| 264 | struct nfc_se *nfc_find_se(struct nfc_dev *dev, u32 se_idx); | ||
| 246 | 265 | ||
| 247 | #endif /* __NET_NFC_H */ | 266 | #endif /* __NET_NFC_H */ |
diff --git a/include/uapi/linux/nfc.h b/include/uapi/linux/nfc.h index 29bed72a4ac4..6ad6cc03ccd3 100644 --- a/include/uapi/linux/nfc.h +++ b/include/uapi/linux/nfc.h | |||
| @@ -85,6 +85,7 @@ | |||
| 85 | * a specific SE notifies us about the end of a transaction. The parameter | 85 | * a specific SE notifies us about the end of a transaction. The parameter |
| 86 | * for this event is the application ID (AID). | 86 | * for this event is the application ID (AID). |
| 87 | * @NFC_CMD_GET_SE: Dump all discovered secure elements from an NFC controller. | 87 | * @NFC_CMD_GET_SE: Dump all discovered secure elements from an NFC controller. |
| 88 | * @NFC_CMD_SE_IO: Send/Receive APDUs to/from the selected secure element. | ||
| 88 | */ | 89 | */ |
| 89 | enum nfc_commands { | 90 | enum nfc_commands { |
| 90 | NFC_CMD_UNSPEC, | 91 | NFC_CMD_UNSPEC, |
| @@ -114,6 +115,7 @@ enum nfc_commands { | |||
| 114 | NFC_EVENT_SE_CONNECTIVITY, | 115 | NFC_EVENT_SE_CONNECTIVITY, |
| 115 | NFC_EVENT_SE_TRANSACTION, | 116 | NFC_EVENT_SE_TRANSACTION, |
| 116 | NFC_CMD_GET_SE, | 117 | NFC_CMD_GET_SE, |
| 118 | NFC_CMD_SE_IO, | ||
| 117 | /* private: internal use only */ | 119 | /* private: internal use only */ |
| 118 | __NFC_CMD_AFTER_LAST | 120 | __NFC_CMD_AFTER_LAST |
| 119 | }; | 121 | }; |
| @@ -147,6 +149,7 @@ enum nfc_commands { | |||
| 147 | * @NFC_ATTR_SE_INDEX: Secure element index | 149 | * @NFC_ATTR_SE_INDEX: Secure element index |
| 148 | * @NFC_ATTR_SE_TYPE: Secure element type (UICC or EMBEDDED) | 150 | * @NFC_ATTR_SE_TYPE: Secure element type (UICC or EMBEDDED) |
| 149 | * @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 | ||
| 150 | */ | 153 | */ |
| 151 | enum nfc_attrs { | 154 | enum nfc_attrs { |
| 152 | NFC_ATTR_UNSPEC, | 155 | NFC_ATTR_UNSPEC, |
| @@ -174,6 +177,7 @@ enum nfc_attrs { | |||
| 174 | NFC_ATTR_SE_TYPE, | 177 | NFC_ATTR_SE_TYPE, |
| 175 | NFC_ATTR_SE_AID, | 178 | NFC_ATTR_SE_AID, |
| 176 | NFC_ATTR_FIRMWARE_DOWNLOAD_STATUS, | 179 | NFC_ATTR_FIRMWARE_DOWNLOAD_STATUS, |
| 180 | NFC_ATTR_SE_APDU, | ||
| 177 | /* private: internal use only */ | 181 | /* private: internal use only */ |
| 178 | __NFC_ATTR_AFTER_LAST | 182 | __NFC_ATTR_AFTER_LAST |
| 179 | }; | 183 | }; |
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index 17f33a62f6db..60ca52819247 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c | |||
| @@ -15,8 +15,9 @@ | |||
| 15 | #include <net/bluetooth/bluetooth.h> | 15 | #include <net/bluetooth/bluetooth.h> |
| 16 | #include <net/bluetooth/hci_core.h> | 16 | #include <net/bluetooth/hci_core.h> |
| 17 | #include <net/bluetooth/l2cap.h> | 17 | #include <net/bluetooth/l2cap.h> |
| 18 | #include <net/bluetooth/a2mp.h> | 18 | |
| 19 | #include <net/bluetooth/amp.h> | 19 | #include "a2mp.h" |
| 20 | #include "amp.h" | ||
| 20 | 21 | ||
| 21 | /* Global AMP Manager list */ | 22 | /* Global AMP Manager list */ |
| 22 | LIST_HEAD(amp_mgr_list); | 23 | LIST_HEAD(amp_mgr_list); |
| @@ -75,33 +76,26 @@ u8 __next_ident(struct amp_mgr *mgr) | |||
| 75 | return mgr->ident; | 76 | return mgr->ident; |
| 76 | } | 77 | } |
| 77 | 78 | ||
| 78 | static inline void __a2mp_cl_bredr(struct a2mp_cl *cl) | ||
| 79 | { | ||
| 80 | cl->id = 0; | ||
| 81 | cl->type = 0; | ||
| 82 | cl->status = 1; | ||
| 83 | } | ||
| 84 | |||
| 85 | /* hci_dev_list shall be locked */ | 79 | /* hci_dev_list shall be locked */ |
| 86 | static void __a2mp_add_cl(struct amp_mgr *mgr, struct a2mp_cl *cl, u8 num_ctrl) | 80 | static void __a2mp_add_cl(struct amp_mgr *mgr, struct a2mp_cl *cl) |
| 87 | { | 81 | { |
| 88 | int i = 0; | ||
| 89 | struct hci_dev *hdev; | 82 | struct hci_dev *hdev; |
| 83 | int i = 1; | ||
| 90 | 84 | ||
| 91 | __a2mp_cl_bredr(cl); | 85 | cl[0].id = AMP_ID_BREDR; |
| 86 | cl[0].type = AMP_TYPE_BREDR; | ||
| 87 | cl[0].status = AMP_STATUS_BLUETOOTH_ONLY; | ||
| 92 | 88 | ||
| 93 | list_for_each_entry(hdev, &hci_dev_list, list) { | 89 | list_for_each_entry(hdev, &hci_dev_list, list) { |
| 94 | /* Iterate through AMP controllers */ | 90 | if (hdev->dev_type == HCI_AMP) { |
| 95 | if (hdev->id == HCI_BREDR_ID) | 91 | cl[i].id = hdev->id; |
| 96 | continue; | 92 | cl[i].type = hdev->amp_type; |
| 97 | 93 | if (test_bit(HCI_UP, &hdev->flags)) | |
| 98 | /* Starting from second entry */ | 94 | cl[i].status = hdev->amp_status; |
| 99 | if (++i >= num_ctrl) | 95 | else |
| 100 | return; | 96 | cl[i].status = AMP_STATUS_POWERED_DOWN; |
| 101 | 97 | i++; | |
| 102 | cl[i].id = hdev->id; | 98 | } |
| 103 | cl[i].type = hdev->amp_type; | ||
| 104 | cl[i].status = hdev->amp_status; | ||
| 105 | } | 99 | } |
| 106 | } | 100 | } |
| 107 | 101 | ||
| @@ -129,6 +123,7 @@ static int a2mp_discover_req(struct amp_mgr *mgr, struct sk_buff *skb, | |||
| 129 | struct a2mp_discov_rsp *rsp; | 123 | struct a2mp_discov_rsp *rsp; |
| 130 | u16 ext_feat; | 124 | u16 ext_feat; |
| 131 | u8 num_ctrl; | 125 | u8 num_ctrl; |
| 126 | struct hci_dev *hdev; | ||
| 132 | 127 | ||
| 133 | if (len < sizeof(*req)) | 128 | if (len < sizeof(*req)) |
| 134 | return -EINVAL; | 129 | return -EINVAL; |
| @@ -152,7 +147,14 @@ static int a2mp_discover_req(struct amp_mgr *mgr, struct sk_buff *skb, | |||
| 152 | 147 | ||
| 153 | read_lock(&hci_dev_list_lock); | 148 | read_lock(&hci_dev_list_lock); |
| 154 | 149 | ||
| 155 | num_ctrl = __hci_num_ctrl(); | 150 | /* at minimum the BR/EDR needs to be listed */ |
| 151 | num_ctrl = 1; | ||
| 152 | |||
| 153 | list_for_each_entry(hdev, &hci_dev_list, list) { | ||
| 154 | if (hdev->dev_type == HCI_AMP) | ||
| 155 | num_ctrl++; | ||
| 156 | } | ||
| 157 | |||
| 156 | len = num_ctrl * sizeof(struct a2mp_cl) + sizeof(*rsp); | 158 | len = num_ctrl * sizeof(struct a2mp_cl) + sizeof(*rsp); |
| 157 | rsp = kmalloc(len, GFP_ATOMIC); | 159 | rsp = kmalloc(len, GFP_ATOMIC); |
| 158 | if (!rsp) { | 160 | if (!rsp) { |
| @@ -163,7 +165,7 @@ static int a2mp_discover_req(struct amp_mgr *mgr, struct sk_buff *skb, | |||
| 163 | rsp->mtu = __constant_cpu_to_le16(L2CAP_A2MP_DEFAULT_MTU); | 165 | rsp->mtu = __constant_cpu_to_le16(L2CAP_A2MP_DEFAULT_MTU); |
| 164 | rsp->ext_feat = 0; | 166 | rsp->ext_feat = 0; |
| 165 | 167 | ||
| 166 | __a2mp_add_cl(mgr, rsp->cl, num_ctrl); | 168 | __a2mp_add_cl(mgr, rsp->cl); |
| 167 | 169 | ||
| 168 | read_unlock(&hci_dev_list_lock); | 170 | read_unlock(&hci_dev_list_lock); |
| 169 | 171 | ||
| @@ -208,7 +210,7 @@ static int a2mp_discover_rsp(struct amp_mgr *mgr, struct sk_buff *skb, | |||
| 208 | BT_DBG("Remote AMP id %d type %d status %d", cl->id, cl->type, | 210 | BT_DBG("Remote AMP id %d type %d status %d", cl->id, cl->type, |
| 209 | cl->status); | 211 | cl->status); |
| 210 | 212 | ||
| 211 | if (cl->id != HCI_BREDR_ID && cl->type == HCI_AMP) { | 213 | if (cl->id != AMP_ID_BREDR && cl->type != AMP_TYPE_BREDR) { |
| 212 | struct a2mp_info_req req; | 214 | struct a2mp_info_req req; |
| 213 | 215 | ||
| 214 | found = true; | 216 | found = true; |
| @@ -344,7 +346,7 @@ static int a2mp_getampassoc_req(struct amp_mgr *mgr, struct sk_buff *skb, | |||
| 344 | tmp = amp_mgr_lookup_by_state(READ_LOC_AMP_ASSOC); | 346 | tmp = amp_mgr_lookup_by_state(READ_LOC_AMP_ASSOC); |
| 345 | 347 | ||
| 346 | hdev = hci_dev_get(req->id); | 348 | hdev = hci_dev_get(req->id); |
| 347 | if (!hdev || hdev->amp_type == HCI_BREDR || tmp) { | 349 | if (!hdev || hdev->amp_type == AMP_TYPE_BREDR || tmp) { |
| 348 | struct a2mp_amp_assoc_rsp rsp; | 350 | struct a2mp_amp_assoc_rsp rsp; |
| 349 | rsp.id = req->id; | 351 | rsp.id = req->id; |
| 350 | 352 | ||
| @@ -451,7 +453,7 @@ static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb, | |||
| 451 | rsp.remote_id = req->local_id; | 453 | rsp.remote_id = req->local_id; |
| 452 | 454 | ||
| 453 | hdev = hci_dev_get(req->remote_id); | 455 | hdev = hci_dev_get(req->remote_id); |
| 454 | if (!hdev || hdev->amp_type != HCI_AMP) { | 456 | if (!hdev || hdev->amp_type == AMP_TYPE_BREDR) { |
| 455 | rsp.status = A2MP_STATUS_INVALID_CTRL_ID; | 457 | rsp.status = A2MP_STATUS_INVALID_CTRL_ID; |
| 456 | goto send_rsp; | 458 | goto send_rsp; |
| 457 | } | 459 | } |
| @@ -535,7 +537,8 @@ static int a2mp_discphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb, | |||
| 535 | goto send_rsp; | 537 | goto send_rsp; |
| 536 | } | 538 | } |
| 537 | 539 | ||
| 538 | hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK, mgr->l2cap_conn->dst); | 540 | hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK, |
| 541 | &mgr->l2cap_conn->hcon->dst); | ||
| 539 | if (!hcon) { | 542 | if (!hcon) { |
| 540 | BT_ERR("No phys link exist"); | 543 | BT_ERR("No phys link exist"); |
| 541 | rsp.status = A2MP_STATUS_NO_PHYSICAL_LINK_EXISTS; | 544 | rsp.status = A2MP_STATUS_NO_PHYSICAL_LINK_EXISTS; |
| @@ -871,7 +874,7 @@ void a2mp_send_getinfo_rsp(struct hci_dev *hdev) | |||
| 871 | rsp.id = hdev->id; | 874 | rsp.id = hdev->id; |
| 872 | rsp.status = A2MP_STATUS_INVALID_CTRL_ID; | 875 | rsp.status = A2MP_STATUS_INVALID_CTRL_ID; |
| 873 | 876 | ||
| 874 | if (hdev->amp_type != HCI_BREDR) { | 877 | if (hdev->amp_type != AMP_TYPE_BREDR) { |
| 875 | rsp.status = 0; | 878 | rsp.status = 0; |
| 876 | rsp.total_bw = cpu_to_le32(hdev->amp_total_bw); | 879 | rsp.total_bw = cpu_to_le32(hdev->amp_total_bw); |
| 877 | rsp.max_bw = cpu_to_le32(hdev->amp_max_bw); | 880 | rsp.max_bw = cpu_to_le32(hdev->amp_max_bw); |
diff --git a/include/net/bluetooth/a2mp.h b/net/bluetooth/a2mp.h index 487b54c1308f..487b54c1308f 100644 --- a/include/net/bluetooth/a2mp.h +++ b/net/bluetooth/a2mp.h | |||
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index e6e1278dca89..1f1a1118f489 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c | |||
| @@ -30,7 +30,7 @@ | |||
| 30 | #include <net/bluetooth/bluetooth.h> | 30 | #include <net/bluetooth/bluetooth.h> |
| 31 | #include <linux/proc_fs.h> | 31 | #include <linux/proc_fs.h> |
| 32 | 32 | ||
| 33 | #define VERSION "2.16" | 33 | #define VERSION "2.17" |
| 34 | 34 | ||
| 35 | /* Bluetooth sockets */ | 35 | /* Bluetooth sockets */ |
| 36 | #define BT_MAX_PROTO 8 | 36 | #define BT_MAX_PROTO 8 |
| @@ -221,12 +221,12 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
| 221 | if (flags & (MSG_OOB)) | 221 | if (flags & (MSG_OOB)) |
| 222 | return -EOPNOTSUPP; | 222 | return -EOPNOTSUPP; |
| 223 | 223 | ||
| 224 | msg->msg_namelen = 0; | ||
| 225 | |||
| 226 | skb = skb_recv_datagram(sk, flags, noblock, &err); | 224 | skb = skb_recv_datagram(sk, flags, noblock, &err); |
| 227 | if (!skb) { | 225 | if (!skb) { |
| 228 | if (sk->sk_shutdown & RCV_SHUTDOWN) | 226 | if (sk->sk_shutdown & RCV_SHUTDOWN) { |
| 227 | msg->msg_namelen = 0; | ||
| 229 | return 0; | 228 | return 0; |
| 229 | } | ||
| 230 | return err; | 230 | return err; |
| 231 | } | 231 | } |
| 232 | 232 | ||
| @@ -238,9 +238,16 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
| 238 | 238 | ||
| 239 | skb_reset_transport_header(skb); | 239 | skb_reset_transport_header(skb); |
| 240 | err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); | 240 | err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); |
| 241 | if (err == 0) | 241 | if (err == 0) { |
| 242 | sock_recv_ts_and_drops(msg, sk, skb); | 242 | sock_recv_ts_and_drops(msg, sk, skb); |
| 243 | 243 | ||
| 244 | if (bt_sk(sk)->skb_msg_name) | ||
| 245 | bt_sk(sk)->skb_msg_name(skb, msg->msg_name, | ||
| 246 | &msg->msg_namelen); | ||
| 247 | else | ||
| 248 | msg->msg_namelen = 0; | ||
| 249 | } | ||
| 250 | |||
| 244 | skb_free_datagram(sk, skb); | 251 | skb_free_datagram(sk, skb); |
| 245 | 252 | ||
| 246 | return err ? : copied; | 253 | return err ? : copied; |
| @@ -604,7 +611,7 @@ static int bt_seq_show(struct seq_file *seq, void *v) | |||
| 604 | struct bt_sock_list *l = s->l; | 611 | struct bt_sock_list *l = s->l; |
| 605 | 612 | ||
| 606 | if (v == SEQ_START_TOKEN) { | 613 | if (v == SEQ_START_TOKEN) { |
| 607 | seq_puts(seq ,"sk RefCnt Rmem Wmem User Inode Src Dst Parent"); | 614 | seq_puts(seq ,"sk RefCnt Rmem Wmem User Inode Parent"); |
| 608 | 615 | ||
| 609 | if (l->custom_seq_show) { | 616 | if (l->custom_seq_show) { |
| 610 | seq_putc(seq, ' '); | 617 | seq_putc(seq, ' '); |
| @@ -617,15 +624,13 @@ static int bt_seq_show(struct seq_file *seq, void *v) | |||
| 617 | struct bt_sock *bt = bt_sk(sk); | 624 | struct bt_sock *bt = bt_sk(sk); |
| 618 | 625 | ||
| 619 | seq_printf(seq, | 626 | seq_printf(seq, |
| 620 | "%pK %-6d %-6u %-6u %-6u %-6lu %pMR %pMR %-6lu", | 627 | "%pK %-6d %-6u %-6u %-6u %-6lu %-6lu", |
| 621 | sk, | 628 | sk, |
| 622 | atomic_read(&sk->sk_refcnt), | 629 | atomic_read(&sk->sk_refcnt), |
| 623 | sk_rmem_alloc_get(sk), | 630 | sk_rmem_alloc_get(sk), |
| 624 | sk_wmem_alloc_get(sk), | 631 | sk_wmem_alloc_get(sk), |
| 625 | from_kuid(seq_user_ns(seq), sock_i_uid(sk)), | 632 | from_kuid(seq_user_ns(seq), sock_i_uid(sk)), |
| 626 | sock_i_ino(sk), | 633 | sock_i_ino(sk), |
| 627 | &bt->src, | ||
| 628 | &bt->dst, | ||
| 629 | bt->parent? sock_i_ino(bt->parent): 0LU); | 634 | bt->parent? sock_i_ino(bt->parent): 0LU); |
| 630 | 635 | ||
| 631 | if (l->custom_seq_show) { | 636 | if (l->custom_seq_show) { |
diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c index d459ed43c779..bb39509b3f06 100644 --- a/net/bluetooth/amp.c +++ b/net/bluetooth/amp.c | |||
| @@ -14,10 +14,11 @@ | |||
| 14 | #include <net/bluetooth/bluetooth.h> | 14 | #include <net/bluetooth/bluetooth.h> |
| 15 | #include <net/bluetooth/hci.h> | 15 | #include <net/bluetooth/hci.h> |
| 16 | #include <net/bluetooth/hci_core.h> | 16 | #include <net/bluetooth/hci_core.h> |
| 17 | #include <net/bluetooth/a2mp.h> | ||
| 18 | #include <net/bluetooth/amp.h> | ||
| 19 | #include <crypto/hash.h> | 17 | #include <crypto/hash.h> |
| 20 | 18 | ||
| 19 | #include "a2mp.h" | ||
| 20 | #include "amp.h" | ||
| 21 | |||
| 21 | /* Remote AMP Controllers interface */ | 22 | /* Remote AMP Controllers interface */ |
| 22 | void amp_ctrl_get(struct amp_ctrl *ctrl) | 23 | void amp_ctrl_get(struct amp_ctrl *ctrl) |
| 23 | { | 24 | { |
| @@ -110,7 +111,7 @@ static u8 __next_handle(struct amp_mgr *mgr) | |||
| 110 | struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr, | 111 | struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr, |
| 111 | u8 remote_id, bool out) | 112 | u8 remote_id, bool out) |
| 112 | { | 113 | { |
| 113 | bdaddr_t *dst = mgr->l2cap_conn->dst; | 114 | bdaddr_t *dst = &mgr->l2cap_conn->hcon->dst; |
| 114 | struct hci_conn *hcon; | 115 | struct hci_conn *hcon; |
| 115 | 116 | ||
| 116 | hcon = hci_conn_add(hdev, AMP_LINK, dst); | 117 | hcon = hci_conn_add(hdev, AMP_LINK, dst); |
| @@ -409,7 +410,8 @@ void amp_create_logical_link(struct l2cap_chan *chan) | |||
| 409 | struct hci_cp_create_accept_logical_link cp; | 410 | struct hci_cp_create_accept_logical_link cp; |
| 410 | struct hci_dev *hdev; | 411 | struct hci_dev *hdev; |
| 411 | 412 | ||
| 412 | BT_DBG("chan %p hs_hcon %p dst %pMR", chan, hs_hcon, chan->conn->dst); | 413 | BT_DBG("chan %p hs_hcon %p dst %pMR", chan, hs_hcon, |
| 414 | &chan->conn->hcon->dst); | ||
| 413 | 415 | ||
| 414 | if (!hs_hcon) | 416 | if (!hs_hcon) |
| 415 | return; | 417 | return; |
diff --git a/include/net/bluetooth/amp.h b/net/bluetooth/amp.h index 7ea3db77ba89..7ea3db77ba89 100644 --- a/include/net/bluetooth/amp.h +++ b/net/bluetooth/amp.h | |||
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index e430b1abcd2f..a841d3e776c5 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <asm/unaligned.h> | 32 | #include <asm/unaligned.h> |
| 33 | 33 | ||
| 34 | #include <net/bluetooth/bluetooth.h> | 34 | #include <net/bluetooth/bluetooth.h> |
| 35 | #include <net/bluetooth/l2cap.h> | ||
| 35 | #include <net/bluetooth/hci_core.h> | 36 | #include <net/bluetooth/hci_core.h> |
| 36 | 37 | ||
| 37 | #include "bnep.h" | 38 | #include "bnep.h" |
| @@ -510,20 +511,13 @@ static int bnep_session(void *arg) | |||
| 510 | 511 | ||
| 511 | static struct device *bnep_get_device(struct bnep_session *session) | 512 | static struct device *bnep_get_device(struct bnep_session *session) |
| 512 | { | 513 | { |
| 513 | bdaddr_t *src = &bt_sk(session->sock->sk)->src; | ||
| 514 | bdaddr_t *dst = &bt_sk(session->sock->sk)->dst; | ||
| 515 | struct hci_dev *hdev; | ||
| 516 | struct hci_conn *conn; | 514 | struct hci_conn *conn; |
| 517 | 515 | ||
| 518 | hdev = hci_get_route(dst, src); | 516 | conn = l2cap_pi(session->sock->sk)->chan->conn->hcon; |
| 519 | if (!hdev) | 517 | if (!conn) |
| 520 | return NULL; | 518 | return NULL; |
| 521 | 519 | ||
| 522 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst); | 520 | return &conn->dev; |
| 523 | |||
| 524 | hci_dev_put(hdev); | ||
| 525 | |||
| 526 | return conn ? &conn->dev : NULL; | ||
| 527 | } | 521 | } |
| 528 | 522 | ||
| 529 | static struct device_type bnep_type = { | 523 | static struct device_type bnep_type = { |
| @@ -539,8 +533,8 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock) | |||
| 539 | 533 | ||
| 540 | BT_DBG(""); | 534 | BT_DBG(""); |
| 541 | 535 | ||
| 542 | baswap((void *) dst, &bt_sk(sock->sk)->dst); | 536 | baswap((void *) dst, &l2cap_pi(sock->sk)->chan->dst); |
| 543 | baswap((void *) src, &bt_sk(sock->sk)->src); | 537 | baswap((void *) src, &l2cap_pi(sock->sk)->chan->src); |
| 544 | 538 | ||
| 545 | /* session struct allocated as private part of net_device */ | 539 | /* session struct allocated as private part of net_device */ |
| 546 | dev = alloc_netdev(sizeof(struct bnep_session), | 540 | dev = alloc_netdev(sizeof(struct bnep_session), |
diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c index e0a6ebf2baa6..67fe5e84e68f 100644 --- a/net/bluetooth/cmtp/core.c +++ b/net/bluetooth/cmtp/core.c | |||
| @@ -340,20 +340,20 @@ int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock) | |||
| 340 | 340 | ||
| 341 | down_write(&cmtp_session_sem); | 341 | down_write(&cmtp_session_sem); |
| 342 | 342 | ||
| 343 | s = __cmtp_get_session(&bt_sk(sock->sk)->dst); | 343 | s = __cmtp_get_session(&l2cap_pi(sock->sk)->chan->dst); |
| 344 | if (s && s->state == BT_CONNECTED) { | 344 | if (s && s->state == BT_CONNECTED) { |
| 345 | err = -EEXIST; | 345 | err = -EEXIST; |
| 346 | goto failed; | 346 | goto failed; |
| 347 | } | 347 | } |
| 348 | 348 | ||
| 349 | bacpy(&session->bdaddr, &bt_sk(sock->sk)->dst); | 349 | bacpy(&session->bdaddr, &l2cap_pi(sock->sk)->chan->dst); |
| 350 | 350 | ||
| 351 | session->mtu = min_t(uint, l2cap_pi(sock->sk)->chan->omtu, | 351 | session->mtu = min_t(uint, l2cap_pi(sock->sk)->chan->omtu, |
| 352 | l2cap_pi(sock->sk)->chan->imtu); | 352 | l2cap_pi(sock->sk)->chan->imtu); |
| 353 | 353 | ||
| 354 | BT_DBG("mtu %d", session->mtu); | 354 | BT_DBG("mtu %d", session->mtu); |
| 355 | 355 | ||
| 356 | sprintf(session->name, "%pMR", &bt_sk(sock->sk)->dst); | 356 | sprintf(session->name, "%pMR", &session->bdaddr); |
| 357 | 357 | ||
| 358 | session->sock = sock; | 358 | session->sock = sock; |
| 359 | session->state = BT_CONFIG; | 359 | session->state = BT_CONFIG; |
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 514148b7a66b..ff04b051792d 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
| @@ -28,8 +28,9 @@ | |||
| 28 | 28 | ||
| 29 | #include <net/bluetooth/bluetooth.h> | 29 | #include <net/bluetooth/bluetooth.h> |
| 30 | #include <net/bluetooth/hci_core.h> | 30 | #include <net/bluetooth/hci_core.h> |
| 31 | #include <net/bluetooth/a2mp.h> | 31 | |
| 32 | #include <net/bluetooth/smp.h> | 32 | #include "smp.h" |
| 33 | #include "a2mp.h" | ||
| 33 | 34 | ||
| 34 | struct sco_param { | 35 | struct sco_param { |
| 35 | u16 pkt_type; | 36 | u16 pkt_type; |
| @@ -49,30 +50,6 @@ static const struct sco_param sco_param_wideband[] = { | |||
| 49 | { EDR_ESCO_MASK | ESCO_EV3, 0x0008 }, /* T1 */ | 50 | { EDR_ESCO_MASK | ESCO_EV3, 0x0008 }, /* T1 */ |
| 50 | }; | 51 | }; |
| 51 | 52 | ||
| 52 | static void hci_le_create_connection(struct hci_conn *conn) | ||
| 53 | { | ||
| 54 | struct hci_dev *hdev = conn->hdev; | ||
| 55 | struct hci_cp_le_create_conn cp; | ||
| 56 | |||
| 57 | conn->state = BT_CONNECT; | ||
| 58 | conn->out = true; | ||
| 59 | conn->link_mode |= HCI_LM_MASTER; | ||
| 60 | conn->sec_level = BT_SECURITY_LOW; | ||
| 61 | |||
| 62 | memset(&cp, 0, sizeof(cp)); | ||
| 63 | cp.scan_interval = __constant_cpu_to_le16(0x0060); | ||
| 64 | cp.scan_window = __constant_cpu_to_le16(0x0030); | ||
| 65 | bacpy(&cp.peer_addr, &conn->dst); | ||
| 66 | cp.peer_addr_type = conn->dst_type; | ||
| 67 | cp.conn_interval_min = __constant_cpu_to_le16(0x0028); | ||
| 68 | cp.conn_interval_max = __constant_cpu_to_le16(0x0038); | ||
| 69 | cp.supervision_timeout = __constant_cpu_to_le16(0x002a); | ||
| 70 | cp.min_ce_len = __constant_cpu_to_le16(0x0000); | ||
| 71 | cp.max_ce_len = __constant_cpu_to_le16(0x0000); | ||
| 72 | |||
| 73 | hci_send_cmd(hdev, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp); | ||
| 74 | } | ||
| 75 | |||
| 76 | static void hci_le_create_connection_cancel(struct hci_conn *conn) | 53 | static void hci_le_create_connection_cancel(struct hci_conn *conn) |
| 77 | { | 54 | { |
| 78 | hci_send_cmd(conn->hdev, HCI_OP_LE_CREATE_CONN_CANCEL, 0, NULL); | 55 | hci_send_cmd(conn->hdev, HCI_OP_LE_CREATE_CONN_CANCEL, 0, NULL); |
| @@ -404,6 +381,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) | |||
| 404 | return NULL; | 381 | return NULL; |
| 405 | 382 | ||
| 406 | bacpy(&conn->dst, dst); | 383 | bacpy(&conn->dst, dst); |
| 384 | bacpy(&conn->src, &hdev->bdaddr); | ||
| 407 | conn->hdev = hdev; | 385 | conn->hdev = hdev; |
| 408 | conn->type = type; | 386 | conn->type = type; |
| 409 | conn->mode = HCI_CM_ACTIVE; | 387 | conn->mode = HCI_CM_ACTIVE; |
| @@ -546,34 +524,128 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src) | |||
| 546 | } | 524 | } |
| 547 | EXPORT_SYMBOL(hci_get_route); | 525 | EXPORT_SYMBOL(hci_get_route); |
| 548 | 526 | ||
| 527 | static void create_le_conn_complete(struct hci_dev *hdev, u8 status) | ||
| 528 | { | ||
| 529 | struct hci_conn *conn; | ||
| 530 | |||
| 531 | if (status == 0) | ||
| 532 | return; | ||
| 533 | |||
| 534 | BT_ERR("HCI request failed to create LE connection: status 0x%2.2x", | ||
| 535 | status); | ||
| 536 | |||
| 537 | hci_dev_lock(hdev); | ||
| 538 | |||
| 539 | conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); | ||
| 540 | if (!conn) | ||
| 541 | goto done; | ||
| 542 | |||
| 543 | conn->state = BT_CLOSED; | ||
| 544 | |||
| 545 | mgmt_connect_failed(hdev, &conn->dst, conn->type, conn->dst_type, | ||
| 546 | status); | ||
| 547 | |||
| 548 | hci_proto_connect_cfm(conn, status); | ||
| 549 | |||
| 550 | hci_conn_del(conn); | ||
| 551 | |||
| 552 | done: | ||
| 553 | hci_dev_unlock(hdev); | ||
| 554 | } | ||
| 555 | |||
| 556 | static int hci_create_le_conn(struct hci_conn *conn) | ||
| 557 | { | ||
| 558 | struct hci_dev *hdev = conn->hdev; | ||
| 559 | struct hci_cp_le_create_conn cp; | ||
| 560 | struct hci_request req; | ||
| 561 | int err; | ||
| 562 | |||
| 563 | hci_req_init(&req, hdev); | ||
| 564 | |||
| 565 | memset(&cp, 0, sizeof(cp)); | ||
| 566 | cp.scan_interval = cpu_to_le16(hdev->le_scan_interval); | ||
| 567 | cp.scan_window = cpu_to_le16(hdev->le_scan_window); | ||
| 568 | bacpy(&cp.peer_addr, &conn->dst); | ||
| 569 | cp.peer_addr_type = conn->dst_type; | ||
| 570 | cp.own_address_type = conn->src_type; | ||
| 571 | cp.conn_interval_min = __constant_cpu_to_le16(0x0028); | ||
| 572 | cp.conn_interval_max = __constant_cpu_to_le16(0x0038); | ||
| 573 | cp.supervision_timeout = __constant_cpu_to_le16(0x002a); | ||
| 574 | cp.min_ce_len = __constant_cpu_to_le16(0x0000); | ||
| 575 | cp.max_ce_len = __constant_cpu_to_le16(0x0000); | ||
| 576 | hci_req_add(&req, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp); | ||
| 577 | |||
| 578 | err = hci_req_run(&req, create_le_conn_complete); | ||
| 579 | if (err) { | ||
| 580 | hci_conn_del(conn); | ||
| 581 | return err; | ||
| 582 | } | ||
| 583 | |||
| 584 | return 0; | ||
| 585 | } | ||
| 586 | |||
| 549 | static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, | 587 | static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, |
| 550 | u8 dst_type, u8 sec_level, u8 auth_type) | 588 | u8 dst_type, u8 sec_level, u8 auth_type) |
| 551 | { | 589 | { |
| 552 | struct hci_conn *le; | 590 | struct hci_conn *conn; |
| 591 | int err; | ||
| 553 | 592 | ||
| 554 | if (test_bit(HCI_LE_PERIPHERAL, &hdev->flags)) | 593 | if (test_bit(HCI_ADVERTISING, &hdev->flags)) |
| 555 | return ERR_PTR(-ENOTSUPP); | 594 | return ERR_PTR(-ENOTSUPP); |
| 556 | 595 | ||
| 557 | le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst); | 596 | /* Some devices send ATT messages as soon as the physical link is |
| 558 | if (!le) { | 597 | * established. To be able to handle these ATT messages, the user- |
| 559 | le = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); | 598 | * space first establishes the connection and then starts the pairing |
| 560 | if (le) | 599 | * process. |
| 561 | return ERR_PTR(-EBUSY); | 600 | * |
| 601 | * So if a hci_conn object already exists for the following connection | ||
| 602 | * attempt, we simply update pending_sec_level and auth_type fields | ||
| 603 | * and return the object found. | ||
| 604 | */ | ||
| 605 | conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst); | ||
| 606 | if (conn) { | ||
| 607 | conn->pending_sec_level = sec_level; | ||
| 608 | conn->auth_type = auth_type; | ||
| 609 | goto done; | ||
| 610 | } | ||
| 562 | 611 | ||
| 563 | le = hci_conn_add(hdev, LE_LINK, dst); | 612 | /* Since the controller supports only one LE connection attempt at a |
| 564 | if (!le) | 613 | * time, we return -EBUSY if there is any connection attempt running. |
| 565 | return ERR_PTR(-ENOMEM); | 614 | */ |
| 615 | conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); | ||
| 616 | if (conn) | ||
| 617 | return ERR_PTR(-EBUSY); | ||
| 618 | |||
| 619 | conn = hci_conn_add(hdev, LE_LINK, dst); | ||
| 620 | if (!conn) | ||
| 621 | return ERR_PTR(-ENOMEM); | ||
| 566 | 622 | ||
| 567 | le->dst_type = bdaddr_to_le(dst_type); | 623 | if (dst_type == BDADDR_LE_PUBLIC) |
| 568 | hci_le_create_connection(le); | 624 | conn->dst_type = ADDR_LE_DEV_PUBLIC; |
| 625 | else | ||
| 626 | conn->dst_type = ADDR_LE_DEV_RANDOM; | ||
| 627 | |||
| 628 | if (bacmp(&conn->src, BDADDR_ANY)) { | ||
| 629 | conn->src_type = ADDR_LE_DEV_PUBLIC; | ||
| 630 | } else { | ||
| 631 | bacpy(&conn->src, &hdev->static_addr); | ||
| 632 | conn->src_type = ADDR_LE_DEV_RANDOM; | ||
| 569 | } | 633 | } |
| 570 | 634 | ||
| 571 | le->pending_sec_level = sec_level; | 635 | conn->state = BT_CONNECT; |
| 572 | le->auth_type = auth_type; | 636 | conn->out = true; |
| 637 | conn->link_mode |= HCI_LM_MASTER; | ||
| 638 | conn->sec_level = BT_SECURITY_LOW; | ||
| 639 | conn->pending_sec_level = sec_level; | ||
| 640 | conn->auth_type = auth_type; | ||
| 573 | 641 | ||
| 574 | hci_conn_hold(le); | 642 | err = hci_create_le_conn(conn); |
| 643 | if (err) | ||
| 644 | return ERR_PTR(err); | ||
| 575 | 645 | ||
| 576 | return le; | 646 | done: |
| 647 | hci_conn_hold(conn); | ||
| 648 | return conn; | ||
| 577 | } | 649 | } |
| 578 | 650 | ||
| 579 | static struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, | 651 | static struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 82dbdc6a7e9e..7add9c96e32c 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
| @@ -307,11 +307,23 @@ static void amp_init(struct hci_request *req) | |||
| 307 | /* Read Local Version */ | 307 | /* Read Local Version */ |
| 308 | hci_req_add(req, HCI_OP_READ_LOCAL_VERSION, 0, NULL); | 308 | hci_req_add(req, HCI_OP_READ_LOCAL_VERSION, 0, NULL); |
| 309 | 309 | ||
| 310 | /* Read Local Supported Commands */ | ||
| 311 | hci_req_add(req, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL); | ||
| 312 | |||
| 313 | /* Read Local Supported Features */ | ||
| 314 | hci_req_add(req, HCI_OP_READ_LOCAL_FEATURES, 0, NULL); | ||
| 315 | |||
| 310 | /* Read Local AMP Info */ | 316 | /* Read Local AMP Info */ |
| 311 | hci_req_add(req, HCI_OP_READ_LOCAL_AMP_INFO, 0, NULL); | 317 | hci_req_add(req, HCI_OP_READ_LOCAL_AMP_INFO, 0, NULL); |
| 312 | 318 | ||
| 313 | /* Read Data Blk size */ | 319 | /* Read Data Blk size */ |
| 314 | hci_req_add(req, HCI_OP_READ_DATA_BLOCK_SIZE, 0, NULL); | 320 | hci_req_add(req, HCI_OP_READ_DATA_BLOCK_SIZE, 0, NULL); |
| 321 | |||
| 322 | /* Read Flow Control Mode */ | ||
| 323 | hci_req_add(req, HCI_OP_READ_FLOW_CONTROL_MODE, 0, NULL); | ||
| 324 | |||
| 325 | /* Read Location Data */ | ||
| 326 | hci_req_add(req, HCI_OP_READ_LOCATION_DATA, 0, NULL); | ||
| 315 | } | 327 | } |
| 316 | 328 | ||
| 317 | static void hci_init1_req(struct hci_request *req, unsigned long opt) | 329 | static void hci_init1_req(struct hci_request *req, unsigned long opt) |
| @@ -341,6 +353,8 @@ static void hci_init1_req(struct hci_request *req, unsigned long opt) | |||
| 341 | 353 | ||
| 342 | static void bredr_setup(struct hci_request *req) | 354 | static void bredr_setup(struct hci_request *req) |
| 343 | { | 355 | { |
| 356 | struct hci_dev *hdev = req->hdev; | ||
| 357 | |||
| 344 | __le16 param; | 358 | __le16 param; |
| 345 | __u8 flt_type; | 359 | __u8 flt_type; |
| 346 | 360 | ||
| @@ -356,6 +370,12 @@ static void bredr_setup(struct hci_request *req) | |||
| 356 | /* Read Voice Setting */ | 370 | /* Read Voice Setting */ |
| 357 | hci_req_add(req, HCI_OP_READ_VOICE_SETTING, 0, NULL); | 371 | hci_req_add(req, HCI_OP_READ_VOICE_SETTING, 0, NULL); |
| 358 | 372 | ||
| 373 | /* Read Number of Supported IAC */ | ||
| 374 | hci_req_add(req, HCI_OP_READ_NUM_SUPPORTED_IAC, 0, NULL); | ||
| 375 | |||
| 376 | /* Read Current IAC LAP */ | ||
| 377 | hci_req_add(req, HCI_OP_READ_CURRENT_IAC_LAP, 0, NULL); | ||
| 378 | |||
| 359 | /* Clear Event Filters */ | 379 | /* Clear Event Filters */ |
| 360 | flt_type = HCI_FLT_CLEAR_ALL; | 380 | flt_type = HCI_FLT_CLEAR_ALL; |
| 361 | hci_req_add(req, HCI_OP_SET_EVENT_FLT, 1, &flt_type); | 381 | hci_req_add(req, HCI_OP_SET_EVENT_FLT, 1, &flt_type); |
| @@ -364,8 +384,10 @@ static void bredr_setup(struct hci_request *req) | |||
| 364 | param = __constant_cpu_to_le16(0x7d00); | 384 | param = __constant_cpu_to_le16(0x7d00); |
| 365 | hci_req_add(req, HCI_OP_WRITE_CA_TIMEOUT, 2, ¶m); | 385 | hci_req_add(req, HCI_OP_WRITE_CA_TIMEOUT, 2, ¶m); |
| 366 | 386 | ||
| 367 | /* Read page scan parameters */ | 387 | /* AVM Berlin (31), aka "BlueFRITZ!", reports version 1.2, |
| 368 | if (req->hdev->hci_ver > BLUETOOTH_VER_1_1) { | 388 | * but it does not support page scan related HCI commands. |
| 389 | */ | ||
| 390 | if (hdev->manufacturer != 31 && hdev->hci_ver > BLUETOOTH_VER_1_1) { | ||
| 369 | hci_req_add(req, HCI_OP_READ_PAGE_SCAN_ACTIVITY, 0, NULL); | 391 | hci_req_add(req, HCI_OP_READ_PAGE_SCAN_ACTIVITY, 0, NULL); |
| 370 | hci_req_add(req, HCI_OP_READ_PAGE_SCAN_TYPE, 0, NULL); | 392 | hci_req_add(req, HCI_OP_READ_PAGE_SCAN_TYPE, 0, NULL); |
| 371 | } | 393 | } |
| @@ -1036,6 +1058,11 @@ int hci_inquiry(void __user *arg) | |||
| 1036 | goto done; | 1058 | goto done; |
| 1037 | } | 1059 | } |
| 1038 | 1060 | ||
| 1061 | if (hdev->dev_type != HCI_BREDR) { | ||
| 1062 | err = -EOPNOTSUPP; | ||
| 1063 | goto done; | ||
| 1064 | } | ||
| 1065 | |||
| 1039 | if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) { | 1066 | if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) { |
| 1040 | err = -EOPNOTSUPP; | 1067 | err = -EOPNOTSUPP; |
| 1041 | goto done; | 1068 | goto done; |
| @@ -1105,7 +1132,7 @@ static u8 create_ad(struct hci_dev *hdev, u8 *ptr) | |||
| 1105 | u8 ad_len = 0, flags = 0; | 1132 | u8 ad_len = 0, flags = 0; |
| 1106 | size_t name_len; | 1133 | size_t name_len; |
| 1107 | 1134 | ||
| 1108 | if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags)) | 1135 | if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) |
| 1109 | flags |= LE_AD_GENERAL; | 1136 | flags |= LE_AD_GENERAL; |
| 1110 | 1137 | ||
| 1111 | if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) { | 1138 | if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) { |
| @@ -1196,13 +1223,29 @@ static int hci_dev_do_open(struct hci_dev *hdev) | |||
| 1196 | goto done; | 1223 | goto done; |
| 1197 | } | 1224 | } |
| 1198 | 1225 | ||
| 1199 | /* Check for rfkill but allow the HCI setup stage to proceed | 1226 | if (!test_bit(HCI_SETUP, &hdev->dev_flags)) { |
| 1200 | * (which in itself doesn't cause any RF activity). | 1227 | /* Check for rfkill but allow the HCI setup stage to |
| 1201 | */ | 1228 | * proceed (which in itself doesn't cause any RF activity). |
| 1202 | if (test_bit(HCI_RFKILLED, &hdev->dev_flags) && | 1229 | */ |
| 1203 | !test_bit(HCI_SETUP, &hdev->dev_flags)) { | 1230 | if (test_bit(HCI_RFKILLED, &hdev->dev_flags)) { |
| 1204 | ret = -ERFKILL; | 1231 | ret = -ERFKILL; |
| 1205 | goto done; | 1232 | goto done; |
| 1233 | } | ||
| 1234 | |||
| 1235 | /* Check for valid public address or a configured static | ||
| 1236 | * random adddress, but let the HCI setup proceed to | ||
| 1237 | * be able to determine if there is a public address | ||
| 1238 | * or not. | ||
| 1239 | * | ||
| 1240 | * This check is only valid for BR/EDR controllers | ||
| 1241 | * since AMP controllers do not have an address. | ||
| 1242 | */ | ||
| 1243 | if (hdev->dev_type == HCI_BREDR && | ||
| 1244 | !bacmp(&hdev->bdaddr, BDADDR_ANY) && | ||
| 1245 | !bacmp(&hdev->static_addr, BDADDR_ANY)) { | ||
| 1246 | ret = -EADDRNOTAVAIL; | ||
| 1247 | goto done; | ||
| 1248 | } | ||
| 1206 | } | 1249 | } |
| 1207 | 1250 | ||
| 1208 | if (test_bit(HCI_UP, &hdev->flags)) { | 1251 | if (test_bit(HCI_UP, &hdev->flags)) { |
| @@ -1238,7 +1281,7 @@ static int hci_dev_do_open(struct hci_dev *hdev) | |||
| 1238 | hci_notify(hdev, HCI_DEV_UP); | 1281 | hci_notify(hdev, HCI_DEV_UP); |
| 1239 | if (!test_bit(HCI_SETUP, &hdev->dev_flags) && | 1282 | if (!test_bit(HCI_SETUP, &hdev->dev_flags) && |
| 1240 | !test_bit(HCI_USER_CHANNEL, &hdev->dev_flags) && | 1283 | !test_bit(HCI_USER_CHANNEL, &hdev->dev_flags) && |
| 1241 | mgmt_valid_hdev(hdev)) { | 1284 | hdev->dev_type == HCI_BREDR) { |
| 1242 | hci_dev_lock(hdev); | 1285 | hci_dev_lock(hdev); |
| 1243 | mgmt_powered(hdev, 1); | 1286 | mgmt_powered(hdev, 1); |
| 1244 | hci_dev_unlock(hdev); | 1287 | hci_dev_unlock(hdev); |
| @@ -1288,6 +1331,10 @@ int hci_dev_open(__u16 dev) | |||
| 1288 | if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) | 1331 | if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) |
| 1289 | cancel_delayed_work(&hdev->power_off); | 1332 | cancel_delayed_work(&hdev->power_off); |
| 1290 | 1333 | ||
| 1334 | /* After this call it is guaranteed that the setup procedure | ||
| 1335 | * has finished. This means that error conditions like RFKILL | ||
| 1336 | * or no valid public or static random address apply. | ||
| 1337 | */ | ||
| 1291 | flush_workqueue(hdev->req_workqueue); | 1338 | flush_workqueue(hdev->req_workqueue); |
| 1292 | 1339 | ||
| 1293 | err = hci_dev_do_open(hdev); | 1340 | err = hci_dev_do_open(hdev); |
| @@ -1341,6 +1388,7 @@ static int hci_dev_do_close(struct hci_dev *hdev) | |||
| 1341 | skb_queue_purge(&hdev->cmd_q); | 1388 | skb_queue_purge(&hdev->cmd_q); |
| 1342 | atomic_set(&hdev->cmd_cnt, 1); | 1389 | atomic_set(&hdev->cmd_cnt, 1); |
| 1343 | if (!test_bit(HCI_RAW, &hdev->flags) && | 1390 | if (!test_bit(HCI_RAW, &hdev->flags) && |
| 1391 | !test_bit(HCI_AUTO_OFF, &hdev->dev_flags) && | ||
| 1344 | test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks)) { | 1392 | test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks)) { |
| 1345 | set_bit(HCI_INIT, &hdev->flags); | 1393 | set_bit(HCI_INIT, &hdev->flags); |
| 1346 | __hci_req_sync(hdev, hci_reset_req, 0, HCI_CMD_TIMEOUT); | 1394 | __hci_req_sync(hdev, hci_reset_req, 0, HCI_CMD_TIMEOUT); |
| @@ -1373,15 +1421,16 @@ static int hci_dev_do_close(struct hci_dev *hdev) | |||
| 1373 | hdev->flags = 0; | 1421 | hdev->flags = 0; |
| 1374 | hdev->dev_flags &= ~HCI_PERSISTENT_MASK; | 1422 | hdev->dev_flags &= ~HCI_PERSISTENT_MASK; |
| 1375 | 1423 | ||
| 1376 | if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags) && | 1424 | if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) { |
| 1377 | mgmt_valid_hdev(hdev)) { | 1425 | if (hdev->dev_type == HCI_BREDR) { |
| 1378 | hci_dev_lock(hdev); | 1426 | hci_dev_lock(hdev); |
| 1379 | mgmt_powered(hdev, 0); | 1427 | mgmt_powered(hdev, 0); |
| 1380 | hci_dev_unlock(hdev); | 1428 | hci_dev_unlock(hdev); |
| 1429 | } | ||
| 1381 | } | 1430 | } |
| 1382 | 1431 | ||
| 1383 | /* Controller radio is available but is currently powered down */ | 1432 | /* Controller radio is available but is currently powered down */ |
| 1384 | hdev->amp_status = 0; | 1433 | hdev->amp_status = AMP_STATUS_POWERED_DOWN; |
| 1385 | 1434 | ||
| 1386 | memset(hdev->eir, 0, sizeof(hdev->eir)); | 1435 | memset(hdev->eir, 0, sizeof(hdev->eir)); |
| 1387 | memset(hdev->dev_class, 0, sizeof(hdev->dev_class)); | 1436 | memset(hdev->dev_class, 0, sizeof(hdev->dev_class)); |
| @@ -1500,6 +1549,11 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg) | |||
| 1500 | goto done; | 1549 | goto done; |
| 1501 | } | 1550 | } |
| 1502 | 1551 | ||
| 1552 | if (hdev->dev_type != HCI_BREDR) { | ||
| 1553 | err = -EOPNOTSUPP; | ||
| 1554 | goto done; | ||
| 1555 | } | ||
| 1556 | |||
| 1503 | if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) { | 1557 | if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) { |
| 1504 | err = -EOPNOTSUPP; | 1558 | err = -EOPNOTSUPP; |
| 1505 | goto done; | 1559 | goto done; |
| @@ -1703,7 +1757,14 @@ static void hci_power_on(struct work_struct *work) | |||
| 1703 | return; | 1757 | return; |
| 1704 | } | 1758 | } |
| 1705 | 1759 | ||
| 1706 | if (test_bit(HCI_RFKILLED, &hdev->dev_flags)) { | 1760 | /* During the HCI setup phase, a few error conditions are |
| 1761 | * ignored and they need to be checked now. If they are still | ||
| 1762 | * valid, it is important to turn the device back off. | ||
| 1763 | */ | ||
| 1764 | if (test_bit(HCI_RFKILLED, &hdev->dev_flags) || | ||
| 1765 | (hdev->dev_type == HCI_BREDR && | ||
| 1766 | !bacmp(&hdev->bdaddr, BDADDR_ANY) && | ||
| 1767 | !bacmp(&hdev->static_addr, BDADDR_ANY))) { | ||
| 1707 | clear_bit(HCI_AUTO_OFF, &hdev->dev_flags); | 1768 | clear_bit(HCI_AUTO_OFF, &hdev->dev_flags); |
| 1708 | hci_dev_do_close(hdev); | 1769 | hci_dev_do_close(hdev); |
| 1709 | } else if (test_bit(HCI_AUTO_OFF, &hdev->dev_flags)) { | 1770 | } else if (test_bit(HCI_AUTO_OFF, &hdev->dev_flags)) { |
| @@ -2216,13 +2277,17 @@ struct hci_dev *hci_alloc_dev(void) | |||
| 2216 | hdev->pkt_type = (HCI_DM1 | HCI_DH1 | HCI_HV1); | 2277 | hdev->pkt_type = (HCI_DM1 | HCI_DH1 | HCI_HV1); |
| 2217 | hdev->esco_type = (ESCO_HV1); | 2278 | hdev->esco_type = (ESCO_HV1); |
| 2218 | hdev->link_mode = (HCI_LM_ACCEPT); | 2279 | hdev->link_mode = (HCI_LM_ACCEPT); |
| 2219 | hdev->io_capability = 0x03; /* No Input No Output */ | 2280 | hdev->num_iac = 0x01; /* One IAC support is mandatory */ |
| 2281 | hdev->io_capability = 0x03; /* No Input No Output */ | ||
| 2220 | hdev->inq_tx_power = HCI_TX_POWER_INVALID; | 2282 | hdev->inq_tx_power = HCI_TX_POWER_INVALID; |
| 2221 | hdev->adv_tx_power = HCI_TX_POWER_INVALID; | 2283 | hdev->adv_tx_power = HCI_TX_POWER_INVALID; |
| 2222 | 2284 | ||
| 2223 | hdev->sniff_max_interval = 800; | 2285 | hdev->sniff_max_interval = 800; |
| 2224 | hdev->sniff_min_interval = 80; | 2286 | hdev->sniff_min_interval = 80; |
| 2225 | 2287 | ||
| 2288 | hdev->le_scan_interval = 0x0060; | ||
| 2289 | hdev->le_scan_window = 0x0030; | ||
| 2290 | |||
| 2226 | mutex_init(&hdev->lock); | 2291 | mutex_init(&hdev->lock); |
| 2227 | mutex_init(&hdev->req_lock); | 2292 | mutex_init(&hdev->req_lock); |
| 2228 | 2293 | ||
| @@ -2329,9 +2394,9 @@ int hci_register_dev(struct hci_dev *hdev) | |||
| 2329 | set_bit(HCI_RFKILLED, &hdev->dev_flags); | 2394 | set_bit(HCI_RFKILLED, &hdev->dev_flags); |
| 2330 | 2395 | ||
| 2331 | set_bit(HCI_SETUP, &hdev->dev_flags); | 2396 | set_bit(HCI_SETUP, &hdev->dev_flags); |
| 2397 | set_bit(HCI_AUTO_OFF, &hdev->dev_flags); | ||
| 2332 | 2398 | ||
| 2333 | if (hdev->dev_type != HCI_AMP) { | 2399 | if (hdev->dev_type == HCI_BREDR) { |
| 2334 | set_bit(HCI_AUTO_OFF, &hdev->dev_flags); | ||
| 2335 | /* Assume BR/EDR support until proven otherwise (such as | 2400 | /* Assume BR/EDR support until proven otherwise (such as |
| 2336 | * through reading supported features during init. | 2401 | * through reading supported features during init. |
| 2337 | */ | 2402 | */ |
| @@ -2435,9 +2500,8 @@ int hci_resume_dev(struct hci_dev *hdev) | |||
| 2435 | EXPORT_SYMBOL(hci_resume_dev); | 2500 | EXPORT_SYMBOL(hci_resume_dev); |
| 2436 | 2501 | ||
| 2437 | /* Receive frame from HCI drivers */ | 2502 | /* Receive frame from HCI drivers */ |
| 2438 | int hci_recv_frame(struct sk_buff *skb) | 2503 | int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb) |
| 2439 | { | 2504 | { |
| 2440 | struct hci_dev *hdev = (struct hci_dev *) skb->dev; | ||
| 2441 | if (!hdev || (!test_bit(HCI_UP, &hdev->flags) | 2505 | if (!hdev || (!test_bit(HCI_UP, &hdev->flags) |
| 2442 | && !test_bit(HCI_INIT, &hdev->flags))) { | 2506 | && !test_bit(HCI_INIT, &hdev->flags))) { |
| 2443 | kfree_skb(skb); | 2507 | kfree_skb(skb); |
| @@ -2496,7 +2560,6 @@ static int hci_reassembly(struct hci_dev *hdev, int type, void *data, | |||
| 2496 | scb->expect = hlen; | 2560 | scb->expect = hlen; |
| 2497 | scb->pkt_type = type; | 2561 | scb->pkt_type = type; |
| 2498 | 2562 | ||
| 2499 | skb->dev = (void *) hdev; | ||
| 2500 | hdev->reassembly[index] = skb; | 2563 | hdev->reassembly[index] = skb; |
| 2501 | } | 2564 | } |
| 2502 | 2565 | ||
| @@ -2556,7 +2619,7 @@ static int hci_reassembly(struct hci_dev *hdev, int type, void *data, | |||
| 2556 | /* Complete frame */ | 2619 | /* Complete frame */ |
| 2557 | 2620 | ||
| 2558 | bt_cb(skb)->pkt_type = type; | 2621 | bt_cb(skb)->pkt_type = type; |
| 2559 | hci_recv_frame(skb); | 2622 | hci_recv_frame(hdev, skb); |
| 2560 | 2623 | ||
| 2561 | hdev->reassembly[index] = NULL; | 2624 | hdev->reassembly[index] = NULL; |
| 2562 | return remain; | 2625 | return remain; |
| @@ -2647,15 +2710,8 @@ int hci_unregister_cb(struct hci_cb *cb) | |||
| 2647 | } | 2710 | } |
| 2648 | EXPORT_SYMBOL(hci_unregister_cb); | 2711 | EXPORT_SYMBOL(hci_unregister_cb); |
| 2649 | 2712 | ||
| 2650 | static int hci_send_frame(struct sk_buff *skb) | 2713 | static void hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb) |
| 2651 | { | 2714 | { |
| 2652 | struct hci_dev *hdev = (struct hci_dev *) skb->dev; | ||
| 2653 | |||
| 2654 | if (!hdev) { | ||
| 2655 | kfree_skb(skb); | ||
| 2656 | return -ENODEV; | ||
| 2657 | } | ||
| 2658 | |||
| 2659 | BT_DBG("%s type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len); | 2715 | BT_DBG("%s type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len); |
| 2660 | 2716 | ||
| 2661 | /* Time stamp */ | 2717 | /* Time stamp */ |
| @@ -2672,7 +2728,8 @@ static int hci_send_frame(struct sk_buff *skb) | |||
| 2672 | /* Get rid of skb owner, prior to sending to the driver. */ | 2728 | /* Get rid of skb owner, prior to sending to the driver. */ |
| 2673 | skb_orphan(skb); | 2729 | skb_orphan(skb); |
| 2674 | 2730 | ||
| 2675 | return hdev->send(skb); | 2731 | if (hdev->send(hdev, skb) < 0) |
| 2732 | BT_ERR("%s sending frame failed", hdev->name); | ||
| 2676 | } | 2733 | } |
| 2677 | 2734 | ||
| 2678 | void hci_req_init(struct hci_request *req, struct hci_dev *hdev) | 2735 | void hci_req_init(struct hci_request *req, struct hci_dev *hdev) |
| @@ -2735,7 +2792,6 @@ static struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode, | |||
| 2735 | BT_DBG("skb len %d", skb->len); | 2792 | BT_DBG("skb len %d", skb->len); |
| 2736 | 2793 | ||
| 2737 | bt_cb(skb)->pkt_type = HCI_COMMAND_PKT; | 2794 | bt_cb(skb)->pkt_type = HCI_COMMAND_PKT; |
| 2738 | skb->dev = (void *) hdev; | ||
| 2739 | 2795 | ||
| 2740 | return skb; | 2796 | return skb; |
| 2741 | } | 2797 | } |
| @@ -2879,7 +2935,6 @@ static void hci_queue_acl(struct hci_chan *chan, struct sk_buff_head *queue, | |||
| 2879 | do { | 2935 | do { |
| 2880 | skb = list; list = list->next; | 2936 | skb = list; list = list->next; |
| 2881 | 2937 | ||
| 2882 | skb->dev = (void *) hdev; | ||
| 2883 | bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT; | 2938 | bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT; |
| 2884 | hci_add_acl_hdr(skb, conn->handle, flags); | 2939 | hci_add_acl_hdr(skb, conn->handle, flags); |
| 2885 | 2940 | ||
| @@ -2898,8 +2953,6 @@ void hci_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags) | |||
| 2898 | 2953 | ||
| 2899 | BT_DBG("%s chan %p flags 0x%4.4x", hdev->name, chan, flags); | 2954 | BT_DBG("%s chan %p flags 0x%4.4x", hdev->name, chan, flags); |
| 2900 | 2955 | ||
| 2901 | skb->dev = (void *) hdev; | ||
| 2902 | |||
| 2903 | hci_queue_acl(chan, &chan->data_q, skb, flags); | 2956 | hci_queue_acl(chan, &chan->data_q, skb, flags); |
| 2904 | 2957 | ||
| 2905 | queue_work(hdev->workqueue, &hdev->tx_work); | 2958 | queue_work(hdev->workqueue, &hdev->tx_work); |
| @@ -2920,7 +2973,6 @@ void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb) | |||
| 2920 | skb_reset_transport_header(skb); | 2973 | skb_reset_transport_header(skb); |
| 2921 | memcpy(skb_transport_header(skb), &hdr, HCI_SCO_HDR_SIZE); | 2974 | memcpy(skb_transport_header(skb), &hdr, HCI_SCO_HDR_SIZE); |
| 2922 | 2975 | ||
| 2923 | skb->dev = (void *) hdev; | ||
| 2924 | bt_cb(skb)->pkt_type = HCI_SCODATA_PKT; | 2976 | bt_cb(skb)->pkt_type = HCI_SCODATA_PKT; |
| 2925 | 2977 | ||
| 2926 | skb_queue_tail(&conn->data_q, skb); | 2978 | skb_queue_tail(&conn->data_q, skb); |
| @@ -3185,7 +3237,7 @@ static void hci_sched_acl_pkt(struct hci_dev *hdev) | |||
| 3185 | hci_conn_enter_active_mode(chan->conn, | 3237 | hci_conn_enter_active_mode(chan->conn, |
| 3186 | bt_cb(skb)->force_active); | 3238 | bt_cb(skb)->force_active); |
| 3187 | 3239 | ||
| 3188 | hci_send_frame(skb); | 3240 | hci_send_frame(hdev, skb); |
| 3189 | hdev->acl_last_tx = jiffies; | 3241 | hdev->acl_last_tx = jiffies; |
| 3190 | 3242 | ||
| 3191 | hdev->acl_cnt--; | 3243 | hdev->acl_cnt--; |
| @@ -3237,7 +3289,7 @@ static void hci_sched_acl_blk(struct hci_dev *hdev) | |||
| 3237 | hci_conn_enter_active_mode(chan->conn, | 3289 | hci_conn_enter_active_mode(chan->conn, |
| 3238 | bt_cb(skb)->force_active); | 3290 | bt_cb(skb)->force_active); |
| 3239 | 3291 | ||
| 3240 | hci_send_frame(skb); | 3292 | hci_send_frame(hdev, skb); |
| 3241 | hdev->acl_last_tx = jiffies; | 3293 | hdev->acl_last_tx = jiffies; |
| 3242 | 3294 | ||
| 3243 | hdev->block_cnt -= blocks; | 3295 | hdev->block_cnt -= blocks; |
| @@ -3290,7 +3342,7 @@ static void hci_sched_sco(struct hci_dev *hdev) | |||
| 3290 | while (hdev->sco_cnt && (conn = hci_low_sent(hdev, SCO_LINK, "e))) { | 3342 | while (hdev->sco_cnt && (conn = hci_low_sent(hdev, SCO_LINK, "e))) { |
| 3291 | while (quote-- && (skb = skb_dequeue(&conn->data_q))) { | 3343 | while (quote-- && (skb = skb_dequeue(&conn->data_q))) { |
| 3292 | BT_DBG("skb %p len %d", skb, skb->len); | 3344 | BT_DBG("skb %p len %d", skb, skb->len); |
| 3293 | hci_send_frame(skb); | 3345 | hci_send_frame(hdev, skb); |
| 3294 | 3346 | ||
| 3295 | conn->sent++; | 3347 | conn->sent++; |
| 3296 | if (conn->sent == ~0) | 3348 | if (conn->sent == ~0) |
| @@ -3314,7 +3366,7 @@ static void hci_sched_esco(struct hci_dev *hdev) | |||
| 3314 | "e))) { | 3366 | "e))) { |
| 3315 | while (quote-- && (skb = skb_dequeue(&conn->data_q))) { | 3367 | while (quote-- && (skb = skb_dequeue(&conn->data_q))) { |
| 3316 | BT_DBG("skb %p len %d", skb, skb->len); | 3368 | BT_DBG("skb %p len %d", skb, skb->len); |
| 3317 | hci_send_frame(skb); | 3369 | hci_send_frame(hdev, skb); |
| 3318 | 3370 | ||
| 3319 | conn->sent++; | 3371 | conn->sent++; |
| 3320 | if (conn->sent == ~0) | 3372 | if (conn->sent == ~0) |
| @@ -3356,7 +3408,7 @@ static void hci_sched_le(struct hci_dev *hdev) | |||
| 3356 | 3408 | ||
| 3357 | skb = skb_dequeue(&chan->data_q); | 3409 | skb = skb_dequeue(&chan->data_q); |
| 3358 | 3410 | ||
| 3359 | hci_send_frame(skb); | 3411 | hci_send_frame(hdev, skb); |
| 3360 | hdev->le_last_tx = jiffies; | 3412 | hdev->le_last_tx = jiffies; |
| 3361 | 3413 | ||
| 3362 | cnt--; | 3414 | cnt--; |
| @@ -3392,7 +3444,7 @@ static void hci_tx_work(struct work_struct *work) | |||
| 3392 | 3444 | ||
| 3393 | /* Send next queued raw (unknown type) packet */ | 3445 | /* Send next queued raw (unknown type) packet */ |
| 3394 | while ((skb = skb_dequeue(&hdev->raw_q))) | 3446 | while ((skb = skb_dequeue(&hdev->raw_q))) |
| 3395 | hci_send_frame(skb); | 3447 | hci_send_frame(hdev, skb); |
| 3396 | } | 3448 | } |
| 3397 | 3449 | ||
| 3398 | /* ----- HCI RX task (incoming data processing) ----- */ | 3450 | /* ----- HCI RX task (incoming data processing) ----- */ |
| @@ -3638,7 +3690,7 @@ static void hci_cmd_work(struct work_struct *work) | |||
| 3638 | hdev->sent_cmd = skb_clone(skb, GFP_KERNEL); | 3690 | hdev->sent_cmd = skb_clone(skb, GFP_KERNEL); |
| 3639 | if (hdev->sent_cmd) { | 3691 | if (hdev->sent_cmd) { |
| 3640 | atomic_dec(&hdev->cmd_cnt); | 3692 | atomic_dec(&hdev->cmd_cnt); |
| 3641 | hci_send_frame(skb); | 3693 | hci_send_frame(hdev, skb); |
| 3642 | if (test_bit(HCI_RESET, &hdev->flags)) | 3694 | if (test_bit(HCI_RESET, &hdev->flags)) |
| 3643 | del_timer(&hdev->cmd_timer); | 3695 | del_timer(&hdev->cmd_timer); |
| 3644 | else | 3696 | else |
| @@ -3650,15 +3702,3 @@ static void hci_cmd_work(struct work_struct *work) | |||
| 3650 | } | 3702 | } |
| 3651 | } | 3703 | } |
| 3652 | } | 3704 | } |
| 3653 | |||
| 3654 | u8 bdaddr_to_le(u8 bdaddr_type) | ||
| 3655 | { | ||
| 3656 | switch (bdaddr_type) { | ||
| 3657 | case BDADDR_LE_PUBLIC: | ||
| 3658 | return ADDR_LE_DEV_PUBLIC; | ||
| 3659 | |||
| 3660 | default: | ||
| 3661 | /* Fallback to LE Random address type */ | ||
| 3662 | return ADDR_LE_DEV_RANDOM; | ||
| 3663 | } | ||
| 3664 | } | ||
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 4785ab0795f5..5391469ff1a5 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
| @@ -29,8 +29,9 @@ | |||
| 29 | #include <net/bluetooth/bluetooth.h> | 29 | #include <net/bluetooth/bluetooth.h> |
| 30 | #include <net/bluetooth/hci_core.h> | 30 | #include <net/bluetooth/hci_core.h> |
| 31 | #include <net/bluetooth/mgmt.h> | 31 | #include <net/bluetooth/mgmt.h> |
| 32 | #include <net/bluetooth/a2mp.h> | 32 | |
| 33 | #include <net/bluetooth/amp.h> | 33 | #include "a2mp.h" |
| 34 | #include "amp.h" | ||
| 34 | 35 | ||
| 35 | /* Handle HCI Event packets */ | 36 | /* Handle HCI Event packets */ |
| 36 | 37 | ||
| @@ -417,6 +418,21 @@ static void hci_cc_write_voice_setting(struct hci_dev *hdev, | |||
| 417 | hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); | 418 | hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); |
| 418 | } | 419 | } |
| 419 | 420 | ||
| 421 | static void hci_cc_read_num_supported_iac(struct hci_dev *hdev, | ||
| 422 | struct sk_buff *skb) | ||
| 423 | { | ||
| 424 | struct hci_rp_read_num_supported_iac *rp = (void *) skb->data; | ||
| 425 | |||
| 426 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | ||
| 427 | |||
| 428 | if (rp->status) | ||
| 429 | return; | ||
| 430 | |||
| 431 | hdev->num_iac = rp->num_iac; | ||
| 432 | |||
| 433 | BT_DBG("%s num iac %d", hdev->name, hdev->num_iac); | ||
| 434 | } | ||
| 435 | |||
| 420 | static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) | 436 | static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) |
| 421 | { | 437 | { |
| 422 | __u8 status = *((__u8 *) skb->data); | 438 | __u8 status = *((__u8 *) skb->data); |
| @@ -918,12 +934,12 @@ static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb) | |||
| 918 | 934 | ||
| 919 | if (!status) { | 935 | if (!status) { |
| 920 | if (*sent) | 936 | if (*sent) |
| 921 | set_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags); | 937 | set_bit(HCI_ADVERTISING, &hdev->dev_flags); |
| 922 | else | 938 | else |
| 923 | clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags); | 939 | clear_bit(HCI_ADVERTISING, &hdev->dev_flags); |
| 924 | } | 940 | } |
| 925 | 941 | ||
| 926 | if (!test_bit(HCI_INIT, &hdev->flags)) { | 942 | if (*sent && !test_bit(HCI_INIT, &hdev->flags)) { |
| 927 | struct hci_request req; | 943 | struct hci_request req; |
| 928 | 944 | ||
| 929 | hci_req_init(&req, hdev); | 945 | hci_req_init(&req, hdev); |
| @@ -1005,7 +1021,7 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev, | |||
| 1005 | } else { | 1021 | } else { |
| 1006 | hdev->features[1][0] &= ~LMP_HOST_LE; | 1022 | hdev->features[1][0] &= ~LMP_HOST_LE; |
| 1007 | clear_bit(HCI_LE_ENABLED, &hdev->dev_flags); | 1023 | clear_bit(HCI_LE_ENABLED, &hdev->dev_flags); |
| 1008 | clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags); | 1024 | clear_bit(HCI_ADVERTISING, &hdev->dev_flags); |
| 1009 | } | 1025 | } |
| 1010 | 1026 | ||
| 1011 | if (sent->simul) | 1027 | if (sent->simul) |
| @@ -1296,9 +1312,11 @@ static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) | |||
| 1296 | goto unlock; | 1312 | goto unlock; |
| 1297 | 1313 | ||
| 1298 | if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { | 1314 | if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { |
| 1299 | struct hci_cp_auth_requested cp; | 1315 | struct hci_cp_auth_requested auth_cp; |
| 1300 | cp.handle = __cpu_to_le16(conn->handle); | 1316 | |
| 1301 | hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); | 1317 | auth_cp.handle = __cpu_to_le16(conn->handle); |
| 1318 | hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, | ||
| 1319 | sizeof(auth_cp), &auth_cp); | ||
| 1302 | } | 1320 | } |
| 1303 | 1321 | ||
| 1304 | unlock: | 1322 | unlock: |
| @@ -1470,33 +1488,6 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) | |||
| 1470 | hci_dev_unlock(hdev); | 1488 | hci_dev_unlock(hdev); |
| 1471 | } | 1489 | } |
| 1472 | 1490 | ||
| 1473 | static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) | ||
| 1474 | { | ||
| 1475 | struct hci_conn *conn; | ||
| 1476 | |||
| 1477 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
| 1478 | |||
| 1479 | if (status) { | ||
| 1480 | hci_dev_lock(hdev); | ||
| 1481 | |||
| 1482 | conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); | ||
| 1483 | if (!conn) { | ||
| 1484 | hci_dev_unlock(hdev); | ||
| 1485 | return; | ||
| 1486 | } | ||
| 1487 | |||
| 1488 | BT_DBG("%s bdaddr %pMR conn %p", hdev->name, &conn->dst, conn); | ||
| 1489 | |||
| 1490 | conn->state = BT_CLOSED; | ||
| 1491 | mgmt_connect_failed(hdev, &conn->dst, conn->type, | ||
| 1492 | conn->dst_type, status); | ||
| 1493 | hci_proto_connect_cfm(conn, status); | ||
| 1494 | hci_conn_del(conn); | ||
| 1495 | |||
| 1496 | hci_dev_unlock(hdev); | ||
| 1497 | } | ||
| 1498 | } | ||
| 1499 | |||
| 1500 | static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status) | 1491 | static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status) |
| 1501 | { | 1492 | { |
| 1502 | struct hci_cp_create_phy_link *cp; | 1493 | struct hci_cp_create_phy_link *cp; |
| @@ -1826,10 +1817,25 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
| 1826 | } | 1817 | } |
| 1827 | 1818 | ||
| 1828 | if (ev->status == 0) { | 1819 | if (ev->status == 0) { |
| 1829 | if (conn->type == ACL_LINK && conn->flush_key) | 1820 | u8 type = conn->type; |
| 1821 | |||
| 1822 | if (type == ACL_LINK && conn->flush_key) | ||
| 1830 | hci_remove_link_key(hdev, &conn->dst); | 1823 | hci_remove_link_key(hdev, &conn->dst); |
| 1831 | hci_proto_disconn_cfm(conn, ev->reason); | 1824 | hci_proto_disconn_cfm(conn, ev->reason); |
| 1832 | hci_conn_del(conn); | 1825 | hci_conn_del(conn); |
| 1826 | |||
| 1827 | /* Re-enable advertising if necessary, since it might | ||
| 1828 | * have been disabled by the connection. From the | ||
| 1829 | * HCI_LE_Set_Advertise_Enable command description in | ||
| 1830 | * the core specification (v4.0): | ||
| 1831 | * "The Controller shall continue advertising until the Host | ||
| 1832 | * issues an LE_Set_Advertise_Enable command with | ||
| 1833 | * Advertising_Enable set to 0x00 (Advertising is disabled) | ||
| 1834 | * or until a connection is created or until the Advertising | ||
| 1835 | * is timed out due to Directed Advertising." | ||
| 1836 | */ | ||
| 1837 | if (type == LE_LINK) | ||
| 1838 | mgmt_reenable_advertising(hdev); | ||
| 1833 | } | 1839 | } |
| 1834 | 1840 | ||
| 1835 | unlock: | 1841 | unlock: |
| @@ -2144,6 +2150,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
| 2144 | hci_cc_write_voice_setting(hdev, skb); | 2150 | hci_cc_write_voice_setting(hdev, skb); |
| 2145 | break; | 2151 | break; |
| 2146 | 2152 | ||
| 2153 | case HCI_OP_READ_NUM_SUPPORTED_IAC: | ||
| 2154 | hci_cc_read_num_supported_iac(hdev, skb); | ||
| 2155 | break; | ||
| 2156 | |||
| 2147 | case HCI_OP_WRITE_SSP_MODE: | 2157 | case HCI_OP_WRITE_SSP_MODE: |
| 2148 | hci_cc_write_ssp_mode(hdev, skb); | 2158 | hci_cc_write_ssp_mode(hdev, skb); |
| 2149 | break; | 2159 | break; |
| @@ -2347,10 +2357,6 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
| 2347 | hci_cs_disconnect(hdev, ev->status); | 2357 | hci_cs_disconnect(hdev, ev->status); |
| 2348 | break; | 2358 | break; |
| 2349 | 2359 | ||
| 2350 | case HCI_OP_LE_CREATE_CONN: | ||
| 2351 | hci_cs_le_create_conn(hdev, ev->status); | ||
| 2352 | break; | ||
| 2353 | |||
| 2354 | case HCI_OP_CREATE_PHY_LINK: | 2360 | case HCI_OP_CREATE_PHY_LINK: |
| 2355 | hci_cs_create_phylink(hdev, ev->status); | 2361 | hci_cs_create_phylink(hdev, ev->status); |
| 2356 | break; | 2362 | break; |
| @@ -3490,6 +3496,17 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
| 3490 | 3496 | ||
| 3491 | conn->dst_type = ev->bdaddr_type; | 3497 | conn->dst_type = ev->bdaddr_type; |
| 3492 | 3498 | ||
| 3499 | /* The advertising parameters for own address type | ||
| 3500 | * define which source address and source address | ||
| 3501 | * type this connections has. | ||
| 3502 | */ | ||
| 3503 | if (bacmp(&conn->src, BDADDR_ANY)) { | ||
| 3504 | conn->src_type = ADDR_LE_DEV_PUBLIC; | ||
| 3505 | } else { | ||
| 3506 | bacpy(&conn->src, &hdev->static_addr); | ||
| 3507 | conn->src_type = ADDR_LE_DEV_RANDOM; | ||
| 3508 | } | ||
| 3509 | |||
| 3493 | if (ev->role == LE_CONN_ROLE_MASTER) { | 3510 | if (ev->role == LE_CONN_ROLE_MASTER) { |
| 3494 | conn->out = true; | 3511 | conn->out = true; |
| 3495 | conn->link_mode |= HCI_LM_MASTER; | 3512 | conn->link_mode |= HCI_LM_MASTER; |
| @@ -3645,8 +3662,8 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) | |||
| 3645 | skb_pull(skb, HCI_EVENT_HDR_SIZE); | 3662 | skb_pull(skb, HCI_EVENT_HDR_SIZE); |
| 3646 | 3663 | ||
| 3647 | if (hdev->sent_cmd && bt_cb(hdev->sent_cmd)->req.event == event) { | 3664 | if (hdev->sent_cmd && bt_cb(hdev->sent_cmd)->req.event == event) { |
| 3648 | struct hci_command_hdr *hdr = (void *) hdev->sent_cmd->data; | 3665 | struct hci_command_hdr *cmd_hdr = (void *) hdev->sent_cmd->data; |
| 3649 | u16 opcode = __le16_to_cpu(hdr->opcode); | 3666 | u16 opcode = __le16_to_cpu(cmd_hdr->opcode); |
| 3650 | 3667 | ||
| 3651 | hci_req_cmd_complete(hdev, opcode, 0); | 3668 | hci_req_cmd_complete(hdev, opcode, 0); |
| 3652 | } | 3669 | } |
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 579886186c3a..97f96ebdd56d 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c | |||
| @@ -387,7 +387,6 @@ static void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data) | |||
| 387 | __net_timestamp(skb); | 387 | __net_timestamp(skb); |
| 388 | 388 | ||
| 389 | bt_cb(skb)->pkt_type = HCI_EVENT_PKT; | 389 | bt_cb(skb)->pkt_type = HCI_EVENT_PKT; |
| 390 | skb->dev = (void *) hdev; | ||
| 391 | hci_send_to_sock(hdev, skb); | 390 | hci_send_to_sock(hdev, skb); |
| 392 | kfree_skb(skb); | 391 | kfree_skb(skb); |
| 393 | } | 392 | } |
| @@ -518,6 +517,9 @@ static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, | |||
| 518 | if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) | 517 | if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) |
| 519 | return -EBUSY; | 518 | return -EBUSY; |
| 520 | 519 | ||
| 520 | if (hdev->dev_type != HCI_BREDR) | ||
| 521 | return -EOPNOTSUPP; | ||
| 522 | |||
| 521 | switch (cmd) { | 523 | switch (cmd) { |
| 522 | case HCISETRAW: | 524 | case HCISETRAW: |
| 523 | if (!capable(CAP_NET_ADMIN)) | 525 | if (!capable(CAP_NET_ADMIN)) |
| @@ -550,10 +552,7 @@ static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, | |||
| 550 | return hci_sock_blacklist_del(hdev, (void __user *) arg); | 552 | return hci_sock_blacklist_del(hdev, (void __user *) arg); |
| 551 | } | 553 | } |
| 552 | 554 | ||
| 553 | if (hdev->ioctl) | 555 | return -ENOIOCTLCMD; |
| 554 | return hdev->ioctl(hdev, cmd, arg); | ||
| 555 | |||
| 556 | return -EINVAL; | ||
| 557 | } | 556 | } |
| 558 | 557 | ||
| 559 | static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, | 558 | static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, |
| @@ -942,7 +941,6 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
| 942 | 941 | ||
| 943 | bt_cb(skb)->pkt_type = *((unsigned char *) skb->data); | 942 | bt_cb(skb)->pkt_type = *((unsigned char *) skb->data); |
| 944 | skb_pull(skb, 1); | 943 | skb_pull(skb, 1); |
| 945 | skb->dev = (void *) hdev; | ||
| 946 | 944 | ||
| 947 | if (hci_pi(sk)->channel == HCI_CHANNEL_RAW && | 945 | if (hci_pi(sk)->channel == HCI_CHANNEL_RAW && |
| 948 | bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) { | 946 | bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) { |
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index bdc35a7a7fee..292e619db896 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c | |||
| @@ -767,10 +767,10 @@ static int hidp_setup_hid(struct hidp_session *session, | |||
| 767 | strncpy(hid->name, req->name, sizeof(req->name) - 1); | 767 | strncpy(hid->name, req->name, sizeof(req->name) - 1); |
| 768 | 768 | ||
| 769 | snprintf(hid->phys, sizeof(hid->phys), "%pMR", | 769 | snprintf(hid->phys, sizeof(hid->phys), "%pMR", |
| 770 | &bt_sk(session->ctrl_sock->sk)->src); | 770 | &l2cap_pi(session->ctrl_sock->sk)->chan->src); |
| 771 | 771 | ||
| 772 | snprintf(hid->uniq, sizeof(hid->uniq), "%pMR", | 772 | snprintf(hid->uniq, sizeof(hid->uniq), "%pMR", |
| 773 | &bt_sk(session->ctrl_sock->sk)->dst); | 773 | &l2cap_pi(session->ctrl_sock->sk)->chan->dst); |
| 774 | 774 | ||
| 775 | hid->dev.parent = &session->conn->hcon->dev; | 775 | hid->dev.parent = &session->conn->hcon->dev; |
| 776 | hid->ll_driver = &hidp_hid_driver; | 776 | hid->ll_driver = &hidp_hid_driver; |
| @@ -1283,23 +1283,29 @@ static int hidp_session_thread(void *arg) | |||
| 1283 | static int hidp_verify_sockets(struct socket *ctrl_sock, | 1283 | static int hidp_verify_sockets(struct socket *ctrl_sock, |
| 1284 | struct socket *intr_sock) | 1284 | struct socket *intr_sock) |
| 1285 | { | 1285 | { |
| 1286 | struct l2cap_chan *ctrl_chan, *intr_chan; | ||
| 1286 | struct bt_sock *ctrl, *intr; | 1287 | struct bt_sock *ctrl, *intr; |
| 1287 | struct hidp_session *session; | 1288 | struct hidp_session *session; |
| 1288 | 1289 | ||
| 1289 | if (!l2cap_is_socket(ctrl_sock) || !l2cap_is_socket(intr_sock)) | 1290 | if (!l2cap_is_socket(ctrl_sock) || !l2cap_is_socket(intr_sock)) |
| 1290 | return -EINVAL; | 1291 | return -EINVAL; |
| 1291 | 1292 | ||
| 1293 | ctrl_chan = l2cap_pi(ctrl_sock->sk)->chan; | ||
| 1294 | intr_chan = l2cap_pi(intr_sock->sk)->chan; | ||
| 1295 | |||
| 1296 | if (bacmp(&ctrl_chan->src, &intr_chan->src) || | ||
| 1297 | bacmp(&ctrl_chan->dst, &intr_chan->dst)) | ||
| 1298 | return -ENOTUNIQ; | ||
| 1299 | |||
| 1292 | ctrl = bt_sk(ctrl_sock->sk); | 1300 | ctrl = bt_sk(ctrl_sock->sk); |
| 1293 | intr = bt_sk(intr_sock->sk); | 1301 | intr = bt_sk(intr_sock->sk); |
| 1294 | 1302 | ||
| 1295 | if (bacmp(&ctrl->src, &intr->src) || bacmp(&ctrl->dst, &intr->dst)) | ||
| 1296 | return -ENOTUNIQ; | ||
| 1297 | if (ctrl->sk.sk_state != BT_CONNECTED || | 1303 | if (ctrl->sk.sk_state != BT_CONNECTED || |
| 1298 | intr->sk.sk_state != BT_CONNECTED) | 1304 | intr->sk.sk_state != BT_CONNECTED) |
| 1299 | return -EBADFD; | 1305 | return -EBADFD; |
| 1300 | 1306 | ||
| 1301 | /* early session check, we check again during session registration */ | 1307 | /* early session check, we check again during session registration */ |
| 1302 | session = hidp_session_find(&ctrl->dst); | 1308 | session = hidp_session_find(&ctrl_chan->dst); |
| 1303 | if (session) { | 1309 | if (session) { |
| 1304 | hidp_session_put(session); | 1310 | hidp_session_put(session); |
| 1305 | return -EEXIST; | 1311 | return -EEXIST; |
| @@ -1332,7 +1338,7 @@ int hidp_connection_add(struct hidp_connadd_req *req, | |||
| 1332 | if (!conn) | 1338 | if (!conn) |
| 1333 | return -EBADFD; | 1339 | return -EBADFD; |
| 1334 | 1340 | ||
| 1335 | ret = hidp_session_new(&session, &bt_sk(ctrl_sock->sk)->dst, ctrl_sock, | 1341 | ret = hidp_session_new(&session, &chan->dst, ctrl_sock, |
| 1336 | intr_sock, req, conn); | 1342 | intr_sock, req, conn); |
| 1337 | if (ret) | 1343 | if (ret) |
| 1338 | goto out_conn; | 1344 | goto out_conn; |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 02dba4e6df96..0c3446da1ec9 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
| @@ -36,14 +36,15 @@ | |||
| 36 | #include <net/bluetooth/bluetooth.h> | 36 | #include <net/bluetooth/bluetooth.h> |
| 37 | #include <net/bluetooth/hci_core.h> | 37 | #include <net/bluetooth/hci_core.h> |
| 38 | #include <net/bluetooth/l2cap.h> | 38 | #include <net/bluetooth/l2cap.h> |
| 39 | #include <net/bluetooth/smp.h> | 39 | |
| 40 | #include <net/bluetooth/a2mp.h> | 40 | #include "smp.h" |
| 41 | #include <net/bluetooth/amp.h> | 41 | #include "a2mp.h" |
| 42 | #include "amp.h" | ||
| 42 | 43 | ||
| 43 | bool disable_ertm; | 44 | bool disable_ertm; |
| 44 | 45 | ||
| 45 | static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN; | 46 | static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN | L2CAP_FEAT_UCD; |
| 46 | static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP, }; | 47 | static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP | L2CAP_FC_CONNLESS, }; |
| 47 | 48 | ||
| 48 | static LIST_HEAD(chan_list); | 49 | static LIST_HEAD(chan_list); |
| 49 | static DEFINE_RWLOCK(chan_list_lock); | 50 | static DEFINE_RWLOCK(chan_list_lock); |
| @@ -58,6 +59,18 @@ static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err); | |||
| 58 | static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, | 59 | static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, |
| 59 | struct sk_buff_head *skbs, u8 event); | 60 | struct sk_buff_head *skbs, u8 event); |
| 60 | 61 | ||
| 62 | static inline __u8 bdaddr_type(struct hci_conn *hcon, __u8 type) | ||
| 63 | { | ||
| 64 | if (hcon->type == LE_LINK) { | ||
| 65 | if (type == ADDR_LE_DEV_PUBLIC) | ||
| 66 | return BDADDR_LE_PUBLIC; | ||
| 67 | else | ||
| 68 | return BDADDR_LE_RANDOM; | ||
| 69 | } | ||
| 70 | |||
| 71 | return BDADDR_BREDR; | ||
| 72 | } | ||
| 73 | |||
| 61 | /* ---- L2CAP channels ---- */ | 74 | /* ---- L2CAP channels ---- */ |
| 62 | 75 | ||
| 63 | static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, | 76 | static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, |
| @@ -148,7 +161,7 @@ static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src) | |||
| 148 | struct l2cap_chan *c; | 161 | struct l2cap_chan *c; |
| 149 | 162 | ||
| 150 | list_for_each_entry(c, &chan_list, global_l) { | 163 | list_for_each_entry(c, &chan_list, global_l) { |
| 151 | if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src)) | 164 | if (c->sport == psm && !bacmp(&c->src, src)) |
| 152 | return c; | 165 | return c; |
| 153 | } | 166 | } |
| 154 | return NULL; | 167 | return NULL; |
| @@ -620,10 +633,8 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) | |||
| 620 | void l2cap_chan_close(struct l2cap_chan *chan, int reason) | 633 | void l2cap_chan_close(struct l2cap_chan *chan, int reason) |
| 621 | { | 634 | { |
| 622 | struct l2cap_conn *conn = chan->conn; | 635 | struct l2cap_conn *conn = chan->conn; |
| 623 | struct sock *sk = chan->sk; | ||
| 624 | 636 | ||
| 625 | BT_DBG("chan %p state %s sk %p", chan, state_to_string(chan->state), | 637 | BT_DBG("chan %p state %s", chan, state_to_string(chan->state)); |
| 626 | sk); | ||
| 627 | 638 | ||
| 628 | switch (chan->state) { | 639 | switch (chan->state) { |
| 629 | case BT_LISTEN: | 640 | case BT_LISTEN: |
| @@ -634,6 +645,7 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason) | |||
| 634 | case BT_CONFIG: | 645 | case BT_CONFIG: |
| 635 | if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && | 646 | if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && |
| 636 | conn->hcon->type == ACL_LINK) { | 647 | conn->hcon->type == ACL_LINK) { |
| 648 | struct sock *sk = chan->sk; | ||
| 637 | __set_chan_timer(chan, sk->sk_sndtimeo); | 649 | __set_chan_timer(chan, sk->sk_sndtimeo); |
| 638 | l2cap_send_disconn_req(chan, reason); | 650 | l2cap_send_disconn_req(chan, reason); |
| 639 | } else | 651 | } else |
| @@ -646,10 +658,11 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason) | |||
| 646 | struct l2cap_conn_rsp rsp; | 658 | struct l2cap_conn_rsp rsp; |
| 647 | __u16 result; | 659 | __u16 result; |
| 648 | 660 | ||
| 649 | if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) | 661 | if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) |
| 650 | result = L2CAP_CR_SEC_BLOCK; | 662 | result = L2CAP_CR_SEC_BLOCK; |
| 651 | else | 663 | else |
| 652 | result = L2CAP_CR_BAD_PSM; | 664 | result = L2CAP_CR_BAD_PSM; |
| 665 | |||
| 653 | l2cap_state_change(chan, BT_DISCONN); | 666 | l2cap_state_change(chan, BT_DISCONN); |
| 654 | 667 | ||
| 655 | rsp.scid = cpu_to_le16(chan->dcid); | 668 | rsp.scid = cpu_to_le16(chan->dcid); |
| @@ -676,7 +689,8 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason) | |||
| 676 | 689 | ||
| 677 | static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) | 690 | static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) |
| 678 | { | 691 | { |
| 679 | if (chan->chan_type == L2CAP_CHAN_RAW) { | 692 | switch (chan->chan_type) { |
| 693 | case L2CAP_CHAN_RAW: | ||
| 680 | switch (chan->sec_level) { | 694 | switch (chan->sec_level) { |
| 681 | case BT_SECURITY_HIGH: | 695 | case BT_SECURITY_HIGH: |
| 682 | return HCI_AT_DEDICATED_BONDING_MITM; | 696 | return HCI_AT_DEDICATED_BONDING_MITM; |
| @@ -685,15 +699,29 @@ static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) | |||
| 685 | default: | 699 | default: |
| 686 | return HCI_AT_NO_BONDING; | 700 | return HCI_AT_NO_BONDING; |
| 687 | } | 701 | } |
| 688 | } else if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_SDP)) { | 702 | break; |
| 689 | if (chan->sec_level == BT_SECURITY_LOW) | 703 | case L2CAP_CHAN_CONN_LESS: |
| 690 | chan->sec_level = BT_SECURITY_SDP; | 704 | if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_3DSP)) { |
| 691 | 705 | if (chan->sec_level == BT_SECURITY_LOW) | |
| 706 | chan->sec_level = BT_SECURITY_SDP; | ||
| 707 | } | ||
| 692 | if (chan->sec_level == BT_SECURITY_HIGH) | 708 | if (chan->sec_level == BT_SECURITY_HIGH) |
| 693 | return HCI_AT_NO_BONDING_MITM; | 709 | return HCI_AT_NO_BONDING_MITM; |
| 694 | else | 710 | else |
| 695 | return HCI_AT_NO_BONDING; | 711 | return HCI_AT_NO_BONDING; |
| 696 | } else { | 712 | break; |
| 713 | case L2CAP_CHAN_CONN_ORIENTED: | ||
| 714 | if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_SDP)) { | ||
| 715 | if (chan->sec_level == BT_SECURITY_LOW) | ||
| 716 | chan->sec_level = BT_SECURITY_SDP; | ||
| 717 | |||
| 718 | if (chan->sec_level == BT_SECURITY_HIGH) | ||
| 719 | return HCI_AT_NO_BONDING_MITM; | ||
| 720 | else | ||
| 721 | return HCI_AT_NO_BONDING; | ||
| 722 | } | ||
| 723 | /* fall through */ | ||
| 724 | default: | ||
| 697 | switch (chan->sec_level) { | 725 | switch (chan->sec_level) { |
| 698 | case BT_SECURITY_HIGH: | 726 | case BT_SECURITY_HIGH: |
| 699 | return HCI_AT_GENERAL_BONDING_MITM; | 727 | return HCI_AT_GENERAL_BONDING_MITM; |
| @@ -702,6 +730,7 @@ static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) | |||
| 702 | default: | 730 | default: |
| 703 | return HCI_AT_NO_BONDING; | 731 | return HCI_AT_NO_BONDING; |
| 704 | } | 732 | } |
| 733 | break; | ||
| 705 | } | 734 | } |
| 706 | } | 735 | } |
| 707 | 736 | ||
| @@ -1015,11 +1044,27 @@ static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan) | |||
| 1015 | static bool __amp_capable(struct l2cap_chan *chan) | 1044 | static bool __amp_capable(struct l2cap_chan *chan) |
| 1016 | { | 1045 | { |
| 1017 | struct l2cap_conn *conn = chan->conn; | 1046 | struct l2cap_conn *conn = chan->conn; |
| 1047 | struct hci_dev *hdev; | ||
| 1048 | bool amp_available = false; | ||
| 1049 | |||
| 1050 | if (!conn->hs_enabled) | ||
| 1051 | return false; | ||
| 1018 | 1052 | ||
| 1019 | if (conn->hs_enabled && hci_amp_capable() && | 1053 | if (!(conn->fixed_chan_mask & L2CAP_FC_A2MP)) |
| 1020 | chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED && | 1054 | return false; |
| 1021 | conn->fixed_chan_mask & L2CAP_FC_A2MP) | 1055 | |
| 1022 | return true; | 1056 | read_lock(&hci_dev_list_lock); |
| 1057 | list_for_each_entry(hdev, &hci_dev_list, list) { | ||
| 1058 | if (hdev->amp_type != AMP_TYPE_BREDR && | ||
| 1059 | test_bit(HCI_UP, &hdev->flags)) { | ||
| 1060 | amp_available = true; | ||
| 1061 | break; | ||
| 1062 | } | ||
| 1063 | } | ||
| 1064 | read_unlock(&hci_dev_list_lock); | ||
| 1065 | |||
| 1066 | if (chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED) | ||
| 1067 | return amp_available; | ||
| 1023 | 1068 | ||
| 1024 | return false; | 1069 | return false; |
| 1025 | } | 1070 | } |
| @@ -1224,8 +1269,6 @@ static void l2cap_conn_start(struct l2cap_conn *conn) | |||
| 1224 | mutex_lock(&conn->chan_lock); | 1269 | mutex_lock(&conn->chan_lock); |
| 1225 | 1270 | ||
| 1226 | list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) { | 1271 | list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) { |
| 1227 | struct sock *sk = chan->sk; | ||
| 1228 | |||
| 1229 | l2cap_chan_lock(chan); | 1272 | l2cap_chan_lock(chan); |
| 1230 | 1273 | ||
| 1231 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { | 1274 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { |
| @@ -1257,9 +1300,10 @@ static void l2cap_conn_start(struct l2cap_conn *conn) | |||
| 1257 | rsp.dcid = cpu_to_le16(chan->scid); | 1300 | rsp.dcid = cpu_to_le16(chan->scid); |
| 1258 | 1301 | ||
| 1259 | if (l2cap_chan_check_security(chan)) { | 1302 | if (l2cap_chan_check_security(chan)) { |
| 1303 | struct sock *sk = chan->sk; | ||
| 1304 | |||
| 1260 | lock_sock(sk); | 1305 | lock_sock(sk); |
| 1261 | if (test_bit(BT_SK_DEFER_SETUP, | 1306 | if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { |
| 1262 | &bt_sk(sk)->flags)) { | ||
| 1263 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND); | 1307 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND); |
| 1264 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHOR_PEND); | 1308 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHOR_PEND); |
| 1265 | chan->ops->defer(chan); | 1309 | chan->ops->defer(chan); |
| @@ -1308,8 +1352,6 @@ static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid, | |||
| 1308 | read_lock(&chan_list_lock); | 1352 | read_lock(&chan_list_lock); |
| 1309 | 1353 | ||
| 1310 | list_for_each_entry(c, &chan_list, global_l) { | 1354 | list_for_each_entry(c, &chan_list, global_l) { |
| 1311 | struct sock *sk = c->sk; | ||
| 1312 | |||
| 1313 | if (state && c->state != state) | 1355 | if (state && c->state != state) |
| 1314 | continue; | 1356 | continue; |
| 1315 | 1357 | ||
| @@ -1318,16 +1360,16 @@ static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid, | |||
| 1318 | int src_any, dst_any; | 1360 | int src_any, dst_any; |
| 1319 | 1361 | ||
| 1320 | /* Exact match. */ | 1362 | /* Exact match. */ |
| 1321 | src_match = !bacmp(&bt_sk(sk)->src, src); | 1363 | src_match = !bacmp(&c->src, src); |
| 1322 | dst_match = !bacmp(&bt_sk(sk)->dst, dst); | 1364 | dst_match = !bacmp(&c->dst, dst); |
| 1323 | if (src_match && dst_match) { | 1365 | if (src_match && dst_match) { |
| 1324 | read_unlock(&chan_list_lock); | 1366 | read_unlock(&chan_list_lock); |
| 1325 | return c; | 1367 | return c; |
| 1326 | } | 1368 | } |
| 1327 | 1369 | ||
| 1328 | /* Closest match */ | 1370 | /* Closest match */ |
| 1329 | src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY); | 1371 | src_any = !bacmp(&c->src, BDADDR_ANY); |
| 1330 | dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY); | 1372 | dst_any = !bacmp(&c->dst, BDADDR_ANY); |
| 1331 | if ((src_match && dst_any) || (src_any && dst_match) || | 1373 | if ((src_match && dst_any) || (src_any && dst_match) || |
| 1332 | (src_any && dst_any)) | 1374 | (src_any && dst_any)) |
| 1333 | c1 = c; | 1375 | c1 = c; |
| @@ -1348,7 +1390,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) | |||
| 1348 | 1390 | ||
| 1349 | /* Check if we have socket listening on cid */ | 1391 | /* Check if we have socket listening on cid */ |
| 1350 | pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_ATT, | 1392 | pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_ATT, |
| 1351 | conn->src, conn->dst); | 1393 | &conn->hcon->src, &conn->hcon->dst); |
| 1352 | if (!pchan) | 1394 | if (!pchan) |
| 1353 | return; | 1395 | return; |
| 1354 | 1396 | ||
| @@ -1366,8 +1408,10 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) | |||
| 1366 | 1408 | ||
| 1367 | chan->dcid = L2CAP_CID_ATT; | 1409 | chan->dcid = L2CAP_CID_ATT; |
| 1368 | 1410 | ||
| 1369 | bacpy(&bt_sk(chan->sk)->src, conn->src); | 1411 | bacpy(&chan->src, &conn->hcon->src); |
| 1370 | bacpy(&bt_sk(chan->sk)->dst, conn->dst); | 1412 | bacpy(&chan->dst, &conn->hcon->dst); |
| 1413 | chan->src_type = bdaddr_type(conn->hcon, conn->hcon->src_type); | ||
| 1414 | chan->dst_type = bdaddr_type(conn->hcon, conn->hcon->dst_type); | ||
| 1371 | 1415 | ||
| 1372 | __l2cap_chan_add(conn, chan); | 1416 | __l2cap_chan_add(conn, chan); |
| 1373 | 1417 | ||
| @@ -1632,9 +1676,6 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon) | |||
| 1632 | break; | 1676 | break; |
| 1633 | } | 1677 | } |
| 1634 | 1678 | ||
| 1635 | conn->src = &hcon->hdev->bdaddr; | ||
| 1636 | conn->dst = &hcon->dst; | ||
| 1637 | |||
| 1638 | conn->feat_mask = 0; | 1679 | conn->feat_mask = 0; |
| 1639 | 1680 | ||
| 1640 | if (hcon->type == ACL_LINK) | 1681 | if (hcon->type == ACL_LINK) |
| @@ -1691,8 +1732,6 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, | |||
| 1691 | read_lock(&chan_list_lock); | 1732 | read_lock(&chan_list_lock); |
| 1692 | 1733 | ||
| 1693 | list_for_each_entry(c, &chan_list, global_l) { | 1734 | list_for_each_entry(c, &chan_list, global_l) { |
| 1694 | struct sock *sk = c->sk; | ||
| 1695 | |||
| 1696 | if (state && c->state != state) | 1735 | if (state && c->state != state) |
| 1697 | continue; | 1736 | continue; |
| 1698 | 1737 | ||
| @@ -1701,16 +1740,16 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, | |||
| 1701 | int src_any, dst_any; | 1740 | int src_any, dst_any; |
| 1702 | 1741 | ||
| 1703 | /* Exact match. */ | 1742 | /* Exact match. */ |
| 1704 | src_match = !bacmp(&bt_sk(sk)->src, src); | 1743 | src_match = !bacmp(&c->src, src); |
| 1705 | dst_match = !bacmp(&bt_sk(sk)->dst, dst); | 1744 | dst_match = !bacmp(&c->dst, dst); |
| 1706 | if (src_match && dst_match) { | 1745 | if (src_match && dst_match) { |
| 1707 | read_unlock(&chan_list_lock); | 1746 | read_unlock(&chan_list_lock); |
| 1708 | return c; | 1747 | return c; |
| 1709 | } | 1748 | } |
| 1710 | 1749 | ||
| 1711 | /* Closest match */ | 1750 | /* Closest match */ |
| 1712 | src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY); | 1751 | src_any = !bacmp(&c->src, BDADDR_ANY); |
| 1713 | dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY); | 1752 | dst_any = !bacmp(&c->dst, BDADDR_ANY); |
| 1714 | if ((src_match && dst_any) || (src_any && dst_match) || | 1753 | if ((src_match && dst_any) || (src_any && dst_match) || |
| 1715 | (src_any && dst_any)) | 1754 | (src_any && dst_any)) |
| 1716 | c1 = c; | 1755 | c1 = c; |
| @@ -1726,17 +1765,16 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, | |||
| 1726 | bdaddr_t *dst, u8 dst_type) | 1765 | bdaddr_t *dst, u8 dst_type) |
| 1727 | { | 1766 | { |
| 1728 | struct sock *sk = chan->sk; | 1767 | struct sock *sk = chan->sk; |
| 1729 | bdaddr_t *src = &bt_sk(sk)->src; | ||
| 1730 | struct l2cap_conn *conn; | 1768 | struct l2cap_conn *conn; |
| 1731 | struct hci_conn *hcon; | 1769 | struct hci_conn *hcon; |
| 1732 | struct hci_dev *hdev; | 1770 | struct hci_dev *hdev; |
| 1733 | __u8 auth_type; | 1771 | __u8 auth_type; |
| 1734 | int err; | 1772 | int err; |
| 1735 | 1773 | ||
| 1736 | BT_DBG("%pMR -> %pMR (type %u) psm 0x%2.2x", src, dst, | 1774 | BT_DBG("%pMR -> %pMR (type %u) psm 0x%2.2x", &chan->src, dst, |
| 1737 | dst_type, __le16_to_cpu(psm)); | 1775 | dst_type, __le16_to_cpu(psm)); |
| 1738 | 1776 | ||
| 1739 | hdev = hci_get_route(dst, src); | 1777 | hdev = hci_get_route(dst, &chan->src); |
| 1740 | if (!hdev) | 1778 | if (!hdev) |
| 1741 | return -EHOSTUNREACH; | 1779 | return -EHOSTUNREACH; |
| 1742 | 1780 | ||
| @@ -1793,9 +1831,8 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, | |||
| 1793 | } | 1831 | } |
| 1794 | 1832 | ||
| 1795 | /* Set destination address and psm */ | 1833 | /* Set destination address and psm */ |
| 1796 | lock_sock(sk); | 1834 | bacpy(&chan->dst, dst); |
| 1797 | bacpy(&bt_sk(sk)->dst, dst); | 1835 | chan->dst_type = dst_type; |
| 1798 | release_sock(sk); | ||
| 1799 | 1836 | ||
| 1800 | chan->psm = psm; | 1837 | chan->psm = psm; |
| 1801 | chan->dcid = cid; | 1838 | chan->dcid = cid; |
| @@ -1828,7 +1865,8 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, | |||
| 1828 | } | 1865 | } |
| 1829 | 1866 | ||
| 1830 | /* Update source addr of the socket */ | 1867 | /* Update source addr of the socket */ |
| 1831 | bacpy(src, conn->src); | 1868 | bacpy(&chan->src, &hcon->src); |
| 1869 | chan->src_type = bdaddr_type(hcon, hcon->src_type); | ||
| 1832 | 1870 | ||
| 1833 | l2cap_chan_unlock(chan); | 1871 | l2cap_chan_unlock(chan); |
| 1834 | l2cap_chan_add(conn, chan); | 1872 | l2cap_chan_add(conn, chan); |
| @@ -2266,7 +2304,8 @@ static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, | |||
| 2266 | int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE; | 2304 | int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE; |
| 2267 | struct l2cap_hdr *lh; | 2305 | struct l2cap_hdr *lh; |
| 2268 | 2306 | ||
| 2269 | BT_DBG("chan %p len %zu priority %u", chan, len, priority); | 2307 | BT_DBG("chan %p psm 0x%2.2x len %zu priority %u", chan, |
| 2308 | __le16_to_cpu(chan->psm), len, priority); | ||
| 2270 | 2309 | ||
| 2271 | count = min_t(unsigned int, (conn->mtu - hlen), len); | 2310 | count = min_t(unsigned int, (conn->mtu - hlen), len); |
| 2272 | 2311 | ||
| @@ -2281,7 +2320,7 @@ static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, | |||
| 2281 | lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); | 2320 | lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); |
| 2282 | lh->cid = cpu_to_le16(chan->dcid); | 2321 | lh->cid = cpu_to_le16(chan->dcid); |
| 2283 | lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE); | 2322 | lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE); |
| 2284 | put_unaligned(chan->psm, skb_put(skb, L2CAP_PSMLEN_SIZE)); | 2323 | put_unaligned(chan->psm, (__le16 *) skb_put(skb, L2CAP_PSMLEN_SIZE)); |
| 2285 | 2324 | ||
| 2286 | err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); | 2325 | err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); |
| 2287 | if (unlikely(err < 0)) { | 2326 | if (unlikely(err < 0)) { |
| @@ -3046,8 +3085,8 @@ int l2cap_ertm_init(struct l2cap_chan *chan) | |||
| 3046 | 3085 | ||
| 3047 | skb_queue_head_init(&chan->tx_q); | 3086 | skb_queue_head_init(&chan->tx_q); |
| 3048 | 3087 | ||
| 3049 | chan->local_amp_id = 0; | 3088 | chan->local_amp_id = AMP_ID_BREDR; |
| 3050 | chan->move_id = 0; | 3089 | chan->move_id = AMP_ID_BREDR; |
| 3051 | chan->move_state = L2CAP_MOVE_STABLE; | 3090 | chan->move_state = L2CAP_MOVE_STABLE; |
| 3052 | chan->move_role = L2CAP_MOVE_ROLE_NONE; | 3091 | chan->move_role = L2CAP_MOVE_ROLE_NONE; |
| 3053 | 3092 | ||
| @@ -3100,7 +3139,7 @@ static inline bool __l2cap_efs_supported(struct l2cap_conn *conn) | |||
| 3100 | static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan, | 3139 | static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan, |
| 3101 | struct l2cap_conf_rfc *rfc) | 3140 | struct l2cap_conf_rfc *rfc) |
| 3102 | { | 3141 | { |
| 3103 | if (chan->local_amp_id && chan->hs_hcon) { | 3142 | if (chan->local_amp_id != AMP_ID_BREDR && chan->hs_hcon) { |
| 3104 | u64 ertm_to = chan->hs_hcon->hdev->amp_be_flush_to; | 3143 | u64 ertm_to = chan->hs_hcon->hdev->amp_be_flush_to; |
| 3105 | 3144 | ||
| 3106 | /* Class 1 devices have must have ERTM timeouts | 3145 | /* Class 1 devices have must have ERTM timeouts |
| @@ -3727,7 +3766,8 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, | |||
| 3727 | BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid); | 3766 | BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid); |
| 3728 | 3767 | ||
| 3729 | /* Check if we have socket listening on psm */ | 3768 | /* Check if we have socket listening on psm */ |
| 3730 | pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src, conn->dst); | 3769 | pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src, |
| 3770 | &conn->hcon->dst); | ||
| 3731 | if (!pchan) { | 3771 | if (!pchan) { |
| 3732 | result = L2CAP_CR_BAD_PSM; | 3772 | result = L2CAP_CR_BAD_PSM; |
| 3733 | goto sendresp; | 3773 | goto sendresp; |
| @@ -3765,8 +3805,10 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, | |||
| 3765 | */ | 3805 | */ |
| 3766 | conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT; | 3806 | conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT; |
| 3767 | 3807 | ||
| 3768 | bacpy(&bt_sk(sk)->src, conn->src); | 3808 | bacpy(&chan->src, &conn->hcon->src); |
| 3769 | bacpy(&bt_sk(sk)->dst, conn->dst); | 3809 | bacpy(&chan->dst, &conn->hcon->dst); |
| 3810 | chan->src_type = bdaddr_type(conn->hcon, conn->hcon->src_type); | ||
| 3811 | chan->dst_type = bdaddr_type(conn->hcon, conn->hcon->dst_type); | ||
| 3770 | chan->psm = psm; | 3812 | chan->psm = psm; |
| 3771 | chan->dcid = scid; | 3813 | chan->dcid = scid; |
| 3772 | chan->local_amp_id = amp_id; | 3814 | chan->local_amp_id = amp_id; |
| @@ -3781,7 +3823,7 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, | |||
| 3781 | 3823 | ||
| 3782 | if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) { | 3824 | if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) { |
| 3783 | if (l2cap_chan_check_security(chan)) { | 3825 | if (l2cap_chan_check_security(chan)) { |
| 3784 | if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) { | 3826 | if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { |
| 3785 | __l2cap_state_change(chan, BT_CONNECT2); | 3827 | __l2cap_state_change(chan, BT_CONNECT2); |
| 3786 | result = L2CAP_CR_PEND; | 3828 | result = L2CAP_CR_PEND; |
| 3787 | status = L2CAP_CS_AUTHOR_PEND; | 3829 | status = L2CAP_CS_AUTHOR_PEND; |
| @@ -3791,12 +3833,12 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, | |||
| 3791 | * The connection will succeed after the | 3833 | * The connection will succeed after the |
| 3792 | * physical link is up. | 3834 | * physical link is up. |
| 3793 | */ | 3835 | */ |
| 3794 | if (amp_id) { | 3836 | if (amp_id == AMP_ID_BREDR) { |
| 3795 | __l2cap_state_change(chan, BT_CONNECT2); | ||
| 3796 | result = L2CAP_CR_PEND; | ||
| 3797 | } else { | ||
| 3798 | __l2cap_state_change(chan, BT_CONFIG); | 3837 | __l2cap_state_change(chan, BT_CONFIG); |
| 3799 | result = L2CAP_CR_SUCCESS; | 3838 | result = L2CAP_CR_SUCCESS; |
| 3839 | } else { | ||
| 3840 | __l2cap_state_change(chan, BT_CONNECT2); | ||
| 3841 | result = L2CAP_CR_PEND; | ||
| 3800 | } | 3842 | } |
| 3801 | status = L2CAP_CS_NO_INFO; | 3843 | status = L2CAP_CS_NO_INFO; |
| 3802 | } | 3844 | } |
| @@ -4423,7 +4465,7 @@ static int l2cap_create_channel_req(struct l2cap_conn *conn, | |||
| 4423 | BT_DBG("psm 0x%2.2x, scid 0x%4.4x, amp_id %d", psm, scid, req->amp_id); | 4465 | BT_DBG("psm 0x%2.2x, scid 0x%4.4x, amp_id %d", psm, scid, req->amp_id); |
| 4424 | 4466 | ||
| 4425 | /* For controller id 0 make BR/EDR connection */ | 4467 | /* For controller id 0 make BR/EDR connection */ |
| 4426 | if (req->amp_id == HCI_BREDR_ID) { | 4468 | if (req->amp_id == AMP_ID_BREDR) { |
| 4427 | l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP, | 4469 | l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP, |
| 4428 | req->amp_id); | 4470 | req->amp_id); |
| 4429 | return 0; | 4471 | return 0; |
| @@ -4445,7 +4487,8 @@ static int l2cap_create_channel_req(struct l2cap_conn *conn, | |||
| 4445 | struct amp_mgr *mgr = conn->hcon->amp_mgr; | 4487 | struct amp_mgr *mgr = conn->hcon->amp_mgr; |
| 4446 | struct hci_conn *hs_hcon; | 4488 | struct hci_conn *hs_hcon; |
| 4447 | 4489 | ||
| 4448 | hs_hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK, conn->dst); | 4490 | hs_hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK, |
| 4491 | &conn->hcon->dst); | ||
| 4449 | if (!hs_hcon) { | 4492 | if (!hs_hcon) { |
| 4450 | hci_dev_put(hdev); | 4493 | hci_dev_put(hdev); |
| 4451 | return -EBADSLT; | 4494 | return -EBADSLT; |
| @@ -4658,7 +4701,7 @@ void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan, | |||
| 4658 | 4701 | ||
| 4659 | if (chan->state != BT_CONNECTED) { | 4702 | if (chan->state != BT_CONNECTED) { |
| 4660 | /* Ignore logical link if channel is on BR/EDR */ | 4703 | /* Ignore logical link if channel is on BR/EDR */ |
| 4661 | if (chan->local_amp_id) | 4704 | if (chan->local_amp_id != AMP_ID_BREDR) |
| 4662 | l2cap_logical_finish_create(chan, hchan); | 4705 | l2cap_logical_finish_create(chan, hchan); |
| 4663 | } else { | 4706 | } else { |
| 4664 | l2cap_logical_finish_move(chan, hchan); | 4707 | l2cap_logical_finish_move(chan, hchan); |
| @@ -4669,7 +4712,7 @@ void l2cap_move_start(struct l2cap_chan *chan) | |||
| 4669 | { | 4712 | { |
| 4670 | BT_DBG("chan %p", chan); | 4713 | BT_DBG("chan %p", chan); |
| 4671 | 4714 | ||
| 4672 | if (chan->local_amp_id == HCI_BREDR_ID) { | 4715 | if (chan->local_amp_id == AMP_ID_BREDR) { |
| 4673 | if (chan->chan_policy != BT_CHANNEL_POLICY_AMP_PREFERRED) | 4716 | if (chan->chan_policy != BT_CHANNEL_POLICY_AMP_PREFERRED) |
| 4674 | return; | 4717 | return; |
| 4675 | chan->move_role = L2CAP_MOVE_ROLE_INITIATOR; | 4718 | chan->move_role = L2CAP_MOVE_ROLE_INITIATOR; |
| @@ -4868,7 +4911,7 @@ static inline int l2cap_move_channel_req(struct l2cap_conn *conn, | |||
| 4868 | goto send_move_response; | 4911 | goto send_move_response; |
| 4869 | } | 4912 | } |
| 4870 | 4913 | ||
| 4871 | if (req->dest_amp_id) { | 4914 | if (req->dest_amp_id != AMP_ID_BREDR) { |
| 4872 | struct hci_dev *hdev; | 4915 | struct hci_dev *hdev; |
| 4873 | hdev = hci_dev_get(req->dest_amp_id); | 4916 | hdev = hci_dev_get(req->dest_amp_id); |
| 4874 | if (!hdev || hdev->dev_type != HCI_AMP || | 4917 | if (!hdev || hdev->dev_type != HCI_AMP || |
| @@ -4888,7 +4931,7 @@ static inline int l2cap_move_channel_req(struct l2cap_conn *conn, | |||
| 4888 | */ | 4931 | */ |
| 4889 | if ((__chan_is_moving(chan) || | 4932 | if ((__chan_is_moving(chan) || |
| 4890 | chan->move_role != L2CAP_MOVE_ROLE_NONE) && | 4933 | chan->move_role != L2CAP_MOVE_ROLE_NONE) && |
| 4891 | bacmp(conn->src, conn->dst) > 0) { | 4934 | bacmp(&conn->hcon->src, &conn->hcon->dst) > 0) { |
| 4892 | result = L2CAP_MR_COLLISION; | 4935 | result = L2CAP_MR_COLLISION; |
| 4893 | goto send_move_response; | 4936 | goto send_move_response; |
| 4894 | } | 4937 | } |
| @@ -4898,7 +4941,7 @@ static inline int l2cap_move_channel_req(struct l2cap_conn *conn, | |||
| 4898 | chan->move_id = req->dest_amp_id; | 4941 | chan->move_id = req->dest_amp_id; |
| 4899 | icid = chan->dcid; | 4942 | icid = chan->dcid; |
| 4900 | 4943 | ||
| 4901 | if (!req->dest_amp_id) { | 4944 | if (req->dest_amp_id == AMP_ID_BREDR) { |
| 4902 | /* Moving to BR/EDR */ | 4945 | /* Moving to BR/EDR */ |
| 4903 | if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { | 4946 | if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { |
| 4904 | chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY; | 4947 | chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY; |
| @@ -5090,7 +5133,7 @@ static int l2cap_move_channel_confirm(struct l2cap_conn *conn, | |||
| 5090 | if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM) { | 5133 | if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM) { |
| 5091 | if (result == L2CAP_MC_CONFIRMED) { | 5134 | if (result == L2CAP_MC_CONFIRMED) { |
| 5092 | chan->local_amp_id = chan->move_id; | 5135 | chan->local_amp_id = chan->move_id; |
| 5093 | if (!chan->local_amp_id) | 5136 | if (chan->local_amp_id == AMP_ID_BREDR) |
| 5094 | __release_logical_link(chan); | 5137 | __release_logical_link(chan); |
| 5095 | } else { | 5138 | } else { |
| 5096 | chan->move_id = chan->local_amp_id; | 5139 | chan->move_id = chan->local_amp_id; |
| @@ -5130,7 +5173,7 @@ static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn, | |||
| 5130 | if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM_RSP) { | 5173 | if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM_RSP) { |
| 5131 | chan->local_amp_id = chan->move_id; | 5174 | chan->local_amp_id = chan->move_id; |
| 5132 | 5175 | ||
| 5133 | if (!chan->local_amp_id && chan->hs_hchan) | 5176 | if (chan->local_amp_id == AMP_ID_BREDR && chan->hs_hchan) |
| 5134 | __release_logical_link(chan); | 5177 | __release_logical_link(chan); |
| 5135 | 5178 | ||
| 5136 | l2cap_move_done(chan); | 5179 | l2cap_move_done(chan); |
| @@ -6403,7 +6446,8 @@ static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, | |||
| 6403 | if (hcon->type != ACL_LINK) | 6446 | if (hcon->type != ACL_LINK) |
| 6404 | goto drop; | 6447 | goto drop; |
| 6405 | 6448 | ||
| 6406 | chan = l2cap_global_chan_by_psm(0, psm, conn->src, conn->dst); | 6449 | chan = l2cap_global_chan_by_psm(0, psm, &conn->hcon->src, |
| 6450 | &conn->hcon->dst); | ||
| 6407 | if (!chan) | 6451 | if (!chan) |
| 6408 | goto drop; | 6452 | goto drop; |
| 6409 | 6453 | ||
| @@ -6415,6 +6459,10 @@ static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, | |||
| 6415 | if (chan->imtu < skb->len) | 6459 | if (chan->imtu < skb->len) |
| 6416 | goto drop; | 6460 | goto drop; |
| 6417 | 6461 | ||
| 6462 | /* Store remote BD_ADDR and PSM for msg_name */ | ||
| 6463 | bacpy(&bt_cb(skb)->bdaddr, &conn->hcon->dst); | ||
| 6464 | bt_cb(skb)->psm = psm; | ||
| 6465 | |||
| 6418 | if (!chan->ops->recv(chan, skb)) | 6466 | if (!chan->ops->recv(chan, skb)) |
| 6419 | return; | 6467 | return; |
| 6420 | 6468 | ||
| @@ -6432,7 +6480,7 @@ static void l2cap_att_channel(struct l2cap_conn *conn, | |||
| 6432 | goto drop; | 6480 | goto drop; |
| 6433 | 6481 | ||
| 6434 | chan = l2cap_global_chan_by_scid(BT_CONNECTED, L2CAP_CID_ATT, | 6482 | chan = l2cap_global_chan_by_scid(BT_CONNECTED, L2CAP_CID_ATT, |
| 6435 | conn->src, conn->dst); | 6483 | &conn->hcon->src, &conn->hcon->dst); |
| 6436 | if (!chan) | 6484 | if (!chan) |
| 6437 | goto drop; | 6485 | goto drop; |
| 6438 | 6486 | ||
| @@ -6507,17 +6555,15 @@ int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) | |||
| 6507 | /* Find listening sockets and check their link_mode */ | 6555 | /* Find listening sockets and check their link_mode */ |
| 6508 | read_lock(&chan_list_lock); | 6556 | read_lock(&chan_list_lock); |
| 6509 | list_for_each_entry(c, &chan_list, global_l) { | 6557 | list_for_each_entry(c, &chan_list, global_l) { |
| 6510 | struct sock *sk = c->sk; | ||
| 6511 | |||
| 6512 | if (c->state != BT_LISTEN) | 6558 | if (c->state != BT_LISTEN) |
| 6513 | continue; | 6559 | continue; |
| 6514 | 6560 | ||
| 6515 | if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) { | 6561 | if (!bacmp(&c->src, &hdev->bdaddr)) { |
| 6516 | lm1 |= HCI_LM_ACCEPT; | 6562 | lm1 |= HCI_LM_ACCEPT; |
| 6517 | if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) | 6563 | if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) |
| 6518 | lm1 |= HCI_LM_MASTER; | 6564 | lm1 |= HCI_LM_MASTER; |
| 6519 | exact++; | 6565 | exact++; |
| 6520 | } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) { | 6566 | } else if (!bacmp(&c->src, BDADDR_ANY)) { |
| 6521 | lm2 |= HCI_LM_ACCEPT; | 6567 | lm2 |= HCI_LM_ACCEPT; |
| 6522 | if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) | 6568 | if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) |
| 6523 | lm2 |= HCI_LM_MASTER; | 6569 | lm2 |= HCI_LM_MASTER; |
| @@ -6623,11 +6669,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) | |||
| 6623 | 6669 | ||
| 6624 | if (!status && (chan->state == BT_CONNECTED || | 6670 | if (!status && (chan->state == BT_CONNECTED || |
| 6625 | chan->state == BT_CONFIG)) { | 6671 | chan->state == BT_CONFIG)) { |
| 6626 | struct sock *sk = chan->sk; | 6672 | chan->ops->resume(chan); |
| 6627 | |||
| 6628 | clear_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags); | ||
| 6629 | sk->sk_state_change(sk); | ||
| 6630 | |||
| 6631 | l2cap_check_encryption(chan, encrypt); | 6673 | l2cap_check_encryption(chan, encrypt); |
| 6632 | l2cap_chan_unlock(chan); | 6674 | l2cap_chan_unlock(chan); |
| 6633 | continue; | 6675 | continue; |
| @@ -6647,8 +6689,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) | |||
| 6647 | lock_sock(sk); | 6689 | lock_sock(sk); |
| 6648 | 6690 | ||
| 6649 | if (!status) { | 6691 | if (!status) { |
| 6650 | if (test_bit(BT_SK_DEFER_SETUP, | 6692 | if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { |
| 6651 | &bt_sk(sk)->flags)) { | ||
| 6652 | res = L2CAP_CR_PEND; | 6693 | res = L2CAP_CR_PEND; |
| 6653 | stat = L2CAP_CS_AUTHOR_PEND; | 6694 | stat = L2CAP_CS_AUTHOR_PEND; |
| 6654 | chan->ops->defer(chan); | 6695 | chan->ops->defer(chan); |
| @@ -6782,9 +6823,13 @@ int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) | |||
| 6782 | conn->rx_len -= skb->len; | 6823 | conn->rx_len -= skb->len; |
| 6783 | 6824 | ||
| 6784 | if (!conn->rx_len) { | 6825 | if (!conn->rx_len) { |
| 6785 | /* Complete frame received */ | 6826 | /* Complete frame received. l2cap_recv_frame |
| 6786 | l2cap_recv_frame(conn, conn->rx_skb); | 6827 | * takes ownership of the skb so set the global |
| 6828 | * rx_skb pointer to NULL first. | ||
| 6829 | */ | ||
| 6830 | struct sk_buff *rx_skb = conn->rx_skb; | ||
| 6787 | conn->rx_skb = NULL; | 6831 | conn->rx_skb = NULL; |
| 6832 | l2cap_recv_frame(conn, rx_skb); | ||
| 6788 | } | 6833 | } |
| 6789 | break; | 6834 | break; |
| 6790 | } | 6835 | } |
| @@ -6801,10 +6846,8 @@ static int l2cap_debugfs_show(struct seq_file *f, void *p) | |||
| 6801 | read_lock(&chan_list_lock); | 6846 | read_lock(&chan_list_lock); |
| 6802 | 6847 | ||
| 6803 | list_for_each_entry(c, &chan_list, global_l) { | 6848 | list_for_each_entry(c, &chan_list, global_l) { |
| 6804 | struct sock *sk = c->sk; | ||
| 6805 | |||
| 6806 | seq_printf(f, "%pMR %pMR %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", | 6849 | seq_printf(f, "%pMR %pMR %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", |
| 6807 | &bt_sk(sk)->src, &bt_sk(sk)->dst, | 6850 | &c->src, &c->dst, |
| 6808 | c->state, __le16_to_cpu(c->psm), | 6851 | c->state, __le16_to_cpu(c->psm), |
| 6809 | c->scid, c->dcid, c->imtu, c->omtu, | 6852 | c->scid, c->dcid, c->imtu, c->omtu, |
| 6810 | c->sec_level, c->mode); | 6853 | c->sec_level, c->mode); |
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 9119898ef040..5ffd75e20bde 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
| @@ -32,7 +32,8 @@ | |||
| 32 | #include <net/bluetooth/bluetooth.h> | 32 | #include <net/bluetooth/bluetooth.h> |
| 33 | #include <net/bluetooth/hci_core.h> | 33 | #include <net/bluetooth/hci_core.h> |
| 34 | #include <net/bluetooth/l2cap.h> | 34 | #include <net/bluetooth/l2cap.h> |
| 35 | #include <net/bluetooth/smp.h> | 35 | |
| 36 | #include "smp.h" | ||
| 36 | 37 | ||
| 37 | static struct bt_sock_list l2cap_sk_list = { | 38 | static struct bt_sock_list l2cap_sk_list = { |
| 38 | .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock) | 39 | .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock) |
| @@ -68,6 +69,9 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) | |||
| 68 | if (la.l2_cid && la.l2_psm) | 69 | if (la.l2_cid && la.l2_psm) |
| 69 | return -EINVAL; | 70 | return -EINVAL; |
| 70 | 71 | ||
| 72 | if (!bdaddr_type_is_valid(la.l2_bdaddr_type)) | ||
| 73 | return -EINVAL; | ||
| 74 | |||
| 71 | lock_sock(sk); | 75 | lock_sock(sk); |
| 72 | 76 | ||
| 73 | if (sk->sk_state != BT_OPEN) { | 77 | if (sk->sk_state != BT_OPEN) { |
| @@ -99,11 +103,20 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) | |||
| 99 | if (err < 0) | 103 | if (err < 0) |
| 100 | goto done; | 104 | goto done; |
| 101 | 105 | ||
| 102 | if (__le16_to_cpu(la.l2_psm) == L2CAP_PSM_SDP || | 106 | switch (chan->chan_type) { |
| 103 | __le16_to_cpu(la.l2_psm) == L2CAP_PSM_RFCOMM) | 107 | case L2CAP_CHAN_CONN_LESS: |
| 104 | chan->sec_level = BT_SECURITY_SDP; | 108 | if (__le16_to_cpu(la.l2_psm) == L2CAP_PSM_3DSP) |
| 109 | chan->sec_level = BT_SECURITY_SDP; | ||
| 110 | break; | ||
| 111 | case L2CAP_CHAN_CONN_ORIENTED: | ||
| 112 | if (__le16_to_cpu(la.l2_psm) == L2CAP_PSM_SDP || | ||
| 113 | __le16_to_cpu(la.l2_psm) == L2CAP_PSM_RFCOMM) | ||
| 114 | chan->sec_level = BT_SECURITY_SDP; | ||
| 115 | break; | ||
| 116 | } | ||
| 105 | 117 | ||
| 106 | bacpy(&bt_sk(sk)->src, &la.l2_bdaddr); | 118 | bacpy(&chan->src, &la.l2_bdaddr); |
| 119 | chan->src_type = la.l2_bdaddr_type; | ||
| 107 | 120 | ||
| 108 | chan->state = BT_BOUND; | 121 | chan->state = BT_BOUND; |
| 109 | sk->sk_state = BT_BOUND; | 122 | sk->sk_state = BT_BOUND; |
| @@ -134,6 +147,15 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, | |||
| 134 | if (la.l2_cid && la.l2_psm) | 147 | if (la.l2_cid && la.l2_psm) |
| 135 | return -EINVAL; | 148 | return -EINVAL; |
| 136 | 149 | ||
| 150 | if (!bdaddr_type_is_valid(la.l2_bdaddr_type)) | ||
| 151 | return -EINVAL; | ||
| 152 | |||
| 153 | if (chan->src_type == BDADDR_BREDR && la.l2_bdaddr_type != BDADDR_BREDR) | ||
| 154 | return -EINVAL; | ||
| 155 | |||
| 156 | if (chan->src_type != BDADDR_BREDR && la.l2_bdaddr_type == BDADDR_BREDR) | ||
| 157 | return -EINVAL; | ||
| 158 | |||
| 137 | err = l2cap_chan_connect(chan, la.l2_psm, __le16_to_cpu(la.l2_cid), | 159 | err = l2cap_chan_connect(chan, la.l2_psm, __le16_to_cpu(la.l2_cid), |
| 138 | &la.l2_bdaddr, la.l2_bdaddr_type); | 160 | &la.l2_bdaddr, la.l2_bdaddr_type); |
| 139 | if (err) | 161 | if (err) |
| @@ -265,12 +287,14 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, | |||
| 265 | 287 | ||
| 266 | if (peer) { | 288 | if (peer) { |
| 267 | la->l2_psm = chan->psm; | 289 | la->l2_psm = chan->psm; |
| 268 | bacpy(&la->l2_bdaddr, &bt_sk(sk)->dst); | 290 | bacpy(&la->l2_bdaddr, &chan->dst); |
| 269 | la->l2_cid = cpu_to_le16(chan->dcid); | 291 | la->l2_cid = cpu_to_le16(chan->dcid); |
| 292 | la->l2_bdaddr_type = chan->dst_type; | ||
| 270 | } else { | 293 | } else { |
| 271 | la->l2_psm = chan->sport; | 294 | la->l2_psm = chan->sport; |
| 272 | bacpy(&la->l2_bdaddr, &bt_sk(sk)->src); | 295 | bacpy(&la->l2_bdaddr, &chan->src); |
| 273 | la->l2_cid = cpu_to_le16(chan->scid); | 296 | la->l2_cid = cpu_to_le16(chan->scid); |
| 297 | la->l2_bdaddr_type = chan->src_type; | ||
| 274 | } | 298 | } |
| 275 | 299 | ||
| 276 | return 0; | 300 | return 0; |
| @@ -660,10 +684,13 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, | |||
| 660 | break; | 684 | break; |
| 661 | } | 685 | } |
| 662 | 686 | ||
| 663 | if (opt) | 687 | if (opt) { |
| 664 | set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags); | 688 | set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags); |
| 665 | else | 689 | set_bit(FLAG_DEFER_SETUP, &chan->flags); |
| 690 | } else { | ||
| 666 | clear_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags); | 691 | clear_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags); |
| 692 | clear_bit(FLAG_DEFER_SETUP, &chan->flags); | ||
| 693 | } | ||
| 667 | break; | 694 | break; |
| 668 | 695 | ||
| 669 | case BT_FLUSHABLE: | 696 | case BT_FLUSHABLE: |
| @@ -678,7 +705,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, | |||
| 678 | } | 705 | } |
| 679 | 706 | ||
| 680 | if (opt == BT_FLUSHABLE_OFF) { | 707 | if (opt == BT_FLUSHABLE_OFF) { |
| 681 | struct l2cap_conn *conn = chan->conn; | 708 | conn = chan->conn; |
| 682 | /* proceed further only when we have l2cap_conn and | 709 | /* proceed further only when we have l2cap_conn and |
| 683 | No Flush support in the LM */ | 710 | No Flush support in the LM */ |
| 684 | if (!conn || !lmp_no_flush_capable(conn->hcon->hdev)) { | 711 | if (!conn || !lmp_no_flush_capable(conn->hcon->hdev)) { |
| @@ -964,13 +991,12 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan) | |||
| 964 | 991 | ||
| 965 | static int l2cap_sock_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) | 992 | static int l2cap_sock_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) |
| 966 | { | 993 | { |
| 967 | int err; | ||
| 968 | struct sock *sk = chan->data; | 994 | struct sock *sk = chan->data; |
| 969 | struct l2cap_pinfo *pi = l2cap_pi(sk); | 995 | int err; |
| 970 | 996 | ||
| 971 | lock_sock(sk); | 997 | lock_sock(sk); |
| 972 | 998 | ||
| 973 | if (pi->rx_busy_skb) { | 999 | if (l2cap_pi(sk)->rx_busy_skb) { |
| 974 | err = -ENOMEM; | 1000 | err = -ENOMEM; |
| 975 | goto done; | 1001 | goto done; |
| 976 | } | 1002 | } |
| @@ -986,9 +1012,9 @@ static int l2cap_sock_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) | |||
| 986 | * acked and reassembled until there is buffer space | 1012 | * acked and reassembled until there is buffer space |
| 987 | * available. | 1013 | * available. |
| 988 | */ | 1014 | */ |
| 989 | if (err < 0 && pi->chan->mode == L2CAP_MODE_ERTM) { | 1015 | if (err < 0 && chan->mode == L2CAP_MODE_ERTM) { |
| 990 | pi->rx_busy_skb = skb; | 1016 | l2cap_pi(sk)->rx_busy_skb = skb; |
| 991 | l2cap_chan_busy(pi->chan, 1); | 1017 | l2cap_chan_busy(chan, 1); |
| 992 | err = 0; | 1018 | err = 0; |
| 993 | } | 1019 | } |
| 994 | 1020 | ||
| @@ -1098,6 +1124,14 @@ static void l2cap_sock_defer_cb(struct l2cap_chan *chan) | |||
| 1098 | parent->sk_data_ready(parent, 0); | 1124 | parent->sk_data_ready(parent, 0); |
| 1099 | } | 1125 | } |
| 1100 | 1126 | ||
| 1127 | static void l2cap_sock_resume_cb(struct l2cap_chan *chan) | ||
| 1128 | { | ||
| 1129 | struct sock *sk = chan->data; | ||
| 1130 | |||
| 1131 | clear_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags); | ||
| 1132 | sk->sk_state_change(sk); | ||
| 1133 | } | ||
| 1134 | |||
| 1101 | static struct l2cap_ops l2cap_chan_ops = { | 1135 | static struct l2cap_ops l2cap_chan_ops = { |
| 1102 | .name = "L2CAP Socket Interface", | 1136 | .name = "L2CAP Socket Interface", |
| 1103 | .new_connection = l2cap_sock_new_connection_cb, | 1137 | .new_connection = l2cap_sock_new_connection_cb, |
| @@ -1107,6 +1141,7 @@ static struct l2cap_ops l2cap_chan_ops = { | |||
| 1107 | .state_change = l2cap_sock_state_change_cb, | 1141 | .state_change = l2cap_sock_state_change_cb, |
| 1108 | .ready = l2cap_sock_ready_cb, | 1142 | .ready = l2cap_sock_ready_cb, |
| 1109 | .defer = l2cap_sock_defer_cb, | 1143 | .defer = l2cap_sock_defer_cb, |
| 1144 | .resume = l2cap_sock_resume_cb, | ||
| 1110 | .alloc_skb = l2cap_sock_alloc_skb_cb, | 1145 | .alloc_skb = l2cap_sock_alloc_skb_cb, |
| 1111 | }; | 1146 | }; |
| 1112 | 1147 | ||
| @@ -1116,6 +1151,7 @@ static void l2cap_sock_destruct(struct sock *sk) | |||
| 1116 | 1151 | ||
| 1117 | if (l2cap_pi(sk)->chan) | 1152 | if (l2cap_pi(sk)->chan) |
| 1118 | l2cap_chan_put(l2cap_pi(sk)->chan); | 1153 | l2cap_chan_put(l2cap_pi(sk)->chan); |
| 1154 | |||
| 1119 | if (l2cap_pi(sk)->rx_busy_skb) { | 1155 | if (l2cap_pi(sk)->rx_busy_skb) { |
| 1120 | kfree_skb(l2cap_pi(sk)->rx_busy_skb); | 1156 | kfree_skb(l2cap_pi(sk)->rx_busy_skb); |
| 1121 | l2cap_pi(sk)->rx_busy_skb = NULL; | 1157 | l2cap_pi(sk)->rx_busy_skb = NULL; |
| @@ -1125,10 +1161,22 @@ static void l2cap_sock_destruct(struct sock *sk) | |||
| 1125 | skb_queue_purge(&sk->sk_write_queue); | 1161 | skb_queue_purge(&sk->sk_write_queue); |
| 1126 | } | 1162 | } |
| 1127 | 1163 | ||
| 1164 | static void l2cap_skb_msg_name(struct sk_buff *skb, void *msg_name, | ||
| 1165 | int *msg_namelen) | ||
| 1166 | { | ||
| 1167 | struct sockaddr_l2 *la = (struct sockaddr_l2 *) msg_name; | ||
| 1168 | |||
| 1169 | memset(la, 0, sizeof(struct sockaddr_l2)); | ||
| 1170 | la->l2_family = AF_BLUETOOTH; | ||
| 1171 | la->l2_psm = bt_cb(skb)->psm; | ||
| 1172 | bacpy(&la->l2_bdaddr, &bt_cb(skb)->bdaddr); | ||
| 1173 | |||
| 1174 | *msg_namelen = sizeof(struct sockaddr_l2); | ||
| 1175 | } | ||
| 1176 | |||
| 1128 | static void l2cap_sock_init(struct sock *sk, struct sock *parent) | 1177 | static void l2cap_sock_init(struct sock *sk, struct sock *parent) |
| 1129 | { | 1178 | { |
| 1130 | struct l2cap_pinfo *pi = l2cap_pi(sk); | 1179 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; |
| 1131 | struct l2cap_chan *chan = pi->chan; | ||
| 1132 | 1180 | ||
| 1133 | BT_DBG("sk %p", sk); | 1181 | BT_DBG("sk %p", sk); |
| 1134 | 1182 | ||
| @@ -1152,13 +1200,13 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) | |||
| 1152 | 1200 | ||
| 1153 | security_sk_clone(parent, sk); | 1201 | security_sk_clone(parent, sk); |
| 1154 | } else { | 1202 | } else { |
| 1155 | |||
| 1156 | switch (sk->sk_type) { | 1203 | switch (sk->sk_type) { |
| 1157 | case SOCK_RAW: | 1204 | case SOCK_RAW: |
| 1158 | chan->chan_type = L2CAP_CHAN_RAW; | 1205 | chan->chan_type = L2CAP_CHAN_RAW; |
| 1159 | break; | 1206 | break; |
| 1160 | case SOCK_DGRAM: | 1207 | case SOCK_DGRAM: |
| 1161 | chan->chan_type = L2CAP_CHAN_CONN_LESS; | 1208 | chan->chan_type = L2CAP_CHAN_CONN_LESS; |
| 1209 | bt_sk(sk)->skb_msg_name = l2cap_skb_msg_name; | ||
| 1162 | break; | 1210 | break; |
| 1163 | case SOCK_SEQPACKET: | 1211 | case SOCK_SEQPACKET: |
| 1164 | case SOCK_STREAM: | 1212 | case SOCK_STREAM: |
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 16125ff918f1..861e389f4b4c 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
| @@ -30,7 +30,8 @@ | |||
| 30 | #include <net/bluetooth/bluetooth.h> | 30 | #include <net/bluetooth/bluetooth.h> |
| 31 | #include <net/bluetooth/hci_core.h> | 31 | #include <net/bluetooth/hci_core.h> |
| 32 | #include <net/bluetooth/mgmt.h> | 32 | #include <net/bluetooth/mgmt.h> |
| 33 | #include <net/bluetooth/smp.h> | 33 | |
| 34 | #include "smp.h" | ||
| 34 | 35 | ||
| 35 | #define MGMT_VERSION 1 | 36 | #define MGMT_VERSION 1 |
| 36 | #define MGMT_REVISION 4 | 37 | #define MGMT_REVISION 4 |
| @@ -77,6 +78,7 @@ static const u16 mgmt_commands[] = { | |||
| 77 | MGMT_OP_SET_ADVERTISING, | 78 | MGMT_OP_SET_ADVERTISING, |
| 78 | MGMT_OP_SET_BREDR, | 79 | MGMT_OP_SET_BREDR, |
| 79 | MGMT_OP_SET_STATIC_ADDRESS, | 80 | MGMT_OP_SET_STATIC_ADDRESS, |
| 81 | MGMT_OP_SET_SCAN_PARAMS, | ||
| 80 | }; | 82 | }; |
| 81 | 83 | ||
| 82 | static const u16 mgmt_events[] = { | 84 | static const u16 mgmt_events[] = { |
| @@ -182,11 +184,6 @@ static u8 mgmt_status_table[] = { | |||
| 182 | MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */ | 184 | MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */ |
| 183 | }; | 185 | }; |
| 184 | 186 | ||
| 185 | bool mgmt_valid_hdev(struct hci_dev *hdev) | ||
| 186 | { | ||
| 187 | return hdev->dev_type == HCI_BREDR; | ||
| 188 | } | ||
| 189 | |||
| 190 | static u8 mgmt_status(u8 hci_status) | 187 | static u8 mgmt_status(u8 hci_status) |
| 191 | { | 188 | { |
| 192 | if (hci_status < ARRAY_SIZE(mgmt_status_table)) | 189 | if (hci_status < ARRAY_SIZE(mgmt_status_table)) |
| @@ -322,10 +319,8 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data, | |||
| 322 | 319 | ||
| 323 | count = 0; | 320 | count = 0; |
| 324 | list_for_each_entry(d, &hci_dev_list, list) { | 321 | list_for_each_entry(d, &hci_dev_list, list) { |
| 325 | if (!mgmt_valid_hdev(d)) | 322 | if (d->dev_type == HCI_BREDR) |
| 326 | continue; | 323 | count++; |
| 327 | |||
| 328 | count++; | ||
| 329 | } | 324 | } |
| 330 | 325 | ||
| 331 | rp_len = sizeof(*rp) + (2 * count); | 326 | rp_len = sizeof(*rp) + (2 * count); |
| @@ -343,11 +338,10 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data, | |||
| 343 | if (test_bit(HCI_USER_CHANNEL, &d->dev_flags)) | 338 | if (test_bit(HCI_USER_CHANNEL, &d->dev_flags)) |
| 344 | continue; | 339 | continue; |
| 345 | 340 | ||
| 346 | if (!mgmt_valid_hdev(d)) | 341 | if (d->dev_type == HCI_BREDR) { |
| 347 | continue; | 342 | rp->index[count++] = cpu_to_le16(d->id); |
| 348 | 343 | BT_DBG("Added hci%u", d->id); | |
| 349 | rp->index[count++] = cpu_to_le16(d->id); | 344 | } |
| 350 | BT_DBG("Added hci%u", d->id); | ||
| 351 | } | 345 | } |
| 352 | 346 | ||
| 353 | rp->num_controllers = cpu_to_le16(count); | 347 | rp->num_controllers = cpu_to_le16(count); |
| @@ -370,9 +364,6 @@ static u32 get_supported_settings(struct hci_dev *hdev) | |||
| 370 | settings |= MGMT_SETTING_POWERED; | 364 | settings |= MGMT_SETTING_POWERED; |
| 371 | settings |= MGMT_SETTING_PAIRABLE; | 365 | settings |= MGMT_SETTING_PAIRABLE; |
| 372 | 366 | ||
| 373 | if (lmp_ssp_capable(hdev)) | ||
| 374 | settings |= MGMT_SETTING_SSP; | ||
| 375 | |||
| 376 | if (lmp_bredr_capable(hdev)) { | 367 | if (lmp_bredr_capable(hdev)) { |
| 377 | settings |= MGMT_SETTING_CONNECTABLE; | 368 | settings |= MGMT_SETTING_CONNECTABLE; |
| 378 | if (hdev->hci_ver >= BLUETOOTH_VER_1_2) | 369 | if (hdev->hci_ver >= BLUETOOTH_VER_1_2) |
| @@ -380,7 +371,11 @@ static u32 get_supported_settings(struct hci_dev *hdev) | |||
| 380 | settings |= MGMT_SETTING_DISCOVERABLE; | 371 | settings |= MGMT_SETTING_DISCOVERABLE; |
| 381 | settings |= MGMT_SETTING_BREDR; | 372 | settings |= MGMT_SETTING_BREDR; |
| 382 | settings |= MGMT_SETTING_LINK_SECURITY; | 373 | settings |= MGMT_SETTING_LINK_SECURITY; |
| 383 | settings |= MGMT_SETTING_HS; | 374 | |
| 375 | if (lmp_ssp_capable(hdev)) { | ||
| 376 | settings |= MGMT_SETTING_SSP; | ||
| 377 | settings |= MGMT_SETTING_HS; | ||
| 378 | } | ||
| 384 | } | 379 | } |
| 385 | 380 | ||
| 386 | if (lmp_le_capable(hdev)) { | 381 | if (lmp_le_capable(hdev)) { |
| @@ -425,7 +420,7 @@ static u32 get_current_settings(struct hci_dev *hdev) | |||
| 425 | if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags)) | 420 | if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags)) |
| 426 | settings |= MGMT_SETTING_HS; | 421 | settings |= MGMT_SETTING_HS; |
| 427 | 422 | ||
| 428 | if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags)) | 423 | if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) |
| 429 | settings |= MGMT_SETTING_ADVERTISING; | 424 | settings |= MGMT_SETTING_ADVERTISING; |
| 430 | 425 | ||
| 431 | return settings; | 426 | return settings; |
| @@ -940,11 +935,52 @@ static u8 mgmt_le_support(struct hci_dev *hdev) | |||
| 940 | return MGMT_STATUS_SUCCESS; | 935 | return MGMT_STATUS_SUCCESS; |
| 941 | } | 936 | } |
| 942 | 937 | ||
| 938 | static void set_discoverable_complete(struct hci_dev *hdev, u8 status) | ||
| 939 | { | ||
| 940 | struct pending_cmd *cmd; | ||
| 941 | struct mgmt_mode *cp; | ||
| 942 | bool changed; | ||
| 943 | |||
| 944 | BT_DBG("status 0x%02x", status); | ||
| 945 | |||
| 946 | hci_dev_lock(hdev); | ||
| 947 | |||
| 948 | cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev); | ||
| 949 | if (!cmd) | ||
| 950 | goto unlock; | ||
| 951 | |||
| 952 | if (status) { | ||
| 953 | u8 mgmt_err = mgmt_status(status); | ||
| 954 | cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err); | ||
| 955 | goto remove_cmd; | ||
| 956 | } | ||
| 957 | |||
| 958 | cp = cmd->param; | ||
| 959 | if (cp->val) | ||
| 960 | changed = !test_and_set_bit(HCI_DISCOVERABLE, | ||
| 961 | &hdev->dev_flags); | ||
| 962 | else | ||
| 963 | changed = test_and_clear_bit(HCI_DISCOVERABLE, | ||
| 964 | &hdev->dev_flags); | ||
| 965 | |||
| 966 | send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev); | ||
| 967 | |||
| 968 | if (changed) | ||
| 969 | new_settings(hdev, cmd->sk); | ||
| 970 | |||
| 971 | remove_cmd: | ||
| 972 | mgmt_pending_remove(cmd); | ||
| 973 | |||
| 974 | unlock: | ||
| 975 | hci_dev_unlock(hdev); | ||
| 976 | } | ||
| 977 | |||
| 943 | static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data, | 978 | static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data, |
| 944 | u16 len) | 979 | u16 len) |
| 945 | { | 980 | { |
| 946 | struct mgmt_cp_set_discoverable *cp = data; | 981 | struct mgmt_cp_set_discoverable *cp = data; |
| 947 | struct pending_cmd *cmd; | 982 | struct pending_cmd *cmd; |
| 983 | struct hci_request req; | ||
| 948 | u16 timeout; | 984 | u16 timeout; |
| 949 | u8 scan, status; | 985 | u8 scan, status; |
| 950 | int err; | 986 | int err; |
| @@ -1026,6 +1062,8 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
| 1026 | goto failed; | 1062 | goto failed; |
| 1027 | } | 1063 | } |
| 1028 | 1064 | ||
| 1065 | hci_req_init(&req, hdev); | ||
| 1066 | |||
| 1029 | scan = SCAN_PAGE; | 1067 | scan = SCAN_PAGE; |
| 1030 | 1068 | ||
| 1031 | if (cp->val) | 1069 | if (cp->val) |
| @@ -1033,7 +1071,9 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
| 1033 | else | 1071 | else |
| 1034 | cancel_delayed_work(&hdev->discov_off); | 1072 | cancel_delayed_work(&hdev->discov_off); |
| 1035 | 1073 | ||
| 1036 | err = hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); | 1074 | hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); |
| 1075 | |||
| 1076 | err = hci_req_run(&req, set_discoverable_complete); | ||
| 1037 | if (err < 0) | 1077 | if (err < 0) |
| 1038 | mgmt_pending_remove(cmd); | 1078 | mgmt_pending_remove(cmd); |
| 1039 | 1079 | ||
| @@ -1077,9 +1117,58 @@ static void write_fast_connectable(struct hci_request *req, bool enable) | |||
| 1077 | hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type); | 1117 | hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type); |
| 1078 | } | 1118 | } |
| 1079 | 1119 | ||
| 1120 | static u8 get_adv_type(struct hci_dev *hdev) | ||
| 1121 | { | ||
| 1122 | struct pending_cmd *cmd; | ||
| 1123 | bool connectable; | ||
| 1124 | |||
| 1125 | /* If there's a pending mgmt command the flag will not yet have | ||
| 1126 | * it's final value, so check for this first. | ||
| 1127 | */ | ||
| 1128 | cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev); | ||
| 1129 | if (cmd) { | ||
| 1130 | struct mgmt_mode *cp = cmd->param; | ||
| 1131 | connectable = !!cp->val; | ||
| 1132 | } else { | ||
| 1133 | connectable = test_bit(HCI_CONNECTABLE, &hdev->dev_flags); | ||
| 1134 | } | ||
| 1135 | |||
| 1136 | return connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND; | ||
| 1137 | } | ||
| 1138 | |||
| 1139 | static void enable_advertising(struct hci_request *req) | ||
| 1140 | { | ||
| 1141 | struct hci_dev *hdev = req->hdev; | ||
| 1142 | struct hci_cp_le_set_adv_param cp; | ||
| 1143 | u8 enable = 0x01; | ||
| 1144 | |||
| 1145 | memset(&cp, 0, sizeof(cp)); | ||
| 1146 | cp.min_interval = __constant_cpu_to_le16(0x0800); | ||
| 1147 | cp.max_interval = __constant_cpu_to_le16(0x0800); | ||
| 1148 | cp.type = get_adv_type(hdev); | ||
| 1149 | if (bacmp(&hdev->bdaddr, BDADDR_ANY)) | ||
| 1150 | cp.own_address_type = ADDR_LE_DEV_PUBLIC; | ||
| 1151 | else | ||
| 1152 | cp.own_address_type = ADDR_LE_DEV_RANDOM; | ||
| 1153 | cp.channel_map = 0x07; | ||
| 1154 | |||
| 1155 | hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp); | ||
| 1156 | |||
| 1157 | hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable); | ||
| 1158 | } | ||
| 1159 | |||
| 1160 | static void disable_advertising(struct hci_request *req) | ||
| 1161 | { | ||
| 1162 | u8 enable = 0x00; | ||
| 1163 | |||
| 1164 | hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable); | ||
| 1165 | } | ||
| 1166 | |||
| 1080 | static void set_connectable_complete(struct hci_dev *hdev, u8 status) | 1167 | static void set_connectable_complete(struct hci_dev *hdev, u8 status) |
| 1081 | { | 1168 | { |
| 1082 | struct pending_cmd *cmd; | 1169 | struct pending_cmd *cmd; |
| 1170 | struct mgmt_mode *cp; | ||
| 1171 | bool changed; | ||
| 1083 | 1172 | ||
| 1084 | BT_DBG("status 0x%02x", status); | 1173 | BT_DBG("status 0x%02x", status); |
| 1085 | 1174 | ||
| @@ -1089,8 +1178,24 @@ static void set_connectable_complete(struct hci_dev *hdev, u8 status) | |||
| 1089 | if (!cmd) | 1178 | if (!cmd) |
| 1090 | goto unlock; | 1179 | goto unlock; |
| 1091 | 1180 | ||
| 1181 | if (status) { | ||
| 1182 | u8 mgmt_err = mgmt_status(status); | ||
| 1183 | cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err); | ||
| 1184 | goto remove_cmd; | ||
| 1185 | } | ||
| 1186 | |||
| 1187 | cp = cmd->param; | ||
| 1188 | if (cp->val) | ||
| 1189 | changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags); | ||
| 1190 | else | ||
| 1191 | changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags); | ||
| 1192 | |||
| 1092 | send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev); | 1193 | send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev); |
| 1093 | 1194 | ||
| 1195 | if (changed) | ||
| 1196 | new_settings(hdev, cmd->sk); | ||
| 1197 | |||
| 1198 | remove_cmd: | ||
| 1094 | mgmt_pending_remove(cmd); | 1199 | mgmt_pending_remove(cmd); |
| 1095 | 1200 | ||
| 1096 | unlock: | 1201 | unlock: |
| @@ -1103,15 +1208,15 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
| 1103 | struct mgmt_mode *cp = data; | 1208 | struct mgmt_mode *cp = data; |
| 1104 | struct pending_cmd *cmd; | 1209 | struct pending_cmd *cmd; |
| 1105 | struct hci_request req; | 1210 | struct hci_request req; |
| 1106 | u8 scan, status; | 1211 | u8 scan; |
| 1107 | int err; | 1212 | int err; |
| 1108 | 1213 | ||
| 1109 | BT_DBG("request for %s", hdev->name); | 1214 | BT_DBG("request for %s", hdev->name); |
| 1110 | 1215 | ||
| 1111 | status = mgmt_bredr_support(hdev); | 1216 | if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) && |
| 1112 | if (status) | 1217 | !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) |
| 1113 | return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE, | 1218 | return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE, |
| 1114 | status); | 1219 | MGMT_STATUS_REJECTED); |
| 1115 | 1220 | ||
| 1116 | if (cp->val != 0x00 && cp->val != 0x01) | 1221 | if (cp->val != 0x00 && cp->val != 0x01) |
| 1117 | return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE, | 1222 | return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE, |
| @@ -1149,30 +1254,29 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
| 1149 | goto failed; | 1254 | goto failed; |
| 1150 | } | 1255 | } |
| 1151 | 1256 | ||
| 1152 | if (!!cp->val == test_bit(HCI_PSCAN, &hdev->flags)) { | ||
| 1153 | err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev); | ||
| 1154 | goto failed; | ||
| 1155 | } | ||
| 1156 | |||
| 1157 | cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len); | 1257 | cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len); |
| 1158 | if (!cmd) { | 1258 | if (!cmd) { |
| 1159 | err = -ENOMEM; | 1259 | err = -ENOMEM; |
| 1160 | goto failed; | 1260 | goto failed; |
| 1161 | } | 1261 | } |
| 1162 | 1262 | ||
| 1163 | if (cp->val) { | 1263 | hci_req_init(&req, hdev); |
| 1164 | scan = SCAN_PAGE; | ||
| 1165 | } else { | ||
| 1166 | scan = 0; | ||
| 1167 | 1264 | ||
| 1168 | if (test_bit(HCI_ISCAN, &hdev->flags) && | 1265 | if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) && |
| 1169 | hdev->discov_timeout > 0) | 1266 | cp->val != test_bit(HCI_PSCAN, &hdev->flags)) { |
| 1170 | cancel_delayed_work(&hdev->discov_off); | ||
| 1171 | } | ||
| 1172 | 1267 | ||
| 1173 | hci_req_init(&req, hdev); | 1268 | if (cp->val) { |
| 1269 | scan = SCAN_PAGE; | ||
| 1270 | } else { | ||
| 1271 | scan = 0; | ||
| 1174 | 1272 | ||
| 1175 | hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); | 1273 | if (test_bit(HCI_ISCAN, &hdev->flags) && |
| 1274 | hdev->discov_timeout > 0) | ||
| 1275 | cancel_delayed_work(&hdev->discov_off); | ||
| 1276 | } | ||
| 1277 | |||
| 1278 | hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); | ||
| 1279 | } | ||
| 1176 | 1280 | ||
| 1177 | /* If we're going from non-connectable to connectable or | 1281 | /* If we're going from non-connectable to connectable or |
| 1178 | * vice-versa when fast connectable is enabled ensure that fast | 1282 | * vice-versa when fast connectable is enabled ensure that fast |
| @@ -1183,9 +1287,20 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
| 1183 | if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) | 1287 | if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) |
| 1184 | write_fast_connectable(&req, false); | 1288 | write_fast_connectable(&req, false); |
| 1185 | 1289 | ||
| 1290 | if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) && | ||
| 1291 | hci_conn_num(hdev, LE_LINK) == 0) { | ||
| 1292 | disable_advertising(&req); | ||
| 1293 | enable_advertising(&req); | ||
| 1294 | } | ||
| 1295 | |||
| 1186 | err = hci_req_run(&req, set_connectable_complete); | 1296 | err = hci_req_run(&req, set_connectable_complete); |
| 1187 | if (err < 0) | 1297 | if (err < 0) { |
| 1188 | mgmt_pending_remove(cmd); | 1298 | mgmt_pending_remove(cmd); |
| 1299 | if (err == -ENODATA) | ||
| 1300 | err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, | ||
| 1301 | hdev); | ||
| 1302 | goto failed; | ||
| 1303 | } | ||
| 1189 | 1304 | ||
| 1190 | failed: | 1305 | failed: |
| 1191 | hci_dev_unlock(hdev); | 1306 | hci_dev_unlock(hdev); |
| @@ -1196,6 +1311,7 @@ static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
| 1196 | u16 len) | 1311 | u16 len) |
| 1197 | { | 1312 | { |
| 1198 | struct mgmt_mode *cp = data; | 1313 | struct mgmt_mode *cp = data; |
| 1314 | bool changed; | ||
| 1199 | int err; | 1315 | int err; |
| 1200 | 1316 | ||
| 1201 | BT_DBG("request for %s", hdev->name); | 1317 | BT_DBG("request for %s", hdev->name); |
| @@ -1207,17 +1323,18 @@ static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
| 1207 | hci_dev_lock(hdev); | 1323 | hci_dev_lock(hdev); |
| 1208 | 1324 | ||
| 1209 | if (cp->val) | 1325 | if (cp->val) |
| 1210 | set_bit(HCI_PAIRABLE, &hdev->dev_flags); | 1326 | changed = !test_and_set_bit(HCI_PAIRABLE, &hdev->dev_flags); |
| 1211 | else | 1327 | else |
| 1212 | clear_bit(HCI_PAIRABLE, &hdev->dev_flags); | 1328 | changed = test_and_clear_bit(HCI_PAIRABLE, &hdev->dev_flags); |
| 1213 | 1329 | ||
| 1214 | err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev); | 1330 | err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev); |
| 1215 | if (err < 0) | 1331 | if (err < 0) |
| 1216 | goto failed; | 1332 | goto unlock; |
| 1217 | 1333 | ||
| 1218 | err = new_settings(hdev, sk); | 1334 | if (changed) |
| 1335 | err = new_settings(hdev, sk); | ||
| 1219 | 1336 | ||
| 1220 | failed: | 1337 | unlock: |
| 1221 | hci_dev_unlock(hdev); | 1338 | hci_dev_unlock(hdev); |
| 1222 | return err; | 1339 | return err; |
| 1223 | } | 1340 | } |
| @@ -1296,7 +1413,7 @@ static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
| 1296 | { | 1413 | { |
| 1297 | struct mgmt_mode *cp = data; | 1414 | struct mgmt_mode *cp = data; |
| 1298 | struct pending_cmd *cmd; | 1415 | struct pending_cmd *cmd; |
| 1299 | u8 val, status; | 1416 | u8 status; |
| 1300 | int err; | 1417 | int err; |
| 1301 | 1418 | ||
| 1302 | BT_DBG("request for %s", hdev->name); | 1419 | BT_DBG("request for %s", hdev->name); |
| @@ -1315,14 +1432,20 @@ static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
| 1315 | 1432 | ||
| 1316 | hci_dev_lock(hdev); | 1433 | hci_dev_lock(hdev); |
| 1317 | 1434 | ||
| 1318 | val = !!cp->val; | ||
| 1319 | |||
| 1320 | if (!hdev_is_powered(hdev)) { | 1435 | if (!hdev_is_powered(hdev)) { |
| 1321 | bool changed = false; | 1436 | bool changed; |
| 1322 | 1437 | ||
| 1323 | if (val != test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) { | 1438 | if (cp->val) { |
| 1324 | change_bit(HCI_SSP_ENABLED, &hdev->dev_flags); | 1439 | changed = !test_and_set_bit(HCI_SSP_ENABLED, |
| 1325 | changed = true; | 1440 | &hdev->dev_flags); |
| 1441 | } else { | ||
| 1442 | changed = test_and_clear_bit(HCI_SSP_ENABLED, | ||
| 1443 | &hdev->dev_flags); | ||
| 1444 | if (!changed) | ||
| 1445 | changed = test_and_clear_bit(HCI_HS_ENABLED, | ||
| 1446 | &hdev->dev_flags); | ||
| 1447 | else | ||
| 1448 | clear_bit(HCI_HS_ENABLED, &hdev->dev_flags); | ||
| 1326 | } | 1449 | } |
| 1327 | 1450 | ||
| 1328 | err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev); | 1451 | err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev); |
| @@ -1335,13 +1458,14 @@ static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
| 1335 | goto failed; | 1458 | goto failed; |
| 1336 | } | 1459 | } |
| 1337 | 1460 | ||
| 1338 | if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev)) { | 1461 | if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) || |
| 1462 | mgmt_pending_find(MGMT_OP_SET_HS, hdev)) { | ||
| 1339 | err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, | 1463 | err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, |
| 1340 | MGMT_STATUS_BUSY); | 1464 | MGMT_STATUS_BUSY); |
| 1341 | goto failed; | 1465 | goto failed; |
| 1342 | } | 1466 | } |
| 1343 | 1467 | ||
| 1344 | if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) == val) { | 1468 | if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) { |
| 1345 | err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev); | 1469 | err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev); |
| 1346 | goto failed; | 1470 | goto failed; |
| 1347 | } | 1471 | } |
| @@ -1352,7 +1476,7 @@ static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
| 1352 | goto failed; | 1476 | goto failed; |
| 1353 | } | 1477 | } |
| 1354 | 1478 | ||
| 1355 | err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, sizeof(val), &val); | 1479 | err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val); |
| 1356 | if (err < 0) { | 1480 | if (err < 0) { |
| 1357 | mgmt_pending_remove(cmd); | 1481 | mgmt_pending_remove(cmd); |
| 1358 | goto failed; | 1482 | goto failed; |
| @@ -1376,6 +1500,14 @@ static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
| 1376 | if (status) | 1500 | if (status) |
| 1377 | return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status); | 1501 | return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status); |
| 1378 | 1502 | ||
| 1503 | if (!lmp_ssp_capable(hdev)) | ||
| 1504 | return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, | ||
| 1505 | MGMT_STATUS_NOT_SUPPORTED); | ||
| 1506 | |||
| 1507 | if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) | ||
| 1508 | return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, | ||
| 1509 | MGMT_STATUS_REJECTED); | ||
| 1510 | |||
| 1379 | if (cp->val != 0x00 && cp->val != 0x01) | 1511 | if (cp->val != 0x00 && cp->val != 0x01) |
| 1380 | return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, | 1512 | return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, |
| 1381 | MGMT_STATUS_INVALID_PARAMS); | 1513 | MGMT_STATUS_INVALID_PARAMS); |
| @@ -1463,8 +1595,8 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
| 1463 | changed = true; | 1595 | changed = true; |
| 1464 | } | 1596 | } |
| 1465 | 1597 | ||
| 1466 | if (!val && test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags)) { | 1598 | if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) { |
| 1467 | clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags); | 1599 | clear_bit(HCI_ADVERTISING, &hdev->dev_flags); |
| 1468 | changed = true; | 1600 | changed = true; |
| 1469 | } | 1601 | } |
| 1470 | 1602 | ||
| @@ -1500,8 +1632,8 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
| 1500 | 1632 | ||
| 1501 | hci_req_init(&req, hdev); | 1633 | hci_req_init(&req, hdev); |
| 1502 | 1634 | ||
| 1503 | if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags) && !val) | 1635 | if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) && !val) |
| 1504 | hci_req_add(&req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(val), &val); | 1636 | disable_advertising(&req); |
| 1505 | 1637 | ||
| 1506 | hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp), | 1638 | hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp), |
| 1507 | &hci_cp); | 1639 | &hci_cp); |
| @@ -2888,7 +3020,7 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, | |||
| 2888 | goto failed; | 3020 | goto failed; |
| 2889 | } | 3021 | } |
| 2890 | 3022 | ||
| 2891 | if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags)) { | 3023 | if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) { |
| 2892 | err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, | 3024 | err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, |
| 2893 | MGMT_STATUS_REJECTED); | 3025 | MGMT_STATUS_REJECTED); |
| 2894 | mgmt_pending_remove(cmd); | 3026 | mgmt_pending_remove(cmd); |
| @@ -2906,6 +3038,10 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, | |||
| 2906 | param_cp.type = LE_SCAN_ACTIVE; | 3038 | param_cp.type = LE_SCAN_ACTIVE; |
| 2907 | param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT); | 3039 | param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT); |
| 2908 | param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN); | 3040 | param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN); |
| 3041 | if (bacmp(&hdev->bdaddr, BDADDR_ANY)) | ||
| 3042 | param_cp.own_address_type = ADDR_LE_DEV_PUBLIC; | ||
| 3043 | else | ||
| 3044 | param_cp.own_address_type = ADDR_LE_DEV_RANDOM; | ||
| 2909 | hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp), | 3045 | hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp), |
| 2910 | ¶m_cp); | 3046 | ¶m_cp); |
| 2911 | 3047 | ||
| @@ -3214,7 +3350,8 @@ static void set_advertising_complete(struct hci_dev *hdev, u8 status) | |||
| 3214 | sock_put(match.sk); | 3350 | sock_put(match.sk); |
| 3215 | } | 3351 | } |
| 3216 | 3352 | ||
| 3217 | static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | 3353 | static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data, |
| 3354 | u16 len) | ||
| 3218 | { | 3355 | { |
| 3219 | struct mgmt_mode *cp = data; | 3356 | struct mgmt_mode *cp = data; |
| 3220 | struct pending_cmd *cmd; | 3357 | struct pending_cmd *cmd; |
| @@ -3236,13 +3373,19 @@ static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data, u1 | |||
| 3236 | hci_dev_lock(hdev); | 3373 | hci_dev_lock(hdev); |
| 3237 | 3374 | ||
| 3238 | val = !!cp->val; | 3375 | val = !!cp->val; |
| 3239 | enabled = test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags); | 3376 | enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags); |
| 3240 | 3377 | ||
| 3241 | if (!hdev_is_powered(hdev) || val == enabled) { | 3378 | /* The following conditions are ones which mean that we should |
| 3379 | * not do any HCI communication but directly send a mgmt | ||
| 3380 | * response to user space (after toggling the flag if | ||
| 3381 | * necessary). | ||
| 3382 | */ | ||
| 3383 | if (!hdev_is_powered(hdev) || val == enabled || | ||
| 3384 | hci_conn_num(hdev, LE_LINK) > 0) { | ||
| 3242 | bool changed = false; | 3385 | bool changed = false; |
| 3243 | 3386 | ||
| 3244 | if (val != test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags)) { | 3387 | if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) { |
| 3245 | change_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags); | 3388 | change_bit(HCI_ADVERTISING, &hdev->dev_flags); |
| 3246 | changed = true; | 3389 | changed = true; |
| 3247 | } | 3390 | } |
| 3248 | 3391 | ||
| @@ -3271,7 +3414,10 @@ static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data, u1 | |||
| 3271 | 3414 | ||
| 3272 | hci_req_init(&req, hdev); | 3415 | hci_req_init(&req, hdev); |
| 3273 | 3416 | ||
| 3274 | hci_req_add(&req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(val), &val); | 3417 | if (val) |
| 3418 | enable_advertising(&req); | ||
| 3419 | else | ||
| 3420 | disable_advertising(&req); | ||
| 3275 | 3421 | ||
| 3276 | err = hci_req_run(&req, set_advertising_complete); | 3422 | err = hci_req_run(&req, set_advertising_complete); |
| 3277 | if (err < 0) | 3423 | if (err < 0) |
| @@ -3322,6 +3468,47 @@ static int set_static_address(struct sock *sk, struct hci_dev *hdev, | |||
| 3322 | return err; | 3468 | return err; |
| 3323 | } | 3469 | } |
| 3324 | 3470 | ||
| 3471 | static int set_scan_params(struct sock *sk, struct hci_dev *hdev, | ||
| 3472 | void *data, u16 len) | ||
| 3473 | { | ||
| 3474 | struct mgmt_cp_set_scan_params *cp = data; | ||
| 3475 | __u16 interval, window; | ||
| 3476 | int err; | ||
| 3477 | |||
| 3478 | BT_DBG("%s", hdev->name); | ||
| 3479 | |||
| 3480 | if (!lmp_le_capable(hdev)) | ||
| 3481 | return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, | ||
| 3482 | MGMT_STATUS_NOT_SUPPORTED); | ||
| 3483 | |||
| 3484 | interval = __le16_to_cpu(cp->interval); | ||
| 3485 | |||
| 3486 | if (interval < 0x0004 || interval > 0x4000) | ||
| 3487 | return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, | ||
| 3488 | MGMT_STATUS_INVALID_PARAMS); | ||
| 3489 | |||
| 3490 | window = __le16_to_cpu(cp->window); | ||
| 3491 | |||
| 3492 | if (window < 0x0004 || window > 0x4000) | ||
| 3493 | return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, | ||
| 3494 | MGMT_STATUS_INVALID_PARAMS); | ||
| 3495 | |||
| 3496 | if (window > interval) | ||
| 3497 | return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, | ||
| 3498 | MGMT_STATUS_INVALID_PARAMS); | ||
| 3499 | |||
| 3500 | hci_dev_lock(hdev); | ||
| 3501 | |||
| 3502 | hdev->le_scan_interval = interval; | ||
| 3503 | hdev->le_scan_window = window; | ||
| 3504 | |||
| 3505 | err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0); | ||
| 3506 | |||
| 3507 | hci_dev_unlock(hdev); | ||
| 3508 | |||
| 3509 | return err; | ||
| 3510 | } | ||
| 3511 | |||
| 3325 | static void fast_connectable_complete(struct hci_dev *hdev, u8 status) | 3512 | static void fast_connectable_complete(struct hci_dev *hdev, u8 status) |
| 3326 | { | 3513 | { |
| 3327 | struct pending_cmd *cmd; | 3514 | struct pending_cmd *cmd; |
| @@ -3420,6 +3607,26 @@ unlock: | |||
| 3420 | return err; | 3607 | return err; |
| 3421 | } | 3608 | } |
| 3422 | 3609 | ||
| 3610 | static void set_bredr_scan(struct hci_request *req) | ||
| 3611 | { | ||
| 3612 | struct hci_dev *hdev = req->hdev; | ||
| 3613 | u8 scan = 0; | ||
| 3614 | |||
| 3615 | /* Ensure that fast connectable is disabled. This function will | ||
| 3616 | * not do anything if the page scan parameters are already what | ||
| 3617 | * they should be. | ||
| 3618 | */ | ||
| 3619 | write_fast_connectable(req, false); | ||
| 3620 | |||
| 3621 | if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) | ||
| 3622 | scan |= SCAN_PAGE; | ||
| 3623 | if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) | ||
| 3624 | scan |= SCAN_INQUIRY; | ||
| 3625 | |||
| 3626 | if (scan) | ||
| 3627 | hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); | ||
| 3628 | } | ||
| 3629 | |||
| 3423 | static void set_bredr_complete(struct hci_dev *hdev, u8 status) | 3630 | static void set_bredr_complete(struct hci_dev *hdev, u8 status) |
| 3424 | { | 3631 | { |
| 3425 | struct pending_cmd *cmd; | 3632 | struct pending_cmd *cmd; |
| @@ -3482,7 +3689,6 @@ static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
| 3482 | 3689 | ||
| 3483 | if (!hdev_is_powered(hdev)) { | 3690 | if (!hdev_is_powered(hdev)) { |
| 3484 | if (!cp->val) { | 3691 | if (!cp->val) { |
| 3485 | clear_bit(HCI_CONNECTABLE, &hdev->dev_flags); | ||
| 3486 | clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags); | 3692 | clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags); |
| 3487 | clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags); | 3693 | clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags); |
| 3488 | clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags); | 3694 | clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags); |
| @@ -3525,7 +3731,12 @@ static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
| 3525 | set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags); | 3731 | set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags); |
| 3526 | 3732 | ||
| 3527 | hci_req_init(&req, hdev); | 3733 | hci_req_init(&req, hdev); |
| 3734 | |||
| 3735 | if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) | ||
| 3736 | set_bredr_scan(&req); | ||
| 3737 | |||
| 3528 | hci_update_ad(&req); | 3738 | hci_update_ad(&req); |
| 3739 | |||
| 3529 | err = hci_req_run(&req, set_bredr_complete); | 3740 | err = hci_req_run(&req, set_bredr_complete); |
| 3530 | if (err < 0) | 3741 | if (err < 0) |
| 3531 | mgmt_pending_remove(cmd); | 3742 | mgmt_pending_remove(cmd); |
| @@ -3587,15 +3798,19 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev, | |||
| 3587 | 3798 | ||
| 3588 | for (i = 0; i < key_count; i++) { | 3799 | for (i = 0; i < key_count; i++) { |
| 3589 | struct mgmt_ltk_info *key = &cp->keys[i]; | 3800 | struct mgmt_ltk_info *key = &cp->keys[i]; |
| 3590 | u8 type; | 3801 | u8 type, addr_type; |
| 3802 | |||
| 3803 | if (key->addr.type == BDADDR_LE_PUBLIC) | ||
| 3804 | addr_type = ADDR_LE_DEV_PUBLIC; | ||
| 3805 | else | ||
| 3806 | addr_type = ADDR_LE_DEV_RANDOM; | ||
| 3591 | 3807 | ||
| 3592 | if (key->master) | 3808 | if (key->master) |
| 3593 | type = HCI_SMP_LTK; | 3809 | type = HCI_SMP_LTK; |
| 3594 | else | 3810 | else |
| 3595 | type = HCI_SMP_LTK_SLAVE; | 3811 | type = HCI_SMP_LTK_SLAVE; |
| 3596 | 3812 | ||
| 3597 | hci_add_ltk(hdev, &key->addr.bdaddr, | 3813 | hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, |
| 3598 | bdaddr_to_le(key->addr.type), | ||
| 3599 | type, 0, key->authenticated, key->val, | 3814 | type, 0, key->authenticated, key->val, |
| 3600 | key->enc_size, key->ediv, key->rand); | 3815 | key->enc_size, key->ediv, key->rand); |
| 3601 | } | 3816 | } |
| @@ -3658,6 +3873,7 @@ static const struct mgmt_handler { | |||
| 3658 | { set_advertising, false, MGMT_SETTING_SIZE }, | 3873 | { set_advertising, false, MGMT_SETTING_SIZE }, |
| 3659 | { set_bredr, false, MGMT_SETTING_SIZE }, | 3874 | { set_bredr, false, MGMT_SETTING_SIZE }, |
| 3660 | { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE }, | 3875 | { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE }, |
| 3876 | { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE }, | ||
| 3661 | }; | 3877 | }; |
| 3662 | 3878 | ||
| 3663 | 3879 | ||
| @@ -3703,7 +3919,8 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) | |||
| 3703 | goto done; | 3919 | goto done; |
| 3704 | } | 3920 | } |
| 3705 | 3921 | ||
| 3706 | if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) { | 3922 | if (test_bit(HCI_SETUP, &hdev->dev_flags) || |
| 3923 | test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) { | ||
| 3707 | err = cmd_status(sk, index, opcode, | 3924 | err = cmd_status(sk, index, opcode, |
| 3708 | MGMT_STATUS_INVALID_INDEX); | 3925 | MGMT_STATUS_INVALID_INDEX); |
| 3709 | goto done; | 3926 | goto done; |
| @@ -3753,44 +3970,24 @@ done: | |||
| 3753 | return err; | 3970 | return err; |
| 3754 | } | 3971 | } |
| 3755 | 3972 | ||
| 3756 | int mgmt_index_added(struct hci_dev *hdev) | 3973 | void mgmt_index_added(struct hci_dev *hdev) |
| 3757 | { | 3974 | { |
| 3758 | if (!mgmt_valid_hdev(hdev)) | 3975 | if (hdev->dev_type != HCI_BREDR) |
| 3759 | return -ENOTSUPP; | 3976 | return; |
| 3760 | 3977 | ||
| 3761 | return mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL); | 3978 | mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL); |
| 3762 | } | 3979 | } |
| 3763 | 3980 | ||
| 3764 | int mgmt_index_removed(struct hci_dev *hdev) | 3981 | void mgmt_index_removed(struct hci_dev *hdev) |
| 3765 | { | 3982 | { |
| 3766 | u8 status = MGMT_STATUS_INVALID_INDEX; | 3983 | u8 status = MGMT_STATUS_INVALID_INDEX; |
| 3767 | 3984 | ||
| 3768 | if (!mgmt_valid_hdev(hdev)) | 3985 | if (hdev->dev_type != HCI_BREDR) |
| 3769 | return -ENOTSUPP; | 3986 | return; |
| 3770 | 3987 | ||
| 3771 | mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status); | 3988 | mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status); |
| 3772 | 3989 | ||
| 3773 | return mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL); | 3990 | mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL); |
| 3774 | } | ||
| 3775 | |||
| 3776 | static void set_bredr_scan(struct hci_request *req) | ||
| 3777 | { | ||
| 3778 | struct hci_dev *hdev = req->hdev; | ||
| 3779 | u8 scan = 0; | ||
| 3780 | |||
| 3781 | /* Ensure that fast connectable is disabled. This function will | ||
| 3782 | * not do anything if the page scan parameters are already what | ||
| 3783 | * they should be. | ||
| 3784 | */ | ||
| 3785 | write_fast_connectable(req, false); | ||
| 3786 | |||
| 3787 | if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) | ||
| 3788 | scan |= SCAN_PAGE; | ||
| 3789 | if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) | ||
| 3790 | scan |= SCAN_INQUIRY; | ||
| 3791 | |||
| 3792 | if (scan) | ||
| 3793 | hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); | ||
| 3794 | } | 3991 | } |
| 3795 | 3992 | ||
| 3796 | static void powered_complete(struct hci_dev *hdev, u8 status) | 3993 | static void powered_complete(struct hci_dev *hdev, u8 status) |
| @@ -3849,12 +4046,9 @@ static int powered_update_hci(struct hci_dev *hdev) | |||
| 3849 | if (bacmp(&hdev->static_addr, BDADDR_ANY)) | 4046 | if (bacmp(&hdev->static_addr, BDADDR_ANY)) |
| 3850 | hci_req_add(&req, HCI_OP_LE_SET_RANDOM_ADDR, 6, | 4047 | hci_req_add(&req, HCI_OP_LE_SET_RANDOM_ADDR, 6, |
| 3851 | &hdev->static_addr); | 4048 | &hdev->static_addr); |
| 3852 | } | ||
| 3853 | |||
| 3854 | if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags)) { | ||
| 3855 | u8 adv = 0x01; | ||
| 3856 | 4049 | ||
| 3857 | hci_req_add(&req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(adv), &adv); | 4050 | if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) |
| 4051 | enable_advertising(&req); | ||
| 3858 | } | 4052 | } |
| 3859 | 4053 | ||
| 3860 | link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags); | 4054 | link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags); |
| @@ -3908,33 +4102,37 @@ new_settings: | |||
| 3908 | return err; | 4102 | return err; |
| 3909 | } | 4103 | } |
| 3910 | 4104 | ||
| 3911 | int mgmt_set_powered_failed(struct hci_dev *hdev, int err) | 4105 | void mgmt_set_powered_failed(struct hci_dev *hdev, int err) |
| 3912 | { | 4106 | { |
| 3913 | struct pending_cmd *cmd; | 4107 | struct pending_cmd *cmd; |
| 3914 | u8 status; | 4108 | u8 status; |
| 3915 | 4109 | ||
| 3916 | cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev); | 4110 | cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev); |
| 3917 | if (!cmd) | 4111 | if (!cmd) |
| 3918 | return -ENOENT; | 4112 | return; |
| 3919 | 4113 | ||
| 3920 | if (err == -ERFKILL) | 4114 | if (err == -ERFKILL) |
| 3921 | status = MGMT_STATUS_RFKILLED; | 4115 | status = MGMT_STATUS_RFKILLED; |
| 3922 | else | 4116 | else |
| 3923 | status = MGMT_STATUS_FAILED; | 4117 | status = MGMT_STATUS_FAILED; |
| 3924 | 4118 | ||
| 3925 | err = cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status); | 4119 | cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status); |
| 3926 | 4120 | ||
| 3927 | mgmt_pending_remove(cmd); | 4121 | mgmt_pending_remove(cmd); |
| 3928 | |||
| 3929 | return err; | ||
| 3930 | } | 4122 | } |
| 3931 | 4123 | ||
| 3932 | int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable) | 4124 | int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable) |
| 3933 | { | 4125 | { |
| 3934 | struct cmd_lookup match = { NULL, hdev }; | ||
| 3935 | bool changed = false; | 4126 | bool changed = false; |
| 3936 | int err = 0; | 4127 | int err = 0; |
| 3937 | 4128 | ||
| 4129 | /* Nothing needed here if there's a pending command since that | ||
| 4130 | * commands request completion callback takes care of everything | ||
| 4131 | * necessary. | ||
| 4132 | */ | ||
| 4133 | if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev)) | ||
| 4134 | return 0; | ||
| 4135 | |||
| 3938 | if (discoverable) { | 4136 | if (discoverable) { |
| 3939 | if (!test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) | 4137 | if (!test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) |
| 3940 | changed = true; | 4138 | changed = true; |
| @@ -3943,24 +4141,24 @@ int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable) | |||
| 3943 | changed = true; | 4141 | changed = true; |
| 3944 | } | 4142 | } |
| 3945 | 4143 | ||
| 3946 | mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev, settings_rsp, | ||
| 3947 | &match); | ||
| 3948 | |||
| 3949 | if (changed) | 4144 | if (changed) |
| 3950 | err = new_settings(hdev, match.sk); | 4145 | err = new_settings(hdev, NULL); |
| 3951 | |||
| 3952 | if (match.sk) | ||
| 3953 | sock_put(match.sk); | ||
| 3954 | 4146 | ||
| 3955 | return err; | 4147 | return err; |
| 3956 | } | 4148 | } |
| 3957 | 4149 | ||
| 3958 | int mgmt_connectable(struct hci_dev *hdev, u8 connectable) | 4150 | int mgmt_connectable(struct hci_dev *hdev, u8 connectable) |
| 3959 | { | 4151 | { |
| 3960 | struct pending_cmd *cmd; | ||
| 3961 | bool changed = false; | 4152 | bool changed = false; |
| 3962 | int err = 0; | 4153 | int err = 0; |
| 3963 | 4154 | ||
| 4155 | /* Nothing needed here if there's a pending command since that | ||
| 4156 | * commands request completion callback takes care of everything | ||
| 4157 | * necessary. | ||
| 4158 | */ | ||
| 4159 | if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) | ||
| 4160 | return 0; | ||
| 4161 | |||
| 3964 | if (connectable) { | 4162 | if (connectable) { |
| 3965 | if (!test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags)) | 4163 | if (!test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags)) |
| 3966 | changed = true; | 4164 | changed = true; |
| @@ -3969,10 +4167,8 @@ int mgmt_connectable(struct hci_dev *hdev, u8 connectable) | |||
| 3969 | changed = true; | 4167 | changed = true; |
| 3970 | } | 4168 | } |
| 3971 | 4169 | ||
| 3972 | cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev); | ||
| 3973 | |||
| 3974 | if (changed) | 4170 | if (changed) |
| 3975 | err = new_settings(hdev, cmd ? cmd->sk : NULL); | 4171 | err = new_settings(hdev, NULL); |
| 3976 | 4172 | ||
| 3977 | return err; | 4173 | return err; |
| 3978 | } | 4174 | } |
| @@ -4032,9 +4228,9 @@ int mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent) | |||
| 4032 | NULL); | 4228 | NULL); |
| 4033 | } | 4229 | } |
| 4034 | 4230 | ||
| 4035 | int mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | 4231 | void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, |
| 4036 | u8 addr_type, u32 flags, u8 *name, u8 name_len, | 4232 | u8 addr_type, u32 flags, u8 *name, u8 name_len, |
| 4037 | u8 *dev_class) | 4233 | u8 *dev_class) |
| 4038 | { | 4234 | { |
| 4039 | char buf[512]; | 4235 | char buf[512]; |
| 4040 | struct mgmt_ev_device_connected *ev = (void *) buf; | 4236 | struct mgmt_ev_device_connected *ev = (void *) buf; |
| @@ -4055,8 +4251,8 @@ int mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | |||
| 4055 | 4251 | ||
| 4056 | ev->eir_len = cpu_to_le16(eir_len); | 4252 | ev->eir_len = cpu_to_le16(eir_len); |
| 4057 | 4253 | ||
| 4058 | return mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf, | 4254 | mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf, |
| 4059 | sizeof(*ev) + eir_len, NULL); | 4255 | sizeof(*ev) + eir_len, NULL); |
| 4060 | } | 4256 | } |
| 4061 | 4257 | ||
| 4062 | static void disconnect_rsp(struct pending_cmd *cmd, void *data) | 4258 | static void disconnect_rsp(struct pending_cmd *cmd, void *data) |
| @@ -4094,12 +4290,11 @@ static void unpair_device_rsp(struct pending_cmd *cmd, void *data) | |||
| 4094 | mgmt_pending_remove(cmd); | 4290 | mgmt_pending_remove(cmd); |
| 4095 | } | 4291 | } |
| 4096 | 4292 | ||
| 4097 | int mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, | 4293 | void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, |
| 4098 | u8 link_type, u8 addr_type, u8 reason) | 4294 | u8 link_type, u8 addr_type, u8 reason) |
| 4099 | { | 4295 | { |
| 4100 | struct mgmt_ev_device_disconnected ev; | 4296 | struct mgmt_ev_device_disconnected ev; |
| 4101 | struct sock *sk = NULL; | 4297 | struct sock *sk = NULL; |
| 4102 | int err; | ||
| 4103 | 4298 | ||
| 4104 | mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk); | 4299 | mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk); |
| 4105 | 4300 | ||
| @@ -4107,45 +4302,39 @@ int mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, | |||
| 4107 | ev.addr.type = link_to_bdaddr(link_type, addr_type); | 4302 | ev.addr.type = link_to_bdaddr(link_type, addr_type); |
| 4108 | ev.reason = reason; | 4303 | ev.reason = reason; |
| 4109 | 4304 | ||
| 4110 | err = mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), | 4305 | mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk); |
| 4111 | sk); | ||
| 4112 | 4306 | ||
| 4113 | if (sk) | 4307 | if (sk) |
| 4114 | sock_put(sk); | 4308 | sock_put(sk); |
| 4115 | 4309 | ||
| 4116 | mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp, | 4310 | mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp, |
| 4117 | hdev); | 4311 | hdev); |
| 4118 | |||
| 4119 | return err; | ||
| 4120 | } | 4312 | } |
| 4121 | 4313 | ||
| 4122 | int mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, | 4314 | void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, |
| 4123 | u8 link_type, u8 addr_type, u8 status) | 4315 | u8 link_type, u8 addr_type, u8 status) |
| 4124 | { | 4316 | { |
| 4125 | struct mgmt_rp_disconnect rp; | 4317 | struct mgmt_rp_disconnect rp; |
| 4126 | struct pending_cmd *cmd; | 4318 | struct pending_cmd *cmd; |
| 4127 | int err; | ||
| 4128 | 4319 | ||
| 4129 | mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp, | 4320 | mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp, |
| 4130 | hdev); | 4321 | hdev); |
| 4131 | 4322 | ||
| 4132 | cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev); | 4323 | cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev); |
| 4133 | if (!cmd) | 4324 | if (!cmd) |
| 4134 | return -ENOENT; | 4325 | return; |
| 4135 | 4326 | ||
| 4136 | bacpy(&rp.addr.bdaddr, bdaddr); | 4327 | bacpy(&rp.addr.bdaddr, bdaddr); |
| 4137 | rp.addr.type = link_to_bdaddr(link_type, addr_type); | 4328 | rp.addr.type = link_to_bdaddr(link_type, addr_type); |
| 4138 | 4329 | ||
| 4139 | err = cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, | 4330 | cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, |
| 4140 | mgmt_status(status), &rp, sizeof(rp)); | 4331 | mgmt_status(status), &rp, sizeof(rp)); |
| 4141 | 4332 | ||
| 4142 | mgmt_pending_remove(cmd); | 4333 | mgmt_pending_remove(cmd); |
| 4143 | |||
| 4144 | return err; | ||
| 4145 | } | 4334 | } |
| 4146 | 4335 | ||
| 4147 | int mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | 4336 | void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, |
| 4148 | u8 addr_type, u8 status) | 4337 | u8 addr_type, u8 status) |
| 4149 | { | 4338 | { |
| 4150 | struct mgmt_ev_connect_failed ev; | 4339 | struct mgmt_ev_connect_failed ev; |
| 4151 | 4340 | ||
| @@ -4153,7 +4342,7 @@ int mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | |||
| 4153 | ev.addr.type = link_to_bdaddr(link_type, addr_type); | 4342 | ev.addr.type = link_to_bdaddr(link_type, addr_type); |
| 4154 | ev.status = mgmt_status(status); | 4343 | ev.status = mgmt_status(status); |
| 4155 | 4344 | ||
| 4156 | return mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL); | 4345 | mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL); |
| 4157 | } | 4346 | } |
| 4158 | 4347 | ||
| 4159 | int mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure) | 4348 | int mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure) |
| @@ -4382,8 +4571,10 @@ int mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status) | |||
| 4382 | u8 mgmt_err = mgmt_status(status); | 4571 | u8 mgmt_err = mgmt_status(status); |
| 4383 | 4572 | ||
| 4384 | if (enable && test_and_clear_bit(HCI_SSP_ENABLED, | 4573 | if (enable && test_and_clear_bit(HCI_SSP_ENABLED, |
| 4385 | &hdev->dev_flags)) | 4574 | &hdev->dev_flags)) { |
| 4575 | clear_bit(HCI_HS_ENABLED, &hdev->dev_flags); | ||
| 4386 | err = new_settings(hdev, NULL); | 4576 | err = new_settings(hdev, NULL); |
| 4577 | } | ||
| 4387 | 4578 | ||
| 4388 | mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp, | 4579 | mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp, |
| 4389 | &mgmt_err); | 4580 | &mgmt_err); |
| @@ -4392,11 +4583,14 @@ int mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status) | |||
| 4392 | } | 4583 | } |
| 4393 | 4584 | ||
| 4394 | if (enable) { | 4585 | if (enable) { |
| 4395 | if (!test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) | 4586 | changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags); |
| 4396 | changed = true; | ||
| 4397 | } else { | 4587 | } else { |
| 4398 | if (test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) | 4588 | changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags); |
| 4399 | changed = true; | 4589 | if (!changed) |
| 4590 | changed = test_and_clear_bit(HCI_HS_ENABLED, | ||
| 4591 | &hdev->dev_flags); | ||
| 4592 | else | ||
| 4593 | clear_bit(HCI_HS_ENABLED, &hdev->dev_flags); | ||
| 4400 | } | 4594 | } |
| 4401 | 4595 | ||
| 4402 | mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match); | 4596 | mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match); |
| @@ -4507,20 +4701,20 @@ int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash, | |||
| 4507 | return err; | 4701 | return err; |
| 4508 | } | 4702 | } |
| 4509 | 4703 | ||
| 4510 | int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | 4704 | void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, |
| 4511 | u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name, u8 | 4705 | u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name, u8 |
| 4512 | ssp, u8 *eir, u16 eir_len) | 4706 | ssp, u8 *eir, u16 eir_len) |
| 4513 | { | 4707 | { |
| 4514 | char buf[512]; | 4708 | char buf[512]; |
| 4515 | struct mgmt_ev_device_found *ev = (void *) buf; | 4709 | struct mgmt_ev_device_found *ev = (void *) buf; |
| 4516 | size_t ev_size; | 4710 | size_t ev_size; |
| 4517 | 4711 | ||
| 4518 | if (!hci_discovery_active(hdev)) | 4712 | if (!hci_discovery_active(hdev)) |
| 4519 | return -EPERM; | 4713 | return; |
| 4520 | 4714 | ||
| 4521 | /* Leave 5 bytes for a potential CoD field */ | 4715 | /* Leave 5 bytes for a potential CoD field */ |
| 4522 | if (sizeof(*ev) + eir_len + 5 > sizeof(buf)) | 4716 | if (sizeof(*ev) + eir_len + 5 > sizeof(buf)) |
| 4523 | return -EINVAL; | 4717 | return; |
| 4524 | 4718 | ||
| 4525 | memset(buf, 0, sizeof(buf)); | 4719 | memset(buf, 0, sizeof(buf)); |
| 4526 | 4720 | ||
| @@ -4542,11 +4736,11 @@ int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | |||
| 4542 | ev->eir_len = cpu_to_le16(eir_len); | 4736 | ev->eir_len = cpu_to_le16(eir_len); |
| 4543 | ev_size = sizeof(*ev) + eir_len; | 4737 | ev_size = sizeof(*ev) + eir_len; |
| 4544 | 4738 | ||
| 4545 | return mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL); | 4739 | mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL); |
| 4546 | } | 4740 | } |
| 4547 | 4741 | ||
| 4548 | int mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | 4742 | void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, |
| 4549 | u8 addr_type, s8 rssi, u8 *name, u8 name_len) | 4743 | u8 addr_type, s8 rssi, u8 *name, u8 name_len) |
| 4550 | { | 4744 | { |
| 4551 | struct mgmt_ev_device_found *ev; | 4745 | struct mgmt_ev_device_found *ev; |
| 4552 | char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2]; | 4746 | char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2]; |
| @@ -4565,11 +4759,10 @@ int mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | |||
| 4565 | 4759 | ||
| 4566 | ev->eir_len = cpu_to_le16(eir_len); | 4760 | ev->eir_len = cpu_to_le16(eir_len); |
| 4567 | 4761 | ||
| 4568 | return mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, | 4762 | mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL); |
| 4569 | sizeof(*ev) + eir_len, NULL); | ||
| 4570 | } | 4763 | } |
| 4571 | 4764 | ||
| 4572 | int mgmt_discovering(struct hci_dev *hdev, u8 discovering) | 4765 | void mgmt_discovering(struct hci_dev *hdev, u8 discovering) |
| 4573 | { | 4766 | { |
| 4574 | struct mgmt_ev_discovering ev; | 4767 | struct mgmt_ev_discovering ev; |
| 4575 | struct pending_cmd *cmd; | 4768 | struct pending_cmd *cmd; |
| @@ -4593,7 +4786,7 @@ int mgmt_discovering(struct hci_dev *hdev, u8 discovering) | |||
| 4593 | ev.type = hdev->discovery.type; | 4786 | ev.type = hdev->discovery.type; |
| 4594 | ev.discovering = discovering; | 4787 | ev.discovering = discovering; |
| 4595 | 4788 | ||
| 4596 | return mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL); | 4789 | mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL); |
| 4597 | } | 4790 | } |
| 4598 | 4791 | ||
| 4599 | int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) | 4792 | int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) |
| @@ -4623,3 +4816,36 @@ int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) | |||
| 4623 | return mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &ev, sizeof(ev), | 4816 | return mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &ev, sizeof(ev), |
| 4624 | cmd ? cmd->sk : NULL); | 4817 | cmd ? cmd->sk : NULL); |
| 4625 | } | 4818 | } |
| 4819 | |||
| 4820 | static void adv_enable_complete(struct hci_dev *hdev, u8 status) | ||
| 4821 | { | ||
| 4822 | BT_DBG("%s status %u", hdev->name, status); | ||
| 4823 | |||
| 4824 | /* Clear the advertising mgmt setting if we failed to re-enable it */ | ||
| 4825 | if (status) { | ||
| 4826 | clear_bit(HCI_ADVERTISING, &hdev->dev_flags); | ||
| 4827 | new_settings(hdev, NULL); | ||
| 4828 | } | ||
| 4829 | } | ||
| 4830 | |||
| 4831 | void mgmt_reenable_advertising(struct hci_dev *hdev) | ||
| 4832 | { | ||
| 4833 | struct hci_request req; | ||
| 4834 | |||
| 4835 | if (hci_conn_num(hdev, LE_LINK) > 0) | ||
| 4836 | return; | ||
| 4837 | |||
| 4838 | if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags)) | ||
| 4839 | return; | ||
| 4840 | |||
| 4841 | hci_req_init(&req, hdev); | ||
| 4842 | enable_advertising(&req); | ||
| 4843 | |||
| 4844 | /* If this fails we have no option but to let user space know | ||
| 4845 | * that we've disabled advertising. | ||
| 4846 | */ | ||
| 4847 | if (hci_req_run(&req, adv_enable_complete) < 0) { | ||
| 4848 | clear_bit(HCI_ADVERTISING, &hdev->dev_flags); | ||
| 4849 | new_settings(hdev, NULL); | ||
| 4850 | } | ||
| 4851 | } | ||
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index ca957d34b0c8..27e936a7ddd9 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c | |||
| @@ -641,13 +641,13 @@ static struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst) | |||
| 641 | { | 641 | { |
| 642 | struct rfcomm_session *s; | 642 | struct rfcomm_session *s; |
| 643 | struct list_head *p, *n; | 643 | struct list_head *p, *n; |
| 644 | struct bt_sock *sk; | 644 | struct l2cap_chan *chan; |
| 645 | list_for_each_safe(p, n, &session_list) { | 645 | list_for_each_safe(p, n, &session_list) { |
| 646 | s = list_entry(p, struct rfcomm_session, list); | 646 | s = list_entry(p, struct rfcomm_session, list); |
| 647 | sk = bt_sk(s->sock->sk); | 647 | chan = l2cap_pi(s->sock->sk)->chan; |
| 648 | 648 | ||
| 649 | if ((!bacmp(src, BDADDR_ANY) || !bacmp(&sk->src, src)) && | 649 | if ((!bacmp(src, BDADDR_ANY) || !bacmp(&chan->src, src)) && |
| 650 | !bacmp(&sk->dst, dst)) | 650 | !bacmp(&chan->dst, dst)) |
| 651 | return s; | 651 | return s; |
| 652 | } | 652 | } |
| 653 | return NULL; | 653 | return NULL; |
| @@ -732,11 +732,11 @@ failed: | |||
| 732 | 732 | ||
| 733 | void rfcomm_session_getaddr(struct rfcomm_session *s, bdaddr_t *src, bdaddr_t *dst) | 733 | void rfcomm_session_getaddr(struct rfcomm_session *s, bdaddr_t *src, bdaddr_t *dst) |
| 734 | { | 734 | { |
| 735 | struct sock *sk = s->sock->sk; | 735 | struct l2cap_chan *chan = l2cap_pi(s->sock->sk)->chan; |
| 736 | if (src) | 736 | if (src) |
| 737 | bacpy(src, &bt_sk(sk)->src); | 737 | bacpy(src, &chan->src); |
| 738 | if (dst) | 738 | if (dst) |
| 739 | bacpy(dst, &bt_sk(sk)->dst); | 739 | bacpy(dst, &chan->dst); |
| 740 | } | 740 | } |
| 741 | 741 | ||
| 742 | /* ---- RFCOMM frame sending ---- */ | 742 | /* ---- RFCOMM frame sending ---- */ |
| @@ -2112,12 +2112,11 @@ static int rfcomm_dlc_debugfs_show(struct seq_file *f, void *x) | |||
| 2112 | rfcomm_lock(); | 2112 | rfcomm_lock(); |
| 2113 | 2113 | ||
| 2114 | list_for_each_entry(s, &session_list, list) { | 2114 | list_for_each_entry(s, &session_list, list) { |
| 2115 | struct l2cap_chan *chan = l2cap_pi(s->sock->sk)->chan; | ||
| 2115 | struct rfcomm_dlc *d; | 2116 | struct rfcomm_dlc *d; |
| 2116 | list_for_each_entry(d, &s->dlcs, list) { | 2117 | list_for_each_entry(d, &s->dlcs, list) { |
| 2117 | struct sock *sk = s->sock->sk; | ||
| 2118 | |||
| 2119 | seq_printf(f, "%pMR %pMR %ld %d %d %d %d\n", | 2118 | seq_printf(f, "%pMR %pMR %ld %d %d %d %d\n", |
| 2120 | &bt_sk(sk)->src, &bt_sk(sk)->dst, | 2119 | &chan->src, &chan->dst, |
| 2121 | d->state, d->dlci, d->mtu, | 2120 | d->state, d->dlci, d->mtu, |
| 2122 | d->rx_credits, d->tx_credits); | 2121 | d->rx_credits, d->tx_credits); |
| 2123 | } | 2122 | } |
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 072938dc527d..df17276eb32b 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c | |||
| @@ -87,7 +87,8 @@ static void rfcomm_sk_state_change(struct rfcomm_dlc *d, int err) | |||
| 87 | parent->sk_data_ready(parent, 0); | 87 | parent->sk_data_ready(parent, 0); |
| 88 | } else { | 88 | } else { |
| 89 | if (d->state == BT_CONNECTED) | 89 | if (d->state == BT_CONNECTED) |
| 90 | rfcomm_session_getaddr(d->session, &bt_sk(sk)->src, NULL); | 90 | rfcomm_session_getaddr(d->session, |
| 91 | &rfcomm_pi(sk)->src, NULL); | ||
| 91 | sk->sk_state_change(sk); | 92 | sk->sk_state_change(sk); |
| 92 | } | 93 | } |
| 93 | 94 | ||
| @@ -110,7 +111,7 @@ static struct sock *__rfcomm_get_sock_by_addr(u8 channel, bdaddr_t *src) | |||
| 110 | 111 | ||
| 111 | sk_for_each(sk, &rfcomm_sk_list.head) { | 112 | sk_for_each(sk, &rfcomm_sk_list.head) { |
| 112 | if (rfcomm_pi(sk)->channel == channel && | 113 | if (rfcomm_pi(sk)->channel == channel && |
| 113 | !bacmp(&bt_sk(sk)->src, src)) | 114 | !bacmp(&rfcomm_pi(sk)->src, src)) |
| 114 | break; | 115 | break; |
| 115 | } | 116 | } |
| 116 | 117 | ||
| @@ -132,11 +133,11 @@ static struct sock *rfcomm_get_sock_by_channel(int state, u8 channel, bdaddr_t * | |||
| 132 | 133 | ||
| 133 | if (rfcomm_pi(sk)->channel == channel) { | 134 | if (rfcomm_pi(sk)->channel == channel) { |
| 134 | /* Exact match. */ | 135 | /* Exact match. */ |
| 135 | if (!bacmp(&bt_sk(sk)->src, src)) | 136 | if (!bacmp(&rfcomm_pi(sk)->src, src)) |
| 136 | break; | 137 | break; |
| 137 | 138 | ||
| 138 | /* Closest match */ | 139 | /* Closest match */ |
| 139 | if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) | 140 | if (!bacmp(&rfcomm_pi(sk)->src, BDADDR_ANY)) |
| 140 | sk1 = sk; | 141 | sk1 = sk; |
| 141 | } | 142 | } |
| 142 | } | 143 | } |
| @@ -355,7 +356,7 @@ static int rfcomm_sock_bind(struct socket *sock, struct sockaddr *addr, int addr | |||
| 355 | err = -EADDRINUSE; | 356 | err = -EADDRINUSE; |
| 356 | } else { | 357 | } else { |
| 357 | /* Save source address */ | 358 | /* Save source address */ |
| 358 | bacpy(&bt_sk(sk)->src, &sa->rc_bdaddr); | 359 | bacpy(&rfcomm_pi(sk)->src, &sa->rc_bdaddr); |
| 359 | rfcomm_pi(sk)->channel = sa->rc_channel; | 360 | rfcomm_pi(sk)->channel = sa->rc_channel; |
| 360 | sk->sk_state = BT_BOUND; | 361 | sk->sk_state = BT_BOUND; |
| 361 | } | 362 | } |
| @@ -393,13 +394,14 @@ static int rfcomm_sock_connect(struct socket *sock, struct sockaddr *addr, int a | |||
| 393 | } | 394 | } |
| 394 | 395 | ||
| 395 | sk->sk_state = BT_CONNECT; | 396 | sk->sk_state = BT_CONNECT; |
| 396 | bacpy(&bt_sk(sk)->dst, &sa->rc_bdaddr); | 397 | bacpy(&rfcomm_pi(sk)->dst, &sa->rc_bdaddr); |
| 397 | rfcomm_pi(sk)->channel = sa->rc_channel; | 398 | rfcomm_pi(sk)->channel = sa->rc_channel; |
| 398 | 399 | ||
| 399 | d->sec_level = rfcomm_pi(sk)->sec_level; | 400 | d->sec_level = rfcomm_pi(sk)->sec_level; |
| 400 | d->role_switch = rfcomm_pi(sk)->role_switch; | 401 | d->role_switch = rfcomm_pi(sk)->role_switch; |
| 401 | 402 | ||
| 402 | err = rfcomm_dlc_open(d, &bt_sk(sk)->src, &sa->rc_bdaddr, sa->rc_channel); | 403 | err = rfcomm_dlc_open(d, &rfcomm_pi(sk)->src, &sa->rc_bdaddr, |
| 404 | sa->rc_channel); | ||
| 403 | if (!err) | 405 | if (!err) |
| 404 | err = bt_sock_wait_state(sk, BT_CONNECTED, | 406 | err = bt_sock_wait_state(sk, BT_CONNECTED, |
| 405 | sock_sndtimeo(sk, flags & O_NONBLOCK)); | 407 | sock_sndtimeo(sk, flags & O_NONBLOCK)); |
| @@ -429,7 +431,7 @@ static int rfcomm_sock_listen(struct socket *sock, int backlog) | |||
| 429 | } | 431 | } |
| 430 | 432 | ||
| 431 | if (!rfcomm_pi(sk)->channel) { | 433 | if (!rfcomm_pi(sk)->channel) { |
| 432 | bdaddr_t *src = &bt_sk(sk)->src; | 434 | bdaddr_t *src = &rfcomm_pi(sk)->src; |
| 433 | u8 channel; | 435 | u8 channel; |
| 434 | 436 | ||
| 435 | err = -EINVAL; | 437 | err = -EINVAL; |
| @@ -530,9 +532,9 @@ static int rfcomm_sock_getname(struct socket *sock, struct sockaddr *addr, int * | |||
| 530 | sa->rc_family = AF_BLUETOOTH; | 532 | sa->rc_family = AF_BLUETOOTH; |
| 531 | sa->rc_channel = rfcomm_pi(sk)->channel; | 533 | sa->rc_channel = rfcomm_pi(sk)->channel; |
| 532 | if (peer) | 534 | if (peer) |
| 533 | bacpy(&sa->rc_bdaddr, &bt_sk(sk)->dst); | 535 | bacpy(&sa->rc_bdaddr, &rfcomm_pi(sk)->dst); |
| 534 | else | 536 | else |
| 535 | bacpy(&sa->rc_bdaddr, &bt_sk(sk)->src); | 537 | bacpy(&sa->rc_bdaddr, &rfcomm_pi(sk)->src); |
| 536 | 538 | ||
| 537 | *len = sizeof(struct sockaddr_rc); | 539 | *len = sizeof(struct sockaddr_rc); |
| 538 | return 0; | 540 | return 0; |
| @@ -951,8 +953,8 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc * | |||
| 951 | bt_sock_reclassify_lock(sk, BTPROTO_RFCOMM); | 953 | bt_sock_reclassify_lock(sk, BTPROTO_RFCOMM); |
| 952 | 954 | ||
| 953 | rfcomm_sock_init(sk, parent); | 955 | rfcomm_sock_init(sk, parent); |
| 954 | bacpy(&bt_sk(sk)->src, &src); | 956 | bacpy(&rfcomm_pi(sk)->src, &src); |
| 955 | bacpy(&bt_sk(sk)->dst, &dst); | 957 | bacpy(&rfcomm_pi(sk)->dst, &dst); |
| 956 | rfcomm_pi(sk)->channel = channel; | 958 | rfcomm_pi(sk)->channel = channel; |
| 957 | 959 | ||
| 958 | sk->sk_state = BT_CONFIG; | 960 | sk->sk_state = BT_CONFIG; |
| @@ -979,7 +981,7 @@ static int rfcomm_sock_debugfs_show(struct seq_file *f, void *p) | |||
| 979 | 981 | ||
| 980 | sk_for_each(sk, &rfcomm_sk_list.head) { | 982 | sk_for_each(sk, &rfcomm_sk_list.head) { |
| 981 | seq_printf(f, "%pMR %pMR %d %d\n", | 983 | seq_printf(f, "%pMR %pMR %d %d\n", |
| 982 | &bt_sk(sk)->src, &bt_sk(sk)->dst, | 984 | &rfcomm_pi(sk)->src, &rfcomm_pi(sk)->dst, |
| 983 | sk->sk_state, rfcomm_pi(sk)->channel); | 985 | sk->sk_state, rfcomm_pi(sk)->channel); |
| 984 | } | 986 | } |
| 985 | 987 | ||
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 96bd388d93a4..a92aebac56ca 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c | |||
| @@ -92,9 +92,6 @@ static struct sco_conn *sco_conn_add(struct hci_conn *hcon) | |||
| 92 | hcon->sco_data = conn; | 92 | hcon->sco_data = conn; |
| 93 | conn->hcon = hcon; | 93 | conn->hcon = hcon; |
| 94 | 94 | ||
| 95 | conn->src = &hdev->bdaddr; | ||
| 96 | conn->dst = &hcon->dst; | ||
| 97 | |||
| 98 | if (hdev->sco_mtu > 0) | 95 | if (hdev->sco_mtu > 0) |
| 99 | conn->mtu = hdev->sco_mtu; | 96 | conn->mtu = hdev->sco_mtu; |
| 100 | else | 97 | else |
| @@ -156,16 +153,14 @@ static int sco_chan_add(struct sco_conn *conn, struct sock *sk, | |||
| 156 | 153 | ||
| 157 | static int sco_connect(struct sock *sk) | 154 | static int sco_connect(struct sock *sk) |
| 158 | { | 155 | { |
| 159 | bdaddr_t *src = &bt_sk(sk)->src; | ||
| 160 | bdaddr_t *dst = &bt_sk(sk)->dst; | ||
| 161 | struct sco_conn *conn; | 156 | struct sco_conn *conn; |
| 162 | struct hci_conn *hcon; | 157 | struct hci_conn *hcon; |
| 163 | struct hci_dev *hdev; | 158 | struct hci_dev *hdev; |
| 164 | int err, type; | 159 | int err, type; |
| 165 | 160 | ||
| 166 | BT_DBG("%pMR -> %pMR", src, dst); | 161 | BT_DBG("%pMR -> %pMR", &sco_pi(sk)->src, &sco_pi(sk)->dst); |
| 167 | 162 | ||
| 168 | hdev = hci_get_route(dst, src); | 163 | hdev = hci_get_route(&sco_pi(sk)->dst, &sco_pi(sk)->src); |
| 169 | if (!hdev) | 164 | if (!hdev) |
| 170 | return -EHOSTUNREACH; | 165 | return -EHOSTUNREACH; |
| 171 | 166 | ||
| @@ -182,7 +177,8 @@ static int sco_connect(struct sock *sk) | |||
| 182 | goto done; | 177 | goto done; |
| 183 | } | 178 | } |
| 184 | 179 | ||
| 185 | hcon = hci_connect_sco(hdev, type, dst, sco_pi(sk)->setting); | 180 | hcon = hci_connect_sco(hdev, type, &sco_pi(sk)->dst, |
| 181 | sco_pi(sk)->setting); | ||
| 186 | if (IS_ERR(hcon)) { | 182 | if (IS_ERR(hcon)) { |
| 187 | err = PTR_ERR(hcon); | 183 | err = PTR_ERR(hcon); |
| 188 | goto done; | 184 | goto done; |
| @@ -196,7 +192,7 @@ static int sco_connect(struct sock *sk) | |||
| 196 | } | 192 | } |
| 197 | 193 | ||
| 198 | /* Update source addr of the socket */ | 194 | /* Update source addr of the socket */ |
| 199 | bacpy(src, conn->src); | 195 | bacpy(&sco_pi(sk)->src, &hcon->src); |
| 200 | 196 | ||
| 201 | err = sco_chan_add(conn, sk, NULL); | 197 | err = sco_chan_add(conn, sk, NULL); |
| 202 | if (err) | 198 | if (err) |
| @@ -270,7 +266,7 @@ static struct sock *__sco_get_sock_listen_by_addr(bdaddr_t *ba) | |||
| 270 | if (sk->sk_state != BT_LISTEN) | 266 | if (sk->sk_state != BT_LISTEN) |
| 271 | continue; | 267 | continue; |
| 272 | 268 | ||
| 273 | if (!bacmp(&bt_sk(sk)->src, ba)) | 269 | if (!bacmp(&sco_pi(sk)->src, ba)) |
| 274 | return sk; | 270 | return sk; |
| 275 | } | 271 | } |
| 276 | 272 | ||
| @@ -291,11 +287,11 @@ static struct sock *sco_get_sock_listen(bdaddr_t *src) | |||
| 291 | continue; | 287 | continue; |
| 292 | 288 | ||
| 293 | /* Exact match. */ | 289 | /* Exact match. */ |
| 294 | if (!bacmp(&bt_sk(sk)->src, src)) | 290 | if (!bacmp(&sco_pi(sk)->src, src)) |
| 295 | break; | 291 | break; |
| 296 | 292 | ||
| 297 | /* Closest match */ | 293 | /* Closest match */ |
| 298 | if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) | 294 | if (!bacmp(&sco_pi(sk)->src, BDADDR_ANY)) |
| 299 | sk1 = sk; | 295 | sk1 = sk; |
| 300 | } | 296 | } |
| 301 | 297 | ||
| @@ -475,7 +471,7 @@ static int sco_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_le | |||
| 475 | goto done; | 471 | goto done; |
| 476 | } | 472 | } |
| 477 | 473 | ||
| 478 | bacpy(&bt_sk(sk)->src, &sa->sco_bdaddr); | 474 | bacpy(&sco_pi(sk)->src, &sa->sco_bdaddr); |
| 479 | 475 | ||
| 480 | sk->sk_state = BT_BOUND; | 476 | sk->sk_state = BT_BOUND; |
| 481 | 477 | ||
| @@ -505,7 +501,7 @@ static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen | |||
| 505 | lock_sock(sk); | 501 | lock_sock(sk); |
| 506 | 502 | ||
| 507 | /* Set destination address and psm */ | 503 | /* Set destination address and psm */ |
| 508 | bacpy(&bt_sk(sk)->dst, &sa->sco_bdaddr); | 504 | bacpy(&sco_pi(sk)->dst, &sa->sco_bdaddr); |
| 509 | 505 | ||
| 510 | err = sco_connect(sk); | 506 | err = sco_connect(sk); |
| 511 | if (err) | 507 | if (err) |
| @@ -522,7 +518,7 @@ done: | |||
| 522 | static int sco_sock_listen(struct socket *sock, int backlog) | 518 | static int sco_sock_listen(struct socket *sock, int backlog) |
| 523 | { | 519 | { |
| 524 | struct sock *sk = sock->sk; | 520 | struct sock *sk = sock->sk; |
| 525 | bdaddr_t *src = &bt_sk(sk)->src; | 521 | bdaddr_t *src = &sco_pi(sk)->src; |
| 526 | int err = 0; | 522 | int err = 0; |
| 527 | 523 | ||
| 528 | BT_DBG("sk %p backlog %d", sk, backlog); | 524 | BT_DBG("sk %p backlog %d", sk, backlog); |
| @@ -626,9 +622,9 @@ static int sco_sock_getname(struct socket *sock, struct sockaddr *addr, int *len | |||
| 626 | *len = sizeof(struct sockaddr_sco); | 622 | *len = sizeof(struct sockaddr_sco); |
| 627 | 623 | ||
| 628 | if (peer) | 624 | if (peer) |
| 629 | bacpy(&sa->sco_bdaddr, &bt_sk(sk)->dst); | 625 | bacpy(&sa->sco_bdaddr, &sco_pi(sk)->dst); |
| 630 | else | 626 | else |
| 631 | bacpy(&sa->sco_bdaddr, &bt_sk(sk)->src); | 627 | bacpy(&sa->sco_bdaddr, &sco_pi(sk)->src); |
| 632 | 628 | ||
| 633 | return 0; | 629 | return 0; |
| 634 | } | 630 | } |
| @@ -999,7 +995,7 @@ static void sco_conn_ready(struct sco_conn *conn) | |||
| 999 | } else { | 995 | } else { |
| 1000 | sco_conn_lock(conn); | 996 | sco_conn_lock(conn); |
| 1001 | 997 | ||
| 1002 | parent = sco_get_sock_listen(conn->src); | 998 | parent = sco_get_sock_listen(&conn->hcon->src); |
| 1003 | if (!parent) { | 999 | if (!parent) { |
| 1004 | sco_conn_unlock(conn); | 1000 | sco_conn_unlock(conn); |
| 1005 | return; | 1001 | return; |
| @@ -1017,8 +1013,8 @@ static void sco_conn_ready(struct sco_conn *conn) | |||
| 1017 | 1013 | ||
| 1018 | sco_sock_init(sk, parent); | 1014 | sco_sock_init(sk, parent); |
| 1019 | 1015 | ||
| 1020 | bacpy(&bt_sk(sk)->src, conn->src); | 1016 | bacpy(&sco_pi(sk)->src, &conn->hcon->src); |
| 1021 | bacpy(&bt_sk(sk)->dst, conn->dst); | 1017 | bacpy(&sco_pi(sk)->dst, &conn->hcon->dst); |
| 1022 | 1018 | ||
| 1023 | hci_conn_hold(conn->hcon); | 1019 | hci_conn_hold(conn->hcon); |
| 1024 | __sco_chan_add(conn, sk, parent); | 1020 | __sco_chan_add(conn, sk, parent); |
| @@ -1051,8 +1047,8 @@ int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags) | |||
| 1051 | if (sk->sk_state != BT_LISTEN) | 1047 | if (sk->sk_state != BT_LISTEN) |
| 1052 | continue; | 1048 | continue; |
| 1053 | 1049 | ||
| 1054 | if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr) || | 1050 | if (!bacmp(&sco_pi(sk)->src, &hdev->bdaddr) || |
| 1055 | !bacmp(&bt_sk(sk)->src, BDADDR_ANY)) { | 1051 | !bacmp(&sco_pi(sk)->src, BDADDR_ANY)) { |
| 1056 | lm |= HCI_LM_ACCEPT; | 1052 | lm |= HCI_LM_ACCEPT; |
| 1057 | 1053 | ||
| 1058 | if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) | 1054 | if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) |
| @@ -1111,8 +1107,8 @@ static int sco_debugfs_show(struct seq_file *f, void *p) | |||
| 1111 | read_lock(&sco_sk_list.lock); | 1107 | read_lock(&sco_sk_list.lock); |
| 1112 | 1108 | ||
| 1113 | sk_for_each(sk, &sco_sk_list.head) { | 1109 | sk_for_each(sk, &sco_sk_list.head) { |
| 1114 | seq_printf(f, "%pMR %pMR %d\n", &bt_sk(sk)->src, | 1110 | seq_printf(f, "%pMR %pMR %d\n", &sco_pi(sk)->src, |
| 1115 | &bt_sk(sk)->dst, sk->sk_state); | 1111 | &sco_pi(sk)->dst, sk->sk_state); |
| 1116 | } | 1112 | } |
| 1117 | 1113 | ||
| 1118 | read_unlock(&sco_sk_list.lock); | 1114 | read_unlock(&sco_sk_list.lock); |
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 884b2081a262..463e50c58716 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c | |||
| @@ -28,7 +28,8 @@ | |||
| 28 | #include <net/bluetooth/hci_core.h> | 28 | #include <net/bluetooth/hci_core.h> |
| 29 | #include <net/bluetooth/l2cap.h> | 29 | #include <net/bluetooth/l2cap.h> |
| 30 | #include <net/bluetooth/mgmt.h> | 30 | #include <net/bluetooth/mgmt.h> |
| 31 | #include <net/bluetooth/smp.h> | 31 | |
| 32 | #include "smp.h" | ||
| 32 | 33 | ||
| 33 | #define SMP_TIMEOUT msecs_to_jiffies(30000) | 34 | #define SMP_TIMEOUT msecs_to_jiffies(30000) |
| 34 | 35 | ||
| @@ -85,8 +86,8 @@ static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r) | |||
| 85 | } | 86 | } |
| 86 | 87 | ||
| 87 | static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16], | 88 | static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16], |
| 88 | u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia, | 89 | u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia, |
| 89 | u8 _rat, bdaddr_t *ra, u8 res[16]) | 90 | u8 _rat, bdaddr_t *ra, u8 res[16]) |
| 90 | { | 91 | { |
| 91 | u8 p1[16], p2[16]; | 92 | u8 p1[16], p2[16]; |
| 92 | int err; | 93 | int err; |
| @@ -126,8 +127,8 @@ static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16], | |||
| 126 | return err; | 127 | return err; |
| 127 | } | 128 | } |
| 128 | 129 | ||
| 129 | static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16], | 130 | static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16], u8 r1[16], |
| 130 | u8 r1[16], u8 r2[16], u8 _r[16]) | 131 | u8 r2[16], u8 _r[16]) |
| 131 | { | 132 | { |
| 132 | int err; | 133 | int err; |
| 133 | 134 | ||
| @@ -150,7 +151,7 @@ static int smp_rand(u8 *buf) | |||
| 150 | } | 151 | } |
| 151 | 152 | ||
| 152 | static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code, | 153 | static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code, |
| 153 | u16 dlen, void *data) | 154 | u16 dlen, void *data) |
| 154 | { | 155 | { |
| 155 | struct sk_buff *skb; | 156 | struct sk_buff *skb; |
| 156 | struct l2cap_hdr *lh; | 157 | struct l2cap_hdr *lh; |
| @@ -213,9 +214,8 @@ static __u8 seclevel_to_authreq(__u8 sec_level) | |||
| 213 | } | 214 | } |
| 214 | 215 | ||
| 215 | static void build_pairing_cmd(struct l2cap_conn *conn, | 216 | static void build_pairing_cmd(struct l2cap_conn *conn, |
| 216 | struct smp_cmd_pairing *req, | 217 | struct smp_cmd_pairing *req, |
| 217 | struct smp_cmd_pairing *rsp, | 218 | struct smp_cmd_pairing *rsp, __u8 authreq) |
| 218 | __u8 authreq) | ||
| 219 | { | 219 | { |
| 220 | u8 dist_keys = 0; | 220 | u8 dist_keys = 0; |
| 221 | 221 | ||
| @@ -249,7 +249,7 @@ static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size) | |||
| 249 | struct smp_chan *smp = conn->smp_chan; | 249 | struct smp_chan *smp = conn->smp_chan; |
| 250 | 250 | ||
| 251 | if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) || | 251 | if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) || |
| 252 | (max_key_size < SMP_MIN_ENC_KEY_SIZE)) | 252 | (max_key_size < SMP_MIN_ENC_KEY_SIZE)) |
| 253 | return SMP_ENC_KEY_SIZE; | 253 | return SMP_ENC_KEY_SIZE; |
| 254 | 254 | ||
| 255 | smp->enc_key_size = max_key_size; | 255 | smp->enc_key_size = max_key_size; |
| @@ -263,15 +263,15 @@ static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send) | |||
| 263 | 263 | ||
| 264 | if (send) | 264 | if (send) |
| 265 | smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), | 265 | smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), |
| 266 | &reason); | 266 | &reason); |
| 267 | 267 | ||
| 268 | clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->flags); | 268 | clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags); |
| 269 | mgmt_auth_failed(conn->hcon->hdev, conn->dst, hcon->type, | 269 | mgmt_auth_failed(hcon->hdev, &hcon->dst, hcon->type, hcon->dst_type, |
| 270 | hcon->dst_type, HCI_ERROR_AUTH_FAILURE); | 270 | HCI_ERROR_AUTH_FAILURE); |
| 271 | 271 | ||
| 272 | cancel_delayed_work_sync(&conn->security_timer); | 272 | cancel_delayed_work_sync(&conn->security_timer); |
| 273 | 273 | ||
| 274 | if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) | 274 | if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) |
| 275 | smp_chan_destroy(conn); | 275 | smp_chan_destroy(conn); |
| 276 | } | 276 | } |
| 277 | 277 | ||
| @@ -309,8 +309,8 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth, | |||
| 309 | /* If either side has unknown io_caps, use JUST WORKS */ | 309 | /* If either side has unknown io_caps, use JUST WORKS */ |
| 310 | /* Otherwise, look up method from the table */ | 310 | /* Otherwise, look up method from the table */ |
| 311 | if (!(auth & SMP_AUTH_MITM) || | 311 | if (!(auth & SMP_AUTH_MITM) || |
| 312 | local_io > SMP_IO_KEYBOARD_DISPLAY || | 312 | local_io > SMP_IO_KEYBOARD_DISPLAY || |
| 313 | remote_io > SMP_IO_KEYBOARD_DISPLAY) | 313 | remote_io > SMP_IO_KEYBOARD_DISPLAY) |
| 314 | method = JUST_WORKS; | 314 | method = JUST_WORKS; |
| 315 | else | 315 | else |
| 316 | method = gen_method[remote_io][local_io]; | 316 | method = gen_method[remote_io][local_io]; |
| @@ -354,10 +354,10 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth, | |||
| 354 | hci_dev_lock(hcon->hdev); | 354 | hci_dev_lock(hcon->hdev); |
| 355 | 355 | ||
| 356 | if (method == REQ_PASSKEY) | 356 | if (method == REQ_PASSKEY) |
| 357 | ret = mgmt_user_passkey_request(hcon->hdev, conn->dst, | 357 | ret = mgmt_user_passkey_request(hcon->hdev, &hcon->dst, |
| 358 | hcon->type, hcon->dst_type); | 358 | hcon->type, hcon->dst_type); |
| 359 | else | 359 | else |
| 360 | ret = mgmt_user_confirm_request(hcon->hdev, conn->dst, | 360 | ret = mgmt_user_confirm_request(hcon->hdev, &hcon->dst, |
| 361 | hcon->type, hcon->dst_type, | 361 | hcon->type, hcon->dst_type, |
| 362 | cpu_to_le32(passkey), 0); | 362 | cpu_to_le32(passkey), 0); |
| 363 | 363 | ||
| @@ -386,12 +386,13 @@ static void confirm_work(struct work_struct *work) | |||
| 386 | smp->tfm = tfm; | 386 | smp->tfm = tfm; |
| 387 | 387 | ||
| 388 | if (conn->hcon->out) | 388 | if (conn->hcon->out) |
| 389 | ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, 0, | 389 | ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, |
| 390 | conn->src, conn->hcon->dst_type, conn->dst, res); | 390 | conn->hcon->src_type, &conn->hcon->src, |
| 391 | conn->hcon->dst_type, &conn->hcon->dst, res); | ||
| 391 | else | 392 | else |
| 392 | ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, | 393 | ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, |
| 393 | conn->hcon->dst_type, conn->dst, 0, conn->src, | 394 | conn->hcon->dst_type, &conn->hcon->dst, |
| 394 | res); | 395 | conn->hcon->src_type, &conn->hcon->src, res); |
| 395 | if (ret) { | 396 | if (ret) { |
| 396 | reason = SMP_UNSPECIFIED; | 397 | reason = SMP_UNSPECIFIED; |
| 397 | goto error; | 398 | goto error; |
| @@ -425,11 +426,13 @@ static void random_work(struct work_struct *work) | |||
| 425 | BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave"); | 426 | BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave"); |
| 426 | 427 | ||
| 427 | if (hcon->out) | 428 | if (hcon->out) |
| 428 | ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, 0, | 429 | ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, |
| 429 | conn->src, hcon->dst_type, conn->dst, res); | 430 | hcon->src_type, &hcon->src, |
| 431 | hcon->dst_type, &hcon->dst, res); | ||
| 430 | else | 432 | else |
| 431 | ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, | 433 | ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, |
| 432 | hcon->dst_type, conn->dst, 0, conn->src, res); | 434 | hcon->dst_type, &hcon->dst, |
| 435 | hcon->src_type, &hcon->src, res); | ||
| 433 | if (ret) { | 436 | if (ret) { |
| 434 | reason = SMP_UNSPECIFIED; | 437 | reason = SMP_UNSPECIFIED; |
| 435 | goto error; | 438 | goto error; |
| @@ -477,9 +480,9 @@ static void random_work(struct work_struct *work) | |||
| 477 | swap128(key, stk); | 480 | swap128(key, stk); |
| 478 | 481 | ||
| 479 | memset(stk + smp->enc_key_size, 0, | 482 | memset(stk + smp->enc_key_size, 0, |
| 480 | SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size); | 483 | SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size); |
| 481 | 484 | ||
| 482 | hci_add_ltk(hcon->hdev, conn->dst, hcon->dst_type, | 485 | hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type, |
| 483 | HCI_SMP_STK_SLAVE, 0, 0, stk, smp->enc_key_size, | 486 | HCI_SMP_STK_SLAVE, 0, 0, stk, smp->enc_key_size, |
| 484 | ediv, rand); | 487 | ediv, rand); |
| 485 | } | 488 | } |
| @@ -494,7 +497,7 @@ static struct smp_chan *smp_chan_create(struct l2cap_conn *conn) | |||
| 494 | { | 497 | { |
| 495 | struct smp_chan *smp; | 498 | struct smp_chan *smp; |
| 496 | 499 | ||
| 497 | smp = kzalloc(sizeof(struct smp_chan), GFP_ATOMIC); | 500 | smp = kzalloc(sizeof(*smp), GFP_ATOMIC); |
| 498 | if (!smp) | 501 | if (!smp) |
| 499 | return NULL; | 502 | return NULL; |
| 500 | 503 | ||
| @@ -649,7 +652,7 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb) | |||
| 649 | memcpy(&smp->prsp[1], rsp, sizeof(*rsp)); | 652 | memcpy(&smp->prsp[1], rsp, sizeof(*rsp)); |
| 650 | 653 | ||
| 651 | if ((req->auth_req & SMP_AUTH_BONDING) && | 654 | if ((req->auth_req & SMP_AUTH_BONDING) && |
| 652 | (rsp->auth_req & SMP_AUTH_BONDING)) | 655 | (rsp->auth_req & SMP_AUTH_BONDING)) |
| 653 | auth = SMP_AUTH_BONDING; | 656 | auth = SMP_AUTH_BONDING; |
| 654 | 657 | ||
| 655 | auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM; | 658 | auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM; |
| @@ -684,7 +687,7 @@ static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb) | |||
| 684 | 687 | ||
| 685 | swap128(smp->prnd, random); | 688 | swap128(smp->prnd, random); |
| 686 | smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random), | 689 | smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random), |
| 687 | random); | 690 | random); |
| 688 | } else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) { | 691 | } else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) { |
| 689 | queue_work(hdev->workqueue, &smp->confirm); | 692 | queue_work(hdev->workqueue, &smp->confirm); |
| 690 | } else { | 693 | } else { |
| @@ -714,7 +717,7 @@ static u8 smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level) | |||
| 714 | struct smp_ltk *key; | 717 | struct smp_ltk *key; |
| 715 | struct hci_conn *hcon = conn->hcon; | 718 | struct hci_conn *hcon = conn->hcon; |
| 716 | 719 | ||
| 717 | key = hci_find_ltk_by_addr(hcon->hdev, conn->dst, hcon->dst_type); | 720 | key = hci_find_ltk_by_addr(hcon->hdev, &hcon->dst, hcon->dst_type); |
| 718 | if (!key) | 721 | if (!key) |
| 719 | return 0; | 722 | return 0; |
| 720 | 723 | ||
| @@ -728,8 +731,8 @@ static u8 smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level) | |||
| 728 | hcon->enc_key_size = key->enc_size; | 731 | hcon->enc_key_size = key->enc_size; |
| 729 | 732 | ||
| 730 | return 1; | 733 | return 1; |
| 731 | |||
| 732 | } | 734 | } |
| 735 | |||
| 733 | static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) | 736 | static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) |
| 734 | { | 737 | { |
| 735 | struct smp_cmd_security_req *rp = (void *) skb->data; | 738 | struct smp_cmd_security_req *rp = (void *) skb->data; |
| @@ -835,9 +838,9 @@ static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb) | |||
| 835 | skb_pull(skb, sizeof(*rp)); | 838 | skb_pull(skb, sizeof(*rp)); |
| 836 | 839 | ||
| 837 | hci_dev_lock(hdev); | 840 | hci_dev_lock(hdev); |
| 838 | authenticated = (conn->hcon->sec_level == BT_SECURITY_HIGH); | 841 | authenticated = (hcon->sec_level == BT_SECURITY_HIGH); |
| 839 | hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type, | 842 | hci_add_ltk(hdev, &hcon->dst, hcon->dst_type, HCI_SMP_LTK, 1, |
| 840 | HCI_SMP_LTK, 1, authenticated, smp->tk, smp->enc_key_size, | 843 | authenticated, smp->tk, smp->enc_key_size, |
| 841 | rp->ediv, rp->rand); | 844 | rp->ediv, rp->rand); |
| 842 | smp_distribute_keys(conn, 1); | 845 | smp_distribute_keys(conn, 1); |
| 843 | hci_dev_unlock(hdev); | 846 | hci_dev_unlock(hdev); |
| @@ -985,7 +988,7 @@ int smp_distribute_keys(struct l2cap_conn *conn, __u8 force) | |||
| 985 | smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc); | 988 | smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc); |
| 986 | 989 | ||
| 987 | authenticated = hcon->sec_level == BT_SECURITY_HIGH; | 990 | authenticated = hcon->sec_level == BT_SECURITY_HIGH; |
| 988 | hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type, | 991 | hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type, |
| 989 | HCI_SMP_LTK_SLAVE, 1, authenticated, | 992 | HCI_SMP_LTK_SLAVE, 1, authenticated, |
| 990 | enc.ltk, smp->enc_key_size, ediv, ident.rand); | 993 | enc.ltk, smp->enc_key_size, ediv, ident.rand); |
| 991 | 994 | ||
| @@ -1007,10 +1010,10 @@ int smp_distribute_keys(struct l2cap_conn *conn, __u8 force) | |||
| 1007 | 1010 | ||
| 1008 | /* Just public address */ | 1011 | /* Just public address */ |
| 1009 | memset(&addrinfo, 0, sizeof(addrinfo)); | 1012 | memset(&addrinfo, 0, sizeof(addrinfo)); |
| 1010 | bacpy(&addrinfo.bdaddr, conn->src); | 1013 | bacpy(&addrinfo.bdaddr, &conn->hcon->src); |
| 1011 | 1014 | ||
| 1012 | smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo), | 1015 | smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo), |
| 1013 | &addrinfo); | 1016 | &addrinfo); |
| 1014 | 1017 | ||
| 1015 | *keydist &= ~SMP_DIST_ID_KEY; | 1018 | *keydist &= ~SMP_DIST_ID_KEY; |
| 1016 | } | 1019 | } |
diff --git a/include/net/bluetooth/smp.h b/net/bluetooth/smp.h index f8ba07f3e5fa..f8ba07f3e5fa 100644 --- a/include/net/bluetooth/smp.h +++ b/net/bluetooth/smp.h | |||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index e73cd0637f3b..fe48b093d4dc 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
| @@ -334,6 +334,7 @@ enum ieee80211_sta_flags { | |||
| 334 | IEEE80211_STA_DISABLE_VHT = BIT(11), | 334 | IEEE80211_STA_DISABLE_VHT = BIT(11), |
| 335 | IEEE80211_STA_DISABLE_80P80MHZ = BIT(12), | 335 | IEEE80211_STA_DISABLE_80P80MHZ = BIT(12), |
| 336 | IEEE80211_STA_DISABLE_160MHZ = BIT(13), | 336 | IEEE80211_STA_DISABLE_160MHZ = BIT(13), |
| 337 | IEEE80211_STA_DISABLE_WMM = BIT(14), | ||
| 337 | }; | 338 | }; |
| 338 | 339 | ||
| 339 | struct ieee80211_mgd_auth_data { | 340 | struct ieee80211_mgd_auth_data { |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 91cc8281e266..d7bdc4b97dde 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
| @@ -2527,7 +2527,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
| 2527 | */ | 2527 | */ |
| 2528 | ifmgd->wmm_last_param_set = -1; | 2528 | ifmgd->wmm_last_param_set = -1; |
| 2529 | 2529 | ||
| 2530 | if (elems.wmm_param) | 2530 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_WMM) && elems.wmm_param) |
| 2531 | ieee80211_sta_wmm_params(local, sdata, elems.wmm_param, | 2531 | ieee80211_sta_wmm_params(local, sdata, elems.wmm_param, |
| 2532 | elems.wmm_param_len); | 2532 | elems.wmm_param_len); |
| 2533 | else | 2533 | else |
| @@ -2955,7 +2955,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
| 2955 | ieee80211_sta_process_chanswitch(sdata, rx_status->mactime, | 2955 | ieee80211_sta_process_chanswitch(sdata, rx_status->mactime, |
| 2956 | &elems, true); | 2956 | &elems, true); |
| 2957 | 2957 | ||
| 2958 | if (ieee80211_sta_wmm_params(local, sdata, elems.wmm_param, | 2958 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_WMM) && |
| 2959 | ieee80211_sta_wmm_params(local, sdata, elems.wmm_param, | ||
| 2959 | elems.wmm_param_len)) | 2960 | elems.wmm_param_len)) |
| 2960 | changed |= BSS_CHANGED_QOS; | 2961 | changed |= BSS_CHANGED_QOS; |
| 2961 | 2962 | ||
| @@ -3937,6 +3938,44 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, | |||
| 3937 | return err; | 3938 | return err; |
| 3938 | } | 3939 | } |
| 3939 | 3940 | ||
| 3941 | static bool ieee80211_usable_wmm_params(struct ieee80211_sub_if_data *sdata, | ||
| 3942 | const u8 *wmm_param, int len) | ||
| 3943 | { | ||
| 3944 | const u8 *pos; | ||
| 3945 | size_t left; | ||
| 3946 | |||
| 3947 | if (len < 8) | ||
| 3948 | return false; | ||
| 3949 | |||
| 3950 | if (wmm_param[5] != 1 /* version */) | ||
| 3951 | return false; | ||
| 3952 | |||
| 3953 | pos = wmm_param + 8; | ||
| 3954 | left = len - 8; | ||
| 3955 | |||
| 3956 | for (; left >= 4; left -= 4, pos += 4) { | ||
| 3957 | u8 aifsn = pos[0] & 0x0f; | ||
| 3958 | u8 ecwmin = pos[1] & 0x0f; | ||
| 3959 | u8 ecwmax = (pos[1] & 0xf0) >> 4; | ||
| 3960 | int aci = (pos[0] >> 5) & 0x03; | ||
| 3961 | |||
| 3962 | if (aifsn < 2) { | ||
| 3963 | sdata_info(sdata, | ||
| 3964 | "AP has invalid WMM params (AIFSN=%d for ACI %d), disabling WMM\n", | ||
| 3965 | aifsn, aci); | ||
| 3966 | return false; | ||
| 3967 | } | ||
| 3968 | if (ecwmin > ecwmax) { | ||
| 3969 | sdata_info(sdata, | ||
| 3970 | "AP has invalid WMM params (ECWmin/max=%d/%d for ACI %d), disabling WMM\n", | ||
| 3971 | ecwmin, ecwmax, aci); | ||
| 3972 | return false; | ||
| 3973 | } | ||
| 3974 | } | ||
| 3975 | |||
| 3976 | return true; | ||
| 3977 | } | ||
| 3978 | |||
| 3940 | int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | 3979 | int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, |
| 3941 | struct cfg80211_assoc_request *req) | 3980 | struct cfg80211_assoc_request *req) |
| 3942 | { | 3981 | { |
| @@ -3994,9 +4033,45 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
| 3994 | } | 4033 | } |
| 3995 | 4034 | ||
| 3996 | /* prepare assoc data */ | 4035 | /* prepare assoc data */ |
| 3997 | 4036 | ||
| 3998 | ifmgd->beacon_crc_valid = false; | 4037 | ifmgd->beacon_crc_valid = false; |
| 3999 | 4038 | ||
| 4039 | assoc_data->wmm = bss->wmm_used && | ||
| 4040 | (local->hw.queues >= IEEE80211_NUM_ACS); | ||
| 4041 | if (assoc_data->wmm) { | ||
| 4042 | /* try to check validity of WMM params IE */ | ||
| 4043 | const struct cfg80211_bss_ies *ies; | ||
| 4044 | const u8 *wp, *start, *end; | ||
| 4045 | |||
| 4046 | rcu_read_lock(); | ||
| 4047 | ies = rcu_dereference(req->bss->ies); | ||
| 4048 | start = ies->data; | ||
| 4049 | end = start + ies->len; | ||
| 4050 | |||
| 4051 | while (true) { | ||
| 4052 | wp = cfg80211_find_vendor_ie( | ||
| 4053 | WLAN_OUI_MICROSOFT, | ||
| 4054 | WLAN_OUI_TYPE_MICROSOFT_WMM, | ||
| 4055 | start, end - start); | ||
| 4056 | if (!wp) | ||
| 4057 | break; | ||
| 4058 | start = wp + wp[1] + 2; | ||
| 4059 | /* if this IE is too short, try the next */ | ||
| 4060 | if (wp[1] <= 4) | ||
| 4061 | continue; | ||
| 4062 | /* if this IE is WMM params, we found what we wanted */ | ||
| 4063 | if (wp[6] == 1) | ||
| 4064 | break; | ||
| 4065 | } | ||
| 4066 | |||
| 4067 | if (!wp || !ieee80211_usable_wmm_params(sdata, wp + 2, | ||
| 4068 | wp[1] - 2)) { | ||
| 4069 | assoc_data->wmm = false; | ||
| 4070 | ifmgd->flags |= IEEE80211_STA_DISABLE_WMM; | ||
| 4071 | } | ||
| 4072 | rcu_read_unlock(); | ||
| 4073 | } | ||
| 4074 | |||
| 4000 | /* | 4075 | /* |
| 4001 | * IEEE802.11n does not allow TKIP/WEP as pairwise ciphers in HT mode. | 4076 | * IEEE802.11n does not allow TKIP/WEP as pairwise ciphers in HT mode. |
| 4002 | * We still associate in non-HT mode (11a/b/g) if any one of these | 4077 | * We still associate in non-HT mode (11a/b/g) if any one of these |
| @@ -4026,18 +4101,22 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
| 4026 | /* Also disable HT if we don't support it or the AP doesn't use WMM */ | 4101 | /* Also disable HT if we don't support it or the AP doesn't use WMM */ |
| 4027 | sband = local->hw.wiphy->bands[req->bss->channel->band]; | 4102 | sband = local->hw.wiphy->bands[req->bss->channel->band]; |
| 4028 | if (!sband->ht_cap.ht_supported || | 4103 | if (!sband->ht_cap.ht_supported || |
| 4029 | local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) { | 4104 | local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used || |
| 4105 | ifmgd->flags & IEEE80211_STA_DISABLE_WMM) { | ||
| 4030 | ifmgd->flags |= IEEE80211_STA_DISABLE_HT; | 4106 | ifmgd->flags |= IEEE80211_STA_DISABLE_HT; |
| 4031 | if (!bss->wmm_used) | 4107 | if (!bss->wmm_used && |
| 4108 | !(ifmgd->flags & IEEE80211_STA_DISABLE_WMM)) | ||
| 4032 | netdev_info(sdata->dev, | 4109 | netdev_info(sdata->dev, |
| 4033 | "disabling HT as WMM/QoS is not supported by the AP\n"); | 4110 | "disabling HT as WMM/QoS is not supported by the AP\n"); |
| 4034 | } | 4111 | } |
| 4035 | 4112 | ||
| 4036 | /* disable VHT if we don't support it or the AP doesn't use WMM */ | 4113 | /* disable VHT if we don't support it or the AP doesn't use WMM */ |
| 4037 | if (!sband->vht_cap.vht_supported || | 4114 | if (!sband->vht_cap.vht_supported || |
| 4038 | local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) { | 4115 | local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used || |
| 4116 | ifmgd->flags & IEEE80211_STA_DISABLE_WMM) { | ||
| 4039 | ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; | 4117 | ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; |
| 4040 | if (!bss->wmm_used) | 4118 | if (!bss->wmm_used && |
| 4119 | !(ifmgd->flags & IEEE80211_STA_DISABLE_WMM)) | ||
| 4041 | netdev_info(sdata->dev, | 4120 | netdev_info(sdata->dev, |
| 4042 | "disabling VHT as WMM/QoS is not supported by the AP\n"); | 4121 | "disabling VHT as WMM/QoS is not supported by the AP\n"); |
| 4043 | } | 4122 | } |
| @@ -4066,8 +4145,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
| 4066 | sdata->smps_mode = ifmgd->req_smps; | 4145 | sdata->smps_mode = ifmgd->req_smps; |
| 4067 | 4146 | ||
| 4068 | assoc_data->capability = req->bss->capability; | 4147 | assoc_data->capability = req->bss->capability; |
| 4069 | assoc_data->wmm = bss->wmm_used && | ||
| 4070 | (local->hw.queues >= IEEE80211_NUM_ACS); | ||
| 4071 | assoc_data->supp_rates = bss->supp_rates; | 4148 | assoc_data->supp_rates = bss->supp_rates; |
| 4072 | assoc_data->supp_rates_len = bss->supp_rates_len; | 4149 | assoc_data->supp_rates_len = bss->supp_rates_len; |
| 4073 | 4150 | ||
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index e126605cec66..22b223f13c9f 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
| @@ -235,7 +235,8 @@ static void rc_send_low_basicrate(s8 *idx, u32 basic_rates, | |||
| 235 | static void __rate_control_send_low(struct ieee80211_hw *hw, | 235 | static void __rate_control_send_low(struct ieee80211_hw *hw, |
| 236 | struct ieee80211_supported_band *sband, | 236 | struct ieee80211_supported_band *sband, |
| 237 | struct ieee80211_sta *sta, | 237 | struct ieee80211_sta *sta, |
| 238 | struct ieee80211_tx_info *info) | 238 | struct ieee80211_tx_info *info, |
| 239 | u32 rate_mask) | ||
| 239 | { | 240 | { |
| 240 | int i; | 241 | int i; |
| 241 | u32 rate_flags = | 242 | u32 rate_flags = |
| @@ -247,6 +248,12 @@ static void __rate_control_send_low(struct ieee80211_hw *hw, | |||
| 247 | 248 | ||
| 248 | info->control.rates[0].idx = 0; | 249 | info->control.rates[0].idx = 0; |
| 249 | for (i = 0; i < sband->n_bitrates; i++) { | 250 | for (i = 0; i < sband->n_bitrates; i++) { |
| 251 | if (!(rate_mask & BIT(i))) | ||
| 252 | continue; | ||
| 253 | |||
| 254 | if ((rate_flags & sband->bitrates[i].flags) != rate_flags) | ||
| 255 | continue; | ||
| 256 | |||
| 250 | if (!rate_supported(sta, sband->band, i)) | 257 | if (!rate_supported(sta, sband->band, i)) |
| 251 | continue; | 258 | continue; |
| 252 | 259 | ||
| @@ -274,7 +281,8 @@ bool rate_control_send_low(struct ieee80211_sta *pubsta, | |||
| 274 | bool use_basicrate = false; | 281 | bool use_basicrate = false; |
| 275 | 282 | ||
| 276 | if (!pubsta || !priv_sta || rc_no_data_or_no_ack_use_min(txrc)) { | 283 | if (!pubsta || !priv_sta || rc_no_data_or_no_ack_use_min(txrc)) { |
| 277 | __rate_control_send_low(txrc->hw, sband, pubsta, info); | 284 | __rate_control_send_low(txrc->hw, sband, pubsta, info, |
| 285 | txrc->rate_idx_mask); | ||
| 278 | 286 | ||
| 279 | if (!pubsta && txrc->bss) { | 287 | if (!pubsta && txrc->bss) { |
| 280 | mcast_rate = txrc->bss_conf->mcast_rate[sband->band]; | 288 | mcast_rate = txrc->bss_conf->mcast_rate[sband->band]; |
| @@ -656,7 +664,8 @@ void ieee80211_get_tx_rates(struct ieee80211_vif *vif, | |||
| 656 | rate_control_apply_mask(sdata, sta, sband, info, dest, max_rates); | 664 | rate_control_apply_mask(sdata, sta, sband, info, dest, max_rates); |
| 657 | 665 | ||
| 658 | if (dest[0].idx < 0) | 666 | if (dest[0].idx < 0) |
| 659 | __rate_control_send_low(&sdata->local->hw, sband, sta, info); | 667 | __rate_control_send_low(&sdata->local->hw, sband, sta, info, |
| 668 | sdata->rc_rateidx_mask[info->band]); | ||
| 660 | 669 | ||
| 661 | if (sta) | 670 | if (sta) |
| 662 | rate_fixup_ratelist(vif, sband, info, dest, max_rates); | 671 | rate_fixup_ratelist(vif, sband, info, dest, max_rates); |
diff --git a/net/nfc/Kconfig b/net/nfc/Kconfig index 5948b2fc72f6..6e0fa0cce198 100644 --- a/net/nfc/Kconfig +++ b/net/nfc/Kconfig | |||
| @@ -14,6 +14,20 @@ menuconfig NFC | |||
| 14 | To compile this support as a module, choose M here: the module will | 14 | To compile this support as a module, choose M here: the module will |
| 15 | be called nfc. | 15 | be called nfc. |
| 16 | 16 | ||
| 17 | config NFC_DIGITAL | ||
| 18 | depends on NFC | ||
| 19 | select CRC_CCITT | ||
| 20 | select CRC_ITU_T | ||
| 21 | tristate "NFC Digital Protocol stack support" | ||
| 22 | default n | ||
| 23 | help | ||
| 24 | Say Y if you want to build NFC digital protocol stack support. | ||
| 25 | This is needed by NFC chipsets whose firmware only implement | ||
| 26 | the NFC analog layer. | ||
| 27 | |||
| 28 | To compile this support as a module, choose M here: the module will | ||
| 29 | be called nfc_digital. | ||
| 30 | |||
| 17 | source "net/nfc/nci/Kconfig" | 31 | source "net/nfc/nci/Kconfig" |
| 18 | source "net/nfc/hci/Kconfig" | 32 | source "net/nfc/hci/Kconfig" |
| 19 | 33 | ||
diff --git a/net/nfc/Makefile b/net/nfc/Makefile index a76f4533cb6c..2555ff8e7219 100644 --- a/net/nfc/Makefile +++ b/net/nfc/Makefile | |||
| @@ -5,7 +5,9 @@ | |||
| 5 | obj-$(CONFIG_NFC) += nfc.o | 5 | obj-$(CONFIG_NFC) += nfc.o |
| 6 | obj-$(CONFIG_NFC_NCI) += nci/ | 6 | obj-$(CONFIG_NFC_NCI) += nci/ |
| 7 | obj-$(CONFIG_NFC_HCI) += hci/ | 7 | obj-$(CONFIG_NFC_HCI) += hci/ |
| 8 | obj-$(CONFIG_NFC_DIGITAL) += nfc_digital.o | ||
| 8 | 9 | ||
| 9 | nfc-objs := core.o netlink.o af_nfc.o rawsock.o llcp_core.o llcp_commands.o \ | 10 | nfc-objs := core.o netlink.o af_nfc.o rawsock.o llcp_core.o llcp_commands.o \ |
| 10 | llcp_sock.o | 11 | llcp_sock.o |
| 11 | 12 | ||
| 13 | nfc_digital-objs := digital_core.o digital_technology.o digital_dep.o | ||
diff --git a/net/nfc/core.c b/net/nfc/core.c index e92923cf3e03..872529105abc 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c | |||
| @@ -384,6 +384,19 @@ int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx, | |||
| 384 | { | 384 | { |
| 385 | dev->dep_link_up = true; | 385 | dev->dep_link_up = true; |
| 386 | 386 | ||
| 387 | if (!dev->active_target) { | ||
| 388 | struct nfc_target *target; | ||
| 389 | |||
| 390 | target = nfc_find_target(dev, target_idx); | ||
| 391 | if (target == NULL) | ||
| 392 | return -ENOTCONN; | ||
| 393 | |||
| 394 | dev->active_target = target; | ||
| 395 | } | ||
| 396 | |||
| 397 | dev->polling = false; | ||
| 398 | dev->rf_mode = rf_mode; | ||
| 399 | |||
| 387 | nfc_llcp_mac_is_up(dev, target_idx, comm_mode, rf_mode); | 400 | nfc_llcp_mac_is_up(dev, target_idx, comm_mode, rf_mode); |
| 388 | 401 | ||
| 389 | return nfc_genl_dep_link_up_event(dev, target_idx, comm_mode, rf_mode); | 402 | return nfc_genl_dep_link_up_event(dev, target_idx, comm_mode, rf_mode); |
| @@ -536,7 +549,7 @@ error: | |||
| 536 | return rc; | 549 | return rc; |
| 537 | } | 550 | } |
| 538 | 551 | ||
| 539 | static struct nfc_se *find_se(struct nfc_dev *dev, u32 se_idx) | 552 | struct nfc_se *nfc_find_se(struct nfc_dev *dev, u32 se_idx) |
| 540 | { | 553 | { |
| 541 | struct nfc_se *se, *n; | 554 | struct nfc_se *se, *n; |
| 542 | 555 | ||
| @@ -546,6 +559,7 @@ static struct nfc_se *find_se(struct nfc_dev *dev, u32 se_idx) | |||
| 546 | 559 | ||
| 547 | return NULL; | 560 | return NULL; |
| 548 | } | 561 | } |
| 562 | EXPORT_SYMBOL(nfc_find_se); | ||
| 549 | 563 | ||
| 550 | int nfc_enable_se(struct nfc_dev *dev, u32 se_idx) | 564 | int nfc_enable_se(struct nfc_dev *dev, u32 se_idx) |
| 551 | { | 565 | { |
| @@ -577,7 +591,7 @@ int nfc_enable_se(struct nfc_dev *dev, u32 se_idx) | |||
| 577 | goto error; | 591 | goto error; |
| 578 | } | 592 | } |
| 579 | 593 | ||
| 580 | se = find_se(dev, se_idx); | 594 | se = nfc_find_se(dev, se_idx); |
| 581 | if (!se) { | 595 | if (!se) { |
| 582 | rc = -EINVAL; | 596 | rc = -EINVAL; |
| 583 | goto error; | 597 | goto error; |
| @@ -622,7 +636,7 @@ int nfc_disable_se(struct nfc_dev *dev, u32 se_idx) | |||
| 622 | goto error; | 636 | goto error; |
| 623 | } | 637 | } |
| 624 | 638 | ||
| 625 | se = find_se(dev, se_idx); | 639 | se = nfc_find_se(dev, se_idx); |
| 626 | if (!se) { | 640 | if (!se) { |
| 627 | rc = -EINVAL; | 641 | rc = -EINVAL; |
| 628 | goto error; | 642 | goto error; |
| @@ -881,7 +895,7 @@ int nfc_add_se(struct nfc_dev *dev, u32 se_idx, u16 type) | |||
| 881 | 895 | ||
| 882 | pr_debug("%s se index %d\n", dev_name(&dev->dev), se_idx); | 896 | pr_debug("%s se index %d\n", dev_name(&dev->dev), se_idx); |
| 883 | 897 | ||
| 884 | se = find_se(dev, se_idx); | 898 | se = nfc_find_se(dev, se_idx); |
| 885 | if (se) | 899 | if (se) |
| 886 | return -EALREADY; | 900 | return -EALREADY; |
| 887 | 901 | ||
diff --git a/net/nfc/digital.h b/net/nfc/digital.h new file mode 100644 index 000000000000..08b29b55ea63 --- /dev/null +++ b/net/nfc/digital.h | |||
| @@ -0,0 +1,170 @@ | |||
| 1 | /* | ||
| 2 | * NFC Digital Protocol stack | ||
| 3 | * Copyright (c) 2013, Intel Corporation. | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify it | ||
| 6 | * under the terms and conditions of the GNU General Public License, | ||
| 7 | * version 2, as published by the Free Software Foundation. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
| 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 12 | * more details. | ||
| 13 | * | ||
| 14 | */ | ||
| 15 | |||
| 16 | #ifndef __DIGITAL_H | ||
| 17 | #define __DIGITAL_H | ||
| 18 | |||
| 19 | #include <net/nfc/nfc.h> | ||
| 20 | #include <net/nfc/digital.h> | ||
| 21 | |||
| 22 | #include <linux/crc-ccitt.h> | ||
| 23 | #include <linux/crc-itu-t.h> | ||
| 24 | |||
| 25 | #define PROTOCOL_ERR(req) pr_err("%d: NFC Digital Protocol error: %s\n", \ | ||
| 26 | __LINE__, req) | ||
| 27 | |||
| 28 | #define DIGITAL_CMD_IN_SEND 0 | ||
| 29 | #define DIGITAL_CMD_TG_SEND 1 | ||
| 30 | #define DIGITAL_CMD_TG_LISTEN 2 | ||
| 31 | #define DIGITAL_CMD_TG_LISTEN_MDAA 3 | ||
| 32 | |||
| 33 | #define DIGITAL_MAX_HEADER_LEN 7 | ||
| 34 | #define DIGITAL_CRC_LEN 2 | ||
| 35 | |||
| 36 | #define DIGITAL_SENSF_NFCID2_NFC_DEP_B1 0x01 | ||
| 37 | #define DIGITAL_SENSF_NFCID2_NFC_DEP_B2 0xFE | ||
| 38 | |||
| 39 | #define DIGITAL_SENS_RES_NFC_DEP 0x0100 | ||
| 40 | #define DIGITAL_SEL_RES_NFC_DEP 0x40 | ||
| 41 | #define DIGITAL_SENSF_FELICA_SC 0xFFFF | ||
| 42 | |||
| 43 | #define DIGITAL_DRV_CAPS_IN_CRC(ddev) \ | ||
| 44 | ((ddev)->driver_capabilities & NFC_DIGITAL_DRV_CAPS_IN_CRC) | ||
| 45 | #define DIGITAL_DRV_CAPS_TG_CRC(ddev) \ | ||
| 46 | ((ddev)->driver_capabilities & NFC_DIGITAL_DRV_CAPS_TG_CRC) | ||
| 47 | |||
| 48 | struct digital_data_exch { | ||
| 49 | data_exchange_cb_t cb; | ||
| 50 | void *cb_context; | ||
| 51 | }; | ||
| 52 | |||
| 53 | struct sk_buff *digital_skb_alloc(struct nfc_digital_dev *ddev, | ||
| 54 | unsigned int len); | ||
| 55 | |||
| 56 | int digital_send_cmd(struct nfc_digital_dev *ddev, u8 cmd_type, | ||
| 57 | struct sk_buff *skb, struct digital_tg_mdaa_params *params, | ||
| 58 | u16 timeout, nfc_digital_cmd_complete_t cmd_cb, | ||
| 59 | void *cb_context); | ||
| 60 | |||
| 61 | int digital_in_configure_hw(struct nfc_digital_dev *ddev, int type, int param); | ||
| 62 | static inline int digital_in_send_cmd(struct nfc_digital_dev *ddev, | ||
| 63 | struct sk_buff *skb, u16 timeout, | ||
| 64 | nfc_digital_cmd_complete_t cmd_cb, | ||
| 65 | void *cb_context) | ||
| 66 | { | ||
| 67 | return digital_send_cmd(ddev, DIGITAL_CMD_IN_SEND, skb, NULL, timeout, | ||
| 68 | cmd_cb, cb_context); | ||
| 69 | } | ||
| 70 | |||
| 71 | void digital_poll_next_tech(struct nfc_digital_dev *ddev); | ||
| 72 | |||
| 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); | ||
| 75 | |||
| 76 | int digital_target_found(struct nfc_digital_dev *ddev, | ||
| 77 | struct nfc_target *target, u8 protocol); | ||
| 78 | |||
| 79 | int digital_in_recv_mifare_res(struct sk_buff *resp); | ||
| 80 | |||
| 81 | int digital_in_send_atr_req(struct nfc_digital_dev *ddev, | ||
| 82 | struct nfc_target *target, __u8 comm_mode, __u8 *gb, | ||
| 83 | size_t gb_len); | ||
| 84 | int digital_in_send_dep_req(struct nfc_digital_dev *ddev, | ||
| 85 | struct nfc_target *target, struct sk_buff *skb, | ||
| 86 | struct digital_data_exch *data_exch); | ||
| 87 | |||
| 88 | int digital_tg_configure_hw(struct nfc_digital_dev *ddev, int type, int param); | ||
| 89 | static inline int digital_tg_send_cmd(struct nfc_digital_dev *ddev, | ||
| 90 | struct sk_buff *skb, u16 timeout, | ||
| 91 | nfc_digital_cmd_complete_t cmd_cb, void *cb_context) | ||
| 92 | { | ||
| 93 | return digital_send_cmd(ddev, DIGITAL_CMD_TG_SEND, skb, NULL, timeout, | ||
| 94 | cmd_cb, cb_context); | ||
| 95 | } | ||
| 96 | |||
| 97 | void digital_tg_recv_sens_req(struct nfc_digital_dev *ddev, void *arg, | ||
| 98 | struct sk_buff *resp); | ||
| 99 | |||
| 100 | void digital_tg_recv_sensf_req(struct nfc_digital_dev *ddev, void *arg, | ||
| 101 | struct sk_buff *resp); | ||
| 102 | |||
| 103 | static inline int digital_tg_listen(struct nfc_digital_dev *ddev, u16 timeout, | ||
| 104 | nfc_digital_cmd_complete_t cb, void *arg) | ||
| 105 | { | ||
| 106 | return digital_send_cmd(ddev, DIGITAL_CMD_TG_LISTEN, NULL, NULL, | ||
| 107 | timeout, cb, arg); | ||
| 108 | } | ||
| 109 | |||
| 110 | void digital_tg_recv_atr_req(struct nfc_digital_dev *ddev, void *arg, | ||
| 111 | struct sk_buff *resp); | ||
| 112 | |||
| 113 | int digital_tg_send_dep_res(struct nfc_digital_dev *ddev, struct sk_buff *skb); | ||
| 114 | |||
| 115 | int digital_tg_listen_nfca(struct nfc_digital_dev *ddev, u8 rf_tech); | ||
| 116 | int digital_tg_listen_nfcf(struct nfc_digital_dev *ddev, u8 rf_tech); | ||
| 117 | |||
| 118 | typedef u16 (*crc_func_t)(u16, const u8 *, size_t); | ||
| 119 | |||
| 120 | #define CRC_A_INIT 0x6363 | ||
| 121 | #define CRC_B_INIT 0xFFFF | ||
| 122 | #define CRC_F_INIT 0x0000 | ||
| 123 | |||
| 124 | void digital_skb_add_crc(struct sk_buff *skb, crc_func_t crc_func, u16 init, | ||
| 125 | u8 bitwise_inv, u8 msb_first); | ||
| 126 | |||
| 127 | static inline void digital_skb_add_crc_a(struct sk_buff *skb) | ||
| 128 | { | ||
| 129 | digital_skb_add_crc(skb, crc_ccitt, CRC_A_INIT, 0, 0); | ||
| 130 | } | ||
| 131 | |||
| 132 | static inline void digital_skb_add_crc_b(struct sk_buff *skb) | ||
| 133 | { | ||
| 134 | digital_skb_add_crc(skb, crc_ccitt, CRC_B_INIT, 1, 0); | ||
| 135 | } | ||
| 136 | |||
| 137 | static inline void digital_skb_add_crc_f(struct sk_buff *skb) | ||
| 138 | { | ||
| 139 | digital_skb_add_crc(skb, crc_itu_t, CRC_F_INIT, 0, 1); | ||
| 140 | } | ||
| 141 | |||
| 142 | static inline void digital_skb_add_crc_none(struct sk_buff *skb) | ||
| 143 | { | ||
| 144 | return; | ||
| 145 | } | ||
| 146 | |||
| 147 | int digital_skb_check_crc(struct sk_buff *skb, crc_func_t crc_func, | ||
| 148 | u16 crc_init, u8 bitwise_inv, u8 msb_first); | ||
| 149 | |||
| 150 | static inline int digital_skb_check_crc_a(struct sk_buff *skb) | ||
| 151 | { | ||
| 152 | return digital_skb_check_crc(skb, crc_ccitt, CRC_A_INIT, 0, 0); | ||
| 153 | } | ||
| 154 | |||
| 155 | static inline int digital_skb_check_crc_b(struct sk_buff *skb) | ||
| 156 | { | ||
| 157 | return digital_skb_check_crc(skb, crc_ccitt, CRC_B_INIT, 1, 0); | ||
| 158 | } | ||
| 159 | |||
| 160 | static inline int digital_skb_check_crc_f(struct sk_buff *skb) | ||
| 161 | { | ||
| 162 | return digital_skb_check_crc(skb, crc_itu_t, CRC_F_INIT, 0, 1); | ||
| 163 | } | ||
| 164 | |||
| 165 | static inline int digital_skb_check_crc_none(struct sk_buff *skb) | ||
| 166 | { | ||
| 167 | return 0; | ||
| 168 | } | ||
| 169 | |||
| 170 | #endif /* __DIGITAL_H */ | ||
diff --git a/net/nfc/digital_core.c b/net/nfc/digital_core.c new file mode 100644 index 000000000000..09fc95439955 --- /dev/null +++ b/net/nfc/digital_core.c | |||
| @@ -0,0 +1,737 @@ | |||
| 1 | /* | ||
| 2 | * NFC Digital Protocol stack | ||
| 3 | * Copyright (c) 2013, Intel Corporation. | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify it | ||
| 6 | * under the terms and conditions of the GNU General Public License, | ||
| 7 | * version 2, as published by the Free Software Foundation. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
| 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 12 | * more details. | ||
| 13 | * | ||
| 14 | */ | ||
| 15 | |||
| 16 | #define pr_fmt(fmt) "digital: %s: " fmt, __func__ | ||
| 17 | |||
| 18 | #include <linux/module.h> | ||
| 19 | |||
| 20 | #include "digital.h" | ||
| 21 | |||
| 22 | #define DIGITAL_PROTO_NFCA_RF_TECH \ | ||
| 23 | (NFC_PROTO_JEWEL_MASK | NFC_PROTO_MIFARE_MASK | NFC_PROTO_NFC_DEP_MASK) | ||
| 24 | |||
| 25 | #define DIGITAL_PROTO_NFCF_RF_TECH \ | ||
| 26 | (NFC_PROTO_FELICA_MASK | NFC_PROTO_NFC_DEP_MASK) | ||
| 27 | |||
| 28 | struct digital_cmd { | ||
| 29 | struct list_head queue; | ||
| 30 | |||
| 31 | u8 type; | ||
| 32 | u8 pending; | ||
| 33 | |||
| 34 | u16 timeout; | ||
| 35 | struct sk_buff *req; | ||
| 36 | struct sk_buff *resp; | ||
| 37 | struct digital_tg_mdaa_params *mdaa_params; | ||
| 38 | |||
| 39 | nfc_digital_cmd_complete_t cmd_cb; | ||
| 40 | void *cb_context; | ||
| 41 | }; | ||
| 42 | |||
| 43 | struct sk_buff *digital_skb_alloc(struct nfc_digital_dev *ddev, | ||
| 44 | unsigned int len) | ||
| 45 | { | ||
| 46 | struct sk_buff *skb; | ||
| 47 | |||
| 48 | skb = alloc_skb(len + ddev->tx_headroom + ddev->tx_tailroom, | ||
| 49 | GFP_KERNEL); | ||
| 50 | if (skb) | ||
| 51 | skb_reserve(skb, ddev->tx_headroom); | ||
| 52 | |||
| 53 | return skb; | ||
| 54 | } | ||
| 55 | |||
| 56 | void digital_skb_add_crc(struct sk_buff *skb, crc_func_t crc_func, u16 init, | ||
| 57 | u8 bitwise_inv, u8 msb_first) | ||
| 58 | { | ||
| 59 | u16 crc; | ||
| 60 | |||
| 61 | crc = crc_func(init, skb->data, skb->len); | ||
| 62 | |||
| 63 | if (bitwise_inv) | ||
| 64 | crc = ~crc; | ||
| 65 | |||
| 66 | if (msb_first) | ||
| 67 | crc = __fswab16(crc); | ||
| 68 | |||
| 69 | *skb_put(skb, 1) = crc & 0xFF; | ||
| 70 | *skb_put(skb, 1) = (crc >> 8) & 0xFF; | ||
| 71 | } | ||
| 72 | |||
| 73 | int digital_skb_check_crc(struct sk_buff *skb, crc_func_t crc_func, | ||
| 74 | u16 crc_init, u8 bitwise_inv, u8 msb_first) | ||
| 75 | { | ||
| 76 | int rc; | ||
| 77 | u16 crc; | ||
| 78 | |||
| 79 | if (skb->len <= 2) | ||
| 80 | return -EIO; | ||
| 81 | |||
| 82 | crc = crc_func(crc_init, skb->data, skb->len - 2); | ||
| 83 | |||
| 84 | if (bitwise_inv) | ||
| 85 | crc = ~crc; | ||
| 86 | |||
| 87 | if (msb_first) | ||
| 88 | crc = __swab16(crc); | ||
| 89 | |||
| 90 | rc = (skb->data[skb->len - 2] - (crc & 0xFF)) + | ||
| 91 | (skb->data[skb->len - 1] - ((crc >> 8) & 0xFF)); | ||
| 92 | |||
| 93 | if (rc) | ||
| 94 | return -EIO; | ||
| 95 | |||
| 96 | skb_trim(skb, skb->len - 2); | ||
| 97 | |||
| 98 | return 0; | ||
| 99 | } | ||
| 100 | |||
| 101 | static inline void digital_switch_rf(struct nfc_digital_dev *ddev, bool on) | ||
| 102 | { | ||
| 103 | ddev->ops->switch_rf(ddev, on); | ||
| 104 | } | ||
| 105 | |||
| 106 | static inline void digital_abort_cmd(struct nfc_digital_dev *ddev) | ||
| 107 | { | ||
| 108 | ddev->ops->abort_cmd(ddev); | ||
| 109 | } | ||
| 110 | |||
| 111 | static void digital_wq_cmd_complete(struct work_struct *work) | ||
| 112 | { | ||
| 113 | struct digital_cmd *cmd; | ||
| 114 | struct nfc_digital_dev *ddev = container_of(work, | ||
| 115 | struct nfc_digital_dev, | ||
| 116 | cmd_complete_work); | ||
| 117 | |||
| 118 | mutex_lock(&ddev->cmd_lock); | ||
| 119 | |||
| 120 | cmd = list_first_entry_or_null(&ddev->cmd_queue, struct digital_cmd, | ||
| 121 | queue); | ||
| 122 | if (!cmd) { | ||
| 123 | mutex_unlock(&ddev->cmd_lock); | ||
| 124 | return; | ||
| 125 | } | ||
| 126 | |||
| 127 | list_del(&cmd->queue); | ||
| 128 | |||
| 129 | mutex_unlock(&ddev->cmd_lock); | ||
| 130 | |||
| 131 | if (!IS_ERR(cmd->resp)) | ||
| 132 | print_hex_dump_debug("DIGITAL RX: ", DUMP_PREFIX_NONE, 16, 1, | ||
| 133 | cmd->resp->data, cmd->resp->len, false); | ||
| 134 | |||
| 135 | cmd->cmd_cb(ddev, cmd->cb_context, cmd->resp); | ||
| 136 | |||
| 137 | kfree(cmd->mdaa_params); | ||
| 138 | kfree(cmd); | ||
| 139 | |||
| 140 | schedule_work(&ddev->cmd_work); | ||
| 141 | } | ||
| 142 | |||
| 143 | static void digital_send_cmd_complete(struct nfc_digital_dev *ddev, | ||
| 144 | void *arg, struct sk_buff *resp) | ||
| 145 | { | ||
| 146 | struct digital_cmd *cmd = arg; | ||
| 147 | |||
| 148 | cmd->resp = resp; | ||
| 149 | |||
| 150 | schedule_work(&ddev->cmd_complete_work); | ||
| 151 | } | ||
| 152 | |||
| 153 | static void digital_wq_cmd(struct work_struct *work) | ||
| 154 | { | ||
| 155 | int rc; | ||
| 156 | struct digital_cmd *cmd; | ||
| 157 | struct digital_tg_mdaa_params *params; | ||
| 158 | struct nfc_digital_dev *ddev = container_of(work, | ||
| 159 | struct nfc_digital_dev, | ||
| 160 | cmd_work); | ||
| 161 | |||
| 162 | mutex_lock(&ddev->cmd_lock); | ||
| 163 | |||
| 164 | cmd = list_first_entry_or_null(&ddev->cmd_queue, struct digital_cmd, | ||
| 165 | queue); | ||
| 166 | if (!cmd || cmd->pending) { | ||
| 167 | mutex_unlock(&ddev->cmd_lock); | ||
| 168 | return; | ||
| 169 | } | ||
| 170 | |||
| 171 | mutex_unlock(&ddev->cmd_lock); | ||
| 172 | |||
| 173 | if (cmd->req) | ||
| 174 | print_hex_dump_debug("DIGITAL TX: ", DUMP_PREFIX_NONE, 16, 1, | ||
| 175 | cmd->req->data, cmd->req->len, false); | ||
| 176 | |||
| 177 | switch (cmd->type) { | ||
| 178 | case DIGITAL_CMD_IN_SEND: | ||
| 179 | rc = ddev->ops->in_send_cmd(ddev, cmd->req, cmd->timeout, | ||
| 180 | digital_send_cmd_complete, cmd); | ||
| 181 | break; | ||
| 182 | |||
| 183 | case DIGITAL_CMD_TG_SEND: | ||
| 184 | rc = ddev->ops->tg_send_cmd(ddev, cmd->req, cmd->timeout, | ||
| 185 | digital_send_cmd_complete, cmd); | ||
| 186 | break; | ||
| 187 | |||
| 188 | case DIGITAL_CMD_TG_LISTEN: | ||
| 189 | rc = ddev->ops->tg_listen(ddev, cmd->timeout, | ||
| 190 | digital_send_cmd_complete, cmd); | ||
| 191 | break; | ||
| 192 | |||
| 193 | case DIGITAL_CMD_TG_LISTEN_MDAA: | ||
| 194 | params = cmd->mdaa_params; | ||
| 195 | |||
| 196 | rc = ddev->ops->tg_listen_mdaa(ddev, params, cmd->timeout, | ||
| 197 | digital_send_cmd_complete, cmd); | ||
| 198 | break; | ||
| 199 | |||
| 200 | default: | ||
| 201 | pr_err("Unknown cmd type %d\n", cmd->type); | ||
| 202 | return; | ||
| 203 | } | ||
| 204 | |||
| 205 | if (!rc) | ||
| 206 | return; | ||
| 207 | |||
| 208 | pr_err("in_send_command returned err %d\n", rc); | ||
| 209 | |||
| 210 | mutex_lock(&ddev->cmd_lock); | ||
| 211 | list_del(&cmd->queue); | ||
| 212 | mutex_unlock(&ddev->cmd_lock); | ||
| 213 | |||
| 214 | kfree_skb(cmd->req); | ||
| 215 | kfree(cmd->mdaa_params); | ||
| 216 | kfree(cmd); | ||
| 217 | |||
| 218 | schedule_work(&ddev->cmd_work); | ||
| 219 | } | ||
| 220 | |||
| 221 | int digital_send_cmd(struct nfc_digital_dev *ddev, u8 cmd_type, | ||
| 222 | struct sk_buff *skb, struct digital_tg_mdaa_params *params, | ||
| 223 | u16 timeout, nfc_digital_cmd_complete_t cmd_cb, | ||
| 224 | void *cb_context) | ||
| 225 | { | ||
| 226 | struct digital_cmd *cmd; | ||
| 227 | |||
| 228 | cmd = kzalloc(sizeof(struct digital_cmd), GFP_KERNEL); | ||
| 229 | if (!cmd) | ||
| 230 | return -ENOMEM; | ||
| 231 | |||
| 232 | cmd->type = cmd_type; | ||
| 233 | cmd->timeout = timeout; | ||
| 234 | cmd->req = skb; | ||
| 235 | cmd->mdaa_params = params; | ||
| 236 | cmd->cmd_cb = cmd_cb; | ||
| 237 | cmd->cb_context = cb_context; | ||
| 238 | INIT_LIST_HEAD(&cmd->queue); | ||
| 239 | |||
| 240 | mutex_lock(&ddev->cmd_lock); | ||
| 241 | list_add_tail(&cmd->queue, &ddev->cmd_queue); | ||
| 242 | mutex_unlock(&ddev->cmd_lock); | ||
| 243 | |||
| 244 | schedule_work(&ddev->cmd_work); | ||
| 245 | |||
| 246 | return 0; | ||
| 247 | } | ||
| 248 | |||
| 249 | int digital_in_configure_hw(struct nfc_digital_dev *ddev, int type, int param) | ||
| 250 | { | ||
| 251 | int rc; | ||
| 252 | |||
| 253 | rc = ddev->ops->in_configure_hw(ddev, type, param); | ||
| 254 | if (rc) | ||
| 255 | pr_err("in_configure_hw failed: %d\n", rc); | ||
| 256 | |||
| 257 | return rc; | ||
| 258 | } | ||
| 259 | |||
| 260 | int digital_tg_configure_hw(struct nfc_digital_dev *ddev, int type, int param) | ||
| 261 | { | ||
| 262 | int rc; | ||
| 263 | |||
| 264 | rc = ddev->ops->tg_configure_hw(ddev, type, param); | ||
| 265 | if (rc) | ||
| 266 | pr_err("tg_configure_hw failed: %d\n", rc); | ||
| 267 | |||
| 268 | return rc; | ||
| 269 | } | ||
| 270 | |||
| 271 | static int digital_tg_listen_mdaa(struct nfc_digital_dev *ddev, u8 rf_tech) | ||
| 272 | { | ||
| 273 | struct digital_tg_mdaa_params *params; | ||
| 274 | |||
| 275 | params = kzalloc(sizeof(struct digital_tg_mdaa_params), GFP_KERNEL); | ||
| 276 | if (!params) | ||
| 277 | return -ENOMEM; | ||
| 278 | |||
| 279 | params->sens_res = DIGITAL_SENS_RES_NFC_DEP; | ||
| 280 | get_random_bytes(params->nfcid1, sizeof(params->nfcid1)); | ||
| 281 | params->sel_res = DIGITAL_SEL_RES_NFC_DEP; | ||
| 282 | |||
| 283 | params->nfcid2[0] = DIGITAL_SENSF_NFCID2_NFC_DEP_B1; | ||
| 284 | params->nfcid2[1] = DIGITAL_SENSF_NFCID2_NFC_DEP_B2; | ||
| 285 | get_random_bytes(params->nfcid2 + 2, NFC_NFCID2_MAXSIZE - 2); | ||
| 286 | params->sc = DIGITAL_SENSF_FELICA_SC; | ||
| 287 | |||
| 288 | return digital_send_cmd(ddev, DIGITAL_CMD_TG_LISTEN_MDAA, NULL, params, | ||
| 289 | 500, digital_tg_recv_atr_req, NULL); | ||
| 290 | } | ||
| 291 | |||
| 292 | int digital_target_found(struct nfc_digital_dev *ddev, | ||
| 293 | struct nfc_target *target, u8 protocol) | ||
| 294 | { | ||
| 295 | int rc; | ||
| 296 | u8 framing; | ||
| 297 | u8 rf_tech; | ||
| 298 | int (*check_crc)(struct sk_buff *skb); | ||
| 299 | void (*add_crc)(struct sk_buff *skb); | ||
| 300 | |||
| 301 | rf_tech = ddev->poll_techs[ddev->poll_tech_index].rf_tech; | ||
| 302 | |||
| 303 | switch (protocol) { | ||
| 304 | case NFC_PROTO_JEWEL: | ||
| 305 | framing = NFC_DIGITAL_FRAMING_NFCA_T1T; | ||
| 306 | check_crc = digital_skb_check_crc_b; | ||
| 307 | add_crc = digital_skb_add_crc_b; | ||
| 308 | break; | ||
| 309 | |||
| 310 | case NFC_PROTO_MIFARE: | ||
| 311 | framing = NFC_DIGITAL_FRAMING_NFCA_T2T; | ||
| 312 | check_crc = digital_skb_check_crc_a; | ||
| 313 | add_crc = digital_skb_add_crc_a; | ||
| 314 | break; | ||
| 315 | |||
| 316 | case NFC_PROTO_FELICA: | ||
| 317 | framing = NFC_DIGITAL_FRAMING_NFCF_T3T; | ||
| 318 | check_crc = digital_skb_check_crc_f; | ||
| 319 | add_crc = digital_skb_add_crc_f; | ||
| 320 | break; | ||
| 321 | |||
| 322 | case NFC_PROTO_NFC_DEP: | ||
| 323 | if (rf_tech == NFC_DIGITAL_RF_TECH_106A) { | ||
| 324 | framing = NFC_DIGITAL_FRAMING_NFCA_NFC_DEP; | ||
| 325 | check_crc = digital_skb_check_crc_a; | ||
| 326 | add_crc = digital_skb_add_crc_a; | ||
| 327 | } else { | ||
| 328 | framing = NFC_DIGITAL_FRAMING_NFCF_NFC_DEP; | ||
| 329 | check_crc = digital_skb_check_crc_f; | ||
| 330 | add_crc = digital_skb_add_crc_f; | ||
| 331 | } | ||
| 332 | break; | ||
| 333 | |||
| 334 | default: | ||
| 335 | pr_err("Invalid protocol %d\n", protocol); | ||
| 336 | return -EINVAL; | ||
| 337 | } | ||
| 338 | |||
| 339 | pr_debug("rf_tech=%d, protocol=%d\n", rf_tech, protocol); | ||
| 340 | |||
| 341 | ddev->curr_rf_tech = rf_tech; | ||
| 342 | ddev->curr_protocol = protocol; | ||
| 343 | |||
| 344 | if (DIGITAL_DRV_CAPS_IN_CRC(ddev)) { | ||
| 345 | ddev->skb_add_crc = digital_skb_add_crc_none; | ||
| 346 | ddev->skb_check_crc = digital_skb_check_crc_none; | ||
| 347 | } else { | ||
| 348 | ddev->skb_add_crc = add_crc; | ||
| 349 | ddev->skb_check_crc = check_crc; | ||
| 350 | } | ||
| 351 | |||
| 352 | rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, framing); | ||
| 353 | if (rc) | ||
| 354 | return rc; | ||
| 355 | |||
| 356 | target->supported_protocols = (1 << protocol); | ||
| 357 | rc = nfc_targets_found(ddev->nfc_dev, target, 1); | ||
| 358 | if (rc) | ||
| 359 | return rc; | ||
| 360 | |||
| 361 | ddev->poll_tech_count = 0; | ||
| 362 | |||
| 363 | return 0; | ||
| 364 | } | ||
| 365 | |||
| 366 | void digital_poll_next_tech(struct nfc_digital_dev *ddev) | ||
| 367 | { | ||
| 368 | digital_switch_rf(ddev, 0); | ||
| 369 | |||
| 370 | mutex_lock(&ddev->poll_lock); | ||
| 371 | |||
| 372 | if (!ddev->poll_tech_count) { | ||
| 373 | mutex_unlock(&ddev->poll_lock); | ||
| 374 | return; | ||
| 375 | } | ||
| 376 | |||
| 377 | ddev->poll_tech_index = (ddev->poll_tech_index + 1) % | ||
| 378 | ddev->poll_tech_count; | ||
| 379 | |||
| 380 | mutex_unlock(&ddev->poll_lock); | ||
| 381 | |||
| 382 | schedule_work(&ddev->poll_work); | ||
| 383 | } | ||
| 384 | |||
| 385 | static void digital_wq_poll(struct work_struct *work) | ||
| 386 | { | ||
| 387 | int rc; | ||
| 388 | struct digital_poll_tech *poll_tech; | ||
| 389 | struct nfc_digital_dev *ddev = container_of(work, | ||
| 390 | struct nfc_digital_dev, | ||
| 391 | poll_work); | ||
| 392 | mutex_lock(&ddev->poll_lock); | ||
| 393 | |||
| 394 | if (!ddev->poll_tech_count) { | ||
| 395 | mutex_unlock(&ddev->poll_lock); | ||
| 396 | return; | ||
| 397 | } | ||
| 398 | |||
| 399 | poll_tech = &ddev->poll_techs[ddev->poll_tech_index]; | ||
| 400 | |||
| 401 | mutex_unlock(&ddev->poll_lock); | ||
| 402 | |||
| 403 | rc = poll_tech->poll_func(ddev, poll_tech->rf_tech); | ||
| 404 | if (rc) | ||
| 405 | digital_poll_next_tech(ddev); | ||
| 406 | } | ||
| 407 | |||
| 408 | static void digital_add_poll_tech(struct nfc_digital_dev *ddev, u8 rf_tech, | ||
| 409 | digital_poll_t poll_func) | ||
| 410 | { | ||
| 411 | struct digital_poll_tech *poll_tech; | ||
| 412 | |||
| 413 | if (ddev->poll_tech_count >= NFC_DIGITAL_POLL_MODE_COUNT_MAX) | ||
| 414 | return; | ||
| 415 | |||
| 416 | poll_tech = &ddev->poll_techs[ddev->poll_tech_count++]; | ||
| 417 | |||
| 418 | poll_tech->rf_tech = rf_tech; | ||
| 419 | poll_tech->poll_func = poll_func; | ||
| 420 | } | ||
| 421 | |||
| 422 | /** | ||
| 423 | * start_poll operation | ||
| 424 | * | ||
| 425 | * For every supported protocol, the corresponding polling function is added | ||
| 426 | * to the table of polling technologies (ddev->poll_techs[]) using | ||
| 427 | * digital_add_poll_tech(). | ||
| 428 | * When a polling function fails (by timeout or protocol error) the next one is | ||
| 429 | * schedule by digital_poll_next_tech() on the poll workqueue (ddev->poll_work). | ||
| 430 | */ | ||
| 431 | static int digital_start_poll(struct nfc_dev *nfc_dev, __u32 im_protocols, | ||
| 432 | __u32 tm_protocols) | ||
| 433 | { | ||
| 434 | struct nfc_digital_dev *ddev = nfc_get_drvdata(nfc_dev); | ||
| 435 | u32 matching_im_protocols, matching_tm_protocols; | ||
| 436 | |||
| 437 | pr_debug("protocols: im 0x%x, tm 0x%x, supported 0x%x\n", im_protocols, | ||
| 438 | tm_protocols, ddev->protocols); | ||
| 439 | |||
| 440 | matching_im_protocols = ddev->protocols & im_protocols; | ||
| 441 | matching_tm_protocols = ddev->protocols & tm_protocols; | ||
| 442 | |||
| 443 | if (!matching_im_protocols && !matching_tm_protocols) { | ||
| 444 | pr_err("Unknown protocol\n"); | ||
| 445 | return -EINVAL; | ||
| 446 | } | ||
| 447 | |||
| 448 | if (ddev->poll_tech_count) { | ||
| 449 | pr_err("Already polling\n"); | ||
| 450 | return -EBUSY; | ||
| 451 | } | ||
| 452 | |||
| 453 | if (ddev->curr_protocol) { | ||
| 454 | pr_err("A target is already active\n"); | ||
| 455 | return -EBUSY; | ||
| 456 | } | ||
| 457 | |||
| 458 | ddev->poll_tech_count = 0; | ||
| 459 | ddev->poll_tech_index = 0; | ||
| 460 | |||
| 461 | if (matching_im_protocols & DIGITAL_PROTO_NFCA_RF_TECH) | ||
| 462 | digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_106A, | ||
| 463 | digital_in_send_sens_req); | ||
| 464 | |||
| 465 | if (im_protocols & DIGITAL_PROTO_NFCF_RF_TECH) { | ||
| 466 | digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_212F, | ||
| 467 | digital_in_send_sensf_req); | ||
| 468 | |||
| 469 | digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_424F, | ||
| 470 | digital_in_send_sensf_req); | ||
| 471 | } | ||
| 472 | |||
| 473 | if (tm_protocols & NFC_PROTO_NFC_DEP_MASK) { | ||
| 474 | if (ddev->ops->tg_listen_mdaa) { | ||
| 475 | digital_add_poll_tech(ddev, 0, | ||
| 476 | digital_tg_listen_mdaa); | ||
| 477 | } else { | ||
| 478 | digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_106A, | ||
| 479 | digital_tg_listen_nfca); | ||
| 480 | |||
| 481 | digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_212F, | ||
| 482 | digital_tg_listen_nfcf); | ||
| 483 | |||
| 484 | digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_424F, | ||
| 485 | digital_tg_listen_nfcf); | ||
| 486 | } | ||
| 487 | } | ||
| 488 | |||
| 489 | if (!ddev->poll_tech_count) { | ||
| 490 | pr_err("Unsupported protocols: im=0x%x, tm=0x%x\n", | ||
| 491 | matching_im_protocols, matching_tm_protocols); | ||
| 492 | return -EINVAL; | ||
| 493 | } | ||
| 494 | |||
| 495 | schedule_work(&ddev->poll_work); | ||
| 496 | |||
| 497 | return 0; | ||
| 498 | } | ||
| 499 | |||
| 500 | static void digital_stop_poll(struct nfc_dev *nfc_dev) | ||
| 501 | { | ||
| 502 | struct nfc_digital_dev *ddev = nfc_get_drvdata(nfc_dev); | ||
| 503 | |||
| 504 | mutex_lock(&ddev->poll_lock); | ||
| 505 | |||
| 506 | if (!ddev->poll_tech_count) { | ||
| 507 | pr_err("Polling operation was not running\n"); | ||
| 508 | mutex_unlock(&ddev->poll_lock); | ||
| 509 | return; | ||
| 510 | } | ||
| 511 | |||
| 512 | ddev->poll_tech_count = 0; | ||
| 513 | |||
| 514 | mutex_unlock(&ddev->poll_lock); | ||
| 515 | |||
| 516 | cancel_work_sync(&ddev->poll_work); | ||
| 517 | |||
| 518 | digital_abort_cmd(ddev); | ||
| 519 | } | ||
| 520 | |||
| 521 | static int digital_dev_up(struct nfc_dev *nfc_dev) | ||
| 522 | { | ||
| 523 | struct nfc_digital_dev *ddev = nfc_get_drvdata(nfc_dev); | ||
| 524 | |||
| 525 | digital_switch_rf(ddev, 1); | ||
| 526 | |||
| 527 | return 0; | ||
| 528 | } | ||
| 529 | |||
| 530 | static int digital_dev_down(struct nfc_dev *nfc_dev) | ||
| 531 | { | ||
| 532 | struct nfc_digital_dev *ddev = nfc_get_drvdata(nfc_dev); | ||
| 533 | |||
| 534 | digital_switch_rf(ddev, 0); | ||
| 535 | |||
| 536 | return 0; | ||
| 537 | } | ||
| 538 | |||
| 539 | static int digital_dep_link_up(struct nfc_dev *nfc_dev, | ||
| 540 | struct nfc_target *target, | ||
| 541 | __u8 comm_mode, __u8 *gb, size_t gb_len) | ||
| 542 | { | ||
| 543 | struct nfc_digital_dev *ddev = nfc_get_drvdata(nfc_dev); | ||
| 544 | |||
| 545 | return digital_in_send_atr_req(ddev, target, comm_mode, gb, gb_len); | ||
| 546 | } | ||
| 547 | |||
| 548 | static int digital_dep_link_down(struct nfc_dev *nfc_dev) | ||
| 549 | { | ||
| 550 | struct nfc_digital_dev *ddev = nfc_get_drvdata(nfc_dev); | ||
| 551 | |||
| 552 | ddev->curr_protocol = 0; | ||
| 553 | |||
| 554 | return 0; | ||
| 555 | } | ||
| 556 | |||
| 557 | static int digital_activate_target(struct nfc_dev *nfc_dev, | ||
| 558 | struct nfc_target *target, __u32 protocol) | ||
| 559 | { | ||
| 560 | return 0; | ||
| 561 | } | ||
| 562 | |||
| 563 | static void digital_deactivate_target(struct nfc_dev *nfc_dev, | ||
| 564 | struct nfc_target *target) | ||
| 565 | { | ||
| 566 | struct nfc_digital_dev *ddev = nfc_get_drvdata(nfc_dev); | ||
| 567 | |||
| 568 | ddev->curr_protocol = 0; | ||
| 569 | } | ||
| 570 | |||
| 571 | static int digital_tg_send(struct nfc_dev *dev, struct sk_buff *skb) | ||
| 572 | { | ||
| 573 | struct nfc_digital_dev *ddev = nfc_get_drvdata(dev); | ||
| 574 | |||
| 575 | return digital_tg_send_dep_res(ddev, skb); | ||
| 576 | } | ||
| 577 | |||
| 578 | static void digital_in_send_complete(struct nfc_digital_dev *ddev, void *arg, | ||
| 579 | struct sk_buff *resp) | ||
| 580 | { | ||
| 581 | struct digital_data_exch *data_exch = arg; | ||
| 582 | int rc; | ||
| 583 | |||
| 584 | if (IS_ERR(resp)) { | ||
| 585 | rc = PTR_ERR(resp); | ||
| 586 | goto done; | ||
| 587 | } | ||
| 588 | |||
| 589 | if (ddev->curr_protocol == NFC_PROTO_MIFARE) | ||
| 590 | rc = digital_in_recv_mifare_res(resp); | ||
| 591 | else | ||
| 592 | rc = ddev->skb_check_crc(resp); | ||
| 593 | |||
| 594 | if (rc) { | ||
| 595 | kfree_skb(resp); | ||
| 596 | resp = NULL; | ||
| 597 | } | ||
| 598 | |||
| 599 | done: | ||
| 600 | data_exch->cb(data_exch->cb_context, resp, rc); | ||
| 601 | |||
| 602 | kfree(data_exch); | ||
| 603 | } | ||
| 604 | |||
| 605 | static int digital_in_send(struct nfc_dev *nfc_dev, struct nfc_target *target, | ||
| 606 | struct sk_buff *skb, data_exchange_cb_t cb, | ||
| 607 | void *cb_context) | ||
| 608 | { | ||
| 609 | struct nfc_digital_dev *ddev = nfc_get_drvdata(nfc_dev); | ||
| 610 | struct digital_data_exch *data_exch; | ||
| 611 | |||
| 612 | data_exch = kzalloc(sizeof(struct digital_data_exch), GFP_KERNEL); | ||
| 613 | if (!data_exch) { | ||
| 614 | pr_err("Failed to allocate data_exch struct\n"); | ||
| 615 | return -ENOMEM; | ||
| 616 | } | ||
| 617 | |||
| 618 | data_exch->cb = cb; | ||
| 619 | data_exch->cb_context = cb_context; | ||
| 620 | |||
| 621 | if (ddev->curr_protocol == NFC_PROTO_NFC_DEP) | ||
| 622 | return digital_in_send_dep_req(ddev, target, skb, data_exch); | ||
| 623 | |||
| 624 | ddev->skb_add_crc(skb); | ||
| 625 | |||
| 626 | return digital_in_send_cmd(ddev, skb, 500, digital_in_send_complete, | ||
| 627 | data_exch); | ||
| 628 | } | ||
| 629 | |||
| 630 | static struct nfc_ops digital_nfc_ops = { | ||
| 631 | .dev_up = digital_dev_up, | ||
| 632 | .dev_down = digital_dev_down, | ||
| 633 | .start_poll = digital_start_poll, | ||
| 634 | .stop_poll = digital_stop_poll, | ||
| 635 | .dep_link_up = digital_dep_link_up, | ||
| 636 | .dep_link_down = digital_dep_link_down, | ||
| 637 | .activate_target = digital_activate_target, | ||
| 638 | .deactivate_target = digital_deactivate_target, | ||
| 639 | .tm_send = digital_tg_send, | ||
| 640 | .im_transceive = digital_in_send, | ||
| 641 | }; | ||
| 642 | |||
| 643 | struct nfc_digital_dev *nfc_digital_allocate_device(struct nfc_digital_ops *ops, | ||
| 644 | __u32 supported_protocols, | ||
| 645 | __u32 driver_capabilities, | ||
| 646 | int tx_headroom, int tx_tailroom) | ||
| 647 | { | ||
| 648 | struct nfc_digital_dev *ddev; | ||
| 649 | |||
| 650 | if (!ops->in_configure_hw || !ops->in_send_cmd || !ops->tg_listen || | ||
| 651 | !ops->tg_configure_hw || !ops->tg_send_cmd || !ops->abort_cmd || | ||
| 652 | !ops->switch_rf) | ||
| 653 | return NULL; | ||
| 654 | |||
| 655 | ddev = kzalloc(sizeof(struct nfc_digital_dev), GFP_KERNEL); | ||
| 656 | if (!ddev) | ||
| 657 | return NULL; | ||
| 658 | |||
| 659 | ddev->driver_capabilities = driver_capabilities; | ||
| 660 | ddev->ops = ops; | ||
| 661 | |||
| 662 | mutex_init(&ddev->cmd_lock); | ||
| 663 | INIT_LIST_HEAD(&ddev->cmd_queue); | ||
| 664 | |||
| 665 | INIT_WORK(&ddev->cmd_work, digital_wq_cmd); | ||
| 666 | INIT_WORK(&ddev->cmd_complete_work, digital_wq_cmd_complete); | ||
| 667 | |||
| 668 | mutex_init(&ddev->poll_lock); | ||
| 669 | INIT_WORK(&ddev->poll_work, digital_wq_poll); | ||
| 670 | |||
| 671 | if (supported_protocols & NFC_PROTO_JEWEL_MASK) | ||
| 672 | ddev->protocols |= NFC_PROTO_JEWEL_MASK; | ||
| 673 | if (supported_protocols & NFC_PROTO_MIFARE_MASK) | ||
| 674 | ddev->protocols |= NFC_PROTO_MIFARE_MASK; | ||
| 675 | if (supported_protocols & NFC_PROTO_FELICA_MASK) | ||
| 676 | ddev->protocols |= NFC_PROTO_FELICA_MASK; | ||
| 677 | if (supported_protocols & NFC_PROTO_NFC_DEP_MASK) | ||
| 678 | ddev->protocols |= NFC_PROTO_NFC_DEP_MASK; | ||
| 679 | |||
| 680 | ddev->tx_headroom = tx_headroom + DIGITAL_MAX_HEADER_LEN; | ||
| 681 | ddev->tx_tailroom = tx_tailroom + DIGITAL_CRC_LEN; | ||
| 682 | |||
| 683 | ddev->nfc_dev = nfc_allocate_device(&digital_nfc_ops, ddev->protocols, | ||
| 684 | ddev->tx_headroom, | ||
| 685 | ddev->tx_tailroom); | ||
| 686 | if (!ddev->nfc_dev) { | ||
| 687 | pr_err("nfc_allocate_device failed\n"); | ||
| 688 | goto free_dev; | ||
| 689 | } | ||
| 690 | |||
| 691 | nfc_set_drvdata(ddev->nfc_dev, ddev); | ||
| 692 | |||
| 693 | return ddev; | ||
| 694 | |||
| 695 | free_dev: | ||
| 696 | kfree(ddev); | ||
| 697 | |||
| 698 | return NULL; | ||
| 699 | } | ||
| 700 | EXPORT_SYMBOL(nfc_digital_allocate_device); | ||
| 701 | |||
| 702 | void nfc_digital_free_device(struct nfc_digital_dev *ddev) | ||
| 703 | { | ||
| 704 | nfc_free_device(ddev->nfc_dev); | ||
| 705 | kfree(ddev); | ||
| 706 | } | ||
| 707 | EXPORT_SYMBOL(nfc_digital_free_device); | ||
| 708 | |||
| 709 | int nfc_digital_register_device(struct nfc_digital_dev *ddev) | ||
| 710 | { | ||
| 711 | return nfc_register_device(ddev->nfc_dev); | ||
| 712 | } | ||
| 713 | EXPORT_SYMBOL(nfc_digital_register_device); | ||
| 714 | |||
| 715 | void nfc_digital_unregister_device(struct nfc_digital_dev *ddev) | ||
| 716 | { | ||
| 717 | struct digital_cmd *cmd, *n; | ||
| 718 | |||
| 719 | nfc_unregister_device(ddev->nfc_dev); | ||
| 720 | |||
| 721 | mutex_lock(&ddev->poll_lock); | ||
| 722 | ddev->poll_tech_count = 0; | ||
| 723 | mutex_unlock(&ddev->poll_lock); | ||
| 724 | |||
| 725 | cancel_work_sync(&ddev->poll_work); | ||
| 726 | cancel_work_sync(&ddev->cmd_work); | ||
| 727 | cancel_work_sync(&ddev->cmd_complete_work); | ||
| 728 | |||
| 729 | list_for_each_entry_safe(cmd, n, &ddev->cmd_queue, queue) { | ||
| 730 | list_del(&cmd->queue); | ||
| 731 | kfree(cmd->mdaa_params); | ||
| 732 | kfree(cmd); | ||
| 733 | } | ||
| 734 | } | ||
| 735 | EXPORT_SYMBOL(nfc_digital_unregister_device); | ||
| 736 | |||
| 737 | MODULE_LICENSE("GPL"); | ||
diff --git a/net/nfc/digital_dep.c b/net/nfc/digital_dep.c new file mode 100644 index 000000000000..07bbc24fb4c7 --- /dev/null +++ b/net/nfc/digital_dep.c | |||
| @@ -0,0 +1,729 @@ | |||
| 1 | /* | ||
| 2 | * NFC Digital Protocol stack | ||
| 3 | * Copyright (c) 2013, Intel Corporation. | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify it | ||
| 6 | * under the terms and conditions of the GNU General Public License, | ||
| 7 | * version 2, as published by the Free Software Foundation. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
| 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 12 | * more details. | ||
| 13 | * | ||
| 14 | */ | ||
| 15 | |||
| 16 | #define pr_fmt(fmt) "digital: %s: " fmt, __func__ | ||
| 17 | |||
| 18 | #include "digital.h" | ||
| 19 | |||
| 20 | #define DIGITAL_NFC_DEP_FRAME_DIR_OUT 0xD4 | ||
| 21 | #define DIGITAL_NFC_DEP_FRAME_DIR_IN 0xD5 | ||
| 22 | |||
| 23 | #define DIGITAL_NFC_DEP_NFCA_SOD_SB 0xF0 | ||
| 24 | |||
| 25 | #define DIGITAL_CMD_ATR_REQ 0x00 | ||
| 26 | #define DIGITAL_CMD_ATR_RES 0x01 | ||
| 27 | #define DIGITAL_CMD_PSL_REQ 0x04 | ||
| 28 | #define DIGITAL_CMD_PSL_RES 0x05 | ||
| 29 | #define DIGITAL_CMD_DEP_REQ 0x06 | ||
| 30 | #define DIGITAL_CMD_DEP_RES 0x07 | ||
| 31 | |||
| 32 | #define DIGITAL_ATR_REQ_MIN_SIZE 16 | ||
| 33 | #define DIGITAL_ATR_REQ_MAX_SIZE 64 | ||
| 34 | |||
| 35 | #define DIGITAL_NFCID3_LEN ((u8)8) | ||
| 36 | #define DIGITAL_LR_BITS_PAYLOAD_SIZE_254B 0x30 | ||
| 37 | #define DIGITAL_GB_BIT 0x02 | ||
| 38 | |||
| 39 | #define DIGITAL_NFC_DEP_PFB_TYPE(pfb) ((pfb) & 0xE0) | ||
| 40 | |||
| 41 | #define DIGITAL_NFC_DEP_PFB_TIMEOUT_BIT 0x10 | ||
| 42 | |||
| 43 | #define DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb) \ | ||
| 44 | ((pfb) & DIGITAL_NFC_DEP_PFB_TIMEOUT_BIT) | ||
| 45 | #define DIGITAL_NFC_DEP_MI_BIT_SET(pfb) ((pfb) & 0x10) | ||
| 46 | #define DIGITAL_NFC_DEP_NAD_BIT_SET(pfb) ((pfb) & 0x08) | ||
| 47 | #define DIGITAL_NFC_DEP_DID_BIT_SET(pfb) ((pfb) & 0x04) | ||
| 48 | #define DIGITAL_NFC_DEP_PFB_PNI(pfb) ((pfb) & 0x03) | ||
| 49 | |||
| 50 | #define DIGITAL_NFC_DEP_PFB_I_PDU 0x00 | ||
| 51 | #define DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU 0x40 | ||
| 52 | #define DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU 0x80 | ||
| 53 | |||
| 54 | struct digital_atr_req { | ||
| 55 | u8 dir; | ||
| 56 | u8 cmd; | ||
| 57 | u8 nfcid3[10]; | ||
| 58 | u8 did; | ||
| 59 | u8 bs; | ||
| 60 | u8 br; | ||
| 61 | u8 pp; | ||
| 62 | u8 gb[0]; | ||
| 63 | } __packed; | ||
| 64 | |||
| 65 | struct digital_atr_res { | ||
| 66 | u8 dir; | ||
| 67 | u8 cmd; | ||
| 68 | u8 nfcid3[10]; | ||
| 69 | u8 did; | ||
| 70 | u8 bs; | ||
| 71 | u8 br; | ||
| 72 | u8 to; | ||
| 73 | u8 pp; | ||
| 74 | u8 gb[0]; | ||
| 75 | } __packed; | ||
| 76 | |||
| 77 | struct digital_psl_req { | ||
| 78 | u8 dir; | ||
| 79 | u8 cmd; | ||
| 80 | u8 did; | ||
| 81 | u8 brs; | ||
| 82 | u8 fsl; | ||
| 83 | } __packed; | ||
| 84 | |||
| 85 | struct digital_psl_res { | ||
| 86 | u8 dir; | ||
| 87 | u8 cmd; | ||
| 88 | u8 did; | ||
| 89 | } __packed; | ||
| 90 | |||
| 91 | struct digital_dep_req_res { | ||
| 92 | u8 dir; | ||
| 93 | u8 cmd; | ||
| 94 | u8 pfb; | ||
| 95 | } __packed; | ||
| 96 | |||
| 97 | static void digital_in_recv_dep_res(struct nfc_digital_dev *ddev, void *arg, | ||
| 98 | struct sk_buff *resp); | ||
| 99 | |||
| 100 | static void digital_skb_push_dep_sod(struct nfc_digital_dev *ddev, | ||
| 101 | struct sk_buff *skb) | ||
| 102 | { | ||
| 103 | skb_push(skb, sizeof(u8)); | ||
| 104 | |||
| 105 | skb->data[0] = skb->len; | ||
| 106 | |||
| 107 | if (ddev->curr_rf_tech == NFC_DIGITAL_RF_TECH_106A) | ||
| 108 | *skb_push(skb, sizeof(u8)) = DIGITAL_NFC_DEP_NFCA_SOD_SB; | ||
| 109 | } | ||
| 110 | |||
| 111 | static int digital_skb_pull_dep_sod(struct nfc_digital_dev *ddev, | ||
| 112 | struct sk_buff *skb) | ||
| 113 | { | ||
| 114 | u8 size; | ||
| 115 | |||
| 116 | if (skb->len < 2) | ||
| 117 | return -EIO; | ||
| 118 | |||
| 119 | if (ddev->curr_rf_tech == NFC_DIGITAL_RF_TECH_106A) | ||
| 120 | skb_pull(skb, sizeof(u8)); | ||
| 121 | |||
| 122 | size = skb->data[0]; | ||
| 123 | if (size != skb->len) | ||
| 124 | return -EIO; | ||
| 125 | |||
| 126 | skb_pull(skb, sizeof(u8)); | ||
| 127 | |||
| 128 | return 0; | ||
| 129 | } | ||
| 130 | |||
| 131 | static void digital_in_recv_atr_res(struct nfc_digital_dev *ddev, void *arg, | ||
| 132 | struct sk_buff *resp) | ||
| 133 | { | ||
| 134 | struct nfc_target *target = arg; | ||
| 135 | struct digital_atr_res *atr_res; | ||
| 136 | u8 gb_len; | ||
| 137 | int rc; | ||
| 138 | |||
| 139 | if (IS_ERR(resp)) { | ||
| 140 | rc = PTR_ERR(resp); | ||
| 141 | resp = NULL; | ||
| 142 | goto exit; | ||
| 143 | } | ||
| 144 | |||
| 145 | rc = ddev->skb_check_crc(resp); | ||
| 146 | if (rc) { | ||
| 147 | PROTOCOL_ERR("14.4.1.6"); | ||
| 148 | goto exit; | ||
| 149 | } | ||
| 150 | |||
| 151 | rc = digital_skb_pull_dep_sod(ddev, resp); | ||
| 152 | if (rc) { | ||
| 153 | PROTOCOL_ERR("14.4.1.2"); | ||
| 154 | goto exit; | ||
| 155 | } | ||
| 156 | |||
| 157 | if (resp->len < sizeof(struct digital_atr_res)) { | ||
| 158 | rc = -EIO; | ||
| 159 | goto exit; | ||
| 160 | } | ||
| 161 | |||
| 162 | gb_len = resp->len - sizeof(struct digital_atr_res); | ||
| 163 | |||
| 164 | atr_res = (struct digital_atr_res *)resp->data; | ||
| 165 | |||
| 166 | rc = nfc_set_remote_general_bytes(ddev->nfc_dev, atr_res->gb, gb_len); | ||
| 167 | if (rc) | ||
| 168 | goto exit; | ||
| 169 | |||
| 170 | rc = nfc_dep_link_is_up(ddev->nfc_dev, target->idx, NFC_COMM_ACTIVE, | ||
| 171 | NFC_RF_INITIATOR); | ||
| 172 | |||
| 173 | ddev->curr_nfc_dep_pni = 0; | ||
| 174 | |||
| 175 | exit: | ||
| 176 | dev_kfree_skb(resp); | ||
| 177 | |||
| 178 | if (rc) | ||
| 179 | ddev->curr_protocol = 0; | ||
| 180 | } | ||
| 181 | |||
| 182 | int digital_in_send_atr_req(struct nfc_digital_dev *ddev, | ||
| 183 | struct nfc_target *target, __u8 comm_mode, __u8 *gb, | ||
| 184 | size_t gb_len) | ||
| 185 | { | ||
| 186 | struct sk_buff *skb; | ||
| 187 | struct digital_atr_req *atr_req; | ||
| 188 | uint size; | ||
| 189 | |||
| 190 | size = DIGITAL_ATR_REQ_MIN_SIZE + gb_len; | ||
| 191 | |||
| 192 | if (size > DIGITAL_ATR_REQ_MAX_SIZE) { | ||
| 193 | PROTOCOL_ERR("14.6.1.1"); | ||
| 194 | return -EINVAL; | ||
| 195 | } | ||
| 196 | |||
| 197 | skb = digital_skb_alloc(ddev, size); | ||
| 198 | if (!skb) | ||
| 199 | return -ENOMEM; | ||
| 200 | |||
| 201 | skb_put(skb, sizeof(struct digital_atr_req)); | ||
| 202 | |||
| 203 | atr_req = (struct digital_atr_req *)skb->data; | ||
| 204 | memset(atr_req, 0, sizeof(struct digital_atr_req)); | ||
| 205 | |||
| 206 | atr_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT; | ||
| 207 | atr_req->cmd = DIGITAL_CMD_ATR_REQ; | ||
| 208 | if (target->nfcid2_len) | ||
| 209 | memcpy(atr_req->nfcid3, target->nfcid2, | ||
| 210 | max(target->nfcid2_len, DIGITAL_NFCID3_LEN)); | ||
| 211 | else | ||
| 212 | get_random_bytes(atr_req->nfcid3, DIGITAL_NFCID3_LEN); | ||
| 213 | |||
| 214 | atr_req->did = 0; | ||
| 215 | atr_req->bs = 0; | ||
| 216 | atr_req->br = 0; | ||
| 217 | |||
| 218 | atr_req->pp = DIGITAL_LR_BITS_PAYLOAD_SIZE_254B; | ||
| 219 | |||
| 220 | if (gb_len) { | ||
| 221 | atr_req->pp |= DIGITAL_GB_BIT; | ||
| 222 | memcpy(skb_put(skb, gb_len), gb, gb_len); | ||
| 223 | } | ||
| 224 | |||
| 225 | digital_skb_push_dep_sod(ddev, skb); | ||
| 226 | |||
| 227 | ddev->skb_add_crc(skb); | ||
| 228 | |||
| 229 | digital_in_send_cmd(ddev, skb, 500, digital_in_recv_atr_res, target); | ||
| 230 | |||
| 231 | return 0; | ||
| 232 | } | ||
| 233 | |||
| 234 | static int digital_in_send_rtox(struct nfc_digital_dev *ddev, | ||
| 235 | struct digital_data_exch *data_exch, u8 rtox) | ||
| 236 | { | ||
| 237 | struct digital_dep_req_res *dep_req; | ||
| 238 | struct sk_buff *skb; | ||
| 239 | int rc; | ||
| 240 | |||
| 241 | skb = digital_skb_alloc(ddev, 1); | ||
| 242 | if (!skb) | ||
| 243 | return -ENOMEM; | ||
| 244 | |||
| 245 | *skb_put(skb, 1) = rtox; | ||
| 246 | |||
| 247 | skb_push(skb, sizeof(struct digital_dep_req_res)); | ||
| 248 | |||
| 249 | dep_req = (struct digital_dep_req_res *)skb->data; | ||
| 250 | |||
| 251 | dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT; | ||
| 252 | dep_req->cmd = DIGITAL_CMD_DEP_REQ; | ||
| 253 | dep_req->pfb = DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU | | ||
| 254 | DIGITAL_NFC_DEP_PFB_TIMEOUT_BIT; | ||
| 255 | |||
| 256 | digital_skb_push_dep_sod(ddev, skb); | ||
| 257 | |||
| 258 | ddev->skb_add_crc(skb); | ||
| 259 | |||
| 260 | rc = digital_in_send_cmd(ddev, skb, 1500, digital_in_recv_dep_res, | ||
| 261 | data_exch); | ||
| 262 | |||
| 263 | return rc; | ||
| 264 | } | ||
| 265 | |||
| 266 | static void digital_in_recv_dep_res(struct nfc_digital_dev *ddev, void *arg, | ||
| 267 | struct sk_buff *resp) | ||
| 268 | { | ||
| 269 | struct digital_data_exch *data_exch = arg; | ||
| 270 | struct digital_dep_req_res *dep_res; | ||
| 271 | u8 pfb; | ||
| 272 | uint size; | ||
| 273 | int rc; | ||
| 274 | |||
| 275 | if (IS_ERR(resp)) { | ||
| 276 | rc = PTR_ERR(resp); | ||
| 277 | resp = NULL; | ||
| 278 | goto exit; | ||
| 279 | } | ||
| 280 | |||
| 281 | rc = ddev->skb_check_crc(resp); | ||
| 282 | if (rc) { | ||
| 283 | PROTOCOL_ERR("14.4.1.6"); | ||
| 284 | goto error; | ||
| 285 | } | ||
| 286 | |||
| 287 | rc = digital_skb_pull_dep_sod(ddev, resp); | ||
| 288 | if (rc) { | ||
| 289 | PROTOCOL_ERR("14.4.1.2"); | ||
| 290 | goto exit; | ||
| 291 | } | ||
| 292 | |||
| 293 | dep_res = (struct digital_dep_req_res *)resp->data; | ||
| 294 | |||
| 295 | if (resp->len < sizeof(struct digital_dep_req_res) || | ||
| 296 | dep_res->dir != DIGITAL_NFC_DEP_FRAME_DIR_IN || | ||
| 297 | dep_res->cmd != DIGITAL_CMD_DEP_RES) { | ||
| 298 | rc = -EIO; | ||
| 299 | goto error; | ||
| 300 | } | ||
| 301 | |||
| 302 | pfb = dep_res->pfb; | ||
| 303 | |||
| 304 | switch (DIGITAL_NFC_DEP_PFB_TYPE(pfb)) { | ||
| 305 | case DIGITAL_NFC_DEP_PFB_I_PDU: | ||
| 306 | if (DIGITAL_NFC_DEP_PFB_PNI(pfb) != ddev->curr_nfc_dep_pni) { | ||
| 307 | PROTOCOL_ERR("14.12.3.3"); | ||
| 308 | rc = -EIO; | ||
| 309 | goto error; | ||
| 310 | } | ||
| 311 | |||
| 312 | ddev->curr_nfc_dep_pni = | ||
| 313 | DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1); | ||
| 314 | rc = 0; | ||
| 315 | break; | ||
| 316 | |||
| 317 | case DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU: | ||
| 318 | pr_err("Received a ACK/NACK PDU\n"); | ||
| 319 | rc = -EIO; | ||
| 320 | goto error; | ||
| 321 | |||
| 322 | case DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU: | ||
| 323 | if (!DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb)) { | ||
| 324 | rc = -EINVAL; | ||
| 325 | goto error; | ||
| 326 | } | ||
| 327 | |||
| 328 | rc = digital_in_send_rtox(ddev, data_exch, resp->data[3]); | ||
| 329 | if (rc) | ||
| 330 | goto error; | ||
| 331 | |||
| 332 | kfree_skb(resp); | ||
| 333 | return; | ||
| 334 | } | ||
| 335 | |||
| 336 | if (DIGITAL_NFC_DEP_MI_BIT_SET(pfb)) { | ||
| 337 | pr_err("MI bit set. Chained PDU not supported\n"); | ||
| 338 | rc = -EIO; | ||
| 339 | goto error; | ||
| 340 | } | ||
| 341 | |||
| 342 | size = sizeof(struct digital_dep_req_res); | ||
| 343 | |||
| 344 | if (DIGITAL_NFC_DEP_DID_BIT_SET(pfb)) | ||
| 345 | size++; | ||
| 346 | |||
| 347 | if (size > resp->len) { | ||
| 348 | rc = -EIO; | ||
| 349 | goto error; | ||
| 350 | } | ||
| 351 | |||
| 352 | skb_pull(resp, size); | ||
| 353 | |||
| 354 | exit: | ||
| 355 | data_exch->cb(data_exch->cb_context, resp, rc); | ||
| 356 | |||
| 357 | error: | ||
| 358 | kfree(data_exch); | ||
| 359 | |||
| 360 | if (rc) | ||
| 361 | kfree_skb(resp); | ||
| 362 | } | ||
| 363 | |||
| 364 | int digital_in_send_dep_req(struct nfc_digital_dev *ddev, | ||
| 365 | struct nfc_target *target, struct sk_buff *skb, | ||
| 366 | struct digital_data_exch *data_exch) | ||
| 367 | { | ||
| 368 | struct digital_dep_req_res *dep_req; | ||
| 369 | |||
| 370 | skb_push(skb, sizeof(struct digital_dep_req_res)); | ||
| 371 | |||
| 372 | dep_req = (struct digital_dep_req_res *)skb->data; | ||
| 373 | dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT; | ||
| 374 | dep_req->cmd = DIGITAL_CMD_DEP_REQ; | ||
| 375 | dep_req->pfb = ddev->curr_nfc_dep_pni; | ||
| 376 | |||
| 377 | digital_skb_push_dep_sod(ddev, skb); | ||
| 378 | |||
| 379 | ddev->skb_add_crc(skb); | ||
| 380 | |||
| 381 | return digital_in_send_cmd(ddev, skb, 1500, digital_in_recv_dep_res, | ||
| 382 | data_exch); | ||
| 383 | } | ||
| 384 | |||
| 385 | static void digital_tg_recv_dep_req(struct nfc_digital_dev *ddev, void *arg, | ||
| 386 | struct sk_buff *resp) | ||
| 387 | { | ||
| 388 | int rc; | ||
| 389 | struct digital_dep_req_res *dep_req; | ||
| 390 | size_t size; | ||
| 391 | |||
| 392 | if (IS_ERR(resp)) { | ||
| 393 | rc = PTR_ERR(resp); | ||
| 394 | resp = NULL; | ||
| 395 | goto exit; | ||
| 396 | } | ||
| 397 | |||
| 398 | rc = ddev->skb_check_crc(resp); | ||
| 399 | if (rc) { | ||
| 400 | PROTOCOL_ERR("14.4.1.6"); | ||
| 401 | goto exit; | ||
| 402 | } | ||
| 403 | |||
| 404 | rc = digital_skb_pull_dep_sod(ddev, resp); | ||
| 405 | if (rc) { | ||
| 406 | PROTOCOL_ERR("14.4.1.2"); | ||
| 407 | goto exit; | ||
| 408 | } | ||
| 409 | |||
| 410 | size = sizeof(struct digital_dep_req_res); | ||
| 411 | dep_req = (struct digital_dep_req_res *)resp->data; | ||
| 412 | |||
| 413 | if (resp->len < size || dep_req->dir != DIGITAL_NFC_DEP_FRAME_DIR_OUT || | ||
| 414 | dep_req->cmd != DIGITAL_CMD_DEP_REQ) { | ||
| 415 | rc = -EIO; | ||
| 416 | goto exit; | ||
| 417 | } | ||
| 418 | |||
| 419 | if (DIGITAL_NFC_DEP_DID_BIT_SET(dep_req->pfb)) | ||
| 420 | size++; | ||
| 421 | |||
| 422 | if (resp->len < size) { | ||
| 423 | rc = -EIO; | ||
| 424 | goto exit; | ||
| 425 | } | ||
| 426 | |||
| 427 | switch (DIGITAL_NFC_DEP_PFB_TYPE(dep_req->pfb)) { | ||
| 428 | case DIGITAL_NFC_DEP_PFB_I_PDU: | ||
| 429 | pr_debug("DIGITAL_NFC_DEP_PFB_I_PDU\n"); | ||
| 430 | ddev->curr_nfc_dep_pni = DIGITAL_NFC_DEP_PFB_PNI(dep_req->pfb); | ||
| 431 | break; | ||
| 432 | case DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU: | ||
| 433 | pr_err("Received a ACK/NACK PDU\n"); | ||
| 434 | rc = -EINVAL; | ||
| 435 | goto exit; | ||
| 436 | break; | ||
| 437 | case DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU: | ||
| 438 | pr_err("Received a SUPERVISOR PDU\n"); | ||
| 439 | rc = -EINVAL; | ||
| 440 | goto exit; | ||
| 441 | break; | ||
| 442 | } | ||
| 443 | |||
| 444 | skb_pull(resp, size); | ||
| 445 | |||
| 446 | rc = nfc_tm_data_received(ddev->nfc_dev, resp); | ||
| 447 | |||
| 448 | exit: | ||
| 449 | if (rc) | ||
| 450 | kfree_skb(resp); | ||
| 451 | } | ||
| 452 | |||
| 453 | int digital_tg_send_dep_res(struct nfc_digital_dev *ddev, struct sk_buff *skb) | ||
| 454 | { | ||
| 455 | struct digital_dep_req_res *dep_res; | ||
| 456 | |||
| 457 | skb_push(skb, sizeof(struct digital_dep_req_res)); | ||
| 458 | dep_res = (struct digital_dep_req_res *)skb->data; | ||
| 459 | |||
| 460 | dep_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN; | ||
| 461 | dep_res->cmd = DIGITAL_CMD_DEP_RES; | ||
| 462 | dep_res->pfb = ddev->curr_nfc_dep_pni; | ||
| 463 | |||
| 464 | digital_skb_push_dep_sod(ddev, skb); | ||
| 465 | |||
| 466 | ddev->skb_add_crc(skb); | ||
| 467 | |||
| 468 | return digital_tg_send_cmd(ddev, skb, 1500, digital_tg_recv_dep_req, | ||
| 469 | NULL); | ||
| 470 | } | ||
| 471 | |||
| 472 | static void digital_tg_send_psl_res_complete(struct nfc_digital_dev *ddev, | ||
| 473 | void *arg, struct sk_buff *resp) | ||
| 474 | { | ||
| 475 | u8 rf_tech = PTR_ERR(arg); | ||
| 476 | |||
| 477 | if (IS_ERR(resp)) | ||
| 478 | return; | ||
| 479 | |||
| 480 | digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, rf_tech); | ||
| 481 | |||
| 482 | digital_tg_listen(ddev, 1500, digital_tg_recv_dep_req, NULL); | ||
| 483 | |||
| 484 | dev_kfree_skb(resp); | ||
| 485 | } | ||
| 486 | |||
| 487 | static int digital_tg_send_psl_res(struct nfc_digital_dev *ddev, u8 did, | ||
| 488 | u8 rf_tech) | ||
| 489 | { | ||
| 490 | struct digital_psl_res *psl_res; | ||
| 491 | struct sk_buff *skb; | ||
| 492 | int rc; | ||
| 493 | |||
| 494 | skb = digital_skb_alloc(ddev, sizeof(struct digital_psl_res)); | ||
| 495 | if (!skb) | ||
| 496 | return -ENOMEM; | ||
| 497 | |||
| 498 | skb_put(skb, sizeof(struct digital_psl_res)); | ||
| 499 | |||
| 500 | psl_res = (struct digital_psl_res *)skb->data; | ||
| 501 | |||
| 502 | psl_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN; | ||
| 503 | psl_res->cmd = DIGITAL_CMD_PSL_RES; | ||
| 504 | psl_res->did = did; | ||
| 505 | |||
| 506 | digital_skb_push_dep_sod(ddev, skb); | ||
| 507 | |||
| 508 | ddev->skb_add_crc(skb); | ||
| 509 | |||
| 510 | rc = digital_tg_send_cmd(ddev, skb, 0, digital_tg_send_psl_res_complete, | ||
| 511 | ERR_PTR(rf_tech)); | ||
| 512 | |||
| 513 | if (rc) | ||
| 514 | kfree_skb(skb); | ||
| 515 | |||
| 516 | return rc; | ||
| 517 | } | ||
| 518 | |||
| 519 | static void digital_tg_recv_psl_req(struct nfc_digital_dev *ddev, void *arg, | ||
| 520 | struct sk_buff *resp) | ||
| 521 | { | ||
| 522 | int rc; | ||
| 523 | struct digital_psl_req *psl_req; | ||
| 524 | u8 rf_tech; | ||
| 525 | u8 dsi; | ||
| 526 | |||
| 527 | if (IS_ERR(resp)) { | ||
| 528 | rc = PTR_ERR(resp); | ||
| 529 | resp = NULL; | ||
| 530 | goto exit; | ||
| 531 | } | ||
| 532 | |||
| 533 | rc = ddev->skb_check_crc(resp); | ||
| 534 | if (rc) { | ||
| 535 | PROTOCOL_ERR("14.4.1.6"); | ||
| 536 | goto exit; | ||
| 537 | } | ||
| 538 | |||
| 539 | rc = digital_skb_pull_dep_sod(ddev, resp); | ||
| 540 | if (rc) { | ||
| 541 | PROTOCOL_ERR("14.4.1.2"); | ||
| 542 | goto exit; | ||
| 543 | } | ||
| 544 | |||
| 545 | psl_req = (struct digital_psl_req *)resp->data; | ||
| 546 | |||
| 547 | if (resp->len != sizeof(struct digital_psl_req) || | ||
| 548 | psl_req->dir != DIGITAL_NFC_DEP_FRAME_DIR_OUT || | ||
| 549 | psl_req->cmd != DIGITAL_CMD_PSL_REQ) { | ||
| 550 | rc = -EIO; | ||
| 551 | goto exit; | ||
| 552 | } | ||
| 553 | |||
| 554 | dsi = (psl_req->brs >> 3) & 0x07; | ||
| 555 | switch (dsi) { | ||
| 556 | case 0: | ||
| 557 | rf_tech = NFC_DIGITAL_RF_TECH_106A; | ||
| 558 | break; | ||
| 559 | case 1: | ||
| 560 | rf_tech = NFC_DIGITAL_RF_TECH_212F; | ||
| 561 | break; | ||
| 562 | case 2: | ||
| 563 | rf_tech = NFC_DIGITAL_RF_TECH_424F; | ||
| 564 | break; | ||
| 565 | default: | ||
| 566 | pr_err("Unsuported dsi value %d\n", dsi); | ||
| 567 | goto exit; | ||
| 568 | } | ||
| 569 | |||
| 570 | rc = digital_tg_send_psl_res(ddev, psl_req->did, rf_tech); | ||
| 571 | |||
| 572 | exit: | ||
| 573 | kfree_skb(resp); | ||
| 574 | } | ||
| 575 | |||
| 576 | static void digital_tg_send_atr_res_complete(struct nfc_digital_dev *ddev, | ||
| 577 | void *arg, struct sk_buff *resp) | ||
| 578 | { | ||
| 579 | int offset; | ||
| 580 | |||
| 581 | if (IS_ERR(resp)) { | ||
| 582 | digital_poll_next_tech(ddev); | ||
| 583 | return; | ||
| 584 | } | ||
| 585 | |||
| 586 | offset = 2; | ||
| 587 | if (resp->data[0] == DIGITAL_NFC_DEP_NFCA_SOD_SB) | ||
| 588 | offset++; | ||
| 589 | |||
| 590 | if (resp->data[offset] == DIGITAL_CMD_PSL_REQ) | ||
| 591 | digital_tg_recv_psl_req(ddev, arg, resp); | ||
| 592 | else | ||
| 593 | digital_tg_recv_dep_req(ddev, arg, resp); | ||
| 594 | } | ||
| 595 | |||
| 596 | static int digital_tg_send_atr_res(struct nfc_digital_dev *ddev, | ||
| 597 | struct digital_atr_req *atr_req) | ||
| 598 | { | ||
| 599 | struct digital_atr_res *atr_res; | ||
| 600 | struct sk_buff *skb; | ||
| 601 | u8 *gb; | ||
| 602 | size_t gb_len; | ||
| 603 | int rc; | ||
| 604 | |||
| 605 | gb = nfc_get_local_general_bytes(ddev->nfc_dev, &gb_len); | ||
| 606 | if (!gb) | ||
| 607 | gb_len = 0; | ||
| 608 | |||
| 609 | skb = digital_skb_alloc(ddev, sizeof(struct digital_atr_res) + gb_len); | ||
| 610 | if (!skb) | ||
| 611 | return -ENOMEM; | ||
| 612 | |||
| 613 | skb_put(skb, sizeof(struct digital_atr_res)); | ||
| 614 | atr_res = (struct digital_atr_res *)skb->data; | ||
| 615 | |||
| 616 | memset(atr_res, 0, sizeof(struct digital_atr_res)); | ||
| 617 | |||
| 618 | atr_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN; | ||
| 619 | atr_res->cmd = DIGITAL_CMD_ATR_RES; | ||
| 620 | memcpy(atr_res->nfcid3, atr_req->nfcid3, sizeof(atr_req->nfcid3)); | ||
| 621 | atr_res->to = 8; | ||
| 622 | atr_res->pp = DIGITAL_LR_BITS_PAYLOAD_SIZE_254B; | ||
| 623 | if (gb_len) { | ||
| 624 | skb_put(skb, gb_len); | ||
| 625 | |||
| 626 | atr_res->pp |= DIGITAL_GB_BIT; | ||
| 627 | memcpy(atr_res->gb, gb, gb_len); | ||
| 628 | } | ||
| 629 | |||
| 630 | digital_skb_push_dep_sod(ddev, skb); | ||
| 631 | |||
| 632 | ddev->skb_add_crc(skb); | ||
| 633 | |||
| 634 | rc = digital_tg_send_cmd(ddev, skb, 999, | ||
| 635 | digital_tg_send_atr_res_complete, NULL); | ||
| 636 | if (rc) { | ||
| 637 | kfree_skb(skb); | ||
| 638 | return rc; | ||
| 639 | } | ||
| 640 | |||
| 641 | return rc; | ||
| 642 | } | ||
| 643 | |||
| 644 | void digital_tg_recv_atr_req(struct nfc_digital_dev *ddev, void *arg, | ||
| 645 | struct sk_buff *resp) | ||
| 646 | { | ||
| 647 | int rc; | ||
| 648 | struct digital_atr_req *atr_req; | ||
| 649 | size_t gb_len, min_size; | ||
| 650 | |||
| 651 | if (IS_ERR(resp)) { | ||
| 652 | rc = PTR_ERR(resp); | ||
| 653 | resp = NULL; | ||
| 654 | goto exit; | ||
| 655 | } | ||
| 656 | |||
| 657 | if (!resp->len) { | ||
| 658 | rc = -EIO; | ||
| 659 | goto exit; | ||
| 660 | } | ||
| 661 | |||
| 662 | if (resp->data[0] == DIGITAL_NFC_DEP_NFCA_SOD_SB) { | ||
| 663 | min_size = DIGITAL_ATR_REQ_MIN_SIZE + 2; | ||
| 664 | |||
| 665 | ddev->curr_rf_tech = NFC_DIGITAL_RF_TECH_106A; | ||
| 666 | ddev->skb_add_crc = digital_skb_add_crc_a; | ||
| 667 | ddev->skb_check_crc = digital_skb_check_crc_a; | ||
| 668 | } else { | ||
| 669 | min_size = DIGITAL_ATR_REQ_MIN_SIZE + 1; | ||
| 670 | |||
| 671 | ddev->curr_rf_tech = NFC_DIGITAL_RF_TECH_212F; | ||
| 672 | ddev->skb_add_crc = digital_skb_add_crc_f; | ||
| 673 | ddev->skb_check_crc = digital_skb_check_crc_f; | ||
| 674 | } | ||
| 675 | |||
| 676 | if (resp->len < min_size) { | ||
| 677 | rc = -EIO; | ||
| 678 | goto exit; | ||
| 679 | } | ||
| 680 | |||
| 681 | if (DIGITAL_DRV_CAPS_TG_CRC(ddev)) { | ||
| 682 | ddev->skb_add_crc = digital_skb_add_crc_none; | ||
| 683 | ddev->skb_check_crc = digital_skb_check_crc_none; | ||
| 684 | } | ||
| 685 | |||
| 686 | rc = ddev->skb_check_crc(resp); | ||
| 687 | if (rc) { | ||
| 688 | PROTOCOL_ERR("14.4.1.6"); | ||
| 689 | goto exit; | ||
| 690 | } | ||
| 691 | |||
| 692 | rc = digital_skb_pull_dep_sod(ddev, resp); | ||
| 693 | if (rc) { | ||
| 694 | PROTOCOL_ERR("14.4.1.2"); | ||
| 695 | goto exit; | ||
| 696 | } | ||
| 697 | |||
| 698 | atr_req = (struct digital_atr_req *)resp->data; | ||
| 699 | |||
| 700 | if (atr_req->dir != DIGITAL_NFC_DEP_FRAME_DIR_OUT || | ||
| 701 | atr_req->cmd != DIGITAL_CMD_ATR_REQ) { | ||
| 702 | rc = -EINVAL; | ||
| 703 | goto exit; | ||
| 704 | } | ||
| 705 | |||
| 706 | rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, | ||
| 707 | NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED); | ||
| 708 | if (rc) | ||
| 709 | goto exit; | ||
| 710 | |||
| 711 | rc = digital_tg_send_atr_res(ddev, atr_req); | ||
| 712 | if (rc) | ||
| 713 | goto exit; | ||
| 714 | |||
| 715 | gb_len = resp->len - sizeof(struct digital_atr_req); | ||
| 716 | rc = nfc_tm_activated(ddev->nfc_dev, NFC_PROTO_NFC_DEP_MASK, | ||
| 717 | NFC_COMM_PASSIVE, atr_req->gb, gb_len); | ||
| 718 | if (rc) | ||
| 719 | goto exit; | ||
| 720 | |||
| 721 | ddev->poll_tech_count = 0; | ||
| 722 | |||
| 723 | rc = 0; | ||
| 724 | exit: | ||
| 725 | if (rc) | ||
| 726 | digital_poll_next_tech(ddev); | ||
| 727 | |||
| 728 | dev_kfree_skb(resp); | ||
| 729 | } | ||
diff --git a/net/nfc/digital_technology.c b/net/nfc/digital_technology.c new file mode 100644 index 000000000000..251c8c753ebe --- /dev/null +++ b/net/nfc/digital_technology.c | |||
| @@ -0,0 +1,770 @@ | |||
| 1 | /* | ||
| 2 | * NFC Digital Protocol stack | ||
| 3 | * Copyright (c) 2013, Intel Corporation. | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify it | ||
| 6 | * under the terms and conditions of the GNU General Public License, | ||
| 7 | * version 2, as published by the Free Software Foundation. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
| 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 12 | * more details. | ||
| 13 | * | ||
| 14 | */ | ||
| 15 | |||
| 16 | #define pr_fmt(fmt) "digital: %s: " fmt, __func__ | ||
| 17 | |||
| 18 | #include "digital.h" | ||
| 19 | |||
| 20 | #define DIGITAL_CMD_SENS_REQ 0x26 | ||
| 21 | #define DIGITAL_CMD_ALL_REQ 0x52 | ||
| 22 | #define DIGITAL_CMD_SEL_REQ_CL1 0x93 | ||
| 23 | #define DIGITAL_CMD_SEL_REQ_CL2 0x95 | ||
| 24 | #define DIGITAL_CMD_SEL_REQ_CL3 0x97 | ||
| 25 | |||
| 26 | #define DIGITAL_SDD_REQ_SEL_PAR 0x20 | ||
| 27 | |||
| 28 | #define DIGITAL_SDD_RES_CT 0x88 | ||
| 29 | #define DIGITAL_SDD_RES_LEN 5 | ||
| 30 | |||
| 31 | #define DIGITAL_SEL_RES_NFCID1_COMPLETE(sel_res) (!((sel_res) & 0x04)) | ||
| 32 | #define DIGITAL_SEL_RES_IS_T2T(sel_res) (!((sel_res) & 0x60)) | ||
| 33 | #define DIGITAL_SEL_RES_IS_NFC_DEP(sel_res) ((sel_res) & 0x40) | ||
| 34 | |||
| 35 | #define DIGITAL_SENS_RES_IS_T1T(sens_res) (((sens_res) & 0x0C00) == 0x0C00) | ||
| 36 | #define DIGITAL_SENS_RES_IS_VALID(sens_res) \ | ||
| 37 | ((!((sens_res) & 0x001F) && (((sens_res) & 0x0C00) == 0x0C00)) || \ | ||
| 38 | (((sens_res) & 0x001F) && ((sens_res) & 0x0C00) != 0x0C00)) | ||
| 39 | |||
| 40 | #define DIGITAL_MIFARE_READ_RES_LEN 16 | ||
| 41 | #define DIGITAL_MIFARE_ACK_RES 0x0A | ||
| 42 | |||
| 43 | #define DIGITAL_CMD_SENSF_REQ 0x00 | ||
| 44 | #define DIGITAL_CMD_SENSF_RES 0x01 | ||
| 45 | |||
| 46 | #define DIGITAL_SENSF_RES_MIN_LENGTH 17 | ||
| 47 | #define DIGITAL_SENSF_RES_RD_AP_B1 0x00 | ||
| 48 | #define DIGITAL_SENSF_RES_RD_AP_B2 0x8F | ||
| 49 | |||
| 50 | #define DIGITAL_SENSF_REQ_RC_NONE 0 | ||
| 51 | #define DIGITAL_SENSF_REQ_RC_SC 1 | ||
| 52 | #define DIGITAL_SENSF_REQ_RC_AP 2 | ||
| 53 | |||
| 54 | struct digital_sdd_res { | ||
| 55 | u8 nfcid1[4]; | ||
| 56 | u8 bcc; | ||
| 57 | } __packed; | ||
| 58 | |||
| 59 | struct digital_sel_req { | ||
| 60 | u8 sel_cmd; | ||
| 61 | u8 b2; | ||
| 62 | u8 nfcid1[4]; | ||
| 63 | u8 bcc; | ||
| 64 | } __packed; | ||
| 65 | |||
| 66 | struct digital_sensf_req { | ||
| 67 | u8 cmd; | ||
| 68 | u8 sc1; | ||
| 69 | u8 sc2; | ||
| 70 | u8 rc; | ||
| 71 | u8 tsn; | ||
| 72 | } __packed; | ||
| 73 | |||
| 74 | struct digital_sensf_res { | ||
| 75 | u8 cmd; | ||
| 76 | u8 nfcid2[8]; | ||
| 77 | u8 pad0[2]; | ||
| 78 | u8 pad1[3]; | ||
| 79 | u8 mrti_check; | ||
| 80 | u8 mrti_update; | ||
| 81 | u8 pad2; | ||
| 82 | u8 rd[2]; | ||
| 83 | } __packed; | ||
| 84 | |||
| 85 | static int digital_in_send_sdd_req(struct nfc_digital_dev *ddev, | ||
| 86 | struct nfc_target *target); | ||
| 87 | |||
| 88 | static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg, | ||
| 89 | struct sk_buff *resp) | ||
| 90 | { | ||
| 91 | struct nfc_target *target = arg; | ||
| 92 | int rc; | ||
| 93 | u8 sel_res; | ||
| 94 | u8 nfc_proto; | ||
| 95 | |||
| 96 | if (IS_ERR(resp)) { | ||
| 97 | rc = PTR_ERR(resp); | ||
| 98 | resp = NULL; | ||
| 99 | goto exit; | ||
| 100 | } | ||
| 101 | |||
| 102 | if (!DIGITAL_DRV_CAPS_IN_CRC(ddev)) { | ||
| 103 | rc = digital_skb_check_crc_a(resp); | ||
| 104 | if (rc) { | ||
| 105 | PROTOCOL_ERR("4.4.1.3"); | ||
| 106 | goto exit; | ||
| 107 | } | ||
| 108 | } | ||
| 109 | |||
| 110 | if (!resp->len) { | ||
| 111 | rc = -EIO; | ||
| 112 | goto exit; | ||
| 113 | } | ||
| 114 | |||
| 115 | sel_res = resp->data[0]; | ||
| 116 | |||
| 117 | if (!DIGITAL_SEL_RES_NFCID1_COMPLETE(sel_res)) { | ||
| 118 | rc = digital_in_send_sdd_req(ddev, target); | ||
| 119 | if (rc) | ||
| 120 | goto exit; | ||
| 121 | |||
| 122 | goto exit_free_skb; | ||
| 123 | } | ||
| 124 | |||
| 125 | if (DIGITAL_SEL_RES_IS_T2T(sel_res)) { | ||
| 126 | nfc_proto = NFC_PROTO_MIFARE; | ||
| 127 | } else if (DIGITAL_SEL_RES_IS_NFC_DEP(sel_res)) { | ||
| 128 | nfc_proto = NFC_PROTO_NFC_DEP; | ||
| 129 | } else { | ||
| 130 | rc = -EOPNOTSUPP; | ||
| 131 | goto exit; | ||
| 132 | } | ||
| 133 | |||
| 134 | target->sel_res = sel_res; | ||
| 135 | |||
| 136 | rc = digital_target_found(ddev, target, nfc_proto); | ||
| 137 | |||
| 138 | exit: | ||
| 139 | kfree(target); | ||
| 140 | |||
| 141 | exit_free_skb: | ||
| 142 | dev_kfree_skb(resp); | ||
| 143 | |||
| 144 | if (rc) | ||
| 145 | digital_poll_next_tech(ddev); | ||
| 146 | } | ||
| 147 | |||
| 148 | static int digital_in_send_sel_req(struct nfc_digital_dev *ddev, | ||
| 149 | struct nfc_target *target, | ||
| 150 | struct digital_sdd_res *sdd_res) | ||
| 151 | { | ||
| 152 | struct sk_buff *skb; | ||
| 153 | struct digital_sel_req *sel_req; | ||
| 154 | u8 sel_cmd; | ||
| 155 | int rc; | ||
| 156 | |||
| 157 | skb = digital_skb_alloc(ddev, sizeof(struct digital_sel_req)); | ||
| 158 | if (!skb) | ||
| 159 | return -ENOMEM; | ||
| 160 | |||
| 161 | skb_put(skb, sizeof(struct digital_sel_req)); | ||
| 162 | sel_req = (struct digital_sel_req *)skb->data; | ||
| 163 | |||
| 164 | if (target->nfcid1_len <= 4) | ||
| 165 | sel_cmd = DIGITAL_CMD_SEL_REQ_CL1; | ||
| 166 | else if (target->nfcid1_len < 10) | ||
| 167 | sel_cmd = DIGITAL_CMD_SEL_REQ_CL2; | ||
| 168 | else | ||
| 169 | sel_cmd = DIGITAL_CMD_SEL_REQ_CL3; | ||
| 170 | |||
| 171 | sel_req->sel_cmd = sel_cmd; | ||
| 172 | sel_req->b2 = 0x70; | ||
| 173 | memcpy(sel_req->nfcid1, sdd_res->nfcid1, 4); | ||
| 174 | sel_req->bcc = sdd_res->bcc; | ||
| 175 | |||
| 176 | if (DIGITAL_DRV_CAPS_IN_CRC(ddev)) { | ||
| 177 | rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, | ||
| 178 | NFC_DIGITAL_FRAMING_NFCA_STANDARD_WITH_CRC_A); | ||
| 179 | if (rc) | ||
| 180 | goto exit; | ||
| 181 | } else { | ||
| 182 | digital_skb_add_crc_a(skb); | ||
| 183 | } | ||
| 184 | |||
| 185 | rc = digital_in_send_cmd(ddev, skb, 30, digital_in_recv_sel_res, | ||
| 186 | target); | ||
| 187 | exit: | ||
| 188 | if (rc) | ||
| 189 | kfree_skb(skb); | ||
| 190 | |||
| 191 | return rc; | ||
| 192 | } | ||
| 193 | |||
| 194 | static void digital_in_recv_sdd_res(struct nfc_digital_dev *ddev, void *arg, | ||
| 195 | struct sk_buff *resp) | ||
| 196 | { | ||
| 197 | struct nfc_target *target = arg; | ||
| 198 | struct digital_sdd_res *sdd_res; | ||
| 199 | int rc; | ||
| 200 | u8 offset, size; | ||
| 201 | u8 i, bcc; | ||
| 202 | |||
| 203 | if (IS_ERR(resp)) { | ||
| 204 | rc = PTR_ERR(resp); | ||
| 205 | resp = NULL; | ||
| 206 | goto exit; | ||
| 207 | } | ||
| 208 | |||
| 209 | if (resp->len < DIGITAL_SDD_RES_LEN) { | ||
| 210 | PROTOCOL_ERR("4.7.2.8"); | ||
| 211 | rc = -EINVAL; | ||
| 212 | goto exit; | ||
| 213 | } | ||
| 214 | |||
| 215 | sdd_res = (struct digital_sdd_res *)resp->data; | ||
| 216 | |||
| 217 | for (i = 0, bcc = 0; i < 4; i++) | ||
| 218 | bcc ^= sdd_res->nfcid1[i]; | ||
| 219 | |||
| 220 | if (bcc != sdd_res->bcc) { | ||
| 221 | PROTOCOL_ERR("4.7.2.6"); | ||
| 222 | rc = -EINVAL; | ||
| 223 | goto exit; | ||
| 224 | } | ||
| 225 | |||
| 226 | if (sdd_res->nfcid1[0] == DIGITAL_SDD_RES_CT) { | ||
| 227 | offset = 1; | ||
| 228 | size = 3; | ||
| 229 | } else { | ||
| 230 | offset = 0; | ||
| 231 | size = 4; | ||
| 232 | } | ||
| 233 | |||
| 234 | memcpy(target->nfcid1 + target->nfcid1_len, sdd_res->nfcid1 + offset, | ||
| 235 | size); | ||
| 236 | target->nfcid1_len += size; | ||
| 237 | |||
| 238 | rc = digital_in_send_sel_req(ddev, target, sdd_res); | ||
| 239 | |||
| 240 | exit: | ||
| 241 | dev_kfree_skb(resp); | ||
| 242 | |||
| 243 | if (rc) { | ||
| 244 | kfree(target); | ||
| 245 | digital_poll_next_tech(ddev); | ||
| 246 | } | ||
| 247 | } | ||
| 248 | |||
| 249 | static int digital_in_send_sdd_req(struct nfc_digital_dev *ddev, | ||
| 250 | struct nfc_target *target) | ||
| 251 | { | ||
| 252 | int rc; | ||
| 253 | struct sk_buff *skb; | ||
| 254 | u8 sel_cmd; | ||
| 255 | |||
| 256 | rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, | ||
| 257 | NFC_DIGITAL_FRAMING_NFCA_STANDARD); | ||
| 258 | if (rc) | ||
| 259 | return rc; | ||
| 260 | |||
| 261 | skb = digital_skb_alloc(ddev, 2); | ||
| 262 | if (!skb) | ||
| 263 | return -ENOMEM; | ||
| 264 | |||
| 265 | if (target->nfcid1_len == 0) | ||
| 266 | sel_cmd = DIGITAL_CMD_SEL_REQ_CL1; | ||
| 267 | else if (target->nfcid1_len == 3) | ||
| 268 | sel_cmd = DIGITAL_CMD_SEL_REQ_CL2; | ||
| 269 | else | ||
| 270 | sel_cmd = DIGITAL_CMD_SEL_REQ_CL3; | ||
| 271 | |||
| 272 | *skb_put(skb, sizeof(u8)) = sel_cmd; | ||
| 273 | *skb_put(skb, sizeof(u8)) = DIGITAL_SDD_REQ_SEL_PAR; | ||
| 274 | |||
| 275 | return digital_in_send_cmd(ddev, skb, 30, digital_in_recv_sdd_res, | ||
| 276 | target); | ||
| 277 | } | ||
| 278 | |||
| 279 | static void digital_in_recv_sens_res(struct nfc_digital_dev *ddev, void *arg, | ||
| 280 | struct sk_buff *resp) | ||
| 281 | { | ||
| 282 | struct nfc_target *target = NULL; | ||
| 283 | int rc; | ||
| 284 | |||
| 285 | if (IS_ERR(resp)) { | ||
| 286 | rc = PTR_ERR(resp); | ||
| 287 | resp = NULL; | ||
| 288 | goto exit; | ||
| 289 | } | ||
| 290 | |||
| 291 | if (resp->len < sizeof(u16)) { | ||
| 292 | rc = -EIO; | ||
| 293 | goto exit; | ||
| 294 | } | ||
| 295 | |||
| 296 | target = kzalloc(sizeof(struct nfc_target), GFP_KERNEL); | ||
| 297 | if (!target) { | ||
| 298 | rc = -ENOMEM; | ||
| 299 | goto exit; | ||
| 300 | } | ||
| 301 | |||
| 302 | target->sens_res = __le16_to_cpu(*(__le16 *)resp->data); | ||
| 303 | |||
| 304 | if (!DIGITAL_SENS_RES_IS_VALID(target->sens_res)) { | ||
| 305 | PROTOCOL_ERR("4.6.3.3"); | ||
| 306 | rc = -EINVAL; | ||
| 307 | goto exit; | ||
| 308 | } | ||
| 309 | |||
| 310 | if (DIGITAL_SENS_RES_IS_T1T(target->sens_res)) | ||
| 311 | rc = digital_target_found(ddev, target, NFC_PROTO_JEWEL); | ||
| 312 | else | ||
| 313 | rc = digital_in_send_sdd_req(ddev, target); | ||
| 314 | |||
| 315 | exit: | ||
| 316 | dev_kfree_skb(resp); | ||
| 317 | |||
| 318 | if (rc) { | ||
| 319 | kfree(target); | ||
| 320 | digital_poll_next_tech(ddev); | ||
| 321 | } | ||
| 322 | } | ||
| 323 | |||
| 324 | int digital_in_send_sens_req(struct nfc_digital_dev *ddev, u8 rf_tech) | ||
| 325 | { | ||
| 326 | struct sk_buff *skb; | ||
| 327 | int rc; | ||
| 328 | |||
| 329 | rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, | ||
| 330 | NFC_DIGITAL_RF_TECH_106A); | ||
| 331 | if (rc) | ||
| 332 | return rc; | ||
| 333 | |||
| 334 | rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, | ||
| 335 | NFC_DIGITAL_FRAMING_NFCA_SHORT); | ||
| 336 | if (rc) | ||
| 337 | return rc; | ||
| 338 | |||
| 339 | skb = digital_skb_alloc(ddev, 1); | ||
| 340 | if (!skb) | ||
| 341 | return -ENOMEM; | ||
| 342 | |||
| 343 | *skb_put(skb, sizeof(u8)) = DIGITAL_CMD_SENS_REQ; | ||
| 344 | |||
| 345 | rc = digital_in_send_cmd(ddev, skb, 30, digital_in_recv_sens_res, NULL); | ||
| 346 | if (rc) | ||
| 347 | kfree_skb(skb); | ||
| 348 | |||
| 349 | return rc; | ||
| 350 | } | ||
| 351 | |||
| 352 | int digital_in_recv_mifare_res(struct sk_buff *resp) | ||
| 353 | { | ||
| 354 | /* Successful READ command response is 16 data bytes + 2 CRC bytes long. | ||
| 355 | * Since the driver can't differentiate a ACK/NACK response from a valid | ||
| 356 | * READ response, the CRC calculation must be handled at digital level | ||
| 357 | * even if the driver supports it for this technology. | ||
| 358 | */ | ||
| 359 | if (resp->len == DIGITAL_MIFARE_READ_RES_LEN + DIGITAL_CRC_LEN) { | ||
| 360 | if (digital_skb_check_crc_a(resp)) { | ||
| 361 | PROTOCOL_ERR("9.4.1.2"); | ||
| 362 | return -EIO; | ||
| 363 | } | ||
| 364 | |||
| 365 | return 0; | ||
| 366 | } | ||
| 367 | |||
| 368 | /* ACK response (i.e. successful WRITE). */ | ||
| 369 | if (resp->len == 1 && resp->data[0] == DIGITAL_MIFARE_ACK_RES) { | ||
| 370 | resp->data[0] = 0; | ||
| 371 | return 0; | ||
| 372 | } | ||
| 373 | |||
| 374 | /* NACK and any other responses are treated as error. */ | ||
| 375 | return -EIO; | ||
| 376 | } | ||
| 377 | |||
| 378 | static void digital_in_recv_sensf_res(struct nfc_digital_dev *ddev, void *arg, | ||
| 379 | struct sk_buff *resp) | ||
| 380 | { | ||
| 381 | int rc; | ||
| 382 | u8 proto; | ||
| 383 | struct nfc_target target; | ||
| 384 | struct digital_sensf_res *sensf_res; | ||
| 385 | |||
| 386 | if (IS_ERR(resp)) { | ||
| 387 | rc = PTR_ERR(resp); | ||
| 388 | resp = NULL; | ||
| 389 | goto exit; | ||
| 390 | } | ||
| 391 | |||
| 392 | if (resp->len < DIGITAL_SENSF_RES_MIN_LENGTH) { | ||
| 393 | rc = -EIO; | ||
| 394 | goto exit; | ||
| 395 | } | ||
| 396 | |||
| 397 | if (!DIGITAL_DRV_CAPS_IN_CRC(ddev)) { | ||
| 398 | rc = digital_skb_check_crc_f(resp); | ||
| 399 | if (rc) { | ||
| 400 | PROTOCOL_ERR("6.4.1.8"); | ||
| 401 | goto exit; | ||
| 402 | } | ||
| 403 | } | ||
| 404 | |||
| 405 | skb_pull(resp, 1); | ||
| 406 | |||
| 407 | memset(&target, 0, sizeof(struct nfc_target)); | ||
| 408 | |||
| 409 | sensf_res = (struct digital_sensf_res *)resp->data; | ||
| 410 | |||
| 411 | memcpy(target.sensf_res, sensf_res, resp->len); | ||
| 412 | target.sensf_res_len = resp->len; | ||
| 413 | |||
| 414 | memcpy(target.nfcid2, sensf_res->nfcid2, NFC_NFCID2_MAXSIZE); | ||
| 415 | target.nfcid2_len = NFC_NFCID2_MAXSIZE; | ||
| 416 | |||
| 417 | if (target.nfcid2[0] == DIGITAL_SENSF_NFCID2_NFC_DEP_B1 && | ||
| 418 | target.nfcid2[1] == DIGITAL_SENSF_NFCID2_NFC_DEP_B2) | ||
| 419 | proto = NFC_PROTO_NFC_DEP; | ||
| 420 | else | ||
| 421 | proto = NFC_PROTO_FELICA; | ||
| 422 | |||
| 423 | rc = digital_target_found(ddev, &target, proto); | ||
| 424 | |||
| 425 | exit: | ||
| 426 | dev_kfree_skb(resp); | ||
| 427 | |||
| 428 | if (rc) | ||
| 429 | digital_poll_next_tech(ddev); | ||
| 430 | } | ||
| 431 | |||
| 432 | int digital_in_send_sensf_req(struct nfc_digital_dev *ddev, u8 rf_tech) | ||
| 433 | { | ||
| 434 | struct digital_sensf_req *sensf_req; | ||
| 435 | struct sk_buff *skb; | ||
| 436 | int rc; | ||
| 437 | u8 size; | ||
| 438 | |||
| 439 | rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, rf_tech); | ||
| 440 | if (rc) | ||
| 441 | return rc; | ||
| 442 | |||
| 443 | rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, | ||
| 444 | NFC_DIGITAL_FRAMING_NFCF); | ||
| 445 | if (rc) | ||
| 446 | return rc; | ||
| 447 | |||
| 448 | size = sizeof(struct digital_sensf_req); | ||
| 449 | |||
| 450 | skb = digital_skb_alloc(ddev, size); | ||
| 451 | if (!skb) | ||
| 452 | return -ENOMEM; | ||
| 453 | |||
| 454 | skb_put(skb, size); | ||
| 455 | |||
| 456 | sensf_req = (struct digital_sensf_req *)skb->data; | ||
| 457 | sensf_req->cmd = DIGITAL_CMD_SENSF_REQ; | ||
| 458 | sensf_req->sc1 = 0xFF; | ||
| 459 | sensf_req->sc2 = 0xFF; | ||
| 460 | sensf_req->rc = 0; | ||
| 461 | sensf_req->tsn = 0; | ||
| 462 | |||
| 463 | *skb_push(skb, 1) = size + 1; | ||
| 464 | |||
| 465 | if (!DIGITAL_DRV_CAPS_IN_CRC(ddev)) | ||
| 466 | digital_skb_add_crc_f(skb); | ||
| 467 | |||
| 468 | rc = digital_in_send_cmd(ddev, skb, 30, digital_in_recv_sensf_res, | ||
| 469 | NULL); | ||
| 470 | if (rc) | ||
| 471 | kfree_skb(skb); | ||
| 472 | |||
| 473 | return rc; | ||
| 474 | } | ||
| 475 | |||
| 476 | static int digital_tg_send_sel_res(struct nfc_digital_dev *ddev) | ||
| 477 | { | ||
| 478 | struct sk_buff *skb; | ||
| 479 | int rc; | ||
| 480 | |||
| 481 | skb = digital_skb_alloc(ddev, 1); | ||
| 482 | if (!skb) | ||
| 483 | return -ENOMEM; | ||
| 484 | |||
| 485 | *skb_put(skb, 1) = DIGITAL_SEL_RES_NFC_DEP; | ||
| 486 | |||
| 487 | if (!DIGITAL_DRV_CAPS_TG_CRC(ddev)) | ||
| 488 | digital_skb_add_crc_a(skb); | ||
| 489 | |||
| 490 | rc = digital_tg_send_cmd(ddev, skb, 300, digital_tg_recv_atr_req, | ||
| 491 | NULL); | ||
| 492 | if (rc) | ||
| 493 | kfree_skb(skb); | ||
| 494 | |||
| 495 | return rc; | ||
| 496 | } | ||
| 497 | |||
| 498 | static void digital_tg_recv_sel_req(struct nfc_digital_dev *ddev, void *arg, | ||
| 499 | struct sk_buff *resp) | ||
| 500 | { | ||
| 501 | int rc; | ||
| 502 | |||
| 503 | if (IS_ERR(resp)) { | ||
| 504 | rc = PTR_ERR(resp); | ||
| 505 | resp = NULL; | ||
| 506 | goto exit; | ||
| 507 | } | ||
| 508 | |||
| 509 | if (!DIGITAL_DRV_CAPS_TG_CRC(ddev)) { | ||
| 510 | rc = digital_skb_check_crc_a(resp); | ||
| 511 | if (rc) { | ||
| 512 | PROTOCOL_ERR("4.4.1.3"); | ||
| 513 | goto exit; | ||
| 514 | } | ||
| 515 | } | ||
| 516 | |||
| 517 | /* Silently ignore SEL_REQ content and send a SEL_RES for NFC-DEP */ | ||
| 518 | |||
| 519 | rc = digital_tg_send_sel_res(ddev); | ||
| 520 | |||
| 521 | exit: | ||
| 522 | if (rc) | ||
| 523 | digital_poll_next_tech(ddev); | ||
| 524 | |||
| 525 | dev_kfree_skb(resp); | ||
| 526 | } | ||
| 527 | |||
| 528 | static int digital_tg_send_sdd_res(struct nfc_digital_dev *ddev) | ||
| 529 | { | ||
| 530 | struct sk_buff *skb; | ||
| 531 | struct digital_sdd_res *sdd_res; | ||
| 532 | int rc, i; | ||
| 533 | |||
| 534 | skb = digital_skb_alloc(ddev, sizeof(struct digital_sdd_res)); | ||
| 535 | if (!skb) | ||
| 536 | return -ENOMEM; | ||
| 537 | |||
| 538 | skb_put(skb, sizeof(struct digital_sdd_res)); | ||
| 539 | sdd_res = (struct digital_sdd_res *)skb->data; | ||
| 540 | |||
| 541 | sdd_res->nfcid1[0] = 0x08; | ||
| 542 | get_random_bytes(sdd_res->nfcid1 + 1, 3); | ||
| 543 | |||
| 544 | sdd_res->bcc = 0; | ||
| 545 | for (i = 0; i < 4; i++) | ||
| 546 | sdd_res->bcc ^= sdd_res->nfcid1[i]; | ||
| 547 | |||
| 548 | rc = digital_tg_send_cmd(ddev, skb, 300, digital_tg_recv_sel_req, | ||
| 549 | NULL); | ||
| 550 | if (rc) | ||
| 551 | kfree_skb(skb); | ||
| 552 | |||
| 553 | return rc; | ||
| 554 | } | ||
| 555 | |||
| 556 | static void digital_tg_recv_sdd_req(struct nfc_digital_dev *ddev, void *arg, | ||
| 557 | struct sk_buff *resp) | ||
| 558 | { | ||
| 559 | u8 *sdd_req; | ||
| 560 | int rc; | ||
| 561 | |||
| 562 | if (IS_ERR(resp)) { | ||
| 563 | rc = PTR_ERR(resp); | ||
| 564 | resp = NULL; | ||
| 565 | goto exit; | ||
| 566 | } | ||
| 567 | |||
| 568 | sdd_req = resp->data; | ||
| 569 | |||
| 570 | if (resp->len < 2 || sdd_req[0] != DIGITAL_CMD_SEL_REQ_CL1 || | ||
| 571 | sdd_req[1] != DIGITAL_SDD_REQ_SEL_PAR) { | ||
| 572 | rc = -EINVAL; | ||
| 573 | goto exit; | ||
| 574 | } | ||
| 575 | |||
| 576 | rc = digital_tg_send_sdd_res(ddev); | ||
| 577 | |||
| 578 | exit: | ||
| 579 | if (rc) | ||
| 580 | digital_poll_next_tech(ddev); | ||
| 581 | |||
| 582 | dev_kfree_skb(resp); | ||
| 583 | } | ||
| 584 | |||
| 585 | static int digital_tg_send_sens_res(struct nfc_digital_dev *ddev) | ||
| 586 | { | ||
| 587 | struct sk_buff *skb; | ||
| 588 | u8 *sens_res; | ||
| 589 | int rc; | ||
| 590 | |||
| 591 | skb = digital_skb_alloc(ddev, 2); | ||
| 592 | if (!skb) | ||
| 593 | return -ENOMEM; | ||
| 594 | |||
| 595 | sens_res = skb_put(skb, 2); | ||
| 596 | |||
| 597 | sens_res[0] = (DIGITAL_SENS_RES_NFC_DEP >> 8) & 0xFF; | ||
| 598 | sens_res[1] = DIGITAL_SENS_RES_NFC_DEP & 0xFF; | ||
| 599 | |||
| 600 | rc = digital_tg_send_cmd(ddev, skb, 300, digital_tg_recv_sdd_req, | ||
| 601 | NULL); | ||
| 602 | if (rc) | ||
| 603 | kfree_skb(skb); | ||
| 604 | |||
| 605 | return rc; | ||
| 606 | } | ||
| 607 | |||
| 608 | void digital_tg_recv_sens_req(struct nfc_digital_dev *ddev, void *arg, | ||
| 609 | struct sk_buff *resp) | ||
| 610 | { | ||
| 611 | u8 sens_req; | ||
| 612 | int rc; | ||
| 613 | |||
| 614 | if (IS_ERR(resp)) { | ||
| 615 | rc = PTR_ERR(resp); | ||
| 616 | resp = NULL; | ||
| 617 | goto exit; | ||
| 618 | } | ||
| 619 | |||
| 620 | sens_req = resp->data[0]; | ||
| 621 | |||
| 622 | if (!resp->len || (sens_req != DIGITAL_CMD_SENS_REQ && | ||
| 623 | sens_req != DIGITAL_CMD_ALL_REQ)) { | ||
| 624 | rc = -EINVAL; | ||
| 625 | goto exit; | ||
| 626 | } | ||
| 627 | |||
| 628 | rc = digital_tg_send_sens_res(ddev); | ||
| 629 | |||
| 630 | exit: | ||
| 631 | if (rc) | ||
| 632 | digital_poll_next_tech(ddev); | ||
| 633 | |||
| 634 | dev_kfree_skb(resp); | ||
| 635 | } | ||
| 636 | |||
| 637 | static int digital_tg_send_sensf_res(struct nfc_digital_dev *ddev, | ||
| 638 | struct digital_sensf_req *sensf_req) | ||
| 639 | { | ||
| 640 | struct sk_buff *skb; | ||
| 641 | u8 size; | ||
| 642 | int rc; | ||
| 643 | struct digital_sensf_res *sensf_res; | ||
| 644 | |||
| 645 | size = sizeof(struct digital_sensf_res); | ||
| 646 | |||
| 647 | if (sensf_req->rc != DIGITAL_SENSF_REQ_RC_NONE) | ||
| 648 | size -= sizeof(sensf_res->rd); | ||
| 649 | |||
| 650 | skb = digital_skb_alloc(ddev, size); | ||
| 651 | if (!skb) | ||
| 652 | return -ENOMEM; | ||
| 653 | |||
| 654 | skb_put(skb, size); | ||
| 655 | |||
| 656 | sensf_res = (struct digital_sensf_res *)skb->data; | ||
| 657 | |||
| 658 | memset(sensf_res, 0, size); | ||
| 659 | |||
| 660 | sensf_res->cmd = DIGITAL_CMD_SENSF_RES; | ||
| 661 | sensf_res->nfcid2[0] = DIGITAL_SENSF_NFCID2_NFC_DEP_B1; | ||
| 662 | sensf_res->nfcid2[1] = DIGITAL_SENSF_NFCID2_NFC_DEP_B2; | ||
| 663 | get_random_bytes(&sensf_res->nfcid2[2], 6); | ||
| 664 | |||
| 665 | switch (sensf_req->rc) { | ||
| 666 | case DIGITAL_SENSF_REQ_RC_SC: | ||
| 667 | sensf_res->rd[0] = sensf_req->sc1; | ||
| 668 | sensf_res->rd[1] = sensf_req->sc2; | ||
| 669 | break; | ||
| 670 | case DIGITAL_SENSF_REQ_RC_AP: | ||
| 671 | sensf_res->rd[0] = DIGITAL_SENSF_RES_RD_AP_B1; | ||
| 672 | sensf_res->rd[1] = DIGITAL_SENSF_RES_RD_AP_B2; | ||
| 673 | break; | ||
| 674 | } | ||
| 675 | |||
| 676 | *skb_push(skb, sizeof(u8)) = size + 1; | ||
| 677 | |||
| 678 | if (!DIGITAL_DRV_CAPS_TG_CRC(ddev)) | ||
| 679 | digital_skb_add_crc_f(skb); | ||
| 680 | |||
| 681 | rc = digital_tg_send_cmd(ddev, skb, 300, | ||
| 682 | digital_tg_recv_atr_req, NULL); | ||
| 683 | if (rc) | ||
| 684 | kfree_skb(skb); | ||
| 685 | |||
| 686 | return rc; | ||
| 687 | } | ||
| 688 | |||
| 689 | void digital_tg_recv_sensf_req(struct nfc_digital_dev *ddev, void *arg, | ||
| 690 | struct sk_buff *resp) | ||
| 691 | { | ||
| 692 | struct digital_sensf_req *sensf_req; | ||
| 693 | int rc; | ||
| 694 | |||
| 695 | if (IS_ERR(resp)) { | ||
| 696 | rc = PTR_ERR(resp); | ||
| 697 | resp = NULL; | ||
| 698 | goto exit; | ||
| 699 | } | ||
| 700 | |||
| 701 | if (!DIGITAL_DRV_CAPS_TG_CRC(ddev)) { | ||
| 702 | rc = digital_skb_check_crc_f(resp); | ||
| 703 | if (rc) { | ||
| 704 | PROTOCOL_ERR("6.4.1.8"); | ||
| 705 | goto exit; | ||
| 706 | } | ||
| 707 | } | ||
| 708 | |||
| 709 | if (resp->len != sizeof(struct digital_sensf_req) + 1) { | ||
| 710 | rc = -EINVAL; | ||
| 711 | goto exit; | ||
| 712 | } | ||
| 713 | |||
| 714 | skb_pull(resp, 1); | ||
| 715 | sensf_req = (struct digital_sensf_req *)resp->data; | ||
| 716 | |||
| 717 | if (sensf_req->cmd != DIGITAL_CMD_SENSF_REQ) { | ||
| 718 | rc = -EINVAL; | ||
| 719 | goto exit; | ||
| 720 | } | ||
| 721 | |||
| 722 | rc = digital_tg_send_sensf_res(ddev, sensf_req); | ||
| 723 | |||
| 724 | exit: | ||
| 725 | if (rc) | ||
| 726 | digital_poll_next_tech(ddev); | ||
| 727 | |||
| 728 | dev_kfree_skb(resp); | ||
| 729 | } | ||
| 730 | |||
| 731 | int digital_tg_listen_nfca(struct nfc_digital_dev *ddev, u8 rf_tech) | ||
| 732 | { | ||
| 733 | int rc; | ||
| 734 | |||
| 735 | rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, rf_tech); | ||
| 736 | if (rc) | ||
| 737 | return rc; | ||
| 738 | |||
| 739 | rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, | ||
| 740 | NFC_DIGITAL_FRAMING_NFCA_NFC_DEP); | ||
| 741 | if (rc) | ||
| 742 | return rc; | ||
| 743 | |||
| 744 | return digital_tg_listen(ddev, 300, digital_tg_recv_sens_req, NULL); | ||
| 745 | } | ||
| 746 | |||
| 747 | int digital_tg_listen_nfcf(struct nfc_digital_dev *ddev, u8 rf_tech) | ||
| 748 | { | ||
| 749 | int rc; | ||
| 750 | u8 *nfcid2; | ||
| 751 | |||
| 752 | rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, rf_tech); | ||
| 753 | if (rc) | ||
| 754 | return rc; | ||
| 755 | |||
| 756 | rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, | ||
| 757 | NFC_DIGITAL_FRAMING_NFCF_NFC_DEP); | ||
| 758 | if (rc) | ||
| 759 | return rc; | ||
| 760 | |||
| 761 | nfcid2 = kzalloc(NFC_NFCID2_MAXSIZE, GFP_KERNEL); | ||
| 762 | if (!nfcid2) | ||
| 763 | return -ENOMEM; | ||
| 764 | |||
| 765 | nfcid2[0] = DIGITAL_SENSF_NFCID2_NFC_DEP_B1; | ||
| 766 | nfcid2[1] = DIGITAL_SENSF_NFCID2_NFC_DEP_B2; | ||
| 767 | get_random_bytes(nfcid2 + 2, NFC_NFCID2_MAXSIZE - 2); | ||
| 768 | |||
| 769 | return digital_tg_listen(ddev, 300, digital_tg_recv_sensf_req, nfcid2); | ||
| 770 | } | ||
diff --git a/net/nfc/nci/spi.c b/net/nfc/nci/spi.c index c7cf37ba7298..f1d426f10cce 100644 --- a/net/nfc/nci/spi.c +++ b/net/nfc/nci/spi.c | |||
| @@ -21,11 +21,8 @@ | |||
| 21 | #include <linux/export.h> | 21 | #include <linux/export.h> |
| 22 | #include <linux/spi/spi.h> | 22 | #include <linux/spi/spi.h> |
| 23 | #include <linux/crc-ccitt.h> | 23 | #include <linux/crc-ccitt.h> |
| 24 | #include <linux/nfc.h> | ||
| 25 | #include <net/nfc/nci_core.h> | 24 | #include <net/nfc/nci_core.h> |
| 26 | 25 | ||
| 27 | #define NCI_SPI_HDR_LEN 4 | ||
| 28 | #define NCI_SPI_CRC_LEN 2 | ||
| 29 | #define NCI_SPI_ACK_SHIFT 6 | 26 | #define NCI_SPI_ACK_SHIFT 6 |
| 30 | #define NCI_SPI_MSB_PAYLOAD_MASK 0x3F | 27 | #define NCI_SPI_MSB_PAYLOAD_MASK 0x3F |
| 31 | 28 | ||
| @@ -41,54 +38,48 @@ | |||
| 41 | 38 | ||
| 42 | #define CRC_INIT 0xFFFF | 39 | #define CRC_INIT 0xFFFF |
| 43 | 40 | ||
| 44 | static int nci_spi_open(struct nci_dev *nci_dev) | 41 | static int __nci_spi_send(struct nci_spi *nspi, struct sk_buff *skb, |
| 45 | { | 42 | int cs_change) |
| 46 | struct nci_spi_dev *ndev = nci_get_drvdata(nci_dev); | ||
| 47 | |||
| 48 | return ndev->ops->open(ndev); | ||
| 49 | } | ||
| 50 | |||
| 51 | static int nci_spi_close(struct nci_dev *nci_dev) | ||
| 52 | { | ||
| 53 | struct nci_spi_dev *ndev = nci_get_drvdata(nci_dev); | ||
| 54 | |||
| 55 | return ndev->ops->close(ndev); | ||
| 56 | } | ||
| 57 | |||
| 58 | static int __nci_spi_send(struct nci_spi_dev *ndev, struct sk_buff *skb) | ||
| 59 | { | 43 | { |
| 60 | struct spi_message m; | 44 | struct spi_message m; |
| 61 | struct spi_transfer t; | 45 | struct spi_transfer t; |
| 62 | 46 | ||
| 63 | t.tx_buf = skb->data; | 47 | memset(&t, 0, sizeof(struct spi_transfer)); |
| 64 | t.len = skb->len; | 48 | /* a NULL skb means we just want the SPI chip select line to raise */ |
| 65 | t.cs_change = 0; | 49 | if (skb) { |
| 66 | t.delay_usecs = ndev->xfer_udelay; | 50 | t.tx_buf = skb->data; |
| 51 | t.len = skb->len; | ||
| 52 | } else { | ||
| 53 | /* still set tx_buf non NULL to make the driver happy */ | ||
| 54 | t.tx_buf = &t; | ||
| 55 | t.len = 0; | ||
| 56 | } | ||
| 57 | t.cs_change = cs_change; | ||
| 58 | t.delay_usecs = nspi->xfer_udelay; | ||
| 67 | 59 | ||
| 68 | spi_message_init(&m); | 60 | spi_message_init(&m); |
| 69 | spi_message_add_tail(&t, &m); | 61 | spi_message_add_tail(&t, &m); |
| 70 | 62 | ||
| 71 | return spi_sync(ndev->spi, &m); | 63 | return spi_sync(nspi->spi, &m); |
| 72 | } | 64 | } |
| 73 | 65 | ||
| 74 | static int nci_spi_send(struct nci_dev *nci_dev, struct sk_buff *skb) | 66 | int nci_spi_send(struct nci_spi *nspi, |
| 67 | struct completion *write_handshake_completion, | ||
| 68 | struct sk_buff *skb) | ||
| 75 | { | 69 | { |
| 76 | struct nci_spi_dev *ndev = nci_get_drvdata(nci_dev); | ||
| 77 | unsigned int payload_len = skb->len; | 70 | unsigned int payload_len = skb->len; |
| 78 | unsigned char *hdr; | 71 | unsigned char *hdr; |
| 79 | int ret; | 72 | int ret; |
| 80 | long completion_rc; | 73 | long completion_rc; |
| 81 | 74 | ||
| 82 | ndev->ops->deassert_int(ndev); | ||
| 83 | |||
| 84 | /* add the NCI SPI header to the start of the buffer */ | 75 | /* add the NCI SPI header to the start of the buffer */ |
| 85 | hdr = skb_push(skb, NCI_SPI_HDR_LEN); | 76 | hdr = skb_push(skb, NCI_SPI_HDR_LEN); |
| 86 | hdr[0] = NCI_SPI_DIRECT_WRITE; | 77 | hdr[0] = NCI_SPI_DIRECT_WRITE; |
| 87 | hdr[1] = ndev->acknowledge_mode; | 78 | hdr[1] = nspi->acknowledge_mode; |
| 88 | hdr[2] = payload_len >> 8; | 79 | hdr[2] = payload_len >> 8; |
| 89 | hdr[3] = payload_len & 0xFF; | 80 | hdr[3] = payload_len & 0xFF; |
| 90 | 81 | ||
| 91 | if (ndev->acknowledge_mode == NCI_SPI_CRC_ENABLED) { | 82 | if (nspi->acknowledge_mode == NCI_SPI_CRC_ENABLED) { |
| 92 | u16 crc; | 83 | u16 crc; |
| 93 | 84 | ||
| 94 | crc = crc_ccitt(CRC_INIT, skb->data, skb->len); | 85 | crc = crc_ccitt(CRC_INIT, skb->data, skb->len); |
| @@ -96,123 +87,77 @@ static int nci_spi_send(struct nci_dev *nci_dev, struct sk_buff *skb) | |||
| 96 | *skb_put(skb, 1) = crc & 0xFF; | 87 | *skb_put(skb, 1) = crc & 0xFF; |
| 97 | } | 88 | } |
| 98 | 89 | ||
| 99 | ret = __nci_spi_send(ndev, skb); | 90 | if (write_handshake_completion) { |
| 91 | /* Trick SPI driver to raise chip select */ | ||
| 92 | ret = __nci_spi_send(nspi, NULL, 1); | ||
| 93 | if (ret) | ||
| 94 | goto done; | ||
| 100 | 95 | ||
| 101 | kfree_skb(skb); | 96 | /* wait for NFC chip hardware handshake to complete */ |
| 102 | ndev->ops->assert_int(ndev); | 97 | if (wait_for_completion_timeout(write_handshake_completion, |
| 98 | msecs_to_jiffies(1000)) == 0) { | ||
| 99 | ret = -ETIME; | ||
| 100 | goto done; | ||
| 101 | } | ||
| 102 | } | ||
| 103 | 103 | ||
| 104 | if (ret != 0 || ndev->acknowledge_mode == NCI_SPI_CRC_DISABLED) | 104 | ret = __nci_spi_send(nspi, skb, 0); |
| 105 | if (ret != 0 || nspi->acknowledge_mode == NCI_SPI_CRC_DISABLED) | ||
| 105 | goto done; | 106 | goto done; |
| 106 | 107 | ||
| 107 | init_completion(&ndev->req_completion); | 108 | init_completion(&nspi->req_completion); |
| 108 | completion_rc = | 109 | completion_rc = wait_for_completion_interruptible_timeout( |
| 109 | wait_for_completion_interruptible_timeout(&ndev->req_completion, | 110 | &nspi->req_completion, |
| 110 | NCI_SPI_SEND_TIMEOUT); | 111 | NCI_SPI_SEND_TIMEOUT); |
| 111 | 112 | ||
| 112 | if (completion_rc <= 0 || ndev->req_result == ACKNOWLEDGE_NACK) | 113 | if (completion_rc <= 0 || nspi->req_result == ACKNOWLEDGE_NACK) |
| 113 | ret = -EIO; | 114 | ret = -EIO; |
| 114 | 115 | ||
| 115 | done: | 116 | done: |
| 117 | kfree_skb(skb); | ||
| 118 | |||
| 116 | return ret; | 119 | return ret; |
| 117 | } | 120 | } |
| 118 | 121 | EXPORT_SYMBOL_GPL(nci_spi_send); | |
| 119 | static struct nci_ops nci_spi_ops = { | ||
| 120 | .open = nci_spi_open, | ||
| 121 | .close = nci_spi_close, | ||
| 122 | .send = nci_spi_send, | ||
| 123 | }; | ||
| 124 | 122 | ||
| 125 | /* ---- Interface to NCI SPI drivers ---- */ | 123 | /* ---- Interface to NCI SPI drivers ---- */ |
| 126 | 124 | ||
| 127 | /** | 125 | /** |
| 128 | * nci_spi_allocate_device - allocate a new nci spi device | 126 | * nci_spi_allocate_spi - allocate a new nci spi |
| 129 | * | 127 | * |
| 130 | * @spi: SPI device | 128 | * @spi: SPI device |
| 131 | * @ops: device operations | 129 | * @acknowledge_mode: Acknowledge mode used by the NFC device |
| 132 | * @supported_protocols: NFC protocols supported by the device | ||
| 133 | * @supported_se: NFC Secure Elements supported by the device | ||
| 134 | * @acknowledge_mode: Acknowledge mode used by the device | ||
| 135 | * @delay: delay between transactions in us | 130 | * @delay: delay between transactions in us |
| 131 | * @ndev: nci dev to send incoming nci frames to | ||
| 136 | */ | 132 | */ |
| 137 | struct nci_spi_dev *nci_spi_allocate_device(struct spi_device *spi, | 133 | struct nci_spi *nci_spi_allocate_spi(struct spi_device *spi, |
| 138 | struct nci_spi_ops *ops, | 134 | u8 acknowledge_mode, unsigned int delay, |
| 139 | u32 supported_protocols, | 135 | struct nci_dev *ndev) |
| 140 | u32 supported_se, | ||
| 141 | u8 acknowledge_mode, | ||
| 142 | unsigned int delay) | ||
| 143 | { | 136 | { |
| 144 | struct nci_spi_dev *ndev; | 137 | struct nci_spi *nspi; |
| 145 | int tailroom = 0; | ||
| 146 | 138 | ||
| 147 | if (!ops->open || !ops->close || !ops->assert_int || !ops->deassert_int) | 139 | nspi = devm_kzalloc(&spi->dev, sizeof(struct nci_spi), GFP_KERNEL); |
| 140 | if (!nspi) | ||
| 148 | return NULL; | 141 | return NULL; |
| 149 | 142 | ||
| 150 | if (!supported_protocols) | 143 | nspi->acknowledge_mode = acknowledge_mode; |
| 151 | return NULL; | 144 | nspi->xfer_udelay = delay; |
| 152 | |||
| 153 | ndev = devm_kzalloc(&spi->dev, sizeof(struct nci_dev), GFP_KERNEL); | ||
| 154 | if (!ndev) | ||
| 155 | return NULL; | ||
| 156 | 145 | ||
| 157 | ndev->ops = ops; | 146 | nspi->spi = spi; |
| 158 | ndev->acknowledge_mode = acknowledge_mode; | 147 | nspi->ndev = ndev; |
| 159 | ndev->xfer_udelay = delay; | ||
| 160 | 148 | ||
| 161 | if (acknowledge_mode == NCI_SPI_CRC_ENABLED) | 149 | return nspi; |
| 162 | tailroom += NCI_SPI_CRC_LEN; | ||
| 163 | |||
| 164 | ndev->nci_dev = nci_allocate_device(&nci_spi_ops, supported_protocols, | ||
| 165 | NCI_SPI_HDR_LEN, tailroom); | ||
| 166 | if (!ndev->nci_dev) | ||
| 167 | return NULL; | ||
| 168 | |||
| 169 | nci_set_drvdata(ndev->nci_dev, ndev); | ||
| 170 | |||
| 171 | return ndev; | ||
| 172 | } | 150 | } |
| 173 | EXPORT_SYMBOL_GPL(nci_spi_allocate_device); | 151 | EXPORT_SYMBOL_GPL(nci_spi_allocate_spi); |
| 174 | 152 | ||
| 175 | /** | 153 | static int send_acknowledge(struct nci_spi *nspi, u8 acknowledge) |
| 176 | * nci_spi_free_device - deallocate nci spi device | ||
| 177 | * | ||
| 178 | * @ndev: The nci spi device to deallocate | ||
| 179 | */ | ||
| 180 | void nci_spi_free_device(struct nci_spi_dev *ndev) | ||
| 181 | { | ||
| 182 | nci_free_device(ndev->nci_dev); | ||
| 183 | } | ||
| 184 | EXPORT_SYMBOL_GPL(nci_spi_free_device); | ||
| 185 | |||
| 186 | /** | ||
| 187 | * nci_spi_register_device - register a nci spi device in the nfc subsystem | ||
| 188 | * | ||
| 189 | * @pdev: The nci spi device to register | ||
| 190 | */ | ||
| 191 | int nci_spi_register_device(struct nci_spi_dev *ndev) | ||
| 192 | { | ||
| 193 | return nci_register_device(ndev->nci_dev); | ||
| 194 | } | ||
| 195 | EXPORT_SYMBOL_GPL(nci_spi_register_device); | ||
| 196 | |||
| 197 | /** | ||
| 198 | * nci_spi_unregister_device - unregister a nci spi device in the nfc subsystem | ||
| 199 | * | ||
| 200 | * @dev: The nci spi device to unregister | ||
| 201 | */ | ||
| 202 | void nci_spi_unregister_device(struct nci_spi_dev *ndev) | ||
| 203 | { | ||
| 204 | nci_unregister_device(ndev->nci_dev); | ||
| 205 | } | ||
| 206 | EXPORT_SYMBOL_GPL(nci_spi_unregister_device); | ||
| 207 | |||
| 208 | static int send_acknowledge(struct nci_spi_dev *ndev, u8 acknowledge) | ||
| 209 | { | 154 | { |
| 210 | struct sk_buff *skb; | 155 | struct sk_buff *skb; |
| 211 | unsigned char *hdr; | 156 | unsigned char *hdr; |
| 212 | u16 crc; | 157 | u16 crc; |
| 213 | int ret; | 158 | int ret; |
| 214 | 159 | ||
| 215 | skb = nci_skb_alloc(ndev->nci_dev, 0, GFP_KERNEL); | 160 | skb = nci_skb_alloc(nspi->ndev, 0, GFP_KERNEL); |
| 216 | 161 | ||
| 217 | /* add the NCI SPI header to the start of the buffer */ | 162 | /* add the NCI SPI header to the start of the buffer */ |
| 218 | hdr = skb_push(skb, NCI_SPI_HDR_LEN); | 163 | hdr = skb_push(skb, NCI_SPI_HDR_LEN); |
| @@ -225,14 +170,14 @@ static int send_acknowledge(struct nci_spi_dev *ndev, u8 acknowledge) | |||
| 225 | *skb_put(skb, 1) = crc >> 8; | 170 | *skb_put(skb, 1) = crc >> 8; |
| 226 | *skb_put(skb, 1) = crc & 0xFF; | 171 | *skb_put(skb, 1) = crc & 0xFF; |
| 227 | 172 | ||
| 228 | ret = __nci_spi_send(ndev, skb); | 173 | ret = __nci_spi_send(nspi, skb, 0); |
| 229 | 174 | ||
| 230 | kfree_skb(skb); | 175 | kfree_skb(skb); |
| 231 | 176 | ||
| 232 | return ret; | 177 | return ret; |
| 233 | } | 178 | } |
| 234 | 179 | ||
| 235 | static struct sk_buff *__nci_spi_recv_frame(struct nci_spi_dev *ndev) | 180 | static struct sk_buff *__nci_spi_read(struct nci_spi *nspi) |
| 236 | { | 181 | { |
| 237 | struct sk_buff *skb; | 182 | struct sk_buff *skb; |
| 238 | struct spi_message m; | 183 | struct spi_message m; |
| @@ -242,43 +187,49 @@ static struct sk_buff *__nci_spi_recv_frame(struct nci_spi_dev *ndev) | |||
| 242 | int ret; | 187 | int ret; |
| 243 | 188 | ||
| 244 | spi_message_init(&m); | 189 | spi_message_init(&m); |
| 190 | |||
| 191 | memset(&tx, 0, sizeof(struct spi_transfer)); | ||
| 245 | req[0] = NCI_SPI_DIRECT_READ; | 192 | req[0] = NCI_SPI_DIRECT_READ; |
| 246 | req[1] = ndev->acknowledge_mode; | 193 | req[1] = nspi->acknowledge_mode; |
| 247 | tx.tx_buf = req; | 194 | tx.tx_buf = req; |
| 248 | tx.len = 2; | 195 | tx.len = 2; |
| 249 | tx.cs_change = 0; | 196 | tx.cs_change = 0; |
| 250 | spi_message_add_tail(&tx, &m); | 197 | spi_message_add_tail(&tx, &m); |
| 198 | |||
| 199 | memset(&rx, 0, sizeof(struct spi_transfer)); | ||
| 251 | rx.rx_buf = resp_hdr; | 200 | rx.rx_buf = resp_hdr; |
| 252 | rx.len = 2; | 201 | rx.len = 2; |
| 253 | rx.cs_change = 1; | 202 | rx.cs_change = 1; |
| 254 | spi_message_add_tail(&rx, &m); | 203 | spi_message_add_tail(&rx, &m); |
| 255 | ret = spi_sync(ndev->spi, &m); | ||
| 256 | 204 | ||
| 205 | ret = spi_sync(nspi->spi, &m); | ||
| 257 | if (ret) | 206 | if (ret) |
| 258 | return NULL; | 207 | return NULL; |
| 259 | 208 | ||
| 260 | if (ndev->acknowledge_mode == NCI_SPI_CRC_ENABLED) | 209 | if (nspi->acknowledge_mode == NCI_SPI_CRC_ENABLED) |
| 261 | rx_len = ((resp_hdr[0] & NCI_SPI_MSB_PAYLOAD_MASK) << 8) + | 210 | rx_len = ((resp_hdr[0] & NCI_SPI_MSB_PAYLOAD_MASK) << 8) + |
| 262 | resp_hdr[1] + NCI_SPI_CRC_LEN; | 211 | resp_hdr[1] + NCI_SPI_CRC_LEN; |
| 263 | else | 212 | else |
| 264 | rx_len = (resp_hdr[0] << 8) | resp_hdr[1]; | 213 | rx_len = (resp_hdr[0] << 8) | resp_hdr[1]; |
| 265 | 214 | ||
| 266 | skb = nci_skb_alloc(ndev->nci_dev, rx_len, GFP_KERNEL); | 215 | skb = nci_skb_alloc(nspi->ndev, rx_len, GFP_KERNEL); |
| 267 | if (!skb) | 216 | if (!skb) |
| 268 | return NULL; | 217 | return NULL; |
| 269 | 218 | ||
| 270 | spi_message_init(&m); | 219 | spi_message_init(&m); |
| 220 | |||
| 221 | memset(&rx, 0, sizeof(struct spi_transfer)); | ||
| 271 | rx.rx_buf = skb_put(skb, rx_len); | 222 | rx.rx_buf = skb_put(skb, rx_len); |
| 272 | rx.len = rx_len; | 223 | rx.len = rx_len; |
| 273 | rx.cs_change = 0; | 224 | rx.cs_change = 0; |
| 274 | rx.delay_usecs = ndev->xfer_udelay; | 225 | rx.delay_usecs = nspi->xfer_udelay; |
| 275 | spi_message_add_tail(&rx, &m); | 226 | spi_message_add_tail(&rx, &m); |
| 276 | ret = spi_sync(ndev->spi, &m); | ||
| 277 | 227 | ||
| 228 | ret = spi_sync(nspi->spi, &m); | ||
| 278 | if (ret) | 229 | if (ret) |
| 279 | goto receive_error; | 230 | goto receive_error; |
| 280 | 231 | ||
| 281 | if (ndev->acknowledge_mode == NCI_SPI_CRC_ENABLED) { | 232 | if (nspi->acknowledge_mode == NCI_SPI_CRC_ENABLED) { |
| 282 | *skb_push(skb, 1) = resp_hdr[1]; | 233 | *skb_push(skb, 1) = resp_hdr[1]; |
| 283 | *skb_push(skb, 1) = resp_hdr[0]; | 234 | *skb_push(skb, 1) = resp_hdr[0]; |
| 284 | } | 235 | } |
| @@ -318,61 +269,53 @@ static u8 nci_spi_get_ack(struct sk_buff *skb) | |||
| 318 | } | 269 | } |
| 319 | 270 | ||
| 320 | /** | 271 | /** |
| 321 | * nci_spi_recv_frame - receive frame from NCI SPI drivers | 272 | * nci_spi_read - read frame from NCI SPI drivers |
| 322 | * | 273 | * |
| 323 | * @ndev: The nci spi device | 274 | * @nspi: The nci spi |
| 324 | * Context: can sleep | 275 | * Context: can sleep |
| 325 | * | 276 | * |
| 326 | * This call may only be used from a context that may sleep. The sleep | 277 | * This call may only be used from a context that may sleep. The sleep |
| 327 | * is non-interruptible, and has no timeout. | 278 | * is non-interruptible, and has no timeout. |
| 328 | * | 279 | * |
| 329 | * It returns zero on success, else a negative error code. | 280 | * It returns an allocated skb containing the frame on success, or NULL. |
| 330 | */ | 281 | */ |
| 331 | int nci_spi_recv_frame(struct nci_spi_dev *ndev) | 282 | struct sk_buff *nci_spi_read(struct nci_spi *nspi) |
| 332 | { | 283 | { |
| 333 | struct sk_buff *skb; | 284 | struct sk_buff *skb; |
| 334 | int ret = 0; | ||
| 335 | |||
| 336 | ndev->ops->deassert_int(ndev); | ||
| 337 | 285 | ||
| 338 | /* Retrieve frame from SPI */ | 286 | /* Retrieve frame from SPI */ |
| 339 | skb = __nci_spi_recv_frame(ndev); | 287 | skb = __nci_spi_read(nspi); |
| 340 | if (!skb) { | 288 | if (!skb) |
| 341 | ret = -EIO; | ||
| 342 | goto done; | 289 | goto done; |
| 343 | } | ||
| 344 | 290 | ||
| 345 | if (ndev->acknowledge_mode == NCI_SPI_CRC_ENABLED) { | 291 | if (nspi->acknowledge_mode == NCI_SPI_CRC_ENABLED) { |
| 346 | if (!nci_spi_check_crc(skb)) { | 292 | if (!nci_spi_check_crc(skb)) { |
| 347 | send_acknowledge(ndev, ACKNOWLEDGE_NACK); | 293 | send_acknowledge(nspi, ACKNOWLEDGE_NACK); |
| 348 | goto done; | 294 | goto done; |
| 349 | } | 295 | } |
| 350 | 296 | ||
| 351 | /* In case of acknowledged mode: if ACK or NACK received, | 297 | /* In case of acknowledged mode: if ACK or NACK received, |
| 352 | * unblock completion of latest frame sent. | 298 | * unblock completion of latest frame sent. |
| 353 | */ | 299 | */ |
| 354 | ndev->req_result = nci_spi_get_ack(skb); | 300 | nspi->req_result = nci_spi_get_ack(skb); |
| 355 | if (ndev->req_result) | 301 | if (nspi->req_result) |
| 356 | complete(&ndev->req_completion); | 302 | complete(&nspi->req_completion); |
| 357 | } | 303 | } |
| 358 | 304 | ||
| 359 | /* If there is no payload (ACK/NACK only frame), | 305 | /* If there is no payload (ACK/NACK only frame), |
| 360 | * free the socket buffer | 306 | * free the socket buffer |
| 361 | */ | 307 | */ |
| 362 | if (skb->len == 0) { | 308 | if (!skb->len) { |
| 363 | kfree_skb(skb); | 309 | kfree_skb(skb); |
| 310 | skb = NULL; | ||
| 364 | goto done; | 311 | goto done; |
| 365 | } | 312 | } |
| 366 | 313 | ||
| 367 | if (ndev->acknowledge_mode == NCI_SPI_CRC_ENABLED) | 314 | if (nspi->acknowledge_mode == NCI_SPI_CRC_ENABLED) |
| 368 | send_acknowledge(ndev, ACKNOWLEDGE_ACK); | 315 | send_acknowledge(nspi, ACKNOWLEDGE_ACK); |
| 369 | |||
| 370 | /* Forward skb to NCI core layer */ | ||
| 371 | ret = nci_recv_frame(ndev->nci_dev, skb); | ||
| 372 | 316 | ||
| 373 | done: | 317 | done: |
| 374 | ndev->ops->assert_int(ndev); | ||
| 375 | 318 | ||
| 376 | return ret; | 319 | return skb; |
| 377 | } | 320 | } |
| 378 | EXPORT_SYMBOL_GPL(nci_spi_recv_frame); | 321 | EXPORT_SYMBOL_GPL(nci_spi_read); |
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index 68063b2025da..84b7e3ea7b7a 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c | |||
| @@ -58,6 +58,7 @@ static const struct nla_policy nfc_genl_policy[NFC_ATTR_MAX + 1] = { | |||
| 58 | [NFC_ATTR_LLC_SDP] = { .type = NLA_NESTED }, | 58 | [NFC_ATTR_LLC_SDP] = { .type = NLA_NESTED }, |
| 59 | [NFC_ATTR_FIRMWARE_NAME] = { .type = NLA_STRING, | 59 | [NFC_ATTR_FIRMWARE_NAME] = { .type = NLA_STRING, |
| 60 | .len = NFC_FIRMWARE_NAME_MAXSIZE }, | 60 | .len = NFC_FIRMWARE_NAME_MAXSIZE }, |
| 61 | [NFC_ATTR_SE_APDU] = { .type = NLA_BINARY }, | ||
| 61 | }; | 62 | }; |
| 62 | 63 | ||
| 63 | static const struct nla_policy nfc_sdp_genl_policy[NFC_SDP_ATTR_MAX + 1] = { | 64 | static const struct nla_policy nfc_sdp_genl_policy[NFC_SDP_ATTR_MAX + 1] = { |
| @@ -1278,6 +1279,91 @@ static int nfc_genl_dump_ses_done(struct netlink_callback *cb) | |||
| 1278 | return 0; | 1279 | return 0; |
| 1279 | } | 1280 | } |
| 1280 | 1281 | ||
| 1282 | struct se_io_ctx { | ||
| 1283 | u32 dev_idx; | ||
| 1284 | u32 se_idx; | ||
| 1285 | }; | ||
| 1286 | |||
| 1287 | static void se_io_cb(void *context, u8 *apdu, size_t apdu_len, int err) | ||
| 1288 | { | ||
| 1289 | struct se_io_ctx *ctx = context; | ||
| 1290 | struct sk_buff *msg; | ||
| 1291 | void *hdr; | ||
| 1292 | |||
| 1293 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
| 1294 | if (!msg) { | ||
| 1295 | kfree(ctx); | ||
| 1296 | return; | ||
| 1297 | } | ||
| 1298 | |||
| 1299 | hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, | ||
| 1300 | NFC_CMD_SE_IO); | ||
| 1301 | if (!hdr) | ||
| 1302 | goto free_msg; | ||
| 1303 | |||
| 1304 | if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, ctx->dev_idx) || | ||
| 1305 | nla_put_u32(msg, NFC_ATTR_SE_INDEX, ctx->se_idx) || | ||
| 1306 | nla_put(msg, NFC_ATTR_SE_APDU, apdu_len, apdu)) | ||
| 1307 | goto nla_put_failure; | ||
| 1308 | |||
| 1309 | genlmsg_end(msg, hdr); | ||
| 1310 | |||
| 1311 | genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL); | ||
| 1312 | |||
| 1313 | kfree(ctx); | ||
| 1314 | |||
| 1315 | return; | ||
| 1316 | |||
| 1317 | nla_put_failure: | ||
| 1318 | genlmsg_cancel(msg, hdr); | ||
| 1319 | free_msg: | ||
| 1320 | nlmsg_free(msg); | ||
| 1321 | kfree(ctx); | ||
| 1322 | |||
| 1323 | return; | ||
| 1324 | } | ||
| 1325 | |||
| 1326 | static int nfc_genl_se_io(struct sk_buff *skb, struct genl_info *info) | ||
| 1327 | { | ||
| 1328 | struct nfc_dev *dev; | ||
| 1329 | struct se_io_ctx *ctx; | ||
| 1330 | u32 dev_idx, se_idx; | ||
| 1331 | u8 *apdu; | ||
| 1332 | size_t apdu_len; | ||
| 1333 | |||
| 1334 | if (!info->attrs[NFC_ATTR_DEVICE_INDEX] || | ||
| 1335 | !info->attrs[NFC_ATTR_SE_INDEX] || | ||
| 1336 | !info->attrs[NFC_ATTR_SE_APDU]) | ||
| 1337 | return -EINVAL; | ||
| 1338 | |||
| 1339 | dev_idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); | ||
| 1340 | se_idx = nla_get_u32(info->attrs[NFC_ATTR_SE_INDEX]); | ||
| 1341 | |||
| 1342 | dev = nfc_get_device(dev_idx); | ||
| 1343 | if (!dev) | ||
| 1344 | return -ENODEV; | ||
| 1345 | |||
| 1346 | if (!dev->ops || !dev->ops->se_io) | ||
| 1347 | return -ENOTSUPP; | ||
| 1348 | |||
| 1349 | apdu_len = nla_len(info->attrs[NFC_ATTR_SE_APDU]); | ||
| 1350 | if (apdu_len == 0) | ||
| 1351 | return -EINVAL; | ||
| 1352 | |||
| 1353 | apdu = nla_data(info->attrs[NFC_ATTR_SE_APDU]); | ||
| 1354 | if (!apdu) | ||
| 1355 | return -EINVAL; | ||
| 1356 | |||
| 1357 | ctx = kzalloc(sizeof(struct se_io_ctx), GFP_KERNEL); | ||
| 1358 | if (!ctx) | ||
| 1359 | return -ENOMEM; | ||
| 1360 | |||
| 1361 | ctx->dev_idx = dev_idx; | ||
| 1362 | ctx->se_idx = se_idx; | ||
| 1363 | |||
| 1364 | return dev->ops->se_io(dev, se_idx, apdu, apdu_len, se_io_cb, ctx); | ||
| 1365 | } | ||
| 1366 | |||
| 1281 | static struct genl_ops nfc_genl_ops[] = { | 1367 | static struct genl_ops nfc_genl_ops[] = { |
| 1282 | { | 1368 | { |
| 1283 | .cmd = NFC_CMD_GET_DEVICE, | 1369 | .cmd = NFC_CMD_GET_DEVICE, |
| @@ -1358,6 +1444,11 @@ static struct genl_ops nfc_genl_ops[] = { | |||
| 1358 | .done = nfc_genl_dump_ses_done, | 1444 | .done = nfc_genl_dump_ses_done, |
| 1359 | .policy = nfc_genl_policy, | 1445 | .policy = nfc_genl_policy, |
| 1360 | }, | 1446 | }, |
| 1447 | { | ||
| 1448 | .cmd = NFC_CMD_SE_IO, | ||
| 1449 | .doit = nfc_genl_se_io, | ||
| 1450 | .policy = nfc_genl_policy, | ||
| 1451 | }, | ||
| 1361 | }; | 1452 | }; |
| 1362 | 1453 | ||
| 1363 | 1454 | ||
diff --git a/net/nfc/rawsock.c b/net/nfc/rawsock.c index 313bf1bc848a..cd958b381f96 100644 --- a/net/nfc/rawsock.c +++ b/net/nfc/rawsock.c | |||
| @@ -142,11 +142,11 @@ static void rawsock_data_exchange_complete(void *context, struct sk_buff *skb, | |||
| 142 | 142 | ||
| 143 | err = rawsock_add_header(skb); | 143 | err = rawsock_add_header(skb); |
| 144 | if (err) | 144 | if (err) |
| 145 | goto error; | 145 | goto error_skb; |
| 146 | 146 | ||
| 147 | err = sock_queue_rcv_skb(sk, skb); | 147 | err = sock_queue_rcv_skb(sk, skb); |
| 148 | if (err) | 148 | if (err) |
| 149 | goto error; | 149 | goto error_skb; |
| 150 | 150 | ||
| 151 | spin_lock_bh(&sk->sk_write_queue.lock); | 151 | spin_lock_bh(&sk->sk_write_queue.lock); |
| 152 | if (!skb_queue_empty(&sk->sk_write_queue)) | 152 | if (!skb_queue_empty(&sk->sk_write_queue)) |
| @@ -158,6 +158,9 @@ static void rawsock_data_exchange_complete(void *context, struct sk_buff *skb, | |||
| 158 | sock_put(sk); | 158 | sock_put(sk); |
| 159 | return; | 159 | return; |
| 160 | 160 | ||
| 161 | error_skb: | ||
| 162 | kfree_skb(skb); | ||
| 163 | |||
| 161 | error: | 164 | error: |
| 162 | rawsock_report_error(sk, err); | 165 | rawsock_report_error(sk, err); |
| 163 | sock_put(sk); | 166 | sock_put(sk); |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index d62cb1e91475..a0ec143ba3dc 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
| @@ -768,23 +768,25 @@ const struct ieee80211_reg_rule *freq_reg_info(struct wiphy *wiphy, | |||
| 768 | } | 768 | } |
| 769 | EXPORT_SYMBOL(freq_reg_info); | 769 | EXPORT_SYMBOL(freq_reg_info); |
| 770 | 770 | ||
| 771 | #ifdef CONFIG_CFG80211_REG_DEBUG | 771 | const char *reg_initiator_name(enum nl80211_reg_initiator initiator) |
| 772 | static const char *reg_initiator_name(enum nl80211_reg_initiator initiator) | ||
| 773 | { | 772 | { |
| 774 | switch (initiator) { | 773 | switch (initiator) { |
| 775 | case NL80211_REGDOM_SET_BY_CORE: | 774 | case NL80211_REGDOM_SET_BY_CORE: |
| 776 | return "Set by core"; | 775 | return "core"; |
| 777 | case NL80211_REGDOM_SET_BY_USER: | 776 | case NL80211_REGDOM_SET_BY_USER: |
| 778 | return "Set by user"; | 777 | return "user"; |
| 779 | case NL80211_REGDOM_SET_BY_DRIVER: | 778 | case NL80211_REGDOM_SET_BY_DRIVER: |
| 780 | return "Set by driver"; | 779 | return "driver"; |
| 781 | case NL80211_REGDOM_SET_BY_COUNTRY_IE: | 780 | case NL80211_REGDOM_SET_BY_COUNTRY_IE: |
| 782 | return "Set by country IE"; | 781 | return "country IE"; |
| 783 | default: | 782 | default: |
| 784 | WARN_ON(1); | 783 | WARN_ON(1); |
| 785 | return "Set by bug"; | 784 | return "bug"; |
| 786 | } | 785 | } |
| 787 | } | 786 | } |
| 787 | EXPORT_SYMBOL(reg_initiator_name); | ||
| 788 | |||
| 789 | #ifdef CONFIG_CFG80211_REG_DEBUG | ||
| 788 | 790 | ||
| 789 | static void chan_reg_rule_print_dbg(struct ieee80211_channel *chan, | 791 | static void chan_reg_rule_print_dbg(struct ieee80211_channel *chan, |
| 790 | const struct ieee80211_reg_rule *reg_rule) | 792 | const struct ieee80211_reg_rule *reg_rule) |
| @@ -979,14 +981,17 @@ static bool ignore_reg_update(struct wiphy *wiphy, | |||
| 979 | struct regulatory_request *lr = get_last_request(); | 981 | struct regulatory_request *lr = get_last_request(); |
| 980 | 982 | ||
| 981 | if (!lr) { | 983 | if (!lr) { |
| 982 | REG_DBG_PRINT("Ignoring regulatory request %s since last_request is not set\n", | 984 | REG_DBG_PRINT("Ignoring regulatory request set by %s " |
| 985 | "since last_request is not set\n", | ||
| 983 | reg_initiator_name(initiator)); | 986 | reg_initiator_name(initiator)); |
| 984 | return true; | 987 | return true; |
| 985 | } | 988 | } |
| 986 | 989 | ||
| 987 | if (initiator == NL80211_REGDOM_SET_BY_CORE && | 990 | if (initiator == NL80211_REGDOM_SET_BY_CORE && |
| 988 | wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY) { | 991 | wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY) { |
| 989 | REG_DBG_PRINT("Ignoring regulatory request %s since the driver uses its own custom regulatory domain\n", | 992 | REG_DBG_PRINT("Ignoring regulatory request set by %s " |
| 993 | "since the driver uses its own custom " | ||
| 994 | "regulatory domain\n", | ||
| 990 | reg_initiator_name(initiator)); | 995 | reg_initiator_name(initiator)); |
| 991 | return true; | 996 | return true; |
| 992 | } | 997 | } |
| @@ -998,7 +1003,9 @@ static bool ignore_reg_update(struct wiphy *wiphy, | |||
| 998 | if (wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY && !wiphy->regd && | 1003 | if (wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY && !wiphy->regd && |
| 999 | initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && | 1004 | initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && |
| 1000 | !is_world_regdom(lr->alpha2)) { | 1005 | !is_world_regdom(lr->alpha2)) { |
| 1001 | REG_DBG_PRINT("Ignoring regulatory request %s since the driver requires its own regulatory domain to be set first\n", | 1006 | REG_DBG_PRINT("Ignoring regulatory request set by %s " |
| 1007 | "since the driver requires its own regulatory " | ||
| 1008 | "domain to be set first\n", | ||
| 1002 | reg_initiator_name(initiator)); | 1009 | reg_initiator_name(initiator)); |
| 1003 | return true; | 1010 | return true; |
| 1004 | } | 1011 | } |
