virtio_pci: move probe/remove code to common
Most of initialization is device-independent. Let's move it to common. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Родитель
2bd56afd44
Коммит
ff31d2e285
|
@ -464,15 +464,80 @@ static const struct pci_device_id 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,
|
||||
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)
|
||||
{
|
||||
virtio_pci_legacy_remove(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);
|
||||
|
||||
pci_release_regions(pci_dev);
|
||||
pci_disable_device(pci_dev);
|
||||
}
|
||||
|
||||
static struct pci_driver virtio_pci_driver = {
|
||||
|
|
|
@ -127,8 +127,7 @@ const char *vp_bus_name(struct virtio_device *vdev);
|
|||
*/
|
||||
int vp_set_vq_affinity(struct virtqueue *vq, int cpu);
|
||||
|
||||
int virtio_pci_legacy_probe(struct pci_dev *pci_dev,
|
||||
const struct pci_device_id *id);
|
||||
void virtio_pci_legacy_remove(struct pci_dev *pci_dev);
|
||||
int virtio_pci_legacy_probe(struct virtio_pci_device *);
|
||||
void virtio_pci_legacy_remove(struct virtio_pci_device *);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -211,23 +211,10 @@ static const struct virtio_config_ops virtio_pci_config_ops = {
|
|||
.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 */
|
||||
int virtio_pci_legacy_probe(struct pci_dev *pci_dev,
|
||||
const struct pci_device_id *id)
|
||||
int virtio_pci_legacy_probe(struct virtio_pci_device *vp_dev)
|
||||
{
|
||||
struct virtio_pci_device *vp_dev;
|
||||
int err;
|
||||
struct pci_dev *pci_dev = vp_dev->pci_dev;
|
||||
|
||||
/* We only own devices >= 0x1000 and <= 0x103f: leave the rest. */
|
||||
if (pci_dev->device < 0x1000 || pci_dev->device > 0x103f)
|
||||
|
@ -239,41 +226,12 @@ int virtio_pci_legacy_probe(struct pci_dev *pci_dev,
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* allocate our structure and fill it out */
|
||||
vp_dev = kzalloc(sizeof(struct virtio_pci_device), GFP_KERNEL);
|
||||
if (vp_dev == NULL)
|
||||
vp_dev->ioaddr = pci_iomap(pci_dev, 0, 0);
|
||||
if (!vp_dev->ioaddr)
|
||||
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);
|
||||
if (vp_dev->ioaddr == NULL) {
|
||||
err = -ENOMEM;
|
||||
goto out_req_regions;
|
||||
}
|
||||
|
||||
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
|
||||
* id. this allows us to use the same PCI vendor/device id for all
|
||||
* virtio devices and to identify the particular virtio driver by
|
||||
|
@ -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.device = pci_dev->subsystem_device;
|
||||
|
||||
vp_dev->vdev.config = &virtio_pci_config_ops;
|
||||
|
||||
vp_dev->config_vector = vp_config_vector;
|
||||
vp_dev->setup_vq = setup_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;
|
||||
|
||||
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);
|
||||
|
||||
unregister_virtio_device(&vp_dev->vdev);
|
||||
struct pci_dev *pci_dev = vp_dev->pci_dev;
|
||||
|
||||
pci_iounmap(pci_dev, vp_dev->ioaddr);
|
||||
pci_release_regions(pci_dev);
|
||||
pci_disable_device(pci_dev);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче