These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / iommu / dmar.c
index 9847613..3821c47 100644 (file)
@@ -26,7 +26,7 @@
  * These routines are used by both DMA-remapping and Interrupt-remapping
  */
 
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt /* has to precede printk.h */
+#define pr_fmt(fmt)     "DMAR: " fmt
 
 #include <linux/pci.h>
 #include <linux/dmar.h>
@@ -329,7 +329,8 @@ static int dmar_pci_bus_notifier(struct notifier_block *nb,
        /* Only care about add/remove events for physical functions */
        if (pdev->is_virtfn)
                return NOTIFY_DONE;
-       if (action != BUS_NOTIFY_ADD_DEVICE && action != BUS_NOTIFY_DEL_DEVICE)
+       if (action != BUS_NOTIFY_ADD_DEVICE &&
+           action != BUS_NOTIFY_REMOVED_DEVICE)
                return NOTIFY_DONE;
 
        info = dmar_alloc_pci_notify_info(pdev, action);
@@ -339,7 +340,7 @@ static int dmar_pci_bus_notifier(struct notifier_block *nb,
        down_write(&dmar_global_lock);
        if (action == BUS_NOTIFY_ADD_DEVICE)
                dmar_pci_bus_add_dev(info);
-       else if (action == BUS_NOTIFY_DEL_DEVICE)
+       else if (action == BUS_NOTIFY_REMOVED_DEVICE)
                dmar_pci_bus_del_dev(info);
        up_write(&dmar_global_lock);
 
@@ -555,7 +556,7 @@ static int dmar_walk_remapping_entries(struct acpi_dmar_header *start,
                        break;
                } else if (next > end) {
                        /* Avoid passing table end */
-                       pr_warn(FW_BUG "record passes table end\n");
+                       pr_warn(FW_BUG "Record passes table end\n");
                        ret = -EINVAL;
                        break;
                }
@@ -802,7 +803,7 @@ int __init dmar_table_init(void)
                ret = parse_dmar_table();
                if (ret < 0) {
                        if (ret != -ENODEV)
-                               pr_info("parse DMAR table failure.\n");
+                               pr_info("Parse DMAR table failure.\n");
                } else  if (list_empty(&dmar_drhd_units)) {
                        pr_info("No DMAR devices found\n");
                        ret = -ENODEV;
@@ -847,7 +848,7 @@ dmar_validate_one_drhd(struct acpi_dmar_header *entry, void *arg)
        else
                addr = early_ioremap(drhd->address, VTD_PAGE_SIZE);
        if (!addr) {
-               pr_warn("IOMMU: can't validate: %llx\n", drhd->address);
+               pr_warn("Can't validate DRHD address: %llx\n", drhd->address);
                return -EINVAL;
        }
 
@@ -921,14 +922,14 @@ static int map_iommu(struct intel_iommu *iommu, u64 phys_addr)
        iommu->reg_size = VTD_PAGE_SIZE;
 
        if (!request_mem_region(iommu->reg_phys, iommu->reg_size, iommu->name)) {
-               pr_err("IOMMU: can't reserve memory\n");
+               pr_err("Can't reserve memory\n");
                err = -EBUSY;
                goto out;
        }
 
        iommu->reg = ioremap(iommu->reg_phys, iommu->reg_size);
        if (!iommu->reg) {
-               pr_err("IOMMU: can't map the region\n");
+               pr_err("Can't map the region\n");
                err = -ENOMEM;
                goto release;
        }
@@ -952,13 +953,13 @@ static int map_iommu(struct intel_iommu *iommu, u64 phys_addr)
                iommu->reg_size = map_size;
                if (!request_mem_region(iommu->reg_phys, iommu->reg_size,
                                        iommu->name)) {
-                       pr_err("IOMMU: can't reserve memory\n");
+                       pr_err("Can't reserve memory\n");
                        err = -EBUSY;
                        goto out;
                }
                iommu->reg = ioremap(iommu->reg_phys, iommu->reg_size);
                if (!iommu->reg) {
-                       pr_err("IOMMU: can't map the region\n");
+                       pr_err("Can't map the region\n");
                        err = -ENOMEM;
                        goto release;
                }
@@ -1014,14 +1015,14 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
                return -ENOMEM;
 
        if (dmar_alloc_seq_id(iommu) < 0) {
-               pr_err("IOMMU: failed to allocate seq_id\n");
+               pr_err("Failed to allocate seq_id\n");
                err = -ENOSPC;
                goto error;
        }
 
        err = map_iommu(iommu, drhd->reg_base_addr);
        if (err) {
-               pr_err("IOMMU: failed to map %s\n", iommu->name);
+               pr_err("Failed to map %s\n", iommu->name);
                goto error_free_seq_id;
        }
 
@@ -1045,8 +1046,8 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
        iommu->node = -1;
 
        ver = readl(iommu->reg + DMAR_VER_REG);
-       pr_info("IOMMU %d: reg_base_addr %llx ver %d:%d cap %llx ecap %llx\n",
-               iommu->seq_id,
+       pr_info("%s: reg_base_addr %llx ver %d:%d cap %llx ecap %llx\n",
+               iommu->name,
                (unsigned long long)drhd->reg_base_addr,
                DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver),
                (unsigned long long)iommu->cap,
@@ -1068,7 +1069,7 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
        if (intel_iommu_enabled)
                iommu->iommu_dev = iommu_device_create(NULL, iommu,
                                                       intel_iommu_groups,
-                                                      iommu->name);
+                                                      "%s", iommu->name);
 
        return 0;
 
@@ -1086,9 +1087,14 @@ static void free_iommu(struct intel_iommu *iommu)
        iommu_device_destroy(iommu->iommu_dev);
 
        if (iommu->irq) {
+               if (iommu->pr_irq) {
+                       free_irq(iommu->pr_irq, iommu);
+                       dmar_free_hwirq(iommu->pr_irq);
+                       iommu->pr_irq = 0;
+               }
                free_irq(iommu->irq, iommu);
-               irq_set_handler_data(iommu->irq, NULL);
                dmar_free_hwirq(iommu->irq);
+               iommu->irq = 0;
        }
 
        if (iommu->qi) {
@@ -1342,7 +1348,7 @@ void dmar_disable_qi(struct intel_iommu *iommu)
 
        raw_spin_lock_irqsave(&iommu->register_lock, flags);
 
-       sts =  dmar_readq(iommu->reg + DMAR_GSTS_REG);
+       sts =  readl(iommu->reg + DMAR_GSTS_REG);
        if (!(sts & DMA_GSTS_QIES))
                goto end;
 
@@ -1493,53 +1499,68 @@ static const char *dmar_get_fault_reason(u8 fault_reason, int *fault_type)
        }
 }
 
+
+static inline int dmar_msi_reg(struct intel_iommu *iommu, int irq)
+{
+       if (iommu->irq == irq)
+               return DMAR_FECTL_REG;
+       else if (iommu->pr_irq == irq)
+               return DMAR_PECTL_REG;
+       else
+               BUG();
+}
+
 void dmar_msi_unmask(struct irq_data *data)
 {
        struct intel_iommu *iommu = irq_data_get_irq_handler_data(data);
+       int reg = dmar_msi_reg(iommu, data->irq);
        unsigned long flag;
 
        /* unmask it */
        raw_spin_lock_irqsave(&iommu->register_lock, flag);
-       writel(0, iommu->reg + DMAR_FECTL_REG);
+       writel(0, iommu->reg + reg);
        /* Read a reg to force flush the post write */
-       readl(iommu->reg + DMAR_FECTL_REG);
+       readl(iommu->reg + reg);
        raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
 }
 
 void dmar_msi_mask(struct irq_data *data)
 {
-       unsigned long flag;
        struct intel_iommu *iommu = irq_data_get_irq_handler_data(data);
+       int reg = dmar_msi_reg(iommu, data->irq);
+       unsigned long flag;
 
        /* mask it */
        raw_spin_lock_irqsave(&iommu->register_lock, flag);
-       writel(DMA_FECTL_IM, iommu->reg + DMAR_FECTL_REG);
+       writel(DMA_FECTL_IM, iommu->reg + reg);
        /* Read a reg to force flush the post write */
-       readl(iommu->reg + DMAR_FECTL_REG);
+       readl(iommu->reg + reg);
        raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
 }
 
 void dmar_msi_write(int irq, struct msi_msg *msg)
 {
        struct intel_iommu *iommu = irq_get_handler_data(irq);
+       int reg = dmar_msi_reg(iommu, irq);
        unsigned long flag;
 
        raw_spin_lock_irqsave(&iommu->register_lock, flag);
-       writel(msg->data, iommu->reg + DMAR_FEDATA_REG);
-       writel(msg->address_lo, iommu->reg + DMAR_FEADDR_REG);
-       writel(msg->address_hi, iommu->reg + DMAR_FEUADDR_REG);
+       writel(msg->data, iommu->reg + reg + 4);
+       writel(msg->address_lo, iommu->reg + reg + 8);
+       writel(msg->address_hi, iommu->reg + reg + 12);
        raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
 }
 
 void dmar_msi_read(int irq, struct msi_msg *msg)
 {
        struct intel_iommu *iommu = irq_get_handler_data(irq);
+       int reg = dmar_msi_reg(iommu, irq);
        unsigned long flag;
 
        raw_spin_lock_irqsave(&iommu->register_lock, flag);
-       msg->data = readl(iommu->reg + DMAR_FEDATA_REG);
-       msg->address_lo = readl(iommu->reg + DMAR_FEADDR_REG);
-       msg->address_hi = readl(iommu->reg + DMAR_FEUADDR_REG);
+       msg->data = readl(iommu->reg + reg + 4);
+       msg->address_lo = readl(iommu->reg + reg + 8);
+       msg->address_hi = readl(iommu->reg + reg + 12);
        raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
 }
 
@@ -1642,26 +1663,17 @@ int dmar_set_interrupt(struct intel_iommu *iommu)
        if (iommu->irq)
                return 0;
 
-       irq = dmar_alloc_hwirq();
-       if (irq <= 0) {
-               pr_err("IOMMU: no free vectors\n");
+       irq = dmar_alloc_hwirq(iommu->seq_id, iommu->node, iommu);
+       if (irq > 0) {
+               iommu->irq = irq;
+       } else {
+               pr_err("No free IRQ vectors\n");
                return -EINVAL;
        }
 
-       irq_set_handler_data(irq, iommu);
-       iommu->irq = irq;
-
-       ret = arch_setup_dmar_msi(irq);
-       if (ret) {
-               irq_set_handler_data(irq, NULL);
-               iommu->irq = 0;
-               dmar_free_hwirq(irq);
-               return ret;
-       }
-
        ret = request_irq(irq, dmar_fault, IRQF_NO_THREAD, iommu->name, iommu);
        if (ret)
-               pr_err("IOMMU: can't request irq\n");
+               pr_err("Can't request irq\n");
        return ret;
 }