Commit ff31d2e2 authored by Michael S. Tsirkin's avatar Michael S. Tsirkin Committed by Rusty Russell

virtio_pci: move probe/remove code to common

Most of initialization is device-independent.
Let's move it to common.
Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>
Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent 2bd56afd
...@@ -464,15 +464,80 @@ static const struct pci_device_id virtio_pci_id_table[] = { ...@@ -464,15 +464,80 @@ static const struct pci_device_id virtio_pci_id_table[] = {
MODULE_DEVICE_TABLE(pci, virtio_pci_id_table); MODULE_DEVICE_TABLE(pci, virtio_pci_id_table);
static void virtio_pci_release_dev(struct device *_d)
{
struct virtio_device *vdev = dev_to_virtio(_d);
struct virtio_pci_device *vp_dev = to_vp_device(vdev);
/* As struct device is a kobject, it's not safe to
* free the memory (including the reference counter itself)
* until it's release callback. */
kfree(vp_dev);
}
static int virtio_pci_probe(struct pci_dev *pci_dev, static int virtio_pci_probe(struct pci_dev *pci_dev,
const struct pci_device_id *id) const struct pci_device_id *id)
{ {
return virtio_pci_legacy_probe(pci_dev, id); struct virtio_pci_device *vp_dev;
int rc;
/* allocate our structure and fill it out */
vp_dev = kzalloc(sizeof(struct virtio_pci_device), GFP_KERNEL);
if (!vp_dev)
return -ENOMEM;
pci_set_drvdata(pci_dev, vp_dev);
vp_dev->vdev.dev.parent = &pci_dev->dev;
vp_dev->vdev.dev.release = virtio_pci_release_dev;
vp_dev->pci_dev = pci_dev;
INIT_LIST_HEAD(&vp_dev->virtqueues);
spin_lock_init(&vp_dev->lock);
/* Disable MSI/MSIX to bring device to a known good state. */
pci_msi_off(pci_dev);
/* enable the device */
rc = pci_enable_device(pci_dev);
if (rc)
goto err_enable_device;
rc = pci_request_regions(pci_dev, "virtio-pci");
if (rc)
goto err_request_regions;
rc = virtio_pci_legacy_probe(vp_dev);
if (rc)
goto err_probe;
pci_set_master(pci_dev);
rc = register_virtio_device(&vp_dev->vdev);
if (rc)
goto err_register;
return 0;
err_register:
virtio_pci_legacy_remove(vp_dev);
err_probe:
pci_release_regions(pci_dev);
err_request_regions:
pci_disable_device(pci_dev);
err_enable_device:
kfree(vp_dev);
return rc;
} }
static void virtio_pci_remove(struct pci_dev *pci_dev) static void virtio_pci_remove(struct pci_dev *pci_dev)
{ {
struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
unregister_virtio_device(&vp_dev->vdev);
virtio_pci_legacy_remove(pci_dev); virtio_pci_legacy_remove(pci_dev);
pci_release_regions(pci_dev);
pci_disable_device(pci_dev);
} }
static struct pci_driver virtio_pci_driver = { static struct pci_driver virtio_pci_driver = {
......
...@@ -127,8 +127,7 @@ const char *vp_bus_name(struct virtio_device *vdev); ...@@ -127,8 +127,7 @@ const char *vp_bus_name(struct virtio_device *vdev);
*/ */
int vp_set_vq_affinity(struct virtqueue *vq, int cpu); int vp_set_vq_affinity(struct virtqueue *vq, int cpu);
int virtio_pci_legacy_probe(struct pci_dev *pci_dev, int virtio_pci_legacy_probe(struct virtio_pci_device *);
const struct pci_device_id *id); void virtio_pci_legacy_remove(struct virtio_pci_device *);
void virtio_pci_legacy_remove(struct pci_dev *pci_dev);
#endif #endif
...@@ -211,23 +211,10 @@ static const struct virtio_config_ops virtio_pci_config_ops = { ...@@ -211,23 +211,10 @@ static const struct virtio_config_ops virtio_pci_config_ops = {
.set_vq_affinity = vp_set_vq_affinity, .set_vq_affinity = vp_set_vq_affinity,
}; };
static void virtio_pci_release_dev(struct device *_d)
{
struct virtio_device *vdev = dev_to_virtio(_d);
struct virtio_pci_device *vp_dev = to_vp_device(vdev);
/* As struct device is a kobject, it's not safe to
* free the memory (including the reference counter itself)
* until it's release callback. */
kfree(vp_dev);
}
/* the PCI probing function */ /* the PCI probing function */
int virtio_pci_legacy_probe(struct pci_dev *pci_dev, int virtio_pci_legacy_probe(struct virtio_pci_device *vp_dev)
const struct pci_device_id *id)
{ {
struct virtio_pci_device *vp_dev; struct pci_dev *pci_dev = vp_dev->pci_dev;
int err;
/* We only own devices >= 0x1000 and <= 0x103f: leave the rest. */ /* We only own devices >= 0x1000 and <= 0x103f: leave the rest. */
if (pci_dev->device < 0x1000 || pci_dev->device > 0x103f) if (pci_dev->device < 0x1000 || pci_dev->device > 0x103f)
...@@ -239,41 +226,12 @@ int virtio_pci_legacy_probe(struct pci_dev *pci_dev, ...@@ -239,41 +226,12 @@ int virtio_pci_legacy_probe(struct pci_dev *pci_dev,
return -ENODEV; return -ENODEV;
} }
/* allocate our structure and fill it out */
vp_dev = kzalloc(sizeof(struct virtio_pci_device), GFP_KERNEL);
if (vp_dev == NULL)
return -ENOMEM;
vp_dev->vdev.dev.parent = &pci_dev->dev;
vp_dev->vdev.dev.release = virtio_pci_release_dev;
vp_dev->vdev.config = &virtio_pci_config_ops;
vp_dev->pci_dev = pci_dev;
INIT_LIST_HEAD(&vp_dev->virtqueues);
spin_lock_init(&vp_dev->lock);
/* Disable MSI/MSIX to bring device to a known good state. */
pci_msi_off(pci_dev);
/* enable the device */
err = pci_enable_device(pci_dev);
if (err)
goto out;
err = pci_request_regions(pci_dev, "virtio-pci");
if (err)
goto out_enable_device;
vp_dev->ioaddr = pci_iomap(pci_dev, 0, 0); vp_dev->ioaddr = pci_iomap(pci_dev, 0, 0);
if (vp_dev->ioaddr == NULL) { if (!vp_dev->ioaddr)
err = -ENOMEM; return -ENOMEM;
goto out_req_regions;
}
vp_dev->isr = vp_dev->ioaddr + VIRTIO_PCI_ISR; vp_dev->isr = vp_dev->ioaddr + VIRTIO_PCI_ISR;
pci_set_drvdata(pci_dev, vp_dev);
pci_set_master(pci_dev);
/* we use the subsystem vendor/device id as the virtio vendor/device /* we use the subsystem vendor/device id as the virtio vendor/device
* id. this allows us to use the same PCI vendor/device id for all * id. this allows us to use the same PCI vendor/device id for all
* virtio devices and to identify the particular virtio driver by * virtio devices and to identify the particular virtio driver by
...@@ -281,35 +239,18 @@ int virtio_pci_legacy_probe(struct pci_dev *pci_dev, ...@@ -281,35 +239,18 @@ int virtio_pci_legacy_probe(struct pci_dev *pci_dev,
vp_dev->vdev.id.vendor = pci_dev->subsystem_vendor; vp_dev->vdev.id.vendor = pci_dev->subsystem_vendor;
vp_dev->vdev.id.device = pci_dev->subsystem_device; vp_dev->vdev.id.device = pci_dev->subsystem_device;
vp_dev->vdev.config = &virtio_pci_config_ops;
vp_dev->config_vector = vp_config_vector; vp_dev->config_vector = vp_config_vector;
vp_dev->setup_vq = setup_vq; vp_dev->setup_vq = setup_vq;
vp_dev->del_vq = del_vq; vp_dev->del_vq = del_vq;
/* finally register the virtio device */
err = register_virtio_device(&vp_dev->vdev);
if (err)
goto out_set_drvdata;
return 0; return 0;
out_set_drvdata:
pci_iounmap(pci_dev, vp_dev->ioaddr);
out_req_regions:
pci_release_regions(pci_dev);
out_enable_device:
pci_disable_device(pci_dev);
out:
kfree(vp_dev);
return err;
} }
void virtio_pci_legacy_remove(struct pci_dev *pci_dev) void virtio_pci_legacy_remove(struct virtio_pci_device *vp_dev)
{ {
struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev); struct pci_dev *pci_dev = vp_dev->pci_dev;
unregister_virtio_device(&vp_dev->vdev);
pci_iounmap(pci_dev, vp_dev->ioaddr); pci_iounmap(pci_dev, vp_dev->ioaddr);
pci_release_regions(pci_dev);
pci_disable_device(pci_dev);
} }
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