summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--drivers/bluetooth/Kconfig20
-rw-r--r--drivers/bluetooth/Makefile1
-rw-r--r--drivers/bluetooth/bpa10x.c2
-rw-r--r--drivers/bluetooth/btmrvl_sdio.c4
-rw-r--r--drivers/bluetooth/btrsi.c1
-rw-r--r--drivers/bluetooth/btuart_cs.c675
-rw-r--r--drivers/bluetooth/btusb.c4
-rw-r--r--drivers/bluetooth/h4_recv.h160
-rw-r--r--drivers/bluetooth/hci_bcm.c305
-rw-r--r--drivers/bluetooth/hci_ll.c222
-rw-r--r--include/net/bluetooth/mgmt.h2
-rw-r--r--net/bluetooth/mgmt.c1
-rw-r--r--net/bluetooth/rfcomm/sock.c1
13 files changed, 473 insertions, 925 deletions
diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
index 149a38ee1fce..010f5f579e68 100644
--- a/drivers/bluetooth/Kconfig
+++ b/drivers/bluetooth/Kconfig
@@ -147,6 +147,7 @@ config BT_HCIUART_ATH3K
 config BT_HCIUART_LL
 	bool "HCILL protocol support"
 	depends on BT_HCIUART_SERDEV
+	select BT_HCIUART_H4
 	help
 	  HCILL (HCI Low Level) is a serial protocol for communication
 	  between Bluetooth device and host. This protocol is required for
@@ -242,8 +243,7 @@ config BT_HCIBCM203X
 
 config BT_HCIBPA10X
 	tristate "HCI BPA10x USB driver"
-	depends on USB && BT_HCIUART
-	select BT_HCIUART_H4
+	depends on USB
 	help
 	  Bluetooth HCI BPA10x USB driver.
 	  This driver provides support for the Digianswer BPA 100/105 Bluetooth
@@ -305,22 +305,6 @@ config BT_HCIBLUECARD
 	  Say Y here to compile support for HCI BlueCard devices into the
 	  kernel or say M to compile it as module (bluecard_cs).
 
-config BT_HCIBTUART
-	tristate "HCI UART (PC Card) device driver"
-	depends on PCMCIA
-	help
-	  Bluetooth HCI UART (PC Card) driver.
-	  This driver provides support for Bluetooth PCMCIA devices with
-	  an UART interface:
-	     Xircom CreditCard Bluetooth Adapter
-	     Xircom RealPort2 Bluetooth Adapter
-	     Sphinx PICO Card
-	     H-Soft blue+Card
-	     Cyber-blue Compact Flash Card
-
-	  Say Y here to compile support for HCI UART devices into the
-	  kernel or say M to compile it as module (btuart_cs).
-
 config BT_HCIVHCI
 	tristate "HCI VHCI (Virtual HCI device) driver"
 	help
diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile
index 03cfc1b20c4a..ec16c55eb6e9 100644
--- a/drivers/bluetooth/Makefile
+++ b/drivers/bluetooth/Makefile
@@ -11,7 +11,6 @@ obj-$(CONFIG_BT_HCIBFUSB)	+= bfusb.o
 obj-$(CONFIG_BT_HCIDTL1)	+= dtl1_cs.o
 obj-$(CONFIG_BT_HCIBT3C)	+= bt3c_cs.o
 obj-$(CONFIG_BT_HCIBLUECARD)	+= bluecard_cs.o
-obj-$(CONFIG_BT_HCIBTUART)	+= btuart_cs.o
 
 obj-$(CONFIG_BT_HCIBTUSB)	+= btusb.o
 obj-$(CONFIG_BT_HCIBTSDIO)	+= btsdio.o
diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c
index 801ea4ca65e4..c6f7cc57db14 100644
--- a/drivers/bluetooth/bpa10x.c
+++ b/drivers/bluetooth/bpa10x.c
@@ -35,7 +35,7 @@
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 
-#include "hci_uart.h"
+#include "h4_recv.h"
 
 #define VERSION "0.11"
 
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
index 7dbb4463b539..6f99b9f3d57f 100644
--- a/drivers/bluetooth/btmrvl_sdio.c
+++ b/drivers/bluetooth/btmrvl_sdio.c
@@ -689,7 +689,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
 	int ret, num_blocks, blksz;
 	struct sk_buff *skb = NULL;
 	u32 type;
-	u8 *payload = NULL;
+	u8 *payload;
 	struct hci_dev *hdev = priv->btmrvl_dev.hcidev;
 	struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
 
