Re: [PATCH V5 02/10] perf/amd/iommu: Consolidate and move perf_event_amd_iommu header

2016-03-20 Thread Borislav Petkov
On Fri, Mar 18, 2016 at 04:09:33PM +0700, Suravee Suthikulpanit wrote:
> But the whole point is that since we are moving it to consolidate these
> duplicated declarations, I think we should just put it in the most common
> place. The include/linux/amd-iommu.h file is already there. It's not like we
> have to create a brand new file, and then having to move it later.

Strictly speaking, it was wrong to put it there in the first place as it
is x86-specific.

-- 
Regards/Gruss,
Boris.

ECO tip #101: Trim your mails when you reply.
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [Patch V2 1/4] iommu/vt-d: replace *hdr with hdr[0] in struct dmar_drhd_unit

2016-03-20 Thread Thomas Gleixner
On Sun, 20 Mar 2016, Wei Yang wrote:

> hdr in struct dmar_drhd_unit is used to point the DMAR hardware unit copied
> at the end of struct dmar_drhd_unit. One zero-sized array may be more
> elegant for this purpose.

You forget to tell why. 
 
> This patch replace *hdr with hdr[0] in struct dmar_drhd_unit.
> 
> Besides this, this patch includes other two changes:
> 1. remove unnecessary type cast in dmar_table_detect()

Again. Why is it not necessary?

> 2. type cast from acpi_dmar_header to acpi_dmar_hardware_unit directly

Don't even think about doing that. container_of() is there for a reason.

Your change works today, because the embedded structure is the first one in
the containing structure. If the containing structure gets reordered later,
the whole thing will explode in hard to debug ways.

Even if such a reordering is unlikely in that ACPI case, we just don't do
that. It's bad and sloppy coding style. The generated code is the same.

Thanks,

tglx
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 1/2] iommu/vt-d: replace *hdr with hdr[0] in struct dmar_drhd_unit

2016-03-20 Thread Wei Yang
Obsolete this one. V2 is sent.

On Sat, Mar 12, 2016 at 09:57:38PM +, Wei Yang wrote:
>hdr in struct dmar_drhd_unit is used to point the DMAR hardware unit copied
>at the end of struct dmar_drhd_unit. One zero-sized array may be more
>elegant for this purpose.
>
>This patch replace *hdr with hdr[0] in struct dmar_drhd_unit.
>
>Besides this, this patch includes other two changes:
>1. remove unnecessary type cast in dmar_table_detect()
>2. type cast from acpi_dmar_header to acpi_dmar_hardware_unit directly
>
>Signed-off-by: Wei Yang 
>---
> drivers/iommu/dmar.c | 15 ---
> include/linux/dmar.h |  2 +-
> 2 files changed, 5 insertions(+), 12 deletions(-)
>
>diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
>index 80e3c17..d6dd23f 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 = (struct acpi_dmar_hardware_unit *)dmaru->hdr;
>   ret = dmar_insert_dev_scope(info, (void *)(drhd + 1),
>   ((void *)drhd) + drhd->header.length,
>   dmaru->segment,
>@@ -390,7 +389,6 @@ 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);
>   dmaru->reg_base_addr = drhd->address;
>   dmaru->segment = drhd->segment;
>@@ -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 = (struct acpi_dmar_hardware_unit *)dmaru->hdr;
> 
>   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 = (struct acpi_dmar_hardware_unit *)dmaru->hdr;
> 
>   for (scope = (void *)(drhd + 1);
>(unsigned long)scope < ((unsigned long)drhd) + 
> drhd->header.length;
>diff --git a/include/linux/dmar.h b/include/linux/dmar.h
>index e9bc929..5f6da7e 100644
>--- a/include/linux/dmar.h
>+++ b/include/linux/dmar.h
>@@ -52,7 +52,6 @@ struct dmar_dev_scope {
> extern struct acpi_table_header *dmar_tbl;
> struct dmar_drhd_unit {
>   struct list_head list;  /* list of drhd units   */
>-  struct  acpi_dmar_header *hdr;  /* ACPI header  */
>   u64 reg_base_addr;  /* register base address*/
>   struct  dmar_dev_scope *devices;/* target device array  */
>   int devices_cnt;/* target device count  */
>@@ -60,6 +59,7 @@ struct dmar_drhd_unit {
>   u8  ignored:1;  /* ignore drhd  */
>   u8  include_all:1;
>   struct intel_iommu *iommu;
>+  struct  acpi_dmar_header hdr[0];/* ACPI header  */
> };
> 
> struct dmar_pci_path {
>-- 
>2.5.0

-- 
Wei Yang
Help you, Help me
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[Patch V2 2/4] iommu/vt-d: use zero-sized array in DMAR related ACPI structures

2016-03-20 Thread Wei Yang
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 d6dd23f..04f199c 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 = (struct acpi_dmar_hardware_unit *)dmaru->hdr;
 
-   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.

[Patch V2 4/4] iommu/vt-d: refine dmar_acpi_dev_scope_init() with dmar_walk_dmar_table()

2016-03-20 Thread Wei Yang
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 82f0b92..538e260 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


[Patch V2 1/4] iommu/vt-d: replace *hdr with hdr[0] in struct dmar_drhd_unit

2016-03-20 Thread Wei Yang
hdr in struct dmar_drhd_unit is used to point the DMAR hardware unit copied
at the end of struct dmar_drhd_unit. One zero-sized array may be more
elegant for this purpose.

This patch replace *hdr with hdr[0] in struct dmar_drhd_unit.

Besides this, this patch includes other two changes:
1. remove unnecessary type cast in dmar_table_detect()
2. type cast from acpi_dmar_header to acpi_dmar_hardware_unit directly

Signed-off-by: Wei Yang 
---
 drivers/iommu/dmar.c |   15 ---
 include/linux/dmar.h |2 +-
 2 files changed, 5 insertions(+), 12 deletions(-)

diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index 80e3c17..d6dd23f 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 = (struct acpi_dmar_hardware_unit *)dmaru->hdr;
ret = dmar_insert_dev_scope(info, (void *)(drhd + 1),
((void *)drhd) + drhd->header.length,
dmaru->segment,
@@ -390,7 +389,6 @@ 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);
dmaru->reg_base_addr = drhd->address;
dmaru->segment = drhd->segment;
@@ -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 = (struct acpi_dmar_hardware_unit *)dmaru->hdr;
 
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 = (struct acpi_dmar_hardware_unit *)dmaru->hdr;
 
for (scope = (void *)(drhd + 1);
 (unsigned long)scope < ((unsigned long)drhd) + 
drhd->header.length;
diff --git a/include/linux/dmar.h b/include/linux/dmar.h
index e9bc929..5f6da7e 100644
--- a/include/linux/dmar.h
+++ b/include/linux/dmar.h
@@ -52,7 +52,6 @@ struct dmar_dev_scope {
 extern struct acpi_table_header *dmar_tbl;
 struct dmar_drhd_unit {
struct list_head list;  /* list of drhd units   */
-   struct  acpi_dmar_header *hdr;  /* ACPI header  */
u64 reg_base_addr;  /* register base address*/
struct  dmar_dev_scope *devices;/* target device array  */
int devices_cnt;/* target device count  */
@@ -60,6 +59,7 @@ struct dmar_drhd_unit {
u8  ignored:1;  /* ignore drhd  */
u8  include_all:1;
struct intel_iommu *iommu;
+   struct  acpi_dmar_header hdr[0];/* ACPI header  */
 };
 
 struct dmar_pci_path {
-- 
1.7.9.5

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[Patch V2 3/4] iommu/vt-d: check Register Base Address at the beginning of dmar_parse_one_drhd()

2016-03-20 Thread Wei Yang
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 04f199c..82f0b92 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 V2 0/4] Code refine for Intel IOMMU

2016-03-20 Thread Wei Yang
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.

V2:
  * add patch 3 and 4

Wei Yang (4):
  iommu/vt-d: replace *hdr with hdr[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  |  127 -
 include/acpi/actbl2.h |   31 ++--
 include/linux/dmar.h  |2 +-
 3 files changed, 81 insertions(+), 79 deletions(-)

-- 
1.7.9.5

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 06/10] iommu/ipmmu-vmsa: Add optional root device feature

2016-03-20 Thread Magnus Damm
From: Magnus Damm 

Add root device handling to the IPMMU driver by
allowing certain DT compat strings to enable
has_cache_leaf_nodes that in turn will support
both root devices with interrupts and leaf devices
that face the actual IPMMU consumer devices.

Signed-off-by: Magnus Damm 
---

 drivers/iommu/ipmmu-vmsa.c |   92 ++--
 1 file changed, 73 insertions(+), 19 deletions(-)

--- 0019/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2016-03-18 00:30:22.270513000 +0900
@@ -35,6 +35,7 @@
 
 struct ipmmu_features {
bool use_ns_alias_offset;
+   bool has_cache_leaf_nodes;
 };
 
 struct ipmmu_vmsa_device {
@@ -50,10 +51,12 @@ struct ipmmu_vmsa_device {
struct dma_iommu_mapping *mapping;
 #endif
const struct ipmmu_features *features;
+   bool is_leaf;
 };
 
 struct ipmmu_vmsa_domain {
struct ipmmu_vmsa_device *mmu;
+   struct ipmmu_vmsa_device *root;
struct iommu_domain io_domain;
 
struct io_pgtable_cfg cfg;
@@ -198,6 +201,36 @@ static struct ipmmu_vmsa_domain *to_vmsa
 #define IMUASID_ASID0_SHIFT0
 
 /* 
-
+ * Root device handling
+ */
+
+static bool ipmmu_is_root(struct ipmmu_vmsa_device *mmu)
+{
+   if (mmu->features->has_cache_leaf_nodes)
+   return mmu->is_leaf ? false : true;
+   else
+   return true; /* older IPMMU hardware treated as single root */
+}
+
+static struct ipmmu_vmsa_device *ipmmu_find_root(struct ipmmu_vmsa_device 
*leaf)
+{
+   struct ipmmu_vmsa_device *mmu = NULL;
+
+   if (ipmmu_is_root(leaf))
+   return leaf;
+
+   spin_lock(&ipmmu_devices_lock);
+
+   list_for_each_entry(mmu, &ipmmu_devices, list) {
+   if (ipmmu_is_root(mmu))
+   break;
+   }
+
+   spin_unlock(&ipmmu_devices_lock);
+   return mmu;
+}
+
+/* 
-
  * Read/Write Access
  */
 
@@ -214,13 +247,13 @@ static void ipmmu_write(struct ipmmu_vms
 
 static u32 ipmmu_ctx_read(struct ipmmu_vmsa_domain *domain, unsigned int reg)
 {
-   return ipmmu_read(domain->mmu, domain->context_id * IM_CTX_SIZE + reg);
+   return ipmmu_read(domain->root, domain->context_id * IM_CTX_SIZE + reg);
 }
 
 static void ipmmu_ctx_write(struct ipmmu_vmsa_domain *domain, unsigned int reg,
u32 data)
 {
-   ipmmu_write(domain->mmu, domain->context_id * IM_CTX_SIZE + reg, data);
+   ipmmu_write(domain->root, domain->context_id * IM_CTX_SIZE + reg, data);
 }
 
 /* 
-
@@ -334,7 +367,7 @@ static int ipmmu_domain_init_context(str
 * TODO: Add support for coherent walk through CCI with DVM and remove
 * cache handling. For now, delegate it to the io-pgtable code.
 */
-   domain->cfg.iommu_dev = domain->mmu->dev;
+   domain->cfg.iommu_dev = domain->root->dev;
 
domain->iop = alloc_io_pgtable_ops(ARM_32_LPAE_S1, &domain->cfg,
   domain);
@@ -344,15 +377,15 @@ static int ipmmu_domain_init_context(str
/*
 * Find an unused context.
 */
-   ret = find_first_zero_bit(domain->mmu->ctx, IPMMU_CTX_MAX);
+   ret = find_first_zero_bit(domain->root->ctx, IPMMU_CTX_MAX);
if (ret == IPMMU_CTX_MAX) {
free_io_pgtable_ops(domain->iop);
return -EBUSY;
}
 
domain->context_id = ret;
-   domain->mmu->domains[ret] = domain;
-   set_bit(ret, domain->mmu->ctx);
+   domain->root->domains[ret] = domain;
+   set_bit(ret, domain->root->ctx);
 
/* TTBR0 */
ttbr = domain->cfg.arm_lpae_s1_cfg.ttbr[0];
@@ -396,7 +429,7 @@ static int ipmmu_domain_init_context(str
 
 static void ipmmu_domain_destroy_context(struct ipmmu_vmsa_domain *domain)
 {
-   clear_bit(domain->context_id, domain->mmu->ctx);
+   clear_bit(domain->context_id, domain->root->ctx);
 
/*
 * Disable the context. Flush the TLB as required when modifying the
@@ -524,7 +557,7 @@ static int ipmmu_attach_device(struct io
   struct device *dev)
 {
struct ipmmu_vmsa_archdata *archdata = dev->archdata.iommu;
-   struct ipmmu_vmsa_device *mmu = archdata->mmu;
+   struct ipmmu_vmsa_device *root, *mmu = archdata->mmu;
struct ipmmu_vmsa_domain *domain = to_vmsa_domain(io_domain);
unsigned long flags;
unsigned int i;
@@ -535,15 +568,23 @@ static int ipmmu_attach_device(struct io
return -ENXIO;
}
 
+   root = ipmmu_find_root(archdata->mmu);
+   if (!root) {
+   dev_err(dev, "Unable to locate root IPMMU\n");
+   return -EAGAIN;
+   }
+
spin_lock_irqsave(&domain->lock, flags);
 
if (!domain

[PATCH v2 0/2] iommu/vt-d: Fault logging improvements

2016-03-20 Thread Alex Williamson
Ratelimit and improve formatting.

v2:

 - Use a single ratelimit state as suggested by Joe Perches, except
   I chose to move it up to dmar_fault() so that it includes the
   "handling fault status reg" pr_err and we can avoid collecting
   entries for logging if we don't plan to print them.
 - Added reformatting changes suggested by Joe Perches.
 - While there is clearly more that could be done with disabling
   fault handling for specific context entries on storm and sending
   errors to drivers, this makes a marked improvement on its own.

Thanks,
Alex

---

Alex Williamson (2):
  iommu/vt-d: Ratelimit fault handler
  iommu/vt-d: Improve fault handler error messages


 drivers/iommu/dmar.c |   47 +++
 1 file changed, 27 insertions(+), 20 deletions(-)
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [v6, 5/5] mmc: sdhci-of-esdhc: fix host version for T4240-R1.0-R2.0

2016-03-20 Thread Arnd Bergmann
On Thursday 17 March 2016 12:01:01 Rob Herring wrote:
> On Mon, Mar 14, 2016 at 05:45:43PM +, Scott Wood wrote:

> > >> This makes the driver non-portable. Better identify the specific
> > >> workarounds based on the compatible string for this device, or add a
> > >> boolean DT property for the quirk.
> > >>
> > >>Arnd
> > > 
> > > [Lu Yangbo-B47093] Hi Arnd, we did have a discussion about using DTS in 
> > > v1 before.
> > > https://patchwork.kernel.org/patch/6834221/
> > > 
> > > We don’t have a separate DTS file for each revision of an SOC and if we 
> > > did, we'd constantly have people using the wrong one.
> > > In addition, the device tree is stable ABI and errata are often 
> > > discovered after device tree are deployed.
> > > See the link for details.
> > > 
> > > So we decide to read SVR from the device-config/guts MMIO block other 
> > > than using DTS.
> > > Thanks.
> > 
> > Also note that this driver is already only for fsl-specific hardware,
> > and it will still work even if fsl_guts doesn't find anything to bind to
> > -- it just wouldn't be able to detect errata based on SVR in that case.
> 
> IIRC, it is the same IP block as i.MX and Arnd's point is this won't 
> even compile on !PPC. It is things like this that prevent sharing the 
> driver.

I think the first four patches take care of building for ARM,
but the problem remains if you want to enable COMPILE_TEST as
we need for certain automated checking.

> Dealing with Si revs is a common problem. We should have a 
> common solution. There is soc_device for this purpose.

Exactly. The last time this came up, I think we agreed to implement a
helper using glob_match() on the soc_device strings. Unfortunately
this hasn't happened then, but I'd still prefer that over yet another
vendor-specific way of dealing with the generic issue.

Arnd
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Re: [PATCH v5 6/9] dmaengine: rcar-dmac: group slave configuration

2016-03-20 Thread Laurent Pinchart
Hi Niklas,

Thank you for the patch.

On Tuesday 08 March 2016 03:42:51 Niklas Söderlund wrote:
> Group slave address and transfer size in own structs for source and
> destination. This is in preparation for hooking up the dma-mapping API
> to the slave addresses.
> 
> Signed-off-by: Niklas Söderlund 

Reviewed-by: Laurent Pinchart 

> ---
>  drivers/dma/sh/rcar-dmac.c | 38 ++
>  1 file changed, 22 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
> index 01cf82f..b3911fe 100644
> --- a/drivers/dma/sh/rcar-dmac.c
> +++ b/drivers/dma/sh/rcar-dmac.c
> @@ -118,14 +118,22 @@ struct rcar_dmac_desc_page {
>   sizeof(struct rcar_dmac_xfer_chunk))
> 
>  /*
> + * struct rcar_dmac_chan_slave - Slave configuration
> + * @slave_addr: slave memory address
> + * @xfer_size: size (in bytes) of hardware transfers
> + */
> +struct rcar_dmac_chan_slave {
> + phys_addr_t slave_addr;
> + unsigned int xfer_size;
> +};
> +
> +/*
>   * struct rcar_dmac_chan - R-Car Gen2 DMA Controller Channel
>   * @chan: base DMA channel object
>   * @iomem: channel I/O memory base
>   * @index: index of this channel in the controller
> - * @src_xfer_size: size (in bytes) of hardware transfers on the source side
> - * @dst_xfer_size: size (in bytes) of hardware transfers on the
> destination side - * @src_slave_addr: slave source memory address
> - * @dst_slave_addr: slave destination memory address
> + * @src: slave memory address and size on the source side
> + * @dst: slave memory address and size on the destination side
>   * @mid_rid: hardware MID/RID for the DMA client using this channel
>   * @lock: protects the channel CHCR register and the desc members
>   * @desc.free: list of free descriptors
> @@ -142,10 +150,8 @@ struct rcar_dmac_chan {
>   void __iomem *iomem;
>   unsigned int index;
> 
> - unsigned int src_xfer_size;
> - unsigned int dst_xfer_size;
> - phys_addr_t src_slave_addr;
> - phys_addr_t dst_slave_addr;
> + struct rcar_dmac_chan_slave src;
> + struct rcar_dmac_chan_slave dst;
>   int mid_rid;
> 
>   spinlock_t lock;
> @@ -793,13 +799,13 @@ static void rcar_dmac_chan_configure_desc(struct
> rcar_dmac_chan *chan, case DMA_DEV_TO_MEM:
>   chcr = RCAR_DMACHCR_DM_INC | RCAR_DMACHCR_SM_FIXED
> 
>| RCAR_DMACHCR_RS_DMARS;
> 
> - xfer_size = chan->src_xfer_size;
> + xfer_size = chan->src.xfer_size;
>   break;
> 
>   case DMA_MEM_TO_DEV:
>   chcr = RCAR_DMACHCR_DM_FIXED | RCAR_DMACHCR_SM_INC
> 
>| RCAR_DMACHCR_RS_DMARS;
> 
> - xfer_size = chan->dst_xfer_size;
> + xfer_size = chan->dst.xfer_size;
>   break;
> 
>   case DMA_MEM_TO_MEM:
> @@ -1038,7 +1044,7 @@ rcar_dmac_prep_slave_sg(struct dma_chan *chan, struct
> scatterlist *sgl, }
> 
>   dev_addr = dir == DMA_DEV_TO_MEM
> -  ? rchan->src_slave_addr : rchan->dst_slave_addr;
> +  ? rchan->src.slave_addr : rchan->dst.slave_addr;
>   return rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
> dir, flags, false);
>  }
> @@ -1093,7 +1099,7 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan,
> dma_addr_t buf_addr, }
> 
>   dev_addr = dir == DMA_DEV_TO_MEM
> -  ? rchan->src_slave_addr : rchan->dst_slave_addr;
> +  ? rchan->src.slave_addr : rchan->dst.slave_addr;
>   desc = rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
> dir, flags, true);
> 
> @@ -1110,10 +1116,10 @@ static int rcar_dmac_device_config(struct dma_chan
> *chan, * We could lock this, but you shouldn't be configuring the
>* channel, while using it...
>*/
> - rchan->src_slave_addr = cfg->src_addr;
> - rchan->dst_slave_addr = cfg->dst_addr;
> - rchan->src_xfer_size = cfg->src_addr_width;
> - rchan->dst_xfer_size = cfg->dst_addr_width;
> + rchan->src.slave_addr = cfg->src_addr;
> + rchan->dst.slave_addr = cfg->dst_addr;
> + rchan->src.xfer_size = cfg->src_addr_width;
> + rchan->dst.xfer_size = cfg->dst_addr_width;
> 
>   return 0;
>  }

-- 
Regards,

Laurent Pinchart

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 0/7] Intel IOMMU scalability improvements

2016-03-20 Thread Benjamin Serebrin via iommu
There are nice.  Thanks very much for doing this work!

We have some preliminary results, looking at scaling to high core counts.
We tested the patches on a 2-socket high core count SNB-EP server with a
Broadcomm NIC.  Our benchmark uses 200 threads of TCP_RR.  We see similar
performance for IOMMU disabled as we do for IOMMU enabled with this
patchset, which is good news.  We're working on getting a lab setup with
Haswell servers so we can further test the scalability of the code.

We owe the scaling results and of course actual code reviews.

On Mon, Dec 28, 2015 at 8:14 AM, Adam Morrison 
wrote:

> This patchset improves the scalability of the Intel IOMMU code by
> resolving two spinlock bottlenecks, yielding up to ~10x performance
> improvement and approaching iommu=off performance.
>
> For example, here's the throughput obtained by 16 memcached instances
> running on a 16-core Sandy Bridge system, accessed using memslap on
> another machine that has iommu=off, using the default memslap config
> (64-byte keys, 1024-byte values, and 10%/90% SET/GET ops):
>
> stock iommu=off:
>1,088,996 memcached transactions/sec (=100%, median of 10 runs).
> stock iommu=on:
>123,760 memcached transactions/sec (=11%).
>[perf: 43.56%0.86%  memcached   [kernel.kallsyms]  [k]
> _raw_spin_lock_irqsave]
> patched iommu=on:
>1,067,586 memcached transactions/sec (=98%).
>[perf: 0.75% 0.75%  memcached   [kernel.kallsyms]  [k]
> _raw_spin_lock_irqsave]
>
> The two resolved spinlocks:
>
>  - Deferred IOTLB invalidations are batched in a global data structure
>and serialized under a spinlock (add_unmap() & flush_unmaps()); this
>patchset batches IOTLB invalidations in a per-CPU data structure.
>
>  - IOVA management (alloc_iova() & __free_iova()) is serialized under
>the rbtree spinlock; this patchset adds per-CPU caches of allocated
>IOVAs so that the rbtree doesn't get accessed frequently. (Adding a
>cache above the existing IOVA allocator is less intrusive than dynamic
>identity mapping and helps keep IOMMU page table usage low; see
>Patch 7.)
>
> The paper "Utilizing the IOMMU Scalably" (presented at the 2015 USENIX
> Annual Technical Conference) contains many more details and experiments:
>
>
> https://www.usenix.org/system/files/conference/atc15/atc15-paper-peleg.pdf
>
>
> Omer Peleg (7):
>   iommu: refactoring of deferred flush entries
>   iommu: per-cpu deferred invalidation queues
>   iommu: correct flush_unmaps pfn usage
>   iommu: only unmap mapped entries
>   iommu: avoid dev iotlb logic in intel-iommu for domains with no dev
> iotlbs
>   iommu: change intel-iommu to use IOVA frame numbers
>   iommu: introduce per-cpu caching to iova allocation
>
>  drivers/iommu/intel-iommu.c | 264 +-
>  drivers/iommu/iova.c| 334
> +---
>  include/linux/iova.h|  23 ++-
>  3 files changed, 470 insertions(+), 151 deletions(-)
>
> --
> 1.9.1
>
>
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCH] iommu: io-pgtable: fixed a brace coding style issue.

2016-03-20 Thread Cosmin-Gabriel Samoila
Fixed a coding style issue.

Signed-off-by: Cosmin-Gabriel Samoila 
---
 drivers/iommu/io-pgtable.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/iommu/io-pgtable.c b/drivers/iommu/io-pgtable.c
index 6f2e319..a4a9a42 100644
--- a/drivers/iommu/io-pgtable.c
+++ b/drivers/iommu/io-pgtable.c
@@ -25,8 +25,7 @@
 #include "io-pgtable.h"
 
 static const struct io_pgtable_init_fns *
-io_pgtable_init_table[IO_PGTABLE_NUM_FMTS] =
-{
+io_pgtable_init_table[IO_PGTABLE_NUM_FMTS] = {
 #ifdef CONFIG_IOMMU_IO_PGTABLE_LPAE
[ARM_32_LPAE_S1] = &io_pgtable_arm_32_lpae_s1_init_fns,
[ARM_32_LPAE_S2] = &io_pgtable_arm_32_lpae_s2_init_fns,
-- 
1.9.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 05/10] iommu/ipmmu-vmsa: Introduce features, break out alias

2016-03-20 Thread Magnus Damm
From: Magnus Damm 

Introduce struct ipmmu_features to track various hardware
and software implementation changes inside the driver for
different kinds of IPMMU hardware. Add use_ns_alias_offset
as a first example of a feature to control if the secure
register bank offset should be used or not.

Signed-off-by: Magnus Damm 
---

 drivers/iommu/ipmmu-vmsa.c |   34 --
 1 file changed, 28 insertions(+), 6 deletions(-)

--- 0017/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2016-03-18 00:29:15.860513000 +0900
@@ -33,6 +33,10 @@
 
 #define IPMMU_CTX_MAX 4
 
+struct ipmmu_features {
+   bool use_ns_alias_offset;
+};
+
 struct ipmmu_vmsa_device {
struct device *dev;
void __iomem *base;
@@ -45,6 +49,7 @@ struct ipmmu_vmsa_device {
 #if defined(CONFIG_ARM) && !defined(CONFIG_IOMMU_DMA)
struct dma_iommu_mapping *mapping;
 #endif
+   const struct ipmmu_features *features;
 };
 
 struct ipmmu_vmsa_domain {
@@ -932,13 +937,33 @@ static void ipmmu_device_reset(struct ip
ipmmu_write(mmu, i * IM_CTX_SIZE + IMCTR, 0);
 }
 
+static const struct ipmmu_features ipmmu_features_default = {
+   .use_ns_alias_offset = true,
+};
+
+static const struct of_device_id ipmmu_of_ids[] = {
+   {
+   .compatible = "renesas,ipmmu-vmsa",
+   .data = &ipmmu_features_default,
+   }, {
+   /* Terminator */
+   },
+};
+
+MODULE_DEVICE_TABLE(of, ipmmu_of_ids);
+
 static int ipmmu_probe(struct platform_device *pdev)
 {
struct ipmmu_vmsa_device *mmu;
+   const struct of_device_id *match;
struct resource *res;
int irq;
int ret;
 
+   match = of_match_node(ipmmu_of_ids, pdev->dev.of_node);
+   if (!match)
+   return -EINVAL;
+
mmu = devm_kzalloc(&pdev->dev, sizeof(*mmu), GFP_KERNEL);
if (!mmu) {
dev_err(&pdev->dev, "cannot allocate device data\n");
@@ -948,6 +973,7 @@ static int ipmmu_probe(struct platform_d
mmu->dev = &pdev->dev;
mmu->num_utlbs = 32;
bitmap_zero(mmu->ctx, IPMMU_CTX_MAX);
+   mmu->features = match->data;
dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
 
/* Map I/O memory and request IRQ. */
@@ -968,7 +994,8 @@ static int ipmmu_probe(struct platform_d
 * Offset the registers base unconditionally to point to the non-secure
 * alias space for now.
 */
-   mmu->base += IM_NS_ALIAS_OFFSET;
+   if (mmu->features->use_ns_alias_offset)
+   mmu->base += IM_NS_ALIAS_OFFSET;
 
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
@@ -1015,11 +1042,6 @@ static int ipmmu_remove(struct platform_
return 0;
 }
 
-static const struct of_device_id ipmmu_of_ids[] = {
-   { .compatible = "renesas,ipmmu-vmsa", },
-   { }
-};
-
 static struct platform_driver ipmmu_driver = {
.driver = {
.name = "ipmmu-vmsa",
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu