Commit 7bcfeead authored by David S. Miller's avatar David S. Miller
Browse files

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 2015-10-08

Here's another set of Bluetooth & 802.15.4 patches for the 4.4 kernel.

802.15.4:
 - Many improvements & fixes to the mrf24j40 driver
 - Fixes and cleanups to nl802154, mac802154 & ieee802154 code

Bluetooth:
 - New chipset support in btmrvl driver
 - Fixes & cleanups to btbcm, btmrvl, bpa10x & btintel drivers
 - Support for vendor specific diagnostic data through common API
 - Cleanups to the 6lowpan code
 - New events & message types for monitor channel

Please let me know if there are any issues pulling. Thanks.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 8fae307c f640ee98
* MRF24J40 IEEE 802.15.4 *
Required properties:
- compatible: should be "microchip,mrf24j40", "microchip,mrf24j40ma",
or "microchip,mrf24j40mc" depends on your transceiver
board
- spi-max-frequency: maximal bus speed, should be set something under or equal
10000000
- reg: the chipselect index
- interrupts: the interrupt generated by the device.
Example:
mrf24j40ma@0 {
compatible = "microchip,mrf24j40ma";
spi-max-frequency = <8500000>;
reg = <0>;
interrupts = <19 8>;
interrupt-parent = <&gpio3>;
};
...@@ -6978,6 +6978,7 @@ M: Alan Ott <alan@signal11.us> ...@@ -6978,6 +6978,7 @@ M: Alan Ott <alan@signal11.us>
L: linux-wpan@vger.kernel.org L: linux-wpan@vger.kernel.org
S: Maintained S: Maintained
F: drivers/net/ieee802154/mrf24j40.c F: drivers/net/ieee802154/mrf24j40.c
F: Documentation/devicetree/bindings/net/ieee802154/mrf24j40.txt
MSI LAPTOP SUPPORT MSI LAPTOP SUPPORT
M: "Lee, Chun-Yi" <jlee@suse.com> M: "Lee, Chun-Yi" <jlee@suse.com>
......
...@@ -4,6 +4,7 @@ menu "Bluetooth device drivers" ...@@ -4,6 +4,7 @@ menu "Bluetooth device drivers"
config BT_INTEL config BT_INTEL
tristate tristate
select REGMAP
config BT_BCM config BT_BCM
tristate tristate
...@@ -183,6 +184,7 @@ config BT_HCIBCM203X ...@@ -183,6 +184,7 @@ config BT_HCIBCM203X
config BT_HCIBPA10X config BT_HCIBPA10X
tristate "HCI BPA10x USB driver" tristate "HCI BPA10x USB driver"
depends on USB depends on USB
select BT_HCIUART_H4
help help
Bluetooth HCI BPA10x USB driver. Bluetooth HCI BPA10x USB driver.
This driver provides support for the Digianswer BPA 100/105 Bluetooth This driver provides support for the Digianswer BPA 100/105 Bluetooth
...@@ -275,7 +277,7 @@ config BT_MRVL ...@@ -275,7 +277,7 @@ config BT_MRVL
The core driver to support Marvell Bluetooth devices. The core driver to support Marvell Bluetooth devices.
This driver is required if you want to support This driver is required if you want to support
Marvell Bluetooth devices, such as 8688/8787/8797/8887/8897. Marvell Bluetooth devices, such as 8688/8787/8797/8887/8897/8997.
Say Y here to compile Marvell Bluetooth driver Say Y here to compile Marvell Bluetooth driver
into the kernel or say M to compile it as module. into the kernel or say M to compile it as module.
...@@ -289,7 +291,7 @@ config BT_MRVL_SDIO ...@@ -289,7 +291,7 @@ config BT_MRVL_SDIO
The driver for Marvell Bluetooth chipsets with SDIO interface. The driver for Marvell Bluetooth chipsets with SDIO interface.
This driver is required if you want to use Marvell Bluetooth This driver is required if you want to use Marvell Bluetooth
devices with SDIO interface. Currently SD8688/SD8787/SD8797/SD8887/SD8897 devices with SDIO interface. Currently SD8688/SD8787/SD8797/SD8887/SD8897/SD8997
chipsets are supported. chipsets are supported.
Say Y here to compile support for Marvell BT-over-SDIO driver Say Y here to compile support for Marvell BT-over-SDIO driver
......
...@@ -422,17 +422,12 @@ static int bfusb_open(struct hci_dev *hdev) ...@@ -422,17 +422,12 @@ static int bfusb_open(struct hci_dev *hdev)
BT_DBG("hdev %p bfusb %p", hdev, data); BT_DBG("hdev %p bfusb %p", hdev, data);
if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
return 0;
write_lock_irqsave(&data->lock, flags); write_lock_irqsave(&data->lock, flags);
err = bfusb_rx_submit(data, NULL); err = bfusb_rx_submit(data, NULL);
if (!err) { if (!err) {
for (i = 1; i < BFUSB_MAX_BULK_RX; i++) for (i = 1; i < BFUSB_MAX_BULK_RX; i++)
bfusb_rx_submit(data, NULL); bfusb_rx_submit(data, NULL);
} else {
clear_bit(HCI_RUNNING, &hdev->flags);
} }
write_unlock_irqrestore(&data->lock, flags); write_unlock_irqrestore(&data->lock, flags);
...@@ -458,9 +453,6 @@ static int bfusb_close(struct hci_dev *hdev) ...@@ -458,9 +453,6 @@ static int bfusb_close(struct hci_dev *hdev)
BT_DBG("hdev %p bfusb %p", hdev, data); BT_DBG("hdev %p bfusb %p", hdev, data);
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
return 0;
write_lock_irqsave(&data->lock, flags); write_lock_irqsave(&data->lock, flags);
write_unlock_irqrestore(&data->lock, flags); write_unlock_irqrestore(&data->lock, flags);
...@@ -479,9 +471,6 @@ static int bfusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -479,9 +471,6 @@ static int bfusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
BT_DBG("hdev %p skb %p type %d len %d", hdev, skb, bt_cb(skb)->pkt_type, skb->len); BT_DBG("hdev %p skb %p type %d len %d", hdev, skb, bt_cb(skb)->pkt_type, skb->len);
if (!test_bit(HCI_RUNNING, &hdev->flags))
return -EBUSY;
switch (bt_cb(skb)->pkt_type) { switch (bt_cb(skb)->pkt_type) {
case HCI_COMMAND_PKT: case HCI_COMMAND_PKT:
hdev->stat.cmd_tx++; hdev->stat.cmd_tx++;
......
...@@ -390,7 +390,7 @@ static void bluecard_receive(struct bluecard_info *info, ...@@ -390,7 +390,7 @@ static void bluecard_receive(struct bluecard_info *info,
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
/* Allocate packet */ /* Allocate packet */
if (info->rx_skb == NULL) { if (!info->rx_skb) {
info->rx_state = RECV_WAIT_PACKET_TYPE; info->rx_state = RECV_WAIT_PACKET_TYPE;
info->rx_count = 0; info->rx_count = 0;
info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC); info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
...@@ -628,9 +628,6 @@ static int bluecard_hci_open(struct hci_dev *hdev) ...@@ -628,9 +628,6 @@ static int bluecard_hci_open(struct hci_dev *hdev)
if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state)))
bluecard_hci_set_baud_rate(hdev, DEFAULT_BAUD_RATE); bluecard_hci_set_baud_rate(hdev, DEFAULT_BAUD_RATE);
if (test_and_set_bit(HCI_RUNNING, &(hdev->flags)))
return 0;
if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) { if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) {
unsigned int iobase = info->p_dev->resource[0]->start; unsigned int iobase = info->p_dev->resource[0]->start;
...@@ -646,9 +643,6 @@ static int bluecard_hci_close(struct hci_dev *hdev) ...@@ -646,9 +643,6 @@ static int bluecard_hci_close(struct hci_dev *hdev)
{ {
struct bluecard_info *info = hci_get_drvdata(hdev); struct bluecard_info *info = hci_get_drvdata(hdev);
if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags)))
return 0;
bluecard_hci_flush(hdev); bluecard_hci_flush(hdev);
if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) { if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) {
......
...@@ -35,7 +35,9 @@ ...@@ -35,7 +35,9 @@
#include <net/bluetooth/bluetooth.h> #include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h> #include <net/bluetooth/hci_core.h>
#define VERSION "0.10" #include "hci_uart.h"
#define VERSION "0.11"
static const struct usb_device_id bpa10x_table[] = { static const struct usb_device_id bpa10x_table[] = {
/* Tektronix BPA 100/105 (Digianswer) */ /* Tektronix BPA 100/105 (Digianswer) */
...@@ -56,112 +58,6 @@ struct bpa10x_data { ...@@ -56,112 +58,6 @@ struct bpa10x_data {
struct sk_buff *rx_skb[2]; struct sk_buff *rx_skb[2];
}; };
#define HCI_VENDOR_HDR_SIZE 5
struct hci_vendor_hdr {
__u8 type;
__le16 snum;
__le16 dlen;
} __packed;
static int bpa10x_recv(struct hci_dev *hdev, int queue, void *buf, int count)
{
struct bpa10x_data *data = hci_get_drvdata(hdev);
BT_DBG("%s queue %d buffer %p count %d", hdev->name,
queue, buf, count);
if (queue < 0 || queue > 1)
return -EILSEQ;
hdev->stat.byte_rx += count;
while (count) {
struct sk_buff *skb = data->rx_skb[queue];
struct { __u8 type; int expect; } *scb;
int type, len = 0;
if (!skb) {
/* Start of the frame */
type = *((__u8 *) buf);
count--; buf++;
switch (type) {
case HCI_EVENT_PKT:
if (count >= HCI_EVENT_HDR_SIZE) {
struct hci_event_hdr *h = buf;
len = HCI_EVENT_HDR_SIZE + h->plen;
} else
return -EILSEQ;
break;
case HCI_ACLDATA_PKT:
if (count >= HCI_ACL_HDR_SIZE) {
struct hci_acl_hdr *h = buf;
len = HCI_ACL_HDR_SIZE +
__le16_to_cpu(h->dlen);
} else
return -EILSEQ;
break;
case HCI_SCODATA_PKT:
if (count >= HCI_SCO_HDR_SIZE) {
struct hci_sco_hdr *h = buf;
len = HCI_SCO_HDR_SIZE + h->dlen;
} else
return -EILSEQ;
break;
case HCI_VENDOR_PKT:
if (count >= HCI_VENDOR_HDR_SIZE) {
struct hci_vendor_hdr *h = buf;
len = HCI_VENDOR_HDR_SIZE +
__le16_to_cpu(h->dlen);
} else
return -EILSEQ;
break;
}
skb = bt_skb_alloc(len, GFP_ATOMIC);
if (!skb) {
BT_ERR("%s no memory for packet", hdev->name);
return -ENOMEM;
}
data->rx_skb[queue] = skb;
scb = (void *) skb->cb;
scb->type = type;
scb->expect = len;
} else {
/* Continuation */
scb = (void *) skb->cb;
len = scb->expect;
}
len = min(len, count);
memcpy(skb_put(skb, len), buf, len);
scb->expect -= len;
if (scb->expect == 0) {
/* Complete frame */
data->rx_skb[queue] = NULL;
bt_cb(skb)->pkt_type = scb->type;
hci_recv_frame(hdev, skb);
}
count -= len; buf += len;
}
return 0;
}
static void bpa10x_tx_complete(struct urb *urb) static void bpa10x_tx_complete(struct urb *urb)
{ {
struct sk_buff *skb = urb->context; struct sk_buff *skb = urb->context;
...@@ -184,6 +80,22 @@ static void bpa10x_tx_complete(struct urb *urb) ...@@ -184,6 +80,22 @@ static void bpa10x_tx_complete(struct urb *urb)
kfree_skb(skb); kfree_skb(skb);
} }
#define HCI_VENDOR_HDR_SIZE 5
#define HCI_RECV_VENDOR \
.type = HCI_VENDOR_PKT, \
.hlen = HCI_VENDOR_HDR_SIZE, \
.loff = 3, \
.lsize = 2, \
.maxlen = HCI_MAX_FRAME_SIZE
static const struct h4_recv_pkt bpa10x_recv_pkts[] = {
{ H4_RECV_ACL, .recv = hci_recv_frame },
{ H4_RECV_SCO, .recv = hci_recv_frame },
{ H4_RECV_EVENT, .recv = hci_recv_frame },
{ HCI_RECV_VENDOR, .recv = hci_recv_diag },
};
static void bpa10x_rx_complete(struct urb *urb) static void bpa10x_rx_complete(struct urb *urb)
{ {
struct hci_dev *hdev = urb->context; struct hci_dev *hdev = urb->context;
...@@ -197,11 +109,17 @@ static void bpa10x_rx_complete(struct urb *urb) ...@@ -197,11 +109,17 @@ static void bpa10x_rx_complete(struct urb *urb)
return; return;
if (urb->status == 0) { if (urb->status == 0) {
if (bpa10x_recv(hdev, usb_pipebulk(urb->pipe), bool idx = usb_pipebulk(urb->pipe);
data->rx_skb[idx] = h4_recv_buf(hdev, data->rx_skb[idx],
urb->transfer_buffer, urb->transfer_buffer,
urb->actual_length) < 0) { urb->actual_length,
bpa10x_recv_pkts,
ARRAY_SIZE(bpa10x_recv_pkts));
if (IS_ERR(data->rx_skb[idx])) {
BT_ERR("%s corrupted event packet", hdev->name); BT_ERR("%s corrupted event packet", hdev->name);
hdev->stat.err_rx++; hdev->stat.err_rx++;
data->rx_skb[idx] = NULL;
} }
} }
...@@ -304,9 +222,6 @@ static int bpa10x_open(struct hci_dev *hdev) ...@@ -304,9 +222,6 @@ static int bpa10x_open(struct hci_dev *hdev)
BT_DBG("%s", hdev->name); BT_DBG("%s", hdev->name);
if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
return 0;
err = bpa10x_submit_intr_urb(hdev); err = bpa10x_submit_intr_urb(hdev);
if (err < 0) if (err < 0)
goto error; goto error;
...@@ -320,8 +235,6 @@ static int bpa10x_open(struct hci_dev *hdev) ...@@ -320,8 +235,6 @@ static int bpa10x_open(struct hci_dev *hdev)
error: error:
usb_kill_anchored_urbs(&data->rx_anchor); usb_kill_anchored_urbs(&data->rx_anchor);
clear_bit(HCI_RUNNING, &hdev->flags);
return err; return err;
} }
...@@ -331,9 +244,6 @@ static int bpa10x_close(struct hci_dev *hdev) ...@@ -331,9 +244,6 @@ static int bpa10x_close(struct hci_dev *hdev)
BT_DBG("%s", hdev->name); BT_DBG("%s", hdev->name);
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
return 0;
usb_kill_anchored_urbs(&data->rx_anchor); usb_kill_anchored_urbs(&data->rx_anchor);
return 0; return 0;
...@@ -350,6 +260,24 @@ static int bpa10x_flush(struct hci_dev *hdev) ...@@ -350,6 +260,24 @@ static int bpa10x_flush(struct hci_dev *hdev)
return 0; return 0;
} }
static int bpa10x_setup(struct hci_dev *hdev)
{
const u8 req[] = { 0x07 };
struct sk_buff *skb;
BT_DBG("%s", hdev->name);
/* Read revision string */
skb = __hci_cmd_sync(hdev, 0xfc0e, sizeof(req), req, HCI_INIT_TIMEOUT);
if (IS_ERR(skb))
return PTR_ERR(skb);
BT_INFO("%s: %s", hdev->name, (char *)(skb->data + 1));
kfree_skb(skb);
return 0;
}
static int bpa10x_send_frame(struct hci_dev *hdev, struct sk_buff *skb) static int bpa10x_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
{ {
struct bpa10x_data *data = hci_get_drvdata(hdev); struct bpa10x_data *data = hci_get_drvdata(hdev);
...@@ -360,9 +288,6 @@ static int bpa10x_send_frame(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -360,9 +288,6 @@ static int bpa10x_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
BT_DBG("%s", hdev->name); BT_DBG("%s", hdev->name);
if (!test_bit(HCI_RUNNING, &hdev->flags))
return -EBUSY;
skb->dev = (void *) hdev; skb->dev = (void *) hdev;
urb = usb_alloc_urb(0, GFP_ATOMIC); urb = usb_alloc_urb(0, GFP_ATOMIC);
...@@ -431,6 +356,25 @@ static int bpa10x_send_frame(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -431,6 +356,25 @@ static int bpa10x_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
return 0; return 0;
} }
static int bpa10x_set_diag(struct hci_dev *hdev, bool enable)
{
const u8 req[] = { 0x00, enable };
struct sk_buff *skb;
BT_DBG("%s", hdev->name);
if (!test_bit(HCI_RUNNING, &hdev->flags))
return -ENETDOWN;
/* Enable sniffer operation */
skb = __hci_cmd_sync(hdev, 0xfc0e, sizeof(req), req, HCI_INIT_TIMEOUT);
if (IS_ERR(skb))
return PTR_ERR(skb);
kfree_skb(skb);
return 0;
}
static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *id) static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *id)
{ {
struct bpa10x_data *data; struct bpa10x_data *data;
...@@ -465,7 +409,9 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id * ...@@ -465,7 +409,9 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *
hdev->open = bpa10x_open; hdev->open = bpa10x_open;
hdev->close = bpa10x_close; hdev->close = bpa10x_close;
hdev->flush = bpa10x_flush; hdev->flush = bpa10x_flush;
hdev->setup = bpa10x_setup;
hdev->send = bpa10x_send_frame; hdev->send = bpa10x_send_frame;
hdev->set_diag = bpa10x_set_diag;
set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
......
...@@ -233,7 +233,7 @@ static void bt3c_receive(struct bt3c_info *info) ...@@ -233,7 +233,7 @@ static void bt3c_receive(struct bt3c_info *info)
info->hdev->stat.byte_rx++; info->hdev->stat.byte_rx++;
/* Allocate packet */ /* Allocate packet */
if (info->rx_skb == NULL) { if (!info->rx_skb) {
info->rx_state = RECV_WAIT_PACKET_TYPE; info->rx_state = RECV_WAIT_PACKET_TYPE;
info->rx_count = 0; info->rx_count = 0;
info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC); info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
...@@ -270,7 +270,6 @@ static void bt3c_receive(struct bt3c_info *info) ...@@ -270,7 +270,6 @@ static void bt3c_receive(struct bt3c_info *info)
/* Unknown packet */ /* Unknown packet */
BT_ERR("Unknown HCI packet with type 0x%02x received", bt_cb(info->rx_skb)->pkt_type); BT_ERR("Unknown HCI packet with type 0x%02x received", bt_cb(info->rx_skb)->pkt_type);
info->hdev->stat.err_rx++; info->hdev->stat.err_rx++;
clear_bit(HCI_RUNNING, &(info->hdev->flags));
kfree_skb(info->rx_skb); kfree_skb(info->rx_skb);
info->rx_skb = NULL; info->rx_skb = NULL;
...@@ -395,17 +394,12 @@ static int bt3c_hci_flush(struct hci_dev *hdev) ...@@ -395,17 +394,12 @@ static int bt3c_hci_flush(struct hci_dev *hdev)
static int bt3c_hci_open(struct hci_dev *hdev) static int bt3c_hci_open(struct hci_dev *hdev)
{ {
set_bit(HCI_RUNNING, &(hdev->flags));
return 0; return 0;
} }
static int bt3c_hci_close(struct hci_dev *hdev) static int bt3c_hci_close(struct hci_dev *hdev)
{ {
if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags)))
return 0;
bt3c_hci_flush(hdev); bt3c_hci_flush(hdev);
return 0; return 0;
......
...@@ -181,6 +181,27 @@ static int btbcm_reset(struct hci_dev *hdev) ...@@ -181,6 +181,27 @@ static int btbcm_reset(struct hci_dev *hdev)
return 0; return 0;
} }
static struct sk_buff *btbcm_read_local_name(struct hci_dev *hdev)
{
struct sk_buff *skb;
skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL,
HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
BT_ERR("%s: BCM: Reading local name failed (%ld)",
hdev->name, PTR_ERR(skb));
return skb;
}
if (skb->len != sizeof(struct hci_rp_read_local_name)) {
BT_ERR("%s: BCM: Local name length mismatch", hdev->name);
kfree_skb(skb);
return ERR_PTR(-EIO);
}
return skb;
}
static struct sk_buff *btbcm_read_local_version(struct hci_dev *hdev) static struct sk_buff *btbcm_read_local_version(struct hci_dev *hdev)
{ {
struct sk_buff *skb; struct sk_buff *skb;
...@@ -393,6 +414,14 @@ int btbcm_setup_patchram(struct hci_dev *hdev) ...@@ -393,6 +414,14 @@ int btbcm_setup_patchram(struct hci_dev *hdev)
BT_INFO("%s: BCM: chip id %u", hdev->name, skb->data[1]); BT_INFO("%s: BCM: chip id %u", hdev->name, skb->data[1]);
kfree_skb(skb); kfree_skb(skb);
/* Read Local Name */
skb = btbcm_read_local_name(hdev);
if (IS_ERR(skb))
return PTR_ERR(skb);
BT_INFO("%s: %s", hdev->name, (char *)(skb->data + 1));
kfree_skb(skb);
switch ((rev & 0xf000) >> 12) { switch ((rev & 0xf000) >> 12) {
case 0: case 0:
case 3: case 3:
...@@ -464,6 +493,14 @@ int btbcm_setup_patchram(struct hci_dev *hdev) ...@@ -464,6 +493,14 @@ int btbcm_setup_patchram(struct hci_dev *hdev)
hw_name ? : "BCM", (subver & 0x7000) >> 13, hw_name ? : "BCM", (subver & 0x7000) >> 13,
(subver & 0x1f00) >> 8, (subver & 0x00ff), rev & 0x0fff); (subver & 0x1f00) >> 8, (subver & 0x00ff), rev & 0x0fff);
/* Read Local Name */
skb = btbcm_read_local_name(hdev);
if (IS_ERR(skb))
return PTR_ERR(skb);
BT_INFO("%s: %s", hdev->name, (char *)(skb->data + 1));
kfree_skb(skb);
btbcm_check_bdaddr(hdev); btbcm_check_bdaddr(hdev);
set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks);
...@@ -475,12 +512,25 @@ EXPORT_SYMBOL_GPL(btbcm_setup_patchram); ...@@ -475,12 +512,25 @@ EXPORT_SYMBOL_GPL(btbcm_setup_patchram);
int btbcm_setup_apple(struct hci_dev *hdev) int btbcm_setup_apple(struct hci_dev *hdev)
{ {
struct sk_buff *skb; struct sk_buff *skb;
int err;
/* Reset */
err = btbcm_reset(hdev);
if (err)
return err;
/* Read Verbose Config Version Info */ /* Read Verbose Config Version Info */
skb = btbcm_read_verbose_config(hdev); skb = btbcm_read_verbose_config(hdev);
if (!IS_ERR(skb)) { if (!IS_ERR(skb)) {
BT_INFO("%s: BCM: chip id %u build %4.4u", hdev->name, skb->data[1], BT_INFO("%s: BCM: chip id %u build %4.4u", hdev->name,
get_unaligned_le16(skb->data + 5)); skb->data[1], get_unaligned_le16(skb->data + 5));
kfree_skb(skb);
}
/* Read Local Name */
skb = btbcm_read_local_name(hdev);
if (!IS_ERR(skb)) {
BT_INFO("%s: %s", hdev->name, (char *)(skb->data + 1));
kfree_skb(skb); kfree_skb(skb);
} }
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/regmap.h>
#include <net/bluetooth/bluetooth.h> #include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h> #include <net/bluetooth/hci_core.h>
...@@ -215,6 +216,201 @@ int btintel_load_ddc_config(struct hci_dev *hdev, const char *ddc_name) ...@@ -215,6 +216,201 @@ int btintel_load_ddc_config(struct hci_dev *hdev, const char *ddc_name)
} }
EXPORT_SYMBOL_GPL(btintel_load_ddc_config); EXPORT_SYMBOL_GPL(btintel_load_ddc_config);
/* ------- REGMAP IBT SUPPORT ------- */
#define IBT_REG_MODE_8BIT 0x00
#define IBT_REG_MODE_16BIT 0x01
#define IBT_REG_MODE_32BIT 0x02
struct regmap_ibt_context {
struct hci_dev *hdev;
__u16 op_write;
__u16 op_read;
};
struct ibt_cp_reg_access {
__le32 addr;
__u8 mode;
__u8 len;
__u8 data[0];
} __packed;
struct ibt_rp_reg_access {
__u8 status;
__le32 addr;
__u8 data[0];
} __packed;
static int regmap_ibt_read(void *context, const void *addr, size_t reg_size,
void *val, size_t val_size)
{
struct regmap_ibt_context *ctx = context;
struct ibt_cp_reg_access cp;
struct ibt_rp_reg_access *rp;
struct sk_buff *skb;
int err = 0;
if (reg_size != sizeof(__le32))
return -EINVAL;
switch (val_size) {
case 1:
cp.mode = IBT_REG_MODE_8BIT;
break;
case 2:
cp.mode = IBT_REG_MODE_16BIT;
break;
case 4:
cp.mode = IBT_REG_MODE_32BIT;
break;
default:
return -EINVAL;
}
/* regmap provides a little-endian formatted addr */
cp.addr = *(__le32 *)addr;
cp.len = val_size;
bt_dev_dbg(ctx->hdev, "Register (0x%x) read", le32_to_cpu(cp.addr));
skb = hci_cmd_sync(ctx->hdev, ctx->op_read, sizeof(cp), &cp,
HCI_CMD_TIMEOUT);
if (IS_ERR(skb)) {
err = PTR_ERR(skb);
bt_dev_err(ctx->hdev, "regmap: Register (0x%x) read error (%d)",
le32_to_cpu(cp.addr), err);
return err;
}
if (skb->len != sizeof(*rp) + val_size) {
bt_dev_err(ctx->hdev, "regmap: Register (0x%x) read error, bad len",
le32_to_cpu(cp.addr));
err = -EINVAL;
goto done;
}
rp = (struct ibt_rp_reg_access *)skb->data;
if (rp->addr != cp.addr) {
bt_dev_err(ctx->hdev, "regmap: Register (0x%x) read error, bad addr",
le32_to_cpu(rp->addr));
err = -EINVAL;
goto done;
}
memcpy(val, rp->data, val_size);
done:
kfree_skb(skb);
return err;
}
static int regmap_ibt_gather_write(void *context,
const void *addr, size_t reg_size,
const void *val, size_t val_size)
{
struct regmap_ibt_context *ctx = context;
struct ibt_cp_reg_access *cp;
struct sk_buff *skb;
int plen = sizeof(*cp) + val_size;
u8 mode;
int err = 0;
if (reg_size != sizeof(__le32))
return -EINVAL;
switch (val_size) {
case 1:
mode = IBT_REG_MODE_8BIT;
break;
case 2:
mode = IBT_REG_MODE_16BIT;
break;
case 4:
mode = IBT_REG_MODE_32BIT;
break;
default:
return -EINVAL;
}
cp = kmalloc(plen, GFP_KERNEL);
if (!cp)
return -ENOMEM;
/* regmap provides a little-endian formatted addr/value */
cp->addr = *(__le32 *)addr;
cp->mode = mode;
cp->len = val_size;
memcpy(&cp->data, val, val_size);
bt_dev_dbg(ctx->hdev, "Register (0x%x) write", le32_to_cpu(cp->addr));
skb = hci_cmd_sync(ctx->hdev, ctx->op_write, plen, cp, HCI_CMD_TIMEOUT);
if (IS_ERR(skb)) {
err = PTR_ERR(skb);
bt_dev_err(ctx->hdev, "regmap: Register (0x%x) write error (%d)",
le32_to_cpu(cp->addr), err);
goto done;
}
kfree_skb(skb);
done:
kfree(cp);
return err;
}
static int regmap_ibt_write(void *context, const void *data, size_t count)
{
/* data contains register+value, since we only support 32bit addr,
* minimum data size is 4 bytes.
*/
if (WARN_ONCE(count < 4, "Invalid register access"))
return -EINVAL;
return regmap_ibt_gather_write(context, data, 4, data + 4, count - 4);
}
static void regmap_ibt_free_context(void *context)
{
kfree(context);
}
static struct regmap_bus regmap_ibt = {
.read = regmap_ibt_read,
.write = regmap_ibt_write,
.gather_write = regmap_ibt_gather_write,
.free_context = regmap_ibt_free_context,
.reg_format_endian_default = REGMAP_ENDIAN_LITTLE,
.val_format_endian_default = REGMAP_ENDIAN_LITTLE,
};
/* Config is the same for all register regions */
static const struct regmap_config regmap_ibt_cfg = {
.name = "btintel_regmap",
.reg_bits = 32,
.val_bits = 32,
};
struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read,
u16 opcode_write)
{
struct regmap_ibt_context *ctx;
bt_dev_info(hdev, "regmap: Init R%x-W%x region", opcode_read,
opcode_write);
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
if (!ctx)
return ERR_PTR(-ENOMEM);
ctx->op_read = opcode_read;
ctx->op_write = opcode_write;
ctx->hdev = hdev;
return regmap_init(&hdev->dev, &regmap_ibt, ctx, &regmap_ibt_cfg);
}
EXPORT_SYMBOL_GPL(btintel_regmap_init);
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
MODULE_DESCRIPTION("Bluetooth support for Intel devices ver " VERSION); MODULE_DESCRIPTION("Bluetooth support for Intel devices ver " VERSION);
MODULE_VERSION(VERSION); MODULE_VERSION(VERSION);
......
...@@ -80,6 +80,9 @@ int btintel_secure_send(struct hci_dev *hdev, u8 fragment_type, u32 plen, ...@@ -80,6 +80,9 @@ int btintel_secure_send(struct hci_dev *hdev, u8 fragment_type, u32 plen,
const void *param); const void *param);
int btintel_load_ddc_config(struct hci_dev *hdev, const char *ddc_name); int btintel_load_ddc_config(struct hci_dev *hdev, const char *ddc_name);
struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read,
u16 opcode_write);
#else #else
static inline int btintel_check_bdaddr(struct hci_dev *hdev) static inline int btintel_check_bdaddr(struct hci_dev *hdev)
...@@ -113,4 +116,10 @@ static inline int btintel_load_ddc_config(struct hci_dev *hdev, ...@@ -113,4 +116,10 @@ static inline int btintel_load_ddc_config(struct hci_dev *hdev,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
static inline struct regmap *btintel_regmap_init(struct hci_dev *hdev,
u16 opcode_read,
u16 opcode_write)
{
return ERR_PTR(-EINVAL);
}
#endif #endif
...@@ -184,7 +184,7 @@ static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 opcode, ...@@ -184,7 +184,7 @@ static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 opcode,
} }
skb = bt_skb_alloc(HCI_COMMAND_HDR_SIZE + len, GFP_ATOMIC); skb = bt_skb_alloc(HCI_COMMAND_HDR_SIZE + len, GFP_ATOMIC);
if (skb == NULL) { if (!skb) {
BT_ERR("No free skb"); BT_ERR("No free skb");
return -ENOMEM; return -ENOMEM;
} }
...@@ -436,13 +436,6 @@ static int btmrvl_send_frame(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -436,13 +436,6 @@ static int btmrvl_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
BT_DBG("type=%d, len=%d", skb->pkt_type, skb->len); BT_DBG("type=%d, len=%d", skb->pkt_type, skb->len);
if (!test_bit(HCI_RUNNING, &hdev->flags)) {
BT_ERR("Failed testing HCI_RUNING, flags=%lx", hdev->flags);
print_hex_dump_bytes("data: ", DUMP_PREFIX_OFFSET,
skb->data, skb->len);
return -EBUSY;
}
switch (bt_cb(skb)->pkt_type) { switch (bt_cb(skb)->pkt_type) {
case HCI_COMMAND_PKT: case HCI_COMMAND_PKT:
hdev->stat.cmd_tx++; hdev->stat.cmd_tx++;
...@@ -477,9 +470,6 @@ static int btmrvl_close(struct hci_dev *hdev) ...@@ -477,9 +470,6 @@ static int btmrvl_close(struct hci_dev *hdev)
{ {
struct btmrvl_private *priv = hci_get_drvdata(hdev); struct btmrvl_private *priv = hci_get_drvdata(hdev);
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
return 0;
skb_queue_purge(&priv->adapter->tx_queue); skb_queue_purge(&priv->adapter->tx_queue);
return 0; return 0;
...@@ -487,8 +477,6 @@ static int btmrvl_close(struct hci_dev *hdev) ...@@ -487,8 +477,6 @@ static int btmrvl_close(struct hci_dev *hdev)
static int btmrvl_open(struct hci_dev *hdev) static int btmrvl_open(struct hci_dev *hdev)
{ {
set_bit(HCI_RUNNING, &hdev->flags);
return 0; return 0;
} }
......
...@@ -146,6 +146,29 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_8897 = { ...@@ -146,6 +146,29 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_8897 = {
.fw_dump_end = 0xea, .fw_dump_end = 0xea,
}; };
static const struct btmrvl_sdio_card_reg btmrvl_reg_8997 = {
.cfg = 0x00,
.host_int_mask = 0x08,
.host_intstatus = 0x0c,
.card_status = 0x5c,
.sq_read_base_addr_a0 = 0xf8,
.sq_read_base_addr_a1 = 0xf9,
.card_revision = 0xc8,
.card_fw_status0 = 0xe8,
.card_fw_status1 = 0xe9,
.card_rx_len = 0xea,
.card_rx_unit = 0xeb,
.io_port_0 = 0xe4,
.io_port_1 = 0xe5,
.io_port_2 = 0xe6,
.int_read_to_clear = true,
.host_int_rsr = 0x04,
.card_misc_cfg = 0xD8,
.fw_dump_ctrl = 0xf0,
.fw_dump_start = 0xf1,
.fw_dump_end = 0xf8,
};
static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = { static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
.helper = "mrvl/sd8688_helper.bin", .helper = "mrvl/sd8688_helper.bin",
.firmware = "mrvl/sd8688.bin", .firmware = "mrvl/sd8688.bin",
...@@ -191,25 +214,37 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = { ...@@ -191,25 +214,37 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = {
.supports_fw_dump = true, .supports_fw_dump = true,
}; };
static const struct btmrvl_sdio_device btmrvl_sdio_sd8997 = {
.helper = NULL,
.firmware = "mrvl/sd8997_uapsta.bin",
.reg = &btmrvl_reg_8997,
.support_pscan_win_report = true,
.sd_blksz_fw_dl = 256,
.supports_fw_dump = true,
};
static const struct sdio_device_id btmrvl_sdio_ids[] = { static const struct sdio_device_id btmrvl_sdio_ids[] = {
/* Marvell SD8688 Bluetooth device */ /* Marvell SD8688 Bluetooth device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9105), { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9105),
.driver_data = (unsigned long) &btmrvl_sdio_sd8688 }, .driver_data = (unsigned long)&btmrvl_sdio_sd8688 },
/* Marvell SD8787 Bluetooth device */ /* Marvell SD8787 Bluetooth device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911A), { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911A),
.driver_data = (unsigned long) &btmrvl_sdio_sd8787 }, .driver_data = (unsigned long)&btmrvl_sdio_sd8787 },
/* Marvell SD8787 Bluetooth AMP device */ /* Marvell SD8787 Bluetooth AMP device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911B), { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911B),
.driver_data = (unsigned long) &btmrvl_sdio_sd8787 }, .driver_data = (unsigned long)&btmrvl_sdio_sd8787 },
/* Marvell SD8797 Bluetooth device */ /* Marvell SD8797 Bluetooth device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912A), { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912A),
.driver_data = (unsigned long) &btmrvl_sdio_sd8797 }, .driver_data = (unsigned long)&btmrvl_sdio_sd8797 },
/* Marvell SD8887 Bluetooth device */ /* Marvell SD8887 Bluetooth device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9136), { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9136),
.driver_data = (unsigned long)&btmrvl_sdio_sd8887 }, .driver_data = (unsigned long)&btmrvl_sdio_sd8887 },
/* Marvell SD8897 Bluetooth device */ /* Marvell SD8897 Bluetooth device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912E), { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912E),
.driver_data = (unsigned long) &btmrvl_sdio_sd8897 }, .driver_data = (unsigned long)&btmrvl_sdio_sd8897 },
/* Marvell SD8997 Bluetooth device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9142),
.driver_data = (unsigned long)&btmrvl_sdio_sd8997 },
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
...@@ -619,7 +654,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv) ...@@ -619,7 +654,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
/* Allocate buffer */ /* Allocate buffer */
skb = bt_skb_alloc(num_blocks * blksz + BTSDIO_DMA_ALIGN, GFP_ATOMIC); skb = bt_skb_alloc(num_blocks * blksz + BTSDIO_DMA_ALIGN, GFP_ATOMIC);
if (skb == NULL) { if (!skb) {
BT_ERR("No free skb"); BT_ERR("No free skb");
ret = -ENOMEM; ret = -ENOMEM;
goto exit; goto exit;
...@@ -1278,6 +1313,12 @@ static void btmrvl_sdio_dump_firmware(struct btmrvl_private *priv) ...@@ -1278,6 +1313,12 @@ static void btmrvl_sdio_dump_firmware(struct btmrvl_private *priv)
if (memory_size == 0) { if (memory_size == 0) {
BT_INFO("Firmware dump finished!"); BT_INFO("Firmware dump finished!");
sdio_writeb(card->func, FW_DUMP_READ_DONE,
card->reg->fw_dump_ctrl, &ret);
if (ret) {
BT_ERR("SDIO Write MEMDUMP_FINISH ERR");
goto done;
}
break; break;
} }
...@@ -1616,3 +1657,4 @@ MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin"); ...@@ -1616,3 +1657,4 @@ MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin"); MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin");
MODULE_FIRMWARE("mrvl/sd8887_uapsta.bin"); MODULE_FIRMWARE("mrvl/sd8887_uapsta.bin");
MODULE_FIRMWARE("mrvl/sd8897_uapsta.bin"); MODULE_FIRMWARE("mrvl/sd8897_uapsta.bin");
MODULE_FIRMWARE("mrvl/sd8997_uapsta.bin");
...@@ -194,21 +194,15 @@ static int btsdio_open(struct hci_dev *hdev) ...@@ -194,21 +194,15 @@ static int btsdio_open(struct hci_dev *hdev)
BT_DBG("%s", hdev->name); BT_DBG("%s", hdev->name);
if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
return 0;
sdio_claim_host(data->func); sdio_claim_host(data->func);
err = sdio_enable_func(data->func); err = sdio_enable_func(data->func);
if (err < 0) { if (err < 0)
clear_bit(HCI_RUNNING, &hdev->flags);
goto release; goto release;
}
err = sdio_claim_irq(data->func, btsdio_interrupt); err = sdio_claim_irq(data->func, btsdio_interrupt);
if (err < 0) { if (err < 0) {
sdio_disable_func(data->func); sdio_disable_func(data->func);
clear_bit(HCI_RUNNING, &hdev->flags);
goto release; goto release;
} }
...@@ -229,9 +223,6 @@ static int btsdio_close(struct hci_dev *hdev) ...@@ -229,9 +223,6 @@ static int btsdio_close(struct hci_dev *hdev)
BT_DBG("%s", hdev->name); BT_DBG("%s", hdev->name);
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
return 0;
sdio_claim_host(data->func); sdio_claim_host(data->func);
sdio_writeb(data->func, 0x00, REG_EN_INTRD, NULL); sdio_writeb(data->func, 0x00, REG_EN_INTRD, NULL);
...@@ -261,9 +252,6 @@ static int btsdio_send_frame(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -261,9 +252,6 @@ static int btsdio_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
BT_DBG("%s", hdev->name); BT_DBG("%s", hdev->name);
if (!test_bit(HCI_RUNNING, &hdev->flags))
return -EBUSY;
switch (bt_cb(skb)->pkt_type) { switch (bt_cb(skb)->pkt_type) {
case HCI_COMMAND_PKT: case HCI_COMMAND_PKT:
hdev->stat.cmd_tx++; hdev->stat.cmd_tx++;
......
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
#include <linux/serial.h> #include <linux/serial.h>
#include <linux/serial_reg.h> #include <linux/serial_reg.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <asm/io.h> #include <linux/io.h>
#include <pcmcia/cistpl.h> #include <pcmcia/cistpl.h>
#include <pcmcia/ciscode.h> #include <pcmcia/ciscode.h>
...@@ -188,7 +188,7 @@ static void btuart_receive(struct btuart_info *info) ...@@ -188,7 +188,7 @@ static void btuart_receive(struct btuart_info *info)
info->hdev->stat.byte_rx++; info->hdev->stat.byte_rx++;
/* Allocate packet */ /* Allocate packet */
if (info->rx_skb == NULL) { if (!info->rx_skb) {
info->rx_state = RECV_WAIT_PACKET_TYPE; info->rx_state = RECV_WAIT_PACKET_TYPE;
info->rx_count = 0; info->rx_count = 0;
info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC); info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
...@@ -223,7 +223,6 @@ static void btuart_receive(struct btuart_info *info) ...@@ -223,7 +223,6 @@ static void btuart_receive(struct btuart_info *info)
/* Unknown packet */ /* Unknown packet */
BT_ERR("Unknown HCI packet with type 0x%02x received", bt_cb(info->rx_skb)->pkt_type); BT_ERR("Unknown HCI packet with type 0x%02x received", bt_cb(info->rx_skb)->pkt_type);
info->hdev->stat.err_rx++; info->hdev->stat.err_rx++;
clear_bit(HCI_RUNNING, &(info->hdev->flags));
kfree_skb(info->rx_skb); kfree_skb(info->rx_skb);
info->rx_skb = NULL; info->rx_skb = NULL;
...@@ -409,17 +408,12 @@ static int btuart_hci_flush(struct hci_dev *hdev) ...@@ -409,17 +408,12 @@ static int btuart_hci_flush(struct hci_dev *hdev)
static int btuart_hci_open(struct hci_dev *hdev) static int btuart_hci_open(struct hci_dev *hdev)
{ {
set_bit(HCI_RUNNING, &(hdev->flags));
return 0; return 0;
} }
static int btuart_hci_close(struct hci_dev *hdev) static int btuart_hci_close(struct hci_dev *hdev)
{ {
if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags)))
return 0;
btuart_hci_flush(hdev); btuart_hci_flush(hdev);
return 0; return 0;
......
...@@ -940,9 +940,6 @@ static int btusb_open(struct hci_dev *hdev) ...@@ -940,9 +940,6 @@ static int btusb_open(struct hci_dev *hdev)
data->intf->needs_remote_wakeup = 1; data->intf->needs_remote_wakeup = 1;
if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
goto done;
if (test_and_set_bit(BTUSB_INTR_RUNNING, &data->flags)) if (test_and_set_bit(BTUSB_INTR_RUNNING, &data->flags))
goto done; goto done;
...@@ -965,7 +962,6 @@ static int btusb_open(struct hci_dev *hdev) ...@@ -965,7 +962,6 @@ static int btusb_open(struct hci_dev *hdev)
failed: failed:
clear_bit(BTUSB_INTR_RUNNING, &data->flags); clear_bit(BTUSB_INTR_RUNNING, &data->flags);
clear_bit(HCI_RUNNING, &hdev->flags);
usb_autopm_put_interface(data->intf); usb_autopm_put_interface(data->intf);
return err; return err;
} }
...@@ -984,9 +980,6 @@ static int btusb_close(struct hci_dev *hdev) ...@@ -984,9 +980,6 @@ static int btusb_close(struct hci_dev *hdev)
BT_DBG("%s", hdev->name); BT_DBG("%s", hdev->name);
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
return 0;
cancel_work_sync(&data->work); cancel_work_sync(&data->work);
cancel_work_sync(&data->waker); cancel_work_sync(&data->waker);
...@@ -1156,9 +1149,6 @@ static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -1156,9 +1149,6 @@ static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
BT_DBG("%s", hdev->name); BT_DBG("%s", hdev->name);
if (!test_bit(HCI_RUNNING, &hdev->flags))
return -EBUSY;
switch (bt_cb(skb)->pkt_type) { switch (bt_cb(skb)->pkt_type) {
case HCI_COMMAND_PKT: case HCI_COMMAND_PKT:
urb = alloc_ctrl_urb(hdev, skb); urb = alloc_ctrl_urb(hdev, skb);
...@@ -1843,9 +1833,6 @@ static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -1843,9 +1833,6 @@ static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb)
BT_DBG("%s", hdev->name); BT_DBG("%s", hdev->name);
if (!test_bit(HCI_RUNNING, &hdev->flags))
return -EBUSY;
switch (bt_cb(skb)->pkt_type) { switch (bt_cb(skb)->pkt_type) {
case HCI_COMMAND_PKT: case HCI_COMMAND_PKT:
if (test_bit(BTUSB_BOOTLOADER, &data->flags)) { if (test_bit(BTUSB_BOOTLOADER, &data->flags)) {
......
...@@ -155,9 +155,6 @@ static int ti_st_open(struct hci_dev *hdev) ...@@ -155,9 +155,6 @@ static int ti_st_open(struct hci_dev *hdev)
BT_DBG("%s %p", hdev->name, hdev); BT_DBG("%s %p", hdev->name, hdev);
if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
return -EBUSY;
/* provide contexts for callbacks from ST */ /* provide contexts for callbacks from ST */
hst = hci_get_drvdata(hdev); hst = hci_get_drvdata(hdev);
...@@ -181,7 +178,6 @@ static int ti_st_open(struct hci_dev *hdev) ...@@ -181,7 +178,6 @@ static int ti_st_open(struct hci_dev *hdev)
goto done; goto done;
if (err != -EINPROGRESS) { if (err != -EINPROGRESS) {
clear_bit(HCI_RUNNING, &hdev->flags);
BT_ERR("st_register failed %d", err); BT_ERR("st_register failed %d", err);
return err; return err;
} }
...@@ -195,7 +191,6 @@ static int ti_st_open(struct hci_dev *hdev) ...@@ -195,7 +191,6 @@ static int ti_st_open(struct hci_dev *hdev)
(&hst->wait_reg_completion, (&hst->wait_reg_completion,
msecs_to_jiffies(BT_REGISTER_TIMEOUT)); msecs_to_jiffies(BT_REGISTER_TIMEOUT));
if (!timeleft) { if (!timeleft) {
clear_bit(HCI_RUNNING, &hdev->flags);
BT_ERR("Timeout(%d sec),didn't get reg " BT_ERR("Timeout(%d sec),didn't get reg "
"completion signal from ST", "completion signal from ST",
BT_REGISTER_TIMEOUT / 1000); BT_REGISTER_TIMEOUT / 1000);
...@@ -205,7 +200,6 @@ static int ti_st_open(struct hci_dev *hdev) ...@@ -205,7 +200,6 @@ static int ti_st_open(struct hci_dev *hdev)
/* Is ST registration callback /* Is ST registration callback
* called with ERROR status? */ * called with ERROR status? */
if (hst->reg_status != 0) { if (hst->reg_status != 0) {
clear_bit(HCI_RUNNING, &hdev->flags);
BT_ERR("ST registration completed with invalid " BT_ERR("ST registration completed with invalid "
"status %d", hst->reg_status); "status %d", hst->reg_status);
return -EAGAIN; return -EAGAIN;
...@@ -215,7 +209,6 @@ static int ti_st_open(struct hci_dev *hdev) ...@@ -215,7 +209,6 @@ static int ti_st_open(struct hci_dev *hdev)
hst->st_write = ti_st_proto[i].write; hst->st_write = ti_st_proto[i].write;
if (!hst->st_write) { if (!hst->st_write) {
BT_ERR("undefined ST write function"); BT_ERR("undefined ST write function");
clear_bit(HCI_RUNNING, &hdev->flags);
for (i = 0; i < MAX_BT_CHNL_IDS; i++) { for (i = 0; i < MAX_BT_CHNL_IDS; i++) {
/* Undo registration with ST */ /* Undo registration with ST */
err = st_unregister(&ti_st_proto[i]); err = st_unregister(&ti_st_proto[i]);
...@@ -236,9 +229,6 @@ static int ti_st_close(struct hci_dev *hdev) ...@@ -236,9 +229,6 @@ static int ti_st_close(struct hci_dev *hdev)
int err, i; int err, i;
struct ti_st *hst = hci_get_drvdata(hdev); struct ti_st *hst = hci_get_drvdata(hdev);
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
return 0;
for (i = MAX_BT_CHNL_IDS-1; i >= 0; i--) { for (i = MAX_BT_CHNL_IDS-1; i >= 0; i--) {
err = st_unregister(&ti_st_proto[i]); err = st_unregister(&ti_st_proto[i]);
if (err) if (err)
...@@ -256,9 +246,6 @@ static int ti_st_send_frame(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -256,9 +246,6 @@ static int ti_st_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
struct ti_st *hst; struct ti_st *hst;
long len; long len;
if (!test_bit(HCI_RUNNING, &hdev->flags))
return -EBUSY;
hst = hci_get_drvdata(hdev); hst = hci_get_drvdata(hdev);
/* Prepend skb with frame type */ /* Prepend skb with frame type */
......
...@@ -357,8 +357,6 @@ static irqreturn_t dtl1_interrupt(int irq, void *dev_inst) ...@@ -357,8 +357,6 @@ static irqreturn_t dtl1_interrupt(int irq, void *dev_inst)
static int dtl1_hci_open(struct hci_dev *hdev) static int dtl1_hci_open(struct hci_dev *hdev)
{ {
set_bit(HCI_RUNNING, &(hdev->flags));
return 0; return 0;
} }
...@@ -376,9 +374,6 @@ static int dtl1_hci_flush(struct hci_dev *hdev) ...@@ -376,9 +374,6 @@ static int dtl1_hci_flush(struct hci_dev *hdev)
static int dtl1_hci_close(struct hci_dev *hdev) static int dtl1_hci_close(struct hci_dev *hdev)
{ {
if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags)))
return 0;
dtl1_hci_flush(hdev); dtl1_hci_flush(hdev);
return 0; return 0;
......
...@@ -32,6 +32,8 @@ ...@@ -32,6 +32,8 @@
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include <linux/tty.h> #include <linux/tty.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/dmi.h>
#include <linux/pm_runtime.h>
#include <net/bluetooth/bluetooth.h> #include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h> #include <net/bluetooth/hci_core.h>
...@@ -39,6 +41,11 @@ ...@@ -39,6 +41,11 @@
#include "btbcm.h" #include "btbcm.h"
#include "hci_uart.h" #include "hci_uart.h"
#define BCM_LM_DIAG_PKT 0x07
#define BCM_LM_DIAG_SIZE 63
#define BCM_AUTOSUSPEND_DELAY 5000 /* default autosleep delay */
struct bcm_device { struct bcm_device {
struct list_head list; struct list_head list;
...@@ -55,7 +62,7 @@ struct bcm_device { ...@@ -55,7 +62,7 @@ struct bcm_device {
int irq; int irq;
u8 irq_polarity; u8 irq_polarity;
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM
struct hci_uart *hu; struct hci_uart *hu;
bool is_suspended; /* suspend/resume flag */ bool is_suspended; /* suspend/resume flag */
#endif #endif
...@@ -152,13 +159,17 @@ static int bcm_gpio_set_power(struct bcm_device *dev, bool powered) ...@@ -152,13 +159,17 @@ static int bcm_gpio_set_power(struct bcm_device *dev, bool powered)
return 0; return 0;
} }
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM
static irqreturn_t bcm_host_wake(int irq, void *data) static irqreturn_t bcm_host_wake(int irq, void *data)
{ {
struct bcm_device *bdev = data; struct bcm_device *bdev = data;
bt_dev_dbg(bdev, "Host wake IRQ"); bt_dev_dbg(bdev, "Host wake IRQ");
pm_runtime_get(&bdev->pdev->dev);
pm_runtime_mark_last_busy(&bdev->pdev->dev);
pm_runtime_put_autosuspend(&bdev->pdev->dev);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -182,6 +193,12 @@ static int bcm_request_irq(struct bcm_data *bcm) ...@@ -182,6 +193,12 @@ static int bcm_request_irq(struct bcm_data *bcm)
goto unlock; goto unlock;
device_init_wakeup(&bdev->pdev->dev, true); device_init_wakeup(&bdev->pdev->dev, true);
pm_runtime_set_autosuspend_delay(&bdev->pdev->dev,
BCM_AUTOSUSPEND_DELAY);
pm_runtime_use_autosuspend(&bdev->pdev->dev);
pm_runtime_set_active(&bdev->pdev->dev);
pm_runtime_enable(&bdev->pdev->dev);
} }
unlock: unlock:
...@@ -197,7 +214,7 @@ static const struct bcm_set_sleep_mode default_sleep_params = { ...@@ -197,7 +214,7 @@ static const struct bcm_set_sleep_mode default_sleep_params = {
.bt_wake_active = 1, /* BT_WAKE active mode: 1 = high, 0 = low */ .bt_wake_active = 1, /* BT_WAKE active mode: 1 = high, 0 = low */
.host_wake_active = 0, /* HOST_WAKE active mode: 1 = high, 0 = low */ .host_wake_active = 0, /* HOST_WAKE active mode: 1 = high, 0 = low */
.allow_host_sleep = 1, /* Allow host sleep in SCO flag */ .allow_host_sleep = 1, /* Allow host sleep in SCO flag */
.combine_modes = 0, /* Combine sleep and LPM flag */ .combine_modes = 1, /* Combine sleep and LPM flag */
.tristate_control = 0, /* Allow tri-state control of UART tx flag */ .tristate_control = 0, /* Allow tri-state control of UART tx flag */
/* Irrelevant USB flags */ /* Irrelevant USB flags */
.usb_auto_sleep = 0, .usb_auto_sleep = 0,
...@@ -232,6 +249,29 @@ static inline int bcm_request_irq(struct bcm_data *bcm) { return 0; } ...@@ -232,6 +249,29 @@ static inline int bcm_request_irq(struct bcm_data *bcm) { return 0; }
static inline int bcm_setup_sleep(struct hci_uart *hu) { return 0; } static inline int bcm_setup_sleep(struct hci_uart *hu) { return 0; }
#endif #endif
static int bcm_set_diag(struct hci_dev *hdev, bool enable)
{
struct hci_uart *hu = hci_get_drvdata(hdev);
struct bcm_data *bcm = hu->priv;
struct sk_buff *skb;
if (!test_bit(HCI_RUNNING, &hdev->flags))
return -ENETDOWN;
skb = bt_skb_alloc(3, GFP_KERNEL);
if (IS_ERR(skb))
return PTR_ERR(skb);
*skb_put(skb, 1) = BCM_LM_DIAG_PKT;
*skb_put(skb, 1) = 0xf0;
*skb_put(skb, 1) = enable;
skb_queue_tail(&bcm->txq, skb);
hci_uart_tx_wakeup(hu);
return 0;
}
static int bcm_open(struct hci_uart *hu) static int bcm_open(struct hci_uart *hu)
{ {
struct bcm_data *bcm; struct bcm_data *bcm;
...@@ -258,7 +298,7 @@ static int bcm_open(struct hci_uart *hu) ...@@ -258,7 +298,7 @@ static int bcm_open(struct hci_uart *hu)
if (hu->tty->dev->parent == dev->pdev->dev.parent) { if (hu->tty->dev->parent == dev->pdev->dev.parent) {
bcm->dev = dev; bcm->dev = dev;
hu->init_speed = dev->init_speed; hu->init_speed = dev->init_speed;
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM
dev->hu = hu; dev->hu = hu;
#endif #endif
bcm_gpio_set_power(bcm->dev, true); bcm_gpio_set_power(bcm->dev, true);
...@@ -282,7 +322,10 @@ static int bcm_close(struct hci_uart *hu) ...@@ -282,7 +322,10 @@ static int bcm_close(struct hci_uart *hu)
mutex_lock(&bcm_device_lock); mutex_lock(&bcm_device_lock);
if (bcm_device_exists(bdev)) { if (bcm_device_exists(bdev)) {
bcm_gpio_set_power(bdev, false); bcm_gpio_set_power(bdev, false);
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM
pm_runtime_disable(&bdev->pdev->dev);
pm_runtime_set_suspended(&bdev->pdev->dev);
if (device_can_wakeup(&bdev->pdev->dev)) { if (device_can_wakeup(&bdev->pdev->dev)) {
devm_free_irq(&bdev->pdev->dev, bdev->irq, bdev); devm_free_irq(&bdev->pdev->dev, bdev->irq, bdev);
device_init_wakeup(&bdev->pdev->dev, false); device_init_wakeup(&bdev->pdev->dev, false);
...@@ -322,6 +365,7 @@ static int bcm_setup(struct hci_uart *hu) ...@@ -322,6 +365,7 @@ static int bcm_setup(struct hci_uart *hu)
bt_dev_dbg(hu->hdev, "hu %p", hu); bt_dev_dbg(hu->hdev, "hu %p", hu);
hu->hdev->set_diag = bcm_set_diag;
hu->hdev->set_bdaddr = btbcm_set_bdaddr; hu->hdev->set_bdaddr = btbcm_set_bdaddr;
err = btbcm_initialize(hu->hdev, fw_name, sizeof(fw_name)); err = btbcm_initialize(hu->hdev, fw_name, sizeof(fw_name));
...@@ -379,10 +423,18 @@ static int bcm_setup(struct hci_uart *hu) ...@@ -379,10 +423,18 @@ static int bcm_setup(struct hci_uart *hu)
return err; return err;
} }
#define BCM_RECV_LM_DIAG \
.type = BCM_LM_DIAG_PKT, \
.hlen = BCM_LM_DIAG_SIZE, \
.loff = 0, \
.lsize = 0, \
.maxlen = BCM_LM_DIAG_SIZE
static const struct h4_recv_pkt bcm_recv_pkts[] = { static const struct h4_recv_pkt bcm_recv_pkts[] = {
{ H4_RECV_ACL, .recv = hci_recv_frame }, { H4_RECV_ACL, .recv = hci_recv_frame },
{ H4_RECV_SCO, .recv = hci_recv_frame }, { H4_RECV_SCO, .recv = hci_recv_frame },
{ H4_RECV_EVENT, .recv = hci_recv_frame }, { H4_RECV_EVENT, .recv = hci_recv_frame },
{ BCM_RECV_LM_DIAG, .recv = hci_recv_diag },
}; };
static int bcm_recv(struct hci_uart *hu, const void *data, int count) static int bcm_recv(struct hci_uart *hu, const void *data, int count)
...@@ -399,6 +451,15 @@ static int bcm_recv(struct hci_uart *hu, const void *data, int count) ...@@ -399,6 +451,15 @@ static int bcm_recv(struct hci_uart *hu, const void *data, int count)
bt_dev_err(hu->hdev, "Frame reassembly failed (%d)", err); bt_dev_err(hu->hdev, "Frame reassembly failed (%d)", err);
bcm->rx_skb = NULL; bcm->rx_skb = NULL;
return err; return err;
} else if (!bcm->rx_skb) {
/* Delay auto-suspend when receiving completed packet */
mutex_lock(&bcm_device_lock);
if (bcm->dev && bcm_device_exists(bcm->dev)) {
pm_runtime_get(&bcm->dev->pdev->dev);
pm_runtime_mark_last_busy(&bcm->dev->pdev->dev);
pm_runtime_put_autosuspend(&bcm->dev->pdev->dev);
}
mutex_unlock(&bcm_device_lock);
} }
return count; return count;
...@@ -420,28 +481,40 @@ static int bcm_enqueue(struct hci_uart *hu, struct sk_buff *skb) ...@@ -420,28 +481,40 @@ static int bcm_enqueue(struct hci_uart *hu, struct sk_buff *skb)
static struct sk_buff *bcm_dequeue(struct hci_uart *hu) static struct sk_buff *bcm_dequeue(struct hci_uart *hu)
{ {
struct bcm_data *bcm = hu->priv; struct bcm_data *bcm = hu->priv;
struct sk_buff *skb = NULL;
struct bcm_device *bdev = NULL;
mutex_lock(&bcm_device_lock);
if (bcm_device_exists(bcm->dev)) {
bdev = bcm->dev;
pm_runtime_get_sync(&bdev->pdev->dev);
/* Shall be resumed here */
}
skb = skb_dequeue(&bcm->txq);
if (bdev) {
pm_runtime_mark_last_busy(&bdev->pdev->dev);
pm_runtime_put_autosuspend(&bdev->pdev->dev);
}
return skb_dequeue(&bcm->txq); mutex_unlock(&bcm_device_lock);
return skb;
} }
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM
/* Platform suspend callback */ static int bcm_suspend_device(struct device *dev)
static int bcm_suspend(struct device *dev)
{ {
struct bcm_device *bdev = platform_get_drvdata(to_platform_device(dev)); struct bcm_device *bdev = platform_get_drvdata(to_platform_device(dev));
int error;
bt_dev_dbg(bdev, "suspend: is_suspended %d", bdev->is_suspended);
mutex_lock(&bcm_device_lock);
if (!bdev->hu) bt_dev_dbg(bdev, "");
goto unlock;
if (!bdev->is_suspended) { if (!bdev->is_suspended && bdev->hu) {
hci_uart_set_flow_control(bdev->hu, true); hci_uart_set_flow_control(bdev->hu, true);
/* Once this callback returns, driver suspends BT via GPIO */ /* Once this returns, driver suspends BT via GPIO */
bdev->is_suspended = true; bdev->is_suspended = true;
} }
...@@ -452,6 +525,53 @@ static int bcm_suspend(struct device *dev) ...@@ -452,6 +525,53 @@ static int bcm_suspend(struct device *dev)
mdelay(15); mdelay(15);
} }
return 0;
}
static int bcm_resume_device(struct device *dev)
{
struct bcm_device *bdev = platform_get_drvdata(to_platform_device(dev));
bt_dev_dbg(bdev, "");
if (bdev->device_wakeup) {
gpiod_set_value(bdev->device_wakeup, true);
bt_dev_dbg(bdev, "resume, delaying 15 ms");
mdelay(15);
}
/* When this executes, the device has woken up already */
if (bdev->is_suspended && bdev->hu) {
bdev->is_suspended = false;
hci_uart_set_flow_control(bdev->hu, false);
}
return 0;
}
#endif
#ifdef CONFIG_PM_SLEEP
/* Platform suspend callback */
static int bcm_suspend(struct device *dev)
{
struct bcm_device *bdev = platform_get_drvdata(to_platform_device(dev));
int error;
bt_dev_dbg(bdev, "suspend: is_suspended %d", bdev->is_suspended);
/* bcm_suspend can be called at any time as long as platform device is
* bound, so it should use bcm_device_lock to protect access to hci_uart
* and device_wake-up GPIO.
*/
mutex_lock(&bcm_device_lock);
if (!bdev->hu)
goto unlock;
if (pm_runtime_active(dev))
bcm_suspend_device(dev);
if (device_may_wakeup(&bdev->pdev->dev)) { if (device_may_wakeup(&bdev->pdev->dev)) {
error = enable_irq_wake(bdev->irq); error = enable_irq_wake(bdev->irq);
if (!error) if (!error)
...@@ -471,6 +591,10 @@ static int bcm_resume(struct device *dev) ...@@ -471,6 +591,10 @@ static int bcm_resume(struct device *dev)
bt_dev_dbg(bdev, "resume: is_suspended %d", bdev->is_suspended); bt_dev_dbg(bdev, "resume: is_suspended %d", bdev->is_suspended);
/* bcm_resume can be called at any time as long as platform device is
* bound, so it should use bcm_device_lock to protect access to hci_uart
* and device_wake-up GPIO.
*/
mutex_lock(&bcm_device_lock); mutex_lock(&bcm_device_lock);
if (!bdev->hu) if (!bdev->hu)
...@@ -481,22 +605,15 @@ static int bcm_resume(struct device *dev) ...@@ -481,22 +605,15 @@ static int bcm_resume(struct device *dev)
bt_dev_dbg(bdev, "BCM irq: disabled"); bt_dev_dbg(bdev, "BCM irq: disabled");
} }
if (bdev->device_wakeup) { bcm_resume_device(dev);
gpiod_set_value(bdev->device_wakeup, true);
bt_dev_dbg(bdev, "resume, delaying 15 ms");
mdelay(15);
}
/* When this callback executes, the device has woken up already */
if (bdev->is_suspended) {
bdev->is_suspended = false;
hci_uart_set_flow_control(bdev->hu, false);
}
unlock: unlock:
mutex_unlock(&bcm_device_lock); mutex_unlock(&bcm_device_lock);
pm_runtime_disable(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
return 0; return 0;
} }
#endif #endif
...@@ -513,6 +630,22 @@ static const struct acpi_gpio_mapping acpi_bcm_default_gpios[] = { ...@@ -513,6 +630,22 @@ static const struct acpi_gpio_mapping acpi_bcm_default_gpios[] = {
}; };
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
static u8 acpi_active_low = ACPI_ACTIVE_LOW;
/* IRQ polarity of some chipsets are not defined correctly in ACPI table. */
static const struct dmi_system_id bcm_wrong_irq_dmi_table[] = {
{
.ident = "Asus T100TA",
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR,
"ASUSTeK COMPUTER INC."),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TA"),
},
.driver_data = &acpi_active_low,
},
{ }
};
static int bcm_resource(struct acpi_resource *ares, void *data) static int bcm_resource(struct acpi_resource *ares, void *data)
{ {
struct bcm_device *dev = data; struct bcm_device *dev = data;
...@@ -549,15 +682,10 @@ static int bcm_resource(struct acpi_resource *ares, void *data) ...@@ -549,15 +682,10 @@ static int bcm_resource(struct acpi_resource *ares, void *data)
static int bcm_acpi_probe(struct bcm_device *dev) static int bcm_acpi_probe(struct bcm_device *dev)
{ {
struct platform_device *pdev = dev->pdev; struct platform_device *pdev = dev->pdev;
const struct acpi_device_id *id;
struct acpi_device *adev;
LIST_HEAD(resources); LIST_HEAD(resources);
const struct dmi_system_id *dmi_id;
int ret; int ret;
id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);
if (!id)
return -ENODEV;
/* Retrieve GPIO data */ /* Retrieve GPIO data */
dev->name = dev_name(&pdev->dev); dev->name = dev_name(&pdev->dev);
ret = acpi_dev_add_driver_gpios(ACPI_COMPANION(&pdev->dev), ret = acpi_dev_add_driver_gpios(ACPI_COMPANION(&pdev->dev),
...@@ -602,11 +730,18 @@ static int bcm_acpi_probe(struct bcm_device *dev) ...@@ -602,11 +730,18 @@ static int bcm_acpi_probe(struct bcm_device *dev)
} }
/* Retrieve UART ACPI info */ /* Retrieve UART ACPI info */
adev = ACPI_COMPANION(&dev->pdev->dev); ret = acpi_dev_get_resources(ACPI_COMPANION(&dev->pdev->dev),
if (!adev) &resources, bcm_resource, dev);
return 0; if (ret < 0)
return ret;
acpi_dev_free_resource_list(&resources);
acpi_dev_get_resources(adev, &resources, bcm_resource, dev); dmi_id = dmi_first_match(bcm_wrong_irq_dmi_table);
if (dmi_id) {
bt_dev_warn(dev, "%s: Overwriting IRQ polarity to active low",
dmi_id->ident);
dev->irq_polarity = *(u8 *)dmi_id->driver_data;
}
return 0; return 0;
} }
...@@ -620,7 +755,6 @@ static int bcm_acpi_probe(struct bcm_device *dev) ...@@ -620,7 +755,6 @@ static int bcm_acpi_probe(struct bcm_device *dev)
static int bcm_probe(struct platform_device *pdev) static int bcm_probe(struct platform_device *pdev)
{ {
struct bcm_device *dev; struct bcm_device *dev;
struct acpi_device_id *pdata = pdev->dev.platform_data;
int ret; int ret;
dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
...@@ -629,15 +763,9 @@ static int bcm_probe(struct platform_device *pdev) ...@@ -629,15 +763,9 @@ static int bcm_probe(struct platform_device *pdev)
dev->pdev = pdev; dev->pdev = pdev;
if (ACPI_HANDLE(&pdev->dev)) { ret = bcm_acpi_probe(dev);
ret = bcm_acpi_probe(dev); if (ret)
if (ret) return ret;
return ret;
} else if (pdata) {
dev->name = pdata->id;
} else {
return -ENODEV;
}
platform_set_drvdata(pdev, dev); platform_set_drvdata(pdev, dev);
...@@ -693,7 +821,10 @@ MODULE_DEVICE_TABLE(acpi, bcm_acpi_match); ...@@ -693,7 +821,10 @@ MODULE_DEVICE_TABLE(acpi, bcm_acpi_match);
#endif #endif
/* Platform suspend and resume callbacks */ /* Platform suspend and resume callbacks */
static SIMPLE_DEV_PM_OPS(bcm_pm_ops, bcm_suspend, bcm_resume); static const struct dev_pm_ops bcm_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(bcm_suspend, bcm_resume)
SET_RUNTIME_PM_OPS(bcm_suspend_device, bcm_resume_device, NULL)
};
static struct platform_driver bcm_driver = { static struct platform_driver bcm_driver = {
.probe = bcm_probe, .probe = bcm_probe,
......
...@@ -266,3 +266,4 @@ struct sk_buff *h4_recv_buf(struct hci_dev *hdev, struct sk_buff *skb, ...@@ -266,3 +266,4 @@ struct sk_buff *h4_recv_buf(struct hci_dev *hdev, struct sk_buff *skb,
return skb; return skb;
} }
EXPORT_SYMBOL_GPL(h4_recv_buf);
...@@ -128,7 +128,7 @@ static void h5_timed_event(unsigned long arg) ...@@ -128,7 +128,7 @@ static void h5_timed_event(unsigned long arg)
{ {
const unsigned char sync_req[] = { 0x01, 0x7e }; const unsigned char sync_req[] = { 0x01, 0x7e };
unsigned char conf_req[] = { 0x03, 0xfc, 0x01 }; unsigned char conf_req[] = { 0x03, 0xfc, 0x01 };
struct hci_uart *hu = (struct hci_uart *) arg; struct hci_uart *hu = (struct hci_uart *)arg;
struct h5 *h5 = hu->priv; struct h5 *h5 = hu->priv;
struct sk_buff *skb; struct sk_buff *skb;
unsigned long flags; unsigned long flags;
...@@ -210,7 +210,7 @@ static int h5_open(struct hci_uart *hu) ...@@ -210,7 +210,7 @@ static int h5_open(struct hci_uart *hu)
init_timer(&h5->timer); init_timer(&h5->timer);
h5->timer.function = h5_timed_event; h5->timer.function = h5_timed_event;
h5->timer.data = (unsigned long) hu; h5->timer.data = (unsigned long)hu;
h5->tx_win = H5_TX_WIN_MAX; h5->tx_win = H5_TX_WIN_MAX;
...@@ -453,7 +453,7 @@ static int h5_rx_pkt_start(struct hci_uart *hu, unsigned char c) ...@@ -453,7 +453,7 @@ static int h5_rx_pkt_start(struct hci_uart *hu, unsigned char c)
return -ENOMEM; return -ENOMEM;
} }
h5->rx_skb->dev = (void *) hu->hdev; h5->rx_skb->dev = (void *)hu->hdev;
return 0; return 0;
} }
...@@ -696,7 +696,7 @@ static struct sk_buff *h5_dequeue(struct hci_uart *hu) ...@@ -696,7 +696,7 @@ static struct sk_buff *h5_dequeue(struct hci_uart *hu)
} }
skb = skb_dequeue(&h5->unrel); skb = skb_dequeue(&h5->unrel);
if (skb != NULL) { if (skb) {
nskb = h5_prepare_pkt(hu, bt_cb(skb)->pkt_type, nskb = h5_prepare_pkt(hu, bt_cb(skb)->pkt_type,
skb->data, skb->len); skb->data, skb->len);
if (nskb) { if (nskb) {
...@@ -714,7 +714,7 @@ static struct sk_buff *h5_dequeue(struct hci_uart *hu) ...@@ -714,7 +714,7 @@ static struct sk_buff *h5_dequeue(struct hci_uart *hu)
goto unlock; goto unlock;
skb = skb_dequeue(&h5->rel); skb = skb_dequeue(&h5->rel);
if (skb != NULL) { if (skb) {
nskb = h5_prepare_pkt(hu, bt_cb(skb)->pkt_type, nskb = h5_prepare_pkt(hu, bt_cb(skb)->pkt_type,
skb->data, skb->len); skb->data, skb->len);
if (nskb) { if (nskb) {
......
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