diff options
author | Katy Moe | 2017-10-06 11:53:01 +0100 |
---|---|---|
committer | Katy Moe | 2017-10-06 11:55:36 +0100 |
commit | 5d22f042d01593612daf9bfaff07f602189db20c (patch) | |
tree | cfcea5ad0e8cf5bbcc39afaa41bb6ef582da1047 | |
parent | aed3a3c4a40a2eef4f9ebfa8493467b4ff8df2bf (diff) | |
download | aur-5d22f042d01593612daf9bfaff07f602189db20c.tar.gz |
v0.9: updates to skbuff
-rw-r--r-- | .SRCINFO | 12 | ||||
-rw-r--r-- | PKGBUILD | 12 | ||||
-rw-r--r-- | btusb.c | 204 |
3 files changed, 193 insertions, 35 deletions
@@ -1,6 +1,6 @@ pkgbase = btusb-qca-0x3004 pkgdesc = patch btusb so it works on QCA devices with id 0x3004 - pkgver = 0.8 + pkgver = 0.9 pkgrel = 1 install = btusb-qca-0x3004.install arch = i686 @@ -10,14 +10,14 @@ pkgbase = btusb-qca-0x3004 source = Makefile source = btusb.patch source = btusb-qca-0x3004.install - source = btusb.c::https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/plain/drivers/bluetooth/btusb.c?id=refs/tags/v4.10.4 - source = btintel.h::https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/plain/drivers/bluetooth/btintel.h?id=refs/tags/v4.10.4 - source = btbcm.h::https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/plain/drivers/bluetooth/btbcm.h?id=refs/tags/v4.10.4 - source = btrtl.h::https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/plain/drivers/bluetooth/btrtl.h?id=refs/tags/v4.10.4 + source = btusb.c::https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/plain/drivers/bluetooth/btusb.c?id=refs/tags/v4.13.4 + source = btintel.h::https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/plain/drivers/bluetooth/btintel.h?id=refs/tags/v4.13.4 + source = btbcm.h::https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/plain/drivers/bluetooth/btbcm.h?id=refs/tags/v4.13.4 + source = btrtl.h::https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/plain/drivers/bluetooth/btrtl.h?id=refs/tags/v4.13.4 md5sums = 369ff1a06ddfa06bc68bd776d3fbc97e md5sums = bf67cf7e920e90f399fafadc2d26f9d7 md5sums = 3b63db7fbf7aab07322b0a1f71a7ffdb - md5sums = 25e4e23aae21b04fa865c8e1b07a1d77 + md5sums = 4e30ace94e0c3842da7d16c1d8dfded1 md5sums = 764863abf53cb70bc04a3af1c24d226e md5sums = 4c5d3ed81979cc6af062b381731d25e3 md5sums = ed7b0912a2e3507068c0d173ed9338fa @@ -4,7 +4,7 @@ _kernver="$(uname -r)" _kernver_base="$(echo $_kernver | cut -d- -f1)" pkgname=btusb-qca-0x3004 _pkgname=btusb -pkgver=0.8 +pkgver=0.9 pkgrel=1 pkgdesc="patch btusb so it works on QCA devices with id 0x3004" arch=('i686' 'x86_64') @@ -13,10 +13,10 @@ depends=('linux-headers') source=("Makefile" "btusb.patch" "btusb-qca-0x3004.install" - "btusb.c::https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/plain/drivers/bluetooth/btusb.c?id=refs/tags/v4.10.4" - "btintel.h::https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/plain/drivers/bluetooth/btintel.h?id=refs/tags/v4.10.4" - "btbcm.h::https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/plain/drivers/bluetooth/btbcm.h?id=refs/tags/v4.10.4" - "btrtl.h::https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/plain/drivers/bluetooth/btrtl.h?id=refs/tags/v4.10.4") + "btusb.c::https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/plain/drivers/bluetooth/btusb.c?id=refs/tags/v4.13.4" + "btintel.h::https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/plain/drivers/bluetooth/btintel.h?id=refs/tags/v4.13.4" + "btbcm.h::https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/plain/drivers/bluetooth/btbcm.h?id=refs/tags/v4.13.4" + "btrtl.h::https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/plain/drivers/bluetooth/btrtl.h?id=refs/tags/v4.13.4") install="btusb-qca-0x3004.install" @@ -37,7 +37,7 @@ package() { md5sums=('369ff1a06ddfa06bc68bd776d3fbc97e' 'bf67cf7e920e90f399fafadc2d26f9d7' '3b63db7fbf7aab07322b0a1f71a7ffdb' - '25e4e23aae21b04fa865c8e1b07a1d77' + '4e30ace94e0c3842da7d16c1d8dfded1' '764863abf53cb70bc04a3af1c24d226e' '4c5d3ed81979cc6af062b381731d25e3' 'ed7b0912a2e3507068c0d173ed9338fa') @@ -24,6 +24,9 @@ #include <linux/module.h> #include <linux/usb.h> #include <linux/firmware.h> +#include <linux/of_device.h> +#include <linux/of_irq.h> +#include <linux/suspend.h> #include <asm/unaligned.h> #include <net/bluetooth/bluetooth.h> @@ -130,6 +133,10 @@ static const struct usb_device_id btusb_table[] = { /* Broadcom BCM43142A0 (Foxconn/Lenovo) */ { USB_DEVICE(0x105b, 0xe065), .driver_info = BTUSB_BCM_PATCHRAM }, + /* Broadcom BCM920703 (HTC Vive) */ + { USB_VENDOR_AND_INTERFACE_INFO(0x0bb4, 0xff, 0x01, 0x01), + .driver_info = BTUSB_BCM_PATCHRAM }, + /* Foxconn - Hon Hai */ { USB_VENDOR_AND_INTERFACE_INFO(0x0489, 0xff, 0x01, 0x01), .driver_info = BTUSB_BCM_PATCHRAM }, @@ -154,6 +161,10 @@ static const struct usb_device_id btusb_table[] = { { USB_VENDOR_AND_INTERFACE_INFO(0x13d3, 0xff, 0x01, 0x01), .driver_info = BTUSB_BCM_PATCHRAM }, + /* Dell Computer - Broadcom based */ + { USB_VENDOR_AND_INTERFACE_INFO(0x413c, 0xff, 0x01, 0x01), + .driver_info = BTUSB_BCM_PATCHRAM }, + /* Toshiba Corp - Broadcom based */ { USB_VENDOR_AND_INTERFACE_INFO(0x0930, 0xff, 0x01, 0x01), .driver_info = BTUSB_BCM_PATCHRAM }, @@ -252,8 +263,10 @@ static const struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x0cf3, 0xe007), .driver_info = BTUSB_QCA_ROME }, { USB_DEVICE(0x0cf3, 0xe009), .driver_info = BTUSB_QCA_ROME }, { USB_DEVICE(0x0cf3, 0xe300), .driver_info = BTUSB_QCA_ROME }, + { USB_DEVICE(0x0cf3, 0xe301), .driver_info = BTUSB_QCA_ROME }, { USB_DEVICE(0x0cf3, 0xe360), .driver_info = BTUSB_QCA_ROME }, { USB_DEVICE(0x0489, 0xe092), .driver_info = BTUSB_QCA_ROME }, + { USB_DEVICE(0x0489, 0xe0a2), .driver_info = BTUSB_QCA_ROME }, { USB_DEVICE(0x04ca, 0x3011), .driver_info = BTUSB_QCA_ROME }, /* Broadcom BCM2035 */ @@ -318,11 +331,13 @@ static const struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x1286, 0x204e), .driver_info = BTUSB_MARVELL }, /* Intel Bluetooth devices */ + { USB_DEVICE(0x8087, 0x0025), .driver_info = BTUSB_INTEL_NEW }, { USB_DEVICE(0x8087, 0x07da), .driver_info = BTUSB_CSR }, { USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL }, { USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL }, { USB_DEVICE(0x8087, 0x0a2b), .driver_info = BTUSB_INTEL_NEW }, { USB_DEVICE(0x8087, 0x0aa7), .driver_info = BTUSB_INTEL }, + { USB_DEVICE(0x8087, 0x0aaa), .driver_info = BTUSB_INTEL_NEW }, /* Other Intel Bluetooth devices */ { USB_VENDOR_AND_INTERFACE_INFO(0x8087, 0xe0, 0x01, 0x01), @@ -342,6 +357,7 @@ static const struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x13d3, 0x3410), .driver_info = BTUSB_REALTEK }, { USB_DEVICE(0x13d3, 0x3416), .driver_info = BTUSB_REALTEK }, { USB_DEVICE(0x13d3, 0x3459), .driver_info = BTUSB_REALTEK }, + { USB_DEVICE(0x13d3, 0x3494), .driver_info = BTUSB_REALTEK }, /* Additional Realtek 8821AE Bluetooth devices */ { USB_DEVICE(0x0b05, 0x17dc), .driver_info = BTUSB_REALTEK }, @@ -370,6 +386,7 @@ static const struct usb_device_id blacklist_table[] = { #define BTUSB_BOOTING 9 #define BTUSB_RESET_RESUME 10 #define BTUSB_DIAG_RUNNING 11 +#define BTUSB_OOB_WAKE_ENABLED 12 struct btusb_data { struct hci_dev *hdev; @@ -417,6 +434,8 @@ struct btusb_data { int (*recv_bulk)(struct btusb_data *data, void *buffer, int count); int (*setup_on_usb)(struct hci_dev *hdev); + + int oob_wake_irq; /* irq for out-of-band wake-on-bt */ }; static inline void btusb_free_frags(struct btusb_data *data) @@ -460,7 +479,7 @@ static int btusb_recv_intr(struct btusb_data *data, void *buffer, int count) } len = min_t(uint, hci_skb_expect(skb), count); - memcpy(skb_put(skb, len), buffer, len); + skb_put_data(skb, buffer, len); count -= len; buffer += len; @@ -515,7 +534,7 @@ static int btusb_recv_bulk(struct btusb_data *data, void *buffer, int count) } len = min_t(uint, hci_skb_expect(skb), count); - memcpy(skb_put(skb, len), buffer, len); + skb_put_data(skb, buffer, len); count -= len; buffer += len; @@ -572,7 +591,7 @@ static int btusb_recv_isoc(struct btusb_data *data, void *buffer, int count) } len = min_t(uint, hci_skb_expect(skb), count); - memcpy(skb_put(skb, len), buffer, len); + skb_put_data(skb, buffer, len); count -= len; buffer += len; @@ -916,8 +935,8 @@ static void btusb_diag_complete(struct urb *urb) skb = bt_skb_alloc(urb->actual_length, GFP_ATOMIC); if (skb) { - memcpy(skb_put(skb, urb->actual_length), - urb->transfer_buffer, urb->actual_length); + skb_put_data(skb, urb->transfer_buffer, + urb->actual_length); hci_recv_diag(hdev, skb); } } else if (urb->status == -ENOENT) { @@ -1818,15 +1837,15 @@ static int inject_cmd_complete(struct hci_dev *hdev, __u16 opcode) if (!skb) return -ENOMEM; - hdr = (struct hci_event_hdr *)skb_put(skb, sizeof(*hdr)); + hdr = skb_put(skb, sizeof(*hdr)); hdr->evt = HCI_EV_CMD_COMPLETE; hdr->plen = sizeof(*evt) + 1; - evt = (struct hci_ev_cmd_complete *)skb_put(skb, sizeof(*evt)); + evt = skb_put(skb, sizeof(*evt)); evt->ncmd = 0x01; evt->opcode = cpu_to_le16(opcode); - *skb_put(skb, 1) = 0x00; + skb_put_u8(skb, 0x00); hci_skb_pkt_type(skb) = HCI_EVENT_PKT; @@ -2011,13 +2030,19 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) return -EINVAL; } - /* At the moment the iBT 3.0 hardware variants 0x0b (LnP/SfP) - * and 0x0c (WsP) are supported by this firmware loading method. + /* Check for supported iBT hardware variants of this firmware + * loading method. * * This check has been put in place to ensure correct forward * compatibility options when newer hardware variants come along. */ - if (ver.hw_variant != 0x0b && ver.hw_variant != 0x0c) { + switch (ver.hw_variant) { + case 0x0b: /* SfP */ + case 0x0c: /* WsP */ + case 0x11: /* JfP */ + case 0x12: /* ThP */ + break; + default: BT_ERR("%s: Unsupported Intel hardware variant (%u)", hdev->name, ver.hw_variant); return -EINVAL; @@ -2117,6 +2142,8 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) * Currently the supported hardware variants are: * 11 (0x0b) for iBT3.0 (LnP/SfP) * 12 (0x0c) for iBT3.5 (WsP) + * 17 (0x11) for iBT3.5 (JfP) + * 18 (0x12) for iBT3.5 (ThP) */ snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.sfi", le16_to_cpu(ver.hw_variant), @@ -2339,6 +2366,50 @@ static int btusb_shutdown_intel(struct hci_dev *hdev) return 0; } +#ifdef CONFIG_PM +/* Configure an out-of-band gpio as wake-up pin, if specified in device tree */ +static int marvell_config_oob_wake(struct hci_dev *hdev) +{ + struct sk_buff *skb; + struct btusb_data *data = hci_get_drvdata(hdev); + struct device *dev = &data->udev->dev; + u16 pin, gap, opcode; + int ret; + u8 cmd[5]; + + /* Move on if no wakeup pin specified */ + if (of_property_read_u16(dev->of_node, "marvell,wakeup-pin", &pin) || + of_property_read_u16(dev->of_node, "marvell,wakeup-gap-ms", &gap)) + return 0; + + /* Vendor specific command to configure a GPIO as wake-up pin */ + opcode = hci_opcode_pack(0x3F, 0x59); + cmd[0] = opcode & 0xFF; + cmd[1] = opcode >> 8; + cmd[2] = 2; /* length of parameters that follow */ + cmd[3] = pin; + cmd[4] = gap; /* time in ms, for which wakeup pin should be asserted */ + + skb = bt_skb_alloc(sizeof(cmd), GFP_KERNEL); + if (!skb) { + bt_dev_err(hdev, "%s: No memory\n", __func__); + return -ENOMEM; + } + + skb_put_data(skb, cmd, sizeof(cmd)); + hci_skb_pkt_type(skb) = HCI_COMMAND_PKT; + + ret = btusb_send_frame(hdev, skb); + if (ret) { + bt_dev_err(hdev, "%s: configuration failed\n", __func__); + kfree_skb(skb); + return ret; + } + + return 0; +} +#endif + static int btusb_set_bdaddr_marvell(struct hci_dev *hdev, const bdaddr_t *bdaddr) { @@ -2697,8 +2768,8 @@ static struct urb *alloc_diag_urb(struct hci_dev *hdev, bool enable) return ERR_PTR(-ENOMEM); } - *skb_put(skb, 1) = 0xf0; - *skb_put(skb, 1) = enable; + skb_put_u8(skb, 0xf0); + skb_put_u8(skb, enable); pipe = usb_sndbulkpipe(data->udev, data->diag_tx_ep->bEndpointAddress); @@ -2729,6 +2800,67 @@ static int btusb_bcm_set_diag(struct hci_dev *hdev, bool enable) } #endif +#ifdef CONFIG_PM +static irqreturn_t btusb_oob_wake_handler(int irq, void *priv) +{ + struct btusb_data *data = priv; + + pm_wakeup_event(&data->udev->dev, 0); + pm_system_wakeup(); + + /* Disable only if not already disabled (keep it balanced) */ + if (test_and_clear_bit(BTUSB_OOB_WAKE_ENABLED, &data->flags)) { + disable_irq_nosync(irq); + disable_irq_wake(irq); + } + return IRQ_HANDLED; +} + +static const struct of_device_id btusb_match_table[] = { + { .compatible = "usb1286,204e" }, + { } +}; +MODULE_DEVICE_TABLE(of, btusb_match_table); + +/* Use an oob wakeup pin? */ +static int btusb_config_oob_wake(struct hci_dev *hdev) +{ + struct btusb_data *data = hci_get_drvdata(hdev); + struct device *dev = &data->udev->dev; + int irq, ret; + + clear_bit(BTUSB_OOB_WAKE_ENABLED, &data->flags); + + if (!of_match_device(btusb_match_table, dev)) + return 0; + + /* Move on if no IRQ specified */ + irq = of_irq_get_byname(dev->of_node, "wakeup"); + if (irq <= 0) { + bt_dev_dbg(hdev, "%s: no OOB Wakeup IRQ in DT", __func__); + return 0; + } + + ret = devm_request_irq(&hdev->dev, irq, btusb_oob_wake_handler, + 0, "OOB Wake-on-BT", data); + if (ret) { + bt_dev_err(hdev, "%s: IRQ request failed", __func__); + return ret; + } + + ret = device_init_wakeup(dev, true); + if (ret) { + bt_dev_err(hdev, "%s: failed to init_wakeup", __func__); + return ret; + } + + data->oob_wake_irq = irq; + disable_irq(irq); + bt_dev_info(hdev, "OOB Wake-on-BT configured at IRQ %u", irq); + return 0; +} +#endif + static int btusb_probe(struct usb_interface *intf, const struct usb_device_id *id) { @@ -2850,6 +2982,18 @@ static int btusb_probe(struct usb_interface *intf, hdev->send = btusb_send_frame; hdev->notify = btusb_notify; +#ifdef CONFIG_PM + err = btusb_config_oob_wake(hdev); + if (err) + goto out_free_dev; + + /* Marvell devices may need a specific chip configuration */ + if (id->driver_info & BTUSB_MARVELL && data->oob_wake_irq) { + err = marvell_config_oob_wake(hdev); + if (err) + goto out_free_dev; + } +#endif if (id->driver_info & BTUSB_CW6622) set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks); @@ -2992,18 +3136,15 @@ static int btusb_probe(struct usb_interface *intf, err = usb_set_interface(data->udev, 0, 0); if (err < 0) { BT_ERR("failed to set interface 0, alt 0 %d", err); - hci_free_dev(hdev); - return err; + goto out_free_dev; } } if (data->isoc) { err = usb_driver_claim_interface(&btusb_driver, data->isoc, data); - if (err < 0) { - hci_free_dev(hdev); - return err; - } + if (err < 0) + goto out_free_dev; } #ifdef CONFIG_BT_HCIBTUSB_BCM @@ -3017,14 +3158,16 @@ static int btusb_probe(struct usb_interface *intf, #endif err = hci_register_dev(hdev); - if (err < 0) { - hci_free_dev(hdev); - return err; - } + if (err < 0) + goto out_free_dev; usb_set_intfdata(intf, data); return 0; + +out_free_dev: + hci_free_dev(hdev); + return err; } static void btusb_disconnect(struct usb_interface *intf) @@ -3063,6 +3206,9 @@ static void btusb_disconnect(struct usb_interface *intf) usb_driver_release_interface(&btusb_driver, data->isoc); } + if (data->oob_wake_irq) + device_init_wakeup(&data->udev->dev, false); + hci_free_dev(hdev); } @@ -3091,6 +3237,12 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message) btusb_stop_traffic(data); usb_kill_anchored_urbs(&data->tx_anchor); + if (data->oob_wake_irq && device_may_wakeup(&data->udev->dev)) { + set_bit(BTUSB_OOB_WAKE_ENABLED, &data->flags); + enable_irq_wake(data->oob_wake_irq); + enable_irq(data->oob_wake_irq); + } + /* Optionally request a device reset on resume, but only when * wakeups are disabled. If wakeups are enabled we assume the * device will stay powered up throughout suspend. @@ -3128,6 +3280,12 @@ static int btusb_resume(struct usb_interface *intf) if (--data->suspend_count) return 0; + /* Disable only if not already disabled (keep it balanced) */ + if (test_and_clear_bit(BTUSB_OOB_WAKE_ENABLED, &data->flags)) { + disable_irq(data->oob_wake_irq); + disable_irq_wake(data->oob_wake_irq); + } + if (!test_bit(HCI_RUNNING, &hdev->flags)) goto done; |