aboutsummaryrefslogtreecommitdiff
path: root/arch/s390/pci/pci.c
diff options
context:
space:
mode:
authorJan Glauber <jang@linux.vnet.ibm.com>2012-11-29 14:33:30 +0100
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2012-11-30 17:47:23 +0100
commit828b35f60eb0148f994bb13e328df94578b07142 (patch)
tree2e06065339ebbfb9aab46f3167fe77ac952ac6fa /arch/s390/pci/pci.c
parent9a4da8a5b109906a64bed5aaeb83bf4edb1f5888 (diff)
s390/pci: DMA support
Add DMA IOMMU support using 4K page table entries. Implement dma_map_ops. Signed-off-by: Jan Glauber <jang@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/pci/pci.c')
-rw-r--r--arch/s390/pci/pci.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index d11dc8a25f3..5a2ef9e75c9 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -34,6 +34,7 @@
#include <asm/facility.h>
#include <asm/pci_insn.h>
#include <asm/pci_clp.h>
+#include <asm/pci_dma.h>
#define DEBUG /* enable pr_debug */
@@ -232,6 +233,25 @@ static int mod_pci(struct zpci_dev *zdev, int fn, u8 dmaas, struct mod_pci_args
return rc;
}
+/* Modify PCI: Register I/O address translation parameters */
+int zpci_register_ioat(struct zpci_dev *zdev, u8 dmaas,
+ u64 base, u64 limit, u64 iota)
+{
+ struct mod_pci_args args = { base, limit, iota };
+
+ WARN_ON_ONCE(iota & 0x3fff);
+ args.iota |= ZPCI_IOTA_RTTO_FLAG;
+ return mod_pci(zdev, ZPCI_MOD_FC_REG_IOAT, dmaas, &args);
+}
+
+/* Modify PCI: Unregister I/O address translation parameters */
+int zpci_unregister_ioat(struct zpci_dev *zdev, u8 dmaas)
+{
+ struct mod_pci_args args = { 0, 0, 0 };
+
+ return mod_pci(zdev, ZPCI_MOD_FC_DEREG_IOAT, dmaas, &args);
+}
+
/* Modify PCI: Unregister adapter interruptions */
static int zpci_unregister_airq(struct zpci_dev *zdev)
{
@@ -602,6 +622,7 @@ static void zpci_remove_device(struct pci_dev *pdev)
dev_info(&pdev->dev, "Removing device %u\n", zdev->domain);
zdev->state = ZPCI_FN_STATE_CONFIGURED;
+ zpci_dma_exit_device(zdev);
zpci_unmap_resources(pdev);
list_del(&zdev->entry); /* can be called from init */
zdev->pdev = NULL;
@@ -887,7 +908,14 @@ int zpci_enable_device(struct zpci_dev *zdev)
if (rc)
goto out;
pr_info("Enabled fh: 0x%x fid: 0x%x\n", zdev->fh, zdev->fid);
+
+ rc = zpci_dma_init_device(zdev);
+ if (rc)
+ goto out_dma;
return 0;
+
+out_dma:
+ clp_disable_fh(zdev);
out:
return rc;
}
@@ -929,6 +957,7 @@ out:
void zpci_stop_device(struct zpci_dev *zdev)
{
+ zpci_dma_exit_device(zdev);
/*
* Note: SCLP disables fh via set-pci-fn so don't
* do that here.
@@ -953,6 +982,7 @@ int zpci_scan_device(struct zpci_dev *zdev)
return 0;
out:
+ zpci_dma_exit_device(zdev);
clp_disable_fh(zdev);
return -EIO;
}
@@ -1028,6 +1058,10 @@ static int __init pci_base_init(void)
if (rc)
goto out_irq;
+ rc = zpci_dma_init();
+ if (rc)
+ goto out_dma;
+
rc = clp_find_pci_devices();
if (rc)
goto out_find;
@@ -1036,6 +1070,8 @@ static int __init pci_base_init(void)
return 0;
out_find:
+ zpci_dma_exit();
+out_dma:
zpci_irq_exit();
out_irq:
zpci_msihash_exit();