summaryrefslogtreecommitdiff
path: root/drivers/bluetooth/virtio_bt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/bluetooth/virtio_bt.c')
-rw-r--r--drivers/bluetooth/virtio_bt.c62
1 files changed, 40 insertions, 22 deletions
diff --git a/drivers/bluetooth/virtio_bt.c b/drivers/bluetooth/virtio_bt.c
index fd281d439505..6f1a37e85c6a 100644
--- a/drivers/bluetooth/virtio_bt.c
+++ b/drivers/bluetooth/virtio_bt.c
@@ -50,8 +50,11 @@ static int virtbt_add_inbuf(struct virtio_bluetooth *vbt)
static int virtbt_open(struct hci_dev *hdev)
{
- struct virtio_bluetooth *vbt = hci_get_drvdata(hdev);
+ return 0;
+}
+static int virtbt_open_vdev(struct virtio_bluetooth *vbt)
+{
if (virtbt_add_inbuf(vbt) < 0)
return -EIO;
@@ -61,7 +64,11 @@ static int virtbt_open(struct hci_dev *hdev)
static int virtbt_close(struct hci_dev *hdev)
{
- struct virtio_bluetooth *vbt = hci_get_drvdata(hdev);
+ return 0;
+}
+
+static int virtbt_close_vdev(struct virtio_bluetooth *vbt)
+{
int i;
cancel_work_sync(&vbt->rx);
@@ -72,6 +79,7 @@ static int virtbt_close(struct hci_dev *hdev)
while ((skb = virtqueue_detach_unused_buf(vq)))
kfree_skb(skb);
+ cond_resched();
}
return 0;
@@ -246,13 +254,9 @@ static void virtbt_rx_done(struct virtqueue *vq)
static int virtbt_probe(struct virtio_device *vdev)
{
- vq_callback_t *callbacks[VIRTBT_NUM_VQS] = {
- [VIRTBT_VQ_TX] = virtbt_tx_done,
- [VIRTBT_VQ_RX] = virtbt_rx_done,
- };
- const char *names[VIRTBT_NUM_VQS] = {
- [VIRTBT_VQ_TX] = "tx",
- [VIRTBT_VQ_RX] = "rx",
+ struct virtqueue_info vqs_info[VIRTBT_NUM_VQS] = {
+ [VIRTBT_VQ_TX] = { "tx", virtbt_tx_done },
+ [VIRTBT_VQ_RX] = { "rx", virtbt_rx_done },
};
struct virtio_bluetooth *vbt;
struct hci_dev *hdev;
@@ -266,7 +270,6 @@ static int virtbt_probe(struct virtio_device *vdev)
switch (type) {
case VIRTIO_BT_CONFIG_TYPE_PRIMARY:
- case VIRTIO_BT_CONFIG_TYPE_AMP:
break;
default:
return -EINVAL;
@@ -281,8 +284,7 @@ static int virtbt_probe(struct virtio_device *vdev)
INIT_WORK(&vbt->rx, virtbt_rx_work);
- err = virtio_find_vqs(vdev, VIRTBT_NUM_VQS, vbt->vqs, callbacks,
- names, NULL);
+ err = virtio_find_vqs(vdev, VIRTBT_NUM_VQS, vbt->vqs, vqs_info, NULL);
if (err)
return err;
@@ -295,7 +297,6 @@ static int virtbt_probe(struct virtio_device *vdev)
vbt->hdev = hdev;
hdev->bus = HCI_VIRTIO;
- hdev->dev_type = type;
hci_set_drvdata(hdev, vbt);
hdev->open = virtbt_open;
@@ -306,7 +307,12 @@ static int virtbt_probe(struct virtio_device *vdev)
if (virtio_has_feature(vdev, VIRTIO_BT_F_VND_HCI)) {
__u16 vendor;
- virtio_cread(vdev, struct virtio_bt_config, vendor, &vendor);
+ if (virtio_has_feature(vdev, VIRTIO_BT_F_CONFIG_V2))
+ virtio_cread(vdev, struct virtio_bt_config_v2,
+ vendor, &vendor);
+ else
+ virtio_cread(vdev, struct virtio_bt_config,
+ vendor, &vendor);
switch (vendor) {
case VIRTIO_BT_CONFIG_VENDOR_ZEPHYR:
@@ -321,17 +327,17 @@ static int virtbt_probe(struct virtio_device *vdev)
hdev->setup = virtbt_setup_intel;
hdev->shutdown = virtbt_shutdown_generic;
hdev->set_bdaddr = virtbt_set_bdaddr_intel;
- set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks);
- set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
- set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks);
+ hci_set_quirk(hdev, HCI_QUIRK_STRICT_DUPLICATE_FILTER);
+ hci_set_quirk(hdev, HCI_QUIRK_SIMULTANEOUS_DISCOVERY);
+ hci_set_quirk(hdev, HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED);
break;
case VIRTIO_BT_CONFIG_VENDOR_REALTEK:
hdev->manufacturer = 93;
hdev->setup = virtbt_setup_realtek;
hdev->shutdown = virtbt_shutdown_generic;
- set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
- set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks);
+ hci_set_quirk(hdev, HCI_QUIRK_SIMULTANEOUS_DISCOVERY);
+ hci_set_quirk(hdev, HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED);
break;
}
}
@@ -339,8 +345,12 @@ static int virtbt_probe(struct virtio_device *vdev)
if (virtio_has_feature(vdev, VIRTIO_BT_F_MSFT_EXT)) {
__u16 msft_opcode;
- virtio_cread(vdev, struct virtio_bt_config,
- msft_opcode, &msft_opcode);
+ if (virtio_has_feature(vdev, VIRTIO_BT_F_CONFIG_V2))
+ virtio_cread(vdev, struct virtio_bt_config_v2,
+ msft_opcode, &msft_opcode);
+ else
+ virtio_cread(vdev, struct virtio_bt_config,
+ msft_opcode, &msft_opcode);
hci_set_msft_opcode(hdev, msft_opcode);
}
@@ -354,8 +364,15 @@ static int virtbt_probe(struct virtio_device *vdev)
goto failed;
}
+ virtio_device_ready(vdev);
+ err = virtbt_open_vdev(vbt);
+ if (err)
+ goto open_failed;
+
return 0;
+open_failed:
+ hci_free_dev(hdev);
failed:
vdev->config->del_vqs(vdev);
return err;
@@ -368,6 +385,7 @@ static void virtbt_remove(struct virtio_device *vdev)
hci_unregister_dev(hdev);
virtio_reset_device(vdev);
+ virtbt_close_vdev(vbt);
hci_free_dev(hdev);
vbt->hdev = NULL;
@@ -387,11 +405,11 @@ static const unsigned int virtbt_features[] = {
VIRTIO_BT_F_VND_HCI,
VIRTIO_BT_F_MSFT_EXT,
VIRTIO_BT_F_AOSP_EXT,
+ VIRTIO_BT_F_CONFIG_V2,
};
static struct virtio_driver virtbt_driver = {
.driver.name = KBUILD_MODNAME,
- .driver.owner = THIS_MODULE,
.feature_table = virtbt_features,
.feature_table_size = ARRAY_SIZE(virtbt_features),
.id_table = virtbt_table,