]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blobdiff - arch/s390/pci/pci.c
s390/pci: Implement ioremap_wc/prot() with MIO
[mirror_ubuntu-hirsute-kernel.git] / arch / s390 / pci / pci.c
index 3902c9f6f2d63dd011f9e1c3244f062ed1d182cc..fdbb99c4569dc83ed68889e4d1a587ebdb9a52bb 100644 (file)
@@ -226,7 +226,7 @@ void __iowrite64_copy(void __iomem *to, const void *from, size_t count)
        zpci_memcpy_toio(to, from, count);
 }
 
-void __iomem *ioremap(phys_addr_t addr, size_t size)
+static void __iomem *__ioremap(phys_addr_t addr, size_t size, pgprot_t prot)
 {
        unsigned long offset, vaddr;
        struct vm_struct *area;
@@ -247,14 +247,37 @@ void __iomem *ioremap(phys_addr_t addr, size_t size)
                return NULL;
 
        vaddr = (unsigned long) area->addr;
-       if (ioremap_page_range(vaddr, vaddr + size, addr, PAGE_KERNEL)) {
+       if (ioremap_page_range(vaddr, vaddr + size, addr, prot)) {
                free_vm_area(area);
                return NULL;
        }
        return (void __iomem *) ((unsigned long) area->addr + offset);
 }
+
+void __iomem *ioremap_prot(phys_addr_t addr, size_t size, unsigned long prot)
+{
+       return __ioremap(addr, size, __pgprot(prot));
+}
+EXPORT_SYMBOL(ioremap_prot);
+
+void __iomem *ioremap(phys_addr_t addr, size_t size)
+{
+       return __ioremap(addr, size, PAGE_KERNEL);
+}
 EXPORT_SYMBOL(ioremap);
 
+void __iomem *ioremap_wc(phys_addr_t addr, size_t size)
+{
+       return __ioremap(addr, size, pgprot_writecombine(PAGE_KERNEL));
+}
+EXPORT_SYMBOL(ioremap_wc);
+
+void __iomem *ioremap_wt(phys_addr_t addr, size_t size)
+{
+       return __ioremap(addr, size, pgprot_writethrough(PAGE_KERNEL));
+}
+EXPORT_SYMBOL(ioremap_wt);
+
 void iounmap(volatile void __iomem *addr)
 {
        if (static_branch_likely(&have_mio))
@@ -672,6 +695,19 @@ int zpci_disable_device(struct zpci_dev *zdev)
 }
 EXPORT_SYMBOL_GPL(zpci_disable_device);
 
+void zpci_remove_device(struct zpci_dev *zdev)
+{
+       struct zpci_bus *zbus = zdev->zbus;
+       struct pci_dev *pdev;
+
+       pdev = pci_get_slot(zbus->bus, zdev->devfn);
+       if (pdev) {
+               if (pdev->is_virtfn)
+                       return zpci_remove_virtfn(pdev, zdev->vfn);
+               pci_stop_and_remove_bus_device_locked(pdev);
+       }
+}
+
 int zpci_create_device(struct zpci_dev *zdev)
 {
        int rc;
@@ -716,13 +752,8 @@ void zpci_release_device(struct kref *kref)
 {
        struct zpci_dev *zdev = container_of(kref, struct zpci_dev, kref);
 
-       if (zdev->zbus->bus) {
-               struct pci_dev *pdev;
-
-               pdev = pci_get_slot(zdev->zbus->bus, zdev->devfn);
-               if (pdev)
-                       pci_stop_and_remove_bus_device_locked(pdev);
-       }
+       if (zdev->zbus->bus)
+               zpci_remove_device(zdev);
 
        switch (zdev->state) {
        case ZPCI_FN_STATE_ONLINE:
@@ -776,6 +807,9 @@ static int zpci_mem_init(void)
        if (!zpci_iomap_bitmap)
                goto error_iomap_bitmap;
 
+       if (static_branch_likely(&have_mio))
+               clp_setup_writeback_mio();
+
        return 0;
 error_iomap_bitmap:
        kfree(zpci_iomap_start);