@@ -920,7 +920,7 @@ static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)
 {
 	struct sdio_func *func;
 	u8 reg;
-	int ret = 0;
+	int ret;
 
 	if (!card || !card->func) {
 		BT_ERR("Error: card or function is NULL!");
diff --git a/drivers/bluetooth/btrsi.c b/drivers/bluetooth/btrsi.c
index 5034325e417c..60d1419590ba 100644
--- a/drivers/bluetooth/btrsi.c
+++ b/drivers/bluetooth/btrsi.c
@@ -13,7 +13,6 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <net/bluetooth/bluetooth.h>
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c
deleted file mode 100644
index 310e9c2e09b6..000000000000
--- a/drivers/bluetooth/btuart_cs.c
+++ /dev/null
@@ -1,675 +0,0 @@
-/*
- *
- *  Driver for Bluetooth PCMCIA cards with HCI UART interface
- *
- *  Copyright (C) 2001-2002  Marcel Holtmann <marcel@holtmann.org>
- *
- *
- *  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;
- *
- *  Software distributed under the License is distributed on an "AS
- *  IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- *  implied. See the License for the specific language governing
- *  rights and limitations under the License.
- *
- *  The initial developer of the original code is David A. Hinds
- *  <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
- *  are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
- *
- */
-
-#include <linux/module.h>
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/types.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/spinlock.h>
-#include <linux/moduleparam.h>
-
-#include <linux/skbuff.h>
-#include <linux/string.h>
-#include <linux/serial.h>
-#include <linux/serial_reg.h>
-#include <linux/bitops.h>
-#include <linux/io.h>
-
-#include <pcmcia/cistpl.h>
-#include <pcmcia/ciscode.h>
-#include <pcmcia/ds.h>
-#include <pcmcia/cisreg.h>
-
-#include <net/bluetooth/bluetooth.h>
-#include <net/bluetooth/hci_core.h>
-
-
-
-/* ======================== Module parameters ======================== */
-
-
-MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
-MODULE_DESCRIPTION("Bluetooth driver for Bluetooth PCMCIA cards with HCI UART interface");
-MODULE_LICENSE("GPL");
-
-
-
-/* ======================== Local structures ======================== */
-
-
-struct btuart_info {
-	struct pcmcia_device *p_dev;
-
-	struct hci_dev *hdev;
-
-	spinlock_t lock;	/* For serializing operations */
-
-	struct sk_buff_head txq;
-	unsigned long tx_state;
-
-	unsigned long rx_state;
-	unsigned long rx_count;
-	struct sk_buff *rx_skb;
-};
-
-
-static int btuart_config(struct pcmcia_device *link);
-static void btuart_release(struct pcmcia_device *link);
-
-static void btuart_detach(struct pcmcia_device *p_dev);
-
-
-/* Maximum baud rate */
-#define SPEED_MAX  115200
-
-/* Default baud rate: 57600, 115200, 230400 or 460800 */
-#define DEFAULT_BAUD_RATE  115200
-
-
-/* Transmit states  */
-#define XMIT_SENDING	1
-#define XMIT_WAKEUP	2
-#define XMIT_WAITING	8
-
-/* Receiver states */
-#define RECV_WAIT_PACKET_TYPE	0
-#define RECV_WAIT_EVENT_HEADER	1
-#define RECV_WAIT_ACL_HEADER	2
-#define RECV_WAIT_SCO_HEADER	3
-#define RECV_WAIT_DATA		4
-
-
-
-/* ======================== Interrupt handling ======================== */
-
-
-static int btuart_write(unsigned int iobase, int fifo_size, __u8 *buf, int len)
-{
-	int actual = 0;
-
-	/* Tx FIFO should be empty */
-	if (!(inb(iobase + UART_LSR) & UART_LSR_THRE))
-		return 0;
-
-	/* Fill FIFO with current frame */
-	while ((fifo_size-- > 0) && (actual < len)) {
-		/* Transmit next byte */
-		outb(buf[actual], iobase + UART_TX);
-		actual++;
-	}
-
-	return actual;
-}
-
-
-static void btuart_write_wakeup(struct btuart_info *info)
-{
-	if (!info) {
-		BT_ERR("Unknown device");
-		return;
-	}
-
-	if (test_and_set_bit(XMIT_SENDING, &(info->tx_state))) {
-		set_bit(XMIT_WAKEUP, &(info->tx_state));
-		return;
-	}
-
-	do {
-		unsigned int iobase = info->p_dev->resource[0]->start;
-		register struct sk_buff *skb;
-		int len;
-
-		clear_bit(XMIT_WAKEUP, &(info->tx_state));
-
-		if (!pcmcia_dev_present(info->p_dev))
-			return;
-
-		skb = skb_dequeue(&(info->txq));
-		if (!skb)
-			break;
-
-		/* Send frame */
-		len = btuart_write(iobase, 16, skb->data, skb->len);
-		set_bit(XMIT_WAKEUP, &(info->tx_state));
-
-		if (len == skb->len) {
-			kfree_skb(skb);
-		} else {
-			skb_pull(skb, len);
-			skb_queue_head(&(info->txq), skb);
-		}
-
-		info->hdev->stat.byte_tx += len;
-
-	} while (test_bit(XMIT_WAKEUP, &(info->tx_state)));
-
-	clear_bit(XMIT_SENDING, &(info->tx_state));
-}
-
-
-static void btuart_receive(struct btuart_info *info)
-{
-	unsigned int iobase;
-	int boguscount = 0;
-
-	if (!info) {
-		BT_ERR("Unknown device");
-		return;
-	}
-
-	iobase = info->p_dev->resource[0]->start;
-
-	do {
-		info->hdev->stat.byte_rx++;
-
-		/* Allocate packet */
-		if (!info->rx_skb) {
-			info->rx_state = RECV_WAIT_PACKET_TYPE;
-			info->rx_count = 0;
-			info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
-			if (!info->rx_skb) {
-				BT_ERR("Can't allocate mem for new packet");
-				return;
-			}
-		}
-
-		if (info->rx_state == RECV_WAIT_PACKET_TYPE) {
-
-			hci_skb_pkt_type(info->rx_skb) = inb(iobase + UART_RX);
-
-			switch (hci_skb_pkt_type(info->rx_skb)) {
-
-			case HCI_EVENT_PKT:
-				info->rx_state = RECV_WAIT_EVENT_HEADER;
-				info->rx_count = HCI_EVENT_HDR_SIZE;
-				break;
-
-			case HCI_ACLDATA_PKT:
-				info->rx_state = RECV_WAIT_ACL_HEADER;
-				info->rx_count = HCI_ACL_HDR_SIZE;
-				break;
-
-			case HCI_SCODATA_PKT:
-				info->rx_state = RECV_WAIT_SCO_HEADER;
-				info->rx_count = HCI_SCO_HDR_SIZE;
-				break;
-
-			default:
-				/* Unknown packet */
-				BT_ERR("Unknown HCI packet with type 0x%02x received",
-				       hci_skb_pkt_type(info->rx_skb));
-				info->hdev->stat.err_rx++;
-
-				kfree_skb(info->rx_skb);
-				info->rx_skb = NULL;
-				break;
-
-			}
-
-		} else {
-
-			skb_put_u8(info->rx_skb, inb(iobase + UART_RX));
-			info->rx_count--;
-
-			if (info->rx_count == 0) {
-
-				int dlen;
-				struct hci_event_hdr *eh;
-				struct hci_acl_hdr *ah;
-				struct hci_sco_hdr *sh;
-
-
-				switch (info->rx_state) {
-
-				case RECV_WAIT_EVENT_HEADER:
-					eh = hci_event_hdr(info->rx_skb);
-					info->rx_state = RECV_WAIT_DATA;
-					info->rx_count = eh->plen;
-					break;
-
-				case RECV_WAIT_ACL_HEADER:
-					ah = hci_acl_hdr(info->rx_skb);
-					dlen = __le16_to_cpu(ah->dlen);
-					info->rx_state = RECV_WAIT_DATA;
-					info->rx_count = dlen;
-					break;
-
-				case RECV_WAIT_SCO_HEADER:
-					sh = hci_sco_hdr(info->rx_skb);
-					info->rx_state = RECV_WAIT_DATA;
-					info->rx_count = sh->dlen;
-					break;
-
-				case RECV_WAIT_DATA:
-					hci_recv_frame(info->hdev, info->rx_skb);
-					info->rx_skb = NULL;
-					break;
-
-				}
-
-			}
-
-		}
-
-		/* Make sure we don't stay here too long */
-		if (boguscount++ > 16)
-			break;
-
-	} while (inb(iobase + UART_LSR) & UART_LSR_DR);
-}
-
-
-static irqreturn_t btuart_interrupt(int irq, void *dev_inst)
-{
-	struct btuart_info *info = dev_inst;
-	unsigned int iobase;
-	int boguscount = 0;
-	int iir, lsr;
-	irqreturn_t r = IRQ_NONE;
-
-	if (!info || !info->hdev)
-		/* our irq handler is shared */
-		return IRQ_NONE;
-
-	iobase = info->p_dev->resource[0]->start;
-
-	spin_lock(&(info->lock));
-
-	iir = inb(iobase + UART_IIR) & UART_IIR_ID;
-	while (iir) {
-		r = IRQ_HANDLED;
-
-		/* Clear interrupt */
-		lsr = inb(iobase + UART_LSR);
-
-		switch (iir) {
-		case UART_IIR_RLSI:
-			BT_ERR("RLSI");
-			break;
-		case UART_IIR_RDI:
-			/* Receive interrupt */
-			btuart_receive(info);
-			break;
-		case UART_IIR_THRI:
-			if (lsr & UART_LSR_THRE) {
-				/* Transmitter ready for data */
-				btuart_write_wakeup(info);
-			}
-			break;
-		default:
-			BT_ERR("Unhandled IIR=%#x", iir);
-			break;
-		}
-
-		/* Make sure we don't stay here too long */
-		if (boguscount++ > 100)
-			break;
-
-		iir = inb(iobase + UART_IIR) & UART_IIR_ID;
-
-	}
-
-	spin_unlock(&(info->lock));
-
-	return r;
-}
-
-
-static void btuart_change_speed(struct btuart_info *info,
-				unsigned int speed)
-{
-	unsigned long flags;
-	unsigned int iobase;
-	int fcr;		/* FIFO control reg */
-	int lcr;		/* Line control reg */
-	int divisor;
-
-	if (!info) {
-		BT_ERR("Unknown device");
-		return;
-	}
-
-	iobase = info->p_dev->resource[0]->start;
-
-	spin_lock_irqsave(&(info->lock), flags);
-
-	/* Turn off interrupts */
-	outb(0, iobase + UART_IER);
-
-	divisor = SPEED_MAX / speed;
-
-	fcr = UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT;
-
-	/* 
-	 * Use trigger level 1 to avoid 3 ms. timeout delay at 9600 bps, and
-	 * almost 1,7 ms at 19200 bps. At speeds above that we can just forget
-	 * about this timeout since it will always be fast enough. 
-	 */
-
-	if (speed < 38400)
-		fcr |= UART_FCR_TRIGGER_1;
-	else
-		fcr |= UART_FCR_TRIGGER_14;
-
-	/* Bluetooth cards use 8N1 */
-	lcr = UART_LCR_WLEN8;
-
-	outb(UART_LCR_DLAB | lcr, iobase + UART_LCR);	/* Set DLAB */
-	outb(divisor & 0xff, iobase + UART_DLL);	/* Set speed */
-	outb(divisor >> 8, iobase + UART_DLM);
-	outb(lcr, iobase + UART_LCR);	/* Set 8N1  */
-	outb(fcr, iobase + UART_FCR);	/* Enable FIFO's */
-
-	/* Turn on interrupts */
-	outb(UART_IER_RLSI | UART_IER_RDI | UART_IER_THRI, iobase + UART_IER);
-
-	spin_unlock_irqrestore(&(info->lock), flags);
-}
-
-
-
-/* ======================== HCI interface ======================== */
-
-
-static int btuart_hci_flush(struct hci_dev *hdev)
-{
-	struct btuart_info *info = hci_get_drvdata(hdev);
-
-	/* Drop TX queue */
-	skb_queue_purge(&(info->txq));
-
-	return 0;
-}
-
-
-static int btuart_hci_open(struct hci_dev *hdev)
-{
-	return 0;
-}
-
-
-static int btuart_hci_close(struct hci_dev *hdev)
-{
-	btuart_hci_flush(hdev);
-
-	return 0;
-}
-
-
-static int btuart_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
-{
-	struct btuart_info *info = hci_get_drvdata(hdev);
-
-	switch (hci_skb_pkt_type(skb)) {
-	case HCI_COMMAND_PKT:
-		hdev->stat.cmd_tx++;
-		break;
-	case HCI_ACLDATA_PKT:
-		hdev->stat.acl_tx++;
-		break;
-	case HCI_SCODATA_PKT:
-		hdev->stat.sco_tx++;
-		break;
-	}
-
-	/* Prepend skb with frame type */
-	memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1);
-	skb_queue_tail(&(info->txq), skb);
-
-	btuart_write_wakeup(info);
-
-	return 0;
-}
-
-
-
-/* ======================== Card services HCI interaction ======================== */
-
-
-static int btuart_open(struct btuart_info *info)
-{
-	unsigned long flags;
-	unsigned int iobase = info->p_dev->resource[0]->start;
-	struct hci_dev *hdev;
-
-	spin_lock_init(&(info->lock));
-
-	skb_queue_head_init(&(info->txq));
-
-	info->rx_state = RECV_WAIT_PACKET_TYPE;
-	info->rx_count = 0;
-	info->rx_skb = NULL;
-
-	/* Initialize HCI device */
-	hdev = hci_alloc_dev();
-	if (!hdev) {
-		BT_ERR("Can't allocate HCI device");
-		return -ENOMEM;
-	}
-
-	info->hdev = hdev;
-
-	hdev->bus = HCI_PCCARD;
-	hci_set_drvdata(hdev, info);
-	SET_HCIDEV_DEV(hdev, &info->p_dev->dev);
-
-	hdev->open  = btuart_hci_open;
-	hdev->close = btuart_hci_close;
-	hdev->flush = btuart_hci_flush;
-	hdev->send  = btuart_hci_send_frame;
-
-	spin_lock_irqsave(&(info->lock), flags);
-
-	/* Reset UART */
-	outb(0, iobase + UART_MCR);
-
-	/* Turn off interrupts */
-	outb(0, iobase + UART_IER);
-
-	/* Initialize UART */
-	outb(UART_LCR_WLEN8, iobase + UART_LCR);	/* Reset DLAB */
-	outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase + UART_MCR);
-
-	/* Turn on interrupts */
-	// outb(UART_IER_RLSI | UART_IER_RDI | UART_IER_THRI, iobase + UART_IER);
-
-	spin_unlock_irqrestore(&(info->lock), flags);
-
-	btuart_change_speed(info, DEFAULT_BAUD_RATE);
-
-	/* Timeout before it is safe to send the first HCI packet */
-	msleep(1000);
-
-	/* Register HCI device */
-	if (hci_register_dev(hdev) < 0) {
-		BT_ERR("Can't register HCI device");
-		info->hdev = NULL;
-		hci_free_dev(hdev);
-		return -ENODEV;
-	}
-
-	return 0;
-}
-
-
-static int btuart_close(struct btuart_info *info)
-{
-	unsigned long flags;
-	unsigned int iobase = info->p_dev->resource[0]->start;
-	struct hci_dev *hdev = info->hdev;
-
-	if (!hdev)
-		return -ENODEV;
-
-	btuart_hci_close(hdev);
-
-	spin_lock_irqsave(&(info->lock), flags);
-
-	/* Reset UART */
-	outb(0, iobase + UART_MCR);
-
-	/* Turn off interrupts */
-	outb(0, iobase + UART_IER);
-
-	spin_unlock_irqrestore(&(info->lock), flags);
-
-	hci_unregister_dev(hdev);
-	hci_free_dev(hdev);
-
-	return 0;
-}
-
-static int btuart_probe(struct pcmcia_device *link)
-{
-	struct btuart_info *info;
-
-	/* Create new info device */
-	info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL);
-	if (!info)
-		return -ENOMEM;
-
-	info->p_dev = link;
-	link->priv = info;
-
-	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
-		CONF_AUTO_SET_IO;
-
-	return btuart_config(link);
-}
-
-
-static void btuart_detach(struct pcmcia_device *link)
-{
-	btuart_release(link);
-}
-
-static int btuart_check_config(struct pcmcia_device *p_dev, void *priv_data)
-{
-	int *try = priv_data;
-
-	if (!try)
-		p_dev->io_lines = 16;
-
-	if ((p_dev->resource[0]->end != 8) || (p_dev->resource[0]->start == 0))
-		return -EINVAL;
-
-	p_dev->resource[0]->end = 8;
-	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-
-	return pcmcia_request_io(p_dev);
-}
-
-static int btuart_check_config_notpicky(struct pcmcia_device *p_dev,
-					void *priv_data)
-{
-	static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
-	int j;
-
-	if (p_dev->io_lines > 3)
-		return -ENODEV;
-
-	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-	p_dev->resource[0]->end = 8;
-
-	for (j = 0; j < 5; j++) {
-		p_dev->resource[0]->start = base[j];
-		p_dev->io_lines = base[j] ? 16 : 3;
-		if (!pcmcia_request_io(p_dev))
-			return 0;
-	}
-	return -ENODEV;
-}
-
-static int btuart_config(struct pcmcia_device *link)
-{
-	struct btuart_info *info = link->priv;
-	int i;
-	int try;
-
-	/* First pass: look for a config entry that looks normal.
-	 * Two tries: without IO aliases, then with aliases
-	 */
-	for (try = 0; try < 2; try++)
-		if (!pcmcia_loop_config(link, btuart_check_config, &try))
-			goto found_port;
-
-	/* Second pass: try to find an entry that isn't picky about
-	 * its base address, then try to grab any standard serial port
-	 * address, and finally try to get any free port.
-	 */
-	if (!pcmcia_loop_config(link, btuart_check_config_notpicky, NULL))
-		goto found_port;
-
-	BT_ERR("No usable port range found");
-	goto failed;
-
-found_port:
-	i = pcmcia_request_irq(link, btuart_interrupt);
-	if (i != 0)
-		goto failed;
-
-	i = pcmcia_enable_device(link);
-	if (i != 0)
-		goto failed;
-
-	if (btuart_open(info) != 0)
-		goto failed;
-
-	return 0;
-
-failed:
-	btuart_release(link);
-	return -ENODEV;
-}
-
-
-static void btuart_release(struct pcmcia_device *link)
-{
-	struct btuart_info *info = link->priv;
-
-	btuart_close(info);
-
-	pcmcia_disable_device(link);
-}
-
-static const struct pcmcia_device_id btuart_ids[] = {
-	/* don't use this driver. Use serial_cs + hci_uart instead */
-	PCMCIA_DEVICE_NULL
-};
-MODULE_DEVICE_TABLE(pcmcia, btuart_ids);
-
-static struct pcmcia_driver btuart_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "btuart_cs",
-	.probe		= btuart_probe,
-	.remove		= btuart_detach,
-	.id_table	= btuart_ids,
-};
-module_pcmcia_driver(btuart_driver);
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 5cd868ea28ed..c8c8b0b8d333 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -368,6 +368,9 @@ static const struct usb_device_id blacklist_table[] = {
 	{ USB_DEVICE(0x13d3, 0x3459), .driver_info = BTUSB_REALTEK },
 	{ USB_DEVICE(0x13d3, 0x3494), .driver_info = BTUSB_REALTEK },
 
+	/* Additional Realtek 8723BU Bluetooth devices */
+	{ USB_DEVICE(0x7392, 0xa611), .driver_info = BTUSB_REALTEK },
+
 	/* Additional Realtek 8821AE Bluetooth devices */
 	{ USB_DEVICE(0x0b05, 0x17dc), .driver_info = BTUSB_REALTEK },
 	{ USB_DEVICE(0x13d3, 0x3414), .driver_info = BTUSB_REALTEK },
@@ -3060,6 +3063,7 @@ static int btusb_probe(struct usb_interface *intf,
 	if (id->driver_info & BTUSB_QCA_ROME) {
 		data->setup_on_usb = btusb_setup_qca;
 		hdev->set_bdaddr = btusb_set_bdaddr_ath3012;
+		set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
 	}
 
 #ifdef CONFIG_BT_HCIBTUSB_RTL
diff --git a/drivers/bluetooth/h4_recv.h b/drivers/bluetooth/h4_recv.h
new file mode 100644
index 000000000000..b432651f8236
--- /dev/null
+++ b/drivers/bluetooth/h4_recv.h
@@ -0,0 +1,160 @@
+/*
+ *
+ *  Generic Bluetooth HCI UART driver
+ *
+ *  Copyright (C) 2015-2018  Intel Corporation
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <asm/unaligned.h>
+
+struct h4_recv_pkt {
+	u8  type;	/* Packet type */
+	u8  hlen;	/* Header length */
+	u8  loff;	/* Data length offset in header */
+	u8  lsize;	/* Data length field size */
+	u16 maxlen;	/* Max overall packet length */
+	int (*recv)(struct hci_dev *hdev, struct sk_buff *skb);
+};
+
+#define H4_RECV_ACL \
+	.type = HCI_ACLDATA_PKT, \
+	.hlen = HCI_ACL_HDR_SIZE, \
+	.loff = 2, \
+	.lsize = 2, \
+	.maxlen = HCI_MAX_FRAME_SIZE \
+
+#define H4_RECV_SCO \
+	.type = HCI_SCODATA_PKT, \
+	.hlen = HCI_SCO_HDR_SIZE, \
+	.loff = 2, \
+	.lsize = 1, \
+	.maxlen = HCI_MAX_SCO_SIZE
+
+#define H4_RECV_EVENT \
+	.type = HCI_EVENT_PKT, \
+	.hlen = HCI_EVENT_HDR_SIZE, \
+	.loff = 1, \
+	.lsize = 1, \
+	.maxlen = HCI_MAX_EVENT_SIZE
+
+static inline struct sk_buff *h4_recv_buf(struct hci_dev *hdev,
+					  struct sk_buff *skb,
+					  const unsigned char *buffer,
+					  int count,
+					  const struct h4_recv_pkt *pkts,
+					  int pkts_count)
+{
+	while (count) {
+		int i, len;
+
+		if (!count)
+			break;
+
+		if (!skb) {
+			for (i = 0; i < pkts_count; i++) {
+				if (buffer[0] != (&pkts[i])->type)
+					continue;
+
+				skb = bt_skb_alloc((&pkts[i])->maxlen,
+						   GFP_ATOMIC);
+				if (!skb)
+					return ERR_PTR(-ENOMEM);
+
+				hci_skb_pkt_type(skb) = (&pkts[i])->type;
+				hci_skb_expect(skb) = (&pkts[i])->hlen;
+				break;
+			}
+
+			/* Check for invalid packet type */
+			if (!skb)
+				return ERR_PTR(-EILSEQ);
+
+			count -= 1;
+			buffer += 1;
+		}
+
+		len = min_t(uint, hci_skb_expect(skb) - skb->len, count);
+		skb_put_data(skb, buffer, len);
+
+		count -= len;
+		buffer += len;
+
+		/* Check for partial packet */
+		if (skb->len < hci_skb_expect(skb))
+			continue;
+
+		for (i = 0; i < pkts_count; i++) {
+			if (hci_skb_pkt_type(skb) == (&pkts[i])->type)
+				break;
+		}
+
+		if (i >= pkts_count) {
+			kfree_skb(skb);
+			return ERR_PTR(-EILSEQ);
+		}
+
+		if (skb->len == (&pkts[i])->hlen) {
+			u16 dlen;
+
+			switch ((&pkts[i])->lsize) {
+			case 0:
+				/* No variable data length */
+				dlen = 0;
+				break;
+			case 1:
+				/* Single octet variable length */
+				dlen = skb->data[(&pkts[i])->loff];
+				hci_skb_expect(skb) += dlen;
+
+				if (skb_tailroom(skb) < dlen) {
+					kfree_skb(skb);
+					return ERR_PTR(-EMSGSIZE);
+				}
+				break;
+			case 2:
+				/* Double octet variable length */
+				dlen = get_unaligned_le16(skb->data +
+							  (&pkts[i])->loff);
+				hci_skb_expect(skb) += dlen;
+
+				if (skb_tailroom(skb) < dlen) {
+					kfree_skb(skb);
+					return ERR_PTR(-EMSGSIZE);
+				}
+				break;
+			default:
+				/* Unsupported variable length */
+				kfree_skb(skb);
+				return ERR_PTR(-EILSEQ);
+			}
+
+			if (!dlen) {
+				/* No more data, complete frame */
+				(&pkts[i])->recv(hdev, skb);
+				skb = NULL;
+			}
+		} else {
+			/* Complete frame */
+			(&pkts[i])->recv(hdev, skb);
+			skb = NULL;
+		}
+	}
+
+	return skb;
+}
diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c
index 40b9fb247010..441f5e1deb11 100644
--- a/drivers/bluetooth/hci_bcm.c
+++ b/drivers/bluetooth/hci_bcm.c
@@ -98,6 +98,8 @@ struct bcm_device {
 	int			(*set_shutdown)(struct bcm_device *, bool);
 #ifdef CONFIG_ACPI
 	acpi_handle		btlp, btpu, btpd;
+	int			gpio_count;
+	int			gpio_int_idx;
 #endif
 
 	struct clk		*clk;
@@ -126,6 +128,10 @@ struct bcm_data {
 static DEFINE_MUTEX(bcm_device_lock);
 static LIST_HEAD(bcm_device_list);
 
+static int irq_polarity = -1;
+module_param(irq_polarity, int, 0444);
+MODULE_PARM_DESC(irq_polarity, "IRQ polarity 0: active-high 1: active-low");
+
 static inline void host_set_baudrate(struct hci_uart *hu, unsigned int speed)
 {
 	if (hu->serdev)
@@ -770,47 +776,27 @@ unlock:
 }
 #endif
 
-static const struct acpi_gpio_params int_last_device_wakeup_gpios = { 0, 0, false };
-static const struct acpi_gpio_params int_last_shutdown_gpios = { 1, 0, false };
-static const struct acpi_gpio_params int_last_host_wakeup_gpios = { 2, 0, false };
+static const struct acpi_gpio_params first_gpio = { 0, 0, false };
+static const struct acpi_gpio_params second_gpio = { 1, 0, false };
+static const struct acpi_gpio_params third_gpio = { 2, 0, false };
 
 static const struct acpi_gpio_mapping acpi_bcm_int_last_gpios[] = {
-	{ "device-wakeup-gpios", &int_last_device_wakeup_gpios, 1 },
-	{ "shutdown-gpios", &int_last_shutdown_gpios, 1 },
-	{ "host-wakeup-gpios", &int_last_host_wakeup_gpios, 1 },
+	{ "device-wakeup-gpios", &first_gpio, 1 },
+	{ "shutdown-gpios", &second_gpio, 1 },
+	{ "host-wakeup-gpios", &third_gpio, 1 },
 	{ },
 };
 
-static const struct acpi_gpio_params int_first_host_wakeup_gpios = { 0, 0, false };
-static const struct acpi_gpio_params int_first_device_wakeup_gpios = { 1, 0, false };
-static const struct acpi_gpio_params int_first_shutdown_gpios = { 2, 0, false };
-
 static const struct acpi_gpio_mapping acpi_bcm_int_first_gpios[] = {
-	{ "device-wakeup-gpios", &int_first_device_wakeup_gpios, 1 },
-	{ "shutdown-gpios", &int_first_shutdown_gpios, 1 },
-	{ "host-wakeup-gpios", &int_first_host_wakeup_gpios, 1 },
+	{ "host-wakeup-gpios", &first_gpio, 1 },
+	{ "device-wakeup-gpios", &second_gpio, 1 },
+	{ "shutdown-gpios", &third_gpio, 1 },
 	{ },
 };
 
 #ifdef CONFIG_ACPI
 /* IRQ polarity of some chipsets are not defined correctly in ACPI table. */
 static const struct dmi_system_id bcm_active_low_irq_dmi_table[] = {
-	{
-		.ident = "Asus T100TA",
-		.matches = {
-			DMI_EXACT_MATCH(DMI_SYS_VENDOR,
-					"ASUSTeK COMPUTER INC."),
-			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TA"),
-		},
-	},
-	{
-		.ident = "Asus T100CHI",
-		.matches = {
-			DMI_EXACT_MATCH(DMI_SYS_VENDOR,
-					"ASUSTeK COMPUTER INC."),
-			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100CHI"),
-		},
-	},
 	{	/* Handle ThinkPad 8 tablets with BCM2E55 chipset ACPI ID */
 		.ident = "Lenovo ThinkPad 8",
 		.matches = {
@@ -818,13 +804,6 @@ static const struct dmi_system_id bcm_active_low_irq_dmi_table[] = {
 			DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "ThinkPad 8"),
 		},
 	},
-	{
-		.ident = "MINIX Z83-4",
-		.matches = {
-			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "MINIX"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Z83-4"),
-		},
-	},
 	{ }
 };
 
@@ -838,13 +817,18 @@ static int bcm_resource(struct acpi_resource *ares, void *data)
 	switch (ares->type) {
 	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
 		irq = &ares->data.extended_irq;
-		dev->irq_active_low = irq->polarity == ACPI_ACTIVE_LOW;
+		if (irq->polarity != ACPI_ACTIVE_LOW)
+			dev_info(dev->dev, "ACPI Interrupt resource is active-high, this is usually wrong, treating the IRQ as active-low\n");
+		dev->irq_active_low = true;
 		break;
 
 	case ACPI_RESOURCE_TYPE_GPIO:
 		gpio = &ares->data.gpio;
-		if (gpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT)
+		if (gpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT) {
+			dev->gpio_int_idx = dev->gpio_count;
 			dev->irq_active_low = gpio->polarity == ACPI_ACTIVE_LOW;
+		}
+		dev->gpio_count++;
 		break;
 
 	case ACPI_RESOURCE_TYPE_SERIAL_BUS:
@@ -908,13 +892,13 @@ static inline int bcm_apple_get_resources(struct bcm_device *dev)
 
 static int bcm_gpio_set_device_wakeup(struct bcm_device *dev, bool awake)
 {
-	gpiod_set_value(dev->device_wakeup, awake);
+	gpiod_set_value_cansleep(dev->device_wakeup, awake);
 	return 0;
 }
 
 static int bcm_gpio_set_shutdown(struct bcm_device *dev, bool powered)
 {
-	gpiod_set_value(dev->shutdown, powered);
+	gpiod_set_value_cansleep(dev->shutdown, powered);
 	return 0;
 }
 
@@ -962,20 +946,11 @@ static int bcm_acpi_probe(struct bcm_device *dev)
 	LIST_HEAD(resources);
 	const struct dmi_system_id *dmi_id;
 	const struct acpi_gpio_mapping *gpio_mapping = acpi_bcm_int_last_gpios;
-	const struct acpi_device_id *id;
 	struct resource_entry *entry;
 	int ret;
 
-	/* Retrieve GPIO data */
-	id = acpi_match_device(dev->dev->driver->acpi_match_table, dev->dev);
-	if (id)
-		gpio_mapping = (const struct acpi_gpio_mapping *) id->driver_data;
-
-	ret = devm_acpi_dev_add_driver_gpios(dev->dev, gpio_mapping);
-	if (ret)
-		return ret;
-
 	/* Retrieve UART ACPI info */
+	dev->gpio_int_idx = -1;
 	ret = acpi_dev_get_resources(ACPI_COMPANION(dev->dev),
 				     &resources, bcm_resource, dev);
 	if (ret < 0)
@@ -989,11 +964,40 @@ static int bcm_acpi_probe(struct bcm_device *dev)
 	}
 	acpi_dev_free_resource_list(&resources);
 
-	dmi_id = dmi_first_match(bcm_active_low_irq_dmi_table);
-	if (dmi_id) {
-		dev_warn(dev->dev, "%s: Overwriting IRQ polarity to active low",
-			    dmi_id->ident);
-		dev->irq_active_low = true;
+	/* If the DSDT uses an Interrupt resource for the IRQ, then there are
+	 * only 2 GPIO resources, we use the irq-last mapping for this, since
+	 * we already have an irq the 3th / last mapping will not be used.
+	 */
+	if (dev->irq)
+		gpio_mapping = acpi_bcm_int_last_gpios;
+	else if (dev->gpio_int_idx == 0)
+		gpio_mapping = acpi_bcm_int_first_gpios;
+	else if (dev->gpio_int_idx == 2)
+		gpio_mapping = acpi_bcm_int_last_gpios;
+	else
+		dev_warn(dev->dev, "Unexpected ACPI gpio_int_idx: %d\n",
+			 dev->gpio_int_idx);
+
+	/* Warn if our expectations are not met. */
+	if (dev->gpio_count != (dev->irq ? 2 : 3))
+		dev_warn(dev->dev, "Unexpected number of ACPI GPIOs: %d\n",
+			 dev->gpio_count);
+
+	ret = devm_acpi_dev_add_driver_gpios(dev->dev, gpio_mapping);
+	if (ret)
+		return ret;
+
+	if (irq_polarity != -1) {
+		dev->irq_active_low = irq_polarity;
+		dev_warn(dev->dev, "Overwriting IRQ polarity to active %s by module-param\n",
+			 dev->irq_active_low ? "low" : "high");
+	} else {
+		dmi_id = dmi_first_match(bcm_active_low_irq_dmi_table);
+		if (dmi_id) {
+			dev_warn(dev->dev, "%s: Overwriting IRQ polarity to active low",
+				 dmi_id->ident);
+			dev->irq_active_low = true;
+		}
 	}
 
 	return 0;
@@ -1079,25 +1083,172 @@ static const struct hci_uart_proto bcm_proto = {
 
 #ifdef CONFIG_ACPI
 static const struct acpi_device_id bcm_acpi_match[] = {
-	{ "BCM2E1A", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
-	{ "BCM2E39", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
-	{ "BCM2E3A", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
-	{ "BCM2E3D", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
-	{ "BCM2E3F", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
-	{ "BCM2E40", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
-	{ "BCM2E54", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
-	{ "BCM2E55", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
-	{ "BCM2E64", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
-	{ "BCM2E65", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
-	{ "BCM2E67", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
-	{ "BCM2E71", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
-	{ "BCM2E72", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
-	{ "BCM2E7B", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
-	{ "BCM2E7C", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
-	{ "BCM2E7E", (kernel_ulong_t)&acpi_bcm_int_first_gpios },
-	{ "BCM2E95", (kernel_ulong_t)&acpi_bcm_int_first_gpios },
-	{ "BCM2E96", (kernel_ulong_t)&acpi_bcm_int_first_gpios },
-	{ "BCM2EA4", (kernel_ulong_t)&acpi_bcm_int_first_gpios },
+	{ "BCM2E00" },
+	{ "BCM2E01" },
+	{ "BCM2E02" },
+	{ "BCM2E03" },
+	{ "BCM2E04" },
+	{ "BCM2E05" },
+	{ "BCM2E06" },
+	{ "BCM2E07" },
+	{ "BCM2E08" },
+	{ "BCM2E09" },
+	{ "BCM2E0A" },
+	{ "BCM2E0B" },
+	{ "BCM2E0C" },
+	{ "BCM2E0D" },
+	{ "BCM2E0E" },
+	{ "BCM2E0F" },
+	{ "BCM2E10" },
+	{ "BCM2E11" },
+	{ "BCM2E12" },
+	{ "BCM2E13" },
+	{ "BCM2E14" },
+	{ "BCM2E15" },
+	{ "BCM2E16" },
+	{ "BCM2E17" },
+	{ "BCM2E18" },
+	{ "BCM2E19" },
+	{ "BCM2E1A" },
+	{ "BCM2E1B" },
+	{ "BCM2E1C" },
+	{ "BCM2E1D" },
+	{ "BCM2E1F" },
+	{ "BCM2E20" },
+	{ "BCM2E21" },
+	{ "BCM2E22" },
+	{ "BCM2E23" },
+	{ "BCM2E24" },
+	{ "BCM2E25" },
+	{ "BCM2E26" },
+	{ "BCM2E27" },
+	{ "BCM2E28" },
+	{ "BCM2E29" },
+	{ "BCM2E2A" },
+	{ "BCM2E2B" },
+	{ "BCM2E2C" },
+	{ "BCM2E2D" },
+	{ "BCM2E2E" },
+	{ "BCM2E2F" },
+	{ "BCM2E30" },
+	{ "BCM2E31" },
+	{ "BCM2E32" },
+	{ "BCM2E33" },
+	{ "BCM2E34" },
+	{ "BCM2E35" },
+	{ "BCM2E36" },
+	{ "BCM2E37" },
+	{ "BCM2E38" },
+	{ "BCM2E39" },
+	{ "BCM2E3A" },
+	{ "BCM2E3B" },
+	{ "BCM2E3C" },
+	{ "BCM2E3D" },
+	{ "BCM2E3E" },
+	{ "BCM2E3F" },
+	{ "BCM2E40" },
+	{ "BCM2E41" },
+	{ "BCM2E42" },
+	{ "BCM2E43" },
+	{ "BCM2E44" },
+	{ "BCM2E45" },
+	{ "BCM2E46" },
+	{ "BCM2E47" },
+	{ "BCM2E48" },
+	{ "BCM2E49" },
+	{ "BCM2E4A" },
+	{ "BCM2E4B" },
+	{ "BCM2E4C" },
+	{ "BCM2E4D" },
+	{ "BCM2E4E" },
+	{ "BCM2E4F" },
+	{ "BCM2E50" },
+	{ "BCM2E51" },
+	{ "BCM2E52" },
+	{ "BCM2E53" },
+	{ "BCM2E54" },
+	{ "BCM2E55" },
+	{ "BCM2E56" },
+	{ "BCM2E57" },
+	{ "BCM2E58" },
+	{ "BCM2E59" },
+	{ "BCM2E5A" },
+	{ "BCM2E5B" },
+	{ "BCM2E5C" },
+	{ "BCM2E5D" },
+	{ "BCM2E5E" },
+	{ "BCM2E5F" },
+	{ "BCM2E60" },
+	{ "BCM2E61" },
+	{ "BCM2E62" },
+	{ "BCM2E63" },
+	{ "BCM2E64" },
+	{ "BCM2E65" },
+	{ "BCM2E66" },
+	{ "BCM2E67" },
+	{ "BCM2E68" },
+	{ "BCM2E69" },
+	{ "BCM2E6B" },
+	{ "BCM2E6D" },
+	{ "BCM2E6E" },
+	{ "BCM2E6F" },
+	{ "BCM2E70" },
+	{ "BCM2E71" },
+	{ "BCM2E72" },
+	{ "BCM2E73" },
+	{ "BCM2E74" },
+	{ "BCM2E75" },
+	{ "BCM2E76" },
+	{ "BCM2E77" },
+	{ "BCM2E78" },
+	{ "BCM2E79" },
+	{ "BCM2E7A" },
+	{ "BCM2E7B" },
+	{ "BCM2E7C" },
+	{ "BCM2E7D" },
+	{ "BCM2E7E" },
+	{ "BCM2E7F" },
+	{ "BCM2E80" },
+	{ "BCM2E81" },
+	{ "BCM2E82" },
+	{ "BCM2E83" },
+	{ "BCM2E84" },
+	{ "BCM2E85" },
+	{ "BCM2E86" },
+	{ "BCM2E87" },
+	{ "BCM2E88" },
+	{ "BCM2E89" },
+	{ "BCM2E8A" },
+	{ "BCM2E8B" },
+	{ "BCM2E8C" },
+	{ "BCM2E8D" },
+	{ "BCM2E8E" },
+	{ "BCM2E90" },
+	{ "BCM2E92" },
+	{ "BCM2E93" },
+	{ "BCM2E94" },
+	{ "BCM2E95" },
+	{ "BCM2E96" },
+	{ "BCM2E97" },
+	{ "BCM2E98" },
+	{ "BCM2E99" },
+	{ "BCM2E9A" },
+	{ "BCM2E9B" },
+	{ "BCM2E9C" },
+	{ "BCM2E9D" },
+	{ "BCM2EA0" },
+	{ "BCM2EA1" },
+	{ "BCM2EA2" },
+	{ "BCM2EA3" },
+	{ "BCM2EA4" },
+	{ "BCM2EA5" },
+	{ "BCM2EA6" },
+	{ "BCM2EA7" },
+	{ "BCM2EA8" },
+	{ "BCM2EA9" },
+	{ "BCM2EAA" },
+	{ "BCM2EAB" },
+	{ "BCM2EAC" },
 	{ },
 };
 MODULE_DEVICE_TABLE(acpi, bcm_acpi_match);
@@ -1146,6 +1297,12 @@ static int bcm_serdev_probe(struct serdev_device *serdev)
 	if (err)
 		return err;
 
+	if (!bcmdev->shutdown) {
+		dev_warn(&serdev->dev,
+			 "No reset resource, using default baud rate\n");
+		bcmdev->oper_speed = bcmdev->init_speed;
+	}
+
 	err = bcm_gpio_set_power(bcmdev, false);
 	if (err)
 		dev_err(&serdev->dev, "Failed to power down\n");
diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c
index 2f30dcad96bd..27e414b4e3a2 100644
--- a/drivers/bluetooth/hci_ll.c
+++ b/drivers/bluetooth/hci_ll.c
@@ -67,13 +67,6 @@
 #define HCILL_WAKE_UP_IND	0x32
 #define HCILL_WAKE_UP_ACK	0x33
 
-/* HCILL receiver States */
-#define HCILL_W4_PACKET_TYPE	0
-#define HCILL_W4_EVENT_HDR	1
-#define HCILL_W4_ACL_HDR	2
-#define HCILL_W4_SCO_HDR	3
-#define HCILL_W4_DATA		4
-
 /* HCILL states */
 enum hcill_states_e {
 	HCILL_ASLEEP,
@@ -82,10 +75,6 @@ enum hcill_states_e {
 	HCILL_AWAKE_TO_ASLEEP
 };
 
-struct hcill_cmd {
-	u8 cmd;
-} __packed;
-
 struct ll_device {
 	struct hci_uart hu;
 	struct serdev_device *serdev;
@@ -95,8 +84,6 @@ struct ll_device {
 };
 
 struct ll_struct {
-	unsigned long rx_state;
-	unsigned long rx_count;
 	struct sk_buff *rx_skb;
 	struct sk_buff_head txq;
 	spinlock_t hcill_lock;		/* HCILL state lock	*/
@@ -113,7 +100,6 @@ static int send_hcill_cmd(u8 cmd, struct hci_uart *hu)
 	int err = 0;
 	struct sk_buff *skb = NULL;
 	struct ll_struct *ll = hu->priv;
-	struct hcill_cmd *hcill_packet;
 
 	BT_DBG("hu %p cmd 0x%x", hu, cmd);
 
@@ -126,8 +112,7 @@ static int send_hcill_cmd(u8 cmd, struct hci_uart *hu)
 	}
 
 	/* prepare packet */
-	hcill_packet = skb_put(skb, 1);
-	hcill_packet->cmd = cmd;
+	skb_put_u8(skb, cmd);
 
 	/* send packet */
 	skb_queue_tail(&ll->txq, skb);
@@ -379,155 +364,88 @@ static int ll_enqueue(struct hci_uart *hu, struct sk_buff *skb)
 	return 0;
 }
 
-static inline int ll_check_data_len(struct hci_dev *hdev, struct ll_struct *ll, int len)
+static int ll_recv_frame(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	int room = skb_tailroom(ll->rx_skb);
-
-	BT_DBG("len %d room %d", len, room);
+	struct hci_uart *hu = hci_get_drvdata(hdev);
+	struct ll_struct *ll = hu->priv;
 
-	if (!len) {
-		hci_recv_frame(hdev, ll->rx_skb);
-	} else if (len > room) {
-		BT_ERR("Data length is too large");
-		kfree_skb(ll->rx_skb);
-	} else {
-		ll->rx_state = HCILL_W4_DATA;
-		ll->rx_count = len;
-		return len;
+	switch (hci_skb_pkt_type(skb)) {
+	case HCILL_GO_TO_SLEEP_IND:
+		BT_DBG("HCILL_GO_TO_SLEEP_IND packet");
+		ll_device_want_to_sleep(hu);
+		break;
+	case HCILL_GO_TO_SLEEP_ACK:
+		/* shouldn't happen */
+		bt_dev_err(hdev, "received HCILL_GO_TO_SLEEP_ACK in state %ld",
+			   ll->hcill_state);
+		break;
+	case HCILL_WAKE_UP_IND:
+		BT_DBG("HCILL_WAKE_UP_IND packet");
+		ll_device_want_to_wakeup(hu);
+		break;
+	case HCILL_WAKE_UP_ACK:
+		BT_DBG("HCILL_WAKE_UP_ACK packet");
+		ll_device_woke_up(hu);
+		break;
 	}
 
-	ll->rx_state = HCILL_W4_PACKET_TYPE;
-	ll->rx_skb   = NULL;
-	ll->rx_count = 0;
-
+	kfree_skb(skb);
 	return 0;
 }
 
+#define LL_RECV_SLEEP_IND \
+	.type = HCILL_GO_TO_SLEEP_IND, \
+	.hlen = 0, \
+	.loff = 0, \
+	.lsize = 0, \
+	.maxlen = 0
+
+#define LL_RECV_SLEEP_ACK \
+	.type = HCILL_GO_TO_SLEEP_ACK, \
+	.hlen = 0, \
+	.loff = 0, \
+	.lsize = 0, \
+	.maxlen = 0
+
+#define LL_RECV_WAKE_IND \
+	.type = HCILL_WAKE_UP_IND, \
+	.hlen = 0, \
+	.loff = 0, \
+	.lsize = 0, \
+	.maxlen = 0
+
+#define LL_RECV_WAKE_ACK \
+	.type = HCILL_WAKE_UP_ACK, \
+	.hlen = 0, \
+	.loff = 0, \
+	.lsize = 0, \
+	.maxlen = 0
+
+static const struct h4_recv_pkt ll_recv_pkts[] = {
+	{ H4_RECV_ACL,       .recv = hci_recv_frame },
+	{ H4_RECV_SCO,       .recv = hci_recv_frame },
+	{ H4_RECV_EVENT,     .recv = hci_recv_frame },
+	{ LL_RECV_SLEEP_IND, .recv = ll_recv_frame  },
+	{ LL_RECV_SLEEP_ACK, .recv = ll_recv_frame  },
+	{ LL_RECV_WAKE_IND,  .recv = ll_recv_frame  },
+	{ LL_RECV_WAKE_ACK,  .recv = ll_recv_frame  },
+};
+
 /* Recv data */
 static int ll_recv(struct hci_uart *hu, const void *data, int count)
 {
 	struct ll_struct *ll = hu->priv;
-	const char *ptr;
-	struct hci_event_hdr *eh;
-	struct hci_acl_hdr   *ah;
-	struct hci_sco_hdr   *sh;
-	int len, type, dlen;
-
-	BT_DBG("hu %p count %d rx_state %ld rx_count %ld", hu, count, ll->rx_state, ll->rx_count);
-
-	ptr = data;
-	while (count) {
-		if (ll->rx_count) {
-			len = min_t(unsigned int, ll->rx_count, count);
-			skb_put_data(ll->rx_skb, ptr, len);
-			ll->rx_count -= len; count -= len; ptr += len;
-
-			if (ll->rx_count)
-				continue;
-
-			switch (ll->rx_state) {
-			case HCILL_W4_DATA:
-				BT_DBG("Complete data");
-				hci_recv_frame(hu->hdev, ll->rx_skb);
-
-				ll->rx_state = HCILL_W4_PACKET_TYPE;
-				ll->rx_skb = NULL;
-				continue;
-
-			case HCILL_W4_EVENT_HDR:
-				eh = hci_event_hdr(ll->rx_skb);
-
-				BT_DBG("Event header: evt 0x%2.2x plen %d", eh->evt, eh->plen);
 
-				ll_check_data_len(hu->hdev, ll, eh->plen);
-				continue;
+	if (!test_bit(HCI_UART_REGISTERED, &hu->flags))
+		return -EUNATCH;
 
-			case HCILL_W4_ACL_HDR:
-				ah = hci_acl_hdr(ll->rx_skb);
-				dlen = __le16_to_cpu(ah->dlen);
-
-				BT_DBG("ACL header: dlen %d", dlen);
-
-				ll_check_data_len(hu->hdev, ll, dlen);
-				continue;
-
-			case HCILL_W4_SCO_HDR:
-				sh = hci_sco_hdr(ll->rx_skb);
-
-				BT_DBG("SCO header: dlen %d", sh->dlen);
-
-				ll_check_data_len(hu->hdev, ll, sh->dlen);
-				continue;
-			}
-		}
-
-		/* HCILL_W4_PACKET_TYPE */
-		switch (*ptr) {
-		case HCI_EVENT_PKT:
-			BT_DBG("Event packet");
-			ll->rx_state = HCILL_W4_EVENT_HDR;
-			ll->rx_count = HCI_EVENT_HDR_SIZE;
-			type = HCI_EVENT_PKT;
-			break;
-
-		case HCI_ACLDATA_PKT:
-			BT_DBG("ACL packet");
-			ll->rx_state = HCILL_W4_ACL_HDR;
-			ll->rx_count = HCI_ACL_HDR_SIZE;
-			type = HCI_ACLDATA_PKT;
-			break;
-
-		case HCI_SCODATA_PKT:
-			BT_DBG("SCO packet");
-			ll->rx_state = HCILL_W4_SCO_HDR;
-			ll->rx_count = HCI_SCO_HDR_SIZE;
-			type = HCI_SCODATA_PKT;
-			break;
-
-		/* HCILL signals */
-		case HCILL_GO_TO_SLEEP_IND:
-			BT_DBG("HCILL_GO_TO_SLEEP_IND packet");
-			ll_device_want_to_sleep(hu);
-			ptr++; count--;
-			continue;
-
-		case HCILL_GO_TO_SLEEP_ACK:
-			/* shouldn't happen */
-			BT_ERR("received HCILL_GO_TO_SLEEP_ACK (in state %ld)", ll->hcill_state);
-			ptr++; count--;
-			continue;
-
-		case HCILL_WAKE_UP_IND:
-			BT_DBG("HCILL_WAKE_UP_IND packet");
-			ll_device_want_to_wakeup(hu);
-			ptr++; count--;
-			continue;
-
-		case HCILL_WAKE_UP_ACK:
-			BT_DBG("HCILL_WAKE_UP_ACK packet");
-			ll_device_woke_up(hu);
-			ptr++; count--;
-			continue;
-
-		default:
-			BT_ERR("Unknown HCI packet type %2.2x", (__u8)*ptr);
-			hu->hdev->stat.err_rx++;
-			ptr++; count--;
-			continue;
-		}
-
-		ptr++; count--;
-
-		/* Allocate packet */
-		ll->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
-		if (!ll->rx_skb) {
-			BT_ERR("Can't allocate mem for new packet");
-			ll->rx_state = HCILL_W4_PACKET_TYPE;
-			ll->rx_count = 0;
-			return -ENOMEM;
-		}
-
-		hci_skb_pkt_type(ll->rx_skb) = type;
+	ll->rx_skb = h4_recv_buf(hu->hdev, ll->rx_skb, data, count,
+				 ll_recv_pkts, ARRAY_SIZE(ll_recv_pkts));
+	if (IS_ERR(ll->rx_skb)) {
+		int err = PTR_ERR(ll->rx_skb);
+		bt_dev_err(hu->hdev, "Frame reassembly failed (%d)", err);
+		ll->rx_skb = NULL;
+		return err;
 	}
 
 	return count;
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 72a456bbbcd5..e7303eee65cd 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -600,7 +600,7 @@ struct mgmt_rp_read_ext_info {
 
 #define MGMT_OP_SET_APPEARANCE		0x0043
 struct mgmt_cp_set_appearance {
-	__u16	appearance;
+	__le16	appearance;
 } __packed;
 #define MGMT_SET_APPEARANCE_SIZE	2
 
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 6e9fc86d8daf..8a80d48d89c4 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -4801,6 +4801,7 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
 		case MGMT_LTK_P256_DEBUG:
 			authenticated = 0x00;
 			type = SMP_LTK_P256_DEBUG;
+			/* fall through */
 		default:
 			continue;
 		}
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index 93a3b219db09..d606e9212291 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -221,6 +221,7 @@ static void __rfcomm_sock_close(struct sock *sk)
 	case BT_CONFIG:
 	case BT_CONNECTED:
 		rfcomm_dlc_close(d, 0);
+		/* fall through */
 
 	default:
 		sock_set_flag(sk, SOCK_ZAPPED);