diff mbox

[v3,24/62] arm: Introduce a generic way to use a device from acpi

Message ID 1447753261-7552-25-git-send-email-shannon.zhao@linaro.org (mailing list archive)
State New, archived
Headers show

Commit Message

Shannon Zhao Nov. 17, 2015, 9:40 a.m. UTC
From: Parth Dixit <parth.dixit@linaro.org>

Add generic way to use device from acpi similar to the way it is
supported in device tree.

Signed-off-by: Parth Dixit <parth.dixit@linaro.org>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
---
 xen/arch/arm/device.c        | 19 +++++++++++++++++++
 xen/arch/arm/xen.lds.S       |  7 +++++++
 xen/include/asm-arm/device.h | 30 ++++++++++++++++++++++++++++++
 3 files changed, 56 insertions(+)

Comments

Julien Grall Nov. 17, 2015, 12:40 p.m. UTC | #1
Hi Shannon,

On 17/11/15 09:40, shannon.zhao@linaro.org wrote:
> From: Parth Dixit <parth.dixit@linaro.org>
> 
> Add generic way to use device from acpi similar to the way it is
> supported in device tree.
> 
> Signed-off-by: Parth Dixit <parth.dixit@linaro.org>
> Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
> ---
>  xen/arch/arm/device.c        | 19 +++++++++++++++++++
>  xen/arch/arm/xen.lds.S       |  7 +++++++
>  xen/include/asm-arm/device.h | 30 ++++++++++++++++++++++++++++++
>  3 files changed, 56 insertions(+)
> 
> diff --git a/xen/arch/arm/device.c b/xen/arch/arm/device.c
> index 0b53f6a..5494de0 100644
> --- a/xen/arch/arm/device.c
> +++ b/xen/arch/arm/device.c
> @@ -22,6 +22,7 @@
>  #include <xen/lib.h>
>  
>  extern const struct device_desc _sdevice[], _edevice[];
> +extern const struct acpi_device_desc _asdevice[], _aedevice[];
>  
>  int __init device_init(struct dt_device_node *dev, enum device_class class,
>                         const void *data)
> @@ -50,6 +51,24 @@ int __init device_init(struct dt_device_node *dev, enum device_class class,
>      return -EBADF;
>  }
>  
> +int __init acpi_device_init(enum device_class class, const void *data, int class_type)

As said on a previous version, please explain what means class_type and
how this will fit with every
ACPI device tables.

AFAICT, it does only works for SPCR table used for UART device. For the
GIC you've hardcoded the value and I can't find any version number in
the table.

You may need to introduce another way to find the device such as a
callback taking the table in parameter.

Regards,
Shannon Zhao Nov. 17, 2015, 1:21 p.m. UTC | #2
On 2015/11/17 20:40, Julien Grall wrote:
> Hi Shannon,
> 
> On 17/11/15 09:40, shannon.zhao@linaro.org wrote:
>> From: Parth Dixit <parth.dixit@linaro.org>
>>
>> Add generic way to use device from acpi similar to the way it is
>> supported in device tree.
>>
>> Signed-off-by: Parth Dixit <parth.dixit@linaro.org>
>> Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
>> ---
>>  xen/arch/arm/device.c        | 19 +++++++++++++++++++
>>  xen/arch/arm/xen.lds.S       |  7 +++++++
>>  xen/include/asm-arm/device.h | 30 ++++++++++++++++++++++++++++++
>>  3 files changed, 56 insertions(+)
>>
>> diff --git a/xen/arch/arm/device.c b/xen/arch/arm/device.c
>> index 0b53f6a..5494de0 100644
>> --- a/xen/arch/arm/device.c
>> +++ b/xen/arch/arm/device.c
>> @@ -22,6 +22,7 @@
>>  #include <xen/lib.h>
>>  
>>  extern const struct device_desc _sdevice[], _edevice[];
>> +extern const struct acpi_device_desc _asdevice[], _aedevice[];
>>  
>>  int __init device_init(struct dt_device_node *dev, enum device_class class,
>>                         const void *data)
>> @@ -50,6 +51,24 @@ int __init device_init(struct dt_device_node *dev, enum device_class class,
>>      return -EBADF;
>>  }
>>  
>> +int __init acpi_device_init(enum device_class class, const void *data, int class_type)
> 
> As said on a previous version, please explain what means class_type and
> how this will fit with every
> ACPI device tables.
> 
> AFAICT, it does only works for SPCR table used for UART device. For the
> GIC you've hardcoded the value and I can't find any version number in
> the table.
> 
No, I didn't hardcode the GIC version. Since ACPI 6.0 introduces GIC
version in generic distributor table, it could get the version from
that. Please see [PATCH v3 28/62].

