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

Johan Hedberg says:

====================
pull request: bluetooth-next 2018-06-04

Here's one last bluetooth-next pull request for the 4.18 kernel:

 - New USB device IDs for Realtek 8822BE and 8723DE
 - reset/resume fix for Dell Inspiron 5565
 - Fix HCI_UART_INIT_PENDING flag behavior
 - Fix patching behavior for some ATH3012 models
 - A few other minor cleanups & fixes

Please let me know if there are any issues pulling. Thanks.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2018-06-04 17:22:17 -04:00
Родитель bb38ccce88 1cd2fabf4b
Коммит 828da43224
15 изменённых файлов: 102 добавлений и 147 удалений

Просмотреть файл

@ -35,15 +35,9 @@ static ssize_t btmrvl_hscfgcmd_write(struct file *file,
const char __user *ubuf, size_t count, loff_t *ppos) const char __user *ubuf, size_t count, loff_t *ppos)
{ {
struct btmrvl_private *priv = file->private_data; struct btmrvl_private *priv = file->private_data;
char buf[16];
long result, ret; long result, ret;
memset(buf, 0, sizeof(buf)); ret = kstrtol_from_user(ubuf, count, 10, &result);
if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
return -EFAULT;
ret = kstrtol(buf, 10, &result);
if (ret) if (ret)
return ret; return ret;
@ -81,15 +75,9 @@ static ssize_t btmrvl_pscmd_write(struct file *file, const char __user *ubuf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct btmrvl_private *priv = file->private_data; struct btmrvl_private *priv = file->private_data;
char buf[16];
long result, ret; long result, ret;
memset(buf, 0, sizeof(buf)); ret = kstrtol_from_user(ubuf, count, 10, &result);
if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
return -EFAULT;
ret = kstrtol(buf, 10, &result);
if (ret) if (ret)
return ret; return ret;
@ -127,15 +115,9 @@ static ssize_t btmrvl_hscmd_write(struct file *file, const char __user *ubuf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct btmrvl_private *priv = file->private_data; struct btmrvl_private *priv = file->private_data;
char buf[16];
long result, ret; long result, ret;
memset(buf, 0, sizeof(buf)); ret = kstrtol_from_user(ubuf, count, 10, &result);
if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
return -EFAULT;
ret = kstrtol(buf, 10, &result);
if (ret) if (ret)
return ret; return ret;
@ -167,35 +149,6 @@ static const struct file_operations btmrvl_hscmd_fops = {
.llseek = default_llseek, .llseek = default_llseek,
}; };
static ssize_t btmrvl_fwdump_write(struct file *file, const char __user *ubuf,
size_t count, loff_t *ppos)
{
struct btmrvl_private *priv = file->private_data;
char buf[16];
bool result;
memset(buf, 0, sizeof(buf));
if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
return -EFAULT;
if (strtobool(buf, &result))
return -EINVAL;
if (!result)
return -EINVAL;
btmrvl_firmware_dump(priv);
return count;
}
static const struct file_operations btmrvl_fwdump_fops = {
.write = btmrvl_fwdump_write,
.open = simple_open,
.llseek = default_llseek,
};
void btmrvl_debugfs_init(struct hci_dev *hdev) void btmrvl_debugfs_init(struct hci_dev *hdev)
{ {
struct btmrvl_private *priv = hci_get_drvdata(hdev); struct btmrvl_private *priv = hci_get_drvdata(hdev);
@ -226,8 +179,6 @@ void btmrvl_debugfs_init(struct hci_dev *hdev)
priv, &btmrvl_hscmd_fops); priv, &btmrvl_hscmd_fops);
debugfs_create_file("hscfgcmd", 0644, dbg->config_dir, debugfs_create_file("hscfgcmd", 0644, dbg->config_dir,
priv, &btmrvl_hscfgcmd_fops); priv, &btmrvl_hscfgcmd_fops);
debugfs_create_file("fw_dump", 0200, dbg->config_dir,
priv, &btmrvl_fwdump_fops);
dbg->status_dir = debugfs_create_dir("status", hdev->debugfs); dbg->status_dir = debugfs_create_dir("status", hdev->debugfs);
debugfs_create_u8("curpsmode", 0444, dbg->status_dir, debugfs_create_u8("curpsmode", 0444, dbg->status_dir,

Просмотреть файл

@ -110,7 +110,6 @@ struct btmrvl_private {
u8 *payload, u16 nb); u8 *payload, u16 nb);
int (*hw_wakeup_firmware)(struct btmrvl_private *priv); int (*hw_wakeup_firmware)(struct btmrvl_private *priv);
int (*hw_process_int_status)(struct btmrvl_private *priv); int (*hw_process_int_status)(struct btmrvl_private *priv);
void (*firmware_dump)(struct btmrvl_private *priv);
spinlock_t driver_lock; /* spinlock used by driver */ spinlock_t driver_lock; /* spinlock used by driver */
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
void *debugfs_data; void *debugfs_data;
@ -183,7 +182,6 @@ int btmrvl_send_hscfg_cmd(struct btmrvl_private *priv);
int btmrvl_enable_ps(struct btmrvl_private *priv); int btmrvl_enable_ps(struct btmrvl_private *priv);
int btmrvl_prepare_command(struct btmrvl_private *priv); int btmrvl_prepare_command(struct btmrvl_private *priv);
int btmrvl_enable_hs(struct btmrvl_private *priv); int btmrvl_enable_hs(struct btmrvl_private *priv);
void btmrvl_firmware_dump(struct btmrvl_private *priv);
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
void btmrvl_debugfs_init(struct hci_dev *hdev); void btmrvl_debugfs_init(struct hci_dev *hdev);

Просмотреть файл

@ -358,12 +358,6 @@ int btmrvl_prepare_command(struct btmrvl_private *priv)
return ret; return ret;
} }
void btmrvl_firmware_dump(struct btmrvl_private *priv)
{
if (priv->firmware_dump)
priv->firmware_dump(priv);
}
static int btmrvl_tx_pkt(struct btmrvl_private *priv, struct sk_buff *skb) static int btmrvl_tx_pkt(struct btmrvl_private *priv, struct sk_buff *skb)
{ {
int ret = 0; int ret = 0;

Просмотреть файл

@ -1311,9 +1311,11 @@ rdwr_status btmrvl_sdio_rdwr_firmware(struct btmrvl_private *priv,
} }
/* This function dump sdio register and memory data */ /* This function dump sdio register and memory data */
static void btmrvl_sdio_dump_firmware(struct btmrvl_private *priv) static void btmrvl_sdio_coredump(struct device *dev)
{ {
struct btmrvl_sdio_card *card = priv->btmrvl_dev.card; struct sdio_func *func = dev_to_sdio_func(dev);
struct btmrvl_sdio_card *card;
struct btmrvl_private *priv;
int ret = 0; int ret = 0;
unsigned int reg, reg_start, reg_end; unsigned int reg, reg_start, reg_end;
enum rdwr_status stat; enum rdwr_status stat;
@ -1321,6 +1323,9 @@ static void btmrvl_sdio_dump_firmware(struct btmrvl_private *priv)
u8 dump_num = 0, idx, i, read_reg, doneflag = 0; u8 dump_num = 0, idx, i, read_reg, doneflag = 0;
u32 memory_size, fw_dump_len = 0; u32 memory_size, fw_dump_len = 0;
card = sdio_get_drvdata(func);
priv = card->priv;
/* dump sdio register first */ /* dump sdio register first */
btmrvl_sdio_dump_regs(priv); btmrvl_sdio_dump_regs(priv);
@ -1547,7 +1552,6 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
priv->hw_host_to_card = btmrvl_sdio_host_to_card; priv->hw_host_to_card = btmrvl_sdio_host_to_card;
priv->hw_wakeup_firmware = btmrvl_sdio_wakeup_fw; priv->hw_wakeup_firmware = btmrvl_sdio_wakeup_fw;
priv->hw_process_int_status = btmrvl_sdio_process_int_status; priv->hw_process_int_status = btmrvl_sdio_process_int_status;
priv->firmware_dump = btmrvl_sdio_dump_firmware;
if (btmrvl_register_hdev(priv)) { if (btmrvl_register_hdev(priv)) {
BT_ERR("Register hdev failed!"); BT_ERR("Register hdev failed!");
@ -1717,6 +1721,7 @@ static struct sdio_driver bt_mrvl_sdio = {
.remove = btmrvl_sdio_remove, .remove = btmrvl_sdio_remove,
.drv = { .drv = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.coredump = btmrvl_sdio_coredump,
.pm = &btmrvl_sdio_pm_ops, .pm = &btmrvl_sdio_pm_ops,
} }
}; };

Просмотреть файл

@ -373,6 +373,9 @@ static const struct usb_device_id blacklist_table[] = {
/* Additional Realtek 8723BU Bluetooth devices */ /* Additional Realtek 8723BU Bluetooth devices */
{ USB_DEVICE(0x7392, 0xa611), .driver_info = BTUSB_REALTEK }, { USB_DEVICE(0x7392, 0xa611), .driver_info = BTUSB_REALTEK },
/* Additional Realtek 8723DE Bluetooth devices */
{ USB_DEVICE(0x2ff8, 0xb011), .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 },
{ USB_DEVICE(0x13d3, 0x3414), .driver_info = BTUSB_REALTEK }, { USB_DEVICE(0x13d3, 0x3414), .driver_info = BTUSB_REALTEK },
@ -381,6 +384,7 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x13d3, 0x3462), .driver_info = BTUSB_REALTEK }, { USB_DEVICE(0x13d3, 0x3462), .driver_info = BTUSB_REALTEK },
/* Additional Realtek 8822BE Bluetooth devices */ /* Additional Realtek 8822BE Bluetooth devices */
{ USB_DEVICE(0x13d3, 0x3526), .driver_info = BTUSB_REALTEK },
{ USB_DEVICE(0x0b05, 0x185c), .driver_info = BTUSB_REALTEK }, { USB_DEVICE(0x0b05, 0x185c), .driver_info = BTUSB_REALTEK },
/* Silicon Wave based devices */ /* Silicon Wave based devices */
@ -408,6 +412,13 @@ static const struct dmi_system_id btusb_needs_reset_resume_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "XPS 13 9360"), DMI_MATCH(DMI_PRODUCT_NAME, "XPS 13 9360"),
}, },
}, },
{
/* Dell Inspiron 5565 (QCA ROME device 0cf3:e009) */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5565"),
},
},
{} {}
}; };
@ -2499,11 +2510,9 @@ static const struct qca_device_info qca_devices_table[] = {
{ 0x00000302, 28, 4, 18 }, /* Rome 3.2 */ { 0x00000302, 28, 4, 18 }, /* Rome 3.2 */
}; };
static int btusb_qca_send_vendor_req(struct hci_dev *hdev, u8 request, static int btusb_qca_send_vendor_req(struct usb_device *udev, u8 request,
void *data, u16 size) void *data, u16 size)
{ {
struct btusb_data *btdata = hci_get_drvdata(hdev);
struct usb_device *udev = btdata->udev;
int pipe, err; int pipe, err;
u8 *buf; u8 *buf;
@ -2518,7 +2527,7 @@ static int btusb_qca_send_vendor_req(struct hci_dev *hdev, u8 request,
err = usb_control_msg(udev, pipe, request, USB_TYPE_VENDOR | USB_DIR_IN, err = usb_control_msg(udev, pipe, request, USB_TYPE_VENDOR | USB_DIR_IN,
0, 0, buf, size, USB_CTRL_SET_TIMEOUT); 0, 0, buf, size, USB_CTRL_SET_TIMEOUT);
if (err < 0) { if (err < 0) {
bt_dev_err(hdev, "Failed to access otp area (%d)", err); dev_err(&udev->dev, "Failed to access otp area (%d)", err);
goto done; goto done;
} }
@ -2668,20 +2677,38 @@ static int btusb_setup_qca_load_nvm(struct hci_dev *hdev,
return err; return err;
} }
/* identify the ROM version and check whether patches are needed */
static bool btusb_qca_need_patch(struct usb_device *udev)
{
struct qca_version ver;
if (btusb_qca_send_vendor_req(udev, QCA_GET_TARGET_VERSION, &ver,
sizeof(ver)) < 0)
return false;
/* only low ROM versions need patches */
return !(le32_to_cpu(ver.rom_version) & ~0xffffU);
}
static int btusb_setup_qca(struct hci_dev *hdev) static int btusb_setup_qca(struct hci_dev *hdev)
{ {
struct btusb_data *btdata = hci_get_drvdata(hdev);
struct usb_device *udev = btdata->udev;
const struct qca_device_info *info = NULL; const struct qca_device_info *info = NULL;
struct qca_version ver; struct qca_version ver;
u32 ver_rom; u32 ver_rom;
u8 status; u8 status;
int i, err; int i, err;
err = btusb_qca_send_vendor_req(hdev, QCA_GET_TARGET_VERSION, &ver, err = btusb_qca_send_vendor_req(udev, QCA_GET_TARGET_VERSION, &ver,
sizeof(ver)); sizeof(ver));
if (err < 0) if (err < 0)
return err; return err;
ver_rom = le32_to_cpu(ver.rom_version); ver_rom = le32_to_cpu(ver.rom_version);
/* Don't care about high ROM versions */
if (ver_rom & ~0xffffU)
return 0;
for (i = 0; i < ARRAY_SIZE(qca_devices_table); i++) { for (i = 0; i < ARRAY_SIZE(qca_devices_table); i++) {
if (ver_rom == qca_devices_table[i].rom_version) if (ver_rom == qca_devices_table[i].rom_version)
info = &qca_devices_table[i]; info = &qca_devices_table[i];
@ -2691,7 +2718,7 @@ static int btusb_setup_qca(struct hci_dev *hdev)
return -ENODEV; return -ENODEV;
} }
err = btusb_qca_send_vendor_req(hdev, QCA_CHECK_STATUS, &status, err = btusb_qca_send_vendor_req(udev, QCA_CHECK_STATUS, &status,
sizeof(status)); sizeof(status));
if (err < 0) if (err < 0)
return err; return err;
@ -2905,7 +2932,8 @@ static int btusb_probe(struct usb_interface *intf,
/* Old firmware would otherwise let ath3k driver load /* Old firmware would otherwise let ath3k driver load
* patch and sysconfig files * patch and sysconfig files
*/ */
if (le16_to_cpu(udev->descriptor.bcdDevice) <= 0x0001) if (le16_to_cpu(udev->descriptor.bcdDevice) <= 0x0001 &&
!btusb_qca_need_patch(udev))
return -ENODEV; return -ENODEV;
} }
@ -3067,6 +3095,7 @@ static int btusb_probe(struct usb_interface *intf,
} }
if (id->driver_info & BTUSB_ATH3012) { if (id->driver_info & BTUSB_ATH3012) {
data->setup_on_usb = btusb_setup_qca;
hdev->set_bdaddr = btusb_set_bdaddr_ath3012; hdev->set_bdaddr = btusb_set_bdaddr_ath3012;
set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks);

Просмотреть файл

@ -380,10 +380,6 @@ static int bcm_open(struct hci_uart *hu)
mutex_lock(&bcm_device_lock); mutex_lock(&bcm_device_lock);
if (hu->serdev) { if (hu->serdev) {
err = serdev_device_open(hu->serdev);
if (err)
goto err_free;
bcm->dev = serdev_device_get_drvdata(hu->serdev); bcm->dev = serdev_device_get_drvdata(hu->serdev);
goto out; goto out;
} }
@ -420,13 +416,10 @@ out:
return 0; return 0;
err_unset_hu: err_unset_hu:
if (hu->serdev)
serdev_device_close(hu->serdev);
#ifdef CONFIG_PM #ifdef CONFIG_PM
else if (!hu->serdev)
bcm->dev->hu = NULL; bcm->dev->hu = NULL;
#endif #endif
err_free:
mutex_unlock(&bcm_device_lock); mutex_unlock(&bcm_device_lock);
hu->priv = NULL; hu->priv = NULL;
kfree(bcm); kfree(bcm);
@ -445,7 +438,6 @@ static int bcm_close(struct hci_uart *hu)
mutex_lock(&bcm_device_lock); mutex_lock(&bcm_device_lock);
if (hu->serdev) { if (hu->serdev) {
serdev_device_close(hu->serdev);
bdev = serdev_device_get_drvdata(hu->serdev); bdev = serdev_device_get_drvdata(hu->serdev);
} else if (bcm_device_exists(bcm->dev)) { } else if (bcm_device_exists(bcm->dev)) {
bdev = bcm->dev; bdev = bcm->dev;

Просмотреть файл

@ -195,7 +195,7 @@ restart:
clear_bit(HCI_UART_SENDING, &hu->tx_state); clear_bit(HCI_UART_SENDING, &hu->tx_state);
} }
static void hci_uart_init_work(struct work_struct *work) void hci_uart_init_work(struct work_struct *work)
{ {
struct hci_uart *hu = container_of(work, struct hci_uart, init_ready); struct hci_uart *hu = container_of(work, struct hci_uart, init_ready);
int err; int err;
@ -229,15 +229,6 @@ int hci_uart_init_ready(struct hci_uart *hu)
} }
/* ------- Interface to HCI layer ------ */ /* ------- Interface to HCI layer ------ */
/* Initialize device */
static int hci_uart_open(struct hci_dev *hdev)
{
BT_DBG("%s %p", hdev->name, hdev);
/* Nothing to do for UART driver */
return 0;
}
/* Reset device */ /* Reset device */
static int hci_uart_flush(struct hci_dev *hdev) static int hci_uart_flush(struct hci_dev *hdev)
{ {
@ -264,6 +255,17 @@ static int hci_uart_flush(struct hci_dev *hdev)
return 0; return 0;
} }
/* Initialize device */
static int hci_uart_open(struct hci_dev *hdev)
{
BT_DBG("%s %p", hdev->name, hdev);
/* Undo clearing this from hci_uart_close() */
hdev->flush = hci_uart_flush;
return 0;
}
/* Close device */ /* Close device */
static int hci_uart_close(struct hci_dev *hdev) static int hci_uart_close(struct hci_dev *hdev)
{ {

Просмотреть файл

@ -141,7 +141,6 @@ static int ll_open(struct hci_uart *hu)
if (hu->serdev) { if (hu->serdev) {
struct ll_device *lldev = serdev_device_get_drvdata(hu->serdev); struct ll_device *lldev = serdev_device_get_drvdata(hu->serdev);
serdev_device_open(hu->serdev);
if (!IS_ERR(lldev->ext_clk)) if (!IS_ERR(lldev->ext_clk))
clk_prepare_enable(lldev->ext_clk); clk_prepare_enable(lldev->ext_clk);
} }
@ -179,8 +178,6 @@ static int ll_close(struct hci_uart *hu)
gpiod_set_value_cansleep(lldev->enable_gpio, 0); gpiod_set_value_cansleep(lldev->enable_gpio, 0);
clk_disable_unprepare(lldev->ext_clk); clk_disable_unprepare(lldev->ext_clk);
serdev_device_close(hu->serdev);
} }
hu->priv = NULL; hu->priv = NULL;

Просмотреть файл

@ -477,8 +477,6 @@ static int nokia_open(struct hci_uart *hu)
dev_dbg(dev, "protocol open"); dev_dbg(dev, "protocol open");
serdev_device_open(hu->serdev);
pm_runtime_enable(dev); pm_runtime_enable(dev);
return 0; return 0;
@ -513,7 +511,6 @@ static int nokia_close(struct hci_uart *hu)
gpiod_set_value(btdev->wakeup_bt, 0); gpiod_set_value(btdev->wakeup_bt, 0);
pm_runtime_disable(&btdev->serdev->dev); pm_runtime_disable(&btdev->serdev->dev);
serdev_device_close(btdev->serdev);
return 0; return 0;
} }

Просмотреть файл

@ -910,7 +910,7 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate)
*/ */
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(msecs_to_jiffies(BAUDRATE_SETTLE_TIMEOUT_MS)); schedule_timeout(msecs_to_jiffies(BAUDRATE_SETTLE_TIMEOUT_MS));
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_RUNNING);
return 0; return 0;
} }

Просмотреть файл

@ -101,14 +101,6 @@ static void hci_uart_write_work(struct work_struct *work)
/* ------- Interface to HCI layer ------ */ /* ------- Interface to HCI layer ------ */
/* Initialize device */
static int hci_uart_open(struct hci_dev *hdev)
{
BT_DBG("%s %p", hdev->name, hdev);
return 0;
}
/* Reset device */ /* Reset device */
static int hci_uart_flush(struct hci_dev *hdev) static int hci_uart_flush(struct hci_dev *hdev)
{ {
@ -129,6 +121,17 @@ static int hci_uart_flush(struct hci_dev *hdev)
return 0; return 0;
} }
/* Initialize device */
static int hci_uart_open(struct hci_dev *hdev)
{
BT_DBG("%s %p", hdev->name, hdev);
/* Undo clearing this from hci_uart_close() */
hdev->flush = hci_uart_flush;
return 0;
}
/* Close device */ /* Close device */
static int hci_uart_close(struct hci_dev *hdev) static int hci_uart_close(struct hci_dev *hdev)
{ {
@ -204,9 +207,8 @@ static int hci_uart_setup(struct hci_dev *hdev)
return 0; return 0;
} }
if (skb->len != sizeof(*ver)) { if (skb->len != sizeof(*ver))
bt_dev_err(hdev, "Event length mismatch for version info"); bt_dev_err(hdev, "Event length mismatch for version info");
}
kfree_skb(skb); kfree_skb(skb);
return 0; return 0;
@ -282,10 +284,14 @@ int hci_uart_register_device(struct hci_uart *hu,
serdev_device_set_client_ops(hu->serdev, &hci_serdev_client_ops); serdev_device_set_client_ops(hu->serdev, &hci_serdev_client_ops);
err = p->open(hu); err = serdev_device_open(hu->serdev);
if (err) if (err)
return err; return err;
err = p->open(hu);
if (err)
goto err_open;
hu->proto = p; hu->proto = p;
set_bit(HCI_UART_PROTO_READY, &hu->flags); set_bit(HCI_UART_PROTO_READY, &hu->flags);
@ -302,6 +308,7 @@ int hci_uart_register_device(struct hci_uart *hu,
hdev->bus = HCI_UART; hdev->bus = HCI_UART;
hci_set_drvdata(hdev, hu); hci_set_drvdata(hdev, hu);
INIT_WORK(&hu->init_ready, hci_uart_init_work);
INIT_WORK(&hu->write_work, hci_uart_write_work); INIT_WORK(&hu->write_work, hci_uart_write_work);
percpu_init_rwsem(&hu->proto_lock); percpu_init_rwsem(&hu->proto_lock);
@ -351,6 +358,8 @@ err_register:
err_alloc: err_alloc:
clear_bit(HCI_UART_PROTO_READY, &hu->flags); clear_bit(HCI_UART_PROTO_READY, &hu->flags);
p->close(hu); p->close(hu);
err_open:
serdev_device_close(hu->serdev);
return err; return err;
} }
EXPORT_SYMBOL_GPL(hci_uart_register_device); EXPORT_SYMBOL_GPL(hci_uart_register_device);
@ -365,5 +374,6 @@ void hci_uart_unregister_device(struct hci_uart *hu)
cancel_work_sync(&hu->write_work); cancel_work_sync(&hu->write_work);
hu->proto->close(hu); hu->proto->close(hu);
serdev_device_close(hu->serdev);
} }
EXPORT_SYMBOL_GPL(hci_uart_unregister_device); EXPORT_SYMBOL_GPL(hci_uart_unregister_device);

