[RFC,v1,08/21] RISC-V: ACPI: RHCT: Add function to get CBO block sizes
Commit Message
CBO related block size in ACPI is provided by RHCT. Add
support to read the CMO node in RHCT to get this information.
Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
arch/riscv/include/asm/acpi.h | 9 ++++++
drivers/acpi/riscv/rhct.c | 61 +++++++++++++++++++++++++++++++++++
2 files changed, 70 insertions(+)
Comments
On Thu, Aug 03, 2023 at 11:29:03PM +0530, Sunil V L wrote:
> CBO related block size in ACPI is provided by RHCT. Add
> support to read the CMO node in RHCT to get this information.
...
> + if (!table) {
Why not positive conditional?
> + rhct = (struct acpi_table_rhct *)acpi_get_rhct();
> + if (!rhct)
> + return -ENOENT;
> + } else {
> + rhct = (struct acpi_table_rhct *)table;
> + }
...
> + end = ACPI_ADD_PTR(struct acpi_rhct_node_header, rhct, rhct->header.length);
> +
Blank line here is not needed.
> + for (node = ACPI_ADD_PTR(struct acpi_rhct_node_header, rhct, rhct->node_offset);
> + node < end;
> + node = ACPI_ADD_PTR(struct acpi_rhct_node_header, node, node->length)) {
> + for (int i = 0; i < hart_info->num_offsets; i++) {
> + ref_node = ACPI_ADD_PTR(struct acpi_rhct_node_header,
> + rhct, hart_info_node_offset[i]);
> + if (ref_node->type == ACPI_RHCT_NODE_TYPE_CMO) {
> + cmo_node = ACPI_ADD_PTR(struct acpi_rhct_cmo_node,
> + ref_node, size_hdr);
> + if (cbom_size)
> + *cbom_size = 1 << cmo_node->cbom_size;
> +
> + if (cboz_size)
> + *cboz_size = 1 << cmo_node->cboz_size;
> +
> + if (cbop_size)
> + *cbop_size = 1 << cmo_node->cbop_size;
BIT() in all three cases?
But how you guarantee it will not overflow? I mean who prevents cboX_size to be
bigger than 30 (note also that 31 in your case is Undefined Behaviour in
accordance with the C standard).
> + return 0;
> + }
> + }
> + }
On Fri, Aug 04, 2023 at 09:00:45AM +0300, Andy Shevchenko wrote:
> On Thu, Aug 03, 2023 at 11:29:03PM +0530, Sunil V L wrote:
> > CBO related block size in ACPI is provided by RHCT. Add
> > support to read the CMO node in RHCT to get this information.
>
> ...
>
> > + if (!table) {
>
> Why not positive conditional?
>
Sure.
> > + rhct = (struct acpi_table_rhct *)acpi_get_rhct();
> > + if (!rhct)
> > + return -ENOENT;
> > + } else {
> > + rhct = (struct acpi_table_rhct *)table;
> > + }
>
> ...
>
> > + end = ACPI_ADD_PTR(struct acpi_rhct_node_header, rhct, rhct->header.length);
>
> > +
>
> Blank line here is not needed.
>
Okay.
> > + for (node = ACPI_ADD_PTR(struct acpi_rhct_node_header, rhct, rhct->node_offset);
> > + node < end;
> > + node = ACPI_ADD_PTR(struct acpi_rhct_node_header, node, node->length)) {
>
> > + for (int i = 0; i < hart_info->num_offsets; i++) {
> > + ref_node = ACPI_ADD_PTR(struct acpi_rhct_node_header,
> > + rhct, hart_info_node_offset[i]);
> > + if (ref_node->type == ACPI_RHCT_NODE_TYPE_CMO) {
> > + cmo_node = ACPI_ADD_PTR(struct acpi_rhct_cmo_node,
> > + ref_node, size_hdr);
> > + if (cbom_size)
> > + *cbom_size = 1 << cmo_node->cbom_size;
> > +
> > + if (cboz_size)
> > + *cboz_size = 1 << cmo_node->cboz_size;
> > +
> > + if (cbop_size)
> > + *cbop_size = 1 << cmo_node->cbop_size;
>
> BIT() in all three cases?
>
Sure.
> But how you guarantee it will not overflow? I mean who prevents cboX_size to be
> bigger than 30 (note also that 31 in your case is Undefined Behaviour in
> accordance with the C standard).
>
Good catch!. Let me add a check that the value is not more than 30.
Thanks!
Sunil
@@ -66,6 +66,8 @@ int acpi_get_riscv_isa(struct acpi_table_header *table,
unsigned int cpu, const char **isa);
static inline int acpi_numa_get_nid(unsigned int cpu) { return NUMA_NO_NODE; }
+int acpi_get_cbo_block_size(struct acpi_table_header *table, unsigned int cpu, u32 *cbom_size,
+ u32 *cboz_size, u32 *cbop_size);
#else
static inline void acpi_init_rintc_map(void) { }
static inline struct acpi_madt_rintc *acpi_cpu_get_madt_rintc(int cpu)
@@ -79,6 +81,13 @@ static inline int acpi_get_riscv_isa(struct acpi_table_header *table,
return -EINVAL;
}
+static inline int acpi_get_cbo_block_size(struct acpi_table_header *table,
+ unsigned int cpu, u32 *cbom_size,
+ u32 *cboz_size, u32 *cbop_size)
+{
+ return -EINVAL;
+}
+
#endif /* CONFIG_ACPI */
#endif /*_ASM_ACPI_H*/
@@ -81,3 +81,64 @@ int acpi_get_riscv_isa(struct acpi_table_header *table, unsigned int cpu, const
return -1;
}
+
+/*
+ * During early boot, the caller should call acpi_get_table() and pass its pointer to
+ * these functions(and free up later). At run time, since this table can be used
+ * multiple times, pass NULL so that the table remains in memory
+ */
+int acpi_get_cbo_block_size(struct acpi_table_header *table, unsigned int cpu,
+ u32 *cbom_size, u32 *cboz_size, u32 *cbop_size)
+{
+ struct acpi_rhct_node_header *node, *ref_node, *end;
+ u32 size_hdr = sizeof(struct acpi_rhct_node_header);
+ u32 size_hartinfo = sizeof(struct acpi_rhct_hart_info);
+ struct acpi_rhct_hart_info *hart_info;
+ struct acpi_rhct_cmo_node *cmo_node;
+ struct acpi_table_rhct *rhct;
+ u32 *hart_info_node_offset;
+ u32 acpi_cpu_id = get_acpi_id_for_cpu(cpu);
+
+ BUG_ON(acpi_disabled);
+
+ if (!table) {
+ rhct = (struct acpi_table_rhct *)acpi_get_rhct();
+ if (!rhct)
+ return -ENOENT;
+ } else {
+ rhct = (struct acpi_table_rhct *)table;
+ }
+
+ end = ACPI_ADD_PTR(struct acpi_rhct_node_header, rhct, rhct->header.length);
+
+ for (node = ACPI_ADD_PTR(struct acpi_rhct_node_header, rhct, rhct->node_offset);
+ node < end;
+ node = ACPI_ADD_PTR(struct acpi_rhct_node_header, node, node->length)) {
+ if (node->type == ACPI_RHCT_NODE_TYPE_HART_INFO) {
+ hart_info = ACPI_ADD_PTR(struct acpi_rhct_hart_info, node, size_hdr);
+ hart_info_node_offset = ACPI_ADD_PTR(u32, hart_info, size_hartinfo);
+ if (acpi_cpu_id != hart_info->uid)
+ continue;
+
+ for (int i = 0; i < hart_info->num_offsets; i++) {
+ ref_node = ACPI_ADD_PTR(struct acpi_rhct_node_header,
+ rhct, hart_info_node_offset[i]);
+ if (ref_node->type == ACPI_RHCT_NODE_TYPE_CMO) {
+ cmo_node = ACPI_ADD_PTR(struct acpi_rhct_cmo_node,
+ ref_node, size_hdr);
+ if (cbom_size)
+ *cbom_size = 1 << cmo_node->cbom_size;
+
+ if (cboz_size)
+ *cboz_size = 1 << cmo_node->cboz_size;
+
+ if (cbop_size)
+ *cbop_size = 1 << cmo_node->cbop_size;
+ return 0;
+ }
+ }
+ }
+ }
+
+ return -ENOENT;
+}