> You may need to introduce another way to find the device such as a
> callback taking the table in parameter.
>
Julien Grall Nov. 17, 2015, 2:25 p.m. UTC | #3
On 17/11/15 13:21, Shannon Zhao wrote:
>> AFAICT, it does only works for SPCR table used for UART device. For the
>> GIC you've hardcoded the value and I can't find any version number in
>> the table.
>>
> No, I didn't hardcode the GIC version. Since ACPI 6.0 introduces GIC
> version in generic distributor table, it could get the version from
> that. Please see [PATCH v3 28/62].

+    if ( dist->version == ACPI_MADT_GIC_VERSION_V2 )
+        rc = acpi_device_init(DEVICE_GIC, NULL, GIC_V2);
+    else if ( dist->version == ACPI_MADT_GIC_VERSION_V3 )
+        rc = acpi_device_init(DEVICE_GIC, NULL, GIC_V3);

Every single time a new GIC version will be added, we will had to add
another else if. I'm sorry but it's what I call hardcoding.

Regards,
Shannon Zhao Nov. 18, 2015, 2:37 a.m. UTC | #4
On 2015/11/17 22:25, Julien Grall wrote:
> On 17/11/15 13:21, Shannon Zhao wrote:
>>> AFAICT, it does only works for SPCR table used for UART device. For the
>>> GIC you've hardcoded the value and I can't find any version number in
>>> the table.
>>>
>> No, I didn't hardcode the GIC version. Since ACPI 6.0 introduces GIC
>> version in generic distributor table, it could get the version from
>> that. Please see [PATCH v3 28/62].
> 
> +    if ( dist->version == ACPI_MADT_GIC_VERSION_V2 )
> +        rc = acpi_device_init(DEVICE_GIC, NULL, GIC_V2);
> +    else if ( dist->version == ACPI_MADT_GIC_VERSION_V3 )
> +        rc = acpi_device_init(DEVICE_GIC, NULL, GIC_V3);
> 
> Every single time a new GIC version will be added, we will had to add
> another else if. I'm sorry but it's what I call hardcoding.
> 

Oh, I see. If it uses the enum acpi_madt_gic_version for ACPI GIC not
the enum gic_version, it could match 1:1. Something like below:

It uses ACPI_MADT_GIC_VERSION_V2 for GICv2.

ACPI_DEVICE_START(agicv2, "GICv2", DEVICE_GIC)
        .class_type = ACPI_MADT_GIC_VERSION_V2,
        .init = acpi_gicv2_preinit,
ACPI_DEVICE_END

Then get the GIC version from MADT table and call

acpi_device_init(DEVICE_GIC, NULL, dist->version);

How about this way?

Thanks,
Julien Grall Nov. 18, 2015, 11:46 a.m. UTC | #5
On 18/11/15 02:37, Shannon Zhao wrote:
> 
> 
> On 2015/11/17 22:25, Julien Grall wrote:
>> On 17/11/15 13:21, Shannon Zhao wrote:
>>>> AFAICT, it does only works for SPCR table used for UART device. For the
>>>> GIC you've hardcoded the value and I can't find any version number in
>>>> the table.
>>>>
>>> No, I didn't hardcode the GIC version. Since ACPI 6.0 introduces GIC
>>> version in generic distributor table, it could get the version from
>>> that. Please see [PATCH v3 28/62].
>>
>> +    if ( dist->version == ACPI_MADT_GIC_VERSION_V2 )
>> +        rc = acpi_device_init(DEVICE_GIC, NULL, GIC_V2);
>> +    else if ( dist->version == ACPI_MADT_GIC_VERSION_V3 )
>> +        rc = acpi_device_init(DEVICE_GIC, NULL, GIC_V3);
>>
>> Every single time a new GIC version will be added, we will had to add
>> another else if. I'm sorry but it's what I call hardcoding.
>>
> 
> Oh, I see. If it uses the enum acpi_madt_gic_version for ACPI GIC not
> the enum gic_version, it could match 1:1. Something like below:
> 
> It uses ACPI_MADT_GIC_VERSION_V2 for GICv2.
> 
> ACPI_DEVICE_START(agicv2, "GICv2", DEVICE_GIC)
>         .class_type = ACPI_MADT_GIC_VERSION_V2,
>         .init = acpi_gicv2_preinit,
> ACPI_DEVICE_END
> 
> Then get the GIC version from MADT table and call
> 
> acpi_device_init(DEVICE_GIC, NULL, dist->version);
> 
> How about this way?

That would be better. We want the common mode as agnostic as possible
from the GIC version.

Regards,
Stefano Stabellini Nov. 24, 2015, 11:18 a.m. UTC | #6
On Tue, 17 Nov 2015, shannon.zhao@linaro.org wrote:
> From: Parth Dixit <parth.dixit@linaro.org>
> 
> Add generic way to use device from acpi similar to the way it is
> supported in device tree.
> 
> Signed-off-by: Parth Dixit <parth.dixit@linaro.org>
> Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
> ---
>  xen/arch/arm/device.c        | 19 +++++++++++++++++++
>  xen/arch/arm/xen.lds.S       |  7 +++++++
>  xen/include/asm-arm/device.h | 30 ++++++++++++++++++++++++++++++
>  3 files changed, 56 insertions(+)
> 
> diff --git a/xen/arch/arm/device.c b/xen/arch/arm/device.c
> index 0b53f6a..5494de0 100644
> --- a/xen/arch/arm/device.c
> +++ b/xen/arch/arm/device.c
> @@ -22,6 +22,7 @@
>  #include <xen/lib.h>
>  
>  extern const struct device_desc _sdevice[], _edevice[];
> +extern const struct acpi_device_desc _asdevice[], _aedevice[];
>  
>  int __init device_init(struct dt_device_node *dev, enum device_class class,
>                         const void *data)
> @@ -50,6 +51,24 @@ int __init device_init(struct dt_device_node *dev, enum device_class class,
>      return -EBADF;
>  }
>  
> +int __init acpi_device_init(enum device_class class, const void *data, int class_type)
> +{
> +    const struct acpi_device_desc *desc;
> +
> +    for ( desc = _asdevice; desc != _aedevice; desc++ )
> +    {
> +        if ( ( desc->class != class ) && ( desc->class_type != class_type ) )
> +            continue;

Shouldn't this be

  if ( ( desc->class != class ) || ( desc->class_type != class_type ) )

?

> +
> +        ASSERT(desc->init != NULL);
> +
> +        return desc->init(data);
> +    }
> +
> +    return -EBADF;
> +}
> +
>  enum device_class device_get_class(const struct dt_device_node *dev)
>  {
>      const struct device_desc *desc;
> diff --git a/xen/arch/arm/xen.lds.S b/xen/arch/arm/xen.lds.S
> index 0488f37..60802f6 100644
> --- a/xen/arch/arm/xen.lds.S
> +++ b/xen/arch/arm/xen.lds.S
> @@ -100,6 +100,13 @@ SECTIONS
>        _edevice = .;
>    } :text
>  
> +  . = ALIGN(8);
> +  .adev.info : {
> +      _asdevice = .;
> +      *(.adev.info)
> +      _aedevice = .;
> +  } :text
> +
>    . = ALIGN(PAGE_SIZE);             /* Init code and data */
>    __init_begin = .;
>    .init.text : {
> diff --git a/xen/include/asm-arm/device.h b/xen/include/asm-arm/device.h
> index 5d0a4cd..085f221 100644
> --- a/xen/include/asm-arm/device.h
> +++ b/xen/include/asm-arm/device.h
> @@ -50,6 +50,27 @@ struct device_desc {
>      int (*init)(struct dt_device_node *dev, const void *data);
>  };
>  
> +struct acpi_device_desc {
> +    /* Device name */
> +    const char *name;
> +    /* Device class */
> +    enum device_class class;
> +    /* type of device supported by the driver */
> +    const int class_type;
> +    /* Device initialization */
> +    int (*init)(const void *data);
> +};
> +
> +/**
> + *  acpi_device_init - Initialize a device
> + *  @class: class of the device (serial, network...)
> + *  @data: specific data for initializing the device
> + *
> + *  Return 0 on success.
> + */
> +int __init acpi_device_init(enum device_class class,
> +                            const void *data, int class_type);
> +
>  /**
>   *  device_init - Initialize a device
>   *  @dev: device to initialize
> @@ -78,6 +99,15 @@ __section(".dev.info") = {                                          \
>  #define DT_DEVICE_END                                               \
>  };
>  
> +#define ACPI_DEVICE_START(_name, _namestr, _class)                    \
> +static const struct acpi_device_desc __dev_desc_##_name __used           \
> +__attribute__((__section__(".adev.info"))) = {                       \

why __attribute__?


> +    .name = _namestr,                                               \
> +    .class = _class,                                                \
> +
> +#define ACPI_DEVICE_END                                               \
> +};
> +
>  #endif /* __ASM_ARM_DEVICE_H */
>  
>  /*
> -- 
> 2.1.0
> 
> 
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xen.org
> http://lists.xen.org/xen-devel
>
diff mbox

Patch

diff --git a/xen/arch/arm/device.c b/xen/arch/arm/device.c
index 0b53f6a..5494de0 100644
--- a/xen/arch/arm/device.c
+++ b/xen/arch/arm/device.c
@@ -22,6 +22,7 @@ 
 #include <xen/lib.h>
 
 extern const struct device_desc _sdevice[], _edevice[];
+extern const struct acpi_device_desc _asdevice[], _aedevice[];
 
 int __init device_init(struct dt_device_node *dev, enum device_class class,
                        const void *data)
@@ -50,6 +51,24 @@  int __init device_init(struct dt_device_node *dev, enum device_class class,
     return -EBADF;
 }
 
+int __init acpi_device_init(enum device_class class, const void *data, int class_type)
+{
+    const struct acpi_device_desc *desc;
+
+    for ( desc = _asdevice; desc != _aedevice; desc++ )
+    {
+        if ( ( desc->class != class ) && ( desc->class_type != class_type ) )
+            continue;
+
+
+        ASSERT(desc->init != NULL);
+
+        return desc->init(data);
+    }
+
+    return -EBADF;
+}
+
 enum device_class device_get_class(const struct dt_device_node *dev)
 {
     const struct device_desc *desc;
diff --git a/xen/arch/arm/xen.lds.S b/xen/arch/arm/xen.lds.S
index 0488f37..60802f6 100644
--- a/xen/arch/arm/xen.lds.S
+++ b/xen/arch/arm/xen.lds.S
@@ -100,6 +100,13 @@  SECTIONS
       _edevice = .;
   } :text
 
+  . = ALIGN(8);
+  .adev.info : {
+      _asdevice = .;
+      *(.adev.info)
+      _aedevice = .;
+  } :text
+
   . = ALIGN(PAGE_SIZE);             /* Init code and data */
   __init_begin = .;
   .init.text : {
diff --git a/xen/include/asm-arm/device.h b/xen/include/asm-arm/device.h
index 5d0a4cd..085f221 100644
--- a/xen/include/asm-arm/device.h
+++ b/xen/include/asm-arm/device.h
@@ -50,6 +50,27 @@  struct device_desc {
     int (*init)(struct dt_device_node *dev, const void *data);
 };
 
+struct acpi_device_desc {
+    /* Device name */
+    const char *name;
+    /* Device class */
+    enum device_class class;
+    /* type of device supported by the driver */
+    const int class_type;
+    /* Device initialization */
+    int (*init)(const void *data);
+};
+
+/**
+ *  acpi_device_init - Initialize a device
+ *  @class: class of the device (serial, network...)
+ *  @data: specific data for initializing the device
+ *
+ *  Return 0 on success.
+ */
+int __init acpi_device_init(enum device_class class,
+                            const void *data, int class_type);
+
 /**
  *  device_init - Initialize a device
  *  @dev: device to initialize
@@ -78,6 +99,15 @@  __section(".dev.info") = {                                          \
 #define DT_DEVICE_END                                               \
 };
 
+#define ACPI_DEVICE_START(_name, _namestr, _class)                    \
+static const struct acpi_device_desc __dev_desc_##_name __used           \
+__attribute__((__section__(".adev.info"))) = {                       \
+    .name = _namestr,                                               \
+    .class = _class,                                                \
+
+#define ACPI_DEVICE_END                                               \
+};
+
 #endif /* __ASM_ARM_DEVICE_H */
 
 /*