Просмотреть файл

@ -116,6 +116,7 @@ void hci_uart_unregister_device(struct hci_uart *hu);
int hci_uart_tx_wakeup(struct hci_uart *hu); int hci_uart_tx_wakeup(struct hci_uart *hu);
int hci_uart_init_ready(struct hci_uart *hu); int hci_uart_init_ready(struct hci_uart *hu);
void hci_uart_init_work(struct work_struct *work);
void hci_uart_set_baudrate(struct hci_uart *hu, unsigned int speed); void hci_uart_set_baudrate(struct hci_uart *hu, unsigned int speed);
void hci_uart_set_flow_control(struct hci_uart *hu, bool enable); void hci_uart_set_flow_control(struct hci_uart *hu, bool enable);
void hci_uart_set_speeds(struct hci_uart *hu, unsigned int init_speed, void hci_uart_set_speeds(struct hci_uart *hu, unsigned int init_speed,

Просмотреть файл

@ -76,19 +76,15 @@ static ssize_t dut_mode_write(struct file *file, const char __user *user_buf,
{ {
struct hci_dev *hdev = file->private_data; struct hci_dev *hdev = file->private_data;
struct sk_buff *skb; struct sk_buff *skb;
char buf[32];
size_t buf_size = min(count, (sizeof(buf)-1));
bool enable; bool enable;
int err;
if (!test_bit(HCI_UP, &hdev->flags)) if (!test_bit(HCI_UP, &hdev->flags))
return -ENETDOWN; return -ENETDOWN;
if (copy_from_user(buf, user_buf, buf_size)) err = kstrtobool_from_user(user_buf, count, &enable);
return -EFAULT; if (err)
return err;
buf[buf_size] = '\0';
if (strtobool(buf, &enable))
return -EINVAL;
if (enable == hci_dev_test_flag(hdev, HCI_DUT_MODE)) if (enable == hci_dev_test_flag(hdev, HCI_DUT_MODE))
return -EALREADY; return -EALREADY;
@ -135,17 +131,12 @@ static ssize_t vendor_diag_write(struct file *file, const char __user *user_buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct hci_dev *hdev = file->private_data; struct hci_dev *hdev = file->private_data;
char buf[32];
size_t buf_size = min(count, (sizeof(buf)-1));
bool enable; bool enable;
int err; int err;
if (copy_from_user(buf, user_buf, buf_size)) err = kstrtobool_from_user(user_buf, count, &enable);
return -EFAULT; if (err)
return err;
buf[buf_size] = '\0';
if (strtobool(buf, &enable))
return -EINVAL;
/* When the diagnostic flags are not persistent and the transport /* When the diagnostic flags are not persistent and the transport
* is not active or in user channel operation, then there is no need * is not active or in user channel operation, then there is no need

Просмотреть файл

@ -47,19 +47,15 @@ static ssize_t __name ## _write(struct file *file, \
size_t count, loff_t *ppos) \ size_t count, loff_t *ppos) \
{ \ { \
struct hci_dev *hdev = file->private_data; \ struct hci_dev *hdev = file->private_data; \
char buf[32]; \
size_t buf_size = min(count, (sizeof(buf) - 1)); \
bool enable; \ bool enable; \
int err; \
\ \
if (test_bit(HCI_UP, &hdev->flags)) \ if (test_bit(HCI_UP, &hdev->flags)) \
return -EBUSY; \ return -EBUSY; \
\ \
if (copy_from_user(buf, user_buf, buf_size)) \ err = kstrtobool_from_user(user_buf, count, &enable); \
return -EFAULT; \ if (err) \
\ return err; \
buf[buf_size] = '\0'; \
if (strtobool(buf, &enable)) \
return -EINVAL; \
\ \
if (enable == test_bit(__quirk, &hdev->quirks)) \ if (enable == test_bit(__quirk, &hdev->quirks)) \
return -EALREADY; \ return -EALREADY; \
@ -658,19 +654,15 @@ static ssize_t force_static_address_write(struct file *file,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct hci_dev *hdev = file->private_data; struct hci_dev *hdev = file->private_data;
char buf[32];
size_t buf_size = min(count, (sizeof(buf)-1));
bool enable; bool enable;
int err;
if (test_bit(HCI_UP, &hdev->flags)) if (test_bit(HCI_UP, &hdev->flags))
return -EBUSY; return -EBUSY;
if (copy_from_user(buf, user_buf, buf_size)) err = kstrtobool_from_user(user_buf, count, &enable);
return -EFAULT; if (err)
return err;
buf[buf_size] = '\0';
if (strtobool(buf, &enable))
return -EINVAL;
if (enable == hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR)) if (enable == hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR))
return -EALREADY; return -EALREADY;

Просмотреть файл

@ -3315,16 +3315,12 @@ static ssize_t force_bredr_smp_write(struct file *file,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct hci_dev *hdev = file->private_data; struct hci_dev *hdev = file->private_data;
char buf[32];
size_t buf_size = min(count, (sizeof(buf)-1));
bool enable; bool enable;
int err;
if (copy_from_user(buf, user_buf, buf_size)) err = kstrtobool_from_user(user_buf, count, &enable);
return -EFAULT; if (err)
return err;
buf[buf_size] = '\0';
if (strtobool(buf, &enable))
return -EINVAL;
if (enable == hci_dev_test_flag(hdev, HCI_FORCE_BREDR_SMP)) if (enable == hci_dev_test_flag(hdev, HCI_FORCE_BREDR_SMP))
return -EALREADY; return -EALREADY;