Code Review
/
kvmfornfv.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
review
|
tree
raw
|
inline
| side by side
These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git]
/
kernel
/
drivers
/
iommu
/
dmar.c
diff --git
a/kernel/drivers/iommu/dmar.c
b/kernel/drivers/iommu/dmar.c
index
9847613
..
3821c47
100644
(file)
--- a/
kernel/drivers/iommu/dmar.c
+++ b/
kernel/drivers/iommu/dmar.c
@@
-26,7
+26,7
@@
* These routines are used by both DMA-remapping and Interrupt-remapping
*/
* 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>
#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;
/* 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);
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);
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);
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 */
break;
} else if (next > end) {
/* Avoid passing table end */
- pr_warn(FW_BUG "
r
ecord passes table end\n");
+ pr_warn(FW_BUG "
R
ecord passes table end\n");
ret = -EINVAL;
break;
}
ret = -EINVAL;
break;
}
@@
-802,7
+803,7
@@
int __init dmar_table_init(void)
ret = parse_dmar_table();
if (ret < 0) {
if (ret != -ENODEV)
ret = parse_dmar_table();
if (ret < 0) {
if (ret != -ENODEV)
- pr_info("
p
arse DMAR table failure.\n");
+ pr_info("
P
arse DMAR table failure.\n");
} else if (list_empty(&dmar_drhd_units)) {
pr_info("No DMAR devices found\n");
ret = -ENODEV;
} 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) {
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;
}
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)) {
iommu->reg_size = VTD_PAGE_SIZE;
if (!request_mem_region(iommu->reg_phys, iommu->reg_size, iommu->name)) {
- pr_err("
IOMMU: c
an't reserve memory\n");
+ pr_err("
C
an't reserve memory\n");
err = -EBUSY;
goto out;
}
iommu->reg = ioremap(iommu->reg_phys, iommu->reg_size);
if (!iommu->reg) {
err = -EBUSY;
goto out;
}
iommu->reg = ioremap(iommu->reg_phys, iommu->reg_size);
if (!iommu->reg) {
- pr_err("
IOMMU: c
an't map the region\n");
+ pr_err("
C
an't map the region\n");
err = -ENOMEM;
goto release;
}
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)) {
iommu->reg_size = map_size;
if (!request_mem_region(iommu->reg_phys, iommu->reg_size,
iommu->name)) {
- pr_err("
IOMMU: c
an't reserve memory\n");
+ pr_err("
C
an't reserve memory\n");
err = -EBUSY;
goto out;
}
iommu->reg = ioremap(iommu->reg_phys, iommu->reg_size);
if (!iommu->reg) {
err = -EBUSY;
goto out;
}
iommu->reg = ioremap(iommu->reg_phys, iommu->reg_size);
if (!iommu->reg) {
- pr_err("
IOMMU: c
an't map the region\n");
+ pr_err("
C
an't map the region\n");
err = -ENOMEM;
goto release;
}
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) {
return -ENOMEM;
if (dmar_alloc_seq_id(iommu) < 0) {
- pr_err("
IOMMU: f
ailed to allocate seq_id\n");
+ pr_err("
F
ailed to allocate seq_id\n");
err = -ENOSPC;
goto error;
}
err = map_iommu(iommu, drhd->reg_base_addr);
if (err) {
err = -ENOSPC;
goto error;
}
err = map_iommu(iommu, drhd->reg_base_addr);
if (err) {
- pr_err("
IOMMU: f
ailed to map %s\n", iommu->name);
+ pr_err("
F
ailed to map %s\n", iommu->name);
goto error_free_seq_id;
}
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);
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,
(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,
if (intel_iommu_enabled)
iommu->iommu_dev = iommu_device_create(NULL, iommu,
intel_iommu_groups,
- iommu->name);
+
"%s",
iommu->name);
return 0;
return 0;
@@
-1086,9
+1087,14
@@
static void free_iommu(struct intel_iommu *iommu)
iommu_device_destroy(iommu->iommu_dev);
if (iommu->irq) {
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);
free_irq(iommu->irq, iommu);
- irq_set_handler_data(iommu->irq, NULL);
dmar_free_hwirq(iommu->irq);
dmar_free_hwirq(iommu->irq);
+ iommu->irq = 0;
}
if (iommu->qi) {
}
if (iommu->qi) {
@@
-1342,7
+1348,7
@@
void dmar_disable_qi(struct intel_iommu *iommu)
raw_spin_lock_irqsave(&iommu->register_lock, flags);
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;
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);
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);
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 */
/* 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)
{
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);
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);
/* 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 */
/* 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);
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);
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);
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);
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);
}
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;
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;
}
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)
ret = request_irq(irq, dmar_fault, IRQF_NO_THREAD, iommu->name, iommu);
if (ret)
- pr_err("
IOMMU: c
an't request irq\n");
+ pr_err("
C
an't request irq\n");
return ret;
}
return ret;
}