if (rc)
goto err_enable_device;
- rc = pci_request_regions(pci_dev, "virtio-pci");
- if (rc)
- goto err_request_regions;
-
if (force_legacy) {
rc = virtio_pci_legacy_probe(vp_dev);
/* Also try modern mode if we can't map BAR0 (no IO space). */
else
virtio_pci_modern_remove(vp_dev);
err_probe:
- pci_release_regions(pci_dev);
-err_request_regions:
pci_disable_device(pci_dev);
err_enable_device:
kfree(vp_dev);
else
virtio_pci_modern_remove(vp_dev);
- pci_release_regions(pci_dev);
pci_disable_device(pci_dev);
}
int virtio_pci_legacy_probe(struct virtio_pci_device *vp_dev)
{
struct pci_dev *pci_dev = vp_dev->pci_dev;
+ int rc;
/* We only own devices >= 0x1000 and <= 0x103f: leave the rest. */
if (pci_dev->device < 0x1000 || pci_dev->device > 0x103f)
return -ENODEV;
}
+ rc = pci_request_region(pci_dev, 0, "virtio-pci-legacy");
+ if (rc)
+ return rc;
+
+ rc = -ENOMEM;
vp_dev->ioaddr = pci_iomap(pci_dev, 0, 0);
if (!vp_dev->ioaddr)
- return -ENOMEM;
+ goto err_iomap;
vp_dev->isr = vp_dev->ioaddr + VIRTIO_PCI_ISR;
vp_dev->del_vq = del_vq;
return 0;
+
+err_iomap:
+ pci_release_region(pci_dev, 0);
+ return rc;
}
void virtio_pci_legacy_remove(struct virtio_pci_device *vp_dev)
struct pci_dev *pci_dev = vp_dev->pci_dev;
pci_iounmap(pci_dev, vp_dev->ioaddr);
+ pci_release_region(pci_dev, 0);
}
* Returns offset of the capability, or 0.
*/
static inline int virtio_pci_find_capability(struct pci_dev *dev, u8 cfg_type,
- u32 ioresource_types)
+ u32 ioresource_types, int *bars)
{
int pos;
if (type == cfg_type) {
if (pci_resource_len(dev, bar) &&
- pci_resource_flags(dev, bar) & ioresource_types)
+ pci_resource_flags(dev, bar) & ioresource_types) {
+ *bars |= (1 << bar);
return pos;
+ }
}
}
return 0;
/* check for a common config: if not, use legacy mode (bar 0). */
common = virtio_pci_find_capability(pci_dev, VIRTIO_PCI_CAP_COMMON_CFG,
- IORESOURCE_IO | IORESOURCE_MEM);
+ IORESOURCE_IO | IORESOURCE_MEM,
+ &vp_dev->modern_bars);
if (!common) {
dev_info(&pci_dev->dev,
"virtio_pci: leaving for legacy driver\n");
/* If common is there, these should be too... */
isr = virtio_pci_find_capability(pci_dev, VIRTIO_PCI_CAP_ISR_CFG,
- IORESOURCE_IO | IORESOURCE_MEM);
+ IORESOURCE_IO | IORESOURCE_MEM,
+ &vp_dev->modern_bars);
notify = virtio_pci_find_capability(pci_dev, VIRTIO_PCI_CAP_NOTIFY_CFG,
- IORESOURCE_IO | IORESOURCE_MEM);
+ IORESOURCE_IO | IORESOURCE_MEM,
+ &vp_dev->modern_bars);
if (!isr || !notify) {
dev_err(&pci_dev->dev,
"virtio_pci: missing capabilities %i/%i/%i\n",
* device-specific configuration.
*/
device = virtio_pci_find_capability(pci_dev, VIRTIO_PCI_CAP_DEVICE_CFG,
- IORESOURCE_IO | IORESOURCE_MEM);
+ IORESOURCE_IO | IORESOURCE_MEM,
+ &vp_dev->modern_bars);
+
+ err = pci_request_selected_regions(pci_dev, vp_dev->modern_bars,
+ "virtio-pci-modern");
+ if (err)
+ return err;
err = -EINVAL;
vp_dev->common = map_capability(pci_dev, common,
pci_iounmap(pci_dev, vp_dev->notify_base);
pci_iounmap(pci_dev, vp_dev->isr);
pci_iounmap(pci_dev, vp_dev->common);
+ pci_release_selected_regions(pci_dev, vp_dev->modern_bars);
}