|
@@ -113,6 +113,30 @@ static ssize_t do_io_rw(void __iomem *io, char __user *buf,
|
|
|
return done;
|
|
|
}
|
|
|
|
|
|
+static int vfio_pci_setup_barmap(struct vfio_pci_device *vdev, int bar)
|
|
|
+{
|
|
|
+ struct pci_dev *pdev = vdev->pdev;
|
|
|
+ int ret;
|
|
|
+ void __iomem *io;
|
|
|
+
|
|
|
+ if (vdev->barmap[bar])
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ ret = pci_request_selected_regions(pdev, 1 << bar, "vfio");
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ io = pci_iomap(pdev, bar, 0);
|
|
|
+ if (!io) {
|
|
|
+ pci_release_selected_regions(pdev, 1 << bar);
|
|
|
+ return -ENOMEM;
|
|
|
+ }
|
|
|
+
|
|
|
+ vdev->barmap[bar] = io;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
ssize_t vfio_pci_bar_rw(struct vfio_pci_device *vdev, char __user *buf,
|
|
|
size_t count, loff_t *ppos, bool iswrite)
|
|
|
{
|
|
@@ -147,22 +171,13 @@ ssize_t vfio_pci_bar_rw(struct vfio_pci_device *vdev, char __user *buf,
|
|
|
if (!io)
|
|
|
return -ENOMEM;
|
|
|
x_end = end;
|
|
|
- } else if (!vdev->barmap[bar]) {
|
|
|
- int ret;
|
|
|
-
|
|
|
- ret = pci_request_selected_regions(pdev, 1 << bar, "vfio");
|
|
|
+ } else {
|
|
|
+ int ret = vfio_pci_setup_barmap(vdev, bar);
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
|
|
|
- io = pci_iomap(pdev, bar, 0);
|
|
|
- if (!io) {
|
|
|
- pci_release_selected_regions(pdev, 1 << bar);
|
|
|
- return -ENOMEM;
|
|
|
- }
|
|
|
-
|
|
|
- vdev->barmap[bar] = io;
|
|
|
- } else
|
|
|
io = vdev->barmap[bar];
|
|
|
+ }
|
|
|
|
|
|
if (bar == vdev->msix_bar) {
|
|
|
x_start = vdev->msix_offset;
|