diff options
Diffstat (limited to 'drivers/bluetooth/hci_serdev.c')
| -rw-r--r-- | drivers/bluetooth/hci_serdev.c | 47 |
1 files changed, 31 insertions, 16 deletions
diff --git a/drivers/bluetooth/hci_serdev.c b/drivers/bluetooth/hci_serdev.c index 9e03402ef1b3..593d9cefbbf9 100644 --- a/drivers/bluetooth/hci_serdev.c +++ b/drivers/bluetooth/hci_serdev.c @@ -152,7 +152,7 @@ static int hci_uart_close(struct hci_dev *hdev) * BT SOC is completely powered OFF during BT OFF, holding port * open may drain the battery. */ - if (test_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks)) { + if (hci_test_quirk(hdev, HCI_QUIRK_NON_PERSISTENT_SETUP)) { clear_bit(HCI_UART_PROTO_READY, &hu->flags); serdev_device_close(hu->serdev); } @@ -231,6 +231,15 @@ static int hci_uart_setup(struct hci_dev *hdev) return 0; } +/* Check if the device is wakeable */ +static bool hci_uart_wakeup(struct hci_dev *hdev) +{ + /* HCI UART devices are assumed to be wakeable by default. + * Implement wakeup callback to override this behavior. + */ + return true; +} + /** hci_uart_write_wakeup - transmit buffer wakeup * @serdev: serial device * @@ -262,8 +271,8 @@ static void hci_uart_write_wakeup(struct serdev_device *serdev) * * Return: number of processed bytes */ -static int hci_uart_receive_buf(struct serdev_device *serdev, const u8 *data, - size_t count) +static size_t hci_uart_receive_buf(struct serdev_device *serdev, + const u8 *data, size_t count) { struct hci_uart *hu = serdev_device_get_drvdata(serdev); @@ -291,8 +300,9 @@ static const struct serdev_device_ops hci_serdev_client_ops = { .write_wakeup = hci_uart_write_wakeup, }; -int hci_uart_register_device(struct hci_uart *hu, - const struct hci_uart_proto *p) +int hci_uart_register_device_priv(struct hci_uart *hu, + const struct hci_uart_proto *p, + int sizeof_priv) { int err; struct hci_dev *hdev; @@ -301,9 +311,12 @@ int hci_uart_register_device(struct hci_uart *hu, serdev_device_set_client_ops(hu->serdev, &hci_serdev_client_ops); + if (percpu_init_rwsem(&hu->proto_lock)) + return -ENOMEM; + err = serdev_device_open(hu->serdev); if (err) - return err; + goto err_rwsem; err = p->open(hu); if (err) @@ -313,7 +326,7 @@ int hci_uart_register_device(struct hci_uart *hu, set_bit(HCI_UART_PROTO_READY, &hu->flags); /* Initialize and register HCI device */ - hdev = hci_alloc_dev(); + hdev = hci_alloc_dev_priv(sizeof_priv); if (!hdev) { BT_ERR("Can't allocate HCI device"); err = -ENOMEM; @@ -327,7 +340,6 @@ int hci_uart_register_device(struct hci_uart *hu, INIT_WORK(&hu->init_ready, hci_uart_init_work); INIT_WORK(&hu->write_work, hci_uart_write_work); - percpu_init_rwsem(&hu->proto_lock); /* Only when vendor specific setup callback is provided, consider * the manufacturer information valid. This avoids filling in the @@ -341,18 +353,18 @@ int hci_uart_register_device(struct hci_uart *hu, hdev->flush = hci_uart_flush; hdev->send = hci_uart_send_frame; hdev->setup = hci_uart_setup; + if (!hdev->wakeup) + hdev->wakeup = hci_uart_wakeup; SET_HCIDEV_DEV(hdev, &hu->serdev->dev); + if (test_bit(HCI_UART_NO_SUSPEND_NOTIFIER, &hu->flags)) + hci_set_quirk(hdev, HCI_QUIRK_NO_SUSPEND_NOTIFIER); + if (test_bit(HCI_UART_RAW_DEVICE, &hu->hdev_flags)) - set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_RAW_DEVICE); if (test_bit(HCI_UART_EXT_CONFIG, &hu->hdev_flags)) - set_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks); - - if (test_bit(HCI_UART_CREATE_AMP, &hu->hdev_flags)) - hdev->dev_type = HCI_AMP; - else - hdev->dev_type = HCI_PRIMARY; + hci_set_quirk(hdev, HCI_QUIRK_EXTERNAL_CONFIG); if (test_bit(HCI_UART_INIT_PENDING, &hu->hdev_flags)) return 0; @@ -374,9 +386,11 @@ err_alloc: p->close(hu); err_open: serdev_device_close(hu->serdev); +err_rwsem: + percpu_free_rwsem(&hu->proto_lock); return err; } -EXPORT_SYMBOL_GPL(hci_uart_register_device); +EXPORT_SYMBOL_GPL(hci_uart_register_device_priv); void hci_uart_unregister_device(struct hci_uart *hu) { @@ -395,5 +409,6 @@ void hci_uart_unregister_device(struct hci_uart *hu) clear_bit(HCI_UART_PROTO_READY, &hu->flags); serdev_device_close(hu->serdev); } + percpu_free_rwsem(&hu->proto_lock); } EXPORT_SYMBOL_GPL(hci_uart_unregister_device); |
