Commit 633cefe3 authored by David S. Miller's avatar David S. Miller

Merge branch 'for-upstream' of...

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

Johan Hedberg says:

====================
pull request: bluetooth-next 2017-08-18

Here's one more bluetooth-next pull request for the 4.14 kernel:

 - Multiple fixes for Broadcom controllers
 - Fixes to the bluecard HCI driver
 - New USB ID for Realtek RTL8723BE controller
 - Fix static analyzer warning with kfree

Please let me know if there are any issues pulling. Thanks.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 401481e0 01d5e44a
Broadcom Bluetooth Chips
---------------------
This documents the binding structure and common properties for serial
attached Broadcom devices.
Serial attached Broadcom devices shall be a child node of the host UART
device the slave device is attached to.
Required properties:
- compatible: should contain one of the following:
* "brcm,bcm43438-bt"
Optional properties:
- max-speed: see Documentation/devicetree/bindings/serial/slave-device.txt
- shutdown-gpios: GPIO specifier, used to enable the BT module
- device-wakeup-gpios: GPIO specifier, used to wakeup the controller
- host-wakeup-gpios: GPIO specifier, used to wakeup the host processor
- clocks: clock specifier if external clock provided to the controller
- clock-names: should be "extclk"
Example:
&uart2 {
pinctrl-names = "default";
pinctrl-0 = <&uart2_pins>;
bluetooth {
compatible = "brcm,bcm43438-bt";
max-speed = <921600>;
};
};
...@@ -168,6 +168,7 @@ config BT_HCIUART_INTEL ...@@ -168,6 +168,7 @@ config BT_HCIUART_INTEL
config BT_HCIUART_BCM config BT_HCIUART_BCM
bool "Broadcom protocol support" bool "Broadcom protocol support"
depends on BT_HCIUART depends on BT_HCIUART
depends on BT_HCIUART_SERDEV
select BT_HCIUART_H4 select BT_HCIUART_H4
select BT_BCM select BT_BCM
help help
......
...@@ -93,6 +93,7 @@ static void bluecard_detach(struct pcmcia_device *p_dev); ...@@ -93,6 +93,7 @@ static void bluecard_detach(struct pcmcia_device *p_dev);
/* Hardware states */ /* Hardware states */
#define CARD_READY 1 #define CARD_READY 1
#define CARD_ACTIVITY 2
#define CARD_HAS_PCCARD_ID 4 #define CARD_HAS_PCCARD_ID 4
#define CARD_HAS_POWER_LED 5 #define CARD_HAS_POWER_LED 5
#define CARD_HAS_ACTIVITY_LED 6 #define CARD_HAS_ACTIVITY_LED 6
...@@ -160,16 +161,14 @@ static void bluecard_activity_led_timeout(u_long arg) ...@@ -160,16 +161,14 @@ static void bluecard_activity_led_timeout(u_long arg)
struct bluecard_info *info = (struct bluecard_info *)arg; struct bluecard_info *info = (struct bluecard_info *)arg;
unsigned int iobase = info->p_dev->resource[0]->start; unsigned int iobase = info->p_dev->resource[0]->start;
if (!test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) if (test_bit(CARD_ACTIVITY, &(info->hw_state))) {
return; /* leave LED in inactive state for HZ/10 for blink effect */
clear_bit(CARD_ACTIVITY, &(info->hw_state));
if (test_bit(CARD_HAS_ACTIVITY_LED, &(info->hw_state))) { mod_timer(&(info->timer), jiffies + HZ / 10);
/* Disable activity LED */
outb(0x08 | 0x20, iobase + 0x30);
} else {
/* Disable power LED */
outb(0x00, iobase + 0x30);
} }
/* Disable activity LED, enable power LED */
outb(0x08 | 0x20, iobase + 0x30);
} }
...@@ -177,22 +176,22 @@ static void bluecard_enable_activity_led(struct bluecard_info *info) ...@@ -177,22 +176,22 @@ static void bluecard_enable_activity_led(struct bluecard_info *info)
{ {
unsigned int iobase = info->p_dev->resource[0]->start; unsigned int iobase = info->p_dev->resource[0]->start;
if (!test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) /* don't disturb running blink timer */
if (timer_pending(&(info->timer)))
return; return;
if (test_bit(CARD_HAS_ACTIVITY_LED, &(info->hw_state))) { set_bit(CARD_ACTIVITY, &(info->hw_state));
/* Enable activity LED */
outb(0x10 | 0x40, iobase + 0x30);
/* Stop the LED after HZ/4 */ if (test_bit(CARD_HAS_ACTIVITY_LED, &(info->hw_state))) {
mod_timer(&(info->timer), jiffies + HZ / 4); /* Enable activity LED, keep power LED enabled */
outb(0x18 | 0x60, iobase + 0x30);
} else { } else {
/* Enable power LED */ /* Disable power LED */
outb(0x08 | 0x20, iobase + 0x30); outb(0x00, iobase + 0x30);
/* Stop the LED after HZ/2 */
mod_timer(&(info->timer), jiffies + HZ / 2);
} }
/* Stop the LED after HZ/10 */
mod_timer(&(info->timer), jiffies + HZ / 10);
} }
...@@ -625,16 +624,13 @@ static int bluecard_hci_flush(struct hci_dev *hdev) ...@@ -625,16 +624,13 @@ static int bluecard_hci_flush(struct hci_dev *hdev)
static int bluecard_hci_open(struct hci_dev *hdev) static int bluecard_hci_open(struct hci_dev *hdev)
{ {
struct bluecard_info *info = hci_get_drvdata(hdev); struct bluecard_info *info = hci_get_drvdata(hdev);
unsigned int iobase = info->p_dev->resource[0]->start;
if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state)))
bluecard_hci_set_baud_rate(hdev, DEFAULT_BAUD_RATE); bluecard_hci_set_baud_rate(hdev, DEFAULT_BAUD_RATE);
if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) { /* Enable power LED */
unsigned int iobase = info->p_dev->resource[0]->start; outb(0x08 | 0x20, iobase + 0x30);
/* Enable LED */
outb(0x08 | 0x20, iobase + 0x30);
}
return 0; return 0;
} }
...@@ -643,15 +639,15 @@ static int bluecard_hci_open(struct hci_dev *hdev) ...@@ -643,15 +639,15 @@ static int bluecard_hci_open(struct hci_dev *hdev)
static int bluecard_hci_close(struct hci_dev *hdev) static int bluecard_hci_close(struct hci_dev *hdev)
{ {
struct bluecard_info *info = hci_get_drvdata(hdev); struct bluecard_info *info = hci_get_drvdata(hdev);
unsigned int iobase = info->p_dev->resource[0]->start;
bluecard_hci_flush(hdev); bluecard_hci_flush(hdev);
if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) { /* Stop LED timer */
unsigned int iobase = info->p_dev->resource[0]->start; del_timer_sync(&(info->timer));
/* Disable LED */ /* Disable power LED */
outb(0x00, iobase + 0x30); outb(0x00, iobase + 0x30);
}
return 0; return 0;
} }
......
...@@ -287,6 +287,37 @@ static struct sk_buff *btbcm_read_usb_product(struct hci_dev *hdev) ...@@ -287,6 +287,37 @@ static struct sk_buff *btbcm_read_usb_product(struct hci_dev *hdev)
return skb; return skb;
} }
static int btbcm_read_info(struct hci_dev *hdev)
{
struct sk_buff *skb;
/* Read Verbose Config Version Info */
skb = btbcm_read_verbose_config(hdev);
if (IS_ERR(skb))
return PTR_ERR(skb);
BT_INFO("%s: BCM: chip id %u", hdev->name, skb->data[1]);
kfree_skb(skb);
/* Read Controller Features */
skb = btbcm_read_controller_features(hdev);
if (IS_ERR(skb))
return PTR_ERR(skb);
BT_INFO("%s: BCM: features 0x%2.2x", hdev->name, skb->data[1]);
kfree_skb(skb);
/* Read Local Name */
skb = btbcm_read_local_name(hdev);
if (IS_ERR(skb))
return PTR_ERR(skb);
BT_INFO("%s: %s", hdev->name, (char *)(skb->data + 1));
kfree_skb(skb);
return 0;
}
static const struct { static const struct {
u16 subver; u16 subver;
const char *name; const char *name;
...@@ -322,13 +353,10 @@ int btbcm_initialize(struct hci_dev *hdev, char *fw_name, size_t len) ...@@ -322,13 +353,10 @@ int btbcm_initialize(struct hci_dev *hdev, char *fw_name, size_t len)
subver = le16_to_cpu(ver->lmp_subver); subver = le16_to_cpu(ver->lmp_subver);
kfree_skb(skb); kfree_skb(skb);
/* Read Verbose Config Version Info */ /* Read controller information */
skb = btbcm_read_verbose_config(hdev); err = btbcm_read_info(hdev);
if (IS_ERR(skb)) if (err)
return PTR_ERR(skb); return err;
BT_INFO("%s: BCM: chip id %u", hdev->name, skb->data[1]);
kfree_skb(skb);
switch ((rev & 0xf000) >> 12) { switch ((rev & 0xf000) >> 12) {
case 0: case 0:
...@@ -431,29 +459,10 @@ int btbcm_setup_patchram(struct hci_dev *hdev) ...@@ -431,29 +459,10 @@ int btbcm_setup_patchram(struct hci_dev *hdev)
subver = le16_to_cpu(ver->lmp_subver); subver = le16_to_cpu(ver->lmp_subver);
kfree_skb(skb); kfree_skb(skb);
/* Read Verbose Config Version Info */ /* Read controller information */
skb = btbcm_read_verbose_config(hdev); err = btbcm_read_info(hdev);
if (IS_ERR(skb)) if (err)
return PTR_ERR(skb); return err;
BT_INFO("%s: BCM: chip id %u", hdev->name, skb->data[1]);
kfree_skb(skb);
/* Read Controller Features */
skb = btbcm_read_controller_features(hdev);
if (IS_ERR(skb))
return PTR_ERR(skb);
BT_INFO("%s: BCM: features 0x%2.2x", hdev->name, skb->data[1]);
kfree_skb(skb);
/* Read Local Name */
skb = btbcm_read_local_name(hdev);
if (IS_ERR(skb))
return PTR_ERR(skb);
BT_INFO("%s: %s", hdev->name, (char *)(skb->data + 1));
kfree_skb(skb);
switch ((rev & 0xf000) >> 12) { switch ((rev & 0xf000) >> 12) {
case 0: case 0:
......
...@@ -66,6 +66,7 @@ static struct usb_driver btusb_driver; ...@@ -66,6 +66,7 @@ static struct usb_driver btusb_driver;
#define BTUSB_BCM2045 0x40000 #define BTUSB_BCM2045 0x40000
#define BTUSB_IFNUM_2 0x80000 #define BTUSB_IFNUM_2 0x80000
#define BTUSB_CW6622 0x100000 #define BTUSB_CW6622 0x100000
#define BTUSB_BCM_NO_PRODID 0x200000
static const struct usb_device_id btusb_table[] = { static const struct usb_device_id btusb_table[] = {
/* Generic Bluetooth USB device */ /* Generic Bluetooth USB device */
...@@ -170,6 +171,10 @@ static const struct usb_device_id btusb_table[] = { ...@@ -170,6 +171,10 @@ static const struct usb_device_id btusb_table[] = {
{ USB_VENDOR_AND_INTERFACE_INFO(0x0930, 0xff, 0x01, 0x01), { USB_VENDOR_AND_INTERFACE_INFO(0x0930, 0xff, 0x01, 0x01),
.driver_info = BTUSB_BCM_PATCHRAM }, .driver_info = BTUSB_BCM_PATCHRAM },
/* Broadcom devices with missing product id */
{ USB_DEVICE_AND_INTERFACE_INFO(0x0000, 0x0000, 0xff, 0x01, 0x01),
.driver_info = BTUSB_BCM_PATCHRAM | BTUSB_BCM_NO_PRODID },
/* Intel Bluetooth USB Bootloader (RAM module) */ /* Intel Bluetooth USB Bootloader (RAM module) */
{ USB_DEVICE(0x8087, 0x0a5a), { USB_DEVICE(0x8087, 0x0a5a),
.driver_info = BTUSB_INTEL_BOOT | BTUSB_BROKEN_ISOC }, .driver_info = BTUSB_INTEL_BOOT | BTUSB_BROKEN_ISOC },
...@@ -359,6 +364,7 @@ static const struct usb_device_id blacklist_table[] = { ...@@ -359,6 +364,7 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x13d3, 0x3410), .driver_info = BTUSB_REALTEK }, { USB_DEVICE(0x13d3, 0x3410), .driver_info = BTUSB_REALTEK },
{ USB_DEVICE(0x13d3, 0x3416), .driver_info = BTUSB_REALTEK }, { USB_DEVICE(0x13d3, 0x3416), .driver_info = BTUSB_REALTEK },
{ USB_DEVICE(0x13d3, 0x3459), .driver_info = BTUSB_REALTEK }, { USB_DEVICE(0x13d3, 0x3459), .driver_info = BTUSB_REALTEK },
{ USB_DEVICE(0x13d3, 0x3494), .driver_info = BTUSB_REALTEK },
/* Additional Realtek 8821AE Bluetooth devices */ /* Additional Realtek 8821AE Bluetooth devices */
{ USB_DEVICE(0x0b05, 0x17dc), .driver_info = BTUSB_REALTEK }, { USB_DEVICE(0x0b05, 0x17dc), .driver_info = BTUSB_REALTEK },
...@@ -1082,6 +1088,10 @@ static int btusb_open(struct hci_dev *hdev) ...@@ -1082,6 +1088,10 @@ static int btusb_open(struct hci_dev *hdev)
} }
data->intf->needs_remote_wakeup = 1; data->intf->needs_remote_wakeup = 1;
/* device specific wakeup source enabled and required for USB
* remote wakeup while host is suspended
*/
device_wakeup_enable(&data->udev->dev);
if (test_and_set_bit(BTUSB_INTR_RUNNING, &data->flags)) if (test_and_set_bit(BTUSB_INTR_RUNNING, &data->flags))
goto done; goto done;
...@@ -1145,6 +1155,7 @@ static int btusb_close(struct hci_dev *hdev) ...@@ -1145,6 +1155,7 @@ static int btusb_close(struct hci_dev *hdev)
goto failed; goto failed;
data->intf->needs_remote_wakeup = 0; data->intf->needs_remote_wakeup = 0;
device_wakeup_disable(&data->udev->dev);
usb_autopm_put_interface(data->intf); usb_autopm_put_interface(data->intf);
failed: failed:
...@@ -2898,6 +2909,19 @@ static int btusb_probe(struct usb_interface *intf, ...@@ -2898,6 +2909,19 @@ static int btusb_probe(struct usb_interface *intf,
if (id->driver_info == BTUSB_IGNORE) if (id->driver_info == BTUSB_IGNORE)
return -ENODEV; return -ENODEV;
if (id->driver_info & BTUSB_BCM_NO_PRODID) {
struct usb_device *udev = interface_to_usbdev(intf);
/* For the broken Broadcom devices that show 0000:0000
* as USB vendor and product information, check that the
* manufacturer string identifies them as Broadcom based
* devices.
*/
if (!udev->manufacturer ||
strcmp(udev->manufacturer, "Broadcom Corp"))
return -ENODEV;
}
if (id->driver_info & BTUSB_ATH3012) { if (id->driver_info & BTUSB_ATH3012) {
struct usb_device *udev = interface_to_usbdev(intf); struct usb_device *udev = interface_to_usbdev(intf);
......
...@@ -27,6 +27,8 @@ ...@@ -27,6 +27,8 @@
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/of.h>
#include <linux/property.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
...@@ -34,6 +36,7 @@ ...@@ -34,6 +36,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/dmi.h> #include <linux/dmi.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/serdev.h>
#include <net/bluetooth/bluetooth.h> #include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h> #include <net/bluetooth/hci_core.h>
...@@ -41,11 +44,15 @@ ...@@ -41,11 +44,15 @@
#include "btbcm.h" #include "btbcm.h"
#include "hci_uart.h" #include "hci_uart.h"
#define BCM_NULL_PKT 0x00
#define BCM_NULL_SIZE 0
#define BCM_LM_DIAG_PKT 0x07 #define BCM_LM_DIAG_PKT 0x07
#define BCM_LM_DIAG_SIZE 63 #define BCM_LM_DIAG_SIZE 63
#define BCM_AUTOSUSPEND_DELAY 5000 /* default autosleep delay */ #define BCM_AUTOSUSPEND_DELAY 5000 /* default autosleep delay */
/* platform device driver resources */
struct bcm_device { struct bcm_device {
struct list_head list; struct list_head list;
...@@ -59,6 +66,7 @@ struct bcm_device { ...@@ -59,6 +66,7 @@ struct bcm_device {
bool clk_enabled; bool clk_enabled;
u32 init_speed; u32 init_speed;
u32 oper_speed;
int irq; int irq;
u8 irq_polarity; u8 irq_polarity;
...@@ -68,6 +76,12 @@ struct bcm_device { ...@@ -68,6 +76,12 @@ struct bcm_device {
#endif #endif
}; };
/* serdev driver resources */
struct bcm_serdev {
struct hci_uart hu;
};
/* generic bcm uart resources */
struct bcm_data { struct bcm_data {
struct sk_buff *rx_skb; struct sk_buff *rx_skb;
struct sk_buff_head txq; struct sk_buff_head txq;
...@@ -79,6 +93,14 @@ struct bcm_data { ...@@ -79,6 +93,14 @@ struct bcm_data {
static DEFINE_MUTEX(bcm_device_lock); static DEFINE_MUTEX(bcm_device_lock);
static LIST_HEAD(bcm_device_list); static LIST_HEAD(bcm_device_list);
static inline void host_set_baudrate(struct hci_uart *hu, unsigned int speed)
{
if (hu->serdev)
serdev_device_set_baudrate(hu->serdev, speed);
else
hci_uart_set_baudrate(hu, speed);
}
static int bcm_set_baudrate(struct hci_uart *hu, unsigned int speed) static int bcm_set_baudrate(struct hci_uart *hu, unsigned int speed)
{ {
struct hci_dev *hdev = hu->hdev; struct hci_dev *hdev = hu->hdev;
...@@ -289,6 +311,14 @@ static int bcm_open(struct hci_uart *hu) ...@@ -289,6 +311,14 @@ static int bcm_open(struct hci_uart *hu)
hu->priv = bcm; hu->priv = bcm;
/* If this is a serdev defined device, then only use
* serdev open primitive and skip the rest.
*/
if (hu->serdev) {
serdev_device_open(hu->serdev);
goto out;
}
if (!hu->tty->dev) if (!hu->tty->dev)
goto out; goto out;
...@@ -303,6 +333,7 @@ static int bcm_open(struct hci_uart *hu) ...@@ -303,6 +333,7 @@ static int bcm_open(struct hci_uart *hu)
if (hu->tty->dev->parent == dev->pdev->dev.parent) { if (hu->tty->dev->parent == dev->pdev->dev.parent) {
bcm->dev = dev; bcm->dev = dev;
hu->init_speed = dev->init_speed; hu->init_speed = dev->init_speed;
hu->oper_speed = dev->oper_speed;
#ifdef CONFIG_PM #ifdef CONFIG_PM
dev->hu = hu; dev->hu = hu;
#endif #endif
...@@ -323,6 +354,12 @@ static int bcm_close(struct hci_uart *hu) ...@@ -323,6 +354,12 @@ static int bcm_close(struct hci_uart *hu)
bt_dev_dbg(hu->hdev, "hu %p", hu); bt_dev_dbg(hu->hdev, "hu %p", hu);
/* If this is a serdev defined device, only use serdev
* close primitive and then continue as usual.
*/
if (hu->serdev)
serdev_device_close(hu->serdev);
/* Protect bcm->dev against removal of the device or driver */ /* Protect bcm->dev against removal of the device or driver */
mutex_lock(&bcm_device_lock); mutex_lock(&bcm_device_lock);
if (bcm_device_exists(bdev)) { if (bcm_device_exists(bdev)) {
...@@ -398,7 +435,7 @@ static int bcm_setup(struct hci_uart *hu) ...@@ -398,7 +435,7 @@ static int bcm_setup(struct hci_uart *hu)
speed = 0; speed = 0;
if (speed) if (speed)
hci_uart_set_baudrate(hu, speed); host_set_baudrate(hu, speed);
/* Operational speed if any */ /* Operational speed if any */
if (hu->oper_speed) if (hu->oper_speed)
...@@ -411,7 +448,7 @@ static int bcm_setup(struct hci_uart *hu) ...@@ -411,7 +448,7 @@ static int bcm_setup(struct hci_uart *hu)
if (speed) { if (speed) {
err = bcm_set_baudrate(hu, speed); err = bcm_set_baudrate(hu, speed);
if (!err) if (!err)
hci_uart_set_baudrate(hu, speed); host_set_baudrate(hu, speed);
} }
finalize: finalize:
...@@ -434,11 +471,19 @@ static int bcm_setup(struct hci_uart *hu) ...@@ -434,11 +471,19 @@ static int bcm_setup(struct hci_uart *hu)
.lsize = 0, \ .lsize = 0, \
.maxlen = BCM_LM_DIAG_SIZE .maxlen = BCM_LM_DIAG_SIZE
#define BCM_RECV_NULL \
.type = BCM_NULL_PKT, \
.hlen = BCM_NULL_SIZE, \
.loff = 0, \
.lsize = 0, \
.maxlen = BCM_NULL_SIZE
static const struct h4_recv_pkt bcm_recv_pkts[] = { static const struct h4_recv_pkt bcm_recv_pkts[] = {
{ H4_RECV_ACL, .recv = hci_recv_frame }, { H4_RECV_ACL, .recv = hci_recv_frame },
{ H4_RECV_SCO, .recv = hci_recv_frame }, { H4_RECV_SCO, .recv = hci_recv_frame },
{ H4_RECV_EVENT, .recv = hci_recv_frame }, { H4_RECV_EVENT, .recv = hci_recv_frame },
{ BCM_RECV_LM_DIAG, .recv = hci_recv_diag }, { BCM_RECV_LM_DIAG, .recv = hci_recv_diag },
{ BCM_RECV_NULL, .recv = hci_recv_diag },
}; };
static int bcm_recv(struct hci_uart *hu, const void *data, int count) static int bcm_recv(struct hci_uart *hu, const void *data, int count)
...@@ -699,8 +744,10 @@ static int bcm_resource(struct acpi_resource *ares, void *data) ...@@ -699,8 +744,10 @@ static int bcm_resource(struct acpi_resource *ares, void *data)
case ACPI_RESOURCE_TYPE_SERIAL_BUS: case ACPI_RESOURCE_TYPE_SERIAL_BUS:
sb = &ares->data.uart_serial_bus; sb = &ares->data.uart_serial_bus;
if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_UART) if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_UART) {
dev->init_speed = sb->default_baud_rate; dev->init_speed = sb->default_baud_rate;
dev->oper_speed = 4000000;
}
break; break;
default: default:
...@@ -853,7 +900,6 @@ static const struct hci_uart_proto bcm_proto = { ...@@ -853,7 +900,6 @@ static const struct hci_uart_proto bcm_proto = {
.name = "Broadcom", .name = "Broadcom",
.manufacturer = 15, .manufacturer = 15,
.init_speed = 115200, .init_speed = 115200,
.oper_speed = 4000000,
.open = bcm_open, .open = bcm_open,
.close = bcm_close, .close = bcm_close,
.flush = bcm_flush, .flush = bcm_flush,
...@@ -903,9 +949,57 @@ static struct platform_driver bcm_driver = { ...@@ -903,9 +949,57 @@ static struct platform_driver bcm_driver = {
}, },
}; };
static int bcm_serdev_probe(struct serdev_device *serdev)
{
struct bcm_serdev *bcmdev;
u32 speed;
int err;
bcmdev = devm_kzalloc(&serdev->dev, sizeof(*bcmdev), GFP_KERNEL);
if (!bcmdev)
return -ENOMEM;
bcmdev->hu.serdev = serdev;
serdev_device_set_drvdata(serdev, bcmdev);
err = device_property_read_u32(&serdev->dev, "max-speed", &speed);
if (!err)
bcmdev->hu.oper_speed = speed;
return hci_uart_register_device(&bcmdev->hu, &bcm_proto);
}
static void bcm_serdev_remove(struct serdev_device *serdev)
{
struct bcm_serdev *bcmdev = serdev_device_get_drvdata(serdev);
hci_uart_unregister_device(&bcmdev->hu);
}
#ifdef CONFIG_OF
static const struct of_device_id bcm_bluetooth_of_match[] = {
{ .compatible = "brcm,bcm43438-bt" },
{ },
};
MODULE_DEVICE_TABLE(of, bcm_bluetooth_of_match);
#endif
static struct serdev_device_driver bcm_serdev_driver = {
.probe = bcm_serdev_probe,
.remove = bcm_serdev_remove,
.driver = {
.name = "hci_uart_bcm",
.of_match_table = of_match_ptr(bcm_bluetooth_of_match),
},
};
int __init bcm_init(void) int __init bcm_init(void)
{ {
/* For now, we need to keep both platform device
* driver (ACPI generated) and serdev driver (DT).
*/
platform_driver_register(&bcm_driver); platform_driver_register(&bcm_driver);
serdev_device_driver_register(&bcm_serdev_driver);
return hci_uart_register_proto(&bcm_proto); return hci_uart_register_proto(&bcm_proto);
} }
...@@ -913,6 +1007,7 @@ int __init bcm_init(void) ...@@ -913,6 +1007,7 @@ int __init bcm_init(void)
int __exit bcm_deinit(void) int __exit bcm_deinit(void)
{ {
platform_driver_unregister(&bcm_driver); platform_driver_unregister(&bcm_driver);
serdev_device_driver_unregister(&bcm_serdev_driver);
return hci_uart_unregister_proto(&bcm_proto); return hci_uart_unregister_proto(&bcm_proto);
} }
...@@ -45,6 +45,11 @@ config BT_BREDR ...@@ -45,6 +45,11 @@ config BT_BREDR
bool "Bluetooth Classic (BR/EDR) features" bool "Bluetooth Classic (BR/EDR) features"
depends on BT depends on BT
default y default y
help
Bluetooth Classic includes support for Basic Rate (BR)
available with Bluetooth version 1.0b or later and support
for Enhanced Data Rate (EDR) available with Bluetooth
version 2.0 or later.
source "net/bluetooth/rfcomm/Kconfig" source "net/bluetooth/rfcomm/Kconfig"
...@@ -58,11 +63,18 @@ config BT_HS ...@@ -58,11 +63,18 @@ config BT_HS
bool "Bluetooth High Speed (HS) features" bool "Bluetooth High Speed (HS) features"
depends on BT_BREDR depends on BT_BREDR
default y default y
help
Bluetooth High Speed includes support for off-loading
Bluetooth connections via 802.11 (wifi) physical layer
available with Bluetooth version 3.0 or later.
config BT_LE config BT_LE
bool "Bluetooth Low Energy (LE) features" bool "Bluetooth Low Energy (LE) features"
depends on BT depends on BT
default y default y
help
Bluetooth Low Energy includes support low-energy physical
layer available with Bluetooth version 4.0 or later.
config BT_6LOWPAN config BT_6LOWPAN
tristate "Bluetooth 6LoWPAN support" tristate "Bluetooth 6LoWPAN support"
......
...@@ -164,7 +164,7 @@ static int __init test_ecdh_sample(const u8 priv_a[32], const u8 priv_b[32], ...@@ -164,7 +164,7 @@ static int __init test_ecdh_sample(const u8 priv_a[32], const u8 priv_b[32],
ret = -EINVAL; ret = -EINVAL;
out: out:
kfree(dhkey_a); kfree(tmp);
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment