summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/bluetooth/Kconfig20
-rw-r--r--drivers/bluetooth/Makefile1
-rw-r--r--drivers/bluetooth/bcm203x.c9
-rw-r--r--drivers/bluetooth/bfusb.c11
-rw-r--r--drivers/bluetooth/bpa10x.c7
-rw-r--r--drivers/bluetooth/bt3c_cs.c8
-rw-r--r--drivers/bluetooth/btsdio.c6
-rw-r--r--drivers/bluetooth/btusb.c229
-rw-r--r--drivers/bluetooth/hci_bcsp.c5
-rw-r--r--drivers/bluetooth/hci_h4.c5
-rw-r--r--drivers/bluetooth/hci_ldisc.c9
-rw-r--r--drivers/bluetooth/hci_usb.c1136
-rw-r--r--drivers/bluetooth/hci_usb.h129
-rw-r--r--drivers/bluetooth/hci_vhci.c5
-rw-r--r--include/net/bluetooth/bluetooth.h4
-rw-r--r--include/net/bluetooth/hci.h2
-rw-r--r--net/bluetooth/af_bluetooth.c50
-rw-r--r--net/bluetooth/bnep/bnep.h2
-rw-r--r--net/bluetooth/bnep/core.c5
-rw-r--r--net/bluetooth/bnep/netdev.c5
-rw-r--r--net/bluetooth/bnep/sock.c5
-rw-r--r--net/bluetooth/cmtp/capi.c5
-rw-r--r--net/bluetooth/cmtp/core.c5
-rw-r--r--net/bluetooth/cmtp/sock.c5
-rw-r--r--net/bluetooth/hci_conn.c5
-rw-r--r--net/bluetooth/hci_core.c11
-rw-r--r--net/bluetooth/hci_event.c5
-rw-r--r--net/bluetooth/hci_sock.c5
-rw-r--r--net/bluetooth/hci_sysfs.c7
-rw-r--r--net/bluetooth/hidp/core.c5
-rw-r--r--net/bluetooth/hidp/sock.c5
-rw-r--r--net/bluetooth/l2cap.c5
-rw-r--r--net/bluetooth/rfcomm/core.c5
-rw-r--r--net/bluetooth/rfcomm/sock.c7
-rw-r--r--net/bluetooth/rfcomm/tty.c35
-rw-r--r--net/bluetooth/sco.c5
36 files changed, 209 insertions, 1559 deletions
diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
index 7cb4029..1164837 100644
--- a/drivers/bluetooth/Kconfig
+++ b/drivers/bluetooth/Kconfig
@@ -2,26 +2,6 @@
menu "Bluetooth device drivers"
depends on BT
-config BT_HCIUSB
- tristate "HCI USB driver (old version)"
- depends on USB && BT_HCIBTUSB=n
- help
- Bluetooth HCI USB driver.
- This driver is required if you want to use Bluetooth devices with
- USB interface.
-
- Say Y here to compile support for Bluetooth USB devices into the
- kernel or say M to compile it as module (hci_usb).
-
-config BT_HCIUSB_SCO
- bool "SCO (voice) support"
- depends on BT_HCIUSB
- help
- This option enables the SCO support in the HCI USB driver. You need this
- to transmit voice data with your Bluetooth USB device.
-
- Say Y here to compile support for SCO over HCI USB.
-
config BT_HCIBTUSB
tristate "HCI USB driver"
depends on USB
diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile
index 77444af..16930f9 100644
--- a/drivers/bluetooth/Makefile
+++ b/drivers/bluetooth/Makefile
@@ -2,7 +2,6 @@
# Makefile for the Linux Bluetooth HCI device drivers.
#
-obj-$(CONFIG_BT_HCIUSB) += hci_usb.o
obj-$(CONFIG_BT_HCIVHCI) += hci_vhci.o
obj-$(CONFIG_BT_HCIUART) += hci_uart.o
obj-$(CONFIG_BT_HCIBCM203X) += bcm203x.o
diff --git a/drivers/bluetooth/bcm203x.c b/drivers/bluetooth/bcm203x.c
index ee40201..eafd4af 100644
--- a/drivers/bluetooth/bcm203x.c
+++ b/drivers/bluetooth/bcm203x.c
@@ -37,11 +37,6 @@
#include <net/bluetooth/bluetooth.h>
-#ifndef CONFIG_BT_HCIBCM203X_DEBUG
-#undef BT_DBG
-#define BT_DBG(D...)
-#endif
-
#define VERSION "1.2"
static struct usb_device_id bcm203x_table[] = {
@@ -199,7 +194,7 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
return -EIO;
}
- BT_DBG("minidrv data %p size %d", firmware->data, firmware->size);
+ BT_DBG("minidrv data %p size %zu", firmware->data, firmware->size);
size = max_t(uint, firmware->size, 4096);
@@ -227,7 +222,7 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
return -EIO;
}
- BT_DBG("firmware data %p size %d", firmware->data, firmware->size);
+ BT_DBG("firmware data %p size %zu", firmware->data, firmware->size);
data->fw_data = kmalloc(firmware->size, GFP_KERNEL);
if (!data->fw_data) {
diff --git a/drivers/bluetooth/bfusb.c b/drivers/bluetooth/bfusb.c
index 90a0946..d3f14be 100644
--- a/drivers/bluetooth/bfusb.c
+++ b/drivers/bluetooth/bfusb.c
@@ -38,11 +38,6 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
-#ifndef CONFIG_BT_HCIBFUSB_DEBUG
-#undef BT_DBG
-#define BT_DBG(D...)
-#endif
-
#define VERSION "1.2"
static struct usb_driver bfusb_driver;
@@ -221,7 +216,7 @@ static int bfusb_rx_submit(struct bfusb_data *data, struct urb *urb)
struct sk_buff *skb;
int err, pipe, size = HCI_MAX_FRAME_SIZE + 32;
- BT_DBG("bfusb %p urb %p", bfusb, urb);
+ BT_DBG("bfusb %p urb %p", data, urb);
if (!urb && !(urb = usb_alloc_urb(0, GFP_ATOMIC)))
return -ENOMEM;
@@ -354,7 +349,7 @@ static void bfusb_rx_complete(struct urb *urb)
int count = urb->actual_length;
int err, hdr, len;
- BT_DBG("bfusb %p urb %p skb %p len %d", bfusb, urb, skb, skb->len);
+ BT_DBG("bfusb %p urb %p skb %p len %d", data, urb, skb, skb->len);
read_lock(&data->lock);
@@ -691,7 +686,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
goto error;
}
- BT_DBG("firmware data %p size %d", firmware->data, firmware->size);
+ BT_DBG("firmware data %p size %zu", firmware->data, firmware->size);
if (bfusb_load_firmware(data, firmware->data, firmware->size) < 0) {
BT_ERR("Firmware loading failed");
diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c
index b936d8c..c115285 100644
--- a/drivers/bluetooth/bpa10x.c
+++ b/drivers/bluetooth/bpa10x.c
@@ -35,11 +35,6 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
-#ifndef CONFIG_BT_HCIBPA10X_DEBUG
-#undef BT_DBG
-#define BT_DBG(D...)
-#endif
-
#define VERSION "0.10"
static struct usb_device_id bpa10x_table[] = {
@@ -489,6 +484,8 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *
hdev->owner = THIS_MODULE;
+ set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks);
+
err = hci_register_dev(hdev);
if (err < 0) {
hci_free_dev(hdev);
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
index b3e4d07..ff195c2 100644
--- a/drivers/bluetooth/bt3c_cs.c
+++ b/drivers/bluetooth/bt3c_cs.c
@@ -502,15 +502,15 @@ static int bt3c_load_firmware(bt3c_info_t *info, const unsigned char *firmware,
memset(b, 0, sizeof(b));
memcpy(b, ptr + 2, 2);
- size = simple_strtol(b, NULL, 16);
+ size = simple_strtoul(b, NULL, 16);
memset(b, 0, sizeof(b));
memcpy(b, ptr + 4, 8);
- addr = simple_strtol(b, NULL, 16);
+ addr = simple_strtoul(b, NULL, 16);
memset(b, 0, sizeof(b));
memcpy(b, ptr + (size * 2) + 2, 2);
- fcs = simple_strtol(b, NULL, 16);
+ fcs = simple_strtoul(b, NULL, 16);
memset(b, 0, sizeof(b));
for (tmp = 0, i = 0; i < size; i++) {
@@ -530,7 +530,7 @@ static int bt3c_load_firmware(bt3c_info_t *info, const unsigned char *firmware,
memset(b, 0, sizeof(b));
for (i = 0; i < (size - 4) / 2; i++) {
memcpy(b, ptr + (i * 4) + 12, 4);
- tmp = simple_strtol(b, NULL, 16);
+ tmp = simple_strtoul(b, NULL, 16);
bt3c_put(iobase, tmp);
}
}
diff --git a/drivers/bluetooth/btsdio.c b/drivers/bluetooth/btsdio.c
index cda6c7c..7e29827 100644
--- a/drivers/bluetooth/btsdio.c
+++ b/drivers/bluetooth/btsdio.c
@@ -37,11 +37,6 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
-#ifndef CONFIG_BT_HCIBTSDIO_DEBUG
-#undef BT_DBG
-#define BT_DBG(D...)
-#endif
-
#define VERSION "0.1"
static const struct sdio_device_id btsdio_table[] = {
@@ -91,6 +86,7 @@ static int btsdio_tx_packet(struct btsdio_data *data, struct sk_buff *skb)
err = sdio_writesb(data->func, REG_TDAT, skb->data, skb->len);
if (err < 0) {
+ skb_pull(skb, 4);
sdio_writeb(data->func, 0x01, REG_PC_WRT, NULL);
return err;
}
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index af472e0..b5fbda6 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -35,31 +35,25 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
-//#define CONFIG_BT_HCIBTUSB_DEBUG
-#ifndef CONFIG_BT_HCIBTUSB_DEBUG
-#undef BT_DBG
-#define BT_DBG(D...)
-#endif
-
-#define VERSION "0.3"
+#define VERSION "0.4"
static int ignore_dga;
static int ignore_csr;
static int ignore_sniffer;
static int disable_scofix;
static int force_scofix;
-static int reset;
+
+static int reset = 1;
static struct usb_driver btusb_driver;
#define BTUSB_IGNORE 0x01
-#define BTUSB_RESET 0x02
-#define BTUSB_DIGIANSWER 0x04
-#define BTUSB_CSR 0x08
-#define BTUSB_SNIFFER 0x10
-#define BTUSB_BCM92035 0x20
-#define BTUSB_BROKEN_ISOC 0x40
-#define BTUSB_WRONG_SCO_MTU 0x80
+#define BTUSB_DIGIANSWER 0x02
+#define BTUSB_CSR 0x04
+#define BTUSB_SNIFFER 0x08
+#define BTUSB_BCM92035 0x10
+#define BTUSB_BROKEN_ISOC 0x20
+#define BTUSB_WRONG_SCO_MTU 0x40
static struct usb_device_id btusb_table[] = {
/* Generic Bluetooth USB device */
@@ -79,7 +73,7 @@ static struct usb_device_id btusb_table[] = {
{ USB_DEVICE(0x0bdb, 0x1002) },
/* Canyon CN-BTU1 with HID interfaces */
- { USB_DEVICE(0x0c10, 0x0000), .driver_info = BTUSB_RESET },
+ { USB_DEVICE(0x0c10, 0x0000) },
{ } /* Terminating entry */
};
@@ -94,52 +88,37 @@ static struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x0a5c, 0x2033), .driver_info = BTUSB_IGNORE },
/* Broadcom BCM2035 */
- { USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU },
- { USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU },
+ { USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU },
+ { USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },
+ { USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 },
/* Broadcom BCM2045 */
- { USB_DEVICE(0x0a5c, 0x2039), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU },
- { USB_DEVICE(0x0a5c, 0x2101), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU },
-
- /* Broadcom BCM2046 */
- { USB_DEVICE(0x0a5c, 0x2146), .driver_info = BTUSB_RESET },
- { USB_DEVICE(0x0a5c, 0x2151), .driver_info = BTUSB_RESET },
-
- /* Apple MacBook Pro with Broadcom chip */
- { USB_DEVICE(0x05ac, 0x820f), .driver_info = BTUSB_RESET },
+ { USB_DEVICE(0x0a5c, 0x2039), .driver_info = BTUSB_WRONG_SCO_MTU },
+ { USB_DEVICE(0x0a5c, 0x2101), .driver_info = BTUSB_WRONG_SCO_MTU },
/* IBM/Lenovo ThinkPad with Broadcom chip */
- { USB_DEVICE(0x0a5c, 0x201e), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU },
- { USB_DEVICE(0x0a5c, 0x2110), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU },
-
- /* Targus ACB10US */
- { USB_DEVICE(0x0a5c, 0x2100), .driver_info = BTUSB_RESET },
- { USB_DEVICE(0x0a5c, 0x2154), .driver_info = BTUSB_RESET },
-
- /* ANYCOM Bluetooth USB-200 and USB-250 */
- { USB_DEVICE(0x0a5c, 0x2111), .driver_info = BTUSB_RESET },
+ { USB_DEVICE(0x0a5c, 0x201e), .driver_info = BTUSB_WRONG_SCO_MTU },
+ { USB_DEVICE(0x0a5c, 0x2110), .driver_info = BTUSB_WRONG_SCO_MTU },
/* HP laptop with Broadcom chip */
- { USB_DEVICE(0x03f0, 0x171d), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU },
+ { USB_DEVICE(0x03f0, 0x171d), .driver_info = BTUSB_WRONG_SCO_MTU },
/* Dell laptop with Broadcom chip */
- { USB_DEVICE(0x413c, 0x8126), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU },
+ { USB_DEVICE(0x413c, 0x8126), .driver_info = BTUSB_WRONG_SCO_MTU },
- /* Dell Wireless 370 */
- { USB_DEVICE(0x413c, 0x8156), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU },
+ /* Dell Wireless 370 and 410 devices */
+ { USB_DEVICE(0x413c, 0x8152), .driver_info = BTUSB_WRONG_SCO_MTU },
+ { USB_DEVICE(0x413c, 0x8156), .driver_info = BTUSB_WRONG_SCO_MTU },
- /* Dell Wireless 410 */
- { USB_DEVICE(0x413c, 0x8152), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU },
+ /* Belkin F8T012 and F8T013 devices */
+ { USB_DEVICE(0x050d, 0x0012), .driver_info = BTUSB_WRONG_SCO_MTU },
+ { USB_DEVICE(0x050d, 0x0013), .driver_info = BTUSB_WRONG_SCO_MTU },
- /* Microsoft Wireless Transceiver for Bluetooth 2.0 */
- { USB_DEVICE(0x045e, 0x009c), .driver_info = BTUSB_RESET },
+ /* Asus WL-BTD202 device */
+ { USB_DEVICE(0x0b05, 0x1715), .driver_info = BTUSB_WRONG_SCO_MTU },
/* Kensington Bluetooth USB adapter */
- { USB_DEVICE(0x047d, 0x105d), .driver_info = BTUSB_RESET },
- { USB_DEVICE(0x047d, 0x105e), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU },
-
- /* ISSC Bluetooth Adapter v3.1 */
- { USB_DEVICE(0x1131, 0x1001), .driver_info = BTUSB_RESET },
+ { USB_DEVICE(0x047d, 0x105e), .driver_info = BTUSB_WRONG_SCO_MTU },
/* RTX Telecom based adapters with buggy SCO support */
{ USB_DEVICE(0x0400, 0x0807), .driver_info = BTUSB_BROKEN_ISOC },
@@ -148,13 +127,6 @@ static struct usb_device_id blacklist_table[] = {
/* CONWISE Technology based adapters with buggy SCO support */
{ USB_DEVICE(0x0e5e, 0x6622), .driver_info = BTUSB_BROKEN_ISOC },
- /* Belkin F8T012 and F8T013 devices */
- { USB_DEVICE(0x050d, 0x0012), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU },
- { USB_DEVICE(0x050d, 0x0013), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU },
-
- /* Belkin F8T016 device */
- { USB_DEVICE(0x050d, 0x016a), .driver_info = BTUSB_RESET },
-
/* Digianswer devices */
{ USB_DEVICE(0x08fd, 0x0001), .driver_info = BTUSB_DIGIANSWER },
{ USB_DEVICE(0x08fd, 0x0002), .driver_info = BTUSB_IGNORE },
@@ -197,7 +169,10 @@ struct btusb_data {
struct usb_endpoint_descriptor *isoc_tx_ep;
struct usb_endpoint_descriptor *isoc_rx_ep;
+ __u8 cmdreq_type;
+
int isoc_altsetting;
+ int suspend_count;
};
static void btusb_intr_complete(struct urb *urb)
@@ -236,7 +211,7 @@ static void btusb_intr_complete(struct urb *urb)
}
}
-static int btusb_submit_intr_urb(struct hci_dev *hdev)
+static int btusb_submit_intr_urb(struct hci_dev *hdev, gfp_t mem_flags)
{
struct btusb_data *data = hdev->driver_data;
struct urb *urb;
@@ -249,13 +224,13 @@ static int btusb_submit_intr_urb(struct hci_dev *hdev)
if (!data->intr_ep)
return -ENODEV;
- urb = usb_alloc_urb(0, GFP_ATOMIC);
+ urb = usb_alloc_urb(0, mem_flags);
if (!urb)
return -ENOMEM;
size = le16_to_cpu(data->intr_ep->wMaxPacketSize);
- buf = kmalloc(size, GFP_ATOMIC);
+ buf = kmalloc(size, mem_flags);
if (!buf) {
usb_free_urb(urb);
return -ENOMEM;
@@ -271,7 +246,7 @@ static int btusb_submit_intr_urb(struct hci_dev *hdev)
usb_anchor_urb(urb, &data->intr_anchor);
- err = usb_submit_urb(urb, GFP_ATOMIC);
+ err = usb_submit_urb(urb, mem_flags);
if (err < 0) {
BT_ERR("%s urb %p submission failed (%d)",
hdev->name, urb, -err);
@@ -319,7 +294,7 @@ static void btusb_bulk_complete(struct urb *urb)
}
}
-static int btusb_submit_bulk_urb(struct hci_dev *hdev)
+static int btusb_submit_bulk_urb(struct hci_dev *hdev, gfp_t mem_flags)
{
struct btusb_data *data = hdev->driver_data;
struct urb *urb;
@@ -332,13 +307,13 @@ static int btusb_submit_bulk_urb(struct hci_dev *hdev)
if (!data->bulk_rx_ep)
return -ENODEV;
- urb = usb_alloc_urb(0, GFP_KERNEL);
+ urb = usb_alloc_urb(0, mem_flags);
if (!urb)
return -ENOMEM;
size = le16_to_cpu(data->bulk_rx_ep->wMaxPacketSize);
- buf = kmalloc(size, GFP_KERNEL);
+ buf = kmalloc(size, mem_flags);
if (!buf) {
usb_free_urb(urb);
return -ENOMEM;
@@ -353,7 +328,7 @@ static int btusb_submit_bulk_urb(struct hci_dev *hdev)
usb_anchor_urb(urb, &data->bulk_anchor);
- err = usb_submit_urb(urb, GFP_KERNEL);
+ err = usb_submit_urb(urb, mem_flags);
if (err < 0) {
BT_ERR("%s urb %p submission failed (%d)",
hdev->name, urb, -err);
@@ -430,7 +405,7 @@ static void inline __fill_isoc_descriptor(struct urb *urb, int len, int mtu)
urb->number_of_packets = i;
}
-static int btusb_submit_isoc_urb(struct hci_dev *hdev)
+static int btusb_submit_isoc_urb(struct hci_dev *hdev, gfp_t mem_flags)
{
struct btusb_data *data = hdev->driver_data;
struct urb *urb;
@@ -443,14 +418,14 @@ static int btusb_submit_isoc_urb(struct hci_dev *hdev)
if (!data->isoc_rx_ep)
return -ENODEV;
- urb = usb_alloc_urb(BTUSB_MAX_ISOC_FRAMES, GFP_KERNEL);
+ urb = usb_alloc_urb(BTUSB_MAX_ISOC_FRAMES, mem_flags);
if (!urb)
return -ENOMEM;
size = le16_to_cpu(data->isoc_rx_ep->wMaxPacketSize) *
BTUSB_MAX_ISOC_FRAMES;
- buf = kmalloc(size, GFP_KERNEL);
+ buf = kmalloc(size, mem_flags);
if (!buf) {
usb_free_urb(urb);
return -ENOMEM;
@@ -473,7 +448,7 @@ static int btusb_submit_isoc_urb(struct hci_dev *hdev)
usb_anchor_urb(urb, &data->isoc_anchor);
- err = usb_submit_urb(urb, GFP_KERNEL);
+ err = usb_submit_urb(urb, mem_flags);
if (err < 0) {
BT_ERR("%s urb %p submission failed (%d)",
hdev->name, urb, -err);
@@ -520,7 +495,7 @@ static int btusb_open(struct hci_dev *hdev)
if (test_and_set_bit(BTUSB_INTR_RUNNING, &data->flags))
return 0;
- err = btusb_submit_intr_urb(hdev);
+ err = btusb_submit_intr_urb(hdev, GFP_KERNEL);
if (err < 0) {
clear_bit(BTUSB_INTR_RUNNING, &data->flags);
clear_bit(HCI_RUNNING, &hdev->flags);
@@ -589,7 +564,7 @@ static int btusb_send_frame(struct sk_buff *skb)
return -ENOMEM;
}
- dr->bRequestType = USB_TYPE_CLASS;
+ dr->bRequestType = data->cmdreq_type;
dr->bRequest = 0;
dr->wIndex = 0;
dr->wValue = 0;
@@ -680,8 +655,19 @@ static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
BT_DBG("%s evt %d", hdev->name, evt);
- if (evt == HCI_NOTIFY_CONN_ADD || evt == HCI_NOTIFY_CONN_DEL)
- schedule_work(&data->work);
+ if (hdev->conn_hash.acl_num > 0) {
+ if (!test_and_set_bit(BTUSB_BULK_RUNNING, &data->flags)) {
+ if (btusb_submit_bulk_urb(hdev, GFP_ATOMIC) < 0)
+ clear_bit(BTUSB_BULK_RUNNING, &data->flags);
+ else
+ btusb_submit_bulk_urb(hdev, GFP_ATOMIC);
+ }
+ } else {
+ clear_bit(BTUSB_BULK_RUNNING, &data->flags);
+ usb_unlink_anchored_urbs(&data->bulk_anchor);
+ }
+
+ schedule_work(&data->work);
}
static int inline __set_isoc_interface(struct hci_dev *hdev, int altsetting)
@@ -732,18 +718,6 @@ static void btusb_work(struct work_struct *work)
struct btusb_data *data = container_of(work, struct btusb_data, work);
struct hci_dev *hdev = data->hdev;
- if (hdev->conn_hash.acl_num > 0) {
- if (!test_and_set_bit(BTUSB_BULK_RUNNING, &data->flags)) {
- if (btusb_submit_bulk_urb(hdev) < 0)
- clear_bit(BTUSB_BULK_RUNNING, &data->flags);
- else
- btusb_submit_bulk_urb(hdev);
- }
- } else {
- clear_bit(BTUSB_BULK_RUNNING, &data->flags);
- usb_kill_anchored_urbs(&data->bulk_anchor);
- }
-
if (hdev->conn_hash.sco_num > 0) {
if (data->isoc_altsetting != 2) {
clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
@@ -754,10 +728,10 @@ static void btusb_work(struct work_struct *work)
}
if (!test_and_set_bit(BTUSB_ISOC_RUNNING, &data->flags)) {
- if (btusb_submit_isoc_urb(hdev) < 0)
+ if (btusb_submit_isoc_urb(hdev, GFP_KERNEL) < 0)
clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
else
- btusb_submit_isoc_urb(hdev);
+ btusb_submit_isoc_urb(hdev, GFP_KERNEL);
}
} else {
clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
@@ -828,6 +802,8 @@ static int btusb_probe(struct usb_interface *intf,
return -ENODEV;
}
+ data->cmdreq_type = USB_TYPE_CLASS;
+
data->udev = interface_to_usbdev(intf);
data->intf = intf;
@@ -862,11 +838,11 @@ static int btusb_probe(struct usb_interface *intf,
hdev->owner = THIS_MODULE;
- /* interface numbers are hardcoded in the spec */
+ /* Interface numbers are hardcoded in the specification */
data->isoc = usb_ifnum_to_if(data->udev, 1);
- if (reset || id->driver_info & BTUSB_RESET)
- set_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks);
+ if (!reset)
+ set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks);
if (force_scofix || id->driver_info & BTUSB_WRONG_SCO_MTU) {
if (!disable_scofix)
@@ -876,9 +852,23 @@ static int btusb_probe(struct usb_interface *intf,
if (id->driver_info & BTUSB_BROKEN_ISOC)
data->isoc = NULL;
+ if (id->driver_info & BTUSB_DIGIANSWER) {
+ data->cmdreq_type = USB_TYPE_VENDOR;
+ set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks);
+ }
+
+ if (id->driver_info & BTUSB_CSR) {
+ struct usb_device *udev = data->udev;
+
+ /* Old firmware would otherwise execute USB reset */
+ if (le16_to_cpu(udev->descriptor.bcdDevice) < 0x117)
+ set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks);
+ }
+
if (id->driver_info & BTUSB_SNIFFER) {
struct usb_device *udev = data->udev;
+ /* New sniffer firmware has crippled HCI interface */
if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x997)
set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
@@ -949,10 +939,71 @@ static void btusb_disconnect(struct usb_interface *intf)
hci_free_dev(hdev);
}
+static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
+{
+ struct btusb_data *data = usb_get_intfdata(intf);
+
+ BT_DBG("intf %p", intf);
+
+ if (data->suspend_count++)
+ return 0;
+
+ cancel_work_sync(&data->work);
+
+ usb_kill_anchored_urbs(&data->tx_anchor);
+
+ usb_kill_anchored_urbs(&data->isoc_anchor);
+ usb_kill_anchored_urbs(&data->bulk_anchor);
+ usb_kill_anchored_urbs(&data->intr_anchor);
+
+ return 0;
+}
+
+static int btusb_resume(struct usb_interface *intf)
+{
+ struct btusb_data *data = usb_get_intfdata(intf);
+ struct hci_dev *hdev = data->hdev;
+ int err;
+
+ BT_DBG("intf %p", intf);
+
+ if (--data->suspend_count)
+ return 0;
+
+ if (!test_bit(HCI_RUNNING, &hdev->flags))
+ return 0;
+
+ if (test_bit(BTUSB_INTR_RUNNING, &data->flags)) {
+ err = btusb_submit_intr_urb(hdev, GFP_NOIO);
+ if (err < 0) {
+ clear_bit(BTUSB_INTR_RUNNING, &data->flags);
+ return err;
+ }
+ }
+
+ if (test_bit(BTUSB_BULK_RUNNING, &data->flags)) {
+ if (btusb_submit_bulk_urb(hdev, GFP_NOIO) < 0)
+ clear_bit(BTUSB_BULK_RUNNING, &data->flags);
+ else
+ btusb_submit_bulk_urb(hdev, GFP_NOIO);
+ }
+
+ if (test_bit(BTUSB_ISOC_RUNNING, &data->flags)) {
+ if (btusb_submit_isoc_urb(hdev, GFP_NOIO) < 0)
+ clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
+ else
+ btusb_submit_isoc_urb(hdev, GFP_NOIO);
+ }
+
+ return 0;
+}
+
static struct usb_driver btusb_driver = {
.name = "btusb",
.probe = btusb_probe,
.disconnect = btusb_disconnect,
+ .suspend = btusb_suspend,
+ .resume = btusb_resume,
.id_table = btusb_table,
};
diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c
index 7938062..894b2cb 100644
--- a/drivers/bluetooth/hci_bcsp.c
+++ b/drivers/bluetooth/hci_bcsp.c
@@ -47,11 +47,6 @@
#include "hci_uart.h"
-#ifndef CONFIG_BT_HCIUART_DEBUG
-#undef BT_DBG
-#define BT_DBG( A... )
-#endif
-
#define VERSION "0.3"
static int txcrc = 1;
diff --git a/drivers/bluetooth/hci_h4.c b/drivers/bluetooth/hci_h4.c
index bfbae14..b0fafb0 100644
--- a/drivers/bluetooth/hci_h4.c
+++ b/drivers/bluetooth/hci_h4.c
@@ -46,11 +46,6 @@
#include "hci_uart.h"
-#ifndef CONFIG_BT_HCIUART_DEBUG
-#undef BT_DBG
-#define BT_DBG( A... )
-#endif
-
#define VERSION "1.2"
struct h4_struct {
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 4426bb5..af761dc 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -46,11 +46,6 @@
#include "hci_uart.h"
-#ifndef CONFIG_BT_HCIUART_DEBUG
-#undef BT_DBG
-#define BT_DBG( A... )
-#endif
-
#define VERSION "2.2"
static int reset = 0;
@@ -399,8 +394,8 @@ static int hci_uart_register_dev(struct hci_uart *hu)
hdev->owner = THIS_MODULE;
- if (reset)
- set_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks);
+ if (!reset)
+ set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks);
if (hci_register_dev(hdev) < 0) {
BT_ERR("Can't register HCI device");
diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c
deleted file mode 100644
index 3c45392..0000000
--- a/drivers/bluetooth/hci_usb.c
+++ /dev/null
@@ -1,1136 +0,0 @@
-/*
- HCI USB driver for Linux Bluetooth protocol stack (BlueZ)
- Copyright (C) 2000-2001 Qualcomm Incorporated
- Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
-
- Copyright (C) 2003 Maxim Krasnyansky <maxk@qualcomm.com>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License version 2 as
- published by the Free Software Foundation;
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
- IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
- CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
- ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
- COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
- SOFTWARE IS DISCLAIMED.
-*/
-
-/*
- * Bluetooth HCI USB driver.
- * Based on original USB Bluetooth driver for Linux kernel
- * Copyright (c) 2000 Greg Kroah-Hartman <greg@kroah.com>
- * Copyright (c) 2000 Mark Douglas Corner <mcorner@umich.edu>
- *
- */
-
-#include <linux/module.h>
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/unistd.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/moduleparam.h>
-
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/skbuff.h>
-
-#include <linux/usb.h>
-
-#include <net/bluetooth/bluetooth.h>
-#include <net/bluetooth/hci_core.h>
-
-#include "hci_usb.h"
-
-#ifndef CONFIG_BT_HCIUSB_DEBUG
-#undef BT_DBG
-#define BT_DBG(D...)
-#endif
-
-#ifndef CONFIG_BT_HCIUSB_ZERO_PACKET
-#undef URB_ZERO_PACKET
-#define URB_ZERO_PACKET 0
-#endif
-
-static int ignore_dga;
-static int ignore_csr;
-static int ignore_sniffer;
-static int disable_scofix;
-static int force_scofix;
-static int reset;
-
-#ifdef CONFIG_BT_HCIUSB_SCO
-static int isoc = 2;
-#endif
-
-#define VERSION "2.10"
-
-static struct usb_driver hci_usb_driver;
-
-static struct usb_device_id bluetooth_ids[] = {
- /* Generic Bluetooth USB device */
- { USB_DEVICE_INFO(HCI_DEV_CLASS, HCI_DEV_SUBCLASS, HCI_DEV_PROTOCOL) },
-
- /* AVM BlueFRITZ! USB v2.0 */
- { USB_DEVICE(0x057c, 0x3800) },
-
- /* Bluetooth Ultraport Module from IBM */
- { USB_DEVICE(0x04bf, 0x030a) },
-
- /* ALPS Modules with non-standard id */
- { USB_DEVICE(0x044e, 0x3001) },
- { USB_DEVICE(0x044e, 0x3002) },
-
- /* Ericsson with non-standard id */
- { USB_DEVICE(0x0bdb, 0x1002) },
-
- /* Canyon CN-BTU1 with HID interfaces */
- { USB_DEVICE(0x0c10, 0x0000), .driver_info = HCI_RESET },
-
- { } /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, bluetooth_ids);
-
-static struct usb_device_id blacklist_ids[] = {
- /* CSR BlueCore devices */
- { USB_DEVICE(0x0a12, 0x0001), .driver_info = HCI_CSR },
-
- /* Broadcom BCM2033 without firmware */
- { USB_DEVICE(0x0a5c, 0x2033), .driver_info = HCI_IGNORE },
-
- /* Broadcom BCM2035 */
- { USB_DEVICE(0x0a5c, 0x2035), .driver_info = HCI_RESET | HCI_WRONG_SCO_MTU },
- { USB_DEVICE(0x0a5c, 0x200a), .driver_info = HCI_RESET | HCI_WRONG_SCO_MTU },
- { USB_DEVICE(0x0a5c, 0x2009), .driver_info = HCI_BCM92035 },
-
- /* Broadcom BCM2045 */
- { USB_DEVICE(0x0a5c, 0x2039), .driver_info = HCI_RESET | HCI_WRONG_SCO_MTU },
- { USB_DEVICE(0x0a5c, 0x2101), .driver_info = HCI_RESET | HCI_WRONG_SCO_MTU },
-
- /* IBM/Lenovo ThinkPad with Broadcom chip */
- { USB_DEVICE(0x0a5c, 0x201e), .driver_info = HCI_RESET | HCI_WRONG_SCO_MTU },
- { USB_DEVICE(0x0a5c, 0x2110), .driver_info = HCI_RESET | HCI_WRONG_SCO_MTU },
-
- /* Targus ACB10US */
- { USB_DEVICE(0x0a5c, 0x2100), .driver_info = HCI_RESET },
-
- /* ANYCOM Bluetooth USB-200 and USB-250 */
- { USB_DEVICE(0x0a5c, 0x2111), .driver_info = HCI_RESET },
-
- /* HP laptop with Broadcom chip */
- { USB_DEVICE(0x03f0, 0x171d), .driver_info = HCI_RESET | HCI_WRONG_SCO_MTU },
-
- /* Dell laptop with Broadcom chip */
- { USB_DEVICE(0x413c, 0x8126), .driver_info = HCI_RESET | HCI_WRONG_SCO_MTU },
- /* Dell Wireless 370 */
- { USB_DEVICE(0x413c, 0x8156), .driver_info = HCI_RESET | HCI_WRONG_SCO_MTU },
- /* Dell Wireless 410 */
- { USB_DEVICE(0x413c, 0x8152), .driver_info = HCI_RESET | HCI_WRONG_SCO_MTU },
-
- /* Broadcom 2046 */
- { USB_DEVICE(0x0a5c, 0x2151), .driver_info = HCI_RESET },
-
- /* Microsoft Wireless Transceiver for Bluetooth 2.0 */
- { USB_DEVICE(0x045e, 0x009c), .driver_info = HCI_RESET },
-
- /* Kensington Bluetooth USB adapter */
- { USB_DEVICE(0x047d, 0x105d), .driver_info = HCI_RESET },
- { USB_DEVICE(0x047d, 0x105e), .driver_info = HCI_RESET | HCI_WRONG_SCO_MTU },
-
- /* ISSC Bluetooth Adapter v3.1 */
- { USB_DEVICE(0x1131, 0x1001), .driver_info = HCI_RESET },
-
- /* RTX Telecom based adapters with buggy SCO support */
- { USB_DEVICE(0x0400, 0x0807), .driver_info = HCI_BROKEN_ISOC },
- { USB_DEVICE(0x0400, 0x080a), .driver_info = HCI_BROKEN_ISOC },
-
- /* CONWISE Technology based adapters with buggy SCO support */
- { USB_DEVICE(0x0e5e, 0x6622), .driver_info = HCI_BROKEN_ISOC },
-
- /* Belkin F8T012 and F8T013 devices */
- { USB_DEVICE(0x050d, 0x0012), .driver_info = HCI_RESET | HCI_WRONG_SCO_MTU },
- { USB_DEVICE(0x050d, 0x0013), .driver_info = HCI_RESET | HCI_WRONG_SCO_MTU },
-
- /* Digianswer devices */
- { USB_DEVICE(0x08fd, 0x0001), .driver_info = HCI_DIGIANSWER },
- { USB_DEVICE(0x08fd, 0x0002), .driver_info = HCI_IGNORE },
-
- /* CSR BlueCore Bluetooth Sniffer */
- { USB_DEVICE(0x0a12, 0x0002), .driver_info = HCI_SNIFFER },
-
- /* Frontline ComProbe Bluetooth Sniffer */
- { USB_DEVICE(0x16d3, 0x0002), .driver_info = HCI_SNIFFER },
-
- { } /* Terminating entry */
-};
-
-static struct _urb *_urb_alloc(int isoc, gfp_t gfp)
-{
- struct _urb *_urb = kmalloc(sizeof(struct _urb) +
- sizeof(struct usb_iso_packet_descriptor) * isoc, gfp);
- if (_urb) {
- memset(_urb, 0, sizeof(*_urb));
- usb_init_urb(&_urb->urb);
- }
- return _urb;
-}
-
-static struct _urb *_urb_dequeue(struct _urb_queue *q)
-{
- struct _urb *_urb = NULL;
- unsigned long flags;
- spin_lock_irqsave(&q->lock, flags);
- {
- struct list_head *head = &q->head;
- struct list_head *next = head->next;
- if (next != head) {
- _urb = list_entry(next, struct _urb, list);
- list_del(next); _urb->queue = NULL;
- }
- }
- spin_unlock_irqrestore(&q->lock, flags);
- return _urb;
-}
-
-static void hci_usb_rx_complete(struct urb *urb);
-static void hci_usb_tx_complete(struct urb *urb);
-
-#define __pending_tx(husb, type) (&husb->pending_tx[type-1])
-#define __pending_q(husb, type) (&husb->pending_q[type-1])
-#define __completed_q(husb, type) (&husb->completed_q[type-1])
-#define __transmit_q(husb, type) (&husb->transmit_q[type-1])
-
-static inline struct _urb *__get_completed(struct hci_usb *husb, int type)
-{
- return _urb_dequeue(__completed_q(husb, type));
-}
-
-#ifdef CONFIG_BT_HCIUSB_SCO
-static void __fill_isoc_desc(struct urb *urb, int len, int mtu)
-{
- int offset = 0, i;
-
- BT_DBG("len %d mtu %d", len, mtu);
-
- for (i=0; i < HCI_MAX_ISOC_FRAMES && len >= mtu; i++, offset += mtu, len -= mtu) {
- urb->iso_frame_desc[i].offset = offset;
- urb->iso_frame_desc[i].length = mtu;
- BT_DBG("desc %d offset %d len %d", i, offset, mtu);
- }
- if (len && i < HCI_MAX_ISOC_FRAMES) {
- urb->iso_frame_desc[i].offset = offset;
- urb->iso_frame_desc[i].length = len;
- BT_DBG("desc %d offset %d len %d", i, offset, len);
- i++;
- }
- urb->number_of_packets = i;
-}
-#endif
-
-static int hci_usb_intr_rx_submit(struct hci_usb *husb)
-{
- struct _urb *_urb;
- struct urb *urb;
- int err, pipe, interval, size;
- void *buf;
-
- BT_DBG("%s", husb->hdev->name);
-
- size = le16_to_cpu(husb->intr_in_ep->desc.wMaxPacketSize);
-
- buf = kmalloc(size, GFP_ATOMIC);
- if (!buf)
- return -ENOMEM;
-
- _urb = _urb_alloc(0, GFP_ATOMIC);
- if (!_urb) {
- kfree(buf);
- return -ENOMEM;
- }
- _urb->type = HCI_EVENT_PKT;
- _urb_queue_tail(__pending_q(husb, _urb->type), _urb);
-
- urb = &_urb->urb;
- pipe = usb_rcvintpipe(husb->udev, husb->intr_in_ep->desc.bEndpointAddress);
- interval = husb->intr_in_ep->desc.bInterval;
- usb_fill_int_urb(urb, husb->udev, pipe, buf, size, hci_usb_rx_complete, husb, interval);
-
- err = usb_submit_urb(urb, GFP_ATOMIC);
- if (err) {
- BT_ERR("%s intr rx submit failed urb %p err %d",
- husb->hdev->name, urb, err);
- _urb_unlink(_urb);
- kfree(_urb);
- kfree(buf);
- }
- return err;
-}
-
-static int hci_usb_bulk_rx_submit(struct hci_usb *husb)
-{
- struct _urb *_urb;
- struct urb *urb;
- int err, pipe, size = HCI_MAX_FRAME_SIZE;
- void *buf;
-
- buf = kmalloc(size, GFP_ATOMIC);
- if (!buf)
- return -ENOMEM;
-
- _urb = _urb_alloc(0, GFP_ATOMIC);
- if (!_urb) {
- kfree(buf);
- return -ENOMEM;
- }
- _urb->type = HCI_ACLDATA_PKT;
- _urb_queue_tail(__pending_q(husb, _urb->type), _urb);
-
- urb = &_urb->urb;
- pipe = usb_rcvbulkpipe(husb->udev, husb->bulk_in_ep->desc.bEndpointAddress);
- usb_fill_bulk_urb(urb, husb->udev, pipe, buf, size, hci_usb_rx_complete, husb);
- urb->transfer_flags = 0;
-
- BT_DBG("%s urb %p", husb->hdev->name, urb);
-
- err = usb_submit_urb(urb, GFP_ATOMIC);
- if (err) {
- BT_ERR("%s bulk rx submit failed urb %p err %d",
- husb->hdev->name, urb, err);
- _urb_unlink(_urb);
- kfree(_urb);
- kfree(buf);
- }
- return err;
-}
-
-#ifdef CONFIG_BT_HCIUSB_SCO
-static int hci_usb_isoc_rx_submit(struct hci_usb *husb)
-{
- struct _urb *_urb;
- struct urb *urb;
- int err, mtu, size;
- void *buf;
-
- mtu = le16_to_cpu(husb->isoc_in_ep->desc.wMaxPacketSize);
- size = mtu * HCI_MAX_ISOC_FRAMES;
-
- buf = kmalloc(size, GFP_ATOMIC);
- if (!buf)
- return -ENOMEM;
-
- _urb = _urb_alloc(HCI_MAX_ISOC_FRAMES, GFP_ATOMIC);
- if (!_urb) {
- kfree(buf);
- return -ENOMEM;
- }
- _urb->type = HCI_SCODATA_PKT;
- _urb_queue_tail(__pending_q(husb, _urb->type), _urb);
-
- urb = &_urb->urb;
-
- urb->context = husb;
- urb->dev = husb->udev;
- urb->pipe = usb_rcvisocpipe(husb->udev, husb->isoc_in_ep->desc.bEndpointAddress);
- urb->complete = hci_usb_rx_complete;
-
- urb->interval = husb->isoc_in_ep->desc.bInterval;
-
- urb->transfer_buffer_length = size;
- urb->transfer_buffer = buf;
- urb->transfer_flags = URB_ISO_ASAP;
-
- __fill_isoc_desc(urb, size, mtu);
-
- BT_DBG("%s urb %p", husb->hdev->name, urb);
-
- err = usb_submit_urb(urb, GFP_ATOMIC);
- if (err) {
- BT_ERR("%s isoc rx submit failed urb %p err %d",
- husb->hdev->name, urb, err);
- _urb_unlink(_urb);
- kfree(_urb);
- kfree(buf);
- }
- return err;
-}
-#endif
-
-/* Initialize device */
-static int hci_usb_open(struct hci_dev *hdev)
-{
- struct hci_usb *husb = (struct hci_usb *) hdev->driver_data;
- int i, err;
- unsigned long flags;
-
- BT_DBG("%s", hdev->name);
-
- if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
- return 0;
-
- write_lock_irqsave(&husb->completion_lock, flags);
-
- err = hci_usb_intr_rx_submit(husb);
- if (!err) {
- for (i = 0; i < HCI_MAX_BULK_RX; i++)
- hci_usb_bulk_rx_submit(husb);
-
-#ifdef CONFIG_BT_HCIUSB_SCO
- if (husb->isoc_iface)
- for (i = 0; i < HCI_MAX_ISOC_RX; i++)
- hci_usb_isoc_rx_submit(husb);
-#endif
- } else {
- clear_bit(HCI_RUNNING, &hdev->flags);
- }
-
- write_unlock_irqrestore(&husb->completion_lock, flags);
- return err;
-}
-
-/* Reset device */
-static int hci_usb_flush(struct hci_dev *hdev)
-{
- struct hci_usb *husb = (struct hci_usb *) hdev->driver_data;
- int i;
-
- BT_DBG("%s", hdev->name);
-
- for (i = 0; i < 4; i++)
- skb_queue_purge(&husb->transmit_q[i]);
- return 0;
-}
-
-static void hci_usb_unlink_urbs(struct hci_usb *husb)
-{
- int i;
-
- BT_DBG("%s", husb->hdev->name);
-
- for (i = 0; i < 4; i++) {
- struct _urb *_urb;
- struct urb *urb;
-
- /* Kill pending requests */
- while ((_urb = _urb_dequeue(&husb->pending_q[i]))) {
- urb = &_urb->urb;
- BT_DBG("%s unlinking _urb %p type %d urb %p",
- husb->hdev->name, _urb, _urb->type, urb);
- usb_kill_urb(urb);
- _urb_queue_tail(__completed_q(husb, _urb->type), _urb);
- }
-
- /* Release completed requests */
- while ((_urb = _urb_dequeue(&husb->completed_q[i]))) {
- urb = &_urb->urb;
- BT_DBG("%s freeing _urb %p type %d urb %p",
- husb->hdev->name, _urb, _urb->type, urb);
- kfree(urb->setup_packet);
- kfree(urb->transfer_buffer);
- kfree(_urb);
- }
- }
-}
-
-/* Close device */
-static int hci_usb_close(struct hci_dev *hdev)
-{
- struct hci_usb *husb = (struct hci_usb *) hdev->driver_data;
- unsigned long flags;
-
- if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
- return 0;
-
- BT_DBG("%s", hdev->name);
-
- /* Synchronize with completion handlers */
- write_lock_irqsave(&husb->completion_lock, flags);
- write_unlock_irqrestore(&husb->completion_lock, flags);
-
- hci_usb_unlink_urbs(husb);
- hci_usb_flush(hdev);
- return 0;
-}
-
-static int __tx_submit(struct hci_usb *husb, struct _urb *_urb)
-{
- struct urb *urb = &_urb->urb;
- int err;
-
- BT_DBG("%s urb %p type %d", husb->hdev->name, urb, _urb->type);
-
- _urb_queue_tail(__pending_q(husb, _urb->type), _urb);
- err = usb_submit_urb(urb, GFP_ATOMIC);
- if (err) {
- BT_ERR("%s tx submit failed urb %p type %d err %d",
- husb->hdev->name, urb, _urb->type, err);
- _urb_unlink(_urb);
- _urb_queue_tail(__completed_q(husb, _urb->type), _urb);
- } else
- atomic_inc(__pending_tx(husb, _urb->type));
-
- return err;
-}
-
-static inline int hci_usb_send_ctrl(struct hci_usb *husb, struct sk_buff *skb)
-{
- struct _urb *_urb = __get_completed(husb, bt_cb(skb)->pkt_type);
- struct usb_ctrlrequest *dr;
- struct urb *urb;
-
- if (!_urb) {
- _urb = _urb_alloc(0, GFP_ATOMIC);
- if (!_urb)
- return -ENOMEM;
- _urb->type = bt_cb(skb)->pkt_type;
-
- dr = kmalloc(sizeof(*dr), GFP_ATOMIC);
- if (!dr) {
- kfree(_urb);
- return -ENOMEM;
- }
- } else
- dr = (void *) _urb->urb.setup_packet;
-
- dr->bRequestType = husb->ctrl_req;
- dr->bRequest = 0;
- dr->wIndex = 0;
- dr->wValue = 0;
- dr->wLength = __cpu_to_le16(skb->len);
-
- urb = &_urb->urb;
- usb_fill_control_urb(urb, husb->udev, usb_sndctrlpipe(husb->udev, 0),
- (void *) dr, skb->data, skb->len, hci_usb_tx_complete, husb);
-
- BT_DBG("%s skb %p len %d", husb->hdev->name, skb, skb->len);
-
- _urb->priv = skb;
- return __tx_submit(husb, _urb);
-}
-
-static inline int hci_usb_send_bulk(struct hci_usb *husb, struct sk_buff *skb)
-{
- struct _urb *_urb = __get_completed(husb, bt_cb(skb)->pkt_type);
- struct urb *urb;
- int pipe;
-
- if (!_urb) {
- _urb = _urb_alloc(0, GFP_ATOMIC);
- if (!_urb)
- return -ENOMEM;
- _urb->type = bt_cb(skb)->pkt_type;
- }
-
- urb = &_urb->urb;
- pipe = usb_sndbulkpipe(husb->udev, husb->bulk_out_ep->desc.bEndpointAddress);
- usb_fill_bulk_urb(urb, husb->udev, pipe, skb->data, skb->len,
- hci_usb_tx_complete, husb);
- urb->transfer_flags = URB_ZERO_PACKET;
-
- BT_DBG("%s skb %p len %d", husb->hdev->name, skb, skb->len);
-
- _urb->priv = skb;
- return __tx_submit(husb, _urb);
-}
-
-#ifdef CONFIG_BT_HCIUSB_SCO
-static inline int hci_usb_send_isoc(struct hci_usb *husb, struct sk_buff *skb)
-{
- struct _urb *_urb = __get_completed(husb, bt_cb(skb)->pkt_type);
- struct urb *urb;
-
- if (!_urb) {
- _urb = _urb_alloc(HCI_MAX_ISOC_FRAMES, GFP_ATOMIC);
- if (!_urb)
- return -ENOMEM;
- _urb->type = bt_cb(skb)->pkt_type;
- }
-
- BT_DBG("%s skb %p len %d", husb->hdev->name, skb, skb->len);
-
- urb = &_urb->urb;
-
- urb->context = husb;
- urb->dev = husb->udev;
- urb->pipe = usb_sndisocpipe(husb->udev, husb->isoc_out_ep->desc.bEndpointAddress);
- urb->complete = hci_usb_tx_complete;
- urb->transfer_flags = URB_ISO_ASAP;
-
- urb->interval = husb->isoc_out_ep->desc.bInterval;
-
- urb->transfer_buffer = skb->data;
- urb->transfer_buffer_length = skb->len;
-
- __fill_isoc_desc(urb, skb->len, le16_to_cpu(husb->isoc_out_ep->desc.wMaxPacketSize));
-
- _urb->priv = skb;
- return __tx_submit(husb, _urb);
-}
-#endif
-
-static void hci_usb_tx_process(struct hci_usb *husb)
-{
- struct sk_buff_head *q;
- struct sk_buff *skb;
-
- BT_DBG("%s", husb->hdev->name);
-
- do {
- clear_bit(HCI_USB_TX_WAKEUP, &husb->state);
-
- /* Process command queue */
- q = __transmit_q(husb, HCI_COMMAND_PKT);
- if (!atomic_read(__pending_tx(husb, HCI_COMMAND_PKT)) &&
- (skb = skb_dequeue(q))) {
- if (hci_usb_send_ctrl(husb, skb) < 0)
- skb_queue_head(q, skb);
- }
-
-#ifdef CONFIG_BT_HCIUSB_SCO
- /* Process SCO queue */
- q = __transmit_q(husb, HCI_SCODATA_PKT);
- if (atomic_read(__pending_tx(husb, HCI_SCODATA_PKT)) < HCI_MAX_ISOC_TX &&
- (skb = skb_dequeue(q))) {
- if (hci_usb_send_isoc(husb, skb) < 0)
- skb_queue_head(q, skb);
- }
-#endif
-
- /* Process ACL queue */
- q = __transmit_q(husb, HCI_ACLDATA_PKT);
- while (atomic_read(__pending_tx(husb, HCI_ACLDATA_PKT)) < HCI_MAX_BULK_TX &&
- (skb = skb_dequeue(q))) {
- if (hci_usb_send_bulk(husb, skb) < 0) {
- skb_queue_head(q, skb);
- break;
- }
- }
- } while(test_bit(HCI_USB_TX_WAKEUP, &husb->state));
-}
-
-static inline void hci_usb_tx_wakeup(struct hci_usb *husb)
-{
- /* Serialize TX queue processing to avoid data reordering */
- if (!test_and_set_bit(HCI_USB_TX_PROCESS, &husb->state)) {
- hci_usb_tx_process(husb);
- clear_bit(HCI_USB_TX_PROCESS, &husb->state);
- } else
- set_bit(HCI_USB_TX_WAKEUP, &husb->state);
-}
-
-/* Send frames from HCI layer */
-static int hci_usb_send_frame(struct sk_buff *skb)
-{
- struct hci_dev *hdev = (struct hci_dev *) skb->dev;
- struct hci_usb *husb;
-
- if (!hdev) {
- BT_ERR("frame for uknown device (hdev=NULL)");
- return -ENODEV;
- }
-
- if (!test_bit(HCI_RUNNING, &hdev->flags))
- return -EBUSY;
-
- BT_DBG("%s type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len);
-
- husb = (struct hci_usb *) hdev->driver_data;
-
- switch (bt_cb(skb)->pkt_type) {
- case HCI_COMMAND_PKT:
- hdev->stat.cmd_tx++;
- break;
-
- case HCI_ACLDATA_PKT:
- hdev->stat.acl_tx++;
- break;
-
-#ifdef CONFIG_BT_HCIUSB_SCO
- case HCI_SCODATA_PKT:
- hdev->stat.sco_tx++;
- break;
-#endif
-
- default:
- kfree_skb(skb);
- return 0;
- }
-
- read_lock(&husb->completion_lock);
-
- skb_queue_tail(__transmit_q(husb, bt_cb(skb)->pkt_type), skb);
- hci_usb_tx_wakeup(husb);
-
- read_unlock(&husb->completion_lock);
- return 0;
-}
-
-static void hci_usb_rx_complete(struct urb *urb)
-{
- struct _urb *_urb = container_of(urb, struct _urb, urb);
- struct hci_usb *husb = (void *) urb->context;
- struct hci_dev *hdev = husb->hdev;
- int err, count = urb->actual_length;
-
- BT_DBG("%s urb %p type %d status %d count %d flags %x", hdev->name, urb,
- _urb->type, urb->status, count, urb->transfer_flags);
-
- read_lock(&husb->completion_lock);
-
- if (!test_bit(HCI_RUNNING, &hdev->flags))
- goto unlock;
-
- if (urb->status || !count)
- goto resubmit;
-
- if (_urb->type == HCI_SCODATA_PKT) {
-#ifdef CONFIG_BT_HCIUSB_SCO
- int i;
- for (i=0; i < urb->number_of_packets; i++) {
- BT_DBG("desc %d status %d offset %d len %d", i,
- urb->iso_frame_desc[i].status,
- urb->iso_frame_desc[i].offset,
- urb->iso_frame_desc[i].actual_length);
-
- if (!urb->iso_frame_desc[i].status) {
- husb->hdev->stat.byte_rx += urb->iso_frame_desc[i].actual_length;
- hci_recv_fragment(husb->hdev, _urb->type,
- urb->transfer_buffer + urb->iso_frame_desc[i].offset,
- urb->iso_frame_desc[i].actual_length);
- }
- }
-#else
- ;
-#endif
- } else {
- husb->hdev->stat.byte_rx += count;
- err = hci_recv_fragment(husb->hdev, _urb->type, urb->transfer_buffer, count);
- if (err < 0) {
- BT_ERR("%s corrupted packet: type %d count %d",
- husb->hdev->name, _urb->type, count);
- hdev->stat.err_rx++;
- }
- }
-
-resubmit:
- urb->dev = husb->udev;
- err = usb_submit_urb(urb, GFP_ATOMIC);
- BT_DBG("%s urb %p type %d resubmit status %d", hdev->name, urb,
- _urb->type, err);
-
-unlock:
- read_unlock(&husb->completion_lock);
-}
-
-static void hci_usb_tx_complete(struct urb *urb)
-{
- struct _urb *_urb = container_of(urb, struct _urb, urb);
- struct hci_usb *husb = (void *) urb->context;
- struct hci_dev *hdev = husb->hdev;
-
- BT_DBG("%s urb %p status %d flags %x", hdev->name, urb,
- urb->status, urb->transfer_flags);
-
- atomic_dec(__pending_tx(husb, _urb->type));
-
- urb->transfer_buffer = NULL;
- kfree_skb((struct sk_buff *) _urb->priv);
-
- if (!test_bit(HCI_RUNNING, &hdev->flags))
- return;
-
- if (!urb->status)
- hdev->stat.byte_tx += urb->transfer_buffer_length;
- else
- hdev->stat.err_tx++;
-
- read_lock(&husb->completion_lock);
-
- _urb_unlink(_urb);
- _urb_queue_tail(__completed_q(husb, _urb->type), _urb);
-
- hci_usb_tx_wakeup(husb);
-
- read_unlock(&husb->completion_lock);
-}
-
-static void hci_usb_destruct(struct hci_dev *hdev)
-{
- struct hci_usb *husb = (struct hci_usb *) hdev->driver_data;
-
- BT_DBG("%s", hdev->name);
-
- kfree(husb);
-}
-
-static void hci_usb_notify(struct hci_dev *hdev, unsigned int evt)
-{
- BT_DBG("%s evt %d", hdev->name, evt);
-}
-
-static int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
-{
- struct usb_device *udev = interface_to_usbdev(intf);
- struct usb_host_endpoint *bulk_out_ep = NULL;
- struct usb_host_endpoint *bulk_in_ep = NULL;
- struct usb_host_endpoint *intr_in_ep = NULL;
- struct usb_host_endpoint *ep;
- struct usb_host_interface *uif;
- struct usb_interface *isoc_iface;
- struct hci_usb *husb;
- struct hci_dev *hdev;
- int i, e, size, isoc_ifnum, isoc_alts;
-
- BT_DBG("udev %p intf %p", udev, intf);
-
- if (!id->driver_info) {
- const struct usb_device_id *match;
- match = usb_match_id(intf, blacklist_ids);
- if (match)
- id = match;
- }
-
- if (id->driver_info & HCI_IGNORE)
- return -ENODEV;
-
- if (ignore_dga && id->driver_info & HCI_DIGIANSWER)
- return -ENODEV;
-
- if (ignore_csr && id->driver_info & HCI_CSR)
- return -ENODEV;
-
- if (ignore_sniffer && id->driver_info & HCI_SNIFFER)
- return -ENODEV;
-
- if (intf->cur_altsetting->desc.bInterfaceNumber > 0)
- return -ENODEV;
-
- /* Find endpoints that we need */
- uif = intf->cur_altsetting;
- for (e = 0; e < uif->desc.bNumEndpoints; e++) {
- ep = &uif->endpoint[e];
-
- switch (ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
- case USB_ENDPOINT_XFER_INT:
- if (ep->desc.bEndpointAddress & USB_DIR_IN)
- intr_in_ep = ep;
- break;
-
- case USB_ENDPOINT_XFER_BULK:
- if (ep->desc.bEndpointAddress & USB_DIR_IN)
- bulk_in_ep = ep;
- else
- bulk_out_ep = ep;
- break;
- }
- }
-
- if (!bulk_in_ep || !bulk_out_ep || !intr_in_ep) {
- BT_DBG("Bulk endpoints not found");
- goto done;
- }
-
- if (!(husb = kzalloc(sizeof(struct hci_usb), GFP_KERNEL))) {
- BT_ERR("Can't allocate: control structure");
- goto done;
- }
-
- husb->udev = udev;
- husb->bulk_out_ep = bulk_out_ep;
- husb->bulk_in_ep = bulk_in_ep;
- husb->intr_in_ep = intr_in_ep;
-
- if (id->driver_info & HCI_DIGIANSWER)
- husb->ctrl_req = USB_TYPE_VENDOR;
- else
- husb->ctrl_req = USB_TYPE_CLASS;
-
- /* Find isochronous endpoints that we can use */
- size = 0;
- isoc_iface = NULL;
- isoc_alts = 0;
- isoc_ifnum = 1;
-
-#ifdef CONFIG_BT_HCIUSB_SCO
- if (isoc && !(id->driver_info & (HCI_BROKEN_ISOC | HCI_SNIFFER)))
- isoc_iface = usb_ifnum_to_if(udev, isoc_ifnum);
-
- if (isoc_iface) {
- int a;
- struct usb_host_endpoint *isoc_out_ep = NULL;
- struct usb_host_endpoint *isoc_in_ep = NULL;
-
- for (a = 0; a < isoc_iface->num_altsetting; a++) {
- uif = &isoc_iface->altsetting[a];
- for (e = 0; e < uif->desc.bNumEndpoints; e++) {
- ep = &uif->endpoint[e];
-
- switch (ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
- case USB_ENDPOINT_XFER_ISOC:
- if (le16_to_cpu(ep->desc.wMaxPacketSize) < size ||
- uif->desc.bAlternateSetting != isoc)
- break;
- size = le16_to_cpu(ep->desc.wMaxPacketSize);
-
- isoc_alts = uif->desc.bAlternateSetting;
-
- if (ep->desc.bEndpointAddress & USB_DIR_IN)
- isoc_in_ep = ep;
- else
- isoc_out_ep = ep;
- break;
- }
- }
- }
-
- if (!isoc_in_ep || !isoc_out_ep)
- BT_DBG("Isoc endpoints not found");
- else {
- BT_DBG("isoc ifnum %d alts %d", isoc_ifnum, isoc_alts);
- if (usb_driver_claim_interface(&hci_usb_driver, isoc_iface, husb) != 0)
- BT_ERR("Can't claim isoc interface");
- else if (usb_set_interface(udev, isoc_ifnum, isoc_alts)) {
- BT_ERR("Can't set isoc interface settings");
- husb->isoc_iface = isoc_iface;
- usb_driver_release_interface(&hci_usb_driver, isoc_iface);
- husb->isoc_iface = NULL;
- } else {
- husb->isoc_iface = isoc_iface;
- husb->isoc_in_ep = isoc_in_ep;
- husb->isoc_out_ep = isoc_out_ep;
- }
- }
- }
-#endif
-
- rwlock_init(&husb->completion_lock);
-
- for (i = 0; i < 4; i++) {
- skb_queue_head_init(&husb->transmit_q[i]);
- _urb_queue_init(&husb->pending_q[i]);
- _urb_queue_init(&husb->completed_q[i]);
- }
-
- /* Initialize and register HCI device */
- hdev = hci_alloc_dev();
- if (!hdev) {
- BT_ERR("Can't allocate HCI device");
- goto probe_error;
- }
-
- husb->hdev = hdev;
-
- hdev->type = HCI_USB;
- hdev->driver_data = husb;
- SET_HCIDEV_DEV(hdev, &intf->dev);
-
- hdev->open = hci_usb_open;
- hdev->close = hci_usb_close;
- hdev->flush = hci_usb_flush;
- hdev->send = hci_usb_send_frame;
- hdev->destruct = hci_usb_destruct;
- hdev->notify = hci_usb_notify;
-
- hdev->owner = THIS_MODULE;
-
- if (reset || id->driver_info & HCI_RESET)
- set_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks);
-
- if (force_scofix || id->driver_info & HCI_WRONG_SCO_MTU) {
- if (!disable_scofix)
- set_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks);
- }
-
- if (id->driver_info & HCI_SNIFFER) {
- if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x997)
- set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
- }
-
- if (id->driver_info & HCI_BCM92035) {
- unsigned char cmd[] = { 0x3b, 0xfc, 0x01, 0x00 };
- struct sk_buff *skb;
-
- skb = bt_skb_alloc(sizeof(cmd), GFP_KERNEL);
- if (skb) {
- memcpy(skb_put(skb, sizeof(cmd)), cmd, sizeof(cmd));
- skb_queue_tail(&hdev->driver_init, skb);
- }
- }
-
- if (hci_register_dev(hdev) < 0) {
- BT_ERR("Can't register HCI device");
- hci_free_dev(hdev);
- goto probe_error;
- }
-
- usb_set_intfdata(intf, husb);
- return 0;
-
-probe_error:
- if (husb->isoc_iface)
- usb_driver_release_interface(&hci_usb_driver, husb->isoc_iface);
- kfree(husb);
-
-done:
- return -EIO;
-}
-
-static void hci_usb_disconnect(struct usb_interface *intf)
-{
- struct hci_usb *husb = usb_get_intfdata(intf);
- struct hci_dev *hdev;
-
- if (!husb || intf == husb->isoc_iface)
- return;
-
- usb_set_intfdata(intf, NULL);
- hdev = husb->hdev;
-
- BT_DBG("%s", hdev->name);
-
- hci_usb_close(hdev);
-
- if (husb->isoc_iface)
- usb_driver_release_interface(&hci_usb_driver, husb->isoc_iface);
-
- if (hci_unregister_dev(hdev) < 0)
- BT_ERR("Can't unregister HCI device %s", hdev->name);
-
- hci_free_dev(hdev);
-}
-
-static int hci_usb_suspend(struct usb_interface *intf, pm_message_t message)
-{
- struct hci_usb *husb = usb_get_intfdata(intf);
- struct list_head killed;
- unsigned long flags;
- int i;
-
- if (!husb || intf == husb->isoc_iface)
- return 0;
-
- hci_suspend_dev(husb->hdev);
-
- INIT_LIST_HEAD(&killed);
-
- for (i = 0; i < 4; i++) {
- struct _urb_queue *q = &husb->pending_q[i];
- struct _urb *_urb, *_tmp;
-
- while ((_urb = _urb_dequeue(q))) {
- /* reset queue since _urb_dequeue sets it to NULL */
- _urb->queue = q;
- usb_kill_urb(&_urb->urb);
- list_add(&_urb->list, &killed);
- }
-
- spin_lock_irqsave(&q->lock, flags);
-
- list_for_each_entry_safe(_urb, _tmp, &killed, list) {
- list_move_tail(&_urb->list, &q->head);
- }
-
- spin_unlock_irqrestore(&q->lock, flags);
- }
-
- return 0;
-}
-
-static int hci_usb_resume(struct usb_interface *intf)
-{
- struct hci_usb *husb = usb_get_intfdata(intf);
- unsigned long flags;
- int i, err = 0;
-
- if (!husb || intf == husb->isoc_iface)
- return 0;
-
- for (i = 0; i < 4; i++) {
- struct _urb_queue *q = &husb->pending_q[i];
- struct _urb *_urb;
-
- spin_lock_irqsave(&q->lock, flags);
-
- list_for_each_entry(_urb, &q->head, list) {
- err = usb_submit_urb(&_urb->urb, GFP_ATOMIC);
- if (err)
- break;
- }
-
- spin_unlock_irqrestore(&q->lock, flags);
-
- if (err)
- return -EIO;
- }
-
- hci_resume_dev(husb->hdev);
-
- return 0;
-}
-
-static struct usb_driver hci_usb_driver = {
- .name = "hci_usb",
- .probe = hci_usb_probe,
- .disconnect = hci_usb_disconnect,
- .suspend = hci_usb_suspend,
- .resume = hci_usb_resume,
- .id_table = bluetooth_ids,
-};
-
-static int __init hci_usb_init(void)
-{
- int err;
-
- BT_INFO("HCI USB driver ver %s", VERSION);
-
- if ((err = usb_register(&hci_usb_driver)) < 0)
- BT_ERR("Failed to register HCI USB driver");
-
- return err;
-}
-
-static void __exit hci_usb_exit(void)
-{
- usb_deregister(&hci_usb_driver);
-}
-
-module_init(hci_usb_init);
-module_exit(hci_usb_exit);
-
-module_param(ignore_dga, bool, 0644);
-MODULE_PARM_DESC(ignore_dga, "Ignore devices with id 08fd:0001");
-
-module_param(ignore_csr, bool, 0644);
-MODULE_PARM_DESC(ignore_csr, "Ignore devices with id 0a12:0001");
-
-module_param(ignore_sniffer, bool, 0644);
-MODULE_PARM_DESC(ignore_sniffer, "Ignore devices with id 0a12:0002");
-
-module_param(disable_scofix, bool, 0644);
-MODULE_PARM_DESC(disable_scofix, "Disable fixup of wrong SCO buffer size");
-
-module_param(force_scofix, bool, 0644);
-MODULE_PARM_DESC(force_scofix, "Force fixup of wrong SCO buffers size");
-
-module_param(reset, bool, 0644);
-MODULE_PARM_DESC(reset, "Send HCI reset command on initialization");
-
-#ifdef CONFIG_BT_HCIUSB_SCO
-module_param(isoc, int, 0644);
-MODULE_PARM_DESC(isoc, "Set isochronous transfers for SCO over HCI support");
-#endif
-
-MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
-MODULE_DESCRIPTION("Bluetooth HCI USB driver ver " VERSION);
-MODULE_VERSION(VERSION);
-MODULE_LICENSE("GPL");
diff --git a/drivers/bluetooth/hci_usb.h b/drivers/bluetooth/hci_usb.h
deleted file mode 100644
index 8e65991..0000000
--- a/drivers/bluetooth/hci_usb.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- HCI USB driver for Linux Bluetooth protocol stack (BlueZ)
- Copyright (C) 2000-2001 Qualcomm Incorporated
- Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
-
- Copyright (C) 2003 Maxim Krasnyansky <maxk@qualcomm.com>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License version 2 as
- published by the Free Software Foundation;
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
- IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
- CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
- ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
- COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
- SOFTWARE IS DISCLAIMED.
-*/
-
-/* Class, SubClass, and Protocol codes that describe a Bluetooth device */
-#define HCI_DEV_CLASS 0xe0 /* Wireless class */
-#define HCI_DEV_SUBCLASS 0x01 /* RF subclass */
-#define HCI_DEV_PROTOCOL 0x01 /* Bluetooth programming protocol */
-
-#define HCI_IGNORE 0x01
-#define HCI_RESET 0x02
-#define HCI_DIGIANSWER 0x04
-#define HCI_CSR 0x08
-#define HCI_SNIFFER 0x10
-#define HCI_BCM92035 0x20
-#define HCI_BROKEN_ISOC 0x40
-#define HCI_WRONG_SCO_MTU 0x80
-
-#define HCI_MAX_IFACE_NUM 3
-
-#define HCI_MAX_BULK_TX 4
-#define HCI_MAX_BULK_RX 1
-
-#define HCI_MAX_ISOC_RX 2
-#define HCI_MAX_ISOC_TX 2
-
-#define HCI_MAX_ISOC_FRAMES 10
-
-struct _urb_queue {
- struct list_head head;
- spinlock_t lock;
-};
-
-struct _urb {
- struct list_head list;
- struct _urb_queue *queue;
- int type;
- void *priv;
- struct urb urb;
-};
-
-static inline void _urb_queue_init(struct _urb_queue *q)
-{
- INIT_LIST_HEAD(&q->head);
- spin_lock_init(&q->lock);
-}
-
-static inline void _urb_queue_head(struct _urb_queue *q, struct _urb *_urb)
-{
- unsigned long flags;
- spin_lock_irqsave(&q->lock, flags);
- /* _urb_unlink needs to know which spinlock to use, thus smp_mb(). */
- _urb->queue = q; smp_mb(); list_add(&_urb->list, &q->head);
- spin_unlock_irqrestore(&q->lock, flags);
-}
-
-static inline void _urb_queue_tail(struct _urb_queue *q, struct _urb *_urb)
-{
- unsigned long flags;
- spin_lock_irqsave(&q->lock, flags);
- /* _urb_unlink needs to know which spinlock to use, thus smp_mb(). */
- _urb->queue = q; smp_mb(); list_add_tail(&_urb->list, &q->head);
- spin_unlock_irqrestore(&q->lock, flags);
-}
-
-static inline void _urb_unlink(struct _urb *_urb)
-{
- struct _urb_queue *q;
- unsigned long flags;
-
- smp_mb();
- q = _urb->queue;
- /* If q is NULL, it will die at easy-to-debug NULL pointer dereference.
- No need to BUG(). */
- spin_lock_irqsave(&q->lock, flags);
- list_del(&_urb->list); _urb->queue = NULL;
- spin_unlock_irqrestore(&q->lock, flags);
-}
-
-struct hci_usb {
- struct hci_dev *hdev;
-
- unsigned long state;
-
- struct usb_device *udev;
-
- struct usb_host_endpoint *bulk_in_ep;
- struct usb_host_endpoint *bulk_out_ep;
- struct usb_host_endpoint *intr_in_ep;
-
- struct usb_interface *isoc_iface;
- struct usb_host_endpoint *isoc_out_ep;
- struct usb_host_endpoint *isoc_in_ep;
-
- __u8 ctrl_req;
-
- struct sk_buff_head transmit_q[4];
-
- rwlock_t completion_lock;
-
- atomic_t pending_tx[4]; /* Number of pending requests */
- struct _urb_queue pending_q[4]; /* Pending requests */
- struct _urb_queue completed_q[4]; /* Completed requests */
-};
-
-/* States */
-#define HCI_USB_TX_PROCESS 1
-#define HCI_USB_TX_WAKEUP 2
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c
index 7320a71..0bbefba 100644
--- a/drivers/bluetooth/hci_vhci.c
+++ b/drivers/bluetooth/hci_vhci.c
@@ -40,11 +40,6 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
-#ifndef CONFIG_BT_HCIVHCI_DEBUG
-#undef BT_DBG
-#define BT_DBG(D...)
-#endif
-
#define VERSION "1.2"
static int minor = MISC_DYNAMIC_MINOR;
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index 996d12d..a04f846 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -54,8 +54,8 @@
#define SOL_RFCOMM 18
#define BT_INFO(fmt, arg...) printk(KERN_INFO "Bluetooth: " fmt "\n" , ## arg)
-#define BT_DBG(fmt, arg...) printk(KERN_INFO "%s: " fmt "\n" , __func__ , ## arg)
-#define BT_ERR(fmt, arg...) printk(KERN_ERR "%s: " fmt "\n" , __func__ , ## arg)
+#define BT_ERR(fmt, arg...) printk(KERN_ERR "%s: " fmt "\n" , __func__ , ## arg)
+#define BT_DBG(fmt, arg...) pr_debug("%s: " fmt "\n" , __func__ , ## arg)
/* Connection and socket states */
enum {
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 3cc2949..3645139 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -54,7 +54,7 @@
/* HCI device quirks */
enum {
- HCI_QUIRK_RESET_ON_INIT,
+ HCI_QUIRK_NO_RESET,
HCI_QUIRK_RAW_DEVICE,
HCI_QUIRK_FIXUP_BUFFER_SIZE
};
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
index 8f9431a..744ed3f 100644
--- a/net/bluetooth/af_bluetooth.c
+++ b/net/bluetooth/af_bluetooth.c
@@ -41,18 +41,14 @@
#include <net/bluetooth/bluetooth.h>
-#ifndef CONFIG_BT_SOCK_DEBUG
-#undef BT_DBG
-#define BT_DBG(D...)
-#endif
-
-#define VERSION "2.13"
+#define VERSION "2.14"
/* Bluetooth sockets */
#define BT_MAX_PROTO 8
static struct net_proto_family *bt_proto[BT_MAX_PROTO];
+static DEFINE_RWLOCK(bt_proto_lock);
-static struct lock_class_key bt_slock_key[BT_MAX_PROTO];
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
static struct lock_class_key bt_lock_key[BT_MAX_PROTO];
static const char *bt_key_strings[BT_MAX_PROTO] = {
"sk_lock-AF_BLUETOOTH-BTPROTO_L2CAP",
@@ -65,6 +61,7 @@ static const char *bt_key_strings[BT_MAX_PROTO] = {
"sk_lock-AF_BLUETOOTH-BTPROTO_AVDTP",
};
+static struct lock_class_key bt_slock_key[BT_MAX_PROTO];
static const char *bt_slock_key_strings[BT_MAX_PROTO] = {
"slock-AF_BLUETOOTH-BTPROTO_L2CAP",
"slock-AF_BLUETOOTH-BTPROTO_HCI",
@@ -75,7 +72,25 @@ static const char *bt_slock_key_strings[BT_MAX_PROTO] = {
"slock-AF_BLUETOOTH-BTPROTO_HIDP",
"slock-AF_BLUETOOTH-BTPROTO_AVDTP",
};
-static DEFINE_RWLOCK(bt_proto_lock);
+
+static inline void bt_sock_reclassify_lock(struct socket *sock, int proto)
+{
+ struct sock *sk = sock->sk;
+
+ if (!sk)
+ return;
+
+ BUG_ON(sock_owned_by_user(sk));
+
+ sock_lock_init_class_and_name(sk,
+ bt_slock_key_strings[proto], &bt_slock_key[proto],
+ bt_key_strings[proto], &bt_lock_key[proto]);
+}
+#else
+static inline void bt_sock_reclassify_lock(struct socket *sock, int proto)
+{
+}
+#endif
int bt_sock_register(int proto, struct net_proto_family *ops)
{
@@ -117,21 +132,6 @@ int bt_sock_unregister(int proto)
}
EXPORT_SYMBOL(bt_sock_unregister);
-static void bt_reclassify_sock_lock(struct socket *sock, int proto)
-{
- struct sock *sk = sock->sk;
-
- if (!sk)
- return;
- BUG_ON(sock_owned_by_user(sk));
-
- sock_lock_init_class_and_name(sk,
- bt_slock_key_strings[proto],
- &bt_slock_key[proto],
- bt_key_strings[proto],
- &bt_lock_key[proto]);
-}
-
static int bt_sock_create(struct net *net, struct socket *sock, int proto)
{
int err;
@@ -151,7 +151,7 @@ static int bt_sock_create(struct net *net, struct socket *sock, int proto)
if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) {
err = bt_proto[proto]->create(net, sock, proto);
- bt_reclassify_sock_lock(sock, proto);
+ bt_sock_reclassify_lock(sock, proto);
module_put(bt_proto[proto]->owner);
}
@@ -240,7 +240,7 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
size_t copied;
int err;
- BT_DBG("sock %p sk %p len %d", sock, sk, len);
+ BT_DBG("sock %p sk %p len %zu", sock, sk, len);
if (flags & (MSG_OOB))
return -EOPNOTSUPP;
diff --git a/net/bluetooth/bnep/bnep.h b/net/bluetooth/bnep/bnep.h
index b69bf4e..d20f8a4 100644
--- a/net/bluetooth/bnep/bnep.h
+++ b/net/bluetooth/bnep/bnep.h
@@ -161,7 +161,7 @@ struct bnep_session {
struct msghdr msg;
struct bnep_proto_filter proto_filter[BNEP_MAX_PROTO_FILTERS];
- u64 mc_filter;
+ unsigned long long mc_filter;
struct socket *sock;
struct net_device *dev;
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
index f8efaf3..70fea8b 100644
--- a/net/bluetooth/bnep/core.c
+++ b/net/bluetooth/bnep/core.c
@@ -52,11 +52,6 @@
#include "bnep.h"
-#ifndef CONFIG_BT_BNEP_DEBUG
-#undef BT_DBG
-#define BT_DBG(D...)
-#endif
-
#define VERSION "1.3"
static int compress_src = 1;
diff --git a/net/bluetooth/bnep/netdev.c b/net/bluetooth/bnep/netdev.c
index 47e179f..f897da6 100644
--- a/net/bluetooth/bnep/netdev.c
+++ b/net/bluetooth/bnep/netdev.c
@@ -41,11 +41,6 @@
#include "bnep.h"
-#ifndef CONFIG_BT_BNEP_DEBUG
-#undef BT_DBG
-#define BT_DBG( A... )
-#endif
-
#define BNEP_TX_QUEUE_LEN 20
static int bnep_net_open(struct net_device *dev)
diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c
index 8ffb57f..e857628 100644
--- a/net/bluetooth/bnep/sock.c
+++ b/net/bluetooth/bnep/sock.c
@@ -46,11 +46,6 @@
#include "bnep.h"
-#ifndef CONFIG_BT_BNEP_DEBUG
-#undef BT_DBG
-#define BT_DBG( A... )
-#endif
-
static int bnep_sock_release(struct socket *sock)
{
struct sock *sk = sock->sk;
diff --git a/net/bluetooth/cmtp/capi.c b/net/bluetooth/cmtp/capi.c
index 3e9d5bb..78958c0 100644
--- a/net/bluetooth/cmtp/capi.c
+++ b/net/bluetooth/cmtp/capi.c
@@ -42,11 +42,6 @@
#include "cmtp.h"
-#ifndef CONFIG_BT_CMTP_DEBUG
-#undef BT_DBG
-#define BT_DBG(D...)
-#endif
-
#define CAPI_INTEROPERABILITY 0x20
#define CAPI_INTEROPERABILITY_REQ CAPICMD(CAPI_INTEROPERABILITY, CAPI_REQ)
diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c
index ca60a451..c9cac77 100644
--- a/net/bluetooth/cmtp/core.c
+++ b/net/bluetooth/cmtp/core.c
@@ -44,11 +44,6 @@
#include "cmtp.h"
-#ifndef CONFIG_BT_CMTP_DEBUG
-#undef BT_DBG
-#define BT_DBG(D...)
-#endif
-
#define VERSION "1.0"
static DECLARE_RWSEM(cmtp_session_sem);
diff --git a/net/bluetooth/cmtp/sock.c b/net/bluetooth/cmtp/sock.c
index 8c7f7bc..16b0fad 100644
--- a/net/bluetooth/cmtp/sock.c
+++ b/net/bluetooth/cmtp/sock.c
@@ -43,11 +43,6 @@
#include "cmtp.h"
-#ifndef CONFIG_BT_CMTP_DEBUG
-#undef BT_DBG
-#define BT_DBG(D...)
-#endif
-
static int cmtp_sock_release(struct socket *sock)
{
struct sock *sk = sock->sk;
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index b700242..a4a789f 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -45,11 +45,6 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
-#ifndef CONFIG_BT_HCI_CORE_DEBUG
-#undef BT_DBG
-#define BT_DBG(D...)
-#endif
-
void hci_acl_connect(struct hci_conn *conn)
{
struct hci_dev *hdev = conn->hdev;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 278a3ac..ba78cc1 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -48,11 +48,6 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
-#ifndef CONFIG_BT_HCI_CORE_DEBUG
-#undef BT_DBG
-#define BT_DBG(D...)
-#endif
-
static void hci_cmd_task(unsigned long arg);
static void hci_rx_task(unsigned long arg);
static void hci_tx_task(unsigned long arg);
@@ -205,7 +200,7 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt)
/* Mandatory initialization */
/* Reset */
- if (test_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks))
+ if (!test_bit(HCI_QUIRK_NO_RESET, &hdev->quirks))
hci_send_cmd(hdev, HCI_OP_RESET, 0, NULL);
/* Read Local Supported Features */
@@ -290,7 +285,7 @@ static void hci_linkpol_req(struct hci_dev *hdev, unsigned long opt)
{
__le16 policy = cpu_to_le16(opt);
- BT_DBG("%s %x", hdev->name, opt);
+ BT_DBG("%s %x", hdev->name, policy);
/* Default link policy */
hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, 2, &policy);
@@ -756,7 +751,7 @@ int hci_get_dev_list(void __user *arg)
size = sizeof(*dl) + dev_num * sizeof(*dr);
- if (!(dl = kmalloc(size, GFP_KERNEL)))
+ if (!(dl = kzalloc(size, GFP_KERNEL)))
return -ENOMEM;
dr = dl->dev_req;
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index ad7a553..f91ba69 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -45,11 +45,6 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
-#ifndef CONFIG_BT_HCI_CORE_DEBUG
-#undef BT_DBG
-#define BT_DBG(D...)
-#endif
-
/* Handle HCI Event packets */
static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index d62579b..4f9621f 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -49,11 +49,6 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
-#ifndef CONFIG_BT_HCI_SOCK_DEBUG
-#undef BT_DBG
-#define BT_DBG(D...)
-#endif
-
/* ----- HCI socket interface ----- */
static inline int hci_test_bit(int nr, void *addr)
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index f2bbb2f..1a1f916 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -6,11 +6,6 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
-#ifndef CONFIG_BT_HCI_CORE_DEBUG
-#undef BT_DBG
-#define BT_DBG(D...)
-#endif
-
struct class *bt_class = NULL;
EXPORT_SYMBOL_GPL(bt_class);
@@ -420,7 +415,7 @@ int hci_register_sysfs(struct hci_dev *hdev)
dev->class = bt_class;
dev->parent = hdev->parent;
- dev_set_name(dev, hdev->name);
+ dev_set_name(dev, "%s", hdev->name);
dev_set_drvdata(dev, hdev);
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index acdeab3..b186768 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -47,11 +47,6 @@
#include "hidp.h"
-#ifndef CONFIG_BT_HIDP_DEBUG
-#undef BT_DBG
-#define BT_DBG(D...)
-#endif
-
#define VERSION "1.2"
static DECLARE_RWSEM(hidp_session_sem);
diff --git a/net/bluetooth/hidp/sock.c b/net/bluetooth/hidp/sock.c
index f4dd02c..37c9d7d 100644
--- a/net/bluetooth/hidp/sock.c
+++ b/net/bluetooth/hidp/sock.c
@@ -39,11 +39,6 @@
#include "hidp.h"
-#ifndef CONFIG_BT_HIDP_DEBUG
-#undef BT_DBG
-#define BT_DBG(D...)
-#endif
-
static int hidp_sock_release(struct socket *sock)
{
struct sock *sk = sock->sk;
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 9610a9c..b93748e 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -50,11 +50,6 @@
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/l2cap.h>
-#ifndef CONFIG_BT_L2CAP_DEBUG
-#undef BT_DBG
-#define BT_DBG(D...)
-#endif
-
#define VERSION "2.11"
static u32 l2cap_feat_mask = 0x0000;
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index ba537fa..37c640d 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -46,11 +46,6 @@
#include <net/bluetooth/l2cap.h>
#include <net/bluetooth/rfcomm.h>
-#ifndef CONFIG_BT_RFCOMM_DEBUG
-#undef BT_DBG
-#define BT_DBG(D...)
-#endif
-
#define VERSION "1.10"
static int disable_cfc = 0;
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index bc0d4a7..ad00cbf 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -50,11 +50,6 @@
#include <net/bluetooth/l2cap.h>
#include <net/bluetooth/rfcomm.h>
-#ifndef CONFIG_BT_RFCOMM_DEBUG
-#undef BT_DBG
-#define BT_DBG(D...)
-#endif
-
static const struct proto_ops rfcomm_sock_ops;
static struct bt_sock_list rfcomm_sk_list = {
@@ -644,7 +639,7 @@ static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
msg->msg_namelen = 0;
- BT_DBG("sk %p size %d", sk, size);
+ BT_DBG("sk %p size %zu", sk, size);
lock_sock(sk);
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index d3340dd..111c6c8 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -39,11 +39,6 @@
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/rfcomm.h>
-#ifndef CONFIG_BT_RFCOMM_DEBUG
-#undef BT_DBG
-#define BT_DBG(D...)
-#endif
-
#define RFCOMM_TTY_MAGIC 0x6d02 /* magic number for rfcomm struct */
#define RFCOMM_TTY_PORTS RFCOMM_MAX_DEV /* whole lotta rfcomm devices */
#define RFCOMM_TTY_MAJOR 216 /* device node major id of the usb/bluetooth.c driver */
@@ -58,7 +53,7 @@ struct rfcomm_dev {
char name[12];
int id;
unsigned long flags;
- int opened;
+ atomic_t opened;
int err;
bdaddr_t src;
@@ -261,6 +256,8 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
dev->flags = req->flags &
((1 << RFCOMM_RELEASE_ONHUP) | (1 << RFCOMM_REUSE_DLC));
+ atomic_set(&dev->opened, 0);
+
init_waitqueue_head(&dev->wait);
tasklet_init(&dev->wakeup_task, rfcomm_tty_wakeup, (unsigned long) dev);
@@ -330,10 +327,10 @@ static void rfcomm_dev_del(struct rfcomm_dev *dev)
{
BT_DBG("dev %p", dev);
- if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags))
- BUG_ON(1);
- else
- set_bit(RFCOMM_TTY_RELEASED, &dev->flags);
+ BUG_ON(test_and_set_bit(RFCOMM_TTY_RELEASED, &dev->flags));
+
+ if (atomic_read(&dev->opened) > 0)
+ return;
write_lock_bh(&rfcomm_dev_lock);
list_del_init(&dev->list);
@@ -689,9 +686,10 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
if (!dev)
return -ENODEV;
- BT_DBG("dev %p dst %s channel %d opened %d", dev, batostr(&dev->dst), dev->channel, dev->opened);
+ BT_DBG("dev %p dst %s channel %d opened %d", dev, batostr(&dev->dst),
+ dev->channel, atomic_read(&dev->opened));
- if (dev->opened++ != 0)
+ if (atomic_inc_return(&dev->opened) > 1)
return 0;
dlc = dev->dlc;
@@ -747,9 +745,10 @@ static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp)
if (!dev)
return;
- BT_DBG("tty %p dev %p dlc %p opened %d", tty, dev, dev->dlc, dev->opened);
+ BT_DBG("tty %p dev %p dlc %p opened %d", tty, dev, dev->dlc,
+ atomic_read(&dev->opened));
- if (--dev->opened == 0) {
+ if (atomic_dec_and_test(&dev->opened)) {
if (dev->tty_dev->parent)
device_move(dev->tty_dev, NULL);
@@ -763,6 +762,14 @@ static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp)
tty->driver_data = NULL;
dev->tty = NULL;
rfcomm_dlc_unlock(dev->dlc);
+
+ if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) {
+ write_lock_bh(&rfcomm_dev_lock);
+ list_del_init(&dev->list);
+ write_unlock_bh(&rfcomm_dev_lock);
+
+ rfcomm_dev_put(dev);
+ }
}
rfcomm_dev_put(dev);
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 0cc91e6..46fd8bf 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -48,11 +48,6 @@
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/sco.h>
-#ifndef CONFIG_BT_SCO_DEBUG
-#undef BT_DBG
-#define BT_DBG(D...)
-#endif
-
#define VERSION "0.6"
static int disable_esco = 0;
OpenPOWER on IntegriCloud