Commit c1ceee5e authored by David S. Miller's avatar David S. Miller

Merge branch 'for-upstream' of...

Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next

Johan Hedberg says:

====================
pull request: bluetooth-next 2017-02-19

Here's a set of Bluetooth patches for the 4.11 kernel:

 - New USB IDs to the btusb driver
 - Race fix in btmrvl driver
 - Added out-of-band wakeup support to the btusb driver
 - NULL dereference fix to bt_sock_recvmsg

Please let me know if there are any issues pulling. Thanks.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 24045a03 8f91566f
Generic Bluetooth controller over USB (btusb driver)
---------------------------------------------------
Required properties:
- compatible : should comply with the format "usbVID,PID" specified in
Documentation/devicetree/bindings/usb/usb-device.txt
At the time of writing, the only OF supported devices
(more may be added later) are:
"usb1286,204e" (Marvell 8997)
Also, vendors that use btusb may have device additional properties, e.g:
Documentation/devicetree/bindings/net/marvell-bt-8xxx.txt
Optional properties:
- interrupt-parent: phandle of the parent interrupt controller
- interrupt-names: (see below)
- interrupts : The interrupt specified by the name "wakeup" is the interrupt
that shall be used for out-of-band wake-on-bt. Driver will
request this interrupt for wakeup. During system suspend, the
irq will be enabled so that the bluetooth chip can wakeup host
platform out of band. During system resume, the irq will be
disabled to make sure unnecessary interrupt is not received.
Example:
Following example uses irq pin number 3 of gpio0 for out of band wake-on-bt:
&usb_host1_ehci {
status = "okay";
#address-cells = <1>;
#size-cells = <0>;
mvl_bt1: bt@1 {
compatible = "usb1286,204e";
reg = <1>;
interrupt-parent = <&gpio0>;
interrupt-name = "wakeup";
interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
};
};
Marvell 8897/8997 (sd8897/sd8997) bluetooth SDIO devices Marvell 8897/8997 (sd8897/sd8997) bluetooth devices (SDIO or USB based)
------ ------
The 8997 devices supports multiple interfaces. When used on SDIO interfaces,
the btmrvl driver is used and when used on USB interface, the btusb driver is
used.
Required properties: Required properties:
- compatible : should be one of the following: - compatible : should be one of the following:
* "marvell,sd8897-bt" * "marvell,sd8897-bt" (for SDIO)
* "marvell,sd8997-bt" * "marvell,sd8997-bt" (for SDIO)
* "usb1286,204e" (for USB)
Optional properties: Optional properties:
- marvell,cal-data: Calibration data downloaded to the device during - marvell,cal-data: Calibration data downloaded to the device during
initialization. This is an array of 28 values(u8). initialization. This is an array of 28 values(u8).
This is only applicable to SDIO devices.
- marvell,wakeup-pin: It represents wakeup pin number of the bluetooth chip. - marvell,wakeup-pin: It represents wakeup pin number of the bluetooth chip.
firmware will use the pin to wakeup host system (u16). firmware will use the pin to wakeup host system (u16).
...@@ -18,10 +23,15 @@ Optional properties: ...@@ -18,10 +23,15 @@ Optional properties:
platform. The value will be configured to firmware. This platform. The value will be configured to firmware. This
is needed to work chip's sleep feature as expected (u16). is needed to work chip's sleep feature as expected (u16).
- interrupt-parent: phandle of the parent interrupt controller - interrupt-parent: phandle of the parent interrupt controller
- interrupts : interrupt pin number to the cpu. Driver will request an irq based - interrupt-names: Used only for USB based devices (See below)
on this interrupt number. During system suspend, the irq will be - interrupts : specifies the interrupt pin number to the cpu. For SDIO, the
enabled so that the bluetooth chip can wakeup host platform under driver will use the first interrupt specified in the interrupt
certain condition. During system resume, the irq will be disabled array. For USB based devices, the driver will use the interrupt
named "wakeup" from the interrupt-names and interrupt arrays.
The driver will request an irq based on this interrupt number.
During system suspend, the irq will be enabled so that the
bluetooth chip can wakeup host platform under certain
conditions. During system resume, the irq will be disabled
to make sure unnecessary interrupt is not received. to make sure unnecessary interrupt is not received.
Example: Example:
...@@ -29,7 +39,9 @@ Example: ...@@ -29,7 +39,9 @@ Example:
IRQ pin 119 is used as system wakeup source interrupt. IRQ pin 119 is used as system wakeup source interrupt.
wakeup pin 13 and gap 100ms are configured so that firmware can wakeup host wakeup pin 13 and gap 100ms are configured so that firmware can wakeup host
using this device side pin and wakeup latency. using this device side pin and wakeup latency.
calibration data is also available in below example.
Example for SDIO device follows (calibration data is also available in
below example).
&mmc3 { &mmc3 {
status = "okay"; status = "okay";
...@@ -54,3 +66,21 @@ calibration data is also available in below example. ...@@ -54,3 +66,21 @@ calibration data is also available in below example.
marvell,wakeup-gap-ms = /bits/ 16 <0x64>; marvell,wakeup-gap-ms = /bits/ 16 <0x64>;
}; };
}; };
Example for USB device:
&usb_host1_ohci {
status = "okay";
#address-cells = <1>;
#size-cells = <0>;
mvl_bt1: bt@1 {
compatible = "usb1286,204e";
reg = <1>;
interrupt-parent = <&gpio0>;
interrupt-names = "wakeup";
interrupts = <119 IRQ_TYPE_LEVEL_LOW>;
marvell,wakeup-pin = /bits/ 16 <0x0d>;
marvell,wakeup-gap-ms = /bits/ 16 <0x64>;
};
};
...@@ -344,7 +344,7 @@ config BT_WILINK ...@@ -344,7 +344,7 @@ config BT_WILINK
config BT_QCOMSMD config BT_QCOMSMD
tristate "Qualcomm SMD based HCI support" tristate "Qualcomm SMD based HCI support"
depends on QCOM_SMD && QCOM_WCNSS_CTRL depends on (QCOM_SMD && QCOM_WCNSS_CTRL) || COMPILE_TEST
select BT_QCA select BT_QCA
help help
Qualcomm SMD based HCI driver. Qualcomm SMD based HCI driver.
......
...@@ -94,6 +94,7 @@ static const struct usb_device_id ath3k_table[] = { ...@@ -94,6 +94,7 @@ static const struct usb_device_id ath3k_table[] = {
{ USB_DEVICE(0x04CA, 0x300f) }, { USB_DEVICE(0x04CA, 0x300f) },
{ USB_DEVICE(0x04CA, 0x3010) }, { USB_DEVICE(0x04CA, 0x3010) },
{ USB_DEVICE(0x04CA, 0x3014) }, { USB_DEVICE(0x04CA, 0x3014) },
{ USB_DEVICE(0x04CA, 0x3018) },
{ USB_DEVICE(0x0930, 0x0219) }, { USB_DEVICE(0x0930, 0x0219) },
{ USB_DEVICE(0x0930, 0x021c) }, { USB_DEVICE(0x0930, 0x021c) },
{ USB_DEVICE(0x0930, 0x0220) }, { USB_DEVICE(0x0930, 0x0220) },
...@@ -162,6 +163,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = { ...@@ -162,6 +163,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
{ USB_DEVICE(0x04ca, 0x300f), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x300f), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3014), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3014), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3018), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x021c), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x021c), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
......
...@@ -178,6 +178,9 @@ static int btbcm_reset(struct hci_dev *hdev) ...@@ -178,6 +178,9 @@ static int btbcm_reset(struct hci_dev *hdev)
} }
kfree_skb(skb); kfree_skb(skb);
/* 100 msec delay for module to complete reset process */
msleep(100);
return 0; return 0;
} }
......
...@@ -502,7 +502,7 @@ static int btmrvl_download_cal_data(struct btmrvl_private *priv, ...@@ -502,7 +502,7 @@ static int btmrvl_download_cal_data(struct btmrvl_private *priv,
ret = btmrvl_send_sync_cmd(priv, BT_CMD_LOAD_CONFIG_DATA, data, ret = btmrvl_send_sync_cmd(priv, BT_CMD_LOAD_CONFIG_DATA, data,
BT_CAL_HDR_LEN + len); BT_CAL_HDR_LEN + len);
if (ret) if (ret)
BT_ERR("Failed to download caibration data"); BT_ERR("Failed to download calibration data");
return 0; return 0;
} }
......
...@@ -97,11 +97,11 @@ static int btmrvl_sdio_probe_of(struct device *dev, ...@@ -97,11 +97,11 @@ static int btmrvl_sdio_probe_of(struct device *dev,
cfg->irq_bt = irq_of_parse_and_map(card->plt_of_node, 0); cfg->irq_bt = irq_of_parse_and_map(card->plt_of_node, 0);
if (!cfg->irq_bt) { if (!cfg->irq_bt) {
dev_err(dev, "fail to parse irq_bt from device tree"); dev_err(dev, "fail to parse irq_bt from device tree");
cfg->irq_bt = -1;
} else { } else {
ret = devm_request_irq(dev, cfg->irq_bt, ret = devm_request_irq(dev, cfg->irq_bt,
btmrvl_wake_irq_bt, btmrvl_wake_irq_bt,
IRQF_TRIGGER_LOW, 0, "bt_wake", cfg);
"bt_wake", cfg);
if (ret) { if (ret) {
dev_err(dev, dev_err(dev,
"Failed to request irq_bt %d (%d)\n", "Failed to request irq_bt %d (%d)\n",
...@@ -1624,7 +1624,7 @@ static int btmrvl_sdio_suspend(struct device *dev) ...@@ -1624,7 +1624,7 @@ static int btmrvl_sdio_suspend(struct device *dev)
if (priv->adapter->hs_state != HS_ACTIVATED) { if (priv->adapter->hs_state != HS_ACTIVATED) {
if (btmrvl_enable_hs(priv)) { if (btmrvl_enable_hs(priv)) {
BT_ERR("HS not actived, suspend failed!"); BT_ERR("HS not activated, suspend failed!");
priv->adapter->is_suspending = false; priv->adapter->is_suspending = false;
return -EBUSY; return -EBUSY;
} }
...@@ -1682,8 +1682,12 @@ static int btmrvl_sdio_resume(struct device *dev) ...@@ -1682,8 +1682,12 @@ static int btmrvl_sdio_resume(struct device *dev)
/* Disable platform specific wakeup interrupt */ /* Disable platform specific wakeup interrupt */
if (card->plt_wake_cfg && card->plt_wake_cfg->irq_bt >= 0) { if (card->plt_wake_cfg && card->plt_wake_cfg->irq_bt >= 0) {
disable_irq_wake(card->plt_wake_cfg->irq_bt); disable_irq_wake(card->plt_wake_cfg->irq_bt);
if (!card->plt_wake_cfg->wake_by_bt) disable_irq(card->plt_wake_cfg->irq_bt);
disable_irq(card->plt_wake_cfg->irq_bt); if (card->plt_wake_cfg->wake_by_bt)
/* Undo our disable, since interrupt handler already
* did this.
*/
enable_irq(card->plt_wake_cfg->irq_bt);
} }
return 0; return 0;
......
...@@ -165,6 +165,7 @@ static const struct of_device_id btqcomsmd_of_match[] = { ...@@ -165,6 +165,7 @@ static const struct of_device_id btqcomsmd_of_match[] = {
{ .compatible = "qcom,wcnss-bt", }, { .compatible = "qcom,wcnss-bt", },
{ }, { },
}; };
MODULE_DEVICE_TABLE(of, btqcomsmd_of_match);
static struct platform_driver btqcomsmd_driver = { static struct platform_driver btqcomsmd_driver = {
.probe = btqcomsmd_probe, .probe = btqcomsmd_probe,
......
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/usb.h> #include <linux/usb.h>
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include <net/bluetooth/bluetooth.h> #include <net/bluetooth/bluetooth.h>
...@@ -130,6 +132,10 @@ static const struct usb_device_id btusb_table[] = { ...@@ -130,6 +132,10 @@ static const struct usb_device_id btusb_table[] = {
/* Broadcom BCM43142A0 (Foxconn/Lenovo) */ /* Broadcom BCM43142A0 (Foxconn/Lenovo) */
{ USB_DEVICE(0x105b, 0xe065), .driver_info = BTUSB_BCM_PATCHRAM }, { 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 */ /* Foxconn - Hon Hai */
{ USB_VENDOR_AND_INTERFACE_INFO(0x0489, 0xff, 0x01, 0x01), { USB_VENDOR_AND_INTERFACE_INFO(0x0489, 0xff, 0x01, 0x01),
.driver_info = BTUSB_BCM_PATCHRAM }, .driver_info = BTUSB_BCM_PATCHRAM },
...@@ -154,6 +160,10 @@ static const struct usb_device_id btusb_table[] = { ...@@ -154,6 +160,10 @@ static const struct usb_device_id btusb_table[] = {
{ USB_VENDOR_AND_INTERFACE_INFO(0x13d3, 0xff, 0x01, 0x01), { USB_VENDOR_AND_INTERFACE_INFO(0x13d3, 0xff, 0x01, 0x01),
.driver_info = BTUSB_BCM_PATCHRAM }, .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 */ /* Toshiba Corp - Broadcom based */
{ USB_VENDOR_AND_INTERFACE_INFO(0x0930, 0xff, 0x01, 0x01), { USB_VENDOR_AND_INTERFACE_INFO(0x0930, 0xff, 0x01, 0x01),
.driver_info = BTUSB_BCM_PATCHRAM }, .driver_info = BTUSB_BCM_PATCHRAM },
...@@ -209,6 +219,7 @@ static const struct usb_device_id blacklist_table[] = { ...@@ -209,6 +219,7 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x04ca, 0x300f), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x300f), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3014), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3014), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3018), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x021c), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x021c), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
...@@ -369,6 +380,7 @@ static const struct usb_device_id blacklist_table[] = { ...@@ -369,6 +380,7 @@ static const struct usb_device_id blacklist_table[] = {
#define BTUSB_BOOTING 9 #define BTUSB_BOOTING 9
#define BTUSB_RESET_RESUME 10 #define BTUSB_RESET_RESUME 10
#define BTUSB_DIAG_RUNNING 11 #define BTUSB_DIAG_RUNNING 11
#define BTUSB_OOB_WAKE_ENABLED 12
struct btusb_data { struct btusb_data {
struct hci_dev *hdev; struct hci_dev *hdev;
...@@ -416,6 +428,8 @@ struct btusb_data { ...@@ -416,6 +428,8 @@ struct btusb_data {
int (*recv_bulk)(struct btusb_data *data, void *buffer, int count); int (*recv_bulk)(struct btusb_data *data, void *buffer, int count);
int (*setup_on_usb)(struct hci_dev *hdev); 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) static inline void btusb_free_frags(struct btusb_data *data)
...@@ -2338,6 +2352,50 @@ static int btusb_shutdown_intel(struct hci_dev *hdev) ...@@ -2338,6 +2352,50 @@ static int btusb_shutdown_intel(struct hci_dev *hdev)
return 0; 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;
}
memcpy(skb_put(skb, sizeof(cmd)), 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, static int btusb_set_bdaddr_marvell(struct hci_dev *hdev,
const bdaddr_t *bdaddr) const bdaddr_t *bdaddr)
{ {
...@@ -2728,6 +2786,66 @@ static int btusb_bcm_set_diag(struct hci_dev *hdev, bool enable) ...@@ -2728,6 +2786,66 @@ static int btusb_bcm_set_diag(struct hci_dev *hdev, bool enable)
} }
#endif #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);
/* 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, static int btusb_probe(struct usb_interface *intf,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
...@@ -2849,6 +2967,18 @@ static int btusb_probe(struct usb_interface *intf, ...@@ -2849,6 +2967,18 @@ static int btusb_probe(struct usb_interface *intf,
hdev->send = btusb_send_frame; hdev->send = btusb_send_frame;
hdev->notify = btusb_notify; 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) if (id->driver_info & BTUSB_CW6622)
set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks); set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks);
...@@ -2991,18 +3121,15 @@ static int btusb_probe(struct usb_interface *intf, ...@@ -2991,18 +3121,15 @@ static int btusb_probe(struct usb_interface *intf,
err = usb_set_interface(data->udev, 0, 0); err = usb_set_interface(data->udev, 0, 0);
if (err < 0) { if (err < 0) {
BT_ERR("failed to set interface 0, alt 0 %d", err); BT_ERR("failed to set interface 0, alt 0 %d", err);
hci_free_dev(hdev); goto out_free_dev;
return err;
} }
} }
if (data->isoc) { if (data->isoc) {
err = usb_driver_claim_interface(&btusb_driver, err = usb_driver_claim_interface(&btusb_driver,
data->isoc, data); data->isoc, data);
if (err < 0) { if (err < 0)
hci_free_dev(hdev); goto out_free_dev;
return err;
}
} }
#ifdef CONFIG_BT_HCIBTUSB_BCM #ifdef CONFIG_BT_HCIBTUSB_BCM
...@@ -3016,14 +3143,16 @@ static int btusb_probe(struct usb_interface *intf, ...@@ -3016,14 +3143,16 @@ static int btusb_probe(struct usb_interface *intf,
#endif #endif
err = hci_register_dev(hdev); err = hci_register_dev(hdev);
if (err < 0) { if (err < 0)
hci_free_dev(hdev); goto out_free_dev;
return err;
}
usb_set_intfdata(intf, data); usb_set_intfdata(intf, data);
return 0; return 0;
out_free_dev:
hci_free_dev(hdev);
return err;
} }
static void btusb_disconnect(struct usb_interface *intf) static void btusb_disconnect(struct usb_interface *intf)
...@@ -3062,6 +3191,9 @@ static void btusb_disconnect(struct usb_interface *intf) ...@@ -3062,6 +3191,9 @@ static void btusb_disconnect(struct usb_interface *intf)
usb_driver_release_interface(&btusb_driver, data->isoc); usb_driver_release_interface(&btusb_driver, data->isoc);
} }
if (data->oob_wake_irq)
device_init_wakeup(&data->udev->dev, false);
hci_free_dev(hdev); hci_free_dev(hdev);
} }
...@@ -3090,6 +3222,12 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message) ...@@ -3090,6 +3222,12 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
btusb_stop_traffic(data); btusb_stop_traffic(data);
usb_kill_anchored_urbs(&data->tx_anchor); 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 /* Optionally request a device reset on resume, but only when
* wakeups are disabled. If wakeups are enabled we assume the * wakeups are disabled. If wakeups are enabled we assume the
* device will stay powered up throughout suspend. * device will stay powered up throughout suspend.
...@@ -3127,6 +3265,12 @@ static int btusb_resume(struct usb_interface *intf) ...@@ -3127,6 +3265,12 @@ static int btusb_resume(struct usb_interface *intf)
if (--data->suspend_count) if (--data->suspend_count)
return 0; 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)) if (!test_bit(HCI_RUNNING, &hdev->flags))
goto done; goto done;
......
...@@ -618,14 +618,25 @@ static int bcm_resume(struct device *dev) ...@@ -618,14 +618,25 @@ static int bcm_resume(struct device *dev)
} }
#endif #endif
static const struct acpi_gpio_params device_wakeup_gpios = { 0, 0, false }; static const struct acpi_gpio_params int_last_device_wakeup_gpios = { 0, 0, false };
static const struct acpi_gpio_params shutdown_gpios = { 1, 0, false }; static const struct acpi_gpio_params int_last_shutdown_gpios = { 1, 0, false };
static const struct acpi_gpio_params host_wakeup_gpios = { 2, 0, false }; static const struct acpi_gpio_params int_last_host_wakeup_gpios = { 2, 0, false };
static const struct acpi_gpio_mapping acpi_bcm_default_gpios[] = { static const struct acpi_gpio_mapping acpi_bcm_int_last_gpios[] = {
{ "device-wakeup-gpios", &device_wakeup_gpios, 1 }, { "device-wakeup-gpios", &int_last_device_wakeup_gpios, 1 },
{ "shutdown-gpios", &shutdown_gpios, 1 }, { "shutdown-gpios", &int_last_shutdown_gpios, 1 },
{ "host-wakeup-gpios", &host_wakeup_gpios, 1 }, { "host-wakeup-gpios", &int_last_host_wakeup_gpios, 1 },
{ },
};
static const struct acpi_gpio_params int_first_host_wakeup_gpios = { 0, 0, false };
static const struct acpi_gpio_params int_first_device_wakeup_gpios = { 1, 0, false };
static const struct acpi_gpio_params int_first_shutdown_gpios = { 2, 0, false };
static const struct acpi_gpio_mapping acpi_bcm_int_first_gpios[] = {
{ "device-wakeup-gpios", &int_first_device_wakeup_gpios, 1 },
{ "shutdown-gpios", &int_first_shutdown_gpios, 1 },
{ "host-wakeup-gpios", &int_first_host_wakeup_gpios, 1 },
{ }, { },
}; };
...@@ -692,12 +703,19 @@ static int bcm_acpi_probe(struct bcm_device *dev) ...@@ -692,12 +703,19 @@ static int bcm_acpi_probe(struct bcm_device *dev)
struct platform_device *pdev = dev->pdev; struct platform_device *pdev = dev->pdev;
LIST_HEAD(resources); LIST_HEAD(resources);
const struct dmi_system_id *dmi_id; const struct dmi_system_id *dmi_id;
const struct acpi_gpio_mapping *gpio_mapping = acpi_bcm_int_last_gpios;
const struct acpi_device_id *id;
int ret; int ret;
/* Retrieve GPIO data */
dev->name = dev_name(&pdev->dev); dev->name = dev_name(&pdev->dev);
/* Retrieve GPIO data */
id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);
if (id)
gpio_mapping = (const struct acpi_gpio_mapping *) id->driver_data;
ret = acpi_dev_add_driver_gpios(ACPI_COMPANION(&pdev->dev), ret = acpi_dev_add_driver_gpios(ACPI_COMPANION(&pdev->dev),
acpi_bcm_default_gpios); gpio_mapping);
if (ret) if (ret)
return ret; return ret;
...@@ -822,20 +840,22 @@ static const struct hci_uart_proto bcm_proto = { ...@@ -822,20 +840,22 @@ static const struct hci_uart_proto bcm_proto = {
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
static const struct acpi_device_id bcm_acpi_match[] = { static const struct acpi_device_id bcm_acpi_match[] = {
{ "BCM2E1A", 0 }, { "BCM2E1A", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
{ "BCM2E39", 0 }, { "BCM2E39", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
{ "BCM2E3A", 0 }, { "BCM2E3A", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
{ "BCM2E3D", 0 }, { "BCM2E3D", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
{ "BCM2E3F", 0 }, { "BCM2E3F", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
{ "BCM2E40", 0 }, { "BCM2E40", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
{ "BCM2E54", 0 }, { "BCM2E54", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
{ "BCM2E55", 0 }, { "BCM2E55", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
{ "BCM2E64", 0 }, { "BCM2E64", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
{ "BCM2E65", 0 }, { "BCM2E65", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
{ "BCM2E67", 0 }, { "BCM2E67", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
{ "BCM2E71", 0 }, { "BCM2E71", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
{ "BCM2E7B", 0 }, { "BCM2E7B", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
{ "BCM2E7C", 0 }, { "BCM2E7C", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
{ "BCM2E95", (kernel_ulong_t)&acpi_bcm_int_first_gpios },
{ "BCM2E96", (kernel_ulong_t)&acpi_bcm_int_first_gpios },
{ }, { },
}; };
MODULE_DEVICE_TABLE(acpi, bcm_acpi_match); MODULE_DEVICE_TABLE(acpi, bcm_acpi_match);
......
...@@ -335,7 +335,7 @@ static void hci_ibs_tx_idle_timeout(unsigned long arg) ...@@ -335,7 +335,7 @@ static void hci_ibs_tx_idle_timeout(unsigned long arg)
/* Fall through */ /* Fall through */
default: default:
BT_ERR("Spurrious timeout tx state %d", qca->tx_ibs_state); BT_ERR("Spurious timeout tx state %d", qca->tx_ibs_state);
break; break;
} }
...@@ -373,7 +373,7 @@ static void hci_ibs_wake_retrans_timeout(unsigned long arg) ...@@ -373,7 +373,7 @@ static void hci_ibs_wake_retrans_timeout(unsigned long arg)
/* Fall through */ /* Fall through */
default: default:
BT_ERR("Spurrious timeout tx state %d", qca->tx_ibs_state); BT_ERR("Spurious timeout tx state %d", qca->tx_ibs_state);
break; break;
} }
......
...@@ -245,7 +245,7 @@ int bt_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, ...@@ -245,7 +245,7 @@ int bt_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
if (err == 0) { if (err == 0) {
sock_recv_ts_and_drops(msg, sk, skb); sock_recv_ts_and_drops(msg, sk, skb);
if (bt_sk(sk)->skb_msg_name) if (msg->msg_name && bt_sk(sk)->skb_msg_name)
bt_sk(sk)->skb_msg_name(skb, msg->msg_name, bt_sk(sk)->skb_msg_name(skb, msg->msg_name,
&msg->msg_namelen); &msg->msg_namelen);
} }
......
...@@ -4749,7 +4749,7 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr, ...@@ -4749,7 +4749,7 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
case LE_ADV_SCAN_RSP: case LE_ADV_SCAN_RSP:
break; break;
default: default:
BT_ERR_RATELIMITED("Unknown advetising packet type: 0x%02x", BT_ERR_RATELIMITED("Unknown advertising packet type: 0x%02x",
type); type);
return; return;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment