[PATCH 1/2] IOMMU/trivial: Use for_each_drhd_unit() instead of list_for_each_entry()
Use for_each_drhd_unit() instead of list_for_each_entry for better readability. Signed-off-by: Yijing Wang wangyij...@huawei.com --- drivers/iommu/dmar.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index 785675a..da2d0d9 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -403,7 +403,7 @@ dmar_find_matched_drhd_unit(struct pci_dev *dev) dev = pci_physfn(dev); - list_for_each_entry(dmaru, dmar_drhd_units, list) { + for_each_drhd_unit(dmaru) { drhd = container_of(dmaru-hdr, struct acpi_dmar_hardware_unit, header); -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 1/1] IOMMU: Save pci device id instead of pci_dev* pointer for DMAR devices
Currently, DMAR driver save target pci devices pointers for drhd/rmrr/atsr in (pci_dev *) array. This is not safe, because pci devices maybe hot added or removed during system running. They will have new pci_dev * pointer. So if there have two IOMMUs or more in system, these devices will find a wrong drhd during DMA mapping. And DMAR faults will occur. This patch save pci device id insted of (pci_dev *) to fix this issue, Because DMAR table just provide pci device id under a specific IOMMU, so there is no reason to bind IOMMU with the (pci_dev *). Other, here use list to manage devices' id for IOMMU, we can easily use list helper to manage device id. after remove and rescan a pci device [ 611.857095] dmar: DRHD: handling fault status reg 2 [ 611.857109] dmar: DMAR:[DMA Read] Request device [86:00.3] fault addr 7000 [ 611.857109] DMAR:[fault reason 02] Present bit in context entry is clear [ 611.857524] dmar: DRHD: handling fault status reg 102 [ 611.857534] dmar: DMAR:[DMA Read] Request device [86:00.3] fault addr 6000 [ 611.857534] DMAR:[fault reason 02] Present bit in context entry is clear [ 611.857936] dmar: DRHD: handling fault status reg 202 [ 611.857947] dmar: DMAR:[DMA Read] Request device [86:00.3] fault addr 5000 [ 611.857947] DMAR:[fault reason 02] Present bit in context entry is clear [ 611.858351] dmar: DRHD: handling fault status reg 302 [ 611.858362] dmar: DMAR:[DMA Read] Request device [86:00.3] fault addr 4000 [ 611.858362] DMAR:[fault reason 02] Present bit in context entry is clear [ 611.860819] IPv6: ADDRCONF(NETDEV_UP): eth3: link is not ready [ 611.860983] dmar: DRHD: handling fault status reg 402 [ 611.860995] dmar: INTR-REMAP: Request device [[86:00.3] fault index a4 [ 611.860995] INTR-REMAP:[fault reason 34] Present field in the IRTE entry is clear Signed-off-by: Yijing Wang wangyij...@huawei.com --- drivers/iommu/dmar.c| 93 +- drivers/iommu/intel-iommu.c | 155 --- include/linux/dmar.h| 20 -- 3 files changed, 159 insertions(+), 109 deletions(-) diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index 785675a..9aa65a3 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -65,12 +65,13 @@ static void __init dmar_register_drhd_unit(struct dmar_drhd_unit *drhd) } static int __init dmar_parse_one_dev_scope(struct acpi_dmar_device_scope *scope, - struct pci_dev **dev, u16 segment) + u16 segment, struct list_head *head) { struct pci_bus *bus; struct pci_dev *pdev = NULL; struct acpi_dmar_pci_path *path; int count; + struct dmar_device *dmar_dev; bus = pci_find_bus(segment, scope-bus); path = (struct acpi_dmar_pci_path *)(scope + 1); @@ -100,7 +101,6 @@ static int __init dmar_parse_one_dev_scope(struct acpi_dmar_device_scope *scope, if (!pdev) { pr_warn(Device scope device [%04x:%02x:%02x.%02x] not found\n, segment, scope-bus, path-dev, path-fn); - *dev = NULL; return 0; } if ((scope-entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT \ @@ -111,54 +111,39 @@ static int __init dmar_parse_one_dev_scope(struct acpi_dmar_device_scope *scope, pci_name(pdev)); return -EINVAL; } - *dev = pdev; + + dmar_dev = kzalloc(sizeof(struct dmar_device), GFP_KERNEL); + if (!dmar_dev) { + pci_dev_put(pdev); + return -ENOMEM; + } + + dmar_dev-segment = segment; + dmar_dev-bus = pdev-bus-number; + dmar_dev-devfn = pdev-devfn; + list_add_tail(dmar_dev-list, head); + + pci_dev_put(pdev); return 0; } -int __init dmar_parse_dev_scope(void *start, void *end, int *cnt, - struct pci_dev ***devices, u16 segment) +int __init dmar_parse_dev_scope(void *start, void *end, u16 segment, + struct list_head *head) { struct acpi_dmar_device_scope *scope; - void * tmp = start; - int index; int ret; - *cnt = 0; - while (start end) { - scope = start; - if (scope-entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT || - scope-entry_type == ACPI_DMAR_SCOPE_TYPE_BRIDGE) - (*cnt)++; - else if (scope-entry_type != ACPI_DMAR_SCOPE_TYPE_IOAPIC - scope-entry_type != ACPI_DMAR_SCOPE_TYPE_HPET) { - pr_warn(Unsupported device scope\n); - } - start += scope-length; - } - if (*cnt == 0) - return 0; - - *devices = kcalloc(*cnt, sizeof(struct pci_dev *), GFP_KERNEL); - if (!*devices) - return -ENOMEM; - - start = tmp; - index = 0
Re: [PATCH 1/1] IOMMU: Save pci device id instead of pci_dev* pointer for DMAR devices
HI Bjorn, Thanks for your review and comments very much! +list_for_each_entry(dmar_dev, head, list) +if (dmar_dev-segment == pci_domain_nr(dev-bus) + dmar_dev-bus == dev-bus-number + dmar_dev-devfn == dev-devfn) +return 1; + /* Check our parent */ dev = dev-bus-self; You didn't change this, but it looks like this may have the same problem we've been talking about here: http://lkml.kernel.org/r/20131105232903.3790.8738.st...@bhelgaas-glaptop.roam.corp.google.com Namely, if dev is a VF on a virtual bus, dev-bus-self == NULL, so we won't search for any of the bridges leading to the VF. I proposed a pci_upstream_bridge() interface that could be used like this: /* Check our parent */ dev = pci_upstream_bridge(dev); It looks good to me, because pci_upstream_bridge() is still in your next branch, I think maybe I can split this changes in a separate patch after 3.13-rc1. static struct intel_iommu *device_to_iommu(int segment, u8 bus, u8 devfn) { struct dmar_drhd_unit *drhd = NULL; -int i; +struct dmar_device *dmar_dev; +struct pci_dev *pdev; for_each_drhd_unit(drhd) { if (drhd-ignored) @@ -658,16 +659,22 @@ static struct intel_iommu *device_to_iommu(int segment, u8 bus, u8 devfn) if (segment != drhd-segment) continue; -for (i = 0; i drhd-devices_cnt; i++) { -if (drhd-devices[i] -drhd-devices[i]-bus-number == bus -drhd-devices[i]-devfn == devfn) -return drhd-iommu; -if (drhd-devices[i] -drhd-devices[i]-subordinate -drhd-devices[i]-subordinate-number = bus -drhd-devices[i]-subordinate-busn_res.end = bus) -return drhd-iommu; +list_for_each_entry(dmar_dev, drhd-head, list) { +if (dmar_dev-bus == bus +dmar_dev-devfn == devfn) +return drhd-iommu; + +pdev = pci_get_domain_bus_and_slot(dmar_dev-segment, +dmar_dev-bus, dmar_dev-devfn); +if (pdev-subordinate +pdev-subordinate-number = bus +pdev-subordinate-busn_res.end = bus) { +pci_dev_put(pdev); +return drhd-iommu; I don't know the details of how device_to_iommu() is used, but this style (acquire ref to pci_dev, match it to some other object, drop pci_dev ref, return object) makes me nervous. How do we know the caller isn't depending on pci_dev to remain attached to the object? What happens if the pci_dev disappears when we do the pci_dev_put() here? Hmmm, this is the thing I am most worried about. If we just only use (pci_dev *) poninter in drhd-devices array as a identification. Change (pci_dev *) pointer instead of pci device id segment:bus:devfn is safe. Or, this is a wrong way to fix this issue. I don't know IOMMU driver much now, so IOMMU guys any comments on this issue is welcome. If this is not safe, what about we both save pci device id and (pci_dev *) pointer in drhd. So we can put pci_dev ref and set pci_dev * = NULL during device removed by bus notify, and update (pci_dev *)pointer during device add. like this: struct dmar_device { struct list_head list; u16 segment; u8 bus; u8 devfn; struct pci_dev *dev; }; for_each_drhd_unit(drhd) { -int i; if (drhd-ignored || drhd-include_all) continue; -for (i = 0; i drhd-devices_cnt; i++) -if (drhd-devices[i] -!IS_GFX_DEVICE(drhd-devices[i])) +list_for_each_entry(dmar_dev, drhd-head, list) { +pdev = pci_get_domain_bus_and_slot(dmar_dev-segment, +dmar_dev-bus, dmar_dev-devfn); +if (!IS_GFX_DEVICE(pdev)) { +pci_dev_put(pdev); break; +} +pci_dev_put(pdev); +} -if (i drhd-devices_cnt) +if (!IS_GFX_DEVICE(pdev)) I think this is clearly wrong. You acquire a pdev reference, drop the reference, then look at pdev again after dropping the reference. But as soon as you do the pci_dev_put(), you have to assume pdev is no longer valid. You are right, should move pci_dev_put() after if (!IS_GFX_DEVICE(pdev)). +struct dmar_device { +struct list_head list; +u8 segment; I think this should be u16. I didn't chase down how you're using it, but Table 8.3 in the Intel VT-d spec shows Segment Number in
Re: [PATCH 1/1] IOMMU: Save pci device id instead of pci_dev* pointer for DMAR devices
Hmmm, this is the thing I am most worried about. If we just only use (pci_dev *) poninter in drhd-devices array as a identification. Change (pci_dev *) pointer instead of pci device id segment:bus:devfn is safe. Or, this is a wrong way to fix this issue. I don't know IOMMU driver much now, so IOMMU guys any comments on this issue is welcome. If this is not safe, what about we both save pci device id and (pci_dev *) pointer in drhd. So we can put pci_dev ref and set pci_dev * = NULL during device removed by bus notify, and update (pci_dev *)pointer during device add. I don't know the IOMMU drivers well either, but it seems like they rely on notifications of device addition and removal (see iommu_bus_notifier()). It doesn't seem right for them to also use the generic PCI interfaces like pci_get_domain_bus_and_slot() because the IOMMU driver should already know what devices exist and their lifetimes. It seems like confusion to mix the two. But I don't have a concrete suggestion. Maybe you are right~, I will try to rework the patch and resend soon. Thanks! Yijing. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/ . -- Thanks! Yijing ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 1/1] IOMMU: Save pci device id instead of pci_dev* pointer for DMAR devices
On 2013/11/20 23:59, David Woodhouse wrote: On Fri, 2013-11-08 at 08:46 -0700, Bjorn Helgaas wrote: I don't know the IOMMU drivers well either, but it seems like they rely on notifications of device addition and removal (see iommu_bus_notifier()). It doesn't seem right for them to also use the generic PCI interfaces like pci_get_domain_bus_and_slot() because the IOMMU driver should already know what devices exist and their lifetimes. It seems like confusion to mix the two. But I don't have a concrete suggestion. Hi David, Thanks for your review and comment! The generic IOMMU code has a notifier, and calls through to an -add_device() method in the specific IOMMU driver's iommu_ops. The Intel IOMMU driver predates that, and its scheme for mapping devices to the correct DMAR unit is different. It happens entirely within the get_domain_for_dev() function, which happens when we're first asked to set up a mapping for a given device (when we don't already have the answer stashed in dev-archdata). I think we should add an -add_device() method to the Intel IOMMU driver, and make it do much of what's in get_domain_for_dev() right now — finding the proxy device (the upstream PCIe bridge or whatever), and then looking through the ACPI DMAR table to find which DMAR unit that's attached to. Then we stash that information (dmar, devfn) in dev-archdata, and get_domain_for_dev() still has *some* work to do, actually allocating a logical domain on the IOMMU in question, but not as much. And refcount the damn domain instead of playing the horrid tricks we currently do to hang it off the upstream proxy device *too*. Intel IOMMU driver has an -add_device() method already, .add_device = intel_iommu_add_device, this method was used to update iommu group info. Since Intel IOMMU driver has its own notifier, so maybe it's a nice candidate to do something. Currently, dmar driver parse DMAR table and find the pci device id under a specific DRHD. But only save the device pci_dev * pointer in devices array. So if this pci device was removed, this info became stale info. In the last version patch, I use pci device id intead of pci_dev * pointer array completely. This maybe introduce some unsafe issues. Because pci device maybe destroyed during process device dma mapping etc. So, I have rework the patch and try to save pci device id as well as pci_dev *pointer, like: struct dmar_device { u16 segment; u8 bus; u8 devfn; ---these tree will be used only when pci device add or remove, we will use them to update pci_dev * pointer in intel iommu driver notifier. struct list_head list; --add to DRHD device list. struct pci_dev *pdev; ---use to hold the pci device } What do you think about ? In this new patch, we won't change the Intel iommu driver much, just enhance Intel driver iommu notifier to make DRHD device list always effect, not stale info. I will send out this new patch soon. My main concern here is that the DMAR table contains the PCI bus numbers at boot time. Doing the lookup later will only work if we don't renumber busses. Or if we have a way to look things up based on the *original* bus number. If we won't remove the pci device, the occupied buses won't be change, I think. And because in the new patch, we still use pci_dev *pointer to find match DRHD, so this is not a regression. Since DMAR also use pci device id to identify the support device, I have not found anything instead of device id. In AMD IOMMU driver, it seems to use pci device id to identify drhd too, although I just take a quickly glanced at it, maybe not correctly. The Intel IOMMU also has a bus notifier of its own which it only uses to know when a driver is *detached*, so it can tear down the logical domain for the corresponding device. Would be nice to have the generic IOMMU notifier call a callback for us then too, perhaps. Update the device info in Intel IOMMU driver is a good point. Thanks! Yijing. -- Thanks! Yijing ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2] Enhance dmar to support device hotplug
This is the v2 patch, the v1 link: http://marc.info/?l=linux-pcim=138364004628824w=2 v1-v2: keep (pci_dev *) pointer array in dmar_drhd_uni, only use pci device id to update pci_dev * pointer info during device hotplug in intel iommu driver notifier. Currently, DMAR driver save target pci devices pointers for drhd/rmrr/atsr in (pci_dev *) array, but never update these info after initialization. It's not safe, because pci devices maybe hot added or removed during system running. They will have new pci_dev * pointer. So if there have two IOMMUs or more in system, these devices will find a wrong drhd during DMA mapping. And DMAR faults will occur. This patch save pci device id as well as (pci_dev *) to fix this issue. Pci device id will be used to update pci_dev * poninter during device hotplug in intel iommu driver notifier. Other, here use list to manage target devices for IOMMU, we can easily use list helper. Yijing Wang (1): IOMMU: enhance dmar to support device hotplug drivers/iommu/dmar.c| 82 +++--- drivers/iommu/intel-iommu.c | 161 +- include/linux/dmar.h| 24 -- 3 files changed, 167 insertions(+), 100 deletions(-) ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [Patch Part1 V2 01/17] iommu/vt-d: use dedicated bitmap to track remapping entry allocation status
Tested-and-reviewed-by: Yijing Wang wangyij...@huawei.com On 2013/11/29 16:50, Jiang Liu wrote: Currently Intel interrupt remapping drivers uses the present flag bit in remapping entry to track whether an entry is allocated or not. It works as follow: 1) allocate a remapping entry and set its present flag bit to 1 2) compose other fields for the entry 3) update the remapping entry with the composed value The remapping hardware may access the entry between step 1 and step 3, which then obervers an entry with the present flag set but random values in all other fields. This patch introduces a dedicated bitmap to track remapping entry allocation status instead of sharing the present flag with hardware, thus eliminate the race window. It also simplifies the implementation. Signed-off-by: Jiang Liu jiang@linux.intel.com --- drivers/iommu/intel_irq_remapping.c | 51 +-- include/linux/intel-iommu.h |1 + 2 files changed, 25 insertions(+), 27 deletions(-) diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c index bab10b1..282d392 100644 --- a/drivers/iommu/intel_irq_remapping.c +++ b/drivers/iommu/intel_irq_remapping.c @@ -72,7 +72,6 @@ static int alloc_irte(struct intel_iommu *iommu, int irq, u16 count) u16 index, start_index; unsigned int mask = 0; unsigned long flags; - int i; if (!count || !irq_iommu) return -1; @@ -96,32 +95,17 @@ static int alloc_irte(struct intel_iommu *iommu, int irq, u16 count) } raw_spin_lock_irqsave(irq_2_ir_lock, flags); - do { - for (i = index; i index + count; i++) - if (table-base[i].present) - break; - /* empty index found */ - if (i == index + count) - break; - - index = (index + count) % INTR_REMAP_TABLE_ENTRIES; - - if (index == start_index) { - raw_spin_unlock_irqrestore(irq_2_ir_lock, flags); - printk(KERN_ERR can't allocate an IRTE\n); - return -1; - } - } while (1); - - for (i = index; i index + count; i++) - table-base[i].present = 1; - - cfg-remapped = 1; - irq_iommu-iommu = iommu; - irq_iommu-irte_index = index; - irq_iommu-sub_handle = 0; - irq_iommu-irte_mask = mask; - + index = bitmap_find_free_region(table-bitmap, + INTR_REMAP_TABLE_ENTRIES, mask); + if (index 0) { + printk(KERN_ERR can't allocate an IRTE\n); + } else { + cfg-remapped = 1; + irq_iommu-iommu = iommu; + irq_iommu-irte_index = index; + irq_iommu-sub_handle = 0; + irq_iommu-irte_mask = mask; + } raw_spin_unlock_irqrestore(irq_2_ir_lock, flags); return index; @@ -254,6 +238,8 @@ static int clear_entries(struct irq_2_iommu *irq_iommu) set_64bit(entry-low, 0); set_64bit(entry-high, 0); } + bitmap_release_region(iommu-ir_table-bitmap, index, + irq_iommu-irte_mask); return qi_flush_iec(iommu, index, irq_iommu-irte_mask); } @@ -453,6 +439,7 @@ static int intel_setup_irq_remapping(struct intel_iommu *iommu, int mode) { struct ir_table *ir_table; struct page *pages; + unsigned long *bitmap; ir_table = iommu-ir_table = kzalloc(sizeof(struct ir_table), GFP_ATOMIC); @@ -470,7 +457,17 @@ static int intel_setup_irq_remapping(struct intel_iommu *iommu, int mode) return -ENOMEM; } + bitmap = kcalloc(BITS_TO_LONGS(INTR_REMAP_TABLE_ENTRIES), + sizeof(long), GFP_ATOMIC); + if (bitmap == NULL) { + printk(KERN_ERR failed to allocate bitmap\n); + __free_pages(pages, INTR_REMAP_PAGE_ORDER); + kfree(ir_table); + return -ENOMEM; + } + ir_table-base = page_address(pages); + ir_table-bitmap = bitmap; iommu_set_irq_remapping(iommu, mode); return 0; diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h index d380c5e..de1e5e9 100644 --- a/include/linux/intel-iommu.h +++ b/include/linux/intel-iommu.h @@ -288,6 +288,7 @@ struct q_inval { struct ir_table { struct irte *base; + unsigned long *bitmap; }; #endif -- Thanks! Yijing ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [Patch Part1 V2 02/17] iommu/vt-d: fix PCI device reference leakage on error recovery path
Reviewed-by: Yijing Wang wangyij...@huawei.com On 2013/11/29 16:50, Jiang Liu wrote: Function dmar_parse_dev_scope() should release the PCI device reference count gained in function dmar_parse_one_dev_scope() on error recovery, otherwise will cause PCI device object leakage. This patch also introduces dmar_free_dev_scope(), which will be used to support DMAR device hotplug. Signed-off-by: Jiang Liu jiang@linux.intel.com --- drivers/iommu/dmar.c | 15 +-- include/linux/dmar.h |1 + 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index 8b452c9..f3043a2 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -72,6 +72,7 @@ static int __init dmar_parse_one_dev_scope(struct acpi_dmar_device_scope *scope, struct acpi_dmar_pci_path *path; int count; + *dev = NULL; bus = pci_find_bus(segment, scope-bus); path = (struct acpi_dmar_pci_path *)(scope + 1); count = (scope-length - sizeof(struct acpi_dmar_device_scope)) @@ -100,7 +101,6 @@ static int __init dmar_parse_one_dev_scope(struct acpi_dmar_device_scope *scope, if (!pdev) { pr_warn(Device scope device [%04x:%02x:%02x.%02x] not found\n, segment, scope-bus, path-device, path-function); - *dev = NULL; return 0; } if ((scope-entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT \ @@ -151,7 +151,7 @@ int __init dmar_parse_dev_scope(void *start, void *end, int *cnt, ret = dmar_parse_one_dev_scope(scope, (*devices)[index], segment); if (ret) { - kfree(*devices); + dmar_free_dev_scope(devices, cnt); return ret; } index ++; @@ -162,6 +162,17 @@ int __init dmar_parse_dev_scope(void *start, void *end, int *cnt, return 0; } +void dmar_free_dev_scope(struct pci_dev ***devices, int *cnt) +{ + if (*devices *cnt) { + while (--*cnt = 0) + pci_dev_put((*devices)[*cnt]); + kfree(*devices); + *devices = NULL; + *cnt = 0; + } +} + /** * dmar_parse_one_drhd - parses exactly one DMA remapping hardware definition * structure which uniquely represent one DMA remapping hardware unit diff --git a/include/linux/dmar.h b/include/linux/dmar.h index b029d1a..8adfce0 100644 --- a/include/linux/dmar.h +++ b/include/linux/dmar.h @@ -159,6 +159,7 @@ extern int dmar_parse_one_rmrr(struct acpi_dmar_header *header); extern int dmar_parse_one_atsr(struct acpi_dmar_header *header); extern int dmar_parse_dev_scope(void *start, void *end, int *cnt, struct pci_dev ***devices, u16 segment); +extern void dmar_free_dev_scope(struct pci_dev ***devices, int *cnt); extern int intel_iommu_init(void); #else /* !CONFIG_INTEL_IOMMU: */ static inline int intel_iommu_init(void) { return -ENODEV; } -- Thanks! Yijing ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [Patch Part1 V2 04/17] iommu/vt-d: fix resource leakage on error recovery path in iommu_init_domains()
On 2013/11/29 16:50, Jiang Liu wrote: Release allocated resources on error recovery path in function iommu_init_domains(). Signed-off-by: Jiang Liu jiang@linux.intel.com --- drivers/iommu/intel-iommu.c |2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index b8e3b48..2398876 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -1273,6 +1273,8 @@ static int iommu_init_domains(struct intel_iommu *iommu) GFP_KERNEL); if (!iommu-domains) { printk(KERN_ERR Allocating domain array failed\n); + kfree(iommu-domain_ids); + iommu-domain_ids = NULL; return -ENOMEM; } Acked-by: Yijing Wang wangyij...@huawei.com -- Thanks! Yijing ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [Patch Part1 V2 07/17] iommu/vt-d. trivial: check suitable flag in function detect_intel_iommu()
This patch is the same as the last.:) On 2013/11/29 16:50, Jiang Liu wrote: Flag irq_remapping_enabled is only set by intel_enable_irq_remapping(), which is called after detect_intel_iommu(). So we should check flag disable_irq_remap instead of irq_remapping_enabled in function detect_intel_iommu(). Signed-off-by: Jiang Liu jiang@linux.intel.com --- drivers/iommu/dmar.c |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index f3043a2..77a066b 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -561,7 +561,7 @@ int __init detect_intel_iommu(void) dmar = (struct acpi_table_dmar *) dmar_tbl; - if (ret irq_remapping_enabled cpu_has_x2apic + if (ret !disable_irq_remap cpu_has_x2apic dmar-flags 0x1) pr_info(Queued invalidation will be enabled to support x2apic and Intr-remapping.\n); -- Thanks! Yijing ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [Patch Part1 V2 07/17] iommu/vt-d, trivial: check suitable flag in function detect_intel_iommu()
On 2013/11/29 16:50, Jiang Liu wrote: Flag irq_remapping_enabled is only set by intel_enable_irq_remapping(), which is called after detect_intel_iommu(). So we should check flag disable_irq_remap instead of irq_remapping_enabled in function detect_intel_iommu(). Signed-off-by: Jiang Liu jiang@linux.intel.com --- drivers/iommu/dmar.c |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index f3043a2..77a066b 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -561,7 +561,7 @@ int __init detect_intel_iommu(void) dmar = (struct acpi_table_dmar *) dmar_tbl; - if (ret irq_remapping_enabled cpu_has_x2apic + if (ret !disable_irq_remap cpu_has_x2apic dmar-flags 0x1) pr_info(Queued invalidation will be enabled to support x2apic and Intr-remapping.\n); Reviewed-by: Yijing Wang wangyij...@huawei.com -- Thanks! Yijing ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [Patch Part1 V2 12/17] iommu/vt-d: fix invalid memory access when freeing DMAR irq
Reviewed-by: Yijing Wang wangyij...@huawei.com On 2013/11/29 16:50, Jiang Liu wrote: In function free_dmar_iommu(), it sets IRQ handler data to NULL before calling free_irq(), which will cause invalid memory access because free_irq() will access IRQ handler data when calling function dmar_msi_mask(). So only set IRQ handler data to NULL after calling free_irq(). Sample stack dump: [ 13.094010] BUG: unable to handle kernel NULL pointer dereference at 0048 [ 13.103215] IP: [810a97cd] __lock_acquire+0x4d/0x12a0 [ 13.110104] PGD 0 [ 13.112614] Oops: [#1] SMP [ 13.116585] Modules linked in: [ 13.120260] CPU: 60 PID: 1 Comm: swapper/0 Tainted: GW 3.13.0-rc1-gerry+ #9 [ 13.129367] Hardware name: Intel Corporation LH Pass ../SVRBD-ROW_T, BIOS SE5C600.86B.99.99.x059.091020121352 09/10/2012 [ 13.142555] task: 88042dd38010 ti: 88042dd32000 task.ti: 88042dd32000 [ 13.151179] RIP: 0010:[810a97cd] [810a97cd] __lock_acquire+0x4d/0x12a0 [ 13.160867] RSP: :88042dd33b78 EFLAGS: 00010046 [ 13.166969] RAX: 0046 RBX: 0002 RCX: [ 13.175122] RDX: RSI: RDI: 0048 [ 13.183274] RBP: 88042dd33bd8 R08: 0002 R09: 0001 [ 13.191417] R10: R11: 0001 R12: 88042dd38010 [ 13.199571] R13: R14: 0048 R15: [ 13.207725] FS: () GS:88103f20() knlGS: [ 13.217014] CS: 0010 DS: ES: CR0: 80050033 [ 13.223596] CR2: 0048 CR3: 01a0b000 CR4: 000407e0 [ 13.231747] Stack: [ 13.234160] 0004 0046 88042dd33b98 810a567d [ 13.243059] 88042dd33c08 810bb14c 828995a0 0046 [ 13.251969] 0002 [ 13.260862] Call Trace: [ 13.263775] [810a567d] ? trace_hardirqs_off+0xd/0x10 [ 13.270571] [810bb14c] ? vprintk_emit+0x23c/0x570 [ 13.277058] [810ab1e3] lock_acquire+0x93/0x120 [ 13.283269] [814623f7] ? dmar_msi_mask+0x47/0x70 [ 13.289677] [8156b449] _raw_spin_lock_irqsave+0x49/0x90 [ 13.296748] [814623f7] ? dmar_msi_mask+0x47/0x70 [ 13.303153] [814623f7] dmar_msi_mask+0x47/0x70 [ 13.309354] [810c0d93] irq_shutdown+0x53/0x60 [ 13.315467] [810bdd9d] __free_irq+0x26d/0x280 [ 13.321580] [810be920] free_irq+0xf0/0x180 [ 13.327395] [81466591] free_dmar_iommu+0x271/0x2b0 [ 13.333996] [810a947d] ? trace_hardirqs_on+0xd/0x10 [ 13.340696] [81461a17] free_iommu+0x17/0x50 [ 13.346597] [81dc75a5] init_dmars+0x691/0x77a [ 13.352711] [81dc7afd] intel_iommu_init+0x351/0x438 [ 13.359400] [81d8a711] ? iommu_setup+0x27d/0x27d [ 13.365806] [81d8a739] pci_iommu_init+0x28/0x52 [ 13.372114] [81000342] do_one_initcall+0x122/0x180 [ 13.378707] [81077738] ? parse_args+0x1e8/0x320 [ 13.385016] [81d850e8] kernel_init_freeable+0x1e1/0x26c [ 13.392100] [81d84833] ? do_early_param+0x88/0x88 [ 13.398596] [8154f8b0] ? rest_init+0xd0/0xd0 [ 13.404614] [8154f8be] kernel_init+0xe/0x130 [ 13.410626] [81574d6c] ret_from_fork+0x7c/0xb0 [ 13.416829] [8154f8b0] ? rest_init+0xd0/0xd0 [ 13.422842] Code: ec 99 00 85 c0 8b 05 53 05 a5 00 41 0f 45 d8 85 c0 0f 84 ff 00 00 00 8b 05 99 f9 7e 01 49 89 fe 41 89 f7 85 c0 0f 84 03 01 00 00 49 8b 06 be 01 00 00 00 48 3d c0 0e 01 82 0f 44 de 41 83 ff 01 [ 13.450191] RIP [810a97cd] __lock_acquire+0x4d/0x12a0 [ 13.458598] RSP 88042dd33b78 [ 13.462671] CR2: 0048 [ 13.466551] ---[ end trace c5bd26a37c81d760 ]--- Signed-off-by: Jiang Liu jiang@linux.intel.com --- drivers/iommu/intel-iommu.c |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 0ec49da..426095e 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -1289,9 +1289,9 @@ void free_dmar_iommu(struct intel_iommu *iommu) iommu_disable_translation(iommu); if (iommu-irq) { - irq_set_handler_data(iommu-irq, NULL); /* This will mask the irq */ free_irq(iommu-irq, iommu); + irq_set_handler_data(iommu-irq, NULL); destroy_irq(iommu-irq); } -- Thanks! Yijing ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 2/3] iommu/fsl_pamu: Use dev_is_pci() to check whether it is pci device
Use PCI standard marco dev_is_pci() instead of directly compare pci_bus_type to check whether it is pci device. Signed-off-by: Yijing Wang wangyij...@huawei.com --- drivers/iommu/fsl_pamu_domain.c |6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/fsl_pamu_domain.c b/drivers/iommu/fsl_pamu_domain.c index c857c30..93072ba 100644 --- a/drivers/iommu/fsl_pamu_domain.c +++ b/drivers/iommu/fsl_pamu_domain.c @@ -691,7 +691,7 @@ static int fsl_pamu_attach_device(struct iommu_domain *domain, * Use LIODN of the PCI controller while attaching a * PCI device. */ - if (dev-bus == pci_bus_type) { + if (dev_is_pci(dev)) { pdev = to_pci_dev(dev); pci_ctl = pci_bus_to_host(pdev-bus); /* @@ -729,7 +729,7 @@ static void fsl_pamu_detach_device(struct iommu_domain *domain, * Use LIODN of the PCI controller while detaching a * PCI device. */ - if (dev-bus == pci_bus_type) { + if (dev_is_pci(dev)) { pdev = to_pci_dev(dev); pci_ctl = pci_bus_to_host(pdev-bus); /* @@ -1056,7 +1056,7 @@ static int fsl_pamu_add_device(struct device *dev) * For platform devices we allocate a separate group for * each of the devices. */ - if (dev-bus == pci_bus_type) { + if (dev_is_pci(dev)) { pdev = to_pci_dev(dev); /* Don't create device groups for virtual PCI bridges */ if (pdev-subordinate) -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 1/3] iommu/amd: Use dev_is_pci() to check whether it is pci device
Use PCI standard marco dev_is_pci() instead of directly compare pci_bus_type to check whether it is pci device. Signed-off-by: Yijing Wang wangyij...@huawei.com --- drivers/iommu/amd_iommu.c |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 72531f0..faf0da4 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -248,8 +248,8 @@ static bool check_device(struct device *dev) if (!dev || !dev-dma_mask) return false; - /* No device or no PCI device */ - if (dev-bus != pci_bus_type) + /* No PCI device */ + if (!dev_is_pci(dev)) return false; devid = get_device_id(dev); -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 3/3] iommu/vt-d: Use dev_is_pci() to check whether it is pci device
Use PCI standard marco dev_is_pci() instead of directly compare pci_bus_type to check whether it is pci device. Signed-off-by: Yijing Wang wangyij...@huawei.com --- drivers/iommu/intel-iommu.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 43b9bfe..64d8942 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -2758,7 +2758,7 @@ static int iommu_no_mapping(struct device *dev) struct pci_dev *pdev; int found; - if (unlikely(dev-bus != pci_bus_type)) + if (unlikely(!dev_is_pci(dev))) return 1; pdev = to_pci_dev(dev); -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v2] Enhance dmar to support device hotplug
On 2013/12/11 1:03, Don Dutile wrote: On 11/21/2013 03:21 AM, Yijing Wang wrote: This is the v2 patch, the v1 link: http://marc.info/?l=linux-pcim=138364004628824w=2 v1-v2: keep (pci_dev *) pointer array in dmar_drhd_uni, only use pci device id to update pci_dev * pointer info during device hotplug in intel iommu driver notifier. Currently, DMAR driver save target pci devices pointers for drhd/rmrr/atsr in (pci_dev *) array, but never update these info after initialization. It's not safe, because pci devices maybe hot added or removed during system running. They will have new pci_dev * pointer. So if there have two IOMMUs or more in system, these devices will find a wrong drhd during DMA mapping. And DMAR faults will occur. This patch save pci device id as well as (pci_dev *) to fix this issue. Pci device id will be used to update pci_dev * poninter during device hotplug in intel iommu driver notifier. Other, here use list to manage target devices for IOMMU, we can easily use list helper. Yijing Wang (1): IOMMU: enhance dmar to support device hotplug drivers/iommu/dmar.c| 82 +++--- drivers/iommu/intel-iommu.c | 161 +- include/linux/dmar.h| 24 -- 3 files changed, 167 insertions(+), 100 deletions(-) ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu Can this bug fix be demonstrated by configuring de-configuring VFs on an SRIOV device, since that effectively looks like a hot-add hot-remove ? Hi Don, It seems can not be demonstrated by configuring de-configuring VFs, because if we only hotplug VFs, the device scope info saved in drhd-devices array will not become stale. In my platform, the target device scope devices are root port, so only we remove and rescan root port, we can trigger this problem. Thanks! Yijing. . -- Thanks! Yijing ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [Patch Part2 V1 07/14] iommu/vt-d: fix error in detect ATS capability
This is a issue, our BIOS also supports several ATSR which have the same segment. Good fix :) On 2014/1/7 17:00, Jiang Liu wrote: Current Intel IOMMU driver only matches a PCIe root port with the first DRHD unit with the samge segment number. It will report false result if there are multiple DRHD units with the same segment number, thus fail to detect ATS capability for some PCIe devices. This patch refines function dmar_find_matched_atsr_unit() to search all DRHD units with the same segment number. An example DMAR table entries as below: [1D0h 0464 2]Subtable Type : 0002 Root Port ATS Capability [1D2h 0466 2] Length : 0028 [1D4h 0468 1]Flags : 00 [1D5h 0469 1] Reserved : 00 [1D6h 0470 2] PCI Segment Number : [1D8h 0472 1] Device Scope Entry Type : 02 [1D9h 0473 1] Entry Length : 08 [1DAh 0474 2] Reserved : [1DCh 0476 1] Enumeration ID : 00 [1DDh 0477 1] PCI Bus Number : 00 [1DEh 0478 2] PCI Path : [02, 00] [1E0h 0480 1] Device Scope Entry Type : 02 [1E1h 0481 1] Entry Length : 08 [1E2h 0482 2] Reserved : [1E4h 0484 1] Enumeration ID : 00 [1E5h 0485 1] PCI Bus Number : 00 [1E6h 0486 2] PCI Path : [03, 00] [1E8h 0488 1] Device Scope Entry Type : 02 [1E9h 0489 1] Entry Length : 08 [1EAh 0490 2] Reserved : [1ECh 0492 1] Enumeration ID : 00 [1EDh 0493 1] PCI Bus Number : 00 [1EEh 0494 2] PCI Path : [03, 02] [1F0h 0496 1] Device Scope Entry Type : 02 [1F1h 0497 1] Entry Length : 08 [1F2h 0498 2] Reserved : [1F4h 0500 1] Enumeration ID : 00 [1F5h 0501 1] PCI Bus Number : 00 [1F6h 0502 2] PCI Path : [03, 03] [1F8h 0504 2]Subtable Type : 0002 Root Port ATS Capability [1FAh 0506 2] Length : 0020 [1FCh 0508 1]Flags : 00 [1FDh 0509 1] Reserved : 00 [1FEh 0510 2] PCI Segment Number : [200h 0512 1] Device Scope Entry Type : 02 [201h 0513 1] Entry Length : 08 [202h 0514 2] Reserved : [204h 0516 1] Enumeration ID : 00 [205h 0517 1] PCI Bus Number : 40 [206h 0518 2] PCI Path : [02, 00] [208h 0520 1] Device Scope Entry Type : 02 [209h 0521 1] Entry Length : 08 [20Ah 0522 2] Reserved : [20Ch 0524 1] Enumeration ID : 00 [20Dh 0525 1] PCI Bus Number : 40 [20Eh 0526 2] PCI Path : [02, 02] [210h 0528 1] Device Scope Entry Type : 02 [211h 0529 1] Entry Length : 08 [212h 0530 2] Reserved : [214h 0532 1] Enumeration ID : 00 [215h 0533 1] PCI Bus Number : 40 [216h 0534 2] PCI Path : [03, 00] [218h 0536 2]Subtable Type : 0002 Root Port ATS Capability [21Ah 0538 2] Length : 0020 [21Ch 0540 1]Flags : 00 [21Dh 0541 1] Reserved : 00 [21Eh 0542 2] PCI Segment Number : [220h 0544 1] Device Scope Entry Type : 02 [221h 0545 1] Entry Length : 08 [222h 0546 2] Reserved : [224h 0548 1] Enumeration ID : 00 [225h 0549 1] PCI Bus Number : 80 [226h 0550 2] PCI Path : [02, 00] [228h 0552 1] Device Scope Entry Type : 02 [229h 0553 1] Entry Length : 08 [22Ah 0554 2] Reserved : [22Ch 0556 1] Enumeration ID : 00 [22Dh 0557 1] PCI Bus Number : 80 [22Eh 0558 2] PCI Path : [02, 02] [230h 0560 1] Device Scope Entry Type : 02 [231h 0561 1] Entry Length : 08 [232h 0562 2] Reserved : [234h 0564 1] Enumeration ID : 00 [235h 0565 1] PCI Bus Number : 80 [236h 0566 2] PCI Path : [03, 00] [238h 0568 2]Subtable Type : 0002 Root Port ATS Capability [23Ah 0570 2] Length : 0020 [23Ch 0572 1]Flags : 00 [23Dh 0573 1] Reserved : 00 [23Eh 0574 2] PCI Segment Number : [240h 0576 1] Device Scope Entry Type : 02 [241h 0577 1] Entry Length : 08 [242h 0578 2] Reserved : [244h 0580 1] Enumeration ID : 00 [245h
Re: [PATCH v2] IOMMU: enhance dmar to support device hotplug
On 2014/3/4 22:31, Joerg Roedel wrote: On Thu, Nov 21, 2013 at 04:21:56PM +0800, Yijing Wang wrote: @@ -3641,21 +3681,42 @@ static int device_notifier(struct notifier_block *nb, struct device *dev = data; struct pci_dev *pdev = to_pci_dev(dev); struct dmar_domain *domain; +struct dmar_device *dmar_dev; +struct dmar_drhd_unit *drhd; -if (iommu_no_mapping(dev)) -return 0; - -domain = find_domain(pdev); -if (!domain) -return 0; +switch (action) { +case BUS_NOTIFY_ADD_DEVICE: +for_each_drhd_unit(drhd) +list_for_each_entry(dmar_dev, drhd-devices, list) +if (dmar_dev-segment == pci_domain_nr(pdev-bus) + dmar_dev-bus == pdev-bus-number + dmar_dev-devfn == pdev-devfn) +dmar_dev-pdev = pci_dev_get(pdev); +break; +case BUS_NOTIFY_DEL_DEVICE: +for_each_drhd_unit(drhd) +list_for_each_entry(dmar_dev, drhd-devices, list) +if (dmar_dev-pdev == pdev) { +pci_dev_put(pdev); +dmar_dev-pdev = NULL; +} How is that synchronized with other users of this dmar_dev structure. Could it happen that you drop the device reference while other parts of the driver still use it? Hi Joerg, Thanks for your review and comments! We use original struct dmar_drhd_unit-devices to attach the pci device to specific DMAR, eg. use dmar_find_matched_drhd_unit() to find the attached DMAR by pci_dev * pointer. So if the related pci_dev was removed, I think we can safely set dmar_dev-pdev = NULL; No pci device will use it again until the new pci device hot add. One problem in this solution is PCI bus number maybe changed after device hotplug, so use the bus,device,function id to update the dmar device scope maybe unreliable. Jiang Liu also provide a solution to fix this problem by save device scope pathes, I think that's a good idea. link:http://lkml.org/lkml/2014/1/7/108 Thanks! Yijing. Joerg -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/ . -- Thanks! Yijing ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 0/6] trivial cleanup for iommu/vt-d
Some cleanup patches for iommu/vt-d. Yijing Wang (6): iommu/vt-d: Use list_for_each_safe() to simplify code iommu/vt-d: move up no_iommu and dmar_disabled check iommu/vt-d: clear the redundant assignment in dmar_enable_qi iommu/vt-d: clear the redundant assignment for domain-nid iommu/vt-d: use inline function dma_pte_superpage instead of macros iommu/vt-d: fix reference count in iommu_prepare_isa drivers/iommu/dmar.c|3 --- drivers/iommu/intel-iommu.c | 18 -- 2 files changed, 8 insertions(+), 13 deletions(-) ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 3/6] iommu/vt-d: clear the redundant assignment in dmar_enable_qi
__dmar_enable_qi() will initialize free_head,free_tail and free_cnt for q_inval. Remove the redundant initialization in dmar_enable_qi(). Signed-off-by: Yijing Wang wangyij...@huawei.com --- drivers/iommu/dmar.c |3 --- 1 files changed, 0 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index 39f8b71..1168469 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -1339,9 +1339,6 @@ int dmar_enable_qi(struct intel_iommu *iommu) return -ENOMEM; } - qi-free_head = qi-free_tail = 0; - qi-free_cnt = QI_LENGTH; - raw_spin_lock_init(qi-q_lock); __dmar_enable_qi(iommu); -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 4/6] iommu/vt-d: clear the redundant assignment for domain-nid
Alloc_domain() will initialize domain-nid to -1. So the initialization for domain-nid in md_domain_init() is redundant, clear it. Signed-off-by: Yijing Wang wangyij...@huawei.com --- drivers/iommu/intel-iommu.c |1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 6b71608..d1d6636 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -4134,7 +4134,6 @@ static int md_domain_init(struct dmar_domain *domain, int guest_width) domain-iommu_snooping = 0; domain-iommu_superpage = 0; domain-max_addr = 0; - domain-nid = -1; /* always allocate the top pgd */ domain-pgd = (struct dma_pte *)alloc_pgtable_page(domain-nid); -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 6/6] iommu/vt-d: fix reference count in iommu_prepare_isa
Decrease the device reference count avoid memory leak. Signed-off-by: Yijing Wang wangyij...@huawei.com --- drivers/iommu/intel-iommu.c |3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 455896c..a78a824 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -2401,7 +2401,8 @@ static inline void iommu_prepare_isa(void) if (ret) printk(KERN_ERR IOMMU: Failed to create 0-16MiB identity map; floppy might not work\n); - + + pci_dev_put(pdev); } #else static inline void iommu_prepare_isa(void) -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 5/6] iommu/vt-d: use inline function dma_pte_superpage instead of macros
Use inline function dma_pte_superpage() instead of macro for better readability. Signed-off-by: Yijing Wang wangyij...@huawei.com --- drivers/iommu/intel-iommu.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index d1d6636..455896c 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -891,7 +891,7 @@ static struct dma_pte *dma_pfn_level_pte(struct dmar_domain *domain, break; } - if (pte-val DMA_PTE_LARGE_PAGE) { + if (dma_pte_superpage(pte)) { *large_page = total; return pte; } -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 1/6] iommu/vt-d: Use list_for_each_safe() to simplify code
Use list_for_each_entry_safe() instead of list_entry() to simplify code. Signed-off-by: Yijing Wang wangyij...@huawei.com --- drivers/iommu/intel-iommu.c |6 ++ 1 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index f256ffc..e020dcf 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -2101,13 +2101,11 @@ static inline void unlink_domain_info(struct device_domain_info *info) static void domain_remove_dev_info(struct dmar_domain *domain) { - struct device_domain_info *info; + struct device_domain_info *info, *tmp; unsigned long flags, flags2; spin_lock_irqsave(device_domain_lock, flags); - while (!list_empty(domain-devices)) { - info = list_entry(domain-devices.next, - struct device_domain_info, link); + list_for_each_entry_safe(info, tmp, domain-devices, link) { unlink_domain_info(info); spin_unlock_irqrestore(device_domain_lock, flags); -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 1/2] iommu/vt-d: remove the useless dma_pte_addr
Signed-off-by: Yijing Wang wangyij...@huawei.com --- drivers/iommu/intel-iommu.c |6 ++ 1 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index f256ffc..7b7127a 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -848,13 +848,11 @@ static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain, domain_flush_cache(domain, tmp_page, VTD_PAGE_SIZE); pteval = ((uint64_t)virt_to_dma_pfn(tmp_page) VTD_PAGE_SHIFT) | DMA_PTE_READ | DMA_PTE_WRITE; - if (cmpxchg64(pte-val, 0ULL, pteval)) { + if (cmpxchg64(pte-val, 0ULL, pteval)) /* Someone else set it while we were thinking; use theirs. */ free_pgtable_page(tmp_page); - } else { - dma_pte_addr(pte); + else domain_flush_cache(domain, pte, sizeof(*pte)); - } } if (level == 1) break; -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 1/2] iommu/vt-d: remove the useless dma_pte_addr
ping... On 2014/5/26 20:13, Yijing Wang wrote: Signed-off-by: Yijing Wang wangyij...@huawei.com --- drivers/iommu/intel-iommu.c |6 ++ 1 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index f256ffc..7b7127a 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -848,13 +848,11 @@ static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain, domain_flush_cache(domain, tmp_page, VTD_PAGE_SIZE); pteval = ((uint64_t)virt_to_dma_pfn(tmp_page) VTD_PAGE_SHIFT) | DMA_PTE_READ | DMA_PTE_WRITE; - if (cmpxchg64(pte-val, 0ULL, pteval)) { + if (cmpxchg64(pte-val, 0ULL, pteval)) /* Someone else set it while we were thinking; use theirs. */ free_pgtable_page(tmp_page); - } else { - dma_pte_addr(pte); + else domain_flush_cache(domain, pte, sizeof(*pte)); - } } if (level == 1) break; -- Thanks! Yijing ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 0/6] trivial cleanup for iommu/vt-d
ping... On 2014/5/20 20:37, Yijing Wang wrote: Some cleanup patches for iommu/vt-d. Yijing Wang (6): iommu/vt-d: Use list_for_each_safe() to simplify code iommu/vt-d: move up no_iommu and dmar_disabled check iommu/vt-d: clear the redundant assignment in dmar_enable_qi iommu/vt-d: clear the redundant assignment for domain-nid iommu/vt-d: use inline function dma_pte_superpage instead of macros iommu/vt-d: fix reference count in iommu_prepare_isa drivers/iommu/dmar.c|3 --- drivers/iommu/intel-iommu.c | 18 -- 2 files changed, 8 insertions(+), 13 deletions(-) . -- Thanks! Yijing ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 2/6] iommu/vt-d: move up no_iommu and dmar_disabled check
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index e020dcf..6b71608 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -3948,6 +3948,9 @@ int __init intel_iommu_init(void) /* VT-d is required for a TXT/tboot launch, so enforce that */ force_on = tboot_force_iommu(); +if (no_iommu || dmar_disabled) +return ret; + if (iommu_init_mempool()) { if (force_on) panic(tboot: Failed to initialize iommu memory\n); @@ -3974,9 +3977,6 @@ int __init intel_iommu_init(void) goto out_free_dmar; } -if (no_iommu || dmar_disabled) -goto out_free_dmar; - if (list_empty(dmar_rmrr_units)) printk(KERN_INFO DMAR: No RMRR found\n); This breaks the kexec case were the old kernel had VT-d enabled and the new one disabled. In this case the new kernel might need to disable the IOMMUs. Hi Joerg, Thanks for your review and comments! You are right, I didn't consider the kexec case, I will drop this patch. Thanks! Yijing. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/ -- Thanks! Yijing ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 0/6] trivial cleanup for iommu/vt-d
On 2014/7/4 17:22, Joerg Roedel wrote: On Tue, May 20, 2014 at 08:37:46PM +0800, Yijing Wang wrote: Yijing Wang (6): iommu/vt-d: Use list_for_each_safe() to simplify code iommu/vt-d: move up no_iommu and dmar_disabled check iommu/vt-d: clear the redundant assignment in dmar_enable_qi iommu/vt-d: clear the redundant assignment for domain-nid iommu/vt-d: use inline function dma_pte_superpage instead of macros iommu/vt-d: fix reference count in iommu_prepare_isa Applied patches 1, 3, 4, 5 and 6, thanks. Also added another patch on-top, see below. Thanks a lot! Yijing. From 77c704bebc5d023ece7af32ea18bc3508cdb0007 Mon Sep 17 00:00:00 2001 From: Joerg Roedel jroe...@suse.de Date: Fri, 4 Jul 2014 11:19:10 +0200 Subject: [PATCH] iommu/vt-d: Don't use magic number in dma_pte_superpage Use the already defined DMA_PTE_LARGE_PAGE for testing instead of hardcoding the value again. Signed-off-by: Joerg Roedel jroe...@suse.de --- drivers/iommu/intel-iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 9b9f28e..5d86e93 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -304,7 +304,7 @@ static inline bool dma_pte_present(struct dma_pte *pte) static inline bool dma_pte_superpage(struct dma_pte *pte) { - return (pte-val (1 7)); + return (pte-val DMA_PTE_LARGE_PAGE); } static inline int first_pte_in_page(struct dma_pte *pte) -- Thanks! Yijing ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH] iommu/vt-d: Fix broken device issue when using iommu=pt
We found some strange devices in HP C7000 and Huawei Server. These devices can not be enumerated by OS, but they still did DMA read/write without OS management. Because iommu will not create the DMA mapping for these devices, the DMA read/write will be blocked by iommu hardware. Eg. \-[:00]-+-00.0 Intel Corporation Xeon E5/Core i7 DMI2 +-01.0-[11]-- +-01.1-[02]-- +-02.0-[04]--+-00.0 Emulex Corporation OneConnect 10Gb NIC (be3) |+-00.1 Emulex Corporation OneConnect 10Gb NIC (be3) |+-00.2 Emulex Corporation OneConnect 10Gb iSCSI Initiator (be3) |\-00.3 Emulex Corporation OneConnect 10Gb iSCSI Initiator (be3) +-02.1-[12]-- Kernel only found four devices in bus 0x04, but we found following DMA errors in dmesg. [ 1438.477262] DRHD: handling fault status reg 402 [ 1438.498278] DMAR:[DMA Write] Request device [04:00.4] fault addr bdf7 [ 1438.498280] DMAR:[fault reason 02] Present bit in context entry is clear [ 1438.566458] DMAR:[DMA Write] Request device [04:00.5] fault addr bdf7 [ 1438.566460] DMAR:[fault reason 02] Present bit in context entry is clear [ 1438.635211] DMAR:[DMA Write] Request device [04:00.6] fault addr bdf7 [ 1438.635213] DMAR:[fault reason 02] Present bit in context entry is clear [ 1438.703849] DMAR:[DMA Write] Request device [04:00.7] fault addr bdf7 [ 1438.703851] DMAR:[fault reason 02] Present bit in context entry is clear Signed-off-by: Yijing Wang wangyij...@huawei.com --- arch/x86/include/asm/iommu.h |2 ++ arch/x86/kernel/pci-dma.c|8 drivers/iommu/intel-iommu.c | 41 + 3 files changed, 51 insertions(+), 0 deletions(-) diff --git a/arch/x86/include/asm/iommu.h b/arch/x86/include/asm/iommu.h index 345c99c..5e3a2d8 100644 --- a/arch/x86/include/asm/iommu.h +++ b/arch/x86/include/asm/iommu.h @@ -5,6 +5,8 @@ extern struct dma_map_ops nommu_dma_ops; extern int force_iommu, no_iommu; extern int iommu_detected; extern int iommu_pass_through; +extern int iommu_pt_force_bus; +extern int iommu_pt_force_domain; /* 10 seconds */ #define DMAR_OPERATION_TIMEOUT ((cycles_t) tsc_khz*10*1000) diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index a25e202..bf21d97 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -44,6 +44,8 @@ int iommu_detected __read_mostly = 0; * guests and not for driver dma translation. */ int iommu_pass_through __read_mostly; +int iommu_pt_force_bus = -1; +int iommu_pt_force_domain = -1; extern struct iommu_table_entry __iommu_table[], __iommu_table_end[]; @@ -146,6 +148,7 @@ void dma_generic_free_coherent(struct device *dev, size_t size, void *vaddr, */ static __init int iommu_setup(char *p) { + char *end; iommu_merge = 1; if (!p) @@ -192,6 +195,11 @@ static __init int iommu_setup(char *p) #endif if (!strncmp(p, pt, 2)) iommu_pass_through = 1; + if (!strncmp(p, pt_force=, 9)) { + iommu_pass_through = 1; + iommu_pt_force_domain = simple_strtol(p+9, end, 0); + iommu_pt_force_bus = simple_strtol(end+1, NULL, 0); + } gart_parse_options(p); diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index d1f5caa..49757f1 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -2705,6 +2705,47 @@ static int __init iommu_prepare_static_identity_mapping(int hw) return ret; } + /* We found some strange devices in HP c7000 and other platforms that +* can not be enumerated by OS, but they did DMA read/write without +* driver management, so we should create the pt mapping for these +* devices to avoid DMA errors. Add iommu=pt_force=segment:busnum to +* force to do pt context mapping in the bus number. +*/ + if (iommu_pt_force_bus = 0 iommu_pt_force_bus = 0) { + int found = 0; + + iommu = NULL; + for_each_active_iommu(iommu, drhd) { + if (iommu_pt_force_domain != drhd-segment) + continue; + + for_each_active_dev_scope(drhd-devices, drhd-devices_cnt, i, dev) { + if (!dev_is_pci(dev)) + continue; + + pdev = to_pci_dev(dev); + if (pdev-bus-number == iommu_pt_force_bus || + (pdev-subordinate + pdev-subordinate-number = iommu_pt_force_bus + pdev-subordinate-busn_res.end
Re: [PATCH] iommu/vt-d: Fix broken device issue when using iommu=pt
extern struct iommu_table_entry __iommu_table[], __iommu_table_end[]; @@ -146,6 +148,7 @@ void dma_generic_free_coherent(struct device *dev, size_t size, void *vaddr, */ static __init int iommu_setup(char *p) { +char *end; iommu_merge = 1; if (!p) @@ -192,6 +195,11 @@ static __init int iommu_setup(char *p) #endif if (!strncmp(p, pt, 2)) iommu_pass_through = 1; +if (!strncmp(p, pt_force=, 9)) { +iommu_pass_through = 1; +iommu_pt_force_domain = simple_strtol(p+9, end, 0); +iommu_pt_force_bus = simple_strtol(end+1, NULL, 0); Documentation/kernel-parameters.txt? Oh, I missed it, I will update it if other guys think the patch is the right fix to the issue later. +} gart_parse_options(p); diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index d1f5caa..49757f1 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -2705,6 +2705,47 @@ static int __init iommu_prepare_static_identity_mapping(int hw) return ret; } +/* We found some strange devices in HP c7000 and other platforms that + * can not be enumerated by OS, but they did DMA read/write without + * driver management, so we should create the pt mapping for these + * devices to avoid DMA errors. Add iommu=pt_force=segment:busnum to + * force to do pt context mapping in the bus number. + */ So best case with this patch is that the user needs to discover that this option exists, figure out the undocumented parameters, be running on VT-d, permanently add a kernel commandline option, and never have any intention of assigning the device to userspace or a VM... Hmmm, we can add some detection code in dmar fault process functions, and print some useful messages. Can't we handle this with the DMA alias quirks that are now in 3.17? Or can the vendor fix this with a firmware update? This device behavior is really quite broken for this kind of server class product. Thanks, Currently, I don't know how many devices have this issue. So I'm not sure the vendor fix is a proper way to fix it. Alex, sorry, I don't understand the firmware update to fix it? Do you mean updating the device EEPROM firmware ? Thanks! Yijing. Alex +if (iommu_pt_force_bus = 0 iommu_pt_force_bus = 0) { +int found = 0; + +iommu = NULL; +for_each_active_iommu(iommu, drhd) { +if (iommu_pt_force_domain != drhd-segment) +continue; + +for_each_active_dev_scope(drhd-devices, drhd-devices_cnt, i, dev) { +if (!dev_is_pci(dev)) +continue; + +pdev = to_pci_dev(dev); +if (pdev-bus-number == iommu_pt_force_bus || +(pdev-subordinate + pdev-subordinate-number = iommu_pt_force_bus + pdev-subordinate-busn_res.end = iommu_pt_force_bus)) { +found = 1; +break; +} +} + +if (drhd-include_all) { +found = 1; +break; +} +} + +if (found iommu) +for (i = 0; i 256; i++) +domain_context_mapping_one(si_domain, iommu, iommu_pt_force_bus, +i, hw ? CONTEXT_TT_PASS_THROUGH : +CONTEXT_TT_MULTI_LEVEL); +} + return 0; } . -- Thanks! Yijing ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH] iommu/vt-d: Fix broken device issue when using iommu=pt
On 2014/8/12 11:18, Jiang Liu wrote: On 2014/8/12 9:37, Yijing Wang wrote: On 2014/8/11 22:59, Linda Knippers wrote: On 8/11/2014 12:43 AM, Alex Williamson wrote: On Mon, 2014-08-11 at 10:54 +0800, Yijing Wang wrote: We found some strange devices in HP C7000 and Huawei Server. These devices can not be enumerated by OS, but they still did DMA read/write without OS management. Because iommu will not create the DMA mapping for these devices, the DMA read/write will be blocked by iommu hardware. Eg. \-[:00]-+-00.0 Intel Corporation Xeon E5/Core i7 DMI2 +-01.0-[11]-- +-01.1-[02]-- +-02.0-[04]--+-00.0 Emulex Corporation OneConnect 10Gb NIC (be3) |+-00.1 Emulex Corporation OneConnect 10Gb NIC (be3) |+-00.2 Emulex Corporation OneConnect 10Gb iSCSI Initiator (be3) |\-00.3 Emulex Corporation OneConnect 10Gb iSCSI Initiator (be3) +-02.1-[12]-- Kernel only found four devices in bus 0x04, but we found following DMA errors in dmesg. [ 1438.477262] DRHD: handling fault status reg 402 [ 1438.498278] DMAR:[DMA Write] Request device [04:00.4] fault addr bdf7 [ 1438.498280] DMAR:[fault reason 02] Present bit in context entry is clear [ 1438.566458] DMAR:[DMA Write] Request device [04:00.5] fault addr bdf7 [ 1438.566460] DMAR:[fault reason 02] Present bit in context entry is clear [ 1438.635211] DMAR:[DMA Write] Request device [04:00.6] fault addr bdf7 [ 1438.635213] DMAR:[fault reason 02] Present bit in context entry is clear [ 1438.703849] DMAR:[DMA Write] Request device [04:00.7] fault addr bdf7 [ 1438.703851] DMAR:[fault reason 02] Present bit in context entry is clear Signed-off-by: Yijing Wang wangyij...@huawei.com --- arch/x86/include/asm/iommu.h |2 ++ arch/x86/kernel/pci-dma.c|8 drivers/iommu/intel-iommu.c | 41 + 3 files changed, 51 insertions(+), 0 deletions(-) diff --git a/arch/x86/include/asm/iommu.h b/arch/x86/include/asm/iommu.h index 345c99c..5e3a2d8 100644 --- a/arch/x86/include/asm/iommu.h +++ b/arch/x86/include/asm/iommu.h @@ -5,6 +5,8 @@ extern struct dma_map_ops nommu_dma_ops; extern int force_iommu, no_iommu; extern int iommu_detected; extern int iommu_pass_through; +extern int iommu_pt_force_bus; +extern int iommu_pt_force_domain; /* 10 seconds */ #define DMAR_OPERATION_TIMEOUT ((cycles_t) tsc_khz*10*1000) diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index a25e202..bf21d97 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -44,6 +44,8 @@ int iommu_detected __read_mostly = 0; * guests and not for driver dma translation. */ int iommu_pass_through __read_mostly; +int iommu_pt_force_bus = -1; +int iommu_pt_force_domain = -1; extern struct iommu_table_entry __iommu_table[], __iommu_table_end[]; @@ -146,6 +148,7 @@ void dma_generic_free_coherent(struct device *dev, size_t size, void *vaddr, */ static __init int iommu_setup(char *p) { + char *end; iommu_merge = 1; if (!p) @@ -192,6 +195,11 @@ static __init int iommu_setup(char *p) #endif if (!strncmp(p, pt, 2)) iommu_pass_through = 1; + if (!strncmp(p, pt_force=, 9)) { + iommu_pass_through = 1; + iommu_pt_force_domain = simple_strtol(p+9, end, 0); + iommu_pt_force_bus = simple_strtol(end+1, NULL, 0); Documentation/kernel-parameters.txt? + } gart_parse_options(p); diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index d1f5caa..49757f1 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -2705,6 +2705,47 @@ static int __init iommu_prepare_static_identity_mapping(int hw) return ret; } + /* We found some strange devices in HP c7000 and other platforms that + * can not be enumerated by OS, but they did DMA read/write without + * driver management, so we should create the pt mapping for these + * devices to avoid DMA errors. Add iommu=pt_force=segment:busnum to + * force to do pt context mapping in the bus number. + */ So best case with this patch is that the user needs to discover that this option exists, figure out the undocumented parameters, be running on VT-d, permanently add a kernel commandline option, and never have any intention of assigning the device to userspace or a VM... Can't we handle this with the DMA alias quirks that are now in 3.17? Or can the vendor fix this with a firmware update? This device behavior is really quite broken for this kind of server class product. Yeah, something doesn't sound right here. I would like to hear more about this configuration, off list if you prefer. What servers? What firmware
[RFC PATCH 03/20] PCI/MSI: Remove useless bus-msi assignment
Currently, PCI drivers will initialize bus-msi in pcibios_add_bus(). pcibios_add_bus() will be called in every pci bus initialization. So the bus-msi assignment in pci_alloc_child_bus() is useless. Signed-off-by: Yijing Wang wangyij...@huawei.com CC: Thierry Reding thierry.red...@avionic-design.de CC: Thomas Petazzoni thomas.petazz...@free-electrons.com --- drivers/pci/probe.c |1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index e3cf8a2..8296576 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -677,7 +677,6 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent, child-parent = parent; child-ops = parent-ops; - child-msi = parent-msi; child-sysdata = parent-sysdata; child-bus_flags = parent-bus_flags; -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[RFC PATCH 05/20] MSI: Refactor struct msi_chip to become more common
Now there are a lot of __weak arch functions in MSI code. These functions make MSI driver complex, It's time to refactor it. Add .restore_irq(), .setup_irqs(), .teardown_irqs() to make msi_chip common across all platforms. Also replace the argument struct pci_dev with struct device to support future Non-PCI MSI device. Signed-off-by: Yijing Wang wangyij...@huawei.com CC: Thierry Reding thierry.red...@avionic-design.de CC: Thomas Petazzoni thomas.petazz...@free-electrons.com --- drivers/irqchip/irq-armada-370-xp.c |4 ++-- drivers/pci/host/pci-tegra.c|3 ++- drivers/pci/host/pcie-designware.c |4 ++-- drivers/pci/host/pcie-rcar.c|3 ++- drivers/pci/msi.c |4 ++-- include/linux/msi.h |7 +-- 6 files changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index ee1f0ba..3761e52 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -129,7 +129,7 @@ static void armada_370_xp_free_msi(int hwirq) mutex_unlock(msi_used_lock); } -static int armada_370_xp_setup_msi_irq(struct pci_dev *pdev, +static int armada_370_xp_setup_msi_irq(struct device *dev, struct msi_desc *desc) { struct msi_msg msg; @@ -164,7 +164,7 @@ static void armada_370_xp_teardown_msi_irq(unsigned int irq) armada_370_xp_free_msi(hwirq); } -static int armada_370_xp_check_msi_device(struct pci_dev *dev, +static int armada_370_xp_check_msi_device(struct device *dev, int nvec, int type) { /* We support MSI, but not MSI-X */ diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c index 3872bc0..a2fa0ec 100644 --- a/drivers/pci/host/pci-tegra.c +++ b/drivers/pci/host/pci-tegra.c @@ -1192,9 +1192,10 @@ static irqreturn_t tegra_pcie_msi_irq(int irq, void *data) return processed 0 ? IRQ_HANDLED : IRQ_NONE; } -static int tegra_msi_setup_irq(struct pci_dev *pdev, +static int tegra_msi_setup_irq(struct device *dev, struct msi_desc *desc) { + struct pci_dev *pdev = to_pci_dev(dev); struct msi_chip *chip = pdev-bus-msi; struct tegra_msi *msi = to_tegra_msi(chip); struct msi_msg msg; diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c index 2204456..9c3816d 100644 --- a/drivers/pci/host/pcie-designware.c +++ b/drivers/pci/host/pcie-designware.c @@ -342,12 +342,12 @@ static void clear_irq(unsigned int irq) msi-msi_attrib.multiple = 0; } -static int dw_msi_setup_irq(struct pci_dev *pdev, - struct msi_desc *desc) +static int dw_msi_setup_irq(struct device *dev, struct msi_desc *desc) { int irq, pos, msgvec; u16 msg_ctr; struct msi_msg msg; + struct pci_dev *pdev = to_pci_dev(dev); struct pcie_port *pp = sys_to_pcie(pdev-bus-sysdata); if (!pp) { diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c index 647bc9f..fa33432 100644 --- a/drivers/pci/host/pcie-rcar.c +++ b/drivers/pci/host/pcie-rcar.c @@ -615,9 +615,10 @@ static irqreturn_t rcar_pcie_msi_irq(int irq, void *data) return IRQ_HANDLED; } -static int rcar_msi_setup_irq(struct pci_dev *pdev, +static int rcar_msi_setup_irq(struct device *dev, struct msi_desc *desc) { + struct pci_dev *pdev = to_pci_dev(dev); struct msi_chip *chip = pdev-bus-msi; struct rcar_msi *msi = to_rcar_msi(chip); struct rcar_pcie *pcie = container_of(chip, struct rcar_pcie, msi.chip); diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 242d775..7b7abe9 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -37,7 +37,7 @@ int __weak arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) if (!chip || !chip-setup_irq) return -EINVAL; - err = chip-setup_irq(dev, desc); + err = chip-setup_irq(dev-dev, desc); if (err 0) return err; @@ -61,7 +61,7 @@ int __weak arch_msi_check_device(struct pci_dev *dev, int nvec, int type) if (!chip || !chip-check_device) return 0; - return chip-check_device(dev, nvec, type); + return chip-check_device(dev-dev, nvec, type); } int __weak arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) diff --git a/include/linux/msi.h b/include/linux/msi.h index a510d25..2068d25 100644 --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -72,9 +72,12 @@ struct msi_chip { struct device_node *of_node; struct list_head list; - int (*setup_irq)(struct pci_dev *dev, struct msi_desc *desc); + int (*check_device)(struct device *dev, int nvec, int type); + int (*setup_irq)(struct device *dev, struct msi_desc *desc); + int (*setup_irqs)(struct device *dev, int nvec, int type); void
[RFC PATCH 02/20] MSI: Clean up struct msi_chip argument
Msi_chip functions setup_irq/teardown_irq/check_device rarely use msi_chip argument. We can get msi_chip pointer from the device pointer or irq number, so clean up msi_chip arguments. This patch is also preparation for using msi_chip in all platforms to setup/teardown MSI irqs. Signed-off-by: Yijing Wang wangyij...@huawei.com CC: Thierry Reding thierry.red...@avionic-design.de CC: Thomas Petazzoni thomas.petazz...@free-electrons.com --- drivers/irqchip/irq-armada-370-xp.c | 12 +--- drivers/pci/host/pci-tegra.c|8 +--- drivers/pci/host/pcie-designware.c |4 ++-- drivers/pci/host/pcie-rcar.c|8 +--- drivers/pci/msi.c |6 +++--- include/linux/msi.h |8 +++- 6 files changed, 23 insertions(+), 23 deletions(-) diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index c887e6e..ee1f0ba 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -129,9 +129,8 @@ static void armada_370_xp_free_msi(int hwirq) mutex_unlock(msi_used_lock); } -static int armada_370_xp_setup_msi_irq(struct msi_chip *chip, - struct pci_dev *pdev, - struct msi_desc *desc) +static int armada_370_xp_setup_msi_irq(struct pci_dev *pdev, + struct msi_desc *desc) { struct msi_msg msg; int virq, hwirq; @@ -156,8 +155,7 @@ static int armada_370_xp_setup_msi_irq(struct msi_chip *chip, return 0; } -static void armada_370_xp_teardown_msi_irq(struct msi_chip *chip, - unsigned int irq) +static void armada_370_xp_teardown_msi_irq(unsigned int irq) { struct irq_data *d = irq_get_irq_data(irq); unsigned long hwirq = d-hwirq; @@ -166,8 +164,8 @@ static void armada_370_xp_teardown_msi_irq(struct msi_chip *chip, armada_370_xp_free_msi(hwirq); } -static int armada_370_xp_check_msi_device(struct msi_chip *chip, struct pci_dev *dev, - int nvec, int type) +static int armada_370_xp_check_msi_device(struct pci_dev *dev, + int nvec, int type) { /* We support MSI, but not MSI-X */ if (type == PCI_CAP_ID_MSI) diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c index 869a921..3872bc0 100644 --- a/drivers/pci/host/pci-tegra.c +++ b/drivers/pci/host/pci-tegra.c @@ -1192,9 +1192,10 @@ static irqreturn_t tegra_pcie_msi_irq(int irq, void *data) return processed 0 ? IRQ_HANDLED : IRQ_NONE; } -static int tegra_msi_setup_irq(struct msi_chip *chip, struct pci_dev *pdev, +static int tegra_msi_setup_irq(struct pci_dev *pdev, struct msi_desc *desc) { + struct msi_chip *chip = pdev-bus-msi; struct tegra_msi *msi = to_tegra_msi(chip); struct msi_msg msg; unsigned int irq; @@ -1220,10 +1221,11 @@ static int tegra_msi_setup_irq(struct msi_chip *chip, struct pci_dev *pdev, return 0; } -static void tegra_msi_teardown_irq(struct msi_chip *chip, unsigned int irq) +static void tegra_msi_teardown_irq(unsigned int irq) { - struct tegra_msi *msi = to_tegra_msi(chip); struct irq_data *d = irq_get_irq_data(irq); + struct msi_chip *chip = irq_get_chip_data(irq); + struct tegra_msi *msi = to_tegra_msi(chip); tegra_msi_free(msi, d-hwirq); } diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c index 52bd3a1..2204456 100644 --- a/drivers/pci/host/pcie-designware.c +++ b/drivers/pci/host/pcie-designware.c @@ -342,7 +342,7 @@ static void clear_irq(unsigned int irq) msi-msi_attrib.multiple = 0; } -static int dw_msi_setup_irq(struct msi_chip *chip, struct pci_dev *pdev, +static int dw_msi_setup_irq(struct pci_dev *pdev, struct msi_desc *desc) { int irq, pos, msgvec; @@ -384,7 +384,7 @@ static int dw_msi_setup_irq(struct msi_chip *chip, struct pci_dev *pdev, return 0; } -static void dw_msi_teardown_irq(struct msi_chip *chip, unsigned int irq) +static void dw_msi_teardown_irq(unsigned int irq) { clear_irq(irq); } diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c index 4884ee5..647bc9f 100644 --- a/drivers/pci/host/pcie-rcar.c +++ b/drivers/pci/host/pcie-rcar.c @@ -615,9 +615,10 @@ static irqreturn_t rcar_pcie_msi_irq(int irq, void *data) return IRQ_HANDLED; } -static int rcar_msi_setup_irq(struct msi_chip *chip, struct pci_dev *pdev, +static int rcar_msi_setup_irq(struct pci_dev *pdev, struct msi_desc *desc) { + struct msi_chip *chip = pdev-bus-msi; struct rcar_msi *msi = to_rcar_msi(chip); struct rcar_pcie *pcie = container_of(chip, struct rcar_pcie, msi.chip); struct msi_msg msg; @@ -645,10 +646,11 @@ static int rcar_msi_setup_irq(struct
[RFC PATCH 04/20] MSI: Remove the redundant irq_set_chip_data()
Currently, pcie-designware, pcie-rcar, pci-tegra drivers use irq chip_data to the msi_chip pointer. They already call irq_set_chip_data() in their own MSI irq map functions. So irq_set_chip_data() in arch_setup_msi_irq() is useless. Signed-off-by: Yijing Wang wangyij...@huawei.com --- drivers/pci/msi.c |2 -- 1 files changed, 0 insertions(+), 2 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 782b242..242d775 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -41,8 +41,6 @@ int __weak arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) if (err 0) return err; - irq_set_chip_data(desc-irq, chip); - return 0; } -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[RFC PATCH 16/20] arm/iop13xx/MSI: Use msi_chip instead of arch func to configure MSI/MSI-X
Introduce a new struct msi_chip iop13xx_msi_chip instead of weak arch functions to configure MSI/MSI-X. And associate the pci bus with msi_chip in pcibios_add_bus(). Signed-off-by: Yijing Wang wangyij...@huawei.com --- arch/arm/mach-iop13xx/include/mach/pci.h |2 ++ arch/arm/mach-iop13xx/iq81340mc.c|1 + arch/arm/mach-iop13xx/iq81340sc.c|1 + arch/arm/mach-iop13xx/msi.c | 14 -- arch/arm/mach-iop13xx/pci.c |6 ++ 5 files changed, 22 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-iop13xx/include/mach/pci.h b/arch/arm/mach-iop13xx/include/mach/pci.h index 59f42b5..7a073cb 100644 --- a/arch/arm/mach-iop13xx/include/mach/pci.h +++ b/arch/arm/mach-iop13xx/include/mach/pci.h @@ -10,6 +10,8 @@ struct pci_bus *iop13xx_scan_bus(int nr, struct pci_sys_data *); void iop13xx_atu_select(struct hw_pci *plat_pci); void iop13xx_pci_init(void); void iop13xx_map_pci_memory(void); +void iop13xx_add_bus(struct pci_bus *bus); +extern struct msi_chip iop13xx_msi_chip; #define IOP_PCI_STATUS_ERROR (PCI_STATUS_PARITY | \ PCI_STATUS_SIG_TARGET_ABORT | \ diff --git a/arch/arm/mach-iop13xx/iq81340mc.c b/arch/arm/mach-iop13xx/iq81340mc.c index 9cd07d3..19d47cb 100644 --- a/arch/arm/mach-iop13xx/iq81340mc.c +++ b/arch/arm/mach-iop13xx/iq81340mc.c @@ -59,6 +59,7 @@ static struct hw_pci iq81340mc_pci __initdata = { .map_irq= iq81340mc_pcix_map_irq, .scan = iop13xx_scan_bus, .preinit= iop13xx_pci_init, + .add_bus= iop13xx_add_bus; }; static int __init iq81340mc_pci_init(void) diff --git a/arch/arm/mach-iop13xx/iq81340sc.c b/arch/arm/mach-iop13xx/iq81340sc.c index b3ec11c..4d56993 100644 --- a/arch/arm/mach-iop13xx/iq81340sc.c +++ b/arch/arm/mach-iop13xx/iq81340sc.c @@ -61,6 +61,7 @@ static struct hw_pci iq81340sc_pci __initdata = { .scan = iop13xx_scan_bus, .map_irq= iq81340sc_atux_map_irq, .preinit= iop13xx_pci_init + .add_bus= iop13xx_add_bus; }; static int __init iq81340sc_pci_init(void) diff --git a/arch/arm/mach-iop13xx/msi.c b/arch/arm/mach-iop13xx/msi.c index e7730cf..59a9f8f 100644 --- a/arch/arm/mach-iop13xx/msi.c +++ b/arch/arm/mach-iop13xx/msi.c @@ -132,7 +132,7 @@ static struct irq_chip iop13xx_msi_chip = { .irq_unmask = unmask_msi_irq, }; -int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) +int iop13xx_setup_msi_irq(struct device *dev, struct msi_desc *desc) { int id, irq = irq_alloc_desc_from(IRQ_IOP13XX_MSI_0, -1); struct msi_msg msg; @@ -159,7 +159,17 @@ int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) return 0; } -void arch_teardown_msi_irq(unsigned int irq) +void iop13xx_teardown_msi_irq(unsigned int irq) { irq_free_desc(irq); } + +struct msi_chip iop13xx_chip = { + .setup_irq = iop13xx_setup_msi_irq, + .teardown_irq = iop13xx_teardown_msi_irq, +}; + +struct msi_chip *arch_get_match_msi_chip(struct device *dev) +{ + return iop13xx_chip; +} diff --git a/arch/arm/mach-iop13xx/pci.c b/arch/arm/mach-iop13xx/pci.c index 9082b84..f498800 100644 --- a/arch/arm/mach-iop13xx/pci.c +++ b/arch/arm/mach-iop13xx/pci.c @@ -962,6 +962,12 @@ void __init iop13xx_atu_select(struct hw_pci *plat_pci) } } +void iop13xx_add_bus(struct pci_bus *bus) +{ + if (IS_ENABLED(CONFIG_PCI_MSI)) + bus-msi = iop13xx_msi_chip; +} + void __init iop13xx_pci_init(void) { /* clear pre-existing south bridge errors */ -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[RFC PATCH 00/20] Use msi_chip to configure MSI/MSI-X in all platforms
This series is mainly to use msi_chip instead of currently weak arch functions across all platforms. Also clean up current MSI code and make drivers support MSI easier. Yijing Wang (20): x86/xen/MSI: Eliminate arch_msix_mask_irq() and arch_msi_mask_irq() MSI: Clean up struct msi_chip argument PCI/MSI: Remove useless bus-msi assignment MSI: Remove the redundant irq_set_chip_data() MSI: Refactor struct msi_chip to become more common PCI/MSI: Introduce arch_get_match_msi_chip() to find the match msi_chip x86/MSI: Use msi_chip instead of arch func to configure MSI/MSI-X x86/xen/MSI: Use msi_chip instead of arch func to configure MSI/MSI-X irq_remapping/MSI: Use msi_chip instead of arch func to configure MSI/MSI-X x86/MSI: Remove unused MSI weak arch functions MIPS/Octeon/MSI: Use msi_chip instead of arch func to configure MSI/MSI-X MIPS/Xlp/MSI: Use msi_chip instead of arch func to configure MSI/MSI-X MIPS/xlr/MSI: Use msi_chip instead of arch func to configure MSI/MSI-X Powerpc/MSI: Use msi_chip instead of arch func to configure MSI/MSI-X s390/MSI: Use msi_chip instead of arch func to configure MSI/MSI-X arm/iop13xx/MSI: Use msi_chip instead of arch func to configure MSI/MSI-X IA64/MSI: Use msi_chip instead of arch func to configure MSI/MSI-X Sparc/MSI: Use msi_chip instead of arch func to configure MSI/MSI-X tile/MSI: Use msi_chip instead of arch func to configure MSI/MSI-X PCI/MSI: Clean up unused MSI arch functions arch/arm/mach-iop13xx/include/mach/pci.h |2 + arch/arm/mach-iop13xx/iq81340mc.c|1 + arch/arm/mach-iop13xx/iq81340sc.c|1 + arch/arm/mach-iop13xx/msi.c | 14 +++- arch/arm/mach-iop13xx/pci.c |6 ++ arch/ia64/kernel/msi_ia64.c | 18 +++- arch/mips/pci/msi-octeon.c | 45 -- arch/mips/pci/msi-xlp.c | 15 +++- arch/mips/pci/pci-xlr.c | 19 +++- arch/powerpc/kernel/msi.c| 23 -- arch/s390/pci/pci.c | 16 +++- arch/sparc/kernel/pci.c | 18 +++- arch/tile/kernel/pci_gx.c| 20 +++- arch/x86/include/asm/pci.h |4 +- arch/x86/include/asm/x86_init.h |3 - arch/x86/kernel/apic/io_apic.c | 35 +++- arch/x86/kernel/x86_init.c | 34 --- arch/x86/pci/xen.c | 139 -- drivers/iommu/irq_remapping.c| 13 ++- drivers/irqchip/irq-armada-370-xp.c | 12 +-- drivers/pci/host/pci-tegra.c |9 ++- drivers/pci/host/pcie-designware.c |6 +- drivers/pci/host/pcie-rcar.c |9 ++- drivers/pci/msi.c| 118 -- drivers/pci/probe.c |1 - include/linux/msi.h | 13 ++-- 26 files changed, 338 insertions(+), 256 deletions(-) ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[RFC PATCH 18/20] Sparc/MSI: Use msi_chip instead of arch func to configure MSI/MSI-X
Introduce a new struct msi_chip sparc_msi_chip instead of weak arch functions to configure MSI/MSI-X. Signed-off-by: Yijing Wang wangyij...@huawei.com --- arch/sparc/kernel/pci.c | 18 ++ 1 files changed, 14 insertions(+), 4 deletions(-) diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c index 857ad77..9eabd22 100644 --- a/arch/sparc/kernel/pci.c +++ b/arch/sparc/kernel/pci.c @@ -839,18 +839,18 @@ int pci_domain_nr(struct pci_bus *pbus) EXPORT_SYMBOL(pci_domain_nr); #ifdef CONFIG_PCI_MSI -int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) +int sparc_setup_msi_irq(struct device *dev, struct msi_desc *desc) { - struct pci_pbm_info *pbm = pdev-dev.archdata.host_controller; + struct pci_pbm_info *pbm = dev-archdata.host_controller; unsigned int irq; if (!pbm-setup_msi_irq) return -EINVAL; - return pbm-setup_msi_irq(irq, pdev, desc); + return pbm-setup_msi_irq(irq, to_pci_dev(dev), desc); } -void arch_teardown_msi_irq(unsigned int irq) +void sparc_teardown_msi_irq(unsigned int irq) { struct msi_desc *entry = irq_get_msi_desc(irq); struct pci_dev *pdev = entry-dev; @@ -859,6 +859,16 @@ void arch_teardown_msi_irq(unsigned int irq) if (pbm-teardown_msi_irq) pbm-teardown_msi_irq(irq, pdev); } + +struct msi_chip sparc_msi_chip = { + .setup_irq = sparc_setup_msi_irq, + .teardown_irq = sparc_teardown_msi_irq, +}; + +struct msi_chip *arch_get_match_msi_chip(struct device *dev) +{ + return sparc_msi_chip; +} #endif /* !(CONFIG_PCI_MSI) */ static void ali_sound_dma_hack(struct pci_dev *pdev, int set_bit) -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[RFC PATCH 01/20] x86/xen/MSI: Eliminate arch_msix_mask_irq() and arch_msi_mask_irq()
Commit 0e4ccb150 added two __weak arch functions arch_msix_mask_irq() and arch_msi_mask_irq() to fix a bug found when running xen in x86. Introduced these two funcntions make MSI code complex. This patch reverted commit 0e4ccb150 and add #ifdef for x86 msi_chip to fix this bug for simplicity. Also this is preparation for using struct msi_chip instead of weak arch MSI functions in all platforms. Signed-off-by: Yijing Wang wangyij...@huawei.com CC: Konrad Rzeszutek Wilk konrad.w...@oracle.com --- arch/x86/include/asm/x86_init.h |3 --- arch/x86/kernel/apic/io_apic.c | 15 +++ arch/x86/kernel/x86_init.c | 10 -- arch/x86/pci/xen.c | 13 + drivers/pci/msi.c | 22 ++ include/linux/msi.h |2 -- 6 files changed, 22 insertions(+), 43 deletions(-) diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h index e45e4da..f58a9c7 100644 --- a/arch/x86/include/asm/x86_init.h +++ b/arch/x86/include/asm/x86_init.h @@ -172,7 +172,6 @@ struct x86_platform_ops { struct pci_dev; struct msi_msg; -struct msi_desc; struct x86_msi_ops { int (*setup_msi_irqs)(struct pci_dev *dev, int nvec, int type); @@ -183,8 +182,6 @@ struct x86_msi_ops { void (*teardown_msi_irqs)(struct pci_dev *dev); void (*restore_msi_irqs)(struct pci_dev *dev); int (*setup_hpet_msi)(unsigned int irq, unsigned int id); - u32 (*msi_mask_irq)(struct msi_desc *desc, u32 mask, u32 flag); - u32 (*msix_mask_irq)(struct msi_desc *desc, u32 flag); }; struct IO_APIC_route_entry; diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 81e08ef..2609dcd 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -3019,14 +3019,29 @@ msi_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force) return IRQ_SET_MASK_OK_NOCOPY; } +#ifdef CONFIG_XEN +static void nop_unmask_msi_irq(struct irq_data *data) +{ +} + +static void nop_mask_msi_irq(struct irq_data *data) +{ +} +#endif + /* * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices, * which implement the MSI or MSI-X Capability Structure. */ static struct irq_chip msi_chip = { .name = PCI-MSI, +#ifdef CONFIG_XEN + .irq_unmask = nop_unmask_msi_irq, + .irq_mask = nop_mask_msi_irq, +#else .irq_unmask = unmask_msi_irq, .irq_mask = mask_msi_irq, +#endif .irq_ack= ack_apic_edge, .irq_set_affinity = msi_set_affinity, .irq_retrigger = ioapic_retrigger_irq, diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c index e48b674..234b072 100644 --- a/arch/x86/kernel/x86_init.c +++ b/arch/x86/kernel/x86_init.c @@ -116,8 +116,6 @@ struct x86_msi_ops x86_msi = { .teardown_msi_irqs = default_teardown_msi_irqs, .restore_msi_irqs = default_restore_msi_irqs, .setup_hpet_msi = default_setup_hpet_msi, - .msi_mask_irq = default_msi_mask_irq, - .msix_mask_irq = default_msix_mask_irq, }; /* MSI arch specific hooks */ @@ -140,14 +138,6 @@ void arch_restore_msi_irqs(struct pci_dev *dev) { x86_msi.restore_msi_irqs(dev); } -u32 arch_msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag) -{ - return x86_msi.msi_mask_irq(desc, mask, flag); -} -u32 arch_msix_mask_irq(struct msi_desc *desc, u32 flag) -{ - return x86_msi.msix_mask_irq(desc, flag); -} #endif struct x86_io_apic_ops x86_io_apic_ops = { diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index 905956f..55c7858 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c @@ -393,14 +393,7 @@ static void xen_teardown_msi_irq(unsigned int irq) { xen_destroy_irq(irq); } -static u32 xen_nop_msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag) -{ - return 0; -} -static u32 xen_nop_msix_mask_irq(struct msi_desc *desc, u32 flag) -{ - return 0; -} + #endif int __init pci_xen_init(void) @@ -424,8 +417,6 @@ int __init pci_xen_init(void) x86_msi.setup_msi_irqs = xen_setup_msi_irqs; x86_msi.teardown_msi_irq = xen_teardown_msi_irq; x86_msi.teardown_msi_irqs = xen_teardown_msi_irqs; - x86_msi.msi_mask_irq = xen_nop_msi_mask_irq; - x86_msi.msix_mask_irq = xen_nop_msix_mask_irq; #endif return 0; } @@ -505,8 +496,6 @@ int __init pci_xen_initial_domain(void) x86_msi.setup_msi_irqs = xen_initdom_setup_msi_irqs; x86_msi.teardown_msi_irq = xen_teardown_msi_irq; x86_msi.restore_msi_irqs = xen_initdom_restore_msi_irqs; - x86_msi.msi_mask_irq = xen_nop_msi_mask_irq; - x86_msi.msix_mask_irq = xen_nop_msix_mask_irq; #endif xen_setup_acpi_sci(); __acpi_register_gsi = acpi_register_gsi_xen; diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index
[RFC PATCH 07/20] x86/MSI: Use msi_chip instead of arch func to configure MSI/MSI-X
Introduce a new struct msi_chip apic_msi_chip instead of weak arch functions to configure MSI/MSI-X in x86. Signed-off-by: Yijing Wang wangyij...@huawei.com --- arch/x86/include/asm/pci.h |1 + arch/x86/kernel/apic/io_apic.c | 20 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h index 0892ea0..878a06d 100644 --- a/arch/x86/include/asm/pci.h +++ b/arch/x86/include/asm/pci.h @@ -101,6 +101,7 @@ void native_teardown_msi_irq(unsigned int irq); void native_restore_msi_irqs(struct pci_dev *dev); int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, unsigned int irq_base, unsigned int irq_offset); +extern struct msi_chip *x86_msi_chip; #else #define native_setup_msi_irqs NULL #define native_teardown_msi_irqNULL diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 2609dcd..eb8ab7c 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -3077,24 +3077,25 @@ int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, return 0; } -int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) +int native_setup_msi_irqs(struct device *dev, int nvec, int type) { struct msi_desc *msidesc; unsigned int irq; int node, ret; + struct pci_dev *pdev = to_pci_dev(dev); /* Multiple MSI vectors only supported with interrupt remapping */ if (type == PCI_CAP_ID_MSI nvec 1) return 1; - node = dev_to_node(dev-dev); + node = dev_to_node(dev); - list_for_each_entry(msidesc, dev-msi_list, list) { + list_for_each_entry(msidesc, pdev-msi_list, list) { irq = irq_alloc_hwirq(node); if (!irq) return -ENOSPC; - ret = setup_msi_irq(dev, msidesc, irq, 0); + ret = setup_msi_irq(pdev, msidesc, irq, 0); if (ret 0) { irq_free_hwirq(irq); return ret; @@ -3214,6 +3215,17 @@ int default_setup_hpet_msi(unsigned int irq, unsigned int id) } #endif +struct msi_chip apic_msi_chip = { + .setup_irqs = native_setup_msi_irqs, + .teardown_irq = native_teardown_msi_irq, +}; + +struct msi_chip *arch_get_match_msi_chip(struct device *dev) +{ + return x86_msi_chip; +} + +struct msi_chip *x86_msi_chip = apic_msi_chip; #endif /* CONFIG_PCI_MSI */ /* * Hypertransport interrupt support -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[RFC PATCH 06/20] PCI/MSI: Introduce arch_get_match_msi_chip() to find the match msi_chip
Introduce __weak arch_get_match_msi_chip() to find the match msi_chip. We prepare to use struct msi_chip to eliminate arch_xxx functions in all platforms. The MSI device and the msi_chip binding is platform specific. For instance, in x86, LAPICs receive all MSI irq, but in arm, PCI device usually deliver their MSI to PCI hostbridge, if more than one msi_chip found in system, DTS file will report the binding between MSI devices and target msi_chip. So we need a platform implemented interface to do that. Signed-off-by: Yijing Wang wangyij...@huawei.com --- drivers/pci/msi.c | 30 ++ 1 files changed, 26 insertions(+), 4 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 7b7abe9..feba5dd 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -29,10 +29,22 @@ static int pci_msi_enable = 1; /* Arch hooks */ -int __weak arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) +struct msi_chip * __weak arch_get_match_msi_chip(struct device *dev) +{ + if (dev_is_pci(dev)) { + struct pci_dev *pdev = to_pci_dev(dev); + struct msi_chip *chip = pdev-bus-msi; + + return chip; + } + + return NULL; +} + +int __weak arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) { - struct msi_chip *chip = dev-bus-msi; int err; + struct msi_chip *chip = arch_get_match_msi_chip(dev-dev); if (!chip || !chip-setup_irq) return -EINVAL; @@ -46,7 +58,8 @@ int __weak arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) void __weak arch_teardown_msi_irq(unsigned int irq) { - struct msi_chip *chip = irq_get_chip_data(irq); + struct msi_desc *entry = irq_get_msi_desc(irq); + struct msi_chip *chip = arch_get_match_msi_chip(entry-dev-dev); if (!chip || !chip-teardown_irq) return; @@ -56,7 +69,7 @@ void __weak arch_teardown_msi_irq(unsigned int irq) int __weak arch_msi_check_device(struct pci_dev *dev, int nvec, int type) { - struct msi_chip *chip = dev-bus-msi; + struct msi_chip *chip = arch_get_match_msi_chip(dev-dev); if (!chip || !chip-check_device) return 0; @@ -68,7 +81,12 @@ int __weak arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) { struct msi_desc *entry; int ret; + struct msi_chip *chip; + chip = arch_get_match_msi_chip(dev-dev); + if (chip chip-setup_irqs) + return chip-setup_irqs(dev-dev, nvec, type); + /* * If an architecture wants to support multiple MSI, it needs to * override arch_setup_msi_irqs() @@ -133,6 +151,10 @@ static void default_restore_msi_irq(struct pci_dev *dev, int irq) void __weak arch_restore_msi_irqs(struct pci_dev *dev) { + struct msi_chip *chip = arch_get_msi_chip(dev-dev); + if (chip chip-restore_irqs) + return chip-restore_irqs(dev-dev); + return default_restore_msi_irqs(dev); } -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[RFC PATCH 17/20] IA64/MSI: Use msi_chip instead of arch func to configure MSI/MSI-X
Introduce a new struct msi_chip ia64_msi_chip instead of weak arch functions to configure MSI/MSI-X. Signed-off-by: Yijing Wang wangyij...@huawei.com --- arch/ia64/kernel/msi_ia64.c | 18 ++ 1 files changed, 14 insertions(+), 4 deletions(-) diff --git a/arch/ia64/kernel/msi_ia64.c b/arch/ia64/kernel/msi_ia64.c index c430f91..6e527c4 100644 --- a/arch/ia64/kernel/msi_ia64.c +++ b/arch/ia64/kernel/msi_ia64.c @@ -112,15 +112,15 @@ static struct irq_chip ia64_msi_chip = { }; -int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) +static int arch_ia64_setup_msi_irq(struct device *dev, struct msi_desc *desc) { if (platform_setup_msi_irq) - return platform_setup_msi_irq(pdev, desc); + return platform_setup_msi_irq(to_pci_dev(dev), desc); - return ia64_setup_msi_irq(pdev, desc); + return ia64_setup_msi_irq(to_pci_dev(dev), desc); } -void arch_teardown_msi_irq(unsigned int irq) +static void arch_ia64_teardown_msi_irq(unsigned int irq) { if (platform_teardown_msi_irq) return platform_teardown_msi_irq(irq); @@ -128,6 +128,16 @@ void arch_teardown_msi_irq(unsigned int irq) return ia64_teardown_msi_irq(irq); } +static struct msi_chip chip = { + .setup_irq = arch_ia64_setup_msi_irq, + .teardown_irq = arch_ia64_teardown_msi_irq, +}; + +struct msi_chip *arch_get_match_msi_chip(struct device *dev) +{ + return chip; +} + #ifdef CONFIG_INTEL_IOMMU #ifdef CONFIG_SMP static int dmar_msi_set_affinity(struct irq_data *data, -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[RFC PATCH 10/20] x86/MSI: Remove unused MSI weak arch functions
Now we can clean up MSI weak arch functions in x86. Signed-off-by: Yijing Wang wangyij...@huawei.com --- arch/x86/include/asm/pci.h |3 --- arch/x86/kernel/apic/io_apic.c |2 +- arch/x86/kernel/x86_init.c | 24 3 files changed, 1 insertions(+), 28 deletions(-) diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h index 878a06d..34f9676 100644 --- a/arch/x86/include/asm/pci.h +++ b/arch/x86/include/asm/pci.h @@ -96,14 +96,11 @@ extern void pci_iommu_alloc(void); #ifdef CONFIG_PCI_MSI /* implemented in arch/x86/kernel/apic/io_apic. */ struct msi_desc; -int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type); void native_teardown_msi_irq(unsigned int irq); -void native_restore_msi_irqs(struct pci_dev *dev); int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, unsigned int irq_base, unsigned int irq_offset); extern struct msi_chip *x86_msi_chip; #else -#define native_setup_msi_irqs NULL #define native_teardown_msi_irqNULL #endif diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index eb8ab7c..e3326d9 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -3077,7 +3077,7 @@ int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, return 0; } -int native_setup_msi_irqs(struct device *dev, int nvec, int type) +static int native_setup_msi_irqs(struct device *dev, int nvec, int type) { struct msi_desc *msidesc; unsigned int irq; diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c index 234b072..cc32568 100644 --- a/arch/x86/kernel/x86_init.c +++ b/arch/x86/kernel/x86_init.c @@ -110,34 +110,10 @@ EXPORT_SYMBOL_GPL(x86_platform); #if defined(CONFIG_PCI_MSI) struct x86_msi_ops x86_msi = { - .setup_msi_irqs = native_setup_msi_irqs, .compose_msi_msg= native_compose_msi_msg, - .teardown_msi_irq = native_teardown_msi_irq, - .teardown_msi_irqs = default_teardown_msi_irqs, - .restore_msi_irqs = default_restore_msi_irqs, .setup_hpet_msi = default_setup_hpet_msi, }; -/* MSI arch specific hooks */ -int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) -{ - return x86_msi.setup_msi_irqs(dev, nvec, type); -} - -void arch_teardown_msi_irqs(struct pci_dev *dev) -{ - x86_msi.teardown_msi_irqs(dev); -} - -void arch_teardown_msi_irq(unsigned int irq) -{ - x86_msi.teardown_msi_irq(irq); -} - -void arch_restore_msi_irqs(struct pci_dev *dev) -{ - x86_msi.restore_msi_irqs(dev); -} #endif struct x86_io_apic_ops x86_io_apic_ops = { -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[RFC PATCH 15/20] s390/MSI: Use msi_chip instead of arch func to configure MSI/MSI-X
Introduce a new struct msi_chip zpci_msi_chip instead of weak arch functions to configure MSI/MSI-X. Signed-off-by: Yijing Wang wangyij...@huawei.com --- arch/s390/pci/pci.c | 16 ++-- 1 files changed, 14 insertions(+), 2 deletions(-) diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index 9ddc51e..ee7b05c 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c @@ -398,8 +398,9 @@ static void zpci_irq_handler(struct airq_struct *airq) } } -int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) +int zpci_setup_msi_irqs(struct device *dev, int nvec, int type) { + struct pci_dev *pdev = to_pci_dev(dev); struct zpci_dev *zdev = get_zdev(pdev); unsigned int hwirq, msi_vecs; unsigned long aisb; @@ -474,8 +475,9 @@ out: return rc; } -void arch_teardown_msi_irqs(struct pci_dev *pdev) +void zpci_teardown_msi_irqs(struct device *dev) { + struct pci_dev *pdev = to_pci_dev(dev); struct zpci_dev *zdev = get_zdev(pdev); struct msi_desc *msi; int rc; @@ -501,6 +503,16 @@ void arch_teardown_msi_irqs(struct pci_dev *pdev) airq_iv_free_bit(zpci_aisb_iv, zdev-aisb); } +struct msi_chip zpci_msi_chip = { + .setup_irqs = zpci_setup_msi_irqs, + .teardown_irqs = zpci_teardown_msi_irqs, +}; + +struct msi_chip *arch_get_match_msi_chip(struct device *dev) +{ + return zpci_msi_chip; +} + static void zpci_map_resources(struct zpci_dev *zdev) { struct pci_dev *pdev = zdev-pdev; -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[RFC PATCH 12/20] MIPS/Xlp/MSI: Use msi_chip instead of arch func to configure MSI/MSI-X
Introduce a new struct msi_chip xlp_chip instead of weak arch functions to configure MSI/MSI-X. Signed-off-by: Yijing Wang wangyij...@huawei.com --- arch/mips/pci/msi-xlp.c | 15 +-- 1 files changed, 13 insertions(+), 2 deletions(-) diff --git a/arch/mips/pci/msi-xlp.c b/arch/mips/pci/msi-xlp.c index fa374fe..6c27346 100644 --- a/arch/mips/pci/msi-xlp.c +++ b/arch/mips/pci/msi-xlp.c @@ -245,7 +245,7 @@ static struct irq_chip xlp_msix_chip = { .irq_unmask = unmask_msi_irq, }; -void arch_teardown_msi_irq(unsigned int irq) +void xlp_teardown_msi_irq(unsigned int irq) { } @@ -452,11 +452,12 @@ static int xlp_setup_msix(uint64_t lnkbase, int node, int link, return 0; } -int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) +int xlp_setup_msi_irq(struct device *d, struct msi_desc *desc) { struct pci_dev *lnkdev; uint64_t lnkbase; int node, link, slot; + struct pci_dev *dev = to_pci_dev(d); lnkdev = xlp_get_pcie_link(dev); if (lnkdev == NULL) { @@ -474,6 +475,16 @@ int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) return xlp_setup_msi(lnkbase, node, link, desc); } +struct msi_chip xlp_chip = { + .setup_irq = xlp_setup_msi_irq, + .teardown_irq = xlp_teardown_msi_irq, +}; + +struct msi_chip *arch_get_match_msi_chip(struct device *dev) +{ + return xlp_chip; +} + void __init xlp_init_node_msi_irqs(int node, int link) { struct nlm_soc_info *nodep; -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[RFC PATCH 09/20] irq_remapping/MSI: Use msi_chip instead of arch func to configure MSI/MSI-X
Introduce a new struct msi_chip remap_msi_chip instead of weak arch functions to configure irq remapping MSI/MSI-X in x86. Signed-off-by: Yijing Wang wangyij...@huawei.com --- drivers/iommu/irq_remapping.c | 13 + 1 files changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c index 33c4395..f494b51 100644 --- a/drivers/iommu/irq_remapping.c +++ b/drivers/iommu/irq_remapping.c @@ -139,15 +139,20 @@ error: return ret; } -static int irq_remapping_setup_msi_irqs(struct pci_dev *dev, +static int irq_remapping_setup_msi_irqs(struct device *dev, int nvec, int type) { if (type == PCI_CAP_ID_MSI) - return do_setup_msi_irqs(dev, nvec); + return do_setup_msi_irqs(to_pci_dev(dev), nvec); else - return do_setup_msix_irqs(dev, nvec); + return do_setup_msix_irqs(to_pci_dev(dev), nvec); } +struct msi_chip remap_msi_chip = { + .setup_irqs = irq_remapping_setup_msi_irqs, + .teardown_irq = native_teardown_msi_irq, +}; + static void eoi_ioapic_pin_remapped(int apic, int pin, int vector) { /* @@ -165,9 +170,9 @@ static void __init irq_remapping_modify_x86_ops(void) x86_io_apic_ops.set_affinity= set_remapped_irq_affinity; x86_io_apic_ops.setup_entry = setup_ioapic_remapped_entry; x86_io_apic_ops.eoi_ioapic_pin = eoi_ioapic_pin_remapped; - x86_msi.setup_msi_irqs = irq_remapping_setup_msi_irqs; x86_msi.setup_hpet_msi = setup_hpet_msi_remapped; x86_msi.compose_msi_msg = compose_remapped_msi_msg; + x86_msi_chip = remap_msi_chip; } static __init int setup_nointremap(char *str) -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[RFC PATCH 13/20] MIPS/xlr/MSI: Use msi_chip instead of arch func to configure MSI/MSI-X
Introduce a new struct msi_chip xlr_msi_chip instead of weak arch functions to configure MSI/MSI-X. Signed-off-by: Yijing Wang wangyij...@huawei.com --- arch/mips/pci/pci-xlr.c | 19 +++ 1 files changed, 15 insertions(+), 4 deletions(-) diff --git a/arch/mips/pci/pci-xlr.c b/arch/mips/pci/pci-xlr.c index 0dde803..6eef164 100644 --- a/arch/mips/pci/pci-xlr.c +++ b/arch/mips/pci/pci-xlr.c @@ -214,11 +214,11 @@ static int get_irq_vector(const struct pci_dev *dev) } #ifdef CONFIG_PCI_MSI -void arch_teardown_msi_irq(unsigned int irq) +void xlr_teardown_msi_irq(unsigned int irq) { } -int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) +int xlr_setup_msi_irq(struct device *dev, struct msi_desc *desc) { struct msi_msg msg; struct pci_dev *lnk; @@ -233,7 +233,7 @@ int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) * Enable MSI on the XLS PCIe controller bridge which was disabled * at enumeration, the bridge MSI capability is at 0x50 */ - lnk = xls_get_pcie_link(dev); + lnk = xls_get_pcie_link(to_pci_dev(dev)); if (lnk == NULL) return 1; @@ -243,7 +243,7 @@ int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) pci_write_config_word(lnk, 0x50 + PCI_MSI_FLAGS, val); } - irq = get_irq_vector(dev); + irq = get_irq_vector(to_pci_dev(dev)); if (irq = 0) return 1; @@ -263,6 +263,17 @@ int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) write_msi_msg(irq, msg); return 0; } + +struct msi_chip xlr_msi_chip = { + .setup_irq = xlr_setup_msi_irq, + .teardown_irq = xlr_teardown_msi_irq, +}; + +struct msi_chip *arch_get_match_msi_chip(struct device *dev) +{ + return xlr_msi_chip; +} + #endif /* Extra ACK needed for XLR on chip PCI controller */ -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[RFC PATCH 14/20] Powerpc/MSI: Use msi_chip instead of arch func to configure MSI/MSI-X
Introduce a new struct msi_chip ppc_msi_chip instead of weak arch functions to configure MSI/MSI-X. Signed-off-by: Yijing Wang wangyij...@huawei.com --- arch/powerpc/kernel/msi.c | 23 +-- 1 files changed, 17 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/kernel/msi.c b/arch/powerpc/kernel/msi.c index 8bbc12d..170b02c 100644 --- a/arch/powerpc/kernel/msi.c +++ b/arch/powerpc/kernel/msi.c @@ -13,7 +13,7 @@ #include asm/machdep.h -int arch_msi_check_device(struct pci_dev* dev, int nvec, int type) +int ppc_msi_check_device(struct device *dev, int nvec, int type) { if (!ppc_md.setup_msi_irqs || !ppc_md.teardown_msi_irqs) { pr_debug(msi: Platform doesn't provide MSI callbacks.\n); @@ -26,18 +26,29 @@ int arch_msi_check_device(struct pci_dev* dev, int nvec, int type) if (ppc_md.msi_check_device) { pr_debug(msi: Using platform check routine.\n); - return ppc_md.msi_check_device(dev, nvec, type); + return ppc_md.msi_check_device(to_pci_dev(dev), nvec, type); } return 0; } -int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) +int ppc_setup_msi_irqs(struct device *dev, int nvec, int type) { - return ppc_md.setup_msi_irqs(dev, nvec, type); + return ppc_md.setup_msi_irqs(to_pci_dev(dev), nvec, type); } -void arch_teardown_msi_irqs(struct pci_dev *dev) +void ppc_teardown_msi_irqs(struct device *dev) { - ppc_md.teardown_msi_irqs(dev); + ppc_md.teardown_msi_irqs(to_pci_dev(dev)); +} + +struct msi_chip ppc_msi_chip = { + .setup_irqs = ppc_setup_msi_irqs, + .teardown_irqs = ppc_teardown_msi_irqs, + .check_device = ppc_msi_check_device, +}; + +struct msi_chip *arch_get_match_msi_chip(struct device *dev) +{ + return ppc_msi_chip; } -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[RFC PATCH 20/20] PCI/MSI: Clean up unused MSI arch functions
Now we use struct msi_chip in all platforms to configure MSI/MSI-X. We can clean up the unused arch functions. Signed-off-by: Yijing Wang wangyij...@huawei.com --- drivers/pci/msi.c | 82 1 files changed, 32 insertions(+), 50 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index feba5dd..2d2d4cd 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -41,33 +41,7 @@ struct msi_chip * __weak arch_get_match_msi_chip(struct device *dev) return NULL; } -int __weak arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) -{ - int err; - struct msi_chip *chip = arch_get_match_msi_chip(dev-dev); - - if (!chip || !chip-setup_irq) - return -EINVAL; - - err = chip-setup_irq(dev-dev, desc); - if (err 0) - return err; - - return 0; -} - -void __weak arch_teardown_msi_irq(unsigned int irq) -{ - struct msi_desc *entry = irq_get_msi_desc(irq); - struct msi_chip *chip = arch_get_match_msi_chip(entry-dev-dev); - - if (!chip || !chip-teardown_irq) - return; - - chip-teardown_irq(irq); -} - -int __weak arch_msi_check_device(struct pci_dev *dev, int nvec, int type) +static int msi_check_device(struct pci_dev *dev, int nvec, int type) { struct msi_chip *chip = arch_get_match_msi_chip(dev-dev); @@ -77,25 +51,31 @@ int __weak arch_msi_check_device(struct pci_dev *dev, int nvec, int type) return chip-check_device(dev-dev, nvec, type); } -int __weak arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) +static int setup_msi_irqs(struct pci_dev *dev, int nvec, int type) { struct msi_desc *entry; int ret; struct msi_chip *chip; chip = arch_get_match_msi_chip(dev-dev); - if (chip chip-setup_irqs) + if (!chip) + return -EINVAL; + + if (chip-setup_irqs) return chip-setup_irqs(dev-dev, nvec, type); /* * If an architecture wants to support multiple MSI, it needs to -* override arch_setup_msi_irqs() +* provide chip-setup_irqs() */ if (type == PCI_CAP_ID_MSI nvec 1) return 1; + if (!chip-setup_irq) + return -EINVAL; + list_for_each_entry(entry, dev-msi_list, list) { - ret = arch_setup_msi_irq(dev, entry); + ret = chip-setup_irq(dev-dev, entry); if (ret 0) return ret; if (ret 0) @@ -105,13 +85,20 @@ int __weak arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) return 0; } -/* - * We have a default implementation available as a separate non-weak - * function, as it is used by the Xen x86 PCI code - */ -void default_teardown_msi_irqs(struct pci_dev *dev) +static void teardown_msi_irqs(struct pci_dev *dev) { struct msi_desc *entry; + struct msi_chip *chip; + + chip = arch_get_match_msi_chip(dev-dev); + if (!chip) + return; + + if (chip-teardown_irqs) + return chip-teardown_irqs(dev-dev); + + if (!chip-teardown_irq) + return; list_for_each_entry(entry, dev-msi_list, list) { int i, nvec; @@ -122,15 +109,10 @@ void default_teardown_msi_irqs(struct pci_dev *dev) else nvec = 1 entry-msi_attrib.multiple; for (i = 0; i nvec; i++) - arch_teardown_msi_irq(entry-irq + i); + chip-teardown_irq(entry-irq + i); } } -void __weak arch_teardown_msi_irqs(struct pci_dev *dev) -{ - return default_teardown_msi_irqs(dev); -} - static void default_restore_msi_irq(struct pci_dev *dev, int irq) { struct msi_desc *entry; @@ -149,9 +131,9 @@ static void default_restore_msi_irq(struct pci_dev *dev, int irq) write_msi_msg(irq, entry-msg); } -void __weak arch_restore_msi_irqs(struct pci_dev *dev) +static void restore_msi_irqs(struct pci_dev *dev) { - struct msi_chip *chip = arch_get_msi_chip(dev-dev); + struct msi_chip *chip = arch_get_match_msi_chip(dev-dev); if (chip chip-restore_irqs) return chip-restore_irqs(dev-dev); @@ -386,7 +368,7 @@ static void free_msi_irqs(struct pci_dev *dev) BUG_ON(irq_has_action(entry-irq + i)); } - arch_teardown_msi_irqs(dev); + teardown_msi_irqs(dev); list_for_each_entry_safe(entry, tmp, dev-msi_list, list) { if (entry-msi_attrib.is_msix) { @@ -456,7 +438,7 @@ static void __pci_restore_msi_state(struct pci_dev *dev) pci_intx_for_msi(dev, 0); msi_set_enable(dev, 0); - arch_restore_msi_irqs(dev); + restore_msi_irqs(dev); pci_read_config_word(dev, dev-msi_cap + PCI_MSI_FLAGS, control); msi_mask_irq(entry, msi_mask
[RFC PATCH 08/20] x86/xen/MSI: Use msi_chip instead of arch func to configure MSI/MSI-X
Introduce a new struct msi_chip xen_msi_chip instead of weak arch functions to configure MSI/MSI-X. Signed-off-by: Yijing Wang wangyij...@huawei.com CC: Konrad Rzeszutek Wilk konrad.w...@oracle.com --- arch/x86/pci/xen.c | 128 +-- 1 files changed, 73 insertions(+), 55 deletions(-) diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index 55c7858..0c4ed47 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c @@ -156,11 +156,12 @@ static int acpi_register_gsi_xen(struct device *dev, u32 gsi, struct xen_pci_frontend_ops *xen_pci_frontend; EXPORT_SYMBOL_GPL(xen_pci_frontend); -static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) +static int xen_setup_msi_irqs(struct device *dev, int nvec, int type) { int irq, ret, i; struct msi_desc *msidesc; int *v; + struct pci_dev *pdev = to_pci_dev(dev); if (type == PCI_CAP_ID_MSI nvec 1) return 1; @@ -170,14 +171,14 @@ static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) return -ENOMEM; if (type == PCI_CAP_ID_MSIX) - ret = xen_pci_frontend_enable_msix(dev, v, nvec); + ret = xen_pci_frontend_enable_msix(pdev, v, nvec); else - ret = xen_pci_frontend_enable_msi(dev, v); + ret = xen_pci_frontend_enable_msi(pdev, v); if (ret) goto error; i = 0; - list_for_each_entry(msidesc, dev-msi_list, list) { - irq = xen_bind_pirq_msi_to_irq(dev, msidesc, v[i], + list_for_each_entry(msidesc, pdev-msi_list, list) { + irq = xen_bind_pirq_msi_to_irq(pdev, msidesc, v[i], (type == PCI_CAP_ID_MSI) ? nvec : 1, (type == PCI_CAP_ID_MSIX) ? pcifront-msi-x : @@ -193,7 +194,7 @@ static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) return 0; error: - dev_err(dev-dev, Xen PCI frontend has not registered MSI/MSI-X support!\n); + dev_err(dev, Xen PCI frontend has not registered MSI/MSI-X support!\n); free: kfree(v); return ret; @@ -218,47 +219,48 @@ static void xen_msi_compose_msg(struct pci_dev *pdev, unsigned int pirq, msg-data = XEN_PIRQ_MSI_DATA; } -static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) +static int xen_hvm_setup_msi_irqs(struct device *dev, int nvec, int type) { int irq, pirq; struct msi_desc *msidesc; struct msi_msg msg; + struct pci_dev *pdev = to_pci_dev(dev); if (type == PCI_CAP_ID_MSI nvec 1) return 1; - list_for_each_entry(msidesc, dev-msi_list, list) { + list_for_each_entry(msidesc, pdev-msi_list, list) { __read_msi_msg(msidesc, msg); pirq = MSI_ADDR_EXT_DEST_ID(msg.address_hi) | ((msg.address_lo MSI_ADDR_DEST_ID_SHIFT) 0xff); if (msg.data != XEN_PIRQ_MSI_DATA || xen_irq_from_pirq(pirq) 0) { - pirq = xen_allocate_pirq_msi(dev, msidesc); + pirq = xen_allocate_pirq_msi(pdev, msidesc); if (pirq 0) { irq = -ENODEV; goto error; } - xen_msi_compose_msg(dev, pirq, msg); + xen_msi_compose_msg(pdev, pirq, msg); __write_msi_msg(msidesc, msg); - dev_dbg(dev-dev, xen: msi bound to pirq=%d\n, pirq); + dev_dbg(dev, xen: msi bound to pirq=%d\n, pirq); } else { - dev_dbg(dev-dev, + dev_dbg(dev, xen: msi already bound to pirq=%d\n, pirq); } - irq = xen_bind_pirq_msi_to_irq(dev, msidesc, pirq, + irq = xen_bind_pirq_msi_to_irq(pdev, msidesc, pirq, (type == PCI_CAP_ID_MSI) ? nvec : 1, (type == PCI_CAP_ID_MSIX) ? msi-x : msi, DOMID_SELF); if (irq 0) goto error; - dev_dbg(dev-dev, + dev_dbg(dev, xen: msi -- pirq=%d -- irq=%d\n, pirq, irq); } return 0; error: - dev_err(dev-dev, + dev_err(dev, Xen PCI frontend has not registered MSI/MSI-X support!\n); return irq; } @@ -266,16 +268,17 @@ error: #ifdef CONFIG_XEN_DOM0 static bool __read_mostly pci_seg_supported = true; -static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) +static int
[RFC PATCH 11/20] MIPS/Octeon/MSI: Use msi_chip instead of arch func to configure MSI/MSI-X
Introduce a new struct msi_chip octeon_msi_chip instead of weak arch functions to configure MSI/MSI-X. Signed-off-by: Yijing Wang wangyij...@huawei.com --- arch/mips/pci/msi-octeon.c | 45 ++- 1 files changed, 19 insertions(+), 26 deletions(-) diff --git a/arch/mips/pci/msi-octeon.c b/arch/mips/pci/msi-octeon.c index ab0c5d1..8098066 100644 --- a/arch/mips/pci/msi-octeon.c +++ b/arch/mips/pci/msi-octeon.c @@ -57,7 +57,7 @@ static int msi_irq_size; * * Returns 0 on success. */ -int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) +int octeon_setup_msi_irq(struct device *dev, struct msi_desc *desc) { struct msi_msg msg; u16 control; @@ -73,7 +73,7 @@ int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) * wants. Most devices only want 1, which will give * configured_private_bits and request_private_bits equal 0. */ - pci_read_config_word(dev, desc-msi_attrib.pos + PCI_MSI_FLAGS, + pci_read_config_word(to_pci_dev(dev), desc-msi_attrib.pos + PCI_MSI_FLAGS, control); /* @@ -176,7 +176,7 @@ msi_irq_allocated: /* Update the number of IRQs the device has available to it */ control = ~PCI_MSI_FLAGS_QSIZE; control |= request_private_bits 4; - pci_write_config_word(dev, desc-msi_attrib.pos + PCI_MSI_FLAGS, + pci_write_config_word(to_pci_dev(dev), desc-msi_attrib.pos + PCI_MSI_FLAGS, control); irq_set_msi_desc(irq, desc); @@ -184,32 +184,14 @@ msi_irq_allocated: return 0; } -int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) +int octeon_check_msi_device(struct device *dev, int nvec, int type) { - struct msi_desc *entry; - int ret; - /* * MSI-X is not supported. */ if (type == PCI_CAP_ID_MSIX) return -EINVAL; - /* -* If an architecture wants to support multiple MSI, it needs to -* override arch_setup_msi_irqs() -*/ - if (type == PCI_CAP_ID_MSI nvec 1) - return 1; - - list_for_each_entry(entry, dev-msi_list, list) { - ret = arch_setup_msi_irq(dev, entry); - if (ret 0) - return ret; - if (ret 0) - return -ENOSPC; - } - return 0; } @@ -219,7 +201,7 @@ int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) * * @irq:The devices first irq number. There may be multple in sequence. */ -void arch_teardown_msi_irq(unsigned int irq) +void octeon_teardown_msi_irq(unsigned int irq) { int number_irqs; u64 bitmask; @@ -229,7 +211,7 @@ void arch_teardown_msi_irq(unsigned int irq) if ((irq OCTEON_IRQ_MSI_BIT0) || (irq msi_irq_size + OCTEON_IRQ_MSI_BIT0)) panic(arch_teardown_msi_irq: Attempted to teardown illegal - MSI interrupt (%d), irq); + MSI interrupt (%d), irq); irq -= OCTEON_IRQ_MSI_BIT0; index = irq / 64; @@ -242,7 +224,7 @@ void arch_teardown_msi_irq(unsigned int irq) */ number_irqs = 0; while ((irq0 + number_irqs 64) - (msi_multiple_irq_bitmask[index] + (msi_multiple_irq_bitmask[index] (1ull (irq0 + number_irqs number_irqs++; number_irqs++; @@ -252,7 +234,7 @@ void arch_teardown_msi_irq(unsigned int irq) bitmask = irq0; if ((msi_free_irq_bitmask[index] bitmask) != bitmask) panic(arch_teardown_msi_irq: Attempted to teardown MSI - interrupt (%d) not in use, irq); + interrupt (%d) not in use, irq); /* Checks are done, update the in use bitmask */ spin_lock(msi_free_irq_bitmask_lock); @@ -261,6 +243,17 @@ void arch_teardown_msi_irq(unsigned int irq) spin_unlock(msi_free_irq_bitmask_lock); } +struct msi_chip octeon_msi_chip = { + .setup_irq = octeon_setup_msi_irq, + .teardown_irq = octeon_teardown_msi_irq, + .check_device = octeon_check_msi_device, +}; + +struct msi_chip *arch_get_match_msi_chip(struct device *dev) +{ + return octeon_msi_chip; +} + static DEFINE_RAW_SPINLOCK(octeon_irq_msi_lock); static u64 msi_rcv_reg[4]; -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [Xen-devel] [RFC PATCH 01/20] x86/xen/MSI: Eliminate arch_msix_mask_irq() and arch_msi_mask_irq()
On 2014/8/12 17:09, David Vrabel wrote: On 12/08/14 08:25, Yijing Wang wrote: Commit 0e4ccb150 added two __weak arch functions arch_msix_mask_irq() and arch_msi_mask_irq() to fix a bug found when running xen in x86. Introduced these two funcntions make MSI code complex. This patch reverted commit 0e4ccb150 and add #ifdef for x86 msi_chip to fix this bug for simplicity. Also this is preparation for using struct msi_chip instead of weak arch MSI functions in all platforms. [...] static struct irq_chip msi_chip = { .name = PCI-MSI, +#ifdef CONFIG_XEN +.irq_unmask = nop_unmask_msi_irq, +.irq_mask = nop_mask_msi_irq, +#else .irq_unmask = unmask_msi_irq, .irq_mask = mask_msi_irq, +#endif No. CONFIG_XEN kernels can run on Xen and bare metal so this must be a runtime option. Hi David, that's my mistake, what about export struct irq_chip msi_chip, then change the msi_chip-irq_mask/irq_unmask() in xen init functions. Eg. diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index 19b0eba..bb6af00 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -43,6 +43,10 @@ static inline void generic_apic_probe(void) } #endif +#ifdef CONFIG_PCI_MSI +extern struct irq_chip msi_chip; +#endif + #ifdef CONFIG_X86_LOCAL_APIC [...] + +#ifdef CONFIG_PCI_MSI +void xen_nop_msi_mask(struct irq_data *data) { - return 0; } #endif @@ -424,8 +423,8 @@ int __init pci_xen_init(void) x86_msi.setup_msi_irqs = xen_setup_msi_irqs; x86_msi.teardown_msi_irq = xen_teardown_msi_irq; x86_msi.teardown_msi_irqs = xen_teardown_msi_irqs; - x86_msi.msi_mask_irq = xen_nop_msi_mask_irq; - x86_msi.msix_mask_irq = xen_nop_msix_mask_irq; + msi_chip.irq_mask = xen_nop_msi_mask; + msi_chip.irq_unmask = xen_nop_msi_mask; #endif return 0; } @@ -505,8 +504,8 @@ int __init pci_xen_initial_domain(void) x86_msi.setup_msi_irqs = xen_initdom_setup_msi_irqs; x86_msi.teardown_msi_irq = xen_teardown_msi_irq; x86_msi.restore_msi_irqs = xen_initdom_restore_msi_irqs; - x86_msi.msi_mask_irq = xen_nop_msi_mask_irq; - x86_msi.msix_mask_irq = xen_nop_msix_mask_irq; + msi_chip.irq_mask = xen_nop_msi_mask; + msi_chip.irq_unmask = xen_nop_msi_mask; #endif xen_setup_acpi_sci(); David . -- Thanks! Yijing ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH] iommu/vt-d: Add domain field for dmar fault message
Maybe there are the same bus:dev.fn in different domains, so add the domain field for dmar fault message to identify the exact source device. Signed-off-by: Yijing Wang wangyij...@huawei.com --- drivers/iommu/dmar.c |8 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index 8ed55b0..4f469c7 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -1466,17 +1466,17 @@ static int dmar_fault_do_one(struct intel_iommu *iommu, int type, reason = dmar_get_fault_reason(fault_reason, fault_type); if (fault_type == INTR_REMAP) - pr_err(INTR-REMAP: Request device [[%02x:%02x.%d] + pr_err(INTR-REMAP: Request device [[%04x:%02x:%02x.%d] fault index %llx\n - INTR-REMAP:[fault reason %02d] %s\n, + INTR-REMAP:[fault reason %02d] %s\n, iommu-segment, (source_id 8), PCI_SLOT(source_id 0xFF), PCI_FUNC(source_id 0xFF), addr 48, fault_reason, reason); else - pr_err(DMAR:[%s] Request device [%02x:%02x.%d] + pr_err(DMAR:[%s] Request device [%04x:%02x:%02x.%d] fault addr %llx \n DMAR:[fault reason %02d] %s\n, - (type ? DMA Read : DMA Write), + (type ? DMA Read : DMA Write), iommu-segment, (source_id 8), PCI_SLOT(source_id 0xFF), PCI_FUNC(source_id 0xFF), addr, fault_reason, reason); return 0; -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2] iommu/vt-d: Fix broken device issue when using iommu=pt
We found some strange devices in HP C7000 and Huawei Storage Server. These devices can not be enumerated by OS, but they still did DMA read/write without OS management. Because iommu will not create the DMA mapping for these devices, the DMA read/write will be blocked by iommu hardware. Eg. in HP C7000: \-[:00]-+-00.0 Intel Corporation Xeon E5/Core i7 DMI2 +-01.0-[11]-- +-01.1-[02]-- +-02.0-[04]--+-00.0 Emulex Corporation OneConnect 10Gb NIC (be3) |+-00.1 Emulex Corporation OneConnect 10Gb NIC (be3) |+-00.2 Emulex Corporation OneConnect 10Gb iSCSI Initiator (be3) |\-00.3 Emulex Corporation OneConnect 10Gb iSCSI Initiator (be3) +-02.1-[12]-- Kernel only found four devices in bus 0x04, but we found following DMA errors in dmesg. [ 1438.477262] DRHD: handling fault status reg 402 [ 1438.498278] DMAR:[DMA Write] Request device [04:00.4] fault addr bdf7 [ 1438.498280] DMAR:[fault reason 02] Present bit in context entry is clear [ 1438.566458] DMAR:[DMA Write] Request device [04:00.5] fault addr bdf7 [ 1438.566460] DMAR:[fault reason 02] Present bit in context entry is clear [ 1438.635211] DMAR:[DMA Write] Request device [04:00.6] fault addr bdf7 [ 1438.635213] DMAR:[fault reason 02] Present bit in context entry is clear [ 1438.703849] DMAR:[DMA Write] Request device [04:00.7] fault addr bdf7 [ 1438.703851] DMAR:[fault reason 02] Present bit in context entry is clear This patch add a kernel boot command parameter iommu=pt_force=domain:busnum that based iommu identity mapping and force to create identity for all devfn in the specific bus number to fix this issue. Signed-off-by: Yijing Wang wangyij...@huawei.com --- v1-v2: Documented to kernel-parameter, tested ok in the real broken platforms. --- Documentation/kernel-parameters.txt |2 + arch/x86/include/asm/iommu.h|2 + arch/x86/kernel/pci-dma.c |8 ++ drivers/iommu/intel-iommu.c | 42 +++ 4 files changed, 54 insertions(+), 0 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 5ae8608..d49a619 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1431,6 +1431,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted. forcesac soft pt [x86, IA-64] + pt_force=[domain:bus] [x86] Force to create identity mapping + for all devfn in specific pci bus. io7=[HW] IO7 for Marvel based alpha systems diff --git a/arch/x86/include/asm/iommu.h b/arch/x86/include/asm/iommu.h index 345c99c..5e3a2d8 100644 --- a/arch/x86/include/asm/iommu.h +++ b/arch/x86/include/asm/iommu.h @@ -5,6 +5,8 @@ extern struct dma_map_ops nommu_dma_ops; extern int force_iommu, no_iommu; extern int iommu_detected; extern int iommu_pass_through; +extern int iommu_pt_force_bus; +extern int iommu_pt_force_domain; /* 10 seconds */ #define DMAR_OPERATION_TIMEOUT ((cycles_t) tsc_khz*10*1000) diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index a25e202..bf21d97 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -44,6 +44,8 @@ int iommu_detected __read_mostly = 0; * guests and not for driver dma translation. */ int iommu_pass_through __read_mostly; +int iommu_pt_force_bus = -1; +int iommu_pt_force_domain = -1; extern struct iommu_table_entry __iommu_table[], __iommu_table_end[]; @@ -146,6 +148,7 @@ void dma_generic_free_coherent(struct device *dev, size_t size, void *vaddr, */ static __init int iommu_setup(char *p) { + char *end; iommu_merge = 1; if (!p) @@ -192,6 +195,11 @@ static __init int iommu_setup(char *p) #endif if (!strncmp(p, pt, 2)) iommu_pass_through = 1; + if (!strncmp(p, pt_force=, 9)) { + iommu_pass_through = 1; + iommu_pt_force_domain = simple_strtol(p+9, end, 0); + iommu_pt_force_bus = simple_strtol(end+1, NULL, 0); + } gart_parse_options(p); diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index d1f5caa..08eb5a0 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -2705,6 +2705,48 @@ static int __init iommu_prepare_static_identity_mapping(int hw) return ret; } + /* We found some strange devices in HP c7000 and other platforms, they +* can not be enumerated by OS, and they did DMA read/write without +* driver management. if we open iommu in these platforms, the DMA read/write +* will be blocked by IOMMU hardware
Re: [PATCH v2] iommu/vt-d: Fix broken device issue when using iommu=pt
+/* We found some strange devices in HP c7000 and other platforms, they + * can not be enumerated by OS, and they did DMA read/write without + * driver management. if we open iommu in these platforms, the DMA read/write + * will be blocked by IOMMU hardware. Currently, we only create identity mapping + * for the devices in OS. To fix this, add iommu=pt_force=segment:busnum to + * force to do identity mapping for the specific bus. + */ +if (iommu_pt_force_bus = 0 iommu_pt_force_bus = 0) { iommu_pt_force_bus twice? Sharp eyes! Sorry, it should be if (iommu_pt_force_domain = 0 iommu_pt_force_bus = 0). Thanks for your good catch! Thanks! Yijing. Thanks -Bharat +int found = 0; + +iommu = NULL; +for_each_active_iommu(iommu, drhd) { +if (iommu_pt_force_domain != drhd-segment) +continue; + +for_each_active_dev_scope(drhd-devices, drhd-devices_cnt, i, dev) { +if (!dev_is_pci(dev)) +continue; + +pdev = to_pci_dev(dev); +if (pdev-bus-number == iommu_pt_force_bus || +(pdev-subordinate + pdev-subordinate-number = iommu_pt_force_bus + pdev-subordinate-busn_res.end = iommu_pt_force_bus)) { +found = 1; +break; +} +} + +if (drhd-include_all) { +found = 1; +break; +} +} + +if (found iommu) +for (i = 0; i 256; i++) +domain_context_mapping_one(si_domain, iommu, iommu_pt_force_bus, +i, hw ? CONTEXT_TT_PASS_THROUGH : +CONTEXT_TT_MULTI_LEVEL); +} + return 0; } -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu . -- Thanks! Yijing ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v2] iommu/vt-d: Fix broken device issue when using iommu=pt
On 2014/8/25 20:11, Sathya Perla wrote: -Original Message- From: Yijing Wang [mailto:wangyij...@huawei.com] On 2014/8/25 17:32, Sathya Perla wrote: -Original Message- From: Joerg Roedel [mailto:j...@8bytes.org] [Adding the Emulex driver developers to Cc for some input on the device, and why it might use wrong request ids] On Mon, Aug 25, 2014 at 02:44:59PM +0800, Yijing Wang wrote: We found some strange devices in HP C7000 and Huawei Storage Server. These devices can not be enumerated by OS, but they still did DMA read/write without OS management. Because iommu will not create the DMA mapping for these devices, the DMA read/write will be blocked by iommu hardware. ... Eg. in HP C7000: \-[:00]-+-00.0 Intel Corporation Xeon E5/Core i7 DMI2 +-01.0-[11]-- +-01.1-[02]-- +-02.0-[04]--+-00.0 Emulex Corporation OneConnect 10Gb NIC (be3) |+-00.1 Emulex Corporation OneConnect 10Gb NIC (be3) |+-00.2 Emulex Corporation OneConnect 10Gb iSCSI Initiator (be3) |\-00.3 Emulex Corporation OneConnect 10Gb iSCSI Initiator (be3) +-02.1-[12]-- Kernel only found four devices in bus 0x04, but we found following DMA errors in dmesg. [ 1438.477262] DRHD: handling fault status reg 402 [ 1438.498278] DMAR:[DMA Write] Request device [04:00.4] fault addr bdf7 [ 1438.498280] DMAR:[fault reason 02] Present bit in context entry is clear [ 1438.566458] DMAR:[DMA Write] Request device [04:00.5] fault addr bdf7 [ 1438.566460] DMAR:[fault reason 02] Present bit in context entry is clear [ 1438.635211] DMAR:[DMA Write] Request device [04:00.6] fault addr bdf7 [ 1438.635213] DMAR:[fault reason 02] Present bit in context entry is clear [ 1438.703849] DMAR:[DMA Write] Request device [04:00.7] fault addr bdf7 [ 1438.703851] DMAR:[fault reason 02] Present bit in context entry is clear Hi Wang, from the kernel log I can see that the faulting address 0xbdf7 falls in the RMRR range the BIOS requested: [0.111343] DMAR: RMRR base: 0x00bdf6f000 end: 0x00bdf7efff An identity map is being setup for the visible functions, but not for the invisible functions: [2.695951] IOMMU: Setting identity map for device :04:00.0 [0xbdf6e000 - 0xbdf6efff] [2.698637] IOMMU: Setting identity map for device :04:00.1 [0xbdf6e000 - 0xbdf6efff] [2.702551] IOMMU: Setting identity map for device :04:00.2 [0xbdf6e000 - 0xbdf6efff] [2.705134] IOMMU: Setting identity map for device :04:00.3 [0xbdf6e000 - 0xbdf6efff] I'm going to follow-up with our FW folks as to why functions 04.00.4-7 are invisible but yet are trying to access the RMRR memory region. Could you also please send the me the FW version (output of ethtool -i eth0) Hi Sathya, thanks for your help. FW version is 4.6.247.5 driver version is 4.4.161.0s Thanks! Yijing. thanks, -Sathya . -- Thanks! Yijing ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v2] iommu/vt-d: Fix broken device issue when using iommu=pt
On 2014/8/25 23:04, David Woodhouse wrote: On Mon, 2014-08-25 at 12:11 +, Sathya Perla wrote: Hi Wang, from the kernel log I can see that the faulting address 0xbdf7 falls in the RMRR range the BIOS requested: [0.111343] DMAR: RMRR base: 0x00bdf6f000 end: 0x00bdf7efff We can't see which *devices* that RMRR was for. If we're asked for an RMRR mapping on a non-existing device, we should probably make sure we set that up. It's insane, but then most RMRR use is insane so what's new. Please could I see a copy of the DMAR table? Hi David, DMAR table is following, my another question is whether the dmar fault source device id 04:00.4 04:00.5 04:00.6 04:00.7 are the wrong request id of physical device 04:00.0 04:00.1 04:00.2 04:00.3. It seems not, I configured the eth4(04:00.1), and the network is good while lots dmar fault message in dmesg including(04:00.4/5/6/7). So I think eth4 used the correct dmar request id, if this is the case, where the invisible request id 04:00.4/5/6/7 from. #ifconfig eth4 Link encap:Ethernet HWaddr F0:92:1C:16:8D:4C inet addr:156.4.110.210 Bcast:156.4.110.255 Mask:255.255.255.0 inet6 addr: fe80::f292:1cff:fe16:8d4c/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:2922928 errors:0 dropped:13101 overruns:0 frame:0 TX packets:141409 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:187229544 (178.5 Mb) TX bytes:48629667 (46.3 Mb) loLink encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:98 errors:0 dropped:0 overruns:0 frame:0 TX packets:98 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:7300 (7.1 Kb) TX bytes:7300 (7.1 Kb) #ethtool -i eth4 driver: be2net version: 4.4.161.0s firmware-version: 4.6.247.5 bus-info: :04:00.1 supports-statistics: yes supports-test: yes supports-eeprom-access: yes supports-register-dump: yes /* * Intel ACPI Component Architecture * AML Disassembler version 20121220-64 * Copyright (c) 2000 - 2012 Intel Corporation * * Disassembly of dmar.dat, Tue Aug 26 03:05:06 2014 * * ACPI Data Table [DMAR] * * Format: [HexOffset DecimalOffset ByteLength] FieldName : FieldValue */ [000h 4]Signature : DMAR[DMA Remapping table] [004h 0004 4] Table Length : 060C [008h 0008 1] Revision : 01 [009h 0009 1] Checksum : 0D [00Ah 0010 6] Oem ID : HP [010h 0016 8] Oem Table ID : ProLiant [018h 0024 4] Oem Revision : 0001 [01Ch 0028 4] Asl Compiler ID : [020h 0032 4]Asl Compiler Revision : 162E [024h 0036 1] Host Address Width : 2D [025h 0037 1]Flags : 03 [030h 0048 2]Subtable Type : [Hardware Unit Definition] [032h 0050 2] Length : 00B0 [034h 0052 1]Flags : 00 [035h 0053 1] Reserved : 00 [036h 0054 2] PCI Segment Number : [038h 0056 8]Register Base Address : EFEFE000 [040h 0064 1] Device Scope Entry Type : 02 [041h 0065 1] Entry Length : 08 [042h 0066 2] Reserved : [044h 0068 1] Enumeration ID : 00 [045h 0069 1] PCI Bus Number : 20 [046h 0070 2] PCI Path : 00,00 [048h 0072 1] Device Scope Entry Type : 02 [049h 0073 1] Entry Length : 08 [04Ah 0074 2] Reserved : [04Ch 0076 1] Enumeration ID : 00 [04Dh 0077 1] PCI Bus Number : 20 [04Eh 0078 2] PCI Path : 01,00 [050h 0080 1] Device Scope Entry Type : 02 [051h 0081 1] Entry Length : 08 [052h 0082 2] Reserved : [054h 0084 1] Enumeration ID : 00 [055h 0085 1] PCI Bus Number : 20 [056h 0086 2] PCI Path : 01,01 [058h 0088 1] Device Scope Entry Type : 02 [059h 0089 1] Entry Length : 08 [05Ah 0090 2] Reserved : [05Ch 0092 1] Enumeration ID : 00 [05Dh 0093 1] PCI Bus Number : 20 [05Eh 0094 2] PCI Path : 02,00 [060h 0096 1] Device Scope Entry Type : 02 [061h 0097 1] Entry Length : 08 [062h 0098 2] Reserved : [064h 0100 1] Enumeration ID : 00 [065h 0101 1] PCI Bus Number : 20 [066h 0102 2] PCI Path : 02,01 [068h 0104 1] Device Scope Entry Type : 02 [069h 0105 1]
Re: [PATCH v2] iommu/vt-d: Fix broken device issue when using iommu=pt
On 2014/8/25 17:15, Joerg Roedel wrote: [Adding the Emulex driver developers to Cc for some input on the device, and why it might use wrong request ids] Thanks! On Mon, Aug 25, 2014 at 02:44:59PM +0800, Yijing Wang wrote: We found some strange devices in HP C7000 and Huawei Storage Server. These ... [ 1438.703851] DMAR:[fault reason 02] Present bit in context entry is clear This patch add a kernel boot command parameter iommu=pt_force=domain:busnum that based iommu identity mapping and force to create identity for all devfn in the specific bus number to fix this issue. No! If the device really uses request-ids it shouldn't use please add a DMA alias quirk instead. A new kernel parameter will not work out of the box for other users of this device. Hi Joerg, It seems not wrong request id of the physical device. Because I configured the eth4(pci id is 04:00.1), and the network is good, no problems found. If eth4(04:00.1) use the wrong request-id, I think network dma should be blocked by IOMMU, but it not. So I don't know where the request-id 04:00.4/5/6/7 come from. Maybe Sathya can help me to find that. :) \-[:00]-+-00.0 Intel Corporation Xeon E5/Core i7 DMI2 +-01.0-[11]-- +-01.1-[02]-- +-02.0-[04]--+-00.0 Emulex Corporation OneConnect 10Gb NIC (be3) |+-00.1 Emulex Corporation OneConnect 10Gb NIC (be3) |+-00.2 Emulex Corporation OneConnect 10Gb iSCSI Initiator (be3) |\-00.3 Emulex Corporation OneConnect 10Gb iSCSI Initiator (be3) Joerg . -- Thanks! Yijing ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v2] iommu/vt-d: Fix broken device issue when using iommu=pt
Could you also please send the me the FW version (output of ethtool -i eth0) Hi Sathya, thanks for your help. FW version is 4.6.247.5 driver version is 4.4.161.0s Hi Wang, this issue (a FW bug) was fixed in the 4.9 FW series. The HP qualified FW (ver 4.9.416.0) is available at http://h20565.www2.hp.com/portal/site/hpsc/template.PAGE/public/psi/swdDetails/?sp4ts.oid=4324790spf_p.tpst=swdMainspf_p.prp_swdMain=wsrp-navigationalState%3Didx%253D%257CswItem%253Dco_131997_1%257CswEnvOID%253D54%257CitemLocale%253D%257CswLang%253D%257Cmode%253D%257Caction%253DdriverDocumentjavax.portlet.begCacheTok=com.vignette.cachetokenjavax.portlet.endCacheTok=com.vignette.cachetoken Could you please upgrade your adapter FW and verify the issue. That's great! Thank you very much. I will notify my colleague to test it. Because this machine is not in my hand, so it may take some time. Thanks! Yijing. thanks, -Sathya . -- Thanks! Yijing ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v1 05/21] PCI/MSI: Introduce weak arch_find_msi_chip() to find MSI chip
Introduce weak arch_find_msi_chip() to find the match msi_chip. Currently, MSI chip associates pci bus to msi_chip. Because in ARM platform, there may be more than one MSI controller in system. Associate pci bus to msi_chip help pci device to find the match msi_chip and setup MSI/MSI-X irq correctly. But in other platform, like in x86. we only need one MSI chip, because all device use the same MSI address/data and irq etc. So it's no need to associate pci bus to MSI chip, just use a arch function, arch_find_msi_chip() to return the MSI chip for simplicity. The default weak arch_find_msi_chip() used in ARM platform, find the MSI chip by pci bus. Signed-off-by: Yijing Wang wangyij...@huawei.com --- drivers/pci/msi.c |7 ++- 1 files changed, 6 insertions(+), 1 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index a77e7f7..539c11d 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -29,9 +29,14 @@ static int pci_msi_enable = 1; /* Arch hooks */ +struct msi_chip * __weak arch_find_msi_chip(struct pci_dev *dev) +{ + return dev-bus-msi; +} + int __weak arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) { - struct msi_chip *chip = dev-bus-msi; + struct msi_chip *chip = arch_find_msi_chip(dev); int err; if (!chip || !chip-setup_irq) -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v1 03/21] MSI: Remove the redundant irq_set_chip_data()
Currently, pcie-designware, pcie-rcar, pci-tegra drivers use irq chip_data to save the msi_chip pointer. They already call irq_set_chip_data() in their own MSI irq map functions. So irq_set_chip_data() in arch_setup_msi_irq() is useless. Signed-off-by: Yijing Wang wangyij...@huawei.com --- drivers/pci/msi.c |2 -- 1 files changed, 0 insertions(+), 2 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index f6cb317..d547f7f 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -41,8 +41,6 @@ int __weak arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) if (err 0) return err; - irq_set_chip_data(desc-irq, chip); - return 0; } -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v1 10/21] x86/MSI: Remove unused MSI weak arch functions
Now we can clean up MSI weak arch functions in x86. Signed-off-by: Yijing Wang wangyij...@huawei.com --- arch/x86/include/asm/pci.h |3 --- arch/x86/include/asm/x86_init.h |4 arch/x86/kernel/apic/io_apic.c |2 +- arch/x86/kernel/x86_init.c | 24 drivers/iommu/irq_remapping.c |1 - 5 files changed, 1 insertions(+), 33 deletions(-) diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h index 878a06d..34f9676 100644 --- a/arch/x86/include/asm/pci.h +++ b/arch/x86/include/asm/pci.h @@ -96,14 +96,11 @@ extern void pci_iommu_alloc(void); #ifdef CONFIG_PCI_MSI /* implemented in arch/x86/kernel/apic/io_apic. */ struct msi_desc; -int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type); void native_teardown_msi_irq(unsigned int irq); -void native_restore_msi_irqs(struct pci_dev *dev); int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, unsigned int irq_base, unsigned int irq_offset); extern struct msi_chip *x86_msi_chip; #else -#define native_setup_msi_irqs NULL #define native_teardown_msi_irqNULL #endif diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h index f58a9c7..2514f67 100644 --- a/arch/x86/include/asm/x86_init.h +++ b/arch/x86/include/asm/x86_init.h @@ -174,13 +174,9 @@ struct pci_dev; struct msi_msg; struct x86_msi_ops { - int (*setup_msi_irqs)(struct pci_dev *dev, int nvec, int type); void (*compose_msi_msg)(struct pci_dev *dev, unsigned int irq, unsigned int dest, struct msi_msg *msg, u8 hpet_id); - void (*teardown_msi_irq)(unsigned int irq); - void (*teardown_msi_irqs)(struct pci_dev *dev); - void (*restore_msi_irqs)(struct pci_dev *dev); int (*setup_hpet_msi)(unsigned int irq, unsigned int id); }; diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 882b95e..f998192 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -3200,7 +3200,7 @@ int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, return 0; } -int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) +static int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) { struct msi_desc *msidesc; unsigned int irq; diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c index 234b072..cc32568 100644 --- a/arch/x86/kernel/x86_init.c +++ b/arch/x86/kernel/x86_init.c @@ -110,34 +110,10 @@ EXPORT_SYMBOL_GPL(x86_platform); #if defined(CONFIG_PCI_MSI) struct x86_msi_ops x86_msi = { - .setup_msi_irqs = native_setup_msi_irqs, .compose_msi_msg= native_compose_msi_msg, - .teardown_msi_irq = native_teardown_msi_irq, - .teardown_msi_irqs = default_teardown_msi_irqs, - .restore_msi_irqs = default_restore_msi_irqs, .setup_hpet_msi = default_setup_hpet_msi, }; -/* MSI arch specific hooks */ -int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) -{ - return x86_msi.setup_msi_irqs(dev, nvec, type); -} - -void arch_teardown_msi_irqs(struct pci_dev *dev) -{ - x86_msi.teardown_msi_irqs(dev); -} - -void arch_teardown_msi_irq(unsigned int irq) -{ - x86_msi.teardown_msi_irq(irq); -} - -void arch_restore_msi_irqs(struct pci_dev *dev) -{ - x86_msi.restore_msi_irqs(dev); -} #endif struct x86_io_apic_ops x86_io_apic_ops = { diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c index e75026e..99b1c0f 100644 --- a/drivers/iommu/irq_remapping.c +++ b/drivers/iommu/irq_remapping.c @@ -170,7 +170,6 @@ static void __init irq_remapping_modify_x86_ops(void) x86_io_apic_ops.set_affinity= set_remapped_irq_affinity; x86_io_apic_ops.setup_entry = setup_ioapic_remapped_entry; x86_io_apic_ops.eoi_ioapic_pin = eoi_ioapic_pin_remapped; - x86_msi.setup_msi_irqs = irq_remapping_setup_msi_irqs; x86_msi.setup_hpet_msi = setup_hpet_msi_remapped; x86_msi.compose_msi_msg = compose_remapped_msi_msg; x86_msi_chip = remap_msi_chip; -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v1 09/21] Irq_remapping/MSI: Use MSI chip framework to configure MSI/MSI-X irq
Use MSI chip framework instead of arch MSI functions to configure MSI/MSI-X irq. So we can manage MSI/MSI-X irq in a unified framework. Signed-off-by: Yijing Wang wangyij...@huawei.com --- drivers/iommu/irq_remapping.c |8 +++- 1 files changed, 7 insertions(+), 1 deletions(-) diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c index 33c4395..e75026e 100644 --- a/drivers/iommu/irq_remapping.c +++ b/drivers/iommu/irq_remapping.c @@ -148,6 +148,11 @@ static int irq_remapping_setup_msi_irqs(struct pci_dev *dev, return do_setup_msix_irqs(dev, nvec); } +static struct msi_chip remap_msi_chip = { + .setup_irqs = irq_remapping_setup_msi_irqs, + .teardown_irq = native_teardown_msi_irq, +}; + static void eoi_ioapic_pin_remapped(int apic, int pin, int vector) { /* @@ -165,9 +170,10 @@ static void __init irq_remapping_modify_x86_ops(void) x86_io_apic_ops.set_affinity= set_remapped_irq_affinity; x86_io_apic_ops.setup_entry = setup_ioapic_remapped_entry; x86_io_apic_ops.eoi_ioapic_pin = eoi_ioapic_pin_remapped; - x86_msi.setup_msi_irqs = irq_remapping_setup_msi_irqs; + x86_msi.setup_msi_irqs = irq_remapping_setup_msi_irqs; x86_msi.setup_hpet_msi = setup_hpet_msi_remapped; x86_msi.compose_msi_msg = compose_remapped_msi_msg; + x86_msi_chip = remap_msi_chip; } static __init int setup_nointremap(char *str) -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v1 08/21] x86/xen/MSI: Use MSI chip framework to configure MSI/MSI-X irq
Use MSI chip framework instead of arch MSI functions to configure MSI/MSI-X irq. So we can manage MSI/MSI-X irq in a unified framework. Signed-off-by: Yijing Wang wangyij...@huawei.com CC: Konrad Rzeszutek Wilk konrad.w...@oracle.com --- arch/x86/pci/xen.c | 46 ++ 1 files changed, 30 insertions(+), 16 deletions(-) diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index 84c2fce..e669ee4 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c @@ -376,6 +376,11 @@ static void xen_initdom_restore_msi_irqs(struct pci_dev *dev) } #endif +static void xen_teardown_msi_irq(unsigned int irq) +{ + xen_destroy_irq(irq); +} + static void xen_teardown_msi_irqs(struct pci_dev *dev) { struct msi_desc *msidesc; @@ -385,19 +390,26 @@ static void xen_teardown_msi_irqs(struct pci_dev *dev) xen_pci_frontend_disable_msix(dev); else xen_pci_frontend_disable_msi(dev); - - /* Free the IRQ's and the msidesc using the generic code. */ - default_teardown_msi_irqs(dev); -} - -static void xen_teardown_msi_irq(unsigned int irq) -{ - xen_destroy_irq(irq); + + list_for_each_entry(msidesc, dev-msi_list, list) { + int i, nvec; + if (msidesc-irq == 0) + continue; + if (msidesc-nvec_used) + nvec = msidesc-nvec_used; + else + nvec = 1 msidesc-msi_attrib.multiple; + for (i = 0; i nvec; i++) + xen_teardown_msi_irq(msidesc-irq + i); + } } void xen_nop_msi_mask(struct irq_data *data) { } + +struct msi_chip xen_msi_chip; + #endif int __init pci_xen_init(void) @@ -418,9 +430,9 @@ int __init pci_xen_init(void) #endif #ifdef CONFIG_PCI_MSI - x86_msi.setup_msi_irqs = xen_setup_msi_irqs; - x86_msi.teardown_msi_irq = xen_teardown_msi_irq; - x86_msi.teardown_msi_irqs = xen_teardown_msi_irqs; + xen_msi_chip.setup_irqs = xen_setup_msi_irqs; + xen_msi_chip.teardown_irqs = xen_teardown_msi_irqs; + x86_msi_chip = xen_msi_chip; msi_chip.irq_mask = xen_nop_msi_mask; msi_chip.irq_unmask = xen_nop_msi_mask; #endif @@ -441,8 +453,9 @@ int __init pci_xen_hvm_init(void) #endif #ifdef CONFIG_PCI_MSI - x86_msi.setup_msi_irqs = xen_hvm_setup_msi_irqs; - x86_msi.teardown_msi_irq = xen_teardown_msi_irq; + xen_msi_chip.setup_irqs = xen_hvm_setup_msi_irqs; + xen_msi_chip.teardown_irq = xen_teardown_msi_irq; + x86_msi_chip = xen_msi_chip; #endif return 0; } @@ -499,9 +512,10 @@ int __init pci_xen_initial_domain(void) int irq; #ifdef CONFIG_PCI_MSI - x86_msi.setup_msi_irqs = xen_initdom_setup_msi_irqs; - x86_msi.teardown_msi_irq = xen_teardown_msi_irq; - x86_msi.restore_msi_irqs = xen_initdom_restore_msi_irqs; + xen_msi_chip.setup_irqs = xen_initdom_setup_msi_irqs; + xen_msi_chip.teardown_irq = xen_teardown_msi_irq; + xen_msi_chip.restore_irqs = xen_initdom_restore_msi_irqs; + x86_msi_chip = xen_msi_chip; msi_chip.irq_mask = xen_nop_msi_mask; msi_chip.irq_unmask = xen_nop_msi_mask; #endif -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v1 17/21] arm/iop13xx/MSI: Use MSI chip framework to configure MSI/MSI-X irq
Use MSI chip framework instead of arch MSI functions to configure MSI/MSI-X irq. So we can manage MSI/MSI-X irq in a unified framework. Signed-off-by: Yijing Wang wangyij...@huawei.com --- arch/arm/mach-iop13xx/include/mach/pci.h |2 ++ arch/arm/mach-iop13xx/iq81340mc.c|1 + arch/arm/mach-iop13xx/iq81340sc.c|1 + arch/arm/mach-iop13xx/msi.c |9 +++-- arch/arm/mach-iop13xx/pci.c |6 ++ 5 files changed, 17 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-iop13xx/include/mach/pci.h b/arch/arm/mach-iop13xx/include/mach/pci.h index 59f42b5..7a073cb 100644 --- a/arch/arm/mach-iop13xx/include/mach/pci.h +++ b/arch/arm/mach-iop13xx/include/mach/pci.h @@ -10,6 +10,8 @@ struct pci_bus *iop13xx_scan_bus(int nr, struct pci_sys_data *); void iop13xx_atu_select(struct hw_pci *plat_pci); void iop13xx_pci_init(void); void iop13xx_map_pci_memory(void); +void iop13xx_add_bus(struct pci_bus *bus); +extern struct msi_chip iop13xx_msi_chip; #define IOP_PCI_STATUS_ERROR (PCI_STATUS_PARITY | \ PCI_STATUS_SIG_TARGET_ABORT | \ diff --git a/arch/arm/mach-iop13xx/iq81340mc.c b/arch/arm/mach-iop13xx/iq81340mc.c index 9cd07d3..19d47cb 100644 --- a/arch/arm/mach-iop13xx/iq81340mc.c +++ b/arch/arm/mach-iop13xx/iq81340mc.c @@ -59,6 +59,7 @@ static struct hw_pci iq81340mc_pci __initdata = { .map_irq= iq81340mc_pcix_map_irq, .scan = iop13xx_scan_bus, .preinit= iop13xx_pci_init, + .add_bus= iop13xx_add_bus; }; static int __init iq81340mc_pci_init(void) diff --git a/arch/arm/mach-iop13xx/iq81340sc.c b/arch/arm/mach-iop13xx/iq81340sc.c index b3ec11c..4d56993 100644 --- a/arch/arm/mach-iop13xx/iq81340sc.c +++ b/arch/arm/mach-iop13xx/iq81340sc.c @@ -61,6 +61,7 @@ static struct hw_pci iq81340sc_pci __initdata = { .scan = iop13xx_scan_bus, .map_irq= iq81340sc_atux_map_irq, .preinit= iop13xx_pci_init + .add_bus= iop13xx_add_bus; }; static int __init iq81340sc_pci_init(void) diff --git a/arch/arm/mach-iop13xx/msi.c b/arch/arm/mach-iop13xx/msi.c index e7730cf..1a8cb2f 100644 --- a/arch/arm/mach-iop13xx/msi.c +++ b/arch/arm/mach-iop13xx/msi.c @@ -132,7 +132,7 @@ static struct irq_chip iop13xx_msi_chip = { .irq_unmask = unmask_msi_irq, }; -int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) +static int iop13xx_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) { int id, irq = irq_alloc_desc_from(IRQ_IOP13XX_MSI_0, -1); struct msi_msg msg; @@ -159,7 +159,12 @@ int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) return 0; } -void arch_teardown_msi_irq(unsigned int irq) +static void iop13xx_teardown_msi_irq(unsigned int irq) { irq_free_desc(irq); } + +struct msi_chip iop13xx_chip = { + .setup_irq = iop13xx_setup_msi_irq, + .teardown_irq = iop13xx_teardown_msi_irq, +}; diff --git a/arch/arm/mach-iop13xx/pci.c b/arch/arm/mach-iop13xx/pci.c index 9082b84..f498800 100644 --- a/arch/arm/mach-iop13xx/pci.c +++ b/arch/arm/mach-iop13xx/pci.c @@ -962,6 +962,12 @@ void __init iop13xx_atu_select(struct hw_pci *plat_pci) } } +void iop13xx_add_bus(struct pci_bus *bus) +{ + if (IS_ENABLED(CONFIG_PCI_MSI)) + bus-msi = iop13xx_msi_chip; +} + void __init iop13xx_pci_init(void) { /* clear pre-existing south bridge errors */ -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v1 16/21] s390/MSI: Use MSI chip framework to configure MSI/MSI-X irq
Use MSI chip framework instead of arch MSI functions to configure MSI/MSI-X irq. So we can manage MSI/MSI-X irq in a unified framework. Signed-off-by: Yijing Wang wangyij...@huawei.com --- arch/s390/pci/pci.c | 18 ++ 1 files changed, 14 insertions(+), 4 deletions(-) diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index 2fa7b14..da5316e 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c @@ -358,7 +358,7 @@ static void zpci_irq_handler(struct airq_struct *airq) } } -int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) +int zpci_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) { struct zpci_dev *zdev = get_zdev(pdev); unsigned int hwirq, msi_vecs; @@ -434,7 +434,7 @@ out: return rc; } -void arch_teardown_msi_irqs(struct pci_dev *pdev) +static void zpci_teardown_msi_irqs(struct pci_dev *pdev) { struct zpci_dev *zdev = get_zdev(pdev); struct msi_desc *msi; @@ -448,9 +448,9 @@ void arch_teardown_msi_irqs(struct pci_dev *pdev) /* Release MSI interrupts */ list_for_each_entry(msi, pdev-msi_list, list) { if (msi-msi_attrib.is_msix) - default_msix_mask_irq(msi, 1); + __msix_mask_irq(msi, 1); else - default_msi_mask_irq(msi, 1, 1); + __msi_mask_irq(msi, 1, 1); irq_set_msi_desc(msi-irq, NULL); irq_free_desc(msi-irq); msi-msg.address_lo = 0; @@ -464,6 +464,16 @@ void arch_teardown_msi_irqs(struct pci_dev *pdev) airq_iv_free_bit(zpci_aisb_iv, zdev-aisb); } +static struct msi_chip zpci_msi_chip = { + .setup_irqs = zpci_setup_msi_irqs, + .teardown_irqs = zpci_teardown_msi_irqs, +}; + +struct msi_chip *arch_find_msi_chip(struct pci_dev *dev) +{ + return zpci_msi_chip; +} + static void zpci_map_resources(struct zpci_dev *zdev) { struct pci_dev *pdev = zdev-pdev; -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v1 13/21] MIPS/Xlp/MSI: Use MSI chip framework to configure MSI/MSI-X irq
Use MSI chip framework instead of arch MSI functions to configure MSI/MSI-X irq. So we can manage MSI/MSI-X irq in a unified framework. Signed-off-by: Yijing Wang wangyij...@huawei.com --- arch/mips/pci/msi-xlp.c | 14 -- 1 files changed, 12 insertions(+), 2 deletions(-) diff --git a/arch/mips/pci/msi-xlp.c b/arch/mips/pci/msi-xlp.c index e469dc7..6b791ef 100644 --- a/arch/mips/pci/msi-xlp.c +++ b/arch/mips/pci/msi-xlp.c @@ -245,7 +245,7 @@ static struct irq_chip xlp_msix_chip = { .irq_unmask = unmask_msi_irq, }; -void arch_teardown_msi_irq(unsigned int irq) +void xlp_teardown_msi_irq(unsigned int irq) { } @@ -450,7 +450,7 @@ static int xlp_setup_msix(uint64_t lnkbase, int node, int link, return 0; } -int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) +static int xlp_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) { struct pci_dev *lnkdev; uint64_t lnkbase; @@ -472,6 +472,16 @@ int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) return xlp_setup_msi(lnkbase, node, link, desc); } +static struct msi_chip xlp_chip = { + .setup_irq = xlp_setup_msi_irq, + .teardown_irq = xlp_teardown_msi_irq, +}; + +struct msi_chip *arch_find_msi_chip(struct pci_dev *dev) +{ + return xlp_chip; +} + void __init xlp_init_node_msi_irqs(int node, int link) { struct nlm_soc_info *nodep; -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v1 19/21] Sparc/MSI: Use MSI chip framework to configure MSI/MSI-X irq
Use MSI chip framework instead of arch MSI functions to configure MSI/MSI-X irq. So we can manage MSI/MSI-X irq in a unified framework. Signed-off-by: Yijing Wang wangyij...@huawei.com --- arch/sparc/kernel/pci.c | 14 -- 1 files changed, 12 insertions(+), 2 deletions(-) diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c index b36365f..2a89ee2 100644 --- a/arch/sparc/kernel/pci.c +++ b/arch/sparc/kernel/pci.c @@ -905,7 +905,7 @@ int pci_domain_nr(struct pci_bus *pbus) EXPORT_SYMBOL(pci_domain_nr); #ifdef CONFIG_PCI_MSI -int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) +int sparc_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) { struct pci_pbm_info *pbm = pdev-dev.archdata.host_controller; unsigned int irq; @@ -916,7 +916,7 @@ int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) return pbm-setup_msi_irq(irq, pdev, desc); } -void arch_teardown_msi_irq(unsigned int irq) +void sparc_teardown_msi_irq(unsigned int irq) { struct msi_desc *entry = irq_get_msi_desc(irq); struct pci_dev *pdev = entry-dev; @@ -925,6 +925,16 @@ void arch_teardown_msi_irq(unsigned int irq) if (pbm-teardown_msi_irq) pbm-teardown_msi_irq(irq, pdev); } + +static struct msi_chip sparc_msi_chip = { + .setup_irq = sparc_setup_msi_irq, + .teardown_irq = sparc_teardown_msi_irq, +}; + +struct msi_chip *arch_find_msi_chip(struct pci_dev *dev) +{ + return sparc_msi_chip; +} #endif /* !(CONFIG_PCI_MSI) */ static void ali_sound_dma_hack(struct pci_dev *pdev, int set_bit) -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v1 15/21] Powerpc/MSI: Use MSI chip framework to configure MSI/MSI-X irq
Use MSI chip framework instead of arch MSI functions to configure MSI/MSI-X irq. So we can manage MSI/MSI-X irq in a unified framework. Signed-off-by: Yijing Wang wangyij...@huawei.com --- arch/powerpc/kernel/msi.c | 14 -- 1 files changed, 12 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/kernel/msi.c b/arch/powerpc/kernel/msi.c index 71bd161..01781a4 100644 --- a/arch/powerpc/kernel/msi.c +++ b/arch/powerpc/kernel/msi.c @@ -13,7 +13,7 @@ #include asm/machdep.h -int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) +static int ppc_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) { if (!ppc_md.setup_msi_irqs || !ppc_md.teardown_msi_irqs) { pr_debug(msi: Platform doesn't provide MSI callbacks.\n); @@ -27,7 +27,17 @@ int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) return ppc_md.setup_msi_irqs(dev, nvec, type); } -void arch_teardown_msi_irqs(struct pci_dev *dev) +static void ppc_teardown_msi_irqs(struct pci_dev *dev) { ppc_md.teardown_msi_irqs(dev); } + +static struct msi_chip ppc_msi_chip = { + .setup_irqs = ppc_setup_msi_irqs, + .teardown_irqs = ppc_teardown_msi_irqs, +}; + +struct msi_chip *arch_find_msi_chip(struct pci_dev *dev) +{ + return ppc_msi_chip; +} -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v1 20/21] tile/MSI: Use MSI chip framework to configure MSI/MSI-X irq
Use MSI chip framework instead of arch MSI functions to configure MSI/MSI-X irq. So we can manage MSI/MSI-X irq in a unified framework. Signed-off-by: Yijing Wang wangyij...@huawei.com --- arch/tile/kernel/pci_gx.c | 14 -- 1 files changed, 12 insertions(+), 2 deletions(-) diff --git a/arch/tile/kernel/pci_gx.c b/arch/tile/kernel/pci_gx.c index e39f9c5..4912b75 100644 --- a/arch/tile/kernel/pci_gx.c +++ b/arch/tile/kernel/pci_gx.c @@ -1485,7 +1485,7 @@ static struct irq_chip tilegx_msi_chip = { /* TBD: support set_affinity. */ }; -int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) +static int tile_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) { struct pci_controller *controller; gxio_trio_context_t *trio_context; @@ -1604,7 +1604,17 @@ is_64_failure: return ret; } -void arch_teardown_msi_irq(unsigned int irq) +void tile_teardown_msi_irq(unsigned int irq) { irq_free_hwirq(irq); } + +static struct msi_chip tile_msi_chip = { + .setup_irq = tile_setup_msi_irq, + .teardown_irq = tile_teardown_msi_irq, +}; + +struct msi_chip *arch_find_msi_chip(struct pci_dev *dev) +{ + return tile_msi_chip; +} -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v1 21/21] PCI/MSI: Clean up unused MSI arch functions
Now we use struct msi_chip in all platforms to configure MSI/MSI-X. We can clean up the unused arch functions. Signed-off-by: Yijing Wang wangyij...@huawei.com --- drivers/iommu/irq_remapping.c |2 +- drivers/pci/msi.c | 99 - include/linux/msi.h | 14 -- 3 files changed, 39 insertions(+), 76 deletions(-) diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c index 99b1c0f..6e645f0 100644 --- a/drivers/iommu/irq_remapping.c +++ b/drivers/iommu/irq_remapping.c @@ -92,7 +92,7 @@ error: /* * Restore altered MSI descriptor fields and prevent just destroyed -* IRQs from tearing down again in default_teardown_msi_irqs() +* IRQs from tearing down again in teardown_msi_irqs() */ msidesc-irq = 0; msidesc-nvec_used = 0; diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index d78d637..e3e7f4f 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -34,50 +34,31 @@ struct msi_chip * __weak arch_find_msi_chip(struct pci_dev *dev) return dev-bus-msi; } -int __weak arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) -{ - struct msi_chip *chip = arch_find_msi_chip(dev); - int err; - - if (!chip || !chip-setup_irq) - return -EINVAL; - - err = chip-setup_irq(dev, desc); - if (err 0) - return err; - - return 0; -} - -void __weak arch_teardown_msi_irq(unsigned int irq) -{ - struct msi_chip *chip = irq_get_chip_data(irq); - - if (!chip || !chip-teardown_irq) - return; - - chip-teardown_irq(irq); -} - -int __weak arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) +int setup_msi_irqs(struct pci_dev *dev, int nvec, int type) { struct msi_desc *entry; int ret; struct msi_chip *chip; chip = arch_find_msi_chip(dev); - if (chip chip-setup_irqs) + if (!chip) + return -EINVAL; + + if (chip-setup_irqs) return chip-setup_irqs(dev, nvec, type); /* * If an architecture wants to support multiple MSI, it needs to -* override arch_setup_msi_irqs() +* implement chip-setup_irqs(). */ if (type == PCI_CAP_ID_MSI nvec 1) return 1; + if (!chip-setup_irq) + return -EINVAL; + list_for_each_entry(entry, dev-msi_list, list) { - ret = arch_setup_msi_irq(dev, entry); + ret = chip-setup_irq(dev, entry); if (ret 0) return ret; if (ret 0) @@ -87,13 +68,20 @@ int __weak arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) return 0; } -/* - * We have a default implementation available as a separate non-weak - * function, as it is used by the Xen x86 PCI code - */ -void default_teardown_msi_irqs(struct pci_dev *dev) +static void teardown_msi_irqs(struct pci_dev *dev) { struct msi_desc *entry; + struct msi_chip *chip; + + chip = arch_find_msi_chip(dev); + if (!chip) + return; + + if (chip-teardown_irqs) + return chip-teardown_irqs(dev); + + if (!chip-teardown_irq) + return; list_for_each_entry(entry, dev-msi_list, list) { int i, nvec; @@ -104,20 +92,10 @@ void default_teardown_msi_irqs(struct pci_dev *dev) else nvec = 1 entry-msi_attrib.multiple; for (i = 0; i nvec; i++) - arch_teardown_msi_irq(entry-irq + i); + chip-teardown_irq(entry-irq + i); } } -void __weak arch_teardown_msi_irqs(struct pci_dev *dev) -{ - struct msi_chip *chip = arch_find_msi_chip(dev); - - if (chip chip-teardown_irqs) - return chip-teardown_irqs(dev); - - return default_teardown_msi_irqs(dev); -} - static void default_restore_msi_irq(struct pci_dev *dev, int irq) { struct msi_desc *entry; @@ -136,10 +114,18 @@ static void default_restore_msi_irq(struct pci_dev *dev, int irq) write_msi_msg(irq, entry-msg); } -void __weak arch_restore_msi_irqs(struct pci_dev *dev) +static void default_restore_msi_irqs(struct pci_dev *dev) { - struct msi_chip *chip = arch_find_msi_chip(dev); + struct msi_desc *entry = NULL; + + list_for_each_entry(entry, dev-msi_list, list) { + default_restore_msi_irq(dev, entry-irq); + } +} +static void restore_msi_irqs(struct pci_dev *dev) +{ + struct msi_chip *chip = arch_find_msi_chip(dev); if (chip chip-restore_irqs) return chip-restore_irqs(dev); @@ -248,15 +234,6 @@ void unmask_msi_irq(struct irq_data *data) msi_set_mask_bit(data, 0); } -void default_restore_msi_irqs(struct pci_dev *dev) -{ - struct msi_desc *entry
[PATCH v1 01/21] PCI/MSI: Clean up struct msi_chip argument
Msi_chip functions setup_irq/teardown_irq rarely use msi_chip argument. We can look up msi_chip pointer by the device pointer or irq number, so clean up msi_chip argument. Signed-off-by: Yijing Wang wangyij...@huawei.com CC: Thierry Reding thierry.red...@gmail.com CC: Thomas Petazzoni thomas.petazz...@free-electrons.com --- drivers/irqchip/irq-armada-370-xp.c | 12 +--- drivers/pci/host/pci-tegra.c|8 +--- drivers/pci/host/pcie-designware.c |4 ++-- drivers/pci/host/pcie-rcar.c|8 +--- drivers/pci/msi.c |4 ++-- include/linux/msi.h |5 ++--- 6 files changed, 21 insertions(+), 20 deletions(-) diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index 574aba0..658990c 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -129,9 +129,8 @@ static void armada_370_xp_free_msi(int hwirq) mutex_unlock(msi_used_lock); } -static int armada_370_xp_setup_msi_irq(struct msi_chip *chip, - struct pci_dev *pdev, - struct msi_desc *desc) +static int armada_370_xp_setup_msi_irq(struct pci_dev *pdev, + struct msi_desc *desc) { struct msi_msg msg; int virq, hwirq; @@ -156,8 +155,7 @@ static int armada_370_xp_setup_msi_irq(struct msi_chip *chip, return 0; } -static void armada_370_xp_teardown_msi_irq(struct msi_chip *chip, - unsigned int irq) +static void armada_370_xp_teardown_msi_irq(unsigned int irq) { struct irq_data *d = irq_get_irq_data(irq); unsigned long hwirq = d-hwirq; @@ -166,8 +164,8 @@ static void armada_370_xp_teardown_msi_irq(struct msi_chip *chip, armada_370_xp_free_msi(hwirq); } -static int armada_370_xp_check_msi_device(struct msi_chip *chip, struct pci_dev *dev, - int nvec, int type) +static int armada_370_xp_check_msi_device(struct pci_dev *dev, + int nvec, int type) { /* We support MSI, but not MSI-X */ if (type == PCI_CAP_ID_MSI) diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c index 0fb0fdb..edd4040 100644 --- a/drivers/pci/host/pci-tegra.c +++ b/drivers/pci/host/pci-tegra.c @@ -1157,9 +1157,10 @@ static irqreturn_t tegra_pcie_msi_irq(int irq, void *data) return processed 0 ? IRQ_HANDLED : IRQ_NONE; } -static int tegra_msi_setup_irq(struct msi_chip *chip, struct pci_dev *pdev, +static int tegra_msi_setup_irq(struct pci_dev *pdev, struct msi_desc *desc) { + struct msi_chip *chip = pdev-bus-msi; struct tegra_msi *msi = to_tegra_msi(chip); struct msi_msg msg; unsigned int irq; @@ -1185,10 +1186,11 @@ static int tegra_msi_setup_irq(struct msi_chip *chip, struct pci_dev *pdev, return 0; } -static void tegra_msi_teardown_irq(struct msi_chip *chip, unsigned int irq) +static void tegra_msi_teardown_irq(unsigned int irq) { - struct tegra_msi *msi = to_tegra_msi(chip); struct irq_data *d = irq_get_irq_data(irq); + struct msi_chip *chip = irq_get_chip_data(irq); + struct tegra_msi *msi = to_tegra_msi(chip); tegra_msi_free(msi, d-hwirq); } diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c index 52bd3a1..2204456 100644 --- a/drivers/pci/host/pcie-designware.c +++ b/drivers/pci/host/pcie-designware.c @@ -342,7 +342,7 @@ static void clear_irq(unsigned int irq) msi-msi_attrib.multiple = 0; } -static int dw_msi_setup_irq(struct msi_chip *chip, struct pci_dev *pdev, +static int dw_msi_setup_irq(struct pci_dev *pdev, struct msi_desc *desc) { int irq, pos, msgvec; @@ -384,7 +384,7 @@ static int dw_msi_setup_irq(struct msi_chip *chip, struct pci_dev *pdev, return 0; } -static void dw_msi_teardown_irq(struct msi_chip *chip, unsigned int irq) +static void dw_msi_teardown_irq(unsigned int irq) { clear_irq(irq); } diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c index 4884ee5..647bc9f 100644 --- a/drivers/pci/host/pcie-rcar.c +++ b/drivers/pci/host/pcie-rcar.c @@ -615,9 +615,10 @@ static irqreturn_t rcar_pcie_msi_irq(int irq, void *data) return IRQ_HANDLED; } -static int rcar_msi_setup_irq(struct msi_chip *chip, struct pci_dev *pdev, +static int rcar_msi_setup_irq(struct pci_dev *pdev, struct msi_desc *desc) { + struct msi_chip *chip = pdev-bus-msi; struct rcar_msi *msi = to_rcar_msi(chip); struct rcar_pcie *pcie = container_of(chip, struct rcar_pcie, msi.chip); struct msi_msg msg; @@ -645,10 +646,11 @@ static int rcar_msi_setup_irq(struct msi_chip *chip, struct pci_dev *pdev, return 0; } -static void rcar_msi_teardown_irq(struct msi_chip *chip
[PATCH v1 02/21] PCI/MSI: Remove useless bus-msi assignment
Currently, PCI drivers will initialize bus-msi in pcibios_add_bus(). pcibios_add_bus() will be called in every pci bus initialization. So the bus-msi assignment in pci_alloc_child_bus() is useless. Signed-off-by: Yijing Wang wangyij...@huawei.com CC: Thierry Reding thierry.red...@avionic-design.de CC: Thomas Petazzoni thomas.petazz...@free-electrons.com --- drivers/pci/probe.c |1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index e3cf8a2..8296576 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -677,7 +677,6 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent, child-parent = parent; child-ops = parent-ops; - child-msi = parent-msi; child-sysdata = parent-sysdata; child-bus_flags = parent-bus_flags; -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [Xen-devel] [PATCH v1 08/21] x86/xen/MSI: Use MSI chip framework to configure MSI/MSI-X irq
On 2014/9/5 22:29, David Vrabel wrote: On 05/09/14 11:09, Yijing Wang wrote: Use MSI chip framework instead of arch MSI functions to configure MSI/MSI-X irq. So we can manage MSI/MSI-X irq in a unified framework. [...] --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c [...] @@ -418,9 +430,9 @@ int __init pci_xen_init(void) #endif #ifdef CONFIG_PCI_MSI -x86_msi.setup_msi_irqs = xen_setup_msi_irqs; -x86_msi.teardown_msi_irq = xen_teardown_msi_irq; -x86_msi.teardown_msi_irqs = xen_teardown_msi_irqs; +xen_msi_chip.setup_irqs = xen_setup_msi_irqs; +xen_msi_chip.teardown_irqs = xen_teardown_msi_irqs; +x86_msi_chip = xen_msi_chip; msi_chip.irq_mask = xen_nop_msi_mask; msi_chip.irq_unmask = xen_nop_msi_mask; Why have these not been changed to set the x86_msi_chip.mask/unmask fields instead? Hi David, x86_msi_chip here is struct msi_chip data type, used to configure MSI/MSI-X irq. msi_chip above is struct irq_chip data type, represent the MSI irq controller. They are not the same object. Their name easily confusing people. Defined in arch/x86/kernel/apic/io_apic.c /* * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices, * which implement the MSI or MSI-X Capability Structure. */ static struct irq_chip msi_chip = { .name = PCI-MSI, .irq_unmask = unmask_msi_irq, .irq_mask = mask_msi_irq, .irq_ack= ack_apic_edge, .irq_set_affinity = msi_set_affinity, .irq_retrigger = ioapic_retrigger_irq, }; Defined in arch/x86/kernel/apic/io_apic.c, introduced in patch 7/21 struct msi_chip apic_msi_chip = { .setup_irqs = native_setup_msi_irqs, .teardown_irq = native_teardown_msi_irq, }; [...] struct msi_chip *x86_msi_chip = apic_msi_chip; Thanks! Yijing. David . -- Thanks! Yijing ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [Xen-devel] [PATCH v1 04/21] x86/xen/MSI: Eliminate arch_msix_mask_irq() and arch_msi_mask_irq()
On 2014/9/10 20:36, David Vrabel wrote: On 05/09/14 11:09, Yijing Wang wrote: Commit 0e4ccb150 added two __weak arch functions arch_msix_mask_irq() and arch_msi_mask_irq() to fix a bug found when running xen in x86. Introduced these two funcntions make MSI code complex. And mask/unmask is the irq actions related to interrupt controller, should not use weak arch functions to override mask/unmask interfaces. This patch reverted commit 0e4ccb150 and export struct irq_chip msi_chip, modify msi_chip-irq_mask/irq_unmask() in xen init functions to fix this bug for simplicity. Also this is preparation for using struct msi_chip instead of weak arch MSI functions in all platforms. Acked-by: David Vrabel david.vra...@citrix.com But I wonder if it would be better the Xen subsystem to provide its own struct irq_chip instead of adjusting the fields in the generic x86 one. Thanks! Currently, Xen and the bare x86 system only have the different irq_chip-irq_mask/irq_unmask. So I chose to override the two ops of bare x86 irq_chip in xen. Konrad Rzeszutek Wilk has been tested it ok in his platform, so I think we could use its own irq_chip for xen later if the difference become large. Thanks! Yijing. David . -- Thanks! Yijing ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [Xen-devel] [PATCH v1 08/21] x86/xen/MSI: Use MSI chip framework to configure MSI/MSI-X irq
On 2014/9/10 20:38, David Vrabel wrote: On 09/09/14 03:06, Yijing Wang wrote: On 2014/9/5 22:29, David Vrabel wrote: On 05/09/14 11:09, Yijing Wang wrote: Use MSI chip framework instead of arch MSI functions to configure MSI/MSI-X irq. So we can manage MSI/MSI-X irq in a unified framework. [...] --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c [...] @@ -418,9 +430,9 @@ int __init pci_xen_init(void) #endif #ifdef CONFIG_PCI_MSI - x86_msi.setup_msi_irqs = xen_setup_msi_irqs; - x86_msi.teardown_msi_irq = xen_teardown_msi_irq; - x86_msi.teardown_msi_irqs = xen_teardown_msi_irqs; + xen_msi_chip.setup_irqs = xen_setup_msi_irqs; + xen_msi_chip.teardown_irqs = xen_teardown_msi_irqs; + x86_msi_chip = xen_msi_chip; msi_chip.irq_mask = xen_nop_msi_mask; msi_chip.irq_unmask = xen_nop_msi_mask; Why have these not been changed to set the x86_msi_chip.mask/unmask fields instead? Hi David, x86_msi_chip here is struct msi_chip data type, used to configure MSI/MSI-X irq. msi_chip above is struct irq_chip data type, represent the MSI irq controller. They are not the same object. Their name easily confusing people. Ok, it all makes sense now. Acked-by: David Vrabel david.vra...@citrix.com Thanks! David . -- Thanks! Yijing ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [Xen-devel] [PATCH v1 08/21] x86/xen/MSI: Use MSI chip framework to configure MSI/MSI-X irq
On 2014/9/10 22:59, Konrad Rzeszutek Wilk wrote: On Wed, Sep 10, 2014 at 01:38:25PM +0100, David Vrabel wrote: On 09/09/14 03:06, Yijing Wang wrote: On 2014/9/5 22:29, David Vrabel wrote: On 05/09/14 11:09, Yijing Wang wrote: Use MSI chip framework instead of arch MSI functions to configure MSI/MSI-X irq. So we can manage MSI/MSI-X irq in a unified framework. [...] --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c [...] @@ -418,9 +430,9 @@ int __init pci_xen_init(void) #endif #ifdef CONFIG_PCI_MSI - x86_msi.setup_msi_irqs = xen_setup_msi_irqs; - x86_msi.teardown_msi_irq = xen_teardown_msi_irq; - x86_msi.teardown_msi_irqs = xen_teardown_msi_irqs; + xen_msi_chip.setup_irqs = xen_setup_msi_irqs; + xen_msi_chip.teardown_irqs = xen_teardown_msi_irqs; + x86_msi_chip = xen_msi_chip; msi_chip.irq_mask = xen_nop_msi_mask; msi_chip.irq_unmask = xen_nop_msi_mask; Why have these not been changed to set the x86_msi_chip.mask/unmask fields instead? Hi David, x86_msi_chip here is struct msi_chip data type, used to configure MSI/MSI-X irq. msi_chip above is struct irq_chip data type, represent the MSI irq controller. They are not the same object. Their name easily confusing people. Ok, it all makes sense now. Acked-by: David Vrabel david.vra...@citrix.com You can also add 'Tested-by: Konrad Rzeszutek Wilk konrad.w...@oracle.com' on the whole series - I ran it through on Xen and on baremetal with a mix of 32/64 builds. Oh, and also Reviewed-by: Konrad Rzeszutek Wilk konrad.w...@oracle.com the Xen parts. Thanks very much for your test and review! Thanks! Yijing. David ___ Xen-devel mailing list xen-de...@lists.xen.org http://lists.xen.org/xen-devel . -- Thanks! Yijing ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH] x86: irq_remapping: Make functions static
Change local functions to static. Signed-off-by: Yijing Wang wangyij...@huawei.com --- arch/x86/include/asm/irq_remapping.h | 27 +-- drivers/iommu/irq_remapping.c| 34 +- 2 files changed, 18 insertions(+), 43 deletions(-) diff --git a/arch/x86/include/asm/irq_remapping.h b/arch/x86/include/asm/irq_remapping.h index b7747c4..944cba6 100644 --- a/arch/x86/include/asm/irq_remapping.h +++ b/arch/x86/include/asm/irq_remapping.h @@ -41,16 +41,7 @@ extern int irq_remapping_enable(void); extern void irq_remapping_disable(void); extern int irq_remapping_reenable(int); extern int irq_remap_enable_fault_handling(void); -extern int setup_ioapic_remapped_entry(int irq, - struct IO_APIC_route_entry *entry, - unsigned int destination, - int vector, - struct io_apic_irq_attr *attr); extern void free_remapped_irq(int irq); -extern void compose_remapped_msi_msg(struct pci_dev *pdev, -unsigned int irq, unsigned int dest, -struct msi_msg *msg, u8 hpet_id); -extern int setup_hpet_msi_remapped(unsigned int irq, unsigned int id); extern void panic_if_irq_remap(const char *msg); extern bool setup_remapped_irq(int irq, struct irq_cfg *cfg, @@ -68,24 +59,8 @@ static inline int irq_remapping_enable(void) { return -ENODEV; } static inline void irq_remapping_disable(void) { } static inline int irq_remapping_reenable(int eim) { return -ENODEV; } static inline int irq_remap_enable_fault_handling(void) { return -ENODEV; } -static inline int setup_ioapic_remapped_entry(int irq, - struct IO_APIC_route_entry *entry, - unsigned int destination, - int vector, - struct io_apic_irq_attr *attr) -{ - return -ENODEV; -} + static inline void free_remapped_irq(int irq) { } -static inline void compose_remapped_msi_msg(struct pci_dev *pdev, - unsigned int irq, unsigned int dest, - struct msi_msg *msg, u8 hpet_id) -{ -} -static inline int setup_hpet_msi_remapped(unsigned int irq, unsigned int id) -{ - return -ENODEV; -} static inline void panic_if_irq_remap(const char *msg) { diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c index 33c4395..85eb212 100644 --- a/drivers/iommu/irq_remapping.c +++ b/drivers/iommu/irq_remapping.c @@ -27,9 +27,7 @@ static struct irq_remap_ops *remap_ops; static int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec); static int msi_setup_remapped_irq(struct pci_dev *pdev, unsigned int irq, int index, int sub_handle); -static int set_remapped_irq_affinity(struct irq_data *data, -const struct cpumask *mask, -bool force); +static void __init irq_remapping_modify_x86_ops(void); static bool irq_remapped(struct irq_cfg *cfg) { @@ -159,17 +157,6 @@ static void eoi_ioapic_pin_remapped(int apic, int pin, int vector) io_apic_eoi(apic, pin); } -static void __init irq_remapping_modify_x86_ops(void) -{ - x86_io_apic_ops.disable = irq_remapping_disable_io_apic; - x86_io_apic_ops.set_affinity= set_remapped_irq_affinity; - x86_io_apic_ops.setup_entry = setup_ioapic_remapped_entry; - x86_io_apic_ops.eoi_ioapic_pin = eoi_ioapic_pin_remapped; - x86_msi.setup_msi_irqs = irq_remapping_setup_msi_irqs; - x86_msi.setup_hpet_msi = setup_hpet_msi_remapped; - x86_msi.compose_msi_msg = compose_remapped_msi_msg; -} - static __init int setup_nointremap(char *str) { disable_irq_remap = 1; @@ -281,7 +268,7 @@ int __init irq_remap_enable_fault_handling(void) return remap_ops-enable_faulting(); } -int setup_ioapic_remapped_entry(int irq, +static int setup_ioapic_remapped_entry(int irq, struct IO_APIC_route_entry *entry, unsigned int destination, int vector, struct io_apic_irq_attr *attr) @@ -314,7 +301,7 @@ void free_remapped_irq(int irq) remap_ops-free_irq(irq); } -void compose_remapped_msi_msg(struct pci_dev *pdev, +static void compose_remapped_msi_msg(struct pci_dev *pdev, unsigned int irq, unsigned int dest, struct msi_msg *msg, u8 hpet_id) { @@ -343,7 +330,7 @@ static int msi_setup_remapped_irq(struct pci_dev *pdev, unsigned int irq, return remap_ops-msi_setup_irq(pdev, irq, index, sub_handle); } -int
[PATCH] x86: irq_remapping: Fix the regression of hpet irq remapping
Commit 71054d8841b4 introduced x86_msi_ops.setup_hpet_msi to setup hpet MSI irq when irq remapping enabled. This caused a regression of hpet MSI irq remapping. Original code flow before commit 71054d8841b4: hpet_setup_msi_irq() arch_setup_hpet_msi() setup_hpet_msi_remapped() remap_ops-setup_hpet_msi() alloc_irte() msi_compose_msg() hpet_msi_write() ... Current code flow after commit 71054d8841b4: hpet_setup_msi_irq() x86_msi.setup_hpet_msi() setup_hpet_msi_remapped() intel_setup_hpet_msi() alloc_irte() Currently, we only alloc_irte() for hpet MSI, but have not composed and wrote its msg... Signed-off-by: Yijing Wang wangyij...@huawei.com --- drivers/iommu/irq_remapping.c |9 - 1 files changed, 8 insertions(+), 1 deletions(-) diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c index 85eb212..3541c71 100644 --- a/drivers/iommu/irq_remapping.c +++ b/drivers/iommu/irq_remapping.c @@ -12,6 +12,7 @@ #include asm/processor.h #include asm/x86_init.h #include asm/apic.h +#include asm/hpet.h #include irq_remapping.h @@ -332,10 +333,16 @@ static int msi_setup_remapped_irq(struct pci_dev *pdev, unsigned int irq, static int setup_hpet_msi_remapped(unsigned int irq, unsigned int id) { + int ret; + if (!remap_ops || !remap_ops-setup_hpet_msi) return -ENODEV; - return remap_ops-setup_hpet_msi(irq, id); + ret = remap_ops-setup_hpet_msi(irq, id); + if (ret) + return -EINVAL; + + return default_setup_hpet_msi(irq, id); } void panic_if_irq_remap(const char *msg) -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH] x86: irq_remapping: Make functions static
On 2014/9/12 16:49, Jiang Liu wrote: Hi Yijing, There's an effort to refine the remapping interface by using hierarchy irqdomain, which plans to kill all these interfaces. Please refer to https://lkml.org/lkml/2014/9/11/101 https://lkml.org/lkml/2014/9/11/554 That's nice, I'm preparing to look at it. Joerg, please drop this trivial patch. Thanks! Yijing. Regards! Gerry On 2014/9/12 17:05, Yijing Wang wrote: Change local functions to static. Signed-off-by: Yijing Wang wangyij...@huawei.com --- arch/x86/include/asm/irq_remapping.h | 27 +-- drivers/iommu/irq_remapping.c| 34 +- 2 files changed, 18 insertions(+), 43 deletions(-) diff --git a/arch/x86/include/asm/irq_remapping.h b/arch/x86/include/asm/irq_remapping.h index b7747c4..944cba6 100644 --- a/arch/x86/include/asm/irq_remapping.h +++ b/arch/x86/include/asm/irq_remapping.h @@ -41,16 +41,7 @@ extern int irq_remapping_enable(void); extern void irq_remapping_disable(void); extern int irq_remapping_reenable(int); extern int irq_remap_enable_fault_handling(void); -extern int setup_ioapic_remapped_entry(int irq, - struct IO_APIC_route_entry *entry, - unsigned int destination, - int vector, - struct io_apic_irq_attr *attr); extern void free_remapped_irq(int irq); -extern void compose_remapped_msi_msg(struct pci_dev *pdev, - unsigned int irq, unsigned int dest, - struct msi_msg *msg, u8 hpet_id); -extern int setup_hpet_msi_remapped(unsigned int irq, unsigned int id); extern void panic_if_irq_remap(const char *msg); extern bool setup_remapped_irq(int irq, struct irq_cfg *cfg, @@ -68,24 +59,8 @@ static inline int irq_remapping_enable(void) { return -ENODEV; } static inline void irq_remapping_disable(void) { } static inline int irq_remapping_reenable(int eim) { return -ENODEV; } static inline int irq_remap_enable_fault_handling(void) { return -ENODEV; } -static inline int setup_ioapic_remapped_entry(int irq, - struct IO_APIC_route_entry *entry, - unsigned int destination, - int vector, - struct io_apic_irq_attr *attr) -{ -return -ENODEV; -} + static inline void free_remapped_irq(int irq) { } -static inline void compose_remapped_msi_msg(struct pci_dev *pdev, -unsigned int irq, unsigned int dest, -struct msi_msg *msg, u8 hpet_id) -{ -} -static inline int setup_hpet_msi_remapped(unsigned int irq, unsigned int id) -{ -return -ENODEV; -} static inline void panic_if_irq_remap(const char *msg) { diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c index 33c4395..85eb212 100644 --- a/drivers/iommu/irq_remapping.c +++ b/drivers/iommu/irq_remapping.c @@ -27,9 +27,7 @@ static struct irq_remap_ops *remap_ops; static int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec); static int msi_setup_remapped_irq(struct pci_dev *pdev, unsigned int irq, int index, int sub_handle); -static int set_remapped_irq_affinity(struct irq_data *data, - const struct cpumask *mask, - bool force); +static void __init irq_remapping_modify_x86_ops(void); static bool irq_remapped(struct irq_cfg *cfg) { @@ -159,17 +157,6 @@ static void eoi_ioapic_pin_remapped(int apic, int pin, int vector) io_apic_eoi(apic, pin); } -static void __init irq_remapping_modify_x86_ops(void) -{ -x86_io_apic_ops.disable = irq_remapping_disable_io_apic; -x86_io_apic_ops.set_affinity= set_remapped_irq_affinity; -x86_io_apic_ops.setup_entry = setup_ioapic_remapped_entry; -x86_io_apic_ops.eoi_ioapic_pin = eoi_ioapic_pin_remapped; -x86_msi.setup_msi_irqs = irq_remapping_setup_msi_irqs; -x86_msi.setup_hpet_msi = setup_hpet_msi_remapped; -x86_msi.compose_msi_msg = compose_remapped_msi_msg; -} - static __init int setup_nointremap(char *str) { disable_irq_remap = 1; @@ -281,7 +268,7 @@ int __init irq_remap_enable_fault_handling(void) return remap_ops-enable_faulting(); } -int setup_ioapic_remapped_entry(int irq, +static int setup_ioapic_remapped_entry(int irq, struct IO_APIC_route_entry *entry, unsigned int destination, int vector, struct io_apic_irq_attr *attr) @@ -314,7 +301,7 @@ void free_remapped_irq(int irq) remap_ops-free_irq
Re: [PATCH] x86: irq_remapping: Fix the regression of hpet irq remapping
On 2014/9/12 17:02, Jiang Liu wrote: On 2014/9/12 17:05, Yijing Wang wrote: Commit 71054d8841b4 introduced x86_msi_ops.setup_hpet_msi to setup hpet MSI irq when irq remapping enabled. This caused a regression of hpet MSI irq remapping. Original code flow before commit 71054d8841b4: hpet_setup_msi_irq() arch_setup_hpet_msi() setup_hpet_msi_remapped() remap_ops-setup_hpet_msi() alloc_irte() msi_compose_msg() hpet_msi_write() ... Current code flow after commit 71054d8841b4: hpet_setup_msi_irq() x86_msi.setup_hpet_msi() setup_hpet_msi_remapped() intel_setup_hpet_msi() alloc_irte() Currently, we only alloc_irte() for hpet MSI, but have not composed and wrote its msg... Signed-off-by: Yijing Wang wangyij...@huawei.com --- drivers/iommu/irq_remapping.c |9 - 1 files changed, 8 insertions(+), 1 deletions(-) diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c index 85eb212..3541c71 100644 --- a/drivers/iommu/irq_remapping.c +++ b/drivers/iommu/irq_remapping.c @@ -12,6 +12,7 @@ #include asm/processor.h #include asm/x86_init.h #include asm/apic.h +#include asm/hpet.h #include irq_remapping.h @@ -332,10 +333,16 @@ static int msi_setup_remapped_irq(struct pci_dev *pdev, unsigned int irq, static int setup_hpet_msi_remapped(unsigned int irq, unsigned int id) { +int ret; + if (!remap_ops || !remap_ops-setup_hpet_msi) return -ENODEV; -return remap_ops-setup_hpet_msi(irq, id); +ret = remap_ops-setup_hpet_msi(irq, id); +if (ret) +return -EINVAL; + +return default_setup_hpet_msi(irq, id); } Hi Yijing, How about move default_setup_hpet_msi(irq, id) into intel_setup_hpet_msi and amd.setup_hpet_msi? Hmmm, because the common irq remapping code is placed at irq_remapping.c, so what about change remap_ops-setup_hpet_msi to remap_ops-alloc_remapping_irq(), static int setup_hpet_msi_remapped(unsigned int irq, unsigned int id) { + int ret; + if (!remap_ops || !remap_ops-alloc_remapping_irq) return -ENODEV; - return remap_ops-alloc_remapping_irq(irq, id); + ret = remap_ops-alloc_remapping_irq(irq, id); + if (ret) + return -EINVAL; + + return default_setup_hpet_msi(irq, id); } Thanks! Yijing. Regards! Gerry void panic_if_irq_remap(const char *msg) . -- Thanks! Yijing ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [Patch Part3 V5 2/8] iommu/vt-d: Dynamically allocate and free seq_id for DMAR units
On 2014/9/12 10:10, Jiang Liu wrote: Introduce functions to support dynamic IOMMU seq_id allocating and releasing, which will be used to support DMAR hotplug. Also rename IOMMU_UNITS_SUPPORTED as DMAR_UNITS_SUPPORTED. Reviewed-by: Yijing Wang wangyij...@huawei.com Signed-off-by: Jiang Liu jiang@linux.intel.com --- drivers/iommu/dmar.c| 40 ++-- drivers/iommu/intel-iommu.c | 13 +++-- include/linux/dmar.h|6 ++ 3 files changed, 43 insertions(+), 16 deletions(-) diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index afd46eb9a5de..b3405c50627f 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -70,6 +70,7 @@ LIST_HEAD(dmar_drhd_units); struct acpi_table_header * __initdata dmar_tbl; static acpi_size dmar_tbl_size; static int dmar_dev_scope_status = 1; +static unsigned long dmar_seq_ids[BITS_TO_LONGS(DMAR_UNITS_SUPPORTED)]; static int alloc_iommu(struct dmar_drhd_unit *drhd); static void free_iommu(struct intel_iommu *iommu); @@ -928,11 +929,32 @@ out: return err; } +static int dmar_alloc_seq_id(struct intel_iommu *iommu) +{ + iommu-seq_id = find_first_zero_bit(dmar_seq_ids, + DMAR_UNITS_SUPPORTED); + if (iommu-seq_id = DMAR_UNITS_SUPPORTED) { + iommu-seq_id = -1; + } else { + set_bit(iommu-seq_id, dmar_seq_ids); + sprintf(iommu-name, dmar%d, iommu-seq_id); + } + + return iommu-seq_id; +} + +static void dmar_free_seq_id(struct intel_iommu *iommu) +{ + if (iommu-seq_id = 0) { + clear_bit(iommu-seq_id, dmar_seq_ids); + iommu-seq_id = -1; + } +} + static int alloc_iommu(struct dmar_drhd_unit *drhd) { struct intel_iommu *iommu; u32 ver, sts; - static int iommu_allocated = 0; int agaw = 0; int msagaw = 0; int err; @@ -946,13 +968,16 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd) if (!iommu) return -ENOMEM; - iommu-seq_id = iommu_allocated++; - sprintf (iommu-name, dmar%d, iommu-seq_id); + if (dmar_alloc_seq_id(iommu) 0) { + pr_err(IOMMU: 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); - goto error; + goto error_free_seq_id; } err = -EINVAL; @@ -1002,9 +1027,11 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd) return 0; - err_unmap: +err_unmap: unmap_iommu(iommu); - error: +error_free_seq_id: + dmar_free_seq_id(iommu); +error: kfree(iommu); return err; } @@ -1028,6 +1055,7 @@ static void free_iommu(struct intel_iommu *iommu) if (iommu-reg) unmap_iommu(iommu); + dmar_free_seq_id(iommu); kfree(iommu); } diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 4af2206e41bc..7daa74ed46d0 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -328,17 +328,10 @@ static int hw_pass_through = 1; /* si_domain contains mulitple devices */ #define DOMAIN_FLAG_STATIC_IDENTITY (1 1) -/* define the limit of IOMMUs supported in each domain */ -#ifdef CONFIG_X86 -# define IOMMU_UNITS_SUPPORTED MAX_IO_APICS -#else -# define IOMMU_UNITS_SUPPORTED 64 -#endif - struct dmar_domain { int id; /* domain id */ int nid;/* node id */ - DECLARE_BITMAP(iommu_bmp, IOMMU_UNITS_SUPPORTED); + DECLARE_BITMAP(iommu_bmp, DMAR_UNITS_SUPPORTED); /* bitmap of iommus this domain uses*/ struct list_head devices; /* all devices' list */ @@ -2728,12 +2721,12 @@ static int __init init_dmars(void) * threaded kernel __init code path all other access are read * only */ - if (g_num_of_iommus IOMMU_UNITS_SUPPORTED) { + if (g_num_of_iommus DMAR_UNITS_SUPPORTED) { g_num_of_iommus++; continue; } printk_once(KERN_ERR intel-iommu: exceeded %d IOMMUs\n, - IOMMU_UNITS_SUPPORTED); + DMAR_UNITS_SUPPORTED); } g_iommus = kcalloc(g_num_of_iommus, sizeof(struct intel_iommu *), diff --git a/include/linux/dmar.h b/include/linux/dmar.h index fac8ca34f9a8..c8a576bc3a98 100644 --- a/include/linux/dmar.h +++ b/include/linux/dmar.h @@ -30,6 +30,12 @@ struct acpi_dmar_header; +#ifdef CONFIG_X86 +# define DMAR_UNITS_SUPPORTEDMAX_IO_APICS +#else +# define DMAR_UNITS_SUPPORTED64 +#endif + /* DMAR Flags */ #define
Re: [Patch Part3 V5 1/8] iommu/vt-d: Introduce helper function dmar_walk_resources()
On 2014/9/12 10:10, Jiang Liu wrote: Introduce helper function dmar_walk_resources to walk resource entries in DMAR table and ACPI buffer object returned by ACPI _DSM method for IOMMU hot-plug. Signed-off-by: Jiang Liu jiang@linux.intel.com Hi Gerry. some comments below. --- drivers/iommu/dmar.c| 209 +++ drivers/iommu/intel-iommu.c |4 +- include/linux/dmar.h| 19 ++-- 3 files changed, 122 insertions(+), 110 deletions(-) diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index 60ab474bfff3..afd46eb9a5de 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -44,6 +44,14 @@ #include irq_remapping.h +typedef int (*dmar_res_handler_t)(struct acpi_dmar_header *, void *); +struct dmar_res_callback { + dmar_res_handler_t cb[ACPI_DMAR_TYPE_RESERVED]; + void*arg[ACPI_DMAR_TYPE_RESERVED]; + boolignore_unhandled; + boolprint_entry; Why do we need a switch to control print ? +}; + +static int dmar_walk_resources(struct acpi_dmar_header *start, size_t len, +struct dmar_res_callback *cb) The name dmar_walk_resources easily make people think this is related with I/O or memory resources. Do you have a better idea of this ? What about dmar_walk_remapping_entry() or dmar_walk_remapping_structure() ? +{ + int ret = 0; + struct acpi_dmar_header *iter, *next; + struct acpi_dmar_header *end = ((void *)start) + len; + + for (iter = start; iter end ret == 0; iter = next) { + next = (void *)iter + iter-length; + if (iter-length == 0) { + /* Avoid looping forever on bad ACPI tables */ + pr_debug(FW_BUG Invalid 0-length structure\n); What about use pr_warn() instead of pr_debug(), pr_debug() default is off. + break; + } else if (next end) { + /* Avoid passing table end */ + pr_warn(FW_BUG record passes table end\n); + ret = -EINVAL; + break; + } + + if (cb-print_entry) + dmar_table_print_dmar_entry(iter); + + if (iter-type = ACPI_DMAR_TYPE_RESERVED) { + /* continue for forward compatibility */ + pr_debug(Unknown DMAR structure type %d\n, + iter-type); Same as above. + } else if (cb-cb[iter-type]) { + ret = cb-cb[iter-type](iter, cb-arg[iter-type]); + } else if (!cb-ignore_unhandled) { + pr_warn(No handler for DMAR structure type %d\n, + iter-type); + ret = -EINVAL; + } + } + + return ret; +} + +static inline int dmar_walk_dmar_table(struct acpi_table_dmar *dmar, +struct dmar_res_callback *cb) +{ + return dmar_walk_resources((struct acpi_dmar_header *)(dmar + 1), +dmar-header.length - sizeof(*dmar), cb); +} + /** * parse_dmar_table - parses the DMA reporting table */ @@ -493,9 +554,18 @@ static int __init parse_dmar_table(void) { struct acpi_table_dmar *dmar; - struct acpi_dmar_header *entry_header; int ret = 0; int drhd_count = 0; + struct dmar_res_callback cb = { + .print_entry = true, + .ignore_unhandled = true, + .arg[ACPI_DMAR_TYPE_HARDWARE_UNIT] = drhd_count, + .cb[ACPI_DMAR_TYPE_HARDWARE_UNIT] = dmar_parse_one_drhd, + .cb[ACPI_DMAR_TYPE_RESERVED_MEMORY] = dmar_parse_one_rmrr, + .cb[ACPI_DMAR_TYPE_ROOT_ATS] = dmar_parse_one_atsr, + .cb[ACPI_DMAR_TYPE_HARDWARE_AFFINITY] = dmar_parse_one_rhsa, + .cb[ACPI_DMAR_TYPE_NAMESPACE] = dmar_parse_one_andd, + }; /* * Do it again, earlier dmar_tbl mapping could be mapped with @@ -519,51 +589,10 @@ parse_dmar_table(void) } pr_info(Host address width %d\n, dmar-width + 1); - - entry_header = (struct acpi_dmar_header *)(dmar + 1); - while (((unsigned long)entry_header) - (((unsigned long)dmar) + dmar_tbl-length)) { - /* Avoid looping forever on bad ACPI tables */ - if (entry_header-length == 0) { - pr_warn(Invalid 0-length structure\n); - ret = -EINVAL; - break; - } - - dmar_table_print_dmar_entry(entry_header); - - switch (entry_header-type) { - case ACPI_DMAR_TYPE_HARDWARE_UNIT: - drhd_count++; - ret = dmar_parse_one_drhd(entry_header); - break; - case
Re: [Patch Part3 V5 5/8] iommu/vt-d: Enhance intel_irq_remapping driver to support DMAR unit hotplug
+static void ir_remove_ioapic_hpet_scope(struct intel_iommu *iommu) +{ + int i; - ir_parse_one_hpet_scope(scope, iommu); - } - start += scope-length; - } + for (i = 0; i MAX_HPET_TBS; i++) + if (ir_hpet[i].iommu == iommu) + ir_hpet[i].iommu = NULL; Hi Gerry, why not reset whole ir_hpe and ir_ioapic data struct? - return 0; + for (i = 0; i MAX_IO_APICS; i++) + if (ir_ioapic[i].iommu == iommu) + ir_ioapic[i].iommu = NULL; } ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [Patch Part3 V5 6/8] iommu/vt-d: Enhance error recovery in function intel_enable_irq_remapping()
On 2014/9/12 10:10, Jiang Liu wrote: Enhance error recovery in function intel_enable_irq_remapping() by tearing down all created data structures. Signed-off-by: Jiang Liu jiang@linux.intel.com --- drivers/iommu/intel_irq_remapping.c |8 +--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c index 7cf31a29f77a..81f110aae6df 100644 --- a/drivers/iommu/intel_irq_remapping.c +++ b/drivers/iommu/intel_irq_remapping.c @@ -701,9 +701,11 @@ static int __init intel_enable_irq_remapping(void) return eim ? IRQ_REMAP_X2APIC_MODE : IRQ_REMAP_XAPIC_MODE; error: - /* - * handle error condition gracefully here! - */ + for_each_iommu(iommu, drhd) + if (ecap_ir_support(iommu-ecap)) { + iommu_disable_irq_remapping(iommu); + intel_teardown_irq_remapping(iommu); + } if (x2apic_present) pr_warn(Failed to enable irq remapping. You are vulnerable to irq-injection attacks.\n); Reviewed-by: Yijing Wang wangyij...@huawei.com -- Thanks! Yijing ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [Patch Part3 V5 7/8] iommu/vt-d: Enhance intel-iommu driver to support DMAR unit hotplug
On 2014/9/12 10:10, Jiang Liu wrote: Implement required callback functions for intel-iommu driver to support DMAR unit hotplug. Reviewed-by: Yijing Wang wangyij...@huawei.com Signed-off-by: Jiang Liu jiang@linux.intel.com --- drivers/iommu/intel-iommu.c | 206 +++ 1 file changed, 151 insertions(+), 55 deletions(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 70d9d47eaeda..c2d369524960 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -1125,8 +1125,11 @@ static int iommu_alloc_root_entry(struct intel_iommu *iommu) unsigned long flags; root = (struct root_entry *)alloc_pgtable_page(iommu-node); - if (!root) + if (!root) { + pr_err(IOMMU: allocating root entry for %s failed\n, + iommu-name); return -ENOMEM; + } __iommu_flush_cache(iommu, root, ROOT_SIZE); @@ -1466,7 +1469,7 @@ static int iommu_init_domains(struct intel_iommu *iommu) return 0; } -static void free_dmar_iommu(struct intel_iommu *iommu) +static void disable_dmar_iommu(struct intel_iommu *iommu) { struct dmar_domain *domain; int i; @@ -1490,11 +1493,16 @@ static void free_dmar_iommu(struct intel_iommu *iommu) if (iommu-gcmd DMA_GCMD_TE) iommu_disable_translation(iommu); +} - kfree(iommu-domains); - kfree(iommu-domain_ids); - iommu-domains = NULL; - iommu-domain_ids = NULL; +static void free_dmar_iommu(struct intel_iommu *iommu) +{ + if ((iommu-domains) (iommu-domain_ids)) { + kfree(iommu-domains); + kfree(iommu-domain_ids); + iommu-domains = NULL; + iommu-domain_ids = NULL; + } g_iommus[iommu-seq_id] = NULL; @@ -2701,6 +2709,41 @@ static int __init iommu_prepare_static_identity_mapping(int hw) return 0; } +static void intel_iommu_init_qi(struct intel_iommu *iommu) +{ + /* + * Start from the sane iommu hardware state. + * If the queued invalidation is already initialized by us + * (for example, while enabling interrupt-remapping) then + * we got the things already rolling from a sane state. + */ + if (!iommu-qi) { + /* + * Clear any previous faults. + */ + dmar_fault(-1, iommu); + /* + * Disable queued invalidation if supported and already enabled + * before OS handover. + */ + dmar_disable_qi(iommu); + } + + if (dmar_enable_qi(iommu)) { + /* + * Queued Invalidate not enabled, use Register Based Invalidate + */ + iommu-flush.flush_context = __iommu_flush_context; + iommu-flush.flush_iotlb = __iommu_flush_iotlb; + pr_info(IOMMU: %s using Register based invalidation\n, + iommu-name); + } else { + iommu-flush.flush_context = qi_flush_context; + iommu-flush.flush_iotlb = qi_flush_iotlb; + pr_info(IOMMU: %s using Queued invalidation\n, iommu-name); + } +} + static int __init init_dmars(void) { struct dmar_drhd_unit *drhd; @@ -2729,6 +2772,10 @@ static int __init init_dmars(void) DMAR_UNITS_SUPPORTED); } + /* Preallocate enough resources for IOMMU hot-addition */ + if (g_num_of_iommus DMAR_UNITS_SUPPORTED) + g_num_of_iommus = DMAR_UNITS_SUPPORTED; + g_iommus = kcalloc(g_num_of_iommus, sizeof(struct intel_iommu *), GFP_KERNEL); if (!g_iommus) { @@ -2757,58 +2804,14 @@ static int __init init_dmars(void) * among all IOMMU's. Need to Split it later. */ ret = iommu_alloc_root_entry(iommu); - if (ret) { - printk(KERN_ERR IOMMU: allocate root entry failed\n); + if (ret) goto free_iommu; - } if (!ecap_pass_through(iommu-ecap)) hw_pass_through = 0; } - /* - * Start from the sane iommu hardware state. - */ - for_each_active_iommu(iommu, drhd) { - /* - * If the queued invalidation is already initialized by us - * (for example, while enabling interrupt-remapping) then - * we got the things already rolling from a sane state. - */ - if (iommu-qi) - continue; - - /* - * Clear any previous faults. - */ - dmar_fault(-1, iommu); - /* - * Disable queued invalidation if supported and already enabled - * before OS handover
Re: [Patch Part3 V5 0/8] Enable support of Intel DMAR device hotplug
I built and boot this series in Huawei RH5885 (Intel(R) Xeon(R) CPU E7- 4807, two IOHs and two IOMMUs), It works fine, IRQ remap and DMA remap are both look good. But because my platform BIOS has no _DSM, so I didn't test the hotplug case yet. Thanks! Yijing. On 2014/9/12 10:10, Jiang Liu wrote: When hot plugging a descrete IOH or a physical processor with embedded IIO, we need to handle DMAR(or IOMMU) unit in the PCIe host bridge if DMAR is in use. This patch set tries to enhance current DMAR/IOMMU/IR drivers to support hotplug and is based on latest Linus master branch. All prerequisite patches to support DMAR device hotplug have been merged into the mainstream kernel, and this is the last patch set to enable DMAR device hotplug. You may access the patch set at: https://github.com/jiangliu/linux.git iommu/hotplug_v5 This patch set has been tested on Intel development machine. Appreciate any comments and tests. Patch 1-4 enhances DMAR framework to support hotplug Patch 5 enhances Intel interrupt remapping driver to support hotplug Patch 6 enhances error handling in Intel IR driver Patch 7 enhance Intel IOMMU to support hotplug Patch 8 enhance ACPI pci_root driver to handle DMAR units Jiang Liu (8): iommu/vt-d: Introduce helper function dmar_walk_resources() iommu/vt-d: Dynamically allocate and free seq_id for DMAR units iommu/vt-d: Implement DMAR unit hotplug framework iommu/vt-d: Search for ACPI _DSM method for DMAR hotplug iommu/vt-d: Enhance intel_irq_remapping driver to support DMAR unit hotplug iommu/vt-d: Enhance error recovery in function intel_enable_irq_remapping() iommu/vt-d: Enhance intel-iommu driver to support DMAR unit hotplug pci, ACPI, iommu: Enhance pci_root to support DMAR device hotplug drivers/acpi/pci_root.c | 16 +- drivers/iommu/dmar.c| 532 --- drivers/iommu/intel-iommu.c | 297 ++- drivers/iommu/intel_irq_remapping.c | 233 +++ include/linux/dmar.h| 50 +++- 5 files changed, 888 insertions(+), 240 deletions(-) -- Thanks! Yijing ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v1 03/21] MSI: Remove the redundant irq_set_chip_data()
On 2014/9/15 22:00, Lucas Stach wrote: Am Freitag, den 05.09.2014, 18:09 +0800 schrieb Yijing Wang: Currently, pcie-designware, pcie-rcar, pci-tegra drivers use irq chip_data to save the msi_chip pointer. They already call irq_set_chip_data() in their own MSI irq map functions. So irq_set_chip_data() in arch_setup_msi_irq() is useless. Signed-off-by: Yijing Wang wangyij...@huawei.com --- drivers/pci/msi.c |2 -- 1 files changed, 0 insertions(+), 2 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index f6cb317..d547f7f 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -41,8 +41,6 @@ int __weak arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) if (err 0) return err; -irq_set_chip_data(desc-irq, chip); - return 0; } arch_teardown_msi_irq() expects to find the msi_chip in the irq chip_data field. As this means drivers don't have any reasonable other possibility to stuff things into this field, I think it would make sense to do the cleanup the other way around: keep the irq_set_chip_data arch_setup_msi_irq() and rip it out of the individual drivers. Hi Lucas, thanks for your review and comments! irq_set_chip_data() should not be placed in MSI core functions, because other arch like x86, use irq_data-chip_data to stores irq_cfg. So how to set the chip_data is arch dependent. And this series is mainly to use MSI chip framework in all platforms. Currently, only ARM platform MSI drivers use the chip_data to store msi_chip, and the drivers call irq_set_chip_data() in their driver already. So I thought we should clean up it in MSI core code. Thanks! Yijing. Regards, Lucas -- Thanks! Yijing ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v1 05/21] PCI/MSI: Introduce weak arch_find_msi_chip() to find MSI chip
On 2014/9/15 22:42, Lucas Stach wrote: Am Freitag, den 05.09.2014, 18:09 +0800 schrieb Yijing Wang: Introduce weak arch_find_msi_chip() to find the match msi_chip. Currently, MSI chip associates pci bus to msi_chip. Because in ARM platform, there may be more than one MSI controller in system. Associate pci bus to msi_chip help pci device to find the match msi_chip and setup MSI/MSI-X irq correctly. But in other platform, like in x86. we only need one MSI chip, because all device use the same MSI address/data and irq etc. So it's no need to associate pci bus to MSI chip, just use a arch function, arch_find_msi_chip() to return the MSI chip for simplicity. The default weak arch_find_msi_chip() used in ARM platform, find the MSI chip by pci bus. Hm, while one weak function sounds much better than the plethora we have now, I wonder how much work it would be to associate the msi_chip with the pci bus on other arches the same way as done on ARM. This way we could kill this calling into arch specific functions which would make things a bit clearer to follow I think. That's a heavy work to associate msi_chip with the pci_bus in all platforms, And only in ARM platform, there are two or more different msi_chips which maybe associate pci hostbridge or irq chip. In other platforms, only one MSI chip exists at the same time. Another reason is I don't think associate the msi_chip with pci bus is a good idea to make PCI device find its own msi_chip. All PCI devices under the same PCI hostbridge should have the same msi_chip, and now a property msi-parent is defined to help pci hostbridge to find its matched msi_chip. I like to associate the msi_chip with a pci hostbridge. So we don't need to add a lot of pcibios_add_bus() to do that. I inspected all MSI chip drivers, and found there are two different relations between msi_chip and PCI hostbridge 1. MSI chip is a irq chip, like irq_armada_370_xp, PCI hostbridge platform device use msi-parent to find msi_chip by of_node. 2. MSI chip is integrated into PCI hostbridge, so msi_chip-dev is the PCI hostbridge platform device. So long as we use PCI hostbridge platform device as the parent of PCI hostbridge, every PCI device under the hostbridge can find the msi_chip by it. All MSI chip drivers now except pci-mvebu have been passed the hostbridge platform dev as the parent. pci_common_init_dev(pcie-dev, hw); ^ Pseudo code like: struct msi_chip *pcibios_find_msi_chip(struct pci_dev *dev) { struct pci_bus *root; struct pci_host_bridge *bridge; struct msi_chip *chip; struct device_node *node, *msi_node; /* First we find msi_chip by the phb of_node */ MSI chip is a irq chip root = pci_find_root_bus(dev-bus); node = pcibios_get_phb_of_node(root); if (node) { msi_node = of_parse_phandle(n, msi-parent, 0); of_node_put(node); if (msi_node) return of_pci_find_msi_chip_by_node(msi_node); } /* Some msi_chip are integrated into pci hostbridge, * we find it by phb device pointer. */ if (bridge bridge-dev.parent) { ---MSI chip is integrated into PCI hostbridge down_read(pci_msi_chip_sem); list_for_each_entry(chip, pci_msi_chip_list, list) { if (chip-dev == bridge-dev.parent) { up_read(pci_msi_chip_sem); return chip; } } up_read(pci_msi_chip_sem); } return NULL; } Thanks! Yijing. Regards, Lucas Signed-off-by: Yijing Wang wangyij...@huawei.com --- drivers/pci/msi.c |7 ++- 1 files changed, 6 insertions(+), 1 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index a77e7f7..539c11d 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -29,9 +29,14 @@ static int pci_msi_enable = 1; /* Arch hooks */ +struct msi_chip * __weak arch_find_msi_chip(struct pci_dev *dev) +{ +return dev-bus-msi; +} + int __weak arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) { -struct msi_chip *chip = dev-bus-msi; +struct msi_chip *chip = arch_find_msi_chip(dev); int err; if (!chip || !chip-setup_irq) -- Thanks! Yijing ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [Patch Part3 V5 5/8] iommu/vt-d: Enhance intel_irq_remapping driver to support DMAR unit hotplug
On 2014/9/16 15:00, Jiang Liu wrote: On 2014/9/15 10:20, Yijing Wang wrote: +static void ir_remove_ioapic_hpet_scope(struct intel_iommu *iommu) +{ + int i; - ir_parse_one_hpet_scope(scope, iommu); - } - start += scope-length; - } + for (i = 0; i MAX_HPET_TBS; i++) + if (ir_hpet[i].iommu == iommu) + ir_hpet[i].iommu = NULL; Hi Gerry, why not reset whole ir_hpe and ir_ioapic data struct? Hi Yijing, Thanks for review. Zero is legal for id, bus and devfn in struct ioapic_scope and struct hpet_scope. So we use domain field as a flag to mark entry valid or invalid and only reset iommu field. Hi Gerry, use iommu field as a flag to mark entry valid may be not safe enough, I found map_hpet_to_ir() and map_ioapic_to_ir() still only check the id field to return the valid iommu. What about this case: E.g. ir_hpet[2].id = N, ir_hpet[2].iommu = NULL, ir_hpet[4].id = N, ir_hpet[4].iommu = iommu; ir_hpet[2] maybe released yet, and the hpet now has been saved in ir_hpet[4], but map_hpet_to_irq() will return the wrong iommu(NULL). static struct intel_iommu *map_hpet_to_ir(u8 hpet_id) { int i; for (i = 0; i MAX_HPET_TBS; i++) if (ir_hpet[i].id == hpet_id) return ir_hpet[i].iommu; return NULL; } Regards! Gerry - return 0; + for (i = 0; i MAX_IO_APICS; i++) + if (ir_ioapic[i].iommu == iommu) + ir_ioapic[i].iommu = NULL; } -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/ . -- Thanks! Yijing ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [Patch Part3 V5 1/8] iommu/vt-d: Introduce helper function dmar_walk_resources()
#include irq_remapping.h +typedef int (*dmar_res_handler_t)(struct acpi_dmar_header *, void *); +struct dmar_res_callback { + dmar_res_handler_t cb[ACPI_DMAR_TYPE_RESERVED]; + void*arg[ACPI_DMAR_TYPE_RESERVED]; + boolignore_unhandled; + boolprint_entry; Why do we need a switch to control print ? We will walk DMAR entries several times during hotplug and only want to print once. Fine, thanks for your explanation. +}; + +static int dmar_walk_resources(struct acpi_dmar_header *start, size_t len, + struct dmar_res_callback *cb) The name dmar_walk_resources easily make people think this is related with I/O or memory resources. Do you have a better idea of this ? What about dmar_walk_remapping_entry() or dmar_walk_remapping_structure() ? Good suggestion, I like dmar_walk_remapping_entries(). +{ + int ret = 0; + struct acpi_dmar_header *iter, *next; + struct acpi_dmar_header *end = ((void *)start) + len; + + for (iter = start; iter end ret == 0; iter = next) { + next = (void *)iter + iter-length; + if (iter-length == 0) { + /* Avoid looping forever on bad ACPI tables */ + pr_debug(FW_BUG Invalid 0-length structure\n); What about use pr_warn() instead of pr_debug(), pr_debug() default is off. It seems a common practice for BIOS engineer to mark the last entry with zero length. So it will be annoying if we generate this debug message on product kernel. OK. + break; + } else if (next end) { + /* Avoid passing table end */ + pr_warn(FW_BUG record passes table end\n); + ret = -EINVAL; + break; + } + + if (cb-print_entry) + dmar_table_print_dmar_entry(iter); + + if (iter-type = ACPI_DMAR_TYPE_RESERVED) { + /* continue for forward compatibility */ + pr_debug(Unknown DMAR structure type %d\n, +iter-type); Same as above. This is typically caused by new DMAR specification. It will also be annoying too if we also generate this debug message on an newer hardware platform with older linux kernel. OK. + } else if (cb-cb[iter-type]) { + ret = cb-cb[iter-type](iter, cb-arg[iter-type]); + } else if (!cb-ignore_unhandled) { + pr_warn(No handler for DMAR structure type %d\n, ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v1 03/21] MSI: Remove the redundant irq_set_chip_data()
arch_teardown_msi_irq() expects to find the msi_chip in the irq chip_data field. As this means drivers don't have any reasonable other possibility to stuff things into this field, I think it would make sense to do the cleanup the other way around: keep the irq_set_chip_data arch_setup_msi_irq() and rip it out of the individual drivers. Hi Lucas, thanks for your review and comments! irq_set_chip_data() should not be placed in MSI core functions, because other arch like x86, use irq_data-chip_data to stores irq_cfg. So how to set the chip_data is arch dependent. And this series is mainly to use MSI chip framework in all platforms. Currently, only ARM platform MSI drivers use the chip_data to store msi_chip, and the drivers call irq_set_chip_data() in their driver already. So I thought we should clean up it in MSI core code. Okay I see your point, so the cleanup done this way is okay. But then this still introduces a problem: arch_teardown_msi_irq() expects to find the msi_chip in the chip_data field, which is okay for all ARM PCI host drivers, but not for other arch MSI chips. You fix this by completely removing arch_teardown_msi_irq() at the end of the series, but this still has the potential to introduce issues for other arches than ARM within the series. So this patch should include a change to replace the line struct msi_chip *chip = irq_get_chip_data(irq); with something that doesn't rely on the msi_chip being in the irq chip_data field. OK, I will update arch_teardown_msi_irq() in this patch, thanks! Thanks! Yijing. Regards, Lucas -- Thanks! Yijing ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2] x86: irq_remapping: Fix the regression of hpet irq remapping
Commit 71054d8841b4 (x86, hpet: Introduce x86_msi_ops.setup_hpet_msi) introduced x86_msi_ops.setup_hpet_msi to setup hpet MSI irq when irq remapping enabled. This caused a regression of hpet MSI irq remapping. Original code flow before commit 71054d8841b4: hpet_setup_msi_irq() arch_setup_hpet_msi() setup_hpet_msi_remapped() remap_ops-setup_hpet_msi() alloc_irte() msi_compose_msg() hpet_msi_write() ... Current code flow after commit 71054d8841b4: hpet_setup_msi_irq() x86_msi.setup_hpet_msi() setup_hpet_msi_remapped() intel_setup_hpet_msi() alloc_irte() Currently, we only call alloc_irte() for hpet MSI, but do not composed and wrote its msg... Signed-off-by: Yijing Wang wangyij...@huawei.com --- v1-v2: rename remap_ops-setup_hpet_msi to remap_ops-alloc_hpet_msi. --- drivers/iommu/amd_iommu.c |4 ++-- drivers/iommu/intel_irq_remapping.c |4 ++-- drivers/iommu/irq_remapping.c | 11 +-- drivers/iommu/irq_remapping.h |2 +- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 1840531..0398314 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -4233,7 +4233,7 @@ static int msi_setup_irq(struct pci_dev *pdev, unsigned int irq, return 0; } -static int setup_hpet_msi(unsigned int irq, unsigned int id) +static int alloc_hpet_msi(unsigned int irq, unsigned int id) { struct irq_2_irte *irte_info; struct irq_cfg *cfg; @@ -4272,6 +4272,6 @@ struct irq_remap_ops amd_iommu_irq_ops = { .compose_msi_msg= compose_msi_msg, .msi_alloc_irq = msi_alloc_irq, .msi_setup_irq = msi_setup_irq, - .setup_hpet_msi = setup_hpet_msi, + .alloc_hpet_msi = alloc_hpet_msi, }; #endif diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c index a872874..7c80661 100644 --- a/drivers/iommu/intel_irq_remapping.c +++ b/drivers/iommu/intel_irq_remapping.c @@ -1138,7 +1138,7 @@ static int intel_msi_setup_irq(struct pci_dev *pdev, unsigned int irq, return ret; } -static int intel_setup_hpet_msi(unsigned int irq, unsigned int id) +static int intel_alloc_hpet_msi(unsigned int irq, unsigned int id) { int ret = -1; struct intel_iommu *iommu; @@ -1169,5 +1169,5 @@ struct irq_remap_ops intel_irq_remap_ops = { .compose_msi_msg= intel_compose_msi_msg, .msi_alloc_irq = intel_msi_alloc_irq, .msi_setup_irq = intel_msi_setup_irq, - .setup_hpet_msi = intel_setup_hpet_msi, + .alloc_hpet_msi = intel_alloc_hpet_msi, }; diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c index 33c4395..74a1767 100644 --- a/drivers/iommu/irq_remapping.c +++ b/drivers/iommu/irq_remapping.c @@ -12,6 +12,7 @@ #include asm/processor.h #include asm/x86_init.h #include asm/apic.h +#include asm/hpet.h #include irq_remapping.h @@ -345,10 +346,16 @@ static int msi_setup_remapped_irq(struct pci_dev *pdev, unsigned int irq, int setup_hpet_msi_remapped(unsigned int irq, unsigned int id) { - if (!remap_ops || !remap_ops-setup_hpet_msi) + int ret; + + if (!remap_ops || !remap_ops-alloc_hpet_msi) return -ENODEV; - return remap_ops-setup_hpet_msi(irq, id); + ret = remap_ops-alloc_hpet_msi(irq, id); + if (ret) + return -EINVAL; + + return default_setup_hpet_msi(irq, id); } void panic_if_irq_remap(const char *msg) diff --git a/drivers/iommu/irq_remapping.h b/drivers/iommu/irq_remapping.h index 90c4dae..fde250f 100644 --- a/drivers/iommu/irq_remapping.h +++ b/drivers/iommu/irq_remapping.h @@ -80,7 +80,7 @@ struct irq_remap_ops { int (*msi_setup_irq)(struct pci_dev *, unsigned int, int, int); /* Setup interrupt remapping for an HPET MSI */ - int (*setup_hpet_msi)(unsigned int, unsigned int); + int (*alloc_hpet_msi)(unsigned int, unsigned int); }; extern struct irq_remap_ops intel_irq_remap_ops; -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v1 00/21] Use MSI chip to configure MSI/MSI-X in all platforms
On 2014/9/24 5:09, Bjorn Helgaas wrote: On Fri, Sep 05, 2014 at 06:09:45PM +0800, Yijing Wang wrote: This series is based Bjorn's pci-next branch + Alexander Gordeev's two patches Remove arch_msi_check_device() link: https://lkml.org/lkml/2014/7/12/41 Currently, there are a lot of weak arch functions in MSI code. Thierry Reding Introduced MSI chip framework to configure MSI/MSI-X in arm. This series use MSI chip framework to refactor MSI code across all platforms to eliminate weak arch functions. It has been tested fine in x86(with or without irq remap). I see you plan some updates, so I'll look for a v2 posting after v3.17 releases. It will be great to get rid of some of those weak functions! Thanks, I will send out the new version soon. Thanks! Yijing. Bjorn . -- Thanks! Yijing ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH] iommu/vt-d: Fix broken device issue when using iommu=pt
On 2014/9/25 5:56, Rob Roschewsk wrote: Hello All wonder if there has been any movement on this issue I'm having a similar issue I'm running an HP dl380 gen 8 with an Emulex OneConnect 10Gb iSCSI (14e4:164c) (rev 11) also known as Hewlett-Packard Company NC373i Integrated Multifunction Gigabit Server Adapter 03:00.2 Mass storage controller: Emulex Corporation OneConnect 10Gb iSCSI Initiator (be3) (rev 01) 03:00.3 Mass storage controller: Emulex Corporation OneConnect 10Gb iSCSI Initiator (be3) (rev 01) Seems as soon as the iscsi target is contacted the following messages appear in the log every few seconds It seems to a different problem, in my issue, the DMA fault messages contained a non-exist PCI ID in system. But in this issue, 03:00.2 is in system, the fault addr is c000, I guess it's DMA virtual address allocated by vt-d driver. And it seems to 03:00.2 has no write access authority. Sep 24 15:25:30 kernel: [ 78.682675] dmar: DRHD: handling fault status reg 2 Sep 24 15:25:30 kernel: [ 78.699797] dmar: DMAR:[DMA Write] Request device [03:00.2] fault addr c000 Sep 24 15:25:30 kernel: [ 78.699797] DMAR:[fault reason 05] PTE Write access is not set Sep 24 15:25:30 kernel: [ 78.934546] dmar: DRHD: handling fault status reg 102 Sep 24 15:25:30 kernel: [ 78.934549] dmar: DMAR:[DMA Write] Request device [03:00.2] fault addr c000 Sep 24 15:25:30 kernel: [ 78.934549] DMAR:[fault reason 05] PTE Write access is not set Sep 24 15:25:30 kernel: [ 78.935359] dmar: DRHD: handling fault status reg 202 If I pull intel_iommu=on out of the kernel command line the problem goes away. System is running Ubuntu 14.04.1 LTS 3.13.0-32-generic #57-Ubuntu SMP Tue Jul 15 03:51:08 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux Looking for help I'm not sure where I should be looking next . I need SR-IOV for other adapters in the box. I have a system up that I can pull any data from that might be required. Thanks, -- Rob ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu -- Thanks! Yijing ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 07/22] PCI/MSI: Refactor struct msi_chip to make it become more common
Now there are a lot of __weak arch functions in MSI code. These functions make MSI driver complex. Thierry Reding Introduced a new MSI chip framework to configure MSI/MSI-X irq in ARM. Use the new MSI chip framework to refactor all other platform MSI arch code to eliminate weak arch MSI functions. This patch add .restore_irq() and .setup_irqs() to make it become more common. Signed-off-by: Yijing Wang wangyij...@huawei.com Reviewed-by: Lucas Stach l.st...@pengutronix.de --- drivers/pci/msi.c | 15 +++ include/linux/msi.h |3 +++ 2 files changed, 18 insertions(+), 0 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 3acbe65..d10edee 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -64,6 +64,11 @@ int __weak arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) { struct msi_desc *entry; int ret; + struct msi_chip *chip; + + chip = arch_find_msi_chip(dev); + if (chip chip-setup_irqs) + return chip-setup_irqs(dev, nvec, type); /* * If an architecture wants to support multiple MSI, it needs to @@ -106,6 +111,11 @@ void default_teardown_msi_irqs(struct pci_dev *dev) void __weak arch_teardown_msi_irqs(struct pci_dev *dev) { + struct msi_chip *chip = arch_find_msi_chip(dev); + + if (chip chip-teardown_irqs) + return chip-teardown_irqs(dev); + return default_teardown_msi_irqs(dev); } @@ -129,6 +139,11 @@ static void default_restore_msi_irq(struct pci_dev *dev, int irq) void __weak arch_restore_msi_irqs(struct pci_dev *dev) { + struct msi_chip *chip = arch_find_msi_chip(dev); + + if (chip chip-restore_irqs) + return chip-restore_irqs(dev); + return default_restore_msi_irqs(dev); } diff --git a/include/linux/msi.h b/include/linux/msi.h index 6fdc5c6..4cf1f31 100644 --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -69,7 +69,10 @@ struct msi_chip { struct list_head list; int (*setup_irq)(struct pci_dev *dev, struct msi_desc *desc); + int (*setup_irqs)(struct pci_dev *dev, int nvec, int type); void (*teardown_irq)(unsigned int irq); + void (*teardown_irqs)(struct pci_dev *dev); + void (*restore_irqs)(struct pci_dev *dev); }; #endif /* LINUX_MSI_H */ -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 18/22] arm/iop13xx/MSI: Use MSI chip framework to configure MSI/MSI-X irq
Use MSI chip framework instead of arch MSI functions to configure MSI/MSI-X irq. So we can manage MSI/MSI-X irq in a unified framework. Signed-off-by: Yijing Wang wangyij...@huawei.com --- arch/arm/mach-iop13xx/include/mach/pci.h |2 ++ arch/arm/mach-iop13xx/iq81340mc.c|1 + arch/arm/mach-iop13xx/iq81340sc.c|1 + arch/arm/mach-iop13xx/msi.c |9 +++-- arch/arm/mach-iop13xx/pci.c |6 ++ 5 files changed, 17 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-iop13xx/include/mach/pci.h b/arch/arm/mach-iop13xx/include/mach/pci.h index 59f42b5..7a073cb 100644 --- a/arch/arm/mach-iop13xx/include/mach/pci.h +++ b/arch/arm/mach-iop13xx/include/mach/pci.h @@ -10,6 +10,8 @@ struct pci_bus *iop13xx_scan_bus(int nr, struct pci_sys_data *); void iop13xx_atu_select(struct hw_pci *plat_pci); void iop13xx_pci_init(void); void iop13xx_map_pci_memory(void); +void iop13xx_add_bus(struct pci_bus *bus); +extern struct msi_chip iop13xx_msi_chip; #define IOP_PCI_STATUS_ERROR (PCI_STATUS_PARITY | \ PCI_STATUS_SIG_TARGET_ABORT | \ diff --git a/arch/arm/mach-iop13xx/iq81340mc.c b/arch/arm/mach-iop13xx/iq81340mc.c index 9cd07d3..19d47cb 100644 --- a/arch/arm/mach-iop13xx/iq81340mc.c +++ b/arch/arm/mach-iop13xx/iq81340mc.c @@ -59,6 +59,7 @@ static struct hw_pci iq81340mc_pci __initdata = { .map_irq= iq81340mc_pcix_map_irq, .scan = iop13xx_scan_bus, .preinit= iop13xx_pci_init, + .add_bus= iop13xx_add_bus; }; static int __init iq81340mc_pci_init(void) diff --git a/arch/arm/mach-iop13xx/iq81340sc.c b/arch/arm/mach-iop13xx/iq81340sc.c index b3ec11c..4d56993 100644 --- a/arch/arm/mach-iop13xx/iq81340sc.c +++ b/arch/arm/mach-iop13xx/iq81340sc.c @@ -61,6 +61,7 @@ static struct hw_pci iq81340sc_pci __initdata = { .scan = iop13xx_scan_bus, .map_irq= iq81340sc_atux_map_irq, .preinit= iop13xx_pci_init + .add_bus= iop13xx_add_bus; }; static int __init iq81340sc_pci_init(void) diff --git a/arch/arm/mach-iop13xx/msi.c b/arch/arm/mach-iop13xx/msi.c index e7730cf..1a8cb2f 100644 --- a/arch/arm/mach-iop13xx/msi.c +++ b/arch/arm/mach-iop13xx/msi.c @@ -132,7 +132,7 @@ static struct irq_chip iop13xx_msi_chip = { .irq_unmask = unmask_msi_irq, }; -int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) +static int iop13xx_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) { int id, irq = irq_alloc_desc_from(IRQ_IOP13XX_MSI_0, -1); struct msi_msg msg; @@ -159,7 +159,12 @@ int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) return 0; } -void arch_teardown_msi_irq(unsigned int irq) +static void iop13xx_teardown_msi_irq(unsigned int irq) { irq_free_desc(irq); } + +struct msi_chip iop13xx_chip = { + .setup_irq = iop13xx_setup_msi_irq, + .teardown_irq = iop13xx_teardown_msi_irq, +}; diff --git a/arch/arm/mach-iop13xx/pci.c b/arch/arm/mach-iop13xx/pci.c index 9082b84..f498800 100644 --- a/arch/arm/mach-iop13xx/pci.c +++ b/arch/arm/mach-iop13xx/pci.c @@ -962,6 +962,12 @@ void __init iop13xx_atu_select(struct hw_pci *plat_pci) } } +void iop13xx_add_bus(struct pci_bus *bus) +{ + if (IS_ENABLED(CONFIG_PCI_MSI)) + bus-msi = iop13xx_msi_chip; +} + void __init iop13xx_pci_init(void) { /* clear pre-existing south bridge errors */ -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 02/22] PCI/MSI: Remove useless bus-msi assignment
Currently, PCI drivers will initialize bus-msi in pcibios_add_bus(). pcibios_add_bus() will be called in every pci bus initialization. So the bus-msi assignment in pci_alloc_child_bus() is useless. Signed-off-by: Yijing Wang wangyij...@huawei.com CC: Thierry Reding thierry.red...@gmail.com CC: Thomas Petazzoni thomas.petazz...@free-electrons.com --- drivers/pci/probe.c |1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index e3cf8a2..8296576 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -677,7 +677,6 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent, child-parent = parent; child-ops = parent-ops; - child-msi = parent-msi; child-sysdata = parent-sysdata; child-bus_flags = parent-bus_flags; -- 1.7.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 00/22] Use MSI chip framework to configure MSI/MSI-X in all platforms
This series is based Bjorn's pci/msi branch git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git pci/msi Currently, there are a lot of weak arch functions in MSI code. Thierry Reding Introduced MSI chip framework to configure MSI/MSI-X in arm. This series use MSI chip framework to refactor MSI code across all platforms to eliminate weak arch functions. Then all MSI irqs will be managed in a unified framework. Because this series changed a lot of ARCH MSI code, so tests in the platforms which MSI code modified are warmly welcomed! v1-v2: Add a patch to make s390 MSI code build happy between patch x86/xen/MSI: E.. and s390/MSI: Use MSI... Fix several typo problems found by Lucas. RFC-v1: Updated [patch 4/21] x86/xen/MSI: Eliminate..., export msi_chip instead of #ifdef to fix MSI bug in xen running in x86. Rename arch_get_match_msi_chip() to arch_find_msi_chip(). Drop use struct device as the msi_chip argument, we will do that later in another patchset. Yijing Wang (22): PCI/MSI: Clean up struct msi_chip argument PCI/MSI: Remove useless bus-msi assignment MSI: Remove the redundant irq_set_chip_data() x86/xen/MSI: Eliminate arch_msix_mask_irq() and arch_msi_mask_irq() s390/MSI: Use __msi_mask_irq() instead of default_msi_mask_irq() PCI/MSI: Introduce weak arch_find_msi_chip() to find MSI chip PCI/MSI: Refactor struct msi_chip to make it become more common x86/MSI: Use MSI chip framework to configure MSI/MSI-X irq x86/xen/MSI: Use MSI chip framework to configure MSI/MSI-X irq Irq_remapping/MSI: Use MSI chip framework to configure MSI/MSI-X irq x86/MSI: Remove unused MSI weak arch functions MIPS/Octeon/MSI: Use MSI chip framework to configure MSI/MSI-X irq MIPS/Xlp: Remove the dead function destroy_irq() to fix build error MIPS/Xlp/MSI: Use MSI chip framework to configure MSI/MSI-X irq MIPS/Xlr/MSI: Use MSI chip framework to configure MSI/MSI-X irq Powerpc/MSI: Use MSI chip framework to configure MSI/MSI-X irq s390/MSI: Use MSI chip framework to configure MSI/MSI-X irq arm/iop13xx/MSI: Use MSI chip framework to configure MSI/MSI-X irq IA64/MSI: Use MSI chip framework to configure MSI/MSI-X irq Sparc/MSI: Use MSI chip framework to configure MSI/MSI-X irq tile/MSI: Use MSI chip framework to configure MSI/MSI-X irq PCI/MSI: Clean up unused MSI arch functions arch/arm/mach-iop13xx/include/mach/pci.h |2 + arch/arm/mach-iop13xx/iq81340mc.c|1 + arch/arm/mach-iop13xx/iq81340sc.c|1 + arch/arm/mach-iop13xx/msi.c |9 ++- arch/arm/mach-iop13xx/pci.c |6 ++ arch/ia64/kernel/msi_ia64.c | 18 - arch/mips/pci/msi-octeon.c | 35 ++ arch/mips/pci/msi-xlp.c | 18 -- arch/mips/pci/pci-xlr.c | 15 - arch/powerpc/kernel/msi.c| 14 +++- arch/s390/pci/pci.c | 18 - arch/sparc/kernel/pci.c | 14 +++- arch/tile/kernel/pci_gx.c| 14 +++- arch/x86/include/asm/apic.h |4 + arch/x86/include/asm/pci.h |4 +- arch/x86/include/asm/x86_init.h |7 -- arch/x86/kernel/apic/io_apic.c | 16 - arch/x86/kernel/x86_init.c | 34 - arch/x86/pci/xen.c | 60 +--- drivers/iommu/irq_remapping.c|9 ++- drivers/irqchip/irq-armada-370-xp.c |8 +-- drivers/pci/host/pci-tegra.c |8 ++- drivers/pci/host/pcie-designware.c |4 +- drivers/pci/host/pcie-rcar.c |8 ++- drivers/pci/msi.c| 114 ++ drivers/pci/probe.c |1 - include/linux/msi.h | 26 ++- 27 files changed, 266 insertions(+), 202 deletions(-) ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu