[PATCH v2] iommu/arm-smmu: Make use of phandle iterators in device-tree device-tree parsing
On Tue, Mar 22, 2016 at 01:38:06PM -0500, Rob Herring wrote: > > + struct of_phandle_iterator it; > > + struct arm_smmu_phandle_args masterspec; > > Isn't this a bit big to put on the stack being ~512 bytes? Yeah, you might be right. I havn't seen any problems booting with this being allocated on the stack, but to be on the safe side I changed the patch to allocate the masterspec with kmalloc, patch below. Joerg >From 85995d1edea7f61aae3c31e0fbd3258622d0b5ae Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 16 Mar 2016 17:10:10 +0100 Subject: [PATCH] iommu/arm-smmu: Make use of phandle iterators in device-tree parsing Remove the usage of of_parse_phandle_with_args() and replace it by the phandle-iterator implementation so that we can parse out all of the potentially present 128 stream-ids. Signed-off-by: Joerg Roedel --- drivers/iommu/arm-smmu.c | 41 + 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 59ee4b8..fa9b98c 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -48,7 +48,7 @@ #include "io-pgtable.h" /* Maximum number of stream IDs assigned to a single device */ -#define MAX_MASTER_STREAMIDS MAX_PHANDLE_ARGS +#define MAX_MASTER_STREAMIDS 128 /* Maximum number of context banks per SMMU */ #define ARM_SMMU_MAX_CBS 128 @@ -349,6 +349,12 @@ struct arm_smmu_domain { struct iommu_domain domain; }; +struct arm_smmu_phandle_args { + struct device_node *np; + int args_count; + uint32_t args[MAX_MASTER_STREAMIDS]; +}; + static struct iommu_ops arm_smmu_ops; static DEFINE_SPINLOCK(arm_smmu_devices_lock); @@ -458,7 +464,7 @@ static int insert_smmu_master(struct arm_smmu_device *smmu, static int register_smmu_master(struct arm_smmu_device *smmu, struct device *dev, - struct of_phandle_args *masterspec) + struct arm_smmu_phandle_args *masterspec) { int i; struct arm_smmu_master *master; @@ -1716,7 +1722,8 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev) struct arm_smmu_device *smmu; struct device *dev = &pdev->dev; struct rb_node *node; - struct of_phandle_args masterspec; + struct of_phandle_iterator it; + struct arm_smmu_phandle_args *masterspec; int num_irqs, i, err; smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL); @@ -1777,20 +1784,38 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev) i = 0; smmu->masters = RB_ROOT; - while (!of_parse_phandle_with_args(dev->of_node, "mmu-masters", - "#stream-id-cells", i, - &masterspec)) { - err = register_smmu_master(smmu, dev, &masterspec); + + err = -ENOMEM; + /* No need to zero the memory for masterspec */ + masterspec = kmalloc(sizeof(*masterspec), GFP_KERNEL); + if (!masterspec) + goto out_put_masters; + + of_for_each_phandle(&it, err, dev->of_node, + "mmu-masters", "#stream-id-cells", 0) { + int count = of_phandle_iterator_args(&it, masterspec->args, +MAX_MASTER_STREAMIDS); + masterspec->np = of_node_get(it.node); + masterspec->args_count = count; + + err = register_smmu_master(smmu, dev, masterspec); if (err) { dev_err(dev, "failed to add master %s\n", - masterspec.np->name); + masterspec->np->name); + kfree(masterspec); goto out_put_masters; } i++; } + + if (i == 0) + goto out_put_masters; + dev_notice(dev, "registered %d master devices\n", i); + kfree(masterspec); + parse_driver_options(smmu); if (smmu->version > ARM_SMMU_V1 && -- 2.4.3 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 6/6] iommu/arm-smmu: Make use of phandle iterators in device-tree parsing
Hi Robin, On Tue, Mar 22, 2016 at 06:53:48PM +, Robin Murphy wrote: > In a stream-matching implementation, a device may quite legitimately > own anything up to _all_ of the stream IDs (32768, or 65536 if we > ever implement support for the SMMUv2 EXID extension), so this is > only a genuine limit for stream indexing (and if anyone ever > actually made one of those, I don't think they're running mainline > on it). Do you mean we might see a lot more than the currently 128 supported stream-ids for an smmu? > Alternatively, how straightforward is it to change the DT on your > machine? I'll be getting a v2 of [1] out in a couple of weeks (after > imminent holidays), which already gets rid of MAX_MASTER_STREAMIDS > altogether, and might also have grown proper SMR support by then. Hmm, I don't know how to change the DT of this Seattle machine. I think it is provided by the ACPI BIOS. At least it boots with grub2 and not u-boot and there is no DT in /boot. Joerg ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 0/6] of: Implement iterator for phandles
Hi Rob, On Tue, Mar 22, 2016 at 01:45:41PM -0500, Rob Herring wrote: > On Tue, Mar 22, 2016 at 12:58 PM, Joerg Roedel wrote: > > Please review. Patches are based on v4.5. > > Other than my one comment, this looks good to me. For the series: > > Acked-by: Rob Herring Thanks a lot for your fast reply! I guess these patches will go through the DT tree, or should I carry them in the IOMMU tree? The DT tree probably makes more sense. Joerg ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[Patch V3 1/4] iommu/vt-d: replace *hdr with drhd[0] in struct dmar_drhd_unit
Before commit <6b1972493a84> ("iommu/vt-d: Implement DMAR unit hotplug framework"),dmaru->hdr just points to the memory region of DMA remapping hardware definition. In this case, it would have no difference to where we put hdr. After this commit, DMA remapping hardware definition is copied and attach to the end of dmaru structure. By replacing a pointer with a zero-sized array, that would save some space for this structure. This patch replace *hdr with drhd[0] in struct dmar_drhd_unit and change the type from acpi_dmar_header to acpi_dmar_hardware_unit. By doing so, it reflects the real data type contained in dmar_drhd_unit and avoid some type cast between them. Besides this, this patch includes another change: * remove redundant type cast to the same type in dmar_table_detect() Signed-off-by: Wei Yang --- drivers/iommu/dmar.c| 17 + drivers/iommu/intel_irq_remapping.c | 10 -- include/linux/dmar.h|3 ++- 3 files changed, 11 insertions(+), 19 deletions(-) diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index 80e3c17..80199b3 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -292,8 +292,7 @@ static int dmar_pci_bus_add_dev(struct dmar_pci_notify_info *info) if (dmaru->include_all) continue; - drhd = container_of(dmaru->hdr, - struct acpi_dmar_hardware_unit, header); + drhd = dmaru->drhd; ret = dmar_insert_dev_scope(info, (void *)(drhd + 1), ((void *)drhd) + drhd->header.length, dmaru->segment, @@ -390,8 +389,7 @@ static int dmar_parse_one_drhd(struct acpi_dmar_header *header, void *arg) * If header is allocated from slab by ACPI _DSM method, we need to * copy the content because the memory buffer will be freed on return. */ - dmaru->hdr = (void *)(dmaru + 1); - memcpy(dmaru->hdr, header, header->length); + memcpy(dmaru->drhd, drhd, drhd->header.length); dmaru->reg_base_addr = drhd->address; dmaru->segment = drhd->segment; dmaru->include_all = drhd->flags & 0x1; /* BIT0: INCLUDE_ALL */ @@ -529,8 +527,7 @@ static int __init dmar_table_detect(void) /* if we could find DMAR table, then there are DMAR devices */ status = acpi_get_table_with_size(ACPI_SIG_DMAR, 0, - (struct acpi_table_header **)&dmar_tbl, - &dmar_tbl_size); + &dmar_tbl, &dmar_tbl_size); if (ACPI_SUCCESS(status) && !dmar_tbl) { pr_warn("Unable to map DMAR\n"); @@ -663,9 +660,7 @@ dmar_find_matched_drhd_unit(struct pci_dev *dev) rcu_read_lock(); for_each_drhd_unit(dmaru) { - drhd = container_of(dmaru->hdr, - struct acpi_dmar_hardware_unit, - header); + drhd = dmaru->drhd; if (dmaru->include_all && drhd->segment == pci_domain_nr(dev->bus)) @@ -693,9 +688,7 @@ static void __init dmar_acpi_insert_dev_scope(u8 device_number, struct acpi_dmar_pci_path *path; for_each_drhd_unit(dmaru) { - drhd = container_of(dmaru->hdr, - struct acpi_dmar_hardware_unit, - header); + drhd = dmaru->drhd; for (scope = (void *)(drhd + 1); (unsigned long)scope < ((unsigned long)drhd) + drhd->header.length; diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c index 1fae188..e35062e 100644 --- a/drivers/iommu/intel_irq_remapping.c +++ b/drivers/iommu/intel_irq_remapping.c @@ -886,17 +886,15 @@ static int ir_parse_one_ioapic_scope(struct acpi_dmar_device_scope *scope, return 0; } -static int ir_parse_ioapic_hpet_scope(struct acpi_dmar_header *header, +static int ir_parse_ioapic_hpet_scope(struct acpi_dmar_hardware_unit *drhd, struct intel_iommu *iommu) { int ret = 0; - struct acpi_dmar_hardware_unit *drhd; struct acpi_dmar_device_scope *scope; void *start, *end; - drhd = (struct acpi_dmar_hardware_unit *)header; start = (void *)(drhd + 1); - end = ((void *)drhd) + header->length; + end = ((void *)drhd) + drhd->header.length; while (start < end && ret == 0) { scope = start; @@ -940,7 +938,7 @@ static int __init parse_ioapics_under_ir(void) if (!ecap_ir_support(iommu->ecap)) continue; - ret = ir_parse_ioapic_hpet_scope(drhd->hdr, iommu); + ret = ir_parse_ioapic_hpet_scope(drhd->drhd, iommu); if (ret) return ret; @@ -1420,7 +1418,
[Patch V3 2/4] iommu/vt-d: use zero-sized array in DMAR related ACPI structures
1. DMAR table has variable number of remapping entries 2. DMAR hardware unit has variable number of device scope 3. DMAR device scope has variable number of pci path In current implementation, we use (head + 1) to access these variable number elements, which may not be obvious for audience. Zero-sized array is usually used for this purpose. This patch adds zero-sized array for variable elements in DMAR ACPI structures, which tries to make the code more audience friendly. Signed-off-by: Wei Yang --- drivers/iommu/dmar.c | 22 ++ include/acpi/actbl2.h | 31 +-- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index 80199b3..6bff602 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -225,7 +225,6 @@ int dmar_insert_dev_scope(struct dmar_pci_notify_info *info, int i, level; struct device *tmp, *dev = &info->dev->dev; struct acpi_dmar_device_scope *scope; - struct acpi_dmar_pci_path *path; if (segment != info->seg) return 0; @@ -236,9 +235,8 @@ int dmar_insert_dev_scope(struct dmar_pci_notify_info *info, scope->entry_type != ACPI_DMAR_SCOPE_TYPE_BRIDGE) continue; - path = (struct acpi_dmar_pci_path *)(scope + 1); - level = (scope->length - sizeof(*scope)) / sizeof(*path); - if (!dmar_match_pci_path(info, scope->bus, path, level)) + level = (scope->length - sizeof(*scope)) / sizeof(*scope->path); + if (!dmar_match_pci_path(info, scope->bus, scope->path, level)) continue; if ((scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT) ^ @@ -393,7 +391,7 @@ static int dmar_parse_one_drhd(struct acpi_dmar_header *header, void *arg) dmaru->reg_base_addr = drhd->address; dmaru->segment = drhd->segment; dmaru->include_all = drhd->flags & 0x1; /* BIT0: INCLUDE_ALL */ - dmaru->devices = dmar_alloc_dev_scope((void *)(drhd + 1), + dmaru->devices = dmar_alloc_dev_scope(drhd->dev_scope, ((void *)drhd) + drhd->header.length, &dmaru->devices_cnt); if (dmaru->devices_cnt && dmaru->devices == NULL) { @@ -579,7 +577,7 @@ static int dmar_walk_remapping_entries(struct acpi_dmar_header *start, static inline int dmar_walk_dmar_table(struct acpi_table_dmar *dmar, struct dmar_res_callback *cb) { - return dmar_walk_remapping_entries((void *)(dmar + 1), + return dmar_walk_remapping_entries(dmar->remapping_entries, dmar->header.length - sizeof(*dmar), cb); } @@ -685,12 +683,11 @@ static void __init dmar_acpi_insert_dev_scope(u8 device_number, struct acpi_dmar_device_scope *scope; struct device *tmp; int i; - struct acpi_dmar_pci_path *path; for_each_drhd_unit(dmaru) { drhd = dmaru->drhd; - for (scope = (void *)(drhd + 1); + for (scope = drhd->dev_scope; (unsigned long)scope < ((unsigned long)drhd) + drhd->header.length; scope = ((void *)scope) + scope->length) { if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_NAMESPACE) @@ -698,15 +695,16 @@ static void __init dmar_acpi_insert_dev_scope(u8 device_number, if (scope->enumeration_id != device_number) continue; - path = (void *)(scope + 1); pr_info("ACPI device \"%s\" under DMAR at %llx as %02x:%02x.%d\n", dev_name(&adev->dev), dmaru->reg_base_addr, - scope->bus, path->device, path->function); + scope->bus, scope->path->device, + scope->path->function); for_each_dev_scope(dmaru->devices, dmaru->devices_cnt, i, tmp) if (tmp == NULL) { dmaru->devices[i].bus = scope->bus; - dmaru->devices[i].devfn = PCI_DEVFN(path->device, - path->function); + dmaru->devices[i].devfn = + PCI_DEVFN(scope->path->device, + scope->path->function); rcu_assign_pointer(dmaru->devices[i].dev, get_device(&adev->dev)); return; diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h index 6e28f54..fd5c615 100644 --- a/include/acp
[Patch V3 0/4] Code refine for Intel IOMMU
These four patches try to refine the Intel IOMMU. Patch 1/2 tries to make it more user friendly by add a zero-sized array in some dmar data structure. Patch 3 move the ckeck of Register Base Address ahead to avoid cleanup when it is NULL. Patch 4 re-use dmar_walk_dmar_table() to make the code easy to understand. V3: * change hdr to drhd from type acpi_dmar_header to acpi_dmar_hardware_unit * add reason in changelog for the change in Patch 1 V2: * add patch 3 and 4 Wei Yang (4): iommu/vt-d: replace *hdr with drhd[0] in struct dmar_drhd_unit iommu/vt-d: use zero-sized array in DMAR related ACPI structures iommu/vt-d: check Register Base Address at the beginning of dmar_parse_one_drhd() iommu/vt-d: refine dmar_acpi_dev_scope_init() with dmar_walk_dmar_table() drivers/iommu/dmar.c| 129 +-- drivers/iommu/intel_irq_remapping.c | 10 ++- include/acpi/actbl2.h | 31 + include/linux/dmar.h|3 +- 4 files changed, 87 insertions(+), 86 deletions(-) -- 1.7.9.5 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[Patch V3 3/4] iommu/vt-d: check Register Base Address at the beginning of dmar_parse_one_drhd()
A NULL value of Register Base Address in a Hardware Unit Definition means it is an invalid dmar. Current implementation checks this value in alloc_iommu(), by when it has already allocated memory to store itself and device scope. This patch moves the check at the beginning of dmar_parse_one_drhd(), so that it notices this is an invalid dmar and avoids related setup jobs. Signed-off-by: Wei Yang --- drivers/iommu/dmar.c | 34 +- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index 6bff602..35fc8fb 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -363,6 +363,18 @@ dmar_find_dmaru(struct acpi_dmar_hardware_unit *drhd) return NULL; } +static void warn_invalid_dmar(u64 addr, const char *message) +{ + WARN_TAINT_ONCE( + 1, TAINT_FIRMWARE_WORKAROUND, + "Your BIOS is broken; DMAR reported at address %llx%s!\n" + "BIOS vendor: %s; Ver: %s; Product Version: %s\n", + addr, message, + dmi_get_system_info(DMI_BIOS_VENDOR), + dmi_get_system_info(DMI_BIOS_VERSION), + dmi_get_system_info(DMI_PRODUCT_VERSION)); +} + /** * dmar_parse_one_drhd - parses exactly one DMA remapping hardware definition * structure which uniquely represent one DMA remapping hardware unit @@ -379,6 +391,11 @@ static int dmar_parse_one_drhd(struct acpi_dmar_header *header, void *arg) if (dmaru) goto out; + if (!drhd->address) { + warn_invalid_dmar(0, ""); + return -EINVAL; + } + dmaru = kzalloc(sizeof(*dmaru) + header->length, GFP_KERNEL); if (!dmaru) return -ENOMEM; @@ -808,18 +825,6 @@ int __init dmar_table_init(void) return dmar_table_initialized < 0 ? dmar_table_initialized : 0; } -static void warn_invalid_dmar(u64 addr, const char *message) -{ - WARN_TAINT_ONCE( - 1, TAINT_FIRMWARE_WORKAROUND, - "Your BIOS is broken; DMAR reported at address %llx%s!\n" - "BIOS vendor: %s; Ver: %s; Product Version: %s\n", - addr, message, - dmi_get_system_info(DMI_BIOS_VENDOR), - dmi_get_system_info(DMI_BIOS_VERSION), - dmi_get_system_info(DMI_PRODUCT_VERSION)); -} - static int __ref dmar_validate_one_drhd(struct acpi_dmar_header *entry, void *arg) { @@ -995,11 +1000,6 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd) int msagaw = 0; int err; - if (!drhd->reg_base_addr) { - warn_invalid_dmar(0, ""); - return -EINVAL; - } - iommu = kzalloc(sizeof(*iommu), GFP_KERNEL); if (!iommu) return -ENOMEM; -- 1.7.9.5 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[Patch V3 4/4] iommu/vt-d: refine dmar_acpi_dev_scope_init() with dmar_walk_dmar_table()
dmar_acpi_dev_scope_init() iterates on the remapping structure and just do proper job for ANDD structure. This is the what dmar_walk_dmar_table() does. This patch improves the code with dmar_walk_dmar_table(). Signed-off-by: Wei Yang --- drivers/iommu/dmar.c | 56 -- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index 35fc8fb..6281b45 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -733,36 +733,44 @@ static void __init dmar_acpi_insert_dev_scope(u8 device_number, device_number, dev_name(&adev->dev)); } -static int __init dmar_acpi_dev_scope_init(void) +static int __dmar_acpi_dev_scope_init(struct acpi_dmar_header *header, + void *arg) { struct acpi_dmar_andd *andd; + acpi_handle h; + struct acpi_device *adev; + + andd = (struct acpi_dmar_andd *)header; + if (!ACPI_SUCCESS(acpi_get_handle(ACPI_ROOT_OBJECT, + andd->device_name, + &h))) { + pr_err("Failed to find handle for ACPI object %s\n", + andd->device_name); + return 0; + } + if (acpi_bus_get_device(h, &adev)) { + pr_err("Failed to get device for ACPI object %s\n", + andd->device_name); + return 0; + } + dmar_acpi_insert_dev_scope(andd->device_number, adev); + return 0; +} + +static int __init dmar_acpi_dev_scope_init(void) +{ + struct acpi_table_dmar *dmar; + struct dmar_res_callback cb = { + .print_entry = false, + .ignore_unhandled = true, + .cb[ACPI_DMAR_TYPE_NAMESPACE] = &__dmar_acpi_dev_scope_init, + }; if (dmar_tbl == NULL) return -ENODEV; - for (andd = (void *)dmar_tbl + sizeof(struct acpi_table_dmar); -((unsigned long)andd) < ((unsigned long)dmar_tbl) + dmar_tbl->length; -andd = ((void *)andd) + andd->header.length) { - if (andd->header.type == ACPI_DMAR_TYPE_NAMESPACE) { - acpi_handle h; - struct acpi_device *adev; - - if (!ACPI_SUCCESS(acpi_get_handle(ACPI_ROOT_OBJECT, - andd->device_name, - &h))) { - pr_err("Failed to find handle for ACPI object %s\n", - andd->device_name); - continue; - } - if (acpi_bus_get_device(h, &adev)) { - pr_err("Failed to get device for ACPI object %s\n", - andd->device_name); - continue; - } - dmar_acpi_insert_dev_scope(andd->device_number, adev); - } - } - return 0; + dmar = (struct acpi_table_dmar *)dmar_tbl; + return dmar_walk_dmar_table(dmar, &cb); } int __init dmar_dev_scope_init(void) -- 1.7.9.5 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v2] iommu/arm-smmu: Make use of phandle iterators in device-tree device-tree parsing
Hi Joerg, [auto build test ERROR on iommu/next] [also build test ERROR on v4.5 next-20160323] [if your patch is applied to the wrong git tree, please drop us a note to help improving the system] url: https://github.com/0day-ci/linux/commits/Joerg-Roedel/iommu-arm-smmu-Make-use-of-phandle-iterators-in-device-tree-device-tree-parsing/20160323-194824 base: https://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git next config: arm64-defconfig (attached as .config) reproduce: wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree make.cross ARCH=arm64 All errors (new ones prefixed by >>): drivers/iommu/arm-smmu.c: In function 'arm_smmu_device_dt_probe': drivers/iommu/arm-smmu.c:1746:29: error: storage size of 'it' isn't known struct of_phandle_iterator it; ^ >> drivers/iommu/arm-smmu.c:1815:2: error: implicit declaration of function >> 'of_for_each_phandle' [-Werror=implicit-function-declaration] of_for_each_phandle(&it, err, dev->of_node, ^ >> drivers/iommu/arm-smmu.c:1816:46: error: expected ';' before '{' token "mmu-masters", "#stream-id-cells", 0) { ^ drivers/iommu/arm-smmu.c:1746:29: warning: unused variable 'it' [-Wunused-variable] struct of_phandle_iterator it; ^ drivers/iommu/arm-smmu.c: At top level: drivers/iommu/arm-smmu.c:473:12: warning: 'register_smmu_master' defined but not used [-Wunused-function] static int register_smmu_master(struct arm_smmu_device *smmu, ^ cc1: some warnings being treated as errors vim +/of_for_each_phandle +1815 drivers/iommu/arm-smmu.c 1740 { 1741 const struct of_device_id *of_id; 1742 struct resource *res; 1743 struct arm_smmu_device *smmu; 1744 struct device *dev = &pdev->dev; 1745 struct rb_node *node; > 1746 struct of_phandle_iterator it; 1747 struct arm_smmu_phandle_args *masterspec; 1748 int num_irqs, i, err; 1749 1750 smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL); 1751 if (!smmu) { 1752 dev_err(dev, "failed to allocate arm_smmu_device\n"); 1753 return -ENOMEM; 1754 } 1755 smmu->dev = dev; 1756 1757 of_id = of_match_node(arm_smmu_of_match, dev->of_node); 1758 smmu->version = (enum arm_smmu_arch_version)of_id->data; 1759 1760 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1761 smmu->base = devm_ioremap_resource(dev, res); 1762 if (IS_ERR(smmu->base)) 1763 return PTR_ERR(smmu->base); 1764 smmu->size = resource_size(res); 1765 1766 if (of_property_read_u32(dev->of_node, "#global-interrupts", 1767 &smmu->num_global_irqs)) { 1768 dev_err(dev, "missing #global-interrupts property\n"); 1769 return -ENODEV; 1770 } 1771 1772 num_irqs = 0; 1773 while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, num_irqs))) { 1774 num_irqs++; 1775 if (num_irqs > smmu->num_global_irqs) 1776 smmu->num_context_irqs++; 1777 } 1778 1779 if (!smmu->num_context_irqs) { 1780 dev_err(dev, "found %d interrupts but expected at least %d\n", 1781 num_irqs, smmu->num_global_irqs + 1); 1782 return -ENODEV; 1783 } 1784 1785 smmu->irqs = devm_kzalloc(dev, sizeof(*smmu->irqs) * num_irqs, 1786GFP_KERNEL); 1787 if (!smmu->irqs) { 1788 dev_err(dev, "failed to allocate %d irqs\n", num_irqs); 1789 return -ENOMEM; 1790 } 1791 1792 for (i = 0; i < num_irqs; ++i) { 1793 int irq = platform_get_irq(pdev, i); 1794 1795 if (irq < 0) { 1796 dev_err(dev, "failed to get irq index %d\n", i); 1797 return -ENODEV; 1798 } 1799 smmu->irqs[i] = irq; 1800 } 1801 1802 err = arm_smmu_device_cfg_probe(smmu); 1803 if (err) 1804 return err; 1805 1806 i = 0; 1807 smmu->masters = RB_ROOT; 1
Re: [v2] powerpc: Fix incorrect PPC32 PAMU dependency
> -Original Message- > From: Andy Fleming > To: j...@8bytes.org > Cc: iommu@lists.linux-foundation.org, linuxppc-...@lists.ozlabs.org > Subject: [v2] powerpc: Fix incorrect PPC32 PAMU dependency > > The Freescale PAMU can be enabled on both 32 and 64-bit Power > chips. Commit 477ab7a19cec8409e4e2dd10e7348e4cac3c06e5 > (iommu: Make more drivers depend on COMPILE_TEST) > restricted PAMU to PPC32. PPC covers both. > > Signed-off-by: Andy Fleming Tested-by: Madalin Bucur ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
RE: [v2] powerpc: Fix incorrect PPC32 PAMU dependency
> -Original Message- > From: Linuxppc-dev [mailto:linuxppc-dev- > bounces+varun.sethi=freescale@lists.ozlabs.org] On Behalf Of Madalin- > Cristian Bucur > Sent: Wednesday, March 23, 2016 3:29 PM > To: j...@8bytes.org; Andy Fleming > Cc: iommu@lists.linux-foundation.org; linuxppc-...@lists.ozlabs.org > Subject: Re: [v2] powerpc: Fix incorrect PPC32 PAMU dependency > > > -Original Message- > > From: Andy Fleming > > To: j...@8bytes.org > > Cc: iommu@lists.linux-foundation.org, linuxppc-...@lists.ozlabs.org > > Subject: [v2] powerpc: Fix incorrect PPC32 PAMU dependency > > > > The Freescale PAMU can be enabled on both 32 and 64-bit Power chips. > > Commit 477ab7a19cec8409e4e2dd10e7348e4cac3c06e5 > > (iommu: Make more drivers depend on COMPILE_TEST) restricted PAMU to > > PPC32. PPC covers both. > > > > Signed-off-by: Andy Fleming > > Tested-by: Madalin Bucur > Ackd-by: Varun Sethi ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH] intel-iommu: fix up comment
dma_pte_free_pagetable no longer depends on last level ptes being clear, it clears them itself. Fix up the comment to match. Cc: Jiang Liu Suggested-by: Alex Williamson Signed-off-by: Michael S. Tsirkin --- 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 a2e1b7f..0100553 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -1143,7 +1143,7 @@ next: } while (!first_pte_in_page(++pte) && pfn <= last_pfn); } -/* free page table pages. last level pte should already be cleared */ +/* clear last level (leaf) ptes and free page table pages. */ static void dma_pte_free_pagetable(struct dmar_domain *domain, unsigned long start_pfn, unsigned long last_pfn) -- MST ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 0/6] of: Implement iterator for phandles
On Wed, Mar 23, 2016 at 6:54 AM, Joerg Roedel wrote: > Hi Rob, > > On Tue, Mar 22, 2016 at 01:45:41PM -0500, Rob Herring wrote: >> On Tue, Mar 22, 2016 at 12:58 PM, Joerg Roedel wrote: >> > Please review. Patches are based on v4.5. >> >> Other than my one comment, this looks good to me. For the series: >> >> Acked-by: Rob Herring > > Thanks a lot for your fast reply! I guess these patches will go through > the DT tree, or should I carry them in the IOMMU tree? The DT tree > probably makes more sense. Sure, I can take them. Rob ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[Patch V2 2/2] iommu: remove sysfs_link to device in iommu_group/devices when failed
The original code forgets to remove the sysfs_link to a device in iommu_group/devices directory, when the creation fails or conflicts on the name. This patch tries to remove the sysfs_link on the failure. Signed-off-by: Wei Yang --- drivers/iommu/iommu.c |1 + 1 file changed, 1 insertion(+) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 2696a38..8f480ba 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -403,6 +403,7 @@ rename: ret = sysfs_create_link_nowarn(group->devices_kobj, &dev->kobj, device->name); if (ret) { + sysfs_remove_link(group->devices_kobj, device->name); kfree(device->name); if (ret == -EEXIST && i >= 0) { /* -- 1.7.9.5 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[Patch V2 1/2] iommu: remove the iommu_callback_data
According to the code path, iommu_callback_data is passed in iommu_bus_init() and just used in {add/remove}_iommu_group, by when the bus->iommu_ops is already set up properly. This patch removes the iommu_callback_data by retrieving iommu_ops from bus->iommu_ops directly. Signed-off-by: Wei Yang --- drivers/iommu/iommu.c | 21 ++--- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 0e3b009..2696a38 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -37,10 +37,6 @@ static struct kset *iommu_group_kset; static struct ida iommu_group_ida; static struct mutex iommu_group_mutex; -struct iommu_callback_data { - const struct iommu_ops *ops; -}; - struct iommu_group { struct kobject kobj; struct kobject *devices_kobj; @@ -867,8 +863,7 @@ struct iommu_domain *iommu_group_default_domain(struct iommu_group *group) static int add_iommu_group(struct device *dev, void *data) { - struct iommu_callback_data *cb = data; - const struct iommu_ops *ops = cb->ops; + const struct iommu_ops *ops = dev->bus->iommu_ops; int ret; if (!ops->add_device) @@ -891,8 +886,7 @@ static int add_iommu_group(struct device *dev, void *data) static int remove_iommu_group(struct device *dev, void *data) { - struct iommu_callback_data *cb = data; - const struct iommu_ops *ops = cb->ops; + const struct iommu_ops *ops = dev->bus->iommu_ops; if (ops->remove_device && dev->iommu_group) ops->remove_device(dev); @@ -953,13 +947,10 @@ static int iommu_bus_notifier(struct notifier_block *nb, return 0; } -static int iommu_bus_init(struct bus_type *bus, const struct iommu_ops *ops) +static int iommu_bus_init(struct bus_type *bus) { int err; struct notifier_block *nb; - struct iommu_callback_data cb = { - .ops = ops, - }; nb = kzalloc(sizeof(struct notifier_block), GFP_KERNEL); if (!nb) @@ -971,7 +962,7 @@ static int iommu_bus_init(struct bus_type *bus, const struct iommu_ops *ops) if (err) goto out_free; - err = bus_for_each_dev(bus, NULL, &cb, add_iommu_group); + err = bus_for_each_dev(bus, NULL, NULL, add_iommu_group); if (err) goto out_err; @@ -980,7 +971,7 @@ static int iommu_bus_init(struct bus_type *bus, const struct iommu_ops *ops) out_err: /* Clean up */ - bus_for_each_dev(bus, NULL, &cb, remove_iommu_group); + bus_for_each_dev(bus, NULL, NULL, remove_iommu_group); bus_unregister_notifier(bus, nb); out_free: @@ -1012,7 +1003,7 @@ int bus_set_iommu(struct bus_type *bus, const struct iommu_ops *ops) bus->iommu_ops = ops; /* Do IOMMU specific setup for this bus-type */ - err = iommu_bus_init(bus, ops); + err = iommu_bus_init(bus); if (err) bus->iommu_ops = NULL; -- 1.7.9.5 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[Patch V2 0/2] Cleanup on IOMMU
This two patches tries to do some cleanup in iommu. V2: * add patch 2 Wei Yang (2): iommu: remove the iommu_callback_data iommu: remove sysfs_link to device in iommu_group/devices when failed drivers/iommu/iommu.c | 22 +++--- 1 file changed, 7 insertions(+), 15 deletions(-) -- 1.7.9.5 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH] iommu: remove the iommu_callback_data
Obsolete this one, V2 is sent. On Sun, Mar 20, 2016 at 01:57:52AM +, Wei Yang wrote: >According to the code path, iommu_callback_data is passed in >iommu_bus_init() and just used in {add/remove}_iommu_group, by when the >bus->iommu_ops is already set up properly. > >This patch removes the iommu_callback_data by retrieving iommu_ops from >bus->iommu_ops directly. > >Signed-off-by: Wei Yang >--- > drivers/iommu/iommu.c | 21 ++--- > 1 file changed, 6 insertions(+), 15 deletions(-) > >diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c >index 0e3b009..2696a38 100644 >--- a/drivers/iommu/iommu.c >+++ b/drivers/iommu/iommu.c >@@ -37,10 +37,6 @@ static struct kset *iommu_group_kset; > static struct ida iommu_group_ida; > static struct mutex iommu_group_mutex; > >-struct iommu_callback_data { >- const struct iommu_ops *ops; >-}; >- > struct iommu_group { > struct kobject kobj; > struct kobject *devices_kobj; >@@ -867,8 +863,7 @@ struct iommu_domain *iommu_group_default_domain(struct >iommu_group *group) > > static int add_iommu_group(struct device *dev, void *data) > { >- struct iommu_callback_data *cb = data; >- const struct iommu_ops *ops = cb->ops; >+ const struct iommu_ops *ops = dev->bus->iommu_ops; > int ret; > > if (!ops->add_device) >@@ -891,8 +886,7 @@ static int add_iommu_group(struct device *dev, void *data) > > static int remove_iommu_group(struct device *dev, void *data) > { >- struct iommu_callback_data *cb = data; >- const struct iommu_ops *ops = cb->ops; >+ const struct iommu_ops *ops = dev->bus->iommu_ops; > > if (ops->remove_device && dev->iommu_group) > ops->remove_device(dev); >@@ -953,13 +947,10 @@ static int iommu_bus_notifier(struct notifier_block *nb, > return 0; > } > >-static int iommu_bus_init(struct bus_type *bus, const struct iommu_ops *ops) >+static int iommu_bus_init(struct bus_type *bus) > { > int err; > struct notifier_block *nb; >- struct iommu_callback_data cb = { >- .ops = ops, >- }; > > nb = kzalloc(sizeof(struct notifier_block), GFP_KERNEL); > if (!nb) >@@ -971,7 +962,7 @@ static int iommu_bus_init(struct bus_type *bus, const >struct iommu_ops *ops) > if (err) > goto out_free; > >- err = bus_for_each_dev(bus, NULL, &cb, add_iommu_group); >+ err = bus_for_each_dev(bus, NULL, NULL, add_iommu_group); > if (err) > goto out_err; > >@@ -980,7 +971,7 @@ static int iommu_bus_init(struct bus_type *bus, const >struct iommu_ops *ops) > > out_err: > /* Clean up */ >- bus_for_each_dev(bus, NULL, &cb, remove_iommu_group); >+ bus_for_each_dev(bus, NULL, NULL, remove_iommu_group); > bus_unregister_notifier(bus, nb); > > out_free: >@@ -1012,7 +1003,7 @@ int bus_set_iommu(struct bus_type *bus, const struct >iommu_ops *ops) > bus->iommu_ops = ops; > > /* Do IOMMU specific setup for this bus-type */ >- err = iommu_bus_init(bus, ops); >+ err = iommu_bus_init(bus); > if (err) > bus->iommu_ops = NULL; > >-- >2.5.0 -- Wei Yang Help you, Help me ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [Patch V2 2/2] iommu: remove sysfs_link to device in iommu_group/devices when failed
On Wed, 23 Mar 2016 22:25:11 + Wei Yang wrote: > The original code forgets to remove the sysfs_link to a device in > iommu_group/devices directory, when the creation fails or conflicts on the > name. > > This patch tries to remove the sysfs_link on the failure. > > Signed-off-by: Wei Yang > --- > drivers/iommu/iommu.c |1 + > 1 file changed, 1 insertion(+) > > diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c > index 2696a38..8f480ba 100644 > --- a/drivers/iommu/iommu.c > +++ b/drivers/iommu/iommu.c > @@ -403,6 +403,7 @@ rename: > ret = sysfs_create_link_nowarn(group->devices_kobj, > &dev->kobj, device->name); > if (ret) { > + sysfs_remove_link(group->devices_kobj, device->name); > kfree(device->name); > if (ret == -EEXIST && i >= 0) { > /* If we failed to create a link, potentially due to a conflicting link already present, then aren't we arbitrarily removing that conflicting link with this change? If sysfs_create_link_nowarn() fails then we haven't created a link of our own to remove. This looks wrong. Thanks, Alex ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu