2021-09-17 15:11:14

by Sudeep Holla

[permalink] [raw]
Subject: [PATCH v2 00/14] mailbox: pcc: Add support for PCCT extended PCC subspaces

Hi,

Though the series is about adding support for PCCT extended PCC subspaces,
except one patch, remaining are either preparatory or clean up to add
the PCCT extended PCC subspaces. Only patch 12 adds the support of extended
PCC type3/4 subspaces.

The main change affecting your is the change in pcc_mbox_request_channel
to avoid clien driver using con_priv member which is designed for controller
private pointer rather than for client's to use that.

Shared memory region accesses could be consolidated but I am planning to
take that up later as some drivers are using different types of mappings,
yet to figure out on how to consolidate that aspect.

Regards,
Sudeep

v1->v2:
- Addressed comments from Cristian and added his review tags as
provided

Sudeep Holla (14):
mailbox: pcc: Fix kernel doc warnings
ACPI: CPPC: Fix kernel doc warnings
mailbox: pcc: Refactor all PCC channel information into a structure
mailbox: pcc: Consolidate subspace interrupt information parsing
mailbox: pcc: Consolidate subspace doorbell register parsing
mailbox: pcc: Add pcc_mbox_chan structure to hold shared memory region info
mailbox: pcc: Use PCC mailbox channel pointer instead of standard
mailbox: pcc: Rename doorbell ack to platform interrupt ack register
mailbox: pcc: Add PCC register bundle and associated accessor functions
mailbox: pcc: Avoid accessing PCCT table in pcc_send_data and pcc_mbox_irq
mailbox: pcc: Drop handling invalid bit-width in {read,write}_register
mailbox: pcc: Add support for PCCT extended PCC subspaces(type 3/4)
mailbox: pcc: Move bulk of PCCT parsing into pcc_mbox_probe
ACPI/PCC: Add myself as maintainer for PCC mailbox driver

MAINTAINERS | 6 +
drivers/acpi/cppc_acpi.c | 50 +--
drivers/hwmon/xgene-hwmon.c | 35 +-
drivers/i2c/busses/i2c-xgene-slimpro.c | 33 +-
drivers/mailbox/pcc.c | 598 +++++++++++++++----------
include/acpi/pcc.h | 21 +-
6 files changed, 436 insertions(+), 307 deletions(-)

--
2.25.1


2021-09-17 15:11:34

by Sudeep Holla

[permalink] [raw]
Subject: [PATCH v2 04/14] mailbox: pcc: Consolidate subspace interrupt information parsing

Extended PCC subspaces(Type 3 and 4) differ from generic(Type 0) and
HW-Reduced Communication(Type 1 and 2) subspace structures. However some
fields share same offsets and same type of structure can be use to extract
the fields. In order to simplify that, let us move all the IRQ related
information parsing into pcc_parse_subspace_irq and consolidate there.
It will be easier to extend it if required within the same.

Reviewed-by: Cristian Marussi <[email protected]>
Signed-off-by: Sudeep Holla <[email protected]>
---
drivers/mailbox/pcc.c | 38 +++++++++++++++++++-------------------
1 file changed, 19 insertions(+), 19 deletions(-)

diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c
index 588d2207edf9..efde77d7038c 100644
--- a/drivers/mailbox/pcc.c
+++ b/drivers/mailbox/pcc.c
@@ -405,18 +405,26 @@ static int parse_pcc_subspace(union acpi_subtable_headers *header,

/**
* pcc_parse_subspace_irq - Parse the PCC IRQ and PCC ACK register
- * There should be one entry per PCC client.
- * @id: PCC subspace index.
- * @pcct_ss: Pointer to the ACPI subtable header under the PCCT.
+ *
+ * @pchan: Pointer to the PCC channel info structure.
+ * @pcct_entry: Pointer to the ACPI subtable header.
*
* Return: 0 for Success, else errno.
*
- * This gets called for each entry in the PCC table.
+ * There should be one entry per PCC channel. This gets called for each
+ * entry in the PCC table. This uses PCCY Type1 structure for all applicable
+ * types(Type 1-4) to fetch irq
*/
-static int pcc_parse_subspace_irq(int id, struct acpi_pcct_hw_reduced *pcct_ss)
+static int pcc_parse_subspace_irq(struct pcc_chan_info *pchan,
+ struct acpi_subtable_header *pcct_entry)
{
- struct pcc_chan_info *pchan = chan_info + id;
+ struct acpi_pcct_hw_reduced *pcct_ss;

+ if (pcct_entry->type < ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE ||
+ pcct_entry->type > ACPI_PCCT_TYPE_EXT_PCC_SLAVE_SUBSPACE)
+ return 0;
+
+ pcct_ss = (struct acpi_pcct_hw_reduced *)pcct_entry;
pchan->db_irq = pcc_map_interrupt(pcct_ss->platform_interrupt,
(u32)pcct_ss->flags);
if (pchan->db_irq <= 0) {
@@ -425,8 +433,7 @@ static int pcc_parse_subspace_irq(int id, struct acpi_pcct_hw_reduced *pcct_ss)
return -EINVAL;
}

- if (pcct_ss->header.type
- == ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE_TYPE2) {
+ if (pcct_ss->header.type == ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE_TYPE2) {
struct acpi_pcct_hw_reduced_type2 *pcct2_ss = (void *)pcct_ss;

pchan->db_ack_vaddr =
@@ -510,17 +517,10 @@ static int __init acpi_pcc_probe(void)
struct acpi_pcct_subspace *pcct_ss;
pcc_mbox_channels[i].con_priv = pcct_entry;

- if (pcct_entry->type == ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE ||
- pcct_entry->type == ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE_TYPE2) {
- struct acpi_pcct_hw_reduced *pcct_hrss;
-
- pcct_hrss = (struct acpi_pcct_hw_reduced *) pcct_entry;
-
- if (pcc_mbox_ctrl.txdone_irq) {
- rc = pcc_parse_subspace_irq(i, pcct_hrss);
- if (rc < 0)
- goto err;
- }
+ if (pcc_mbox_ctrl.txdone_irq) {
+ rc = pcc_parse_subspace_irq(pchan, pcct_entry);
+ if (rc < 0)
+ goto err;
}
pcct_ss = (struct acpi_pcct_subspace *) pcct_entry;

--
2.25.1

2021-09-17 15:11:52

by Sudeep Holla

[permalink] [raw]
Subject: [PATCH v2 05/14] mailbox: pcc: Consolidate subspace doorbell register parsing

Extended PCC subspaces(Type 3 and 4) differ from generic(Type 0) and
HW-Reduced Communication(Type 1 and 2) subspace structures. However some
fields share same offsets and same type of structure can be use to
extract the fields. In order to simplify that, let us move all the doorbell
register parsing into pcc_parse_subspace_db_reg and consolidate there.
It will be easier to extend it if required within the same.

Reviewed-by: Cristian Marussi <[email protected]>
Signed-off-by: Sudeep Holla <[email protected]>
---
drivers/mailbox/pcc.c | 31 +++++++++++++++++++++++--------
1 file changed, 23 insertions(+), 8 deletions(-)

diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c
index efde77d7038c..97c44c431ada 100644
--- a/drivers/mailbox/pcc.c
+++ b/drivers/mailbox/pcc.c
@@ -448,6 +448,28 @@ static int pcc_parse_subspace_irq(struct pcc_chan_info *pchan,
return 0;
}

+/**
+ * pcc_parse_subspace_db_reg - Parse the PCC doorbell register
+ *
+ * @pchan: Pointer to the PCC channel info structure.
+ * @pcct_entry: Pointer to the ACPI subtable header.
+ *
+ */
+static void pcc_parse_subspace_db_reg(struct pcc_chan_info *pchan,
+ struct acpi_subtable_header *pcct_entry)
+{
+ struct acpi_pcct_subspace *pcct_ss;
+ struct acpi_generic_address *db_reg;
+
+ pcct_ss = (struct acpi_pcct_subspace *)pcct_entry;
+
+ /* If doorbell is in system memory cache the virt address */
+ db_reg = &pcct_ss->doorbell_register;
+ if (db_reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
+ pchan->db_vaddr = acpi_os_ioremap(db_reg->address,
+ db_reg->bit_width / 8);
+}
+
/**
* acpi_pcc_probe - Parse the ACPI tree for the PCCT.
*
@@ -513,8 +535,6 @@ static int __init acpi_pcc_probe(void)

for (i = 0; i < count; i++) {
struct pcc_chan_info *pchan = chan_info + i;
- struct acpi_generic_address *db_reg;
- struct acpi_pcct_subspace *pcct_ss;
pcc_mbox_channels[i].con_priv = pcct_entry;

if (pcc_mbox_ctrl.txdone_irq) {
@@ -522,13 +542,8 @@ static int __init acpi_pcc_probe(void)
if (rc < 0)
goto err;
}
- pcct_ss = (struct acpi_pcct_subspace *) pcct_entry;
+ pcc_parse_subspace_db_reg(pchan, pcct_entry);

- /* If doorbell is in system memory cache the virt address */
- db_reg = &pcct_ss->doorbell_register;
- if (db_reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
- pchan->db_vaddr = acpi_os_ioremap(db_reg->address,
- db_reg->bit_width / 8);
pcct_entry = (struct acpi_subtable_header *)
((unsigned long) pcct_entry + pcct_entry->length);
}
--
2.25.1

2021-09-17 15:12:14

by Sudeep Holla

[permalink] [raw]
Subject: [PATCH v2 06/14] mailbox: pcc: Add pcc_mbox_chan structure to hold shared memory region info

Currently PCC mailbox controller sets con_priv in each channel to hold
the pointer to pcct subspace entry it corresponds to. The mailbox user
will then fetch this pointer from the channel descriptor they get when
they request for the channel. Using that pointer they then parse the
pcct entry again to fetch all the information about shared memory region.

In order to remove individual users of PCC mailbox parsing the PCCT
subspace entries to fetch same information, let us consolidate the same
in pcc mailbox controller by parsing all the shared memory region
information into a structure that can also hold the mbox_chan pointer it
represent.

This can then be used as main PCC mailbox channel pointer that we can
return as part of pcc_mbox_request_channel instead of standard mailbox
channel pointer.

Reviewed-by: Cristian Marussi <[email protected]>
Signed-off-by: Sudeep Holla <[email protected]>
---
drivers/mailbox/pcc.c | 27 +++++++++++++++++++++++++++
include/acpi/pcc.h | 9 +++++++++
2 files changed, 36 insertions(+)

diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c
index 97c44c431ada..f358ced827f2 100644
--- a/drivers/mailbox/pcc.c
+++ b/drivers/mailbox/pcc.c
@@ -67,11 +67,13 @@ static struct mbox_chan *pcc_mbox_channels;
/**
* struct pcc_chan_info - PCC channel specific information
*
+ * @chan: PCC channel information with Shared Memory Region info
* @db_vaddr: cached virtual address for doorbell register
* @db_ack_vaddr: cached virtual address for doorbell ack register
* @db_irq: doorbell interrupt
*/
struct pcc_chan_info {
+ struct pcc_mbox_chan chan;
void __iomem *db_vaddr;
void __iomem *db_ack_vaddr;
int db_irq;
@@ -470,6 +472,27 @@ static void pcc_parse_subspace_db_reg(struct pcc_chan_info *pchan,
db_reg->bit_width / 8);
}

+/**
+ * pcc_parse_subspace_shmem - Parse the PCC Shared Memory Region information
+ *
+ * @pchan: Pointer to the PCC channel info structure.
+ * @pcct_entry: Pointer to the ACPI subtable header.
+ *
+ */
+static void pcc_parse_subspace_shmem(struct pcc_chan_info *pchan,
+ struct acpi_subtable_header *pcct_entry)
+{
+ struct acpi_pcct_subspace *pcct_ss;
+
+ pcct_ss = (struct acpi_pcct_subspace *)pcct_entry;
+
+ pchan->chan.shmem_base_addr = pcct_ss->base_address;
+ pchan->chan.shmem_size = pcct_ss->length;
+ pchan->chan.latency = pcct_ss->latency;
+ pchan->chan.max_access_rate = pcct_ss->max_access_rate;
+ pchan->chan.min_turnaround_time = pcct_ss->min_turnaround_time;
+}
+
/**
* acpi_pcc_probe - Parse the ACPI tree for the PCCT.
*
@@ -537,6 +560,8 @@ static int __init acpi_pcc_probe(void)
struct pcc_chan_info *pchan = chan_info + i;
pcc_mbox_channels[i].con_priv = pcct_entry;

+ pchan->chan.mchan = &pcc_mbox_channels[i];
+
if (pcc_mbox_ctrl.txdone_irq) {
rc = pcc_parse_subspace_irq(pchan, pcct_entry);
if (rc < 0)
@@ -544,6 +569,8 @@ static int __init acpi_pcc_probe(void)
}
pcc_parse_subspace_db_reg(pchan, pcct_entry);

+ pcc_parse_subspace_shmem(pchan, pcct_entry);
+
pcct_entry = (struct acpi_subtable_header *)
((unsigned long) pcct_entry + pcct_entry->length);
}
diff --git a/include/acpi/pcc.h b/include/acpi/pcc.h
index 4dec4ed138cd..5e510a6b8052 100644
--- a/include/acpi/pcc.h
+++ b/include/acpi/pcc.h
@@ -9,6 +9,15 @@
#include <linux/mailbox_controller.h>
#include <linux/mailbox_client.h>

+struct pcc_mbox_chan {
+ struct mbox_chan *mchan;
+ u64 shmem_base_addr;
+ u64 shmem_size;
+ u32 latency;
+ u32 max_access_rate;
+ u16 min_turnaround_time;
+};
+
#define MAX_PCC_SUBSPACES 256
#ifdef CONFIG_PCC
extern struct mbox_chan *pcc_mbox_request_channel(struct mbox_client *cl,
--
2.25.1

2021-09-17 15:12:38

by Sudeep Holla

[permalink] [raw]
Subject: [PATCH v2 10/14] mailbox: pcc: Avoid accessing PCCT table in pcc_send_data and pcc_mbox_irq

Now that the con_priv is availvale solely for PCC mailbox controller
driver, let us use the same to save the channel specific information
in it so that we can it whenever required instead of parsing the PCCT
table entries every time in both pcc_send_data and pcc_mbox_irq.

We can now use the newly introduces PCC register bundle to simplify both
saving of channel specific information and accessing them without repeated
checks for the subspace type.

Reviewed-by: Cristian Marussi <[email protected]>
Signed-off-by: Sudeep Holla <[email protected]>
---
drivers/mailbox/pcc.c | 119 ++++++++++++------------------------------
1 file changed, 32 insertions(+), 87 deletions(-)

diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c
index deaea9d423a7..ed635f7d3f60 100644
--- a/drivers/mailbox/pcc.c
+++ b/drivers/mailbox/pcc.c
@@ -86,15 +86,15 @@ struct pcc_chan_reg {
* struct pcc_chan_info - PCC channel specific information
*
* @chan: PCC channel information with Shared Memory Region info
- * @db_vaddr: cached virtual address for doorbell register
- * @plat_irq_ack_vaddr: cached virtual address for platform interrupt
- * acknowledge register
+ * @db: PCC register bundle for the doorbell register
+ * @plat_irq_ack: PCC register bundle for the platform interrupt acknowledge
+ * register
* @plat_irq: platform interrupt
*/
struct pcc_chan_info {
struct pcc_mbox_chan chan;
- void __iomem *db_vaddr;
- void __iomem *plat_irq_ack_vaddr;
+ struct pcc_chan_reg db;
+ struct pcc_chan_reg plat_irq_ack;
int plat_irq;
};

@@ -242,40 +242,15 @@ static int pcc_map_interrupt(u32 interrupt, u32 flags)
*/
static irqreturn_t pcc_mbox_irq(int irq, void *p)
{
- struct acpi_generic_address *doorbell_ack;
- struct acpi_pcct_hw_reduced *pcct_ss;
struct pcc_chan_info *pchan;
struct mbox_chan *chan = p;
- u64 doorbell_ack_preserve;
- u64 doorbell_ack_write;
- u64 doorbell_ack_val;
- int ret;

- pcct_ss = chan->con_priv;
+ pchan = chan->con_priv;

- mbox_chan_received_data(chan, NULL);
+ if (pcc_chan_reg_read_modify_write(&pchan->plat_irq_ack))
+ return IRQ_NONE;

- if (pcct_ss->header.type == ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE_TYPE2) {
- struct acpi_pcct_hw_reduced_type2 *pcct2_ss = chan->con_priv;
- u32 id = chan - pcc_mbox_channels;
-
- pchan = chan_info + id;
- doorbell_ack = &pcct2_ss->platform_ack_register;
- doorbell_ack_preserve = pcct2_ss->ack_preserve_mask;
- doorbell_ack_write = pcct2_ss->ack_write_mask;
-
- ret = read_register(pchan->plat_irq_ack_vaddr,
- &doorbell_ack_val, doorbell_ack->bit_width);
- if (ret)
- return IRQ_NONE;
-
- ret = write_register(pchan->plat_irq_ack_vaddr,
- (doorbell_ack_val & doorbell_ack_preserve)
- | doorbell_ack_write,
- doorbell_ack->bit_width);
- if (ret)
- return IRQ_NONE;
- }
+ mbox_chan_received_data(chan, NULL);

return IRQ_HANDLED;
}
@@ -381,42 +356,9 @@ EXPORT_SYMBOL_GPL(pcc_mbox_free_channel);
*/
static int pcc_send_data(struct mbox_chan *chan, void *data)
{
- struct acpi_pcct_hw_reduced *pcct_ss = chan->con_priv;
- struct acpi_generic_address *doorbell;
- struct pcc_chan_info *pchan;
- u64 doorbell_preserve;
- u64 doorbell_val;
- u64 doorbell_write;
- u32 id = chan - pcc_mbox_channels;
- int ret = 0;
+ struct pcc_chan_info *pchan = chan->con_priv;

- if (id >= pcc_mbox_ctrl.num_chans) {
- pr_debug("pcc_send_data: Invalid mbox_chan passed\n");
- return -ENOENT;
- }
-
- pchan = chan_info + id;
- doorbell = &pcct_ss->doorbell_register;
- doorbell_preserve = pcct_ss->preserve_mask;
- doorbell_write = pcct_ss->write_mask;
-
- /* Sync notification from OS to Platform. */
- if (pchan->db_vaddr) {
- ret = read_register(pchan->db_vaddr, &doorbell_val,
- doorbell->bit_width);
- if (ret)
- return ret;
- ret = write_register(pchan->db_vaddr,
- (doorbell_val & doorbell_preserve)
- | doorbell_write, doorbell->bit_width);
- } else {
- ret = acpi_read(&doorbell_val, doorbell);
- if (ret)
- return ret;
- ret = acpi_write((doorbell_val & doorbell_preserve) | doorbell_write,
- doorbell);
- }
- return ret;
+ return pcc_chan_reg_read_modify_write(&pchan->db);
}

static const struct mbox_chan_ops pcc_chan_ops = {
@@ -484,6 +426,7 @@ pcc_chan_reg_init(struct pcc_chan_reg *reg, struct acpi_generic_address *gas,
static int pcc_parse_subspace_irq(struct pcc_chan_info *pchan,
struct acpi_subtable_header *pcct_entry)
{
+ int ret = 0;
struct acpi_pcct_hw_reduced *pcct_ss;

if (pcct_entry->type < ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE ||
@@ -502,16 +445,14 @@ static int pcc_parse_subspace_irq(struct pcc_chan_info *pchan,
if (pcct_ss->header.type == ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE_TYPE2) {
struct acpi_pcct_hw_reduced_type2 *pcct2_ss = (void *)pcct_ss;

- pchan->plat_irq_ack_vaddr =
- acpi_os_ioremap(pcct2_ss->platform_ack_register.address,
- pcct2_ss->platform_ack_register.bit_width / 8);
- if (!pchan->plat_irq_ack_vaddr) {
- pr_err("Failed to ioremap PCC ACK register\n");
- return -ENOMEM;
- }
+ ret = pcc_chan_reg_init(&pchan->plat_irq_ack,
+ &pcct2_ss->platform_ack_register,
+ pcct2_ss->ack_preserve_mask,
+ pcct2_ss->ack_write_mask, 0,
+ "PLAT IRQ ACK");
}

- return 0;
+ return ret;
}

/**
@@ -520,20 +461,22 @@ static int pcc_parse_subspace_irq(struct pcc_chan_info *pchan,
* @pchan: Pointer to the PCC channel info structure.
* @pcct_entry: Pointer to the ACPI subtable header.
*
+ * Return: 0 for Success, else errno.
*/
-static void pcc_parse_subspace_db_reg(struct pcc_chan_info *pchan,
- struct acpi_subtable_header *pcct_entry)
+static int pcc_parse_subspace_db_reg(struct pcc_chan_info *pchan,
+ struct acpi_subtable_header *pcct_entry)
{
+ int ret = 0;
+
struct acpi_pcct_subspace *pcct_ss;
- struct acpi_generic_address *db_reg;

pcct_ss = (struct acpi_pcct_subspace *)pcct_entry;

- /* If doorbell is in system memory cache the virt address */
- db_reg = &pcct_ss->doorbell_register;
- if (db_reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
- pchan->db_vaddr = acpi_os_ioremap(db_reg->address,
- db_reg->bit_width / 8);
+ ret = pcc_chan_reg_init(&pchan->db,
+ &pcct_ss->doorbell_register,
+ pcct_ss->preserve_mask,
+ pcct_ss->write_mask, 0, "Doorbell");
+ return ret;
}

/**
@@ -622,8 +565,8 @@ static int __init acpi_pcc_probe(void)

for (i = 0; i < count; i++) {
struct pcc_chan_info *pchan = chan_info + i;
- pcc_mbox_channels[i].con_priv = pcct_entry;

+ pcc_mbox_channels[i].con_priv = pchan;
pchan->chan.mchan = &pcc_mbox_channels[i];

if (pcc_mbox_ctrl.txdone_irq) {
@@ -631,7 +574,9 @@ static int __init acpi_pcc_probe(void)
if (rc < 0)
goto err;
}
- pcc_parse_subspace_db_reg(pchan, pcct_entry);
+ rc = pcc_parse_subspace_db_reg(pchan, pcct_entry);
+ if (rc < 0)
+ goto err;

pcc_parse_subspace_shmem(pchan, pcct_entry);

--
2.25.1

2021-09-17 15:13:04

by Sudeep Holla

[permalink] [raw]
Subject: [PATCH v2 12/14] mailbox: pcc: Add support for PCCT extended PCC subspaces(type 3/4)

With all the plumbing in place to avoid accessing PCCT type and other
fields directly from the PCCT table all the time, let us now add the
support for extended PCC subspaces(type 3 and 4).

Signed-off-by: Sudeep Holla <[email protected]>
---
drivers/mailbox/pcc.c | 126 ++++++++++++++++++++++++++++++++++++------
1 file changed, 109 insertions(+), 17 deletions(-)

diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c
index 4bace1fa48f0..eb90c9eaaf9c 100644
--- a/drivers/mailbox/pcc.c
+++ b/drivers/mailbox/pcc.c
@@ -89,12 +89,18 @@ struct pcc_chan_reg {
* @db: PCC register bundle for the doorbell register
* @plat_irq_ack: PCC register bundle for the platform interrupt acknowledge
* register
+ * @cmd_complete: PCC register bundle for the command complete check register
+ * @cmd_update: PCC register bundle for the command complete update register
+ * @error: PCC register bundle for the error status register
* @plat_irq: platform interrupt
*/
struct pcc_chan_info {
struct pcc_mbox_chan chan;
struct pcc_chan_reg db;
struct pcc_chan_reg plat_irq_ack;
+ struct pcc_chan_reg cmd_complete;
+ struct pcc_chan_reg cmd_update;
+ struct pcc_chan_reg error;
int plat_irq;
};

@@ -228,9 +234,29 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p)
{
struct pcc_chan_info *pchan;
struct mbox_chan *chan = p;
+ u64 val;
+ int ret;

pchan = chan->con_priv;

+ ret = pcc_chan_reg_read(&pchan->cmd_complete, &val);
+ if (ret)
+ return IRQ_NONE;
+
+ val &= pchan->cmd_complete.status_mask;
+ if (!val)
+ return IRQ_NONE;
+
+ ret = pcc_chan_reg_read(&pchan->error, &val);
+ if (ret)
+ return IRQ_NONE;
+ val &= pchan->error.status_mask;
+ if (val) {
+ val &= ~pchan->error.status_mask;
+ pcc_chan_reg_write(&pchan->error, val);
+ return IRQ_NONE;
+ }
+
if (pcc_chan_reg_read_modify_write(&pchan->plat_irq_ack))
return IRQ_NONE;

@@ -340,8 +366,13 @@ EXPORT_SYMBOL_GPL(pcc_mbox_free_channel);
*/
static int pcc_send_data(struct mbox_chan *chan, void *data)
{
+ int ret;
struct pcc_chan_info *pchan = chan->con_priv;

+ ret = pcc_chan_reg_read_modify_write(&pchan->cmd_update);
+ if (ret)
+ return ret;
+
return pcc_chan_reg_read_modify_write(&pchan->db);
}

@@ -434,6 +465,16 @@ static int pcc_parse_subspace_irq(struct pcc_chan_info *pchan,
pcct2_ss->ack_preserve_mask,
pcct2_ss->ack_write_mask, 0,
"PLAT IRQ ACK");
+
+ } else if (pcct_ss->header.type == ACPI_PCCT_TYPE_EXT_PCC_MASTER_SUBSPACE ||
+ pcct_ss->header.type == ACPI_PCCT_TYPE_EXT_PCC_SLAVE_SUBSPACE) {
+ struct acpi_pcct_ext_pcc_master *pcct_ext = (void *)pcct_ss;
+
+ ret = pcc_chan_reg_init(&pchan->plat_irq_ack,
+ &pcct_ext->platform_ack_register,
+ pcct_ext->ack_preserve_mask,
+ pcct_ext->ack_set_mask, 0,
+ "PLAT IRQ ACK");
}

return ret;
@@ -452,14 +493,48 @@ static int pcc_parse_subspace_db_reg(struct pcc_chan_info *pchan,
{
int ret = 0;

- struct acpi_pcct_subspace *pcct_ss;
-
- pcct_ss = (struct acpi_pcct_subspace *)pcct_entry;
-
- ret = pcc_chan_reg_init(&pchan->db,
- &pcct_ss->doorbell_register,
- pcct_ss->preserve_mask,
- pcct_ss->write_mask, 0, "Doorbell");
+ if (pcct_entry->type <= ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE_TYPE2) {
+ struct acpi_pcct_subspace *pcct_ss;
+
+ pcct_ss = (struct acpi_pcct_subspace *)pcct_entry;
+
+ ret = pcc_chan_reg_init(&pchan->db,
+ &pcct_ss->doorbell_register,
+ pcct_ss->preserve_mask,
+ pcct_ss->write_mask, 0, "Doorbell");
+
+ } else {
+ struct acpi_pcct_ext_pcc_master *pcct_ext;
+
+ pcct_ext = (struct acpi_pcct_ext_pcc_master *)pcct_entry;
+
+ ret = pcc_chan_reg_init(&pchan->db,
+ &pcct_ext->doorbell_register,
+ pcct_ext->preserve_mask,
+ pcct_ext->write_mask, 0, "Doorbell");
+ if (ret)
+ return ret;
+
+ ret = pcc_chan_reg_init(&pchan->cmd_complete,
+ &pcct_ext->cmd_complete_register,
+ 0, 0, pcct_ext->cmd_complete_mask,
+ "Command Complete Check");
+ if (ret)
+ return ret;
+
+ ret = pcc_chan_reg_init(&pchan->cmd_update,
+ &pcct_ext->cmd_update_register,
+ pcct_ext->cmd_update_preserve_mask,
+ pcct_ext->cmd_update_set_mask, 0,
+ "Command Complete Update");
+ if (ret)
+ return ret;
+
+ ret = pcc_chan_reg_init(&pchan->error,
+ &pcct_ext->error_status_register,
+ 0, 0, pcct_ext->error_status_mask,
+ "Error Status");
+ }
return ret;
}

@@ -473,15 +548,25 @@ static int pcc_parse_subspace_db_reg(struct pcc_chan_info *pchan,
static void pcc_parse_subspace_shmem(struct pcc_chan_info *pchan,
struct acpi_subtable_header *pcct_entry)
{
- struct acpi_pcct_subspace *pcct_ss;
-
- pcct_ss = (struct acpi_pcct_subspace *)pcct_entry;
-
- pchan->chan.shmem_base_addr = pcct_ss->base_address;
- pchan->chan.shmem_size = pcct_ss->length;
- pchan->chan.latency = pcct_ss->latency;
- pchan->chan.max_access_rate = pcct_ss->max_access_rate;
- pchan->chan.min_turnaround_time = pcct_ss->min_turnaround_time;
+ if (pcct_entry->type <= ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE_TYPE2) {
+ struct acpi_pcct_subspace *pcct_ss =
+ (struct acpi_pcct_subspace *)pcct_entry;
+
+ pchan->chan.shmem_base_addr = pcct_ss->base_address;
+ pchan->chan.shmem_size = pcct_ss->length;
+ pchan->chan.latency = pcct_ss->latency;
+ pchan->chan.max_access_rate = pcct_ss->max_access_rate;
+ pchan->chan.min_turnaround_time = pcct_ss->min_turnaround_time;
+ } else {
+ struct acpi_pcct_ext_pcc_master *pcct_ext =
+ (struct acpi_pcct_ext_pcc_master *)pcct_entry;
+
+ pchan->chan.shmem_base_addr = pcct_ext->base_address;
+ pchan->chan.shmem_size = pcct_ext->length;
+ pchan->chan.latency = pcct_ext->latency;
+ pchan->chan.max_access_rate = pcct_ext->max_access_rate;
+ pchan->chan.min_turnaround_time = pcct_ext->min_turnaround_time;
+ }
}

/**
@@ -553,6 +638,13 @@ static int __init acpi_pcc_probe(void)
pcc_mbox_channels[i].con_priv = pchan;
pchan->chan.mchan = &pcc_mbox_channels[i];

+ if (pcct_entry->type == ACPI_PCCT_TYPE_EXT_PCC_SLAVE_SUBSPACE &&
+ !pcc_mbox_ctrl.txdone_irq) {
+ pr_err("Plaform Interrupt flag must be set to 1");
+ rc = -EINVAL;
+ goto err;
+ }
+
if (pcc_mbox_ctrl.txdone_irq) {
rc = pcc_parse_subspace_irq(pchan, pcct_entry);
if (rc < 0)
--
2.25.1

2021-09-17 15:14:36

by Sudeep Holla

[permalink] [raw]
Subject: [PATCH v2 03/14] mailbox: pcc: Refactor all PCC channel information into a structure

Currently all the PCC channel specific information are stored/maintained
in global individual arrays for each of those information. It is not
scalable and not clean if we have to stash more channel specific
information. Couple of reasons to stash more information are to extend
the support to Type 3/4 PCCT subspace and also to avoid accessing the
PCCT table entries themselves each time we need the information.

This patch moves all those PCC channel specific information into a
separate structure pcc_chan_info.

Signed-off-by: Sudeep Holla <[email protected]>
---
drivers/mailbox/pcc.c | 107 +++++++++++++++++++++---------------------
1 file changed, 54 insertions(+), 53 deletions(-)

diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c
index 23391e224a68..588d2207edf9 100644
--- a/drivers/mailbox/pcc.c
+++ b/drivers/mailbox/pcc.c
@@ -64,12 +64,20 @@

static struct mbox_chan *pcc_mbox_channels;

-/* Array of cached virtual address for doorbell registers */
-static void __iomem **pcc_doorbell_vaddr;
-/* Array of cached virtual address for doorbell ack registers */
-static void __iomem **pcc_doorbell_ack_vaddr;
-/* Array of doorbell interrupts */
-static int *pcc_doorbell_irq;
+/**
+ * struct pcc_chan_info - PCC channel specific information
+ *
+ * @db_vaddr: cached virtual address for doorbell register
+ * @db_ack_vaddr: cached virtual address for doorbell ack register
+ * @db_irq: doorbell interrupt
+ */
+struct pcc_chan_info {
+ void __iomem *db_vaddr;
+ void __iomem *db_ack_vaddr;
+ int db_irq;
+};
+
+static struct pcc_chan_info *chan_info;

static struct mbox_controller pcc_mbox_ctrl = {};
/**
@@ -183,6 +191,7 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p)
{
struct acpi_generic_address *doorbell_ack;
struct acpi_pcct_hw_reduced *pcct_ss;
+ struct pcc_chan_info *pchan;
struct mbox_chan *chan = p;
u64 doorbell_ack_preserve;
u64 doorbell_ack_write;
@@ -197,17 +206,17 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p)
struct acpi_pcct_hw_reduced_type2 *pcct2_ss = chan->con_priv;
u32 id = chan - pcc_mbox_channels;

+ pchan = chan_info + id;
doorbell_ack = &pcct2_ss->platform_ack_register;
doorbell_ack_preserve = pcct2_ss->ack_preserve_mask;
doorbell_ack_write = pcct2_ss->ack_write_mask;

- ret = read_register(pcc_doorbell_ack_vaddr[id],
- &doorbell_ack_val,
- doorbell_ack->bit_width);
+ ret = read_register(pchan->db_ack_vaddr,
+ &doorbell_ack_val, doorbell_ack->bit_width);
if (ret)
return IRQ_NONE;

- ret = write_register(pcc_doorbell_ack_vaddr[id],
+ ret = write_register(pchan->db_ack_vaddr,
(doorbell_ack_val & doorbell_ack_preserve)
| doorbell_ack_write,
doorbell_ack->bit_width);
@@ -232,8 +241,9 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p)
* ERR_PTR.
*/
struct mbox_chan *pcc_mbox_request_channel(struct mbox_client *cl,
- int subspace_id)
+ int subspace_id)
{
+ struct pcc_chan_info *pchan;
struct device *dev = pcc_mbox_ctrl.dev;
struct mbox_chan *chan;
unsigned long flags;
@@ -251,6 +261,7 @@ struct mbox_chan *pcc_mbox_request_channel(struct mbox_client *cl,
dev_err(dev, "Channel not found for idx: %d\n", subspace_id);
return ERR_PTR(-EBUSY);
}
+ pchan = chan_info + subspace_id;

spin_lock_irqsave(&chan->lock, flags);
chan->msg_free = 0;
@@ -264,14 +275,14 @@ struct mbox_chan *pcc_mbox_request_channel(struct mbox_client *cl,

spin_unlock_irqrestore(&chan->lock, flags);

- if (pcc_doorbell_irq[subspace_id] > 0) {
+ if (pchan->db_irq > 0) {
int rc;

- rc = devm_request_irq(dev, pcc_doorbell_irq[subspace_id],
- pcc_mbox_irq, 0, MBOX_IRQ_NAME, chan);
+ rc = devm_request_irq(dev, pchan->db_irq, pcc_mbox_irq, 0,
+ MBOX_IRQ_NAME, chan);
if (unlikely(rc)) {
dev_err(dev, "failed to register PCC interrupt %d\n",
- pcc_doorbell_irq[subspace_id]);
+ pchan->db_irq);
pcc_mbox_free_channel(chan);
chan = ERR_PTR(rc);
}
@@ -290,6 +301,7 @@ EXPORT_SYMBOL_GPL(pcc_mbox_request_channel);
void pcc_mbox_free_channel(struct mbox_chan *chan)
{
u32 id = chan - pcc_mbox_channels;
+ struct pcc_chan_info *pchan;
unsigned long flags;

if (!chan || !chan->cl)
@@ -300,8 +312,9 @@ void pcc_mbox_free_channel(struct mbox_chan *chan)
return;
}

- if (pcc_doorbell_irq[id] > 0)
- devm_free_irq(chan->mbox->dev, pcc_doorbell_irq[id], chan);
+ pchan = chan_info + id;
+ if (pchan->db_irq > 0)
+ devm_free_irq(chan->mbox->dev, pchan->db_irq, chan);

spin_lock_irqsave(&chan->lock, flags);
chan->cl = NULL;
@@ -329,6 +342,7 @@ static int pcc_send_data(struct mbox_chan *chan, void *data)
{
struct acpi_pcct_hw_reduced *pcct_ss = chan->con_priv;
struct acpi_generic_address *doorbell;
+ struct pcc_chan_info *pchan;
u64 doorbell_preserve;
u64 doorbell_val;
u64 doorbell_write;
@@ -340,19 +354,20 @@ static int pcc_send_data(struct mbox_chan *chan, void *data)
return -ENOENT;
}

+ pchan = chan_info + id;
doorbell = &pcct_ss->doorbell_register;
doorbell_preserve = pcct_ss->preserve_mask;
doorbell_write = pcct_ss->write_mask;

/* Sync notification from OS to Platform. */
- if (pcc_doorbell_vaddr[id]) {
- ret = read_register(pcc_doorbell_vaddr[id], &doorbell_val,
- doorbell->bit_width);
+ if (pchan->db_vaddr) {
+ ret = read_register(pchan->db_vaddr, &doorbell_val,
+ doorbell->bit_width);
if (ret)
return ret;
- ret = write_register(pcc_doorbell_vaddr[id],
- (doorbell_val & doorbell_preserve) | doorbell_write,
- doorbell->bit_width);
+ ret = write_register(pchan->db_vaddr,
+ (doorbell_val & doorbell_preserve)
+ | doorbell_write, doorbell->bit_width);
} else {
ret = acpi_read(&doorbell_val, doorbell);
if (ret)
@@ -398,12 +413,13 @@ static int parse_pcc_subspace(union acpi_subtable_headers *header,
*
* This gets called for each entry in the PCC table.
*/
-static int pcc_parse_subspace_irq(int id,
- struct acpi_pcct_hw_reduced *pcct_ss)
+static int pcc_parse_subspace_irq(int id, struct acpi_pcct_hw_reduced *pcct_ss)
{
- pcc_doorbell_irq[id] = pcc_map_interrupt(pcct_ss->platform_interrupt,
- (u32)pcct_ss->flags);
- if (pcc_doorbell_irq[id] <= 0) {
+ struct pcc_chan_info *pchan = chan_info + id;
+
+ pchan->db_irq = pcc_map_interrupt(pcct_ss->platform_interrupt,
+ (u32)pcct_ss->flags);
+ if (pchan->db_irq <= 0) {
pr_err("PCC GSI %d not registered\n",
pcct_ss->platform_interrupt);
return -EINVAL;
@@ -413,10 +429,10 @@ static int pcc_parse_subspace_irq(int id,
== ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE_TYPE2) {
struct acpi_pcct_hw_reduced_type2 *pcct2_ss = (void *)pcct_ss;

- pcc_doorbell_ack_vaddr[id] = acpi_os_ioremap(
- pcct2_ss->platform_ack_register.address,
- pcct2_ss->platform_ack_register.bit_width / 8);
- if (!pcc_doorbell_ack_vaddr[id]) {
+ pchan->db_ack_vaddr =
+ acpi_os_ioremap(pcct2_ss->platform_ack_register.address,
+ pcct2_ss->platform_ack_register.bit_width / 8);
+ if (!pchan->db_ack_vaddr) {
pr_err("Failed to ioremap PCC ACK register\n");
return -ENOMEM;
}
@@ -474,24 +490,12 @@ static int __init acpi_pcc_probe(void)
goto err_put_pcct;
}

- pcc_doorbell_vaddr = kcalloc(count, sizeof(void *), GFP_KERNEL);
- if (!pcc_doorbell_vaddr) {
+ chan_info = kcalloc(count, sizeof(*chan_info), GFP_KERNEL);
+ if (!chan_info) {
rc = -ENOMEM;
goto err_free_mbox;
}

- pcc_doorbell_ack_vaddr = kcalloc(count, sizeof(void *), GFP_KERNEL);
- if (!pcc_doorbell_ack_vaddr) {
- rc = -ENOMEM;
- goto err_free_db_vaddr;
- }
-
- pcc_doorbell_irq = kcalloc(count, sizeof(int), GFP_KERNEL);
- if (!pcc_doorbell_irq) {
- rc = -ENOMEM;
- goto err_free_db_ack_vaddr;
- }
-
/* Point to the first PCC subspace entry */
pcct_entry = (struct acpi_subtable_header *) (
(unsigned long) pcct_tbl + sizeof(struct acpi_table_pcct));
@@ -501,6 +505,7 @@ static int __init acpi_pcc_probe(void)
pcc_mbox_ctrl.txdone_irq = true;

for (i = 0; i < count; i++) {
+ struct pcc_chan_info *pchan = chan_info + i;
struct acpi_generic_address *db_reg;
struct acpi_pcct_subspace *pcct_ss;
pcc_mbox_channels[i].con_priv = pcct_entry;
@@ -522,8 +527,8 @@ static int __init acpi_pcc_probe(void)
/* If doorbell is in system memory cache the virt address */
db_reg = &pcct_ss->doorbell_register;
if (db_reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
- pcc_doorbell_vaddr[i] = acpi_os_ioremap(db_reg->address,
- db_reg->bit_width/8);
+ pchan->db_vaddr = acpi_os_ioremap(db_reg->address,
+ db_reg->bit_width / 8);
pcct_entry = (struct acpi_subtable_header *)
((unsigned long) pcct_entry + pcct_entry->length);
}
@@ -535,11 +540,7 @@ static int __init acpi_pcc_probe(void)
return 0;

err:
- kfree(pcc_doorbell_irq);
-err_free_db_ack_vaddr:
- kfree(pcc_doorbell_ack_vaddr);
-err_free_db_vaddr:
- kfree(pcc_doorbell_vaddr);
+ kfree(chan_info);
err_free_mbox:
kfree(pcc_mbox_channels);
err_put_pcct:
--
2.25.1

2021-09-17 15:16:01

by Sudeep Holla

[permalink] [raw]
Subject: [PATCH v2 11/14] mailbox: pcc: Drop handling invalid bit-width in {read,write}_register

pcc_chan_reg_init now checks if the register bit width is within the
list [8, 16, 32, 64] and flags error if that is not the case. Therefore
there is no need to handling invalid bit-width in both read_register
and write_register. We can drop that along with the return values for
these 2 functions.

Signed-off-by: Sudeep Holla <[email protected]>
---
drivers/mailbox/pcc.c | 24 ++++--------------------
1 file changed, 4 insertions(+), 20 deletions(-)

diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c
index ed635f7d3f60..4bace1fa48f0 100644
--- a/drivers/mailbox/pcc.c
+++ b/drivers/mailbox/pcc.c
@@ -110,10 +110,8 @@ static struct mbox_controller pcc_mbox_ctrl = {};
* The below read_register and write_registers are used to read and
* write from perf critical registers such as PCC doorbell register
*/
-static int read_register(void __iomem *vaddr, u64 *val, unsigned int bit_width)
+static void read_register(void __iomem *vaddr, u64 *val, unsigned int bit_width)
{
- int ret_val = 0;
-
switch (bit_width) {
case 8:
*val = readb(vaddr);
@@ -127,19 +125,11 @@ static int read_register(void __iomem *vaddr, u64 *val, unsigned int bit_width)
case 64:
*val = readq(vaddr);
break;
- default:
- pr_debug("Error: Cannot read register of %u bit width",
- bit_width);
- ret_val = -EFAULT;
- break;
}
- return ret_val;
}

-static int write_register(void __iomem *vaddr, u64 val, unsigned int bit_width)
+static void write_register(void __iomem *vaddr, u64 val, unsigned int bit_width)
{
- int ret_val = 0;
-
switch (bit_width) {
case 8:
writeb(val, vaddr);
@@ -153,13 +143,7 @@ static int write_register(void __iomem *vaddr, u64 val, unsigned int bit_width)
case 64:
writeq(val, vaddr);
break;
- default:
- pr_debug("Error: Cannot write register of %u bit width",
- bit_width);
- ret_val = -EFAULT;
- break;
}
- return ret_val;
}

static int pcc_chan_reg_read(struct pcc_chan_reg *reg, u64 *val)
@@ -172,7 +156,7 @@ static int pcc_chan_reg_read(struct pcc_chan_reg *reg, u64 *val)
}

if (reg->vaddr)
- ret = read_register(reg->vaddr, val, reg->gas->bit_width);
+ read_register(reg->vaddr, val, reg->gas->bit_width);
else
ret = acpi_read(val, reg->gas);

@@ -187,7 +171,7 @@ static int pcc_chan_reg_write(struct pcc_chan_reg *reg, u64 val)
return 0;

if (reg->vaddr)
- ret = write_register(reg->vaddr, val, reg->gas->bit_width);
+ write_register(reg->vaddr, val, reg->gas->bit_width);
else
ret = acpi_write(val, reg->gas);

--
2.25.1

2021-09-17 21:17:31

by Sudeep Holla

[permalink] [raw]
Subject: [PATCH v2 09/14] mailbox: pcc: Add PCC register bundle and associated accessor functions

Extended PCC subspaces introduces more registers into the PCCT. In order
to consolidate access to these registers and to keep all the details
contained in one place, let us introduce PCC register bundle that holds
the ACPI Generic Address Structure as well as the virtual address for
the same if it is mapped in the OS.

It also contains the various masks used to access the register and
the associated read, write and read-modify-write accessors.

We can also clean up the initialisations by having a helper function
for the same.

Signed-off-by: Sudeep Holla <[email protected]>
---
drivers/mailbox/pcc.c | 90 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 90 insertions(+)

diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c
index ae4b7a4b3531..deaea9d423a7 100644
--- a/drivers/mailbox/pcc.c
+++ b/drivers/mailbox/pcc.c
@@ -52,6 +52,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/list.h>
+#include <linux/log2.h>
#include <linux/platform_device.h>
#include <linux/mailbox_controller.h>
#include <linux/mailbox_client.h>
@@ -64,6 +65,23 @@

static struct mbox_chan *pcc_mbox_channels;

+/**
+ * struct pcc_chan_reg - PCC register bundle
+ *
+ * @vaddr: cached virtual address for this register
+ * @gas: pointer to the generic address structure for this register
+ * @preserve_mask: bitmask to preserve when writing to this register
+ * @set_mask: bitmask to set when writing to this register
+ * @status_mask: bitmask to determine and/or update the status for this register
+ */
+struct pcc_chan_reg {
+ void __iomem *vaddr;
+ struct acpi_generic_address *gas;
+ u64 preserve_mask;
+ u64 set_mask;
+ u64 status_mask;
+};
+
/**
* struct pcc_chan_info - PCC channel specific information
*
@@ -144,6 +162,53 @@ static int write_register(void __iomem *vaddr, u64 val, unsigned int bit_width)
return ret_val;
}

+static int pcc_chan_reg_read(struct pcc_chan_reg *reg, u64 *val)
+{
+ int ret = 0;
+
+ if (!reg->gas) {
+ *val = 0;
+ return 0;
+ }
+
+ if (reg->vaddr)
+ ret = read_register(reg->vaddr, val, reg->gas->bit_width);
+ else
+ ret = acpi_read(val, reg->gas);
+
+ return ret;
+}
+
+static int pcc_chan_reg_write(struct pcc_chan_reg *reg, u64 val)
+{
+ int ret = 0;
+
+ if (!reg->gas)
+ return 0;
+
+ if (reg->vaddr)
+ ret = write_register(reg->vaddr, val, reg->gas->bit_width);
+ else
+ ret = acpi_write(val, reg->gas);
+
+ return ret;
+}
+
+static int pcc_chan_reg_read_modify_write(struct pcc_chan_reg *reg)
+{
+ int ret = 0;
+ u64 val;
+
+ ret = pcc_chan_reg_read(reg, &val);
+ if (ret)
+ return ret;
+
+ val &= reg->preserve_mask;
+ val |= reg->set_mask;
+
+ return pcc_chan_reg_write(reg, val);
+}
+
/**
* pcc_map_interrupt - Map a PCC subspace GSI to a linux IRQ number
* @interrupt: GSI number.
@@ -379,6 +444,31 @@ static int parse_pcc_subspace(union acpi_subtable_headers *header,
return -EINVAL;
}

+static int
+pcc_chan_reg_init(struct pcc_chan_reg *reg, struct acpi_generic_address *gas,
+ u64 preserve_mask, u64 set_mask, u64 status_mask, char *name)
+{
+ if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
+ if (!(gas->bit_width >= 8 && gas->bit_width <= 64 &&
+ is_power_of_2(gas->bit_width))) {
+ pr_err("Error: Cannot access register of %u bit width",
+ gas->bit_width);
+ return -EFAULT;
+ }
+
+ reg->vaddr = acpi_os_ioremap(gas->address, gas->bit_width / 8);
+ if (!reg->vaddr) {
+ pr_err("Failed to ioremap PCC %s register\n", name);
+ return -ENOMEM;
+ }
+ }
+ reg->gas = gas;
+ reg->preserve_mask = preserve_mask;
+ reg->set_mask = set_mask;
+ reg->status_mask = status_mask;
+ return 0;
+}
+
/**
* pcc_parse_subspace_irq - Parse the PCC IRQ and PCC ACK register
*
--
2.25.1

2021-09-17 22:04:31

by Sudeep Holla

[permalink] [raw]
Subject: [PATCH v2 01/14] mailbox: pcc: Fix kernel doc warnings

Kernel doc validation script is unhappy and complains with the below set
of warnings.

| drivers/mailbox/pcc.c:179: warning: Function parameter or member 'irq'
| not described in 'pcc_mbox_irq'
| drivers/mailbox/pcc.c:179: warning: Function parameter or member 'p'
| not described in 'pcc_mbox_irq'
| drivers/mailbox/pcc.c:378: warning: expecting prototype for
| parse_pcc_subspaces(). Prototype was for parse_pcc_subspace() instead

Fix it.

Signed-off-by: Sudeep Holla <[email protected]>
---
drivers/mailbox/pcc.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c
index 0296558f9e22..23391e224a68 100644
--- a/drivers/mailbox/pcc.c
+++ b/drivers/mailbox/pcc.c
@@ -174,6 +174,10 @@ static int pcc_map_interrupt(u32 interrupt, u32 flags)

/**
* pcc_mbox_irq - PCC mailbox interrupt handler
+ * @irq: interrupt number
+ * @p: data/cookie passed from the caller to identify the channel
+ *
+ * Returns: IRQ_HANDLED if interrupt is handled or IRQ_NONE if not
*/
static irqreturn_t pcc_mbox_irq(int irq, void *p)
{
@@ -364,7 +368,7 @@ static const struct mbox_chan_ops pcc_chan_ops = {
};

/**
- * parse_pcc_subspaces -- Count PCC subspaces defined
+ * parse_pcc_subspace - Count PCC subspaces defined
* @header: Pointer to the ACPI subtable header under the PCCT.
* @end: End of subtable entry.
*
--
2.25.1

2021-09-17 22:05:07

by Sudeep Holla

[permalink] [raw]
Subject: [PATCH v2 02/14] ACPI: CPPC: Fix kernel doc warnings

Kernel doc validation script is unhappy and complains with the below set
of warnings.

| drivers/acpi/cppc_acpi.c:560: warning: Function parameter or member
| 'pcc_ss_id' not described in 'pcc_data_alloc'
| drivers/acpi/cppc_acpi.c:1343: warning: Function parameter or member
| 'cpu_num' not described in 'cppc_get_transition_latency'

Fix it.

Signed-off-by: Sudeep Holla <[email protected]>
---
drivers/acpi/cppc_acpi.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
index bd482108310c..e195123e26c0 100644
--- a/drivers/acpi/cppc_acpi.c
+++ b/drivers/acpi/cppc_acpi.c
@@ -561,6 +561,7 @@ bool __weak cpc_ffh_supported(void)

/**
* pcc_data_alloc() - Allocate the pcc_data memory for pcc subspace
+ * @pcc_ss_id: PCC Subspace channel identifier
*
* Check and allocate the cppc_pcc_data memory.
* In some processor configurations it is possible that same subspace
@@ -1360,12 +1361,16 @@ int cppc_set_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls)
EXPORT_SYMBOL_GPL(cppc_set_perf);

/**
- * cppc_get_transition_latency - returns frequency transition latency in ns
+ * cppc_get_transition_latency - Provides frequency transition latency in ns
+ * @cpu_num: Logical index of the CPU for which latencty is requested
*
* ACPI CPPC does not explicitly specify how a platform can specify the
* transition latency for performance change requests. The closest we have
* is the timing information from the PCCT tables which provides the info
* on the number and frequency of PCC commands the platform can handle.
+ *
+ * Returns: frequency transition latency on success or CPUFREQ_ETERNAL on
+ * failure
*/
unsigned int cppc_get_transition_latency(int cpu_num)
{
--
2.25.1

2021-09-17 22:05:11

by Sudeep Holla

[permalink] [raw]
Subject: [PATCH v2 07/14] mailbox: pcc: Use PCC mailbox channel pointer instead of standard

Now that we have all the shared memory region information populated in
the pcc_mbox_chan, let us propagate the pointer to the same as the
return value to pcc_mbox_request channel.

This eliminates the need for the individual users of PCC mailbox to
parse the PCCT subspace entries and fetch the shmem information. This
also eliminates the need for PCC mailbox controller to set con_priv to
PCCT subspace entries. This is required as con_priv is private to the
controller driver to attach private data associated with the channel and
not meant to be used by the mailbox client/users.

Let us convert all the users of pcc_mbox_{request,free}_channel to use
new interface.

Cc: Jean Delvare <[email protected]>
Cc: Guenter Roeck <[email protected]>
Cc: Wolfram Sang <[email protected]>
Cc: [email protected]
Cc: [email protected]
Signed-off-by: Sudeep Holla <[email protected]>
---
drivers/acpi/cppc_acpi.c | 43 ++++++------------
drivers/hwmon/xgene-hwmon.c | 35 ++++++--------
drivers/i2c/busses/i2c-xgene-slimpro.c | 33 +++++---------
drivers/mailbox/pcc.c | 63 ++++++++------------------
include/acpi/pcc.h | 12 ++---
5 files changed, 64 insertions(+), 122 deletions(-)

diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
index e195123e26c0..aa6623bd3f00 100644
--- a/drivers/acpi/cppc_acpi.c
+++ b/drivers/acpi/cppc_acpi.c
@@ -43,7 +43,7 @@
#include <acpi/cppc_acpi.h>

struct cppc_pcc_data {
- struct mbox_chan *pcc_channel;
+ struct pcc_mbox_chan *pcc_channel;
void __iomem *pcc_comm_addr;
bool pcc_channel_acquired;
unsigned int deadline_us;
@@ -295,7 +295,7 @@ static int send_pcc_cmd(int pcc_ss_id, u16 cmd)
pcc_ss_data->platform_owns_pcc = true;

/* Ring doorbell */
- ret = mbox_send_message(pcc_ss_data->pcc_channel, &cmd);
+ ret = mbox_send_message(pcc_ss_data->pcc_channel->mchan, &cmd);
if (ret < 0) {
pr_err("Err sending PCC mbox message. ss: %d cmd:%d, ret:%d\n",
pcc_ss_id, cmd, ret);
@@ -308,10 +308,10 @@ static int send_pcc_cmd(int pcc_ss_id, u16 cmd)
if (pcc_ss_data->pcc_mrtt)
pcc_ss_data->last_cmd_cmpl_time = ktime_get();

- if (pcc_ss_data->pcc_channel->mbox->txdone_irq)
- mbox_chan_txdone(pcc_ss_data->pcc_channel, ret);
+ if (pcc_ss_data->pcc_channel->mchan->mbox->txdone_irq)
+ mbox_chan_txdone(pcc_ss_data->pcc_channel->mchan, ret);
else
- mbox_client_txdone(pcc_ss_data->pcc_channel, ret);
+ mbox_client_txdone(pcc_ss_data->pcc_channel->mchan, ret);

end:
if (cmd == CMD_WRITE) {
@@ -493,46 +493,33 @@ EXPORT_SYMBOL_GPL(acpi_get_psd_map);

static int register_pcc_channel(int pcc_ss_idx)
{
- struct acpi_pcct_hw_reduced *cppc_ss;
+ struct pcc_mbox_chan *pcc_chan;
u64 usecs_lat;

if (pcc_ss_idx >= 0) {
- pcc_data[pcc_ss_idx]->pcc_channel =
- pcc_mbox_request_channel(&cppc_mbox_cl, pcc_ss_idx);
+ pcc_chan = pcc_mbox_request_channel(&cppc_mbox_cl, pcc_ss_idx);

- if (IS_ERR(pcc_data[pcc_ss_idx]->pcc_channel)) {
+ if (IS_ERR(pcc_chan)) {
pr_err("Failed to find PCC channel for subspace %d\n",
pcc_ss_idx);
return -ENODEV;
}

- /*
- * The PCC mailbox controller driver should
- * have parsed the PCCT (global table of all
- * PCC channels) and stored pointers to the
- * subspace communication region in con_priv.
- */
- cppc_ss = (pcc_data[pcc_ss_idx]->pcc_channel)->con_priv;
-
- if (!cppc_ss) {
- pr_err("No PCC subspace found for %d CPPC\n",
- pcc_ss_idx);
- return -ENODEV;
- }
-
+ pcc_data[pcc_ss_idx]->pcc_channel = pcc_chan;
/*
* cppc_ss->latency is just a Nominal value. In reality
* the remote processor could be much slower to reply.
* So add an arbitrary amount of wait on top of Nominal.
*/
- usecs_lat = NUM_RETRIES * cppc_ss->latency;
+ usecs_lat = NUM_RETRIES * pcc_chan->latency;
pcc_data[pcc_ss_idx]->deadline_us = usecs_lat;
- pcc_data[pcc_ss_idx]->pcc_mrtt = cppc_ss->min_turnaround_time;
- pcc_data[pcc_ss_idx]->pcc_mpar = cppc_ss->max_access_rate;
- pcc_data[pcc_ss_idx]->pcc_nominal = cppc_ss->latency;
+ pcc_data[pcc_ss_idx]->pcc_mrtt = pcc_chan->min_turnaround_time;
+ pcc_data[pcc_ss_idx]->pcc_mpar = pcc_chan->max_access_rate;
+ pcc_data[pcc_ss_idx]->pcc_nominal = pcc_chan->latency;

pcc_data[pcc_ss_idx]->pcc_comm_addr =
- acpi_os_ioremap(cppc_ss->base_address, cppc_ss->length);
+ acpi_os_ioremap(pcc_chan->shmem_base_addr,
+ pcc_chan->shmem_size);
if (!pcc_data[pcc_ss_idx]->pcc_comm_addr) {
pr_err("Failed to ioremap PCC comm region mem for %d\n",
pcc_ss_idx);
diff --git a/drivers/hwmon/xgene-hwmon.c b/drivers/hwmon/xgene-hwmon.c
index 382ef0395d8e..30aae8642069 100644
--- a/drivers/hwmon/xgene-hwmon.c
+++ b/drivers/hwmon/xgene-hwmon.c
@@ -93,6 +93,7 @@ struct slimpro_resp_msg {
struct xgene_hwmon_dev {
struct device *dev;
struct mbox_chan *mbox_chan;
+ struct pcc_mbox_chan *pcc_chan;
struct mbox_client mbox_client;
int mbox_idx;

@@ -652,7 +653,7 @@ static int xgene_hwmon_probe(struct platform_device *pdev)
goto out_mbox_free;
}
} else {
- struct acpi_pcct_hw_reduced *cppc_ss;
+ struct pcc_mbox_chan *pcc_chan;
const struct acpi_device_id *acpi_id;
int version;

@@ -671,26 +672,16 @@ static int xgene_hwmon_probe(struct platform_device *pdev)
}

cl->rx_callback = xgene_hwmon_pcc_rx_cb;
- ctx->mbox_chan = pcc_mbox_request_channel(cl, ctx->mbox_idx);
- if (IS_ERR(ctx->mbox_chan)) {
+ pcc_chan = pcc_mbox_request_channel(cl, ctx->mbox_idx);
+ if (IS_ERR(pcc_chan)) {
dev_err(&pdev->dev,
"PPC channel request failed\n");
rc = -ENODEV;
goto out_mbox_free;
}

- /*
- * The PCC mailbox controller driver should
- * have parsed the PCCT (global table of all
- * PCC channels) and stored pointers to the
- * subspace communication region in con_priv.
- */
- cppc_ss = ctx->mbox_chan->con_priv;
- if (!cppc_ss) {
- dev_err(&pdev->dev, "PPC subspace not found\n");
- rc = -ENODEV;
- goto out;
- }
+ ctx->pcc_chan = pcc_chan;
+ ctx->mbox_chan = pcc_chan->mchan;

if (!ctx->mbox_chan->mbox->txdone_irq) {
dev_err(&pdev->dev, "PCC IRQ not supported\n");
@@ -702,16 +693,16 @@ static int xgene_hwmon_probe(struct platform_device *pdev)
* This is the shared communication region
* for the OS and Platform to communicate over.
*/
- ctx->comm_base_addr = cppc_ss->base_address;
+ ctx->comm_base_addr = pcc_chan->shmem_base_addr;
if (ctx->comm_base_addr) {
if (version == XGENE_HWMON_V2)
ctx->pcc_comm_addr = (void __force *)ioremap(
ctx->comm_base_addr,
- cppc_ss->length);
+ pcc_chan->shmem_size);
else
ctx->pcc_comm_addr = memremap(
ctx->comm_base_addr,
- cppc_ss->length,
+ pcc_chan->shmem_size,
MEMREMAP_WB);
} else {
dev_err(&pdev->dev, "Failed to get PCC comm region\n");
@@ -727,11 +718,11 @@ static int xgene_hwmon_probe(struct platform_device *pdev)
}

/*
- * cppc_ss->latency is just a Nominal value. In reality
+ * pcc_chan->latency is just a Nominal value. In reality
* the remote processor could be much slower to reply.
* So add an arbitrary amount of wait on top of Nominal.
*/
- ctx->usecs_lat = PCC_NUM_RETRIES * cppc_ss->latency;
+ ctx->usecs_lat = PCC_NUM_RETRIES * pcc_chan->latency;
}

ctx->hwmon_dev = hwmon_device_register_with_groups(ctx->dev,
@@ -757,7 +748,7 @@ static int xgene_hwmon_probe(struct platform_device *pdev)
if (acpi_disabled)
mbox_free_channel(ctx->mbox_chan);
else
- pcc_mbox_free_channel(ctx->mbox_chan);
+ pcc_mbox_free_channel(ctx->pcc_chan);
out_mbox_free:
kfifo_free(&ctx->async_msg_fifo);

@@ -773,7 +764,7 @@ static int xgene_hwmon_remove(struct platform_device *pdev)
if (acpi_disabled)
mbox_free_channel(ctx->mbox_chan);
else
- pcc_mbox_free_channel(ctx->mbox_chan);
+ pcc_mbox_free_channel(ctx->pcc_chan);

return 0;
}
diff --git a/drivers/i2c/busses/i2c-xgene-slimpro.c b/drivers/i2c/busses/i2c-xgene-slimpro.c
index bba08cbce6e1..1a19ebad60ad 100644
--- a/drivers/i2c/busses/i2c-xgene-slimpro.c
+++ b/drivers/i2c/busses/i2c-xgene-slimpro.c
@@ -103,6 +103,7 @@ struct slimpro_i2c_dev {
struct i2c_adapter adapter;
struct device *dev;
struct mbox_chan *mbox_chan;
+ struct pcc_mbox_chan *pcc_chan;
struct mbox_client mbox_client;
int mbox_idx;
struct completion rd_complete;
@@ -466,7 +467,7 @@ static int xgene_slimpro_i2c_probe(struct platform_device *pdev)
return PTR_ERR(ctx->mbox_chan);
}
} else {
- struct acpi_pcct_hw_reduced *cppc_ss;
+ struct pcc_mbox_chan *pcc_chan;
const struct acpi_device_id *acpi_id;
int version = XGENE_SLIMPRO_I2C_V1;

@@ -483,24 +484,14 @@ static int xgene_slimpro_i2c_probe(struct platform_device *pdev)

cl->tx_block = false;
cl->rx_callback = slimpro_i2c_pcc_rx_cb;
- ctx->mbox_chan = pcc_mbox_request_channel(cl, ctx->mbox_idx);
- if (IS_ERR(ctx->mbox_chan)) {
+ pcc_chan = pcc_mbox_request_channel(cl, ctx->mbox_idx);
+ if (IS_ERR(pcc_chan)) {
dev_err(&pdev->dev, "PCC mailbox channel request failed\n");
- return PTR_ERR(ctx->mbox_chan);
+ return PTR_ERR(ctx->pcc_chan);
}

- /*
- * The PCC mailbox controller driver should
- * have parsed the PCCT (global table of all
- * PCC channels) and stored pointers to the
- * subspace communication region in con_priv.
- */
- cppc_ss = ctx->mbox_chan->con_priv;
- if (!cppc_ss) {
- dev_err(&pdev->dev, "PPC subspace not found\n");
- rc = -ENOENT;
- goto mbox_err;
- }
+ ctx->pcc_chan = pcc_chan;
+ ctx->mbox_chan = pcc_chan->mchan;

if (!ctx->mbox_chan->mbox->txdone_irq) {
dev_err(&pdev->dev, "PCC IRQ not supported\n");
@@ -512,17 +503,17 @@ static int xgene_slimpro_i2c_probe(struct platform_device *pdev)
* This is the shared communication region
* for the OS and Platform to communicate over.
*/
- ctx->comm_base_addr = cppc_ss->base_address;
+ ctx->comm_base_addr = pcc_chan->shmem_base_addr;
if (ctx->comm_base_addr) {
if (version == XGENE_SLIMPRO_I2C_V2)
ctx->pcc_comm_addr = memremap(
ctx->comm_base_addr,
- cppc_ss->length,
+ pcc_chan->shmem_size,
MEMREMAP_WT);
else
ctx->pcc_comm_addr = memremap(
ctx->comm_base_addr,
- cppc_ss->length,
+ pcc_chan->shmem_size,
MEMREMAP_WB);
} else {
dev_err(&pdev->dev, "Failed to get PCC comm region\n");
@@ -561,7 +552,7 @@ static int xgene_slimpro_i2c_probe(struct platform_device *pdev)
if (acpi_disabled)
mbox_free_channel(ctx->mbox_chan);
else
- pcc_mbox_free_channel(ctx->mbox_chan);
+ pcc_mbox_free_channel(ctx->pcc_chan);

return rc;
}
@@ -575,7 +566,7 @@ static int xgene_slimpro_i2c_remove(struct platform_device *pdev)
if (acpi_disabled)
mbox_free_channel(ctx->mbox_chan);
else
- pcc_mbox_free_channel(ctx->mbox_chan);
+ pcc_mbox_free_channel(ctx->pcc_chan);

return 0;
}
diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c
index f358ced827f2..453a58fda3a4 100644
--- a/drivers/mailbox/pcc.c
+++ b/drivers/mailbox/pcc.c
@@ -79,24 +79,9 @@ struct pcc_chan_info {
int db_irq;
};

+#define to_pcc_chan_info(c) container_of(c, struct pcc_chan_info, chan)
static struct pcc_chan_info *chan_info;
-
static struct mbox_controller pcc_mbox_ctrl = {};
-/**
- * get_pcc_channel - Given a PCC subspace idx, get
- * the respective mbox_channel.
- * @id: PCC subspace index.
- *
- * Return: ERR_PTR(errno) if error, else pointer
- * to mbox channel.
- */
-static struct mbox_chan *get_pcc_channel(int id)
-{
- if (id < 0 || id >= pcc_mbox_ctrl.num_chans)
- return ERR_PTR(-ENOENT);
-
- return &pcc_mbox_channels[id];
-}

/*
* PCC can be used with perf critical drivers such as CPPC
@@ -239,31 +224,25 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p)
* ACPI package. This is used to lookup the array of PCC
* subspaces as parsed by the PCC Mailbox controller.
*
- * Return: Pointer to the Mailbox Channel if successful or
- * ERR_PTR.
+ * Return: Pointer to the PCC Mailbox Channel if successful or ERR_PTR.
*/
-struct mbox_chan *pcc_mbox_request_channel(struct mbox_client *cl,
- int subspace_id)
+struct pcc_mbox_chan *
+pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id)
{
struct pcc_chan_info *pchan;
struct device *dev = pcc_mbox_ctrl.dev;
struct mbox_chan *chan;
unsigned long flags;

- /*
- * Each PCC Subspace is a Mailbox Channel.
- * The PCC Clients get their PCC Subspace ID
- * from their own tables and pass it here.
- * This returns a pointer to the PCC subspace
- * for the Client to operate on.
- */
- chan = get_pcc_channel(subspace_id);
+ if (subspace_id < 0 || subspace_id >= pcc_mbox_ctrl.num_chans)
+ return ERR_PTR(-ENOENT);

+ pchan = chan_info + subspace_id;
+ chan = pchan->chan.mchan;
if (IS_ERR(chan) || chan->cl) {
dev_err(dev, "Channel not found for idx: %d\n", subspace_id);
return ERR_PTR(-EBUSY);
}
- pchan = chan_info + subspace_id;

spin_lock_irqsave(&chan->lock, flags);
chan->msg_free = 0;
@@ -285,38 +264,32 @@ struct mbox_chan *pcc_mbox_request_channel(struct mbox_client *cl,
if (unlikely(rc)) {
dev_err(dev, "failed to register PCC interrupt %d\n",
pchan->db_irq);
- pcc_mbox_free_channel(chan);
- chan = ERR_PTR(rc);
+ pcc_mbox_free_channel(&pchan->chan);
+ return ERR_PTR(rc);
}
}

- return chan;
+ return &pchan->chan;
}
EXPORT_SYMBOL_GPL(pcc_mbox_request_channel);

/**
* pcc_mbox_free_channel - Clients call this to free their Channel.
*
- * @chan: Pointer to the mailbox channel as returned by
- * pcc_mbox_request_channel()
+ * @pchan: Pointer to the PCC mailbox channel as returned by
+ * pcc_mbox_request_channel()
*/
-void pcc_mbox_free_channel(struct mbox_chan *chan)
+void pcc_mbox_free_channel(struct pcc_mbox_chan *pchan)
{
- u32 id = chan - pcc_mbox_channels;
- struct pcc_chan_info *pchan;
+ struct pcc_chan_info *pchan_info = to_pcc_chan_info(pchan);
+ struct mbox_chan *chan = pchan->mchan;
unsigned long flags;

if (!chan || !chan->cl)
return;

- if (id >= pcc_mbox_ctrl.num_chans) {
- pr_debug("pcc_mbox_free_channel: Invalid mbox_chan passed\n");
- return;
- }
-
- pchan = chan_info + id;
- if (pchan->db_irq > 0)
- devm_free_irq(chan->mbox->dev, pchan->db_irq, chan);
+ if (pchan_info->db_irq > 0)
+ devm_free_irq(chan->mbox->dev, pchan_info->db_irq, chan);

spin_lock_irqsave(&chan->lock, flags);
chan->cl = NULL;
diff --git a/include/acpi/pcc.h b/include/acpi/pcc.h
index 5e510a6b8052..73e806fe7ce7 100644
--- a/include/acpi/pcc.h
+++ b/include/acpi/pcc.h
@@ -20,16 +20,16 @@ struct pcc_mbox_chan {

#define MAX_PCC_SUBSPACES 256
#ifdef CONFIG_PCC
-extern struct mbox_chan *pcc_mbox_request_channel(struct mbox_client *cl,
- int subspace_id);
-extern void pcc_mbox_free_channel(struct mbox_chan *chan);
+extern struct pcc_mbox_chan *
+pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id);
+extern void pcc_mbox_free_channel(struct pcc_mbox_chan *chan);
#else
-static inline struct mbox_chan *pcc_mbox_request_channel(struct mbox_client *cl,
- int subspace_id)
+static inline struct pcc_mbox_chan *
+pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id)
{
return ERR_PTR(-ENODEV);
}
-static inline void pcc_mbox_free_channel(struct mbox_chan *chan) { }
+static inline void pcc_mbox_free_channel(struct pcc_mbox_chan *chan) { }
#endif

#endif /* _PCC_H */
--
2.25.1

2021-09-17 22:05:47

by Sudeep Holla

[permalink] [raw]
Subject: [PATCH v2 08/14] mailbox: pcc: Rename doorbell ack to platform interrupt ack register

The specification refers this register and associated bitmask as platform
interrupt acknowledge register. Let us rename it so that it is easier to
map and understand.

Signed-off-by: Sudeep Holla <[email protected]>
---
drivers/mailbox/pcc.c | 33 +++++++++++++++++----------------
1 file changed, 17 insertions(+), 16 deletions(-)

diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c
index 453a58fda3a4..ae4b7a4b3531 100644
--- a/drivers/mailbox/pcc.c
+++ b/drivers/mailbox/pcc.c
@@ -69,14 +69,15 @@ static struct mbox_chan *pcc_mbox_channels;
*
* @chan: PCC channel information with Shared Memory Region info
* @db_vaddr: cached virtual address for doorbell register
- * @db_ack_vaddr: cached virtual address for doorbell ack register
- * @db_irq: doorbell interrupt
+ * @plat_irq_ack_vaddr: cached virtual address for platform interrupt
+ * acknowledge register
+ * @plat_irq: platform interrupt
*/
struct pcc_chan_info {
struct pcc_mbox_chan chan;
void __iomem *db_vaddr;
- void __iomem *db_ack_vaddr;
- int db_irq;
+ void __iomem *plat_irq_ack_vaddr;
+ int plat_irq;
};

#define to_pcc_chan_info(c) container_of(c, struct pcc_chan_info, chan)
@@ -198,12 +199,12 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p)
doorbell_ack_preserve = pcct2_ss->ack_preserve_mask;
doorbell_ack_write = pcct2_ss->ack_write_mask;

- ret = read_register(pchan->db_ack_vaddr,
+ ret = read_register(pchan->plat_irq_ack_vaddr,
&doorbell_ack_val, doorbell_ack->bit_width);
if (ret)
return IRQ_NONE;

- ret = write_register(pchan->db_ack_vaddr,
+ ret = write_register(pchan->plat_irq_ack_vaddr,
(doorbell_ack_val & doorbell_ack_preserve)
| doorbell_ack_write,
doorbell_ack->bit_width);
@@ -256,14 +257,14 @@ pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id)

spin_unlock_irqrestore(&chan->lock, flags);

- if (pchan->db_irq > 0) {
+ if (pchan->plat_irq > 0) {
int rc;

- rc = devm_request_irq(dev, pchan->db_irq, pcc_mbox_irq, 0,
+ rc = devm_request_irq(dev, pchan->plat_irq, pcc_mbox_irq, 0,
MBOX_IRQ_NAME, chan);
if (unlikely(rc)) {
dev_err(dev, "failed to register PCC interrupt %d\n",
- pchan->db_irq);
+ pchan->plat_irq);
pcc_mbox_free_channel(&pchan->chan);
return ERR_PTR(rc);
}
@@ -288,8 +289,8 @@ void pcc_mbox_free_channel(struct pcc_mbox_chan *pchan)
if (!chan || !chan->cl)
return;

- if (pchan_info->db_irq > 0)
- devm_free_irq(chan->mbox->dev, pchan_info->db_irq, chan);
+ if (pchan_info->plat_irq > 0)
+ devm_free_irq(chan->mbox->dev, pchan_info->plat_irq, chan);

spin_lock_irqsave(&chan->lock, flags);
chan->cl = NULL;
@@ -400,9 +401,9 @@ static int pcc_parse_subspace_irq(struct pcc_chan_info *pchan,
return 0;

pcct_ss = (struct acpi_pcct_hw_reduced *)pcct_entry;
- pchan->db_irq = pcc_map_interrupt(pcct_ss->platform_interrupt,
- (u32)pcct_ss->flags);
- if (pchan->db_irq <= 0) {
+ pchan->plat_irq = pcc_map_interrupt(pcct_ss->platform_interrupt,
+ (u32)pcct_ss->flags);
+ if (pchan->plat_irq <= 0) {
pr_err("PCC GSI %d not registered\n",
pcct_ss->platform_interrupt);
return -EINVAL;
@@ -411,10 +412,10 @@ static int pcc_parse_subspace_irq(struct pcc_chan_info *pchan,
if (pcct_ss->header.type == ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE_TYPE2) {
struct acpi_pcct_hw_reduced_type2 *pcct2_ss = (void *)pcct_ss;

- pchan->db_ack_vaddr =
+ pchan->plat_irq_ack_vaddr =
acpi_os_ioremap(pcct2_ss->platform_ack_register.address,
pcct2_ss->platform_ack_register.bit_width / 8);
- if (!pchan->db_ack_vaddr) {
+ if (!pchan->plat_irq_ack_vaddr) {
pr_err("Failed to ioremap PCC ACK register\n");
return -ENOMEM;
}
--
2.25.1

2021-09-17 22:20:32

by Sudeep Holla

[permalink] [raw]
Subject: [PATCH v2 14/14] ACPI/PCC: Add myself as maintainer for PCC mailbox driver

Not much functionality is added since PCC driver was added 5 years ago.
There is need to restructure the driver while adding support for PCC
Extended subspaces type 3&4. There is more rework needed as more users
adopt PCC on arm64 platforms. In order to ease the same, I would like
to take responsibility to maintain this driver.

Cc: "Rafael J. Wysocki" <[email protected]>
Cc: "Rafael J. Wysocki" <[email protected]>
Cc: Jassi Brar <[email protected]>
Signed-off-by: Sudeep Holla <[email protected]>
---
MAINTAINERS | 6 ++++++
1 file changed, 6 insertions(+)

Hi Rafael,

As you mentioned offline that you haven't followed ACPI PCC changes
much and don't have time to review this, I thought of adding myself
as maintainer for the ACPI PCC part of the mailbox as I will be tracking
and using PCCT. Let me know if you have any objections.

Regards,
Sudeep

diff --git a/MAINTAINERS b/MAINTAINERS
index eeb4c70b3d5b..8d41dd710ae9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -401,6 +401,12 @@ L: [email protected]
S: Maintained
F: drivers/platform/x86/i2c-multi-instantiate.c

+ACPI PCC(Platform Communication Channel) MAILBOX DRIVER
+M: Sudeep Holla <[email protected]>
+L: [email protected]
+S: Supported
+F: drivers/mailbox/pcc.c
+
ACPI PMIC DRIVERS
M: "Rafael J. Wysocki" <[email protected]>
M: Len Brown <[email protected]>
--
2.25.1

2021-09-17 22:20:32

by Sudeep Holla

[permalink] [raw]
Subject: [PATCH v2 13/14] mailbox: pcc: Move bulk of PCCT parsing into pcc_mbox_probe

Move the PCCT subspace parsing and allocation into pcc_mbox_probe so
that we can get rid of global PCC channel and mailbox controller data.
It also helps to make use of devm_* APIs for all the allocations.

Signed-off-by: Sudeep Holla <[email protected]>
---
drivers/mailbox/pcc.c | 124 ++++++++++++++++++++++--------------------
1 file changed, 66 insertions(+), 58 deletions(-)

diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c
index eb90c9eaaf9c..887a3704c12e 100644
--- a/drivers/mailbox/pcc.c
+++ b/drivers/mailbox/pcc.c
@@ -63,8 +63,6 @@

#define MBOX_IRQ_NAME "pcc-mbox"

-static struct mbox_chan *pcc_mbox_channels;
-
/**
* struct pcc_chan_reg - PCC register bundle
*
@@ -106,7 +104,7 @@ struct pcc_chan_info {

#define to_pcc_chan_info(c) container_of(c, struct pcc_chan_info, chan)
static struct pcc_chan_info *chan_info;
-static struct mbox_controller pcc_mbox_ctrl = {};
+static int pcc_chan_count;

/*
* PCC can be used with perf critical drivers such as CPPC
@@ -281,11 +279,11 @@ struct pcc_mbox_chan *
pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id)
{
struct pcc_chan_info *pchan;
- struct device *dev = pcc_mbox_ctrl.dev;
struct mbox_chan *chan;
+ struct device *dev;
unsigned long flags;

- if (subspace_id < 0 || subspace_id >= pcc_mbox_ctrl.num_chans)
+ if (subspace_id < 0 || subspace_id >= pcc_chan_count)
return ERR_PTR(-ENOENT);

pchan = chan_info + subspace_id;
@@ -294,6 +292,7 @@ pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id)
dev_err(dev, "Channel not found for idx: %d\n", subspace_id);
return ERR_PTR(-EBUSY);
}
+ dev = chan->mbox->dev;

spin_lock_irqsave(&chan->lock, flags);
chan->msg_free = 0;
@@ -576,16 +575,12 @@ static void pcc_parse_subspace_shmem(struct pcc_chan_info *pchan,
*/
static int __init acpi_pcc_probe(void)
{
+ int count, i, rc = 0;
+ acpi_status status;
struct acpi_table_header *pcct_tbl;
- struct acpi_subtable_header *pcct_entry;
- struct acpi_table_pcct *acpi_pcct_tbl;
struct acpi_subtable_proc proc[ACPI_PCCT_TYPE_RESERVED];
- int count, i, rc;
- acpi_status status = AE_OK;

- /* Search for PCCT */
status = acpi_get_table(ACPI_SIG_PCCT, 0, &pcct_tbl);
-
if (ACPI_FAILURE(status) || !pcct_tbl)
return -ENODEV;

@@ -607,21 +602,60 @@ static int __init acpi_pcc_probe(void)
pr_warn("Invalid PCCT: %d PCC subspaces\n", count);

rc = -EINVAL;
- goto err_put_pcct;
+ } else {
+ pcc_chan_count = count;
}

- pcc_mbox_channels = kcalloc(count, sizeof(struct mbox_chan),
- GFP_KERNEL);
+ acpi_put_table(pcct_tbl);
+
+ return rc;
+}
+
+/**
+ * pcc_mbox_probe - Called when we find a match for the
+ * PCCT platform device. This is purely used to represent
+ * the PCCT as a virtual device for registering with the
+ * generic Mailbox framework.
+ *
+ * @pdev: Pointer to platform device returned when a match
+ * is found.
+ *
+ * Return: 0 for Success, else errno.
+ */
+static int pcc_mbox_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct mbox_controller *pcc_mbox_ctrl;
+ struct mbox_chan *pcc_mbox_channels;
+ struct acpi_table_header *pcct_tbl;
+ struct acpi_subtable_header *pcct_entry;
+ struct acpi_table_pcct *acpi_pcct_tbl;
+ acpi_status status = AE_OK;
+ int i, rc, count = pcc_chan_count;
+
+ /* Search for PCCT */
+ status = acpi_get_table(ACPI_SIG_PCCT, 0, &pcct_tbl);
+
+ if (ACPI_FAILURE(status) || !pcct_tbl)
+ return -ENODEV;
+
+ pcc_mbox_channels = devm_kcalloc(dev, count, sizeof(*pcc_mbox_channels),
+ GFP_KERNEL);
if (!pcc_mbox_channels) {
- pr_err("Could not allocate space for PCC mbox channels\n");
rc = -ENOMEM;
- goto err_put_pcct;
+ goto err;
}

- chan_info = kcalloc(count, sizeof(*chan_info), GFP_KERNEL);
+ chan_info = devm_kcalloc(dev, count, sizeof(*chan_info), GFP_KERNEL);
if (!chan_info) {
rc = -ENOMEM;
- goto err_free_mbox;
+ goto err;
+ }
+
+ pcc_mbox_ctrl = devm_kmalloc(dev, sizeof(*pcc_mbox_ctrl), GFP_KERNEL);
+ if (!pcc_mbox_ctrl) {
+ rc = -ENOMEM;
+ goto err;
}

/* Point to the first PCC subspace entry */
@@ -630,7 +664,7 @@ static int __init acpi_pcc_probe(void)

acpi_pcct_tbl = (struct acpi_table_pcct *) pcct_tbl;
if (acpi_pcct_tbl->flags & ACPI_PCCT_DOORBELL)
- pcc_mbox_ctrl.txdone_irq = true;
+ pcc_mbox_ctrl->txdone_irq = true;

for (i = 0; i < count; i++) {
struct pcc_chan_info *pchan = chan_info + i;
@@ -639,13 +673,13 @@ static int __init acpi_pcc_probe(void)
pchan->chan.mchan = &pcc_mbox_channels[i];

if (pcct_entry->type == ACPI_PCCT_TYPE_EXT_PCC_SLAVE_SUBSPACE &&
- !pcc_mbox_ctrl.txdone_irq) {
+ !pcc_mbox_ctrl->txdone_irq) {
pr_err("Plaform Interrupt flag must be set to 1");
rc = -EINVAL;
goto err;
}

- if (pcc_mbox_ctrl.txdone_irq) {
+ if (pcc_mbox_ctrl->txdone_irq) {
rc = pcc_parse_subspace_irq(pchan, pcct_entry);
if (rc < 0)
goto err;
@@ -660,51 +694,25 @@ static int __init acpi_pcc_probe(void)
((unsigned long) pcct_entry + pcct_entry->length);
}

- pcc_mbox_ctrl.num_chans = count;
+ pcc_mbox_ctrl->num_chans = count;

- pr_info("Detected %d PCC Subspaces\n", pcc_mbox_ctrl.num_chans);
+ pr_info("Detected %d PCC Subspaces\n", pcc_mbox_ctrl->num_chans);

- return 0;
+ pcc_mbox_ctrl->chans = pcc_mbox_channels;
+ pcc_mbox_ctrl->ops = &pcc_chan_ops;
+ pcc_mbox_ctrl->dev = dev;

+ pr_info("Registering PCC driver as Mailbox controller\n");
+ rc = mbox_controller_register(pcc_mbox_ctrl);
+ if (rc)
+ pr_err("Err registering PCC as Mailbox controller: %d\n", rc);
+ else
+ return 0;
err:
- kfree(chan_info);
-err_free_mbox:
- kfree(pcc_mbox_channels);
-err_put_pcct:
acpi_put_table(pcct_tbl);
return rc;
}

-/**
- * pcc_mbox_probe - Called when we find a match for the
- * PCCT platform device. This is purely used to represent
- * the PCCT as a virtual device for registering with the
- * generic Mailbox framework.
- *
- * @pdev: Pointer to platform device returned when a match
- * is found.
- *
- * Return: 0 for Success, else errno.
- */
-static int pcc_mbox_probe(struct platform_device *pdev)
-{
- int ret = 0;
-
- pcc_mbox_ctrl.chans = pcc_mbox_channels;
- pcc_mbox_ctrl.ops = &pcc_chan_ops;
- pcc_mbox_ctrl.dev = &pdev->dev;
-
- pr_info("Registering PCC driver as Mailbox controller\n");
- ret = mbox_controller_register(&pcc_mbox_ctrl);
-
- if (ret) {
- pr_err("Err registering PCC as Mailbox controller: %d\n", ret);
- ret = -ENODEV;
- }
-
- return ret;
-}
-
static struct platform_driver pcc_mbox_driver = {
.probe = pcc_mbox_probe,
.driver = {
--
2.25.1

2021-10-04 23:45:18

by Wolfram Sang

[permalink] [raw]
Subject: Re: [PATCH v2 07/14] mailbox: pcc: Use PCC mailbox channel pointer instead of standard

On Fri, Sep 17, 2021 at 02:33:50PM +0100, Sudeep Holla wrote:
> Now that we have all the shared memory region information populated in
> the pcc_mbox_chan, let us propagate the pointer to the same as the
> return value to pcc_mbox_request channel.
>
> This eliminates the need for the individual users of PCC mailbox to
> parse the PCCT subspace entries and fetch the shmem information. This
> also eliminates the need for PCC mailbox controller to set con_priv to
> PCCT subspace entries. This is required as con_priv is private to the
> controller driver to attach private data associated with the channel and
> not meant to be used by the mailbox client/users.
>
> Let us convert all the users of pcc_mbox_{request,free}_channel to use
> new interface.
>
> Cc: Jean Delvare <[email protected]>
> Cc: Guenter Roeck <[email protected]>
> Cc: Wolfram Sang <[email protected]>
> Cc: [email protected]
> Cc: [email protected]
> Signed-off-by: Sudeep Holla <[email protected]>
> ---
> drivers/acpi/cppc_acpi.c | 43 ++++++------------
> drivers/hwmon/xgene-hwmon.c | 35 ++++++--------
> drivers/i2c/busses/i2c-xgene-slimpro.c | 33 +++++---------
> drivers/mailbox/pcc.c | 63 ++++++++------------------
> include/acpi/pcc.h | 12 ++---

There is no maintainer for the xgene driver, but I trust you and other
reviewers of this whole series on this. The I2C part is a minor piece
anyhow. So:

Acked-by: Wolfram Sang <[email protected]>


Attachments:
(No filename) (1.51 kB)
signature.asc (849.00 B)
Download all attachments

2021-10-11 16:18:25

by Sudeep Holla

[permalink] [raw]
Subject: Re: [PATCH v2 00/14] mailbox: pcc: Add support for PCCT extended PCC subspaces

Hi Jassi,

On Fri, Sep 17, 2021 at 02:33:43PM +0100, Sudeep Holla wrote:
> Hi,
>
> Though the series is about adding support for PCCT extended PCC subspaces,
> except one patch, remaining are either preparatory or clean up to add
> the PCCT extended PCC subspaces. Only patch 12 adds the support of extended
> PCC type3/4 subspaces.
>
> The main change affecting your is the change in pcc_mbox_request_channel
> to avoid clien driver using con_priv member which is designed for controller
> private pointer rather than for client's to use that.
>

Once I have ack from Guenter, is it OK to get this merged via mailbox tree.
Rafael is happy for me to maintain this PCC part of ACPI. Do you prefer
to merge patches directly or do you prefer pull request ? Let me know.

--
Regards,
Sudeep

2021-10-11 16:19:29

by Sudeep Holla

[permalink] [raw]
Subject: Re: [PATCH v2 07/14] mailbox: pcc: Use PCC mailbox channel pointer instead of standard

Hi Guenter,

On Fri, Sep 17, 2021 at 02:33:50PM +0100, Sudeep Holla wrote:
> Now that we have all the shared memory region information populated in
> the pcc_mbox_chan, let us propagate the pointer to the same as the
> return value to pcc_mbox_request channel.
>
> This eliminates the need for the individual users of PCC mailbox to
> parse the PCCT subspace entries and fetch the shmem information. This
> also eliminates the need for PCC mailbox controller to set con_priv to
> PCCT subspace entries. This is required as con_priv is private to the
> controller driver to attach private data associated with the channel and
> not meant to be used by the mailbox client/users.
>
> Let us convert all the users of pcc_mbox_{request,free}_channel to use
> new interface.
>
> Cc: Jean Delvare <[email protected]>
> Cc: Guenter Roeck <[email protected]>

Any objections ? If you are OK, can I have your ack so that the series
can go in one go.

--
Regards,
Sudeep

2021-10-11 16:40:26

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v2 07/14] mailbox: pcc: Use PCC mailbox channel pointer instead of standard

On Fri, Sep 17, 2021 at 02:33:50PM +0100, Sudeep Holla wrote:
> Now that we have all the shared memory region information populated in
> the pcc_mbox_chan, let us propagate the pointer to the same as the
> return value to pcc_mbox_request channel.
>
> This eliminates the need for the individual users of PCC mailbox to
> parse the PCCT subspace entries and fetch the shmem information. This
> also eliminates the need for PCC mailbox controller to set con_priv to
> PCCT subspace entries. This is required as con_priv is private to the
> controller driver to attach private data associated with the channel and
> not meant to be used by the mailbox client/users.
>
> Let us convert all the users of pcc_mbox_{request,free}_channel to use
> new interface.
>
> Cc: Jean Delvare <[email protected]>
> Cc: Guenter Roeck <[email protected]>
> Cc: Wolfram Sang <[email protected]>
> Cc: [email protected]
> Cc: [email protected]
> Signed-off-by: Sudeep Holla <[email protected]>
> Acked-by: Wolfram Sang <[email protected]>
> ---
> drivers/acpi/cppc_acpi.c | 43 ++++++------------
> drivers/hwmon/xgene-hwmon.c | 35 ++++++--------

Acked-by: Guenter Roeck <[email protected]>

> drivers/i2c/busses/i2c-xgene-slimpro.c | 33 +++++---------
> drivers/mailbox/pcc.c | 63 ++++++++------------------
> include/acpi/pcc.h | 12 ++---
> 5 files changed, 64 insertions(+), 122 deletions(-)
>
> diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
> index e195123e26c0..aa6623bd3f00 100644
> --- a/drivers/acpi/cppc_acpi.c
> +++ b/drivers/acpi/cppc_acpi.c
> @@ -43,7 +43,7 @@
> #include <acpi/cppc_acpi.h>
>
> struct cppc_pcc_data {
> - struct mbox_chan *pcc_channel;
> + struct pcc_mbox_chan *pcc_channel;
> void __iomem *pcc_comm_addr;
> bool pcc_channel_acquired;
> unsigned int deadline_us;
> @@ -295,7 +295,7 @@ static int send_pcc_cmd(int pcc_ss_id, u16 cmd)
> pcc_ss_data->platform_owns_pcc = true;
>
> /* Ring doorbell */
> - ret = mbox_send_message(pcc_ss_data->pcc_channel, &cmd);
> + ret = mbox_send_message(pcc_ss_data->pcc_channel->mchan, &cmd);
> if (ret < 0) {
> pr_err("Err sending PCC mbox message. ss: %d cmd:%d, ret:%d\n",
> pcc_ss_id, cmd, ret);
> @@ -308,10 +308,10 @@ static int send_pcc_cmd(int pcc_ss_id, u16 cmd)
> if (pcc_ss_data->pcc_mrtt)
> pcc_ss_data->last_cmd_cmpl_time = ktime_get();
>
> - if (pcc_ss_data->pcc_channel->mbox->txdone_irq)
> - mbox_chan_txdone(pcc_ss_data->pcc_channel, ret);
> + if (pcc_ss_data->pcc_channel->mchan->mbox->txdone_irq)
> + mbox_chan_txdone(pcc_ss_data->pcc_channel->mchan, ret);
> else
> - mbox_client_txdone(pcc_ss_data->pcc_channel, ret);
> + mbox_client_txdone(pcc_ss_data->pcc_channel->mchan, ret);
>
> end:
> if (cmd == CMD_WRITE) {
> @@ -493,46 +493,33 @@ EXPORT_SYMBOL_GPL(acpi_get_psd_map);
>
> static int register_pcc_channel(int pcc_ss_idx)
> {
> - struct acpi_pcct_hw_reduced *cppc_ss;
> + struct pcc_mbox_chan *pcc_chan;
> u64 usecs_lat;
>
> if (pcc_ss_idx >= 0) {
> - pcc_data[pcc_ss_idx]->pcc_channel =
> - pcc_mbox_request_channel(&cppc_mbox_cl, pcc_ss_idx);
> + pcc_chan = pcc_mbox_request_channel(&cppc_mbox_cl, pcc_ss_idx);
>
> - if (IS_ERR(pcc_data[pcc_ss_idx]->pcc_channel)) {
> + if (IS_ERR(pcc_chan)) {
> pr_err("Failed to find PCC channel for subspace %d\n",
> pcc_ss_idx);
> return -ENODEV;
> }
>
> - /*
> - * The PCC mailbox controller driver should
> - * have parsed the PCCT (global table of all
> - * PCC channels) and stored pointers to the
> - * subspace communication region in con_priv.
> - */
> - cppc_ss = (pcc_data[pcc_ss_idx]->pcc_channel)->con_priv;
> -
> - if (!cppc_ss) {
> - pr_err("No PCC subspace found for %d CPPC\n",
> - pcc_ss_idx);
> - return -ENODEV;
> - }
> -
> + pcc_data[pcc_ss_idx]->pcc_channel = pcc_chan;
> /*
> * cppc_ss->latency is just a Nominal value. In reality
> * the remote processor could be much slower to reply.
> * So add an arbitrary amount of wait on top of Nominal.
> */
> - usecs_lat = NUM_RETRIES * cppc_ss->latency;
> + usecs_lat = NUM_RETRIES * pcc_chan->latency;
> pcc_data[pcc_ss_idx]->deadline_us = usecs_lat;
> - pcc_data[pcc_ss_idx]->pcc_mrtt = cppc_ss->min_turnaround_time;
> - pcc_data[pcc_ss_idx]->pcc_mpar = cppc_ss->max_access_rate;
> - pcc_data[pcc_ss_idx]->pcc_nominal = cppc_ss->latency;
> + pcc_data[pcc_ss_idx]->pcc_mrtt = pcc_chan->min_turnaround_time;
> + pcc_data[pcc_ss_idx]->pcc_mpar = pcc_chan->max_access_rate;
> + pcc_data[pcc_ss_idx]->pcc_nominal = pcc_chan->latency;
>
> pcc_data[pcc_ss_idx]->pcc_comm_addr =
> - acpi_os_ioremap(cppc_ss->base_address, cppc_ss->length);
> + acpi_os_ioremap(pcc_chan->shmem_base_addr,
> + pcc_chan->shmem_size);
> if (!pcc_data[pcc_ss_idx]->pcc_comm_addr) {
> pr_err("Failed to ioremap PCC comm region mem for %d\n",
> pcc_ss_idx);
> diff --git a/drivers/hwmon/xgene-hwmon.c b/drivers/hwmon/xgene-hwmon.c
> index 382ef0395d8e..30aae8642069 100644
> --- a/drivers/hwmon/xgene-hwmon.c
> +++ b/drivers/hwmon/xgene-hwmon.c
> @@ -93,6 +93,7 @@ struct slimpro_resp_msg {
> struct xgene_hwmon_dev {
> struct device *dev;
> struct mbox_chan *mbox_chan;
> + struct pcc_mbox_chan *pcc_chan;
> struct mbox_client mbox_client;
> int mbox_idx;
>
> @@ -652,7 +653,7 @@ static int xgene_hwmon_probe(struct platform_device *pdev)
> goto out_mbox_free;
> }
> } else {
> - struct acpi_pcct_hw_reduced *cppc_ss;
> + struct pcc_mbox_chan *pcc_chan;
> const struct acpi_device_id *acpi_id;
> int version;
>
> @@ -671,26 +672,16 @@ static int xgene_hwmon_probe(struct platform_device *pdev)
> }
>
> cl->rx_callback = xgene_hwmon_pcc_rx_cb;
> - ctx->mbox_chan = pcc_mbox_request_channel(cl, ctx->mbox_idx);
> - if (IS_ERR(ctx->mbox_chan)) {
> + pcc_chan = pcc_mbox_request_channel(cl, ctx->mbox_idx);
> + if (IS_ERR(pcc_chan)) {
> dev_err(&pdev->dev,
> "PPC channel request failed\n");
> rc = -ENODEV;
> goto out_mbox_free;
> }
>
> - /*
> - * The PCC mailbox controller driver should
> - * have parsed the PCCT (global table of all
> - * PCC channels) and stored pointers to the
> - * subspace communication region in con_priv.
> - */
> - cppc_ss = ctx->mbox_chan->con_priv;
> - if (!cppc_ss) {
> - dev_err(&pdev->dev, "PPC subspace not found\n");
> - rc = -ENODEV;
> - goto out;
> - }
> + ctx->pcc_chan = pcc_chan;
> + ctx->mbox_chan = pcc_chan->mchan;
>
> if (!ctx->mbox_chan->mbox->txdone_irq) {
> dev_err(&pdev->dev, "PCC IRQ not supported\n");
> @@ -702,16 +693,16 @@ static int xgene_hwmon_probe(struct platform_device *pdev)
> * This is the shared communication region
> * for the OS and Platform to communicate over.
> */
> - ctx->comm_base_addr = cppc_ss->base_address;
> + ctx->comm_base_addr = pcc_chan->shmem_base_addr;
> if (ctx->comm_base_addr) {
> if (version == XGENE_HWMON_V2)
> ctx->pcc_comm_addr = (void __force *)ioremap(
> ctx->comm_base_addr,
> - cppc_ss->length);
> + pcc_chan->shmem_size);
> else
> ctx->pcc_comm_addr = memremap(
> ctx->comm_base_addr,
> - cppc_ss->length,
> + pcc_chan->shmem_size,
> MEMREMAP_WB);
> } else {
> dev_err(&pdev->dev, "Failed to get PCC comm region\n");
> @@ -727,11 +718,11 @@ static int xgene_hwmon_probe(struct platform_device *pdev)
> }
>
> /*
> - * cppc_ss->latency is just a Nominal value. In reality
> + * pcc_chan->latency is just a Nominal value. In reality
> * the remote processor could be much slower to reply.
> * So add an arbitrary amount of wait on top of Nominal.
> */
> - ctx->usecs_lat = PCC_NUM_RETRIES * cppc_ss->latency;
> + ctx->usecs_lat = PCC_NUM_RETRIES * pcc_chan->latency;
> }
>
> ctx->hwmon_dev = hwmon_device_register_with_groups(ctx->dev,
> @@ -757,7 +748,7 @@ static int xgene_hwmon_probe(struct platform_device *pdev)
> if (acpi_disabled)
> mbox_free_channel(ctx->mbox_chan);
> else
> - pcc_mbox_free_channel(ctx->mbox_chan);
> + pcc_mbox_free_channel(ctx->pcc_chan);
> out_mbox_free:
> kfifo_free(&ctx->async_msg_fifo);
>
> @@ -773,7 +764,7 @@ static int xgene_hwmon_remove(struct platform_device *pdev)
> if (acpi_disabled)
> mbox_free_channel(ctx->mbox_chan);
> else
> - pcc_mbox_free_channel(ctx->mbox_chan);
> + pcc_mbox_free_channel(ctx->pcc_chan);
>
> return 0;
> }
> diff --git a/drivers/i2c/busses/i2c-xgene-slimpro.c b/drivers/i2c/busses/i2c-xgene-slimpro.c
> index bba08cbce6e1..1a19ebad60ad 100644
> --- a/drivers/i2c/busses/i2c-xgene-slimpro.c
> +++ b/drivers/i2c/busses/i2c-xgene-slimpro.c
> @@ -103,6 +103,7 @@ struct slimpro_i2c_dev {
> struct i2c_adapter adapter;
> struct device *dev;
> struct mbox_chan *mbox_chan;
> + struct pcc_mbox_chan *pcc_chan;
> struct mbox_client mbox_client;
> int mbox_idx;
> struct completion rd_complete;
> @@ -466,7 +467,7 @@ static int xgene_slimpro_i2c_probe(struct platform_device *pdev)
> return PTR_ERR(ctx->mbox_chan);
> }
> } else {
> - struct acpi_pcct_hw_reduced *cppc_ss;
> + struct pcc_mbox_chan *pcc_chan;
> const struct acpi_device_id *acpi_id;
> int version = XGENE_SLIMPRO_I2C_V1;
>
> @@ -483,24 +484,14 @@ static int xgene_slimpro_i2c_probe(struct platform_device *pdev)
>
> cl->tx_block = false;
> cl->rx_callback = slimpro_i2c_pcc_rx_cb;
> - ctx->mbox_chan = pcc_mbox_request_channel(cl, ctx->mbox_idx);
> - if (IS_ERR(ctx->mbox_chan)) {
> + pcc_chan = pcc_mbox_request_channel(cl, ctx->mbox_idx);
> + if (IS_ERR(pcc_chan)) {
> dev_err(&pdev->dev, "PCC mailbox channel request failed\n");
> - return PTR_ERR(ctx->mbox_chan);
> + return PTR_ERR(ctx->pcc_chan);
> }
>
> - /*
> - * The PCC mailbox controller driver should
> - * have parsed the PCCT (global table of all
> - * PCC channels) and stored pointers to the
> - * subspace communication region in con_priv.
> - */
> - cppc_ss = ctx->mbox_chan->con_priv;
> - if (!cppc_ss) {
> - dev_err(&pdev->dev, "PPC subspace not found\n");
> - rc = -ENOENT;
> - goto mbox_err;
> - }
> + ctx->pcc_chan = pcc_chan;
> + ctx->mbox_chan = pcc_chan->mchan;
>
> if (!ctx->mbox_chan->mbox->txdone_irq) {
> dev_err(&pdev->dev, "PCC IRQ not supported\n");
> @@ -512,17 +503,17 @@ static int xgene_slimpro_i2c_probe(struct platform_device *pdev)
> * This is the shared communication region
> * for the OS and Platform to communicate over.
> */
> - ctx->comm_base_addr = cppc_ss->base_address;
> + ctx->comm_base_addr = pcc_chan->shmem_base_addr;
> if (ctx->comm_base_addr) {
> if (version == XGENE_SLIMPRO_I2C_V2)
> ctx->pcc_comm_addr = memremap(
> ctx->comm_base_addr,
> - cppc_ss->length,
> + pcc_chan->shmem_size,
> MEMREMAP_WT);
> else
> ctx->pcc_comm_addr = memremap(
> ctx->comm_base_addr,
> - cppc_ss->length,
> + pcc_chan->shmem_size,
> MEMREMAP_WB);
> } else {
> dev_err(&pdev->dev, "Failed to get PCC comm region\n");
> @@ -561,7 +552,7 @@ static int xgene_slimpro_i2c_probe(struct platform_device *pdev)
> if (acpi_disabled)
> mbox_free_channel(ctx->mbox_chan);
> else
> - pcc_mbox_free_channel(ctx->mbox_chan);
> + pcc_mbox_free_channel(ctx->pcc_chan);
>
> return rc;
> }
> @@ -575,7 +566,7 @@ static int xgene_slimpro_i2c_remove(struct platform_device *pdev)
> if (acpi_disabled)
> mbox_free_channel(ctx->mbox_chan);
> else
> - pcc_mbox_free_channel(ctx->mbox_chan);
> + pcc_mbox_free_channel(ctx->pcc_chan);
>
> return 0;
> }
> diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c
> index f358ced827f2..453a58fda3a4 100644
> --- a/drivers/mailbox/pcc.c
> +++ b/drivers/mailbox/pcc.c
> @@ -79,24 +79,9 @@ struct pcc_chan_info {
> int db_irq;
> };
>
> +#define to_pcc_chan_info(c) container_of(c, struct pcc_chan_info, chan)
> static struct pcc_chan_info *chan_info;
> -
> static struct mbox_controller pcc_mbox_ctrl = {};
> -/**
> - * get_pcc_channel - Given a PCC subspace idx, get
> - * the respective mbox_channel.
> - * @id: PCC subspace index.
> - *
> - * Return: ERR_PTR(errno) if error, else pointer
> - * to mbox channel.
> - */
> -static struct mbox_chan *get_pcc_channel(int id)
> -{
> - if (id < 0 || id >= pcc_mbox_ctrl.num_chans)
> - return ERR_PTR(-ENOENT);
> -
> - return &pcc_mbox_channels[id];
> -}
>
> /*
> * PCC can be used with perf critical drivers such as CPPC
> @@ -239,31 +224,25 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p)
> * ACPI package. This is used to lookup the array of PCC
> * subspaces as parsed by the PCC Mailbox controller.
> *
> - * Return: Pointer to the Mailbox Channel if successful or
> - * ERR_PTR.
> + * Return: Pointer to the PCC Mailbox Channel if successful or ERR_PTR.
> */
> -struct mbox_chan *pcc_mbox_request_channel(struct mbox_client *cl,
> - int subspace_id)
> +struct pcc_mbox_chan *
> +pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id)
> {
> struct pcc_chan_info *pchan;
> struct device *dev = pcc_mbox_ctrl.dev;
> struct mbox_chan *chan;
> unsigned long flags;
>
> - /*
> - * Each PCC Subspace is a Mailbox Channel.
> - * The PCC Clients get their PCC Subspace ID
> - * from their own tables and pass it here.
> - * This returns a pointer to the PCC subspace
> - * for the Client to operate on.
> - */
> - chan = get_pcc_channel(subspace_id);
> + if (subspace_id < 0 || subspace_id >= pcc_mbox_ctrl.num_chans)
> + return ERR_PTR(-ENOENT);
>
> + pchan = chan_info + subspace_id;
> + chan = pchan->chan.mchan;
> if (IS_ERR(chan) || chan->cl) {
> dev_err(dev, "Channel not found for idx: %d\n", subspace_id);
> return ERR_PTR(-EBUSY);
> }
> - pchan = chan_info + subspace_id;
>
> spin_lock_irqsave(&chan->lock, flags);
> chan->msg_free = 0;
> @@ -285,38 +264,32 @@ struct mbox_chan *pcc_mbox_request_channel(struct mbox_client *cl,
> if (unlikely(rc)) {
> dev_err(dev, "failed to register PCC interrupt %d\n",
> pchan->db_irq);
> - pcc_mbox_free_channel(chan);
> - chan = ERR_PTR(rc);
> + pcc_mbox_free_channel(&pchan->chan);
> + return ERR_PTR(rc);
> }
> }
>
> - return chan;
> + return &pchan->chan;
> }
> EXPORT_SYMBOL_GPL(pcc_mbox_request_channel);
>
> /**
> * pcc_mbox_free_channel - Clients call this to free their Channel.
> *
> - * @chan: Pointer to the mailbox channel as returned by
> - * pcc_mbox_request_channel()
> + * @pchan: Pointer to the PCC mailbox channel as returned by
> + * pcc_mbox_request_channel()
> */
> -void pcc_mbox_free_channel(struct mbox_chan *chan)
> +void pcc_mbox_free_channel(struct pcc_mbox_chan *pchan)
> {
> - u32 id = chan - pcc_mbox_channels;
> - struct pcc_chan_info *pchan;
> + struct pcc_chan_info *pchan_info = to_pcc_chan_info(pchan);
> + struct mbox_chan *chan = pchan->mchan;
> unsigned long flags;
>
> if (!chan || !chan->cl)
> return;
>
> - if (id >= pcc_mbox_ctrl.num_chans) {
> - pr_debug("pcc_mbox_free_channel: Invalid mbox_chan passed\n");
> - return;
> - }
> -
> - pchan = chan_info + id;
> - if (pchan->db_irq > 0)
> - devm_free_irq(chan->mbox->dev, pchan->db_irq, chan);
> + if (pchan_info->db_irq > 0)
> + devm_free_irq(chan->mbox->dev, pchan_info->db_irq, chan);
>
> spin_lock_irqsave(&chan->lock, flags);
> chan->cl = NULL;
> diff --git a/include/acpi/pcc.h b/include/acpi/pcc.h
> index 5e510a6b8052..73e806fe7ce7 100644
> --- a/include/acpi/pcc.h
> +++ b/include/acpi/pcc.h
> @@ -20,16 +20,16 @@ struct pcc_mbox_chan {
>
> #define MAX_PCC_SUBSPACES 256
> #ifdef CONFIG_PCC
> -extern struct mbox_chan *pcc_mbox_request_channel(struct mbox_client *cl,
> - int subspace_id);
> -extern void pcc_mbox_free_channel(struct mbox_chan *chan);
> +extern struct pcc_mbox_chan *
> +pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id);
> +extern void pcc_mbox_free_channel(struct pcc_mbox_chan *chan);
> #else
> -static inline struct mbox_chan *pcc_mbox_request_channel(struct mbox_client *cl,
> - int subspace_id)
> +static inline struct pcc_mbox_chan *
> +pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id)
> {
> return ERR_PTR(-ENODEV);
> }
> -static inline void pcc_mbox_free_channel(struct mbox_chan *chan) { }
> +static inline void pcc_mbox_free_channel(struct pcc_mbox_chan *chan) { }
> #endif
>
> #endif /* _PCC_H */

2021-10-21 16:56:23

by Sudeep Holla

[permalink] [raw]
Subject: Re: [PATCH v2 00/14] mailbox: pcc: Add support for PCCT extended PCC subspaces

Hi Jassi,

Gentle ping!

On Mon, Oct 11, 2021 at 11:09:49AM +0100, Sudeep Holla wrote:
> Hi Jassi,
>
> On Fri, Sep 17, 2021 at 02:33:43PM +0100, Sudeep Holla wrote:
> > Hi,
> >
> > Though the series is about adding support for PCCT extended PCC subspaces,
> > except one patch, remaining are either preparatory or clean up to add
> > the PCCT extended PCC subspaces. Only patch 12 adds the support of extended
> > PCC type3/4 subspaces.
> >
> > The main change affecting your is the change in pcc_mbox_request_channel
> > to avoid clien driver using con_priv member which is designed for controller
> > private pointer rather than for client's to use that.
> >
>
> Once I have ack from Guenter, is it OK to get this merged via mailbox tree.
> Rafael is happy for me to maintain this PCC part of ACPI. Do you prefer
> to merge patches directly or do you prefer pull request ? Let me know.
>
> --
> Regards,
> Sudeep

--
Regards,
Sudeep

2021-10-22 15:11:10

by Jassi Brar

[permalink] [raw]
Subject: Re: [PATCH v2 00/14] mailbox: pcc: Add support for PCCT extended PCC subspaces

On Thu, Oct 21, 2021 at 11:54 AM Sudeep Holla <[email protected]> wrote:
>
> Hi Jassi,
>
> Gentle ping!
>
I'll pick them.

thanks.

2021-10-22 17:10:54

by Sudeep Holla

[permalink] [raw]
Subject: Re: [PATCH v2 00/14] mailbox: pcc: Add support for PCCT extended PCC subspaces

On Fri, Oct 22, 2021 at 10:05:52AM -0500, Jassi Brar wrote:
> On Thu, Oct 21, 2021 at 11:54 AM Sudeep Holla <[email protected]> wrote:
> >
> > Hi Jassi,
> >
> > Gentle ping!
> >
> I'll pick them.
>
> thanks.

Thanks, you can drop 02/14. I will ask Rafael you pick that up once he is
happy with it.

--
Regards,
Sudeep